From 0baa38d4e414c1e7daa8c10565d9f140eef3999b Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Oct 2026 00:07:57 +0000 Subject: [PATCH 1/8] Add bounded retained checkpoint query and isolated chart adapter --- docs/contracts/retained-analysis-query.md | 81 ++++ docs/contracts/retained-analysis-renderer.md | 111 +++++ .../retained-analysis/execution-ledger.md | 22 + docs/plans/retained-analysis/issues.md | 7 + docs/plans/retained-analysis/plan.md | 145 ++++++ .../reports/independent-review.md | 39 ++ .../reports/m1/focused-tests.log | 18 + .../reports/m2/browser-errors.log | 0 .../retained-analysis/reports/m2/browser.json | 18 + .../reports/source/active-pr-write-sets.json | 1 + .../reports/source/checkpoint.json | 55 +++ examples/analysis/requirements.txt | 2 + .../analysis/retained_checkpoint_curve.py | 30 ++ retained_analysis.py | 262 +++++++++++ static/retained-analysis.js | 187 ++++++++ static/retained-checkpoint-curve.vl.json | 1 + .../retained-analysis/licenses/d3-array.txt | 14 + .../retained-analysis/licenses/d3-color.txt | 14 + .../licenses/d3-delaunay.txt | 15 + .../licenses/d3-dispatch.txt | 14 + .../retained-analysis/licenses/d3-dsv.txt | 14 + .../retained-analysis/licenses/d3-force.txt | 14 + .../retained-analysis/licenses/d3-format.txt | 14 + .../licenses/d3-geo-projection.txt | 38 ++ .../retained-analysis/licenses/d3-geo.txt | 35 ++ .../licenses/d3-hierarchy.txt | 14 + .../licenses/d3-interpolate.txt | 14 + .../retained-analysis/licenses/d3-path.txt | 14 + .../licenses/d3-quadtree.txt | 14 + .../licenses/d3-scale-chromatic.txt | 29 ++ .../retained-analysis/licenses/d3-scale.txt | 14 + .../retained-analysis/licenses/d3-shape.txt | 14 + .../licenses/d3-time-format.txt | 14 + .../retained-analysis/licenses/d3-time.txt | 14 + .../retained-analysis/licenses/d3-timer.txt | 14 + .../retained-analysis/licenses/delaunator.txt | 16 + .../licenses/fast-json-patch.txt | 23 + .../retained-analysis/licenses/internmap.txt | 14 + .../json-stringify-pretty-compact.txt | 22 + .../licenses/robust-predicates.txt | 25 ++ .../retained-analysis/licenses/semver.txt | 16 + .../licenses/topojson-client.txt | 14 + .../licenses/vega-canvas.txt | 28 ++ .../licenses/vega-crossfilter.txt | 28 ++ .../retained-analysis/licenses/vega-embed.txt | 28 ++ .../licenses/vega-encode.txt | 28 ++ .../licenses/vega-event-selector.txt | 28 ++ .../retained-analysis/licenses/vega-force.txt | 28 ++ .../retained-analysis/licenses/vega-geo.txt | 28 ++ .../licenses/vega-hierarchy.txt | 28 ++ .../licenses/vega-interpreter.txt | 28 ++ .../retained-analysis/licenses/vega-label.txt | 28 ++ .../retained-analysis/licenses/vega-lite.txt | 28 ++ .../licenses/vega-parser.txt | 28 ++ .../licenses/vega-projection.txt | 28 ++ .../licenses/vega-regression.txt | 28 ++ .../licenses/vega-runtime.txt | 28 ++ .../licenses/vega-schema-url-parser.txt | 30 ++ .../licenses/vega-statistics.txt | 28 ++ .../licenses/vega-themes.txt | 28 ++ .../licenses/vega-tooltip.txt | 12 + .../licenses/vega-transforms.txt | 28 ++ .../licenses/vega-view-transforms.txt | 28 ++ .../retained-analysis/licenses/vega-view.txt | 28 ++ .../licenses/vega-voronoi.txt | 28 ++ .../licenses/vega-wordcloud.txt | 28 ++ .../retained-analysis/licenses/vega.txt | 28 ++ static/vendor/retained-analysis/manifest.json | 420 ++++++++++++++++++ .../retained-analysis/vega-embed.min.js | 7 + .../retained-analysis/vega-interpreter.min.js | 2 + .../vendor/retained-analysis/vega-lite.min.js | 2 + static/vendor/retained-analysis/vega.min.js | 2 + tests/browser_retained_analysis.cjs | 121 +++++ tests/fixtures/retained-analysis-browser.css | 7 + tests/fixtures/retained-analysis-browser.js | 42 ++ tests/retained_analysis_browser_fixture.py | 35 ++ tests/test_retained_analysis.py | 289 ++++++++++++ 77 files changed, 3049 insertions(+) create mode 100644 docs/contracts/retained-analysis-query.md create mode 100644 docs/contracts/retained-analysis-renderer.md create mode 100644 docs/plans/retained-analysis/execution-ledger.md create mode 100644 docs/plans/retained-analysis/issues.md create mode 100644 docs/plans/retained-analysis/plan.md create mode 100644 docs/plans/retained-analysis/reports/independent-review.md create mode 100644 docs/plans/retained-analysis/reports/m1/focused-tests.log create mode 100644 docs/plans/retained-analysis/reports/m2/browser-errors.log create mode 100644 docs/plans/retained-analysis/reports/m2/browser.json create mode 100644 docs/plans/retained-analysis/reports/source/active-pr-write-sets.json create mode 100644 docs/plans/retained-analysis/reports/source/checkpoint.json create mode 100644 examples/analysis/requirements.txt create mode 100644 examples/analysis/retained_checkpoint_curve.py create mode 100644 retained_analysis.py create mode 100644 static/retained-analysis.js create mode 100644 static/retained-checkpoint-curve.vl.json create mode 100644 static/vendor/retained-analysis/licenses/d3-array.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-color.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-delaunay.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-dispatch.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-dsv.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-force.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-format.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-geo-projection.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-geo.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-hierarchy.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-interpolate.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-path.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-quadtree.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-scale-chromatic.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-scale.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-shape.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-time-format.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-time.txt create mode 100644 static/vendor/retained-analysis/licenses/d3-timer.txt create mode 100644 static/vendor/retained-analysis/licenses/delaunator.txt create mode 100644 static/vendor/retained-analysis/licenses/fast-json-patch.txt create mode 100644 static/vendor/retained-analysis/licenses/internmap.txt create mode 100644 static/vendor/retained-analysis/licenses/json-stringify-pretty-compact.txt create mode 100644 static/vendor/retained-analysis/licenses/robust-predicates.txt create mode 100644 static/vendor/retained-analysis/licenses/semver.txt create mode 100644 static/vendor/retained-analysis/licenses/topojson-client.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-canvas.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-crossfilter.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-embed.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-encode.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-event-selector.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-force.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-geo.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-hierarchy.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-interpreter.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-label.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-lite.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-parser.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-projection.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-regression.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-runtime.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-schema-url-parser.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-statistics.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-themes.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-tooltip.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-transforms.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-view-transforms.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-view.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-voronoi.txt create mode 100644 static/vendor/retained-analysis/licenses/vega-wordcloud.txt create mode 100644 static/vendor/retained-analysis/licenses/vega.txt create mode 100644 static/vendor/retained-analysis/manifest.json create mode 100644 static/vendor/retained-analysis/vega-embed.min.js create mode 100644 static/vendor/retained-analysis/vega-interpreter.min.js create mode 100644 static/vendor/retained-analysis/vega-lite.min.js create mode 100644 static/vendor/retained-analysis/vega.min.js create mode 100644 tests/browser_retained_analysis.cjs create mode 100644 tests/fixtures/retained-analysis-browser.css create mode 100644 tests/fixtures/retained-analysis-browser.js create mode 100644 tests/retained_analysis_browser_fixture.py create mode 100644 tests/test_retained_analysis.py diff --git a/docs/contracts/retained-analysis-query.md b/docs/contracts/retained-analysis-query.md new file mode 100644 index 00000000..85a57053 --- /dev/null +++ b/docs/contracts/retained-analysis-query.md @@ -0,0 +1,81 @@ +# Retained checkpoint examples query v1 + +Status: additive implementation under review, **not registered in HTTP/agent/UI**. +Production consumers must wait for coordinated integration and actual-store +qualification. Python entry point: `retained_analysis.query(runs, body)`. + +```json +{ + "query_id": "retained_checkpoint_examples", + "query_version": 1, + "run_id": "", + "evaluation_sha256": "", + "checkpoint_sha256": "", + "metric_id": "accuracy", + "metric_definition_sha256": "", + "fields": ["example_id", "truth_index", "predicted_index", "confidence", "error"], + "errors_only": false, + "limit": 50, + "offset": 0 +} +``` + +Closed object; last four fields optional with shown defaults. Metrics allow +accuracy/loss/macro_f1 only. Fields must be unique and include example_id. +Integer booleans are rejected; limit 1–100, offset 0–10000. One exact completed +native `model_evidence_v1` Run, validation split only. Scientific field and +one-fit formats require their own later query variants. All hashes lowercase +64-character SHA256; a valid hash from another result/checkpoint is rejected. + +Access: inspect checked before evidence and again after the SQL read snapshot, +including exports. No cache, training, inference, new analysis, checkpoint +deserialization or holdout exposure. Existing Runs verification re-tallies +retained metric evidence; it does not publish a new computed result. +`export=True` is a host-owned keyword, never caller metadata; it runs the same +bounded query under `runs.export_retained_analysis`. Each exported page is a +fresh authorized query; no unbounded export endpoint or persistent URL. + +Runs verifies immutable bytes and graph/task compatibility. Query selects the +exact PostgreSQL workspace_runs row and checks artifact identity. Curve SQL +reads catalog metric history and joins verified checkpoint epochs. Every value, +epoch and support must equal retained observations. Bounded verified per-example +scalars are passed to PostgreSQL as a parameterized disposable recordset for +error filtering and stable ordinal pagination. This is an initial projection, +not a new persisted statistics schema. Original text and hash-bound bytes are +unchanged; JSONB casts never define evidence identity. + +Budgets: 128 checkpoints, 10000 fixed-probe examples, 2 MiB scalar projection, +16 MiB existing Run document, 256 KiB response, 100-row pages; SQL statement and +lock timeouts 2000ms scoped to the read transaction, two-second ownership wait. +Existing Runs verification/artifact budgets still apply before SQL; the SQL +timeout is not a hard wall deadline on artifact verification. These initial +limits are explicit admission bounds, not measured performance targets. An +outer transaction is refused; a standalone read owns Repeatable Read and READ +ONLY. These settings are consistency controls, not an untrusted-SQL sandbox. +All query structure/relations/functions are server-owned; credentials remain +server-side. No new roles, privileges, DDL or production migrations. + +Response: state verified; query ID/version; frozen mode; provenance including +catalog/Run/evaluation/checkpoint/metric-definition/population/probe/data hashes +and retained producer identity. Metric includes its original definition/units +and unfiltered support. Curve rows carry checkpoint hash, epoch, exact value, +support. Table columns carry type/units; rows always include stable example_id, +ordinal and complete frozen_reference. Confidence is the retained predicted +class probability. Errors mean truth_index != predicted_index. Population +support, filtered support, page offset/limit/next_offset and visible filters +remain distinct. Error filtering never recomputes curve statistics or changes +their population. No display sampling is used: the population is explicitly +the frozen validation probe, not an implied full dataset. selection_sha256 +identifies canonical query settings and is not a new computed-result identity. + +Failures use WorkbenchError: invalid request 400; unsupported query/task 409; +stale evaluation/metric 409; foreign checkpoint/not-found Run 404; limit 413; +unavailable standalone/read state 503 where applicable. Existing Access and +storage errors propagate with their established boundaries. A failed or revoked +request must clear the future renderer, cancel obsolete requests, and exclude +late replies. Already returned bytes cannot be recalled. + +The future renderer consumes an immutable base spec/result and revisioned +allowlisted display overrides separately. Changed analysis creates a new result; +series/color/range/display filters cannot silently redefine metric meaning. +No renderer or spec is accepted merely because it is JSON. diff --git a/docs/contracts/retained-analysis-renderer.md b/docs/contracts/retained-analysis-renderer.md new file mode 100644 index 00000000..0de61d68 --- /dev/null +++ b/docs/contracts/retained-analysis-renderer.md @@ -0,0 +1,111 @@ +# Retained checkpoint renderer adapter + +Status: isolated implementation under review. Not mounted in production Runs. +The existing Runs/API/contract registry hooks await repository-lead coordination. + +`WorkspaceRetainedAnalysis.mount(root, {load, onSelection})` returns: + +- `update(request, authorityKey)`: clear previous private state, abort obsolete + work, load one bounded named query page and the pinned local spec, validate + identities/counts/types, then render. Host changes authorityKey and calls + update/dispose whenever credential, catalog, Run or navigation authority changes. +- `resize()`: resize the active Vega view; container changes also use an owned + ResizeObserver. +- `selection()`: copy of the current exact query selection, or null after + failure/disposal. Declared checkbox and page controls issue fresh queries. +- `dispose()`: abort pending reads, invalidate late callbacks, finalize Vega, + disconnect observer and clear DOM/private state. + +`load` is host code accepting `(request, {signal, authorityKey, export})`, returning +the query response. It must use current authenticated transport and the exact +registered contract. It must never select credentials from caller metadata. +The optional host onSelection callback receives a checkpoint hash selected by +chart or keyboard buttons; arbitrary callbacks cannot come from chart JSON. + +Exports reissue the same bounded request with export true, validate the fresh +response, then download JSON through a short-lived Blob URL that is immediately +revoked. Failure clears existing private content. Vega export/editor/source +actions are disabled. No export uses previously displayed bytes as authority. + +## Spec and dependency authority + +`examples/analysis/retained_checkpoint_curve.py` is a readable Altair 5.5.0 authoring +script. Run it explicitly with its authoring-only requirements to generate +`static/retained-checkpoint-curve.vl.json`. View opening never imports Python or +executes the script. JSON bytes and their reviewed SHA256 are retained; JSONB +or mutable overrides never replace that byte identity. + +This first recipe accepts exactly one local specification, at most 16 KiB, whose +bytes must match the renderer's pinned digest. The specification contains a +single named inline curve dataset, two marks and one checkpoint point-selection +parameter. Arbitrary user specs, URLs, patches, expression functions, embed +options and HTML/tooltips are not accepted. Changing the script/spec requires a +new reviewed digest. The host alone supplies validated curve data. The bound +schema hint is not fetched. A denied Vega loader prevents data/image/link URL +loading even after compilation; tooltips are disabled and table text uses DOM +textContent. A JSON format alone is never the security boundary. + +Self-hosted unmodified upstream browser distributions: + +| Package | Pinned version | License | +| --- | --- | --- | +| vega | 5.33.0 | BSD-3-Clause | +| vega-lite | 5.23.0 | BSD-3-Clause | +| vega-embed | 6.29.0 | BSD-3-Clause | +| vega-interpreter | 1.2.0 | BSD-3-Clause | + +The v5 family matches the v5 schema emitted by Altair 5.5 and supplies UMD +distributions without a new application bundler. Load in the table order before +retained-analysis.js. The interpreter extends window.vega. Embed passes ast true +and expressionInterpreter; strict CSP does not need unsafe-eval or unsafe-inline. +Do not weaken app CSP. `static/vendor/retained-analysis/manifest.json` records +exact asset/tarball hashes, upstream URLs, and retained notices for packages in +the upstream source maps. Notice-source resolution versions do not claim exact +embedded transitive versions. BSD, MIT and ISC notices are retained with the +assets. No license implies dataset/model rights. + +## Acceptance boundary + +`node tests/browser_retained_analysis.cjs` starts a local fixture server and real +headless Chromium with a disposable profile. It exercises the actual assets, +interpreter, strict CSP, exact authored numbers, physical keyboard/focus, SVG +point selection, pagination/filter, 390px width, stale reply after revoked-mode +response, decoder/spec tampering limits, fresh export and downloaded JSON, +cache-bypassed page reload and disposal. No external chart-asset request or CSP +violation is permitted. Headless/no-sandbox/software rendering is test-only and +does not establish an application execution sandbox. + +This test uses authored responses and access-failure substitutes. It establishes +renderer behavior only. It does not establish actual Runs custody, PostgreSQL +execution, real credential revocation, full application accessibility, or +cold-process retained result reproducibility. These remain blocked gates until +the shared hooks and an authorized existing DB/training environment are supplied. + +## Pending API dependency and shared hook proposal + +No shared-file changes are part of this branch. Proposed additive contracts for +lead agreement before implementation: + +1. Register new inspect operations `runs.retained_analysis/1` and + `runs.export_retained_analysis/1`, each with explicit closed request/response + schema hashes. Keep existing operations/versions unchanged. +2. Add POST `/api/workspace/runs//retained-analysis` and an explicit + `/retained-analysis/export` sibling. Require the chosen new contract; reject + route/body run mismatch. Delegate to `retained_analysis.query(dataset.runs, + body, export=host_route_choice)`. No user-controlled export flag. +3. In the existing verified native classifier Runs section, build the request + from its exact artifact/metric/checkpoint inventory. Mount a separate root; + load through authenticated transport. Dispose on navigation, credential or + Run replacement; never change coordinator/phase/publication/scientific + comparison controllers. Include adapter cleanup in existing authority-failure + paths and exclude obsolete replies before any DOM update. +4. Load self-hosted assets with the agreed current CSP; add actual authenticated + application/DB/browser tests and CI only after coordinated write-set approval. + The lead owns serial integration and merge; no approval or schema migration + is inferred from this proposal. + +Official references checked 2026-10-19/20: +[Altair serialization](https://altair-viz.github.io/user_guide/saving_charts.html), +[Vega-Lite parameters](https://vega.github.io/vega-lite/docs/parameter.html), +[vega-embed options](https://vega.github.io/vega-embed/index.html), +[Vega interpreter](https://vega.github.io/vega/usage/interpreter/). diff --git a/docs/plans/retained-analysis/execution-ledger.md b/docs/plans/retained-analysis/execution-ledger.md new file mode 100644 index 00000000..4d554947 --- /dev/null +++ b/docs/plans/retained-analysis/execution-ledger.md @@ -0,0 +1,22 @@ +# Execution ledger + +2026-10-19: Fetched main 8c9c0b0 (PR101), clean checkout. Created isolated +feature/retained-analysis-query-20261019. Read supplied five-page Library brief, +Runs/evidence/access/Metadata owners and adopted standards sources. Froze M1 +additive write set before code. PR102–110 overlap shared API/Run/UI files; +parent relay is pending. No shared-file edit, schema migration, credential or +permission change performed. No existing PostgreSQL configuration is available. + +2026-10-20: Parent relayed lead ownership confirmation: new query/chart modules, +renderer/tests/contracts belong to this branch. Existing shared handlers and +workspace controllers remain coordinated through parent; no edit performed. +Implemented M1 bounded exact-result query and M2 isolated Altair/Vega renderer. +Python boundary tests: 12 pass, one actual PostgreSQL SQL test explicitly skips. +Real headless Chromium uses authored query responses; checks strict CSP with +interpreter, local-only assets, exact values, keyboard/pointer links, pagination, +error filters, 390px layout, bad specs/responses, stale reply after authority +failure, fresh export/download, cold page reload and disposal. This is not +actual-store or authenticated application acceptance. Review identified and +closed preflight typed-error and frontend count/provenance/type-decoding gaps. +Full objective remains Verifying pending shared hook agreement and a provisioned +authorized PostgreSQL/training environment. Nothing merged. diff --git a/docs/plans/retained-analysis/issues.md b/docs/plans/retained-analysis/issues.md new file mode 100644 index 00000000..afd6d272 --- /dev/null +++ b/docs/plans/retained-analysis/issues.md @@ -0,0 +1,7 @@ +# Issues + +| ID | Finding | Owner | State / disposition | +| --- | --- | --- | --- | +| V1 | Shared API/Run/UI hooks overlap PR102–110 | parent/repository lead | pending coordination; continue additive M1 | +| V2 | No PostgreSQL binaries/configuration or qualified training runtime in selected environment | environment/parent | actual-store acceptance blocked; do not create credentials | +| V3 | General results and saved view revisions are later milestones | visualization owner | preserve immutable result boundary; no early persistence engine | diff --git a/docs/plans/retained-analysis/plan.md b/docs/plans/retained-analysis/plan.md new file mode 100644 index 00000000..1dfda5ee --- /dev/null +++ b/docs/plans/retained-analysis/plan.md @@ -0,0 +1,145 @@ +# Plan: Retained checkpoint curve and linked examples + +**Plan status:** `Verifying` + +**Current phase:** M2 isolated renderer qualified; shared integration pending + +**Next slice:** Coordinate additive HTTP/contracts and Runs mount hooks with the repository lead via the parent. + +**Acceptance status:** `pending` + +**Execution ledger:** [execution-ledger.md](execution-ledger.md) + +**Issues:** [issues.md](issues.md) + +## Objective + +Open an exact retained classifier result in Runs, inspect its metric curve, +select an exact checkpoint and page its frozen examples/errors, with current +access, numeric, lifecycle and provenance guarantees. View opening is inert. + +## Objective Acceptance + +| ID | Observable criterion | Kind | Environment | Mode | Status | Evidence | +| --- | --- | --- | --- | --- | --- | --- | +| A1 | Closed named query rejects malformed identities, unknown fields and unbounded requests before reads; exact substitutions fail before result return | contract | not-applicable | automated | passed | [focused tests](reports/m1/focused-tests.log) | +| A2 | Exact metric values, stable examples, pagination/support and frozen identity agree with retained bytes and actual PostgreSQL | integration | required-real | automated | blocked | existing DB configuration absent | +| A3 | Actual Runs browser supports keyboard, linked selections, narrow layout, stale replies, revocation, malformed/large specs, offline assets and cold reopen | user-workflow | required-real | automated | partial | [isolated actual Chromium renderer](reports/m2/browser.json); shared Runs hooks pending | +| A4 | Query/export reauthorize every retrieval, no cache authority, no computation or mutation on opening | integration | required-real | automated | pending | query tests and actual-store qualification | + +## Scope + +### In Scope + +First recipe: existing native `model_evidence_v1` classifier checkpoints, +validation metrics and retained fixed-probe examples. One result/run per request; +exact result and metric-definition hashes. Server-owned parameterized SQL over +the existing PostgreSQL Run document and a bounded verified example projection. +No schema change, role/credential change, or production migration. + +### Out Of Scope + +Scientific field queries, arbitrary SQL/Python/JS, benchmark execution, extra +plot libraries, generic EAV/schema engines, computed-on-open analyses and saved +view persistence. Revisioned overrides follow the completed immutable slice. + +## Binding Decisions + +| Decision | Owner | Evidence | Supersedes | +| --- | --- | --- | --- | +| Runs owns retained verification; query owner only projects verified results | Runs | `runs.py:2331`, `model_evidence.py:381` at main 8c9c0b0 | none | +| `retained_checkpoint_examples` v1 selects explicit run, evaluation, metric definition and checkpoint hashes | retained_analysis | [contract](../../contracts/retained-analysis-query.md) | none | +| Existing text Run document remains authoritative; JSONB casts are disposable query projections | Metadata/Runs | schema v10; raw artifact hashes retained | none | +| Vega-Lite/vega-embed with interpreter and self-hosted pinned assets | renderer | official upstream docs; later asset/browser qualification required | none | +| Lead alone merges; shared-file hooks wait for parent coordination | repository lead | delegation; PR102–110 write-set snapshot | none | + +## Design Observations And Remaining Evidence + +No AGENTS.md exists in workspace/repository. Applied Core/Router and selected +implementation, verification/oracles/GUI, planning, commit, documentation, +architecture/replay/code-design, contracts/protocol/evolution, persistence/IPC, +security/delegation, concurrency/resilience, performance, dependencies/licensing, +accessibility/frontend guidance from Coding-Standards dcc56f26. No callable +Standards Engine is exposed; this is source-guided routing, not certification. +Brief `libfile_e94877d6735c8191a6e5d78c82d1151b` read in full (five pages). + +Current source lacks PostgreSQL binaries, TULDOK_DATABASE_URL and a qualified +training runtime. Do not manufacture credentials or claim actual-store evidence. +The first query is useful independently of UI hook coordination; tests separate +controlled owner fixtures from required-real PostgreSQL and retained Runs. + +## Simplicity And Ownership Review + +**Applicability:** `applicable` + +- Independent concepts and dimensions: frozen analysis identity; mutable view + selection; current access; transport lifecycle; chart rendering. +- State, identity, value, time, policy, mechanism: Runs/artifacts own evidence, + Access owns current scopes, Metadata owns transaction/lock, this module owns + one closed read query. Query version does not revise metric meaning. Result + hash changes invalidate selections; colors never change result identity. +- Caller/composition knowledge: caller sends exact identities and bounded page; + query invokes the established verifier. Browser needs no artifact paths/SQL. +- Representative changes: adding a second recipe changes the query registry; + replacing renderer leaves result query intact; new metric meaning creates a + new retained result instead of mutating this query. +- Stable interfaces: explicit response fields, units, support and unavailable + errors. Internal evidence path knowledge stays in Runs. +- Independent evolution/failure: query can be tested without shared UI edits; + missing data is typed unsupported/unavailable, never substituted. +- Necessary complexity: strict decoding, evidence closure, bounded SQL and + post-read authorization protect separate reachable failures. +- Deletion result: removing renderer leaves current Runs fully functional; + removing query leaves no persisted second authority or migration. + +## Milestones + +### M1: Authorized bounded retained query + +**Allowed write set:** `retained_analysis.py`, `tests/test_retained_analysis.py`, +`docs/contracts/retained-analysis-query.md`, `docs/plans/retained-analysis/**`. + +Implement closed validation, exact retained identity, owned bounded SQL, +typed columns/units/support/provenance and final access check. Review through a +separate GPT-6.1 Sol High instance. Gate A1; A2/A4 remain blocked without actual DB. + +### M2: Embedded curve and linked table + +Allowed additive files: `static/retained-analysis.js`, +`static/retained-checkpoint-curve.vl.json`, `static/vendor/retained-analysis/**`, +`examples/analysis/retained_checkpoint_curve.py`, +`examples/analysis/requirements.txt`, `tests/browser_retained_analysis.cjs`, +`tests/retained_analysis_browser_fixture.py`, +`tests/fixtures/retained-analysis-browser.js`, +`tests/fixtures/retained-analysis-browser.css`, +`docs/contracts/retained-analysis-renderer.md`. +Shared integration candidates `app.py`, +`agent_api.py`, `static/workspace-real.js`, `static/workspaces.html`, +`static/workspaces.css`, CI; exact hooks must be agreed with lead before edit. +Define mount/resize/update/selection/export/dispose; deny external loaders/editor, +use interpreter under strict CSP. Gate A3 plus actual A2/A4. + +## Blockers + +- Parent relay/lead coordination is pending. Cross-thread collaboration send to + source_thread_id returns `agent ... not found`; no shared-file edits authorized + by coordination yet. No GitHub comment to another person is substituted. +- Actual PostgreSQL/training environment unavailable. No credentials created. + +## Re-Plan Triggers + +Real data exceeds declared query budgets; incompatible artifact formats; +shared hook ownership changes; actual CSP/interpreter incompatibility; measured +need for indexed relational facts requiring a separately gated schema migration. + +## Repository Isolation + +Path `/workspace/Tuldok`; branch `feature/retained-analysis-query-20261019` from +main `8c9c0b0`. Preserve all README and reliability branches. Lead owns merge; +retain source/evidence and branch for its review. No worktree deletion planned. + +## Final Acceptance + +- Acceptance status: `pending` +- Deferred follow-ups: M2 integration and actual-store/browser qualification +- Final status: `Verifying` diff --git a/docs/plans/retained-analysis/reports/independent-review.md b/docs/plans/retained-analysis/reports/independent-review.md new file mode 100644 index 00000000..631908b4 --- /dev/null +++ b/docs/plans/retained-analysis/reports/independent-review.md @@ -0,0 +1,39 @@ +# Independent review + +Reviewer: separate GPT-6.1 Sol instance, high reasoning, read-only code/tests. +Final disposition: no remaining blocking findings in additive query or isolated +renderer. No review-side files or credentials created. + +Findings closed before final review: + +1. Plan overstated semantic identity rejection before evidence reads. Narrowed + acceptance to malformed identity rejection before reads and exact semantic + rejection before return. Added early size-bounded evaluation check before + expensive inherited verification, repeated inside final SQL snapshot. +2. Early malformed Run-envelope preflight could raise raw TypeError/KeyError. + Added typed unavailable409 mapping and isolated malformed-envelope cases. +3. Browser decoder accepted mismatched supports/ordinals and missing provenance, + metric definition or column types. Enforced relationships and complete used + fields; each malformed variant now reaches and fails that boundary. +4. Browser fixture could interact before Vega embed settled. Waits include busy + completion; keyboard and actual SVG pointer paths are exercised separately. + +Final independent checks: 12 Python fixture tests pass, one PostgreSQL SQL test +skips; actual headless Chromium fixture passes, including bad-spec cancellation. +Reviewer verified asset hashes and notice-file presence. Spec stream cancellation, +update abort/busy cleanup and owned child-process exit were reviewed in final code. + +Reviewed SHA256: + +| File | SHA256 | +| --- | --- | +| retained_analysis.py | 317ba63b0f89367ba26dd62b8157910654943eb8a9d3ab1442f09f09827f218b | +| tests/test_retained_analysis.py | 10ab4c7ad35c9df868320add066799a18896538ee59593156d4b52b0b2d1a11a | +| static/retained-analysis.js | b6203812c4dd04586062e903ef981cff074ba80ff5d01eeb218b711c8417a1e9 | +| tests/browser_retained_analysis.cjs | 822d6df2d8c29e909f6f0dcee42595f90c9eae70306ff9c8b20eba042bdd05ce | +| static/retained-checkpoint-curve.vl.json | 6603c860ce76a434a11e6c96cf7418246ce2dd5da3d7a56a5f2448a0537ec183 | + +Limit: query fixture orchestration and real browser rendering over authored data +are established. Actual PostgreSQL/retained-Run custody/revocation, production +integration and full cold-process scientific reproducibility are unqualified. +Do not merge or register this capability on the basis of fixture evidence alone. diff --git a/docs/plans/retained-analysis/reports/m1/focused-tests.log b/docs/plans/retained-analysis/reports/m1/focused-tests.log new file mode 100644 index 00000000..703ee444 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m1/focused-tests.log @@ -0,0 +1,18 @@ +test_parameterized_curve_and_stable_error_page_on_actual_postgres (test_retained_analysis.ActualPostgresSqlTests.test_parameterized_curve_and_stable_error_page_on_actual_postgres) ... skipped 'Existing authorized PostgreSQL configuration required; no credentials created.' +test_exact_frozen_examples_and_retained_confidence (test_retained_analysis.ProjectionTests.test_exact_frozen_examples_and_retained_confidence) ... ok +test_foreign_metric_checkpoint_and_population_are_distinct_failures (test_retained_analysis.ProjectionTests.test_foreign_metric_checkpoint_and_population_are_distinct_failures) ... ok +test_unsupported_task_and_oversize_are_explicit (test_retained_analysis.ProjectionTests.test_unsupported_task_and_oversize_are_explicit) ... ok +test_catalog_mismatch_is_refused (test_retained_analysis.QueryBoundaryTests.test_catalog_mismatch_is_refused) ... ok +test_error_filter_does_not_change_metric_population_and_page_identity (test_retained_analysis.QueryBoundaryTests.test_error_filter_does_not_change_metric_population_and_page_identity) ... ok +test_exact_provenance_and_values_with_fresh_access_outside_snapshot (test_retained_analysis.QueryBoundaryTests.test_exact_provenance_and_values_with_fresh_access_outside_snapshot) ... ok +test_export_and_repeated_retrieval_do_not_bypass_current_authority (test_retained_analysis.QueryBoundaryTests.test_export_and_repeated_retrieval_do_not_bypass_current_authority) ... ok +test_malformed_catalog_envelope_preserves_typed_failure (test_retained_analysis.QueryBoundaryTests.test_malformed_catalog_envelope_preserves_typed_failure) ... ok +test_nested_transaction_and_oversized_response_refused (test_retained_analysis.QueryBoundaryTests.test_nested_transaction_and_oversized_response_refused) ... ok +test_revocation_during_read_prevents_return (test_retained_analysis.QueryBoundaryTests.test_revocation_during_read_prevents_return) ... ok +test_closed_bounds_and_types_before_evidence_read (test_retained_analysis.RequestTests.test_closed_bounds_and_types_before_evidence_read) ... ok +test_defaults_and_explicit_field_projection (test_retained_analysis.RequestTests.test_defaults_and_explicit_field_projection) ... ok + +---------------------------------------------------------------------- +Ran 13 tests in 0.004s + +OK (skipped=1) diff --git a/docs/plans/retained-analysis/reports/m2/browser-errors.log b/docs/plans/retained-analysis/reports/m2/browser-errors.log new file mode 100644 index 00000000..e69de29b diff --git a/docs/plans/retained-analysis/reports/m2/browser.json b/docs/plans/retained-analysis/reports/m2/browser.json new file mode 100644 index 00000000..a4122f3d --- /dev/null +++ b/docs/plans/retained-analysis/reports/m2/browser.json @@ -0,0 +1,18 @@ +{ + "status": "passed", + "evidence": "actual-headless-Chromium-authored-renderer-fixture", + "checks": [ + "strict CSP/interpreter", + "self-hosted/offline external assets", + "exact numbers", + "keyboard linked selection/focus", + "visible error filter", + "390px layout", + "stale reply after revocation", + "malformed/oversized response and spec rejection", + "support/ordinal/provenance/type validation", + "fresh export authorization path", + "cold page reopen", + "dispose" + ] +} diff --git a/docs/plans/retained-analysis/reports/source/active-pr-write-sets.json b/docs/plans/retained-analysis/reports/source/active-pr-write-sets.json new file mode 100644 index 00000000..cb7b5c17 --- /dev/null +++ b/docs/plans/retained-analysis/reports/source/active-pr-write-sets.json @@ -0,0 +1 @@ +[{"files":["docs/contracts/project-cli.md","docs/contracts/workflow-client.md","docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-01/actual-http-cli.log","docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-01/cleanup-independent.json","docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-01/cleanup-publication.json","docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-01/cleanup-twenty.json","docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-01/source.json","docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/actual-affected.log","docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/cleanup-independent.json","docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/cleanup-publication.json","docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/cleanup-twenty.json","docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/preparation.json","docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/source-before-comment.json","docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/source.json","docs/plans/lab-workflow-reliability/reports/m4-batch-client/consumer-independent-final-review.json","docs/plans/lab-workflow-reliability/reports/m4-batch-client/pure-composed.log","docs/plans/lab-workflow-reliability/reports/m4-batch-client/pure-initial.log","docs/plans/lab-workflow-reliability/reports/m4-batch-client/qualification.md","docs/plans/lab-workflow-reliability/reports/m4-batch-client/validation.json","project_cli.py","tests/test_workflow_batch_client.py","tests/test_workflow_batch_client_http.py","tuldok_client.py"],"headRefName":"feature/lab-batch-client-20261019","headRefOid":"ff17f438fc328f9100fba6ec9fd9525f6d452410","number":110},{"files":["agent_api.py","app.py","docs/contracts/run-artifact-segments.md","docs/plans/lab-workflow-reliability/execution-ledger.md","docs/plans/lab-workflow-reliability/plan.md","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/actual-initial.log","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/before.log","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02.log","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02/environment-start.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02/raw/artifacts-1-setup-integrity.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02/raw/publication-artifacts-1-history-2-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02/raw/run-artifacts-1-history-1-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02/raw/unavailable-artifacts-1-history-0-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02/summary.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pure-final.log","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/initial-validation.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/legacy-regressions.log","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/analyze_pairs.py","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/environment-start.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/parent-cleanup-independent.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/qualified-pairs.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/artifacts-1-setup-integrity.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/artifacts-20-setup-integrity.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/publication-artifacts-1-history-56-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/publication-artifacts-1-history-56-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/publication-artifacts-1-history-56-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/publication-artifacts-20-history-56-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/publication-artifacts-20-history-56-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/publication-artifacts-20-history-56-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-1-history-55-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-1-history-55-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-1-history-55-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-1-history-8-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-1-history-8-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-1-history-8-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-20-history-55-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-20-history-55-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-20-history-55-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-20-history-8-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-20-history-8-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-20-history-8-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/unavailable-artifacts-1-history-0-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/unavailable-artifacts-1-history-0-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/unavailable-artifacts-1-history-0-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/unavailable-artifacts-20-history-0-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/unavailable-artifacts-20-history-0-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/unavailable-artifacts-20-history-0-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/results.md","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/stdout.log","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/summary.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/validation.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/analyze_pairs.py","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/environment-start.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/producer-independent-review.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/qualified-pairs.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/artifacts-1-setup-integrity.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/artifacts-20-setup-integrity.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/publication-artifacts-1-history-56-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/publication-artifacts-1-history-56-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/publication-artifacts-1-history-56-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/publication-artifacts-20-history-56-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/publication-artifacts-20-history-56-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/publication-artifacts-20-history-56-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-1-history-55-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-1-history-55-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-1-history-55-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-1-history-8-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-1-history-8-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-1-history-8-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-20-history-55-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-20-history-55-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-20-history-55-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-20-history-8-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-20-history-8-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-20-history-8-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/unavailable-artifacts-1-history-0-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/unavailable-artifacts-1-history-0-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/unavailable-artifacts-1-history-0-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/unavailable-artifacts-20-history-0-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/unavailable-artifacts-20-history-0-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/unavailable-artifacts-20-history-0-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/refinement-independent-review.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/results.md","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/stdout.log","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/summary.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/validation.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-harness-tests.log","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01.log","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01/environment-start.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01/raw/artifacts-2-setup-integrity.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01/raw/publication-artifacts-2-history-2-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01/raw/run-artifacts-2-history-1-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01/raw/unavailable-artifacts-2-history-0-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01/summary.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/pure-initial.log","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/refinement/actual-attempt01-source.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/refinement/actual-attempt01.log","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/refinement/before.log","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/refinement/independent-review.json","docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/refinement/parent-997-cleanup-independent.json"],"headRefName":"feature/lab-bounded-collection-20261019","headRefOid":"0dbaab7da26728d1f6ef43a09d6fafe65fd8c9b6","number":109},{"files":["docs/contracts/indexed-diagnostics.md","docs/contracts/run-preflight-publication.md","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/indexed-final-9d563ceb-independent-review.json","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/qualification.md","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/tuldok-indexed-composed-actual.log","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/tuldok-indexed-composed-qualification.json","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/tuldok-indexed-composed-readers-70dcaeb-independent-review.json","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/tuldok-indexed-composed-source.json","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/tuldok-refined-indexed-cleanup-independent.json","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/validation.json","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/owner-roundtrip-final.log","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/owner-roundtrip-first.log","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/owner-roundtrip-receipt.json","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/owner-roundtrip-second.log","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/pure-tests-final.log","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/pure-tests.log","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/report.md","docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/source-sha256.txt","extension_evidence.py","recipe_contract.py","tests/test_indexed_diagnostics.py","tests/test_indexed_diagnostics_publication.py","tuldok_extension_sdk/diagnostics.py","tuldok_extension_sdk/evidence.py"],"headRefName":"feature/lab-indexed-diagnostics-20261019","headRefOid":"83a1e1289f3f7e4f8c3e697c1748a862a69d0897","number":108},{"files":["docs/contracts/lab-workflow-baseline.md","docs/plans/lab-workflow-reliability/execution-ledger.md","docs/plans/lab-workflow-reliability/plan.md","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/analysis-verification.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/analysis.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/README.md","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-exploratory-preflight.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-01.log","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-01/environment-start.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-01/failure.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-02.log","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-02/environment-start.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-02/raw/artifacts-1-history-0-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-02/raw/artifacts-1-history-2-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-02/raw/artifacts-1-real-history-population.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-02/summary.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03.log","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03/environment-start.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03/failure.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03/raw/artifacts-1-history-0-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03/raw/artifacts-1-history-2-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03/raw/artifacts-1-real-history-population.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03/raw/artifacts-2-history-0-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04.log","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04/environment-start.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04/raw/artifacts-2-fresh-workflow-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04/raw/artifacts-2-history-0-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04/raw/artifacts-2-history-2-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04/raw/artifacts-2-real-history-population.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04/summary.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pure-final.log","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pure.log","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f.log","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/environment-start.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-fresh-workflow-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-fresh-workflow-1.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-fresh-workflow-2.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-0-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-0-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-0-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-55-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-55-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-55-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-8-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-8-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-8-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-real-history-population.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-fresh-workflow-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-fresh-workflow-1.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-fresh-workflow-2.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-0-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-0-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-0-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-55-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-55-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-55-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-8-process-0.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-8-process-1.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-8-process-2.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-real-history-population.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/summary.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/qualified-distributions.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/reporting-tests-final.log","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/results.md","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/root-cleanup-independent.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/tooling.json","docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/validation.json","tests/benchmark_lab_workflow.py","tests/test_benchmark_lab_workflow.py"],"headRefName":"test/lab-workflow-baseline-20261019","headRefOid":"6e44137bf65374d6a148e6ea0fc3dcc1600a8a5c","number":107},{"files":[".github/workflows/tests.yml","agent_api.py","app.py","docs/contracts/model-development.md","docs/contracts/run-preflight-publication.md","docs/contracts/scientific-comparison.md","docs/plans/lab-workflow-reliability/reports/m6/evidence/agent-api-green.log","docs/plans/lab-workflow-reliability/reports/m6/evidence/browser-first-red.log","docs/plans/lab-workflow-reliability/reports/m6/evidence/browser-green.log","docs/plans/lab-workflow-reliability/reports/m6/evidence/browser-receipt.json","docs/plans/lab-workflow-reliability/reports/m6/evidence/controller-green.log","docs/plans/lab-workflow-reliability/reports/m6/evidence/coordinator-green.log","docs/plans/lab-workflow-reliability/reports/m6/evidence/domain-receipt.json","docs/plans/lab-workflow-reliability/reports/m6/evidence/external-controller-green.log","docs/plans/lab-workflow-reliability/reports/m6/evidence/field-controller-green.log","docs/plans/lab-workflow-reliability/reports/m6/evidence/pure-green.log","docs/plans/lab-workflow-reliability/reports/m6/evidence/reader-first-red.log","docs/plans/lab-workflow-reliability/reports/m6/evidence/reader-green.log","docs/plans/lab-workflow-reliability/reports/m6/evidence/retained-green.log","docs/plans/lab-workflow-reliability/reports/m6/evidence/schema-cleanup.json","docs/plans/lab-workflow-reliability/reports/m6/integration-source.md","docs/plans/lab-workflow-reliability/reports/m6/qualification.md","docs/plans/lab-workflow-reliability/reports/m6/recovery-browser-fixture/tuldok-pr106-browser-composition-green.log","docs/plans/lab-workflow-reliability/reports/m6/recovery-browser-fixture/tuldok-pr106-browser-composition-red.log","docs/plans/lab-workflow-reliability/reports/m6/recovery-browser-fixture/validation.json","docs/plans/lab-workflow-reliability/reports/m6/source-review.md","docs/plans/lab-workflow-reliability/reports/m6/validation.json","extension_evidence.py","run_publication.py","runs.py","static/workspace-real.js","static/workspace-scientific-comparison.js","static/workspaces.css","static/workspaces.html","tests/browser_scientific_comparison.cjs","tests/browser_workspace_recovery.cjs","tests/scientific_comparison_fixture.py","tests/test_scientific_comparison.py","tests/test_scientific_comparison_client.py","tests/test_scientific_comparison_controller.cjs","tests/test_workspace_external_controller.cjs"],"headRefName":"feature/lab-field-comparison-20261019","headRefOid":"fc034a0f096a73798ec22fa3088406cd68b4c5a4","number":106},{"files":["README.md","agent_api.py","docs/contracts/agent-operations.md","docs/contracts/project-cli.md","docs/contracts/workflow-client.md","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/batch-consumer-independent-review.json","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/comparison-guard-focused.log","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/comparison-guard-http-source.json","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/comparison-guard-http.log","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/comparison-guard-red.log","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/comparison-guard-source.json","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/focused-comparison.log","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/focused-followup.log","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/focused-inventory-fix.log","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/focused-review-fixes.log","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/focused.log","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/http-attempt-01-source.json","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/http-attempt-01.log","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/http-attempt-02-source.json","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/http-attempt-02.log","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/http-review-fixes-source.json","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/http-review-fixes.log","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/legacy-client-cli-contracts-source.json","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/legacy-client-cli-contracts.log","docs/plans/lab-workflow-reliability/reports/m5-workflow-client/qualification.md","project_cli.py","tests/test_workflow_client.py","tests/test_workflow_client_http.py","tuldok_client.py"],"headRefName":"feature/lab-workflow-client-20261019","headRefOid":"a635be3dcb7187eec17266714631a4e0485a20b7","number":105},{"files":[".github/workflows/tests.yml","app.py","docs/contracts/run-phase-timings.md","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/coordinator-regression/coordinator-1440.jpg","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/coordinator-regression/coordinator-390.jpg","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/coordinator-regression/domain-receipt.json","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/coordinator-regression/receipt.json","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/external-controller-fixture/tuldok-pr104-external-composition-final-source.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/external-controller-fixture/tuldok-pr104-external-composition-green.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/external-controller-fixture/tuldok-pr104-external-composition-red.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/external-controller-fixture/validation.json","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/final-phase-browser/domain-receipt.json","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/final-phase-browser/phases-1440.jpg","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/final-phase-browser/phases-390.jpg","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/final-phase-browser/receipt.json","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/publication-regression/domain-receipt.json","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/publication-regression/publication-1440.jpg","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/publication-regression/publication-390.jpg","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/publication-regression/receipt.json","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/recovery-browser-fixture/tuldok-pr104-browser-composition-green.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/recovery-browser-fixture/tuldok-pr104-browser-composition-red.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/recovery-browser-fixture/validation.json","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-same-selection-stale-fixed-repro.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-same-selection-stale-repro.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-browser-final-predicate-source.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-browser-final-source.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-browser-first.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-browser-reviewed-window-source.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-browser-second.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-controller-same-selection-sequential.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-coordinator-ready-regression.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-coordinator-regression-final-source.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-native-ancestor-regression.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-pins-final-source.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-publication-regression-final-source.log","docs/plans/lab-workflow-reliability/reports/m3-phase-ui/validation.json","static/workspace-external.js","static/workspace-phase-timings.js","static/workspace-real.js","static/workspaces.css","static/workspaces.html","tests/browser_run_phase_timings.cjs","tests/browser_workspace_coordinator.cjs","tests/browser_workspace_recovery.cjs","tests/phase_timing_browser_fixture.py","tests/test_run_phase_controller.cjs","tests/test_workspace_external_controller.cjs","tests/test_workspace_phase_timings.py"],"headRefName":"feature/lab-phase-panel-20261019","headRefOid":"381bfccdad516010e83f6051f098a5835fb8aac3","number":104},{"files":[".github/workflows/tests.yml","agent_api.py","app.py","docs/contracts/run-phase-timings.md","docs/plans/lab-workflow-reliability/execution-ledger.md","docs/plans/lab-workflow-reliability/plan.md","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/integration-validation.json","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/selected-contracts.json","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/source-manifest.json","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-affected-qualified.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-core-composed-final.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-correlated-final-module.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-exact-source-qualified.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-expanded-actual.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-final-closed-evidence-qualified.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-final-qualified.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-final-reader-qualified.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-first-actual-and-m2-followup.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-first-compatibility.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-owner-final-shapes.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-owner-first.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-root-independent-qualification.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-second-compatibility.log","docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/validation.json","phase_timings.py","pipeline.py","project_cli.py","recipe_process.py","run_publication.py","runs.py","tests/fixtures/agent_contract_hashes_phase5a1feac.json","tests/test_run_phase_timings.py"],"headRefName":"feature/lab-phase-timing-20261019","headRefOid":"5cd2cf60c68dc361c840420441e8f59a52f756d8","number":103},{"files":[".github/workflows/tests.yml","docs/contracts/run-coordinator-recovery.md","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/README.md","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/ci-controller-fixture/tuldok-pr102-controller-composition-green.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/ci-controller-fixture/tuldok-pr102-controller-composition-red.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/ci-controller-fixture/tuldok-pr102-controller-fixture-independent-review.json","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/ci-controller-fixture/tuldok-pr102-controller-independent-green.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/ci-controller-fixture/tuldok-pr102-independent-lifecycle-job-118328520352.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/ci-controller-fixture/validation.json","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/coordinator-coordinator-1440.jpg","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/coordinator-coordinator-390.jpg","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/coordinator-domain-receipt.json","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/coordinator-receipt.json","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/publication-domain-receipt.json","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/publication-publication-1440.jpg","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/publication-publication-390.jpg","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/publication-receipt.json","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/reviewed-source-browser/coordinator-1440.jpg","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/reviewed-source-browser/coordinator-390.jpg","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/reviewed-source-browser/domain-receipt.json","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/reviewed-source-browser/receipt.json","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-browser-final-source.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-browser-first.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-controller-final-source.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-delivery-boundary-qualified.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-existing-recovery.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-pins-final-source.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-publication-regression.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-reviewed-source-browser.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-undelivered-new-key-after.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-undelivered-new-key-before.log","docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/validation.json","static/workspace-real.js","tests/browser_workspace_coordinator.cjs","tests/coordinator_browser_fixture.py","tests/test_workspace_coordinator.py","tests/test_workspace_coordinator_controller.cjs","tests/test_workspace_external_controller.cjs"],"headRefName":"feature/lab-coordinator-panel-20261019","headRefOid":"b4070b60b0119c73284c4832610cc82ef471963a","number":102},{"files":["docs/plans/lab-workflow-reliability/execution-ledger.md","docs/plans/lab-workflow-reliability/issues.md","docs/plans/lab-workflow-reliability/plan.md","docs/plans/lab-workflow-reliability/reports/baseline-and-standards.md","docs/plans/lab-workflow-reliability/reports/contracts-and-acceptance.md","docs/plans/lab-workflow-reliability/reports/independent-plan-review.md","docs/plans/lab-workflow-reliability/reports/validation.json","docs/plans/lab-workflow-reliability/reports/validation.md"],"headRefName":"docs/lab-workflow-reliability-plan","headRefOid":"b446d9a19dbd553b80bf9f3af574b8b34ddbd5cb","number":91},{"files":[".github/workflows/tests.yml",".gitignore","README.md","agent_api.py","app.py","docs/contracts/agent-operations.md","docs/plans/generic-scientific-projects/plan.md","docs/plans/generic-scientific-projects/reports/p6-admission.md","docs/plans/generic-scientific-projects/reports/p6-agent-dependencies.json","docs/plans/generic-scientific-projects/reports/p6-dependency-review.md","docs/plans/generic-scientific-projects/reports/p6-verification.md","docs/plans/generic-scientific-projects/reports/p6/final-test-receipt.json","docs/plans/generic-scientific-projects/reports/p6/scientific-mcp-receipt.json","mcp_stdio.py","requirements-agent.lock","requirements-agent.txt","runs.py","tests/qualify_agent_scientific.py","tests/test_agent_api.py","tests/test_agent_domain_parity.py","tests/test_agent_http.py","tests/test_agent_workflow.py","tests/test_artifact_segments.py","tests/test_mcp_stdio.py"],"headRefName":"feature/scoped-agent-operations-20261013","headRefOid":"5c0e7f92914e5aeac6ec939e3a667fc85b22aa90","number":53},{"files":[".github/workflows/tests.yml","README.md","app.py","docs/contracts/sequence-release-validation.md","docs/contracts/workspace-sequence-runs.md","docs/licenses/rheon-APACHE-2.0.txt","docs/plans/rheon-v2-consumer/execution-ledger.md","docs/plans/rheon-v2-consumer/issues.md","docs/plans/rheon-v2-consumer/plan.md","docs/plans/rheon-v2-consumer/reports/a8-runtime-20261013.md","docs/plans/rheon-v2-consumer/reports/implementation-20261013.md","docs/plans/rheon-v2-consumer/reports/producer-source.json","docs/plans/rheon-v2-consumer/reports/retained-v1-prechange.json","rheon_controls_contract.py","rheon_controls_sequence_contract.py","rheon_sequences.py","sequence_assets.py","sequence_batch_import.py","sequence_release.py","static/sequence-batch.js","static/sequences.js","static/workbench.html","static/workspace-real.js","tests/browser_workspace_sequence_run.cjs","tests/fixtures/rheon_controls_authored.py","tests/test_sequence_batch_controller.cjs","tests/test_sequence_v2_runs.py","tests/test_sequences_controller.cjs","tests/test_sequences_v2.py"],"headRefName":"feature/rheon-v2-consumer-20261013","headRefOid":"51bec9ea89f03357473aca0d40f2fa8251598a25","number":43}] diff --git a/docs/plans/retained-analysis/reports/source/checkpoint.json b/docs/plans/retained-analysis/reports/source/checkpoint.json new file mode 100644 index 00000000..c3e133eb --- /dev/null +++ b/docs/plans/retained-analysis/reports/source/checkpoint.json @@ -0,0 +1,55 @@ +{ + "baseline_main": "8c9c0b0", + "branch": "feature/retained-analysis-query-20261019", + "python": "3.12.14", + "chromium": "Chromium 151.0.7922.173 built on Debian GNU/Linux 13 (trixie)", + "node": "v24.19.0", + "source_sha256": { + "retained_analysis.py": "317ba63b0f89367ba26dd62b8157910654943eb8a9d3ab1442f09f09827f218b", + "tests/test_retained_analysis.py": "10ab4c7ad35c9df868320add066799a18896538ee59593156d4b52b0b2d1a11a", + "static/retained-analysis.js": "b6203812c4dd04586062e903ef981cff074ba80ff5d01eeb218b711c8417a1e9", + "static/retained-checkpoint-curve.vl.json": "6603c860ce76a434a11e6c96cf7418246ce2dd5da3d7a56a5f2448a0537ec183", + "tests/browser_retained_analysis.cjs": "822d6df2d8c29e909f6f0dcee42595f90c9eae70306ff9c8b20eba042bdd05ce", + "tests/retained_analysis_browser_fixture.py": "ececc679267b6e8671ab3fb189ca093f53bf874ad5d9469df0b36ff008f7ad62", + "tests/fixtures/retained-analysis-browser.js": "20693914724c187875e53b79198280c197b93256cc542bbdb74e7799b9789e8b", + "examples/analysis/retained_checkpoint_curve.py": "dce74b88c13f85f272734da5876d96bfcef746074ece0027f9f57532de767f8f", + "static/vendor/retained-analysis/manifest.json": "298dbcaf1a3852db247cd781ef60c620d67c6ddfdcd646cae38a321368a280a5" + }, + "standards_pin": "dcc56f26e884ade260770beceba2501d3746200d", + "standards_sha256": { + "CORE-STANDARDS.md": "8d81c8b558269cf45aa768f67399e6ea120acf2318e0e4c3030b8114a083a14d", + "STANDARDS-ROUTER.md": "35f014a0090301e89815700ff60aa5f043f3c033660c20ab144e6e6461df2181", + "profiles/applications/frontend.md": "32ab0d4e9f24dfcd48661f8fd3ea7547c0b6f7fc995b6c8e1d3bc0938606797b", + "profiles/boundaries/ipc.md": "2f6d0391e6a01fecf259386f314daccdcd0ed5c0b58ac0fadc6816b8171347e4", + "profiles/boundaries/persistence.md": "9ec9473c865a4293433d0f22d0b82b6089fce9a72b47c7f735612a20faf1734b", + "templates/PLAN-TEMPLATE.md": "c12c0365bb558c8ef973647fc74af9678cd1c35f54d17b104afdd3ed373f4f50", + "topics/accessibility.md": "e1dac1dc41f883418d3b753db8ffa53d485b4f3afec2e48b1c0fee371771f6d6", + "topics/architecture/replay.md": "678edd13bdaf6db9604c8dd4e98cc68e358d6e39eba8089d4f0ab69b52a085c5", + "topics/architecture.md": "d35471532ba216056a4a88474fac15f2aada1de866ada136efb31ce26dc06036", + "topics/code-design.md": "659f47b7d53abc05627cb3672aab33265062f92001b4d212d4c52ffd8c2de8e0", + "topics/concurrency.md": "e0cd8f80f95c0acc8d6c246e871f1d674861d8019a906137127aa51ad4065e0c", + "topics/contracts/evolution.md": "9789fccbc295188ec264a50d0e4183021e6bc136807d49eb7417b1159f0e86b8", + "topics/contracts/protocols.md": "a49bb7b346c3fcacc39cc4402d8338b211df98299185aa0b6a5549d52e520194", + "topics/contracts.md": "3190700189e589d7baec3551ff6330ca7afd64d8f425566cb621db9dd1399532", + "topics/dependencies.md": "b9698a1985aec38491f2d66d141978952fa691bef99ee7222f67e992d552b07f", + "topics/licensing.md": "80e8558198346fd6f5f57d5756fcf81d0929ebcbc4ca18288e22aba946bd4cb7", + "topics/performance.md": "ff1ce8f1e7592c14bbb8f84fd2d6fef2434e861c29ddf517fe5f9ba9d983ae40", + "topics/resilience.md": "573d59e334455d8f35c4e9213ce7f68a6edb23c36a36abdf72104af3f27685e8", + "topics/security/untrusted-execution.md": "c743d6232b20a22e19f1a34cb834a6fd48c3de483289893f42cec5580feb0c4b", + "topics/security.md": "1ae23154bf405dd3722819189ae4bd1859b7777aecbf0b5951b532c6aece16e7", + "workflows/commit.md": "c2e86c065db1e2907201beaa8efb872acffaaff650959c15407c48384c870757", + "workflows/development-proportionality.md": "bdd29ec308d035e5ab9b5375560321a459a82a7ef29fb941b9c858fb417eea94", + "workflows/documentation.md": "154f4d866ef99ccfde5f85cc01de2e5480e25e8c116cd5b9082b9e69d42faf6b", + "workflows/implementation.md": "02bc0feb1f411072b082236da5354ab44b1a4cdfe4a07afab70108631c80e532", + "workflows/planning.md": "59d2cbd6b7525e41b41761b0caf7471ddde9c4e33290ba4a16c812937abc4403", + "workflows/verification/gui.md": "042d4fb92f880a07d1f025ace5c02aa211fadf921dd4a98701755f2e2edcbe8a", + "workflows/verification/oracles.md": "f5cfd7d06a894f8f63ed14ebefafb6c861015bcd9746862e23d3918d1397f191", + "workflows/verification.md": "798071f8beed08fca9937ad5ea9d6d6a42b99157b82a3f2dc80c46412f475f8b" + }, + "scope": "Query boundary fixtures and actual browser over authored data; not actual PostgreSQL/Run acceptance", + "blockers": [ + "Existing authorized PostgreSQL/training environment unavailable", + "Shared API/contract/Run mount hooks pending lead coordination via parent" + ], + "no_credential_permission_schema_changes": true +} diff --git a/examples/analysis/requirements.txt b/examples/analysis/requirements.txt new file mode 100644 index 00000000..808189ee --- /dev/null +++ b/examples/analysis/requirements.txt @@ -0,0 +1,2 @@ +# Authoring only; never installed or invoked when a Run view opens. +altair==5.5.0 diff --git a/examples/analysis/retained_checkpoint_curve.py b/examples/analysis/retained_checkpoint_curve.py new file mode 100644 index 00000000..bd197717 --- /dev/null +++ b/examples/analysis/retained_checkpoint_curve.py @@ -0,0 +1,30 @@ +"""Build the first inert chart specification; data comes from the named query. + +Run explicitly with the authoring requirements installed, then review the JSON +and update the renderer's allowed spec digest. No database or Run is opened. +""" +import argparse +import json +from pathlib import Path + +import altair as alt + + +def specification(): + selection = alt.selection_point(name='checkpoint_select', fields=['checkpoint_sha256'], + on='click', clear=False, toggle=False) + base = alt.Chart(alt.NamedData(name='curve')).encode( + x=alt.X('epoch:Q', title='Retained epoch', axis=alt.Axis(tickMinStep=1)), + y=alt.Y('value:Q', title='Metric value', scale=alt.Scale(zero=False))) + line = base.mark_line(color='#60a5fa') + points = base.mark_point(filled=True, size=80).encode( + color=alt.condition(alt.datum.selected, alt.value('#fbbf24'), alt.value('#60a5fa'))).add_params(selection) + return (line + points).properties(width='container', height=200, + description='Retained checkpoint metric curve. Use the epoch buttons for exact values and keyboard selection.').to_dict() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('output', type=Path) + options = parser.parse_args() + options.output.write_text(json.dumps(specification(), sort_keys=True, separators=(',', ':'), allow_nan=False) + '\n') diff --git a/retained_analysis.py b/retained_analysis.py new file mode 100644 index 00000000..45297dcd --- /dev/null +++ b/retained_analysis.py @@ -0,0 +1,262 @@ +"""Inert, exact-result classifier curve and example query. + +Runs owns artifact verification. PostgreSQL owns the existing Run facts; this +query creates only disposable projections, never a second retained authority. +No caller-controlled SQL, identifiers, expressions, files or computation. +""" +from contextlib import contextmanager +import json +import math +import re +import time + +from psycopg.pq import TransactionStatus + +from model_evidence import canonical, digest +from pipeline import closed, identifier +from workbench import WorkbenchError + +QUERY_ID = 'retained_checkpoint_examples' +QUERY_VERSION = 1 +MAX_PAGE = 100 +MAX_OFFSET = 10000 +MAX_EXAMPLES = 10000 +MAX_CHECKPOINTS = 128 +MAX_RESPONSE_BYTES = 256 * 1024 +MAX_PROJECTION_BYTES = 2 * 1024 * 1024 +MAX_DOCUMENT_BYTES = 16 * 1024 * 1024 +SQL_TIMEOUT_MS = 2000 +LOCK_SECONDS = 2 +FIELDS = ('example_id', 'truth_index', 'predicted_index', 'confidence', 'error') +METRICS = ('accuracy', 'loss', 'macro_f1') +HASH = re.compile(r'^[a-f0-9]{64}$') + +# The metric name is a bound JSON lookup key, not SQL text. Checkpoint mapping +# comes from the verified retained index, while values come from catalog facts. +CURVE_SQL = ''' +WITH checkpoints AS ( + SELECT * FROM jsonb_to_recordset(%s::jsonb) + AS c(checkpoint_sha256 text, epoch integer) +) +SELECT c.checkpoint_sha256, c.epoch, + (h->'validation'->>%s)::double precision AS value, + (h->'validation'->>'examples')::integer AS support +FROM workspace_runs r +CROSS JOIN LATERAL jsonb_array_elements(r.document::jsonb->'metrics'->'history') h +JOIN checkpoints c ON c.epoch=(h->>'epoch')::integer +WHERE r.id=%s +ORDER BY c.epoch +LIMIT %s +''' + +# Only bounded scalar rows enter this projection. Large probability arrays and +# all original hash-bound bytes stay in managed evidence artifacts. +EXAMPLES_SQL = ''' +WITH examples AS ( + SELECT * FROM jsonb_to_recordset(%s::jsonb) + AS e(ordinal integer, example_id text, truth_index integer, + predicted_index integer, confidence double precision, error boolean, + frozen_reference jsonb) +), filtered AS ( + SELECT * FROM examples WHERE (NOT %s OR error) +), page AS ( + SELECT * FROM filtered ORDER BY ordinal LIMIT %s OFFSET %s +) +SELECT (SELECT count(*) FROM filtered) AS filtered_support, + coalesce((SELECT jsonb_agg(to_jsonb(p) ORDER BY p.ordinal) FROM page p), '[]'::jsonb) AS rows +''' + + +def validate_request(body): + """Decode a complete closed variant before any evidence or catalog read.""" + closed(body, ('query_id', 'query_version', 'run_id', 'evaluation_sha256', + 'checkpoint_sha256', 'metric_id', 'metric_definition_sha256'), + ('fields', 'errors_only', 'limit', 'offset')) + if (body['query_id'] != QUERY_ID or type(body['query_version']) is not int + or body['query_version'] != QUERY_VERSION): + raise WorkbenchError('Unsupported retained analysis query.', 'unsupported', 409) + identifier(body['run_id'], 'Run ID') + for key in ('evaluation_sha256', 'checkpoint_sha256', 'metric_definition_sha256'): + if type(body[key]) is not str or not HASH.fullmatch(body[key]): + raise WorkbenchError('Retained analysis requires exact SHA256 identities.') + if type(body['metric_id']) is not str or body['metric_id'] not in METRICS: + raise WorkbenchError('Choose a declared validation metric.') + fields = body.get('fields', list(FIELDS)) + if (type(fields) is not list or not fields or len(fields) > len(FIELDS) + or any(type(field) is not str or field not in FIELDS for field in fields) + or len(set(fields)) != len(fields) or 'example_id' not in fields): + raise WorkbenchError('Choose unique declared fields including example_id.') + limit, offset = body.get('limit', 50), body.get('offset', 0) + if type(limit) is not int or not 1 <= limit <= MAX_PAGE: + raise WorkbenchError('Retained analysis page limit must be 1–100.') + if type(offset) is not int or not 0 <= offset <= MAX_OFFSET: + raise WorkbenchError('Retained analysis offset must be 0–10000.') + errors_only = body.get('errors_only', False) + if type(errors_only) is not bool: + raise WorkbenchError('errors_only must be a boolean.') + return dict(body, fields=list(fields), limit=limit, offset=offset, errors_only=errors_only) + + +def _refuse(message, code='invalid', status=409): + raise WorkbenchError(message, code, status) + + +@contextmanager +def _read_snapshot(db): + with db.connection.transaction(): + db.execute('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ ONLY') + db.execute("SELECT set_config('statement_timeout', %s, true)", (str(SQL_TIMEOUT_MS),)) + db.execute("SELECT set_config('lock_timeout', %s, true)", (str(SQL_TIMEOUT_MS),)) + yield + + +def _retained_run(db, request): + # Refuse a stale result before the expensive existing artifact verifier. + # Repeat this check inside the SQL snapshot to close the intervening gap. + stored = db.execute('''SELECT CASE WHEN octet_length(document)<=%s THEN document ELSE NULL END AS document + FROM workspace_runs WHERE id=%s''', + (MAX_DOCUMENT_BYTES, request['run_id'])).fetchone() + if stored is None: + _refuse('Retained Run is unavailable.', 'not_found', 404) + if stored['document'] is None: + _refuse('Retained Run document exceeds this query budget.', 'limit', 413) + try: + run = json.loads(stored['document']) + artifact = [item for item in run['artifacts'] if item['name'] == 'model-evidence.json'] + state, run_id = run['state'], run['id'] + actual_hash = artifact[0]['sha256'] if len(artifact) == 1 else None + except (ValueError, KeyError, TypeError): + _refuse('Retained Run envelope is unavailable.', 'unavailable', 409) + if actual_hash != request['evaluation_sha256']: + _refuse('Retained evaluation snapshot differs.', 'stale') + if state != 'completed' or run_id != request['run_id']: + _refuse('Retained analysis requires a completed Run.', 'unavailable', 503) + return run + + +def _projection(evidence, request): + """Project the native verified variant; other task owners remain explicit.""" + if (evidence.get('state') != 'verified' + or evidence.get('manifest', {}).get('format') != 'model_evidence_v1'): + _refuse('Retained analysis requires verified native classifier evidence.', 'unsupported') + definitions = [item for item in evidence['metric_definitions'] if item['id'] == request['metric_id']] + if len(definitions) != 1 or digest(definitions[0]) != request['metric_definition_sha256']: + _refuse('Retained analysis metric definition differs.', 'stale') + definition = definitions[0] + if definition['split'] != 'validation': + _refuse('Retained analysis only supports frozen validation.', 'unsupported') + entries = evidence['checkpoint_index']['entries'] + if not 1 <= len(entries) <= MAX_CHECKPOINTS: + _refuse('Retained checkpoint count exceeds this query budget.', 'limit', 413) + checkpoints = [{'checkpoint_sha256': item['checkpoint']['sha256'], 'epoch': item['clocks']['epoch']} + for item in entries] + if any(type(item['epoch']) is not int or item['epoch'] < 1 for item in checkpoints): + _refuse('Retained analysis requires epoch-based classifier evidence.', 'unsupported') + if request['checkpoint_sha256'] not in {item['checkpoint_sha256'] for item in checkpoints}: + _refuse('Checkpoint does not belong to this result.', 'not_found', 404) + predictions = evidence['predictions'] + if (predictions is None or predictions['checkpoint_sha256'] != request['checkpoint_sha256'] + or predictions['probe_sha256'] != evidence['manifest']['probe']['sha256']): + _refuse('Selected checkpoint predictions differ.', 'stale') + members = evidence['probe']['members'] + if len(members) > MAX_EXAMPLES: + _refuse('Frozen example population exceeds this query budget.', 'limit', 413) + by_ordinal = {member['ordinal']: member for member in members} + if len(by_ordinal) != len(members) or len(predictions['rows']) != len(members): + _refuse('Frozen example membership differs.') + rows = [] + seen = set() + for row in predictions['rows']: + ordinal = row['ordinal'] + if ordinal not in by_ordinal or ordinal in seen: + _refuse('Frozen example ordinal differs.') + seen.add(ordinal) + frozen = by_ordinal[ordinal]['frozen_reference'] + confidence = row['probabilities'][row['predicted_index']] + if type(confidence) not in (int, float) or not math.isfinite(confidence) or not 0 <= confidence <= 1: + _refuse('Frozen prediction confidence differs.') + rows.append({'ordinal': ordinal, 'example_id': frozen['id'], 'frozen_reference': frozen, + 'truth_index': row['truth_index'], 'predicted_index': row['predicted_index'], + 'confidence': confidence, 'error': row['truth_index'] != row['predicted_index']}) + if len({row['example_id'] for row in rows}) != len(rows): + _refuse('Frozen example IDs are ambiguous.') + raw = canonical(rows) + if len(raw) > MAX_PROJECTION_BYTES: + _refuse('Frozen scalar projection exceeds this query budget.', 'limit', 413) + return definition, checkpoints, raw.decode('ascii') + + +def query(runs, body, *, export=False): + """Read one exact result; callable by a later explicitly registered HTTP hook. + + No cache or download URL is returned. An export must call this boundary + again. Final authorization happens outside the read snapshot, so revocation + committed during verification/query cannot be hidden by Repeatable Read. + """ + request = validate_request(body) + if type(export) is not bool: + raise TypeError('export must be a host-owned boolean') + action = 'runs.export_retained_analysis' if export else 'runs.retained_analysis' + run_id = request['run_id'] + db = runs.db + with db.lock.bounded(time.monotonic() + LOCK_SECONDS): + runs.access.require('inspect', action, run_id) + # SET TRANSACTION must own its snapshot, never alter a caller's write + # transaction or check current revocation inside an inherited snapshot. + if db.connection.info.transaction_status != TransactionStatus.IDLE: + _refuse('Retained analysis requires a standalone read.', 'unavailable', 503) + with _read_snapshot(db): + _retained_run(db, request) + evidence = runs.model_evidence(run_id, {'checkpoint_sha256': request['checkpoint_sha256']}, + contract_version=1) + definition, checkpoints, example_json = _projection(evidence, request) + with _read_snapshot(db): + _retained_run(db, request) + curve = [dict(row) for row in db.execute(CURVE_SQL, + (canonical(checkpoints).decode('ascii'), request['metric_id'], run_id, MAX_CHECKPOINTS + 1))] + expected = {item['checkpoint_sha256']: item for item in evidence['observations'] + if item['metric_id'] == request['metric_id'] and item['split'] == 'validation'} + if len(curve) != len(checkpoints): + _refuse('Catalog curve coverage differs from retained checkpoints.') + for point in curve: + observation = expected.get(point['checkpoint_sha256']) + if (observation is None or observation['state'] != 'observed' + or point['epoch'] != observation['clocks']['epoch'] + or point['value'] != observation['value'] or point['support'] != observation['sample_count']): + _refuse('Catalog curve differs from retained metric observations.') + page = db.execute(EXAMPLES_SQL, (example_json, request['errors_only'], + request['limit'], request['offset'])).fetchone() + selected_rows = [{key: row[key] for key in (*request['fields'], 'ordinal', 'frozen_reference')} + for row in page['rows']] + provenance = {'catalog_id': db.dataset_id, 'run_id': run_id, + 'evaluation_sha256': request['evaluation_sha256'], + 'checkpoint_sha256': request['checkpoint_sha256'], + 'metric_definition_sha256': request['metric_definition_sha256'], + 'population_sha256': definition['population_sha256'], + 'probe_sha256': evidence['manifest']['probe']['sha256'], + 'data_sha256': evidence['manifest']['data_sha256'], + 'producer': evidence['manifest']['producer']} + count = page['filtered_support'] + result = {'state': 'verified', 'query_id': QUERY_ID, 'query_version': QUERY_VERSION, + 'mode': 'frozen', 'provenance': provenance, + 'metric': {'id': definition['id'], 'units': definition['units'], + 'definition': definition, 'support': len(evidence['probe']['members'])}, + 'curve': curve, 'columns': _columns(request['fields']), + 'examples': {'rows': selected_rows, 'population_support': len(evidence['probe']['members']), + 'filtered_support': count, 'offset': request['offset'], 'limit': request['limit'], + 'next_offset': request['offset'] + len(selected_rows) + if request['offset'] + len(selected_rows) < count else None, + 'filters': {'errors_only': request['errors_only']}}, + 'sampling': {'method': 'none', 'population': 'frozen_validation_probe'}, + 'selection_sha256': digest(request)} + if len(canonical(result)) > MAX_RESPONSE_BYTES: + _refuse('Retained analysis response exceeds this query budget.', 'limit', 413) + runs.access.require('inspect', action, run_id) + return result + + +def _columns(fields): + types = {'example_id': 'string', 'truth_index': 'integer', 'predicted_index': 'integer', + 'confidence': 'number', 'error': 'boolean'} + return [{'field': field, 'type': types[field], + 'units': 'dimensionless' if field == 'confidence' else None} for field in fields] diff --git a/static/retained-analysis.js b/static/retained-analysis.js new file mode 100644 index 00000000..4617bba0 --- /dev/null +++ b/static/retained-analysis.js @@ -0,0 +1,187 @@ +/* Host-owned renderer for one pinned Altair recipe. No dynamic chart plugins. */ +(() => { + 'use strict'; + const SPEC_PATH = '/static/retained-checkpoint-curve.vl.json'; + const SPEC_SHA256 = '6603c860ce76a434a11e6c96cf7418246ce2dd5da3d7a56a5f2448a0537ec183'; + const HASH = /^[a-f0-9]{64}$/; + const MAX_BYTES = 256 * 1024; + const fields = ['example_id', 'truth_index', 'predicted_index', 'confidence', 'error']; + const types = ['string', 'integer', 'integer', 'number', 'boolean']; + const own = (value, key) => Object.prototype.hasOwnProperty.call(value, key); + const object = value => value !== null && typeof value === 'object' && !Array.isArray(value); + const integer = value => Number.isSafeInteger(value) && value >= 0; + const finite = value => typeof value === 'number' && Number.isFinite(value); + const fail = () => { throw Error('Retained analysis response is invalid or exceeds its budget.'); }; + function validate(value, request) { + if (!object(value) || new TextEncoder().encode(JSON.stringify(value)).length > MAX_BYTES) fail(); + const keys = ['state', 'query_id', 'query_version', 'mode', 'provenance', 'metric', 'curve', 'columns', 'examples', 'sampling', 'selection_sha256']; + if (Object.keys(value).length !== keys.length || keys.some(key => !own(value, key))) fail(); + if (value.state !== 'verified' || value.query_id !== 'retained_checkpoint_examples' || value.query_version !== 1 || value.mode !== 'frozen') fail(); + const p = value.provenance; + if (!object(p) || ['evaluation_sha256', 'checkpoint_sha256', 'metric_definition_sha256'].some(key => p[key] !== request[key] || !HASH.test(p[key])) || p.run_id !== request.run_id) fail(); + if (typeof p.catalog_id !== 'string' || p.catalog_id.length > 64 || ['population_sha256', 'probe_sha256', 'data_sha256'].some(key => typeof p[key] !== 'string' || !HASH.test(p[key]))) fail(); + if (!object(p.producer) || p.producer.catalog_id !== p.catalog_id || p.producer.run_id !== p.run_id || ['material_sha256', 'adapter_sha256'].some(key => typeof p.producer[key] !== 'string' || !HASH.test(p.producer[key]))) fail(); + if (!object(value.metric) || value.metric.id !== request.metric_id || typeof value.metric.units !== 'string' || value.metric.units.length > 64 || !integer(value.metric.support) || value.metric.support > 10000) fail(); + if (!object(value.metric.definition) || value.metric.definition.id !== value.metric.id || value.metric.definition.split !== 'validation' || value.metric.definition.units !== value.metric.units || value.metric.definition.population_sha256 !== p.population_sha256) fail(); + if (!Array.isArray(value.curve) || value.curve.length < 1 || value.curve.length > 128) fail(); + const checkpoints = new Set(); + let previous = 0; + for (const point of value.curve) { + if (!object(point) || typeof point.checkpoint_sha256 !== 'string' || !HASH.test(point.checkpoint_sha256) || checkpoints.has(point.checkpoint_sha256) || !integer(point.epoch) || point.epoch <= previous || !finite(point.value) || point.support !== value.metric.support) fail(); + checkpoints.add(point.checkpoint_sha256); previous = point.epoch; + } + if (!checkpoints.has(request.checkpoint_sha256) || !HASH.test(value.selection_sha256)) fail(); + const e = value.examples; + if (!object(e) || !Array.isArray(e.rows) || !integer(e.limit) || e.limit < 1 || e.limit > 100 || e.rows.length > e.limit || !integer(e.offset) || e.offset > 10000 || !integer(e.population_support) || e.population_support > 10000 || !integer(e.filtered_support) || e.filtered_support > e.population_support) fail(); + if (!object(e.filters) || e.filters.errors_only !== (request.errors_only ?? false) || e.offset !== (request.offset ?? 0) || e.limit !== (request.limit ?? 50) || e.population_support !== value.metric.support) fail(); + if (!e.filters.errors_only && e.filtered_support !== e.population_support) fail(); + if (e.rows.length > Math.max(0, e.filtered_support - e.offset)) fail(); + const next = e.offset + e.rows.length < e.filtered_support ? e.offset + e.rows.length : null; + if (e.next_offset !== next || (next !== null && e.rows.length === 0)) fail(); + if (!Array.isArray(value.columns) || value.columns.length > fields.length || value.columns.length < 1) fail(); + const selected = request.fields ?? fields; + if (value.columns.length !== selected.length || value.columns.some((column, index) => !object(column) || column.field !== selected[index] || !fields.includes(column.field) || column.type !== types[fields.indexOf(column.field)] || column.units !== (column.field === 'confidence' ? 'dimensionless' : null))) fail(); + const seen = new Set(); + let ordinal = -1; + for (const row of e.rows) { + if (!object(row) || typeof row.example_id !== 'string' || row.example_id.length > 200 || seen.has(row.example_id) || !integer(row.ordinal) || row.ordinal >= e.population_support || row.ordinal <= ordinal || !object(row.frozen_reference) || row.frozen_reference.id !== row.example_id) fail(); + if (own(row, 'confidence') && (!finite(row.confidence) || row.confidence < 0 || row.confidence > 1)) fail(); + if (own(row, 'truth_index') && !integer(row.truth_index) || own(row, 'predicted_index') && !integer(row.predicted_index) || own(row, 'error') && typeof row.error !== 'boolean') fail(); + if (selected.some(field => !own(row, field))) fail(); + if (e.filters.errors_only && own(row, 'error') && !row.error) fail(); + seen.add(row.example_id); ordinal = row.ordinal; + } + if (!object(value.sampling) || value.sampling.method !== 'none' || value.sampling.population !== 'frozen_validation_probe') fail(); + return value; + } + function node(tag, text, attributes = {}) { + const element = document.createElement(tag); + if (text !== undefined) element.textContent = text; + for (const [key, value] of Object.entries(attributes)) element.setAttribute(key, value); + return element; + } + async function specification(signal) { + const reply = await fetch(SPEC_PATH, {signal, credentials: 'same-origin', cache: 'no-cache'}); + if (!reply.ok) throw Error('Retained chart specification is unavailable.'); + const reader = reply.body.getReader(); + let raw = new Uint8Array(0); + while (true) { + const {value, done} = await reader.read(); + if (done) break; + if (raw.byteLength + value.byteLength > 16384) { + await reader.cancel(); + throw Error('Retained chart specification exceeds its budget.'); + } + const next = new Uint8Array(raw.byteLength + value.byteLength); + next.set(raw); next.set(value, raw.byteLength); raw = next; + } + const hash = [...new Uint8Array(await crypto.subtle.digest('SHA-256', raw))].map(byte => byte.toString(16).padStart(2, '0')).join(''); + if (hash !== SPEC_SHA256) throw Error('Retained chart specification identity differs.'); + return JSON.parse(new TextDecoder().decode(raw)); + } + function mount(root, {load, onSelection = () => {}}) { + let disposed = false, generation = 0, pending, view, observer, current; + function clear() { + view?.finalize(); view = undefined; + observer?.disconnect(); observer = undefined; + current = undefined; + root.replaceChildren(); + } + async function update(body, authorityKey) { + if (disposed) return; + const request = structuredClone(body), ticket = ++generation; + pending?.abort(); pending = new AbortController(); + const signal = pending.signal; + clear(); root.setAttribute('aria-busy', 'true'); + root.append(node('p', 'Loading exact retained result…', {role: 'status'})); + const active = () => !disposed && ticket === generation && !signal.aborted; + try { + const [received, base] = await Promise.all([load(request, {signal, authorityKey, export: false}), specification(signal)]); + if (!active()) return; + const data = validate(received, request); + clear(); + const heading = node('h3', 'Retained checkpoint analysis', {tabindex: '-1'}); + const status = node('p', `Frozen validation probe · ${data.metric.support} examples · ${data.metric.units}`, {role: 'status'}); + const chart = node('div', undefined, {role: 'img', 'aria-label': 'Checkpoint curve; exact values and keyboard selection follow.'}); + const buttons = node('div', undefined, {'aria-label': 'Select retained epoch'}); + const choose = sha => { + if (!active() || sha === request.checkpoint_sha256) return; + onSelection({checkpoint_sha256: sha}); + void update({...request, checkpoint_sha256: sha, offset: 0}, authorityKey).then(() => root.querySelector('h3')?.focus()); + }; + for (const point of data.curve) { + const button = node('button', `Epoch ${point.epoch}: ${point.value} · support ${point.support}`, {type: 'button', 'aria-pressed': String(point.checkpoint_sha256 === request.checkpoint_sha256)}); + button.addEventListener('click', () => choose(point.checkpoint_sha256)); + buttons.append(button); + } + const filterLabel = node('label', ' Show only errors '); + const filter = node('input', undefined, {type: 'checkbox'}); + filter.checked = request.errors_only ?? false; + filter.addEventListener('change', () => void update({...request, errors_only: filter.checked, offset: 0}, authorityKey).then(() => root.querySelector('input')?.focus())); + filterLabel.prepend(filter); + const support = node('p', `${data.examples.filtered_support} matching examples of ${data.examples.population_support}; curve statistics retain the full probe population.`); + const table = node('table'); + table.append(node('caption', 'Frozen examples at the selected checkpoint')); + const headers = node('tr'); + for (const column of data.columns) headers.append(node('th', column.field, {scope: 'col'})); + const head = node('thead'); head.append(headers); table.append(head); + const rows = node('tbody'); + for (const row of data.examples.rows) { + const tr = node('tr'); + for (const column of data.columns) tr.append(node('td', String(row[column.field]))); + rows.append(tr); + } + table.append(rows); + const navigation = node('div'); + for (const [label, offset] of [['Previous examples', Math.max(0, data.examples.offset - data.examples.limit)], ['Next examples', data.examples.next_offset]]) { + const button = node('button', label, {type: 'button'}); + button.disabled = offset === null || offset === data.examples.offset; + button.addEventListener('click', () => void update({...request, offset}, authorityKey)); navigation.append(button); + } + const exportButton = node('button', 'Export this page', {type: 'button'}); + exportButton.addEventListener('click', async () => { + exportButton.disabled = true; + try { + const fresh = validate(await load(request, {signal, authorityKey, export: true}), request); + if (!active()) return; + const url = URL.createObjectURL(new Blob([JSON.stringify(fresh)], {type: 'application/json'})); + const link = node('a', undefined, {href: url, download: 'retained-analysis-page.json'}); + root.append(link); link.click(); link.remove(); URL.revokeObjectURL(url); + } catch (error) { + if (active()) { clear(); root.append(node('p', 'Retained result access or export failed. Refresh with current access.', {role: 'alert'})); } + } finally { if (active()) exportButton.disabled = false; } + }); + const details = node('details'); details.append(node('summary', 'Exact retained provenance'), node('pre', JSON.stringify(data.provenance, null, 2))); + root.append(heading, status, chart, buttons, filterLabel, support, table, navigation, exportButton, details); + if (typeof window.vegaEmbed !== 'function' || typeof window.vega?.expressionInterpreter !== 'object') throw Error('Pinned chart assets are unavailable.'); + base.datasets = {curve: data.curve.map(point => ({...point, selected: point.checkpoint_sha256 === request.checkpoint_sha256}))}; + // Data, images and links cannot leave the controlled inline dataset. + const deny = () => Promise.reject(Error('Chart URL loading is disabled.')); + const embedded = await window.vegaEmbed(chart, base, {actions: false, defaultStyle: false, tooltip: false, mode: 'vega-lite', renderer: 'svg', ast: true, expr: window.vega.expressionInterpreter, loader: {load: deny, sanitize: deny}}); + if (!active()) { embedded.finalize(); return; } + view = embedded.view; + view.addSignalListener('checkpoint_select', (_name, value) => { + const sha = value?.checkpoint_sha256?.[0]; + if (data.curve.some(point => point.checkpoint_sha256 === sha)) choose(sha); + }); + observer = new ResizeObserver(() => { + if (active()) void view?.resize().runAsync().catch(() => { if (active()) { clear(); root.append(node('p', 'Retained chart resize failed.', {role: 'alert'})); } }); + }); + observer.observe(chart); + current = {request, authorityKey}; + } catch (error) { + if (active()) { + clear(); root.append(node('p', String(error.message || 'Retained analysis unavailable.'), {role: 'alert'})); + root.setAttribute('aria-busy', 'false'); pending.abort(); + } + } finally { if (active()) root.setAttribute('aria-busy', 'false'); } + } + return { + update, + resize() { return view?.resize().runAsync(); }, + selection() { return current ? structuredClone(current.request) : null; }, + dispose() { disposed = true; ++generation; pending?.abort(); clear(); root.removeAttribute('aria-busy'); } + }; + } + window.WorkspaceRetainedAnalysis = Object.freeze({mount}); +})(); diff --git a/static/retained-checkpoint-curve.vl.json b/static/retained-checkpoint-curve.vl.json new file mode 100644 index 00000000..8628e384 --- /dev/null +++ b/static/retained-checkpoint-curve.vl.json @@ -0,0 +1 @@ +{"$schema":"https://vega.github.io/schema/vega-lite/v5.20.1.json","config":{"view":{"continuousHeight":300,"continuousWidth":300}},"data":{"name":"curve"},"description":"Retained checkpoint metric curve. Use the epoch buttons for exact values and keyboard selection.","height":200,"layer":[{"encoding":{"x":{"axis":{"tickMinStep":1},"field":"epoch","title":"Retained epoch","type":"quantitative"},"y":{"field":"value","scale":{"zero":false},"title":"Metric value","type":"quantitative"}},"mark":{"color":"#60a5fa","type":"line"}},{"encoding":{"color":{"condition":{"test":"datum.selected","value":"#fbbf24"},"value":"#60a5fa"},"x":{"axis":{"tickMinStep":1},"field":"epoch","title":"Retained epoch","type":"quantitative"},"y":{"field":"value","scale":{"zero":false},"title":"Metric value","type":"quantitative"}},"mark":{"filled":true,"size":80,"type":"point"},"name":"view_1"}],"params":[{"name":"checkpoint_select","select":{"clear":false,"fields":["checkpoint_sha256"],"on":"click","toggle":false,"type":"point"},"views":["view_1"]}],"width":"container"} diff --git a/static/vendor/retained-analysis/licenses/d3-array.txt b/static/vendor/retained-analysis/licenses/d3-array.txt new file mode 100644 index 00000000..97e0a36c --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-array.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2023 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-color.txt b/static/vendor/retained-analysis/licenses/d3-color.txt new file mode 100644 index 00000000..8ee860fc --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-color.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2022 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-delaunay.txt b/static/vendor/retained-analysis/licenses/d3-delaunay.txt new file mode 100644 index 00000000..65b9c72e --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-delaunay.txt @@ -0,0 +1,15 @@ +LICENSE +Copyright 2018-2021 Observable, Inc. +Copyright 2021 Mapbox + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-dispatch.txt b/static/vendor/retained-analysis/licenses/d3-dispatch.txt new file mode 100644 index 00000000..16bdfa50 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-dispatch.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2021 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-dsv.txt b/static/vendor/retained-analysis/licenses/d3-dsv.txt new file mode 100644 index 00000000..23a34683 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-dsv.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2013-2021 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-force.txt b/static/vendor/retained-analysis/licenses/d3-force.txt new file mode 100644 index 00000000..16bdfa50 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-force.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2021 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-format.txt b/static/vendor/retained-analysis/licenses/d3-format.txt new file mode 100644 index 00000000..a33c9924 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-format.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2026 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-geo-projection.txt b/static/vendor/retained-analysis/licenses/d3-geo-projection.txt new file mode 100644 index 00000000..3763f6af --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-geo-projection.txt @@ -0,0 +1,38 @@ +LICENSE +Copyright 2013-2021 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +MIT License for https://github.com/scijs/integrate-adaptive-simpson + +The MIT License (MIT) + +Copyright 2015 Ricky Reusser + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-geo.txt b/static/vendor/retained-analysis/licenses/d3-geo.txt new file mode 100644 index 00000000..45e3fd76 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-geo.txt @@ -0,0 +1,35 @@ +LICENSE +Copyright 2010-2024 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +This license applies to GeographicLib, versions 1.12 and later. + +Copyright 2008-2012 Charles Karney + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-hierarchy.txt b/static/vendor/retained-analysis/licenses/d3-hierarchy.txt new file mode 100644 index 00000000..16bdfa50 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-hierarchy.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2021 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-interpolate.txt b/static/vendor/retained-analysis/licenses/d3-interpolate.txt new file mode 100644 index 00000000..16bdfa50 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-interpolate.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2021 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-path.txt b/static/vendor/retained-analysis/licenses/d3-path.txt new file mode 100644 index 00000000..16934264 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-path.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2015-2022 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-quadtree.txt b/static/vendor/retained-analysis/licenses/d3-quadtree.txt new file mode 100644 index 00000000..16bdfa50 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-quadtree.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2021 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-scale-chromatic.txt b/static/vendor/retained-analysis/licenses/d3-scale-chromatic.txt new file mode 100644 index 00000000..dea725e3 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-scale-chromatic.txt @@ -0,0 +1,29 @@ +LICENSE +Copyright 2010-2024 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +Apache-Style Software License for ColorBrewer software and ColorBrewer Color Schemes + +Copyright 2002 Cynthia Brewer, Mark Harrower, and The Pennsylvania State University + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. diff --git a/static/vendor/retained-analysis/licenses/d3-scale.txt b/static/vendor/retained-analysis/licenses/d3-scale.txt new file mode 100644 index 00000000..16bdfa50 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-scale.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2021 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-shape.txt b/static/vendor/retained-analysis/licenses/d3-shape.txt new file mode 100644 index 00000000..8ee860fc --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-shape.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2022 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-time-format.txt b/static/vendor/retained-analysis/licenses/d3-time-format.txt new file mode 100644 index 00000000..16bdfa50 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-time-format.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2021 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-time.txt b/static/vendor/retained-analysis/licenses/d3-time.txt new file mode 100644 index 00000000..8ee860fc --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-time.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2022 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/d3-timer.txt b/static/vendor/retained-analysis/licenses/d3-timer.txt new file mode 100644 index 00000000..16bdfa50 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/d3-timer.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2010-2021 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/delaunator.txt b/static/vendor/retained-analysis/licenses/delaunator.txt new file mode 100644 index 00000000..1d230d36 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/delaunator.txt @@ -0,0 +1,16 @@ +LICENSE +ISC License + +Copyright (c) 2026, Mapbox + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/fast-json-patch.txt b/static/vendor/retained-analysis/licenses/fast-json-patch.txt new file mode 100644 index 00000000..fb6bd4df --- /dev/null +++ b/static/vendor/retained-analysis/licenses/fast-json-patch.txt @@ -0,0 +1,23 @@ +LICENSE.txt +(The MIT License) + +Copyright (c) 2013, 2014, 2020 Joachim Wester + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/internmap.txt b/static/vendor/retained-analysis/licenses/internmap.txt new file mode 100644 index 00000000..cb979506 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/internmap.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2021 Mike Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/json-stringify-pretty-compact.txt b/static/vendor/retained-analysis/licenses/json-stringify-pretty-compact.txt new file mode 100644 index 00000000..8313ca19 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/json-stringify-pretty-compact.txt @@ -0,0 +1,22 @@ +LICENSE +The MIT License (MIT) + +Copyright (c) 2014, 2016, 2017, 2019, 2021, 2022 Simon Lydell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/robust-predicates.txt b/static/vendor/retained-analysis/licenses/robust-predicates.txt new file mode 100644 index 00000000..0e9e4a32 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/robust-predicates.txt @@ -0,0 +1,25 @@ +LICENSE +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/static/vendor/retained-analysis/licenses/semver.txt b/static/vendor/retained-analysis/licenses/semver.txt new file mode 100644 index 00000000..b9c30165 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/semver.txt @@ -0,0 +1,16 @@ +LICENSE +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/topojson-client.txt b/static/vendor/retained-analysis/licenses/topojson-client.txt new file mode 100644 index 00000000..12f428af --- /dev/null +++ b/static/vendor/retained-analysis/licenses/topojson-client.txt @@ -0,0 +1,14 @@ +LICENSE +Copyright 2012-2019 Michael Bostock + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/static/vendor/retained-analysis/licenses/vega-canvas.txt b/static/vendor/retained-analysis/licenses/vega-canvas.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-canvas.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-crossfilter.txt b/static/vendor/retained-analysis/licenses/vega-crossfilter.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-crossfilter.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-embed.txt b/static/vendor/retained-analysis/licenses/vega-embed.txt new file mode 100644 index 00000000..93d1ed4c --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-embed.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-encode.txt b/static/vendor/retained-analysis/licenses/vega-encode.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-encode.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-event-selector.txt b/static/vendor/retained-analysis/licenses/vega-event-selector.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-event-selector.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-force.txt b/static/vendor/retained-analysis/licenses/vega-force.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-force.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-geo.txt b/static/vendor/retained-analysis/licenses/vega-geo.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-geo.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-hierarchy.txt b/static/vendor/retained-analysis/licenses/vega-hierarchy.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-hierarchy.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-interpreter.txt b/static/vendor/retained-analysis/licenses/vega-interpreter.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-interpreter.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-label.txt b/static/vendor/retained-analysis/licenses/vega-label.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-label.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-lite.txt b/static/vendor/retained-analysis/licenses/vega-lite.txt new file mode 100644 index 00000000..31977bae --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-lite.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015, University of Washington Interactive Data Lab. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-parser.txt b/static/vendor/retained-analysis/licenses/vega-parser.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-parser.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-projection.txt b/static/vendor/retained-analysis/licenses/vega-projection.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-projection.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-regression.txt b/static/vendor/retained-analysis/licenses/vega-regression.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-regression.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-runtime.txt b/static/vendor/retained-analysis/licenses/vega-runtime.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-runtime.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-schema-url-parser.txt b/static/vendor/retained-analysis/licenses/vega-schema-url-parser.txt new file mode 100644 index 00000000..2fc25470 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-schema-url-parser.txt @@ -0,0 +1,30 @@ +LICENSE +BSD 3-Clause License + +Copyright (c) 2017, Vega +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-statistics.txt b/static/vendor/retained-analysis/licenses/vega-statistics.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-statistics.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-themes.txt b/static/vendor/retained-analysis/licenses/vega-themes.txt new file mode 100644 index 00000000..854a7eeb --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-themes.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2016, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-tooltip.txt b/static/vendor/retained-analysis/licenses/vega-tooltip.txt new file mode 100644 index 00000000..243f3563 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-tooltip.txt @@ -0,0 +1,12 @@ +LICENSE +Copyright 2016 Interactive Data Lab and contributors + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-transforms.txt b/static/vendor/retained-analysis/licenses/vega-transforms.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-transforms.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-view-transforms.txt b/static/vendor/retained-analysis/licenses/vega-view-transforms.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-view-transforms.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-view.txt b/static/vendor/retained-analysis/licenses/vega-view.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-view.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-voronoi.txt b/static/vendor/retained-analysis/licenses/vega-voronoi.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-voronoi.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega-wordcloud.txt b/static/vendor/retained-analysis/licenses/vega-wordcloud.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega-wordcloud.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/licenses/vega.txt b/static/vendor/retained-analysis/licenses/vega.txt new file mode 100644 index 00000000..da413b34 --- /dev/null +++ b/static/vendor/retained-analysis/licenses/vega.txt @@ -0,0 +1,28 @@ +LICENSE +Copyright (c) 2015-2023, University of Washington Interactive Data Lab +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/static/vendor/retained-analysis/manifest.json b/static/vendor/retained-analysis/manifest.json new file mode 100644 index 00000000..0c013741 --- /dev/null +++ b/static/vendor/retained-analysis/manifest.json @@ -0,0 +1,420 @@ +{ + "purpose": "Self-hosted fixed retained-checkpoint recipe only", + "assets": [ + { + "package": "vega", + "version": "5.33.0", + "filename": "vega.min.js", + "sha256": "a71f14828abacac82fbe8adb07ce65cbb82561d8eef188053c4a1c09e0164dcb", + "tarball_sha256": "7b61f992d1a1e196e7f2eeb3d6176e5694949d0d4bbfea237a842d523dd6e1f3", + "source": "https://registry.npmjs.org/vega/-/vega-5.33.0.tgz", + "license": "BSD-3-Clause" + }, + { + "package": "vega-lite", + "version": "5.23.0", + "filename": "vega-lite.min.js", + "sha256": "58c27358e26f2d319cf62f45bc17a4c8362f08645001df2ec8d341eee4097c7f", + "tarball_sha256": "e4cbfdd8f6f1abe381c59cd558fd6a559c12b1496bfdf2e0c3295263a40fe4da", + "source": "https://registry.npmjs.org/vega-lite/-/vega-lite-5.23.0.tgz", + "license": "BSD-3-Clause" + }, + { + "package": "vega-embed", + "version": "6.29.0", + "filename": "vega-embed.min.js", + "sha256": "12d02acfbe3ec59ef9a37dd4822a2e04e2961b5bbb671bbe661d2221715b99da", + "tarball_sha256": "ecf1ee709c2bac9e0a4ead6908114b05b62c71493e10a8a4308109bb070f8eb1", + "source": "https://registry.npmjs.org/vega-embed/-/vega-embed-6.29.0.tgz", + "license": "BSD-3-Clause" + }, + { + "package": "vega-interpreter", + "version": "1.2.0", + "filename": "vega-interpreter.min.js", + "sha256": "13002339c7e6231ef919584cbdf7391b246ea5073f686ffd707c62628b7f87df", + "tarball_sha256": "1eebed53f379d1c95ac7bba508b47eae8d4f8a19ecb1ec29b60b0be8b6334e5d", + "source": "https://registry.npmjs.org/vega-interpreter/-/vega-interpreter-1.2.0.tgz", + "license": "BSD-3-Clause" + } + ], + "notices": [ + { + "package": "d3-array", + "version": "3.2.4", + "license": "ISC", + "notice_file": "d3-array.txt" + }, + { + "package": "d3-color", + "version": "3.1.0", + "license": "ISC", + "notice_file": "d3-color.txt" + }, + { + "package": "d3-delaunay", + "version": "6.0.4", + "license": "ISC", + "notice_file": "d3-delaunay.txt" + }, + { + "package": "d3-dispatch", + "version": "3.0.1", + "license": "ISC", + "notice_file": "d3-dispatch.txt" + }, + { + "package": "d3-dsv", + "version": "3.0.1", + "license": "ISC", + "notice_file": "d3-dsv.txt" + }, + { + "package": "d3-force", + "version": "3.0.0", + "license": "ISC", + "notice_file": "d3-force.txt" + }, + { + "package": "d3-format", + "version": "3.1.2", + "license": "ISC", + "notice_file": "d3-format.txt" + }, + { + "package": "d3-geo", + "version": "3.1.1", + "license": "ISC", + "notice_file": "d3-geo.txt" + }, + { + "package": "d3-geo-projection", + "version": "4.0.0", + "license": "ISC", + "notice_file": "d3-geo-projection.txt" + }, + { + "package": "d3-hierarchy", + "version": "3.1.2", + "license": "ISC", + "notice_file": "d3-hierarchy.txt" + }, + { + "package": "d3-interpolate", + "version": "3.0.1", + "license": "ISC", + "notice_file": "d3-interpolate.txt" + }, + { + "package": "d3-path", + "version": "3.1.0", + "license": "ISC", + "notice_file": "d3-path.txt" + }, + { + "package": "d3-quadtree", + "version": "3.0.1", + "license": "ISC", + "notice_file": "d3-quadtree.txt" + }, + { + "package": "d3-scale", + "version": "4.0.2", + "license": "ISC", + "notice_file": "d3-scale.txt" + }, + { + "package": "d3-scale-chromatic", + "version": "3.1.0", + "license": "ISC", + "notice_file": "d3-scale-chromatic.txt" + }, + { + "package": "d3-shape", + "version": "3.2.0", + "license": "ISC", + "notice_file": "d3-shape.txt" + }, + { + "package": "d3-time", + "version": "3.1.0", + "license": "ISC", + "notice_file": "d3-time.txt" + }, + { + "package": "d3-time-format", + "version": "4.1.0", + "license": "ISC", + "notice_file": "d3-time-format.txt" + }, + { + "package": "d3-timer", + "version": "3.0.1", + "license": "ISC", + "notice_file": "d3-timer.txt" + }, + { + "package": "delaunator", + "version": "5.1.0", + "license": "ISC", + "notice_file": "delaunator.txt" + }, + { + "package": "fast-json-patch", + "version": "3.1.1", + "license": "MIT", + "notice_file": "fast-json-patch.txt" + }, + { + "package": "internmap", + "version": "2.0.3", + "license": "ISC", + "notice_file": "internmap.txt" + }, + { + "package": "json-stringify-pretty-compact", + "version": "4.0.0", + "license": "MIT", + "notice_file": "json-stringify-pretty-compact.txt" + }, + { + "package": "robust-predicates", + "version": "3.0.3", + "license": "Unlicense", + "notice_file": "robust-predicates.txt" + }, + { + "package": "semver", + "version": "7.8.5", + "license": "ISC", + "notice_file": "semver.txt" + }, + { + "package": "topojson-client", + "version": "3.1.0", + "license": "ISC", + "notice_file": "topojson-client.txt" + }, + { + "package": "vega", + "version": "5.33.0", + "license": "BSD-3-Clause", + "notice_file": "vega.txt" + }, + { + "package": "vega-canvas", + "version": "1.2.7", + "license": "BSD-3-Clause", + "notice_file": "vega-canvas.txt" + }, + { + "package": "vega-crossfilter", + "version": "4.1.4", + "license": "BSD-3-Clause", + "notice_file": "vega-crossfilter.txt" + }, + { + "package": "vega-dataflow", + "version": "5.7.8", + "license": "BSD-3-Clause", + "notice_file": "vega.txt", + "notice_source": "Vega monorepo BSD-3-Clause notice in upstream vega@5.33.0 distribution" + }, + { + "package": "vega-embed", + "version": "6.29.0", + "license": "BSD-3-Clause", + "notice_file": "vega-embed.txt" + }, + { + "package": "vega-encode", + "version": "4.10.3", + "license": "BSD-3-Clause", + "notice_file": "vega-encode.txt" + }, + { + "package": "vega-event-selector", + "version": "3.0.1", + "license": "BSD-3-Clause", + "notice_file": "vega-event-selector.txt" + }, + { + "package": "vega-expression", + "version": "5.2.1", + "license": "BSD-3-Clause", + "notice_file": "vega.txt", + "notice_source": "Vega monorepo BSD-3-Clause notice in upstream vega@5.33.0 distribution" + }, + { + "package": "vega-force", + "version": "4.2.3", + "license": "BSD-3-Clause", + "notice_file": "vega-force.txt" + }, + { + "package": "vega-format", + "version": "1.1.4", + "license": "BSD-3-Clause", + "notice_file": "vega.txt", + "notice_source": "Vega monorepo BSD-3-Clause notice in upstream vega@5.33.0 distribution" + }, + { + "package": "vega-functions", + "version": "5.18.1", + "license": "BSD-3-Clause", + "notice_file": "vega.txt", + "notice_source": "Vega monorepo BSD-3-Clause notice in upstream vega@5.33.0 distribution" + }, + { + "package": "vega-geo", + "version": "4.4.4", + "license": "BSD-3-Clause", + "notice_file": "vega-geo.txt" + }, + { + "package": "vega-hierarchy", + "version": "4.1.4", + "license": "BSD-3-Clause", + "notice_file": "vega-hierarchy.txt" + }, + { + "package": "vega-interpreter", + "version": "1.2.0", + "license": "BSD-3-Clause", + "notice_file": "vega-interpreter.txt" + }, + { + "package": "vega-label", + "version": "1.3.2", + "license": "BSD-3-Clause", + "notice_file": "vega-label.txt" + }, + { + "package": "vega-lite", + "version": "5.23.0", + "license": "BSD-3-Clause", + "notice_file": "vega-lite.txt" + }, + { + "package": "vega-loader", + "version": "4.5.4", + "license": "BSD-3-Clause", + "notice_file": "vega.txt", + "notice_source": "Vega monorepo BSD-3-Clause notice in upstream vega@5.33.0 distribution" + }, + { + "package": "vega-parser", + "version": "6.6.1", + "license": "BSD-3-Clause", + "notice_file": "vega-parser.txt" + }, + { + "package": "vega-projection", + "version": "1.6.3", + "license": "BSD-3-Clause", + "notice_file": "vega-projection.txt" + }, + { + "package": "vega-regression", + "version": "1.3.2", + "license": "BSD-3-Clause", + "notice_file": "vega-regression.txt" + }, + { + "package": "vega-runtime", + "version": "6.2.2", + "license": "BSD-3-Clause", + "notice_file": "vega-runtime.txt" + }, + { + "package": "vega-scale", + "version": "7.4.3", + "license": "BSD-3-Clause", + "notice_file": "vega.txt", + "notice_source": "Vega monorepo BSD-3-Clause notice in upstream vega@5.33.0 distribution" + }, + { + "package": "vega-scenegraph", + "version": "4.13.2", + "license": "BSD-3-Clause", + "notice_file": "vega.txt", + "notice_source": "Vega monorepo BSD-3-Clause notice in upstream vega@5.33.0 distribution" + }, + { + "package": "vega-schema-url-parser", + "version": "2.2.0", + "license": "BSD-3-Clause", + "notice_file": "vega-schema-url-parser.txt" + }, + { + "package": "vega-selections", + "version": "5.6.3", + "license": "BSD-3-Clause", + "notice_file": "vega.txt", + "notice_source": "Vega monorepo BSD-3-Clause notice in upstream vega@5.33.0 distribution" + }, + { + "package": "vega-statistics", + "version": "1.9.0", + "license": "BSD-3-Clause", + "notice_file": "vega-statistics.txt" + }, + { + "package": "vega-themes", + "version": "2.15.0", + "license": "BSD-3-Clause", + "notice_file": "vega-themes.txt" + }, + { + "package": "vega-time", + "version": "2.1.4", + "license": "BSD-3-Clause", + "notice_file": "vega.txt", + "notice_source": "Vega monorepo BSD-3-Clause notice in upstream vega@5.33.0 distribution" + }, + { + "package": "vega-tooltip", + "version": "0.35.2", + "license": "BSD-3-Clause", + "notice_file": "vega-tooltip.txt" + }, + { + "package": "vega-transforms", + "version": "4.12.2", + "license": "BSD-3-Clause", + "notice_file": "vega-transforms.txt" + }, + { + "package": "vega-util", + "version": "1.17.4", + "license": "BSD-3-Clause", + "notice_file": "vega.txt", + "notice_source": "Vega monorepo BSD-3-Clause notice in upstream vega@5.33.0 distribution" + }, + { + "package": "vega-view", + "version": "5.16.1", + "license": "BSD-3-Clause", + "notice_file": "vega-view.txt" + }, + { + "package": "vega-view-transforms", + "version": "4.6.2", + "license": "BSD-3-Clause", + "notice_file": "vega-view-transforms.txt" + }, + { + "package": "vega-voronoi", + "version": "4.2.5", + "license": "BSD-3-Clause", + "notice_file": "vega-voronoi.txt" + }, + { + "package": "vega-wordcloud", + "version": "4.1.7", + "license": "BSD-3-Clause", + "notice_file": "vega-wordcloud.txt" + } + ], + "notice_scope": "Packages present in upstream distribution source maps; notice package versions describe the local resolution used to retrieve notices, not an assertion about each bundled dependency version." +} diff --git a/static/vendor/retained-analysis/vega-embed.min.js b/static/vendor/retained-analysis/vega-embed.min.js new file mode 100644 index 00000000..8ae62235 --- /dev/null +++ b/static/vendor/retained-analysis/vega-embed.min.js @@ -0,0 +1,7 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("vega"),require("vega-lite")):"function"==typeof define&&define.amd?define(["vega","vega-lite"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).vegaEmbed=t(e.vega,e.vegaLite)}(this,(function(e,t){"use strict";function n(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}})),t.default=e,Object.freeze(t)}var r,i=n(e),o=n(t),a=(r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},r(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),s=Object.prototype.hasOwnProperty;function l(e,t){return s.call(e,t)}function c(e){if(Array.isArray(e)){for(var t=new Array(e.length),n=0;n=48&&t<=57))return!1;n++}return!0}function p(e){return-1===e.indexOf("/")&&-1===e.indexOf("~")?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function u(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function h(e){if(void 0===e)return!0;if(e)if(Array.isArray(e)){for(var t=0,n=e.length;t0&&"constructor"==s[c-1]))throw new TypeError("JSON-Patch: modifying `__proto__` or `constructor/prototype` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(n&&void 0===h&&(void 0===l[g]?h=s.slice(0,c).join("/"):c==p-1&&(h=t.path),void 0!==h&&m(t,0,e,h)),c++,Array.isArray(l)){if("-"===g)g=l.length;else{if(n&&!d(g))throw new E("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",o,t,e);d(g)&&(g=~~g)}if(c>=p){if(n&&"add"===t.op&&g>l.length)throw new E("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",o,t,e);if(!1===(a=y[t.op].call(t,l,g,e)).test)throw new E("Test operation failed","TEST_OPERATION_FAILED",o,t,e);return a}}else if(c>=p){if(!1===(a=b[t.op].call(t,l,g,e)).test)throw new E("Test operation failed","TEST_OPERATION_FAILED",o,t,e);return a}if(l=l[g],n&&c0)throw new E('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,n);if(("move"===e.op||"copy"===e.op)&&"string"!=typeof e.from)throw new E("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&void 0===e.value)throw new E("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,n);if(("add"===e.op||"replace"===e.op||"test"===e.op)&&h(e.value))throw new E("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",t,e,n);if(n)if("add"==e.op){var i=e.path.split("/").length,o=r.split("/").length;if(i!==o+1&&i!==o)throw new E("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",t,e,n)}else if("replace"===e.op||"remove"===e.op||"_get"===e.op){if(e.path!==r)throw new E("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",t,e,n)}else if("move"===e.op||"copy"===e.op){var a=x([{op:"_get",path:e.from,value:void 0}],n);if(a&&"OPERATION_PATH_UNRESOLVABLE"===a.name)throw new E("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",t,e,n)}}function x(e,t,n){try{if(!Array.isArray(e))throw new E("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(t)A(f(t),f(e),n||!0);else{n=n||I;for(var r=0;r0&&(e.patches=[],e.callback&&e.callback(r)),r}function C(e,t,n,r,i){if(t!==e){"function"==typeof t.toJSON&&(t=t.toJSON());for(var o=c(t),a=c(e),s=!1,d=a.length-1;d>=0;d--){var u=e[g=a[d]];if(!l(t,g)||void 0===t[g]&&void 0!==u&&!1===Array.isArray(t))Array.isArray(e)===Array.isArray(t)?(i&&n.push({op:"test",path:r+"/"+p(g),value:f(u)}),n.push({op:"remove",path:r+"/"+p(g)}),s=!0):(i&&n.push({op:"test",path:r,value:e}),n.push({op:"replace",path:r,value:t}));else{var h=t[g];"object"==typeof u&&null!=u&&"object"==typeof h&&null!=h&&Array.isArray(u)===Array.isArray(h)?C(u,h,n,r+"/"+p(g),i):u!==h&&(i&&n.push({op:"test",path:r+"/"+p(g),value:f(u)}),n.push({op:"replace",path:r+"/"+p(g),value:f(h)}))}}if(s||o.length!=a.length)for(d=0;dt||`${e} `));if(e.length<=l)return e}if(null!=i&&(t=JSON.parse(s),i=void 0),"object"==typeof t&&null!==t){const r=o+n,i=[];let a,s,l=0;if(Array.isArray(t)){a="[",s="]";const{length:n}=t;for(;l0)return[a,n+i.join(`,\n${r}`),s].join(`\n${o}`)}return s}(e,"",0)}function _(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var P,M,z,j;function U(){if(j)return z;j=1;const e=Object.freeze({loose:!0}),t=Object.freeze({});return z=n=>n?"object"!=typeof n?e:n:t}var B,G,W,X,V,H,Y,q,J,Q,Z,K,ee,te,ne,re,ie,oe,ae,se,le,ce,fe,de,pe,ue,he,ge,me,Ee,ve,be={exports:{}};function ye(){if(G)return B;G=1;const e=Number.MAX_SAFE_INTEGER||9007199254740991;return B={MAX_LENGTH:256,MAX_SAFE_COMPONENT_LENGTH:16,MAX_SAFE_BUILD_LENGTH:250,MAX_SAFE_INTEGER:e,RELEASE_TYPES:["major","premajor","minor","preminor","patch","prepatch","prerelease"],SEMVER_SPEC_VERSION:"2.0.0",FLAG_INCLUDE_PRERELEASE:1,FLAG_LOOSE:2}}function we(){if(X)return W;X=1;const e="object"==typeof process&&process.env&&process.env.NODE_DEBUG&&/\bsemver\b/i.test(process.env.NODE_DEBUG)?(...e)=>console.error("SEMVER",...e):()=>{};return W=e}function Oe(){return V||(V=1,function(e,t){const{MAX_SAFE_COMPONENT_LENGTH:n,MAX_SAFE_BUILD_LENGTH:r,MAX_LENGTH:i}=ye(),o=we(),a=(t=e.exports={}).re=[],s=t.safeRe=[],l=t.src=[],c=t.t={};let f=0;const d="[a-zA-Z0-9-]",p=[["\\s",1],["\\d",i],[d,r]],u=(e,t,n)=>{const r=(e=>{for(const[t,n]of p)e=e.split(`${t}*`).join(`${t}{0,${n}}`).split(`${t}+`).join(`${t}{1,${n}}`);return e})(t),i=f++;o(e,i,t),c[e]=i,l[i]=t,a[i]=new RegExp(t,n?"g":void 0),s[i]=new RegExp(r,n?"g":void 0)};u("NUMERICIDENTIFIER","0|[1-9]\\d*"),u("NUMERICIDENTIFIERLOOSE","\\d+"),u("NONNUMERICIDENTIFIER",`\\d*[a-zA-Z-]${d}*`),u("MAINVERSION",`(${l[c.NUMERICIDENTIFIER]})\\.(${l[c.NUMERICIDENTIFIER]})\\.(${l[c.NUMERICIDENTIFIER]})`),u("MAINVERSIONLOOSE",`(${l[c.NUMERICIDENTIFIERLOOSE]})\\.(${l[c.NUMERICIDENTIFIERLOOSE]})\\.(${l[c.NUMERICIDENTIFIERLOOSE]})`),u("PRERELEASEIDENTIFIER",`(?:${l[c.NUMERICIDENTIFIER]}|${l[c.NONNUMERICIDENTIFIER]})`),u("PRERELEASEIDENTIFIERLOOSE",`(?:${l[c.NUMERICIDENTIFIERLOOSE]}|${l[c.NONNUMERICIDENTIFIER]})`),u("PRERELEASE",`(?:-(${l[c.PRERELEASEIDENTIFIER]}(?:\\.${l[c.PRERELEASEIDENTIFIER]})*))`),u("PRERELEASELOOSE",`(?:-?(${l[c.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${l[c.PRERELEASEIDENTIFIERLOOSE]})*))`),u("BUILDIDENTIFIER",`${d}+`),u("BUILD",`(?:\\+(${l[c.BUILDIDENTIFIER]}(?:\\.${l[c.BUILDIDENTIFIER]})*))`),u("FULLPLAIN",`v?${l[c.MAINVERSION]}${l[c.PRERELEASE]}?${l[c.BUILD]}?`),u("FULL",`^${l[c.FULLPLAIN]}$`),u("LOOSEPLAIN",`[v=\\s]*${l[c.MAINVERSIONLOOSE]}${l[c.PRERELEASELOOSE]}?${l[c.BUILD]}?`),u("LOOSE",`^${l[c.LOOSEPLAIN]}$`),u("GTLT","((?:<|>)?=?)"),u("XRANGEIDENTIFIERLOOSE",`${l[c.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`),u("XRANGEIDENTIFIER",`${l[c.NUMERICIDENTIFIER]}|x|X|\\*`),u("XRANGEPLAIN",`[v=\\s]*(${l[c.XRANGEIDENTIFIER]})(?:\\.(${l[c.XRANGEIDENTIFIER]})(?:\\.(${l[c.XRANGEIDENTIFIER]})(?:${l[c.PRERELEASE]})?${l[c.BUILD]}?)?)?`),u("XRANGEPLAINLOOSE",`[v=\\s]*(${l[c.XRANGEIDENTIFIERLOOSE]})(?:\\.(${l[c.XRANGEIDENTIFIERLOOSE]})(?:\\.(${l[c.XRANGEIDENTIFIERLOOSE]})(?:${l[c.PRERELEASELOOSE]})?${l[c.BUILD]}?)?)?`),u("XRANGE",`^${l[c.GTLT]}\\s*${l[c.XRANGEPLAIN]}$`),u("XRANGELOOSE",`^${l[c.GTLT]}\\s*${l[c.XRANGEPLAINLOOSE]}$`),u("COERCEPLAIN",`(^|[^\\d])(\\d{1,${n}})(?:\\.(\\d{1,${n}}))?(?:\\.(\\d{1,${n}}))?`),u("COERCE",`${l[c.COERCEPLAIN]}(?:$|[^\\d])`),u("COERCEFULL",l[c.COERCEPLAIN]+`(?:${l[c.PRERELEASE]})?`+`(?:${l[c.BUILD]})?(?:$|[^\\d])`),u("COERCERTL",l[c.COERCE],!0),u("COERCERTLFULL",l[c.COERCEFULL],!0),u("LONETILDE","(?:~>?)"),u("TILDETRIM",`(\\s*)${l[c.LONETILDE]}\\s+`,!0),t.tildeTrimReplace="$1~",u("TILDE",`^${l[c.LONETILDE]}${l[c.XRANGEPLAIN]}$`),u("TILDELOOSE",`^${l[c.LONETILDE]}${l[c.XRANGEPLAINLOOSE]}$`),u("LONECARET","(?:\\^)"),u("CARETTRIM",`(\\s*)${l[c.LONECARET]}\\s+`,!0),t.caretTrimReplace="$1^",u("CARET",`^${l[c.LONECARET]}${l[c.XRANGEPLAIN]}$`),u("CARETLOOSE",`^${l[c.LONECARET]}${l[c.XRANGEPLAINLOOSE]}$`),u("COMPARATORLOOSE",`^${l[c.GTLT]}\\s*(${l[c.LOOSEPLAIN]})$|^$`),u("COMPARATOR",`^${l[c.GTLT]}\\s*(${l[c.FULLPLAIN]})$|^$`),u("COMPARATORTRIM",`(\\s*)${l[c.GTLT]}\\s*(${l[c.LOOSEPLAIN]}|${l[c.XRANGEPLAIN]})`,!0),t.comparatorTrimReplace="$1$2$3",u("HYPHENRANGE",`^\\s*(${l[c.XRANGEPLAIN]})\\s+-\\s+(${l[c.XRANGEPLAIN]})\\s*$`),u("HYPHENRANGELOOSE",`^\\s*(${l[c.XRANGEPLAINLOOSE]})\\s+-\\s+(${l[c.XRANGEPLAINLOOSE]})\\s*$`),u("STAR","(<|>)?=?\\s*\\*"),u("GTE0","^\\s*>=\\s*0\\.0\\.0\\s*$"),u("GTE0PRE","^\\s*>=\\s*0\\.0\\.0-0\\s*$")}(be,be.exports)),be.exports}function Ae(){if(J)return q;J=1;const e=we(),{MAX_LENGTH:t,MAX_SAFE_INTEGER:n}=ye(),{safeRe:r,t:i}=Oe(),o=U(),{compareIdentifiers:a}=function(){if(Y)return H;Y=1;const e=/^[0-9]+$/,t=(t,n)=>{const r=e.test(t),i=e.test(n);return r&&i&&(t=+t,n=+n),t===n?0:r&&!i?-1:i&&!r?1:tt(n,e)}}();class s{constructor(a,l){if(l=o(l),a instanceof s){if(a.loose===!!l.loose&&a.includePrerelease===!!l.includePrerelease)return a;a=a.version}else if("string"!=typeof a)throw new TypeError(`Invalid version. Must be a string. Got type "${typeof a}".`);if(a.length>t)throw new TypeError(`version is longer than ${t} characters`);e("SemVer",a,l),this.options=l,this.loose=!!l.loose,this.includePrerelease=!!l.includePrerelease;const c=a.trim().match(l.loose?r[i.LOOSE]:r[i.FULL]);if(!c)throw new TypeError(`Invalid Version: ${a}`);if(this.raw=a,this.major=+c[1],this.minor=+c[2],this.patch=+c[3],this.major>n||this.major<0)throw new TypeError("Invalid major version");if(this.minor>n||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>n||this.patch<0)throw new TypeError("Invalid patch version");c[4]?this.prerelease=c[4].split(".").map((e=>{if(/^[0-9]+$/.test(e)){const t=+e;if(t>=0&&t=0;)"number"==typeof this.prerelease[r]&&(this.prerelease[r]++,r=-2);if(-1===r){if(t===this.prerelease.join(".")&&!1===n)throw new Error("invalid increment argument: identifier already exists");this.prerelease.push(e)}}if(t){let r=[t,e];!1===n&&(r=[t]),0===a(this.prerelease[0],t)?isNaN(this.prerelease[1])&&(this.prerelease=r):this.prerelease=r}break}default:throw new Error(`invalid increment argument: ${e}`)}return this.raw=this.format(),this.build.length&&(this.raw+=`+${this.build.join(".")}`),this}}return q=s}function Ie(){if(Z)return Q;Z=1;const e=Ae();return Q=(t,n,r)=>new e(t,r).compare(new e(n,r))}function xe(){if(pe)return de;pe=1;const e=function(){if(ee)return K;ee=1;const e=Ie();return K=(t,n,r)=>0===e(t,n,r)}(),t=function(){if(ne)return te;ne=1;const e=Ie();return te=(t,n,r)=>0!==e(t,n,r)}(),n=function(){if(ie)return re;ie=1;const e=Ie();return re=(t,n,r)=>e(t,n,r)>0}(),r=function(){if(ae)return oe;ae=1;const e=Ie();return oe=(t,n,r)=>e(t,n,r)>=0}(),i=function(){if(le)return se;le=1;const e=Ie();return se=(t,n,r)=>e(t,n,r)<0}(),o=function(){if(fe)return ce;fe=1;const e=Ie();return ce=(t,n,r)=>e(t,n,r)<=0}();return de=(a,s,l,c)=>{switch(s){case"===":return"object"==typeof a&&(a=a.version),"object"==typeof l&&(l=l.version),a===l;case"!==":return"object"==typeof a&&(a=a.version),"object"==typeof l&&(l=l.version),a!==l;case"":case"=":case"==":return e(a,l,c);case"!=":return t(a,l,c);case">":return n(a,l,c);case">=":return r(a,l,c);case"<":return i(a,l,c);case"<=":return o(a,l,c);default:throw new TypeError(`Invalid operator: ${s}`)}}}function Le(){if(me)return ge;me=1;const e=/\s+/g;class t{constructor(n,o){if(o=r(o),n instanceof t)return n.loose===!!o.loose&&n.includePrerelease===!!o.includePrerelease?n:new t(n.raw,o);if(n instanceof i)return this.raw=n.value,this.set=[[n]],this.formatted=void 0,this;if(this.options=o,this.loose=!!o.loose,this.includePrerelease=!!o.includePrerelease,this.raw=n.trim().replace(e," "),this.set=this.raw.split("||").map((e=>this.parseRange(e.trim()))).filter((e=>e.length)),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${this.raw}`);if(this.set.length>1){const e=this.set[0];if(this.set=this.set.filter((e=>!h(e[0]))),0===this.set.length)this.set=[e];else if(this.set.length>1)for(const e of this.set)if(1===e.length&&g(e[0])){this.set=[e];break}}this.formatted=void 0}get range(){if(void 0===this.formatted){this.formatted="";for(let e=0;e0&&(this.formatted+="||");const t=this.set[e];for(let e=0;e0&&(this.formatted+=" "),this.formatted+=t[e].toString().trim()}}return this.formatted}format(){return this.range}toString(){return this.range}parseRange(e){const t=((this.options.includePrerelease&&p)|(this.options.loose&&u))+":"+e,r=n.get(t);if(r)return r;const a=this.options.loose,g=a?s[l.HYPHENRANGELOOSE]:s[l.HYPHENRANGE];e=e.replace(g,N(this.options.includePrerelease)),o("hyphen replace",e),e=e.replace(s[l.COMPARATORTRIM],c),o("comparator trim",e),e=e.replace(s[l.TILDETRIM],f),o("tilde trim",e),e=e.replace(s[l.CARETTRIM],d),o("caret trim",e);let m=e.split(" ").map((e=>E(e,this.options))).join(" ").split(/\s+/).map((e=>L(e,this.options)));a&&(m=m.filter((e=>(o("loose invalid filter",e,this.options),!!e.match(s[l.COMPARATORLOOSE]))))),o("range list",m);const v=new Map,b=m.map((e=>new i(e,this.options)));for(const e of b){if(h(e))return[e];v.set(e.value,e)}v.size>1&&v.has("")&&v.delete("");const y=[...v.values()];return n.set(t,y),y}intersects(e,n){if(!(e instanceof t))throw new TypeError("a Range is required");return this.set.some((t=>m(t,n)&&e.set.some((e=>m(e,n)&&t.every((t=>e.every((e=>t.intersects(e,n)))))))))}test(e){if(!e)return!1;if("string"==typeof e)try{e=new a(e,this.options)}catch(e){return!1}for(let t=0;t=this.max){const e=this.map.keys().next().value;this.delete(e)}this.map.set(e,t)}return this}})),r=U(),i=function(){if(he)return ue;he=1;const e=Symbol("SemVer ANY");class t{static get ANY(){return e}constructor(r,i){if(i=n(i),r instanceof t){if(r.loose===!!i.loose)return r;r=r.value}r=r.trim().split(/\s+/).join(" "),a("comparator",r,i),this.options=i,this.loose=!!i.loose,this.parse(r),this.semver===e?this.value="":this.value=this.operator+this.semver.version,a("comp",this)}parse(t){const n=this.options.loose?r[i.COMPARATORLOOSE]:r[i.COMPARATOR],o=t.match(n);if(!o)throw new TypeError(`Invalid comparator: ${t}`);this.operator=void 0!==o[1]?o[1]:"","="===this.operator&&(this.operator=""),o[2]?this.semver=new s(o[2],this.options.loose):this.semver=e}toString(){return this.value}test(t){if(a("Comparator.test",t,this.options.loose),this.semver===e||t===e)return!0;if("string"==typeof t)try{t=new s(t,this.options)}catch(e){return!1}return o(t,this.operator,this.semver,this.options)}intersects(e,r){if(!(e instanceof t))throw new TypeError("a Comparator is required");return""===this.operator?""===this.value||new l(e.value,r).test(this.value):""===e.operator?""===e.value||new l(this.value,r).test(e.semver):!((r=n(r)).includePrerelease&&("<0.0.0-0"===this.value||"<0.0.0-0"===e.value)||!r.includePrerelease&&(this.value.startsWith("<0.0.0")||e.value.startsWith("<0.0.0"))||(!this.operator.startsWith(">")||!e.operator.startsWith(">"))&&(!this.operator.startsWith("<")||!e.operator.startsWith("<"))&&(this.semver.version!==e.semver.version||!this.operator.includes("=")||!e.operator.includes("="))&&!(o(this.semver,"<",e.semver,r)&&this.operator.startsWith(">")&&e.operator.startsWith("<"))&&!(o(this.semver,">",e.semver,r)&&this.operator.startsWith("<")&&e.operator.startsWith(">")))}}ue=t;const n=U(),{safeRe:r,t:i}=Oe(),o=xe(),a=we(),s=Ae(),l=Le();return ue}(),o=we(),a=Ae(),{safeRe:s,t:l,comparatorTrimReplace:c,tildeTrimReplace:f,caretTrimReplace:d}=Oe(),{FLAG_INCLUDE_PRERELEASE:p,FLAG_LOOSE:u}=ye(),h=e=>"<0.0.0-0"===e.value,g=e=>""===e.value,m=(e,t)=>{let n=!0;const r=e.slice();let i=r.pop();for(;n&&r.length;)n=r.every((e=>i.intersects(e,t))),i=r.pop();return n},E=(e,t)=>(o("comp",e,t),e=w(e,t),o("caret",e),e=b(e,t),o("tildes",e),e=A(e,t),o("xrange",e),e=x(e,t),o("stars",e),e),v=e=>!e||"x"===e.toLowerCase()||"*"===e,b=(e,t)=>e.trim().split(/\s+/).map((e=>y(e,t))).join(" "),y=(e,t)=>{const n=t.loose?s[l.TILDELOOSE]:s[l.TILDE];return e.replace(n,((t,n,r,i,a)=>{let s;return o("tilde",e,t,n,r,i,a),v(n)?s="":v(r)?s=`>=${n}.0.0 <${+n+1}.0.0-0`:v(i)?s=`>=${n}.${r}.0 <${n}.${+r+1}.0-0`:a?(o("replaceTilde pr",a),s=`>=${n}.${r}.${i}-${a} <${n}.${+r+1}.0-0`):s=`>=${n}.${r}.${i} <${n}.${+r+1}.0-0`,o("tilde return",s),s}))},w=(e,t)=>e.trim().split(/\s+/).map((e=>O(e,t))).join(" "),O=(e,t)=>{o("caret",e,t);const n=t.loose?s[l.CARETLOOSE]:s[l.CARET],r=t.includePrerelease?"-0":"";return e.replace(n,((t,n,i,a,s)=>{let l;return o("caret",e,t,n,i,a,s),v(n)?l="":v(i)?l=`>=${n}.0.0${r} <${+n+1}.0.0-0`:v(a)?l="0"===n?`>=${n}.${i}.0${r} <${n}.${+i+1}.0-0`:`>=${n}.${i}.0${r} <${+n+1}.0.0-0`:s?(o("replaceCaret pr",s),l="0"===n?"0"===i?`>=${n}.${i}.${a}-${s} <${n}.${i}.${+a+1}-0`:`>=${n}.${i}.${a}-${s} <${n}.${+i+1}.0-0`:`>=${n}.${i}.${a}-${s} <${+n+1}.0.0-0`):(o("no pr"),l="0"===n?"0"===i?`>=${n}.${i}.${a}${r} <${n}.${i}.${+a+1}-0`:`>=${n}.${i}.${a}${r} <${n}.${+i+1}.0-0`:`>=${n}.${i}.${a} <${+n+1}.0.0-0`),o("caret return",l),l}))},A=(e,t)=>(o("replaceXRanges",e,t),e.split(/\s+/).map((e=>I(e,t))).join(" ")),I=(e,t)=>{e=e.trim();const n=t.loose?s[l.XRANGELOOSE]:s[l.XRANGE];return e.replace(n,((n,r,i,a,s,l)=>{o("xRange",e,n,r,i,a,s,l);const c=v(i),f=c||v(a),d=f||v(s),p=d;return"="===r&&p&&(r=""),l=t.includePrerelease?"-0":"",c?n=">"===r||"<"===r?"<0.0.0-0":"*":r&&p?(f&&(a=0),s=0,">"===r?(r=">=",f?(i=+i+1,a=0,s=0):(a=+a+1,s=0)):"<="===r&&(r="<",f?i=+i+1:a=+a+1),"<"===r&&(l="-0"),n=`${r+i}.${a}.${s}${l}`):f?n=`>=${i}.0.0${l} <${+i+1}.0.0-0`:d&&(n=`>=${i}.${a}.0${l} <${i}.${+a+1}.0-0`),o("xRange return",n),n}))},x=(e,t)=>(o("replaceStars",e,t),e.trim().replace(s[l.STAR],"")),L=(e,t)=>(o("replaceGTE0",e,t),e.trim().replace(s[t.includePrerelease?l.GTE0PRE:l.GTE0],"")),N=e=>(t,n,r,i,o,a,s,l,c,f,d,p)=>`${n=v(r)?"":v(i)?`>=${r}.0.0${e?"-0":""}`:v(o)?`>=${r}.${i}.0${e?"-0":""}`:a?`>=${n}`:`>=${n}${e?"-0":""}`} ${l=v(c)?"":v(f)?`<${+c+1}.0.0-0`:v(d)?`<${c}.${+f+1}.0-0`:p?`<=${c}.${f}.${d}-${p}`:e?`<${c}.${f}.${+d+1}-0`:`<=${l}`}`.trim(),$=(e,t,n)=>{for(let n=0;n0){const r=e[n].semver;if(r.major===t.major&&r.minor===t.minor&&r.patch===t.patch)return!0}return!1}return!0};return ge}var Ne=function(){if(ve)return Ee;ve=1;const e=Le();return Ee=(t,n,r)=>{try{n=new e(n,r)}catch(e){return!1}return n.test(t)},Ee}(),$e=_(Ne);var Re={NaN:NaN,E:Math.E,LN2:Math.LN2,LN10:Math.LN10,LOG2E:Math.LOG2E,LOG10E:Math.LOG10E,PI:Math.PI,SQRT1_2:Math.SQRT1_2,SQRT2:Math.SQRT2,MIN_VALUE:Number.MIN_VALUE,MAX_VALUE:Number.MAX_VALUE},Te={"*":(e,t)=>e*t,"+":(e,t)=>e+t,"-":(e,t)=>e-t,"/":(e,t)=>e/t,"%":(e,t)=>e%t,">":(e,t)=>e>t,"<":(e,t)=>ee<=t,">=":(e,t)=>e>=t,"==":(e,t)=>e==t,"!=":(e,t)=>e!=t,"===":(e,t)=>e===t,"!==":(e,t)=>e!==t,"&":(e,t)=>e&t,"|":(e,t)=>e|t,"^":(e,t)=>e^t,"<<":(e,t)=>e<>":(e,t)=>e>>t,">>>":(e,t)=>e>>>t},Se={"+":e=>+e,"-":e=>-e,"~":e=>~e,"!":e=>!e};const Ce=Array.prototype.slice,De=(e,t,n)=>{const r=n?n(t[0]):t[0];return r[e].apply(r,Ce.call(t,1))};var Fe={isNaN:Number.isNaN,isFinite:Number.isFinite,abs:Math.abs,acos:Math.acos,asin:Math.asin,atan:Math.atan,atan2:Math.atan2,ceil:Math.ceil,cos:Math.cos,exp:Math.exp,floor:Math.floor,log:Math.log,max:Math.max,min:Math.min,pow:Math.pow,random:Math.random,round:Math.round,sin:Math.sin,sqrt:Math.sqrt,tan:Math.tan,clamp:(e,t,n)=>Math.max(t,Math.min(n,e)),now:Date.now,utc:Date.UTC,datetime:(e,t,n,r,i,o,a)=>new Date(e,t||0,null!=n?n:1,r||0,i||0,o||0,a||0),date:e=>new Date(e).getDate(),day:e=>new Date(e).getDay(),year:e=>new Date(e).getFullYear(),month:e=>new Date(e).getMonth(),hours:e=>new Date(e).getHours(),minutes:e=>new Date(e).getMinutes(),seconds:e=>new Date(e).getSeconds(),milliseconds:e=>new Date(e).getMilliseconds(),time:e=>new Date(e).getTime(),timezoneoffset:e=>new Date(e).getTimezoneOffset(),utcdate:e=>new Date(e).getUTCDate(),utcday:e=>new Date(e).getUTCDay(),utcyear:e=>new Date(e).getUTCFullYear(),utcmonth:e=>new Date(e).getUTCMonth(),utchours:e=>new Date(e).getUTCHours(),utcminutes:e=>new Date(e).getUTCMinutes(),utcseconds:e=>new Date(e).getUTCSeconds(),utcmilliseconds:e=>new Date(e).getUTCMilliseconds(),length:e=>e.length,join:function(){return De("join",arguments)},indexof:function(){return De("indexOf",arguments)},lastindexof:function(){return De("lastIndexOf",arguments)},slice:function(){return De("slice",arguments)},reverse:e=>e.slice().reverse(),parseFloat:parseFloat,parseInt:parseInt,upper:e=>String(e).toUpperCase(),lower:e=>String(e).toLowerCase(),substring:function(){return De("substring",arguments,String)},split:function(){return De("split",arguments,String)},replace:function(){return De("replace",arguments,String)},trim:e=>String(e).trim(),regexp:RegExp,test:(e,t)=>RegExp(e).test(t)};const ke=["view","item","group","xy","x","y"],_e=new Set([Function,eval,setTimeout,setInterval]);"function"==typeof setImmediate&&_e.add(setImmediate);const Pe={Literal:(e,t)=>t.value,Identifier:(e,t)=>{const n=t.name;return e.memberDepth>0?n:"datum"===n?e.datum:"event"===n?e.event:"item"===n?e.item:Re[n]||e.params["$"+n]},MemberExpression:(e,t)=>{const n=!t.computed,r=e(t.object);n&&(e.memberDepth+=1);const i=e(t.property);if(n&&(e.memberDepth-=1),!_e.has(r[i]))return r[i];console.error(`Prevented interpretation of member "${i}" which could lead to insecure code execution`)},CallExpression:(e,t)=>{const n=t.arguments;let r=t.callee.name;return r.startsWith("_")&&(r=r.slice(1)),"if"===r?e(n[0])?e(n[1]):e(n[2]):(e.fn[r]||Fe[r]).apply(e.fn,n.map(e))},ArrayExpression:(e,t)=>t.elements.map(e),BinaryExpression:(e,t)=>Te[t.operator](e(t.left),e(t.right)),UnaryExpression:(e,t)=>Se[t.operator](e(t.argument)),ConditionalExpression:(e,t)=>e(t.test)?e(t.consequent):e(t.alternate),LogicalExpression:(e,t)=>"&&"===t.operator?e(t.left)&&e(t.right):e(t.left)||e(t.right),ObjectExpression:(e,t)=>t.properties.reduce(((t,n)=>{e.memberDepth+=1;const r=e(n.key);return e.memberDepth-=1,_e.has(e(n.value))?console.error(`Prevented interpretation of property "${r}" which could lead to insecure code execution`):t[r]=e(n.value),t}),{})};function Me(e,t,n,r,i,o){const a=e=>Pe[e.type](a,e);return a.memberDepth=0,a.fn=Object.create(t),a.params=n,a.datum=r,a.event=i,a.item=o,ke.forEach((e=>a.fn[e]=function(){return i.vega[e](...arguments)})),a(e)}var ze={operator(e,t){const n=t.ast,r=e.functions;return e=>Me(n,r,e)},parameter(e,t){const n=t.ast,r=e.functions;return(e,t)=>Me(n,r,t,e)},event(e,t){const n=t.ast,r=e.functions;return e=>Me(n,r,void 0,void 0,e)},handler(e,t){const n=t.ast,r=e.functions;return(e,t)=>{const i=t.item&&t.item.datum;return Me(n,r,e,i,t)}},encode(e,t){const{marktype:n,channels:r}=t,i=e.functions,o="group"===n||"image"===n||"rect"===n;return(e,t)=>{const a=e.datum;let s,l=0;for(const n in r)s=Me(r[n].ast,i,t,a,void 0,e),e[n]!==s&&(e[n]=s,l=1);return"rule"!==n&&function(e,t,n){let r;t.x2&&(t.x?(n&&e.x>e.x2&&(r=e.x,e.x=e.x2,e.x2=r),e.width=e.x2-e.x):e.x=e.x2-(e.width||0)),t.xc&&(e.x=e.xc-(e.width||0)/2),t.y2&&(t.y?(n&&e.y>e.y2&&(r=e.y,e.y=e.y2,e.y2=r),e.height=e.y2-e.y):e.y=e.y2-(e.height||0)),t.yc&&(e.y=e.yc-(e.height||0)/2)}(e,r,o),l}}};function je(e){const[t,n]=/schema\/([\w-]+)\/([\w\.\-]+)\.json$/g.exec(e).slice(1,3);return{library:t,version:n}}var Ue="2.15.0";const Be="#fff",Ge="#888",We={background:"#333",view:{stroke:Ge},title:{color:Be,subtitleColor:Be},style:{"guide-label":{fill:Be},"guide-title":{fill:Be}},axis:{domainColor:Be,gridColor:Ge,tickColor:Be}},Xe="#4572a7",Ve={background:"#fff",arc:{fill:Xe},area:{fill:Xe},line:{stroke:Xe,strokeWidth:2},path:{stroke:Xe},rect:{fill:Xe},shape:{stroke:Xe},symbol:{fill:Xe,strokeWidth:1.5,size:50},axis:{bandPosition:.5,grid:!0,gridColor:"#000000",gridOpacity:1,gridWidth:.5,labelPadding:10,tickSize:5,tickWidth:.5},axisBand:{grid:!1,tickExtra:!0},legend:{labelBaseline:"middle",labelFontSize:11,symbolSize:50,symbolType:"square"},range:{category:["#4572a7","#aa4643","#8aa453","#71598e","#4598ae","#d98445","#94aace","#d09393","#b9cc98","#a99cbc"]}},He="#30a2da",Ye="#cbcbcb",qe="#f0f0f0",Je="#333",Qe={arc:{fill:He},area:{fill:He},axis:{domainColor:Ye,grid:!0,gridColor:Ye,gridWidth:1,labelColor:"#999",labelFontSize:10,titleColor:"#333",tickColor:Ye,tickSize:10,titleFontSize:14,titlePadding:10,labelPadding:4},axisBand:{grid:!1},background:qe,group:{fill:qe},legend:{labelColor:Je,labelFontSize:11,padding:1,symbolSize:30,symbolType:"square",titleColor:Je,titleFontSize:14,titlePadding:10},line:{stroke:He,strokeWidth:2},path:{stroke:He,strokeWidth:.5},rect:{fill:He},range:{category:["#30a2da","#fc4f30","#e5ae38","#6d904f","#8b8b8b","#b96db8","#ff9e27","#56cc60","#52d2ca","#52689e","#545454","#9fe4f8"],diverging:["#cc0020","#e77866","#f6e7e1","#d6e8ed","#91bfd9","#1d78b5"],heatmap:["#d6e8ed","#cee0e5","#91bfd9","#549cc6","#1d78b5"]},point:{filled:!0,shape:"circle"},shape:{stroke:He},bar:{binSpacing:2,fill:He,stroke:null},title:{anchor:"start",fontSize:24,fontWeight:600,offset:20}},Ze="#000",Ke={group:{fill:"#e5e5e5"},arc:{fill:Ze},area:{fill:Ze},line:{stroke:Ze},path:{stroke:Ze},rect:{fill:Ze},shape:{stroke:Ze},symbol:{fill:Ze,size:40},axis:{domain:!1,grid:!0,gridColor:"#FFFFFF",gridOpacity:1,labelColor:"#7F7F7F",labelPadding:4,tickColor:"#7F7F7F",tickSize:5.67,titleFontSize:16,titleFontWeight:"normal"},legend:{labelBaseline:"middle",labelFontSize:11,symbolSize:40},range:{category:["#000000","#7F7F7F","#1A1A1A","#999999","#333333","#B0B0B0","#4D4D4D","#C9C9C9","#666666","#DCDCDC"]}},et="Benton Gothic, sans-serif",tt="#82c6df",nt="Benton Gothic Bold, sans-serif",rt="normal",it={"category-6":["#ec8431","#829eb1","#c89d29","#3580b1","#adc839","#ab7fb4"],"fire-7":["#fbf2c7","#f9e39c","#f8d36e","#f4bb6a","#e68a4f","#d15a40","#ab4232"],"fireandice-6":["#e68a4f","#f4bb6a","#f9e39c","#dadfe2","#a6b7c6","#849eae"],"ice-7":["#edefee","#dadfe2","#c4ccd2","#a6b7c6","#849eae","#607785","#47525d"]},ot={background:"#ffffff",title:{anchor:"start",color:"#000000",font:nt,fontSize:22,fontWeight:"normal"},arc:{fill:tt},area:{fill:tt},line:{stroke:tt,strokeWidth:2},path:{stroke:tt},rect:{fill:tt},shape:{stroke:tt},symbol:{fill:tt,size:30},axis:{labelFont:et,labelFontSize:11.5,labelFontWeight:"normal",titleFont:nt,titleFontSize:13,titleFontWeight:rt},axisX:{labelAngle:0,labelPadding:4,tickSize:3},axisY:{labelBaseline:"middle",maxExtent:45,minExtent:45,tickSize:2,titleAlign:"left",titleAngle:0,titleX:-45,titleY:-11},legend:{labelFont:et,labelFontSize:11.5,symbolType:"square",titleFont:nt,titleFontSize:13,titleFontWeight:rt},range:{category:it["category-6"],diverging:it["fireandice-6"],heatmap:it["fire-7"],ordinal:it["fire-7"],ramp:it["fire-7"]}},at="#ab5787",st="#979797",lt={background:"#f9f9f9",arc:{fill:at},area:{fill:at},line:{stroke:at},path:{stroke:at},rect:{fill:at},shape:{stroke:at},symbol:{fill:at,size:30},axis:{domainColor:st,domainWidth:.5,gridWidth:.2,labelColor:st,tickColor:st,tickWidth:.2,titleColor:st},axisBand:{grid:!1},axisX:{grid:!0,tickSize:10},axisY:{domain:!1,grid:!0,tickSize:0},legend:{labelFontSize:11,padding:1,symbolSize:30,symbolType:"square"},range:{category:["#ab5787","#51b2e5","#703c5c","#168dd9","#d190b6","#00609f","#d365ba","#154866","#666666","#c4c4c4"]}},ct="#3e5c69",ft={background:"#fff",arc:{fill:ct},area:{fill:ct},line:{stroke:ct},path:{stroke:ct},rect:{fill:ct},shape:{stroke:ct},symbol:{fill:ct},axis:{domainWidth:.5,grid:!0,labelPadding:2,tickSize:5,tickWidth:.5,titleFontWeight:"normal"},axisBand:{grid:!1},axisX:{gridWidth:.2},axisY:{gridDash:[3],gridWidth:.4},legend:{labelFontSize:11,padding:1,symbolType:"square"},range:{category:["#3e5c69","#6793a6","#182429","#0570b0","#3690c0","#74a9cf","#a6bddb","#e2ddf2"]}},dt="#1696d2",pt="#000000",ut="Lato",ht="Lato",gt={"main-colors":["#1696d2","#d2d2d2","#000000","#fdbf11","#ec008b","#55b748","#5c5859","#db2b27"],"shades-blue":["#CFE8F3","#A2D4EC","#73BFE2","#46ABDB","#1696D2","#12719E","#0A4C6A","#062635"],"shades-gray":["#F5F5F5","#ECECEC","#E3E3E3","#DCDBDB","#D2D2D2","#9D9D9D","#696969","#353535"],"shades-yellow":["#FFF2CF","#FCE39E","#FDD870","#FCCB41","#FDBF11","#E88E2D","#CA5800","#843215"],"shades-magenta":["#F5CBDF","#EB99C2","#E46AA7","#E54096","#EC008B","#AF1F6B","#761548","#351123"],"shades-green":["#DCEDD9","#BCDEB4","#98CF90","#78C26D","#55B748","#408941","#2C5C2D","#1A2E19"],"shades-black":["#D5D5D4","#ADABAC","#848081","#5C5859","#332D2F","#262223","#1A1717","#0E0C0D"],"shades-red":["#F8D5D4","#F1AAA9","#E9807D","#E25552","#DB2B27","#A4201D","#6E1614","#370B0A"],"one-group":["#1696d2","#000000"],"two-groups-cat-1":["#1696d2","#000000"],"two-groups-cat-2":["#1696d2","#fdbf11"],"two-groups-cat-3":["#1696d2","#db2b27"],"two-groups-seq":["#a2d4ec","#1696d2"],"three-groups-cat":["#1696d2","#fdbf11","#000000"],"three-groups-seq":["#a2d4ec","#1696d2","#0a4c6a"],"four-groups-cat-1":["#000000","#d2d2d2","#fdbf11","#1696d2"],"four-groups-cat-2":["#1696d2","#ec0008b","#fdbf11","#5c5859"],"four-groups-seq":["#cfe8f3","#73bf42","#1696d2","#0a4c6a"],"five-groups-cat-1":["#1696d2","#fdbf11","#d2d2d2","#ec008b","#000000"],"five-groups-cat-2":["#1696d2","#0a4c6a","#d2d2d2","#fdbf11","#332d2f"],"five-groups-seq":["#cfe8f3","#73bf42","#1696d2","#0a4c6a","#000000"],"six-groups-cat-1":["#1696d2","#ec008b","#fdbf11","#000000","#d2d2d2","#55b748"],"six-groups-cat-2":["#1696d2","#d2d2d2","#ec008b","#fdbf11","#332d2f","#0a4c6a"],"six-groups-seq":["#cfe8f3","#a2d4ec","#73bfe2","#46abdb","#1696d2","#12719e"],"diverging-colors":["#ca5800","#fdbf11","#fdd870","#fff2cf","#cfe8f3","#73bfe2","#1696d2","#0a4c6a"]},mt={background:"#FFFFFF",title:{anchor:"start",fontSize:18,font:ut},axisX:{domain:!0,domainColor:pt,domainWidth:1,grid:!1,labelFontSize:12,labelFont:ht,labelAngle:0,tickColor:pt,tickSize:5,titleFontSize:12,titlePadding:10,titleFont:ut},axisY:{domain:!1,domainWidth:1,grid:!0,gridColor:"#DEDDDD",gridWidth:1,labelFontSize:12,labelFont:ht,labelPadding:8,ticks:!1,titleFontSize:12,titlePadding:10,titleFont:ut,titleAngle:0,titleY:-10,titleX:18},legend:{labelFontSize:12,labelFont:ht,symbolSize:100,titleFontSize:12,titlePadding:10,titleFont:ut,orient:"right",offset:10},view:{stroke:"transparent"},range:{category:gt["six-groups-cat-1"],diverging:gt["diverging-colors"],heatmap:gt["diverging-colors"],ordinal:gt["six-groups-seq"],ramp:gt["shades-blue"]},area:{fill:dt},rect:{fill:dt},line:{color:dt,stroke:dt,strokeWidth:5},trail:{color:dt,stroke:dt,strokeWidth:0,size:1},path:{stroke:dt,strokeWidth:.5},point:{filled:!0},text:{font:"Lato",color:dt,fontSize:11,align:"center",fontWeight:400,size:11},style:{bar:{fill:dt,stroke:null}},arc:{fill:dt},shape:{stroke:dt},symbol:{fill:dt,size:30}},Et="#3366CC",vt="#ccc",bt="Arial, sans-serif",yt={arc:{fill:Et},area:{fill:Et},path:{stroke:Et},rect:{fill:Et},shape:{stroke:Et},symbol:{stroke:Et},circle:{fill:Et},background:"#fff",padding:{top:10,right:10,bottom:10,left:10},style:{"guide-label":{font:bt,fontSize:12},"guide-title":{font:bt,fontSize:12},"group-title":{font:bt,fontSize:12}},title:{font:bt,fontSize:14,fontWeight:"bold",dy:-3,anchor:"start"},axis:{gridColor:vt,tickColor:vt,domain:!1,grid:!0},range:{category:["#4285F4","#DB4437","#F4B400","#0F9D58","#AB47BC","#00ACC1","#FF7043","#9E9D24","#5C6BC0","#F06292","#00796B","#C2185B"],heatmap:["#c6dafc","#5e97f6","#2a56c6"]}},wt=e=>e*(1/3+1),Ot=wt(9),At=wt(10),It=wt(12),xt="Segoe UI",Lt="wf_standard-font, helvetica, arial, sans-serif",Nt="#252423",$t="#605E5C",Rt="transparent",Tt="#118DFF",St="#DEEFFF",Ct=[St,Tt],Dt={view:{stroke:Rt},background:Rt,font:xt,header:{titleFont:Lt,titleFontSize:It,titleColor:Nt,labelFont:xt,labelFontSize:At,labelColor:$t},axis:{ticks:!1,grid:!1,domain:!1,labelColor:$t,labelFontSize:Ot,titleFont:Lt,titleColor:Nt,titleFontSize:It,titleFontWeight:"normal"},axisQuantitative:{tickCount:3,grid:!0,gridColor:"#C8C6C4",gridDash:[1,5],labelFlush:!1},axisBand:{tickExtra:!0},axisX:{labelPadding:5},axisY:{labelPadding:10},bar:{fill:Tt},line:{stroke:Tt,strokeWidth:3,strokeCap:"round",strokeJoin:"round"},text:{font:xt,fontSize:Ot,fill:$t},arc:{fill:Tt},area:{fill:Tt,line:!0,opacity:.6},path:{stroke:Tt},rect:{fill:Tt},point:{fill:Tt,filled:!0,size:75},shape:{stroke:Tt},symbol:{fill:Tt,strokeWidth:1.5,size:50},legend:{titleFont:xt,titleFontWeight:"bold",titleColor:$t,labelFont:xt,labelFontSize:At,labelColor:$t,symbolType:"circle",symbolSize:75},range:{category:[Tt,"#12239E","#E66C37","#6B007B","#E044A7","#744EC2","#D9B300","#D64550"],diverging:Ct,heatmap:Ct,ordinal:[St,"#c7e4ff","#b0d9ff","#9aceff","#83c3ff","#6cb9ff","#55aeff","#3fa3ff","#2898ff",Tt]}},Ft='IBM Plex Sans,system-ui,-apple-system,BlinkMacSystemFont,".sfnstext-regular",sans-serif',kt={textPrimary:{g90:"#f4f4f4",g100:"#f4f4f4",white:"#161616",g10:"#161616"},textSecondary:{g90:"#c6c6c6",g100:"#c6c6c6",white:"#525252",g10:"#525252"},layerAccent01:{white:"#e0e0e0",g10:"#e0e0e0",g90:"#525252",g100:"#393939"},gridBg:{white:"#ffffff",g10:"#ffffff",g90:"#161616",g100:"#161616"}},_t=["#8a3ffc","#33b1ff","#007d79","#ff7eb6","#fa4d56","#fff1f1","#6fdc8c","#4589ff","#d12771","#d2a106","#08bdba","#bae6ff","#ba4e00","#d4bbff"],Pt=["#6929c4","#1192e8","#005d5d","#9f1853","#fa4d56","#570408","#198038","#002d9c","#ee538b","#b28600","#009d9a","#012749","#8a3800","#a56eff"];function Mt({theme:e,background:t}){const n=["white","g10"].includes(e)?"light":"dark",r=kt.gridBg[e],i=kt.textPrimary[e],o=kt.textSecondary[e],a="dark"===n?_t:Pt,s="dark"===n?"#d4bbff":"#6929c4";return{background:t,arc:{fill:s},area:{fill:s},path:{stroke:s},rect:{fill:s},shape:{stroke:s},symbol:{stroke:s},circle:{fill:s},view:{fill:r,stroke:r},group:{fill:r},title:{color:i,anchor:"start",dy:-15,fontSize:16,font:Ft,fontWeight:600},axis:{labelColor:o,labelFontSize:12,labelFont:'IBM Plex Sans Condensed, system-ui, -apple-system, BlinkMacSystemFont, ".SFNSText-Regular", sans-serif',labelFontWeight:400,titleColor:i,titleFontWeight:600,titleFontSize:12,grid:!0,gridColor:kt.layerAccent01[e],labelAngle:0},axisX:{titlePadding:10},axisY:{titlePadding:2.5},style:{"guide-label":{font:Ft,fill:o,fontWeight:400},"guide-title":{font:Ft,fill:o,fontWeight:400}},range:{category:a,diverging:["#750e13","#a2191f","#da1e28","#fa4d56","#ff8389","#ffb3b8","#ffd7d9","#fff1f1","#e5f6ff","#bae6ff","#82cfff","#33b1ff","#1192e8","#0072c3","#00539a","#003a6d"],heatmap:["#f6f2ff","#e8daff","#d4bbff","#be95ff","#a56eff","#8a3ffc","#6929c4","#491d8b","#31135e","#1c0f30"]}}}const zt=Mt({theme:"white",background:"#ffffff"}),jt=Mt({theme:"g10",background:"#f4f4f4"}),Ut=Mt({theme:"g90",background:"#262626"}),Bt=Mt({theme:"g100",background:"#161616"}),Gt=Ue;var Wt=Object.freeze({__proto__:null,carbong10:jt,carbong100:Bt,carbong90:Ut,carbonwhite:zt,dark:We,excel:Ve,fivethirtyeight:Qe,ggplot2:Ke,googlecharts:yt,latimes:ot,powerbi:Dt,quartz:lt,urbaninstitute:mt,version:Gt,vox:ft});function Xt(e,t,n){return e.fields=t||[],e.fname=n,e}const Vt=e=>function(t){return t[e]},Ht=e=>{const t=e.length;return function(n){for(let r=0;rr&&c(),s=r=i+1):"]"===o&&(s||Yt("Access path missing open bracket: "+e),s>0&&c(),s=0,r=i+1):i>r?c():r=i+1}return s&&Yt("Access path missing closing bracket: "+e),a&&Yt("Access path missing closing quote: "+e),i>r&&(i++,c()),t}(e);e=1===t.length?t[0]:e,Xt(function(e){return 1===e.length?Vt(e[0]):Ht(e)}(t),[e],e)}("id"),Xt((e=>e),[],"identity"),Xt((()=>0),[],"zero"),Xt((()=>1),[],"one"),Xt((()=>!0),[],"true"),Xt((()=>!1),[],"false");var qt=Array.isArray;function Jt(e){return e===Object(e)}function Qt(e,t){return JSON.stringify(e,function(e){const t=[];return function(n,r){if("object"!=typeof r||null===r)return r;const i=t.indexOf(this)+1;return t.length=i,t.length>e?"[Object]":t.indexOf(r)>=0?"[Circular]":(t.push(r),r)}}(t))}var Zt="#vg-tooltip-element {\n visibility: hidden;\n padding: 8px;\n position: fixed;\n z-index: 1000;\n font-family: sans-serif;\n font-size: 11px;\n border-radius: 3px;\n box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);\n /* The default theme is the light theme. */\n background-color: rgba(255, 255, 255, 0.95);\n border: 1px solid #d9d9d9;\n color: black;\n}\n#vg-tooltip-element.visible {\n visibility: visible;\n}\n#vg-tooltip-element h2 {\n margin-top: 0;\n margin-bottom: 10px;\n font-size: 13px;\n}\n#vg-tooltip-element table {\n border-spacing: 0;\n}\n#vg-tooltip-element table tr {\n border: none;\n}\n#vg-tooltip-element table tr td {\n overflow: hidden;\n text-overflow: ellipsis;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n#vg-tooltip-element table tr td.key {\n color: #808080;\n max-width: 150px;\n text-align: right;\n padding-right: 4px;\n}\n#vg-tooltip-element table tr td.value {\n display: block;\n max-width: 300px;\n max-height: 7em;\n text-align: left;\n}\n#vg-tooltip-element.dark-theme {\n background-color: rgba(32, 32, 32, 0.9);\n border: 1px solid #f5f5f5;\n color: white;\n}\n#vg-tooltip-element.dark-theme td.key {\n color: #bfbfbf;\n}\n";const Kt="vg-tooltip-element",en={offsetX:10,offsetY:10,id:Kt,styleId:"vega-tooltip-style",theme:"light",disableDefaultStyle:!1,sanitize:function(e){return String(e).replace(/&/g,"&").replace(/t("string"==typeof e?e:Qt(e,n)))).join(", ")}]`;if(Jt(e)){let i="";const{title:o,image:a,...s}=e;o&&(i+=`

${t(o)}

`),a&&(i+=``);const l=Object.keys(s);if(l.length>0){i+="";for(const e of l){let r=s[e];void 0!==r&&(Jt(r)&&(r=Qt(r,n)),i+=``)}i+="
${t(e)}${t(r)}
"}return i||"{}"}return t(e)},baseURL:"",anchor:"cursor",position:["top","bottom","left","right","top-left","top-right","bottom-left","bottom-right"]};function tn(e,t,{offsetX:n,offsetY:r}){const i=nn({x1:e.clientX,x2:e.clientX,y1:e.clientY,y2:e.clientY},t,n,r),o=["bottom-right","bottom-left","top-right","top-left"];for(const e of o)if(rn(i[e],t))return i[e];return i["top-left"]}function nn(e,t,n,r){const i=(e.x1+e.x2)/2,o=(e.y1+e.y2)/2,a=e.x1-t.width-n,s=i-t.width/2,l=e.x2+n,c=e.y1-t.height-r,f=o-t.height/2,d=e.y2+r;return{top:{x:s,y:c},bottom:{x:s,y:d},left:{x:a,y:f},right:{x:l,y:f},"top-left":{x:a,y:c},"top-right":{x:l,y:c},"bottom-left":{x:a,y:d},"bottom-right":{x:l,y:d}}}function rn(e,t){return e.x>=0&&e.y>=0&&e.x+t.width<=window.innerWidth&&e.y+t.height<=window.innerHeight}function on(e,t,n){return e.clientX>=t.x&&e.clientX<=t.x+n.width&&e.clientY>=t.y&&e.clientY<=t.y+n.height}class an{constructor(e){this.options={...en,...e};const t=this.options.id;if(this.el=null,this.call=this.tooltipHandler.bind(this),!this.options.disableDefaultStyle&&!document.getElementById(this.options.styleId)){const e=document.createElement("style");e.setAttribute("id",this.options.styleId),e.innerHTML=function(e){if(!/^[A-Za-z]+[-:.\w]*$/.test(e))throw new Error("Invalid HTML ID");return Zt.toString().replace(Kt,e)}(t);const n=document.head;n.childNodes.length>0?n.insertBefore(e,n.childNodes[0]):n.appendChild(e)}}tooltipHandler(e,t,n,r){if(this.el=document.getElementById(this.options.id),!this.el){this.el=document.createElement("div"),this.el.setAttribute("id",this.options.id),this.el.classList.add("vg-tooltip");(document.fullscreenElement??document.body).appendChild(this.el)}if(null==r||""===r)return void this.el.classList.remove("visible",`${this.options.theme}-theme`);this.el.innerHTML=this.options.formatTooltip(r,this.options.sanitize,this.options.maxDepth,this.options.baseURL),this.el.classList.add("visible",`${this.options.theme}-theme`);const{x:i,y:o}="mark"===this.options.anchor?function(e,t,n,r,i){const{position:o,offsetX:a,offsetY:s}=i,l=function(e,t,n){const r=n.isVoronoi?n.datum.bounds:n.bounds;let i=e.left+t[0]+r.x1,o=e.top+t[1]+r.y1,a=n;for(;a.mark.group;)a=a.mark.group,i+=a.x??0,o+=a.y??0;return{x1:i,x2:i+(r.x2-r.x1),y1:o,y2:o+(r.y2-r.y1)}}(e._el.getBoundingClientRect(),e._origin,n),c=nn(l,r,a,s),f=Array.isArray(o)?o:[o];for(const e of f)if(rn(c[e],r)&&!on(t,c[e],r))return c[e];return tn(t,r,i)}(e,t,n,this.el.getBoundingClientRect(),this.options):tn(t,this.el.getBoundingClientRect(),this.options);this.el.style.top=`${o}px`,this.el.style.left=`${i}px`}}var sn='.vega-embed {\n position: relative;\n display: inline-block;\n box-sizing: border-box;\n}\n.vega-embed.has-actions {\n padding-right: 38px;\n}\n.vega-embed details:not([open]) > :not(summary) {\n display: none !important;\n}\n.vega-embed summary {\n list-style: none;\n position: absolute;\n top: 0;\n right: 0;\n padding: 6px;\n z-index: 1000;\n background: white;\n box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);\n color: #1b1e23;\n border: 1px solid #aaa;\n border-radius: 999px;\n opacity: 0.2;\n transition: opacity 0.4s ease-in;\n cursor: pointer;\n line-height: 0px;\n}\n.vega-embed summary::-webkit-details-marker {\n display: none;\n}\n.vega-embed summary:active {\n box-shadow: #aaa 0px 0px 0px 1px inset;\n}\n.vega-embed summary svg {\n width: 14px;\n height: 14px;\n}\n.vega-embed details[open] summary {\n opacity: 0.7;\n}\n.vega-embed:hover summary, .vega-embed:focus-within summary {\n opacity: 1 !important;\n transition: opacity 0.2s ease;\n}\n.vega-embed .vega-actions {\n position: absolute;\n z-index: 1001;\n top: 35px;\n right: -9px;\n display: flex;\n flex-direction: column;\n padding-bottom: 8px;\n padding-top: 8px;\n border-radius: 4px;\n box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.2);\n border: 1px solid #d9d9d9;\n background: white;\n animation-duration: 0.15s;\n animation-name: scale-in;\n animation-timing-function: cubic-bezier(0.2, 0, 0.13, 1.5);\n text-align: left;\n}\n.vega-embed .vega-actions a {\n padding: 8px 16px;\n font-family: sans-serif;\n font-size: 14px;\n font-weight: 600;\n white-space: nowrap;\n color: #434a56;\n text-decoration: none;\n}\n.vega-embed .vega-actions a:hover, .vega-embed .vega-actions a:focus {\n background-color: #f7f7f9;\n color: black;\n}\n.vega-embed .vega-actions::before, .vega-embed .vega-actions::after {\n content: "";\n display: inline-block;\n position: absolute;\n}\n.vega-embed .vega-actions::before {\n left: auto;\n right: 14px;\n top: -16px;\n border: 8px solid rgba(0, 0, 0, 0);\n border-bottom-color: #d9d9d9;\n}\n.vega-embed .vega-actions::after {\n left: auto;\n right: 15px;\n top: -14px;\n border: 7px solid rgba(0, 0, 0, 0);\n border-bottom-color: #fff;\n}\n.vega-embed .chart-wrapper.fit-x {\n width: 100%;\n}\n.vega-embed .chart-wrapper.fit-y {\n height: 100%;\n}\n\n.vega-embed-wrapper {\n max-width: 100%;\n overflow: auto;\n padding-right: 14px;\n}\n\n@keyframes scale-in {\n from {\n opacity: 0;\n transform: scale(0.6);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n';function ln(e,...t){for(const n of t)cn(e,n);return e}function cn(t,n){for(const r of Object.keys(n))e.writeConfig(t,r,n[r],!0)}const fn="6.29.0",dn=i;let pn=o;const un="undefined"!=typeof window?window:void 0;void 0===pn&&un?.vl?.compile&&(pn=un.vl);const hn={export:{svg:!0,png:!0},source:!0,compiled:!0,editor:!0},gn={CLICK_TO_VIEW_ACTIONS:"Click to view actions",COMPILED_ACTION:"View Compiled Vega",EDITOR_ACTION:"Open in Vega Editor",PNG_ACTION:"Save as PNG",SOURCE_ACTION:"View Source",SVG_ACTION:"Save as SVG"},mn={vega:"Vega","vega-lite":"Vega-Lite"},En={vega:dn.version,"vega-lite":pn?pn.version:"not available"},vn={vega:e=>e,"vega-lite":(e,t)=>pn.compile(e,{config:t}).spec},bn='\n\n \n \n \n',yn="chart-wrapper";function wn(e,t,n,r){const i=`${t}
`,o=`
${n}`,a=window.open("");a.document.write(i+e+o),a.document.title=`${mn[r]} JSON Source`}function On(e){return!(!e||!("load"in e))}function An(e){return On(e)?e:dn.loader(e)}async function In(t,n,r={}){let i,o;e.isString(n)?(o=An(r.loader),i=JSON.parse(await o.load(n))):i=n;const a=function(t){const n=t.usermeta?.embedOptions??{};return e.isString(n.defaultStyle)&&(n.defaultStyle=!1),n}(i),s=a.loader;o&&!s||(o=An(r.loader??s));const l=await xn(a,o),c=await xn(r,o),f={...ln(c,l),config:e.mergeConfig(c.config??{},l.config??{})};return await async function(t,n,r={},i){const o=r.theme?e.mergeConfig(Wt[r.theme],r.config??{}):r.config,a=e.isBoolean(r.actions)?r.actions:ln({},hn,r.actions??{}),s={...gn,...r.i18n},l=r.renderer??"canvas",c=r.logLevel??dn.Warn,f=r.downloadFileName??"visualization",d="string"==typeof t?document.querySelector(t):t;if(!d)throw new Error(`${t} does not exist`);if(!1!==r.defaultStyle){const e="vega-embed-style",{root:t,rootContainer:n}=function(e){const t=e.getRootNode?e.getRootNode():document;return t instanceof ShadowRoot?{root:t,rootContainer:t}:{root:document,rootContainer:document.head??document.body}}(d);if(!t.getElementById(e)){const t=document.createElement("style");t.id=e,t.innerHTML=void 0===r.defaultStyle||!0===r.defaultStyle?sn.toString():r.defaultStyle,n.appendChild(t)}}const p=function(e,t){if(e.$schema){const n=je(e.$schema);t&&t!==n.library&&console.warn(`The given visualization spec is written in ${mn[n.library]}, but mode argument sets ${mn[t]??t}.`);const r=n.library;return $e(En[r],`^${n.version.slice(1)}`)||console.warn(`The input spec uses ${mn[r]} ${n.version}, but the current version of ${mn[r]} is v${En[r]}.`),r}return"mark"in e||"encoding"in e||"layer"in e||"hconcat"in e||"vconcat"in e||"facet"in e||"repeat"in e?"vega-lite":"marks"in e||"signals"in e||"scales"in e||"axes"in e?"vega":t??"vega"}(n,r.mode);let u=vn[p](n,o);if("vega-lite"===p&&u.$schema){const e=je(u.$schema);$e(En.vega,`^${e.version.slice(1)}`)||console.warn(`The compiled spec uses Vega ${e.version}, but current version is v${En.vega}.`)}d.classList.add("vega-embed"),a&&d.classList.add("has-actions");d.innerHTML="";let h=d;if(a){const e=document.createElement("div");e.classList.add(yn),d.appendChild(e),h=e}const g=r.patch;g&&(u=g instanceof Function?g(u):A(u,g,!0,!1).newDocument);r.formatLocale&&dn.formatLocale(r.formatLocale);r.timeFormatLocale&&dn.timeFormatLocale(r.timeFormatLocale);if(r.expressionFunctions)for(const e in r.expressionFunctions){const t=r.expressionFunctions[e];"fn"in t?dn.expressionFunction(e,t.fn,t.visitor):t instanceof Function&&dn.expressionFunction(e,t)}const{ast:m}=r,E=dn.parse(u,"vega-lite"===p?{}:o,{ast:m}),v=new(r.viewClass||dn.View)(E,{loader:i,logLevel:c,renderer:l,...m?{expr:dn.expressionInterpreter??r.expr??ze}:{}});if(v.addSignalListener("autosize",((e,t)=>{const{type:n}=t;"fit-x"==n?(h.classList.add("fit-x"),h.classList.remove("fit-y")):"fit-y"==n?(h.classList.remove("fit-x"),h.classList.add("fit-y")):"fit"==n?h.classList.add("fit-x","fit-y"):h.classList.remove("fit-x","fit-y")})),!1!==r.tooltip){const{loader:e,tooltip:t}=r,n=e&&!On(e)?e?.baseURL:void 0,i="function"==typeof t?t:new an({baseURL:n,...!0===t?{}:t}).call;v.tooltip(i)}let b,{hover:y}=r;void 0===y&&(y="vega"===p);if(y){const{hoverSet:e,updateSet:t}="boolean"==typeof y?{}:y;v.hover(e,t)}r&&(null!=r.width&&v.width(r.width),null!=r.height&&v.height(r.height),null!=r.padding&&v.padding(r.padding));if(await v.initialize(h,r.bind).runAsync(),!1!==a){let t=d;if(!1!==r.defaultStyle||r.forceActionsMenu){const e=document.createElement("details");e.title=s.CLICK_TO_VIEW_ACTIONS,d.append(e),t=e;const n=document.createElement("summary");n.innerHTML=bn,e.append(n),b=t=>{e.contains(t.target)||e.removeAttribute("open")},document.addEventListener("click",b)}const i=document.createElement("div");if(t.append(i),i.classList.add("vega-actions"),!0===a||!1!==a.export)for(const t of["svg","png"])if(!0===a||!0===a.export||a.export[t]){const n=s[`${t.toUpperCase()}_ACTION`],o=document.createElement("a"),a=e.isObject(r.scaleFactor)?r.scaleFactor[t]:r.scaleFactor;o.text=n,o.href="#",o.target="_blank",o.download=`${f}.${t}`,o.addEventListener("mousedown",(async function(e){e.preventDefault();const n=await v.toImageURL(t,a);this.href=n})),i.append(o)}if(!0===a||!1!==a.source){const e=document.createElement("a");e.text=s.SOURCE_ACTION,e.href="#",e.addEventListener("click",(function(e){wn(k(n),r.sourceHeader??"",r.sourceFooter??"",p),e.preventDefault()})),i.append(e)}if("vega-lite"===p&&(!0===a||!1!==a.compiled)){const e=document.createElement("a");e.text=s.COMPILED_ACTION,e.href="#",e.addEventListener("click",(function(e){wn(k(u),r.sourceHeader??"",r.sourceFooter??"","vega"),e.preventDefault()})),i.append(e)}if(!0===a||!1!==a.editor){const e=r.editorUrl??"https://vega.github.io/editor/",t=document.createElement("a");t.text=s.EDITOR_ACTION,t.href="#",t.addEventListener("click",(function(t){!function(e,t,n){const r=e.open(t),{origin:i}=new URL(t);let o=40;e.addEventListener("message",(function t(n){n.source===r&&(o=0,e.removeEventListener("message",t,!1))}),!1),setTimeout((function e(){o<=0||(r.postMessage(n,i),setTimeout(e,250),o-=1)}),250)}(window,e,{config:o,mode:g?"vega":p,renderer:l,spec:k(g?u:n)}),t.preventDefault()})),i.append(t)}}function w(){b&&document.removeEventListener("click",b),v.finalize()}return{view:v,spec:n,vgSpec:u,finalize:w,embedOptions:r}}(t,i,f,o)}async function xn(t,n){const r=e.isString(t.config)?JSON.parse(await n.load(t.config)):t.config??{},i=e.isString(t.patch)?JSON.parse(await n.load(t.patch)):t.patch;return{...t,...i?{patch:i}:{},...r?{config:r}:{}}}async function Ln(e,t={}){const n=document.createElement("div");n.classList.add("vega-embed-wrapper");const r=document.createElement("div");n.appendChild(r);const i=!0===t.actions||!1===t.actions?t.actions:{export:!0,source:!1,compiled:!0,editor:!0,...t.actions},o=await In(r,e,{actions:i,...t});return n.value=o.view,n}const Nn=(...t)=>{return t.length>1&&(e.isString(t[0])&&!((n=t[0]).startsWith("http://")||n.startsWith("https://")||n.startsWith("//"))||t[0]instanceof HTMLElement||3===t.length)?In(t[0],t[1],t[2]):Ln(t[0],t[1]);var n};return Nn.vegaLite=pn,Nn.vl=pn,Nn.container=Ln,Nn.embed=In,Nn.vega=dn,Nn.default=In,Nn.version=fn,Nn})); +//# sourceMappingURL=vega-embed.min.js.map diff --git a/static/vendor/retained-analysis/vega-interpreter.min.js b/static/vendor/retained-analysis/vega-interpreter.min.js new file mode 100644 index 00000000..de346e43 --- /dev/null +++ b/static/vendor/retained-analysis/vega-interpreter.min.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vega-util")):"function"==typeof define&&define.amd?define(["exports","vega-util"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).vega=e.vega||{},e.vega)}(this,(function(e,t){"use strict";var n={NaN:NaN,E:Math.E,LN2:Math.LN2,LN10:Math.LN10,LOG2E:Math.LOG2E,LOG10E:Math.LOG10E,PI:Math.PI,SQRT1_2:Math.SQRT1_2,SQRT2:Math.SQRT2,MIN_VALUE:Number.MIN_VALUE,MAX_VALUE:Number.MAX_VALUE},a={"*":(e,t)=>e*t,"+":(e,t)=>e+t,"-":(e,t)=>e-t,"/":(e,t)=>e/t,"%":(e,t)=>e%t,">":(e,t)=>e>t,"<":(e,t)=>ee<=t,">=":(e,t)=>e>=t,"==":(e,t)=>e==t,"!=":(e,t)=>e!=t,"===":(e,t)=>e===t,"!==":(e,t)=>e!==t,"&":(e,t)=>e&t,"|":(e,t)=>e|t,"^":(e,t)=>e^t,"<<":(e,t)=>e<>":(e,t)=>e>>t,">>>":(e,t)=>e>>>t},r={"+":e=>+e,"-":e=>-e,"~":e=>~e,"!":e=>!e};const o=Array.prototype.slice,i=(e,t,n)=>{const a=n?n(t[0]):t[0];return a[e].apply(a,o.call(t,1))};var s={isNaN:Number.isNaN,isFinite:Number.isFinite,abs:Math.abs,acos:Math.acos,asin:Math.asin,atan:Math.atan,atan2:Math.atan2,ceil:Math.ceil,cos:Math.cos,exp:Math.exp,floor:Math.floor,log:Math.log,max:Math.max,min:Math.min,pow:Math.pow,random:Math.random,round:Math.round,sin:Math.sin,sqrt:Math.sqrt,tan:Math.tan,clamp:(e,t,n)=>Math.max(t,Math.min(n,e)),now:Date.now,utc:Date.UTC,datetime:(e,t,n,a,r,o,i)=>new Date(e,t||0,null!=n?n:1,a||0,r||0,o||0,i||0),date:e=>new Date(e).getDate(),day:e=>new Date(e).getDay(),year:e=>new Date(e).getFullYear(),month:e=>new Date(e).getMonth(),hours:e=>new Date(e).getHours(),minutes:e=>new Date(e).getMinutes(),seconds:e=>new Date(e).getSeconds(),milliseconds:e=>new Date(e).getMilliseconds(),time:e=>new Date(e).getTime(),timezoneoffset:e=>new Date(e).getTimezoneOffset(),utcdate:e=>new Date(e).getUTCDate(),utcday:e=>new Date(e).getUTCDay(),utcyear:e=>new Date(e).getUTCFullYear(),utcmonth:e=>new Date(e).getUTCMonth(),utchours:e=>new Date(e).getUTCHours(),utcminutes:e=>new Date(e).getUTCMinutes(),utcseconds:e=>new Date(e).getUTCSeconds(),utcmilliseconds:e=>new Date(e).getUTCMilliseconds(),length:e=>e.length,join:function(){return i("join",arguments)},indexof:function(){return i("indexOf",arguments)},lastindexof:function(){return i("lastIndexOf",arguments)},slice:function(){return i("slice",arguments)},reverse:e=>e.slice().reverse(),sort:e=>e.slice().sort(t.ascending),parseFloat:parseFloat,parseInt:parseInt,upper:e=>String(e).toUpperCase(),lower:e=>String(e).toLowerCase(),substring:function(){return i("substring",arguments,String)},split:function(){return i("split",arguments,String)},replace:function(){return i("replace",arguments,String)},trim:e=>String(e).trim(),btoa:e=>btoa(e),atob:e=>atob(e),regexp:RegExp,test:(e,t)=>RegExp(e).test(t)};const c=["view","item","group","xy","x","y"],u=new Set([Function,eval,setTimeout,setInterval]);"function"==typeof setImmediate&&u.add(setImmediate);const l={Literal:(e,t)=>t.value,Identifier:(e,t)=>{const a=t.name;return e.memberDepth>0?a:"datum"===a?e.datum:"event"===a?e.event:"item"===a?e.item:n[a]||e.params["$"+a]},MemberExpression:(e,t)=>{const n=!t.computed,a=e(t.object);n&&(e.memberDepth+=1);const r=e(t.property);if(n&&(e.memberDepth-=1),!u.has(a[r]))return a[r];console.error(`Prevented interpretation of member "${r}" which could lead to insecure code execution`)},CallExpression:(e,t)=>{const n=t.arguments;let a=t.callee.name;return a.startsWith("_")&&(a=a.slice(1)),"if"===a?e(n[0])?e(n[1]):e(n[2]):(e.fn[a]||s[a]).apply(e.fn,n.map(e))},ArrayExpression:(e,t)=>t.elements.map(e),BinaryExpression:(e,t)=>a[t.operator](e(t.left),e(t.right)),UnaryExpression:(e,t)=>r[t.operator](e(t.argument)),ConditionalExpression:(e,t)=>e(t.test)?e(t.consequent):e(t.alternate),LogicalExpression:(e,t)=>"&&"===t.operator?e(t.left)&&e(t.right):e(t.left)||e(t.right),ObjectExpression:(e,t)=>t.properties.reduce(((t,n)=>{e.memberDepth+=1;const a=e(n.key);return e.memberDepth-=1,u.has(e(n.value))?console.error(`Prevented interpretation of property "${a}" which could lead to insecure code execution`):t[a]=e(n.value),t}),{})};function m(e,t,n,a,r,o){const i=e=>l[e.type](i,e);return i.memberDepth=0,i.fn=Object.create(t),i.params=n,i.datum=a,i.event=r,i.item=o,c.forEach((e=>i.fn[e]=function(){return r.vega[e](...arguments)})),i(e)}var p={operator(e,t){const n=t.ast,a=e.functions;return e=>m(n,a,e)},parameter(e,t){const n=t.ast,a=e.functions;return(e,t)=>m(n,a,t,e)},event(e,t){const n=t.ast,a=e.functions;return e=>m(n,a,void 0,void 0,e)},handler(e,t){const n=t.ast,a=e.functions;return(e,t)=>{const r=t.item&&t.item.datum;return m(n,a,e,r,t)}},encode(e,t){const{marktype:n,channels:a}=t,r=e.functions,o="group"===n||"image"===n||"rect"===n;return(e,t)=>{const i=e.datum;let s,c=0;for(const n in a)s=m(a[n].ast,r,t,i,void 0,e),e[n]!==s&&(e[n]=s,c=1);return"rule"!==n&&function(e,t,n){let a;t.x2&&(t.x?(n&&e.x>e.x2&&(a=e.x,e.x=e.x2,e.x2=a),e.width=e.x2-e.x):e.x=e.x2-(e.width||0)),t.xc&&(e.x=e.xc-(e.width||0)/2),t.y2&&(t.y?(n&&e.y>e.y2&&(a=e.y,e.y=e.y2,e.y2=a),e.height=e.y2-e.y):e.y=e.y2-(e.height||0)),t.yc&&(e.y=e.yc-(e.height||0)/2)}(e,a,o),c}}};e.expressionInterpreter=p})); +//# sourceMappingURL=vega-interpreter.min.js.map diff --git a/static/vendor/retained-analysis/vega-lite.min.js b/static/vendor/retained-analysis/vega-lite.min.js new file mode 100644 index 00000000..31b00323 --- /dev/null +++ b/static/vendor/retained-analysis/vega-lite.min.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vega")):"function"==typeof define&&define.amd?define(["exports","vega"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).vegaLite={},e.vega)}(this,(function(e,t){"use strict";var n="5.23.0";function i(e){return J(e,"or")}function r(e){return J(e,"and")}function o(e){return J(e,"not")}function a(e,t){if(o(e))a(e.not,t);else if(r(e))for(const n of e.and)a(n,t);else if(i(e))for(const n of e.or)a(n,t);else t(e)}function s(e,t){return o(e)?{not:s(e.not,t)}:r(e)?{and:e.and.map((e=>s(e,t)))}:i(e)?{or:e.or.map((e=>s(e,t)))}:t(e)}const l=structuredClone;function c(e){throw new Error(e)}function u(e,n){const i={};for(const r of n)t.hasOwnProperty(e,r)&&(i[r]=e[r]);return i}function f(e,t){const n={...e};for(const e of t)delete n[e];return n}function d(e){if(t.isNumber(e))return e;const n=t.isString(e)?e:Q(e);if(n.length<250)return n;let i=0;for(let e=0;e1?t-1:0),i=1;i0===t?e:`[${e}]`)),r=e.map(((t,n)=>e.slice(0,n+1).join("")));for(const e of r)n.add(e)}return n}function k(e,t){return void 0===e||void 0===t||$(w(e),w(t))}function S(e){return 0===D(e).length}Set.prototype.toJSON=function(){return`Set(${[...this].map((e=>Q(e))).join(",")})`};const D=Object.keys,F=Object.values,O=Object.entries;function z(e){return!0===e||!1===e}function C(e){const t=e.replace(/\W/g,"_");return(e.match(/^\d+/)?"_":"")+t}function _(e,t){return o(e)?`!(${_(e.not,t)})`:r(e)?`(${e.and.map((e=>_(e,t))).join(") && (")})`:i(e)?`(${e.or.map((e=>_(e,t))).join(") || (")})`:t(e)}function P(e,t){if(0===t.length)return!0;const n=t.shift();return n in e&&P(e[n],t)&&delete e[n],S(e)}function N(e){return e.charAt(0).toUpperCase()+e.substr(1)}function A(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"datum";const i=t.splitAccessPath(e),r=[];for(let e=1;e<=i.length;e++){const o=`[${i.slice(0,e).map(t.stringValue).join("][")}]`;r.push(`${n}${o}`)}return r.join(" && ")}function T(e){return`${arguments.length>1&&void 0!==arguments[1]?arguments[1]:"datum"}[${t.stringValue(t.splitAccessPath(e).join("."))}]`}function j(e){return`datum['${e.replaceAll("'","\\'")}']`}function E(e){return e.replace(/(\[|\]|\.|'|")/g,"\\$1")}function M(e){return`${t.splitAccessPath(e).map(E).join("\\.")}`}function R(e,t,n){return e.replace(new RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"g"),n)}function L(e){return`${t.splitAccessPath(e).join(".")}`}function q(e){return e?t.splitAccessPath(e).length:0}function U(){for(var e=arguments.length,t=new Array(e),n=0;nvoid 0!==e))}let W=42;function I(e){const t=++W;return e?String(e)+t:t}function B(e){return V(e)?e:`__${e}`}function V(e){return e.startsWith("__")}function H(e){if(void 0!==e)return(e%360+360)%360}function G(e){return!!t.isNumber(e)||!isNaN(e)&&!isNaN(parseFloat(e))}const Y=Object.getPrototypeOf(structuredClone({}));function X(e,t){if(e===t)return!0;if(e&&t&&"object"==typeof e&&"object"==typeof t){if(e.constructor.name!==t.constructor.name)return!1;let n,i;if(Array.isArray(e)){if(n=e.length,n!=t.length)return!1;for(i=n;0!=i--;)if(!X(e[i],t[i]))return!1;return!0}if(e instanceof Map&&t instanceof Map){if(e.size!==t.size)return!1;for(const n of e.entries())if(!t.has(n[0]))return!1;for(const n of e.entries())if(!X(n[1],t.get(n[0])))return!1;return!0}if(e instanceof Set&&t instanceof Set){if(e.size!==t.size)return!1;for(const n of e.entries())if(!t.has(n[0]))return!1;return!0}if(ArrayBuffer.isView(e)&&ArrayBuffer.isView(t)){if(n=e.length,n!=t.length)return!1;for(i=n;0!=i--;)if(e[i]!==t[i])return!1;return!0}if(e.constructor===RegExp)return e.source===t.source&&e.flags===t.flags;if(e.valueOf!==Object.prototype.valueOf&&e.valueOf!==Y.valueOf)return e.valueOf()===t.valueOf();if(e.toString!==Object.prototype.toString&&e.toString!==Y.toString)return e.toString()===t.toString();const r=Object.keys(e);if(n=r.length,n!==Object.keys(t).length)return!1;for(i=n;0!=i--;)if(!Object.prototype.hasOwnProperty.call(t,r[i]))return!1;for(i=n;0!=i--;){const n=r[i];if(!X(e[n],t[n]))return!1}return!0}return e!=e&&t!=t}function Q(e){const t=[];return function e(n){if(n&&n.toJSON&&"function"==typeof n.toJSON&&(n=n.toJSON()),void 0===n)return;if("number"==typeof n)return isFinite(n)?""+n:"null";if("object"!=typeof n)return JSON.stringify(n);let i,r;if(Array.isArray(n)){for(r="[",i=0;ihn(e[t])?C(`_${t}_${O(e[t])}`):C(`_${t}_${e[t]}`))).join("")}function mn(e){return!0===e||gn(e)&&!e.binned}function pn(e){return"binned"===e||gn(e)&&!0===e.binned}function gn(e){return t.isObject(e)}function hn(e){return J(e,"param")}function yn(e){switch(e){case K:case Z:case xe:case he:case ye:case ve:case De:case we:case ke:case Se:case be:return 6;case Fe:return 4;default:return 10}}function vn(e){return J(e,"expr")}function bn(e){let{level:t}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{level:0};const n=D(e||{}),i={};for(const r of n)i[r]=0===t?Cn(e[r]):bn(e[r],{level:t-1});return i}function xn(e){const{anchor:t,frame:n,offset:i,orient:r,angle:o,limit:a,color:s,subtitleColor:l,subtitleFont:c,subtitleFontSize:f,subtitleFontStyle:d,subtitleFontWeight:m,subtitleLineHeight:p,subtitlePadding:g,...h}=e,y={...t?{anchor:t}:{},...n?{frame:n}:{},...i?{offset:i}:{},...r?{orient:r}:{},...void 0!==o?{angle:o}:{},...void 0!==a?{limit:a}:{}},v={...l?{subtitleColor:l}:{},...c?{subtitleFont:c}:{},...f?{subtitleFontSize:f}:{},...d?{subtitleFontStyle:d}:{},...m?{subtitleFontWeight:m}:{},...p?{subtitleLineHeight:p}:{},...g?{subtitlePadding:g}:{}};return{titleMarkConfig:{...h,...s?{fill:s}:{}},subtitleMarkConfig:u(e,["align","baseline","dx","dy","limit"]),nonMarkTitleProperties:y,subtitle:v}}function $n(e){return t.isString(e)||t.isArray(e)&&t.isString(e[0])}function wn(e){return J(e,"signal")}function kn(e){return J(e,"step")}function Sn(e){return!t.isArray(e)&&(J(e,"field")&&J(e,"data"))}const Dn=D({aria:1,description:1,ariaRole:1,ariaRoleDescription:1,blend:1,opacity:1,fill:1,fillOpacity:1,stroke:1,strokeCap:1,strokeWidth:1,strokeOpacity:1,strokeDash:1,strokeDashOffset:1,strokeJoin:1,strokeOffset:1,strokeMiterLimit:1,startAngle:1,endAngle:1,padAngle:1,innerRadius:1,outerRadius:1,size:1,shape:1,interpolate:1,tension:1,orient:1,align:1,baseline:1,text:1,dir:1,dx:1,dy:1,ellipsis:1,limit:1,radius:1,theta:1,angle:1,font:1,fontSize:1,fontWeight:1,fontStyle:1,lineBreak:1,lineHeight:1,cursor:1,href:1,tooltip:1,cornerRadius:1,cornerRadiusTopLeft:1,cornerRadiusTopRight:1,cornerRadiusBottomLeft:1,cornerRadiusBottomRight:1,aspect:1,width:1,height:1,url:1,smooth:1}),Fn={arc:1,area:1,group:1,image:1,line:1,path:1,rect:1,rule:1,shape:1,symbol:1,text:1,trail:1},On=["cornerRadius","cornerRadiusTopLeft","cornerRadiusTopRight","cornerRadiusBottomLeft","cornerRadiusBottomRight"];function zn(e){const n=t.isArray(e.condition)?e.condition.map(_n):_n(e.condition);return{...Cn(e),condition:n}}function Cn(e){if(vn(e)){const{expr:t,...n}=e;return{signal:t,...n}}return e}function _n(e){if(vn(e)){const{expr:t,...n}=e;return{signal:t,...n}}return e}function Pn(e){if(vn(e)){const{expr:t,...n}=e;return{signal:t,...n}}return wn(e)?e:void 0!==e?{value:e}:void 0}function Nn(e){return wn(e)?e.signal:t.stringValue(e.value)}function An(e){return wn(e)?e.signal:null==e?null:t.stringValue(e)}function Tn(e,t,n){for(const i of n){const n=Mn(i,t.markDef,t.config);void 0!==n&&(e[i]=Pn(n))}return e}function jn(e){return[].concat(e.type,e.style??[])}function En(e,t,n){let i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};const{vgChannel:r,ignoreVgConfig:o}=i;return r&&J(t,r)?t[r]:void 0!==t[e]?t[e]:!o||r&&r!==e?Mn(e,t,n,i):void 0}function Mn(e,t,n){let{vgChannel:i}=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};const r=Rn(e,t,n.style);return U(i?r:void 0,r,i?n[t.type][i]:void 0,n[t.type][e],i?n.mark[i]:n.mark[e])}function Rn(e,t,n){return Ln(e,jn(t),n)}function Ln(e,n,i){let r;n=t.array(n);for(const t of n){const n=i[t];J(n,e)&&(r=n[e])}return r}function qn(e,n){return t.array(e).reduce(((e,t)=>(e.field.push(ma(t,n)),e.order.push(t.sort??"ascending"),e)),{field:[],order:[]})}function Un(e,t){const n=[...e];return t.forEach((e=>{for(const t of n)if(X(t,e))return;n.push(e)})),n}function Wn(e,n){return X(e,n)||!n?e:e?[...t.array(e),...t.array(n)].join(", "):n}function In(e,t){const n=e.value,i=t.value;if(null==n||null===i)return{explicit:e.explicit,value:null};if(($n(n)||wn(n))&&($n(i)||wn(i)))return{explicit:e.explicit,value:Wn(n,i)};if($n(n)||wn(n))return{explicit:e.explicit,value:n};if($n(i)||wn(i))return{explicit:e.explicit,value:i};if(!($n(n)||wn(n)||$n(i)||wn(i)))return{explicit:e.explicit,value:Un(n,i)};throw new Error("It should never reach here")}function Bn(e){return`Invalid specification ${Q(e)}. Make sure the specification includes at least one of the following properties: "mark", "layer", "facet", "hconcat", "vconcat", "concat", or "repeat".`}const Vn='Autosize "fit" only works for single views and layered views.';function Hn(e){return`${"width"==e?"Width":"Height"} "container" only works for single views and layered views.`}function Gn(e){return`${"width"==e?"Width":"Height"} "container" only works well with autosize "fit" or "fit-${"width"==e?"x":"y"}".`}function Yn(e){return e?`Dropping "fit-${e}" because spec has discrete ${st(e)}.`:'Dropping "fit" because spec has discrete size.'}function Xn(e){return`Unknown field for ${e}. Cannot calculate view size.`}function Qn(e){return`Cannot project a selection on encoding channel "${e}", which has no field.`}function Jn(e,t){return`Cannot project a selection on encoding channel "${e}" as it uses an aggregate function ("${t}").`}function Kn(e){return`Selection not supported for ${e} yet.`}const Zn="The same selection must be used to override scale domains in a layered view.";function ei(e){return`The "columns" property cannot be used when "${e}" has nested row/column.`}const ti="Animation involving facet, layer, or concat is currently unsupported.";function ni(e,t,n){return`An ancestor parsed field "${e}" as ${n} but a child wants to parse the field as ${t}.`}function ii(e){return`Config.customFormatTypes is not true, thus custom format type and format for channel ${e} are dropped.`}function ri(e){return`${e}Offset dropped because ${e} is continuous`}function oi(e){return`Invalid field type "${e}".`}function ai(e,t){const{fill:n,stroke:i}=t;return`Dropping color ${e} as the plot also has ${n&&i?"fill and stroke":n?"fill":"stroke"}.`}function si(e,t){return`Dropping ${Q(e)} from channel "${t}" since it does not contain any data field, datum, value, or signal.`}function li(e,t,n){return`${e} dropped as it is incompatible with "${t}".`}function ci(e){return`${e} encoding should be discrete (ordinal / nominal / binned).`}function ui(e){return`${e} encoding should be discrete (ordinal / nominal / binned) or use a discretizing scale (e.g. threshold).`}function fi(e,t){return`Using discrete channel "${e}" to encode "${t}" field can be misleading as it does not encode ${"ordinal"===t?"order":"magnitude"}.`}function di(e){return`Using unaggregated domain with raw field has no effect (${Q(e)}).`}function mi(e){return`Unaggregated domain not applicable for "${e}" since it produces values outside the origin domain of the source data.`}function pi(e){return`Unaggregated domain is currently unsupported for log scale (${Q(e)}).`}function gi(e,t,n){return`${n}-scale's "${t}" is dropped as it does not work with ${e} scale.`}function hi(e){return`The step for "${e}" is dropped because the ${"width"===e?"x":"y"} is continuous.`}const yi="Domains that should be unioned has conflicting sort properties. Sort will be set to true.";function vi(e,t){return`Invalid ${e}: ${Q(t)}.`}function bi(e){return`1D error band does not support ${e}.`}function xi(e){return`Channel ${e} is required for "binned" bin.`}const $i=t.logger(t.Warn);let wi=$i;function ki(){wi.error(...arguments)}function Si(){wi.warn(...arguments)}function Di(e){if(e&&t.isObject(e))for(const t of Ai)if(J(e,t))return!0;return!1}const Fi=["january","february","march","april","may","june","july","august","september","october","november","december"],Oi=Fi.map((e=>e.substr(0,3))),zi=["sunday","monday","tuesday","wednesday","thursday","friday","saturday"],Ci=zi.map((e=>e.substr(0,3)));function _i(e,n){const i=[];if(n&&void 0!==e.day&&D(e).length>1&&(Si(function(e){return`Dropping day from datetime ${Q(e)} as day cannot be combined with other units.`}(e)),delete(e=l(e)).day),void 0!==e.year?i.push(e.year):i.push(2012),void 0!==e.month){const r=n?function(e){if(G(e)&&(e=+e),t.isNumber(e))return e-1;{const t=e.toLowerCase(),n=Fi.indexOf(t);if(-1!==n)return n;const i=t.substr(0,3),r=Oi.indexOf(i);if(-1!==r)return r;throw new Error(vi("month",e))}}(e.month):e.month;i.push(r)}else if(void 0!==e.quarter){const r=n?function(e){if(G(e)&&(e=+e),t.isNumber(e))return e>4&&Si(vi("quarter",e)),e-1;throw new Error(vi("quarter",e))}(e.quarter):e.quarter;i.push(t.isNumber(r)?3*r:`${r}*3`)}else i.push(0);if(void 0!==e.date)i.push(e.date);else if(void 0!==e.day){const r=n?function(e){if(G(e)&&(e=+e),t.isNumber(e))return e%7;{const t=e.toLowerCase(),n=zi.indexOf(t);if(-1!==n)return n;const i=t.substr(0,3),r=Ci.indexOf(i);if(-1!==r)return r;throw new Error(vi("day",e))}}(e.day):e.day;i.push(t.isNumber(r)?r+1:`${r}+1`)}else i.push(1);for(const t of["hours","minutes","seconds","milliseconds"]){const n=e[t];i.push(void 0===n?0:n)}return i}function Pi(e){const t=_i(e,!0).join(", ");return e.utc?`utc(${t})`:`datetime(${t})`}const Ni={year:1,quarter:1,month:1,week:1,day:1,dayofyear:1,date:1,hours:1,minutes:1,seconds:1,milliseconds:1},Ai=D(Ni);function Ti(e){return t.isObject(e)?e.binned:ji(e)}function ji(e){return e&&e.startsWith("binned")}function Ei(e){return e.startsWith("utc")}const Mi={"year-month":"%b %Y ","year-month-date":"%b %d, %Y "};function Ri(e){return Ai.filter((t=>qi(e,t)))}function Li(e){const t=Ri(e);return t[t.length-1]}function qi(e,t){const n=e.indexOf(t);return!(n<0)&&(!(n>0&&"seconds"===t&&"i"===e.charAt(n-1))&&(!(e.length>n+3&&"day"===t&&"o"===e.charAt(n+3))&&!(n>0&&"year"===t&&"f"===e.charAt(n-1))))}function Ui(e,t){let{end:n}=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{end:!1};const i=A(t),r=Ei(e)?"utc":"";let o;const a={};for(const t of Ai)qi(e,t)&&(a[t]="quarter"===(s=t)?`(${r}quarter(${i})-1)`:`${r}${s}(${i})`,o=t);var s;return n&&(a[o]+="+1"),function(e){const t=_i(e,!1).join(", ");return e.utc?`utc(${t})`:`datetime(${t})`}(a)}function Wi(e){if(!e)return;return`timeUnitSpecifier(${Q(Ri(e))}, ${Q(Mi)})`}function Ii(e){if(!e)return;let n;return t.isString(e)?n=ji(e)?{unit:e.substring(6),binned:!0}:{unit:e}:t.isObject(e)&&(n={...e,...e.unit?{unit:e.unit}:{}}),Ei(n.unit)&&(n.utc=!0,n.unit=n.unit.substring(3)),n}function Bi(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:e=>e;const n=Ii(e),i=Li(n.unit);if(i&&"day"!==i){const e={year:2001,month:1,date:1,hours:0,minutes:0,seconds:0,milliseconds:0},{step:r,part:o}=Hi(i,n.step);return`${t(Pi({...e,[o]:+e[o]+r}))} - ${t(Pi(e))}`}}const Vi={year:1,month:1,date:1,hours:1,minutes:1,seconds:1,milliseconds:1};function Hi(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;if(function(e){return t.hasOwnProperty(Vi,e)}(e))return{part:e,step:n};switch(e){case"day":case"dayofyear":return{part:"date",step:n};case"quarter":return{part:"month",step:3*n};case"week":return{part:"date",step:7*n}}}function Gi(e){return!!e?.field&&void 0!==e.equal}function Yi(e){return!!e?.field&&void 0!==e.lt}function Xi(e){return!!e?.field&&void 0!==e.lte}function Qi(e){return!!e?.field&&void 0!==e.gt}function Ji(e){return!!e?.field&&void 0!==e.gte}function Ki(e){if(e?.field){if(t.isArray(e.range)&&2===e.range.length)return!0;if(wn(e.range))return!0}return!1}function Zi(e){return!!e?.field&&(t.isArray(e.oneOf)||t.isArray(e.in))}function er(e){return Zi(e)||Gi(e)||Ki(e)||Yi(e)||Qi(e)||Xi(e)||Ji(e)}function tr(e,t){return _a(e,{timeUnit:t,wrapTime:!0})}function nr(e){let t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];const{field:n}=e,i=Ii(e.timeUnit),{unit:r,binned:o}=i||{},a=ma(e,{expr:"datum"}),s=r?`time(${o?a:Ui(r,n)})`:a;if(Gi(e))return`${s}===${tr(e.equal,r)}`;if(Yi(e)){return`${s}<${tr(e.lt,r)}`}if(Qi(e)){return`${s}>${tr(e.gt,r)}`}if(Xi(e)){return`${s}<=${tr(e.lte,r)}`}if(Ji(e)){return`${s}>=${tr(e.gte,r)}`}if(Zi(e))return`indexof([${function(e,t){return e.map((e=>tr(e,t)))}(e.oneOf,r).join(",")}], ${s}) !== -1`;if(function(e){return!!e?.field&&void 0!==e.valid}(e))return ir(s,e.valid);if(Ki(e)){const{range:n}=bn(e),i=wn(n)?{signal:`${n.signal}[0]`}:n[0],o=wn(n)?{signal:`${n.signal}[1]`}:n[1];if(null!==i&&null!==o&&t)return"inrange("+s+", ["+tr(i,r)+", "+tr(o,r)+"])";const a=[];return null!==i&&a.push(`${s} >= ${tr(i,r)}`),null!==o&&a.push(`${s} <= ${tr(o,r)}`),a.length>0?a.join(" && "):"true"}throw new Error(`Invalid field predicate: ${Q(e)}`)}function ir(e){return!(arguments.length>1&&void 0!==arguments[1])||arguments[1]?`isValid(${e}) && isFinite(+${e})`:`!isValid(${e}) || !isFinite(+${e})`}function rr(e){return er(e)&&e.timeUnit?{...e,timeUnit:Ii(e.timeUnit)}:e}function or(e){return"quantitative"===e||"temporal"===e}function ar(e){return"ordinal"===e||"nominal"===e}const sr="quantitative",lr="ordinal",cr="temporal",ur="nominal",fr="geojson";const dr={LINEAR:"linear",LOG:"log",POW:"pow",SQRT:"sqrt",SYMLOG:"symlog",IDENTITY:"identity",SEQUENTIAL:"sequential",TIME:"time",UTC:"utc",QUANTILE:"quantile",QUANTIZE:"quantize",THRESHOLD:"threshold",BIN_ORDINAL:"bin-ordinal",ORDINAL:"ordinal",POINT:"point",BAND:"band"},mr={linear:"numeric",log:"numeric",pow:"numeric",sqrt:"numeric",symlog:"numeric",identity:"numeric",sequential:"numeric",time:"time",utc:"time",ordinal:"ordinal","bin-ordinal":"bin-ordinal",point:"ordinal-position",band:"ordinal-position",quantile:"discretizing",quantize:"discretizing",threshold:"discretizing"};function pr(e,t){const n=mr[e],i=mr[t];return n===i||"ordinal-position"===n&&"time"===i||"ordinal-position"===i&&"time"===n}const gr={linear:0,log:1,pow:1,sqrt:1,symlog:1,identity:1,sequential:1,time:0,utc:0,point:10,band:11,ordinal:0,"bin-ordinal":0,quantile:0,quantize:0,threshold:0};function hr(e){return gr[e]}const yr=new Set(["linear","log","pow","sqrt","symlog"]),vr=new Set([...yr,"time","utc"]);function br(e){return yr.has(e)}const xr=new Set(["quantile","quantize","threshold"]),$r=new Set([...vr,...xr,"sequential","identity"]),wr=new Set(["ordinal","bin-ordinal","point","band"]);function kr(e){return wr.has(e)}function Sr(e){return $r.has(e)}function Dr(e){return vr.has(e)}function Fr(e){return xr.has(e)}function Or(e){return J(e,"param")}const{type:zr,domain:Cr,range:_r,rangeMax:Pr,rangeMin:Nr,scheme:Ar,...Tr}={type:1,domain:1,domainMax:1,domainMin:1,domainMid:1,domainRaw:1,align:1,range:1,rangeMax:1,rangeMin:1,scheme:1,bins:1,reverse:1,round:1,clamp:1,nice:1,base:1,exponent:1,constant:1,interpolate:1,zero:1,padding:1,paddingInner:1,paddingOuter:1},jr=D(Tr);function Er(e,t){switch(t){case"type":case"domain":case"reverse":case"range":return!0;case"scheme":case"interpolate":return!["point","band","identity"].includes(e);case"bins":return!["point","band","identity","ordinal"].includes(e);case"round":return Dr(e)||"band"===e||"point"===e;case"padding":case"rangeMin":case"rangeMax":return Dr(e)||["point","band"].includes(e);case"paddingOuter":case"align":return["point","band"].includes(e);case"paddingInner":return"band"===e;case"domainMax":case"domainMid":case"domainMin":case"domainRaw":case"clamp":return Dr(e);case"nice":return Dr(e)||"quantize"===e||"threshold"===e;case"exponent":return"pow"===e;case"base":return"log"===e;case"constant":return"symlog"===e;case"zero":return Sr(e)&&!p(["log","time","utc","threshold","quantile"],e)}}function Mr(e,t){switch(t){case"interpolate":case"scheme":case"domainMid":return We(e)?void 0:`Cannot use the scale property "${t}" with non-color channel.`;case"align":case"type":case"bins":case"domain":case"domainMax":case"domainMin":case"domainRaw":case"range":case"base":case"exponent":case"constant":case"nice":case"padding":case"paddingInner":case"paddingOuter":case"rangeMax":case"rangeMin":case"reverse":case"round":case"clamp":case"zero":return}}const Rr={arc:"arc",area:"area",bar:"bar",image:"image",line:"line",point:"point",rect:"rect",rule:"rule",text:"text",tick:"tick",trail:"trail",circle:"circle",square:"square",geoshape:"geoshape"},Lr=Rr.arc,qr=Rr.area,Ur=Rr.bar,Wr=Rr.image,Ir=Rr.line,Br=Rr.point,Vr=Rr.rect,Hr=Rr.rule,Gr=Rr.text,Yr=Rr.tick,Xr=Rr.trail,Qr=Rr.circle,Jr=Rr.square,Kr=Rr.geoshape;function Zr(e){return["line","area","trail"].includes(e)}function eo(e){return["rect","bar","image","arc","tick"].includes(e)}const to=new Set(D(Rr));function no(e){return J(e,"type")}const io=["stroke","strokeWidth","strokeDash","strokeDashOffset","strokeOpacity","strokeJoin","strokeMiterLimit","fill","fillOpacity"],ro=D({color:1,filled:1,invalid:1,order:1,radius2:1,theta2:1,timeUnitBandSize:1,timeUnitBandPosition:1}),oo=["binSpacing","continuousBandSize","discreteBandSize","minBandSize"],ao={area:["line","point"],bar:oo,rect:oo,line:["point"],tick:["bandSize","thickness",...oo]},so=D({mark:1,arc:1,area:1,bar:1,circle:1,image:1,line:1,point:1,rect:1,rule:1,square:1,text:1,tick:1,trail:1,geoshape:1});function lo(e){return J(e,"band")}const co={horizontal:["cornerRadiusTopRight","cornerRadiusBottomRight"],vertical:["cornerRadiusTopLeft","cornerRadiusTopRight"]},uo={binSpacing:0,continuousBandSize:5,minBandSize:.25,timeUnitBandPosition:.5},fo={...uo,binSpacing:1},mo={...uo,thickness:1};function po(e,t){let{isPath:n}=t;return void 0===e||"break-paths-show-path-domains"===e?n?"break-paths-show-domains":"filter":null===e?"show":e}function go(e){let{markDef:t,config:n,scaleChannel:i,scaleType:r,isCountAggregate:o}=e;if(!r||!Sr(r)||o)return"always-valid";const a=po(En("invalid",t,n),{isPath:Zr(t.type)}),s=n.scale?.invalid?.[i];return void 0!==s?"show":a}function ho(e){let{scaleName:t,scale:n,mode:i}=e;const r=`domain('${t}')`;if(!n||!t)return;const o=`${r}[0]`,a=`peek(${r})`,s=n.domainHasZero();if("definitely"===s)return{scale:t,value:0};if("maybe"===s){return{signal:`scale('${t}', inrange(0, ${r}) ? 0 : ${"zeroOrMin"===i?o:a})`}}return{signal:`scale('${t}', ${"zeroOrMin"===i?o:a})`}}function yo(e){let{scaleChannel:t,channelDef:n,scale:i,scaleName:r,markDef:o,config:a}=e;const s=i?.get("type"),l=wa(n),c=go({scaleChannel:t,markDef:o,config:a,scaleType:s,isCountAggregate:cn(l?.aggregate)});if(l&&"show"===c){const e=a.scale.invalid?.[t]??"zero-or-min";return{test:ir(ma(l,{expr:"datum"}),!1),...vo(e,i,r)}}}function vo(e,n,i){if(r=e,t.isObject(r)&&"value"in r){const{value:t}=e;return wn(t)?{signal:t.signal}:{value:t}}var r;return ho({scale:n,scaleName:i,mode:"zeroOrMin"})}function bo(e){const{channel:t,channelDef:n,markDef:i,scale:r,scaleName:o,config:a}=e,s=rt(t),l=wo(e),c=yo({scaleChannel:s,channelDef:n,scale:r,scaleName:o,markDef:i,config:a});return void 0!==c?[c,l]:l}function xo(e,t,n,i){const r={};if(t&&(r.scale=t),ta(e)){const{datum:t}=e;Di(t)?r.signal=Pi(t):wn(t)?r.signal=t.signal:vn(t)?r.signal=t.expr:r.value=t}else r.field=ma(e,n);if(i){const{offset:e,band:t}=i;e&&(r.offset=e),t&&(r.band=t)}return r}function $o(e){let{scaleName:t,fieldOrDatumDef:n,fieldOrDatumDef2:i,offset:r,startSuffix:o,endSuffix:a="end",bandPosition:s=.5}=e;const l=!wn(s)&&01&&void 0!==arguments[1]?arguments[1]:{},n=e.field;const i=t.prefix;let r=t.suffix,o="";if(function(e){return"count"===e.aggregate}(e))n=B("count");else{let i;if(!t.nofn)if(function(e){return J(e,"op")}(e))i=e.op;else{const{bin:a,aggregate:s,timeUnit:l}=e;mn(a)?(i=dn(a),r=(t.binSuffix??"")+(t.suffix??"")):s?an(s)?(o=`["${n}"]`,n=`argmax_${s.argmax}`):on(s)?(o=`["${n}"]`,n=`argmin_${s.argmin}`):i=String(s):l&&!Ti(l)&&(i=function(e){const{utc:t,...n}=Ii(e);return n.unit?(t?"utc":"")+D(n).map((e=>C(`${"unit"===e?"":`_${e}_`}${n[e]}`))).join(""):(t?"utc":"")+"timeunit"+D(n).map((e=>C(`_${e}_${n[e]}`))).join("")}(l),r=(!["range","mid"].includes(t.binSuffix)&&t.binSuffix||"")+(t.suffix??""))}i&&(n=n?`${i}_${n}`:i)}return r&&(n=`${n}_${r}`),i&&(n=`${i}_${n}`),t.forAs?L(n):t.expr?T(n,t.expr)+o:M(n)+o}function pa(e){switch(e.type){case"nominal":case"ordinal":case"geojson":return!0;case"quantitative":return Zo(e)&&!!e.bin;case"temporal":return!1}throw new Error(oi(e.type))}const ga=(e,t)=>{switch(t.fieldTitle){case"plain":return e.field;case"functional":return function(e){const{aggregate:t,bin:n,timeUnit:i,field:r}=e;if(an(t))return`${r} for argmax(${t.argmax})`;if(on(t))return`${r} for argmin(${t.argmin})`;const o=i&&!Ti(i)?Ii(i):void 0,a=t||o?.unit||o?.maxbins&&"timeunit"||mn(n)&&"bin";return a?`${a.toUpperCase()}(${r})`:r}(e);default:return function(e,t){const{field:n,bin:i,timeUnit:r,aggregate:o}=e;if("count"===o)return t.countTitle;if(mn(i))return`${n} (binned)`;if(r&&!Ti(r)){const e=Ii(r)?.unit;if(e)return`${n} (${Ri(e).join("-")})`}else if(o)return an(o)?`${n} for max ${o.argmax}`:on(o)?`${n} for min ${o.argmin}`:`${N(o)} of ${n}`;return n}(e,t)}};let ha=ga;function ya(e){ha=e}function va(e,t,n){let{allowDisabling:i,includeDefault:r=!0}=n;const o=ba(e)?.title;if(!Zo(e))return o??e.title;const a=e,s=r?xa(a,t):void 0;return i?U(o,a.title,s):o??a.title??s}function ba(e){return ca(e)&&e.axis?e.axis:ua(e)&&e.legend?e.legend:Wo(e)&&e.header?e.header:void 0}function xa(e,t){return ha(e,t)}function $a(e){if(fa(e)){const{format:t,formatType:n}=e;return{format:t,formatType:n}}{const t=ba(e)??{},{format:n,formatType:i}=t;return{format:n,formatType:i}}}function wa(e){return Zo(e)?e:Jo(e)?e.condition:void 0}function ka(e){return oa(e)?e:Ko(e)?e.condition:void 0}function Sa(e,n,i){let r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};if(t.isString(e)||t.isNumber(e)||t.isBoolean(e)){return Si(function(e,t,n){return`Channel ${e} is a ${t}. Converted to {value: ${Q(n)}}.`}(n,t.isString(e)?"string":t.isNumber(e)?"number":"boolean",e)),{value:e}}return oa(e)?Da(e,n,i,r):Ko(e)?{...e,condition:Da(e.condition,n,i,r)}:e}function Da(e,n,i,r){if(fa(e)){const{format:t,formatType:o,...a}=e;if(So(o)&&!i.customFormatTypes)return Si(ii(n)),Da(a,n,i,r)}else{const t=ca(e)?"axis":ua(e)?"legend":Wo(e)?"header":null;if(t&&e[t]){const{format:o,formatType:a,...s}=e[t];if(So(a)&&!i.customFormatTypes)return Si(ii(n)),Da({...e,[t]:s},n,i,r)}}return Zo(e)?Fa(e,n,r):function(e){let n=e.type;if(n)return e;const{datum:i}=e;return n=t.isNumber(i)?"quantitative":t.isString(i)?"nominal":Di(i)?"temporal":void 0,{...e,type:n}}(e)}function Fa(e,n){let{compositeMark:i=!1}=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const{aggregate:r,timeUnit:o,bin:a,field:s}=e,l={...e};if(i||!r||sn(r)||an(r)||on(r)||(Si(function(e){return`Invalid aggregation operator "${e}".`}(r)),delete l.aggregate),o&&(l.timeUnit=Ii(o)),s&&(l.field=`${s}`),mn(a)&&(l.bin=Oa(a,n)),pn(a)&&!_t(n)&&Si(function(e){return`Channel ${e} should not be used with "binned" bin.`}(n)),aa(l)){const{type:e}=l,t=function(e){if(e)switch(e=e.toLowerCase()){case"q":case sr:return"quantitative";case"t":case cr:return"temporal";case"o":case lr:return"ordinal";case"n":case ur:return"nominal";case fr:return"geojson"}}(e);e!==t&&(l.type=t),"quantitative"!==e&&cn(r)&&(Si(function(e,t){return`Invalid field type "${e}" for aggregate: "${t}", using "quantitative" instead.`}(e,r)),l.type="quantitative")}else if(!it(n)){const e=function(e,n){switch(n){case"latitude":case"longitude":return"quantitative";case"row":case"column":case"facet":case"shape":case"strokeDash":return"nominal";case"order":return"ordinal"}if(Vo(e)&&t.isArray(e.sort))return"ordinal";const{aggregate:i,bin:r,timeUnit:o}=e;if(o)return"temporal";if(r||i&&!an(i)&&!on(i))return"quantitative";if(la(e)&&e.scale?.type)switch(mr[e.scale.type]){case"numeric":case"discretizing":return"quantitative";case"time":return"temporal"}return"nominal"}(l,n);l.type=e}if(aa(l)){const{compatible:e,warning:t}=function(e,t){const n=e.type;if("geojson"===n&&"shape"!==t)return{compatible:!1,warning:`Channel ${t} should not be used with a geojson data.`};switch(t){case K:case Z:case ee:return pa(e)?za:{compatible:!1,warning:ci(t)};case te:case ne:case oe:case ae:case he:case ye:case ve:case Oe:case Ce:case _e:case Pe:case Ne:case Ae:case $e:case ce:case se:case Te:return za;case de:case pe:case fe:case me:return n!==sr?{compatible:!1,warning:`Channel ${t} should be used with a quantitative field only, not ${e.type} field.`}:za;case we:case ke:case Se:case De:case xe:case ue:case le:case ie:case re:case ge:return"nominal"!==n||e.sort?za:{compatible:!1,warning:`Channel ${t} should not be used with an unsorted discrete field.`};case be:case Fe:return pa(e)||la(i=e)&&Fr(i.scale?.type)?za:{compatible:!1,warning:ui(t)};case ze:return"nominal"!==e.type||"sort"in e?za:{compatible:!1,warning:"Channel order is inappropriate for nominal field, which has no inherent order."}}var i}(l,n)||{};!1===e&&Si(t)}if(Vo(l)&&t.isString(l.sort)){const{sort:e}=l;if(Ro(e))return{...l,sort:{encoding:e}};const t=e.substring(1);if("-"===e.charAt(0)&&Ro(t))return{...l,sort:{encoding:t,order:"descending"}}}if(Wo(l)){const{header:e}=l;if(e){const{orient:t,...n}=e;if(t)return{...l,header:{...n,labelOrient:e.labelOrient||t,titleOrient:e.titleOrient||t}}}}return l}function Oa(e,n){return t.isBoolean(e)?{maxbins:yn(n)}:"binned"===e?{binned:!0}:e.maxbins||e.step?e:{...e,maxbins:yn(n)}}const za={compatible:!0};function Ca(e){const{formatType:t}=$a(e);return"time"===t||!t&&((n=e)&&("temporal"===n.type||Zo(n)&&!!n.timeUnit));var n}function _a(e,n){let{timeUnit:i,type:r,wrapTime:o,undefinedIfExprNotRequired:a}=n;const s=i&&Ii(i)?.unit;let l,c=s||"temporal"===r;return vn(e)?l=e.expr:wn(e)?l=e.signal:Di(e)?(c=!0,l=Pi(e)):(t.isString(e)||t.isNumber(e))&&c&&(l=`datetime(${Q(e)})`,function(e){return t.hasOwnProperty(Ni,e)}(s)&&(t.isNumber(e)&&e<1e4||t.isString(e)&&isNaN(Date.parse(e)))&&(l=Pi({[s]:e}))),l?o&&c?`time(${l})`:l:a?void 0:Q(e)}function Pa(e,t){const{type:n}=e;return t.map((t=>{const i=_a(t,{timeUnit:Zo(e)&&!Ti(e.timeUnit)?e.timeUnit:void 0,type:n,undefinedIfExprNotRequired:!0});return void 0!==i?{signal:i}:t}))}function Na(e,t){return mn(e.bin)?Qt(t)&&["ordinal","nominal"].includes(e.type):(console.warn("Only call this method for binned field defs."),!1)}const Aa={labelAlign:{part:"labels",vgProp:"align"},labelBaseline:{part:"labels",vgProp:"baseline"},labelColor:{part:"labels",vgProp:"fill"},labelFont:{part:"labels",vgProp:"font"},labelFontSize:{part:"labels",vgProp:"fontSize"},labelFontStyle:{part:"labels",vgProp:"fontStyle"},labelFontWeight:{part:"labels",vgProp:"fontWeight"},labelOpacity:{part:"labels",vgProp:"opacity"},labelOffset:null,labelPadding:null,gridColor:{part:"grid",vgProp:"stroke"},gridDash:{part:"grid",vgProp:"strokeDash"},gridDashOffset:{part:"grid",vgProp:"strokeDashOffset"},gridOpacity:{part:"grid",vgProp:"opacity"},gridWidth:{part:"grid",vgProp:"strokeWidth"},tickColor:{part:"ticks",vgProp:"stroke"},tickDash:{part:"ticks",vgProp:"strokeDash"},tickDashOffset:{part:"ticks",vgProp:"strokeDashOffset"},tickOpacity:{part:"ticks",vgProp:"opacity"},tickSize:null,tickWidth:{part:"ticks",vgProp:"strokeWidth"}};function Ta(e){return e?.condition}const ja=["domain","grid","labels","ticks","title"],Ea={grid:"grid",gridCap:"grid",gridColor:"grid",gridDash:"grid",gridDashOffset:"grid",gridOpacity:"grid",gridScale:"grid",gridWidth:"grid",orient:"main",bandPosition:"both",aria:"main",description:"main",domain:"main",domainCap:"main",domainColor:"main",domainDash:"main",domainDashOffset:"main",domainOpacity:"main",domainWidth:"main",format:"main",formatType:"main",labelAlign:"main",labelAngle:"main",labelBaseline:"main",labelBound:"main",labelColor:"main",labelFlush:"main",labelFlushOffset:"main",labelFont:"main",labelFontSize:"main",labelFontStyle:"main",labelFontWeight:"main",labelLimit:"main",labelLineHeight:"main",labelOffset:"main",labelOpacity:"main",labelOverlap:"main",labelPadding:"main",labels:"main",labelSeparation:"main",maxExtent:"main",minExtent:"main",offset:"both",position:"main",tickCap:"main",tickColor:"main",tickDash:"main",tickDashOffset:"main",tickMinStep:"both",tickOffset:"both",tickOpacity:"main",tickRound:"both",ticks:"main",tickSize:"main",tickWidth:"both",title:"main",titleAlign:"main",titleAnchor:"main",titleAngle:"main",titleBaseline:"main",titleColor:"main",titleFont:"main",titleFontSize:"main",titleFontStyle:"main",titleFontWeight:"main",titleLimit:"main",titleLineHeight:"main",titleOpacity:"main",titlePadding:"main",titleX:"main",titleY:"main",encode:"both",scale:"both",tickBand:"both",tickCount:"both",tickExtra:"both",translate:"both",values:"both",zindex:"both"},Ma={orient:1,aria:1,bandPosition:1,description:1,domain:1,domainCap:1,domainColor:1,domainDash:1,domainDashOffset:1,domainOpacity:1,domainWidth:1,format:1,formatType:1,grid:1,gridCap:1,gridColor:1,gridDash:1,gridDashOffset:1,gridOpacity:1,gridWidth:1,labelAlign:1,labelAngle:1,labelBaseline:1,labelBound:1,labelColor:1,labelFlush:1,labelFlushOffset:1,labelFont:1,labelFontSize:1,labelFontStyle:1,labelFontWeight:1,labelLimit:1,labelLineHeight:1,labelOffset:1,labelOpacity:1,labelOverlap:1,labelPadding:1,labels:1,labelSeparation:1,maxExtent:1,minExtent:1,offset:1,position:1,tickBand:1,tickCap:1,tickColor:1,tickCount:1,tickDash:1,tickDashOffset:1,tickExtra:1,tickMinStep:1,tickOffset:1,tickOpacity:1,tickRound:1,ticks:1,tickSize:1,tickWidth:1,title:1,titleAlign:1,titleAnchor:1,titleAngle:1,titleBaseline:1,titleColor:1,titleFont:1,titleFontSize:1,titleFontStyle:1,titleFontWeight:1,titleLimit:1,titleLineHeight:1,titleOpacity:1,titlePadding:1,titleX:1,titleY:1,translate:1,values:1,zindex:1},Ra={...Ma,style:1,labelExpr:1,encoding:1};function La(e){return t.hasOwnProperty(Ra,e)}const qa=D({axis:1,axisBand:1,axisBottom:1,axisDiscrete:1,axisLeft:1,axisPoint:1,axisQuantitative:1,axisRight:1,axisTemporal:1,axisTop:1,axisX:1,axisXBand:1,axisXDiscrete:1,axisXPoint:1,axisXQuantitative:1,axisXTemporal:1,axisY:1,axisYBand:1,axisYDiscrete:1,axisYPoint:1,axisYQuantitative:1,axisYTemporal:1});function Ua(e){return J(e,"mark")}class Wa{constructor(e,t){this.name=e,this.run=t}hasMatchingType(e){return!!Ua(e)&&(no(t=e.mark)?t.type:t)===this.name;var t}}function Ia(e,n){const i=e&&e[n];return!!i&&(t.isArray(i)?g(i,(e=>!!e.field)):Zo(i)||Jo(i))}function Ba(e,n){const i=e&&e[n];return!!i&&(t.isArray(i)?g(i,(e=>!!e.field)):Zo(i)||ta(i)||Ko(i))}function Va(e,t){if(_t(t)){const n=e[t];if((Zo(n)||ta(n))&&(ar(n.type)||Zo(n)&&n.timeUnit)){return Ba(e,ct(t))}}return!1}function Ha(e){return g(He,(n=>{if(Ia(e,n)){const i=e[n];if(t.isArray(i))return g(i,(e=>!!e.aggregate));{const e=wa(i);return e&&!!e.aggregate}}return!1}))}function Ga(e,n){const i=[],r=[],o=[],a=[],s={};return Qa(e,((l,c)=>{if(Zo(l)){const{field:u,aggregate:f,bin:d,timeUnit:m,...p}=l;if(f||m||d){const e=ba(l),g=e?.title;let h=ma(l,{forAs:!0});const y={...g?[]:{title:va(l,n,{allowDisabling:!0})},...p,field:h};if(f){let e;if(an(f)?(e="argmax",h=ma({op:"argmax",field:f.argmax},{forAs:!0}),y.field=`${h}.${u}`):on(f)?(e="argmin",h=ma({op:"argmin",field:f.argmin},{forAs:!0}),y.field=`${h}.${u}`):"boxplot"!==f&&"errorbar"!==f&&"errorband"!==f&&(e=f),e){const t={op:e,as:h};u&&(t.field=u),a.push(t)}}else if(i.push(h),aa(l)&&mn(d)){if(r.push({bin:d,field:u,as:h}),i.push(ma(l,{binSuffix:"end"})),Na(l,c)&&i.push(ma(l,{binSuffix:"range"})),_t(c)){const e={field:`${h}_end`};s[`${c}2`]=e}y.bin="binned",it(c)||(y.type=sr)}else if(m&&!Ti(m)){o.push({timeUnit:m,field:u,as:h});const e=aa(l)&&l.type!==cr&&"time";e&&(c===Oe||c===Pe?y.formatType=e:!function(e){return t.hasOwnProperty(Ft,e)}(c)?_t(c)&&(y.axis={formatType:e,...y.axis}):y.legend={formatType:e,...y.legend})}s[c]=y}else i.push(u),s[c]=e[c]}else s[c]=e[c]})),{bins:r,timeUnits:o,aggregate:a,groupby:i,encoding:s}}function Ya(e,t,n){const i=Jt(t,n);if(!i)return!1;if("binned"===i){const n=e[t===ie?te:ne];return!!(Zo(n)&&Zo(e[t])&&pn(n.bin))}return!0}function Xa(e,t){const n={};for(const i of D(e)){const r=Sa(e[i],i,t,{compositeMark:!0});n[i]=r}return n}function Qa(e,n,i){if(e)for(const r of D(e)){const o=e[r];if(t.isArray(o))for(const e of o)n.call(i,e,r);else n.call(i,o,r)}}function Ja(e,n){return D(n).reduce(((i,r)=>{switch(r){case te:case ne:case Ne:case Te:case Ae:case ie:case re:case oe:case ae:case ce:case ue:case se:case le:case ge:case fe:case de:case me:case pe:case Oe:case be:case $e:case Pe:return i;case ze:if("line"===e||"trail"===e)return i;case Ce:case _e:{const e=n[r];if(t.isArray(e)||Zo(e))for(const n of t.array(e))n.aggregate||i.push(ma(n,{}));return i}case xe:if("trail"===e)return i;case he:case ye:case ve:case we:case ke:case Se:case Fe:case De:{const e=wa(n[r]);return e&&!e.aggregate&&i.push(ma(e,{})),i}}}),[])}function Ka(e,n,i){let r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];if("tooltip"in i)return{tooltip:i.tooltip};return{tooltip:[...e.map((e=>{let{fieldPrefix:t,titlePrefix:i}=e;const o=r?` of ${Za(n)}`:"";return{field:t+n.field,type:n.type,title:wn(i)?{signal:`${i}"${escape(o)}"`}:i+o}})),...b(function(e){const n=[];for(const i of D(e))if(Ia(e,i)){const r=e[i],o=t.array(r);for(const e of o)Zo(e)?n.push(e):Jo(e)&&n.push(e.condition)}return n}(i).map(da),d)]}}function Za(e){const{title:t,field:n}=e;return U(t,n)}function es(e,n,i,r,o){const{scale:a,axis:s}=i;return l=>{let{partName:c,mark:u,positionPrefix:f,endPositionPrefix:d,extraEncoding:m={}}=l;const p=Za(i);return ts(e,c,o,{mark:u,encoding:{[n]:{field:`${f}_${i.field}`,type:i.type,...void 0!==p?{title:p}:{},...void 0!==a?{scale:a}:{},...void 0!==s?{axis:s}:{}},...t.isString(d)?{[`${n}2`]:{field:`${d}_${i.field}`}}:{},...r,...m}})}}function ts(e,n,i,r){const{clip:o,color:a,opacity:s}=e,l=e.type;return e[n]||void 0===e[n]&&i[n]?[{...r,mark:{...i[n],...o?{clip:o}:{},...a?{color:a}:{},...s?{opacity:s}:{},...no(r.mark)?r.mark:{type:r.mark},style:`${l}-${String(n)}`,...t.isBoolean(e[n])?{}:e[n]}}]:[]}function ns(e,t,n){const{encoding:i}=e,r="vertical"===t?"y":"x",o=i[r],a=i[`${r}2`],s=i[`${r}Error`],l=i[`${r}Error2`];return{continuousAxisChannelDef:is(o,n),continuousAxisChannelDef2:is(a,n),continuousAxisChannelDefError:is(s,n),continuousAxisChannelDefError2:is(l,n),continuousAxis:r}}function is(e,t){if(e?.aggregate){const{aggregate:n,...i}=e;return n!==t&&Si(function(e,t){return`Continuous axis should not have customized aggregation function ${e}; ${t} already agregates the axis.`}(n,t)),i}return e}function rs(e,t){const{mark:n,encoding:i}=e,{x:r,y:o}=i;if(no(n)&&n.orient)return n.orient;if(na(r)){if(na(o)){const e=Zo(r)&&r.aggregate,n=Zo(o)&&o.aggregate;if(e||n!==t){if(n||e!==t){if(e===t&&n===t)throw new Error("Both x and y cannot have aggregate");return Ca(o)&&!Ca(r)?"horizontal":"vertical"}return"horizontal"}return"vertical"}return"horizontal"}if(na(o))return"vertical";throw new Error(`Need a valid continuous axis for ${t}s`)}const os="boxplot",as=new Wa(os,ls);function ss(e){return t.isNumber(e)?"tukey":e}function ls(e,n){let{config:i}=n;e={...e,encoding:Xa(e.encoding,i)};const{mark:r,encoding:o,params:a,projection:s,...l}=e,c=no(r)?r:{type:r};a&&Si(Kn("boxplot"));const u=c.extent??i.boxplot.extent,d=En("size",c,i),m=c.invalid,p=ss(u),{bins:g,timeUnits:h,transform:y,continuousAxisChannelDef:v,continuousAxis:b,groupby:x,aggregate:$,encodingWithoutContinuousAxis:w,ticksOrient:k,boxOrient:D,customTooltipWithoutAggregatedField:F}=function(e,n,i){const r=rs(e,os),{continuousAxisChannelDef:o,continuousAxis:a}=ns(e,r,os),s=o.field,l=L(s),c=ss(n),u=[...cs(s),{op:"median",field:s,as:`mid_box_${l}`},{op:"min",field:s,as:("min-max"===c?"lower_whisker_":"min_")+l},{op:"max",field:s,as:("min-max"===c?"upper_whisker_":"max_")+l}],f="min-max"===c||"tukey"===c?[]:[{calculate:`${j(`upper_box_${l}`)} - ${j(`lower_box_${l}`)}`,as:`iqr_${l}`},{calculate:`min(${j(`upper_box_${l}`)} + ${j(`iqr_${l}`)} * ${n}, ${j(`max_${l}`)})`,as:`upper_whisker_${l}`},{calculate:`max(${j(`lower_box_${l}`)} - ${j(`iqr_${l}`)} * ${n}, ${j(`min_${l}`)})`,as:`lower_whisker_${l}`}],{[a]:d,...m}=e.encoding,{customTooltipWithoutAggregatedField:p,filteredEncoding:g}=function(e){const{tooltip:n,...i}=e;if(!n)return{filteredEncoding:i};let r,o;if(t.isArray(n)){for(const e of n)e.aggregate?(r||(r=[]),r.push(e)):(o||(o=[]),o.push(e));r&&(i.tooltip=r)}else n.aggregate?i.tooltip=n:o=n;return t.isArray(o)&&1===o.length&&(o=o[0]),{customTooltipWithoutAggregatedField:o,filteredEncoding:i}}(m),{bins:h,timeUnits:y,aggregate:v,groupby:b,encoding:x}=Ga(g,i),$="vertical"===r?"horizontal":"vertical",w=r,k=[...h,...y,{aggregate:[...v,...u],groupby:b},...f];return{bins:h,timeUnits:y,transform:k,groupby:b,aggregate:v,continuousAxisChannelDef:o,continuousAxis:a,encodingWithoutContinuousAxis:x,ticksOrient:$,boxOrient:w,customTooltipWithoutAggregatedField:p}}(e,u,i),O=L(v.field),{color:z,size:C,..._}=w,P=e=>es(c,b,v,e,i.boxplot),N=P(_),A=P(w),T=(t.isObject(i.boxplot.box)?i.boxplot.box.color:i.mark.color)||"#4c78a8",E=P({..._,...C?{size:C}:{},color:{condition:{test:`${j(`lower_box_${v.field}`)} >= ${j(`upper_box_${v.field}`)}`,...z||{value:T}}}}),M=Ka([{fieldPrefix:"min-max"===p?"upper_whisker_":"max_",titlePrefix:"Max"},{fieldPrefix:"upper_box_",titlePrefix:"Q3"},{fieldPrefix:"mid_box_",titlePrefix:"Median"},{fieldPrefix:"lower_box_",titlePrefix:"Q1"},{fieldPrefix:"min-max"===p?"lower_whisker_":"min_",titlePrefix:"Min"}],v,w),R={type:"tick",color:"black",opacity:1,orient:k,invalid:m,aria:!1},q="min-max"===p?M:Ka([{fieldPrefix:"upper_whisker_",titlePrefix:"Upper Whisker"},{fieldPrefix:"lower_whisker_",titlePrefix:"Lower Whisker"}],v,w),U=[...N({partName:"rule",mark:{type:"rule",invalid:m,aria:!1},positionPrefix:"lower_whisker",endPositionPrefix:"lower_box",extraEncoding:q}),...N({partName:"rule",mark:{type:"rule",invalid:m,aria:!1},positionPrefix:"upper_box",endPositionPrefix:"upper_whisker",extraEncoding:q}),...N({partName:"ticks",mark:R,positionPrefix:"lower_whisker",extraEncoding:q}),...N({partName:"ticks",mark:R,positionPrefix:"upper_whisker",extraEncoding:q})],W=[..."tukey"!==p?U:[],...A({partName:"box",mark:{type:"bar",...d?{size:d}:{},orient:D,invalid:m,ariaRoleDescription:"box"},positionPrefix:"lower_box",endPositionPrefix:"upper_box",extraEncoding:M}),...E({partName:"median",mark:{type:"tick",invalid:m,...t.isObject(i.boxplot.median)&&i.boxplot.median.color?{color:i.boxplot.median.color}:{},...d?{size:d}:{},orient:k,aria:!1},positionPrefix:"mid_box",extraEncoding:M})];if("min-max"===p)return{...l,transform:(l.transform??[]).concat(y),layer:W};const I=j(`lower_box_${v.field}`),B=j(`upper_box_${v.field}`),V=`(${B} - ${I})`,H=`${I} - ${u} * ${V}`,G=`${B} + ${u} * ${V}`,Y=j(v.field),X={joinaggregate:cs(v.field),groupby:x},Q={transform:[{filter:`(${H} <= ${Y}) && (${Y} <= ${G})`},{aggregate:[{op:"min",field:v.field,as:`lower_whisker_${O}`},{op:"max",field:v.field,as:`upper_whisker_${O}`},{op:"min",field:`lower_box_${v.field}`,as:`lower_box_${O}`},{op:"max",field:`upper_box_${v.field}`,as:`upper_box_${O}`},...$],groupby:x}],layer:U},{tooltip:J,...K}=_,{scale:Z,axis:ee}=v,te=Za(v),ne=f(ee,["title"]),ie=ts(c,"outliers",i.boxplot,{transform:[{filter:`(${Y} < ${H}) || (${Y} > ${G})`}],mark:"point",encoding:{[b]:{field:v.field,type:v.type,...void 0!==te?{title:te}:{},...void 0!==Z?{scale:Z}:{},...S(ne)?{}:{axis:ne}},...K,...z?{color:z}:{},...F?{tooltip:F}:{}}})[0];let re;const oe=[...g,...h,X];return ie?re={transform:oe,layer:[ie,Q]}:(re=Q,re.transform.unshift(...oe)),{...l,layer:[re,{transform:y,layer:W}]}}function cs(e){const t=L(e);return[{op:"q1",field:e,as:`lower_box_${t}`},{op:"q3",field:e,as:`upper_box_${t}`}]}const us="errorbar",fs=new Wa(us,ds);function ds(e,t){let{config:n}=t;e={...e,encoding:Xa(e.encoding,n)};const{transform:i,continuousAxisChannelDef:r,continuousAxis:o,encodingWithoutContinuousAxis:a,ticksOrient:s,markDef:l,outerSpec:c,tooltipEncoding:u}=ps(e,us,n);delete a.size;const f=es(l,o,r,a,n.errorbar),d=l.thickness,m=l.size,p={type:"tick",orient:s,aria:!1,...void 0!==d?{thickness:d}:{},...void 0!==m?{size:m}:{}},g=[...f({partName:"ticks",mark:p,positionPrefix:"lower",extraEncoding:u}),...f({partName:"ticks",mark:p,positionPrefix:"upper",extraEncoding:u}),...f({partName:"rule",mark:{type:"rule",ariaRoleDescription:"errorbar",...void 0!==d?{size:d}:{}},positionPrefix:"lower",endPositionPrefix:"upper",extraEncoding:u})];return{...c,transform:i,...g.length>1?{layer:g}:{...g[0]}}}function ms(e,t){const{encoding:n}=e;if(function(e){return(oa(e.x)||oa(e.y))&&!oa(e.x2)&&!oa(e.y2)&&!oa(e.xError)&&!oa(e.xError2)&&!oa(e.yError)&&!oa(e.yError2)}(n))return{orient:rs(e,t),inputType:"raw"};const i=function(e){return oa(e.x2)||oa(e.y2)}(n),r=function(e){return oa(e.xError)||oa(e.xError2)||oa(e.yError)||oa(e.yError2)}(n),o=n.x,a=n.y;if(i){if(r)throw new Error(`${t} cannot be both type aggregated-upper-lower and aggregated-error`);const e=n.x2,i=n.y2;if(oa(e)&&oa(i))throw new Error(`${t} cannot have both x2 and y2`);if(oa(e)){if(na(o))return{orient:"horizontal",inputType:"aggregated-upper-lower"};throw new Error(`Both x and x2 have to be quantitative in ${t}`)}if(oa(i)){if(na(a))return{orient:"vertical",inputType:"aggregated-upper-lower"};throw new Error(`Both y and y2 have to be quantitative in ${t}`)}throw new Error("No ranged axis")}{const e=n.xError,i=n.xError2,r=n.yError,s=n.yError2;if(oa(i)&&!oa(e))throw new Error(`${t} cannot have xError2 without xError`);if(oa(s)&&!oa(r))throw new Error(`${t} cannot have yError2 without yError`);if(oa(e)&&oa(r))throw new Error(`${t} cannot have both xError and yError with both are quantiative`);if(oa(e)){if(na(o))return{orient:"horizontal",inputType:"aggregated-error"};throw new Error("All x, xError, and xError2 (if exist) have to be quantitative")}if(oa(r)){if(na(a))return{orient:"vertical",inputType:"aggregated-error"};throw new Error("All y, yError, and yError2 (if exist) have to be quantitative")}throw new Error("No ranged axis")}}function ps(e,t,n){const{mark:i,encoding:r,params:o,projection:a,...s}=e,l=no(i)?i:{type:i};o&&Si(Kn(t));const{orient:c,inputType:u}=ms(e,t),{continuousAxisChannelDef:f,continuousAxisChannelDef2:d,continuousAxisChannelDefError:m,continuousAxisChannelDefError2:p,continuousAxis:g}=ns(e,c,t),{errorBarSpecificAggregate:h,postAggregateCalculates:y,tooltipSummary:v,tooltipTitleWithFieldName:b}=function(e,t,n,i,r,o,a,s){let l=[],c=[];const u=t.field;let f,d=!1;if("raw"===o){const t=e.center?e.center:e.extent?"iqr"===e.extent?"median":"mean":s.errorbar.center,n=e.extent?e.extent:"mean"===t?"stderr":"iqr";if("median"===t!=("iqr"===n)&&Si(function(e,t,n){return`${e} is not usually used with ${t} for ${n}.`}(t,n,a)),"stderr"===n||"stdev"===n)l=[{op:n,field:u,as:`extent_${u}`},{op:t,field:u,as:`center_${u}`}],c=[{calculate:`${j(`center_${u}`)} + ${j(`extent_${u}`)}`,as:`upper_${u}`},{calculate:`${j(`center_${u}`)} - ${j(`extent_${u}`)}`,as:`lower_${u}`}],f=[{fieldPrefix:"center_",titlePrefix:N(t)},{fieldPrefix:"upper_",titlePrefix:gs(t,n,"+")},{fieldPrefix:"lower_",titlePrefix:gs(t,n,"-")}],d=!0;else{let e,t,i;"ci"===n?(e="mean",t="ci0",i="ci1"):(e="median",t="q1",i="q3"),l=[{op:t,field:u,as:`lower_${u}`},{op:i,field:u,as:`upper_${u}`},{op:e,field:u,as:`center_${u}`}],f=[{fieldPrefix:"upper_",titlePrefix:va({field:u,aggregate:i,type:"quantitative"},s,{allowDisabling:!1})},{fieldPrefix:"lower_",titlePrefix:va({field:u,aggregate:t,type:"quantitative"},s,{allowDisabling:!1})},{fieldPrefix:"center_",titlePrefix:va({field:u,aggregate:e,type:"quantitative"},s,{allowDisabling:!1})}]}}else{(e.center||e.extent)&&Si((m=e.center,`${(p=e.extent)?"extent ":""}${p&&m?"and ":""}${m?"center ":""}${p&&m?"are ":"is "}not needed when data are aggregated.`)),"aggregated-upper-lower"===o?(f=[],c=[{calculate:j(n.field),as:`upper_${u}`},{calculate:j(u),as:`lower_${u}`}]):"aggregated-error"===o&&(f=[{fieldPrefix:"",titlePrefix:u}],c=[{calculate:`${j(u)} + ${j(i.field)}`,as:`upper_${u}`}],r?c.push({calculate:`${j(u)} + ${j(r.field)}`,as:`lower_${u}`}):c.push({calculate:`${j(u)} - ${j(i.field)}`,as:`lower_${u}`}));for(const e of c)f.push({fieldPrefix:e.as.substring(0,6),titlePrefix:R(R(e.calculate,"datum['",""),"']","")})}var m,p;return{postAggregateCalculates:c,errorBarSpecificAggregate:l,tooltipSummary:f,tooltipTitleWithFieldName:d}}(l,f,d,m,p,u,t,n),{[g]:x,["x"===g?"x2":"y2"]:$,["x"===g?"xError":"yError"]:w,["x"===g?"xError2":"yError2"]:k,...S}=r,{bins:D,timeUnits:F,aggregate:O,groupby:z,encoding:C}=Ga(S,n),_=[...O,...h],P="raw"!==u?[]:z,A=Ka(v,f,C,b);return{transform:[...s.transform??[],...D,...F,...0===_.length?[]:[{aggregate:_,groupby:P}],...y],groupby:P,continuousAxisChannelDef:f,continuousAxis:g,encodingWithoutContinuousAxis:C,ticksOrient:"vertical"===c?"horizontal":"vertical",markDef:l,outerSpec:s,tooltipEncoding:A}}function gs(e,t,n){return`${N(e)} ${n} ${t}`}const hs="errorband",ys=new Wa(hs,vs);function vs(e,t){let{config:n}=t;e={...e,encoding:Xa(e.encoding,n)};const{transform:i,continuousAxisChannelDef:r,continuousAxis:o,encodingWithoutContinuousAxis:a,markDef:s,outerSpec:l,tooltipEncoding:c}=ps(e,hs,n),u=s,f=es(u,o,r,a,n.errorband),d=void 0!==e.encoding.x&&void 0!==e.encoding.y;let m={type:d?"area":"rect"},p={type:d?"line":"rule"};const g={...u.interpolate?{interpolate:u.interpolate}:{},...u.tension&&u.interpolate?{tension:u.tension}:{}};return d?(m={...m,...g,ariaRoleDescription:"errorband"},p={...p,...g,aria:!1}):u.interpolate?Si(bi("interpolate")):u.tension&&Si(bi("tension")),{...l,transform:i,layer:[...f({partName:"band",mark:m,positionPrefix:"lower",endPositionPrefix:"upper",extraEncoding:c}),...f({partName:"borders",mark:p,positionPrefix:"lower",extraEncoding:c}),...f({partName:"borders",mark:p,positionPrefix:"upper",extraEncoding:c})]}}const bs={};function xs(e,t,n){const i=new Wa(e,t);bs[e]={normalizer:i,parts:n}}xs(os,ls,["box","median","outliers","rule","ticks"]),xs(us,ds,["ticks","rule"]),xs(hs,vs,["band","borders"]);const $s=["gradientHorizontalMaxLength","gradientHorizontalMinLength","gradientVerticalMaxLength","gradientVerticalMinLength","unselectedOpacity"],ws={titleAlign:"align",titleAnchor:"anchor",titleAngle:"angle",titleBaseline:"baseline",titleColor:"color",titleFont:"font",titleFontSize:"fontSize",titleFontStyle:"fontStyle",titleFontWeight:"fontWeight",titleLimit:"limit",titleLineHeight:"lineHeight",titleOrient:"orient",titlePadding:"offset"},ks={labelAlign:"align",labelAnchor:"anchor",labelAngle:"angle",labelBaseline:"baseline",labelColor:"color",labelFont:"font",labelFontSize:"fontSize",labelFontStyle:"fontStyle",labelFontWeight:"fontWeight",labelLimit:"limit",labelLineHeight:"lineHeight",labelOrient:"orient",labelPadding:"offset"},Ss=D(ws),Ds=D(ks),Fs=D({header:1,headerRow:1,headerColumn:1,headerFacet:1}),Os=["size","shape","fill","stroke","strokeDash","strokeWidth","opacity"],zs="_vgsid_",Cs={point:{on:"click",fields:[zs],toggle:"event.shiftKey",resolve:"global",clear:"dblclick"},interval:{on:"[pointerdown, window:pointerup] > window:pointermove!",encodings:["x","y"],translate:"[pointerdown, window:pointerup] > window:pointermove!",zoom:"wheel!",mark:{fill:"#333",fillOpacity:.125,stroke:"white"},resolve:"global",clear:"dblclick"}};function _s(e){return"legend"===e||!!e?.legend}function Ps(e){return _s(e)&&t.isObject(e)}function Ns(e){return!!e?.select}function As(e){const t=[];for(const n of e||[]){if(Ns(n))continue;const{expr:e,bind:i,...r}=n;if(i&&e){const n={...r,bind:i,init:e};t.push(n)}else{const n={...r,...e?{update:e}:{},...i?{bind:i}:{}};t.push(n)}}return t}function Ts(e){return J(e,"concat")}function js(e){return J(e,"vconcat")}function Es(e){return J(e,"hconcat")}function Ms(e){let{step:t,offsetIsDiscrete:n}=e;return n?t.for??"offset":"position"}function Rs(e){return J(e,"step")}function Ls(e){return J(e,"view")||J(e,"width")||J(e,"height")}const qs=D({align:1,bounds:1,center:1,columns:1,spacing:1});function Us(e,t){return e[t]??e["width"===t?"continuousWidth":"continuousHeight"]}function Ws(e,t){const n=Is(e,t);return Rs(n)?n.step:Bs}function Is(e,t){return U(e[t]??e["width"===t?"discreteWidth":"discreteHeight"],{step:e.step})}const Bs=20,Vs={background:"white",padding:5,timeFormat:"%b %d, %Y",countTitle:"Count of Records",view:{continuousWidth:200,continuousHeight:200,step:Bs},mark:{color:"#4c78a8",invalid:"break-paths-show-path-domains",timeUnitBandSize:1},arc:{},area:{},bar:fo,circle:{},geoshape:{},image:{},line:{},point:{},rect:uo,rule:{color:"black"},square:{},text:{color:"black"},tick:mo,trail:{},boxplot:{size:14,extent:1.5,box:{},median:{color:"white"},outliers:{},rule:{},ticks:null},errorbar:{center:"mean",rule:!0,ticks:!1},errorband:{band:{opacity:.3},borders:!1},scale:{pointPadding:.5,barBandPaddingInner:.1,rectBandPaddingInner:0,tickBandPaddingInner:.25,bandWithNestedOffsetPaddingInner:.2,bandWithNestedOffsetPaddingOuter:.2,minBandSize:2,minFontSize:8,maxFontSize:40,minOpacity:.3,maxOpacity:.8,minSize:4,minStrokeWidth:1,maxStrokeWidth:4,quantileCount:4,quantizeCount:4,zero:!0,framesPerSecond:2,animationDuration:5},projection:{},legend:{gradientHorizontalMaxLength:200,gradientHorizontalMinLength:100,gradientVerticalMaxLength:200,gradientVerticalMinLength:64,unselectedOpacity:.35},header:{titlePadding:10,labelPadding:10},headerColumn:{},headerRow:{},headerFacet:{},selection:Cs,style:{},title:{},facet:{spacing:20},concat:{spacing:20},normalizedNumberFormat:".0%"},Hs=["#4c78a8","#f58518","#e45756","#72b7b2","#54a24b","#eeca3b","#b279a2","#ff9da6","#9d755d","#bab0ac"],Gs={text:11,guideLabel:10,guideTitle:11,groupTitle:13,groupSubtitle:12},Ys={blue:Hs[0],orange:Hs[1],red:Hs[2],teal:Hs[3],green:Hs[4],yellow:Hs[5],purple:Hs[6],pink:Hs[7],brown:Hs[8],gray0:"#000",gray1:"#111",gray2:"#222",gray3:"#333",gray4:"#444",gray5:"#555",gray6:"#666",gray7:"#777",gray8:"#888",gray9:"#999",gray10:"#aaa",gray11:"#bbb",gray12:"#ccc",gray13:"#ddd",gray14:"#eee",gray15:"#fff"};function Xs(e){const t=D(e||{}),n={};for(const i of t){const t=e[i];n[i]=Ta(t)?zn(t):Cn(t)}return n}const Qs=[...so,...qa,...Fs,"background","padding","legend","lineBreak","scale","style","title","view"];function Js(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};const{color:n,font:i,fontSize:r,selection:o,...a}=e,s=t.mergeConfig({},l(Vs),i?function(e){return{text:{font:e},style:{"guide-label":{font:e},"guide-title":{font:e},"group-title":{font:e},"group-subtitle":{font:e}}}}(i):{},n?function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return{signals:[{name:"color",value:t.isObject(e)?{...Ys,...e}:Ys}],mark:{color:{signal:"color.blue"}},rule:{color:{signal:"color.gray0"}},text:{color:{signal:"color.gray0"}},style:{"guide-label":{fill:{signal:"color.gray0"}},"guide-title":{fill:{signal:"color.gray0"}},"group-title":{fill:{signal:"color.gray0"}},"group-subtitle":{fill:{signal:"color.gray0"}},cell:{stroke:{signal:"color.gray8"}}},axis:{domainColor:{signal:"color.gray13"},gridColor:{signal:"color.gray8"},tickColor:{signal:"color.gray13"}},range:{category:[{signal:"color.blue"},{signal:"color.orange"},{signal:"color.red"},{signal:"color.teal"},{signal:"color.green"},{signal:"color.yellow"},{signal:"color.purple"},{signal:"color.pink"},{signal:"color.brown"},{signal:"color.grey8"}]}}}(n):{},r?function(e){return{signals:[{name:"fontSize",value:t.isObject(e)?{...Gs,...e}:Gs}],text:{fontSize:{signal:"fontSize.text"}},style:{"guide-label":{fontSize:{signal:"fontSize.guideLabel"}},"guide-title":{fontSize:{signal:"fontSize.guideTitle"}},"group-title":{fontSize:{signal:"fontSize.groupTitle"}},"group-subtitle":{fontSize:{signal:"fontSize.groupSubtitle"}}}}}(r):{},a||{});o&&t.writeConfig(s,"selection",o,!0);const c=f(s,Qs);for(const e of["background","lineBreak","padding"])s[e]&&(c[e]=Cn(s[e]));for(const e of so)s[e]&&(c[e]=bn(s[e]));for(const e of qa)s[e]&&(c[e]=Xs(s[e]));for(const e of Fs)s[e]&&(c[e]=bn(s[e]));if(s.legend&&(c.legend=bn(s.legend)),s.scale){const{invalid:e,...t}=s.scale,n=bn(e,{level:1});c.scale={...bn(t),...D(n).length>0?{invalid:n}:{}}}return s.style&&(c.style=function(e){const t=D(e),n={};for(const i of t)n[i]=Xs(e[i]);return n}(s.style)),s.title&&(c.title=bn(s.title)),s.view&&(c.view=bn(s.view)),c}const Ks=new Set(["view",...to]),Zs=["color","fontSize","background","padding","facet","concat","numberFormat","numberFormatType","normalizedNumberFormat","normalizedNumberFormatType","timeFormat","countTitle","header","axisQuantitative","axisTemporal","axisDiscrete","axisPoint","axisXBand","axisXPoint","axisXDiscrete","axisXQuantitative","axisXTemporal","axisYBand","axisYPoint","axisYDiscrete","axisYQuantitative","axisYTemporal","scale","selection","overlay"],el={view:["continuousWidth","continuousHeight","discreteWidth","discreteHeight","step"],...ao};function tl(e){e=l(e);for(const t of Zs)delete e[t];if(e.axis)for(const t in e.axis)Ta(e.axis[t])&&delete e.axis[t];if(e.legend)for(const t of $s)delete e.legend[t];if(e.mark){for(const t of ro)delete e.mark[t];e.mark.tooltip&&t.isObject(e.mark.tooltip)&&delete e.mark.tooltip}e.params&&(e.signals=(e.signals||[]).concat(As(e.params)),delete e.params);for(const t of Ks){for(const n of ro)delete e[t][n];const n=el[t];if(n)for(const i of n)delete e[t][i];nl(e,t)}for(const t of D(bs))delete e[t];!function(e){const{titleMarkConfig:t,subtitleMarkConfig:n,subtitle:i}=xn(e.title);S(t)||(e.style["group-title"]={...e.style["group-title"],...t});S(n)||(e.style["group-subtitle"]={...e.style["group-subtitle"],...n});S(i)?delete e.title:e.title=i}(e);for(const n in e)t.isObject(e[n])&&S(e[n])&&delete e[n];return S(e)?void 0:e}function nl(e,t,n,i){"view"===t&&(n="cell");const r={...e[t],...e.style[n??t]};S(r)||(e.style[n??t]=r),delete e[t]}function il(e){return J(e,"layer")}class rl{map(e,t){return Io(e)?this.mapFacet(e,t):function(e){return J(e,"repeat")}(e)?this.mapRepeat(e,t):Es(e)?this.mapHConcat(e,t):js(e)?this.mapVConcat(e,t):Ts(e)?this.mapConcat(e,t):this.mapLayerOrUnit(e,t)}mapLayerOrUnit(e,t){if(il(e))return this.mapLayer(e,t);if(Ua(e))return this.mapUnit(e,t);throw new Error(Bn(e))}mapLayer(e,t){return{...e,layer:e.layer.map((e=>this.mapLayerOrUnit(e,t)))}}mapHConcat(e,t){return{...e,hconcat:e.hconcat.map((e=>this.map(e,t)))}}mapVConcat(e,t){return{...e,vconcat:e.vconcat.map((e=>this.map(e,t)))}}mapConcat(e,t){const{concat:n,...i}=e;return{...i,concat:n.map((e=>this.map(e,t)))}}mapFacet(e,t){return{...e,spec:this.map(e.spec,t)}}mapRepeat(e,t){return{...e,spec:this.map(e.spec,t)}}}const ol={zero:1,center:1,normalize:1};const al=new Set([Lr,Ur,qr,Hr,Br,Qr,Jr,Ir,Gr,Yr]),sl=new Set([Ur,qr,Lr]);function ll(e){return Zo(e)&&"quantitative"===ea(e)&&!e.bin}function cl(e,t,n){let{orient:i,type:r}=n;const o="x"===t?"y":"radius",a="x"===t&&["bar","area"].includes(r),s=e[t],l=e[o];if(Zo(s)&&Zo(l))if(ll(s)&&ll(l)){if(s.stack)return t;if(l.stack)return o;const e=Zo(s)&&!!s.aggregate;if(e!==(Zo(l)&&!!l.aggregate))return e?t:o;if(a){if("vertical"===i)return o;if("horizontal"===i)return t}}else{if(ll(s))return t;if(ll(l))return o}else{if(ll(s)){if(a&&"vertical"===i)return;return t}if(ll(l)){if(a&&"horizontal"===i)return;return o}}}function ul(e,n){const i=no(e)?e:{type:e},r=i.type;if(!al.has(r))return null;const o=cl(n,"x",i)||cl(n,"theta",i);if(!o)return null;const a=n[o],s=Zo(a)?ma(a,{}):void 0,l=function(e){switch(e){case"x":return"y";case"y":return"x";case"theta":return"radius";case"radius":return"theta"}}(o),c=[],u=new Set;if(n[l]){const e=n[l],t=Zo(e)?ma(e,{}):void 0;t&&t!==s&&(c.push(l),u.add(t))}const f="x"===l?"xOffset":"yOffset",d=n[f],m=Zo(d)?ma(d,{}):void 0;m&&m!==s&&(c.push(f),u.add(m));const p=Ot.reduce(((e,i)=>{if("tooltip"!==i&&Ia(n,i)){const r=n[i];for(const n of t.array(r)){const t=wa(n);if(t.aggregate)continue;const r=ma(t,{});r&&u.has(r)||e.push({channel:i,fieldDef:t})}}return e}),[]);let g;return void 0!==a.stack?g=t.isBoolean(a.stack)?a.stack?"zero":null:a.stack:sl.has(r)&&(g="zero"),g&&(h=g,t.hasOwnProperty(ol,h))?Ha(n)&&0===p.length?null:(a?.scale?.type&&a?.scale?.type!==dr.LINEAR&&a?.stack&&Si(function(e){return`Stack is applied to a non-linear scale (${e}).`}(a.scale.type)),oa(n[at(o)])?(void 0!==a.stack&&Si(`Cannot stack "${y=o}" if there is already "${y}2".`),null):(Zo(a)&&a.aggregate&&!un.has(a.aggregate)&&Si(`Stacking is applied even though the aggregate function is non-summative ("${a.aggregate}").`),{groupbyChannels:c,groupbyFields:u,fieldChannel:o,impute:null!==a.impute&&Zr(r),stackBy:p,offset:g})):null;var h,y}function fl(e,t,n){const i=bn(e),r=En("orient",i,n);if(i.orient=function(e,t,n){switch(e){case Br:case Qr:case Jr:case Gr:case Vr:case Wr:return}const{x:i,y:r,x2:o,y2:a}=t;switch(e){case Ur:if(Zo(i)&&(pn(i.bin)||Zo(r)&&r.aggregate&&!i.aggregate))return"vertical";if(Zo(r)&&(pn(r.bin)||Zo(i)&&i.aggregate&&!r.aggregate))return"horizontal";if(a||o){if(n)return n;if(!o)return(Zo(i)&&i.type===sr&&!mn(i.bin)||ra(i))&&Zo(r)&&pn(r.bin)?"horizontal":"vertical";if(!a)return(Zo(r)&&r.type===sr&&!mn(r.bin)||ra(r))&&Zo(i)&&pn(i.bin)?"vertical":"horizontal"}case Hr:if(o&&(!Zo(i)||!pn(i.bin))&&a&&(!Zo(r)||!pn(r.bin)))return;case qr:if(a)return Zo(r)&&pn(r.bin)?"horizontal":"vertical";if(o)return Zo(i)&&pn(i.bin)?"vertical":"horizontal";if(e===Hr){if(i&&!r)return"vertical";if(r&&!i)return"horizontal"}case Ir:case Yr:{const t=ia(i),o=ia(r);if(n)return n;if(t&&!o)return"tick"!==e?"horizontal":"vertical";if(!t&&o)return"tick"!==e?"vertical":"horizontal";if(t&&o)return"vertical";{const e=aa(i)&&i.type===cr,t=aa(r)&&r.type===cr;if(e&&!t)return"vertical";if(!e&&t)return"horizontal"}return}}return"vertical"}(i.type,t,r),void 0!==r&&r!==i.orient&&Si(`Specified orient "${i.orient}" overridden with "${r}".`),"bar"===i.type&&i.orient){const e=En("cornerRadiusEnd",i,n);if(void 0!==e){const n="horizontal"===i.orient&&t.x2||"vertical"===i.orient&&t.y2?["cornerRadius"]:co[i.orient];for(const t of n)i[t]=e;void 0!==i.cornerRadiusEnd&&delete i.cornerRadiusEnd}}const o=En("opacity",i,n),a=En("fillOpacity",i,n);void 0===o&&void 0===a&&(i.opacity=function(e,t){if(p([Br,Yr,Qr,Jr],e)&&!Ha(t))return.7;return}(i.type,t));return void 0===En("cursor",i,n)&&(i.cursor=function(e,t,n){if(t.href||e.href||En("href",e,n))return"pointer";return e.cursor}(i,t,n)),i}function dl(e){const{point:t,line:n,...i}=e;return D(i).length>1?i:i.type}function ml(e){for(const t of["line","area","rule","trail"])e[t]&&(e={...e,[t]:f(e[t],["point","line"])});return e}function pl(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=arguments.length>2?arguments[2]:void 0;return"transparent"===e.point?{opacity:0}:e.point?t.isObject(e.point)?e.point:{}:void 0!==e.point?null:n.point||i.shape?t.isObject(n.point)?n.point:{}:void 0}function gl(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e.line?!0===e.line?{}:e.line:void 0!==e.line?null:t.line?!0===t.line?{}:t.line:void 0}class hl{name="path-overlay";hasMatchingType(e,t){if(Ua(e)){const{mark:n,encoding:i}=e,r=no(n)?n:{type:n};switch(r.type){case"line":case"rule":case"trail":return!!pl(r,t[r.type],i);case"area":return!!pl(r,t[r.type],i)||!!gl(r,t[r.type])}}return!1}run(e,t,n){const{config:i}=t,{params:r,projection:o,mark:a,name:s,encoding:l,...c}=e,d=Xa(l,i),m=no(a)?a:{type:a},p=pl(m,i[m.type],d),g="area"===m.type&&gl(m,i[m.type]),h=[{name:s,...r?{params:r}:{},mark:dl({..."area"===m.type&&void 0===m.opacity&&void 0===m.fillOpacity?{opacity:.7}:{},...m}),encoding:f(d,["shape"])}],y=ul(fl(m,d,i),d);let v=d;if(y){const{fieldChannel:e,offset:t}=y;v={...d,[e]:{...d[e],...t?{stack:t}:{}}}}return v=f(v,["y2","x2"]),g&&h.push({...o?{projection:o}:{},mark:{type:"line",...u(m,["clip","interpolate","tension","tooltip"]),...g},encoding:v}),p&&h.push({...o?{projection:o}:{},mark:{type:"point",opacity:1,filled:!0,...u(m,["clip","tooltip"]),...p},encoding:v}),n({...c,layer:h},{...t,config:ml(i)})}}function yl(e,t){return t?Uo(e)?kl(e,t):xl(e,t):e}function vl(e,t){return t?kl(e,t):e}function bl(e,n,i){const r=n[e];return o=r,!t.isString(o)&&J(o,"repeat")?r.repeat in i?{...n,[e]:i[r.repeat]}:void Si(function(e){return`Unknown repeated value "${e}".`}(r.repeat)):n;var o}function xl(e,t){if(void 0!==(e=bl("field",e,t))){if(null===e)return null;if(Vo(e)&&Lo(e.sort)){const n=bl("field",e.sort,t);e={...e,...n?{sort:n}:{}}}return e}}function $l(e,t){if(Zo(e))return xl(e,t);{const n=bl("datum",e,t);return n===e||n.type||(n.type="nominal"),n}}function wl(e,t){if(!oa(e)){if(Ko(e)){const n=$l(e.condition,t);if(n)return{...e,condition:n};{const{condition:t,...n}=e;return n}}return e}{const n=$l(e,t);if(n)return n;if(Qo(e))return{condition:e.condition}}}function kl(e,n){const i={};for(const r in e)if(J(e,r)){const o=e[r];if(t.isArray(o))i[r]=o.map((e=>wl(e,n))).filter((e=>e));else{const e=wl(o,n);void 0!==e&&(i[r]=e)}}return i}class Sl{name="RuleForRangedLine";hasMatchingType(e){if(Ua(e)){const{encoding:t,mark:n}=e;if("line"===n||no(n)&&"line"===n.type)for(const e of nt){const n=t[rt(e)];if(t[e]&&(Zo(n)&&!pn(n.bin)||ta(n)))return!0}}return!1}run(e,n,i){const{encoding:r,mark:o}=e;var a,s;return Si((a=!!r.x2,s=!!r.y2,`Line mark is for continuous lines and thus cannot be used with ${a&&s?"x2 and y2":a?"x2":"y2"}. We will use the rule mark (line segments) instead.`)),i({...e,mark:t.isObject(o)?{...o,type:"rule"}:"rule"},n)}}function Dl(e){let{parentEncoding:n,encoding:i={},layer:r}=e,o={};if(n){const e=new Set([...D(n),...D(i)]);for(const a of e){const e=i[a],s=n[a];if(oa(e)){const t={...s,...e};o[a]=t}else Ko(e)?o[a]={...e,condition:{...s,...e.condition}}:e||null===e?o[a]=e:(r||sa(s)||wn(s)||oa(s)||t.isArray(s))&&(o[a]=s)}}else o=i;return!o||S(o)?void 0:o}function Fl(e){const{parentProjection:t,projection:n}=e;return t&&n&&Si(function(e){const{parentProjection:t,projection:n}=e;return`Layer's shared projection ${Q(t)} is overridden by a child projection ${Q(n)}.`}({parentProjection:t,projection:n})),n??t}function Ol(e){return J(e,"filter")}function zl(e){return J(e,"lookup")}function Cl(e){return J(e,"pivot")}function _l(e){return J(e,"density")}function Pl(e){return J(e,"quantile")}function Nl(e){return J(e,"regression")}function Al(e){return J(e,"loess")}function Tl(e){return J(e,"sample")}function jl(e){return J(e,"window")}function El(e){return J(e,"joinaggregate")}function Ml(e){return J(e,"flatten")}function Rl(e){return J(e,"calculate")}function Ll(e){return J(e,"bin")}function ql(e){return J(e,"impute")}function Ul(e){return J(e,"timeUnit")}function Wl(e){return J(e,"aggregate")}function Il(e){return J(e,"stack")}function Bl(e){return J(e,"fold")}function Vl(e){return J(e,"extent")&&!J(e,"density")&&!J(e,"regression")}function Hl(e,t){const{transform:n,...i}=e;if(n){return{...i,transform:n.map((e=>{if(Ol(e))return{filter:Xl(e,t)};if(Ll(e)&&gn(e.bin))return{...e,bin:Yl(e.bin)};if(zl(e)){const{selection:t,...n}=e.from;return t?{...e,from:{param:t,...n}}:e}return e}))}}return e}function Gl(e,n){const i=l(e);if(Zo(i)&&gn(i.bin)&&(i.bin=Yl(i.bin)),la(i)&&i.scale?.domain?.selection){const{selection:e,...t}=i.scale.domain;i.scale.domain={...t,...e?{param:e}:{}}}if(Qo(i))if(t.isArray(i.condition))i.condition=i.condition.map((e=>{const{selection:t,param:i,test:r,...o}=e;return i?e:{...o,test:Xl(e,n)}}));else{const{selection:e,param:t,test:r,...o}=Gl(i.condition,n);i.condition=t?i.condition:{...o,test:Xl(i.condition,n)}}return i}function Yl(e){const t=e.extent;if(t?.selection){const{selection:n,...i}=t;return{...e,extent:{...i,param:n}}}return e}function Xl(e,t){const n=e=>s(e,(e=>{const n={param:e,empty:t.emptySelections[e]??!0};return t.selectionPredicates[e]??=[],t.selectionPredicates[e].push(n),n}));return e.selection?n(e.selection):s(e.test||e.filter,(e=>e.selection?n(e.selection):e))}class Ql extends rl{map(e,t){const n=t.selections??[];if(e.params&&!Ua(e)){const t=[];for(const i of e.params)Ns(i)?n.push(i):t.push(i);e.params=t}return t.selections=n,super.map(e,t)}mapUnit(e,n){const i=n.selections;if(!i||!i.length)return e;const r=(n.path??[]).concat(e.name),o=[];for(const n of i)if(n.views&&n.views.length)for(const i of n.views)(t.isString(i)&&(i===e.name||r.includes(i))||t.isArray(i)&&i.map((e=>r.indexOf(e))).every(((e,t,n)=>-1!==e&&(0===t||e>n[t-1]))))&&o.push(n);else o.push(n);return o.length&&(e.params=o),e}}for(const e of["mapFacet","mapRepeat","mapHConcat","mapVConcat","mapLayer"]){const t=Ql.prototype[e];Ql.prototype[e]=function(e,n){return t.call(this,e,Jl(e,n))}}function Jl(e,t){return e.name?{...t,path:(t.path??[]).concat(e.name)}:t}function Kl(e,t){void 0===t&&(t=Js(e.config));const n=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const n={config:t};return tc.map(Zl.map(ec.map(e,n),n),n)}(e,t),{width:i,height:r}=e,o=function(e,t,n){let{width:i,height:r}=t;const o=Ua(e)||il(e),a={};o?"container"==i&&"container"==r?(a.type="fit",a.contains="padding"):"container"==i?(a.type="fit-x",a.contains="padding"):"container"==r&&(a.type="fit-y",a.contains="padding"):("container"==i&&(Si(Hn("width")),i=void 0),"container"==r&&(Si(Hn("height")),r=void 0));const s={type:"pad",...a,...n?nc(n.autosize):{},...nc(e.autosize)};"fit"!==s.type||o||(Si(Vn),s.type="pad");"container"==i&&"fit"!=s.type&&"fit-x"!=s.type&&Si(Gn("width"));"container"==r&&"fit"!=s.type&&"fit-y"!=s.type&&Si(Gn("height"));if(X(s,{type:"pad"}))return;return s}(n,{width:i,height:r,autosize:e.autosize},t);return{...n,...o?{autosize:o}:{}}}const Zl=new class extends rl{nonFacetUnitNormalizers=(()=>[as,fs,ys,new hl,new Sl])();map(e,t){if(Ua(e)){const n=Ia(e.encoding,K),i=Ia(e.encoding,Z),r=Ia(e.encoding,ee);if(n||i||r)return this.mapFacetedUnit(e,t)}return super.map(e,t)}mapUnit(e,t){const{parentEncoding:n,parentProjection:i}=t,r=vl(e.encoding,t.repeater),o={...e,...e.name?{name:[t.repeaterPrefix,e.name].filter((e=>e)).join("_")}:{},...r?{encoding:r}:{}};if(n||i)return this.mapUnitWithParentEncodingOrProjection(o,t);const a=this.mapLayerOrUnit.bind(this);for(const e of this.nonFacetUnitNormalizers)if(e.hasMatchingType(o,t.config))return e.run(o,t,a);return o}mapRepeat(e,n){return function(e){return!t.isArray(e.repeat)&&J(e.repeat,"layer")}(e)?this.mapLayerRepeat(e,n):this.mapNonLayerRepeat(e,n)}mapLayerRepeat(e,t){const{repeat:n,spec:i,...r}=e,{row:o,column:a,layer:s}=n,{repeater:l={},repeaterPrefix:c=""}=t;return o||a?this.mapRepeat({...e,repeat:{...o?{row:o}:{},...a?{column:a}:{}},spec:{repeat:{layer:s},spec:i}},t):{...r,layer:s.map((e=>{const n={...l,layer:e},r=`${(i.name?`${i.name}_`:"")+c}child__layer_${C(e)}`,o=this.mapLayerOrUnit(i,{...t,repeater:n,repeaterPrefix:r});return o.name=r,o}))}}mapNonLayerRepeat(e,n){const{repeat:i,spec:r,data:o,...a}=e;!t.isArray(i)&&e.columns&&(e=f(e,["columns"]),Si(ei("repeat")));const s=[],{repeater:l={},repeaterPrefix:c=""}=n,u=!t.isArray(i)&&i.row||[l?l.row:null],d=!t.isArray(i)&&i.column||[l?l.column:null],m=t.isArray(i)&&i||[l?l.repeat:null];for(const e of m)for(const o of u)for(const a of d){const u={repeat:e,row:o,column:a,layer:l.layer},d=(r.name?`${r.name}_`:"")+c+"child__"+(t.isArray(i)?`${C(e)}`:(i.row?`row_${C(o)}`:"")+(i.column?`column_${C(a)}`:"")),m=this.map(r,{...n,repeater:u,repeaterPrefix:d});m.name=d,s.push(f(m,["data"]))}const p=t.isArray(i)?e.columns:i.column?i.column.length:1;return{data:r.data??o,align:"all",...a,columns:p,concat:s}}mapFacet(e,t){const{facet:n}=e;return Uo(n)&&e.columns&&(e=f(e,["columns"]),Si(ei("facet"))),super.mapFacet(e,t)}mapUnitWithParentEncodingOrProjection(e,t){const{encoding:n,projection:i}=e,{parentEncoding:r,parentProjection:o,config:a}=t,s=Fl({parentProjection:o,projection:i}),l=Dl({parentEncoding:r,encoding:vl(n,t.repeater)});return this.mapUnit({...e,...s?{projection:s}:{},...l?{encoding:l}:{}},{config:a})}mapFacetedUnit(e,t){const{row:n,column:i,facet:r,...o}=e.encoding,{mark:a,width:s,projection:l,height:c,view:u,params:f,encoding:d,...m}=e,{facetMapping:p,layout:g}=this.getFacetMappingAndLayout({row:n,column:i,facet:r},t),h=vl(o,t.repeater);return this.mapFacet({...m,...g,facet:p,spec:{...s?{width:s}:{},...c?{height:c}:{},...u?{view:u}:{},...l?{projection:l}:{},mark:a,encoding:h,...f?{params:f}:{}}},t)}getFacetMappingAndLayout(e,t){const{row:n,column:i,facet:r}=e;if(n||i){r&&Si(`Facet encoding dropped as ${(o=[...n?[K]:[],...i?[Z]:[]]).join(" and ")} ${o.length>1?"are":"is"} also specified.`);const t={},a={};for(const n of[K,Z]){const i=e[n];if(i){const{align:e,center:r,spacing:o,columns:s,...l}=i;t[n]=l;for(const e of["align","center","spacing"])void 0!==i[e]&&(a[e]??={},a[e][n]=i[e])}}return{facetMapping:t,layout:a}}{const{align:e,center:n,spacing:i,columns:o,...a}=r;return{facetMapping:yl(a,t.repeater),layout:{...e?{align:e}:{},...n?{center:n}:{},...i?{spacing:i}:{},...o?{columns:o}:{}}}}var o}mapLayer(e,t){let{parentEncoding:n,parentProjection:i,...r}=t;const{encoding:o,projection:a,...s}=e,l={...r,parentEncoding:Dl({parentEncoding:n,encoding:o,layer:!0}),parentProjection:Fl({parentProjection:i,projection:a})};return super.mapLayer({...s,...e.name?{name:[l.repeaterPrefix,e.name].filter((e=>e)).join("_")}:{}},l)}},ec=new class extends rl{map(e,t){return t.emptySelections??={},t.selectionPredicates??={},e=Hl(e,t),super.map(e,t)}mapLayerOrUnit(e,t){if((e=Hl(e,t)).encoding){const n={};for(const[i,r]of O(e.encoding))n[i]=Gl(r,t);e={...e,encoding:n}}return super.mapLayerOrUnit(e,t)}mapUnit(e,t){const{selection:n,...i}=e;return n?{...i,params:O(n).map((e=>{let[n,i]=e;const{init:r,bind:o,empty:a,...s}=i;"single"===s.type?(s.type="point",s.toggle=!1):"multi"===s.type&&(s.type="point"),t.emptySelections[n]="none"!==a;for(const e of F(t.selectionPredicates[n]??{}))e.empty="none"!==a;return{name:n,value:r,select:s,bind:o}}))}:e}},tc=new Ql;function nc(e){return t.isString(e)?{type:e}:e??{}}const ic=["background","padding"];function rc(e,t){const n={};for(const t of ic)e&&void 0!==e[t]&&(n[t]=Cn(e[t]));return t&&(n.params=e.params),n}class oc{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};this.explicit=e,this.implicit=t}clone(){return new oc(l(this.explicit),l(this.implicit))}combine(){return{...this.explicit,...this.implicit}}get(e){return U(this.explicit[e],this.implicit[e])}getWithExplicit(e){return void 0!==this.explicit[e]?{explicit:!0,value:this.explicit[e]}:void 0!==this.implicit[e]?{explicit:!1,value:this.implicit[e]}:{explicit:!1,value:void 0}}setWithExplicit(e,t){let{value:n,explicit:i}=t;void 0!==n&&this.set(e,n,i)}set(e,t,n){return delete this[n?"implicit":"explicit"][e],this[n?"explicit":"implicit"][e]=t,this}copyKeyFromSplit(e,t){let{explicit:n,implicit:i}=t;void 0!==n[e]?this.set(e,n[e],!0):void 0!==i[e]&&this.set(e,i[e],!1)}copyKeyFromObject(e,t){void 0!==t[e]&&this.set(e,t[e],!0)}copyAll(e){for(const t of D(e.combine())){const n=e.getWithExplicit(t);this.setWithExplicit(t,n)}}}function ac(e){return{explicit:!0,value:e}}function sc(e){return{explicit:!1,value:e}}function lc(e){return(t,n,i,r)=>{const o=e(t.value,n.value);return o>0?t:o<0?n:cc(t,n,i,r)}}function cc(e,t,n,i){return e.explicit&&t.explicit&&Si(function(e,t,n,i){return`Conflicting ${t.toString()} property "${e.toString()}" (${Q(n)} and ${Q(i)}). Using ${Q(n)}.`}(n,i,e.value,t.value)),e}function uc(e,t,n,i){let r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:cc;return void 0===e||void 0===e.value?t:e.explicit&&!t.explicit?e:t.explicit&&!e.explicit?t:X(e.value,t.value)?e:r(e,t,n,i)}class fc extends oc{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];super(e,t),this.explicit=e,this.implicit=t,this.parseNothing=n}clone(){const e=super.clone();return e.parseNothing=this.parseNothing,e}}function dc(e){return J(e,"url")}function mc(e){return J(e,"values")}function pc(e){return J(e,"name")&&!dc(e)&&!mc(e)&&!gc(e)}function gc(e){return e&&(hc(e)||yc(e)||vc(e))}function hc(e){return J(e,"sequence")}function yc(e){return J(e,"sphere")}function vc(e){return J(e,"graticule")}let bc=function(e){return e[e.Raw=0]="Raw",e[e.Main=1]="Main",e[e.Row=2]="Row",e[e.Column=3]="Column",e[e.Lookup=4]="Lookup",e[e.PreFilterInvalid=5]="PreFilterInvalid",e[e.PostFilterInvalid=6]="PostFilterInvalid",e}({});function xc(e){let{invalid:t,isPath:n}=e;switch(po(t,{isPath:n})){case"filter":return{marks:"exclude-invalid-values",scales:"exclude-invalid-values"};case"break-paths-show-domains":return{marks:n?"include-invalid-values":"exclude-invalid-values",scales:"include-invalid-values"};case"break-paths-filter-domains":return{marks:n?"include-invalid-values":"exclude-invalid-values",scales:"exclude-invalid-values"};case"show":return{marks:"include-invalid-values",scales:"include-invalid-values"}}}class $c{_children=[];_parent=null;constructor(e,t){this.debugName=t,e&&(this.parent=e)}clone(){throw new Error("Cannot clone node")}get parent(){return this._parent}set parent(e){this._parent=e,e&&e.addChild(this)}get children(){return this._children}numChildren(){return this._children.length}addChild(e,t){this._children.includes(e)?Si("Attempt to add the same child twice."):void 0!==t?this._children.splice(t,0,e):this._children.push(e)}removeChild(e){const t=this._children.indexOf(e);return this._children.splice(t,1),t}remove(){let e=this._parent.removeChild(this);for(const t of this._children)t._parent=this._parent,this._parent.addChild(t,e++)}insertAsParentOf(e){const t=e.parent;t.removeChild(this),this.parent=t,e.parent=this}swapWithParent(){const e=this._parent,t=e.parent;for(const t of this._children)t.parent=e;this._children=[],e.removeChild(this);const n=e.parent.removeChild(e);this._parent=t,t.addChild(this,n),e.parent=this}}class wc extends $c{clone(){const e=new this.constructor;return e.debugName=`clone_${this.debugName}`,e._source=this._source,e._name=`clone_${this._name}`,e.type=this.type,e.refCounts=this.refCounts,e.refCounts[e._name]=0,e}constructor(e,t,n,i){super(e,t),this.type=n,this.refCounts=i,this._source=this._name=t,this.refCounts&&!(this._name in this.refCounts)&&(this.refCounts[this._name]=0)}dependentFields(){return new Set}producedFields(){return new Set}hash(){return void 0===this._hash&&(this._hash=`Output ${I()}`),this._hash}getSource(){return this.refCounts[this._name]++,this._source}isRequired(){return!!this.refCounts[this._name]}setSource(e){this._source=e}}function kc(e){return void 0!==e.as}function Sc(e){return`${e}_end`}class Dc extends $c{clone(){return new Dc(null,l(this.timeUnits))}constructor(e,t){super(e),this.timeUnits=t}static makeFromEncoding(e,t){const n=t.reduceFieldDef(((e,n,i)=>{const{field:r,timeUnit:o}=n;if(o){let a;if(Ti(o)){if(qm(t)){const{mark:e,markDef:i,config:s}=t,l=Ho({fieldDef:n,markDef:i,config:s});(eo(e)||l)&&(a={timeUnit:Ii(o),field:r})}}else a={as:ma(n,{forAs:!0}),field:r,timeUnit:o};if(qm(t)){const{mark:e,markDef:r,config:o}=t,s=Ho({fieldDef:n,markDef:r,config:o});eo(e)&&_t(i)&&.5!==s&&(a.rectBandPosition=s)}a&&(e[d(a)]=a)}return e}),{});return S(n)?null:new Dc(e,n)}static makeFromTransform(e,t){const{timeUnit:n,...i}={...t},r={...i,timeUnit:Ii(n)};return new Dc(e,{[d(r)]:r})}merge(e){this.timeUnits={...this.timeUnits};for(const t in e.timeUnits)this.timeUnits[t]||(this.timeUnits[t]=e.timeUnits[t]);for(const t of e.children)e.removeChild(t),t.parent=this;e.remove()}removeFormulas(e){const t={};for(const[n,i]of O(this.timeUnits)){const r=kc(i)?i.as:`${i.field}_end`;e.has(r)||(t[n]=i)}this.timeUnits=t}producedFields(){return new Set(F(this.timeUnits).map((e=>kc(e)?e.as:Sc(e.field))))}dependentFields(){return new Set(F(this.timeUnits).map((e=>e.field)))}hash(){return`TimeUnit ${d(this.timeUnits)}`}assemble(){const e=[];for(const t of F(this.timeUnits)){const{rectBandPosition:n}=t,i=Ii(t.timeUnit);if(kc(t)){const{field:r,as:o}=t,{unit:a,utc:s,...l}=i,c=[o,`${o}_end`];e.push({field:M(r),type:"timeunit",...a?{units:Ri(a)}:{},...s?{timezone:"utc"}:{},...l,as:c}),e.push(...Cc(c,n,i))}else if(t){const{field:r}=t,o=r.replaceAll("\\.","."),a=zc({timeUnit:i,field:o}),s=Sc(o);e.push({type:"formula",expr:a,as:s}),e.push(...Cc([o,s],n,i))}}return e}}const Fc="offsetted_rect_start",Oc="offsetted_rect_end";function zc(e){let{timeUnit:t,field:n,reverse:i}=e;const{unit:r,utc:o}=t,a=Li(r),{part:s,step:l}=Hi(a,t.step);return`${o?"utcOffset":"timeOffset"}('${s}', ${j(n)}, ${i?-l:l})`}function Cc(e,t,n){let[i,r]=e;if(void 0!==t&&.5!==t){const e=j(i),o=j(r);return[{type:"formula",expr:_c([zc({timeUnit:n,field:i,reverse:!0}),e],t+.5),as:`${i}_${Fc}`},{type:"formula",expr:_c([e,o],t+.5),as:`${i}_${Oc}`}]}return[]}function _c(e,t){let[n,i]=e;return`${1-t} * ${n} + ${t} * ${i}`}const Pc="_tuple_fields";class Nc{constructor(){for(var e=arguments.length,t=new Array(e),n=0;n!0,parse:(e,n,i)=>{const r=n.name,o=n.project??=new Nc,a={},s={},l=new Set,c=(e,t)=>{const n="visual"===t?e.channel:e.field;let i=C(`${r}_${n}`);for(let e=1;l.has(i);e++)i=C(`${r}_${n}_${e}`);return l.add(i),{[t]:i}},u=n.type,f=e.config.selection[u],m=void 0!==i.value?t.array(i.value):null;let{fields:p,encodings:g}=t.isObject(i.select)?i.select:{};if(!p&&!g&&m)for(const e of m)if(t.isObject(e))for(const n of D(e))h=n,t.hasOwnProperty(et,h)?(g||(g=[])).push(n):"interval"===u?(Si('Interval selections should be initialized using "x", "y", "longitude", or "latitude" keys.'),g=f.encodings):(p??=[]).push(n);var h;p||g||(g=f.encodings,"fields"in f&&(p=f.fields));for(const t of g??[]){const n=e.fieldDef(t);if(n){let i=n.field;if(n.aggregate){Si(Jn(t,n.aggregate));continue}if(!i){Si(Qn(t));continue}if(n.timeUnit&&!Ti(n.timeUnit)){i=e.vgField(t);const r={timeUnit:n.timeUnit,as:i,field:n.field};s[d(r)]=r}if(!a[i]){const r={field:i,channel:t,type:"interval"===u&&Qt(t)&&Sr(e.getScaleComponent(t).get("type"))?"R":n.bin?"R-RE":"E",index:o.items.length};r.signals={...c(r,"data"),...c(r,"visual")},o.items.push(a[i]=r),o.hasField[i]=a[i],o.hasSelectionId=o.hasSelectionId||i===zs,Le(t)?(r.geoChannel=t,r.channel=Re(t),o.hasChannel[r.channel]=a[i]):o.hasChannel[t]=a[i]}}else Si(Qn(t))}for(const e of p??[]){if(o.hasField[e])continue;const t={type:"E",field:e,index:o.items.length};t.signals={...c(t,"data")},o.items.push(t),o.hasField[e]=t,o.hasSelectionId=o.hasSelectionId||e===zs}m&&(n.init=m.map((e=>o.items.map((n=>t.isObject(e)?void 0!==e[n.geoChannel||n.channel]?e[n.geoChannel||n.channel]:e[n.field]:e))))),S(s)||(o.timeUnit=new Dc(null,s))},signals:(e,t,n)=>{const i=t.name+Pc;return n.filter((e=>e.name===i)).length>0||t.project.hasSelectionId?n:n.concat({name:i,value:t.project.items.map(Bc)})}},Tc="_curr",jc="anim_value",Ec="anim_clock",Mc="eased_anim_clock",Rc="min_extent",Lc="max_range_extent",qc="last_tick_at",Uc="is_playing",Wc=1/60*1e3,Ic={defined:e=>"point"===e.type,topLevelSignals:(e,t,n)=>(af(t)&&(n=n.concat([{name:Ec,init:"0",on:[{events:{type:"timer",throttle:Wc},update:`${Uc} ? (${Ec} + (now() - ${qc}) > ${Lc} ? 0 : ${Ec} + (now() - ${qc})) : ${Ec}`}]},{name:qc,init:"now()",on:[{events:[{signal:Ec},{signal:Uc}],update:"now()"}]},{name:Uc,init:"true"}])),n),signals:(e,n,i)=>{const r=n.name,o=r+Pc,a=n.project,s="(item().isVoronoi ? datum.datum : datum)",l=F(e.component.selection??{}).reduce(((e,t)=>"interval"===t.type?e.concat(t.name+Zc):e),[]).map((e=>`indexof(item().mark.name, '${e}') < 0`)).join(" && "),c="datum && item().mark.marktype !== 'group' && indexof(item().mark.role, 'legend') < 0"+(l?` && ${l}`:"");let u=`unit: ${nf(e)}, `;if(n.project.hasSelectionId)u+=`${zs}: ${s}[${t.stringValue(zs)}]`;else if(af(n))u+=`fields: ${o}, values: [${jc} ? ${jc} : ${Rc}]`;else{u+=`fields: ${o}, values: [${a.items.map((n=>{const i=e.fieldDef(n.channel);return i?.bin?`[${s}[${t.stringValue(e.vgField(n.channel,{}))}], ${s}[${t.stringValue(e.vgField(n.channel,{binSuffix:"end"}))}]]`:`${s}[${t.stringValue(n.field)}]`})).join(", ")}]`}if(af(n))return i.concat((f=n.name,d=e.scaleName(ge),[{name:Mc,update:Ec},{name:`${f}_domain`,init:`domain('${d}')`},{name:Rc,init:`extent(${f}_domain)[0]`},{name:Lc,init:`extent(range('${d}'))[1]`},{name:jc,update:`invert('${d}', ${Mc})`}]),[{name:r+Ku,on:[{events:[{signal:Mc},{signal:jc}],update:`{${u}}`,force:!0}]}]);{const e=n.events;return i.concat([{name:r+Ku,on:e?[{events:e,update:`${c} ? {${u}} : null`,force:!0}]:[]}])}var f,d}};function Bc(e){const{signals:t,hasLegend:n,index:i,...r}=e;return r.field=M(r.field),r}function Vc(e){let n=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.identity;if(t.isArray(e)){const t=e.map((e=>Vc(e,n,i)));return n?`[${t.join(", ")}]`:t}return Di(e)?i(n?Pi(e):function(e){const t=_i(e,!0);return e.utc?+new Date(Date.UTC(...t)):+new Date(...t)}(e)):n?i(Q(e)):e}function Hc(e,n){for(const i of F(e.component.selection??{})){const r=i.name;let o=`${r}${Ku}, ${"global"===i.resolve?"true":`{unit: ${nf(e)}}`}`;for(const t of tf)t.defined(i)&&(t.signals&&(n=t.signals(e,i,n)),t.modifyExpr&&(o=t.modifyExpr(e,i,o)));n.push({name:r+Zu,on:[{events:{signal:i.name+Ku},update:`modify(${t.stringValue(i.name+Ju)}, ${o})`}]})}return Xc(n)}function Gc(e,n){if(e.component.selection&&D(e.component.selection).length){const i=t.stringValue(e.getName("cell"));n.unshift({name:"facet",value:{},on:[{events:t.parseSelector("pointermove","scope"),update:`isTuple(facet) ? facet : group(${i}).datum`}]})}return Xc(n)}function Yc(e,t){for(const n of F(e.component.selection??{}))for(const i of tf)i.defined(n)&&i.marks&&(t=i.marks(e,n,t));return t}function Xc(e){return e.map((e=>(e.on&&!e.on.length&&delete e.on,e)))}const Qc={defined:e=>"interval"===e.type&&"global"===e.resolve&&e.bind&&"scales"===e.bind,parse:(e,t)=>{const n=t.scales=[];for(const i of t.project.items){const r=i.channel;if(!Qt(r))continue;const o=e.getScaleComponent(r),a=o?o.get("type"):void 0;"sequential"==a&&Si("Sequntial scales are deprecated. The available quantitative scale type values are linear, log, pow, sqrt, symlog, time and utc"),o&&Sr(a)?(o.set("selectionExtent",{param:t.name,field:i.field},!0),n.push(i)):Si("Scale bindings are currently only supported for scales with unbinned, continuous domains.")}},topLevelSignals:(e,n,i)=>{const r=n.scales.filter((e=>0===i.filter((t=>t.name===e.signals.data)).length));if(!e.parent||Kc(e)||0===r.length)return i;const o=i.find((e=>e.name===n.name));let a=o.update;if(a.includes(ef))o.update=`{${r.map((e=>`${t.stringValue(M(e.field))}: ${e.signals.data}`)).join(", ")}}`;else{for(const e of r){const n=`${t.stringValue(M(e.field))}: ${e.signals.data}`;a.includes(n)||(a=`${a.substring(0,a.length-1)}, ${n}}`)}o.update=a}return i.concat(r.map((e=>({name:e.signals.data}))))},signals:(e,t,n)=>{if(e.parent&&!Kc(e))for(const e of t.scales){const t=n.find((t=>t.name===e.signals.data));t.push="outer",delete t.value,delete t.update}return n}};function Jc(e,n){return`domain(${t.stringValue(e.scaleName(n))})`}function Kc(e){return e.parent&&Im(e.parent)&&(!e.parent.parent||Kc(e.parent.parent))}const Zc="_brush",eu="_scale_trigger",tu="geo_interval_init_tick",nu="_init",iu={defined:e=>"interval"===e.type,parse:(e,n,i)=>{if(e.hasProjection){const e={...t.isObject(i.select)?i.select:{}};e.fields=[zs],e.encodings||(e.encodings=i.value?D(i.value):[de,fe]),i.select={type:"interval",...e}}if(n.translate&&!Qc.defined(n)){const e=`!event.item || event.item.mark.name !== ${t.stringValue(n.name+Zc)}`;for(const i of n.events){if(!i.between){Si(`${i} is not an ordered event stream for interval selections.`);continue}const n=t.array(i.between[0].filter??=[]);n.includes(e)||n.push(e)}}},signals:(e,n,i)=>{const r=n.name,o=r+Ku,a=F(n.project.hasChannel).filter((e=>e.channel===te||e.channel===ne)),s=n.init?n.init[0]:null;if(i.push(...a.reduce(((i,r)=>i.concat(function(e,n,i,r){const o=!e.hasProjection,a=i.channel,s=i.signals.visual,l=t.stringValue(o?e.scaleName(a):e.projectionName()),c=e=>`scale(${l}, ${e})`,u=e.getSizeSignalRef(a===te?"width":"height").signal,f=`${a}(unit)`,d=n.events.reduce(((e,t)=>[...e,{events:t.between[0],update:`[${f}, ${f}]`},{events:t,update:`[${s}[0], clamp(${f}, 0, ${u})]`}]),[]);if(o){const t=i.signals.data,o=Qc.defined(n),u=e.getScaleComponent(a),f=u?u.get("type"):void 0,m=r?{init:Vc(r,!0,c)}:{value:[]};return d.push({events:{signal:n.name+eu},update:Sr(f)?`[${c(`${t}[0]`)}, ${c(`${t}[1]`)}]`:"[0, 0]"}),o?[{name:t,on:[]}]:[{name:s,...m,on:d},{name:t,...r?{init:Vc(r)}:{},on:[{events:{signal:s},update:`${s}[0] === ${s}[1] ? null : invert(${l}, ${s})`}]}]}{const e=a===te?0:1,t=n.name+nu;return[{name:s,...r?{init:`[${t}[0][${e}], ${t}[1][${e}]]`}:{value:[]},on:d}]}}(e,n,r,s&&s[r.index]))),[])),e.hasProjection){const l=t.stringValue(e.projectionName()),c=e.projectionName()+"_center",{x:u,y:f}=n.project.hasChannel,d=u&&u.signals.visual,m=f&&f.signals.visual,p=u?s&&s[u.index]:`${c}[0]`,g=f?s&&s[f.index]:`${c}[1]`,h=t=>e.getSizeSignalRef(t).signal,y=`[[${d?d+"[0]":"0"}, ${m?m+"[0]":"0"}],[${d?d+"[1]":h("width")}, ${m?m+"[1]":h("height")}]]`;if(s&&(i.unshift({name:r+nu,init:`[scale(${l}, [${u?p[0]:p}, ${f?g[0]:g}]), scale(${l}, [${u?p[1]:p}, ${f?g[1]:g}])]`}),!u||!f)){i.find((e=>e.name===c))||i.unshift({name:c,update:`invert(${l}, [${h("width")}/2, ${h("height")}/2])`})}const v=`vlSelectionTuples(${`intersect(${y}, {markname: ${t.stringValue(e.getName("marks"))}}, unit.mark)`}, ${`{unit: ${nf(e)}}`})`,b=a.map((e=>e.signals.visual));return i.concat({name:o,on:[{events:[...b.length?[{signal:b.join(" || ")}]:[],...s?[{signal:tu}]:[]],update:v}]})}{if(!Qc.defined(n)){const n=r+eu,o=a.map((n=>{const i=n.channel,{data:r,visual:o}=n.signals,a=t.stringValue(e.scaleName(i)),s=Sr(e.getScaleComponent(i).get("type"))?"+":"";return`(!isArray(${r}) || (${s}invert(${a}, ${o})[0] === ${s}${r}[0] && ${s}invert(${a}, ${o})[1] === ${s}${r}[1]))`}));o.length&&i.push({name:n,value:{},on:[{events:a.map((t=>({scale:e.scaleName(t.channel)}))),update:o.join(" && ")+` ? ${n} : {}`}]})}const l=a.map((e=>e.signals.data)),c=`unit: ${nf(e)}, fields: ${r+Pc}, values`;return i.concat({name:o,...s?{init:`{${c}: ${Vc(s)}}`}:{},...l.length?{on:[{events:[{signal:l.join(" || ")}],update:`${l.join(" && ")} ? {${c}: [${l}]} : null`}]}:{}})}},topLevelSignals:(e,t,n)=>{if(qm(e)&&e.hasProjection&&t.init){n.filter((e=>e.name===tu)).length||n.unshift({name:tu,value:null,on:[{events:"timer{1}",update:`${tu} === null ? {} : ${tu}`}]})}return n},marks:(e,n,i)=>{const r=n.name,{x:o,y:a}=n.project.hasChannel,s=o?.signals.visual,l=a?.signals.visual,c=`data(${t.stringValue(n.name+Ju)})`;if(Qc.defined(n)||!o&&!a)return i;const u={x:void 0!==o?{signal:`${s}[0]`}:{value:0},y:void 0!==a?{signal:`${l}[0]`}:{value:0},x2:void 0!==o?{signal:`${s}[1]`}:{field:{group:"width"}},y2:void 0!==a?{signal:`${l}[1]`}:{field:{group:"height"}}};if("global"===n.resolve)for(const t of D(u))u[t]=[{test:`${c}.length && ${c}[0].unit === ${nf(e)}`,...u[t]},{value:0}];const{fill:f,fillOpacity:d,cursor:m,...p}=n.mark,g=D(p).reduce(((e,t)=>(e[t]=[{test:[void 0!==o&&`${s}[0] !== ${s}[1]`,void 0!==a&&`${l}[0] !== ${l}[1]`].filter((e=>e)).join(" && "),value:p[t]},{value:null}],e)),{}),h=m??(n.translate?"move":null);return[{name:`${r+Zc}_bg`,type:"rect",clip:!0,encode:{enter:{fill:{value:f},fillOpacity:{value:d}},update:u}},...i,{name:r+Zc,type:"rect",clip:!0,encode:{enter:{...h?{cursor:{value:h}}:{},fill:{value:"transparent"}},update:{...u,...g}}}]}};function ru(e){let{model:n,channelDef:i,vgChannel:r,invalidValueRef:o,mainRefFn:a}=e;const s=Qo(i)&&i.condition;let l=[];if(s){l=t.array(s).map((e=>{const t=a(e);if(function(e){return J(e,"param")}(e)){const{param:i,empty:r}=e;return{test:ff(n,{param:i,empty:r}),...t}}return{test:mf(n,e.test),...t}}))}void 0!==o&&l.push(o);const c=a(i);return void 0!==c&&l.push(c),l.length>1||1===l.length&&Boolean(l[0].test)?{[r]:l}:1===l.length?{[r]:l[0]}:{}}function ou(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"text";const n=e.encoding[t];return ru({model:e,channelDef:n,vgChannel:t,mainRefFn:t=>au(t,e.config),invalidValueRef:void 0})}function au(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"datum";if(e){if(sa(e))return Pn(e.value);if(oa(e)){const{format:i,formatType:r}=$a(e);return Oo({fieldOrDatumDef:e,format:i,formatType:r,expr:n,config:t})}}}function su(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const{encoding:i,markDef:r,config:o,stack:a}=e,s=i.tooltip;if(t.isArray(s))return{tooltip:cu({tooltip:s},a,o,n)};{const l=n.reactiveGeom?"datum.datum":"datum";return ru({model:e,channelDef:s,vgChannel:"tooltip",mainRefFn:e=>{const s=au(e,o,l);if(s)return s;if(null===e)return;let c=En("tooltip",r,o);return!0===c&&(c={content:"encoding"}),t.isString(c)?{value:c}:t.isObject(c)?wn(c)?c:"encoding"===c.content?cu(i,a,o,n):{signal:l}:void 0},invalidValueRef:void 0})}}function lu(e,n,i){let{reactiveGeom:r}=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};const o={...i,...i.tooltipFormat},a=new Set,s=r?"datum.datum":"datum",l=[];function c(i,r){const c=rt(r),u=aa(i)?i:{...i,type:e[c].type},f=u.title||xa(u,o),d=t.array(f).join(", ").replaceAll(/"/g,'\\"');let m;if(_t(r)){const t="x"===r?"x2":"y2",n=wa(e[t]);if(pn(u.bin)&&n){const e=ma(u,{expr:s}),i=ma(n,{expr:s}),{format:r,formatType:l}=$a(u);m=jo(e,i,r,l,o),a.add(t)}}if((_t(r)||r===ce||r===se)&&n&&n.fieldChannel===r&&"normalize"===n.offset){const{format:e,formatType:t}=$a(u);m=Oo({fieldOrDatumDef:u,format:e,formatType:t,expr:s,config:o,normalizeStack:!0}).signal}m??=au(u,o,s).signal,l.push({channel:r,key:d,value:m})}Qa(e,((e,t)=>{Zo(e)?c(e,t):Jo(e)&&c(e.condition,t)}));const u={};for(const{channel:e,key:t,value:n}of l)a.has(e)||u[t]||(u[t]=n);return u}function cu(e,t,n){let{reactiveGeom:i}=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};const r=lu(e,t,n,{reactiveGeom:i}),o=O(r).map((e=>{let[t,n]=e;return`"${t}": ${n}`}));return o.length>0?{signal:`{${o.join(", ")}}`}:void 0}function uu(e){const{markDef:t,config:n}=e,i=En("aria",t,n);return!1===i?{}:{...i?{aria:i}:{},...fu(e),...du(e)}}function fu(e){const{mark:n,markDef:i,config:r}=e;if(!1===r.aria)return{};const o=En("ariaRoleDescription",i,r);return null!=o?{ariaRoleDescription:{value:o}}:t.hasOwnProperty(Fn,n)?{}:{ariaRoleDescription:{value:n}}}function du(e){const{encoding:t,markDef:n,config:i,stack:r}=e,o=t.description;if(o)return ru({model:e,channelDef:o,vgChannel:"description",mainRefFn:t=>au(t,e.config),invalidValueRef:void 0});const a=En("description",n,i);if(null!=a)return{description:Pn(a)};if(!1===i.aria)return{};const s=lu(t,r,i);return S(s)?void 0:{description:{signal:O(s).map(((e,t)=>{let[n,i]=e;return`"${t>0?"; ":""}${n}: " + (${i})`})).join(" + ")}}}function mu(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const{markDef:i,encoding:r,config:o}=t,{vgChannel:a}=n;let{defaultRef:s,defaultValue:l}=n;const c=r[e];void 0===s&&(l??=En(e,i,o,{vgChannel:a,ignoreVgConfig:!Qo(c)}),void 0!==l&&(s=Pn(l)));const u={markDef:i,config:o,scaleName:t.scaleName(e),scale:t.getScaleComponent(e)},f=yo({...u,scaleChannel:e,channelDef:c});return ru({model:t,channelDef:c,vgChannel:a??e,invalidValueRef:f,mainRefFn:t=>wo({...u,channel:e,channelDef:t,stack:null,defaultRef:s})})}function pu(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{filled:void 0};const{markDef:n,encoding:i,config:r}=e,{type:o}=n,a=t.filled??En("filled",n,r),s=p(["bar","point","circle","square","geoshape"],o)?"transparent":void 0,l=En(!0===a?"color":void 0,n,r,{vgChannel:"fill"})??r.mark[!0===a&&"color"]??s,c=En(!1===a?"color":void 0,n,r,{vgChannel:"stroke"})??r.mark[!1===a&&"color"],u=a?"fill":"stroke",f={...l?{fill:Pn(l)}:{},...c?{stroke:Pn(c)}:{}};return n.color&&(a?n.fill:n.stroke)&&Si(ai("property",{fill:"fill"in n,stroke:"stroke"in n})),{...f,...mu("color",e,{vgChannel:u,defaultValue:a?l:c}),...mu("fill",e,{defaultValue:i.fill?l:void 0}),...mu("stroke",e,{defaultValue:i.stroke?c:void 0})}}function gu(e){const{encoding:t,mark:n}=e,i=t.order;return!Zr(n)&&sa(i)?ru({model:e,channelDef:i,vgChannel:"zindex",mainRefFn:e=>Pn(e.value),invalidValueRef:void 0}):{}}function hu(e){let{channel:t,markDef:n,encoding:i={},model:r,bandPosition:o}=e;const a=`${t}Offset`,s=n[a],l=i[a];if(("xOffset"===a||"yOffset"===a)&&l){return{offsetType:"encoding",offset:wo({channel:a,channelDef:l,markDef:n,config:r?.config,scaleName:r.scaleName(a),scale:r.getScaleComponent(a),stack:null,defaultRef:Pn(s),bandPosition:o})}}const c=n[a];return c?{offsetType:"visual",offset:c}:{}}function yu(e,t,n){let{defaultPos:i,vgChannel:r}=n;const{encoding:o,markDef:a,config:s,stack:l}=t,c=o[e],u=o[at(e)],f=t.scaleName(e),d=t.getScaleComponent(e),{offset:m,offsetType:p}=hu({channel:e,markDef:a,encoding:o,model:t,bandPosition:.5}),g=vu({model:t,defaultPos:i,channel:e,scaleName:f,scale:d}),h=!c&&_t(e)&&(o.latitude||o.longitude)?{field:t.getName(e)}:function(e){const{channel:t,channelDef:n,scaleName:i,stack:r,offset:o,markDef:a}=e;if(oa(n)&&r&&t===r.fieldChannel){if(Zo(n)){let e=n.bandPosition;if(void 0!==e||"text"!==a.type||"radius"!==t&&"theta"!==t||(e=.5),void 0!==e)return $o({scaleName:i,fieldOrDatumDef:n,startSuffix:"start",bandPosition:e,offset:o})}return xo(n,i,{suffix:"end"},{offset:o})}return bo(e)}({channel:e,channelDef:c,channel2Def:u,markDef:a,config:s,scaleName:f,scale:d,stack:l,offset:m,defaultRef:g,bandPosition:"encoding"===p?0:void 0});return h?{[r||e]:h}:void 0}function vu(e){let{model:t,defaultPos:n,channel:i,scaleName:r,scale:o}=e;const{markDef:a,config:s}=t;return()=>{const e=rt(i),l=ot(i),c=En(i,a,s,{vgChannel:l});if(void 0!==c)return ko(i,c);switch(n){case"zeroOrMin":return bu({scaleName:r,scale:o,mode:"zeroOrMin",mainChannel:e,config:s});case"zeroOrMax":return bu({scaleName:r,scale:o,mode:{zeroOrMax:{widthSignal:t.width.signal,heightSignal:t.height.signal}},mainChannel:e,config:s});case"mid":return{...t[st(i)],mult:.5}}}}function bu(e){let{mainChannel:t,config:n,...i}=e;const r=ho(i),{mode:o}=i;if(r)return r;switch(t){case"radius":{if("zeroOrMin"===o)return{value:0};const{widthSignal:e,heightSignal:t}=o.zeroOrMax;return{signal:`min(${e},${t})/2`}}case"theta":return"zeroOrMin"===o?{value:0}:{signal:"2*PI"};case"x":return"zeroOrMin"===o?{value:0}:{field:{group:"width"}};case"y":return"zeroOrMin"===o?{field:{group:"height"}}:{value:0}}}const xu={left:"x",center:"xc",right:"x2"},$u={top:"y",middle:"yc",bottom:"y2"};function wu(e,t,n){let i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"middle";if("radius"===e||"theta"===e)return ot(e);const r="x"===e?"align":"baseline",o=En(r,t,n);let a;return wn(o)?(Si(function(e){return`The ${e} for range marks cannot be an expression`}(r)),a=void 0):a=o,"x"===e?xu[a||("top"===i?"left":"center")]:$u[a||i]}function ku(e,t,n){let{defaultPos:i,defaultPos2:r,range:o}=n;return o?Su(e,t,{defaultPos:i,defaultPos2:r}):yu(e,t,{defaultPos:i})}function Su(e,t,n){let{defaultPos:i,defaultPos2:r}=n;const{markDef:o,config:a}=t,s=at(e),l=st(e),c=function(e,t,n){const{encoding:i,mark:r,markDef:o,stack:a,config:s}=e,l=rt(n),c=st(n),u=ot(n),f=i[l],d=e.scaleName(l),m=e.getScaleComponent(l),{offset:p}=hu(n in i||n in o?{channel:n,markDef:o,encoding:i,model:e}:{channel:l,markDef:o,encoding:i,model:e});if(!f&&("x2"===n||"y2"===n)&&(i.latitude||i.longitude)){const t=st(n),i=e.markDef[t];return null!=i?{[t]:{value:i}}:{[u]:{field:e.getName(n)}}}const g=function(e){let{channel:t,channelDef:n,channel2Def:i,markDef:r,config:o,scaleName:a,scale:s,stack:l,offset:c,defaultRef:u}=e;if(oa(n)&&l&&t.charAt(0)===l.fieldChannel.charAt(0))return xo(n,a,{suffix:"start"},{offset:c});return bo({channel:t,channelDef:i,scaleName:a,scale:s,stack:l,markDef:r,config:o,offset:c,defaultRef:u})}({channel:n,channelDef:f,channel2Def:i[n],markDef:o,config:s,scaleName:d,scale:m,stack:a,offset:p,defaultRef:void 0});if(void 0!==g)return{[u]:g};return Du(n,o)||Du(n,{[n]:Rn(n,o,s.style),[c]:Rn(c,o,s.style)})||Du(n,s[r])||Du(n,s.mark)||{[u]:vu({model:e,defaultPos:t,channel:n,scaleName:d,scale:m})()}}(t,r,s);return{...yu(e,t,{defaultPos:i,vgChannel:c[l]?wu(e,o,a):ot(e)}),...c}}function Du(e,t){const n=st(e),i=ot(e);if(void 0!==t[i])return{[i]:ko(e,t[i])};if(void 0!==t[e])return{[i]:ko(e,t[e])};if(t[n]){const i=t[n];if(!lo(i))return{[n]:ko(e,i)};Si(function(e){return`Position range does not support relative band size for ${e}.`}(n))}}function Fu(e,n){const{config:i,encoding:r,markDef:o}=e,a=o.type,s=at(n),l=st(n),c=r[n],u=r[s],f=e.getScaleComponent(n),d=f?f.get("type"):void 0,m=o.orient,p=r[l]??r.size??En("size",o,i,{vgChannel:l}),g=lt(n),h="bar"===a&&("x"===n?"vertical"===m:"horizontal"===m)||"tick"===a&&("y"===n?"vertical"===m:"horizontal"===m);return!Zo(c)||!(mn(c.bin)||pn(c.bin)||c.timeUnit&&!u)||p&&!lo(p)||r[g]||kr(d)?(oa(c)&&kr(d)||h)&&!u?function(e,n,i){const{markDef:r,encoding:o,config:a,stack:s}=i,l=r.orient,c=i.scaleName(n),u=i.getScaleComponent(n),f=st(n),d=at(n),m=lt(n),p=i.scaleName(m),g=i.getScaleComponent(ct(n)),h="tick"===r.type||"horizontal"===l&&"y"===n||"vertical"===l&&"x"===n;let y;(o.size||r.size)&&(h?y=mu("size",i,{vgChannel:f,defaultRef:Pn(r.size)}):Si(function(e){return`Cannot apply size to non-oriented mark "${e}".`}(r.type)));const v=!!y,b=Go({channel:n,fieldDef:e,markDef:r,config:a,scaleType:(u||g)?.get("type"),useVlSizeChannel:h});y=y||{[f]:Ou(f,p||c,g||u,a,b,!!e,r.type)};const x="band"===(u||g)?.get("type")&&lo(b)&&!v?"top":"middle",$=wu(n,r,a,x),w="xc"===$||"yc"===$,{offset:k,offsetType:S}=hu({channel:n,markDef:r,encoding:o,model:i,bandPosition:w?.5:0}),D=bo({channel:n,channelDef:e,markDef:r,config:a,scaleName:c,scale:u,stack:s,offset:k,defaultRef:vu({model:i,defaultPos:"mid",channel:n,scaleName:c,scale:u}),bandPosition:w?"encoding"===S?0:.5:wn(b)?{signal:`(1-${b})/2`}:lo(b)?(1-b.band)/2:0});if(f)return{[$]:D,...y};{const e=ot(d),n=y[f],i=k?{...n,offset:k}:n;return{[$]:D,[e]:t.isArray(D)?[D[0],{...D[1],offset:i}]:{...D,offset:i}}}}(c,n,e):Su(n,e,{defaultPos:"zeroOrMax",defaultPos2:"zeroOrMin"}):function(e){let{fieldDef:t,fieldDef2:n,channel:i,model:r}=e;const{config:o,markDef:a,encoding:s}=r,l=r.getScaleComponent(i),c=r.scaleName(i),u=l?l.get("type"):void 0,f=l.get("reverse"),d=Go({channel:i,fieldDef:t,markDef:a,config:o,scaleType:u}),m=r.component.axes[i]?.[0],p=m?.get("translate")??.5,g=_t(i)?En("binSpacing",a,o)??0:0,h=at(i),y=ot(i),v=ot(h),b=Mn("minBandSize",a,o),{offset:x}=hu({channel:i,markDef:a,encoding:s,model:r,bandPosition:0}),{offset:$}=hu({channel:h,markDef:a,encoding:s,model:r,bandPosition:0}),w=function(e){let{scaleName:t,fieldDef:n}=e;const i=ma(n,{expr:"datum"});return`abs(scale("${t}", ${ma(n,{expr:"datum",suffix:"end"})}) - scale("${t}", ${i}))`}({fieldDef:t,scaleName:c}),k=zu(i,g,f,p,x,b,w),S=zu(h,g,f,p,$??x,b,w),D=wn(d)?{signal:`(1-${d.signal})/2`}:lo(d)?(1-d.band)/2:.5,F=Ho({fieldDef:t,fieldDef2:n,markDef:a,config:o});if(mn(t.bin)||t.timeUnit){const e=t.timeUnit&&.5!==F;return{[v]:Cu({fieldDef:t,scaleName:c,bandPosition:D,offset:S,useRectOffsetField:e}),[y]:Cu({fieldDef:t,scaleName:c,bandPosition:wn(D)?{signal:`1-${D.signal}`}:1-D,offset:k,useRectOffsetField:e})}}if(pn(t.bin)){const e=xo(t,c,{},{offset:S});if(Zo(n))return{[v]:e,[y]:xo(n,c,{},{offset:k})};if(gn(t.bin)&&t.bin.step)return{[v]:e,[y]:{signal:`scale("${c}", ${ma(t,{expr:"datum"})} + ${t.bin.step})`,offset:k}}}return void Si(xi(h))}({fieldDef:c,fieldDef2:u,channel:n,model:e})}function Ou(e,n,i,r,o,a,s){if(lo(o)){if(!i)return{mult:o.band,field:{group:e}};{const e=i.get("type");if("band"===e){let e=`bandwidth('${n}')`;1!==o.band&&(e=`${o.band} * ${e}`);const t=Mn("minBandSize",{type:s},r);return{signal:t?`max(${An(t)}, ${e})`:e}}1!==o.band&&(Si(function(e){return`Cannot use the relative band size with ${e} scale.`}(e)),o=void 0)}}else{if(wn(o))return o;if(o)return{value:o}}if(i){const e=i.get("range");if(kn(e)&&t.isNumber(e.step))return{value:e.step-2}}if(!a){const{bandPaddingInner:n,barBandPaddingInner:i,rectBandPaddingInner:o,tickBandPaddingInner:a}=r.scale,l=U(n,"tick"===s?a:"bar"===s?i:o);if(wn(l))return{signal:`(1 - (${l.signal})) * ${e}`};if(t.isNumber(l))return{signal:`${1-l} * ${e}`}}return{value:Ws(r.view,e)-2}}function zu(e,t,n,i,r,o,a){if(Ee(e))return 0;const s="x"===e||"y2"===e,l=s?-t/2:t/2;if(wn(n)||wn(r)||wn(i)||o){const e=An(n),t=An(r),c=An(i),u=An(o),f=o?`(${a} < ${u} ? ${s?"":"-"}0.5 * (${u} - (${a})) : ${l})`:l;return{signal:(c?`${c} + `:"")+(e?`(${e} ? -1 : 1) * `:"")+(t?`(${t} + ${f})`:f)}}return r=r||0,i+(n?-r-l:+r+l)}function Cu(e){let{fieldDef:t,scaleName:n,bandPosition:i,offset:r,useRectOffsetField:o}=e;return $o({scaleName:n,fieldOrDatumDef:t,bandPosition:i,offset:r,...o?{startSuffix:Fc,endSuffix:Oc}:{}})}const _u=new Set(["aria","width","height"]);function Pu(e,t){const{fill:n,stroke:i}="include"===t.color?pu(e):{};return{...Au(e.markDef,t),...Nu("fill",n),...Nu("stroke",i),...mu("opacity",e),...mu("fillOpacity",e),...mu("strokeOpacity",e),...mu("strokeWidth",e),...mu("strokeDash",e),...gu(e),...su(e),...ou(e,"href"),...uu(e)}}function Nu(e,t){return t?{[e]:t}:{}}function Au(e,t){return Dn.reduce(((n,i)=>(!_u.has(i)&&J(e,i)&&"ignore"!==t[i]&&(n[i]=Pn(e[i])),n)),{})}function Tu(e){const{config:t,markDef:n}=e,i=new Set;if(e.forEachFieldDef(((r,o)=>{let a;if(!Qt(o)||!(a=e.getScaleType(o)))return;const s=cn(r.aggregate),l=go({scaleChannel:o,markDef:n,config:t,scaleType:a,isCountAggregate:s});if("break-paths-filter-domains"===(c=l)||"break-paths-show-domains"===c){const t=e.vgField(o,{expr:"datum",binSuffix:e.stack?.impute?"mid":void 0});t&&i.add(t)}var c})),i.size>0){return{defined:{signal:[...i].map((e=>ir(e,!0))).join(" && ")}}}}function ju(e,t){if(void 0!==t)return{[e]:Pn(t)}}const Eu="voronoi",Mu={defined:e=>"point"===e.type&&e.nearest,parse:(e,t)=>{if(t.events)for(const n of t.events)n.markname=e.getName(Eu)},marks:(e,t,n)=>{const{x:i,y:r}=t.project.hasChannel,o=e.mark;if(Zr(o))return Si(`The "nearest" transform is not supported for ${o} marks.`),n;const a={name:e.getName(Eu),type:"path",interactive:!0,from:{data:e.getName("marks")},encode:{update:{fill:{value:"transparent"},strokeWidth:{value:.35},stroke:{value:"transparent"},isVoronoi:{value:!0},...su(e,{reactiveGeom:!0})}},transform:[{type:"voronoi",x:{expr:i||!r?"datum.datum.x || 0":"0"},y:{expr:r||!i?"datum.datum.y || 0":"0"},size:[e.getSizeSignalRef("width"),e.getSizeSignalRef("height")]}]};let s=0,l=!1;return n.forEach(((t,n)=>{const i=t.name??"";i===e.component.mark[0].name?s=n:i.includes(Eu)&&(l=!0)})),l||n.splice(s+1,0,a),n}},Ru={defined:e=>"point"===e.type&&"global"===e.resolve&&e.bind&&"scales"!==e.bind&&!_s(e.bind),parse:(e,t,n)=>of(t,n),topLevelSignals:(e,n,i)=>{const r=n.name,o=n.project,a=n.bind,s=n.init&&n.init[0],l=Mu.defined(n)?"(item().isVoronoi ? datum.datum : datum)":"datum";return o.items.forEach(((e,o)=>{const c=C(`${r}_${e.field}`);i.filter((e=>e.name===c)).length||i.unshift({name:c,...s?{init:Vc(s[o])}:{value:null},on:n.events?[{events:n.events,update:`datum && item().mark.marktype !== 'group' ? ${l}[${t.stringValue(e.field)}] : null`}]:[],bind:a[e.field]??a[e.channel]??a})})),i},signals:(e,t,n)=>{const i=t.name,r=t.project,o=n.find((e=>e.name===i+Ku)),a=i+Pc,s=r.items.map((e=>C(`${i}_${e.field}`))),l=s.map((e=>`${e} !== null`)).join(" && ");return s.length&&(o.update=`${l} ? {fields: ${a}, values: [${s.join(", ")}]} : null`),delete o.value,delete o.on,n}},Lu="_toggle",qu={defined:e=>"point"===e.type&&!af(e)&&!!e.toggle,signals:(e,t,n)=>n.concat({name:t.name+Lu,value:!1,on:[{events:t.events,update:t.toggle}]}),modifyExpr:(e,t)=>{const n=t.name+Ku,i=t.name+Lu;return`${i} ? null : ${n}, `+("global"===t.resolve?`${i} ? null : true, `:`${i} ? null : {unit: ${nf(e)}}, `)+`${i} ? ${n} : null`}},Uu={defined:e=>void 0!==e.clear&&!1!==e.clear&&!af(e),parse:(e,n)=>{n.clear&&(n.clear=t.isString(n.clear)?t.parseSelector(n.clear,"view"):n.clear)},topLevelSignals:(e,t,n)=>{if(Ru.defined(t))for(const e of t.project.items){const i=n.findIndex((n=>n.name===C(`${t.name}_${e.field}`)));-1!==i&&n[i].on.push({events:t.clear,update:"null"})}return n},signals:(e,t,n)=>{function i(e,i){-1!==e&&n[e].on&&n[e].on.push({events:t.clear,update:i})}if("interval"===t.type)for(const e of t.project.items){const t=n.findIndex((t=>t.name===e.signals.visual));if(i(t,"[0, 0]"),-1===t){i(n.findIndex((t=>t.name===e.signals.data)),"null")}}else{let e=n.findIndex((e=>e.name===t.name+Ku));i(e,"null"),qu.defined(t)&&(e=n.findIndex((e=>e.name===t.name+Lu)),i(e,"false"))}return n}},Wu={defined:e=>{const t="global"===e.resolve&&e.bind&&_s(e.bind),n=1===e.project.items.length&&e.project.items[0].field!==zs;return t&&!n&&Si("Legend bindings are only supported for selections over an individual field or encoding channel."),t&&n},parse:(e,n,i)=>{const r=l(i);if(r.select=t.isString(r.select)?{type:r.select,toggle:n.toggle}:{...r.select,toggle:n.toggle},of(n,r),t.isObject(i.select)&&(i.select.on||i.select.clear)){const e='event.item && indexof(event.item.mark.role, "legend") < 0';for(const i of n.events)i.filter=t.array(i.filter??[]),i.filter.includes(e)||i.filter.push(e)}const o=Ps(n.bind)?n.bind.legend:"click",a=t.isString(o)?t.parseSelector(o,"view"):t.array(o);n.bind={legend:{merge:a}}},topLevelSignals:(e,t,n)=>{const i=t.name,r=Ps(t.bind)&&t.bind.legend,o=e=>t=>{const n=l(t);return n.markname=e,n};for(const e of t.project.items){if(!e.hasLegend)continue;const a=`${C(e.field)}_legend`,s=`${i}_${a}`;if(0===n.filter((e=>e.name===s)).length){const e=r.merge.map(o(`${a}_symbols`)).concat(r.merge.map(o(`${a}_labels`))).concat(r.merge.map(o(`${a}_entries`)));n.unshift({name:s,...t.init?{}:{value:null},on:[{events:e,update:"isDefined(datum.value) ? datum.value : item().items[0].items[0].datum.value",force:!0},{events:r.merge,update:`!event.item || !datum ? null : ${s}`,force:!0}]})}}return n},signals:(e,t,n)=>{const i=t.name,r=t.project,o=n.find((e=>e.name===i+Ku)),a=i+Pc,s=r.items.filter((e=>e.hasLegend)).map((e=>C(`${i}_${C(e.field)}_legend`))),l=`${s.map((e=>`${e} !== null`)).join(" && ")} ? {fields: ${a}, values: [${s.join(", ")}]} : null`;t.events&&s.length>0?o.on.push({events:s.map((e=>({signal:e}))),update:l}):s.length>0&&(o.update=l,delete o.value,delete o.on);const c=n.find((e=>e.name===i+Lu)),u=Ps(t.bind)&&t.bind.legend;return c&&(t.events?c.on.push({...c.on[0],events:u}):c.on[0].events=u),n}};const Iu="_translate_anchor",Bu="_translate_delta",Vu={defined:e=>"interval"===e.type&&e.translate,signals:(e,n,i)=>{const r=n.name,o=Qc.defined(n),a=r+Iu,{x:s,y:l}=n.project.hasChannel;let c=t.parseSelector(n.translate,"scope");return o||(c=c.map((e=>(e.between[0].markname=r+Zc,e)))),i.push({name:a,value:{},on:[{events:c.map((e=>e.between[0])),update:"{x: x(unit), y: y(unit)"+(void 0!==s?`, extent_x: ${o?Jc(e,te):`slice(${s.signals.visual})`}`:"")+(void 0!==l?`, extent_y: ${o?Jc(e,ne):`slice(${l.signals.visual})`}`:"")+"}"}]},{name:r+Bu,value:{},on:[{events:c,update:`{x: ${a}.x - x(unit), y: ${a}.y - y(unit)}`}]}),void 0!==s&&Hu(e,n,s,"width",i),void 0!==l&&Hu(e,n,l,"height",i),i}};function Hu(e,t,n,i,r){const o=t.name,a=o+Iu,s=o+Bu,l=n.channel,c=Qc.defined(t),u=r.find((e=>e.name===n.signals[c?"data":"visual"])),f=e.getSizeSignalRef(i).signal,d=e.getScaleComponent(l),m=d&&d.get("type"),p=d&&d.get("reverse"),g=`${a}.extent_${l}`,h=`${c&&d?"log"===m?"panLog":"symlog"===m?"panSymlog":"pow"===m?"panPow":"panLinear":"panLinear"}(${g}, ${`${c?l===te?p?"":"-":p?"-":"":""}${s}.${l} / ${c?`${f}`:`span(${g})`}`}${c?"pow"===m?`, ${d.get("exponent")??1}`:"symlog"===m?`, ${d.get("constant")??1}`:"":""})`;u.on.push({events:{signal:s},update:c?h:`clampRange(${h}, 0, ${f})`})}const Gu="_zoom_anchor",Yu="_zoom_delta",Xu={defined:e=>"interval"===e.type&&e.zoom,signals:(e,n,i)=>{const r=n.name,o=Qc.defined(n),a=r+Yu,{x:s,y:l}=n.project.hasChannel,c=t.stringValue(e.scaleName(te)),u=t.stringValue(e.scaleName(ne));let f=t.parseSelector(n.zoom,"scope");return o||(f=f.map((e=>(e.markname=r+Zc,e)))),i.push({name:r+Gu,on:[{events:f,update:o?"{"+[c?`x: invert(${c}, x(unit))`:"",u?`y: invert(${u}, y(unit))`:""].filter((e=>e)).join(", ")+"}":"{x: x(unit), y: y(unit)}"}]},{name:a,on:[{events:f,force:!0,update:"pow(1.001, event.deltaY * pow(16, event.deltaMode))"}]}),void 0!==s&&Qu(e,n,s,"width",i),void 0!==l&&Qu(e,n,l,"height",i),i}};function Qu(e,t,n,i,r){const o=t.name,a=n.channel,s=Qc.defined(t),l=r.find((e=>e.name===n.signals[s?"data":"visual"])),c=e.getSizeSignalRef(i).signal,u=e.getScaleComponent(a),f=u&&u.get("type"),d=s?Jc(e,a):l.name,m=o+Yu,p=`${s&&u?"log"===f?"zoomLog":"symlog"===f?"zoomSymlog":"pow"===f?"zoomPow":"zoomLinear":"zoomLinear"}(${d}, ${`${o}${Gu}.${a}`}, ${m}${s?"pow"===f?`, ${u.get("exponent")??1}`:"symlog"===f?`, ${u.get("constant")??1}`:"":""})`;l.on.push({events:{signal:m},update:s?p:`clampRange(${p}, 0, ${c})`})}const Ju="_store",Ku="_tuple",Zu="_modify",ef="vlSelectionResolve",tf=[Ic,iu,Ac,qu,Ru,Qc,Wu,Uu,Vu,Xu,Mu];function nf(e){let{escape:n}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{escape:!0},i=n?t.stringValue(e.name):e.name;const r=function(e){let t=e.parent;for(;t&&!Um(t);)t=t.parent;return t}(e);if(r){const{facet:e}=r;for(const n of Be)e[n]&&(i+=` + '__facet_${n}_' + (facet[${t.stringValue(r.vgField(n))}])`)}return i}function rf(e){return F(e.component.selection??{}).reduce(((e,t)=>e||t.project.hasSelectionId),!1)}function of(e,n){!t.isString(n.select)&&n.select.on||delete e.events,!t.isString(n.select)&&n.select.clear||delete e.clear,!t.isString(n.select)&&n.select.toggle||delete e.toggle}function af(e){return e.events?.find((e=>"type"in e&&"timer"===e.type))}function sf(e){const t=[];return"Identifier"===e.type?[e.name]:"Literal"===e.type?[e.value]:("MemberExpression"===e.type&&(t.push(...sf(e.object)),t.push(...sf(e.property))),t)}function lf(e){return"MemberExpression"===e.object.type?lf(e.object):"datum"===e.object.name}function cf(e){const n=t.parseExpression(e),i=new Set;return n.visit((e=>{"MemberExpression"===e.type&&lf(e)&&i.add(sf(e).slice(1).join("."))})),i}class uf extends $c{clone(){return new uf(null,this.model,l(this.filter))}constructor(e,t,n){super(e),this.model=t,this.filter=n,this.expr=mf(this.model,this.filter,this),this._dependentFields=cf(this.expr)}dependentFields(){return this._dependentFields}producedFields(){return new Set}assemble(){return{type:"filter",expr:this.expr}}hash(){return`Filter ${this.expr}`}}function ff(e,n,i){let r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"datum";const o=t.isString(n)?n:n.param,a=C(o),s=t.stringValue(a+Ju);let l;try{l=e.getSelectionComponent(a,o)}catch(e){return`!!${a}`}if(l.project.timeUnit){const t=i??e.component.data.raw,n=l.project.timeUnit.clone();t.parent?n.insertAsParentOf(t):t.parent=n}const c=`${l.project.hasSelectionId?"vlSelectionIdTest(":"vlSelectionTest("}${s}, ${r}${"global"===l.resolve?")":`, ${t.stringValue(l.resolve)})`}`,u=`length(data(${s}))`;return!1===n.empty?`${u} && ${c}`:`!${u} || ${c}`}function df(e,n,i){const r=C(n),o=i.encoding;let a,s=i.field;try{a=e.getSelectionComponent(r,n)}catch(e){return r}if(o||s){if(o&&!s){const e=a.project.items.filter((e=>e.channel===o));!e.length||e.length>1?(s=a.project.items[0].field,Si(function(e,n,i,r){return(e.length?"Multiple ":"No ")+`matching ${t.stringValue(n)} encoding found for selection ${t.stringValue(i.param)}. `+`Using "field": ${t.stringValue(r)}.`}(e,o,i,s))):s=e[0].field}}else s=a.project.items[0].field,a.project.items.length>1&&Si(function(e){return`A "field" or "encoding" must be specified when using a selection as a scale domain. Using "field": ${t.stringValue(e)}.`}(s));return`${a.name}[${t.stringValue(M(s))}]`}function mf(e,n,i){return _(n,(n=>t.isString(n)?n:function(e){return J(e,"param")}(n)?ff(e,n,i):nr(n)))}function pf(e,t,n,i){e.encode??={},e.encode[t]??={},e.encode[t].update??={},e.encode[t].update[n]=i}function gf(e,n,i){let r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{header:!1};const{disable:o,orient:a,scale:s,labelExpr:l,title:c,zindex:u,...f}=e.combine();if(!o){for(const e in f){const i=e,r=Ea[i],o=f[i];if(r&&r!==n&&"both"!==r)delete f[i];else if(Ta(o)){const{condition:e,...n}=o,r=t.array(e),a=Aa[i];if(a){const{vgProp:e,part:t}=a;pf(f,t,e,[...r.map((e=>{const{test:t,...n}=e;return{test:mf(null,t),...n}})),n]),delete f[i]}else if(null===a){const e={signal:r.map((e=>{const{test:t,...n}=e;return`${mf(null,t)} ? ${Nn(n)} : `})).join("")+Nn(n)};f[i]=e}}else if(wn(o)){const e=Aa[i];if(e){const{vgProp:t,part:n}=e;pf(f,n,t,o),delete f[i]}}p(["labelAlign","labelBaseline"],i)&&null===f[i]&&delete f[i]}if("grid"===n){if(!f.grid)return;if(f.encode){const{grid:e}=f.encode;f.encode={...e?{grid:e}:{}},S(f.encode)&&delete f.encode}return{scale:s,orient:a,...f,domain:!1,labels:!1,aria:!1,maxExtent:0,minExtent:0,ticks:!1,zindex:U(u,0)}}{if(!r.header&&e.mainExtracted)return;if(void 0!==l){let e=l;f.encode?.labels?.update&&wn(f.encode.labels.update.text)&&(e=R(l,"datum.label",f.encode.labels.update.text.signal)),pf(f,"labels","text",{signal:e})}if(null===f.labelAlign&&delete f.labelAlign,f.encode){for(const t of ja)e.hasAxisPart(t)||delete f.encode[t];S(f.encode)&&delete f.encode}const n=function(e,n){if(e)return t.isArray(e)&&!$n(e)?e.map((e=>xa(e,n))).join(", "):e}(c,i);return{scale:s,orient:a,grid:!1,...n?{title:n}:{},...f,...!1===i.aria?{aria:!1}:{},zindex:U(u,0)}}}}function hf(e){const{axes:t}=e.component,n=[];for(const i of Ct)if(t[i])for(const r of t[i])if(!r.get("disable")&&!r.get("gridScale")){const t="x"===i?"height":"width",r=e.getSizeSignalRef(t).signal;t!==r&&n.push({name:t,update:r})}return n}function yf(e,t,n,i){return Object.assign.apply(null,[{},...e.map((e=>{if("axisOrient"===e){const e="x"===n?"bottom":"left",r=t["x"===n?"axisBottom":"axisLeft"]||{},o=t["x"===n?"axisTop":"axisRight"]||{},a=new Set([...D(r),...D(o)]),s={};for(const t of a.values())s[t]={signal:`${i.signal} === "${e}" ? ${An(r[t])} : ${An(o[t])}`};return s}return t[e]}))])}function vf(e,n){const i=[{}];for(const r of e){let e=n[r]?.style;if(e){e=t.array(e);for(const t of e)i.push(n.style[t])}}return Object.assign.apply(null,i)}function bf(e,t,n){let i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};const r=Ln(e,n,t);if(void 0!==r)return{configFrom:"style",configValue:r};for(const t of["vlOnlyAxisConfig","vgAxisConfig","axisConfigStyle"])if(void 0!==i[t]?.[e])return{configFrom:t,configValue:i[t][e]};return{}}const xf={scale:e=>{let{model:t,channel:n}=e;return t.scaleName(n)},format:e=>{let{format:t}=e;return t},formatType:e=>{let{formatType:t}=e;return t},grid:e=>{let{fieldOrDatumDef:t,axis:n,scaleType:i}=e;return n.grid??function(e,t){return!kr(e)&&Zo(t)&&!mn(t?.bin)&&!pn(t?.bin)}(i,t)},gridScale:e=>{let{model:t,channel:n}=e;return function(e,t){const n="x"===t?"y":"x";if(e.getScaleComponent(n))return e.scaleName(n);return}(t,n)},labelAlign:e=>{let{axis:t,labelAngle:n,orient:i,channel:r}=e;return t.labelAlign||kf(n,i,r)},labelAngle:e=>{let{labelAngle:t}=e;return t},labelBaseline:e=>{let{axis:t,labelAngle:n,orient:i,channel:r}=e;return t.labelBaseline||wf(n,i,r)},labelFlush:e=>{let{axis:t,fieldOrDatumDef:n,channel:i}=e;return t.labelFlush??function(e,t){if("x"===t&&p(["quantitative","temporal"],e))return!0;return}(n.type,i)},labelOverlap:e=>{let{axis:n,fieldOrDatumDef:i,scaleType:r}=e;return n.labelOverlap??function(e,n,i,r){if(i&&!t.isObject(r)||"nominal"!==e&&"ordinal"!==e)return"log"!==n&&"symlog"!==n||"greedy";return}(i.type,r,Zo(i)&&!!i.timeUnit,Zo(i)?i.sort:void 0)},orient:e=>{let{orient:t}=e;return t},tickCount:e=>{let{channel:t,model:n,axis:i,fieldOrDatumDef:r,scaleType:o}=e;const a="x"===t?"width":"y"===t?"height":void 0,s=a?n.getSizeSignalRef(a):void 0;return i.tickCount??function(e){let{fieldOrDatumDef:t,scaleType:n,size:i,values:r}=e;if(!r&&!kr(n)&&"log"!==n){if(Zo(t)){if(mn(t.bin))return{signal:`ceil(${i.signal}/10)`};if(t.timeUnit&&p(["month","hours","day","quarter"],Ii(t.timeUnit)?.unit))return}return{signal:`ceil(${i.signal}/40)`}}return}({fieldOrDatumDef:r,scaleType:o,size:s,values:i.values})},tickMinStep:function(e){let{format:t,fieldOrDatumDef:n}=e;if("d"===t)return 1;if(Zo(n)){const{timeUnit:e}=n;if(e){const t=Bi(e);if(t)return{signal:t}}}return},title:e=>{let{axis:t,model:n,channel:i}=e;if(void 0!==t.title)return t.title;const r=Sf(n,i);if(void 0!==r)return r;const o=n.typedFieldDef(i),a="x"===i?"x2":"y2",s=n.fieldDef(a);return Un(o?[Bo(o)]:[],Zo(s)?[Bo(s)]:[])},values:e=>{let{axis:n,fieldOrDatumDef:i}=e;return function(e,n){const i=e.values;if(t.isArray(i))return Pa(n,i);if(wn(i))return i;return}(n,i)},zindex:e=>{let{axis:t,fieldOrDatumDef:n,mark:i}=e;return t.zindex??function(e,t){if("rect"===e&&pa(t))return 1;return 0}(i,n)}};function $f(e){return`(((${e.signal} % 360) + 360) % 360)`}function wf(e,t,n,i){if(void 0!==e){if("x"===n){if(wn(e)){const n=$f(e);return{signal:`(45 < ${n} && ${n} < 135) || (225 < ${n} && ${n} < 315) ? "middle" :(${n} <= 45 || 315 <= ${n}) === ${wn(t)?`(${t.signal} === "top")`:"top"===t} ? "bottom" : "top"`}}if(45{if(la(t)&&qo(t.sort)){const{field:i,timeUnit:r}=t,o=t.sort,a=o.map(((e,t)=>`${nr({field:i,timeUnit:r,equal:e})} ? ${t} : `)).join("")+o.length;e=new Df(e,{calculate:a,as:Ff(t,n,{forAs:!0})})}})),e}producedFields(){return new Set([this.transform.as])}dependentFields(){return this._dependentFields}assemble(){return{type:"formula",expr:this.transform.calculate,as:this.transform.as}}hash(){return`Calculate ${d(this.transform)}`}}function Ff(e,t,n){return ma(e,{prefix:t,suffix:"sort_index",...n})}function Of(e,t){return p(["top","bottom"],t)?"column":p(["left","right"],t)||"row"===e?"row":"column"}function zf(e,t,n,i){const r="row"===i?n.headerRow:"column"===i?n.headerColumn:n.headerFacet;return U((t||{})[e],r[e],n.header[e])}function Cf(e,t,n,i){const r={};for(const o of e){const e=zf(o,t||{},n,i);void 0!==e&&(r[o]=e)}return r}const _f=["row","column"],Pf=["header","footer"];function Nf(e,t){const n=e.component.layoutHeaders[t].title,i=e.config?e.config:void 0,r=e.component.layoutHeaders[t].facetFieldDef?e.component.layoutHeaders[t].facetFieldDef:void 0,{titleAnchor:o,titleAngle:a,titleOrient:s}=Cf(["titleAnchor","titleAngle","titleOrient"],r.header,i,t),l=Of(t,s),c=H(a);return{name:`${t}-title`,type:"group",role:`${l}-title`,title:{text:n,..."row"===t?{orient:"left"}:{},style:"guide-title",...Tf(c,l),...Af(l,c,o),...Uf(i,r,t,Ss,ws)}}}function Af(e,t){switch(arguments.length>2&&void 0!==arguments[2]?arguments[2]:"middle"){case"start":return{align:"left"};case"end":return{align:"right"}}const n=kf(t,"row"===e?"left":"top","row"===e?"y":"x");return n?{align:n}:{}}function Tf(e,t){const n=wf(e,"row"===t?"left":"top","row"===t?"y":"x",!0);return n?{baseline:n}:{}}function jf(e,t){const n=e.component.layoutHeaders[t],i=[];for(const r of Pf)if(n[r])for(const o of n[r]){const a=Rf(e,t,r,n,o);null!=a&&i.push(a)}return i}function Ef(e,n){const{sort:i}=e;return Lo(i)?{field:ma(i,{expr:"datum"}),order:i.order??"ascending"}:t.isArray(i)?{field:Ff(e,n,{expr:"datum"}),order:"ascending"}:{field:ma(e,{expr:"datum"}),order:i??"ascending"}}function Mf(e,t,n){const{format:i,formatType:r,labelAngle:o,labelAnchor:a,labelOrient:s,labelExpr:l}=Cf(["format","formatType","labelAngle","labelAnchor","labelOrient","labelExpr"],e.header,n,t),c=Oo({fieldOrDatumDef:e,format:i,formatType:r,expr:"parent",config:n}).signal,u=Of(t,s);return{text:{signal:l?R(R(l,"datum.label",c),"datum.value",ma(e,{expr:"parent"})):c},..."row"===t?{orient:"left"}:{},style:"guide-label",frame:"group",...Tf(o,u),...Af(u,o,a),...Uf(n,e,t,Ds,ks)}}function Rf(e,t,n,i,r){if(r){let o=null;const{facetFieldDef:a}=i,s=e.config?e.config:void 0;if(a&&r.labels){const{labelOrient:e}=Cf(["labelOrient"],a.header,s,t);("row"===t&&!p(["top","bottom"],e)||"column"===t&&!p(["left","right"],e))&&(o=Mf(a,t,s))}const l=Um(e)&&!Uo(e.facet),c=r.axes,u=c?.length>0;if(o||u){const s="row"===t?"height":"width";return{name:e.getName(`${t}_${n}`),type:"group",role:`${t}-${n}`,...i.facetFieldDef?{from:{data:e.getName(`${t}_domain`)},sort:Ef(a,t)}:{},...u&&l?{from:{data:e.getName(`facet_domain_${t}`)}}:{},...o?{title:o}:{},...r.sizeSignal?{encode:{update:{[s]:r.sizeSignal}}}:{},...u?{axes:c}:{}}}}return null}const Lf={column:{start:0,end:1},row:{start:1,end:0}};function qf(e,t){return Lf[t][e]}function Uf(e,t,n,i,r){const o={};for(const a of i){if(!r[a])continue;const i=zf(a,t?.header,e,n);void 0!==i&&(o[r[a]]=i)}return o}function Wf(e){return[...If(e,"width"),...If(e,"height"),...If(e,"childWidth"),...If(e,"childHeight")]}function If(e,t){const n="width"===t?"x":"y",i=e.component.layoutSize.get(t);if(!i||"merged"===i)return[];const r=e.getSizeSignalRef(t).signal;if("step"===i){const t=e.getScaleComponent(n);if(t){const i=t.get("type"),o=t.get("range");if(kr(i)&&kn(o)){const i=e.scaleName(n);if(Um(e.parent)){if("independent"===e.parent.component.resolve.scale[n])return[Bf(i,o)]}return[Bf(i,o),{name:r,update:Vf(i,t,`domain('${i}').length`)}]}}throw new Error("layout size is step although width/height is not step.")}if("container"==i){const t=r.endsWith("width"),n=t?"containerSize()[0]":"containerSize()[1]",i=`isFinite(${n}) ? ${n} : ${Us(e.config.view,t?"width":"height")}`;return[{name:r,init:i,on:[{update:i,events:"window:resize"}]}]}return[{name:r,value:i}]}function Bf(e,t){const n=`${e}_step`;return wn(t.step)?{name:n,update:t.step.signal}:{name:n,value:t.step}}function Vf(e,t,n){const i=t.get("type"),r=t.get("padding"),o=U(t.get("paddingOuter"),r);let a=t.get("paddingInner");return a="band"===i?void 0!==a?a:r:1,`bandspace(${n}, ${An(a)}, ${An(o)}) * ${e}_step`}function Hf(e){return"childWidth"===e?"width":"childHeight"===e?"height":e}function Gf(e,t){return D(e).reduce(((n,i)=>({...n,...ru({model:t,channelDef:e[i],vgChannel:i,mainRefFn:e=>Pn(e.value),invalidValueRef:void 0})})),{})}function Yf(e,t){if(Um(t))return"theta"===e?"independent":"shared";if(Im(t))return"shared";if(Wm(t))return _t(e)||"theta"===e||"radius"===e?"independent":"shared";throw new Error("invalid model type for resolve")}function Xf(e,t){const n=e.scale[t],i=_t(t)?"axis":"legend";return"independent"===n?("shared"===e[i][t]&&Si(function(e){return`Setting the scale to be independent for "${e}" means we also have to set the guide (axis or legend) to be independent.`}(t)),"independent"):e[i][t]||"shared"}const Qf=D({aria:1,clipHeight:1,columnPadding:1,columns:1,cornerRadius:1,description:1,direction:1,fillColor:1,format:1,formatType:1,gradientLength:1,gradientOpacity:1,gradientStrokeColor:1,gradientStrokeWidth:1,gradientThickness:1,gridAlign:1,labelAlign:1,labelBaseline:1,labelColor:1,labelFont:1,labelFontSize:1,labelFontStyle:1,labelFontWeight:1,labelLimit:1,labelOffset:1,labelOpacity:1,labelOverlap:1,labelPadding:1,labelSeparation:1,legendX:1,legendY:1,offset:1,orient:1,padding:1,rowPadding:1,strokeColor:1,symbolDash:1,symbolDashOffset:1,symbolFillColor:1,symbolLimit:1,symbolOffset:1,symbolOpacity:1,symbolSize:1,symbolStrokeColor:1,symbolStrokeWidth:1,symbolType:1,tickCount:1,tickMinStep:1,title:1,titleAlign:1,titleAnchor:1,titleBaseline:1,titleColor:1,titleFont:1,titleFontSize:1,titleFontStyle:1,titleFontWeight:1,titleLimit:1,titleLineHeight:1,titleOpacity:1,titleOrient:1,titlePadding:1,type:1,values:1,zindex:1,disable:1,labelExpr:1,selections:1,opacity:1,shape:1,stroke:1,fill:1,size:1,strokeWidth:1,strokeDash:1,encode:1});class Jf extends oc{}const Kf={symbols:function(e,n){let{fieldOrDatumDef:i,model:r,channel:o,legendCmpt:a,legendType:s}=n;if("symbol"!==s)return;const{markDef:l,encoding:c,config:u,mark:f}=r,d=l.filled&&"trail"!==f;let m={...Tn({},r,io),...pu(r,{filled:d})};const p=a.get("symbolOpacity")??u.legend.symbolOpacity,g=a.get("symbolFillColor")??u.legend.symbolFillColor,h=a.get("symbolStrokeColor")??u.legend.symbolStrokeColor,y=void 0===p?Zf(c.opacity)??l.opacity:void 0;if(m.fill)if("fill"===o||d&&o===he)delete m.fill;else if(J(m.fill,"field"))g?delete m.fill:(m.fill=Pn(u.legend.symbolBaseFillColor??"black"),m.fillOpacity=Pn(y??1));else if(t.isArray(m.fill)){const e=ed(c.fill??c.color)??l.fill??(d&&l.color);e&&(m.fill=Pn(e))}if(m.stroke)if("stroke"===o||!d&&o===he)delete m.stroke;else if(J(m.stroke,"field")||h)delete m.stroke;else if(t.isArray(m.stroke)){const e=U(ed(c.stroke||c.color),l.stroke,d?l.color:void 0);e&&(m.stroke={value:e})}if(o!==we){const e=Zo(i)&&nd(r,a,i);e?m.opacity=[{test:e,...Pn(y??1)},Pn(u.legend.unselectedOpacity)]:y&&(m.opacity=Pn(y))}return m={...m,...e},S(m)?void 0:m},gradient:function(e,t){let{model:n,legendType:i,legendCmpt:r}=t;if("gradient"!==i)return;const{config:o,markDef:a,encoding:s}=n;let l={};const c=void 0===(r.get("gradientOpacity")??o.legend.gradientOpacity)?Zf(s.opacity)||a.opacity:void 0;c&&(l.opacity=Pn(c));return l={...l,...e},S(l)?void 0:l},labels:function(e,t){let{fieldOrDatumDef:n,model:i,channel:r,legendCmpt:o}=t;const a=i.legend(r)||{},s=i.config,l=Zo(n)?nd(i,o,n):void 0,c=l?[{test:l,value:1},{value:s.legend.unselectedOpacity}]:void 0,{format:u,formatType:f}=a;let d;So(f)?d=Co({fieldOrDatumDef:n,field:"datum.value",format:u,formatType:f,config:s}):void 0===u&&void 0===f&&s.customFormatTypes&&("quantitative"===n.type&&s.numberFormatType?d=Co({fieldOrDatumDef:n,field:"datum.value",format:s.numberFormat,formatType:s.numberFormatType,config:s}):"temporal"===n.type&&s.timeFormatType&&Zo(n)&&void 0===n.timeUnit&&(d=Co({fieldOrDatumDef:n,field:"datum.value",format:s.timeFormat,formatType:s.timeFormatType,config:s})));const m={...c?{opacity:c}:{},...d?{text:d}:{},...e};return S(m)?void 0:m},entries:function(e,t){let{legendCmpt:n}=t;const i=n.get("selections");return i?.length?{...e,fill:{value:"transparent"}}:e}};function Zf(e){return td(e,((e,t)=>Math.max(e,t.value)))}function ed(e){return td(e,((e,t)=>U(e,t.value)))}function td(e,n){return function(e){const n=e?.condition;return!!n&&(t.isArray(n)||sa(n))}(e)?t.array(e.condition).reduce(n,e.value):sa(e)?e.value:void 0}function nd(e,n,i){const r=n.get("selections");if(!r?.length)return;const o=t.stringValue(i.field);return r.map((e=>`(!length(data(${t.stringValue(C(e)+Ju)})) || (${e}[${o}] && indexof(${e}[${o}], datum.value) >= 0))`)).join(" || ")}const id={direction:e=>{let{direction:t}=e;return t},format:e=>{let{fieldOrDatumDef:t,legend:n,config:i}=e;const{format:r,formatType:o}=n;return _o(t,t.type,r,o,i,!1)},formatType:e=>{let{legend:t,fieldOrDatumDef:n,scaleType:i}=e;const{formatType:r}=t;return Po(r,n,i)},gradientLength:e=>{const{legend:t,legendConfig:n}=e;return t.gradientLength??n.gradientLength??function(e){let{legendConfig:t,model:n,direction:i,orient:r,scaleType:o}=e;const{gradientHorizontalMaxLength:a,gradientHorizontalMinLength:s,gradientVerticalMaxLength:l,gradientVerticalMinLength:c}=t;if(Dr(o))return"horizontal"===i?"top"===r||"bottom"===r?ad(n,"width",s,a):s:ad(n,"height",c,l);return}(e)},labelOverlap:e=>{let{legend:t,legendConfig:n,scaleType:i}=e;return t.labelOverlap??n.labelOverlap??function(e){if(p(["quantile","threshold","log","symlog"],e))return"greedy";return}(i)},symbolType:e=>{let{legend:t,markDef:n,channel:i,encoding:r}=e;return t.symbolType??function(e,t,n,i){if("shape"!==t){const e=ed(n)??i;if(e)return e}switch(e){case"bar":case"rect":case"image":case"square":return"square";case"line":case"trail":case"rule":return"stroke";case"arc":case"point":case"circle":case"tick":case"geoshape":case"area":case"text":return"circle"}}(n.type,i,r.shape,n.shape)},title:e=>{let{fieldOrDatumDef:t,config:n}=e;return va(t,n,{allowDisabling:!0})},type:e=>{let{legendType:t,scaleType:n,channel:i}=e;if(We(i)&&Dr(n)){if("gradient"===t)return}else if("symbol"===t)return;return t},values:e=>{let{fieldOrDatumDef:n,legend:i}=e;return function(e,n){const i=e.values;if(t.isArray(i))return Pa(n,i);if(wn(i))return i;return}(i,n)}};function rd(e){const{legend:t}=e;return U(t.type,function(e){let{channel:t,timeUnit:n,scaleType:i}=e;if(We(t)){if(p(["quarter","month","day"],n))return"symbol";if(Dr(i))return"gradient"}return"symbol"}(e))}function od(e){let{legendConfig:t,legendType:n,orient:i,legend:r}=e;return r.direction??t[n?"gradientDirection":"symbolDirection"]??function(e,t){switch(e){case"top":case"bottom":return"horizontal";case"left":case"right":case"none":case void 0:return;default:return"gradient"===t?"horizontal":void 0}}(i,n)}function ad(e,t,n,i){return{signal:`clamp(${e.getSizeSignalRef(t).signal}, ${n}, ${i})`}}function sd(e){const t=qm(e)?function(e){const{encoding:t}=e,n={};for(const i of[he,...Os]){const r=ka(t[i]);r&&e.getScaleComponent(i)&&(i===be&&Zo(r)&&r.type===fr||(n[i]=cd(e,i)))}return n}(e):function(e){const{legends:t,resolve:n}=e.component;for(const i of e.children){sd(i);for(const r of D(i.component.legends))n.legend[r]=Xf(e.component.resolve,r),"shared"===n.legend[r]&&(t[r]=ud(t[r],i.component.legends[r]),t[r]||(n.legend[r]="independent",delete t[r]))}for(const i of D(t))for(const t of e.children)t.component.legends[i]&&"shared"===n.legend[i]&&delete t.component.legends[i];return t}(e);return e.component.legends=t,t}function ld(e,t,n,i){switch(t){case"disable":return void 0!==n;case"values":return!!n?.values;case"title":if("title"===t&&e===i?.title)return!0}return e===(n||{})[t]}function cd(e,t){let n=e.legend(t);const{markDef:i,encoding:r,config:o}=e,a=o.legend,s=new Jf({},function(e,t){const n=e.scaleName(t);if("trail"===e.mark){if("color"===t)return{stroke:n};if("size"===t)return{strokeWidth:n}}return"color"===t?e.markDef.filled?{fill:n}:{stroke:n}:{[t]:n}}(e,t));!function(e,t,n){const i=e.fieldDef(t)?.field;for(const r of F(e.component.selection??{})){const e=r.project.hasField[i]??r.project.hasChannel[t];if(e&&Wu.defined(r)){const t=n.get("selections")??[];t.push(r.name),n.set("selections",t,!1),e.hasLegend=!0}}}(e,t,s);const l=void 0!==n?!n:a.disable;if(s.set("disable",l,void 0!==n),l)return s;n=n||{};const c=e.getScaleComponent(t).get("type"),u=ka(r[t]),f=Zo(u)?Ii(u.timeUnit)?.unit:void 0,d=n.orient||o.legend.orient||"right",m=rd({legend:n,channel:t,timeUnit:f,scaleType:c}),p={legend:n,channel:t,model:e,markDef:i,encoding:r,fieldOrDatumDef:u,legendConfig:a,config:o,scaleType:c,orient:d,legendType:m,direction:od({legend:n,legendType:m,orient:d,legendConfig:a})};for(const i of Qf){if("gradient"===m&&i.startsWith("symbol")||"symbol"===m&&i.startsWith("gradient"))continue;const r=i in id?id[i](p):n[i];if(void 0!==r){const a=ld(r,i,n,e.fieldDef(t));(a||void 0===o.legend[i])&&s.set(i,r,a)}}const g=n?.encoding??{},h=s.get("selections"),y={},v={fieldOrDatumDef:u,model:e,channel:t,legendCmpt:s,legendType:m};for(const t of["labels","legend","title","symbols","gradient","entries"]){const n=Gf(g[t]??{},e),i=t in Kf?Kf[t](n,v):n;void 0===i||S(i)||(y[t]={...h?.length&&Zo(u)?{name:`${C(u.field)}_legend_${t}`}:{},...h?.length?{interactive:!!h}:{},update:i})}return S(y)||s.set("encode",y,!!n?.encoding),s}function ud(e,t){if(!e)return t.clone();const n=e.getWithExplicit("orient"),i=t.getWithExplicit("orient");if(n.explicit&&i.explicit&&n.value!==i.value)return;let r=!1;for(const n of Qf){const i=uc(e.getWithExplicit(n),t.getWithExplicit(n),n,"legend",((e,t)=>{switch(n){case"symbolType":return fd(e,t);case"title":return In(e,t);case"type":return r=!0,sc("symbol")}return cc(e,t,n,"legend")}));e.setWithExplicit(n,i)}return r&&(e.implicit?.encode?.gradient&&P(e.implicit,["encode","gradient"]),e.explicit?.encode?.gradient&&P(e.explicit,["encode","gradient"])),e}function fd(e,t){return"circle"===t.value?t:e}function dd(e){const t=e.component.legends,n={};for(const i of D(t)){const r=Q(e.getScaleComponent(i).get("domains"));if(n[r])for(const e of n[r]){ud(e,t[i])||n[r].push(t[i])}else n[r]=[t[i].clone()]}return F(n).flat().map((t=>function(e,t){const{disable:n,labelExpr:i,selections:r,...o}=e.combine();if(n)return;!1===t.aria&&null==o.aria&&(o.aria=!1);if(o.encode?.symbols){const e=o.encode.symbols.update;!e.fill||"transparent"===e.fill.value||e.stroke||o.stroke||(e.stroke={value:"transparent"});for(const t of Os)o[t]&&delete e[t]}o.title||delete o.title;if(void 0!==i){let e=i;o.encode?.labels?.update&&wn(o.encode.labels.update.text)&&(e=R(i,"datum.label",o.encode.labels.update.text.signal)),function(e,t,n,i){e.encode??={},e.encode[t]??={},e.encode[t].update??={},e.encode[t].update[n]=i}(o,"labels","text",{signal:e})}return o}(t,e.config))).filter((e=>void 0!==e))}function md(e){return Im(e)||Wm(e)?function(e){return e.children.reduce(((e,t)=>e.concat(t.assembleProjections())),pd(e))}(e):pd(e)}function pd(e){const t=e.component.projection;if(!t||t.merged)return[];const n=t.combine(),{name:i}=n;if(t.data){const r={signal:`[${t.size.map((e=>e.signal)).join(", ")}]`},o=t.data.reduce(((t,n)=>{const i=wn(n)?n.signal:`data('${e.lookupDataSource(n)}')`;return p(t,i)||t.push(i),t}),[]);if(o.length<=0)throw new Error("Projection's fit didn't find any data sources");return[{name:i,size:r,fit:{signal:o.length>1?`[${o.join(", ")}]`:o[0]},...n}]}return[{name:i,translate:{signal:"[width / 2, height / 2]"},...n}]}const gd=["type","clipAngle","clipExtent","center","rotate","precision","reflectX","reflectY","coefficient","distance","fraction","lobes","parallel","radius","ratio","spacing","tilt"];class hd extends oc{merged=!1;constructor(e,t,n,i){super({...t},{name:e}),this.specifiedProjection=t,this.size=n,this.data=i}get isFit(){return!!this.data}}function yd(e){e.component.projection=qm(e)?function(e){if(e.hasProjection){const t=bn(e.specifiedProjection),n=!(t&&(null!=t.scale||null!=t.translate)),i=n?[e.getSizeSignalRef("width"),e.getSizeSignalRef("height")]:void 0,r=n?function(e){const t=[],{encoding:n}=e;for(const i of[[de,fe],[pe,me]])(ka(n[i[0]])||ka(n[i[1]]))&&t.push({signal:e.getName(`geojson_${t.length}`)});e.channelHasField(be)&&e.typedFieldDef(be).type===fr&&t.push({signal:e.getName(`geojson_${t.length}`)});0===t.length&&t.push(e.requestDataName(bc.Main));return t}(e):void 0,o=new hd(e.projectionName(!0),{...bn(e.config.projection),...t},i,r);return o.get("type")||o.set("type","equalEarth",!1),o}return}(e):function(e){if(0===e.children.length)return;let n;for(const t of e.children)yd(t);const i=h(e.children,(e=>{const i=e.component.projection;if(i){if(n){const e=function(e,n){const i=h(gd,(i=>!t.hasOwnProperty(e.explicit,i)&&!t.hasOwnProperty(n.explicit,i)||!!(t.hasOwnProperty(e.explicit,i)&&t.hasOwnProperty(n.explicit,i)&&X(e.get(i),n.get(i)))));if(X(e.size,n.size)){if(i)return e;if(X(e.explicit,{}))return n;if(X(n.explicit,{}))return e}return null}(n,i);return e&&(n=e),!!e}return n=i,!0}return!0}));if(n&&i){const t=e.projectionName(!0),i=new hd(t,n.specifiedProjection,n.size,l(n.data));for(const n of e.children){const e=n.component.projection;e&&(e.isFit&&i.data.push(...n.component.projection.data),n.renameProjection(e.get("name"),t),e.merged=!0)}return i}return}(e)}function vd(e,t,n,i){if(Na(t,n)){const r=qm(e)?e.axis(n)??e.legend(n)??{}:{},o=ma(t,{expr:"datum"}),a=ma(t,{expr:"datum",binSuffix:"end"});return{formulaAs:ma(t,{binSuffix:"range",forAs:!0}),formula:jo(o,a,r.format,r.formatType,i)}}return{}}function bd(e,t){return`${dn(e)}_${t}`}function xd(e,t,n){const i=bd(Oa(n,void 0)??{},t);return e.getName(`${i}_bins`)}function $d(e,n,i){let r,o;r=function(e){return"as"in e}(e)?t.isString(e.as)?[e.as,`${e.as}_end`]:[e.as[0],e.as[1]]:[ma(e,{forAs:!0}),ma(e,{binSuffix:"end",forAs:!0})];const a={...Oa(n,void 0)},s=bd(a,e.field),{signal:l,extentSignal:c}=function(e,t){return{signal:e.getName(`${t}_bins`),extentSignal:e.getName(`${t}_extent`)}}(i,s);if(hn(a.extent)){const e=a.extent;o=df(i,e.param,e),delete a.extent}return{key:s,binComponent:{bin:a,field:e.field,as:[r],...l?{signal:l}:{},...c?{extentSignal:c}:{},...o?{span:o}:{}}}}class wd extends $c{clone(){return new wd(null,l(this.bins))}constructor(e,t){super(e),this.bins=t}static makeFromEncoding(e,t){const n=t.reduceFieldDef(((e,n,i)=>{if(aa(n)&&mn(n.bin)){const{key:r,binComponent:o}=$d(n,n.bin,t);e[r]={...o,...e[r],...vd(t,n,i,t.config)}}return e}),{});return S(n)?null:new wd(e,n)}static makeFromTransform(e,t,n){const{key:i,binComponent:r}=$d(t,t.bin,n);return new wd(e,{[i]:r})}merge(e,t){for(const n of D(e.bins))n in this.bins?(t(e.bins[n].signal,this.bins[n].signal),this.bins[n].as=b([...this.bins[n].as,...e.bins[n].as],d)):this.bins[n]=e.bins[n];for(const t of e.children)e.removeChild(t),t.parent=this;e.remove()}producedFields(){return new Set(F(this.bins).map((e=>e.as)).flat(2))}dependentFields(){return new Set(F(this.bins).map((e=>e.field)))}hash(){return`Bin ${d(this.bins)}`}assemble(){return F(this.bins).flatMap((e=>{const t=[],[n,...i]=e.as,{extent:r,...o}=e.bin,a={type:"bin",field:M(e.field),as:n,signal:e.signal,...hn(r)?{extent:null}:{extent:r},...e.span?{span:{signal:`span(${e.span})`}}:{},...o};!r&&e.extentSignal&&(t.push({type:"extent",field:M(e.field),signal:e.extentSignal}),a.extent={signal:e.extentSignal}),t.push(a);for(const e of i)for(let i=0;i<2;i++)t.push({type:"formula",expr:ma({field:n[i]},{expr:"datum"}),as:e[i]});return e.formula&&t.push({type:"formula",expr:e.formula,as:e.formulaAs}),t}))}}function kd(e,n,i,r){const o=qm(r)?r.encoding[at(n)]:void 0;if(aa(i)&&qm(r)&&Yo(i,o,r.markDef,r.config)){e.add(ma(i,{})),e.add(ma(i,{suffix:"end"}));const{mark:t,markDef:o,config:a}=r,s=Ho({fieldDef:i,markDef:o,config:a});eo(t)&&.5!==s&&_t(n)&&(e.add(ma(i,{suffix:Fc})),e.add(ma(i,{suffix:Oc}))),i.bin&&Na(i,n)&&e.add(ma(i,{binSuffix:"range"}))}else if(Le(n)){const t=Re(n);e.add(r.getName(t))}else e.add(ma(i));return la(i)&&function(e){return t.isObject(e)&&"field"in e}(i.scale?.range)&&e.add(i.scale.range.field),e}class Sd extends $c{clone(){return new Sd(null,new Set(this.dimensions),l(this.measures))}constructor(e,t,n){super(e),this.dimensions=t,this.measures=n}get groupBy(){return this.dimensions}static makeFromEncoding(e,t){let n=!1;t.forEachFieldDef((e=>{e.aggregate&&(n=!0)}));const i={},r=new Set;return n?(t.forEachFieldDef(((e,n)=>{const{aggregate:o,field:a}=e;if(o)if("count"===o)i["*"]??={},i["*"].count=new Set([ma(e,{forAs:!0})]);else{if(on(o)||an(o)){const e=on(o)?"argmin":"argmax",t=o[e];i[t]??={},i[t][e]=new Set([ma({op:e,field:t},{forAs:!0})])}else i[a]??={},i[a][o]=new Set([ma(e,{forAs:!0})]);Qt(n)&&"unaggregated"===t.scaleDomain(n)&&(i[a]??={},i[a].min=new Set([ma({field:a,aggregate:"min"},{forAs:!0})]),i[a].max=new Set([ma({field:a,aggregate:"max"},{forAs:!0})]))}else kd(r,n,e,t)})),r.size+D(i).length===0?null:new Sd(e,r,i)):null}static makeFromTransform(e,t){const n=new Set,i={};for(const e of t.aggregate){const{op:t,field:n,as:r}=e;t&&("count"===t?(i["*"]??={},i["*"].count=new Set([r||ma(e,{forAs:!0})])):(i[n]??={},i[n][t]??=new Set,i[n][t].add(r||ma(e,{forAs:!0}))))}for(const e of t.groupby??[])n.add(e);return n.size+D(i).length===0?null:new Sd(e,n,i)}merge(e){return x(this.dimensions,e.dimensions)?(function(e,t){for(const n of D(t)){const i=t[n];for(const t of D(i))n in e?e[n][t]=new Set([...e[n][t]??[],...i[t]]):e[n]={[t]:i[t]}}}(this.measures,e.measures),!0):(function(){wi.debug(...arguments)}("different dimensions, cannot merge"),!1)}addDimensions(e){e.forEach(this.dimensions.add,this.dimensions)}dependentFields(){return new Set([...this.dimensions,...D(this.measures)])}producedFields(){const e=new Set;for(const t of D(this.measures))for(const n of D(this.measures[t])){const i=this.measures[t][n];0===i.size?e.add(`${n}_${t}`):i.forEach(e.add,e)}return e}hash(){return`Aggregate ${d({dimensions:this.dimensions,measures:this.measures})}`}assemble(){const e=[],t=[],n=[];for(const i of D(this.measures))for(const r of D(this.measures[i]))for(const o of this.measures[i][r])n.push(o),e.push(r),t.push("*"===i?null:M(i));return{type:"aggregate",groupby:[...this.dimensions].map(M),ops:e,fields:t,as:n}}}class Dd extends $c{constructor(e,n,i,r){super(e),this.model=n,this.name=i,this.data=r;for(const e of Be){const i=n.facet[e];if(i){const{bin:r,sort:o}=i;this[e]={name:n.getName(`${e}_domain`),fields:[ma(i),...mn(r)?[ma(i,{binSuffix:"end"})]:[]],...Lo(o)?{sortField:o}:t.isArray(o)?{sortIndexField:Ff(i,e)}:{}}}}this.childModel=n.child}hash(){let e="Facet";for(const t of Be)this[t]&&(e+=` ${t.charAt(0)}:${d(this[t])}`);return e}get fields(){const e=[];for(const t of Be)this[t]?.fields&&e.push(...this[t].fields);return e}dependentFields(){const e=new Set(this.fields);for(const t of Be)this[t]&&(this[t].sortField&&e.add(this[t].sortField.field),this[t].sortIndexField&&e.add(this[t].sortIndexField));return e}producedFields(){return new Set}getSource(){return this.name}getChildIndependentFieldsWithStep(){const e={};for(const t of Ct){const n=this.childModel.component.scales[t];if(n&&!n.merged){const i=n.get("type"),r=n.get("range");if(kr(i)&&kn(r)){const n=ym(vm(this.childModel,t));n?e[t]=n:Si(Xn(t))}}}return e}assembleRowColumnHeaderData(e,t,n){const i={row:"y",column:"x",facet:void 0}[e],r=[],o=[],a=[];i&&n&&n[i]&&(t?(r.push(`distinct_${n[i]}`),o.push("max")):(r.push(n[i]),o.push("distinct")),a.push(`distinct_${n[i]}`));const{sortField:s,sortIndexField:l}=this[e];if(s){const{op:e=Eo,field:t}=s;r.push(t),o.push(e),a.push(ma(s,{forAs:!0}))}else l&&(r.push(l),o.push("max"),a.push(l));return{name:this[e].name,source:t??this.data,transform:[{type:"aggregate",groupby:this[e].fields,...r.length?{fields:r,ops:o,as:a}:{}}]}}assembleFacetHeaderData(e){const{columns:t}=this.model.layout,{layoutHeaders:n}=this.model.component,i=[],r={};for(const e of _f){for(const t of Pf){const i=(n[e]&&n[e][t])??[];for(const t of i)if(t.axes?.length>0){r[e]=!0;break}}if(r[e]){const n=`length(data("${this.facet.name}"))`,r="row"===e?t?{signal:`ceil(${n} / ${t})`}:1:t?{signal:`min(${n}, ${t})`}:{signal:n};i.push({name:`${this.facet.name}_${e}`,transform:[{type:"sequence",start:0,stop:r}]})}}const{row:o,column:a}=r;return(o||a)&&i.unshift(this.assembleRowColumnHeaderData("facet",null,e)),i}assemble(){const e=[];let t=null;const n=this.getChildIndependentFieldsWithStep(),{column:i,row:r,facet:o}=this;if(i&&r&&(n.x||n.y)){t=`cross_${this.column.name}_${this.row.name}`;const i=[].concat(n.x??[],n.y??[]),r=i.map((()=>"distinct"));e.push({name:t,source:this.data,transform:[{type:"aggregate",groupby:this.fields,fields:i,ops:r}]})}for(const i of[Z,K])this[i]&&e.push(this.assembleRowColumnHeaderData(i,t,n));if(o){const t=this.assembleFacetHeaderData(n);t&&e.push(...t)}return e}}function Fd(e){return e.startsWith("'")&&e.endsWith("'")||e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1):e}function Od(e){const n={};return a(e.filter,(e=>{if(er(e)){let i=null;Gi(e)?i=Cn(e.equal):Xi(e)?i=Cn(e.lte):Yi(e)?i=Cn(e.lt):Qi(e)?i=Cn(e.gt):Ji(e)?i=Cn(e.gte):Ki(e)?i=e.range[0]:Zi(e)&&(i=(e.oneOf??e.in)[0]),i&&(Di(i)?n[e.field]="date":t.isNumber(i)?n[e.field]="number":t.isString(i)&&(n[e.field]="string")),e.timeUnit&&(n[e.field]="date")}})),n}function zd(e){const n={};function i(e){var i;Ca(e)?n[e.field]="date":"quantitative"===e.type&&(i=e.aggregate,t.isString(i)&&p(["min","max"],i))?n[e.field]="number":q(e.field)>1?e.field in n||(n[e.field]="flatten"):la(e)&&Lo(e.sort)&&q(e.sort.field)>1&&(e.sort.field in n||(n[e.sort.field]="flatten"))}if((qm(e)||Um(e))&&e.forEachFieldDef(((t,n)=>{if(aa(t))i(t);else{const r=rt(n),o=e.fieldDef(r);i({...t,type:o.type})}})),qm(e)){const{mark:t,markDef:i,encoding:r}=e;if(Zr(t)&&!e.encoding.order){const e=r["horizontal"===i.orient?"y":"x"];Zo(e)&&"quantitative"===e.type&&!(e.field in n)&&(n[e.field]="number")}}return n}class Cd extends $c{clone(){return new Cd(null,l(this._parse))}constructor(e,t){super(e),this._parse=t}hash(){return`Parse ${d(this._parse)}`}static makeExplicit(e,t,n){let i={};const r=t.data;return!gc(r)&&r?.format?.parse&&(i=r.format.parse),this.makeWithAncestors(e,i,{},n)}static makeWithAncestors(e,t,n,i){for(const e of D(n)){const t=i.getWithExplicit(e);void 0!==t.value&&(t.explicit||t.value===n[e]||"derived"===t.value||"flatten"===n[e]?delete n[e]:Si(ni(e,n[e],t.value)))}for(const e of D(t)){const n=i.get(e);void 0!==n&&(n===t[e]?delete t[e]:Si(ni(e,t[e],n)))}const r=new oc(t,n);i.copyAll(r);const o={};for(const e of D(r.combine())){const t=r.get(e);null!==t&&(o[e]=t)}return 0===D(o).length||i.parseNothing?null:new Cd(e,o)}get parse(){return this._parse}merge(e){this._parse={...this._parse,...e.parse},e.remove()}assembleFormatParse(){const e={};for(const t of D(this._parse)){const n=this._parse[t];1===q(t)&&(e[t]=n)}return e}producedFields(){return new Set(D(this._parse))}dependentFields(){return new Set(D(this._parse))}assembleTransforms(){let e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return D(this._parse).filter((t=>!e||q(t)>1)).map((e=>{const t=function(e,t){const n=A(e);if("number"===t)return`toNumber(${n})`;if("boolean"===t)return`toBoolean(${n})`;if("string"===t)return`toString(${n})`;if("date"===t)return`toDate(${n})`;if("flatten"===t)return n;if(t.startsWith("date:"))return`timeParse(${n},'${Fd(t.slice(5,t.length))}')`;if(t.startsWith("utc:"))return`utcParse(${n},'${Fd(t.slice(4,t.length))}')`;return Si(`Unrecognized parse "${t}".`),null}(e,this._parse[e]);if(!t)return null;return{type:"formula",expr:t,as:L(e)}})).filter((e=>null!==e))}}class _d extends $c{clone(){return new _d(null)}constructor(e){super(e)}dependentFields(){return new Set}producedFields(){return new Set([zs])}hash(){return"Identifier"}assemble(){return{type:"identifier",as:zs}}}class Pd extends $c{clone(){return new Pd(null,this.params)}constructor(e,t){super(e),this.params=t}dependentFields(){return new Set}producedFields(){}hash(){return`Graticule ${d(this.params)}`}assemble(){return{type:"graticule",...!0===this.params?{}:this.params}}}class Nd extends $c{clone(){return new Nd(null,this.params)}constructor(e,t){super(e),this.params=t}dependentFields(){return new Set}producedFields(){return new Set([this.params.as??"data"])}hash(){return`Hash ${d(this.params)}`}assemble(){return{type:"sequence",...this.params}}}class Ad extends $c{constructor(e){let t;if(super(null),e??={name:"source"},gc(e)||(t=e.format?{...f(e.format,["parse"])}:{}),mc(e))this._data={values:e.values};else if(dc(e)){if(this._data={url:e.url},!t.type){let n=/(?:\.([^.]+))?$/.exec(e.url)[1];p(["json","csv","tsv","dsv","topojson"],n)||(n="json"),t.type=n}}else yc(e)?this._data={values:[{type:"Sphere"}]}:(pc(e)||gc(e))&&(this._data={});this._generator=gc(e),e.name&&(this._name=e.name),t&&!S(t)&&(this._data.format=t)}dependentFields(){return new Set}producedFields(){}get data(){return this._data}hasName(){return!!this._name}get isGenerator(){return this._generator}get dataName(){return this._name}set dataName(e){this._name=e}set parent(e){throw new Error("Source nodes have to be roots.")}remove(){throw new Error("Source nodes are roots and cannot be removed.")}hash(){throw new Error("Cannot hash sources")}assemble(){return{name:this._name,...this._data,transform:[]}}}function Td(e){return e instanceof Ad||e instanceof Pd||e instanceof Nd}class jd{#e;constructor(){this.#e=!1}setModified(){this.#e=!0}get modifiedFlag(){return this.#e}}class Ed extends jd{getNodeDepths(e,t,n){n.set(e,t);for(const i of e.children)this.getNodeDepths(i,t+1,n);return n}optimize(e){const t=[...this.getNodeDepths(e,0,new Map).entries()].sort(((e,t)=>t[1]-e[1]));for(const e of t)this.run(e[0]);return this.modifiedFlag}}class Md extends jd{optimize(e){this.run(e);for(const t of e.children)this.optimize(t);return this.modifiedFlag}}class Rd extends Md{mergeNodes(e,t){const n=t.shift();for(const i of t)e.removeChild(i),i.parent=n,i.remove()}run(e){const t=e.children.map((e=>e.hash())),n={};for(let i=0;i1&&(this.setModified(),this.mergeNodes(e,n[t]))}}class Ld extends Md{constructor(e){super(),this.requiresSelectionId=e&&rf(e)}run(e){e instanceof _d&&(this.requiresSelectionId&&(Td(e.parent)||e.parent instanceof Sd||e.parent instanceof Cd)||(this.setModified(),e.remove()))}}class qd extends jd{optimize(e){return this.run(e,new Set),this.modifiedFlag}run(e,t){let n=new Set;e instanceof Dc&&(n=e.producedFields(),$(n,t)&&(this.setModified(),e.removeFormulas(t),0===e.producedFields.length&&e.remove()));for(const i of e.children)this.run(i,new Set([...t,...n]))}}class Ud extends Md{constructor(){super()}run(e){e instanceof wc&&!e.isRequired()&&(this.setModified(),e.remove())}}class Wd extends Ed{run(e){if(!(Td(e)||e.numChildren()>1))for(const t of e.children)if(t instanceof Cd)if(e instanceof Cd)this.setModified(),e.merge(t);else{if(k(e.producedFields(),t.dependentFields()))continue;this.setModified(),t.swapWithParent()}}}class Id extends Ed{run(e){const t=[...e.children],n=e.children.filter((e=>e instanceof Cd));if(e.numChildren()>1&&n.length>=1){const i={},r=new Set;for(const e of n){const t=e.parse;for(const e of D(t))e in i?i[e]!==t[e]&&r.add(e):i[e]=t[e]}for(const e of r)delete i[e];if(!S(i)){this.setModified();const n=new Cd(e,i);for(const r of t){if(r instanceof Cd)for(const e of D(i))delete r.parse[e];e.removeChild(r),r.parent=n,r instanceof Cd&&0===D(r.parse).length&&r.remove()}}}}}class Bd extends Ed{run(e){e instanceof wc||e.numChildren()>0||e instanceof Dd||e instanceof Ad||(this.setModified(),e.remove())}}class Vd extends Ed{run(e){const t=e.children.filter((e=>e instanceof Dc)),n=t.pop();for(const e of t)this.setModified(),n.merge(e)}}class Hd extends Ed{run(e){const t=e.children.filter((e=>e instanceof Sd)),n={};for(const e of t){const t=d(e.groupBy);t in n||(n[t]=[]),n[t].push(e)}for(const t of D(n)){const i=n[t];if(i.length>1){const t=i.pop();for(const n of i)t.merge(n)&&(e.removeChild(n),n.parent=t,n.remove(),this.setModified())}}}}class Gd extends Ed{constructor(e){super(),this.model=e}run(e){const t=!(Td(e)||e instanceof uf||e instanceof Cd||e instanceof _d),n=[],i=[];for(const r of e.children)r instanceof wd&&(t&&!k(e.producedFields(),r.dependentFields())?n.push(r):i.push(r));if(n.length>0){const t=n.pop();for(const e of n)t.merge(e,this.model.renameSignal.bind(this.model));this.setModified(),e instanceof wd?e.merge(t,this.model.renameSignal.bind(this.model)):t.swapWithParent()}if(i.length>1){const e=i.pop();for(const t of i)e.merge(t,this.model.renameSignal.bind(this.model));this.setModified()}}}class Yd extends Ed{run(e){const t=[...e.children];if(!g(t,(e=>e instanceof wc))||e.numChildren()<=1)return;const n=[];let i;for(const r of t)if(r instanceof wc){let t=r;for(;1===t.numChildren();){const[e]=t.children;if(!(e instanceof wc))break;t=e}n.push(...t.children),i?(e.removeChild(r),r.parent=i.parent,i.parent.removeChild(i),i.parent=t,this.setModified()):i=t}else n.push(r);if(n.length){this.setModified();for(const e of n)e.parent.removeChild(e),e.parent=i}}}class Xd extends $c{clone(){return new Xd(null,l(this.transform))}constructor(e,t){super(e),this.transform=t}addDimensions(e){this.transform.groupby=b(this.transform.groupby.concat(e),(e=>e))}dependentFields(){const e=new Set;return this.transform.groupby&&this.transform.groupby.forEach(e.add,e),this.transform.joinaggregate.map((e=>e.field)).filter((e=>void 0!==e)).forEach(e.add,e),e}producedFields(){return new Set(this.transform.joinaggregate.map(this.getDefaultName))}getDefaultName(e){return e.as??ma(e)}hash(){return`JoinAggregateTransform ${d(this.transform)}`}assemble(){const e=[],t=[],n=[];for(const i of this.transform.joinaggregate)t.push(i.op),n.push(this.getDefaultName(i)),e.push(void 0===i.field?null:i.field);const i=this.transform.groupby;return{type:"joinaggregate",as:n,ops:t,fields:e,...void 0!==i?{groupby:i}:{}}}}class Qd extends $c{clone(){return new Qd(null,{...this.filter})}constructor(e,t){super(e),this.filter=t}static make(e,t,n){const{config:i,markDef:r}=t,{marks:o,scales:a}=n;if("include-invalid-values"===o&&"include-invalid-values"===a)return null;const s=t.reduceFieldDef(((e,n,o)=>{const a=Qt(o)&&t.getScaleComponent(o);if(a){const t=a.get("type"),{aggregate:s}=n,l=go({scaleChannel:o,markDef:r,config:i,scaleType:t,isCountAggregate:cn(s)});"show"!==l&&"always-valid"!==l&&(e[n.field]=n)}return e}),{});return D(s).length?new Qd(e,s):null}dependentFields(){return new Set(D(this.filter))}producedFields(){return new Set}hash(){return`FilterInvalid ${d(this.filter)}`}assemble(){const e=D(this.filter).reduce(((e,t)=>{const n=this.filter[t],i=ma(n,{expr:"datum"});return null!==n&&("temporal"===n.type?e.push(`(isDate(${i}) || (${Jd(i)}))`):"quantitative"===n.type&&e.push(Jd(i))),e}),[]);return e.length>0?{type:"filter",expr:e.join(" && ")}:null}}function Jd(e){return`isValid(${e}) && isFinite(+${e})`}class Kd extends $c{clone(){return new Kd(null,l(this._stack))}constructor(e,t){super(e),this._stack=t}static makeFromTransform(e,n){const{stack:i,groupby:r,as:o,offset:a="zero"}=n,s=[],l=[];if(void 0!==n.sort)for(const e of n.sort)s.push(e.field),l.push(U(e.order,"ascending"));const c={field:s,order:l};let u;return u=function(e){return t.isArray(e)&&e.every((e=>t.isString(e)))&&e.length>1}(o)?o:t.isString(o)?[o,`${o}_end`]:[`${n.stack}_start`,`${n.stack}_end`],new Kd(e,{dimensionFieldDefs:[],stackField:i,groupby:r,offset:a,sort:c,facetby:[],as:u})}static makeFromEncoding(e,n){const i=n.stack,{encoding:r}=n;if(!i)return null;const{groupbyChannels:o,fieldChannel:a,offset:s,impute:l}=i,c=o.map((e=>wa(r[e]))).filter((e=>!!e)),u=function(e){return e.stack.stackBy.reduce(((e,t)=>{const n=ma(t.fieldDef);return n&&e.push(n),e}),[])}(n),f=n.encoding.order;let d;if(t.isArray(f)||Zo(f))d=qn(f);else{const e=Xo(f)?f.sort:"y"===a?"descending":"ascending";d=u.reduce(((t,n)=>(t.field.includes(n)||(t.field.push(n),t.order.push(e)),t)),{field:[],order:[]})}return new Kd(e,{dimensionFieldDefs:c,stackField:n.vgField(a),facetby:[],stackby:u,sort:d,offset:s,impute:l,as:[n.vgField(a,{suffix:"start",forAs:!0}),n.vgField(a,{suffix:"end",forAs:!0})]})}get stack(){return this._stack}addDimensions(e){this._stack.facetby.push(...e)}dependentFields(){const e=new Set;return e.add(this._stack.stackField),this.getGroupbyFields().forEach(e.add,e),this._stack.facetby.forEach(e.add,e),this._stack.sort.field.forEach(e.add,e),e}producedFields(){return new Set(this._stack.as)}hash(){return`Stack ${d(this._stack)}`}getGroupbyFields(){const{dimensionFieldDefs:e,impute:t,groupby:n}=this._stack;return e.length>0?e.map((e=>e.bin?t?[ma(e,{binSuffix:"mid"})]:[ma(e,{}),ma(e,{binSuffix:"end"})]:[ma(e)])).flat():n??[]}assemble(){const e=[],{facetby:t,dimensionFieldDefs:n,stackField:i,stackby:r,sort:o,offset:a,impute:s,as:l}=this._stack;if(s)for(const o of n){const{bandPosition:n=.5,bin:a}=o;if(a){const t=ma(o,{expr:"datum"}),i=ma(o,{expr:"datum",binSuffix:"end"});e.push({type:"formula",expr:`${Jd(t)} ? ${n}*${t}+${1-n}*${i} : ${t}`,as:ma(o,{binSuffix:"mid",forAs:!0})})}e.push({type:"impute",field:i,groupby:[...r,...t],key:ma(o,{binSuffix:"mid"}),method:"value",value:0})}return e.push({type:"stack",groupby:[...this.getGroupbyFields(),...t],field:i,sort:o,as:l,offset:a}),e}}class Zd extends $c{clone(){return new Zd(null,l(this.transform))}constructor(e,t){super(e),this.transform=t}addDimensions(e){this.transform.groupby=b(this.transform.groupby.concat(e),(e=>e))}dependentFields(){const e=new Set;return(this.transform.groupby??[]).forEach(e.add,e),(this.transform.sort??[]).forEach((t=>e.add(t.field))),this.transform.window.map((e=>e.field)).filter((e=>void 0!==e)).forEach(e.add,e),e}producedFields(){return new Set(this.transform.window.map(this.getDefaultName))}getDefaultName(e){return e.as??ma(e)}hash(){return`WindowTransform ${d(this.transform)}`}assemble(){const e=[],t=[],n=[],i=[];for(const r of this.transform.window)t.push(r.op),n.push(this.getDefaultName(r)),i.push(void 0===r.param?null:r.param),e.push(void 0===r.field?null:r.field);const r=this.transform.frame,o=this.transform.groupby;if(r&&null===r[0]&&null===r[1]&&t.every((e=>sn(e))))return{type:"joinaggregate",as:n,ops:t,fields:e,...void 0!==o?{groupby:o}:{}};const a=[],s=[];if(void 0!==this.transform.sort)for(const e of this.transform.sort)a.push(e.field),s.push(e.order??"ascending");const l={field:a,order:s},c=this.transform.ignorePeers;return{type:"window",params:i,as:n,ops:t,fields:e,sort:l,...void 0!==c?{ignorePeers:c}:{},...void 0!==o?{groupby:o}:{},...void 0!==r?{frame:r}:{}}}}function em(e){if(e instanceof Dd)if(1!==e.numChildren()||e.children[0]instanceof wc){const n=e.model.component.data.main;tm(n);const i=(t=e,function e(n){if(!(n instanceof Dd)){const i=n.clone();if(i instanceof wc){const e=nm+i.getSource();i.setSource(e),t.model.component.data.outputNodes[e]=i}else(i instanceof Sd||i instanceof Kd||i instanceof Zd||i instanceof Xd)&&i.addDimensions(t.fields);for(const t of n.children.flatMap(e))t.parent=i;return[i]}return n.children.flatMap(e)}),r=e.children.map(i).flat();for(const e of r)e.parent=n}else{const t=e.children[0];(t instanceof Sd||t instanceof Kd||t instanceof Zd||t instanceof Xd)&&t.addDimensions(e.fields),t.swapWithParent(),em(e)}else e.children.map(em);var t}function tm(e){if(e instanceof wc&&e.type===bc.Main&&1===e.numChildren()){const t=e.children[0];t instanceof Dd||(t.swapWithParent(),tm(e))}}const nm="scale_",im=5;function rm(e){for(const t of e){for(const e of t.children)if(e.parent!==t)return!1;if(!rm(t.children))return!1}return!0}function om(e,t){let n=!1;for(const i of t)n=e.optimize(i)||n;return n}function am(e,t,n){let i=e.sources,r=!1;return r=om(new Ud,i)||r,r=om(new Ld(t),i)||r,i=i.filter((e=>e.numChildren()>0)),r=om(new Bd,i)||r,i=i.filter((e=>e.numChildren()>0)),n||(r=om(new Wd,i)||r,r=om(new Gd(t),i)||r,r=om(new qd,i)||r,r=om(new Id,i)||r,r=om(new Hd,i)||r,r=om(new Vd,i)||r,r=om(new Rd,i)||r,r=om(new Yd,i)||r),e.sources=i,r}class sm{constructor(e){Object.defineProperty(this,"signal",{enumerable:!0,get:e})}static fromName(e,t){return new sm((()=>e(t)))}}function lm(e){qm(e)?function(e){const t=e.component.scales;for(const n of D(t)){const i=cm(e,n);if(t[n].setWithExplicit("domains",i),mm(e,n),e.component.data.isFaceted){let t=e;for(;!Um(t)&&t.parent;)t=t.parent;if("shared"===t.component.resolve.scale[n])for(const e of i.value)Sn(e)&&(e.data=nm+e.data.replace(nm,""))}}}(e):function(e){for(const t of e.children)lm(t);const t=e.component.scales;for(const n of D(t)){let i,r=null;for(const t of e.children){const e=t.component.scales[n];if(e){i=void 0===i?e.getWithExplicit("domains"):uc(i,e.getWithExplicit("domains"),"domains","scale",gm);const t=e.get("selectionExtent");r&&t&&r.param!==t.param&&Si(Zn),r=t}}t[n].setWithExplicit("domains",i),r&&t[n].set("selectionExtent",r,!0)}}(e)}function cm(e,t){const n=e.getScaleComponent(t).get("type"),{encoding:i}=e,r=function(e,t,n,i){if("unaggregated"===e){const{valid:e,reason:i}=pm(t,n);if(!e)return void Si(i)}else if(void 0===e&&i.useUnaggregatedDomain){const{valid:e}=pm(t,n);if(e)return"unaggregated"}return e}(e.scaleDomain(t),e.typedFieldDef(t),n,e.config.scale);return r!==e.scaleDomain(t)&&(e.specifiedScales[t]={...e.specifiedScales[t],domain:r}),"x"===t&&ka(i.x2)?ka(i.x)?uc(fm(n,r,e,"x"),fm(n,r,e,"x2"),"domain","scale",gm):fm(n,r,e,"x2"):"y"===t&&ka(i.y2)?ka(i.y)?uc(fm(n,r,e,"y"),fm(n,r,e,"y2"),"domain","scale",gm):fm(n,r,e,"y2"):fm(n,r,e,t)}function um(e,t,n){const i=Ii(n)?.unit;return"temporal"===t||i?function(e,t,n){return e.map((e=>({signal:`{data: ${_a(e,{timeUnit:n,type:t})}}`})))}(e,t,i):[e]}function fm(e,n,i,r){const{encoding:o,markDef:a,mark:s,config:l,stack:c}=i,u=ka(o[r]),{type:f}=u,d=u.timeUnit,m=function(e){const{marks:t,scales:n}=xc(e);return t===n?bc.Main:"include-invalid-values"===n?bc.PreFilterInvalid:bc.PostFilterInvalid}({invalid:Mn("invalid",a,l),isPath:Zr(s)});if(function(e){return J(e,"unionWith")}(n)){const t=fm(e,void 0,i,r);return ac([...um(n.unionWith,f,d),...t.value])}if(wn(n))return ac([n]);if(n&&"unaggregated"!==n&&!Or(n))return ac(um(n,f,d));if(c&&r===c.fieldChannel){if("normalize"===c.offset)return sc([[0,1]]);const e=i.requestDataName(m);return sc([{data:e,field:i.vgField(r,{suffix:"start"})},{data:e,field:i.vgField(r,{suffix:"end"})}])}const g=Qt(r)&&Zo(u)?function(e,t,n){if(!kr(n))return;const i=e.fieldDef(t),r=i.sort;if(qo(r))return{op:"min",field:Ff(i,t),order:"ascending"};const{stack:o}=e,a=o?new Set([...o.groupbyFields,...o.stackBy.map((e=>e.fieldDef.field))]):void 0;if(Lo(r)){return dm(r,o&&!a.has(r.field))}if(function(e){return J(e,"encoding")}(r)){const{encoding:t,order:n}=r,i=e.fieldDef(t),{aggregate:s,field:l}=i,c=o&&!a.has(l);if(on(s)||an(s))return dm({field:ma(i),order:n},c);if(sn(s)||!s)return dm({op:s,field:l,order:n},c)}else{if("descending"===r)return{op:"min",field:e.vgField(t),order:"descending"};if(p(["ascending",void 0],r))return!0}return}(i,r,e):void 0;if(ta(u)){return sc(um([u.datum],f,d))}const h=u;if("unaggregated"===n){const{field:e}=u;return sc([{data:i.requestDataName(m),field:ma({field:e,aggregate:"min"})},{data:i.requestDataName(m),field:ma({field:e,aggregate:"max"})}])}if(mn(h.bin)){if(kr(e))return sc("bin-ordinal"===e?[]:[{data:z(g)?i.requestDataName(m):i.requestDataName(bc.Raw),field:i.vgField(r,Na(h,r)?{binSuffix:"range"}:{}),sort:!0!==g&&t.isObject(g)?g:{field:i.vgField(r,{}),op:"min"}}]);{const{bin:e}=h;if(mn(e)){const t=xd(i,h.field,e);return sc([new sm((()=>{const e=i.getSignalName(t);return`[${e}.start, ${e}.stop]`}))])}return sc([{data:i.requestDataName(m),field:i.vgField(r,{})}])}}if(h.timeUnit&&p(["time","utc"],e)){const e=o[at(r)];if(Yo(h,e,a,l)){const t=i.requestDataName(m),n=Ho({fieldDef:h,fieldDef2:e,markDef:a,config:l}),o=eo(s)&&.5!==n&&_t(r);return sc([{data:t,field:i.vgField(r,o?{suffix:Fc}:{})},{data:t,field:i.vgField(r,{suffix:o?Oc:"end"})}])}}return sc(g?[{data:z(g)?i.requestDataName(m):i.requestDataName(bc.Raw),field:i.vgField(r),sort:g}]:[{data:i.requestDataName(m),field:i.vgField(r)}])}function dm(e,t){const{op:n,field:i,order:r}=e;return{op:n??(t?"sum":Eo),...i?{field:M(i)}:{},...r?{order:r}:{}}}function mm(e,t){const n=e.component.scales[t],i=e.specifiedScales[t].domain,r=e.fieldDef(t)?.bin,o=Or(i)?i:void 0,a=gn(r)&&hn(r.extent)?r.extent:void 0;(o||a)&&n.set("selectionExtent",o??a,!0)}function pm(e,n){const{aggregate:i,type:r}=e;return i?t.isString(i)&&!fn.has(i)?{valid:!1,reason:mi(i)}:"quantitative"===r&&"log"===n?{valid:!1,reason:pi(e)}:{valid:!0}:{valid:!1,reason:di(e)}}function gm(e,t,n,i){return e.explicit&&t.explicit&&Si(function(e,t,n,i){return`Conflicting ${t.toString()} property "${e.toString()}" (${Q(n)} and ${Q(i)}). Using the union of the two domains.`}(n,i,e.value,t.value)),{explicit:e.explicit,value:[...e.value,...t.value]}}function hm(e){const n=b(e.map((e=>{if(Sn(e)){const{sort:t,...n}=e;return n}return e})),d),i=b(e.map((e=>{if(Sn(e)){const t=e.sort;return void 0===t||z(t)||("op"in t&&"count"===t.op&&delete t.field,"ascending"===t.order&&delete t.order),t}})).filter((e=>void 0!==e)),d);if(0===n.length)return;if(1===n.length){const n=e[0];if(Sn(n)&&i.length>0){let e=i[0];if(i.length>1){Si(yi);const n=i.filter((e=>t.isObject(e)&&"op"in e&&"min"!==e.op));e=!i.every((e=>t.isObject(e)&&"op"in e))||1!==n.length||n[0]}else if(t.isObject(e)&&"field"in e){const t=e.field;n.field===t&&(e=!e.order||{order:e.order})}return{...n,sort:e}}return n}const r=b(i.map((e=>z(e)||!("op"in e)||t.isString(e.op)&&t.hasOwnProperty(rn,e.op)?e:(Si(function(e){return`Dropping sort property ${Q(e)} as unioned domains only support boolean or op "count", "min", and "max".`}(e)),!0))),d);let o;1===r.length?o=r[0]:r.length>1&&(Si(yi),o=!0);const a=b(e.map((e=>Sn(e)?e.data:null)),(e=>e));if(1===a.length&&null!==a[0]){return{data:a[0],fields:n.map((e=>e.field)),...o?{sort:o}:{}}}return{fields:n,...o?{sort:o}:{}}}function ym(e){if(Sn(e)&&t.isString(e.field))return e.field;if(function(e){return!t.isArray(e)&&J(e,"fields")&&!J(e,"data")}(e)){let n;for(const i of e.fields)if(Sn(i)&&t.isString(i.field))if(n){if(n!==i.field)return Si("Detected faceted independent scales that union domain of multiple fields from different data sources. We will use the first field. The result view size may be incorrect."),n}else n=i.field;return Si("Detected faceted independent scales that union domain of the same fields from different source. We will assume that this is the same field from a different fork of the same data source. However, if this is not the case, the result view size may be incorrect."),n}if(function(e){return!t.isArray(e)&&J(e,"fields")&&J(e,"data")}(e)){Si("Detected faceted independent scales that union domain of multiple fields from the same data source. We will use the first field. The result view size may be incorrect.");const n=e.fields[0];return t.isString(n)?n:void 0}}function vm(e,t){const n=e.component.scales[t].get("domains").map((t=>(Sn(t)&&(t.data=e.lookupDataSource(t.data)),t)));return hm(n)}function bm(e){return Im(e)||Wm(e)?e.children.reduce(((e,t)=>e.concat(bm(t))),xm(e)):xm(e)}function xm(e){return D(e.component.scales).reduce(((n,i)=>{const r=e.component.scales[i];if(r.merged)return n;const o=r.combine(),{name:a,type:s,selectionExtent:l,domains:c,range:u,reverse:f,...d}=o,m=function(e,n,i,r){if(_t(i)){if(kn(e))return{step:{signal:`${n}_step`}}}else if(t.isObject(e)&&Sn(e))return{...e,data:r.lookupDataSource(e.data)};return e}(o.range,a,i,e),p=vm(e,i),g=l?function(e,n,i,r){const o=df(e,n.param,n);return{signal:Sr(i.get("type"))&&t.isArray(r)&&r[0]>r[1]?`isValid(${o}) && reverse(${o})`:o}}(e,l,r,p):null;return n.push({name:a,type:s,...p?{domain:p}:{},...g?{domainRaw:g}:{},range:m,...void 0!==f?{reverse:f}:{},...d}),n}),[])}class $m extends oc{merged=!1;constructor(e,t){super({},{name:e}),this.setWithExplicit("type",t)}domainHasZero(){const e=this.get("type");if(p([dr.LOG,dr.TIME,dr.UTC],e))return"definitely-not";const n=this.get("zero");if(!0===n||void 0===n&&p([dr.LINEAR,dr.SQRT,dr.POW],e))return"definitely";const i=this.get("domains");if(i.length>0){let e=!1,n=!1,r=!1;for(const o of i){if(t.isArray(o)){const i=o[0],r=o[o.length-1];if(t.isNumber(i)&&t.isNumber(r)){if(i<=0&&r>=0){e=!0;continue}n=!0;continue}}r=!0}if(e)return"definitely";if(n&&!r)return"definitely-not"}return"maybe"}}const wm=["range","scheme"];function km(e,n){const i=e.fieldDef(n);if(i?.bin){const{bin:r,field:o}=i,a=st(n),s=e.getName(a);if(t.isObject(r)&&r.binned&&void 0!==r.step)return new sm((()=>{const t=e.scaleName(n),i=`(domain("${t}")[1] - domain("${t}")[0]) / ${r.step}`;return`${e.getSignalName(s)} / (${i})`}));if(mn(r)){const t=xd(e,o,r);return new sm((()=>{const n=e.getSignalName(t),i=`(${n}.stop - ${n}.start) / ${n}.step`;return`${e.getSignalName(s)} / (${i})`}))}}}function Sm(e,n){const i=n.specifiedScales[e],{size:r}=n,o=n.getScaleComponent(e).get("type");for(const r of wm)if(void 0!==i[r]){const a=Er(o,r),s=Mr(e,r);if(a)if(s)Si(s);else switch(r){case"range":{const r=i.range;if(t.isArray(r)){if(_t(e))return ac(r.map((e=>{if("width"===e||"height"===e){const t=n.getName(e),i=n.getSignalName.bind(n);return sm.fromName(i,t)}return e})))}else if(t.isObject(r))return ac({data:n.requestDataName(bc.Main),field:r.field,sort:{op:"min",field:n.vgField(e)}});return ac(r)}case"scheme":return ac(Dm(i[r]))}else Si(gi(o,r,e))}const a=e===te||"xOffset"===e?"width":"height",s=r[a];if(Rs(s))if(_t(e))if(kr(o)){const t=Om(s,n,e);if(t)return ac({step:t})}else Si(hi(a));else if(jt(e)){const t=e===oe?"x":"y";if("band"===n.getScaleComponent(t).get("type")){const e=zm(s,o);if(e)return ac(e)}}const{rangeMin:l,rangeMax:u}=i,f=function(e,n){const{size:i,config:r,mark:o,encoding:a}=n,{type:s}=ka(a[e]),l=n.getScaleComponent(e),u=l.get("type"),{domain:f,domainMid:d}=n.specifiedScales[e];switch(e){case te:case ne:if(p(["point","band"],u)){const t=Cm(e,i,r.view);if(Rs(t)){return{step:Om(t,n,e)}}}return Fm(e,n,u);case oe:case ae:return function(e,t,n){const i=e===oe?"x":"y",r=t.getScaleComponent(i);if(!r)return Fm(i,t,n,{center:!0});const o=r.get("type"),a=t.scaleName(i),{markDef:s,config:l}=t;if("band"===o){const e=Cm(i,t.size,t.config.view);if(Rs(e)){const t=zm(e,n);if(t)return t}return[0,{signal:`bandwidth('${a}')`}]}{const n=t.encoding[i];if(Zo(n)&&n.timeUnit){const e=Bi(n.timeUnit,(e=>`scale('${a}', ${e})`)),i=t.config.scale.bandWithNestedOffsetPaddingInner,r=Ho({fieldDef:n,markDef:s,config:l})-.5,o=0!==r?` + ${r}`:"";if(i){return[{signal:`${wn(i)?`${i.signal}/2`+o:`${i/2+r}`} * (${e})`},{signal:`${wn(i)?`(1 - ${i.signal}/2)`+o:`${1-i/2+r}`} * (${e})`}]}return[0,{signal:e}]}return c(`Cannot use ${e} scale if ${i} scale is not discrete.`)}}(e,n,u);case xe:{const a=function(e,t){switch(e){case"bar":case"tick":return t.scale.minBandSize;case"line":case"trail":case"rule":return t.scale.minStrokeWidth;case"text":return t.scale.minFontSize;case"point":case"square":case"circle":return t.scale.minSize}throw new Error(li("size",e))}(o,r),s=function(e,n,i,r){const o={x:km(i,"x"),y:km(i,"y")};switch(e){case"bar":case"tick":{if(void 0!==r.scale.maxBandSize)return r.scale.maxBandSize;const e=Pm(n,o,r.view);return t.isNumber(e)?e-1:new sm((()=>`${e.signal} - 1`))}case"line":case"trail":case"rule":return r.scale.maxStrokeWidth;case"text":return r.scale.maxFontSize;case"point":case"square":case"circle":{if(r.scale.maxSize)return r.scale.maxSize;const e=Pm(n,o,r.view);return t.isNumber(e)?Math.pow(_m*e,2):new sm((()=>`pow(${_m} * ${e.signal}, 2)`))}}throw new Error(li("size",e))}(o,i,n,r);return Fr(u)?function(e,t,n){const i=()=>{const i=An(t),r=An(e),o=`(${i} - ${r}) / (${n} - 1)`;return`sequence(${r}, ${i} + ${o}, ${o})`};return wn(t)?new sm(i):{signal:i()}}(a,s,function(e,n,i,r){switch(e){case"quantile":return n.scale.quantileCount;case"quantize":return n.scale.quantizeCount;case"threshold":return void 0!==i&&t.isArray(i)?i.length+1:(Si(function(e){return`Domain for ${e} is required for threshold scale.`}(r)),3)}}(u,r,f,e)):[a,s]}case ce:return[0,2*Math.PI];case $e:return[0,360];case se:return[0,new sm((()=>`min(${n.getSignalName(Um(n.parent)?"child_width":"width")},${n.getSignalName(Um(n.parent)?"child_height":"height")})/2`))];case ge:return{step:1e3/r.scale.framesPerSecond};case De:return[r.scale.minStrokeWidth,r.scale.maxStrokeWidth];case Fe:return[[1,0],[4,2],[2,1],[1,1],[1,2,4,2]];case be:return"symbol";case he:case ye:case ve:return"ordinal"===u?"nominal"===s?"category":"ordinal":void 0!==d?"diverging":"rect"===o||"geoshape"===o?"heatmap":"ramp";case we:case ke:case Se:return[r.scale.minOpacity,r.scale.maxOpacity]}}(e,n);return(void 0!==l||void 0!==u)&&Er(o,"rangeMin")&&t.isArray(f)&&2===f.length?ac([l??f[0],u??f[1]]):sc(f)}function Dm(e){return function(e){return!t.isString(e)&&J(e,"name")}(e)?{scheme:e.name,...f(e,["name"])}:{scheme:e}}function Fm(e,t,n){let{center:i}=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};const r=st(e),o=t.getName(r),a=t.getSignalName.bind(t);return e===ne&&Sr(n)?i?[sm.fromName((e=>`${a(e)}/2`),o),sm.fromName((e=>`-${a(e)}/2`),o)]:[sm.fromName(a,o),0]:i?[sm.fromName((e=>`-${a(e)}/2`),o),sm.fromName((e=>`${a(e)}/2`),o)]:[0,sm.fromName(a,o)]}function Om(e,n,i){const{encoding:r}=n,o=n.getScaleComponent(i),a=ct(i),s=r[a];if("offset"===Ms({step:e,offsetIsDiscrete:oa(s)&&ar(s.type)})&&Ba(r,a)){const i=n.getScaleComponent(a);let r=`domain('${n.scaleName(a)}').length`;if("band"===i.get("type")){r=`bandspace(${r}, ${i.get("paddingInner")??i.get("padding")??0}, ${i.get("paddingOuter")??i.get("padding")??0})`}const s=o.get("paddingInner")??o.get("padding");return{signal:`${e.step} * ${r} / (1-${l=s,wn(l)?l.signal:t.stringValue(l)})`}}return e.step;var l}function zm(e,t){if("offset"===Ms({step:e,offsetIsDiscrete:kr(t)}))return{step:e.step}}function Cm(e,t,n){const i=e===te?"width":"height",r=t[i];return r||Is(n,i)}const _m=.95;function Pm(e,t,n){const i=Rs(e.width)?e.width.step:Ws(n,"width"),r=Rs(e.height)?e.height.step:Ws(n,"height");return t.x||t.y?new sm((()=>`min(${[t.x?t.x.signal:i,t.y?t.y.signal:r].join(", ")})`)):Math.min(i,r)}function Nm(e,t){qm(e)?function(e,t){const n=e.component.scales,{config:i,encoding:r,markDef:o,specifiedScales:a}=e;for(const s of D(n)){const l=a[s],c=n[s],u=e.getScaleComponent(s),f=ka(r[s]),d=l[t],m=u.get("type"),p=u.get("padding"),g=u.get("paddingInner"),h=Er(m,t),y=Mr(s,t);if(void 0!==d&&(h?y&&Si(y):Si(gi(m,t,s))),h&&void 0===y)if(void 0!==d){const e=f.timeUnit,n=f.type;switch(t){case"domainMax":case"domainMin":Di(l[t])||"temporal"===n||e?c.set(t,{signal:_a(l[t],{type:n,timeUnit:e})},!0):c.set(t,l[t],!0);break;default:c.copyKeyFromObject(t,l)}}else{const n=J(Am,t)?Am[t]({model:e,channel:s,fieldOrDatumDef:f,scaleType:m,scalePadding:p,scalePaddingInner:g,domain:l.domain,domainMin:l.domainMin,domainMax:l.domainMax,markDef:o,config:i,hasNestedOffsetScale:Va(r,s),hasSecondaryRangeChannel:!!r[at(s)]}):i.scale[t];void 0!==n&&c.set(t,n,!1)}}}(e,t):jm(e,t)}const Am={bins:e=>{let{model:t,fieldOrDatumDef:n}=e;return Zo(n)?function(e,t){const n=t.bin;if(mn(n)){const i=xd(e,t.field,n);return new sm((()=>e.getSignalName(i)))}if(pn(n)&&gn(n)&&void 0!==n.step)return{step:n.step};return}(t,n):void 0},interpolate:e=>{let{channel:t,fieldOrDatumDef:n}=e;return function(e,t){if(p([he,ye,ve],e)&&"nominal"!==t)return"hcl";return}(t,n.type)},nice:e=>{let{scaleType:n,channel:i,domain:r,domainMin:o,domainMax:a,fieldOrDatumDef:s}=e;return function(e,n,i,r,o,a){if(wa(a)?.bin||t.isArray(i)||null!=o||null!=r||p([dr.TIME,dr.UTC],e))return;return!!_t(n)||void 0}(n,i,r,o,a,s)},padding:e=>{let{channel:t,scaleType:n,fieldOrDatumDef:i,markDef:r,config:o}=e;return function(e,t,n,i,r,o){if(_t(e)){if(Dr(t)){if(void 0!==n.continuousPadding)return n.continuousPadding;const{type:t,orient:a}=r;if("bar"===t&&(!Zo(i)||!i.bin&&!i.timeUnit)&&("vertical"===a&&"x"===e||"horizontal"===a&&"y"===e))return o.continuousBandSize}if(t===dr.POINT)return n.pointPadding}return}(t,n,o.scale,i,r,o.bar)},paddingInner:e=>{let{scalePadding:t,channel:n,markDef:i,scaleType:r,config:o,hasNestedOffsetScale:a}=e;return function(e,t,n,i,r){let o=arguments.length>5&&void 0!==arguments[5]&&arguments[5];if(void 0!==e)return;if(_t(t)){const{bandPaddingInner:e,barBandPaddingInner:t,rectBandPaddingInner:i,tickBandPaddingInner:a,bandWithNestedOffsetPaddingInner:s}=r;return o?s:U(e,"bar"===n?t:"tick"===n?a:i)}if(jt(t)&&i===dr.BAND)return r.offsetBandPaddingInner;return}(t,n,i.type,r,o.scale,a)},paddingOuter:e=>{let{scalePadding:t,channel:n,scaleType:i,scalePaddingInner:r,config:o,hasNestedOffsetScale:a}=e;return function(e,t,n,i,r){let o=arguments.length>5&&void 0!==arguments[5]&&arguments[5];if(void 0!==e)return;if(_t(t)){const{bandPaddingOuter:e,bandWithNestedOffsetPaddingOuter:t}=r;if(o)return t;if(n===dr.BAND)return U(e,wn(i)?{signal:`${i.signal}/2`}:i/2)}else if(jt(t)){if(n===dr.POINT)return.5;if(n===dr.BAND)return r.offsetBandPaddingOuter}return}(t,n,i,r,o.scale,a)},reverse:e=>{let{fieldOrDatumDef:t,scaleType:n,channel:i,config:r}=e;return function(e,t,n,i){if("x"===n&&void 0!==i.xReverse)return Sr(e)&&"descending"===t?wn(i.xReverse)?{signal:`!${i.xReverse.signal}`}:!i.xReverse:i.xReverse;if(Sr(e)&&"descending"===t)return!0;return}(n,Zo(t)?t.sort:void 0,i,r.scale)},zero:e=>{let{channel:n,fieldOrDatumDef:i,domain:r,markDef:o,scaleType:a,config:s,hasSecondaryRangeChannel:l}=e;return function(e,n,i,r,o,a,s){if(i&&"unaggregated"!==i&&Sr(o)){if(t.isArray(i)){const e=i[0],n=i[i.length-1];if(t.isNumber(e)&&e<=0&&t.isNumber(n)&&n>=0)return!0}return!1}if("size"===e&&"quantitative"===n.type&&!Fr(o))return!0;if((!Zo(n)||!n.bin)&&p([...Ct,...Nt],e)){const{orient:t,type:n}=r;return(!p(["bar","area","line","trail"],n)||!("horizontal"===t&&"y"===e||"vertical"===t&&"x"===e))&&(!(!p(["bar","area"],n)||s)||a?.zero)}return!1}(n,i,r,o,a,s.scale,l)}};function Tm(e){qm(e)?function(e){const t=e.component.scales;for(const n of Xt){const i=t[n];if(!i)continue;const r=Sm(n,e);i.setWithExplicit("range",r)}}(e):jm(e,"range")}function jm(e,t){const n=e.component.scales;for(const n of e.children)"range"===t?Tm(n):Nm(n,t);for(const i of D(n)){let r;for(const n of e.children){const e=n.component.scales[i];if(e){r=uc(r,e.getWithExplicit(t),t,"scale",lc(((e,n)=>"range"===t&&e.step&&n.step?e.step-n.step:0)))}}n[i].setWithExplicit(t,r)}}function Em(e,t,n,i){const r=function(e,t,n,i){switch(t.type){case"nominal":case"ordinal":if(We(e)||"discrete"===tn(e))return"shape"===e&&"ordinal"===t.type&&Si(fi(e,"ordinal")),"ordinal";if(Mt(e))return"band";if(_t(e)||jt(e)){if(p(["rect","bar","image","rule","tick"],n.type))return"band";if(i)return"band"}else if("arc"===n.type&&e in Pt)return"band";return lo(n[st(e)])||ca(t)&&t.axis?.tickBand?"band":"point";case"temporal":return We(e)?"time":"discrete"===tn(e)?(Si(fi(e,"temporal")),"ordinal"):Zo(t)&&t.timeUnit&&Ii(t.timeUnit).utc?"utc":Mt(e)?"band":"time";case"quantitative":return We(e)?Zo(t)&&mn(t.bin)?"bin-ordinal":"linear":"discrete"===tn(e)?(Si(fi(e,"quantitative")),"ordinal"):Mt(e)?"band":"linear";case"geojson":return}throw new Error(oi(t.type))}(t,n,i,arguments.length>4&&void 0!==arguments[4]&&arguments[4]),{type:o}=e;return Qt(t)?void 0!==o?function(e,t){let n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(!Qt(e))return!1;switch(e){case te:case ne:case oe:case ae:case ce:case se:return!!Dr(t)||"band"===t||"point"===t&&!n;case ge:return p(["linear","band"],t);case xe:case De:case we:case ke:case Se:case $e:return Dr(t)||Fr(t)||p(["band","point","ordinal"],t);case he:case ye:case ve:return"band"!==t;case Fe:case be:return"ordinal"===t||Fr(t)}}(t,o)?Zo(n)&&(a=o,s=n.type,!(p([lr,ur],s)?void 0===a||kr(a):s===cr?p([dr.TIME,dr.UTC,void 0],a):s!==sr||br(a)||Fr(a)||void 0===a))?(Si(function(e,t){return`FieldDef does not work with "${e}" scale. We are using "${t}" scale instead.`}(o,r)),r):o:(Si(function(e,t,n){return`Channel "${e}" does not work with "${t}" scale. We are using "${n}" scale instead.`}(t,o,r)),r):r:null;var a,s}function Mm(e){qm(e)?e.component.scales=function(e){const{encoding:t,mark:n,markDef:i}=e,r={};for(const o of Xt){const a=ka(t[o]);if(a&&n===Kr&&o===be&&a.type===fr)continue;let s=a&&a.scale;if(a&&null!==s&&!1!==s){s??={};const n=Em(s,o,a,i,Va(t,o));r[o]=new $m(e.scaleName(`${o}`,!0),{value:n,explicit:s.type===n})}}return r}(e):e.component.scales=function(e){const t=e.component.scales={},n={},i=e.component.resolve;for(const t of e.children){Mm(t);for(const r of D(t.component.scales))if(i.scale[r]??=Yf(r,e),"shared"===i.scale[r]){const e=n[r],o=t.component.scales[r].getWithExplicit("type");e?pr(e.value,o.value)?n[r]=uc(e,o,"type","scale",Rm):(i.scale[r]="independent",delete n[r]):n[r]=o}}for(const i of D(n)){const r=e.scaleName(i,!0),o=n[i];t[i]=new $m(r,o);for(const t of e.children){const e=t.component.scales[i];e&&(t.renameScale(e.get("name"),r),e.merged=!0)}}return t}(e)}const Rm=lc(((e,t)=>hr(e)-hr(t)));class Lm{constructor(){this.nameMap={}}rename(e,t){this.nameMap[e]=t}has(e){return void 0!==this.nameMap[e]}get(e){for(;this.nameMap[e]&&e!==this.nameMap[e];)e=this.nameMap[e];return e}}function qm(e){return"unit"===e?.type}function Um(e){return"facet"===e?.type}function Wm(e){return"concat"===e?.type}function Im(e){return"layer"===e?.type}class Bm{constructor(e,n,i,r,o,a,c){this.type=n,this.parent=i,this.config=o,this.parent=i,this.config=o,this.view=bn(c),this.name=e.name??r,this.title=$n(e.title)?{text:e.title}:e.title?bn(e.title):void 0,this.scaleNameMap=i?i.scaleNameMap:new Lm,this.projectionNameMap=i?i.projectionNameMap:new Lm,this.signalNameMap=i?i.signalNameMap:new Lm,this.data=e.data,this.description=e.description,this.transforms=(e.transform??[]).map((e=>Ol(e)?{filter:s(e.filter,rr)}:e)),this.layout="layer"===n||"unit"===n?{}:function(e,n,i){const r=i[n],o={},{spacing:a,columns:s}=r;void 0!==a&&(o.spacing=a),void 0!==s&&(Io(e)&&!Uo(e.facet)||Ts(e))&&(o.columns=s),js(e)&&(o.columns=1);for(const n of qs)if(void 0!==e[n])if("spacing"===n){const i=e[n];o[n]=t.isNumber(i)?i:{row:i.row??a,column:i.column??a}}else o[n]=e[n];return o}(e,n,o),this.component={data:{sources:i?i.component.data.sources:[],outputNodes:i?i.component.data.outputNodes:{},outputNodeRefCounts:i?i.component.data.outputNodeRefCounts:{},isFaceted:Io(e)||i?.component.data.isFaceted&&void 0===e.data},layoutSize:new oc,layoutHeaders:{row:{},column:{},facet:{}},mark:null,resolve:{scale:{},axis:{},legend:{},...a?l(a):{}},selection:null,scales:null,projection:null,axes:{},legends:{}}}get width(){return this.getSizeSignalRef("width")}get height(){return this.getSizeSignalRef("height")}parse(){this.parseScale(),this.parseLayoutSize(),this.renameTopLevelLayoutSizeSignal(),this.parseSelections(),this.parseProjection(),this.parseData(),this.parseAxesAndHeaders(),this.parseLegends(),this.parseMarkGroup()}parseScale(){!function(e){let{ignoreRange:t}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};Mm(e),lm(e);for(const t of jr)Nm(e,t);t||Tm(e)}(this)}parseProjection(){yd(this)}renameTopLevelLayoutSizeSignal(){"width"!==this.getName("width")&&this.renameSignal(this.getName("width"),"width"),"height"!==this.getName("height")&&this.renameSignal(this.getName("height"),"height")}parseLegends(){sd(this)}assembleEncodeFromView(e){const{style:t,...n}=e,i={};for(const e of D(n)){const t=n[e];void 0!==t&&(i[e]=Pn(t))}return i}assembleGroupEncodeEntry(e){let t={};return this.view&&(t=this.assembleEncodeFromView(this.view)),e||(this.description&&(t.description=Pn(this.description)),"unit"!==this.type&&"layer"!==this.type)?S(t)?void 0:t:{width:this.getSizeSignalRef("width"),height:this.getSizeSignalRef("height"),...t}}assembleLayout(){if(!this.layout)return;const{spacing:e,...t}=this.layout,{component:n,config:i}=this,r=function(e,t){const n={};for(const i of Be){const r=e[i];if(r?.facetFieldDef){const{titleAnchor:e,titleOrient:o}=Cf(["titleAnchor","titleOrient"],r.facetFieldDef.header,t,i),a=Of(i,o),s=qf(e,a);void 0!==s&&(n[a]=s)}}return S(n)?void 0:n}(n.layoutHeaders,i);return{padding:e,...this.assembleDefaultLayout(),...t,...r?{titleBand:r}:{}}}assembleDefaultLayout(){return{}}assembleHeaderMarks(){const{layoutHeaders:e}=this.component;let t=[];for(const n of Be)e[n].title&&t.push(Nf(this,n));for(const e of _f)t=t.concat(jf(this,e));return t}assembleAxes(){return function(e,t){const{x:n=[],y:i=[]}=e;return[...n.map((e=>gf(e,"grid",t))),...i.map((e=>gf(e,"grid",t))),...n.map((e=>gf(e,"main",t))),...i.map((e=>gf(e,"main",t)))].filter((e=>e))}(this.component.axes,this.config)}assembleLegends(){return dd(this)}assembleProjections(){return md(this)}assembleTitle(){const{encoding:e,...t}=this.title??{},n={...xn(this.config.title).nonMarkTitleProperties,...t,...e?{encode:{update:e}}:{}};if(n.text)return p(["unit","layer"],this.type)?p(["middle",void 0],n.anchor)&&(n.frame??="group"):n.anchor??="start",S(n)?void 0:n}assembleGroup(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];const t={};e=e.concat(this.assembleSignals()),e.length>0&&(t.signals=e);const n=this.assembleLayout();n&&(t.layout=n),t.marks=[].concat(this.assembleHeaderMarks(),this.assembleMarks());const i=!this.parent||Um(this.parent)?bm(this):[];i.length>0&&(t.scales=i);const r=this.assembleAxes();r.length>0&&(t.axes=r);const o=this.assembleLegends();return o.length>0&&(t.legends=o),t}getName(e){return C((this.name?`${this.name}_`:"")+e)}getDataName(e){return this.getName(bc[e].toLowerCase())}requestDataName(e){const t=this.getDataName(e),n=this.component.data.outputNodeRefCounts;return n[t]=(n[t]||0)+1,t}getSizeSignalRef(e){if(Um(this.parent)){const t=At(Hf(e)),n=this.component.scales[t];if(n&&!n.merged){const e=n.get("type"),i=n.get("range");if(kr(e)&&kn(i)){const e=n.get("name"),i=ym(vm(this,t));if(i){return{signal:Vf(e,n,ma({aggregate:"distinct",field:i},{expr:"datum"}))}}return Si(Xn(t)),null}}}return{signal:this.signalNameMap.get(this.getName(e))}}lookupDataSource(e){const t=this.component.data.outputNodes[e];return t?t.getSource():e}getSignalName(e){return this.signalNameMap.get(e)}renameSignal(e,t){this.signalNameMap.rename(e,t)}renameScale(e,t){this.scaleNameMap.rename(e,t)}renameProjection(e,t){this.projectionNameMap.rename(e,t)}scaleName(e,t){return t?this.getName(e):tt(e)&&Qt(e)&&this.component.scales[e]||this.scaleNameMap.has(this.getName(e))?this.scaleNameMap.get(this.getName(e)):void 0}projectionName(e){return e?this.getName("projection"):this.component.projection&&!this.component.projection.merged||this.projectionNameMap.has(this.getName("projection"))?this.projectionNameMap.get(this.getName("projection")):void 0}getScaleComponent(e){if(!this.component.scales)throw new Error("getScaleComponent cannot be called before parseScale(). Make sure you have called parseScale or use parseUnitModelWithScale().");const t=this.component.scales[e];return t&&!t.merged?t:this.parent?this.parent.getScaleComponent(e):void 0}getScaleType(e){const t=this.getScaleComponent(e);return t?t.get("type"):void 0}getSelectionComponent(e,t){let n=this.component.selection[e];if(!n&&this.parent&&(n=this.parent.getSelectionComponent(e,t)),!n)throw new Error(function(e){return`Cannot find a selection named "${e}".`}(t));return n}hasAxisOrientSignalRef(){return this.component.axes.x?.some((e=>e.hasOrientSignalRef()))||this.component.axes.y?.some((e=>e.hasOrientSignalRef()))}}class Vm extends Bm{vgField(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const n=this.fieldDef(e);if(n)return ma(n,t)}reduceFieldDef(e,n){return function(e,n,i,r){return e?D(e).reduce(((i,o)=>{const a=e[o];return t.isArray(a)?a.reduce(((e,t)=>n.call(r,e,t,o)),i):n.call(r,i,a,o)}),i):i}(this.getMapping(),((t,n,i)=>{const r=wa(n);return r?e(t,r,i):t}),n)}forEachFieldDef(e,t){Qa(this.getMapping(),((t,n)=>{const i=wa(t);i&&e(i,n)}),t)}}class Hm extends $c{clone(){return new Hm(null,l(this.transform))}constructor(e,t){super(e),this.transform=t,this.transform=l(t);const n=this.transform.as??[void 0,void 0];this.transform.as=[n[0]??"value",n[1]??"density"];const i=this.transform.resolve??"shared";this.transform.resolve=i}dependentFields(){return new Set([this.transform.density,...this.transform.groupby??[]])}producedFields(){return new Set(this.transform.as)}hash(){return`DensityTransform ${d(this.transform)}`}assemble(){const{density:e,...t}=this.transform,n={type:"kde",field:e,...t};return n.resolve=this.transform.resolve,n}}class Gm extends $c{clone(){return new Gm(null,l(this.transform))}constructor(e,t){super(e),this.transform=t,this.transform=l(t)}dependentFields(){return new Set([this.transform.extent])}producedFields(){return new Set([])}hash(){return`ExtentTransform ${d(this.transform)}`}assemble(){const{extent:e,param:t}=this.transform;return{type:"extent",field:e,signal:t}}}class Ym extends $c{clone(){return new Ym(this.parent,l(this.transform))}constructor(e,t){super(e),this.transform=t,this.transform=l(t);const{flatten:n,as:i=[]}=this.transform;this.transform.as=n.map(((e,t)=>i[t]??e))}dependentFields(){return new Set(this.transform.flatten)}producedFields(){return new Set(this.transform.as)}hash(){return`FlattenTransform ${d(this.transform)}`}assemble(){const{flatten:e,as:t}=this.transform;return{type:"flatten",fields:e,as:t}}}class Xm extends $c{clone(){return new Xm(null,l(this.transform))}constructor(e,t){super(e),this.transform=t,this.transform=l(t);const n=this.transform.as??[void 0,void 0];this.transform.as=[n[0]??"key",n[1]??"value"]}dependentFields(){return new Set(this.transform.fold)}producedFields(){return new Set(this.transform.as)}hash(){return`FoldTransform ${d(this.transform)}`}assemble(){const{fold:e,as:t}=this.transform;return{type:"fold",fields:e,as:t}}}class Qm extends $c{clone(){return new Qm(null,l(this.fields),this.geojson,this.signal)}static parseAll(e,t){if(t.component.projection&&!t.component.projection.isFit)return e;let n=0;for(const i of[[de,fe],[pe,me]]){const r=i.map((e=>{const n=ka(t.encoding[e]);return Zo(n)?n.field:ta(n)?{expr:`${n.datum}`}:sa(n)?{expr:`${n.value}`}:void 0}));(r[0]||r[1])&&(e=new Qm(e,r,null,t.getName("geojson_"+n++)))}if(t.channelHasField(be)){const i=t.typedFieldDef(be);i.type===fr&&(e=new Qm(e,null,i.field,t.getName("geojson_"+n++)))}return e}constructor(e,t,n,i){super(e),this.fields=t,this.geojson=n,this.signal=i}dependentFields(){const e=(this.fields??[]).filter(t.isString);return new Set([...this.geojson?[this.geojson]:[],...e])}producedFields(){return new Set}hash(){return`GeoJSON ${this.geojson} ${this.signal} ${d(this.fields)}`}assemble(){return[...this.geojson?[{type:"filter",expr:`isValid(datum["${this.geojson}"])`}]:[],{type:"geojson",...this.fields?{fields:this.fields}:{},...this.geojson?{geojson:this.geojson}:{},signal:this.signal}]}}class Jm extends $c{clone(){return new Jm(null,this.projection,l(this.fields),l(this.as))}constructor(e,t,n,i){super(e),this.projection=t,this.fields=n,this.as=i}static parseAll(e,t){if(!t.projectionName())return e;for(const n of[[de,fe],[pe,me]]){const i=n.map((e=>{const n=ka(t.encoding[e]);return Zo(n)?n.field:ta(n)?{expr:`${n.datum}`}:sa(n)?{expr:`${n.value}`}:void 0})),r=n[0]===pe?"2":"";(i[0]||i[1])&&(e=new Jm(e,t.projectionName(),i,[t.getName(`x${r}`),t.getName(`y${r}`)]))}return e}dependentFields(){return new Set(this.fields.filter(t.isString))}producedFields(){return new Set(this.as)}hash(){return`Geopoint ${this.projection} ${d(this.fields)} ${d(this.as)}`}assemble(){return{type:"geopoint",projection:this.projection,fields:this.fields,as:this.as}}}class Km extends $c{clone(){return new Km(null,l(this.transform))}constructor(e,t){super(e),this.transform=t}dependentFields(){return new Set([this.transform.impute,this.transform.key,...this.transform.groupby??[]])}producedFields(){return new Set([this.transform.impute])}processSequence(e){const{start:t=0,stop:n,step:i}=e;return{signal:`sequence(${[t,n,...i?[i]:[]].join(",")})`}}static makeFromTransform(e,t){return new Km(e,t)}static makeFromEncoding(e,t){const n=t.encoding,i=n.x,r=n.y;if(Zo(i)&&Zo(r)){const o=i.impute?i:r.impute?r:void 0;if(void 0===o)return;const a=i.impute?r:r.impute?i:void 0,{method:s,value:l,frame:c,keyvals:u}=o.impute,f=Ja(t.mark,n);return new Km(e,{impute:o.field,key:a.field,...s?{method:s}:{},...void 0!==l?{value:l}:{},...c?{frame:c}:{},...void 0!==u?{keyvals:u}:{},...f.length?{groupby:f}:{}})}return null}hash(){return`Impute ${d(this.transform)}`}assemble(){const{impute:e,key:t,keyvals:n,method:i,groupby:r,value:o,frame:a=[null,null]}=this.transform,s={type:"impute",field:e,key:t,...n?{keyvals:(l=n,J(l,"stop")?this.processSequence(n):n)}:{},method:"value",...r?{groupby:r}:{},value:i&&"value"!==i?null:o};var l;if(i&&"value"!==i){return[s,{type:"window",as:[`imputed_${e}_value`],ops:[i],fields:[e],frame:a,ignorePeers:!1,...r?{groupby:r}:{}},{type:"formula",expr:`datum.${e} === null ? datum.imputed_${e}_value : datum.${e}`,as:e}]}return[s]}}class Zm extends $c{clone(){return new Zm(null,l(this.transform))}constructor(e,t){super(e),this.transform=t,this.transform=l(t);const n=this.transform.as??[void 0,void 0];this.transform.as=[n[0]??t.on,n[1]??t.loess]}dependentFields(){return new Set([this.transform.loess,this.transform.on,...this.transform.groupby??[]])}producedFields(){return new Set(this.transform.as)}hash(){return`LoessTransform ${d(this.transform)}`}assemble(){const{loess:e,on:t,...n}=this.transform;return{type:"loess",x:t,y:e,...n}}}class ep extends $c{clone(){return new ep(null,l(this.transform),this.secondary)}constructor(e,t,n){super(e),this.transform=t,this.secondary=n}static make(e,t,n,i){const r=t.component.data.sources,{from:o}=n;let a=null;if(function(e){return J(e,"data")}(o)){let e=gp(o.data,r);e||(e=new Ad(o.data),r.push(e));const n=t.getName(`lookup_${i}`);a=new wc(e,n,bc.Lookup,t.component.data.outputNodeRefCounts),t.component.data.outputNodes[n]=a}else if(function(e){return J(e,"param")}(o)){const e=o.param;let i;n={as:e,...n};try{i=t.getSelectionComponent(C(e),e)}catch(t){throw new Error(function(e){return`Lookups can only be performed on selection parameters. "${e}" is a variable parameter.`}(e))}if(a=i.materialized,!a)throw new Error(function(e){return`Cannot define and lookup the "${e}" selection in the same view. Try moving the lookup into a second, layered view?`}(e))}return new ep(e,n,a.getSource())}dependentFields(){return new Set([this.transform.lookup])}producedFields(){return new Set(this.transform.as?t.array(this.transform.as):this.transform.from.fields)}hash(){return`Lookup ${d({transform:this.transform,secondary:this.secondary})}`}assemble(){let e;if(this.transform.from.fields)e={values:this.transform.from.fields,...this.transform.as?{as:t.array(this.transform.as)}:{}};else{let n=this.transform.as;t.isString(n)||(Si('If "from.fields" is not specified, "as" has to be a string that specifies the key to be used for the data from the secondary source.'),n="_lookup"),e={as:[n]}}return{type:"lookup",from:this.secondary,key:this.transform.from.key,fields:[this.transform.lookup],...e,...this.transform.default?{default:this.transform.default}:{}}}}class tp extends $c{clone(){return new tp(null,l(this.transform))}constructor(e,t){super(e),this.transform=t,this.transform=l(t);const n=this.transform.as??[void 0,void 0];this.transform.as=[n[0]??"prob",n[1]??"value"]}dependentFields(){return new Set([this.transform.quantile,...this.transform.groupby??[]])}producedFields(){return new Set(this.transform.as)}hash(){return`QuantileTransform ${d(this.transform)}`}assemble(){const{quantile:e,...t}=this.transform;return{type:"quantile",field:e,...t}}}class np extends $c{clone(){return new np(null,l(this.transform))}constructor(e,t){super(e),this.transform=t,this.transform=l(t);const n=this.transform.as??[void 0,void 0];this.transform.as=[n[0]??t.on,n[1]??t.regression]}dependentFields(){return new Set([this.transform.regression,this.transform.on,...this.transform.groupby??[]])}producedFields(){return new Set(this.transform.as)}hash(){return`RegressionTransform ${d(this.transform)}`}assemble(){const{regression:e,on:t,...n}=this.transform;return{type:"regression",x:t,y:e,...n}}}class ip extends $c{clone(){return new ip(null,l(this.transform))}constructor(e,t){super(e),this.transform=t}addDimensions(e){this.transform.groupby=b((this.transform.groupby??[]).concat(e),(e=>e))}producedFields(){}dependentFields(){return new Set([this.transform.pivot,this.transform.value,...this.transform.groupby??[]])}hash(){return`PivotTransform ${d(this.transform)}`}assemble(){const{pivot:e,value:t,groupby:n,limit:i,op:r}=this.transform;return{type:"pivot",field:e,value:t,...void 0!==i?{limit:i}:{},...void 0!==r?{op:r}:{},...void 0!==n?{groupby:n}:{}}}}class rp extends $c{clone(){return new rp(null,l(this.transform))}constructor(e,t){super(e),this.transform=t}dependentFields(){return new Set}producedFields(){return new Set}hash(){return`SampleTransform ${d(this.transform)}`}assemble(){return{type:"sample",size:this.transform.sample}}}function op(e){let t=0;return function n(i,r){if(i instanceof Ad&&!i.isGenerator&&!dc(i.data)){e.push(r);r={name:null,source:r.name,transform:[]}}if(i instanceof Cd&&(i.parent instanceof Ad&&!r.source?(r.format={...r.format,parse:i.assembleFormatParse()},r.transform.push(...i.assembleTransforms(!0))):r.transform.push(...i.assembleTransforms())),i instanceof Dd)return r.name||(r.name="data_"+t++),!r.source||r.transform.length>0?(e.push(r),i.data=r.name):i.data=r.source,void e.push(...i.assemble());if((i instanceof Pd||i instanceof Nd||i instanceof Qd||i instanceof uf||i instanceof Df||i instanceof Jm||i instanceof Sd||i instanceof ep||i instanceof Zd||i instanceof Xd||i instanceof Xm||i instanceof Ym||i instanceof Hm||i instanceof Zm||i instanceof tp||i instanceof np||i instanceof _d||i instanceof rp||i instanceof ip||i instanceof Gm)&&r.transform.push(i.assemble()),(i instanceof wd||i instanceof Dc||i instanceof Km||i instanceof Kd||i instanceof Qm)&&r.transform.push(...i.assemble()),i instanceof wc)if(r.source&&0===r.transform.length)i.setSource(r.source);else if(i.parent instanceof wc)i.setSource(r.name);else if(r.name||(r.name="data_"+t++),i.setSource(r.name),1===i.numChildren()){e.push(r);r={name:null,source:r.name,transform:[]}}switch(i.numChildren()){case 0:i instanceof wc&&(!r.source||r.transform.length>0)&&e.push(r);break;case 1:n(i.children[0],r);break;default:{r.name||(r.name="data_"+t++);let o=r.name;!r.source||r.transform.length>0?e.push(r):o=r.source;for(const e of i.children){n(e,{name:null,source:o,transform:[]})}break}}}}function ap(e){return"top"===e||"left"===e||wn(e)?"header":"footer"}function sp(e,n){const{facet:i,config:r,child:o,component:a}=e;if(e.channelHasField(n)){const s=i[n],l=zf("title",null,r,n);let c=va(s,r,{allowDisabling:!0,includeDefault:void 0===l||!!l});o.component.layoutHeaders[n].title&&(c=t.isArray(c)?c.join(", "):c,c+=` / ${o.component.layoutHeaders[n].title}`,o.component.layoutHeaders[n].title=null);const u=zf("labelOrient",s.header,r,n),f=null!==s.header&&U(s.header?.labels,r.header.labels,!0),d=p(["bottom","right"],u)?"footer":"header";a.layoutHeaders[n]={title:null!==s.header?c:null,facetFieldDef:s,[d]:"facet"===n?[]:[lp(e,n,f)]}}}function lp(e,t,n){const i="row"===t?"height":"width";return{labels:n,sizeSignal:e.child.component.layoutSize.get(i)?e.child.getSizeSignalRef(i):void 0,axes:[]}}function cp(e,t){const{child:n}=e;if(n.component.axes[t]){const{layoutHeaders:i,resolve:r}=e.component;if(r.axis[t]=Xf(r,t),"shared"===r.axis[t]){const r="x"===t?"column":"row",o=i[r];for(const i of n.component.axes[t]){const t=ap(i.get("orient"));o[t]??=[lp(e,r,!1)];const n=gf(i,"main",e.config,{header:!0});n&&o[t][0].axes.push(n),i.mainExtracted=!0}}}}function up(e){for(const t of e.children)t.parseLayoutSize()}function fp(e,t){const n=Hf(t),i=At(n),r=e.component.resolve,o=e.component.layoutSize;let a;for(const t of e.children){const o=t.component.layoutSize.getWithExplicit(n),s=r.scale[i]??Yf(i,e);if("independent"===s&&"step"===o.value){a=void 0;break}if(a){if("independent"===s&&a.value!==o.value){a=void 0;break}a=uc(a,o,n,"")}else a=o}if(a){for(const i of e.children)e.renameSignal(i.getName(n),e.getName(t)),i.component.layoutSize.set(n,"merged",!1);o.setWithExplicit(t,a)}else o.setWithExplicit(t,{explicit:!1,value:void 0})}function dp(e,t){const n="width"===t?"x":"y",i=e.config,r=e.getScaleComponent(n);if(r){const e=r.get("type"),n=r.get("range");if(kr(e)){const e=Is(i.view,t);return kn(n)||Rs(e)?"step":e}return Us(i.view,t)}if(e.hasProjection||"arc"===e.mark)return Us(i.view,t);{const e=Is(i.view,t);return Rs(e)?e.step:e}}function mp(e,t,n){return ma(t,{suffix:`by_${ma(e)}`,...n})}class pp extends Vm{constructor(e,t,n,i){super(e,"facet",t,n,i,e.resolve),this.child=Up(e.spec,this,this.getName("child"),void 0,i),this.children=[this.child],this.facet=this.initFacet(e.facet)}initFacet(e){if(!Uo(e))return{facet:this.initFacetFieldDef(e,"facet")};const t=D(e),n={};for(const i of t){if(![K,Z].includes(i)){Si(li(i,"facet"));break}const t=e[i];if(void 0===t.field){Si(si(t,i));break}n[i]=this.initFacetFieldDef(t,i)}return n}initFacetFieldDef(e,t){const n=Fa(e,t);return n.header?n.header=bn(n.header):null===n.header&&(n.header=null),n}channelHasField(e){return J(this.facet,e)}fieldDef(e){return this.facet[e]}parseData(){this.component.data=hp(this),this.child.parseData()}parseLayoutSize(){up(this)}parseSelections(){this.child.parseSelections(),this.component.selection=this.child.component.selection,Object.values(this.component.selection).some((e=>af(e)))&&ki(ti)}parseMarkGroup(){this.child.parseMarkGroup()}parseAxesAndHeaders(){this.child.parseAxesAndHeaders(),function(e){for(const t of Be)sp(e,t);cp(e,"x"),cp(e,"y")}(this)}assembleSelectionTopLevelSignals(e){return this.child.assembleSelectionTopLevelSignals(e)}assembleSignals(){return this.child.assembleSignals(),[]}assembleSelectionData(e){return this.child.assembleSelectionData(e)}getHeaderLayoutMixins(){const e={};for(const t of Be)for(const n of Pf){const i=this.component.layoutHeaders[t],r=i[n],{facetFieldDef:o}=i;if(o){const n=zf("titleOrient",o.header,this.config,t);if(["right","bottom"].includes(n)){const i=Of(t,n);e.titleAnchor??={},e.titleAnchor[i]="end"}}if(r?.[0]){const r="row"===t?"height":"width",o="header"===n?"headerBand":"footerBand";"facet"===t||this.child.component.layoutSize.get(r)||(e[o]??={},e[o][t]=.5),i.title&&(e.offset??={},e.offset["row"===t?"rowTitle":"columnTitle"]=10)}}return e}assembleDefaultLayout(){const{column:e,row:t}=this.facet,n=e?this.columnDistinctSignal():t?1:void 0;let i="all";return(t||"independent"!==this.component.resolve.scale.x)&&(e||"independent"!==this.component.resolve.scale.y)||(i="none"),{...this.getHeaderLayoutMixins(),...n?{columns:n}:{},bounds:"full",align:i}}assembleLayoutSignals(){return this.child.assembleLayoutSignals()}columnDistinctSignal(){if(!(this.parent&&this.parent instanceof pp)){return{signal:`length(data('${this.getName("column_domain")}'))`}}}assembleGroupStyle(){}assembleGroup(e){return this.parent&&this.parent instanceof pp?{...this.channelHasField("column")?{encode:{update:{columns:{field:ma(this.facet.column,{prefix:"distinct"})}}}}:{},...super.assembleGroup(e)}:super.assembleGroup(e)}getCardinalityAggregateForChild(){const e=[],t=[],n=[];if(this.child instanceof pp){if(this.child.channelHasField("column")){const i=ma(this.child.facet.column);e.push(i),t.push("distinct"),n.push(`distinct_${i}`)}}else for(const i of Ct){const r=this.child.component.scales[i];if(r&&!r.merged){const o=r.get("type"),a=r.get("range");if(kr(o)&&kn(a)){const r=ym(vm(this.child,i));r?(e.push(r),t.push("distinct"),n.push(`distinct_${r}`)):Si(Xn(i))}}}return{fields:e,ops:t,as:n}}assembleFacet(){const{name:e,data:n}=this.component.data.facetRoot,{row:i,column:r}=this.facet,{fields:o,ops:a,as:s}=this.getCardinalityAggregateForChild(),l=[];for(const e of Be){const n=this.facet[e];if(n){l.push(ma(n));const{bin:c,sort:u}=n;if(mn(c)&&l.push(ma(n,{binSuffix:"end"})),Lo(u)){const{field:e,op:t=Eo}=u,l=mp(n,u);i&&r?(o.push(l),a.push("max"),s.push(l)):(o.push(e),a.push(t),s.push(l))}else if(t.isArray(u)){const t=Ff(n,e);o.push(t),a.push("max"),s.push(t)}}}const c=!!i&&!!r;return{name:e,data:n,groupby:l,...c||o.length>0?{aggregate:{...c?{cross:c}:{},...o.length?{fields:o,ops:a,as:s}:{}}}:{}}}facetSortFields(e){const{facet:n}=this,i=n[e];return i?Lo(i.sort)?[mp(i,i.sort,{expr:"datum"})]:t.isArray(i.sort)?[Ff(i,e,{expr:"datum"})]:[ma(i,{expr:"datum"})]:[]}facetSortOrder(e){const{facet:n}=this,i=n[e];if(i){const{sort:e}=i;return[(Lo(e)?e.order:!t.isArray(e)&&e)||"ascending"]}return[]}assembleLabelTitle(){const{facet:e,config:t}=this;if(e.facet)return Mf(e.facet,"facet",t);const n={row:["top","bottom"],column:["left","right"]};for(const i of _f)if(e[i]){const r=zf("labelOrient",e[i]?.header,t,i);if(n[i].includes(r))return Mf(e[i],i,t)}}assembleMarks(){const{child:e}=this,t=function(e){const t=[],n=op(t);for(const t of e.children)n(t,{source:e.name,name:null,transform:[]});return t}(this.component.data.facetRoot),n=e.assembleGroupEncodeEntry(!1),i=this.assembleLabelTitle()||e.assembleTitle(),r=e.assembleGroupStyle();return[{name:this.getName("cell"),type:"group",...i?{title:i}:{},...r?{style:r}:{},from:{facet:this.assembleFacet()},sort:{field:Be.map((e=>this.facetSortFields(e))).flat(),order:Be.map((e=>this.facetSortOrder(e))).flat()},...t.length>0?{data:t}:{},...n?{encode:{update:n}}:{},...e.assembleGroup(Gc(this,[]))}]}getMapping(){return this.facet}}function gp(e,t){for(const n of t){const t=n.data;if(e.name&&n.hasName()&&e.name!==n.dataName)continue;const i=e.format?.mesh,r=t.format?.feature;if(i&&r)continue;const o=e.format?.feature;if((o||r)&&o!==r)continue;const a=t.format?.mesh;if(!i&&!a||i===a)if(mc(e)&&mc(t)){if(X(e.values,t.values))return n}else if(dc(e)&&dc(t)){if(e.url===t.url)return n}else if(pc(e)&&e.name===n.dataName)return n}return null}function hp(e){let t=function(e,t){if(e.data||!e.parent){if(null===e.data){const e=new Ad({values:[]});return t.push(e),e}const n=gp(e.data,t);if(n)return gc(e.data)||(n.data.format=y({},e.data.format,n.data.format)),!n.hasName()&&e.data.name&&(n.dataName=e.data.name),n;{const n=new Ad(e.data);return t.push(n),n}}return e.parent.component.data.facetRoot?e.parent.component.data.facetRoot:e.parent.component.data.main}(e,e.component.data.sources);const{outputNodes:n,outputNodeRefCounts:i}=e.component.data,r=e.data,o=!(r&&(gc(r)||dc(r)||mc(r)))&&e.parent?e.parent.component.data.ancestorParse.clone():new fc;gc(r)?(hc(r)?t=new Nd(t,r.sequence):vc(r)&&(t=new Pd(t,r.graticule)),o.parseNothing=!0):null===r?.format?.parse&&(o.parseNothing=!0),t=Cd.makeExplicit(t,e,o)??t,t=new _d(t);const a=e.parent&&Im(e.parent);(qm(e)||Um(e))&&a&&(t=wd.makeFromEncoding(t,e)??t),e.transforms.length>0&&(t=function(e,t,n){let i=0;for(const r of t.transforms){let o,a;if(Rl(r))a=e=new Df(e,r),o="derived";else if(Ol(r)){const i=Od(r);a=e=Cd.makeWithAncestors(e,{},i,n)??e,e=new uf(e,t,r.filter)}else if(Ll(r))a=e=wd.makeFromTransform(e,r,t),o="number";else if(Ul(r))o="date",void 0===n.getWithExplicit(r.field).value&&(e=new Cd(e,{[r.field]:o}),n.set(r.field,o,!1)),a=e=Dc.makeFromTransform(e,r);else if(Wl(r))a=e=Sd.makeFromTransform(e,r),o="number",rf(t)&&(e=new _d(e));else if(zl(r))a=e=ep.make(e,t,r,i++),o="derived";else if(jl(r))a=e=new Zd(e,r),o="number";else if(El(r))a=e=new Xd(e,r),o="number";else if(Il(r))a=e=Kd.makeFromTransform(e,r),o="derived";else if(Bl(r))a=e=new Xm(e,r),o="derived";else if(Vl(r))a=e=new Gm(e,r),o="derived";else if(Ml(r))a=e=new Ym(e,r),o="derived";else if(Cl(r))a=e=new ip(e,r),o="derived";else if(Tl(r))e=new rp(e,r);else if(ql(r))a=e=Km.makeFromTransform(e,r),o="derived";else if(_l(r))a=e=new Hm(e,r),o="derived";else if(Pl(r))a=e=new tp(e,r),o="derived";else if(Nl(r))a=e=new np(e,r),o="derived";else{if(!Al(r)){Si(`Ignoring an invalid transform: ${Q(r)}.`);continue}a=e=new Zm(e,r),o="derived"}if(a&&void 0!==o)for(const e of a.producedFields()??[])n.set(e,o,!1)}return e}(t,e,o));const s=function(e){const t={};if(qm(e)&&e.component.selection)for(const n of D(e.component.selection)){const i=e.component.selection[n];for(const e of i.project.items)!e.channel&&q(e.field)>1&&(t[e.field]="flatten")}return t}(e),l=zd(e);t=Cd.makeWithAncestors(t,{},{...s,...l},o)??t,qm(e)&&(t=Qm.parseAll(t,e),t=Jm.parseAll(t,e)),(qm(e)||Um(e))&&(a||(t=wd.makeFromEncoding(t,e)??t),t=Dc.makeFromEncoding(t,e)??t,t=Df.parseAllForSortIndex(t,e));const c=t=yp(bc.Raw,e,t);if(qm(e)){const n=Sd.makeFromEncoding(t,e);n&&(t=n,rf(e)&&(t=new _d(t))),t=Km.makeFromEncoding(t,e)??t,t=Kd.makeFromEncoding(t,e)??t}let u,f;if(qm(e)){const{markDef:n,mark:i,config:r}=e,o=En("invalid",n,r),{marks:a,scales:s}=f=xc({invalid:o,isPath:Zr(i)});a!==s&&"include-invalid-values"===s&&(u=t=yp(bc.PreFilterInvalid,e,t)),"exclude-invalid-values"===a&&(t=Qd.make(t,e,f)??t)}const d=t=yp(bc.Main,e,t);let m;if(qm(e)&&f){const{marks:n,scales:i}=f;"include-invalid-values"===n&&"exclude-invalid-values"===i&&(t=Qd.make(t,e,f)??t,m=t=yp(bc.PostFilterInvalid,e,t))}qm(e)&&function(e,t){for(const[n,i]of O(e.component.selection??{})){const r=e.getName(`lookup_${n}`);e.component.data.outputNodes[r]=i.materialized=new wc(new uf(t,e,{param:n}),r,bc.Lookup,e.component.data.outputNodeRefCounts)}}(e,d);let p=null;if(Um(e)){const i=e.getName("facet");t=function(e,t){const{row:n,column:i}=t;if(n&&i){let t=null;for(const r of[n,i])if(Lo(r.sort)){const{field:n,op:i=Eo}=r.sort;e=t=new Xd(e,{joinaggregate:[{op:i,field:n,as:mp(r,r.sort,{forAs:!0})}],groupby:[ma(r)]})}return t}return null}(t,e.facet)??t,p=new Dd(t,e,i,d.getSource()),n[i]=p}return{...e.component.data,outputNodes:n,outputNodeRefCounts:i,raw:c,main:d,facetRoot:p,ancestorParse:o,preFilterInvalid:u,postFilterInvalid:m}}function yp(e,t,n){const{outputNodes:i,outputNodeRefCounts:r}=t.component.data,o=t.getDataName(e),a=new wc(n,o,e,r);return i[o]=a,a}class vp extends Bm{constructor(e,t,n,i){super(e,"concat",t,n,i,e.resolve),"shared"!==e.resolve?.axis?.x&&"shared"!==e.resolve?.axis?.y||Si("Axes cannot be shared in concatenated or repeated views yet (https://github.com/vega/vega-lite/issues/2415)."),this.children=this.getChildren(e).map(((e,t)=>Up(e,this,this.getName(`concat_${t}`),void 0,i)))}parseData(){this.component.data=hp(this);for(const e of this.children)e.parseData()}parseSelections(){this.component.selection={};for(const e of this.children){e.parseSelections();for(const t of D(e.component.selection))this.component.selection[t]=e.component.selection[t]}Object.values(this.component.selection).some((e=>af(e)))&&ki(ti)}parseMarkGroup(){for(const e of this.children)e.parseMarkGroup()}parseAxesAndHeaders(){for(const e of this.children)e.parseAxesAndHeaders()}getChildren(e){return js(e)?e.vconcat:Es(e)?e.hconcat:e.concat}parseLayoutSize(){!function(e){up(e);const t=1===e.layout.columns?"width":"childWidth",n=void 0===e.layout.columns?"height":"childHeight";fp(e,t),fp(e,n)}(this)}parseAxisGroup(){return null}assembleSelectionTopLevelSignals(e){return this.children.reduce(((e,t)=>t.assembleSelectionTopLevelSignals(e)),e)}assembleSignals(){return this.children.forEach((e=>e.assembleSignals())),[]}assembleLayoutSignals(){const e=Wf(this);for(const t of this.children)e.push(...t.assembleLayoutSignals());return e}assembleSelectionData(e){return this.children.reduce(((e,t)=>t.assembleSelectionData(e)),e)}assembleMarks(){return this.children.map((e=>{const t=e.assembleTitle(),n=e.assembleGroupStyle(),i=e.assembleGroupEncodeEntry(!1);return{type:"group",name:e.getName("group"),...t?{title:t}:{},...n?{style:n}:{},...i?{encode:{update:i}}:{},...e.assembleGroup()}}))}assembleGroupStyle(){}assembleDefaultLayout(){const e=this.layout.columns;return{...null!=e?{columns:e}:{},bounds:"full",align:"each"}}}const bp={disable:1,gridScale:1,scale:1,...Ma,labelExpr:1,encode:1},xp=D(bp);class $p extends oc{constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];super(),this.explicit=e,this.implicit=t,this.mainExtracted=n}clone(){return new $p(l(this.explicit),l(this.implicit),this.mainExtracted)}hasAxisPart(e){return"axis"===e||("grid"===e||"title"===e?!!this.get(e):!(!1===(t=this.get(e))||null===t));var t}hasOrientSignalRef(){return wn(this.explicit.orient)}}const wp={bottom:"top",top:"bottom",left:"right",right:"left"};function kp(e,t){if(!e)return t.map((e=>e.clone()));{if(e.length!==t.length)return;const n=e.length;for(let i=0;i{switch(n){case"title":return In(e,t);case"gridScale":return{explicit:e.explicit,value:U(e.value,t.value)}}return cc(e,t,n,"axis")}));e.setWithExplicit(n,i)}return e}function Dp(e,t,n,i,r){if("disable"===t)return void 0!==n;switch(n=n||{},t){case"titleAngle":case"labelAngle":return e===(wn(n.labelAngle)?n.labelAngle:H(n.labelAngle));case"values":return!!n.values;case"encode":return!!n.encoding||!!n.labelAngle;case"title":if(e===Sf(i,r))return!0}return e===n[t]}const Fp=new Set(["grid","translate","format","formatType","orient","labelExpr","tickCount","position","tickMinStep"]);function Op(e,t){let n=t.axis(e);const i=new $p,r=ka(t.encoding[e]),{mark:o,config:a}=t,s=n?.orient||a["x"===e?"axisX":"axisY"]?.orient||a.axis?.orient||function(e){return"x"===e?"bottom":"left"}(e),l=t.getScaleComponent(e).get("type"),c=function(e,t,n,i){const r="band"===t?["axisDiscrete","axisBand"]:"point"===t?["axisDiscrete","axisPoint"]:br(t)?["axisQuantitative"]:"time"===t||"utc"===t?["axisTemporal"]:[],o="x"===e?"axisX":"axisY",a=wn(n)?"axisOrient":`axis${N(n)}`,s=[...r,...r.map((e=>o+e.substr(4)))],l=["axis",a,o];return{vlOnlyAxisConfig:yf(s,i,e,n),vgAxisConfig:yf(l,i,e,n),axisConfigStyle:vf([...l,...s],i)}}(e,l,s,t.config),u=void 0!==n?!n:bf("disable",a.style,n?.style,c).configValue;if(i.set("disable",u,void 0!==n),u)return i;n=n||{};const f=function(e,t,n,i,r){const o=t?.labelAngle;if(void 0!==o)return wn(o)?o:H(o);{const{configValue:o}=bf("labelAngle",i,t?.style,r);return void 0!==o?H(o):n!==te||!p([ur,lr],e.type)||Zo(e)&&e.timeUnit?void 0:270}}(r,n,e,a.style,c),d=Po(n.formatType,r,l),m=_o(r,r.type,n.format,n.formatType,a,!0),g={fieldOrDatumDef:r,axis:n,channel:e,model:t,scaleType:l,orient:s,labelAngle:f,format:m,formatType:d,mark:o,config:a};for(const r of xp){const o=r in xf?xf[r](g):La(r)?n[r]:void 0,s=void 0!==o,l=Dp(o,r,n,t,e);if(s&&l)i.set(r,o,l);else{const{configValue:e,configFrom:t}=La(r)&&"values"!==r?bf(r,a.style,n.style,c):{},u=void 0!==e;s&&!u?i.set(r,o,l):("vgAxisConfig"!==t||Fp.has(r)&&u||Ta(e)||wn(e))&&i.set(r,e,!1)}}const h=n.encoding??{},y=ja.reduce(((n,r)=>{if(!i.hasAxisPart(r))return n;const o=Gf(h[r]??{},t),a="labels"===r?function(e,t,n){const{encoding:i,config:r}=e,o=ka(i[t])??ka(i[at(t)]),a=e.axis(t)||{},{format:s,formatType:l}=a;if(So(l))return{text:Co({fieldOrDatumDef:o,field:"datum.value",format:s,formatType:l,config:r}),...n};if(void 0===s&&void 0===l&&r.customFormatTypes){if("quantitative"===ea(o)){if(ca(o)&&"normalize"===o.stack&&r.normalizedNumberFormatType)return{text:Co({fieldOrDatumDef:o,field:"datum.value",format:r.normalizedNumberFormat,formatType:r.normalizedNumberFormatType,config:r}),...n};if(r.numberFormatType)return{text:Co({fieldOrDatumDef:o,field:"datum.value",format:r.numberFormat,formatType:r.numberFormatType,config:r}),...n}}if("temporal"===ea(o)&&r.timeFormatType&&Zo(o)&&!o.timeUnit)return{text:Co({fieldOrDatumDef:o,field:"datum.value",format:r.timeFormat,formatType:r.timeFormatType,config:r}),...n}}return n}(t,e,o):o;return void 0===a||S(a)||(n[r]={update:a}),n}),{});return S(y)||i.set("encode",y,!!n.encoding||void 0!==n.labelAngle),i}function zp(e,t){const{config:n}=e;return{...Pu(e,{align:"ignore",baseline:"ignore",color:"include",size:"include",orient:"ignore",theta:"ignore"}),...yu("x",e,{defaultPos:"mid"}),...yu("y",e,{defaultPos:"mid"}),...mu("size",e),...mu("angle",e),...Cp(e,n,t)}}function Cp(e,t,n){return n?{shape:{value:n}}:mu("shape",e)}const _p={vgMark:"rule",encodeEntry:e=>{const{markDef:t}=e,n=t.orient;return e.encoding.x||e.encoding.y||e.encoding.latitude||e.encoding.longitude?{...Pu(e,{align:"ignore",baseline:"ignore",color:"include",orient:"ignore",size:"ignore",theta:"ignore"}),...ku("x",e,{defaultPos:"horizontal"===n?"zeroOrMax":"mid",defaultPos2:"zeroOrMin",range:"vertical"!==n}),...ku("y",e,{defaultPos:"vertical"===n?"zeroOrMax":"mid",defaultPos2:"zeroOrMin",range:"horizontal"!==n}),...mu("size",e,{vgChannel:"strokeWidth"})}:{}}};function Pp(e,t,n){if(void 0===En("align",e,n))return"center"}function Np(e,t,n){if(void 0===En("baseline",e,n))return"middle"}const Ap={vgMark:"rect",encodeEntry:e=>{const{config:t,markDef:n}=e,i=n.orient,r="horizontal"===i?"x":"y",o="horizontal"===i?"y":"x",a="horizontal"===i?"height":"width";return{...Pu(e,{align:"ignore",baseline:"ignore",color:"include",orient:"ignore",size:"ignore",theta:"ignore"}),...Fu(e,r),...yu(o,e,{defaultPos:"mid",vgChannel:"y"===o?"yc":"xc"}),[a]:Pn(En("thickness",n,t))}}},Tp={arc:{vgMark:"arc",encodeEntry:e=>({...Pu(e,{align:"ignore",baseline:"ignore",color:"include",size:"ignore",orient:"ignore",theta:"ignore"}),...yu("x",e,{defaultPos:"mid"}),...yu("y",e,{defaultPos:"mid"}),...Fu(e,"radius"),...Fu(e,"theta")})},area:{vgMark:"area",encodeEntry:e=>({...Pu(e,{align:"ignore",baseline:"ignore",color:"include",orient:"include",size:"ignore",theta:"ignore"}),...ku("x",e,{defaultPos:"zeroOrMin",defaultPos2:"zeroOrMin",range:"horizontal"===e.markDef.orient}),...ku("y",e,{defaultPos:"zeroOrMin",defaultPos2:"zeroOrMin",range:"vertical"===e.markDef.orient}),...Tu(e)})},bar:{vgMark:"rect",encodeEntry:e=>({...Pu(e,{align:"ignore",baseline:"ignore",color:"include",orient:"ignore",size:"ignore",theta:"ignore"}),...Fu(e,"x"),...Fu(e,"y")})},circle:{vgMark:"symbol",encodeEntry:e=>zp(e,"circle")},geoshape:{vgMark:"shape",encodeEntry:e=>({...Pu(e,{align:"ignore",baseline:"ignore",color:"include",size:"ignore",orient:"ignore",theta:"ignore"})}),postEncodingTransform:e=>{const{encoding:t}=e,n=t.shape;return[{type:"geoshape",projection:e.projectionName(),...n&&Zo(n)&&n.type===fr?{field:ma(n,{expr:"datum"})}:{}}]}},image:{vgMark:"image",encodeEntry:e=>({...Pu(e,{align:"ignore",baseline:"ignore",color:"ignore",orient:"ignore",size:"ignore",theta:"ignore"}),...Fu(e,"x"),...Fu(e,"y"),...ou(e,"url")})},line:{vgMark:"line",encodeEntry:e=>({...Pu(e,{align:"ignore",baseline:"ignore",color:"include",size:"ignore",orient:"ignore",theta:"ignore"}),...yu("x",e,{defaultPos:"mid"}),...yu("y",e,{defaultPos:"mid"}),...mu("size",e,{vgChannel:"strokeWidth"}),...Tu(e)})},point:{vgMark:"symbol",encodeEntry:e=>zp(e)},rect:{vgMark:"rect",encodeEntry:e=>({...Pu(e,{align:"ignore",baseline:"ignore",color:"include",orient:"ignore",size:"ignore",theta:"ignore"}),...Fu(e,"x"),...Fu(e,"y")})},rule:_p,square:{vgMark:"symbol",encodeEntry:e=>zp(e,"square")},text:{vgMark:"text",encodeEntry:e=>{const{config:t,encoding:n}=e;return{...Pu(e,{align:"include",baseline:"include",color:"include",size:"ignore",orient:"ignore",theta:"include"}),...yu("x",e,{defaultPos:"mid"}),...yu("y",e,{defaultPos:"mid"}),...ou(e),...mu("size",e,{vgChannel:"fontSize"}),...mu("angle",e),...ju("align",Pp(e.markDef,n,t)),...ju("baseline",Np(e.markDef,n,t)),...yu("radius",e,{defaultPos:null}),...yu("theta",e,{defaultPos:null})}}},tick:Ap,trail:{vgMark:"trail",encodeEntry:e=>({...Pu(e,{align:"ignore",baseline:"ignore",color:"include",size:"include",orient:"ignore",theta:"ignore"}),...yu("x",e,{defaultPos:"mid"}),...yu("y",e,{defaultPos:"mid"}),...mu("size",e),...Tu(e)})}};function jp(e){if(p([Ir,qr,Xr],e.mark)){const t=Ja(e.mark,e.encoding);if(t.length>0)return function(e,t){return[{name:e.getName("pathgroup"),type:"group",from:{facet:{name:Ep+e.requestDataName(bc.Main),data:e.requestDataName(bc.Main),groupby:t}},encode:{update:{width:{field:{group:"width"}},height:{field:{group:"height"}}}},marks:Rp(e,{fromPrefix:Ep})}]}(e,t)}else if(e.mark===Ur){const t=On.some((t=>En(t,e.markDef,e.config)));if(e.stack&&!e.fieldDef("size")&&t)return function(e){const[t]=Rp(e,{fromPrefix:Mp}),n=e.scaleName(e.stack.fieldChannel),i=function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return e.vgField(e.stack.fieldChannel,t)},r=(e,t)=>`${e}(${[i({prefix:"min",suffix:"start",expr:t}),i({prefix:"max",suffix:"start",expr:t}),i({prefix:"min",suffix:"end",expr:t}),i({prefix:"max",suffix:"end",expr:t})].map((e=>`scale('${n}',${e})`)).join(",")})`;let o,a;"x"===e.stack.fieldChannel?(o={...u(t.encode.update,["y","yc","y2","height",...On]),x:{signal:r("min","datum")},x2:{signal:r("max","datum")},clip:{value:!0}},a={x:{field:{group:"x"},mult:-1},height:{field:{group:"height"}}},t.encode.update={...f(t.encode.update,["y","yc","y2"]),height:{field:{group:"height"}}}):(o={...u(t.encode.update,["x","xc","x2","width"]),y:{signal:r("min","datum")},y2:{signal:r("max","datum")},clip:{value:!0}},a={y:{field:{group:"y"},mult:-1},width:{field:{group:"width"}}},t.encode.update={...f(t.encode.update,["x","xc","x2"]),width:{field:{group:"width"}}});for(const n of On){const i=Mn(n,e.markDef,e.config);t.encode.update[n]?(o[n]=t.encode.update[n],delete t.encode.update[n]):i&&(o[n]=Pn(i)),i&&(t.encode.update[n]={value:0})}const s=[];if(e.stack.groupbyChannels?.length>0)for(const t of e.stack.groupbyChannels){const n=e.fieldDef(t),i=ma(n);i&&s.push(i),(n?.bin||n?.timeUnit)&&s.push(ma(n,{binSuffix:"end"}))}o=["stroke","strokeWidth","strokeJoin","strokeCap","strokeDash","strokeDashOffset","strokeMiterLimit","strokeOpacity"].reduce(((n,i)=>{if(t.encode.update[i])return{...n,[i]:t.encode.update[i]};{const t=Mn(i,e.markDef,e.config);return void 0!==t?{...n,[i]:Pn(t)}:n}}),o),o.stroke&&(o.strokeForeground={value:!0},o.strokeOffset={value:0});return[{type:"group",from:{facet:{data:e.requestDataName(bc.Main),name:Mp+e.requestDataName(bc.Main),groupby:s,aggregate:{fields:[i({suffix:"start"}),i({suffix:"start"}),i({suffix:"end"}),i({suffix:"end"})],ops:["min","max","min","max"]}}},encode:{update:o},marks:[{type:"group",encode:{update:a},marks:[t]}]}]}(e)}return Rp(e)}const Ep="faceted_path_";const Mp="stack_group_";function Rp(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{fromPrefix:""};const{mark:i,markDef:r,encoding:o,config:a}=e,s=U(r.clip,function(e){const t=e.getScaleComponent("x"),n=e.getScaleComponent("y");return!(!t?.get("selectionExtent")&&!n?.get("selectionExtent"))||void 0}(e),function(e){const t=e.component.projection;return!(!t||t.isFit)||void 0}(e)),l=jn(r),c=o.key,u=function(e){const{encoding:n,stack:i,mark:r,markDef:o,config:a}=e,s=n.order;if(!(!t.isArray(s)&&sa(s)&&m(s.value)||!s&&m(En("order",o,a)))){if((t.isArray(s)||Zo(s))&&!i)return qn(s,{expr:"datum"});if(Zr(r)){const e="horizontal"===o.orient?"y":"x";if(Zo(n[e]))return{field:e}}}}(e),f=function(e){if(!e.component.selection)return null;const t=D(e.component.selection).length;let n=t,i=e.parent;for(;i&&0===n;)n=D(i.component.selection).length,i=i.parent;return n?{interactive:t>0||"geoshape"===e.mark||!!e.encoding.tooltip||!!e.markDef.tooltip}:null}(e),d=En("aria",r,a),p=Tp[i].postEncodingTransform?Tp[i].postEncodingTransform(e):null;return[{name:e.getName("marks"),type:Tp[i].vgMark,...s?{clip:s}:{},...l?{style:l}:{},...c?{key:c.field}:{},...u?{sort:u}:{},...f||{},...!1===d?{aria:d}:{},from:{data:n.fromPrefix+e.requestDataName(bc.Main)},encode:{update:Tp[i].encodeEntry(e)},...p?{transform:p}:{}}]}class Lp extends Vm{specifiedScales={};specifiedAxes={};specifiedLegends={};specifiedProjection={};selection=[];children=[];constructor(e,n,i){let r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},o=arguments.length>4?arguments[4]:void 0;super(e,"unit",n,i,o,void 0,Ls(e)?e.view:void 0);const a=no(e.mark)?{...e.mark}:{type:e.mark},s=a.type;void 0===a.filled&&(a.filled=function(e,t,n){let{graticule:i}=n;if(i)return!1;const r=Mn("filled",e,t),o=e.type;return U(r,o!==Br&&o!==Ir&&o!==Hr)}(a,o,{graticule:e.data&&vc(e.data)}));const l=this.encoding=function(e,n,i,r){const o={};for(const t of D(e))tt(t)||Si(`${a=t}-encoding is dropped as ${a} is not a valid encoding channel.`);var a;for(let a of ft){if(!e[a])continue;const s=e[a];if(jt(a)){const e=ut(a),t=o[e];if(Zo(t)&&or(t.type)&&Zo(s)&&!t.timeUnit){Si(ri(e));continue}}if("angle"!==a||"arc"!==n||e.theta||(Si("Arc marks uses theta channel rather than angle, replacing angle with theta."),a=ce),Ya(e,a,n)){if(a===xe&&"line"===n){const t=wa(e[a]);if(t?.aggregate){Si("Line marks cannot encode size with a non-groupby field. You may want to use trail marks instead.");continue}}if(a===he&&(i?"fill"in e:"stroke"in e))Si(ai("encoding",{fill:"fill"in e,stroke:"stroke"in e}));else if(a===Ce||a===ze&&!t.isArray(s)&&!sa(s)||a===Pe&&t.isArray(s)){if(s){if(a===ze){const t=e[a];if(Xo(t)){o[a]=t;continue}}o[a]=t.array(s).reduce(((e,t)=>(Zo(t)?e.push(Fa(t,a)):Si(si(t,a)),e)),[])}}else{if(a===Pe&&null===s)o[a]=null;else if(!(Zo(s)||ta(s)||sa(s)||Qo(s)||wn(s))){Si(si(s,a));continue}o[a]=Sa(s,a,r)}}else Si(li(a,n))}return o}(e.encoding||{},s,a.filled,o);this.markDef=fl(a,l,o),this.size=function(e){let{encoding:t,size:n}=e;for(const e of Ct){const i=st(e);Rs(n[i])&&na(t[e])&&(delete n[i],Si(hi(i)))}return n}({encoding:l,size:Ls(e)?{...r,...e.width?{width:e.width}:{},...e.height?{height:e.height}:{}}:r}),this.stack=ul(this.markDef,l),this.specifiedScales=this.initScales(s,l),this.specifiedAxes=this.initAxes(l),this.specifiedLegends=this.initLegends(l),this.specifiedProjection=e.projection,this.selection=(e.params??[]).filter((e=>Ns(e)))}get hasProjection(){const{encoding:e}=this,t=this.mark===Kr,n=e&&qe.some((t=>oa(e[t])));return t||n}scaleDomain(e){const t=this.specifiedScales[e];return t?t.domain:void 0}axis(e){return this.specifiedAxes[e]}legend(e){return this.specifiedLegends[e]}initScales(e,t){return Xt.reduce(((e,n)=>{const i=ka(t[n]);return i&&(e[n]=this.initScale(i.scale??{})),e}),{})}initScale(e){const{domain:n,range:i}=e,r=bn(e);return t.isArray(n)&&(r.domain=n.map(Cn)),t.isArray(i)&&(r.range=i.map(Cn)),r}initAxes(e){return Ct.reduce(((t,n)=>{const i=e[n];if(oa(i)||n===te&&oa(e.x2)||n===ne&&oa(e.y2)){const e=oa(i)?i.axis:void 0;t[n]=e?this.initAxis({...e}):e}return t}),{})}initAxis(e){const t=D(e),n={};for(const i of t){const t=e[i];n[i]=Ta(t)?zn(t):Cn(t)}return n}initLegends(e){return Gt.reduce(((t,n)=>{const i=ka(e[n]);if(i&&function(e){switch(e){case he:case ye:case ve:case xe:case be:case we:case De:case Fe:return!0;case ke:case Se:case $e:case ge:return!1}}(n)){const e=i.legend;t[n]=e?bn(e):e}return t}),{})}parseData(){this.component.data=hp(this)}parseLayoutSize(){!function(e){const{size:t,component:n}=e;for(const i of Ct){const r=st(i);if(t[r]){const e=t[r];n.layoutSize.set(r,Rs(e)?"step":e,!0)}else{const t=dp(e,r);n.layoutSize.set(r,t,!1)}}}(this)}parseSelections(){this.component.selection=function(e,n){const i={},r=e.config.selection;if(!n||!n.length)return i;let o=0;for(const a of n){const n=C(a.name),s=a.select,c=t.isString(s)?s:s.type,u=t.isObject(s)?l(s):{type:c},f=r[c];for(const e in f)"fields"!==e&&"encodings"!==e&&("mark"===e&&(u.mark={...f.mark,...u.mark}),void 0!==u[e]&&!0!==u[e]||(u[e]=l(f[e]??u[e])));const d=i[n]={...u,name:n,type:c,init:a.value,bind:a.bind,events:t.isString(u.on)?t.parseSelector(u.on,"scope"):t.array(l(u.on))};if(af(d)&&(o++,o>1)){delete i[n];continue}const m=l(a);for(const t of tf)t.defined(d)&&t.parse&&t.parse(e,d,m)}return o>1&&Si("Multiple timer selections in one unit spec are not supported. Ignoring all but the first."),i}(this,this.selection)}parseMarkGroup(){this.component.mark=jp(this)}parseAxesAndHeaders(){var e;this.component.axes=(e=this,Ct.reduce(((t,n)=>(e.component.scales[n]&&(t[n]=[Op(n,e)]),t)),{}))}assembleSelectionTopLevelSignals(e){return function(e,n){let i=!1;for(const r of F(e.component.selection??{})){const o=r.name,a=t.stringValue(o+Ju);if(0===n.filter((e=>e.name===o)).length){const e="global"===r.resolve?"union":r.resolve,i="point"===r.type?", true, true)":")";n.push({name:r.name,update:`${ef}(${a}, ${t.stringValue(e)}${i}`})}i=!0;for(const t of tf)t.defined(r)&&t.topLevelSignals&&(n=t.topLevelSignals(e,r,n))}i&&0===n.filter((e=>"unit"===e.name)).length&&n.unshift({name:"unit",value:{},on:[{events:"pointermove",update:"isTuple(group()) ? group() : unit"}]});return Xc(n)}(this,e)}assembleSignals(){return[...hf(this),...Hc(this,[])]}assembleSelectionData(e){return function(e,t){const n=[],i=[],r=nf(e,{escape:!1});for(const o of F(e.component.selection??{})){const a={name:o.name+Ju};if(o.project.hasSelectionId&&(a.transform=[{type:"collect",sort:{field:zs}}]),o.init){const e=o.project.items.map(Bc);a.values=o.project.hasSelectionId?o.init.map((e=>({unit:r,[zs]:Vc(e,!1)[0]}))):o.init.map((t=>({unit:r,fields:e,values:Vc(t,!1)})))}if([...n,...t].filter((e=>e.name===o.name+Ju)).length||n.push(a),af(o)&&t.length){const n=e.lookupDataSource(e.getDataName(bc.Main)),r=t.find((e=>e.name===n)),o=r.transform.find((e=>"filter"===e.type&&e.expr.includes("vlSelectionTest")));if(o){r.transform=r.transform.filter((e=>e!==o));const e={name:r.name+Tc,source:r.name,transform:[o]};i.push(e)}}}return n.concat(t,i)}(this,e)}assembleLayout(){return null}assembleLayoutSignals(){return Wf(this)}correctDataNames=e=>(e.from?.data&&(e.from.data=this.lookupDataSource(e.from.data),"time"in this.encoding&&(e.from.data=e.from.data+Tc)),e.from?.facet?.data&&(e.from.facet.data=this.lookupDataSource(e.from.facet.data)),e);assembleMarks(){let e=this.component.mark??[];return this.parent&&Im(this.parent)||(e=Yc(this,e)),e.map(this.correctDataNames)}assembleGroupStyle(){const{style:e}=this.view||{};return void 0!==e?e:this.encoding.x||this.encoding.y?"cell":"view"}getMapping(){return this.encoding}get mark(){return this.markDef.type}channelHasField(e){return Ia(this.encoding,e)}fieldDef(e){return wa(this.encoding[e])}typedFieldDef(e){const t=this.fieldDef(e);return aa(t)?t:null}}class qp extends Bm{constructor(e,t,n,i,r){super(e,"layer",t,n,r,e.resolve,e.view);const o={...i,...e.width?{width:e.width}:{},...e.height?{height:e.height}:{}};this.children=e.layer.map(((e,t)=>{if(il(e))return new qp(e,this,this.getName(`layer_${t}`),o,r);if(Ua(e))return new Lp(e,this,this.getName(`layer_${t}`),o,r);throw new Error(Bn(e))}))}parseData(){this.component.data=hp(this);for(const e of this.children)e.parseData()}parseLayoutSize(){var e;up(e=this),fp(e,"width"),fp(e,"height")}parseSelections(){this.component.selection={};for(const e of this.children){e.parseSelections();for(const t of D(e.component.selection))this.component.selection[t]=e.component.selection[t]}Object.values(this.component.selection).some((e=>af(e)))&&ki(ti)}parseMarkGroup(){for(const e of this.children)e.parseMarkGroup()}parseAxesAndHeaders(){!function(e){const{axes:t,resolve:n}=e.component,i={top:0,bottom:0,right:0,left:0};for(const i of e.children){i.parseAxesAndHeaders();for(const r of D(i.component.axes))n.axis[r]=Xf(e.component.resolve,r),"shared"===n.axis[r]&&(t[r]=kp(t[r],i.component.axes[r]),t[r]||(n.axis[r]="independent",delete t[r]))}for(const r of Ct){for(const o of e.children)if(o.component.axes[r]){if("independent"===n.axis[r]){t[r]=(t[r]??[]).concat(o.component.axes[r]);for(const e of o.component.axes[r]){const{value:t,explicit:n}=e.getWithExplicit("orient");if(!wn(t)){if(i[t]>0&&!n){const n=wp[t];i[t]>i[n]&&e.set("orient",n,!1)}i[t]++}}}delete o.component.axes[r]}if("independent"===n.axis[r]&&t[r]&&t[r].length>1)for(const[e,n]of(t[r]||[]).entries())e>0&&n.get("grid")&&!n.explicit.grid&&(n.implicit.grid=!1)}}(this)}assembleSelectionTopLevelSignals(e){return this.children.reduce(((e,t)=>t.assembleSelectionTopLevelSignals(e)),e)}assembleSignals(){return this.children.reduce(((e,t)=>e.concat(t.assembleSignals())),hf(this))}assembleLayoutSignals(){return this.children.reduce(((e,t)=>e.concat(t.assembleLayoutSignals())),Wf(this))}assembleSelectionData(e){return this.children.reduce(((e,t)=>t.assembleSelectionData(e)),e)}assembleGroupStyle(){const e=new Set;for(const n of this.children)for(const i of t.array(n.assembleGroupStyle()))e.add(i);const n=Array.from(e);return n.length>1?n:1===n.length?n[0]:void 0}assembleTitle(){let e=super.assembleTitle();if(e)return e;for(const t of this.children)if(e=t.assembleTitle(),e)return e}assembleLayout(){return null}assembleMarks(){return function(e,t){for(const n of e.children)qm(n)&&(t=Yc(n,t));return t}(this,this.children.flatMap((e=>e.assembleMarks())))}assembleLegends(){return this.children.reduce(((e,t)=>e.concat(t.assembleLegends())),dd(this))}}function Up(e,t,n,i,r){if(Io(e))return new pp(e,t,n,r);if(il(e))return new qp(e,t,n,i,r);if(Ua(e))return new Lp(e,t,n,i,r);if(function(e){return js(e)||Es(e)||Ts(e)}(e))return new vp(e,t,n,r);throw new Error(Bn(e))}const Wp=n;e.accessPathDepth=q,e.accessPathWithDatum=A,e.accessWithDatumToUnescapedPath=j,e.compile=function(e){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};var i;n.logger&&(i=n.logger,wi=i),n.fieldTitle&&ya(n.fieldTitle);try{const i=Js(t.mergeConfig(n.config,e.config)),r=Kl(e,i),o=Up(r,null,"",void 0,i);o.parse(),function(e,t){rm(e.sources);let n=0,i=0;for(let i=0;i2&&void 0!==arguments[2]?arguments[2]:{},i=arguments.length>3?arguments[3]:void 0;const r=e.config?tl(e.config):void 0,o=function(e,t){const n=[],i=op(n);let r=0;for(const t of e.sources){t.hasName()||(t.dataName="source_"+r++);const e=t.assemble();i(t,e)}for(const e of n)0===e.transform.length&&delete e.transform;let o=0;for(const[e,t]of n.entries())0!==(t.transform??[]).length||t.source||n.splice(o++,0,n.splice(e,1)[0]);for(const t of n)for(const n of t.transform??[])"lookup"===n.type&&(n.from=e.outputNodes[n.from].getSource());for(const e of n)e.name in t&&(e.values=t[e.name]);return n}(e.component.data,n),a=e.assembleSelectionData(o),s=e.assembleProjections(),l=e.assembleTitle(),c=e.assembleGroupStyle(),u=e.assembleGroupEncodeEntry(!0);let f=e.assembleLayoutSignals();f=f.filter((e=>"width"!==e.name&&"height"!==e.name||void 0===e.value||(t[e.name]=+e.value,!1)));const{params:d,...m}=t;return{$schema:"https://vega.github.io/schema/vega/v5.json",...e.description?{description:e.description}:{},...m,...l?{title:l}:{},...c?{style:c}:{},...u?{encode:{update:u}}:{},data:a,...s.length>0?{projections:s}:{},...e.assembleGroup([...f,...e.assembleSelectionTopLevelSignals([]),...As(d)]),...r?{config:r}:{},...i?{usermeta:i}:{}}}(o,function(e,n,i,r){const o=r.component.layoutSize.get("width"),a=r.component.layoutSize.get("height");void 0===n?(n={type:"pad"},r.hasAxisOrientSignalRef()&&(n.resize=!0)):t.isString(n)&&(n={type:n});if(o&&a&&(s=n.type,["fit","fit-x","fit-y"].includes(s)))if("step"===o&&"step"===a)Si(Yn()),n.type="pad";else if("step"===o||"step"===a){const e="step"===o?"width":"height";Si(Yn(At(e)));const t="width"===e?"height":"width";n.type=function(e){return e?`fit-${At(e)}`:"fit"}(t)}var s;return{...1===D(n).length&&n.type?"pad"===n.type?{}:{autosize:n.type}:{autosize:n},...rc(i,!1),...rc(e,!0)}}(e,r.autosize,i,o),e.datasets,e.usermeta);return{spec:a,normalized:r}}finally{n.logger&&(wi=$i),n.fieldTitle&&ya(ga)}},e.contains=p,e.deepEqual=X,e.deleteNestedProperty=P,e.duplicate=l,e.entries=O,e.every=h,e.fieldIntersection=k,e.flatAccessWithDatum=T,e.getFirstDefined=U,e.hasIntersection=$,e.hasProperty=J,e.hash=d,e.internalField=B,e.isBoolean=z,e.isEmpty=S,e.isEqual=function(e,t){const n=D(e),i=D(t);if(n.length!==i.length)return!1;for(const i of n)if(e[i]!==t[i])return!1;return!0},e.isInternalField=V,e.isNullOrFalse=m,e.isNumeric=G,e.keys=D,e.logicalExpr=_,e.mergeDeep=y,e.never=c,e.normalize=Kl,e.normalizeAngle=H,e.omit=f,e.pick=u,e.prefixGenerator=w,e.removePathFromField=L,e.replaceAll=R,e.replacePathInField=M,e.resetIdCounter=function(){W=42},e.setEqual=x,e.some=g,e.stringify=Q,e.titleCase=N,e.unique=b,e.uniqueId=I,e.vals=F,e.varName=C,e.version=Wp})); +//# sourceMappingURL=vega-lite.min.js.map diff --git a/static/vendor/retained-analysis/vega.min.js b/static/vendor/retained-analysis/vega.min.js new file mode 100644 index 00000000..572741ee --- /dev/null +++ b/static/vendor/retained-analysis/vega.min.js @@ -0,0 +1,2 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).vega={})}(this,(function(t){"use strict";function e(t,e,n){return t.fields=e||[],t.fname=n,t}function n(t){return null==t?null:t.fname}function r(t){return null==t?null:t.fields}function i(t){return 1===t.length?o(t[0]):a(t)}const o=t=>function(e){return e[t]},a=t=>{const e=t.length;return function(n){for(let r=0;rr&&c(),u=r=i+1):"]"===o&&(u||s("Access path missing open bracket: "+t),u>0&&c(),u=0,r=i+1):i>r?c():r=i+1}return u&&s("Access path missing closing bracket: "+t),a&&s("Access path missing closing quote: "+t),i>r&&(i++,c()),e}function l(t,n,r){const o=u(t);return t=1===o.length?o[0]:t,e((r&&r.get||i)(o),[t],n||t)}const c=l("id"),f=e((t=>t),[],"identity"),h=e((()=>0),[],"zero"),d=e((()=>1),[],"one"),p=e((()=>!0),[],"true"),g=e((()=>!1),[],"false");function m(t,e,n){const r=[e].concat([].slice.call(n));console[t].apply(console,r)}const y=0,v=1,_=2,x=3,b=4;function w(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:m,r=t||y;return{level(t){return arguments.length?(r=+t,this):r},error(){return r>=v&&n(e||"error","ERROR",arguments),this},warn(){return r>=_&&n(e||"warn","WARN",arguments),this},info(){return r>=x&&n(e||"log","INFO",arguments),this},debug(){return r>=b&&n(e||"log","DEBUG",arguments),this}}}var k=Array.isArray;function A(t){return t===Object(t)}const M=t=>"__proto__"!==t;function E(){for(var t=arguments.length,e=new Array(t),n=0;n{for(const n in e)if("signals"===n)t.signals=C(t.signals,e.signals);else{const r="legend"===n?{layout:1}:"style"===n||null;D(t,n,e[n],r)}return t}),{})}function D(t,e,n,r){if(!M(e))return;let i,o;if(A(n)&&!k(n))for(i in o=A(t[e])?t[e]:t[e]={},n)r&&(!0===r||r[i])?D(o,i,n[i]):M(i)&&(o[i]=n[i]);else t[e]=n}function C(t,e){if(null==t)return e;const n={},r=[];function i(t){n[t.name]||(n[t.name]=1,r.push(t))}return e.forEach(i),t.forEach(i),r}function F(t){return t[t.length-1]}function S(t){return null==t||""===t?null:+t}const $=t=>e=>t*Math.exp(e),T=t=>e=>Math.log(t*e),B=t=>e=>Math.sign(e)*Math.log1p(Math.abs(e/t)),z=t=>e=>Math.sign(e)*Math.expm1(Math.abs(e))*t,N=t=>e=>e<0?-Math.pow(-e,t):Math.pow(e,t);function O(t,e,n,r){const i=n(t[0]),o=n(F(t)),a=(o-i)*e;return[r(i-a),r(o-a)]}function R(t,e){return O(t,e,S,f)}function L(t,e){var n=Math.sign(t[0]);return O(t,e,T(n),$(n))}function U(t,e,n){return O(t,e,N(n),N(1/n))}function q(t,e,n){return O(t,e,B(n),z(n))}function P(t,e,n,r,i){const o=r(t[0]),a=r(F(t)),s=null!=e?r(e):(o+a)/2;return[i(s+(o-s)*n),i(s+(a-s)*n)]}function j(t,e,n){return P(t,e,n,S,f)}function I(t,e,n){const r=Math.sign(t[0]);return P(t,e,n,T(r),$(r))}function W(t,e,n,r){return P(t,e,n,N(r),N(1/r))}function H(t,e,n,r){return P(t,e,n,B(r),z(r))}function Y(t){return 1+~~(new Date(t).getMonth()/3)}function G(t){return 1+~~(new Date(t).getUTCMonth()/3)}function V(t){return null!=t?k(t)?t:[t]:[]}function X(t,e,n){let r,i=t[0],o=t[1];return o=n-e?[e,n]:[i=Math.min(Math.max(i,e),n-r),i+r]}function J(t){return"function"==typeof t}const Z="descending";function Q(t,n,i){i=i||{},n=V(n)||[];const o=[],a=[],s={},u=i.comparator||tt;return V(t).forEach(((t,e)=>{null!=t&&(o.push(n[e]===Z?-1:1),a.push(t=J(t)?t:l(t,null,i)),(r(t)||[]).forEach((t=>s[t]=1)))})),0===a.length?null:e(u(a,o),Object.keys(s))}const K=(t,e)=>(te||null==e)&&null!=t?1:(e=e instanceof Date?+e:e,(t=t instanceof Date?+t:t)!==t&&e==e?-1:e!=e&&t==t?1:0),tt=(t,e)=>1===t.length?et(t[0],e[0]):nt(t,e,t.length),et=(t,e)=>function(n,r){return K(t(n),t(r))*e},nt=(t,e,n)=>(e.push(0),function(r,i){let o,a=0,s=-1;for(;0===a&&++st}function it(t,e){let n;return r=>{n&&clearTimeout(n),n=setTimeout((()=>(e(r),n=null)),t)}}function ot(t){for(let e,n,r=1,i=arguments.length;ro&&(o=r))}else{for(r=e(t[a]);ao&&(o=r))}return[i,o]}function st(t,e){const n=t.length;let r,i,o,a,s,u=-1;if(null==e){for(;++u=i){r=o=i;break}if(u===n)return[-1,-1];for(a=s=u;++ui&&(r=i,a=u),o=i){r=o=i;break}if(u===n)return[-1,-1];for(a=s=u;++ui&&(r=i,a=u),or(t)?n[t]:void 0,set(t,e){return r(t)||(++i.size,n[t]===lt&&--i.empty),n[t]=e,this},delete(t){return r(t)&&(--i.size,++i.empty,n[t]=lt),this},clear(){i.size=i.empty=0,i.object=n={}},test(t){return arguments.length?(e=t,i):e},clean(){const t={};let r=0;for(const i in n){const o=n[i];o===lt||e&&e(o)||(t[i]=o,++r)}i.size=r,i.empty=0,i.object=n=t}};return t&&Object.keys(t).forEach((e=>{i.set(e,t[e])})),i}function ft(t,e,n,r,i,o){if(!n&&0!==n)return o;const a=+n;let s,u=t[0],l=F(t);la&&(i=o,o=a,a=i),r=void 0===r||r,((n=void 0===n||n)?o<=t:ot.replace(/\\(.)/g,"$1"))):V(t));const o=t&&t.length,a=r&&r.get||i,s=t=>a(n?[t]:u(t));let l;if(o)if(1===o){const e=s(t[0]);l=function(t){return""+e(t)}}else{const e=t.map(s);l=function(t){let n=""+e[0](t),r=0;for(;++r{e={},n={},r=0},o=(i,o)=>(++r>t&&(n=e,e={},r=1),e[i]=o);return i(),{clear:i,has:t=>ut(e,t)||ut(n,t),get:t=>ut(e,t)?e[t]:ut(n,t)?o(t,n[t]):void 0,set:(t,n)=>ut(e,t)?e[t]=n:o(t,n)}}function kt(t,e,n,r){const i=e.length,o=n.length;if(!o)return e;if(!i)return n;const a=r||new e.constructor(i+o);let s=0,u=0,l=0;for(;s0?n[u++]:e[s++];for(;s=0;)n+=t;return n}function Mt(t,e,n,r){const i=n||" ",o=t+"",a=e-o.length;return a<=0?o:"left"===r?At(i,a)+o:"center"===r?At(i,~~(a/2))+o+At(i,Math.ceil(a/2)):o+At(i,a)}function Et(t){return t&&F(t)-t[0]||0}function Dt(t){return k(t)?"["+t.map(Dt)+"]":A(t)||_t(t)?JSON.stringify(t).replace("\u2028","\\u2028").replace("\u2029","\\u2029"):t}function Ct(t){return null==t||""===t?null:!(!t||"false"===t||"0"===t)&&!!t}const Ft=t=>yt(t)||gt(t)?t:Date.parse(t);function St(t,e){return e=e||Ft,null==t||""===t?null:e(t)}function $t(t){return null==t||""===t?null:t+""}function Tt(t){const e={},n=t.length;for(let r=0;r9999?"+"+jt(e,6):jt(e,4))+"-"+jt(t.getUTCMonth()+1,2)+"-"+jt(t.getUTCDate(),2)+(o?"T"+jt(n,2)+":"+jt(r,2)+":"+jt(i,2)+"."+jt(o,3)+"Z":i?"T"+jt(n,2)+":"+jt(r,2)+":"+jt(i,2)+"Z":r||n?"T"+jt(n,2)+":"+jt(r,2)+"Z":"")}function Wt(t){var e=new RegExp('["'+t+"\n\r]"),n=t.charCodeAt(0);function r(t,e){var r,i=[],o=t.length,a=0,s=0,u=o<=0,l=!1;function c(){if(u)return Ot;if(l)return l=!1,Nt;var e,r,i=a;if(t.charCodeAt(i)===Rt){for(;a++=o?u=!0:(r=t.charCodeAt(a++))===Lt?l=!0:r===Ut&&(l=!0,t.charCodeAt(a)===Lt&&++a),t.slice(i+1,e-1).replace(/""/g,'"')}for(;a1)r=function(t,e,n){var r,i=[],o=[];function a(t){var e=t<0?~t:t;(o[e]||(o[e]=[])).push({i:t,g:r})}function s(t){t.forEach(a)}function u(t){t.forEach(s)}function l(t){t.forEach(u)}function c(t){switch(r=t,t.type){case"GeometryCollection":t.geometries.forEach(c);break;case"LineString":s(t.arcs);break;case"MultiLineString":case"Polygon":u(t.arcs);break;case"MultiPolygon":l(t.arcs)}}return c(e),o.forEach(null==n?function(t){i.push(t[0].i)}:function(t){n(t[0].g,t[t.length-1].g)&&i.push(t[0].i)}),i}(0,e,n);else for(i=0,r=new Array(o=t.arcs.length);ie?1:t>=e?0:NaN}function Kt(t,e){return null==t||null==e?NaN:et?1:e>=t?0:NaN}function te(t){let e,n,r;function i(t,r){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:t.length;if(i>>1;n(t[e],r)<0?i=e+1:o=e}while(iQt(t(e),n),r=(e,n)=>t(e)-n):(e=t===Qt||t===Kt?t:ee,n=t,r=t),{left:i,center:function(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;const o=i(t,e,n,(arguments.length>3&&void 0!==arguments[3]?arguments[3]:t.length)-1);return o>n&&r(t[o-1],e)>-r(t[o],e)?o-1:o},right:function(t,r){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:t.length;if(i>>1;n(t[e],r)<=0?i=e+1:o=e}while(i0){for(o=t[--i];i>0&&(e=o,n=t[--i],o=e+n,r=n-(o-e),!r););i>0&&(r<0&&t[i-1]<0||r>0&&t[i-1]>0)&&(n=2*r,e=o+n,n==e-o&&(o=e))}return o}}class se extends Map{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:he;if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:e}}),null!=t)for(const[e,n]of t)this.set(e,n)}get(t){return super.get(le(this,t))}has(t){return super.has(le(this,t))}set(t,e){return super.set(ce(this,t),e)}delete(t){return super.delete(fe(this,t))}}class ue extends Set{constructor(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:he;if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:e}}),null!=t)for(const e of t)this.add(e)}has(t){return super.has(le(this,t))}add(t){return super.add(ce(this,t))}delete(t){return super.delete(fe(this,t))}}function le(t,e){let{_intern:n,_key:r}=t;const i=r(e);return n.has(i)?n.get(i):e}function ce(t,e){let{_intern:n,_key:r}=t;const i=r(e);return n.has(i)?n.get(i):(n.set(i,e),e)}function fe(t,e){let{_intern:n,_key:r}=t;const i=r(e);return n.has(i)&&(e=n.get(i),n.delete(i)),e}function he(t){return null!==t&&"object"==typeof t?t.valueOf():t}function de(t,e){return(null==t||!(t>=t))-(null==e||!(e>=e))||(te?1:0)}const pe=Math.sqrt(50),ge=Math.sqrt(10),me=Math.sqrt(2);function ye(t,e,n){const r=(e-t)/Math.max(0,n),i=Math.floor(Math.log10(r)),o=r/Math.pow(10,i),a=o>=pe?10:o>=ge?5:o>=me?2:1;let s,u,l;return i<0?(l=Math.pow(10,-i)/a,s=Math.round(t*l),u=Math.round(e*l),s/le&&--u,l=-l):(l=Math.pow(10,i)*a,s=Math.round(t/l),u=Math.round(e/l),s*le&&--u),u0))return[];if((t=+t)===(e=+e))return[t];const r=e=i))return[];const s=o-i+1,u=new Array(s);if(r)if(a<0)for(let t=0;t=e)&&(n=e);else{let r=-1;for(let i of t)null!=(i=e(i,++r,t))&&(n=i)&&(n=i)}return n}function we(t,e){let n;if(void 0===e)for(const e of t)null!=e&&(n>e||void 0===n&&e>=e)&&(n=e);else{let r=-1;for(let i of t)null!=(i=e(i,++r,t))&&(n>i||void 0===n&&i>=i)&&(n=i)}return n}function ke(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1/0,i=arguments.length>4?arguments[4]:void 0;if(e=Math.floor(e),n=Math.floor(Math.max(0,n)),r=Math.floor(Math.min(t.length-1,r)),!(n<=e&&e<=r))return t;for(i=void 0===i?de:function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Qt;if(t===Qt)return de;if("function"!=typeof t)throw new TypeError("compare is not a function");return(e,n)=>{const r=t(e,n);return r||0===r?r:(0===t(n,n))-(0===t(e,e))}}(i);r>n;){if(r-n>600){const o=r-n+1,a=e-n+1,s=Math.log(o),u=.5*Math.exp(2*s/3),l=.5*Math.sqrt(s*u*(o-u)/o)*(a-o/2<0?-1:1);ke(t,e,Math.max(n,Math.floor(e-a*u/o+l)),Math.min(r,Math.floor(e+(o-a)*u/o+l)),i)}const o=t[e];let a=n,s=r;for(Ae(t,n,e),i(t[r],o)>0&&Ae(t,n,r);a0;)--s}0===i(t[n],o)?Ae(t,n,s):(++s,Ae(t,s,r)),s<=e&&(n=s+1),e<=s&&(r=s-1)}return t}function Ae(t,e,n){const r=t[e];t[e]=t[n],t[n]=r}function Me(t,e,n){if(t=Float64Array.from(function*(t,e){if(void 0===e)for(let e of t)null!=e&&(e=+e)>=e&&(yield e);else{let n=-1;for(let r of t)null!=(r=e(r,++n,t))&&(r=+r)>=r&&(yield r)}}(t,n)),(r=t.length)&&!isNaN(e=+e)){if(e<=0||r<2)return we(t);if(e>=1)return be(t);var r,i=(r-1)*e,o=Math.floor(i),a=be(ke(t,o).subarray(0,o+1));return a+(we(t.subarray(o+1))-a)*(i-o)}}function Ee(t,e){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:ne;if((r=t.length)&&!isNaN(e=+e)){if(e<=0||r<2)return+n(t[0],0,t);if(e>=1)return+n(t[r-1],r-1,t);var r,i=(r-1)*e,o=Math.floor(i),a=+n(t[o],o,t);return a+(+n(t[o+1],o+1,t)-a)*(i-o)}}function De(t,e){return Me(t,.5,e)}function Ce(t){return Array.from(function*(t){for(const e of t)yield*e}(t))}function Fe(t,e,n){t=+t,e=+e,n=(i=arguments.length)<2?(e=t,t=0,1):i<3?1:+n;for(var r=-1,i=0|Math.max(0,Math.ceil((e-t)/n)),o=new Array(i);++r1?r[0]+r.slice(2):r,+t.slice(n+1)]}function Be(t){return(t=Te(Math.abs(t)))?t[1]:NaN}var ze,Ne=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function Oe(t){if(!(e=Ne.exec(t)))throw new Error("invalid format: "+t);var e;return new Re({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}function Re(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function Le(t,e){var n=Te(t,e);if(!n)return t+"";var r=n[0],i=n[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}Oe.prototype=Re.prototype,Re.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};var Ue={"%":(t,e)=>(100*t).toFixed(e),b:t=>Math.round(t).toString(2),c:t=>t+"",d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:(t,e)=>t.toExponential(e),f:(t,e)=>t.toFixed(e),g:(t,e)=>t.toPrecision(e),o:t=>Math.round(t).toString(8),p:(t,e)=>Le(100*t,e),r:Le,s:function(t,e){var n=Te(t,e);if(!n)return t+"";var r=n[0],i=n[1],o=i-(ze=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,a=r.length;return o===a?r:o>a?r+new Array(o-a+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+Te(t,Math.max(0,e+o-1))[0]},X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function qe(t){return t}var Pe,je,Ie,We=Array.prototype.map,He=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function Ye(t){var e,n,r=void 0===t.grouping||void 0===t.thousands?qe:(e=We.call(t.grouping,Number),n=t.thousands+"",function(t,r){for(var i=t.length,o=[],a=0,s=e[0],u=0;i>0&&s>0&&(u+s+1>r&&(s=Math.max(1,r-u)),o.push(t.substring(i-=s,i+s)),!((u+=s+1)>r));)s=e[a=(a+1)%e.length];return o.reverse().join(n)}),i=void 0===t.currency?"":t.currency[0]+"",o=void 0===t.currency?"":t.currency[1]+"",a=void 0===t.decimal?".":t.decimal+"",s=void 0===t.numerals?qe:function(t){return function(e){return e.replace(/[0-9]/g,(function(e){return t[+e]}))}}(We.call(t.numerals,String)),u=void 0===t.percent?"%":t.percent+"",l=void 0===t.minus?"−":t.minus+"",c=void 0===t.nan?"NaN":t.nan+"";function f(t){var e=(t=Oe(t)).fill,n=t.align,f=t.sign,h=t.symbol,d=t.zero,p=t.width,g=t.comma,m=t.precision,y=t.trim,v=t.type;"n"===v?(g=!0,v="g"):Ue[v]||(void 0===m&&(m=12),y=!0,v="g"),(d||"0"===e&&"="===n)&&(d=!0,e="0",n="=");var _="$"===h?i:"#"===h&&/[boxX]/.test(v)?"0"+v.toLowerCase():"",x="$"===h?o:/[%p]/.test(v)?u:"",b=Ue[v],w=/[defgprs%]/.test(v);function k(t){var i,o,u,h=_,k=x;if("c"===v)k=b(t)+k,t="";else{var A=(t=+t)<0||1/t<0;if(t=isNaN(t)?c:b(Math.abs(t),m),y&&(t=function(t){t:for(var e,n=t.length,r=1,i=-1;r0&&(i=0)}return i>0?t.slice(0,i)+t.slice(e+1):t}(t)),A&&0==+t&&"+"!==f&&(A=!1),h=(A?"("===f?f:l:"-"===f||"("===f?"":f)+h,k=("s"===v?He[8+ze/3]:"")+k+(A&&"("===f?")":""),w)for(i=-1,o=t.length;++i(u=t.charCodeAt(i))||u>57){k=(46===u?a+t.slice(i+1):t.slice(i))+k,t=t.slice(0,i);break}}g&&!d&&(t=r(t,1/0));var M=h.length+t.length+k.length,E=M>1)+h+t+k+E.slice(M);break;default:t=E+h+t+k}return s(t)}return m=void 0===m?6:/[gprs]/.test(v)?Math.max(1,Math.min(21,m)):Math.max(0,Math.min(20,m)),k.toString=function(){return t+""},k}return{format:f,formatPrefix:function(t,e){var n=f(((t=Oe(t)).type="f",t)),r=3*Math.max(-8,Math.min(8,Math.floor(Be(e)/3))),i=Math.pow(10,-r),o=He[8+r/3];return function(t){return n(i*t)+o}}}}function Ge(t){return Math.max(0,-Be(Math.abs(t)))}function Ve(t,e){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(Be(e)/3)))-Be(Math.abs(t)))}function Xe(t,e){return t=Math.abs(t),e=Math.abs(e)-t,Math.max(0,Be(e)-Be(t))+1}!function(t){Pe=Ye(t),je=Pe.format,Ie=Pe.formatPrefix}({thousands:",",grouping:[3],currency:["$",""]});const Je=new Date,Ze=new Date;function Qe(t,e,n,r){function i(e){return t(e=0===arguments.length?new Date:new Date(+e)),e}return i.floor=e=>(t(e=new Date(+e)),e),i.ceil=n=>(t(n=new Date(n-1)),e(n,1),t(n),n),i.round=t=>{const e=i(t),n=i.ceil(t);return t-e(e(t=new Date(+t),null==n?1:Math.floor(n)),t),i.range=(n,r,o)=>{const a=[];if(n=i.ceil(n),o=null==o?1:Math.floor(o),!(n0))return a;let s;do{a.push(s=new Date(+n)),e(n,o),t(n)}while(sQe((e=>{if(e>=e)for(;t(e),!n(e);)e.setTime(e-1)}),((t,r)=>{if(t>=t)if(r<0)for(;++r<=0;)for(;e(t,-1),!n(t););else for(;--r>=0;)for(;e(t,1),!n(t););})),n&&(i.count=(e,r)=>(Je.setTime(+e),Ze.setTime(+r),t(Je),t(Ze),Math.floor(n(Je,Ze))),i.every=t=>(t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?e=>r(e)%t==0:e=>i.count(0,e)%t==0):i:null)),i}const Ke=Qe((()=>{}),((t,e)=>{t.setTime(+t+e)}),((t,e)=>e-t));Ke.every=t=>(t=Math.floor(t),isFinite(t)&&t>0?t>1?Qe((e=>{e.setTime(Math.floor(e/t)*t)}),((e,n)=>{e.setTime(+e+n*t)}),((e,n)=>(n-e)/t)):Ke:null),Ke.range;const tn=1e3,en=6e4,nn=36e5,rn=864e5,on=6048e5,an=2592e6,sn=31536e6,un=Qe((t=>{t.setTime(t-t.getMilliseconds())}),((t,e)=>{t.setTime(+t+e*tn)}),((t,e)=>(e-t)/tn),(t=>t.getUTCSeconds()));un.range;const ln=Qe((t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*tn)}),((t,e)=>{t.setTime(+t+e*en)}),((t,e)=>(e-t)/en),(t=>t.getMinutes()));ln.range;const cn=Qe((t=>{t.setUTCSeconds(0,0)}),((t,e)=>{t.setTime(+t+e*en)}),((t,e)=>(e-t)/en),(t=>t.getUTCMinutes()));cn.range;const fn=Qe((t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*tn-t.getMinutes()*en)}),((t,e)=>{t.setTime(+t+e*nn)}),((t,e)=>(e-t)/nn),(t=>t.getHours()));fn.range;const hn=Qe((t=>{t.setUTCMinutes(0,0,0)}),((t,e)=>{t.setTime(+t+e*nn)}),((t,e)=>(e-t)/nn),(t=>t.getUTCHours()));hn.range;const dn=Qe((t=>t.setHours(0,0,0,0)),((t,e)=>t.setDate(t.getDate()+e)),((t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*en)/rn),(t=>t.getDate()-1));dn.range;const pn=Qe((t=>{t.setUTCHours(0,0,0,0)}),((t,e)=>{t.setUTCDate(t.getUTCDate()+e)}),((t,e)=>(e-t)/rn),(t=>t.getUTCDate()-1));pn.range;const gn=Qe((t=>{t.setUTCHours(0,0,0,0)}),((t,e)=>{t.setUTCDate(t.getUTCDate()+e)}),((t,e)=>(e-t)/rn),(t=>Math.floor(t/rn)));function mn(t){return Qe((e=>{e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)}),((t,e)=>{t.setDate(t.getDate()+7*e)}),((t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*en)/on))}gn.range;const yn=mn(0),vn=mn(1),_n=mn(2),xn=mn(3),bn=mn(4),wn=mn(5),kn=mn(6);function An(t){return Qe((e=>{e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)}),((t,e)=>{t.setUTCDate(t.getUTCDate()+7*e)}),((t,e)=>(e-t)/on))}yn.range,vn.range,_n.range,xn.range,bn.range,wn.range,kn.range;const Mn=An(0),En=An(1),Dn=An(2),Cn=An(3),Fn=An(4),Sn=An(5),$n=An(6);Mn.range,En.range,Dn.range,Cn.range,Fn.range,Sn.range,$n.range;const Tn=Qe((t=>{t.setDate(1),t.setHours(0,0,0,0)}),((t,e)=>{t.setMonth(t.getMonth()+e)}),((t,e)=>e.getMonth()-t.getMonth()+12*(e.getFullYear()-t.getFullYear())),(t=>t.getMonth()));Tn.range;const Bn=Qe((t=>{t.setUTCDate(1),t.setUTCHours(0,0,0,0)}),((t,e)=>{t.setUTCMonth(t.getUTCMonth()+e)}),((t,e)=>e.getUTCMonth()-t.getUTCMonth()+12*(e.getUTCFullYear()-t.getUTCFullYear())),(t=>t.getUTCMonth()));Bn.range;const zn=Qe((t=>{t.setMonth(0,1),t.setHours(0,0,0,0)}),((t,e)=>{t.setFullYear(t.getFullYear()+e)}),((t,e)=>e.getFullYear()-t.getFullYear()),(t=>t.getFullYear()));zn.every=t=>isFinite(t=Math.floor(t))&&t>0?Qe((e=>{e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)}),((e,n)=>{e.setFullYear(e.getFullYear()+n*t)})):null,zn.range;const Nn=Qe((t=>{t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),((t,e)=>{t.setUTCFullYear(t.getUTCFullYear()+e)}),((t,e)=>e.getUTCFullYear()-t.getUTCFullYear()),(t=>t.getUTCFullYear()));function On(t,e,n,r,i,o){const a=[[un,1,tn],[un,5,5e3],[un,15,15e3],[un,30,3e4],[o,1,en],[o,5,3e5],[o,15,9e5],[o,30,18e5],[i,1,nn],[i,3,108e5],[i,6,216e5],[i,12,432e5],[r,1,rn],[r,2,1728e5],[n,1,on],[e,1,an],[e,3,7776e6],[t,1,sn]];function s(e,n,r){const i=Math.abs(n-e)/r,o=te((t=>{let[,,e]=t;return e})).right(a,i);if(o===a.length)return t.every(xe(e/sn,n/sn,r));if(0===o)return Ke.every(Math.max(xe(e,n,r),1));const[s,u]=a[i/a[o-1][2]isFinite(t=Math.floor(t))&&t>0?Qe((e=>{e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)}),((e,n)=>{e.setUTCFullYear(e.getUTCFullYear()+n*t)})):null,Nn.range;const[Rn,Ln]=On(Nn,Bn,Mn,gn,hn,cn),[Un,qn]=On(zn,Tn,yn,dn,fn,ln),Pn="year",jn="quarter",In="month",Wn="week",Hn="date",Yn="day",Gn="dayofyear",Vn="hours",Xn="minutes",Jn="seconds",Zn="milliseconds",Qn=[Pn,jn,In,Wn,Hn,Yn,Gn,Vn,Xn,Jn,Zn],Kn=Qn.reduce(((t,e,n)=>(t[e]=1+n,t)),{});function tr(t){const e=V(t).slice(),n={};e.length||s("Missing time unit."),e.forEach((t=>{ut(Kn,t)?n[t]=1:s(`Invalid time unit: ${t}.`)}));return(n[Wn]||n[Yn]?1:0)+(n[jn]||n[In]||n[Hn]?1:0)+(n[Gn]?1:0)>1&&s(`Incompatible time units: ${t}`),e.sort(((t,e)=>Kn[t]-Kn[e])),e}const er={[Pn]:"%Y ",[jn]:"Q%q ",[In]:"%b ",[Hn]:"%d ",[Wn]:"W%U ",[Yn]:"%a ",[Gn]:"%j ",[Vn]:"%H:00",[Xn]:"00:%M",[Jn]:":%S",[Zn]:".%L",[`${Pn}-${In}`]:"%Y-%m ",[`${Pn}-${In}-${Hn}`]:"%Y-%m-%d ",[`${Vn}-${Xn}`]:"%H:%M"};function nr(t,e){const n=ot({},er,e),r=tr(t),i=r.length;let o,a,s="",u=0;for(u=0;uu;--o)if(a=r.slice(u,o).join("-"),null!=n[a]){s+=n[a],u=o;break}return s.trim()}const rr=new Date;function ir(t){return rr.setFullYear(t),rr.setMonth(0),rr.setDate(1),rr.setHours(0,0,0,0),rr}function or(t){return sr(new Date(t))}function ar(t){return ur(new Date(t))}function sr(t){return dn.count(ir(t.getFullYear())-1,t)}function ur(t){return yn.count(ir(t.getFullYear())-1,t)}function lr(t){return ir(t).getDay()}function cr(t,e,n,r,i,o,a){if(0<=t&&t<100){const s=new Date(-1,e,n,r,i,o,a);return s.setFullYear(t),s}return new Date(t,e,n,r,i,o,a)}function fr(t){return dr(new Date(t))}function hr(t){return pr(new Date(t))}function dr(t){const e=Date.UTC(t.getUTCFullYear(),0,1);return pn.count(e-1,t)}function pr(t){const e=Date.UTC(t.getUTCFullYear(),0,1);return Mn.count(e-1,t)}function gr(t){return rr.setTime(Date.UTC(t,0,1)),rr.getUTCDay()}function mr(t,e,n,r,i,o,a){if(0<=t&&t<100){const t=new Date(Date.UTC(-1,e,n,r,i,o,a));return t.setUTCFullYear(n.y),t}return new Date(Date.UTC(t,e,n,r,i,o,a))}function yr(t,e,n,r,i){const o=e||1,a=F(t),s=(t,e,i)=>function(t,e,n,r){const i=n<=1?t:r?(e,i)=>r+n*Math.floor((t(e,i)-r)/n):(e,r)=>n*Math.floor(t(e,r)/n);return e?(t,n)=>e(i(t,n),n):i}(n[i=i||t],r[i],t===a&&o,e),u=new Date,l=Tt(t),c=l[Pn]?s(Pn):rt(2012),f=l[In]?s(In):l[jn]?s(jn):h,p=l[Wn]&&l[Yn]?s(Yn,1,Wn+Yn):l[Wn]?s(Wn,1):l[Yn]?s(Yn,1):l[Hn]?s(Hn,1):l[Gn]?s(Gn,1):d,g=l[Vn]?s(Vn):h,m=l[Xn]?s(Xn):h,y=l[Jn]?s(Jn):h,v=l[Zn]?s(Zn):h;return function(t){u.setTime(+t);const e=c(u);return i(e,f(u),p(u,e),g(u),m(u),y(u),v(u))}}function vr(t,e,n){return e+7*t-(n+6)%7}const _r={[Pn]:t=>t.getFullYear(),[jn]:t=>Math.floor(t.getMonth()/3),[In]:t=>t.getMonth(),[Hn]:t=>t.getDate(),[Vn]:t=>t.getHours(),[Xn]:t=>t.getMinutes(),[Jn]:t=>t.getSeconds(),[Zn]:t=>t.getMilliseconds(),[Gn]:t=>sr(t),[Wn]:t=>ur(t),[Wn+Yn]:(t,e)=>vr(ur(t),t.getDay(),lr(e)),[Yn]:(t,e)=>vr(1,t.getDay(),lr(e))},xr={[jn]:t=>3*t,[Wn]:(t,e)=>vr(t,0,lr(e))};function br(t,e){return yr(t,e||1,_r,xr,cr)}const wr={[Pn]:t=>t.getUTCFullYear(),[jn]:t=>Math.floor(t.getUTCMonth()/3),[In]:t=>t.getUTCMonth(),[Hn]:t=>t.getUTCDate(),[Vn]:t=>t.getUTCHours(),[Xn]:t=>t.getUTCMinutes(),[Jn]:t=>t.getUTCSeconds(),[Zn]:t=>t.getUTCMilliseconds(),[Gn]:t=>dr(t),[Wn]:t=>pr(t),[Yn]:(t,e)=>vr(1,t.getUTCDay(),gr(e)),[Wn+Yn]:(t,e)=>vr(pr(t),t.getUTCDay(),gr(e))},kr={[jn]:t=>3*t,[Wn]:(t,e)=>vr(t,0,gr(e))};function Ar(t,e){return yr(t,e||1,wr,kr,mr)}const Mr={[Pn]:zn,[jn]:Tn.every(3),[In]:Tn,[Wn]:yn,[Hn]:dn,[Yn]:dn,[Gn]:dn,[Vn]:fn,[Xn]:ln,[Jn]:un,[Zn]:Ke},Er={[Pn]:Nn,[jn]:Bn.every(3),[In]:Bn,[Wn]:Mn,[Hn]:pn,[Yn]:pn,[Gn]:pn,[Vn]:hn,[Xn]:cn,[Jn]:un,[Zn]:Ke};function Dr(t){return Mr[t]}function Cr(t){return Er[t]}function Fr(t,e,n){return t?t.offset(e,n):void 0}function Sr(t,e,n){return Fr(Dr(t),e,n)}function $r(t,e,n){return Fr(Cr(t),e,n)}function Tr(t,e,n,r){return t?t.range(e,n,r):void 0}function Br(t,e,n,r){return Tr(Dr(t),e,n,r)}function zr(t,e,n,r){return Tr(Cr(t),e,n,r)}const Nr=1e3,Or=6e4,Rr=36e5,Lr=864e5,Ur=2592e6,qr=31536e6,Pr=[Pn,In,Hn,Vn,Xn,Jn,Zn],jr=Pr.slice(0,-1),Ir=jr.slice(0,-1),Wr=Ir.slice(0,-1),Hr=Wr.slice(0,-1),Yr=[Pn,In],Gr=[Pn],Vr=[[jr,1,Nr],[jr,5,5e3],[jr,15,15e3],[jr,30,3e4],[Ir,1,Or],[Ir,5,3e5],[Ir,15,9e5],[Ir,30,18e5],[Wr,1,Rr],[Wr,3,108e5],[Wr,6,216e5],[Wr,12,432e5],[Hr,1,Lr],[[Pn,Wn],1,6048e5],[Yr,1,Ur],[Yr,3,7776e6],[Gr,1,qr]];function Xr(t){const e=t.extent,n=t.maxbins||40,r=Math.abs(Et(e))/n;let i,o,a=te((t=>t[2])).right(Vr,r);return a===Vr.length?(i=Gr,o=xe(e[0]/qr,e[1]/qr,n)):a?(a=Vr[r/Vr[a-1][2]=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:bo,s:wo,S:Pi,u:ji,U:Ii,V:Hi,w:Yi,W:Gi,x:null,X:null,y:Vi,Y:Ji,Z:Qi,"%":xo},x={a:function(t){return a[t.getUTCDay()]},A:function(t){return o[t.getUTCDay()]},b:function(t){return u[t.getUTCMonth()]},B:function(t){return s[t.getUTCMonth()]},c:null,d:Ki,e:Ki,f:io,g:mo,G:vo,H:to,I:eo,j:no,L:ro,m:oo,M:ao,p:function(t){return i[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:bo,s:wo,S:so,u:uo,U:lo,V:fo,w:ho,W:po,x:null,X:null,y:go,Y:yo,Z:_o,"%":xo},b={a:function(t,e,n){var r=d.exec(e.slice(n));return r?(t.w=p.get(r[0].toLowerCase()),n+r[0].length):-1},A:function(t,e,n){var r=f.exec(e.slice(n));return r?(t.w=h.get(r[0].toLowerCase()),n+r[0].length):-1},b:function(t,e,n){var r=y.exec(e.slice(n));return r?(t.m=v.get(r[0].toLowerCase()),n+r[0].length):-1},B:function(t,e,n){var r=g.exec(e.slice(n));return r?(t.m=m.get(r[0].toLowerCase()),n+r[0].length):-1},c:function(t,n,r){return A(t,e,n,r)},d:ki,e:ki,f:Fi,g:_i,G:vi,H:Mi,I:Mi,j:Ai,L:Ci,m:wi,M:Ei,p:function(t,e,n){var r=l.exec(e.slice(n));return r?(t.p=c.get(r[0].toLowerCase()),n+r[0].length):-1},q:bi,Q:$i,s:Ti,S:Di,u:pi,U:gi,V:mi,w:di,W:yi,x:function(t,e,r){return A(t,n,e,r)},X:function(t,e,n){return A(t,r,e,n)},y:_i,Y:vi,Z:xi,"%":Si};function w(t,e){return function(n){var r,i,o,a=[],s=-1,u=0,l=t.length;for(n instanceof Date||(n=new Date(+n));++s53)return null;"w"in o||(o.w=1),"Z"in o?(i=(r=Zr(Qr(o.y,0,1))).getUTCDay(),r=i>4||0===i?En.ceil(r):En(r),r=pn.offset(r,7*(o.V-1)),o.y=r.getUTCFullYear(),o.m=r.getUTCMonth(),o.d=r.getUTCDate()+(o.w+6)%7):(i=(r=Jr(Qr(o.y,0,1))).getDay(),r=i>4||0===i?vn.ceil(r):vn(r),r=dn.offset(r,7*(o.V-1)),o.y=r.getFullYear(),o.m=r.getMonth(),o.d=r.getDate()+(o.w+6)%7)}else("W"in o||"U"in o)&&("w"in o||(o.w="u"in o?o.u%7:"W"in o?1:0),i="Z"in o?Zr(Qr(o.y,0,1)).getUTCDay():Jr(Qr(o.y,0,1)).getDay(),o.m=0,o.d="W"in o?(o.w+6)%7+7*o.W-(i+5)%7:o.w+7*o.U-(i+6)%7);return"Z"in o?(o.H+=o.Z/100|0,o.M+=o.Z%100,Zr(o)):Jr(o)}}function A(t,e,n,r){for(var i,o,a=0,s=e.length,u=n.length;a=u)return-1;if(37===(i=e.charCodeAt(a++))){if(i=e.charAt(a++),!(o=b[i in oi?e.charAt(a++):i])||(r=o(t,n,r))<0)return-1}else if(i!=n.charCodeAt(r++))return-1}return r}return _.x=w(n,_),_.X=w(r,_),_.c=w(e,_),x.x=w(n,x),x.X=w(r,x),x.c=w(e,x),{format:function(t){var e=w(t+="",_);return e.toString=function(){return t},e},parse:function(t){var e=k(t+="",!1);return e.toString=function(){return t},e},utcFormat:function(t){var e=w(t+="",x);return e.toString=function(){return t},e},utcParse:function(t){var e=k(t+="",!0);return e.toString=function(){return t},e}}}var ti,ei,ni,ri,ii,oi={"-":"",_:" ",0:"0"},ai=/^\s*\d+/,si=/^%/,ui=/[\\^$*+?|[\]().{}]/g;function li(t,e,n){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o[t.toLowerCase(),e])))}function di(t,e,n){var r=ai.exec(e.slice(n,n+1));return r?(t.w=+r[0],n+r[0].length):-1}function pi(t,e,n){var r=ai.exec(e.slice(n,n+1));return r?(t.u=+r[0],n+r[0].length):-1}function gi(t,e,n){var r=ai.exec(e.slice(n,n+2));return r?(t.U=+r[0],n+r[0].length):-1}function mi(t,e,n){var r=ai.exec(e.slice(n,n+2));return r?(t.V=+r[0],n+r[0].length):-1}function yi(t,e,n){var r=ai.exec(e.slice(n,n+2));return r?(t.W=+r[0],n+r[0].length):-1}function vi(t,e,n){var r=ai.exec(e.slice(n,n+4));return r?(t.y=+r[0],n+r[0].length):-1}function _i(t,e,n){var r=ai.exec(e.slice(n,n+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function xi(t,e,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(n,n+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function bi(t,e,n){var r=ai.exec(e.slice(n,n+1));return r?(t.q=3*r[0]-3,n+r[0].length):-1}function wi(t,e,n){var r=ai.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function ki(t,e,n){var r=ai.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function Ai(t,e,n){var r=ai.exec(e.slice(n,n+3));return r?(t.m=0,t.d=+r[0],n+r[0].length):-1}function Mi(t,e,n){var r=ai.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function Ei(t,e,n){var r=ai.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function Di(t,e,n){var r=ai.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function Ci(t,e,n){var r=ai.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function Fi(t,e,n){var r=ai.exec(e.slice(n,n+6));return r?(t.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function Si(t,e,n){var r=si.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function $i(t,e,n){var r=ai.exec(e.slice(n));return r?(t.Q=+r[0],n+r[0].length):-1}function Ti(t,e,n){var r=ai.exec(e.slice(n));return r?(t.s=+r[0],n+r[0].length):-1}function Bi(t,e){return li(t.getDate(),e,2)}function zi(t,e){return li(t.getHours(),e,2)}function Ni(t,e){return li(t.getHours()%12||12,e,2)}function Oi(t,e){return li(1+dn.count(zn(t),t),e,3)}function Ri(t,e){return li(t.getMilliseconds(),e,3)}function Li(t,e){return Ri(t,e)+"000"}function Ui(t,e){return li(t.getMonth()+1,e,2)}function qi(t,e){return li(t.getMinutes(),e,2)}function Pi(t,e){return li(t.getSeconds(),e,2)}function ji(t){var e=t.getDay();return 0===e?7:e}function Ii(t,e){return li(yn.count(zn(t)-1,t),e,2)}function Wi(t){var e=t.getDay();return e>=4||0===e?bn(t):bn.ceil(t)}function Hi(t,e){return t=Wi(t),li(bn.count(zn(t),t)+(4===zn(t).getDay()),e,2)}function Yi(t){return t.getDay()}function Gi(t,e){return li(vn.count(zn(t)-1,t),e,2)}function Vi(t,e){return li(t.getFullYear()%100,e,2)}function Xi(t,e){return li((t=Wi(t)).getFullYear()%100,e,2)}function Ji(t,e){return li(t.getFullYear()%1e4,e,4)}function Zi(t,e){var n=t.getDay();return li((t=n>=4||0===n?bn(t):bn.ceil(t)).getFullYear()%1e4,e,4)}function Qi(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+li(e/60|0,"0",2)+li(e%60,"0",2)}function Ki(t,e){return li(t.getUTCDate(),e,2)}function to(t,e){return li(t.getUTCHours(),e,2)}function eo(t,e){return li(t.getUTCHours()%12||12,e,2)}function no(t,e){return li(1+pn.count(Nn(t),t),e,3)}function ro(t,e){return li(t.getUTCMilliseconds(),e,3)}function io(t,e){return ro(t,e)+"000"}function oo(t,e){return li(t.getUTCMonth()+1,e,2)}function ao(t,e){return li(t.getUTCMinutes(),e,2)}function so(t,e){return li(t.getUTCSeconds(),e,2)}function uo(t){var e=t.getUTCDay();return 0===e?7:e}function lo(t,e){return li(Mn.count(Nn(t)-1,t),e,2)}function co(t){var e=t.getUTCDay();return e>=4||0===e?Fn(t):Fn.ceil(t)}function fo(t,e){return t=co(t),li(Fn.count(Nn(t),t)+(4===Nn(t).getUTCDay()),e,2)}function ho(t){return t.getUTCDay()}function po(t,e){return li(En.count(Nn(t)-1,t),e,2)}function go(t,e){return li(t.getUTCFullYear()%100,e,2)}function mo(t,e){return li((t=co(t)).getUTCFullYear()%100,e,2)}function yo(t,e){return li(t.getUTCFullYear()%1e4,e,4)}function vo(t,e){var n=t.getUTCDay();return li((t=n>=4||0===n?Fn(t):Fn.ceil(t)).getUTCFullYear()%1e4,e,4)}function _o(){return"+0000"}function xo(){return"%"}function bo(t){return+t}function wo(t){return Math.floor(+t/1e3)}function ko(t){const e={};return n=>e[n]||(e[n]=t(n))}function Ao(t){const e=ko(t.format),n=t.formatPrefix;return{format:e,formatPrefix:n,formatFloat(t){const n=Oe(t||",");if(null==n.precision){switch(n.precision=12,n.type){case"%":n.precision-=2;break;case"e":n.precision-=1}return r=e(n),i=e(".1f")(1)[1],t=>{const e=r(t),n=e.indexOf(i);if(n<0)return e;let o=function(t,e){let n,r=t.lastIndexOf("e");if(r>0)return r;for(r=t.length;--r>e;)if(n=t.charCodeAt(r),n>=48&&n<=57)return r+1}(e,n);const a=on;)if("0"!==e[o]){++o;break}return e.slice(0,o)+a}}return e(n);var r,i},formatSpan(t,r,i,o){o=Oe(null==o?",f":o);const a=xe(t,r,i),s=Math.max(Math.abs(t),Math.abs(r));let u;if(null==o.precision)switch(o.type){case"s":return isNaN(u=Ve(a,s))||(o.precision=u),n(o,s);case"":case"e":case"g":case"p":case"r":isNaN(u=Xe(a,s))||(o.precision=u-("e"===o.type));break;case"f":case"%":isNaN(u=Ge(a))||(o.precision=u-2*("%"===o.type))}return e(o)}}}let Mo,Eo;function Do(){return Mo=Ao({format:je,formatPrefix:Ie})}function Co(t){return Ao(Ye(t))}function Fo(t){return arguments.length?Mo=Co(t):Mo}function So(t,e,n){A(n=n||{})||s(`Invalid time multi-format specifier: ${n}`);const r=e(Jn),i=e(Xn),o=e(Vn),a=e(Hn),u=e(Wn),l=e(In),c=e(jn),f=e(Pn),h=t(n[Zn]||".%L"),d=t(n[Jn]||":%S"),p=t(n[Xn]||"%I:%M"),g=t(n[Vn]||"%I %p"),m=t(n[Hn]||n[Yn]||"%a %d"),y=t(n[Wn]||"%b %d"),v=t(n[In]||"%B"),_=t(n[jn]||"%B"),x=t(n[Pn]||"%Y");return t=>(r(t)_t(t)?e(t):So(e,Dr,t),utcFormat:t=>_t(t)?n(t):So(n,Cr,t),timeParse:ko(t.parse),utcParse:ko(t.utcParse)}}function To(){return Eo=$o({format:ei,parse:ni,utcFormat:ri,utcParse:ii})}function Bo(t){return $o(Kr(t))}function zo(t){return arguments.length?Eo=Bo(t):Eo}!function(t){ti=Kr(t),ei=ti.format,ni=ti.parse,ri=ti.utcFormat,ii=ti.utcParse}({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}),Do(),To();const No=(t,e)=>ot({},t,e);function Oo(t,e){const n=t?Co(t):Fo(),r=e?Bo(e):zo();return No(n,r)}function Ro(t,e){const n=arguments.length;return n&&2!==n&&s("defaultLocale expects either zero or two arguments."),n?No(Fo(t),zo(e)):No(Fo(),zo())}const Lo=/^(data:|([A-Za-z]+:)?\/\/)/,Uo=/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp|file|data):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i,qo=/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g,Po="file://";async function jo(t,e){const n=await this.sanitize(t,e),r=n.href;return n.localFile?this.file(r):this.http(r,e)}async function Io(t,e){e=ot({},this.options,e);const n=this.fileAccess,r={href:null};let i,o,a;const u=Uo.test(t.replace(qo,""));null!=t&&"string"==typeof t&&u||s("Sanitize failure, invalid URI: "+Dt(t));const l=Lo.test(t);return(a=e.baseURL)&&!l&&(t.startsWith("/")||a.endsWith("/")||(t="/"+t),t=a+t),o=(i=t.startsWith(Po))||"file"===e.mode||"http"!==e.mode&&!l&&n,i?t=t.slice(Po.length):t.startsWith("//")&&("file"===e.defaultProtocol?(t=t.slice(2),o=!0):t=(e.defaultProtocol||"http")+":"+t),Object.defineProperty(r,"localFile",{value:!!o}),r.href=t,e.target&&(r.target=e.target+""),e.rel&&(r.rel=e.rel+""),"image"===e.context&&e.crossOrigin&&(r.crossOrigin=e.crossOrigin+""),r}function Wo(t){return Ho}async function Ho(){s("No file system access.")}function Yo(t){return t?async function(e,n){const r=ot({},this.options.http,n),i=n&&n.response,o=await t(e,r);return o.ok?J(o[i])?o[i]():o.text():s(o.status+""+o.statusText)}:Go}async function Go(){s("No HTTP fetch method available.")}const Vo=t=>null!=t&&t==t,Xo=t=>!(Number.isNaN(+t)||t instanceof Date),Jo={boolean:Ct,integer:S,number:S,date:St,string:$t,unknown:f},Zo=[t=>"true"===t||"false"===t||!0===t||!1===t,t=>Xo(t)&&Number.isInteger(+t),Xo,t=>!Number.isNaN(Date.parse(t))],Qo=["boolean","integer","number","date"];function Ko(t,e){if(!t||!t.length)return"unknown";const n=t.length,r=Zo.length,i=Zo.map(((t,e)=>e+1));for(let o,a,s=0,u=0;s0===t?e:t),0)-1]}function ta(t,e){return e.reduce(((e,n)=>(e[n]=Ko(t,n),e)),{})}function ea(t){const e=function(e,n){const r={delimiter:t};return na(e,n?ot(n,r):r)};return e.responseType="text",e}function na(t,e){return e.header&&(t=e.header.map(Dt).join(e.delimiter)+"\n"+t),Wt(e.delimiter).parse(t+"")}function ra(t,e){const n=e&&e.property?l(e.property):f;return!A(t)||(r=t,"function"==typeof Buffer&&J(Buffer.isBuffer)&&Buffer.isBuffer(r))?n(JSON.parse(t)):function(t,e){!k(t)&&mt(t)&&(t=[...t]);return e&&e.copy?JSON.parse(JSON.stringify(t)):t}(n(t),e);var r}na.responseType="text",ra.responseType="json";const ia={interior:(t,e)=>t!==e,exterior:(t,e)=>t===e};function oa(t,e){let n,r,i,o;return t=ra(t,e),e&&e.feature?(n=Yt,i=e.feature):e&&e.mesh?(n=Jt,i=e.mesh,o=ia[e.filter]):s("Missing TopoJSON feature or mesh parameter."),r=(r=t.objects[i])?n(t,r,o):s("Invalid TopoJSON object: "+i),r&&r.features||[r]}oa.responseType="json";const aa={dsv:na,csv:ea(","),tsv:ea("\t"),json:ra,topojson:oa};function sa(t,e){return arguments.length>1?(aa[t]=e,this):ut(aa,t)?aa[t]:null}function ua(t){const e=sa(t);return e&&e.responseType||"text"}function la(t,e,n,r){const i=sa((e=e||{}).type||"json");return i||s("Unknown data format type: "+e.type),t=i(t,e),e.parse&&function(t,e,n,r){if(!t.length)return;const i=zo();n=n||i.timeParse,r=r||i.utcParse;let o,a,s,u,l,c,f=t.columns||Object.keys(t[0]);"auto"===e&&(e=ta(t,f));f=Object.keys(e);const h=f.map((t=>{const i=e[t];let o,a;if(i&&(i.startsWith("date:")||i.startsWith("utc:"))){o=i.split(/:(.+)?/,2),a=o[1],("'"===a[0]&&"'"===a[a.length-1]||'"'===a[0]&&'"'===a[a.length-1])&&(a=a.slice(1,-1));return("utc"===o[0]?r:n)(a)}if(!Jo[i])throw Error("Illegal format pattern: "+t+":"+i);return Jo[i]}));for(s=0,l=t.length,c=f.length;s({options:e||{},sanitize:Io,load:jo,fileAccess:!1,file:Wo(),http:Yo(t)})}("undefined"!=typeof fetch&&fetch);function fa(t){const e=t||f,n=[],r={};return n.add=t=>{const i=e(t);return r[i]||(r[i]=1,n.push(t)),n},n.remove=t=>{const i=e(t);if(r[i]){r[i]=0;const e=n.indexOf(t);e>=0&&n.splice(e,1)}return n},n}async function ha(t,e){try{await e(t)}catch(e){t.error(e)}}const da=Symbol("vega_id");let pa=1;function ga(t){return!(!t||!ma(t))}function ma(t){return t[da]}function ya(t,e){return t[da]=e,t}function va(t){const e=t===Object(t)?t:{data:t};return ma(e)?e:ya(e,pa++)}function _a(t){return xa(t,va({}))}function xa(t,e){for(const n in t)e[n]=t[n];return e}function ba(t,e){return ya(e,ma(t))}function wa(t,e){return t?e?(n,r)=>t(n,r)||ma(e(n))-ma(e(r)):(e,n)=>t(e,n)||ma(e)-ma(n):null}function ka(t){return t&&t.constructor===Aa}function Aa(){const t=[],e=[],n=[],r=[],i=[];let o=null,a=!1;return{constructor:Aa,insert(e){const n=V(e),r=n.length;for(let e=0;e{p(t)&&(l[ma(t)]=-1)}));for(f=0,h=t.length;f0&&(y(g,p,d.value),s.modifies(p));for(f=0,h=i.length;f{p(t)&&l[ma(t)]>0&&y(t,d.field,d.value)})),s.modifies(d.field);if(a)s.mod=e.length||r.length?u.filter((t=>l[ma(t)]>0)):u.slice();else for(m in c)s.mod.push(c[m]);return(o||null==o&&(e.length||r.length))&&s.clean(!0),s}}}const Ma="_:mod:_";function Ea(){Object.defineProperty(this,Ma,{writable:!0,value:{}})}Ea.prototype={set(t,e,n,r){const i=this,o=i[t],a=i[Ma];return null!=e&&e>=0?(o[e]!==n||r)&&(o[e]=n,a[e+":"+t]=-1,a[t]=-1):(o!==n||r)&&(i[t]=n,a[t]=k(n)?1+n.length:-1),i},modified(t,e){const n=this[Ma];if(!arguments.length){for(const t in n)if(n[t])return!0;return!1}if(k(t)){for(let e=0;e=0?e+1{a instanceof Fa?(a!==this&&(e&&a.targets().add(this),o.push(a)),i.push({op:a,name:t,index:n})):r.set(t,n,a)};for(a in t)if(u=t[a],"pulse"===a)V(u).forEach((t=>{t instanceof Fa?t!==this&&(t.targets().add(this),o.push(t)):s("Pulse parameters must be operator instances.")})),this.source=u;else if(k(u))for(r.set(a,-1,Array(l=u.length)),c=0;c{const n=Date.now();return n-e>t?(e=n,1):0}))},debounce(t){const e=Ba();return this.targets().add(Ba(null,null,it(t,(t=>{const n=t.dataflow;e.receive(t),n&&n.run&&n.run()})))),e},between(t,e){let n=!1;return t.targets().add(Ba(null,null,(()=>n=!0))),e.targets().add(Ba(null,null,(()=>n=!1))),this.filter((()=>n))},detach(){this._filter=p,this._targets=null}};const za={skip:!0};function Na(t,e,n,r,i,o){const a=ot({},o,za);let s,u;J(n)||(n=rt(n)),void 0===r?s=e=>t.touch(n(e)):J(r)?(u=new Fa(null,r,i,!1),s=e=>{u.evaluate(e);const r=n(e),i=u.value;ka(i)?t.pulse(r,i,o):t.update(r,i,a)}):s=e=>t.update(n(e),r,a),e.apply(s)}function Oa(t,e,n,r,i,o){if(void 0===r)e.targets().add(n);else{const a=o||{},s=new Fa(null,function(t,e){return e=J(e)?e:rt(e),t?function(n,r){const i=e(n,r);return t.skip()||(t.skip(i!==this.value).value=i),i}:e}(n,r),i,!1);s.modified(a.force),s.rank=e.rank,e.targets().add(s),n&&(s.skip(!0),s.value=n.value,s.targets().add(n),t.connect(n,[s]))}}const Ra={};function La(t,e,n){this.dataflow=t,this.stamp=null==e?-1:e,this.add=[],this.rem=[],this.mod=[],this.fields=null,this.encode=n||null}function Ua(t,e){const n=[];return zt(t,e,(t=>n.push(t))),n}function qa(t,e){const n={};return t.visit(e,(t=>{n[ma(t)]=1})),t=>n[ma(t)]?null:t}function Pa(t,e){return t?(n,r)=>t(n,r)&&e(n,r):e}function ja(t,e,n,r){const i=this;let o=0;this.dataflow=t,this.stamp=e,this.fields=null,this.encode=r||null,this.pulses=n;for(const t of n)if(t.stamp===e){if(t.fields){const e=i.fields||(i.fields={});for(const n in t.fields)e[n]=1}t.changed(i.ADD)&&(o|=i.ADD),t.changed(i.REM)&&(o|=i.REM),t.changed(i.MOD)&&(o|=i.MOD)}this.changes=o}function Ia(t){return t.error("Dataflow already running. Use runAsync() to chain invocations."),t}La.prototype={StopPropagation:Ra,ADD:1,REM:2,MOD:4,ADD_REM:3,ADD_MOD:5,ALL:7,REFLOW:8,SOURCE:16,NO_SOURCE:32,NO_FIELDS:64,fork(t){return new La(this.dataflow).init(this,t)},clone(){const t=this.fork(7);return t.add=t.add.slice(),t.rem=t.rem.slice(),t.mod=t.mod.slice(),t.source&&(t.source=t.source.slice()),t.materialize(23)},addAll(){let t=this;return!t.source||t.add===t.rem||!t.rem.length&&t.source.length===t.add.length||(t=new La(this.dataflow).init(this),t.add=t.source,t.rem=[]),t},init(t,e){const n=this;return n.stamp=t.stamp,n.encode=t.encode,!t.fields||64&e||(n.fields=t.fields),1&e?(n.addF=t.addF,n.add=t.add):(n.addF=null,n.add=[]),2&e?(n.remF=t.remF,n.rem=t.rem):(n.remF=null,n.rem=[]),4&e?(n.modF=t.modF,n.mod=t.mod):(n.modF=null,n.mod=[]),32&e?(n.srcF=null,n.source=null):(n.srcF=t.srcF,n.source=t.source,t.cleans&&(n.cleans=t.cleans)),n},runAfter(t){this.dataflow.runAfter(t)},changed(t){const e=t||7;return 1&e&&this.add.length||2&e&&this.rem.length||4&e&&this.mod.length},reflow(t){if(t)return this.fork(7).reflow();const e=this.add.length,n=this.source&&this.source.length;return n&&n!==e&&(this.mod=this.source,e&&this.filter(4,qa(this,1))),this},clean(t){return arguments.length?(this.cleans=!!t,this):this.cleans},modifies(t){const e=this.fields||(this.fields={});return k(t)?t.forEach((t=>e[t]=!0)):e[t]=!0,this},modified(t,e){const n=this.fields;return!(!e&&!this.mod.length||!n)&&(arguments.length?k(t)?t.some((t=>n[t])):n[t]:!!n)},filter(t,e){const n=this;return 1&t&&(n.addF=Pa(n.addF,e)),2&t&&(n.remF=Pa(n.remF,e)),4&t&&(n.modF=Pa(n.modF,e)),16&t&&(n.srcF=Pa(n.srcF,e)),n},materialize(t){const e=this;return 1&(t=t||7)&&e.addF&&(e.add=Ua(e.add,e.addF),e.addF=null),2&t&&e.remF&&(e.rem=Ua(e.rem,e.remF),e.remF=null),4&t&&e.modF&&(e.mod=Ua(e.mod,e.modF),e.modF=null),16&t&&e.srcF&&(e.source=e.source.filter(e.srcF),e.srcF=null),e},visit(t,e){const n=this,r=e;if(16&t)return zt(n.source,n.srcF,r),n;1&t&&zt(n.add,n.addF,r),2&t&&zt(n.rem,n.remF,r),4&t&&zt(n.mod,n.modF,r);const i=n.source;if(8&t&&i){const t=n.add.length+n.mod.length;t===i.length||zt(i,t?qa(n,5):n.srcF,r)}return n}},ht(ja,La,{fork(t){const e=new La(this.dataflow).init(this,t&this.NO_FIELDS);return void 0!==t&&(t&e.ADD&&this.visit(e.ADD,(t=>e.add.push(t))),t&e.REM&&this.visit(e.REM,(t=>e.rem.push(t))),t&e.MOD&&this.visit(e.MOD,(t=>e.mod.push(t)))),e},changed(t){return this.changes&t},modified(t){const e=this,n=e.fields;return n&&e.changes&e.MOD?k(t)?t.some((t=>n[t])):n[t]:0},filter(){s("MultiPulse does not support filtering.")},materialize(){s("MultiPulse does not support materialization.")},visit(t,e){const n=this,r=n.pulses,i=r.length;let o=0;if(t&n.SOURCE)for(;oe=[],size:()=>e.length,peek:()=>e[0],push:n=>(e.push(n),Ya(e,0,e.length-1,t)),pop:()=>{const n=e.pop();let r;return e.length?(r=e[0],e[0]=n,function(t,e,n){const r=e,i=t.length,o=t[e];let a,s=1+(e<<1);for(;s=0&&(s=a),t[e]=t[s],s=1+((e=s)<<1);t[e]=o,Ya(t,r,e,n)}(e,0,t)):r=n,r}}}function Ya(t,e,n,r){let i,o;const a=t[n];for(;n>e&&(o=n-1>>1,i=t[o],r(a,i)<0);)t[n]=i,n=o;return t[n]=a}function Ga(){this.logger(w()),this.logLevel(v),this._clock=0,this._rank=0,this._locale=Ro();try{this._loader=ca()}catch(t){}this._touched=fa(c),this._input={},this._pulse=null,this._heap=Ha(((t,e)=>t.qrank-e.qrank)),this._postrun=[]}function Va(t){return function(){return this._log[t].apply(this,arguments)}}function Xa(t,e){Fa.call(this,t,null,e)}Ga.prototype={stamp(){return this._clock},loader(t){return arguments.length?(this._loader=t,this):this._loader},locale(t){return arguments.length?(this._locale=t,this):this._locale},logger(t){return arguments.length?(this._log=t,this):this._log},error:Va("error"),warn:Va("warn"),info:Va("info"),debug:Va("debug"),logLevel:Va("level"),cleanThreshold:1e4,add:function(t,e,n,r){let i,o=1;return t instanceof Fa?i=t:t&&t.prototype instanceof Fa?i=new t:J(t)?i=new Fa(null,t):(o=0,i=new Fa(t,e)),this.rank(i),o&&(r=n,n=e),n&&this.connect(i,i.parameters(n,r)),this.touch(i),i},connect:function(t,e){const n=t.rank,r=e.length;for(let i=0;i=0;)e.push(n=r[i]),n===t&&s("Cycle detected in dataflow graph.")},pulse:function(t,e,n){this.touch(t,n||Wa);const r=new La(this,this._clock+(this._pulse?0:1)),i=t.pulse&&t.pulse.source||[];return r.target=t,this._input[t.id]=e.pulse(r,i),this},touch:function(t,e){const n=e||Wa;return this._pulse?this._enqueue(t):this._touched.add(t),n.skip&&t.skip(!0),this},update:function(t,e,n){const r=n||Wa;return(t.set(e)||r.force)&&this.touch(t,r),this},changeset:Aa,ingest:function(t,e,n){return e=this.parse(e,n),this.pulse(t,this.changeset().insert(e))},parse:function(t,e){const n=this.locale();return la(t,e,n.timeParse,n.utcParse)},preload:async function(t,e,n){const r=this,i=r._pending||function(t){let e;const n=new Promise((t=>e=t));return n.requests=0,n.done=()=>{0==--n.requests&&(t._pending=null,e(t))},t._pending=n}(r);i.requests+=1;const o=await r.request(e,n);return r.pulse(t,r.changeset().remove(p).insert(o.data||[])),i.done(),o},request:async function(t,e){const n=this;let r,i=0;try{r=await n.loader().load(t,{context:"dataflow",response:ua(e&&e.type)});try{r=n.parse(r,e)}catch(e){i=-2,n.warn("Data ingestion failed",t,e)}}catch(e){i=-1,n.warn("Loading failed",t,e)}return{data:r,status:i}},events:function(t,e,n,r){const i=this,o=Ba(n,r),a=function(t){t.dataflow=i;try{o.receive(t)}catch(t){i.error(t)}finally{i.run()}};let s;s="string"==typeof t&&"undefined"!=typeof document?document.querySelectorAll(t):V(t);const u=s.length;for(let t=0;tr._enqueue(t,!0))),r._touched=fa(c);let a,s,u,l=0;try{for(;r._heap.size()>0;)a=r._heap.pop(),a.rank===a.qrank?(s=a.run(r._getPulse(a,t)),s.then?s=await s:s.async&&(i.push(s.async),s=Ra),s!==Ra&&a._targets&&a._targets.forEach((t=>r._enqueue(t))),++l):r._enqueue(a,!0)}catch(t){r._heap.clear(),u=t}if(r._input={},r._pulse=null,r.debug(`Pulse ${o}: ${l} operators`),u&&(r._postrun=[],r.error(u)),r._postrun.length){const t=r._postrun.sort(((t,e)=>e.priority-t.priority));r._postrun=[];for(let e=0;er.runAsync(null,(()=>{t.forEach((t=>{try{t(r)}catch(t){r.error(t)}}))})))),r},run:function(t,e,n){return this._pulse?Ia(this):(this.evaluate(t,e,n),this)},runAsync:async function(t,e,n){for(;this._running;)await this._running;const r=()=>this._running=null;return(this._running=this.evaluate(t,e,n)).then(r,r),this._running},runAfter:function(t,e,n){if(this._pulse||e)this._postrun.push({priority:n||0,callback:t});else try{t(this)}catch(t){this.error(t)}},_enqueue:function(t,e){const n=t.stampt.pulse)),e):this._input[t.id]||function(t,e){if(e&&e.stamp===t.stamp)return e;t=t.fork(),e&&e!==Ra&&(t.source=e.source);return t}(this._pulse,n&&n.pulse)}},ht(Xa,Fa,{run(t){if(t.stampthis.pulse=t)):e!==t.StopPropagation&&(this.pulse=e),e},evaluate(t){const e=this.marshall(t.stamp),n=this.transform(e,t);return e.clear(),n},transform(){}});const Ja={};function Za(t){const e=Qa(t);return e&&e.Definition||null}function Qa(t){return t=t&&t.toLowerCase(),ut(Ja,t)?Ja[t]:null}function*Ka(t,e){if(null==e)for(let e of t)null!=e&&""!==e&&(e=+e)>=e&&(yield e);else{let n=-1;for(let r of t)r=e(r,++n,t),null!=r&&""!==r&&(r=+r)>=r&&(yield r)}}function ts(t,e,n){const r=Float64Array.from(Ka(t,n));return r.sort(Qt),e.map((t=>Ee(r,t)))}function es(t,e){return ts(t,[.25,.5,.75],e)}function ns(t,e){const n=t.length,r=function(t,e){const n=function(t,e){let n,r=0,i=0,o=0;if(void 0===e)for(let e of t)null!=e&&(e=+e)>=e&&(n=e-i,i+=n/++r,o+=n*(e-i));else{let a=-1;for(let s of t)null!=(s=e(s,++a,t))&&(s=+s)>=s&&(n=s-i,i+=n/++r,o+=n*(s-i))}if(r>1)return o/(r-1)}(t,e);return n?Math.sqrt(n):n}(t,e),i=es(t,e),o=(i[2]-i[0])/1.34;return 1.06*(Math.min(r,o)||r||Math.abs(i[0])||1)*Math.pow(n,-.2)}function rs(t){const e=t.maxbins||20,n=t.base||10,r=Math.log(n),i=t.divide||[5,2];let o,a,s,u,l,c,f=t.extent[0],h=t.extent[1];const d=t.span||h-f||Math.abs(f)||1;if(t.step)o=t.step;else if(t.steps){for(u=d/e,l=0,c=t.steps.length;le;)o*=n;for(l=0,c=i.length;l=s&&d/u<=e&&(o=u)}u=Math.log(o);const p=u>=0?0:1+~~(-u/r),g=Math.pow(n,-p-1);return(t.nice||void 0===t.nice)&&(u=Math.floor(f/o+g)*o,f=ft);const i=t.length,o=new Float64Array(i);let a,s=0,u=1,l=r(t[0]),c=l,f=l+e;for(;u=f){for(c=(l+c)/2;s>1);ia;)t[i--]=t[o]}o=a,a=r}return t}(o,e+e/4):o}t.random=Math.random;const as=Math.sqrt(2*Math.PI),ss=Math.SQRT2;let us=NaN;function ls(e,n){e=e||0,n=null==n?1:n;let r,i,o=0,a=0;if(us==us)o=us,us=NaN;else{do{o=2*t.random()-1,a=2*t.random()-1,r=o*o+a*a}while(0===r||r>1);i=Math.sqrt(-2*Math.log(r)/r),o*=i,us=a*i}return e+o*n}function cs(t,e,n){const r=(t-(e||0))/(n=null==n?1:n);return Math.exp(-.5*r*r)/(n*as)}function fs(t,e,n){const r=(t-(e=e||0))/(n=null==n?1:n),i=Math.abs(r);let o;if(i>37)o=0;else{const t=Math.exp(-i*i/2);let e;i<7.07106781186547?(e=.0352624965998911*i+.700383064443688,e=e*i+6.37396220353165,e=e*i+33.912866078383,e=e*i+112.079291497871,e=e*i+221.213596169931,e=e*i+220.206867912376,o=t*e,e=.0883883476483184*i+1.75566716318264,e=e*i+16.064177579207,e=e*i+86.7807322029461,e=e*i+296.564248779674,e=e*i+637.333633378831,e=e*i+793.826512519948,e=e*i+440.413735824752,o/=e):(e=i+.65,e=i+4/e,e=i+3/e,e=i+2/e,e=i+1/e,o=t/e/2.506628274631)}return r>0?1-o:o}function hs(t,e,n){return t<0||t>1?NaN:(e||0)+(null==n?1:n)*ss*function(t){let e,n=-Math.log((1-t)*(1+t));n<6.25?(n-=3.125,e=-364441206401782e-35,e=e*n-16850591381820166e-35,e=128584807152564e-32+e*n,e=11157877678025181e-33+e*n,e=e*n-1333171662854621e-31,e=20972767875968562e-33+e*n,e=6637638134358324e-30+e*n,e=e*n-4054566272975207e-29,e=e*n-8151934197605472e-29,e=26335093153082323e-28+e*n,e=e*n-12975133253453532e-27,e=e*n-5415412054294628e-26,e=1.0512122733215323e-9+e*n,e=e*n-4.112633980346984e-9,e=e*n-2.9070369957882005e-8,e=4.2347877827932404e-7+e*n,e=e*n-13654692000834679e-22,e=e*n-13882523362786469e-21,e=.00018673420803405714+e*n,e=e*n-.000740702534166267,e=e*n-.006033670871430149,e=.24015818242558962+e*n,e=1.6536545626831027+e*n):n<16?(n=Math.sqrt(n)-3.25,e=2.2137376921775787e-9,e=9.075656193888539e-8+e*n,e=e*n-2.7517406297064545e-7,e=1.8239629214389228e-8+e*n,e=15027403968909828e-22+e*n,e=e*n-4013867526981546e-21,e=29234449089955446e-22+e*n,e=12475304481671779e-21+e*n,e=e*n-47318229009055734e-21,e=6828485145957318e-20+e*n,e=24031110387097894e-21+e*n,e=e*n-.0003550375203628475,e=.0009532893797373805+e*n,e=e*n-.0016882755560235047,e=.002491442096107851+e*n,e=e*n-.003751208507569241,e=.005370914553590064+e*n,e=1.0052589676941592+e*n,e=3.0838856104922208+e*n):Number.isFinite(n)?(n=Math.sqrt(n)-5,e=-27109920616438573e-27,e=e*n-2.555641816996525e-10,e=1.5076572693500548e-9+e*n,e=e*n-3.789465440126737e-9,e=7.61570120807834e-9+e*n,e=e*n-1.496002662714924e-8,e=2.914795345090108e-8+e*n,e=e*n-6.771199775845234e-8,e=2.2900482228026655e-7+e*n,e=e*n-9.9298272942317e-7,e=4526062597223154e-21+e*n,e=e*n-1968177810553167e-20,e=7599527703001776e-20+e*n,e=e*n-.00021503011930044477,e=e*n-.00013871931833623122,e=1.0103004648645344+e*n,e=4.849906401408584+e*n):e=1/0;return e*t}(2*t-1)}function ds(t,e){let n,r;const i={mean(t){return arguments.length?(n=t||0,i):n},stdev(t){return arguments.length?(r=null==t?1:t,i):r},sample:()=>ls(n,r),pdf:t=>cs(t,n,r),cdf:t=>fs(t,n,r),icdf:t=>hs(t,n,r)};return i.mean(t).stdev(e)}function ps(e,n){const r=ds();let i=0;const o={data(t){return arguments.length?(e=t,i=t?t.length:0,o.bandwidth(n)):e},bandwidth(t){return arguments.length?(!(n=t)&&e&&(n=ns(e)),o):n},sample:()=>e[~~(t.random()*i)]+n*r.sample(),pdf(t){let o=0,a=0;for(;ags(n,r),pdf:t=>ms(t,n,r),cdf:t=>ys(t,n,r),icdf:t=>vs(t,n,r)};return i.mean(t).stdev(e)}function xs(e,n){let r,i=0;const o={weights(t){return arguments.length?(r=function(t){const e=[];let n,r=0;for(n=0;n=e&&t<=n?1/(n-e):0}function ks(t,e,n){return null==n&&(n=null==e?1:e,e=0),tn?1:(t-e)/(n-e)}function As(t,e,n){return null==n&&(n=null==e?1:e,e=0),t>=0&&t<=1?e+t*(n-e):NaN}function Ms(t,e){let n,r;const i={min(t){return arguments.length?(n=t||0,i):n},max(t){return arguments.length?(r=null==t?1:t,i):r},sample:()=>bs(n,r),pdf:t=>ws(t,n,r),cdf:t=>ks(t,n,r),icdf:t=>As(t,n,r)};return null==e&&(e=null==t?1:t,t=0),i.min(t).max(e)}function Es(t,e,n){let r=0,i=0;for(const o of t){const t=n(o);null==e(o)||null==t||isNaN(t)||(r+=(t-r)/++i)}return{coef:[r],predict:()=>r,rSquared:0}}function Ds(t,e,n,r){const i=r-t*t,o=Math.abs(i)<1e-24?0:(n-t*e)/i;return[e-o*t,o]}function Cs(t,e,n,r){t=t.filter((t=>{let r=e(t),i=n(t);return null!=r&&(r=+r)>=r&&null!=i&&(i=+i)>=i})),r&&t.sort(((t,n)=>e(t)-e(n)));const i=t.length,o=new Float64Array(i),a=new Float64Array(i);let s,u,l,c=0,f=0,h=0;for(l of t)o[c]=s=+e(l),a[c]=u=+n(l),++c,f+=(s-f)/c,h+=(u-h)/c;for(c=0;c=i&&null!=o&&(o=+o)>=o&&r(i,o,++a)}function Ss(t,e,n,r,i){let o=0,a=0;return Fs(t,e,n,((t,e)=>{const n=e-i(t),s=e-r;o+=n*n,a+=s*s})),1-o/a}function $s(t,e,n){let r=0,i=0,o=0,a=0,s=0;Fs(t,e,n,((t,e)=>{++s,r+=(t-r)/s,i+=(e-i)/s,o+=(t*e-o)/s,a+=(t*t-a)/s}));const u=Ds(r,i,o,a),l=t=>u[0]+u[1]*t;return{coef:u,predict:l,rSquared:Ss(t,e,n,i,l)}}function Ts(t,e,n){let r=0,i=0,o=0,a=0,s=0;Fs(t,e,n,((t,e)=>{++s,t=Math.log(t),r+=(t-r)/s,i+=(e-i)/s,o+=(t*e-o)/s,a+=(t*t-a)/s}));const u=Ds(r,i,o,a),l=t=>u[0]+u[1]*Math.log(t);return{coef:u,predict:l,rSquared:Ss(t,e,n,i,l)}}function Bs(t,e,n){const[r,i,o,a]=Cs(t,e,n);let s,u,l,c=0,f=0,h=0,d=0,p=0;Fs(t,e,n,((t,e)=>{s=r[p++],u=Math.log(e),l=s*e,c+=(e*u-c)/p,f+=(l-f)/p,h+=(l*u-h)/p,d+=(s*l-d)/p}));const[g,m]=Ds(f/a,c/a,h/a,d/a),y=t=>Math.exp(g+m*(t-o));return{coef:[Math.exp(g-m*o),m],predict:y,rSquared:Ss(t,e,n,a,y)}}function zs(t,e,n){let r=0,i=0,o=0,a=0,s=0,u=0;Fs(t,e,n,((t,e)=>{const n=Math.log(t),l=Math.log(e);++u,r+=(n-r)/u,i+=(l-i)/u,o+=(n*l-o)/u,a+=(n*n-a)/u,s+=(e-s)/u}));const l=Ds(r,i,o,a),c=t=>l[0]*Math.pow(t,l[1]);return l[0]=Math.exp(l[0]),{coef:l,predict:c,rSquared:Ss(t,e,n,s,c)}}function Ns(t,e,n){const[r,i,o,a]=Cs(t,e,n),s=r.length;let u,l,c,f,h=0,d=0,p=0,g=0,m=0;for(u=0;u_*(t-=o)*t+x*t+b+a;return{coef:[b-x*o+_*o*o+a,x-2*_*o,_],predict:w,rSquared:Ss(t,e,n,a,w)}}function Os(t,e,n,r){if(0===r)return Es(t,e,n);if(1===r)return $s(t,e,n);if(2===r)return Ns(t,e,n);const[i,o,a,s]=Cs(t,e,n),u=i.length,l=[],c=[],f=r+1;let h,d,p,g,m;for(h=0;hMath.abs(t[r][a])&&(a=i);for(o=r;o=r;o--)t[o][i]-=t[o][r]*t[r][i]/t[r][r]}for(i=e-1;i>=0;--i){for(s=0,o=i+1;o{t-=a;let e=s+y[0]+y[1]*t+y[2]*t*t;for(h=3;h=0;--o)for(s=e[o],u=1,i[o]+=s,a=1;a<=o;++a)u*=(o+1-a)/a,i[o-a]+=s*Math.pow(n,a)*u;return i[0]+=r,i}function Ls(t,e,n,r){const[i,o,a,s]=Cs(t,e,n,!0),u=i.length,l=Math.max(2,~~(r*u)),c=new Float64Array(u),f=new Float64Array(u),h=new Float64Array(u).fill(1);for(let t=-1;++t<=2;){const e=[0,l-1];for(let t=0;ti[a]-n?r:a;let u=0,l=0,d=0,p=0,g=0;const m=1/Math.abs(i[s]-n||1);for(let t=r;t<=a;++t){const e=i[t],r=o[t],a=Us(Math.abs(n-e)*m)*h[t],s=e*a;u+=a,l+=s,d+=r*a,p+=r*s,g+=e*s}const[y,v]=Ds(l/u,d/u,p/u,g/u);c[t]=y+v*n,f[t]=Math.abs(o[t]-c[t]),qs(i,t+1,e)}if(2===t)break;const n=De(f);if(Math.abs(n)<1e-12)break;for(let t,e,r=0;r=1?1e-12:(e=1-t*t)*e}return function(t,e,n,r){const i=t.length,o=[];let a,s=0,u=0,l=[];for(;s=t.length))for(;e>i&&t[o]-r<=r-t[i];)n[0]=++i,n[1]=o,++o}const Ps=.5*Math.PI/180;function js(t,e,n,r){n=n||25,r=Math.max(n,r||200);const i=e=>[e,t(e)],o=e[0],a=e[1],s=a-o,u=s/r,l=[i(o)],c=[];if(n===r){for(let t=1;t0;)c.push(i(o+t/n*s));let f=l[0],h=c[c.length-1];const d=1/s,p=function(t,e){let n=t,r=t;const i=e.length;for(let t=0;tr&&(r=i)}return 1/(r-n)}(f[1],c);for(;h;){const t=i((f[0]+h[0])/2);t[0]-f[0]>=u&&Is(f,t,h,d,p)>Ps?c.push(t):(f=h,l.push(h),c.pop()),h=c[c.length-1]}return l}function Is(t,e,n,r,i){const o=Math.atan2(i*(n[1]-t[1]),r*(n[0]-t[0])),a=Math.atan2(i*(e[1]-t[1]),r*(e[0]-t[0]));return Math.abs(o-a)}function Ws(t){return t&&t.length?1===t.length?t[0]:(e=t,t=>{const n=e.length;let r=1,i=String(e[0](t));for(;r{},Gs={init:Ys,add:Ys,rem:Ys,idx:0},Vs={values:{init:t=>t.cell.store=!0,value:t=>t.cell.data.values(),idx:-1},count:{value:t=>t.cell.num},__count__:{value:t=>t.missing+t.valid},missing:{value:t=>t.missing},valid:{value:t=>t.valid},sum:{init:t=>t.sum=0,value:t=>t.valid?t.sum:void 0,add:(t,e)=>t.sum+=+e,rem:(t,e)=>t.sum-=e},product:{init:t=>t.product=1,value:t=>t.valid?t.product:void 0,add:(t,e)=>t.product*=e,rem:(t,e)=>t.product/=e},mean:{init:t=>t.mean=0,value:t=>t.valid?t.mean:void 0,add:(t,e)=>(t.mean_d=e-t.mean,t.mean+=t.mean_d/t.valid),rem:(t,e)=>(t.mean_d=e-t.mean,t.mean-=t.valid?t.mean_d/t.valid:t.mean)},average:{value:t=>t.valid?t.mean:void 0,req:["mean"],idx:1},variance:{init:t=>t.dev=0,value:t=>t.valid>1?t.dev/(t.valid-1):void 0,add:(t,e)=>t.dev+=t.mean_d*(e-t.mean),rem:(t,e)=>t.dev-=t.mean_d*(e-t.mean),req:["mean"],idx:1},variancep:{value:t=>t.valid>1?t.dev/t.valid:void 0,req:["variance"],idx:2},stdev:{value:t=>t.valid>1?Math.sqrt(t.dev/(t.valid-1)):void 0,req:["variance"],idx:2},stdevp:{value:t=>t.valid>1?Math.sqrt(t.dev/t.valid):void 0,req:["variance"],idx:2},stderr:{value:t=>t.valid>1?Math.sqrt(t.dev/(t.valid*(t.valid-1))):void 0,req:["variance"],idx:2},distinct:{value:t=>t.cell.data.distinct(t.get),req:["values"],idx:3},ci0:{value:t=>t.cell.data.ci0(t.get),req:["values"],idx:3},ci1:{value:t=>t.cell.data.ci1(t.get),req:["values"],idx:3},median:{value:t=>t.cell.data.q2(t.get),req:["values"],idx:3},q1:{value:t=>t.cell.data.q1(t.get),req:["values"],idx:3},q3:{value:t=>t.cell.data.q3(t.get),req:["values"],idx:3},min:{init:t=>t.min=void 0,value:t=>t.min=Number.isNaN(t.min)?t.cell.data.min(t.get):t.min,add:(t,e)=>{(e{e<=t.min&&(t.min=NaN)},req:["values"],idx:4},max:{init:t=>t.max=void 0,value:t=>t.max=Number.isNaN(t.max)?t.cell.data.max(t.get):t.max,add:(t,e)=>{(e>t.max||void 0===t.max)&&(t.max=e)},rem:(t,e)=>{e>=t.max&&(t.max=NaN)},req:["values"],idx:4},argmin:{init:t=>t.argmin=void 0,value:t=>t.argmin||t.cell.data.argmin(t.get),add:(t,e,n)=>{e{e<=t.min&&(t.argmin=void 0)},req:["min","values"],idx:3},argmax:{init:t=>t.argmax=void 0,value:t=>t.argmax||t.cell.data.argmax(t.get),add:(t,e,n)=>{e>t.max&&(t.argmax=n)},rem:(t,e)=>{e>=t.max&&(t.argmax=void 0)},req:["max","values"],idx:3},exponential:{init:(t,e)=>{t.exp=0,t.exp_r=e},value:t=>t.valid?t.exp*(1-t.exp_r)/(1-t.exp_r**t.valid):void 0,add:(t,e)=>t.exp=t.exp_r*t.exp+e,rem:(t,e)=>t.exp=(t.exp-e/t.exp_r**(t.valid-1))/t.exp_r},exponentialb:{value:t=>t.valid?t.exp*(1-t.exp_r):void 0,req:["exponential"],idx:1}},Xs=Object.keys(Vs).filter((t=>"__count__"!==t));function Js(t,e,n){return Vs[t](n,e)}function Zs(t,e){return t.idx-e.idx}function Qs(){this.valid=0,this.missing=0,this._ops.forEach((t=>null==t.aggregate_param?t.init(this):t.init(this,t.aggregate_param)))}function Ks(t,e){null!=t&&""!==t?t==t&&(++this.valid,this._ops.forEach((n=>n.add(this,t,e)))):++this.missing}function tu(t,e){null!=t&&""!==t?t==t&&(--this.valid,this._ops.forEach((n=>n.rem(this,t,e)))):--this.missing}function eu(t){return this._out.forEach((e=>t[e.out]=e.value(this))),t}function nu(t,e){const n=e||f,r=function(t){const e={};t.forEach((t=>e[t.name]=t));const n=t=>{t.req&&t.req.forEach((t=>{e[t]||n(e[t]=Vs[t]())}))};return t.forEach(n),Object.values(e).sort(Zs)}(t),i=t.slice().sort(Zs);function o(t){this._ops=r,this._out=i,this.cell=t,this.init()}return o.prototype.init=Qs,o.prototype.add=Ks,o.prototype.rem=tu,o.prototype.set=eu,o.prototype.get=n,o.fields=t.map((t=>t.out)),o}function ru(t){this._key=t?l(t):ma,this.reset()}[...Xs,"__count__"].forEach((t=>{Vs[t]=function(t,e){return(n,r)=>ot({name:t,aggregate_param:r,out:n||t},Gs,e)}(t,Vs[t])}));const iu=ru.prototype;function ou(t){Xa.call(this,null,t),this._adds=[],this._mods=[],this._alen=0,this._mlen=0,this._drop=!0,this._cross=!1,this._dims=[],this._dnames=[],this._measures=[],this._countOnly=!1,this._counts=null,this._prev=null,this._inputs=null,this._outputs=null}iu.reset=function(){this._add=[],this._rem=[],this._ext=null,this._get=null,this._q=null},iu.add=function(t){this._add.push(t)},iu.rem=function(t){this._rem.push(t)},iu.values=function(){if(this._get=null,0===this._rem.length)return this._add;const t=this._add,e=this._rem,n=this._key,r=t.length,i=e.length,o=Array(r-i),a={};let s,u,l;for(s=0;s=0;)r=t(e[i])+"",ut(n,r)||(n[r]=1,++o);return o},iu.extent=function(t){if(this._get!==t||!this._ext){const e=this.values(),n=st(e,t);this._ext=[e[n[0]],e[n[1]]],this._get=t}return this._ext},iu.argmin=function(t){return this.extent(t)[0]||{}},iu.argmax=function(t){return this.extent(t)[1]||{}},iu.min=function(t){const e=this.extent(t)[0];return null!=e?t(e):void 0},iu.max=function(t){const e=this.extent(t)[1];return null!=e?t(e):void 0},iu.quartile=function(t){return this._get===t&&this._q||(this._q=es(this.values(),t),this._get=t),this._q},iu.q1=function(t){return this.quartile(t)[0]},iu.q2=function(t){return this.quartile(t)[1]},iu.q3=function(t){return this.quartile(t)[2]},iu.ci=function(t){return this._get===t&&this._ci||(this._ci=is(this.values(),1e3,.05,t),this._get=t),this._ci},iu.ci0=function(t){return this.ci(t)[0]},iu.ci1=function(t){return this.ci(t)[1]},ou.Definition={type:"Aggregate",metadata:{generates:!0,changes:!0},params:[{name:"groupby",type:"field",array:!0},{name:"ops",type:"enum",array:!0,values:Xs},{name:"aggregate_params",type:"number",null:!0,array:!0},{name:"fields",type:"field",null:!0,array:!0},{name:"as",type:"string",null:!0,array:!0},{name:"drop",type:"boolean",default:!0},{name:"cross",type:"boolean",default:!1},{name:"key",type:"field"}]},ht(ou,Xa,{transform(t,e){const n=this,r=e.fork(e.NO_SOURCE|e.NO_FIELDS),i=t.modified();return n.stamp=r.stamp,n.value&&(i||e.modified(n._inputs,!0))?(n._prev=n.value,n.value=i?n.init(t):Object.create(null),e.visit(e.SOURCE,(t=>n.add(t)))):(n.value=n.value||n.init(t),e.visit(e.REM,(t=>n.rem(t))),e.visit(e.ADD,(t=>n.add(t)))),r.modifies(n._outputs),n._drop=!1!==t.drop,t.cross&&n._dims.length>1&&(n._drop=!1,n.cross()),e.clean()&&n._drop&&r.clean(!0).runAfter((()=>this.clean())),n.changes(r)},cross(){const t=this,e=t.value,n=t._dnames,r=n.map((()=>({}))),i=n.length;function o(t){let e,o,a,s;for(e in t)for(a=t[e].tuple,o=0;o{const e=n(t);return a(t),i.push(e),e})),this.cellkey=t.key?t.key:Ws(this._dims),this._countOnly=!0,this._counts=[],this._measures=[];const u=t.fields||[null],l=t.ops||["count"],c=t.aggregate_params||[null],f=t.as||[],h=u.length,d={};let p,g,m,y,v,_,x;for(h!==l.length&&s("Unmatched number of fields and aggregate ops."),x=0;xnu(t,t.field))),Object.create(null)},cellkey:Ws(),cell(t,e){let n=this.value[t];return n?0===n.num&&this._drop&&n.stampo.push(t),remove:t=>a[r(t)]=++s,size:()=>i.length,data:(t,e)=>(s&&(i=i.filter((t=>!a[r(t)])),a={},s=0),e&&t&&i.sort(t),o.length&&(i=t?kt(t,i,o.sort(t)):i.concat(o),o=[]),i)}}function uu(t){Xa.call(this,[],t)}function lu(t){Fa.call(this,null,cu,t)}function cu(t){return this.value&&!t.modified()?this.value:Q(t.fields,t.orders)}function fu(t){Xa.call(this,null,t)}function hu(t){Xa.call(this,null,t)}au.Definition={type:"Bin",metadata:{modifies:!0},params:[{name:"field",type:"field",required:!0},{name:"interval",type:"boolean",default:!0},{name:"anchor",type:"number"},{name:"maxbins",type:"number",default:20},{name:"base",type:"number",default:10},{name:"divide",type:"number",array:!0,default:[5,2]},{name:"extent",type:"number",array:!0,length:2,required:!0},{name:"span",type:"number"},{name:"step",type:"number"},{name:"steps",type:"number",array:!0},{name:"minstep",type:"number",default:0},{name:"nice",type:"boolean",default:!0},{name:"name",type:"string"},{name:"as",type:"string",array:!0,length:2,default:["bin0","bin1"]}]},ht(au,Xa,{transform(t,e){const n=!1!==t.interval,i=this._bins(t),o=i.start,a=i.step,s=t.as||["bin0","bin1"],u=s[0],l=s[1];let c;return c=t.modified()?(e=e.reflow(!0)).SOURCE:e.modified(r(t.field))?e.ADD_MOD:e.ADD,e.visit(c,n?t=>{const e=i(t);t[u]=e,t[l]=null==e?null:o+a*(1+(e-o)/a)}:t=>t[u]=i(t)),e.modifies(n?s:u)},_bins(t){if(this.value&&!t.modified())return this.value;const i=t.field,o=rs(t),a=o.step;let s,u,l=o.start,c=l+Math.ceil((o.stop-l)/a)*a;null!=(s=t.anchor)&&(u=s-(l+a*Math.floor((s-l)/a)),l+=u,c+=u);const f=function(t){let e=S(i(t));return null==e?null:ec?1/0:(e=Math.max(l,Math.min(e,c-a)),l+a*Math.floor(1e-14+(e-l)/a))};return f.start=l,f.stop=o.stop,f.step=a,this.value=e(f,r(i),t.name||"bin_"+n(i))}}),uu.Definition={type:"Collect",metadata:{source:!0},params:[{name:"sort",type:"compare"}]},ht(uu,Xa,{transform(t,e){const n=e.fork(e.ALL),r=su(ma,this.value,n.materialize(n.ADD).add),i=t.sort,o=e.changed()||i&&(t.modified("sort")||e.modified(i.fields));return n.visit(n.REM,r.remove),this.modified(o),this.value=n.source=r.data(wa(i),o),e.source&&e.source.root&&(this.value.root=e.source.root),n}}),ht(lu,Fa),fu.Definition={type:"CountPattern",metadata:{generates:!0,changes:!0},params:[{name:"field",type:"field",required:!0},{name:"case",type:"enum",values:["upper","lower","mixed"],default:"mixed"},{name:"pattern",type:"string",default:'[\\w"]+'},{name:"stopwords",type:"string",default:""},{name:"as",type:"string",array:!0,length:2,default:["text","count"]}]},ht(fu,Xa,{transform(t,e){const n=e=>n=>{for(var r,i=function(t,e,n){switch(e){case"upper":t=t.toUpperCase();break;case"lower":t=t.toLowerCase()}return t.match(n)}(s(n),t.case,o)||[],u=0,l=i.length;ui[t]=1+(i[t]||0))),c=n((t=>i[t]-=1));return r?e.visit(e.SOURCE,l):(e.visit(e.ADD,l),e.visit(e.REM,c)),this._finish(e,u)},_parameterCheck(t,e){let n=!1;return!t.modified("stopwords")&&this._stop||(this._stop=new RegExp("^"+(t.stopwords||"")+"$","i"),n=!0),!t.modified("pattern")&&this._match||(this._match=new RegExp(t.pattern||"[\\w']+","g"),n=!0),(t.modified("field")||e.modified(t.field.fields))&&(n=!0),n&&(this._counts={}),n},_finish(t,e){const n=this._counts,r=this._tuples||(this._tuples={}),i=e[0],o=e[1],a=t.fork(t.NO_SOURCE|t.NO_FIELDS);let s,u,l;for(s in n)u=r[s],l=n[s]||0,!u&&l?(r[s]=u=va({}),u[i]=s,u[o]=l,a.add.push(u)):0===l?(u&&a.rem.push(u),n[s]=null,r[s]=null):u[o]!==l&&(u[o]=l,a.mod.push(u));return a.modifies(e)}}),hu.Definition={type:"Cross",metadata:{generates:!0},params:[{name:"filter",type:"expr"},{name:"as",type:"string",array:!0,length:2,default:["a","b"]}]},ht(hu,Xa,{transform(t,e){const n=e.fork(e.NO_SOURCE),r=t.as||["a","b"],i=r[0],o=r[1],a=!this.value||e.changed(e.ADD_REM)||t.modified("as")||t.modified("filter");let s=this.value;return a?(s&&(n.rem=s),s=e.materialize(e.SOURCE).source,n.add=this.value=function(t,e,n,r){for(var i,o,a=[],s={},u=t.length,l=0;lgu(t,e)))):typeof r[n]===pu&&r[n](t[n]);return r}function mu(t){Xa.call(this,null,t)}const yu=[{key:{function:"normal"},params:[{name:"mean",type:"number",default:0},{name:"stdev",type:"number",default:1}]},{key:{function:"lognormal"},params:[{name:"mean",type:"number",default:0},{name:"stdev",type:"number",default:1}]},{key:{function:"uniform"},params:[{name:"min",type:"number",default:0},{name:"max",type:"number",default:1}]},{key:{function:"kde"},params:[{name:"field",type:"field",required:!0},{name:"from",type:"data"},{name:"bandwidth",type:"number",default:0}]}],vu={key:{function:"mixture"},params:[{name:"distributions",type:"param",array:!0,params:yu},{name:"weights",type:"number",array:!0}]};function _u(t,e){return t?t.map(((t,r)=>e[r]||n(t))):null}function xu(t,e,n){const r=[],i=t=>t(u);let o,a,s,u,l,c;if(null==e)r.push(t.map(n));else for(o={},a=0,s=t.length;at.materialize(t.SOURCE).source}(e)),i=t.steps||t.minsteps||25,o=t.steps||t.maxsteps||200;let a=t.method||"pdf";"pdf"!==a&&"cdf"!==a&&s("Invalid density method: "+a),t.extent||r.data||s("Missing density extent parameter."),a=r[a];const u=t.as||["value","density"],l=js(a,t.extent||at(r.data()),i,o).map((t=>{const e={};return e[u[0]]=t[0],e[u[1]]=t[1],va(e)}));this.value&&(n.rem=this.value),this.value=n.add=n.source=l}return n}});function bu(t){Xa.call(this,null,t)}bu.Definition={type:"DotBin",metadata:{modifies:!0},params:[{name:"field",type:"field",required:!0},{name:"groupby",type:"field",array:!0},{name:"step",type:"number"},{name:"smooth",type:"boolean",default:!1},{name:"as",type:"string",default:"bin"}]};function wu(t){Fa.call(this,null,ku,t),this.modified(!0)}function ku(t){const i=t.expr;return this.value&&!t.modified("expr")?this.value:e((e=>i(e,t)),r(i),n(i))}function Au(t){Xa.call(this,[void 0,void 0],t)}function Mu(t,e){Fa.call(this,t),this.parent=e,this.count=0}function Eu(t){Xa.call(this,{},t),this._keys=ct();const e=this._targets=[];e.active=0,e.forEach=t=>{for(let n=0,r=e.active;nl(t))):l(t.name,t.as)}function Fu(t){Xa.call(this,ct(),t)}function Su(t){Xa.call(this,[],t)}function $u(t){Xa.call(this,[],t)}function Tu(t){Xa.call(this,null,t)}function Bu(t){Xa.call(this,[],t)}ht(bu,Xa,{transform(t,e){if(this.value&&!t.modified()&&!e.changed())return e;const n=e.materialize(e.SOURCE).source,r=xu(e.source,t.groupby,f),i=t.smooth||!1,o=t.field,a=t.step||((t,e)=>Et(at(t,e))/30)(n,o),s=wa(((t,e)=>o(t)-o(e))),u=t.as||"bin",l=r.length;let c,h=1/0,d=-1/0,p=0;for(;pd&&(d=e),t[++c][u]=e}return this.value={start:h,stop:d,step:a},e.reflow(!0).modifies(u)}}),ht(wu,Fa),Au.Definition={type:"Extent",metadata:{},params:[{name:"field",type:"field",required:!0}]},ht(Au,Xa,{transform(t,e){const r=this.value,i=t.field,o=e.changed()||e.modified(i.fields)||t.modified("field");let a=r[0],s=r[1];if((o||null==a)&&(a=1/0,s=-1/0),e.visit(o?e.SOURCE:e.ADD,(t=>{const e=S(i(t));null!=e&&(es&&(s=e))})),!Number.isFinite(a)||!Number.isFinite(s)){let t=n(i);t&&(t=` for field "${t}"`),e.dataflow.warn(`Infinite extent${t}: [${a}, ${s}]`),a=s=void 0}this.value=[a,s]}}),ht(Mu,Fa,{connect(t){return this.detachSubflow=t.detachSubflow,this.targets().add(t),t.source=this},add(t){this.count+=1,this.value.add.push(t)},rem(t){this.count-=1,this.value.rem.push(t)},mod(t){this.value.mod.push(t)},init(t){this.value.init(t,t.NO_SOURCE)},evaluate(){return this.value}}),ht(Eu,Xa,{activate(t){this._targets[this._targets.active++]=t},subflow(t,e,n,r){const i=this.value;let o,a,s=ut(i,t)&&i[t];return s?s.value.stampt&&t.count>0));this.initTargets(t)}},initTargets(t){const e=this._targets,n=e.length,r=t?t.length:0;let i=0;for(;ithis.subflow(t,i,e);return this._group=t.group||{},this.initTargets(),e.visit(e.REM,(t=>{const e=ma(t),n=o.get(e);void 0!==n&&(o.delete(e),s(n).rem(t))})),e.visit(e.ADD,(t=>{const e=r(t);o.set(ma(t),e),s(e).add(t)})),a||e.modified(r.fields)?e.visit(e.MOD,(t=>{const e=ma(t),n=o.get(e),i=r(t);n===i?s(i).mod(t):(o.set(e,i),s(n).rem(t),s(i).add(t))})):e.changed(e.MOD)&&e.visit(e.MOD,(t=>{s(o.get(ma(t))).mod(t)})),a&&e.visit(e.REFLOW,(t=>{const e=ma(t),n=o.get(e),i=r(t);n!==i&&(o.set(e,i),s(n).rem(t),s(i).add(t))})),e.clean()?n.runAfter((()=>{this.clean(),o.clean()})):o.empty>n.cleanThreshold&&n.runAfter(o.clean),e}}),ht(Du,Fa),Fu.Definition={type:"Filter",metadata:{changes:!0},params:[{name:"expr",type:"expr",required:!0}]},ht(Fu,Xa,{transform(t,e){const n=e.dataflow,r=this.value,i=e.fork(),o=i.add,a=i.rem,s=i.mod,u=t.expr;let l=!0;function c(e){const n=ma(e),i=u(e,t),c=r.get(n);i&&c?(r.delete(n),o.push(e)):i||c?l&&i&&!c&&s.push(e):(r.set(n,1),a.push(e))}return e.visit(e.REM,(t=>{const e=ma(t);r.has(e)?r.delete(e):a.push(t)})),e.visit(e.ADD,(e=>{u(e,t)?o.push(e):r.set(ma(e),1)})),e.visit(e.MOD,c),t.modified()&&(l=!1,e.visit(e.REFLOW,c)),r.empty>n.cleanThreshold&&n.runAfter(r.clean),i}}),Su.Definition={type:"Flatten",metadata:{generates:!0},params:[{name:"fields",type:"field",array:!0,required:!0},{name:"index",type:"string"},{name:"as",type:"string",array:!0}]},ht(Su,Xa,{transform(t,e){const n=e.fork(e.NO_SOURCE),r=t.fields,i=_u(r,t.as||[]),o=t.index||null,a=i.length;return n.rem=this.value,e.visit(e.SOURCE,(t=>{const e=r.map((e=>e(t))),s=e.reduce(((t,e)=>Math.max(t,e.length)),0);let u,l,c,f=0;for(;f{for(let e,n=0;ne[r]=n(e,t)))}}),ht(Bu,Xa,{transform(t,e){const n=e.fork(e.ALL),r=t.generator;let i,o,a,s=this.value,u=t.size-s.length;if(u>0){for(i=[];--u>=0;)i.push(a=va(r(t))),s.push(a);n.add=n.add.length?n.materialize(n.ADD).add.concat(i):i}else o=s.slice(0,-u),n.rem=n.rem.length?n.materialize(n.REM).rem.concat(o):o,s=s.slice(-u);return n.source=this.value=s,n}});const zu={value:"value",median:De,mean:function(t,e){let n=0,r=0;if(void 0===e)for(let e of t)null!=e&&(e=+e)>=e&&(++n,r+=e);else{let i=-1;for(let o of t)null!=(o=e(o,++i,t))&&(o=+o)>=o&&(++n,r+=o)}if(n)return r/n},min:we,max:be},Nu=[];function Ou(t){Xa.call(this,[],t)}function Ru(t){ou.call(this,t)}function Lu(t){Xa.call(this,null,t)}function Uu(t){Fa.call(this,null,qu,t)}function qu(t){return this.value&&!t.modified()?this.value:xt(t.fields,t.flat)}function Pu(t){Xa.call(this,[],t),this._pending=null}function ju(t,e,n){n.forEach(va);const r=e.fork(e.NO_FIELDS&e.NO_SOURCE);return r.rem=t.value,t.value=r.source=r.add=n,t._pending=null,r.rem.length&&r.clean(!0),r}function Iu(t){Xa.call(this,{},t)}function Wu(t){Fa.call(this,null,Hu,t)}function Hu(t){if(this.value&&!t.modified())return this.value;const e=t.extents,n=e.length;let r,i,o=1/0,a=-1/0;for(r=0;ra&&(a=i[1]);return[o,a]}function Yu(t){Fa.call(this,null,Gu,t)}function Gu(t){return this.value&&!t.modified()?this.value:t.values.reduce(((t,e)=>t.concat(e)),[])}function Vu(t){Xa.call(this,null,t)}function Xu(t){ou.call(this,t)}function Ju(t){Eu.call(this,t)}function Zu(t){Xa.call(this,null,t)}function Qu(t){Xa.call(this,null,t)}function Ku(t){Xa.call(this,null,t)}Ou.Definition={type:"Impute",metadata:{changes:!0},params:[{name:"field",type:"field",required:!0},{name:"key",type:"field",required:!0},{name:"keyvals",array:!0},{name:"groupby",type:"field",array:!0},{name:"method",type:"enum",default:"value",values:["value","mean","median","max","min"]},{name:"value",default:0}]},ht(Ou,Xa,{transform(t,e){var r,i,o,a,u,l,c,f,h,d,p=e.fork(e.ALL),g=function(t){var e,n=t.method||zu.value;if(null!=zu[n])return n===zu.value?(e=void 0!==t.value?t.value:0,()=>e):zu[n];s("Unrecognized imputation method: "+n)}(t),m=function(t){const e=t.field;return t=>t?e(t):NaN}(t),y=n(t.field),v=n(t.key),_=(t.groupby||[]).map(n),x=function(t,e,n,r){var i,o,a,s,u,l,c,f,h=t=>t(f),d=[],p=r?r.slice():[],g={},m={};for(p.forEach(((t,e)=>g[t]=e+1)),s=0,c=t.length;sn.add(t)))):(i=n.value=n.value||this.init(t),e.visit(e.REM,(t=>n.rem(t))),e.visit(e.ADD,(t=>n.add(t)))),n.changes(),e.visit(e.SOURCE,(t=>{ot(t,i[n.cellkey(t)].tuple)})),e.reflow(r).modifies(this._outputs)},changes(){const t=this._adds,e=this._mods;let n,r;for(n=0,r=this._alen;n{const n=ps(e,u)[l],r=t.counts?e.length:1;js(n,h||at(e),d,p).forEach((t=>{const n={};for(let t=0;t(this._pending=V(t.data),t=>t.touch(this))));return{async:e}}return n.request(t.url,t.format).then((t=>ju(this,e,V(t.data))))}}),Iu.Definition={type:"Lookup",metadata:{modifies:!0},params:[{name:"index",type:"index",params:[{name:"from",type:"data",required:!0},{name:"key",type:"field",required:!0}]},{name:"values",type:"field",array:!0},{name:"fields",type:"field",array:!0,required:!0},{name:"as",type:"string",array:!0},{name:"default",default:null}]},ht(Iu,Xa,{transform(t,e){const r=t.fields,i=t.index,o=t.values,a=null==t.default?null:t.default,u=t.modified(),l=r.length;let c,f,h,d=u?e.SOURCE:e.ADD,p=e,g=t.as;return o?(f=o.length,l>1&&!g&&s('Multi-field lookup requires explicit "as" parameter.'),g&&g.length!==l*f&&s('The "as" parameter has too few output field names.'),g=g||o.map(n),c=function(t){for(var e,n,s=0,u=0;se.modified(t.fields))),d|=h?e.MOD:0),e.visit(d,c),p.modifies(g)}}),ht(Wu,Fa),ht(Yu,Fa),ht(Vu,Xa,{transform(t,e){return this.modified(t.modified()),this.value=t,e.fork(e.NO_SOURCE|e.NO_FIELDS)}}),Xu.Definition={type:"Pivot",metadata:{generates:!0,changes:!0},params:[{name:"groupby",type:"field",array:!0},{name:"field",type:"field",required:!0},{name:"value",type:"field",required:!0},{name:"op",type:"enum",values:Xs,default:"sum"},{name:"limit",type:"number",default:0},{name:"key",type:"field"}]},ht(Xu,ou,{_transform:ou.prototype.transform,transform(t,n){return this._transform(function(t,n){const i=t.field,o=t.value,a=("count"===t.op?"__count__":t.op)||"sum",s=r(i).concat(r(o)),u=function(t,e,n){const r={},i=[];return n.visit(n.SOURCE,(e=>{const n=t(e);r[n]||(r[n]=1,i.push(n))})),i.sort(K),e?i.slice(0,e):i}(i,t.limit||0,n);n.changed()&&t.set("__pivot__",null,null,!0);return{key:t.key,groupby:t.groupby,ops:u.map((()=>a)),fields:u.map((t=>function(t,n,r,i){return e((e=>n(e)===t?r(e):NaN),i,t+"")}(t,i,o,s))),as:u.map((t=>t+"")),modified:t.modified.bind(t)}}(t,n),n)}}),ht(Ju,Eu,{transform(t,e){const n=t.subflow,i=t.field,o=t=>this.subflow(ma(t),n,e,t);return(t.modified("field")||i&&e.modified(r(i)))&&s("PreFacet does not support field modification."),this.initTargets(),i?(e.visit(e.MOD,(t=>{const e=o(t);i(t).forEach((t=>e.mod(t)))})),e.visit(e.ADD,(t=>{const e=o(t);i(t).forEach((t=>e.add(va(t))))})),e.visit(e.REM,(t=>{const e=o(t);i(t).forEach((t=>e.rem(t)))}))):(e.visit(e.MOD,(t=>o(t).mod(t))),e.visit(e.ADD,(t=>o(t).add(t))),e.visit(e.REM,(t=>o(t).rem(t)))),e.clean()&&e.runAfter((()=>this.clean())),e}}),Zu.Definition={type:"Project",metadata:{generates:!0,changes:!0},params:[{name:"fields",type:"field",array:!0},{name:"as",type:"string",null:!0,array:!0}]},ht(Zu,Xa,{transform(t,e){const n=e.fork(e.NO_SOURCE),r=t.fields,i=_u(t.fields,t.as||[]),o=r?(t,e)=>function(t,e,n,r){for(let i=0,o=n.length;i{const e=ma(t);n.rem.push(a[e]),a[e]=null})),e.visit(e.ADD,(t=>{const e=o(t,va({}));a[ma(t)]=e,n.add.push(e)})),e.visit(e.MOD,(t=>{n.mod.push(o(t,a[ma(t)]))})),n}}),ht(Qu,Xa,{transform(t,e){return this.value=t.value,t.modified("value")?e.fork(e.NO_SOURCE|e.NO_FIELDS):e.StopPropagation}}),Ku.Definition={type:"Quantile",metadata:{generates:!0,changes:!0},params:[{name:"groupby",type:"field",array:!0},{name:"field",type:"field",required:!0},{name:"probs",type:"number",array:!0},{name:"step",type:"number",default:.01},{name:"as",type:"string",array:!0,default:["prob","value"]}]};function tl(t){Xa.call(this,null,t)}function el(t){Xa.call(this,[],t),this.count=0}function nl(t){Xa.call(this,null,t)}function rl(t){Xa.call(this,null,t),this.modified(!0)}function il(t){Xa.call(this,null,t)}ht(Ku,Xa,{transform(t,e){const r=e.fork(e.NO_SOURCE|e.NO_FIELDS),i=t.as||["prob","value"];if(this.value&&!t.modified()&&!e.changed())return r.source=this.value,r;const o=xu(e.materialize(e.SOURCE).source,t.groupby,t.field),a=(t.groupby||[]).map(n),s=[],u=t.step||.01,l=t.probs||Fe(u/2,1-1e-14,u),c=l.length;return o.forEach((t=>{const e=ts(t,l);for(let n=0;n{const e=ma(t);n.rem.push(r[e]),r[e]=null})),e.visit(e.ADD,(t=>{const e=_a(t);r[ma(t)]=e,n.add.push(e)})),e.visit(e.MOD,(t=>{const e=r[ma(t)];for(const r in t)e[r]=t[r],n.modifies(r);n.mod.push(e)}))),n}}),el.Definition={type:"Sample",metadata:{},params:[{name:"size",type:"number",default:1e3}]},ht(el,Xa,{transform(e,n){const r=n.fork(n.NO_SOURCE),i=e.modified("size"),o=e.size,a=this.value.reduce(((t,e)=>(t[ma(e)]=1,t)),{});let s=this.value,u=this.count,l=0;function c(e){let n,i;s.length=l&&(n=s[i],a[ma(n)]&&r.rem.push(n),s[i]=e)),++u}if(n.rem.length&&(n.visit(n.REM,(t=>{const e=ma(t);a[e]&&(a[e]=-1,r.rem.push(t)),--u})),s=s.filter((t=>-1!==a[ma(t)]))),(n.rem.length||i)&&s.length{a[ma(t)]||c(t)})),l=-1),i&&s.length>o){const t=s.length-o;for(let e=0;e{a[ma(t)]&&r.mod.push(t)})),n.add.length&&n.visit(n.ADD,c),(n.add.length||l<0)&&(r.add=s.filter((t=>!a[ma(t)]))),this.count=u,this.value=r.source=s,r}}),nl.Definition={type:"Sequence",metadata:{generates:!0,changes:!0},params:[{name:"start",type:"number",required:!0},{name:"stop",type:"number",required:!0},{name:"step",type:"number",default:1},{name:"as",type:"string",default:"data"}]},ht(nl,Xa,{transform(t,e){if(this.value&&!t.modified())return;const n=e.materialize().fork(e.MOD),r=t.as||"data";return n.rem=this.value?e.rem.concat(this.value):e.rem,this.value=Fe(t.start,t.stop,t.step||1).map((t=>{const e={};return e[r]=t,va(e)})),n.add=e.add.concat(this.value),n}}),ht(rl,Xa,{transform(t,e){return this.value=e.source,e.changed()?e.fork(e.NO_SOURCE|e.NO_FIELDS):e.StopPropagation}});const ol=["unit0","unit1"];function al(t){Xa.call(this,ct(),t)}function sl(t){Xa.call(this,null,t)}il.Definition={type:"TimeUnit",metadata:{modifies:!0},params:[{name:"field",type:"field",required:!0},{name:"interval",type:"boolean",default:!0},{name:"units",type:"enum",values:Qn,array:!0},{name:"step",type:"number",default:1},{name:"maxbins",type:"number",default:40},{name:"extent",type:"date",array:!0},{name:"timezone",type:"enum",default:"local",values:["local","utc"]},{name:"as",type:"string",array:!0,length:2,default:ol}]},ht(il,Xa,{transform(t,e){const n=t.field,i=!1!==t.interval,o="utc"===t.timezone,a=this._floor(t,e),s=(o?Cr:Dr)(a.unit).offset,u=t.as||ol,l=u[0],c=u[1],f=a.step;let h=a.start||1/0,d=a.stop||-1/0,p=e.ADD;return(t.modified()||e.changed(e.REM)||e.modified(r(n)))&&(p=(e=e.reflow(!0)).SOURCE,h=1/0,d=-1/0),e.visit(p,(t=>{const e=n(t);let r,o;null==e?(t[l]=null,i&&(t[c]=null)):(t[l]=r=o=a(e),i&&(t[c]=o=s(r,f)),rd&&(d=o))})),a.start=h,a.stop=d,e.modifies(i?u:l)},_floor(t,e){const n="utc"===t.timezone,{units:r,step:i}=t.units?{units:t.units,step:t.step||1}:Xr({extent:t.extent||at(e.materialize(e.SOURCE).source,t.field),maxbins:t.maxbins}),o=tr(r),a=this.value||{},s=(n?Ar:br)(o,i);return s.unit=F(o),s.units=o,s.step=i,s.start=a.start,s.stop=a.stop,this.value=s}}),ht(al,Xa,{transform(t,e){const n=e.dataflow,r=t.field,i=this.value,o=t=>i.set(r(t),t);let a=!0;return t.modified("field")||e.modified(r.fields)?(i.clear(),e.visit(e.SOURCE,o)):e.changed()?(e.visit(e.REM,(t=>i.delete(r(t)))),e.visit(e.ADD,o)):a=!1,this.modified(a),i.empty>n.cleanThreshold&&n.runAfter(i.clean),e.fork()}}),ht(sl,Xa,{transform(t,e){(!this.value||t.modified("field")||t.modified("sort")||e.changed()||t.sort&&e.modified(t.sort.fields))&&(this.value=(t.sort?e.source.slice().sort(wa(t.sort)):e.source).map(t.field))}});const ul={row_number:function(){return{next:t=>t.index+1}},rank:function(){let t;return{init:()=>t=1,next:e=>{const n=e.index,r=e.data;return n&&e.compare(r[n-1],r[n])?t=n+1:t}}},dense_rank:function(){let t;return{init:()=>t=1,next:e=>{const n=e.index,r=e.data;return n&&e.compare(r[n-1],r[n])?++t:t}}},percent_rank:function(){const t=ul.rank(),e=t.next;return{init:t.init,next:t=>(e(t)-1)/(t.data.length-1)}},cume_dist:function(){let t;return{init:()=>t=0,next:e=>{const n=e.data,r=e.compare;let i=e.index;if(t0||s("ntile num must be greater than zero.");const n=ul.cume_dist(),r=n.next;return{init:n.init,next:t=>Math.ceil(e*r(t))}},lag:function(t,e){return e=+e||1,{next:n=>{const r=n.index-e;return r>=0?t(n.data[r]):null}}},lead:function(t,e){return e=+e||1,{next:n=>{const r=n.index+e,i=n.data;return rt(e.data[e.i0])}},last_value:function(t){return{next:e=>t(e.data[e.i1-1])}},nth_value:function(t,e){return(e=+e)>0||s("nth_value nth must be greater than zero."),{next:n=>{const r=n.i0+(e-1);return re=null,next:n=>{const r=t(n.data[n.index]);return null!=r?e=r:e}}},next_value:function(t){let e,n;return{init:()=>(e=null,n=-1),next:r=>{const i=r.data;return r.index<=n?e:(n=function(t,e,n){for(let r=e.length;nf[t]=1))}y(t.sort),e.forEach(((t,e)=>{const r=i[e],f=o[e],v=a[e]||null,_=n(r),x=Hs(t,_,u[e]);if(y(r),l.push(x),ut(ul,t))c.push(function(t,e,n,r){const i=ul[t](e,n);return{init:i.init||h,update:function(t,e){e[r]=i.next(t)}}}(t,r,f,x));else{if(null==r&&"count"!==t&&s("Null aggregate field specified."),"count"===t)return void p.push(x);m=!1;let e=d[_];e||(e=d[_]=[],e.field=r,g.push(e)),e.push(Js(t,v,x))}})),(p.length||g.length)&&(this.cell=function(t,e,n){t=t.map((t=>nu(t,t.field)));const r={num:0,agg:null,store:!1,count:e};if(!n)for(var i=t.length,o=r.agg=Array(i),a=0;a0&&!i(o[n],o[n-1])&&(t.i0=e.left(o,o[n])),rt.init())),this.cell&&this.cell.init()},fl.update=function(t,e){const n=this.cell,r=this.windows,i=t.data,o=r&&r.length;let a;if(n){for(a=t.p0;athis.group(i(t));let a=this.state;a&&!n||(a=this.state=new cl(t)),n||e.modified(a.inputs)?(this.value={},e.visit(e.SOURCE,(t=>o(t).add(t)))):(e.visit(e.REM,(t=>o(t).remove(t))),e.visit(e.ADD,(t=>o(t).add(t))));for(let e=0,n=this._mlen;e=1?Dl:t<=-1?-Dl:Math.asin(t)}const Sl=Math.PI,$l=2*Sl,Tl=1e-6,Bl=$l-Tl;function zl(t){this._+=t[0];for(let e=1,n=t.length;e=0))throw new Error(`invalid digits: ${t}`);if(e>15)return zl;const n=10**e;return function(t){this._+=t[0];for(let e=1,r=t.length;eTl)if(Math.abs(c*s-u*l)>Tl&&i){let h=n-o,d=r-a,p=s*s+u*u,g=h*h+d*d,m=Math.sqrt(p),y=Math.sqrt(f),v=i*Math.tan((Sl-Math.acos((p+f-g)/(2*m*y)))/2),_=v/y,x=v/m;Math.abs(_-1)>Tl&&this._append`L${t+_*l},${e+_*c}`,this._append`A${i},${i},0,0,${+(c*h>l*d)},${this._x1=t+x*s},${this._y1=e+x*u}`}else this._append`L${this._x1=t},${this._y1=e}`;else;}arc(t,e,n,r,i,o){if(t=+t,e=+e,o=!!o,(n=+n)<0)throw new Error(`negative radius: ${n}`);let a=n*Math.cos(r),s=n*Math.sin(r),u=t+a,l=e+s,c=1^o,f=o?r-i:i-r;null===this._x1?this._append`M${u},${l}`:(Math.abs(this._x1-u)>Tl||Math.abs(this._y1-l)>Tl)&&this._append`L${u},${l}`,n&&(f<0&&(f=f%$l+$l),f>Bl?this._append`A${n},${n},0,1,${c},${t-a},${e-s}A${n},${n},0,1,${c},${this._x1=u},${this._y1=l}`:f>Tl&&this._append`A${n},${n},0,${+(f>=Sl)},${c},${this._x1=t+n*Math.cos(i)},${this._y1=e+n*Math.sin(i)}`)}rect(t,e,n,r){this._append`M${this._x0=this._x1=+t},${this._y0=this._y1=+e}h${n=+n}v${+r}h${-n}Z`}toString(){return this._}};function Ol(){return new Nl}function Rl(t){let e=3;return t.digits=function(n){if(!arguments.length)return e;if(null==n)e=null;else{const t=Math.floor(n);if(!(t>=0))throw new RangeError(`invalid digits: ${n}`);e=t}return t},()=>new Nl(e)}function Ll(t){return t.innerRadius}function Ul(t){return t.outerRadius}function ql(t){return t.startAngle}function Pl(t){return t.endAngle}function jl(t){return t&&t.padAngle}function Il(t,e,n,r,i,o,a){var s=t-n,u=e-r,l=(a?o:-o)/Al(s*s+u*u),c=l*u,f=-l*s,h=t+c,d=e+f,p=n+c,g=r+f,m=(h+p)/2,y=(d+g)/2,v=p-h,_=g-d,x=v*v+_*_,b=i-o,w=h*g-p*d,k=(_<0?-1:1)*Al(bl(0,b*b*x-w*w)),A=(w*_-v*k)/x,M=(-w*v-_*k)/x,E=(w*_+v*k)/x,D=(-w*v+_*k)/x,C=A-m,F=M-y,S=E-m,$=D-y;return C*C+F*F>S*S+$*$&&(A=E,M=D),{cx:A,cy:M,x01:-c,y01:-f,x11:A*(i/b-1),y11:M*(i/b-1)}}function Wl(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}function Hl(t){this._context=t}function Yl(t){return new Hl(t)}function Gl(t){return t[0]}function Vl(t){return t[1]}function Xl(t,e){var n=yl(!0),r=null,i=Yl,o=null,a=Rl(s);function s(s){var u,l,c,f=(s=Wl(s)).length,h=!1;for(null==r&&(o=i(c=a())),u=0;u<=f;++u)!(u=f;--h)s.point(y[h],v[h]);s.lineEnd(),s.areaEnd()}m&&(y[c]=+t(d,c,l),v[c]=+e(d,c,l),s.point(r?+r(d,c,l):y[c],n?+n(d,c,l):v[c]))}if(p)return s=null,p+""||null}function c(){return Xl().defined(i).curve(a).context(o)}return t="function"==typeof t?t:void 0===t?Gl:yl(+t),e="function"==typeof e?e:yl(void 0===e?0:+e),n="function"==typeof n?n:void 0===n?Vl:yl(+n),l.x=function(e){return arguments.length?(t="function"==typeof e?e:yl(+e),r=null,l):t},l.x0=function(e){return arguments.length?(t="function"==typeof e?e:yl(+e),l):t},l.x1=function(t){return arguments.length?(r=null==t?null:"function"==typeof t?t:yl(+t),l):r},l.y=function(t){return arguments.length?(e="function"==typeof t?t:yl(+t),n=null,l):e},l.y0=function(t){return arguments.length?(e="function"==typeof t?t:yl(+t),l):e},l.y1=function(t){return arguments.length?(n=null==t?null:"function"==typeof t?t:yl(+t),l):n},l.lineX0=l.lineY0=function(){return c().x(t).y(e)},l.lineY1=function(){return c().x(t).y(n)},l.lineX1=function(){return c().x(r).y(e)},l.defined=function(t){return arguments.length?(i="function"==typeof t?t:yl(!!t),l):i},l.curve=function(t){return arguments.length?(a=t,null!=o&&(s=a(o)),l):a},l.context=function(t){return arguments.length?(null==t?o=s=null:s=a(o=t),l):o},l}Ol.prototype=Nl.prototype,Hl.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:this._context.lineTo(t,e)}}};var Zl={draw(t,e){const n=Al(e/El);t.moveTo(n,0),t.arc(0,0,n,0,Cl)}};function Ql(){}function Kl(t,e,n){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+e)/6,(t._y0+4*t._y1+n)/6)}function tc(t){this._context=t}function ec(t){this._context=t}function nc(t){this._context=t}function rc(t,e){this._basis=new tc(t),this._beta=e}tc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:Kl(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:Kl(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},ec.prototype={areaStart:Ql,areaEnd:Ql,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._x2=t,this._y2=e;break;case 1:this._point=2,this._x3=t,this._y3=e;break;case 2:this._point=3,this._x4=t,this._y4=e,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+e)/6);break;default:Kl(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},nc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var n=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+e)/6;this._line?this._context.lineTo(n,r):this._context.moveTo(n,r);break;case 3:this._point=4;default:Kl(this,t,e)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=e}},rc.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var t=this._x,e=this._y,n=t.length-1;if(n>0)for(var r,i=t[0],o=e[0],a=t[n]-i,s=e[n]-o,u=-1;++u<=n;)r=u/n,this._basis.point(this._beta*t[u]+(1-this._beta)*(i+r*a),this._beta*e[u]+(1-this._beta)*(o+r*s));this._x=this._y=null,this._basis.lineEnd()},point:function(t,e){this._x.push(+t),this._y.push(+e)}};var ic=function t(e){function n(t){return 1===e?new tc(t):new rc(t,e)}return n.beta=function(e){return t(+e)},n}(.85);function oc(t,e,n){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._y1+t._k*(t._y2-t._y0),t._x2+t._k*(t._x1-e),t._y2+t._k*(t._y1-n),t._x2,t._y2)}function ac(t,e){this._context=t,this._k=(1-e)/6}ac.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:oc(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2,this._x1=t,this._y1=e;break;case 2:this._point=3;default:oc(this,t,e)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};var sc=function t(e){function n(t){return new ac(t,e)}return n.tension=function(e){return t(+e)},n}(0);function uc(t,e){this._context=t,this._k=(1-e)/6}uc.prototype={areaStart:Ql,areaEnd:Ql,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._x3=t,this._y3=e;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=e);break;case 2:this._point=3,this._x5=t,this._y5=e;break;default:oc(this,t,e)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};var lc=function t(e){function n(t){return new uc(t,e)}return n.tension=function(e){return t(+e)},n}(0);function cc(t,e){this._context=t,this._k=(1-e)/6}cc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:oc(this,t,e)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};var fc=function t(e){function n(t){return new cc(t,e)}return n.tension=function(e){return t(+e)},n}(0);function hc(t,e,n){var r=t._x1,i=t._y1,o=t._x2,a=t._y2;if(t._l01_a>Ml){var s=2*t._l01_2a+3*t._l01_a*t._l12_a+t._l12_2a,u=3*t._l01_a*(t._l01_a+t._l12_a);r=(r*s-t._x0*t._l12_2a+t._x2*t._l01_2a)/u,i=(i*s-t._y0*t._l12_2a+t._y2*t._l01_2a)/u}if(t._l23_a>Ml){var l=2*t._l23_2a+3*t._l23_a*t._l12_a+t._l12_2a,c=3*t._l23_a*(t._l23_a+t._l12_a);o=(o*l+t._x1*t._l23_2a-e*t._l12_2a)/c,a=(a*l+t._y1*t._l23_2a-n*t._l12_2a)/c}t._context.bezierCurveTo(r,i,o,a,t._x2,t._y2)}function dc(t,e){this._context=t,this._alpha=e}dc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){if(t=+t,e=+e,this._point){var n=this._x2-t,r=this._y2-e;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;break;case 2:this._point=3;default:hc(this,t,e)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};var pc=function t(e){function n(t){return e?new dc(t,e):new ac(t,0)}return n.alpha=function(e){return t(+e)},n}(.5);function gc(t,e){this._context=t,this._alpha=e}gc.prototype={areaStart:Ql,areaEnd:Ql,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,e){if(t=+t,e=+e,this._point){var n=this._x2-t,r=this._y2-e;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=t,this._y3=e;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=e);break;case 2:this._point=3,this._x5=t,this._y5=e;break;default:hc(this,t,e)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};var mc=function t(e){function n(t){return e?new gc(t,e):new uc(t,0)}return n.alpha=function(e){return t(+e)},n}(.5);function yc(t,e){this._context=t,this._alpha=e}yc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){if(t=+t,e=+e,this._point){var n=this._x2-t,r=this._y2-e;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:hc(this,t,e)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=e}};var vc=function t(e){function n(t){return e?new yc(t,e):new cc(t,0)}return n.alpha=function(e){return t(+e)},n}(.5);function _c(t){this._context=t}function xc(t){return t<0?-1:1}function bc(t,e,n){var r=t._x1-t._x0,i=e-t._x1,o=(t._y1-t._y0)/(r||i<0&&-0),a=(n-t._y1)/(i||r<0&&-0),s=(o*i+a*r)/(r+i);return(xc(o)+xc(a))*Math.min(Math.abs(o),Math.abs(a),.5*Math.abs(s))||0}function wc(t,e){var n=t._x1-t._x0;return n?(3*(t._y1-t._y0)/n-e)/2:e}function kc(t,e,n){var r=t._x0,i=t._y0,o=t._x1,a=t._y1,s=(o-r)/3;t._context.bezierCurveTo(r+s,i+s*e,o-s,a-s*n,o,a)}function Ac(t){this._context=t}function Mc(t){this._context=new Ec(t)}function Ec(t){this._context=t}function Dc(t){this._context=t}function Cc(t){var e,n,r=t.length-1,i=new Array(r),o=new Array(r),a=new Array(r);for(i[0]=0,o[0]=2,a[0]=t[0]+2*t[1],e=1;e=0;--e)i[e]=(a[e]-i[e+1])/o[e];for(o[r-1]=(t[r]+i[r-1])/2,e=0;e=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,e),this._context.lineTo(t,e);else{var n=this._x*(1-this._t)+t*this._t;this._context.lineTo(n,this._y),this._context.lineTo(n,e)}}this._x=t,this._y=e}};const $c=()=>"undefined"!=typeof Image?Image:null;function Tc(t,e){switch(arguments.length){case 0:break;case 1:this.range(t);break;default:this.range(e).domain(t)}return this}function Bc(t,e){switch(arguments.length){case 0:break;case 1:"function"==typeof t?this.interpolator(t):this.range(t);break;default:this.domain(t),"function"==typeof e?this.interpolator(e):this.range(e)}return this}const zc=Symbol("implicit");function Nc(){var t=new se,e=[],n=[],r=zc;function i(i){let o=t.get(i);if(void 0===o){if(r!==zc)return r;t.set(i,o=e.push(i)-1)}return n[o%n.length]}return i.domain=function(n){if(!arguments.length)return e.slice();e=[],t=new se;for(const r of n)t.has(r)||t.set(r,e.push(r)-1);return i},i.range=function(t){return arguments.length?(n=Array.from(t),i):n.slice()},i.unknown=function(t){return arguments.length?(r=t,i):r},i.copy=function(){return Nc(e,n).unknown(r)},Tc.apply(i,arguments),i}function Oc(t,e,n){t.prototype=e.prototype=n,n.constructor=t}function Rc(t,e){var n=Object.create(t.prototype);for(var r in e)n[r]=e[r];return n}function Lc(){}var Uc=.7,qc=1/Uc,Pc="\\s*([+-]?\\d+)\\s*",jc="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*",Ic="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*",Wc=/^#([0-9a-f]{3,8})$/,Hc=new RegExp(`^rgb\\(${Pc},${Pc},${Pc}\\)$`),Yc=new RegExp(`^rgb\\(${Ic},${Ic},${Ic}\\)$`),Gc=new RegExp(`^rgba\\(${Pc},${Pc},${Pc},${jc}\\)$`),Vc=new RegExp(`^rgba\\(${Ic},${Ic},${Ic},${jc}\\)$`),Xc=new RegExp(`^hsl\\(${jc},${Ic},${Ic}\\)$`),Jc=new RegExp(`^hsla\\(${jc},${Ic},${Ic},${jc}\\)$`),Zc={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function Qc(){return this.rgb().formatHex()}function Kc(){return this.rgb().formatRgb()}function tf(t){var e,n;return t=(t+"").trim().toLowerCase(),(e=Wc.exec(t))?(n=e[1].length,e=parseInt(e[1],16),6===n?ef(e):3===n?new af(e>>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?nf(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?nf(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=Hc.exec(t))?new af(e[1],e[2],e[3],1):(e=Yc.exec(t))?new af(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=Gc.exec(t))?nf(e[1],e[2],e[3],e[4]):(e=Vc.exec(t))?nf(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=Xc.exec(t))?hf(e[1],e[2]/100,e[3]/100,1):(e=Jc.exec(t))?hf(e[1],e[2]/100,e[3]/100,e[4]):Zc.hasOwnProperty(t)?ef(Zc[t]):"transparent"===t?new af(NaN,NaN,NaN,0):null}function ef(t){return new af(t>>16&255,t>>8&255,255&t,1)}function nf(t,e,n,r){return r<=0&&(t=e=n=NaN),new af(t,e,n,r)}function rf(t){return t instanceof Lc||(t=tf(t)),t?new af((t=t.rgb()).r,t.g,t.b,t.opacity):new af}function of(t,e,n,r){return 1===arguments.length?rf(t):new af(t,e,n,null==r?1:r)}function af(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function sf(){return`#${ff(this.r)}${ff(this.g)}${ff(this.b)}`}function uf(){const t=lf(this.opacity);return`${1===t?"rgb(":"rgba("}${cf(this.r)}, ${cf(this.g)}, ${cf(this.b)}${1===t?")":`, ${t})`}`}function lf(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function cf(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function ff(t){return((t=cf(t))<16?"0":"")+t.toString(16)}function hf(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new gf(t,e,n,r)}function df(t){if(t instanceof gf)return new gf(t.h,t.s,t.l,t.opacity);if(t instanceof Lc||(t=tf(t)),!t)return new gf;if(t instanceof gf)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),o=Math.max(e,n,r),a=NaN,s=o-i,u=(o+i)/2;return s?(a=e===o?(n-r)/s+6*(n0&&u<1?0:a,new gf(a,s,u,t.opacity)}function pf(t,e,n,r){return 1===arguments.length?df(t):new gf(t,e,n,null==r?1:r)}function gf(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function mf(t){return(t=(t||0)%360)<0?t+360:t}function yf(t){return Math.max(0,Math.min(1,t||0))}function vf(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}Oc(Lc,tf,{copy(t){return Object.assign(new this.constructor,this,t)},displayable(){return this.rgb().displayable()},hex:Qc,formatHex:Qc,formatHex8:function(){return this.rgb().formatHex8()},formatHsl:function(){return df(this).formatHsl()},formatRgb:Kc,toString:Kc}),Oc(af,of,Rc(Lc,{brighter(t){return t=null==t?qc:Math.pow(qc,t),new af(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=null==t?Uc:Math.pow(Uc,t),new af(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new af(cf(this.r),cf(this.g),cf(this.b),lf(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:sf,formatHex:sf,formatHex8:function(){return`#${ff(this.r)}${ff(this.g)}${ff(this.b)}${ff(255*(isNaN(this.opacity)?1:this.opacity))}`},formatRgb:uf,toString:uf})),Oc(gf,pf,Rc(Lc,{brighter(t){return t=null==t?qc:Math.pow(qc,t),new gf(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=null==t?Uc:Math.pow(Uc,t),new gf(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new af(vf(t>=240?t-240:t+120,i,r),vf(t,i,r),vf(t<120?t+240:t-120,i,r),this.opacity)},clamp(){return new gf(mf(this.h),yf(this.s),yf(this.l),lf(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=lf(this.opacity);return`${1===t?"hsl(":"hsla("}${mf(this.h)}, ${100*yf(this.s)}%, ${100*yf(this.l)}%${1===t?")":`, ${t})`}`}}));const _f=Math.PI/180,xf=180/Math.PI,bf=.96422,wf=1,kf=.82521,Af=4/29,Mf=6/29,Ef=3*Mf*Mf,Df=Mf*Mf*Mf;function Cf(t){if(t instanceof Sf)return new Sf(t.l,t.a,t.b,t.opacity);if(t instanceof Of)return Rf(t);t instanceof af||(t=rf(t));var e,n,r=zf(t.r),i=zf(t.g),o=zf(t.b),a=$f((.2225045*r+.7168786*i+.0606169*o)/wf);return r===i&&i===o?e=n=a:(e=$f((.4360747*r+.3850649*i+.1430804*o)/bf),n=$f((.0139322*r+.0971045*i+.7141733*o)/kf)),new Sf(116*a-16,500*(e-a),200*(a-n),t.opacity)}function Ff(t,e,n,r){return 1===arguments.length?Cf(t):new Sf(t,e,n,null==r?1:r)}function Sf(t,e,n,r){this.l=+t,this.a=+e,this.b=+n,this.opacity=+r}function $f(t){return t>Df?Math.pow(t,1/3):t/Ef+Af}function Tf(t){return t>Mf?t*t*t:Ef*(t-Af)}function Bf(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function zf(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Nf(t,e,n,r){return 1===arguments.length?function(t){if(t instanceof Of)return new Of(t.h,t.c,t.l,t.opacity);if(t instanceof Sf||(t=Cf(t)),0===t.a&&0===t.b)return new Of(NaN,0=1?(n=1,e-1):Math.floor(n*e),i=t[r],o=t[r+1],a=r>0?t[r-1]:2*i-o,s=r()=>t;function Qf(t,e){return function(n){return t+n*e}}function Kf(t,e){var n=e-t;return n?Qf(t,n>180||n<-180?n-360*Math.round(n/360):n):Zf(isNaN(t)?e:t)}function th(t){return 1==(t=+t)?eh:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):Zf(isNaN(e)?n:e)}}function eh(t,e){var n=e-t;return n?Qf(t,n):Zf(isNaN(t)?e:t)}var nh=function t(e){var n=th(e);function r(t,e){var r=n((t=of(t)).r,(e=of(e)).r),i=n(t.g,e.g),o=n(t.b,e.b),a=eh(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=o(e),t.opacity=a(e),t+""}}return r.gamma=t,r}(1);function rh(t){return function(e){var n,r,i=e.length,o=new Array(i),a=new Array(i),s=new Array(i);for(n=0;no&&(i=e.slice(o,i),s[a]?s[a]+=i:s[++a]=i),(n=n[0])===(r=r[0])?s[a]?s[a]+=r:s[++a]=r:(s[++a]=null,u.push({i:a,x:ch(n,r)})),o=dh.lastIndex;return o180?e+=360:e-t>180&&(t+=360),o.push({i:n.push(i(n)+"rotate(",null,r)-2,x:ch(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(o.rotate,a.rotate,s,u),function(t,e,n,o){t!==e?o.push({i:n.push(i(n)+"skewX(",null,r)-2,x:ch(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(o.skewX,a.skewX,s,u),function(t,e,n,r,o,a){if(t!==n||e!==r){var s=o.push(i(o)+"scale(",null,",",null,")");a.push({i:s-4,x:ch(t,n)},{i:s-2,x:ch(e,r)})}else 1===n&&1===r||o.push(i(o)+"scale("+n+","+r+")")}(o.scaleX,o.scaleY,a.scaleX,a.scaleY,s,u),o=a=null,function(t){for(var e,n=-1,r=u.length;++ne&&(n=t,t=e,e=n),function(n){return Math.max(t,Math.min(e,n))}}(a[0],a[t-1])),r=t>2?jh:Ph,i=o=null,f}function f(e){return null==e||isNaN(e=+e)?n:(i||(i=r(a.map(t),s,u)))(t(l(e)))}return f.invert=function(n){return l(e((o||(o=r(s,a.map(t),ch)))(n)))},f.domain=function(t){return arguments.length?(a=Array.from(t,Rh),c()):a.slice()},f.range=function(t){return arguments.length?(s=Array.from(t),c()):s.slice()},f.rangeRound=function(t){return s=Array.from(t),u=mh,c()},f.clamp=function(t){return arguments.length?(l=!!t||Uh,c()):l!==Uh},f.interpolate=function(t){return arguments.length?(u=t,c()):u},f.unknown=function(t){return arguments.length?(n=t,f):n},function(n,r){return t=n,e=r,c()}}function Hh(){return Wh()(Uh,Uh)}function Yh(t,e,n,r){var i,o=xe(t,e,n);switch((r=Oe(null==r?",f":r)).type){case"s":var a=Math.max(Math.abs(t),Math.abs(e));return null!=r.precision||isNaN(i=Ve(o,a))||(r.precision=i),Ie(r,a);case"":case"e":case"g":case"p":case"r":null!=r.precision||isNaN(i=Xe(o,Math.max(Math.abs(t),Math.abs(e))))||(r.precision=i-("e"===r.type));break;case"f":case"%":null!=r.precision||isNaN(i=Ge(o))||(r.precision=i-2*("%"===r.type))}return je(r)}function Gh(t){var e=t.domain;return t.ticks=function(t){var n=e();return ve(n[0],n[n.length-1],null==t?10:t)},t.tickFormat=function(t,n){var r=e();return Yh(r[0],r[r.length-1],null==t?10:t,n)},t.nice=function(n){null==n&&(n=10);var r,i,o=e(),a=0,s=o.length-1,u=o[a],l=o[s],c=10;for(l0;){if((i=_e(u,l,n))===r)return o[a]=u,o[s]=l,e(o);if(i>0)u=Math.floor(u/i)*i,l=Math.ceil(l/i)*i;else{if(!(i<0))break;u=Math.ceil(u*i)/i,l=Math.floor(l*i)/i}r=i}return t},t}function Vh(t,e){var n,r=0,i=(t=t.slice()).length-1,o=t[r],a=t[i];return a-t(-e,n)}function ed(t){const e=t(Xh,Jh),n=e.domain;let r,i,o=10;function a(){return r=function(t){return t===Math.E?Math.log:10===t&&Math.log10||2===t&&Math.log2||(t=Math.log(t),e=>Math.log(e)/t)}(o),i=function(t){return 10===t?Kh:t===Math.E?Math.exp:e=>Math.pow(t,e)}(o),n()[0]<0?(r=td(r),i=td(i),t(Zh,Qh)):t(Xh,Jh),e}return e.base=function(t){return arguments.length?(o=+t,a()):o},e.domain=function(t){return arguments.length?(n(t),a()):n()},e.ticks=t=>{const e=n();let a=e[0],s=e[e.length-1];const u=s0){for(;f<=h;++f)for(l=1;ls)break;p.push(c)}}else for(;f<=h;++f)for(l=o-1;l>=1;--l)if(c=f>0?l/i(-f):l*i(f),!(cs)break;p.push(c)}2*p.length{if(null==t&&(t=10),null==n&&(n=10===o?"s":","),"function"!=typeof n&&(o%1||null!=(n=Oe(n)).precision||(n.trim=!0),n=je(n)),t===1/0)return n;const a=Math.max(1,o*t/e.ticks().length);return t=>{let e=t/i(Math.round(r(t)));return e*on(Vh(n(),{floor:t=>i(Math.floor(r(t))),ceil:t=>i(Math.ceil(r(t)))})),e}function nd(t){return function(e){return Math.sign(e)*Math.log1p(Math.abs(e/t))}}function rd(t){return function(e){return Math.sign(e)*Math.expm1(Math.abs(e))*t}}function id(t){var e=1,n=t(nd(e),rd(e));return n.constant=function(n){return arguments.length?t(nd(e=+n),rd(e)):e},Gh(n)}function od(t){return function(e){return e<0?-Math.pow(-e,t):Math.pow(e,t)}}function ad(t){return t<0?-Math.sqrt(-t):Math.sqrt(t)}function sd(t){return t<0?-t*t:t*t}function ud(t){var e=t(Uh,Uh),n=1;return e.exponent=function(e){return arguments.length?1===(n=+e)?t(Uh,Uh):.5===n?t(ad,sd):t(od(n),od(1/n)):n},Gh(e)}function ld(){var t=ud(Wh());return t.copy=function(){return Ih(t,ld()).exponent(t.exponent())},Tc.apply(t,arguments),t}function cd(t){return new Date(t)}function fd(t){return t instanceof Date?+t:+new Date(+t)}function hd(t,e,n,r,i,o,a,s,u,l){var c=Hh(),f=c.invert,h=c.domain,d=l(".%L"),p=l(":%S"),g=l("%I:%M"),m=l("%I %p"),y=l("%a %d"),v=l("%b %d"),_=l("%B"),x=l("%Y");function b(t){return(u(t)0?r:1:0}const $d="linear",Td="log",Bd="pow",zd="sqrt",Nd="symlog",Od="time",Rd="utc",Ld="sequential",Ud="diverging",qd="quantile",Pd="quantize",jd="threshold",Id="ordinal",Wd="point",Hd="band",Yd="bin-ordinal",Gd="continuous",Vd="discrete",Xd="discretizing",Jd="interpolating",Zd="temporal";function Qd(){const t=Nc().unknown(void 0),e=t.domain,n=t.range;let r,i,o=[0,1],a=!1,s=0,u=0,l=.5;function c(){const t=e().length,c=o[1]d+r*t));return n(c?p.reverse():p)}return delete t.unknown,t.domain=function(t){return arguments.length?(e(t),c()):e()},t.range=function(t){return arguments.length?(o=[+t[0],+t[1]],c()):o.slice()},t.rangeRound=function(t){return o=[+t[0],+t[1]],a=!0,c()},t.bandwidth=function(){return i},t.step=function(){return r},t.round=function(t){return arguments.length?(a=!!t,c()):a},t.padding=function(t){return arguments.length?(u=Math.max(0,Math.min(1,t)),s=u,c()):s},t.paddingInner=function(t){return arguments.length?(s=Math.max(0,Math.min(1,t)),c()):s},t.paddingOuter=function(t){return arguments.length?(u=Math.max(0,Math.min(1,t)),c()):u},t.align=function(t){return arguments.length?(l=Math.max(0,Math.min(1,t)),c()):l},t.invertRange=function(t){if(null==t[0]||null==t[1])return;const r=o[1]o[1-r])?void 0:(u=Math.max(0,ie(a,f)-1),l=f===h?u:ie(a,h)-1,f-a[u]>i+1e-10&&++u,r&&(c=u,u=s-l,l=s-c),u>l?void 0:e().slice(u,l+1))},t.invert=function(e){const n=t.invertRange([e,e]);return n?n[0]:n},t.copy=function(){return Qd().domain(e()).range(o).round(a).paddingInner(s).paddingOuter(u).align(l)},c()}function Kd(t){const e=t.copy;return t.padding=t.paddingOuter,delete t.paddingInner,t.copy=function(){return Kd(e())},t}var tp=Array.prototype.map;const ep=Array.prototype.slice;const np=new Map,rp=Symbol("vega_scale");function ip(t){return t[rp]=!0,t}function op(t){return t&&!0===t[rp]}function ap(t,e,n){return arguments.length>1?(np.set(t,function(t,e,n){const r=function(){const n=e();return n.invertRange||(n.invertRange=n.invert?function(t){return function(e){let n,r=e[0],i=e[1];return i=s&&n[o]<=u&&(l<0&&(l=o),r=o);if(!(l<0))return s=t.invertExtent(n[l]),u=t.invertExtent(n[r]),[void 0===s[0]?s[1]:s[0],void 0===u[1]?u[0]:u[1]]}}(n):void 0),n.type=t,ip(n)};return r.metadata=Tt(V(n)),r}(t,e,n)),this):sp(t)?np.get(t):void 0}function sp(t){return np.has(t)}function up(t,e){const n=np.get(t);return n&&n.metadata[e]}function lp(t){return up(t,Gd)}function cp(t){return up(t,Vd)}function fp(t){return up(t,Xd)}function hp(t){return up(t,Td)}function dp(t){return up(t,Jd)}function pp(t){return up(t,qd)}ap("identity",(function t(e){var n;function r(t){return null==t||isNaN(t=+t)?n:t}return r.invert=r,r.domain=r.range=function(t){return arguments.length?(e=Array.from(t,Rh),r):e.slice()},r.unknown=function(t){return arguments.length?(n=t,r):n},r.copy=function(){return t(e).unknown(n)},e=arguments.length?Array.from(e,Rh):[0,1],Gh(r)})),ap($d,(function t(){var e=Hh();return e.copy=function(){return Ih(e,t())},Tc.apply(e,arguments),Gh(e)}),Gd),ap(Td,(function t(){const e=ed(Wh()).domain([1,10]);return e.copy=()=>Ih(e,t()).base(e.base()),Tc.apply(e,arguments),e}),[Gd,Td]),ap(Bd,ld,Gd),ap(zd,(function(){return ld.apply(null,arguments).exponent(.5)}),Gd),ap(Nd,(function t(){var e=id(Wh());return e.copy=function(){return Ih(e,t()).constant(e.constant())},Tc.apply(e,arguments)}),Gd),ap(Od,(function(){return Tc.apply(hd(Un,qn,zn,Tn,yn,dn,fn,ln,un,ei).domain([new Date(2e3,0,1),new Date(2e3,0,2)]),arguments)}),[Gd,Zd]),ap(Rd,(function(){return Tc.apply(hd(Rn,Ln,Nn,Bn,Mn,pn,hn,cn,un,ri).domain([Date.UTC(2e3,0,1),Date.UTC(2e3,0,2)]),arguments)}),[Gd,Zd]),ap(Ld,gd,[Gd,Jd]),ap(`${Ld}-${$d}`,gd,[Gd,Jd]),ap(`${Ld}-${Td}`,(function t(){var e=ed(dd()).domain([1,10]);return e.copy=function(){return pd(e,t()).base(e.base())},Bc.apply(e,arguments)}),[Gd,Jd,Td]),ap(`${Ld}-${Bd}`,md,[Gd,Jd]),ap(`${Ld}-${zd}`,(function(){return md.apply(null,arguments).exponent(.5)}),[Gd,Jd]),ap(`${Ld}-${Nd}`,(function t(){var e=id(dd());return e.copy=function(){return pd(e,t()).constant(e.constant())},Bc.apply(e,arguments)}),[Gd,Jd]),ap(`${Ud}-${$d}`,(function t(){var e=Gh(yd()(Uh));return e.copy=function(){return pd(e,t())},Bc.apply(e,arguments)}),[Gd,Jd]),ap(`${Ud}-${Td}`,(function t(){var e=ed(yd()).domain([.1,1,10]);return e.copy=function(){return pd(e,t()).base(e.base())},Bc.apply(e,arguments)}),[Gd,Jd,Td]),ap(`${Ud}-${Bd}`,vd,[Gd,Jd]),ap(`${Ud}-${zd}`,(function(){return vd.apply(null,arguments).exponent(.5)}),[Gd,Jd]),ap(`${Ud}-${Nd}`,(function t(){var e=id(yd());return e.copy=function(){return pd(e,t()).constant(e.constant())},Bc.apply(e,arguments)}),[Gd,Jd]),ap(qd,(function t(){var e,n=[],r=[],i=[];function o(){var t=0,e=Math.max(1,r.length);for(i=new Array(e-1);++t0?i[e-1]:n[0],e=i?[o[i-1],r]:[o[e-1],o[e]]},s.unknown=function(t){return arguments.length?(e=t,s):s},s.thresholds=function(){return o.slice()},s.copy=function(){return t().domain([n,r]).range(a).unknown(e)},Tc.apply(Gh(s),arguments)}),Xd),ap(jd,(function t(){var e,n=[.5],r=[0,1],i=1;function o(t){return null!=t&&t<=t?r[ie(n,t,0,i)]:e}return o.domain=function(t){return arguments.length?(n=Array.from(t),i=Math.min(n.length,r.length-1),o):n.slice()},o.range=function(t){return arguments.length?(r=Array.from(t),i=Math.min(n.length,r.length-1),o):r.slice()},o.invertExtent=function(t){var e=r.indexOf(t);return[n[e-1],n[e]]},o.unknown=function(t){return arguments.length?(e=t,o):e},o.copy=function(){return t().domain(n).range(r).unknown(e)},Tc.apply(o,arguments)}),Xd),ap(Yd,(function t(){let e=[],n=[];function r(t){return null==t||t!=t?void 0:n[(ie(e,t)-1)%n.length]}return r.domain=function(t){return arguments.length?(e=function(t){return tp.call(t,S)}(t),r):e.slice()},r.range=function(t){return arguments.length?(n=ep.call(t),r):n.slice()},r.tickFormat=function(t,n){return Yh(e[0],F(e),null==t?10:t,n)},r.copy=function(){return t().domain(r.domain()).range(r.range())},r}),[Vd,Xd]),ap(Id,Nc,Vd),ap(Hd,Qd,Vd),ap(Wd,(function(){return Kd(Qd().paddingInner(1))}),Vd);const gp=["clamp","base","constant","exponent"];function mp(t,e){const n=e[0],r=F(e)-n;return function(e){return t(n+e*r)}}function yp(t,e,n){return Nh(xp(e||"rgb",n),t)}function vp(t,e){const n=new Array(e),r=e+1;for(let i=0;it[e]?a[e](t[e]()):0)),a):rt(.5)}function xp(t,e){const n=Oh[function(t){return"interpolate"+t.toLowerCase().split("-").map((t=>t[0].toUpperCase()+t.slice(1))).join("")}(t)];return null!=e&&n&&n.gamma?n.gamma(e):n}function bp(t){if(k(t))return t;const e=t.length/6|0,n=new Array(e);for(let r=0;r1?(kp[t]=e,this):kp[t]}wp({accent:bd,category10:xd,category20:"1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5",category20b:"393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6",category20c:"3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9",dark2:wd,observable10:kd,paired:Ad,pastel1:Md,pastel2:Ed,set1:Dd,set2:Cd,set3:Fd,tableau10:"4c78a8f58518e4575672b7b254a24beeca3bb279a2ff9da69d755dbab0ac",tableau20:"4c78a89ecae9f58518ffbf7954a24b88d27ab79a20f2cf5b43989483bcb6e45756ff9d9879706ebab0acd67195fcbfd2b279a2d6a5c99e765fd8b5a5"},bp),wp({blues:"cfe1f2bed8eca8cee58fc1de74b2d75ba3cf4592c63181bd206fb2125ca40a4a90",greens:"d3eecdc0e6baabdda594d3917bc77d60ba6c46ab5e329a512089430e7735036429",greys:"e2e2e2d4d4d4c4c4c4b1b1b19d9d9d8888887575756262624d4d4d3535351e1e1e",oranges:"fdd8b3fdc998fdb87bfda55efc9244f87f2cf06b18e4580bd14904b93d029f3303",purples:"e2e1efd4d4e8c4c5e0b4b3d6a3a0cc928ec3827cb97566ae684ea25c3696501f8c",reds:"fdc9b4fcb49afc9e80fc8767fa7051f6573fec3f2fdc2a25c81b1db21218970b13",blueGreen:"d5efedc1e8e0a7ddd18bd2be70c6a958ba9144ad77319c5d2089460e7736036429",bluePurple:"ccddecbad0e4a8c2dd9ab0d4919cc98d85be8b6db28a55a6873c99822287730f71",greenBlue:"d3eecec5e8c3b1e1bb9bd8bb82cec269c2ca51b2cd3c9fc7288abd1675b10b60a1",orangeRed:"fddcaffdcf9bfdc18afdad77fb9562f67d53ee6545e24932d32d1ebf130da70403",purpleBlue:"dbdaebc8cee4b1c3de97b7d87bacd15b9fc93a90c01e7fb70b70ab056199045281",purpleBlueGreen:"dbd8eac8cee4b0c3de93b7d872acd1549fc83892bb1c88a3097f8702736b016353",purpleRed:"dcc9e2d3b3d7ce9eccd186c0da6bb2e14da0e23189d91e6fc61159ab07498f023a",redPurple:"fccfccfcbec0faa9b8f98faff571a5ec539ddb3695c41b8aa908808d0179700174",yellowGreen:"e4f4acd1eca0b9e2949ed68880c97c62bb6e47aa5e3297502083440e723b036034",yellowOrangeBrown:"feeaa1fedd84fecc63feb746fca031f68921eb7215db5e0bc54c05ab3d038f3204",yellowOrangeRed:"fee087fed16ffebd59fea849fd903efc7335f9522bee3423de1b20ca0b22af0225",blueOrange:"134b852f78b35da2cb9dcae1d2e5eff2f0ebfce0bafbbf74e8932fc5690d994a07",brownBlueGreen:"704108a0651ac79548e3c78af3e6c6eef1eac9e9e48ed1c74da79e187a72025147",purpleGreen:"5b1667834792a67fb6c9aed3e6d6e8eff0efd9efd5aedda971bb75368e490e5e29",purpleOrange:"4114696647968f83b7b9b4d6dadbebf3eeeafce0bafbbf74e8932fc5690d994a07",redBlue:"8c0d25bf363adf745ef4ae91fbdbc9f2efeed2e5ef9dcae15da2cb2f78b3134b85",redGrey:"8c0d25bf363adf745ef4ae91fcdccbfaf4f1e2e2e2c0c0c0969696646464343434",yellowGreenBlue:"eff9bddbf1b4bde5b594d5b969c5be45b4c22c9ec02182b82163aa23479c1c3185",redYellowBlue:"a50026d4322cf16e43fcac64fedd90faf8c1dcf1ecabd6e875abd04a74b4313695",redYellowGreen:"a50026d4322cf16e43fcac63fedd8df9f7aed7ee8ea4d86e64bc6122964f006837",pinkYellowGreen:"8e0152c0267edd72adf0b3d6faddedf5f3efe1f2cab6de8780bb474f9125276419",spectral:"9e0142d13c4bf0704afcac63fedd8dfbf8b0e0f3a1a9dda269bda94288b55e4fa2",viridis:"440154470e61481a6c482575472f7d443a834144873d4e8a39568c35608d31688e2d708e2a788e27818e23888e21918d1f988b1fa08822a8842ab07f35b77943bf7154c56866cc5d7ad1518fd744a5db36bcdf27d2e21be9e51afde725",magma:"0000040404130b0924150e3720114b2c11603b0f704a107957157e651a80721f817f24828c29819a2e80a8327db6377ac43c75d1426fde4968e95462f1605df76f5cfa7f5efc8f65fe9f6dfeaf78febf84fece91fddea0fcedaffcfdbf",inferno:"0000040403130c0826170c3b240c4f330a5f420a68500d6c5d126e6b176e781c6d86216b932667a12b62ae305cbb3755c73e4cd24644dd513ae65c30ed6925f3771af8850ffb9506fca50afcb519fac62df6d645f2e661f3f484fcffa4",plasma:"0d088723069033059742039d5002a25d01a66a00a87801a88405a7900da49c179ea72198b12a90ba3488c33d80cb4779d35171da5a69e16462e76e5bed7953f2834cf68f44fa9a3dfca636fdb32ffec029fcce25f9dc24f5ea27f0f921",cividis:"00205100235800265d002961012b65042e670831690d346b11366c16396d1c3c6e213f6e26426e2c456e31476e374a6e3c4d6e42506e47536d4c566d51586e555b6e5a5e6e5e616e62646f66676f6a6a706e6d717270717573727976737c79747f7c75827f758682768985778c8877908b78938e789691789a94789e9778a19b78a59e77a9a177aea575b2a874b6ab73bbaf71c0b26fc5b66dc9b96acebd68d3c065d8c462ddc85fe2cb5ce7cf58ebd355f0d652f3da4ff7de4cfae249fce647",rainbow:"6e40aa883eb1a43db3bf3cafd83fa4ee4395fe4b83ff576eff6659ff7847ff8c38f3a130e2b72fcfcc36bee044aff05b8ff4576ff65b52f6673af27828ea8d1ddfa319d0b81cbecb23abd82f96e03d82e14c6edb5a5dd0664dbf6e40aa",sinebow:"ff4040fc582af47218e78d0bd5a703bfbf00a7d5038de70b72f41858fc2a40ff402afc5818f4720be78d03d5a700bfbf03a7d50b8de71872f42a58fc4040ff582afc7218f48d0be7a703d5bf00bfd503a7e70b8df41872fc2a58ff4040",turbo:"23171b32204a3e2a71453493493eae4b49c54a53d7485ee44569ee4074f53c7ff8378af93295f72e9ff42ba9ef28b3e926bce125c5d925cdcf27d5c629dcbc2de3b232e9a738ee9d3ff39347f68950f9805afc7765fd6e70fe667cfd5e88fc5795fb51a1f84badf545b9f140c5ec3cd0e637dae034e4d931ecd12ef4c92bfac029ffb626ffad24ffa223ff9821ff8d1fff821dff771cfd6c1af76118f05616e84b14df4111d5380fcb2f0dc0260ab61f07ac1805a313029b0f00950c00910b00",browns:"eedbbdecca96e9b97ae4a865dc9856d18954c7784cc0673fb85536ad44339f3632",tealBlues:"bce4d89dd3d181c3cb65b3c245a2b9368fae347da0306a932c5985",teals:"bbdfdfa2d4d58ac9c975bcbb61b0af4da5a43799982b8b8c1e7f7f127273006667",warmGreys:"dcd4d0cec5c1c0b8b4b3aaa7a59c9998908c8b827f7e7673726866665c5a59504e",goldGreen:"f4d166d5ca60b6c35c98bb597cb25760a6564b9c533f8f4f33834a257740146c36",goldOrange:"f4d166f8be5cf8aa4cf5983bf3852aef701be2621fd65322c54923b142239e3a26",goldRed:"f4d166f6be59f9aa51fc964ef6834bee734ae56249db5247cf4244c43141b71d3e",lightGreyRed:"efe9e6e1dad7d5cbc8c8bdb9bbaea9cd967ddc7b43e15f19df4011dc000b",lightGreyTeal:"e4eaead6dcddc8ced2b7c2c7a6b4bc64b0bf22a6c32295c11f85be1876bc",lightMulti:"e0f1f2c4e9d0b0de9fd0e181f6e072f6c053f3993ef77440ef4a3c",lightOrange:"f2e7daf7d5baf9c499fab184fa9c73f68967ef7860e8645bde515bd43d5b",lightTealBlue:"e3e9e0c0dccf9aceca7abfc859afc0389fb9328dad2f7ca0276b95255988",darkBlue:"3232322d46681a5c930074af008cbf05a7ce25c0dd38daed50f3faffffff",darkGold:"3c3c3c584b37725e348c7631ae8b2bcfa424ecc31ef9de30fff184ffffff",darkGreen:"3a3a3a215748006f4d048942489e4276b340a6c63dd2d836ffeb2cffffaa",darkMulti:"3737371f5287197d8c29a86995ce3fffe800ffffff",darkRed:"3434347036339e3c38cc4037e75d1eec8620eeab29f0ce32ffeb2c"},(t=>yp(bp(t))));const Mp="symbol",Ep="discrete",Dp=t=>k(t)?t.map((t=>String(t))):String(t),Cp=(t,e)=>t[1]-e[1],Fp=(t,e)=>e[1]-t[1];function Sp(t,e,n){let r;return yt(e)&&(t.bins&&(e=Math.max(e,t.bins.length)),null!=n&&(e=Math.min(e,Math.floor(Et(t.domain())/n||1)+1))),A(e)&&(r=e.step,e=e.interval),_t(e)&&(e=t.type===Od?Dr(e):t.type==Rd?Cr(e):s("Only time and utc scales accept interval strings."),r&&(e=e.every(r))),e}function $p(t,e,n){let r=t.range(),i=r[0],o=F(r),a=Cp;if(i>o&&(r=o,o=i,i=r,a=Fp),i=Math.floor(i),o=Math.ceil(o),e=e.map((e=>[e,t(e)])).filter((t=>i<=t[1]&&t[1]<=o)).sort(a).map((t=>t[0])),n>0&&e.length>1){const t=[e[0],F(e)];for(;e.length>n&&e.length>=3;)e=e.filter(((t,e)=>!(e%2)));e.length<3&&(e=t)}return e}function Tp(t,e){return t.bins?$p(t,t.bins,e):t.ticks?t.ticks(e):t.domain()}function Bp(t,e,n,r,i,o){const a=e.type;let s=Dp;if(a===Od||i===Od)s=t.timeFormat(r);else if(a===Rd||i===Rd)s=t.utcFormat(r);else if(hp(a)){const i=t.formatFloat(r);if(o||e.bins)s=i;else{const t=zp(e,n,!1);s=e=>t(e)?i(e):""}}else if(e.tickFormat){const i=e.domain();s=t.formatSpan(i[0],i[i.length-1],n,r)}else r&&(s=t.format(r));return s}function zp(t,e,n){const r=Tp(t,e),i=t.base(),o=Math.log(i),a=Math.max(1,i*e/r.length),s=t=>{let e=t/Math.pow(i,Math.round(Math.log(t)/o));return e*iNp[t.type]||t.bins;function Up(t,e,n,r,i,o,a){const s=Op[e.type]&&o!==Od&&o!==Rd?function(t,e,n){const r=e[Op[e.type]](),i=r.length;let o,a=i>1?r[1]-r[0]:r[0];for(o=1;o(e,n,r)=>{const i=Pp(r[n+1],Pp(r.max,1/0)),o=Wp(e,t),a=Wp(i,t);return o&&a?o+" – "+a:a?"< "+a:"≥ "+o},Pp=(t,e)=>null!=t?t:e,jp=t=>(e,n)=>n?t(e):null,Ip=t=>e=>t(e),Wp=(t,e)=>Number.isFinite(t)?e(t):null;function Hp(t,e,n,r){const i=r||e.type;return _t(n)&&function(t){return up(t,Zd)}(i)&&(n=n.replace(/%a/g,"%A").replace(/%b/g,"%B")),n||i!==Od?n||i!==Rd?Up(t,e,5,null,n,r,!0):t.utcFormat("%A, %d %B %Y, %X UTC"):t.timeFormat("%A, %d %B %Y, %X")}function Yp(t,e,n){n=n||{};const r=Math.max(3,n.maxlen||7),i=Hp(t,e,n.format,n.formatType);if(fp(e.type)){const t=Rp(e).slice(1).map(i),n=t.length;return`${n} boundar${1===n?"y":"ies"}: ${t.join(", ")}`}if(cp(e.type)){const t=e.domain(),n=t.length;return`${n} value${1===n?"":"s"}: ${n>r?t.slice(0,r-2).map(i).join(", ")+", ending with "+t.slice(-1).map(i):t.map(i).join(", ")}`}{const t=e.domain();return`values from ${i(t[0])} to ${i(F(t))}`}}let Gp=0;const Vp="p_";function Xp(t){return t&&t.gradient}function Jp(t,e,n){const r=t.gradient;let i=t.id,o="radial"===r?Vp:"";return i||(i=t.id="gradient_"+Gp++,"radial"===r?(t.x1=Zp(t.x1,.5),t.y1=Zp(t.y1,.5),t.r1=Zp(t.r1,0),t.x2=Zp(t.x2,.5),t.y2=Zp(t.y2,.5),t.r2=Zp(t.r2,.5),o=Vp):(t.x1=Zp(t.x1,0),t.y1=Zp(t.y1,0),t.x2=Zp(t.x2,1),t.y2=Zp(t.y2,0))),e[i]=t,"url("+(n||"")+"#"+o+i+")"}function Zp(t,e){return null!=t?t:e}function Qp(t,e){var n,r=[];return n={gradient:"linear",x1:t?t[0]:0,y1:t?t[1]:0,x2:e?e[0]:1,y2:e?e[1]:0,stops:r,stop:function(t,e){return r.push({offset:t,color:e}),n}}}const Kp={basis:{curve:function(t){return new tc(t)}},"basis-closed":{curve:function(t){return new ec(t)}},"basis-open":{curve:function(t){return new nc(t)}},bundle:{curve:ic,tension:"beta",value:.85},cardinal:{curve:sc,tension:"tension",value:0},"cardinal-open":{curve:fc,tension:"tension",value:0},"cardinal-closed":{curve:lc,tension:"tension",value:0},"catmull-rom":{curve:pc,tension:"alpha",value:.5},"catmull-rom-closed":{curve:mc,tension:"alpha",value:.5},"catmull-rom-open":{curve:vc,tension:"alpha",value:.5},linear:{curve:Yl},"linear-closed":{curve:function(t){return new _c(t)}},monotone:{horizontal:function(t){return new Mc(t)},vertical:function(t){return new Ac(t)}},natural:{curve:function(t){return new Dc(t)}},step:{curve:function(t){return new Fc(t,.5)}},"step-after":{curve:function(t){return new Fc(t,1)}},"step-before":{curve:function(t){return new Fc(t,0)}}};function tg(t,e,n){var r=ut(Kp,t)&&Kp[t],i=null;return r&&(i=r.curve||r[e||"vertical"],r.tension&&null!=n&&(i=i[r.tension](n))),i}const eg={m:2,l:2,h:1,v:1,z:0,c:6,s:4,q:4,t:2,a:7},ng=/[mlhvzcsqta]([^mlhvzcsqta]+|$)/gi,rg=/^[+-]?(([0-9]*\.[0-9]+)|([0-9]+\.)|([0-9]+))([eE][+-]?[0-9]+)?/,ig=/^((\s+,?\s*)|(,\s*))/,og=/^[01]/;function ag(t){const e=[];return(t.match(ng)||[]).forEach((t=>{let n=t[0];const r=n.toLowerCase(),i=eg[r],o=function(t,e,n){const r=[];for(let i=0;e&&i1&&(g=Math.sqrt(g),n*=g,r*=g);const m=h/n,y=f/n,v=-f/r,_=h/r,x=m*s+y*u,b=v*s+_*u,w=m*t+y*e,k=v*t+_*e;let A=1/((w-x)*(w-x)+(k-b)*(k-b))-.25;A<0&&(A=0);let M=Math.sqrt(A);o==i&&(M=-M);const E=.5*(x+w)-M*(k-b),D=.5*(b+k)+M*(w-x),C=Math.atan2(b-D,x-E);let F=Math.atan2(k-D,w-E)-C;F<0&&1===o?F+=lg:F>0&&0===o&&(F-=lg);const S=Math.ceil(Math.abs(F/(ug+.001))),$=[];for(let t=0;t+t}function Fg(t,e,n){return Math.max(e,Math.min(t,n))}function Sg(){var t=Ag,e=Mg,n=Eg,r=Dg,i=Cg(0),o=i,a=i,s=i,u=null;function l(l,c,f){var h,d=null!=c?c:+t.call(this,l),p=null!=f?f:+e.call(this,l),g=+n.call(this,l),m=+r.call(this,l),y=Math.min(g,m)/2,v=Fg(+i.call(this,l),0,y),_=Fg(+o.call(this,l),0,y),x=Fg(+a.call(this,l),0,y),b=Fg(+s.call(this,l),0,y);if(u||(u=h=Ol()),v<=0&&_<=0&&x<=0&&b<=0)u.rect(d,p,g,m);else{var w=d+g,k=p+m;u.moveTo(d+v,p),u.lineTo(w-_,p),u.bezierCurveTo(w-kg*_,p,w,p+kg*_,w,p+_),u.lineTo(w,k-b),u.bezierCurveTo(w,k-kg*b,w-kg*b,k,w-b,k),u.lineTo(d+x,k),u.bezierCurveTo(d+kg*x,k,d,k-kg*x,d,k-x),u.lineTo(d,p+v),u.bezierCurveTo(d,p+kg*v,d+kg*v,p,d+v,p),u.closePath()}if(h)return u=null,h+""||null}return l.x=function(e){return arguments.length?(t=Cg(e),l):t},l.y=function(t){return arguments.length?(e=Cg(t),l):e},l.width=function(t){return arguments.length?(n=Cg(t),l):n},l.height=function(t){return arguments.length?(r=Cg(t),l):r},l.cornerRadius=function(t,e,n,r){return arguments.length?(i=Cg(t),o=null!=e?Cg(e):i,s=null!=n?Cg(n):i,a=null!=r?Cg(r):o,l):i},l.context=function(t){return arguments.length?(u=null==t?null:t,l):u},l}function $g(){var t,e,n,r,i,o,a,s,u=null;function l(t,e,n){const r=n/2;if(i){var l=a-e,c=t-o;if(l||c){var f=Math.hypot(l,c),h=(l/=f)*s,d=(c/=f)*s,p=Math.atan2(c,l);u.moveTo(o-h,a-d),u.lineTo(t-l*r,e-c*r),u.arc(t,e,r,p-Math.PI,p),u.lineTo(o+h,a+d),u.arc(o,a,s,p,p+Math.PI)}else u.arc(t,e,r,0,lg);u.closePath()}else i=1;o=t,a=e,s=r}function c(o){var a,s,c,f=o.length,h=!1;for(null==u&&(u=c=Ol()),a=0;a<=f;++a)!(at.x||0,zg=t=>t.y||0,Ng=t=>!(!1===t.defined),Og=function(){var t=Ll,e=Ul,n=yl(0),r=null,i=ql,o=Pl,a=jl,s=null,u=Rl(l);function l(){var l,c,f=+t.apply(this,arguments),h=+e.apply(this,arguments),d=i.apply(this,arguments)-Dl,p=o.apply(this,arguments)-Dl,g=vl(p-d),m=p>d;if(s||(s=l=u()),hMl)if(g>Cl-Ml)s.moveTo(h*xl(d),h*kl(d)),s.arc(0,0,h,d,p,!m),f>Ml&&(s.moveTo(f*xl(p),f*kl(p)),s.arc(0,0,f,p,d,m));else{var y,v,_=d,x=p,b=d,w=p,k=g,A=g,M=a.apply(this,arguments)/2,E=M>Ml&&(r?+r.apply(this,arguments):Al(f*f+h*h)),D=wl(vl(h-f)/2,+n.apply(this,arguments)),C=D,F=D;if(E>Ml){var S=Fl(E/f*kl(M)),$=Fl(E/h*kl(M));(k-=2*S)>Ml?(b+=S*=m?1:-1,w-=S):(k=0,b=w=(d+p)/2),(A-=2*$)>Ml?(_+=$*=m?1:-1,x-=$):(A=0,_=x=(d+p)/2)}var T=h*xl(_),B=h*kl(_),z=f*xl(w),N=f*kl(w);if(D>Ml){var O,R=h*xl(x),L=h*kl(x),U=f*xl(b),q=f*kl(b);if(g1?0:t<-1?El:Math.acos(t)}((P*I+j*W)/(Al(P*P+j*j)*Al(I*I+W*W)))/2),Y=Al(O[0]*O[0]+O[1]*O[1]);C=wl(D,(f-Y)/(H-1)),F=wl(D,(h-Y)/(H+1))}else C=F=0}A>Ml?F>Ml?(y=Il(U,q,T,B,h,F,m),v=Il(R,L,z,N,h,F,m),s.moveTo(y.cx+y.x01,y.cy+y.y01),FMl&&k>Ml?C>Ml?(y=Il(z,N,R,L,f,-C,m),v=Il(T,B,U,q,f,-C,m),s.lineTo(y.cx+y.x01,y.cy+y.y01),Ct.startAngle||0)).endAngle((t=>t.endAngle||0)).padAngle((t=>t.padAngle||0)).innerRadius((t=>t.innerRadius||0)).outerRadius((t=>t.outerRadius||0)).cornerRadius((t=>t.cornerRadius||0)),Rg=Jl().x(Bg).y1(zg).y0((t=>(t.y||0)+(t.height||0))).defined(Ng),Lg=Jl().y(zg).x1(Bg).x0((t=>(t.x||0)+(t.width||0))).defined(Ng),Ug=Xl().x(Bg).y(zg).defined(Ng),qg=Sg().x(Bg).y(zg).width((t=>t.width||0)).height((t=>t.height||0)).cornerRadius((t=>Tg(t.cornerRadiusTopLeft,t.cornerRadius)||0),(t=>Tg(t.cornerRadiusTopRight,t.cornerRadius)||0),(t=>Tg(t.cornerRadiusBottomRight,t.cornerRadius)||0),(t=>Tg(t.cornerRadiusBottomLeft,t.cornerRadius)||0)),Pg=function(t,e){let n=null,r=Rl(i);function i(){let i;if(n||(n=i=r()),t.apply(this,arguments).draw(n,+e.apply(this,arguments)),i)return n=null,i+""||null}return t="function"==typeof t?t:yl(t||Zl),e="function"==typeof e?e:yl(void 0===e?64:+e),i.type=function(e){return arguments.length?(t="function"==typeof e?e:yl(e),i):t},i.size=function(t){return arguments.length?(e="function"==typeof t?t:yl(+t),i):e},i.context=function(t){return arguments.length?(n=null==t?null:t,i):n},i}().type((t=>bg(t.shape||"circle"))).size((t=>Tg(t.size,64))),jg=$g().x(Bg).y(zg).defined(Ng).size((t=>t.size||1));function Ig(t){return t.cornerRadius||t.cornerRadiusTopLeft||t.cornerRadiusTopRight||t.cornerRadiusBottomRight||t.cornerRadiusBottomLeft}function Wg(t,e,n,r){return qg.context(t)(e,n,r)}var Hg=1;function Yg(){Hg=1}function Gg(t,e,n){var r=e.clip,i=t._defs,o=e.clip_id||(e.clip_id="clip"+Hg++),a=i.clipping[o]||(i.clipping[o]={id:o});return J(r)?a.path=r(null):Ig(n)?a.path=Wg(null,n,0,0):(a.width=n.width||0,a.height=n.height||0),"url(#"+o+")"}function Vg(t){this.clear(),t&&this.union(t)}function Xg(t){this.mark=t,this.bounds=this.bounds||new Vg}function Jg(t){Xg.call(this,t),this.items=this.items||[]}Vg.prototype={clone(){return new Vg(this)},clear(){return this.x1=+Number.MAX_VALUE,this.y1=+Number.MAX_VALUE,this.x2=-Number.MAX_VALUE,this.y2=-Number.MAX_VALUE,this},empty(){return this.x1===+Number.MAX_VALUE&&this.y1===+Number.MAX_VALUE&&this.x2===-Number.MAX_VALUE&&this.y2===-Number.MAX_VALUE},equals(t){return this.x1===t.x1&&this.y1===t.y1&&this.x2===t.x2&&this.y2===t.y2},set(t,e,n,r){return nthis.x2&&(this.x2=t),e>this.y2&&(this.y2=e),this},expand(t){return this.x1-=t,this.y1-=t,this.x2+=t,this.y2+=t,this},round(){return this.x1=Math.floor(this.x1),this.y1=Math.floor(this.y1),this.x2=Math.ceil(this.x2),this.y2=Math.ceil(this.y2),this},scale(t){return this.x1*=t,this.y1*=t,this.x2*=t,this.y2*=t,this},translate(t,e){return this.x1+=t,this.x2+=t,this.y1+=e,this.y2+=e,this},rotate(t,e,n){const r=this.rotatedPoints(t,e,n);return this.clear().add(r[0],r[1]).add(r[2],r[3]).add(r[4],r[5]).add(r[6],r[7])},rotatedPoints(t,e,n){var{x1:r,y1:i,x2:o,y2:a}=this,s=Math.cos(t),u=Math.sin(t),l=e-e*s+n*u,c=n-e*u-n*s;return[s*r-u*i+l,u*r+s*i+c,s*r-u*a+l,u*r+s*a+c,s*o-u*i+l,u*o+s*i+c,s*o-u*a+l,u*o+s*a+c]},union(t){return t.x1this.x2&&(this.x2=t.x2),t.y2>this.y2&&(this.y2=t.y2),this},intersect(t){return t.x1>this.x1&&(this.x1=t.x1),t.y1>this.y1&&(this.y1=t.y1),t.x2=t.x2&&this.y1<=t.y1&&this.y2>=t.y2},alignsWith(t){return t&&(this.x1==t.x1||this.x2==t.x2||this.y1==t.y1||this.y2==t.y2)},intersects(t){return t&&!(this.x2t.x2||this.y2t.y2)},contains(t,e){return!(tthis.x2||ethis.y2)},width(){return this.x2-this.x1},height(){return this.y2-this.y1}},ht(Jg,Xg);class Zg{constructor(t){this._pending=0,this._loader=t||ca()}pending(){return this._pending}sanitizeURL(t){const e=this;return Qg(e),e._loader.sanitize(t,{context:"href"}).then((t=>(Kg(e),t))).catch((()=>(Kg(e),null)))}loadImage(t){const e=this,n=$c();return Qg(e),e._loader.sanitize(t,{context:"image"}).then((t=>{const r=t.href;if(!r||!n)throw{url:r};const i=new n,o=ut(t,"crossOrigin")?t.crossOrigin:"anonymous";return null!=o&&(i.crossOrigin=o),i.onload=()=>Kg(e),i.onerror=()=>Kg(e),i.src=r,i})).catch((t=>(Kg(e),{complete:!1,width:0,height:0,src:t&&t.url||""})))}ready(){const t=this;return new Promise((e=>{!function n(r){t.pending()?setTimeout((()=>{n(!0)}),10):e(r)}(!1)}))}}function Qg(t){t._pending+=1}function Kg(t){t._pending-=1}function tm(t,e,n){if(e.stroke&&0!==e.opacity&&0!==e.strokeOpacity){const r=null!=e.strokeWidth?+e.strokeWidth:1;t.expand(r+(n?function(t,e){return t.strokeJoin&&"miter"!==t.strokeJoin?0:e}(e,r):0))}return t}const em=lg-1e-8;let nm,rm,im,om,am,sm,um,lm;const cm=(t,e)=>nm.add(t,e),fm=(t,e)=>cm(rm=t,im=e),hm=t=>cm(t,nm.y1),dm=t=>cm(nm.x1,t),pm=(t,e)=>am*t+um*e,gm=(t,e)=>sm*t+lm*e,mm=(t,e)=>cm(pm(t,e),gm(t,e)),ym=(t,e)=>fm(pm(t,e),gm(t,e));function vm(t,e){return nm=t,e?(om=e*sg,am=lm=Math.cos(om),sm=Math.sin(om),um=-sm):(am=lm=1,om=sm=um=0),_m}const _m={beginPath(){},closePath(){},moveTo:ym,lineTo:ym,rect(t,e,n,r){om?(mm(t+n,e),mm(t+n,e+r),mm(t,e+r),ym(t,e)):(cm(t+n,e+r),fm(t,e))},quadraticCurveTo(t,e,n,r){const i=pm(t,e),o=gm(t,e),a=pm(n,r),s=gm(n,r);xm(rm,i,a,hm),xm(im,o,s,dm),fm(a,s)},bezierCurveTo(t,e,n,r,i,o){const a=pm(t,e),s=gm(t,e),u=pm(n,r),l=gm(n,r),c=pm(i,o),f=gm(i,o);bm(rm,a,u,c,hm),bm(im,s,l,f,dm),fm(c,f)},arc(t,e,n,r,i,o){if(r+=om,i+=om,rm=n*Math.cos(i)+t,im=n*Math.sin(i)+e,Math.abs(i-r)>em)cm(t-n,e-n),cm(t+n,e+n);else{const a=r=>cm(n*Math.cos(r)+t,n*Math.sin(r)+e);let s,u;if(a(r),a(i),i!==r)if((r%=lg)<0&&(r+=lg),(i%=lg)<0&&(i+=lg),ii;++u,s-=ug)a(s);else for(s=r-r%ug+ug,u=0;u<4&&s1e-14?(u=a*a+s*o,u>=0&&(u=Math.sqrt(u),l=(-a+u)/o,c=(-a-u)/o)):l=.5*s/a,0m)return!1;d>g&&(g=d)}else if(f>0){if(d0&&(t.globalAlpha=n,t.fillStyle=Bm(t,e,e.fill),!0)}var Nm=[];function Om(t,e,n){var r=null!=(r=e.strokeWidth)?r:1;return!(r<=0)&&((n*=null==e.strokeOpacity?1:e.strokeOpacity)>0&&(t.globalAlpha=n,t.strokeStyle=Bm(t,e,e.stroke),t.lineWidth=r,t.lineCap=e.strokeCap||"butt",t.lineJoin=e.strokeJoin||"miter",t.miterLimit=e.strokeMiterLimit||10,t.setLineDash&&(t.setLineDash(e.strokeDash||Nm),t.lineDashOffset=e.strokeDashOffset||0),!0))}function Rm(t,e){return t.zindex-e.zindex||t.index-e.index}function Lm(t){if(!t.zdirty)return t.zitems;var e,n,r,i=t.items,o=[];for(n=0,r=i.length;n=0;)if(n=e(i[r]))return n;if(i===o)for(r=(i=t.items).length;--r>=0;)if(!i[r].zindex&&(n=e(i[r])))return n;return null}function Pm(t){return function(e,n,r){Um(n,(n=>{r&&!r.intersects(n.bounds)||Im(t,e,n,n)}))}}function jm(t){return function(e,n,r){!n.items.length||r&&!r.intersects(n.bounds)||Im(t,e,n.items[0],n.items)}}function Im(t,e,n,r){var i=null==n.opacity?1:n.opacity;0!==i&&(t(e,r)||(Sm(e,n),n.fill&&zm(e,n,i)&&e.fill(),n.stroke&&Om(e,n,i)&&e.stroke()))}function Wm(t){return t=t||p,function(e,n,r,i,o,a){return r*=e.pixelRatio,i*=e.pixelRatio,qm(n,(n=>{const s=n.bounds;if((!s||s.contains(o,a))&&s)return t(e,n,r,i,o,a)?n:void 0}))}}function Hm(t,e){return function(n,r,i,o){var a,s,u=Array.isArray(r)?r[0]:r,l=null==e?u.fill:e,c=u.stroke&&n.isPointInStroke;return c&&(a=u.strokeWidth,s=u.strokeCap,n.lineWidth=null!=a?a:1,n.lineCap=null!=s?s:"butt"),!t(n,r)&&(l&&n.isPointInPath(i,o)||c&&n.isPointInStroke(i,o))}}function Ym(t){return Wm(Hm(t))}function Gm(t,e){return"translate("+t+","+e+")"}function Vm(t){return"rotate("+t+")"}function Xm(t){return Gm(t.x||0,t.y||0)}function Jm(t,e,n){function r(t,n){var r=n.x||0,i=n.y||0,o=n.angle||0;t.translate(r,i),o&&t.rotate(o*=sg),t.beginPath(),e(t,n),o&&t.rotate(-o),t.translate(-r,-i)}return{type:t,tag:"path",nested:!1,attr:function(t,n){t("transform",function(t){return Gm(t.x||0,t.y||0)+(t.angle?" "+Vm(t.angle):"")}(n)),t("d",e(null,n))},bound:function(t,n){return e(vm(t,n.angle),n),tm(t,n).translate(n.x||0,n.y||0)},draw:Pm(r),pick:Ym(r),isect:n||Mm(r)}}var Zm=Jm("arc",(function(t,e){return Og.context(t)(e)}));function Qm(t,e,n){function r(t,n){t.beginPath(),e(t,n)}const i=Hm(r);return{type:t,tag:"path",nested:!0,attr:function(t,n){var r=n.mark.items;r.length&&t("d",e(null,r))},bound:function(t,n){var r=n.items;return 0===r.length?t:(e(vm(t),r),tm(t,r[0]))},draw:jm(r),pick:function(t,e,n,r,o,a){var s=e.items,u=e.bounds;return!s||!s.length||u&&!u.contains(o,a)?null:(n*=t.pixelRatio,r*=t.pixelRatio,i(t,s,n,r)?s[0]:null)},isect:Em,tip:n}}var Km=Qm("area",(function(t,e){const n=e[0],r=n.interpolate||"linear";return("horizontal"===n.orient?Lg:Rg).curve(tg(r,n.orient,n.tension)).context(t)(e)}),(function(t,e){for(var n,r,i="horizontal"===t[0].orient?e[1]:e[0],o="horizontal"===t[0].orient?"y":"x",a=t.length,s=1/0;--a>=0;)!1!==t[a].defined&&(r=Math.abs(t[a][o]-i)).5&&e<1.5?.5-Math.abs(e-1):0}function ny(t,e){const n=ey(e);t("d",Wg(null,e,n,n))}function ry(t,e,n,r){const i=ey(e);t.beginPath(),Wg(t,e,(n||0)+i,(r||0)+i)}const iy=Hm(ry),oy=Hm(ry,!1),ay=Hm(ry,!0);var sy={type:"group",tag:"g",nested:!1,attr:function(t,e){t("transform",Xm(e))},bound:function(t,e){if(!e.clip&&e.items){const n=e.items,r=n.length;for(let e=0;e{const i=e.x||0,o=e.y||0,a=e.strokeForeground,s=null==e.opacity?1:e.opacity;(e.stroke||e.fill)&&s&&(ry(t,e,i,o),Sm(t,e),e.fill&&zm(t,e,s)&&t.fill(),e.stroke&&!a&&Om(t,e,s)&&t.stroke()),t.save(),t.translate(i,o),e.clip&&ty(t,e),n&&n.translate(-i,-o),Um(e,(e=>{("group"===e.marktype||null==r||r.includes(e.marktype))&&this.draw(t,e,n,r)})),n&&n.translate(i,o),t.restore(),a&&e.stroke&&s&&(ry(t,e,i,o),Sm(t,e),Om(t,e,s)&&t.stroke())}))},pick:function(t,e,n,r,i,o){if(e.bounds&&!e.bounds.contains(i,o)||!e.items)return null;const a=n*t.pixelRatio,s=r*t.pixelRatio;return qm(e,(u=>{let l,c,f;const h=u.bounds;if(h&&!h.contains(i,o))return;c=u.x||0,f=u.y||0;const d=c+(u.width||0),p=f+(u.height||0),g=u.clip;if(g&&(id||op))return;if(t.save(),t.translate(c,f),c=i-c,f=o-f,g&&Ig(u)&&!ay(t,u,a,s))return t.restore(),null;const m=u.strokeForeground,y=!1!==e.interactive;return y&&m&&u.stroke&&oy(t,u,a,s)?(t.restore(),u):(l=qm(u,(t=>function(t,e,n){return(!1!==t.interactive||"group"===t.marktype)&&t.bounds&&t.bounds.contains(e,n)}(t,c,f)?this.pick(t,n,r,c,f):null)),!l&&y&&(u.fill||!m&&u.stroke)&&iy(t,u,a,s)&&(l=u),t.restore(),l||null)}))},isect:Dm,content:function(t,e,n){t("clip-path",e.clip?Gg(n,e,e):null)},background:function(t,e){t("class","background"),t("aria-hidden",!0),ny(t,e)},foreground:function(t,e){t("class","foreground"),t("aria-hidden",!0),e.strokeForeground?ny(t,e):t("d","")}},uy={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",version:"1.1"};function ly(t,e){var n=t.image;return(!n||t.url&&t.url!==n.url)&&(n={complete:!1,width:0,height:0},e.loadImage(t.url).then((e=>{t.image=e,t.image.url=t.url}))),n}function cy(t,e){return null!=t.width?t.width:e&&e.width?!1!==t.aspect&&t.height?t.height*e.width/e.height:e.width:0}function fy(t,e){return null!=t.height?t.height:e&&e.height?!1!==t.aspect&&t.width?t.width*e.height/e.width:e.height:0}function hy(t,e){return"center"===t?e/2:"right"===t?e:0}function dy(t,e){return"middle"===t?e/2:"bottom"===t?e:0}var py={type:"image",tag:"image",nested:!1,attr:function(t,e,n){const r=ly(e,n),i=cy(e,r),o=fy(e,r),a=(e.x||0)-hy(e.align,i),s=(e.y||0)-dy(e.baseline,o);t("href",!r.src&&r.toDataURL?r.toDataURL():r.src||"",uy["xmlns:xlink"],"xlink:href"),t("transform",Gm(a,s)),t("width",i),t("height",o),t("preserveAspectRatio",!1===e.aspect?"none":"xMidYMid")},bound:function(t,e){const n=e.image,r=cy(e,n),i=fy(e,n),o=(e.x||0)-hy(e.align,r),a=(e.y||0)-dy(e.baseline,i);return t.set(o,a,o+r,a+i)},draw:function(t,e,n){Um(e,(e=>{if(n&&!n.intersects(e.bounds))return;const r=ly(e,this);let i=cy(e,r),o=fy(e,r);if(0===i||0===o)return;let a,s,u,l,c=(e.x||0)-hy(e.align,i),f=(e.y||0)-dy(e.baseline,o);!1!==e.aspect&&(s=r.width/r.height,u=e.width/e.height,s==s&&u==u&&s!==u&&(u=0;)if(!1!==t[o].defined&&(n=t[o].x-e[0])*n+(r=t[o].y-e[1])*r{if(!n||n.intersects(e.bounds)){var r=null==e.opacity?1:e.opacity;r&&xy(t,e,r)&&(Sm(t,e),t.stroke())}}))},pick:Wm((function(t,e,n,r){return!!t.isPointInStroke&&(xy(t,e,1)&&t.isPointInStroke(n,r))})),isect:Cm},wy=Jm("shape",(function(t,e){return(e.mark.shape||e.shape).context(t)(e)})),ky=Jm("symbol",(function(t,e){return Pg.context(t)(e)}),Em);const Ay=wt();var My={height:$y,measureWidth:Fy,estimateWidth:Dy,width:Dy,canvas:Ey};function Ey(t){My.width=t&&km?Fy:Dy}function Dy(t,e){return Cy(Ny(t,e),$y(t))}function Cy(t,e){return~~(.8*t.length*e)}function Fy(t,e){return $y(t)<=0||!(e=Ny(t,e))?0:Sy(e,Ry(t))}function Sy(t,e){const n=`(${e}) ${t}`;let r=Ay.get(n);return void 0===r&&(km.font=e,r=km.measureText(t).width,Ay.set(n,r)),r}function $y(t){return null!=t.fontSize?+t.fontSize||0:11}function Ty(t){return null!=t.lineHeight?t.lineHeight:$y(t)+2}function By(t){return e=t.lineBreak&&t.text&&!k(t.text)?t.text.split(t.lineBreak):t.text,k(e)?e.length>1?e:e[0]:e;var e}function zy(t){const e=By(t);return(k(e)?e.length-1:0)*Ty(t)}function Ny(t,e){const n=null==e?"":(e+"").trim();return t.limit>0&&n.length?function(t,e){var n=+t.limit,r=function(t){if(My.width===Fy){const e=Ry(t);return t=>Sy(t,e)}if(My.width===Dy){const e=$y(t);return t=>Cy(t,e)}return e=>My.width(t,e)}(t);if(r(e)>>1,r(e.slice(i))>n?s=i+1:u=i;return o+e.slice(s)}for(;s>>1),r(e.slice(0,i))Math.max(t,My.width(e,n))),0)):r=My.width(e,f),"center"===o?l-=r/2:"right"===o&&(l-=r),t.set(l+=s,c+=u,l+r,c+i),e.angle&&!n)t.rotate(e.angle*sg,s,u);else if(2===n)return t.rotatedPoints(e.angle*sg,s,u);return t}var Iy={type:"text",tag:"text",nested:!1,attr:function(t,e){var n,r=e.dx||0,i=(e.dy||0)+Ly(e),o=Py(e),a=o.x1,s=o.y1,u=e.angle||0;t("text-anchor",Uy[e.align]||"start"),u?(n=Gm(a,s)+" "+Vm(u),(r||i)&&(n+=" "+Gm(r,i))):n=Gm(a+r,s+i),t("transform",n)},bound:jy,draw:function(t,e,n){Um(e,(e=>{var r,i,o,a,s,u,l,c=null==e.opacity?1:e.opacity;if(!(n&&!n.intersects(e.bounds)||0===c||e.fontSize<=0||null==e.text||0===e.text.length)){if(t.font=Ry(e),t.textAlign=e.align||"left",i=(r=Py(e)).x1,o=r.y1,e.angle&&(t.save(),t.translate(i,o),t.rotate(e.angle*sg),i=o=0),i+=e.dx||0,o+=(e.dy||0)+Ly(e),u=By(e),Sm(t,e),k(u))for(s=Ty(e),a=0;a=0;)if(!1!==t[i].defined&&(n=t[i].x-e[0])*n+(r=t[i].y-e[1])*r<(n=t[i].size||1)*n)return t[i];return null})),Hy={arc:Zm,area:Km,group:sy,image:py,line:gy,path:yy,rect:_y,rule:by,shape:wy,symbol:ky,text:Iy,trail:Wy};function Yy(t,e,n){var r=Hy[t.mark.marktype],i=e||r.bound;return r.nested&&(t=t.mark),i(t.bounds||(t.bounds=new Vg),t,n)}var Gy={mark:null};function Vy(t,e,n){var r,i,o,a,s=Hy[t.marktype],u=s.bound,l=t.items,c=l&&l.length;if(s.nested)return c?o=l[0]:(Gy.mark=t,o=Gy),a=Yy(o,u,n),e=e&&e.union(a)||a;if(e=e||t.bounds&&t.bounds.clear()||new Vg,c)for(r=0,i=l.length;re;)t.removeChild(n[--r]);return t}function ov(t){return"mark-"+t.marktype+(t.role?" role-"+t.role:"")+(t.name?" "+t.name:"")}function av(t,e){const n=e.getBoundingClientRect();return[t.clientX-n.left-(e.clientLeft||0),t.clientY-n.top-(e.clientTop||0)]}class sv{constructor(t,e){this._active=null,this._handlers={},this._loader=t||ca(),this._tooltip=e||uv}initialize(t,e,n){return this._el=t,this._obj=n||null,this.origin(e)}element(){return this._el}canvas(){return this._el&&this._el.firstChild}origin(t){return arguments.length?(this._origin=t||[0,0],this):this._origin.slice()}scene(t){return arguments.length?(this._scene=t,this):this._scene}on(){}off(){}_handlerIndex(t,e,n){for(let r=t?t.length:0;--r>=0;)if(t[r].type===e&&(!n||t[r].handler===n))return r;return-1}handlers(t){const e=this._handlers,n=[];if(t)n.push(...e[this.eventName(t)]);else for(const t in e)n.push(...e[t]);return n}eventName(t){const e=t.indexOf(".");return e<0?t:t.slice(0,e)}handleHref(t,e,n){this._loader.sanitize(n,{context:"href"}).then((e=>{const n=new MouseEvent(t.type,t),r=ev(null,"a");for(const t in e)r.setAttribute(t,e[t]);r.dispatchEvent(n)})).catch((()=>{}))}handleTooltip(t,e,n){if(e&&null!=e.tooltip){e=function(t,e,n,r){var i,o,a=t&&t.mark;if(a&&(i=Hy[a.marktype]).tip){for((o=av(e,n))[0]-=r[0],o[1]-=r[1];t=t.mark.group;)o[0]-=t.x||0,o[1]-=t.y||0;t=i.tip(a.items,o)}return t}(e,t,this.canvas(),this._origin);const r=n&&e&&e.tooltip||null;this._tooltip.call(this._obj,this,t,e,r)}}getItemBoundingClientRect(t){const e=this.canvas();if(!e)return;const n=e.getBoundingClientRect(),r=this._origin,i=t.bounds,o=i.width(),a=i.height();let s=i.x1+r[0]+n.left,u=i.y1+r[1]+n.top;for(;t.mark&&(t=t.mark.group);)s+=t.x||0,u+=t.y||0;return{x:s,y:u,width:o,height:a,left:s,top:u,right:s+o,bottom:u+a}}}function uv(t,e,n,r){t.element().setAttribute("title",r||"")}class lv{constructor(t){this._el=null,this._bgcolor=null,this._loader=new Zg(t)}initialize(t,e,n,r,i){return this._el=t,this.resize(e,n,r,i)}element(){return this._el}canvas(){return this._el&&this._el.firstChild}background(t){return 0===arguments.length?this._bgcolor:(this._bgcolor=t,this)}resize(t,e,n,r){return this._width=t,this._height=e,this._origin=n||[0,0],this._scale=r||1,this}dirty(){}render(t,e){const n=this;return n._call=function(){n._render(t,e)},n._call(),n._call=null,n}_render(){}renderAsync(t,e){const n=this.render(t,e);return this._ready?this._ready.then((()=>n)):Promise.resolve(n)}_load(t,e){var n=this,r=n._loader[t](e);if(!n._ready){const t=n._call;n._ready=n._loader.ready().then((e=>{e&&t(),n._ready=null}))}return r}sanitizeURL(t){return this._load("sanitizeURL",t)}loadImage(t){return this._load("loadImage",t)}}const cv="dragenter",fv="dragleave",hv="dragover",dv="pointerdown",pv="pointermove",gv="pointerout",mv="pointerover",yv="mousedown",vv="mousemove",_v="mouseout",xv="mouseover",bv="click",wv="mousewheel",kv="touchstart",Av="touchmove",Mv="touchend",Ev=["keydown","keypress","keyup",cv,fv,hv,dv,"pointerup",pv,gv,mv,yv,"mouseup",vv,_v,xv,bv,"dblclick","wheel",wv,kv,Av,Mv],Dv=pv,Cv=_v,Fv=bv;class Sv extends sv{constructor(t,e){super(t,e),this._down=null,this._touch=null,this._first=!0,this._events={},this.events=Ev,this.pointermove=zv([pv,vv],[mv,xv],[gv,_v]),this.dragover=zv([hv],[cv],[fv]),this.pointerout=Nv([gv,_v]),this.dragleave=Nv([fv])}initialize(t,e,n){return this._canvas=t&&nv(t,"canvas"),[bv,yv,dv,pv,gv,fv].forEach((t=>Tv(this,t))),super.initialize(t,e,n)}canvas(){return this._canvas}context(){return this._canvas.getContext("2d")}DOMMouseScroll(t){this.fire(wv,t)}pointerdown(t){this._down=this._active,this.fire(dv,t)}mousedown(t){this._down=this._active,this.fire(yv,t)}click(t){this._down===this._active&&(this.fire(bv,t),this._down=null)}touchstart(t){this._touch=this.pickEvent(t.changedTouches[0]),this._first&&(this._active=this._touch,this._first=!1),this.fire(kv,t,!0)}touchmove(t){this.fire(Av,t,!0)}touchend(t){this.fire(Mv,t,!0),this._touch=null}fire(t,e,n){const r=n?this._touch:this._active,i=this._handlers[t];if(e.vegaType=t,t===Fv&&r&&r.href?this.handleHref(e,r,r.href):t!==Dv&&t!==Cv||this.handleTooltip(e,r,t!==Cv),i)for(let t=0,n=i.length;t=0&&r.splice(i,1),this}pickEvent(t){const e=av(t,this._canvas),n=this._origin;return this.pick(this._scene,e[0],e[1],e[0]-n[0],e[1]-n[1])}pick(t,e,n,r,i){const o=this.context();return Hy[t.marktype].pick.call(this,o,t,e,n,r,i)}}const $v=t=>t===kv||t===Av||t===Mv?[kv,Av,Mv]:[t];function Tv(t,e){$v(e).forEach((e=>function(t,e){const n=t.canvas();n&&!t._events[e]&&(t._events[e]=1,n.addEventListener(e,t[e]?n=>t[e](n):n=>t.fire(e,n)))}(t,e)))}function Bv(t,e,n){e.forEach((e=>t.fire(e,n)))}function zv(t,e,n){return function(r){const i=this._active,o=this.pickEvent(r);o===i||(i&&i.exit||Bv(this,n,r),this._active=o,Bv(this,e,r)),Bv(this,t,r)}}function Nv(t){return function(e){Bv(this,t,e),this._active=null}}function Ov(t,e,n,r,i,o){const a="undefined"!=typeof HTMLElement&&t instanceof HTMLElement&&null!=t.parentNode,s=t.getContext("2d"),u=a?"undefined"!=typeof window&&window.devicePixelRatio||1:i;t.width=e*u,t.height=n*u;for(const t in o)s[t]=o[t];return a&&1!==u&&(t.style.width=e+"px",t.style.height=n+"px"),s.pixelRatio=u,s.setTransform(u,0,0,u,u*r[0],u*r[1]),t}class Rv extends lv{constructor(t){super(t),this._options={},this._redraw=!1,this._dirty=new Vg,this._tempb=new Vg}initialize(t,e,n,r,i,o){return this._options=o||{},this._canvas=this._options.externalContext?null:Sc(1,1,this._options.type),t&&this._canvas&&(iv(t,0).appendChild(this._canvas),this._canvas.setAttribute("class","marks")),super.initialize(t,e,n,r,i)}resize(t,e,n,r){if(super.resize(t,e,n,r),this._canvas)Ov(this._canvas,this._width,this._height,this._origin,this._scale,this._options.context);else{const t=this._options.externalContext;t||s("CanvasRenderer is missing a valid canvas or context"),t.scale(this._scale,this._scale),t.translate(this._origin[0],this._origin[1])}return this._redraw=!0,this}canvas(){return this._canvas}context(){return this._options.externalContext||(this._canvas?this._canvas.getContext("2d"):null)}dirty(t){const e=this._tempb.clear().union(t.bounds);let n=t.mark.group;for(;n;)e.translate(n.x||0,n.y||0),n=n.mark.group;this._dirty.union(e)}_render(t,e){const n=this.context(),r=this._origin,i=this._width,o=this._height,a=this._dirty,s=Lv(r,i,o);n.save();const u=this._redraw||a.empty()?(this._redraw=!1,s.expand(1)):function(t,e,n){e.expand(1).round(),t.pixelRatio%1&&e.scale(t.pixelRatio).round().scale(1/t.pixelRatio);return e.translate(-n[0]%1,-n[1]%1),t.beginPath(),t.rect(e.x1,e.y1,e.width(),e.height()),t.clip(),e}(n,s.intersect(a),r);return this.clear(-r[0],-r[1],i,o),this.draw(n,t,u,e),n.restore(),a.clear(),this}draw(t,e,n,r){if("group"!==e.marktype&&null!=r&&!r.includes(e.marktype))return;const i=Hy[e.marktype];e.clip&&function(t,e){var n=e.clip;t.save(),J(n)?(t.beginPath(),n(t),t.clip()):ty(t,e.group)}(t,e),i.draw.call(this,t,e,n,r),e.clip&&t.restore()}clear(t,e,n,r){const i=this._options,o=this.context();"pdf"===i.type||i.externalContext||o.clearRect(t,e,n,r),null!=this._bgcolor&&(o.fillStyle=this._bgcolor,o.fillRect(t,e,n,r))}}const Lv=(t,e,n)=>(new Vg).set(0,0,e,n).translate(-t[0],-t[1]);class Uv extends sv{constructor(t,e){super(t,e);const n=this;n._hrefHandler=qv(n,((t,e)=>{e&&e.href&&n.handleHref(t,e,e.href)})),n._tooltipHandler=qv(n,((t,e)=>{n.handleTooltip(t,e,t.type!==Cv)}))}initialize(t,e,n){let r=this._svg;return r&&(r.removeEventListener(Fv,this._hrefHandler),r.removeEventListener(Dv,this._tooltipHandler),r.removeEventListener(Cv,this._tooltipHandler)),this._svg=r=t&&nv(t,"svg"),r&&(r.addEventListener(Fv,this._hrefHandler),r.addEventListener(Dv,this._tooltipHandler),r.addEventListener(Cv,this._tooltipHandler)),super.initialize(t,e,n)}canvas(){return this._svg}on(t,e){const n=this.eventName(t),r=this._handlers;if(this._handlerIndex(r[n],t,e)<0){const i={type:t,handler:e,listener:qv(this,e)};(r[n]||(r[n]=[])).push(i),this._svg&&this._svg.addEventListener(n,i.listener)}return this}off(t,e){const n=this.eventName(t),r=this._handlers[n],i=this._handlerIndex(r,t,e);return i>=0&&(this._svg&&this._svg.removeEventListener(n,r[i].listener),r.splice(i,1)),this}}const qv=(t,e)=>n=>{let r=n.target.__data__;r=Array.isArray(r)?r[0]:r,n.vegaType=n.type,e.call(t._obj,n,r)},Pv="aria-hidden",jv="aria-label",Iv="role",Wv="aria-roledescription",Hv="graphics-object",Yv="graphics-symbol",Gv=(t,e,n)=>({[Iv]:t,[Wv]:e,[jv]:n||void 0}),Vv=Tt(["axis-domain","axis-grid","axis-label","axis-tick","axis-title","legend-band","legend-entry","legend-gradient","legend-label","legend-title","legend-symbol","title"]),Xv={axis:{desc:"axis",caption:function(t){const e=t.datum,n=t.orient,r=e.title?t_(t):null,i=t.context,o=i.scales[e.scale].value,a=i.dataflow.locale(),s=o.type;return("left"===n||"right"===n?"Y":"X")+"-axis"+(r?` titled '${r}'`:"")+` for a ${cp(s)?"discrete":s} scale`+` with ${Yp(a,o,t)}`}},legend:{desc:"legend",caption:function(t){const e=t.datum,n=e.title?t_(t):null,r=`${e.type||""} legend`.trim(),i=e.scales,o=Object.keys(i),a=t.context,s=a.scales[i[o[0]]].value,u=a.dataflow.locale();return l=r,(l.length?l[0].toUpperCase()+l.slice(1):l)+(n?` titled '${n}'`:"")+` for ${function(t){return t=t.map((t=>t+("fill"===t||"stroke"===t?" color":""))),t.length<2?t[0]:t.slice(0,-1).join(", ")+" and "+F(t)}(o)}`+` with ${Yp(u,s,t)}`;var l}},"title-text":{desc:"title",caption:t=>`Title text '${Kv(t)}'`},"title-subtitle":{desc:"subtitle",caption:t=>`Subtitle text '${Kv(t)}'`}},Jv={ariaRole:Iv,ariaRoleDescription:Wv,description:jv};function Zv(t,e){const n=!1===e.aria;if(t(Pv,n||void 0),n||null==e.description)for(const e in Jv)t(Jv[e],void 0);else{const n=e.mark.marktype;t(jv,e.description),t(Iv,e.ariaRole||("group"===n?Hv:Yv)),t(Wv,e.ariaRoleDescription||`${n} mark`)}}function Qv(t){return!1===t.aria?{[Pv]:!0}:Vv[t.role]?null:Xv[t.role]?function(t,e){try{const n=t.items[0],r=e.caption||(()=>"");return Gv(e.role||Yv,e.desc,n.description||r(n))}catch(t){return null}}(t,Xv[t.role]):function(t){const e=t.marktype,n="group"===e||"text"===e||t.items.some((t=>null!=t.description&&!1!==t.aria));return Gv(n?Hv:Yv,`${e} mark container`,t.description)}(t)}function Kv(t){return V(t.text).join(" ")}function t_(t){try{return V(F(t.items).items[0].text).join(" ")}catch(t){return null}}const e_=t=>(t+"").replace(/&/g,"&").replace(//g,">");function n_(){let t="",e="",n="";const r=[],i=()=>e=n="",o=(t,n)=>{var r;return null!=n&&(e+=` ${t}="${r=n,e_(r).replace(/"/g,""").replace(/\t/g," ").replace(/\n/g," ").replace(/\r/g," ")}"`),a},a={open(s){(o=>{e&&(t+=`${e}>${n}`,i()),r.push(o)})(s),e="<"+s;for(var u=arguments.length,l=new Array(u>1?u-1:0),c=1;c${n}`:"/>"):``,i(),a},attr:o,text:t=>(n+=e_(t),a),toString:()=>t};return a}const r_=t=>i_(n_(),t)+"";function i_(t,e){if(t.open(e.tagName),e.hasAttributes()){const n=e.attributes,r=n.length;for(let e=0;e{t.dirty=e}))),r.zdirty||(n.exit?(o.nested&&r.items.length?(u=r.items[0],u._svg&&this._update(o,u._svg,u)):n._svg&&(u=n._svg.parentNode,u&&u.removeChild(n._svg)),n._svg=null):(n=o.nested?r.items[0]:n,n._update!==e&&(n._svg&&n._svg.ownerSVGElement?this._update(o,n._svg,n):(this._dirtyAll=!1,f_(n,e)),n._update=e)));return!this._dirtyAll}mark(t,e,n,r){if(!this.isDirty(e))return e._svg;const i=this._svg,o=e.marktype,a=Hy[o],s=!1===e.interactive?"none":null,u="g"===a.tag,l=p_(e,t,n,"g",i);if("group"!==o&&null!=r&&!r.includes(o))return iv(l,0),e._svg;l.setAttribute("class",ov(e));const c=Qv(e);for(const t in c)b_(l,t,c[t]);u||b_(l,"pointer-events",s),b_(l,"clip-path",e.clip?Gg(this,e,e.group):null);let f=null,h=0;const d=t=>{const e=this.isDirty(t),n=p_(t,l,f,a.tag,i);e&&(this._update(a,n,t),u&&function(t,e,n,r){e=e.lastChild.previousSibling;let i,o=0;Um(n,(n=>{i=t.mark(e,n,i,r),++o})),iv(e,1+o)}(this,n,t,r)),f=n,++h};return a.nested?e.items.length&&d(e.items[0]):Um(e,d),iv(l,h),l}_update(t,e,n){g_=e,m_=e.__values__,Zv(v_,n),t.attr(v_,n,this);const r=y_[t.type];r&&r.call(this,t,e,n),g_&&this.style(g_,n)}style(t,e){if(null!=e){for(const n in o_){let r="font"===n?Oy(e):e[n];if(r===m_[n])continue;const i=o_[n];null==r?t.removeAttribute(i):(Xp(r)&&(r=Jp(r,this._defs.gradient,w_())),t.setAttribute(i,r+"")),m_[n]=r}for(const n in a_)__(t,a_[n],e[n])}}defs(){const t=this._svg,e=this._defs;let n=e.el,r=0;for(const i in e.gradient)n||(e.el=n=rv(t,1,"defs",l_)),r=h_(n,e.gradient[i],r);for(const i in e.clipping)n||(e.el=n=rv(t,1,"defs",l_)),r=d_(n,e.clipping[i],r);n&&(0===r?(t.removeChild(n),e.el=null):iv(n,r))}_clearDefs(){const t=this._defs;t.gradient={},t.clipping={}}}function f_(t,e){for(;t&&t.dirty!==e;t=t.mark.group){if(t.dirty=e,!t.mark||t.mark.dirty===e)return;t.mark.dirty=e}}function h_(t,e,n){let r,i,o;if("radial"===e.gradient){let r=rv(t,n++,"pattern",l_);x_(r,{id:Vp+e.id,viewBox:"0,0,1,1",width:"100%",height:"100%",preserveAspectRatio:"xMidYMid slice"}),r=rv(r,0,"rect",l_),x_(r,{width:1,height:1,fill:`url(${w_()}#${e.id})`}),x_(t=rv(t,n++,"radialGradient",l_),{id:e.id,fx:e.x1,fy:e.y1,fr:e.r1,cx:e.x2,cy:e.y2,r:e.r2})}else x_(t=rv(t,n++,"linearGradient",l_),{id:e.id,x1:e.x1,x2:e.x2,y1:e.y1,y2:e.y2});for(r=0,i=e.stops.length;r1&&t.previousSibling!=e}(a,n))&&e.insertBefore(a,n?n.nextSibling:e.firstChild),a}let g_=null,m_=null;const y_={group(t,e,n){const r=g_=e.childNodes[2];m_=r.__values__,t.foreground(v_,n,this),m_=e.__values__,g_=e.childNodes[1],t.content(v_,n,this);const i=g_=e.childNodes[0];t.background(v_,n,this);const o=!1===n.mark.interactive?"none":null;if(o!==m_.events&&(b_(r,"pointer-events",o),b_(i,"pointer-events",o),m_.events=o),n.strokeForeground&&n.stroke){const t=n.fill;b_(r,"display",null),this.style(i,n),b_(i,"stroke",null),t&&(n.fill=null),m_=r.__values__,this.style(r,n),t&&(n.fill=t),g_=null}else b_(r,"display","none")},image(t,e,n){!1===n.smooth?(__(e,"image-rendering","optimizeSpeed"),__(e,"image-rendering","pixelated")):__(e,"image-rendering",null)},text(t,e,n){const r=By(n);let i,o,a,s;k(r)?(o=r.map((t=>Ny(n,t))),i=o.join("\n"),i!==m_.text&&(iv(e,0),a=e.ownerDocument,s=Ty(n),o.forEach(((t,r)=>{const i=ev(a,"tspan",l_);i.__data__=n,i.textContent=t,r&&(i.setAttribute("x",0),i.setAttribute("dy",s)),e.appendChild(i)})),m_.text=i)):(o=Ny(n,r),o!==m_.text&&(e.textContent=o,m_.text=o)),b_(e,"font-family",Oy(n)),b_(e,"font-size",$y(n)+"px"),b_(e,"font-style",n.fontStyle),b_(e,"font-variant",n.fontVariant),b_(e,"font-weight",n.fontWeight)}};function v_(t,e,n){e!==m_[t]&&(n?function(t,e,n,r){null!=n?t.setAttributeNS(r,e,n):t.removeAttributeNS(r,e)}(g_,t,e,n):b_(g_,t,e),m_[t]=e)}function __(t,e,n){n!==m_[e]&&(null==n?t.style.removeProperty(e):t.style.setProperty(e,n+""),m_[e]=n)}function x_(t,e){for(const n in e)b_(t,n,e[n])}function b_(t,e,n){null!=n?t.setAttribute(e,n):t.removeAttribute(e)}function w_(){let t;return"undefined"==typeof window?"":(t=window.location).hash?t.href.slice(0,-t.hash.length):t.href}class k_ extends lv{constructor(t){super(t),this._text=null,this._defs={gradient:{},clipping:{}}}svg(){return this._text}_render(t){const e=n_();e.open("svg",ot({},uy,{class:"marks",width:this._width*this._scale,height:this._height*this._scale,viewBox:`0 0 ${this._width} ${this._height}`}));const n=this._bgcolor;return n&&"transparent"!==n&&"none"!==n&&e.open("rect",{width:this._width,height:this._height,fill:n}).close(),e.open("g",s_,{transform:"translate("+this._origin+")"}),this.mark(e,t),e.close(),this.defs(e),this._text=e.close()+"",this}mark(t,e){const n=Hy[e.marktype],r=n.tag,i=[Zv,n.attr];t.open("g",{class:ov(e),"clip-path":e.clip?Gg(this,e,e.group):null},Qv(e),{"pointer-events":"g"!==r&&!1===e.interactive?"none":null});const o=o=>{const a=this.href(o);if(a&&t.open("a",a),t.open(r,this.attr(e,o,i,"g"!==r?r:null)),"text"===r){const e=By(o);if(k(e)){const n={x:0,dy:Ty(o)};for(let r=0;rthis.mark(t,e))),t.close(),r&&a?(i&&(o.fill=null),o.stroke=a,t.open("path",this.attr(e,o,n.foreground,"bgrect")).close(),i&&(o.fill=i)):t.open("path",this.attr(e,o,n.foreground,"bgfore")).close()}t.close(),a&&t.close()};return n.nested?e.items&&e.items.length&&o(e.items[0]):Um(e,o),t.close()}href(t){const e=t.href;let n;if(e){if(n=this._hrefs&&this._hrefs[e])return n;this.sanitizeURL(e).then((t=>{t["xlink:href"]=t.href,t.href=null,(this._hrefs||(this._hrefs={}))[e]=t}))}return null}attr(t,e,n,r){const i={},o=(t,e,n,r)=>{i[r||t]=e};return Array.isArray(n)?n.forEach((t=>t(o,e,this))):n(o,e,this),r&&function(t,e,n,r,i){let o;if(null==e)return t;"bgrect"===r&&!1===n.interactive&&(t["pointer-events"]="none");if("bgfore"===r&&(!1===n.interactive&&(t["pointer-events"]="none"),t.display="none",null!==e.fill))return t;"image"===r&&!1===e.smooth&&(o=["image-rendering: optimizeSpeed;","image-rendering: pixelated;"]);"text"===r&&(t["font-family"]=Oy(e),t["font-size"]=$y(e)+"px",t["font-style"]=e.fontStyle,t["font-variant"]=e.fontVariant,t["font-weight"]=e.fontWeight);for(const n in o_){let r=e[n];const o=o_[n];("transparent"!==r||"fill"!==o&&"stroke"!==o)&&null!=r&&(Xp(r)&&(r=Jp(r,i.gradient,"")),t[o]=r)}for(const t in a_){const n=e[t];null!=n&&(o=o||[],o.push(`${a_[t]}: ${n};`))}o&&(t.style=o.join(" "))}(i,e,t,r,this._defs),i}defs(t){const e=this._defs.gradient,n=this._defs.clipping;if(0!==Object.keys(e).length+Object.keys(n).length){t.open("defs");for(const n in e){const r=e[n],i=r.stops;"radial"===r.gradient?(t.open("pattern",{id:Vp+n,viewBox:"0,0,1,1",width:"100%",height:"100%",preserveAspectRatio:"xMidYMid slice"}),t.open("rect",{width:"1",height:"1",fill:"url(#"+n+")"}).close(),t.close(),t.open("radialGradient",{id:n,fx:r.x1,fy:r.y1,fr:r.r1,cx:r.x2,cy:r.y2,r:r.r2})):t.open("linearGradient",{id:n,x1:r.x1,x2:r.x2,y1:r.y1,y2:r.y2});for(let e=0;e!A_.svgMarkTypes.includes(t)));this._svgRenderer.render(t,A_.svgMarkTypes),this._canvasRenderer.render(t,n)}resize(t,e,n,r){return super.resize(t,e,n,r),this._svgRenderer.resize(t,e,n,r),this._canvasRenderer.resize(t,e,n,r),this}background(t){return A_.svgOnTop?this._canvasRenderer.background(t):this._svgRenderer.background(t),this}}class E_ extends Sv{constructor(t,e){super(t,e)}initialize(t,e,n){const r=rv(rv(t,0,"div"),A_.svgOnTop?0:1,"div");return super.initialize(r,e,n)}}const D_="canvas",C_="hybrid",F_="none",S_={Canvas:D_,PNG:"png",SVG:"svg",Hybrid:C_,None:F_},$_={};function T_(t,e){return t=String(t||"").toLowerCase(),arguments.length>1?($_[t]=e,this):$_[t]}function B_(t,e,n){const r=[],i=(new Vg).union(e),o=t.marktype;return o?z_(t,i,n,r):"group"===o?N_(t,i,n,r):s("Intersect scene must be mark node or group item.")}function z_(t,e,n,r){if(function(t,e,n){return t.bounds&&e.intersects(t.bounds)&&("group"===t.marktype||!1!==t.interactive&&(!n||n(t)))}(t,e,n)){const i=t.items,o=t.marktype,a=i.length;let s=0;if("group"===o)for(;s=0;r--)if(i[r]!=o[r])return!1;for(r=i.length-1;r>=0;r--)if(!q_(t[n=i[r]],e[n],n))return!1;return typeof t==typeof e}(t,e):t==e)}function P_(t,e){return q_(ag(t),ag(e))}const j_="top",I_="left",W_="right",H_="bottom",Y_="top-left",G_="top-right",V_="bottom-left",X_="bottom-right",J_="start",Z_="middle",Q_="end",K_="x",tx="y",ex="group",nx="axis",rx="title",ix="frame",ox="scope",ax="legend",sx="row-header",ux="row-footer",lx="row-title",cx="column-header",fx="column-footer",hx="column-title",dx="padding",px="symbol",gx="fit",mx="fit-x",yx="fit-y",vx="pad",_x="none",xx="all",bx="each",wx="flush",kx="column",Ax="row";function Mx(t){Xa.call(this,null,t)}function Ex(t,e,n){return e(t.bounds.clear(),t,n)}ht(Mx,Xa,{transform(t,e){const n=e.dataflow,r=t.mark,i=r.marktype,o=Hy[i],a=o.bound;let s,u=r.bounds;if(o.nested)r.items.length&&n.dirty(r.items[0]),u=Ex(r,a),r.items.forEach((t=>{t.bounds.clear().union(u)}));else if(i===ex||t.modified())switch(e.visit(e.MOD,(t=>n.dirty(t))),u.clear(),r.items.forEach((t=>u.union(Ex(t,a)))),r.role){case nx:case ax:case rx:e.reflow()}else s=e.changed(e.REM),e.visit(e.ADD,(t=>{u.union(Ex(t,a))})),e.visit(e.MOD,(t=>{s=s||u.alignsWith(t.bounds),n.dirty(t),u.union(Ex(t,a))})),s&&(u.clear(),r.items.forEach((t=>u.union(t.bounds))));return L_(r),e.modifies("bounds")}});const Dx=":vega_identifier:";function Cx(t){Xa.call(this,0,t)}function Fx(t){Xa.call(this,null,t)}function Sx(t){Xa.call(this,null,t)}Cx.Definition={type:"Identifier",metadata:{modifies:!0},params:[{name:"as",type:"string",required:!0}]},ht(Cx,Xa,{transform(t,e){const n=(i=e.dataflow)._signals[Dx]||(i._signals[Dx]=i.add(0)),r=t.as;var i;let o=n.value;return e.visit(e.ADD,(t=>t[r]=t[r]||++o)),n.set(this.value=o),e}}),ht(Fx,Xa,{transform(t,e){let n=this.value;n||(n=e.dataflow.scenegraph().mark(t.markdef,function(t){const e=t.groups,n=t.parent;return e&&1===e.size?e.get(Object.keys(e.object)[0]):e&&n?e.lookup(n):null}(t),t.index),n.group.context=t.context,t.context.group||(t.context.group=n.group),n.source=this.source,n.clip=t.clip,n.interactive=t.interactive,this.value=n);const r=n.marktype===ex?Jg:Xg;return e.visit(e.ADD,(t=>r.call(t,n))),(t.modified("clip")||t.modified("interactive"))&&(n.clip=t.clip,n.interactive=!!t.interactive,n.zdirty=!0,e.reflow()),n.items=e.source,e}});const $x={parity:t=>t.filter(((t,e)=>e%2?t.opacity=0:1)),greedy:(t,e)=>{let n;return t.filter(((t,r)=>r&&Tx(n.bounds,t.bounds,e)?t.opacity=0:(n=t,1)))}},Tx=(t,e,n)=>n>Math.max(e.x1-t.x2,t.x1-e.x2,e.y1-t.y2,t.y1-e.y2),Bx=(t,e)=>{for(var n,r=1,i=t.length,o=t[0].bounds;r{const e=t.bounds;return e.width()>1&&e.height()>1},Nx=t=>(t.forEach((t=>t.opacity=1)),t),Ox=(t,e)=>t.reflow(e.modified()).modifies("opacity");function Rx(t){Xa.call(this,null,t)}ht(Sx,Xa,{transform(t,e){const n=$x[t.method]||$x.parity,r=t.separation||0;let i,o,a=e.materialize(e.SOURCE).source;if(!a||!a.length)return;if(!t.method)return t.modified("method")&&(Nx(a),e=Ox(e,t)),e;if(a=a.filter(zx),!a.length)return;if(t.sort&&(a=a.slice().sort(t.sort)),i=Nx(a),e=Ox(e,t),i.length>=3&&Bx(i,r)){do{i=n(i,r)}while(i.length>=3&&Bx(i,r));i.length<3&&!F(a).opacity&&(i.length>1&&(F(i).opacity=0),F(a).opacity=1)}t.boundScale&&t.boundTolerance>=0&&(o=((t,e,n)=>{var r=t.range(),i=new Vg;return e===j_||e===H_?i.set(r[0],-1/0,r[1],1/0):i.set(-1/0,r[0],1/0,r[1]),i.expand(n||1),t=>i.encloses(t.bounds)})(t.boundScale,t.boundOrient,+t.boundTolerance),a.forEach((t=>{o(t)||(t.opacity=0)})));const s=i[0].mark.bounds.clear();return a.forEach((t=>{t.opacity&&s.union(t.bounds)})),e}}),ht(Rx,Xa,{transform(t,e){const n=e.dataflow;if(e.visit(e.ALL,(t=>n.dirty(t))),e.fields&&e.fields.zindex){const t=e.source&&e.source[0];t&&(t.mark.zdirty=!0)}}});const Lx=new Vg;function Ux(t,e,n){return t[e]===n?0:(t[e]=n,1)}function qx(t){var e=t.items[0].orient;return e===I_||e===W_}function Px(t,e,n,r){var i,o,a=e.items[0],s=a.datum,u=null!=a.translate?a.translate:.5,l=a.orient,c=function(t){let e=+t.grid;return[t.ticks?e++:-1,t.labels?e++:-1,e+ +t.domain]}(s),f=a.range,h=a.offset,d=a.position,p=a.minExtent,g=a.maxExtent,m=s.title&&a.items[c[2]].items[0],y=a.titlePadding,v=a.bounds,_=m&&zy(m),x=0,b=0;switch(Lx.clear().union(v),v.clear(),(i=c[0])>-1&&v.union(a.items[i].bounds),(i=c[1])>-1&&v.union(a.items[i].bounds),l){case j_:x=d||0,b=-h,o=Math.max(p,Math.min(g,-v.y1)),v.add(0,-o).add(f,0),m&&jx(t,m,o,y,_,0,-1,v);break;case I_:x=-h,b=d||0,o=Math.max(p,Math.min(g,-v.x1)),v.add(-o,0).add(0,f),m&&jx(t,m,o,y,_,1,-1,v);break;case W_:x=n+h,b=d||0,o=Math.max(p,Math.min(g,v.x2)),v.add(0,0).add(o,f),m&&jx(t,m,o,y,_,1,1,v);break;case H_:x=d||0,b=r+h,o=Math.max(p,Math.min(g,v.y2)),v.add(0,0).add(f,o),m&&jx(t,m,o,y,0,0,1,v);break;default:x=a.x,b=a.y}return tm(v.translate(x,b),a),Ux(a,"x",x+u)|Ux(a,"y",b+u)&&(a.bounds=Lx,t.dirty(a),a.bounds=v,t.dirty(a)),a.mark.bounds.clear().union(v)}function jx(t,e,n,r,i,o,a,s){const u=e.bounds;if(e.auto){const s=a*(n+i+r);let l=0,c=0;t.dirty(e),o?l=(e.x||0)-(e.x=s):c=(e.y||0)-(e.y=s),e.mark.bounds.clear().union(u.translate(-l,-c)),t.dirty(e)}s.union(u)}const Ix=(t,e)=>Math.floor(Math.min(t,e)),Wx=(t,e)=>Math.ceil(Math.max(t,e));function Hx(t){return(new Vg).set(0,0,t.width||0,t.height||0)}function Yx(t){const e=t.bounds.clone();return e.empty()?e.set(0,0,0,0):e.translate(-(t.x||0),-(t.y||0))}function Gx(t,e,n){const r=A(t)?t[e]:t;return null!=r?r:void 0!==n?n:0}function Vx(t){return t<0?Math.ceil(-t):0}function Xx(t,e,n){var r,i,o,a,s,u,l,c,f,h,d,p=!n.nodirty,g=n.bounds===wx?Hx:Yx,m=Lx.set(0,0,0,0),y=Gx(n.align,kx),v=Gx(n.align,Ax),_=Gx(n.padding,kx),x=Gx(n.padding,Ax),b=n.columns||e.length,w=b<=0?1:Math.ceil(e.length/b),k=e.length,A=Array(k),M=Array(b),E=0,D=Array(k),C=Array(w),F=0,S=Array(k),$=Array(k),T=Array(k);for(i=0;i1)for(i=0;i0&&(S[i]+=f/2);if(v&&Gx(n.center,Ax)&&1!==b)for(i=0;i0&&($[i]+=h/2);for(i=0;ii&&(t.warn("Grid headers exceed limit: "+i),e=e.slice(0,i)),A+=o,g=0,y=e.length;g=0&&null==(x=n[m]);m-=h);s?(b=null==d?x.x:Math.round(x.bounds.x1+d*x.bounds.width()),w=A):(b=A,w=null==d?x.y:Math.round(x.bounds.y1+d*x.bounds.height())),v.union(_.bounds.translate(b-(_.x||0),w-(_.y||0))),_.x=b,_.y=w,t.dirty(_),M=a(M,v[l])}return M}function tb(t,e,n,r,i,o){if(e){t.dirty(e);var a=n,s=n;r?a=Math.round(i.x1+o*i.width()):s=Math.round(i.y1+o*i.height()),e.bounds.translate(a-(e.x||0),s-(e.y||0)),e.mark.bounds.clear().union(e.bounds),e.x=a,e.y=s,t.dirty(e)}}function eb(t,e,n,r,i,o,a){const s=function(t,e){const n=t[e]||{};return(e,r)=>null!=n[e]?n[e]:null!=t[e]?t[e]:r}(n,e),u=function(t,e){let n=-1/0;return t.forEach((t=>{null!=t.offset&&(n=Math.max(n,t.offset))})),n>-1/0?n:e}(t,s("offset",0)),l=s("anchor",J_),c=l===Q_?1:l===Z_?.5:0,f={align:bx,bounds:s("bounds",wx),columns:"vertical"===s("direction")?1:t.length,padding:s("margin",8),center:s("center"),nodirty:!0};switch(e){case I_:f.anchor={x:Math.floor(r.x1)-u,column:Q_,y:c*(a||r.height()+2*r.y1),row:l};break;case W_:f.anchor={x:Math.ceil(r.x2)+u,y:c*(a||r.height()+2*r.y1),row:l};break;case j_:f.anchor={y:Math.floor(i.y1)-u,row:Q_,x:c*(o||i.width()+2*i.x1),column:l};break;case H_:f.anchor={y:Math.ceil(i.y2)+u,x:c*(o||i.width()+2*i.x1),column:l};break;case Y_:f.anchor={x:u,y:u};break;case G_:f.anchor={x:o-u,y:u,column:Q_};break;case V_:f.anchor={x:u,y:a-u,row:Q_};break;case X_:f.anchor={x:o-u,y:a-u,column:Q_,row:Q_}}return f}function nb(t,e){var n,r,i=e.items[0],o=i.datum,a=i.orient,s=i.bounds,u=i.x,l=i.y;return i._bounds?i._bounds.clear().union(s):i._bounds=s.clone(),s.clear(),function(t,e,n){var r=e.padding,i=r-n.x,o=r-n.y;if(e.datum.title){var a=e.items[1].items[0],s=a.anchor,u=e.titlePadding||0,l=r-a.x,c=r-a.y;switch(a.orient){case I_:i+=Math.ceil(a.bounds.width())+u;break;case W_:case H_:break;default:o+=a.bounds.height()+u}switch((i||o)&&ib(t,n,i,o),a.orient){case I_:c+=rb(e,n,a,s,1,1);break;case W_:l+=rb(e,n,a,Q_,0,0)+u,c+=rb(e,n,a,s,1,1);break;case H_:l+=rb(e,n,a,s,0,0),c+=rb(e,n,a,Q_,-1,0,1)+u;break;default:l+=rb(e,n,a,s,0,0)}(l||c)&&ib(t,a,l,c),(l=Math.round(a.bounds.x1-r))<0&&(ib(t,n,-l,0),ib(t,a,-l,0))}else(i||o)&&ib(t,n,i,o)}(t,i,i.items[0].items[0]),s=function(t,e){return t.items.forEach((t=>e.union(t.bounds))),e.x1=t.padding,e.y1=t.padding,e}(i,s),n=2*i.padding,r=2*i.padding,s.empty()||(n=Math.ceil(s.width()+n),r=Math.ceil(s.height()+r)),o.type===px&&function(t){const e=t.reduce(((t,e)=>(t[e.column]=Math.max(e.bounds.x2-e.x,t[e.column]||0),t)),{});t.forEach((t=>{t.width=e[t.column],t.height=t.bounds.y2-t.y}))}(i.items[0].items[0].items[0].items),a!==_x&&(i.x=u=0,i.y=l=0),i.width=n,i.height=r,tm(s.set(u,l,u+n,l+r),i),i.mark.bounds.clear().union(s),i}function rb(t,e,n,r,i,o,a){const s="symbol"!==t.datum.type,u=n.datum.vgrad,l=(!s||!o&&u||a?e:e.items[0]).bounds[i?"y2":"x2"]-t.padding,c=u&&o?l:0,f=u&&o?0:l,h=i<=0?0:zy(n);return Math.round(r===J_?c:r===Q_?f-h:.5*(l-h))}function ib(t,e,n,r){e.x+=n,e.y+=r,e.bounds.translate(n,r),e.mark.bounds.translate(n,r),t.dirty(e)}function ob(t){Xa.call(this,null,t)}ht(ob,Xa,{transform(t,e){const n=e.dataflow;return t.mark.items.forEach((e=>{t.layout&&Jx(n,e,t.layout),function(t,e,n){var r,i,o,a,s,u=e.items,l=Math.max(0,e.width||0),c=Math.max(0,e.height||0),f=(new Vg).set(0,0,l,c),h=f.clone(),d=f.clone(),p=[];for(a=0,s=u.length;a{(o=t.orient||W_)!==_x&&(e[o]||(e[o]=[])).push(t)}));for(const r in e){const i=e[r];Xx(t,i,eb(i,r,n.legends,h,d,l,c))}p.forEach((e=>{const r=e.bounds;if(r.equals(e._bounds)||(e.bounds=e._bounds,t.dirty(e),e.bounds=r,t.dirty(e)),!n.autosize||n.autosize.type!==gx&&n.autosize.type!==mx&&n.autosize.type!==yx)f.union(r);else switch(e.orient){case I_:case W_:f.add(r.x1,0).add(r.x2,0);break;case j_:case H_:f.add(0,r.y1).add(0,r.y2)}}))}f.union(h).union(d),r&&f.union(function(t,e,n,r,i){var o,a=e.items[0],s=a.frame,u=a.orient,l=a.anchor,c=a.offset,f=a.padding,h=a.items[0].items[0],d=a.items[1]&&a.items[1].items[0],p=u===I_||u===W_?r:n,g=0,m=0,y=0,v=0,_=0;if(s!==ex?u===I_?(g=i.y2,p=i.y1):u===W_?(g=i.y1,p=i.y2):(g=i.x1,p=i.x2):u===I_&&(g=r,p=0),o=l===J_?g:l===Q_?p:(g+p)/2,d&&d.text){switch(u){case j_:case H_:_=h.bounds.height()+f;break;case I_:v=h.bounds.width()+f;break;case W_:v=-h.bounds.width()-f}Lx.clear().union(d.bounds),Lx.translate(v-(d.x||0),_-(d.y||0)),Ux(d,"x",v)|Ux(d,"y",_)&&(t.dirty(d),d.bounds.clear().union(Lx),d.mark.bounds.clear().union(Lx),t.dirty(d)),Lx.clear().union(d.bounds)}else Lx.clear();switch(Lx.union(h.bounds),u){case j_:m=o,y=i.y1-Lx.height()-c;break;case I_:m=i.x1-Lx.width()-c,y=o;break;case W_:m=i.x2+Lx.width()+c,y=o;break;case H_:m=o,y=i.y2+c;break;default:m=a.x,y=a.y}return Ux(a,"x",m)|Ux(a,"y",y)&&(Lx.translate(m,y),t.dirty(a),a.bounds.clear().union(Lx),e.bounds.clear().union(Lx),t.dirty(a)),a.bounds}(t,r,l,c,f));e.clip&&f.set(0,0,e.width||0,e.height||0);!function(t,e,n,r){const i=r.autosize||{},o=i.type;if(t._autosize<1||!o)return;let a=t._width,s=t._height,u=Math.max(0,e.width||0),l=Math.max(0,Math.ceil(-n.x1)),c=Math.max(0,e.height||0),f=Math.max(0,Math.ceil(-n.y1));const h=Math.max(0,Math.ceil(n.x2-u)),d=Math.max(0,Math.ceil(n.y2-c));if(i.contains===dx){const e=t.padding();a-=e.left+e.right,s-=e.top+e.bottom}o===_x?(l=0,f=0,u=a,c=s):o===gx?(u=Math.max(0,a-l-h),c=Math.max(0,s-f-d)):o===mx?(u=Math.max(0,a-l-h),s=c+f+d):o===yx?(a=u+l+h,c=Math.max(0,s-f-d)):o===vx&&(a=u+l+h,s=c+f+d);t._resizeView(a,s,u,c,[l,f],i.resize)}(t,e,f,n)}(n,e,t)})),function(t){return t&&"legend-entry"!==t.mark.role}(t.mark.group)?e.reflow():e}});var ab=Object.freeze({__proto__:null,bound:Mx,identifier:Cx,mark:Fx,overlap:Sx,render:Rx,viewlayout:ob});function sb(t){Xa.call(this,null,t)}function ub(t){Xa.call(this,null,t)}function lb(){return va({})}function cb(t){Xa.call(this,null,t)}function fb(t){Xa.call(this,[],t)}ht(sb,Xa,{transform(t,e){if(this.value&&!t.modified())return e.StopPropagation;var n=e.dataflow.locale(),r=e.fork(e.NO_SOURCE|e.NO_FIELDS),i=this.value,o=t.scale,a=Sp(o,null==t.count?t.values?t.values.length:10:t.count,t.minstep),s=t.format||Bp(n,o,a,t.formatSpecifier,t.formatType,!!t.values),u=t.values?$p(o,t.values,a):Tp(o,a);return i&&(r.rem=i),i=u.map(((t,e)=>va({index:e/(u.length-1||1),value:t,label:s(t)}))),t.extra&&i.length&&i.push(va({index:-1,extra:{value:i[0].value},label:""})),r.source=i,r.add=i,this.value=i,r}}),ht(ub,Xa,{transform(t,e){var n=e.dataflow,r=e.fork(e.NO_SOURCE|e.NO_FIELDS),i=t.item||lb,o=t.key||ma,a=this.value;return k(r.encode)&&(r.encode=null),a&&(t.modified("key")||e.modified(o))&&s("DataJoin does not support modified key function or fields."),a||(e=e.addAll(),this.value=a=function(t){const e=ct().test((t=>t.exit));return e.lookup=n=>e.get(t(n)),e}(o)),e.visit(e.ADD,(t=>{const e=o(t);let n=a.get(e);n?n.exit?(a.empty--,r.add.push(n)):r.mod.push(n):(n=i(t),a.set(e,n),r.add.push(n)),n.datum=t,n.exit=!1})),e.visit(e.MOD,(t=>{const e=o(t),n=a.get(e);n&&(n.datum=t,r.mod.push(n))})),e.visit(e.REM,(t=>{const e=o(t),n=a.get(e);t!==n.datum||n.exit||(r.rem.push(n),n.exit=!0,++a.empty)})),e.changed(e.ADD_MOD)&&r.modifies("datum"),(e.clean()||t.clean&&a.empty>n.cleanThreshold)&&n.runAfter(a.clean),r}}),ht(cb,Xa,{transform(t,e){var n=e.fork(e.ADD_REM),r=t.mod||!1,i=t.encoders,o=e.encode;if(k(o)){if(!n.changed()&&!o.every((t=>i[t])))return e.StopPropagation;o=o[0],n.encode=null}var a="enter"===o,s=i.update||g,u=i.enter||g,l=i.exit||g,c=(o&&!a?i[o]:s)||g;if(e.changed(e.ADD)&&(e.visit(e.ADD,(e=>{u(e,t),s(e,t)})),n.modifies(u.output),n.modifies(s.output),c!==g&&c!==s&&(e.visit(e.ADD,(e=>{c(e,t)})),n.modifies(c.output))),e.changed(e.REM)&&l!==g&&(e.visit(e.REM,(e=>{l(e,t)})),n.modifies(l.output)),a||c!==g){const i=e.MOD|(t.modified()?e.REFLOW:0);a?(e.visit(i,(e=>{const i=u(e,t)||r;(c(e,t)||i)&&n.mod.push(e)})),n.mod.length&&n.modifies(u.output)):e.visit(i,(e=>{(c(e,t)||r)&&n.mod.push(e)})),n.mod.length&&n.modifies(c.output)}return n.changed()?n:e.StopPropagation}}),ht(fb,Xa,{transform(t,e){if(null!=this.value&&!t.modified())return e.StopPropagation;var n,r,i,o,a,s=e.dataflow.locale(),u=e.fork(e.NO_SOURCE|e.NO_FIELDS),l=this.value,c=t.type||Mp,f=t.scale,h=+t.limit,d=Sp(f,null==t.count?5:t.count,t.minstep),p=!!t.values||c===Mp,g=t.format||Up(s,f,d,c,t.formatSpecifier,t.formatType,p),m=t.values||Rp(f,d);return l&&(u.rem=l),c===Mp?(h&&m.length>h?(e.dataflow.warn("Symbol legend count exceeds limit, filtering items."),l=m.slice(0,h-1),a=!0):l=m,J(i=t.size)?(t.values||0!==f(l[0])||(l=l.slice(1)),o=l.reduce(((e,n)=>Math.max(e,i(n,t))),0)):i=rt(o=i||8),l=l.map(((e,n)=>va({index:n,label:g(e,n,l),value:e,offset:o,size:i(e,t)}))),a&&(a=m[l.length],l.push(va({index:l.length,label:`…${m.length-l.length} entries`,value:a,offset:o,size:i(a,t)})))):"gradient"===c?(n=f.domain(),r=_p(f,n[0],F(n)),m.length<3&&!t.values&&n[0]!==F(n)&&(m=[n[0],F(n)]),l=m.map(((t,e)=>va({index:e,label:g(t,e,m),value:t,perc:r(t)})))):(i=m.length-1,r=function(t){const e=t.domain(),n=e.length-1;let r=+e[0],i=+F(e),o=i-r;if(t.type===jd){const t=n?o/n:.1;r-=t,i+=t,o=i-r}return t=>(t-r)/o}(f),l=m.map(((t,e)=>va({index:e,label:g(t,e,m),value:t,perc:e?r(t):0,perc2:e===i?1:r(m[e+1])})))),u.source=l,u.add=l,this.value=l,u}});const hb=t=>t.source.x,db=t=>t.source.y,pb=t=>t.target.x,gb=t=>t.target.y;function mb(t){Xa.call(this,{},t)}mb.Definition={type:"LinkPath",metadata:{modifies:!0},params:[{name:"sourceX",type:"field",default:"source.x"},{name:"sourceY",type:"field",default:"source.y"},{name:"targetX",type:"field",default:"target.x"},{name:"targetY",type:"field",default:"target.y"},{name:"orient",type:"enum",default:"vertical",values:["horizontal","vertical","radial"]},{name:"shape",type:"enum",default:"line",values:["line","arc","curve","diagonal","orthogonal"]},{name:"require",type:"signal"},{name:"as",type:"string",default:"path"}]},ht(mb,Xa,{transform(t,e){var n=t.sourceX||hb,r=t.sourceY||db,i=t.targetX||pb,o=t.targetY||gb,a=t.as||"path",u=t.orient||"vertical",l=t.shape||"line",c=xb.get(l+"-"+u)||xb.get(l);return c||s("LinkPath unsupported type: "+t.shape+(t.orient?"-"+t.orient:"")),e.visit(e.SOURCE,(t=>{t[a]=c(n(t),r(t),i(t),o(t))})),e.reflow(t.modified()).modifies(a)}});const yb=(t,e,n,r)=>"M"+t+","+e+"L"+n+","+r,vb=(t,e,n,r)=>{var i=n-t,o=r-e,a=Math.hypot(i,o)/2;return"M"+t+","+e+"A"+a+","+a+" "+180*Math.atan2(o,i)/Math.PI+" 0 1 "+n+","+r},_b=(t,e,n,r)=>{const i=n-t,o=r-e,a=.2*(i+o),s=.2*(o-i);return"M"+t+","+e+"C"+(t+a)+","+(e+s)+" "+(n+s)+","+(r-a)+" "+n+","+r},xb=ct({line:yb,"line-radial":(t,e,n,r)=>yb(e*Math.cos(t),e*Math.sin(t),r*Math.cos(n),r*Math.sin(n)),arc:vb,"arc-radial":(t,e,n,r)=>vb(e*Math.cos(t),e*Math.sin(t),r*Math.cos(n),r*Math.sin(n)),curve:_b,"curve-radial":(t,e,n,r)=>_b(e*Math.cos(t),e*Math.sin(t),r*Math.cos(n),r*Math.sin(n)),"orthogonal-horizontal":(t,e,n,r)=>"M"+t+","+e+"V"+r+"H"+n,"orthogonal-vertical":(t,e,n,r)=>"M"+t+","+e+"H"+n+"V"+r,"orthogonal-radial":(t,e,n,r)=>{const i=Math.cos(t),o=Math.sin(t),a=Math.cos(n),s=Math.sin(n);return"M"+e*i+","+e*o+"A"+e+","+e+" 0 0,"+((Math.abs(n-t)>Math.PI?n<=t:n>t)?1:0)+" "+e*a+","+e*s+"L"+r*a+","+r*s},"diagonal-horizontal":(t,e,n,r)=>{const i=(t+n)/2;return"M"+t+","+e+"C"+i+","+e+" "+i+","+r+" "+n+","+r},"diagonal-vertical":(t,e,n,r)=>{const i=(e+r)/2;return"M"+t+","+e+"C"+t+","+i+" "+n+","+i+" "+n+","+r},"diagonal-radial":(t,e,n,r)=>{const i=Math.cos(t),o=Math.sin(t),a=Math.cos(n),s=Math.sin(n),u=(e+r)/2;return"M"+e*i+","+e*o+"C"+u*i+","+u*o+" "+u*a+","+u*s+" "+r*a+","+r*s}});function bb(t){Xa.call(this,null,t)}bb.Definition={type:"Pie",metadata:{modifies:!0},params:[{name:"field",type:"field"},{name:"startAngle",type:"number",default:0},{name:"endAngle",type:"number",default:6.283185307179586},{name:"sort",type:"boolean",default:!1},{name:"as",type:"string",array:!0,length:2,default:["startAngle","endAngle"]}]},ht(bb,Xa,{transform(t,e){var n,r,i,o=t.as||["startAngle","endAngle"],a=o[0],s=o[1],u=t.field||d,l=t.startAngle||0,c=null!=t.endAngle?t.endAngle:2*Math.PI,f=e.source,h=f.map(u),p=h.length,g=l,m=(c-l)/Se(h),y=Fe(p);for(t.sort&&y.sort(((t,e)=>h[t]-h[e])),n=0;nt+(e<0?-1:e>0?1:0)),0))!==e.length&&n.warn("Log scale domain includes zero: "+Dt(e)));return e}function Db(t,e,n){return J(t)&&(e||n)?mp(t,Cb(e||[0,1],n)):t}function Cb(t,e){return e?t.slice().reverse():t}function Fb(t){Xa.call(this,null,t)}ht(Mb,Xa,{transform(t,e){var n=e.dataflow,r=this.value,i=function(t){var e,n=t.type,r="";if(n===Ld)return Ld+"-"+$d;(function(t){const e=t.type;return lp(e)&&e!==Od&&e!==Rd&&(t.scheme||t.range&&t.range.length&&t.range.every(_t))})(t)&&(r=2===(e=t.rawDomain?t.rawDomain.length:t.domain?t.domain.length+ +(null!=t.domainMid):0)?Ld+"-":3===e?Ud+"-":"");return(r+n||$d).toLowerCase()}(t);for(i in r&&i===r.type||(this.value=r=ap(i)()),t)if(!Ab[i]){if("padding"===i&&kb(r.type))continue;J(r[i])?r[i](t[i]):n.warn("Unsupported scale property: "+i)}return function(t,e,n){var r=t.type,i=e.round||!1,o=e.range;if(null!=e.rangeStep)o=function(t,e,n){t!==Hd&&t!==Wd&&s("Only band and point scales support rangeStep.");var r=(null!=e.paddingOuter?e.paddingOuter:e.padding)||0,i=t===Wd?1:(null!=e.paddingInner?e.paddingInner:e.padding)||0;return[0,e.rangeStep*Sd(n,i,r)]}(r,e,n);else if(e.scheme&&(o=function(t,e,n){var r,i=e.schemeExtent;k(e.scheme)?r=yp(e.scheme,e.interpolate,e.interpolateGamma):(r=Ap(e.scheme.toLowerCase()))||s(`Unrecognized scheme name: ${e.scheme}`);return n=t===jd?n+1:t===Yd?n-1:t===qd||t===Pd?+e.schemeCount||wb:n,dp(t)?Db(r,i,e.reverse):J(r)?vp(Db(r,i),n):t===Id?r:r.slice(0,n)}(r,e,n),J(o))){if(t.interpolator)return t.interpolator(o);s(`Scale type ${r} does not support interpolating color schemes.`)}if(o&&dp(r))return t.interpolator(yp(Cb(o,e.reverse),e.interpolate,e.interpolateGamma));o&&e.interpolate&&t.interpolate?t.interpolate(xp(e.interpolate,e.interpolateGamma)):J(t.round)?t.round(i):J(t.rangeRound)&&t.interpolate(i?mh:gh);o&&t.range(Cb(o,e.reverse))}(r,t,function(t,e,n){let r=e.bins;if(r&&!k(r)){const e=t.domain(),n=e[0],i=F(e),o=r.step;let a=null==r.start?n:r.start,u=null==r.stop?i:r.stop;o||s("Scale bins parameter missing step property."),ai&&(u=o*Math.floor(i/o)),r=Fe(a,u+o/2,o)}r?t.bins=r:t.bins&&delete t.bins;t.type===Yd&&(r?e.domain||e.domainRaw||(t.domain(r),n=r.length):t.bins=t.domain());return n}(r,t,function(t,e,n){const r=function(t,e,n){return e?(t.domain(Eb(t.type,e,n)),e.length):-1}(t,e.domainRaw,n);if(r>-1)return r;var i,o,a=e.domain,s=t.type,u=e.zero||void 0===e.zero&&function(t){const e=t.type;return!t.bins&&(e===$d||e===Bd||e===zd)}(t);if(!a)return 0;if((u||null!=e.domainMin||null!=e.domainMax||null!=e.domainMid)&&(i=(a=a.slice()).length-1||1,u&&(a[0]>0&&(a[0]=0),a[i]<0&&(a[i]=0)),null!=e.domainMin&&(a[0]=e.domainMin),null!=e.domainMax&&(a[i]=e.domainMax),null!=e.domainMid)){const t=(o=e.domainMid)>a[i]?i+1:ot(u);if(null==e)d.push(t.slice());else for(i={},o=0,a=t.length;oh&&(h=f),n&&c.sort(n)}return d.max=h,d}(e.source,t.groupby,l,c),r=0,i=n.length,o=n.max;r0?1:t<0?-1:0},iw=Math.sqrt,ow=Math.tan;function aw(t){return t>1?0:t<-1?Pb:Math.acos(t)}function sw(t){return t>1?jb:t<-1?-jb:Math.asin(t)}function uw(){}function lw(t,e){t&&fw.hasOwnProperty(t.type)&&fw[t.type](t,e)}var cw={Feature:function(t,e){lw(t.geometry,e)},FeatureCollection:function(t,e){for(var n=t.features,r=-1,i=n.length;++r=0?1:-1,i=r*n,o=Jb(e=(e*=Yb)/2+Ib),a=nw(e),s=_w*a,u=vw*o+s*Jb(i),l=s*r*nw(i);$w.add(Xb(l,u)),yw=t,vw=o,_w=a}function Lw(t){return[Xb(t[1],t[0]),sw(t[2])]}function Uw(t){var e=t[0],n=t[1],r=Jb(n);return[r*Jb(e),r*nw(e),nw(n)]}function qw(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function Pw(t,e){return[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]]}function jw(t,e){t[0]+=e[0],t[1]+=e[1],t[2]+=e[2]}function Iw(t,e){return[t[0]*e,t[1]*e,t[2]*e]}function Ww(t){var e=iw(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=e,t[1]/=e,t[2]/=e}var Hw,Yw,Gw,Vw,Xw,Jw,Zw,Qw,Kw,tk,ek,nk,rk,ik,ok,ak,sk={point:uk,lineStart:ck,lineEnd:fk,polygonStart:function(){sk.point=hk,sk.lineStart=dk,sk.lineEnd=pk,Cw=new ae,Bw.polygonStart()},polygonEnd:function(){Bw.polygonEnd(),sk.point=uk,sk.lineStart=ck,sk.lineEnd=fk,$w<0?(xw=-(ww=180),bw=-(kw=90)):Cw>Ub?kw=90:Cw<-1e-6&&(bw=-90),Sw[0]=xw,Sw[1]=ww},sphere:function(){xw=-(ww=180),bw=-(kw=90)}};function uk(t,e){Fw.push(Sw=[xw=t,ww=t]),ekw&&(kw=e)}function lk(t,e){var n=Uw([t*Yb,e*Yb]);if(Dw){var r=Pw(Dw,n),i=Pw([r[1],-r[0],0],r);Ww(i),i=Lw(i);var o,a=t-Aw,s=a>0?1:-1,u=i[0]*Hb*s,l=Gb(a)>180;l^(s*Awkw&&(kw=o):l^(s*Aw<(u=(u+360)%360-180)&&ukw&&(kw=e)),l?tgk(xw,ww)&&(ww=t):gk(t,ww)>gk(xw,ww)&&(xw=t):ww>=xw?(tww&&(ww=t)):t>Aw?gk(xw,t)>gk(xw,ww)&&(ww=t):gk(t,ww)>gk(xw,ww)&&(xw=t)}else Fw.push(Sw=[xw=t,ww=t]);ekw&&(kw=e),Dw=n,Aw=t}function ck(){sk.point=lk}function fk(){Sw[0]=xw,Sw[1]=ww,sk.point=uk,Dw=null}function hk(t,e){if(Dw){var n=t-Aw;Cw.add(Gb(n)>180?n+(n>0?360:-360):n)}else Mw=t,Ew=e;Bw.point(t,e),lk(t,e)}function dk(){Bw.lineStart()}function pk(){hk(Mw,Ew),Bw.lineEnd(),Gb(Cw)>Ub&&(xw=-(ww=180)),Sw[0]=xw,Sw[1]=ww,Dw=null}function gk(t,e){return(e-=t)<0?e+360:e}function mk(t,e){return t[0]-e[0]}function yk(t,e){return t[0]<=t[1]?t[0]<=e&&e<=t[1]:ePb&&(t-=Math.round(t/Wb)*Wb),[t,e]}function $k(t,e,n){return(t%=Wb)?e||n?Fk(Bk(t),zk(e,n)):Bk(t):e||n?zk(e,n):Sk}function Tk(t){return function(e,n){return Gb(e+=t)>Pb&&(e-=Math.round(e/Wb)*Wb),[e,n]}}function Bk(t){var e=Tk(t);return e.invert=Tk(-t),e}function zk(t,e){var n=Jb(t),r=nw(t),i=Jb(e),o=nw(e);function a(t,e){var a=Jb(e),s=Jb(t)*a,u=nw(t)*a,l=nw(e),c=l*n+s*r;return[Xb(u*i-c*o,s*n-l*r),sw(c*i+u*o)]}return a.invert=function(t,e){var a=Jb(e),s=Jb(t)*a,u=nw(t)*a,l=nw(e),c=l*i-u*o;return[Xb(u*i+l*o,s*n+c*r),sw(c*n-s*r)]},a}function Nk(t,e){(e=Uw(e))[0]-=t,Ww(e);var n=aw(-e[1]);return((-e[2]<0?-n:n)+Wb-Ub)%Wb}function Ok(){var t,e=[];return{point:function(e,n,r){t.push([e,n,r])},lineStart:function(){e.push(t=[])},lineEnd:uw,rejoin:function(){e.length>1&&e.push(e.pop().concat(e.shift()))},result:function(){var n=e;return e=[],t=null,n}}}function Rk(t,e){return Gb(t[0]-e[0])=0;--o)i.point((c=l[o])[0],c[1]);else r(h.x,h.p.x,-1,i);h=h.p}l=(h=h.o).z,d=!d}while(!h.v);i.lineEnd()}}}function qk(t){if(e=t.length){for(var e,n,r=0,i=t[0];++r=0?1:-1,E=M*A,D=E>Pb,C=m*w;if(u.add(Xb(C*M*nw(E),y*k+C*Jb(E))),a+=D?A+M*Wb:A,D^p>=n^x>=n){var F=Pw(Uw(d),Uw(_));Ww(F);var S=Pw(o,F);Ww(S);var $=(D^A>=0?-1:1)*sw(S[2]);(r>$||r===$&&(F[0]||F[1]))&&(s+=D^A>=0?1:-1)}}return(a<-1e-6||a0){for(f||(i.polygonStart(),f=!0),i.lineStart(),t=0;t1&&2&u&&h.push(h.pop().concat(h.shift())),a.push(h.filter(Ik))}return h}}function Ik(t){return t.length>1}function Wk(t,e){return((t=t.x)[0]<0?t[1]-jb-Ub:jb-t[1])-((e=e.x)[0]<0?e[1]-jb-Ub:jb-e[1])}Sk.invert=Sk;var Hk=jk((function(){return!0}),(function(t){var e,n=NaN,r=NaN,i=NaN;return{lineStart:function(){t.lineStart(),e=1},point:function(o,a){var s=o>0?Pb:-Pb,u=Gb(o-n);Gb(u-Pb)0?jb:-jb),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(s,r),t.point(o,r),e=0):i!==s&&u>=Pb&&(Gb(n-i)Ub?Vb((nw(e)*(o=Jb(r))*nw(n)-nw(r)*(i=Jb(e))*nw(t))/(i*o*a)):(e+r)/2}(n,r,o,a),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(s,r),e=0),t.point(n=o,r=a),i=s},lineEnd:function(){t.lineEnd(),n=r=NaN},clean:function(){return 2-e}}}),(function(t,e,n,r){var i;if(null==t)i=n*jb,r.point(-Pb,i),r.point(0,i),r.point(Pb,i),r.point(Pb,0),r.point(Pb,-i),r.point(0,-i),r.point(-Pb,-i),r.point(-Pb,0),r.point(-Pb,i);else if(Gb(t[0]-e[0])>Ub){var o=t[0]0,i=Gb(e)>Ub;function o(t,n){return Jb(t)*Jb(n)>e}function a(t,n,r){var i=[1,0,0],o=Pw(Uw(t),Uw(n)),a=qw(o,o),s=o[0],u=a-s*s;if(!u)return!r&&t;var l=e*a/u,c=-e*s/u,f=Pw(i,o),h=Iw(i,l);jw(h,Iw(o,c));var d=f,p=qw(h,d),g=qw(d,d),m=p*p-g*(qw(h,h)-1);if(!(m<0)){var y=iw(m),v=Iw(d,(-p-y)/g);if(jw(v,h),v=Lw(v),!r)return v;var _,x=t[0],b=n[0],w=t[1],k=n[1];b0^v[1]<(Gb(v[0]-x)Pb^(x<=v[0]&&v[0]<=b)){var E=Iw(d,(-p+y)/g);return jw(E,h),[v,Lw(E)]}}}function s(e,n){var i=r?t:Pb-t,o=0;return e<-i?o|=1:e>i&&(o|=2),n<-i?o|=4:n>i&&(o|=8),o}return jk(o,(function(t){var e,n,u,l,c;return{lineStart:function(){l=u=!1,c=1},point:function(f,h){var d,p=[f,h],g=o(f,h),m=r?g?0:s(f,h):g?s(f+(f<0?Pb:-Pb),h):0;if(!e&&(l=u=g)&&t.lineStart(),g!==u&&(!(d=a(e,p))||Rk(e,d)||Rk(p,d))&&(p[2]=1),g!==u)c=0,g?(t.lineStart(),d=a(p,e),t.point(d[0],d[1])):(d=a(e,p),t.point(d[0],d[1],2),t.lineEnd()),e=d;else if(i&&e&&r^g){var y;m&n||!(y=a(p,e,!0))||(c=0,r?(t.lineStart(),t.point(y[0][0],y[0][1]),t.point(y[1][0],y[1][1]),t.lineEnd()):(t.point(y[1][0],y[1][1]),t.lineEnd(),t.lineStart(),t.point(y[0][0],y[0][1],3)))}!g||e&&Rk(e,p)||t.point(p[0],p[1]),e=p,u=g,n=m},lineEnd:function(){u&&t.lineEnd(),e=null},clean:function(){return c|(l&&u)<<1}}}),(function(e,r,i,o){!function(t,e,n,r,i,o){if(n){var a=Jb(e),s=nw(e),u=r*n;null==i?(i=e+r*Wb,o=e-u/2):(i=Nk(a,i),o=Nk(a,o),(r>0?io)&&(i+=r*Wb));for(var l,c=i;r>0?c>o:c0)do{l.point(0===c||3===c?t:n,c>1?r:e)}while((c=(c+s+4)%4)!==f);else l.point(o[0],o[1])}function a(r,i){return Gb(r[0]-t)0?0:3:Gb(r[0]-n)0?2:1:Gb(r[1]-e)0?1:0:i>0?3:2}function s(t,e){return u(t.x,e.x)}function u(t,e){var n=a(t,1),r=a(e,1);return n!==r?n-r:0===n?e[1]-t[1]:1===n?t[0]-e[0]:2===n?t[1]-e[1]:e[0]-t[0]}return function(a){var u,l,c,f,h,d,p,g,m,y,v,_=a,x=Ok(),b={point:w,lineStart:function(){b.point=k,l&&l.push(c=[]);y=!0,m=!1,p=g=NaN},lineEnd:function(){u&&(k(f,h),d&&m&&x.rejoin(),u.push(x.result()));b.point=w,m&&_.lineEnd()},polygonStart:function(){_=x,u=[],l=[],v=!0},polygonEnd:function(){var e=function(){for(var e=0,n=0,i=l.length;nr&&(h-o)*(r-a)>(d-a)*(t-o)&&++e:d<=r&&(h-o)*(r-a)<(d-a)*(t-o)&&--e;return e}(),n=v&&e,i=(u=Ce(u)).length;(n||i)&&(a.polygonStart(),n&&(a.lineStart(),o(null,null,1,a),a.lineEnd()),i&&Uk(u,s,e,o,a),a.polygonEnd());_=a,u=l=c=null}};function w(t,e){i(t,e)&&_.point(t,e)}function k(o,a){var s=i(o,a);if(l&&c.push([o,a]),y)f=o,h=a,d=s,y=!1,s&&(_.lineStart(),_.point(o,a));else if(s&&m)_.point(o,a);else{var u=[p=Math.max(Vk,Math.min(Gk,p)),g=Math.max(Vk,Math.min(Gk,g))],x=[o=Math.max(Vk,Math.min(Gk,o)),a=Math.max(Vk,Math.min(Gk,a))];!function(t,e,n,r,i,o){var a,s=t[0],u=t[1],l=0,c=1,f=e[0]-s,h=e[1]-u;if(a=n-s,f||!(a>0)){if(a/=f,f<0){if(a0){if(a>c)return;a>l&&(l=a)}if(a=i-s,f||!(a<0)){if(a/=f,f<0){if(a>c)return;a>l&&(l=a)}else if(f>0){if(a0)){if(a/=h,h<0){if(a0){if(a>c)return;a>l&&(l=a)}if(a=o-u,h||!(a<0)){if(a/=h,h<0){if(a>c)return;a>l&&(l=a)}else if(h>0){if(a0&&(t[0]=s+l*f,t[1]=u+l*h),c<1&&(e[0]=s+c*f,e[1]=u+c*h),!0}}}}}(u,x,t,e,n,r)?s&&(_.lineStart(),_.point(o,a),v=!1):(m||(_.lineStart(),_.point(u[0],u[1])),_.point(x[0],x[1]),s||_.lineEnd(),v=!1)}p=o,g=a,m=s}return b}}function Jk(t,e,n){var r=Fe(t,e-Ub,n).concat(e);return function(t){return r.map((function(e){return[t,e]}))}}function Zk(t,e,n){var r=Fe(t,e-Ub,n).concat(e);return function(t){return r.map((function(e){return[e,t]}))}}var Qk,Kk,tA,eA,nA=t=>t,rA=new ae,iA=new ae,oA={point:uw,lineStart:uw,lineEnd:uw,polygonStart:function(){oA.lineStart=aA,oA.lineEnd=lA},polygonEnd:function(){oA.lineStart=oA.lineEnd=oA.point=uw,rA.add(Gb(iA)),iA=new ae},result:function(){var t=rA/2;return rA=new ae,t}};function aA(){oA.point=sA}function sA(t,e){oA.point=uA,Qk=tA=t,Kk=eA=e}function uA(t,e){iA.add(eA*t-tA*e),tA=t,eA=e}function lA(){uA(Qk,Kk)}var cA=1/0,fA=cA,hA=-cA,dA=hA,pA={point:function(t,e){thA&&(hA=t);edA&&(dA=e)},lineStart:uw,lineEnd:uw,polygonStart:uw,polygonEnd:uw,result:function(){var t=[[cA,fA],[hA,dA]];return hA=dA=-(fA=cA=1/0),t}};var gA,mA,yA,vA,_A=0,xA=0,bA=0,wA=0,kA=0,AA=0,MA=0,EA=0,DA=0,CA={point:FA,lineStart:SA,lineEnd:BA,polygonStart:function(){CA.lineStart=zA,CA.lineEnd=NA},polygonEnd:function(){CA.point=FA,CA.lineStart=SA,CA.lineEnd=BA},result:function(){var t=DA?[MA/DA,EA/DA]:AA?[wA/AA,kA/AA]:bA?[_A/bA,xA/bA]:[NaN,NaN];return _A=xA=bA=wA=kA=AA=MA=EA=DA=0,t}};function FA(t,e){_A+=t,xA+=e,++bA}function SA(){CA.point=$A}function $A(t,e){CA.point=TA,FA(yA=t,vA=e)}function TA(t,e){var n=t-yA,r=e-vA,i=iw(n*n+r*r);wA+=i*(yA+t)/2,kA+=i*(vA+e)/2,AA+=i,FA(yA=t,vA=e)}function BA(){CA.point=FA}function zA(){CA.point=OA}function NA(){RA(gA,mA)}function OA(t,e){CA.point=RA,FA(gA=yA=t,mA=vA=e)}function RA(t,e){var n=t-yA,r=e-vA,i=iw(n*n+r*r);wA+=i*(yA+t)/2,kA+=i*(vA+e)/2,AA+=i,MA+=(i=vA*t-yA*e)*(yA+t),EA+=i*(vA+e),DA+=3*i,FA(yA=t,vA=e)}function LA(t){this._context=t}LA.prototype={_radius:4.5,pointRadius:function(t){return this._radius=t,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._context.closePath(),this._point=NaN},point:function(t,e){switch(this._point){case 0:this._context.moveTo(t,e),this._point=1;break;case 1:this._context.lineTo(t,e);break;default:this._context.moveTo(t+this._radius,e),this._context.arc(t,e,this._radius,0,Wb)}},result:uw};var UA,qA,PA,jA,IA,WA=new ae,HA={point:uw,lineStart:function(){HA.point=YA},lineEnd:function(){UA&&GA(qA,PA),HA.point=uw},polygonStart:function(){UA=!0},polygonEnd:function(){UA=null},result:function(){var t=+WA;return WA=new ae,t}};function YA(t,e){HA.point=GA,qA=jA=t,PA=IA=e}function GA(t,e){jA-=t,IA-=e,WA.add(iw(jA*jA+IA*IA)),jA=t,IA=e}let VA,XA,JA,ZA;class QA{constructor(t){this._append=null==t?KA:function(t){const e=Math.floor(t);if(!(e>=0))throw new RangeError(`invalid digits: ${t}`);if(e>15)return KA;if(e!==VA){const t=10**e;VA=e,XA=function(e){let n=1;this._+=e[0];for(const r=e.length;n=0))throw new RangeError(`invalid digits: ${t}`);i=e}return null===e&&(r=new QA(i)),a},a.projection(t).digits(i).context(e)}function eM(t){return function(e){var n=new nM;for(var r in t)n[r]=t[r];return n.stream=e,n}}function nM(){}function rM(t,e,n){var r=t.clipExtent&&t.clipExtent();return t.scale(150).translate([0,0]),null!=r&&t.clipExtent(null),pw(n,t.stream(pA)),e(pA.result()),null!=r&&t.clipExtent(r),t}function iM(t,e,n){return rM(t,(function(n){var r=e[1][0]-e[0][0],i=e[1][1]-e[0][1],o=Math.min(r/(n[1][0]-n[0][0]),i/(n[1][1]-n[0][1])),a=+e[0][0]+(r-o*(n[1][0]+n[0][0]))/2,s=+e[0][1]+(i-o*(n[1][1]+n[0][1]))/2;t.scale(150*o).translate([a,s])}),n)}function oM(t,e,n){return iM(t,[[0,0],e],n)}function aM(t,e,n){return rM(t,(function(n){var r=+e,i=r/(n[1][0]-n[0][0]),o=(r-i*(n[1][0]+n[0][0]))/2,a=-i*n[0][1];t.scale(150*i).translate([o,a])}),n)}function sM(t,e,n){return rM(t,(function(n){var r=+e,i=r/(n[1][1]-n[0][1]),o=-i*n[0][0],a=(r-i*(n[1][1]+n[0][1]))/2;t.scale(150*i).translate([o,a])}),n)}nM.prototype={constructor:nM,point:function(t,e){this.stream.point(t,e)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};var uM=16,lM=Jb(30*Yb);function cM(t,e){return+e?function(t,e){function n(r,i,o,a,s,u,l,c,f,h,d,p,g,m){var y=l-r,v=c-i,_=y*y+v*v;if(_>4*e&&g--){var x=a+h,b=s+d,w=u+p,k=iw(x*x+b*b+w*w),A=sw(w/=k),M=Gb(Gb(w)-1)e||Gb((y*F+v*S)/_-.5)>.3||a*h+s*d+u*p2?t[2]%360*Yb:0,F()):[m*Hb,y*Hb,v*Hb]},D.angle=function(t){return arguments.length?(_=t%360*Yb,F()):_*Hb},D.reflectX=function(t){return arguments.length?(x=t?-1:1,F()):x<0},D.reflectY=function(t){return arguments.length?(b=t?-1:1,F()):b<0},D.precision=function(t){return arguments.length?(a=cM(s,E=t*t),S()):iw(E)},D.fitExtent=function(t,e){return iM(D,t,e)},D.fitSize=function(t,e){return oM(D,t,e)},D.fitWidth=function(t,e){return aM(D,t,e)},D.fitHeight=function(t,e){return sM(D,t,e)},function(){return e=t.apply(this,arguments),D.invert=e.invert&&C,F()}}function gM(t){var e=0,n=Pb/3,r=pM(t),i=r(e,n);return i.parallels=function(t){return arguments.length?r(e=t[0]*Yb,n=t[1]*Yb):[e*Hb,n*Hb]},i}function mM(t,e){var n=nw(t),r=(n+nw(e))/2;if(Gb(r)2?t[2]*Yb:0),e.invert=function(e){return(e=t.invert(e[0]*Yb,e[1]*Yb))[0]*=Hb,e[1]*=Hb,e},e}(i.rotate()).invert([0,0]));return u(null==l?[[s[0]-o,s[1]-o],[s[0]+o,s[1]+o]]:t===kM?[[Math.max(s[0]-o,l),e],[Math.min(s[0]+o,n),r]]:[[l,Math.max(s[1]-o,e)],[n,Math.min(s[1]+o,r)]])}return i.scale=function(t){return arguments.length?(a(t),c()):a()},i.translate=function(t){return arguments.length?(s(t),c()):s()},i.center=function(t){return arguments.length?(o(t),c()):o()},i.clipExtent=function(t){return arguments.length?(null==t?l=e=n=r=null:(l=+t[0][0],e=+t[0][1],n=+t[1][0],r=+t[1][1]),c()):null==l?null:[[l,e],[n,r]]},c()}function MM(t){return ow((jb+t)/2)}function EM(t,e){var n=Jb(t),r=t===e?nw(t):tw(n/Jb(e))/tw(MM(e)/MM(t)),i=n*ew(MM(t),r)/r;if(!r)return kM;function o(t,e){i>0?e<-jb+Ub&&(e=-jb+Ub):e>jb-Ub&&(e=jb-Ub);var n=i/ew(MM(e),r);return[n*nw(r*t),i-n*Jb(r*t)]}return o.invert=function(t,e){var n=i-e,o=rw(r)*iw(t*t+n*n),a=Xb(t,Gb(n))*rw(n);return n*r<0&&(a-=Pb*rw(t)*rw(n)),[a/r,2*Vb(ew(i/o,1/r))-jb]},o}function DM(t,e){return[t,e]}function CM(t,e){var n=Jb(t),r=t===e?nw(t):(n-Jb(e))/(e-t),i=n/r+t;if(Gb(r)Ub&&--i>0);return[t/(.8707+(o=r*r)*(o*(o*o*o*(.003971-.001529*o)-.013791)-.131979)),r]},RM.invert=xM(sw),LM.invert=xM((function(t){return 2*Vb(t)})),UM.invert=function(t,e){return[-e,2*Vb(Qb(t))-jb]};var qM=Math.abs,PM=Math.cos,jM=Math.sin,IM=1e-6,WM=Math.PI,HM=WM/2,YM=function(t){return t>0?Math.sqrt(t):0}(2);function GM(t){return t>1?HM:t<-1?-HM:Math.asin(t)}function VM(t,e){var n,r=t*jM(e),i=30;do{e-=n=(e+jM(e)-r)/(1+PM(e))}while(qM(n)>IM&&--i>0);return e/2}var XM=function(t,e,n){function r(r,i){return[t*r*PM(i=VM(n,i)),e*jM(i)]}return r.invert=function(r,i){return i=GM(i/e),[r/(t*PM(i)),GM((2*i+jM(2*i))/n)]},r}(YM/HM,YM,WM);const JM=tM(),ZM=["clipAngle","clipExtent","scale","translate","center","rotate","parallels","precision","reflectX","reflectY","coefficient","distance","fraction","lobes","parallel","radius","ratio","spacing","tilt"];function QM(t,e){if(!t||"string"!=typeof t)throw new Error("Projection type must be a name string.");return t=t.toLowerCase(),arguments.length>1?(tE[t]=function(t,e){return function n(){const r=e();return r.type=t,r.path=tM().projection(r),r.copy=r.copy||function(){const t=n();return ZM.forEach((e=>{r[e]&&t[e](r[e]())})),t.path.pointRadius(r.path.pointRadius()),t},ip(r)}}(t,e),this):tE[t]||null}function KM(t){return t&&t.path||JM}const tE={albers:vM,albersusa:function(){var t,e,n,r,i,o,a=vM(),s=yM().rotate([154,0]).center([-2,58.5]).parallels([55,65]),u=yM().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(t,e){o=[t,e]}};function c(t){var e=t[0],a=t[1];return o=null,n.point(e,a),o||(r.point(e,a),o)||(i.point(e,a),o)}function f(){return t=e=null,c}return c.invert=function(t){var e=a.scale(),n=a.translate(),r=(t[0]-n[0])/e,i=(t[1]-n[1])/e;return(i>=.12&&i<.234&&r>=-.425&&r<-.214?s:i>=.166&&i<.234&&r>=-.214&&r<-.115?u:a).invert(t)},c.stream=function(n){return t&&e===n?t:(r=[a.stream(e=n),s.stream(n),u.stream(n)],i=r.length,t={point:function(t,e){for(var n=-1;++n2?t[2]+90:90]):[(t=n())[0],t[1],t[2]-90]},n([0,0,90]).scale(159.155)}};for(const t in tE)QM(t,tE[t]);function eE(){}const nE=[[],[[[1,1.5],[.5,1]]],[[[1.5,1],[1,1.5]]],[[[1.5,1],[.5,1]]],[[[1,.5],[1.5,1]]],[[[1,1.5],[.5,1]],[[1,.5],[1.5,1]]],[[[1,.5],[1,1.5]]],[[[1,.5],[.5,1]]],[[[.5,1],[1,.5]]],[[[1,1.5],[1,.5]]],[[[.5,1],[1,.5]],[[1.5,1],[1,1.5]]],[[[1.5,1],[1,.5]]],[[[.5,1],[1.5,1]]],[[[1,1.5],[1.5,1]]],[[[.5,1],[1,1.5]]],[]];function rE(){var t=1,e=1,n=a;function r(t,e){return e.map((e=>i(t,e)))}function i(r,i){var a=[],s=[];return function(n,r,i){var a,s,u,l,c,f,h=[],d=[];a=s=-1,l=n[0]>=r,nE[l<<1].forEach(p);for(;++a=r,nE[u|l<<1].forEach(p);nE[l<<0].forEach(p);for(;++s=r,c=n[s*t]>=r,nE[l<<1|c<<2].forEach(p);++a=r,f=c,c=n[s*t+a+1]>=r,nE[u|l<<1|c<<2|f<<3].forEach(p);nE[l|c<<3].forEach(p)}a=-1,c=n[s*t]>=r,nE[c<<2].forEach(p);for(;++a=r,nE[c<<2|f<<3].forEach(p);function p(t){var e,n,r=[t[0][0]+a,t[0][1]+s],u=[t[1][0]+a,t[1][1]+s],l=o(r),c=o(u);(e=d[l])?(n=h[c])?(delete d[e.end],delete h[n.start],e===n?(e.ring.push(u),i(e.ring)):h[e.start]=d[n.end]={start:e.start,end:n.end,ring:e.ring.concat(n.ring)}):(delete d[e.end],e.ring.push(u),d[e.end=c]=e):(e=h[c])?(n=d[l])?(delete h[e.start],delete d[n.end],e===n?(e.ring.push(u),i(e.ring)):h[n.start]=d[e.end]={start:n.start,end:e.end,ring:n.ring.concat(e.ring)}):(delete h[e.start],e.ring.unshift(r),h[e.start=l]=e):h[l]=d[c]={start:l,end:c,ring:[r,u]}}nE[c<<3].forEach(p)}(r,i,(t=>{n(t,r,i),function(t){var e=0,n=t.length,r=t[n-1][1]*t[0][0]-t[n-1][0]*t[0][1];for(;++e0?a.push([t]):s.push(t)})),s.forEach((t=>{for(var e,n=0,r=a.length;n{var o,a=n[0],s=n[1],u=0|a,l=0|s,c=r[l*t+u];a>0&&a0&&s=0&&o>=0||s("invalid size"),t=i,e=o,r},r.smooth=function(t){return arguments.length?(n=t?a:eE,r):n===a},r}function iE(t,e){for(var n,r=-1,i=e.length;++rr!=d>r&&n<(h-l)*(r-c)/(d-c)+l&&(i=-i)}return i}function aE(t,e,n){var r,i,o,a;return function(t,e,n){return(e[0]-t[0])*(n[1]-t[1])==(n[0]-t[0])*(e[1]-t[1])}(t,e,n)&&(i=t[r=+(t[0]===e[0])],o=n[r],a=e[r],i<=o&&o<=a||a<=o&&o<=i)}function sE(t,e,n){return function(r){var i=at(r),o=n?Math.min(i[0],0):i[0],a=i[1],s=a-o,u=e?xe(o,a,t):s/(t+1);return Fe(o+u,a,u)}}function uE(t){Xa.call(this,null,t)}function lE(t,e,n,r,i){const o=t.x1||0,a=t.y1||0,s=e*n<0;function u(t){t.forEach(l)}function l(t){s&&t.reverse(),t.forEach(c)}function c(t){t[0]=(t[0]-o)*e+r,t[1]=(t[1]-a)*n+i}return function(t){return t.coordinates.forEach(u),t}}function cE(t,e,n){const r=t>=0?t:ns(e,n);return Math.round((Math.sqrt(4*r*r+1)-1)/2)}function fE(t){return J(t)?t:rt(+t)}function hE(){var t=t=>t[0],e=t=>t[1],n=d,r=[-1,-1],i=960,o=500,a=2;function u(s,u){const l=cE(r[0],s,t)>>a,c=cE(r[1],s,e)>>a,f=l?l+2:0,h=c?c+2:0,d=2*f+(i>>a),p=2*h+(o>>a),g=new Float32Array(d*p),m=new Float32Array(d*p);let y=g;s.forEach((r=>{const i=f+(+t(r)>>a),o=h+(+e(r)>>a);i>=0&&i=0&&o0&&c>0?(dE(d,p,g,m,l),pE(d,p,m,g,c),dE(d,p,g,m,l),pE(d,p,m,g,c),dE(d,p,g,m,l),pE(d,p,m,g,c)):l>0?(dE(d,p,g,m,l),dE(d,p,m,g,l),dE(d,p,g,m,l),y=m):c>0&&(pE(d,p,g,m,c),pE(d,p,m,g,c),pE(d,p,g,m,c),y=m);const v=u?Math.pow(2,-2*a):1/Se(y);for(let t=0,e=d*p;t>a),y2:h+(o>>a)}}return u.x=function(e){return arguments.length?(t=fE(e),u):t},u.y=function(t){return arguments.length?(e=fE(t),u):e},u.weight=function(t){return arguments.length?(n=fE(t),u):n},u.size=function(t){if(!arguments.length)return[i,o];var e=+t[0],n=+t[1];return e>=0&&n>=0||s("invalid size"),i=e,o=n,u},u.cellSize=function(t){return arguments.length?((t=+t)>=1||s("invalid cell size"),a=Math.floor(Math.log(t)/Math.LN2),u):1<=i&&(e>=o&&(s-=n[e-o+a*t]),r[e-i+a*t]=s/Math.min(e+1,t-1+o-e,o))}function pE(t,e,n,r,i){const o=1+(i<<1);for(let a=0;a=i&&(s>=o&&(u-=n[a+(s-o)*t]),r[a+(s-i)*t]=u/Math.min(s+1,e-1+o-s,o))}function gE(t){Xa.call(this,null,t)}uE.Definition={type:"Isocontour",metadata:{generates:!0},params:[{name:"field",type:"field"},{name:"thresholds",type:"number",array:!0},{name:"levels",type:"number"},{name:"nice",type:"boolean",default:!1},{name:"resolve",type:"enum",values:["shared","independent"],default:"independent"},{name:"zero",type:"boolean",default:!0},{name:"smooth",type:"boolean",default:!0},{name:"scale",type:"number",expr:!0},{name:"translate",type:"number",array:!0,expr:!0},{name:"as",type:"string",null:!0,default:"contour"}]},ht(uE,Xa,{transform(t,e){if(this.value&&!e.changed()&&!t.modified())return e.StopPropagation;var n=e.fork(e.NO_SOURCE|e.NO_FIELDS),r=e.materialize(e.SOURCE).source,i=t.field||f,o=rE().smooth(!1!==t.smooth),a=t.thresholds||function(t,e,n){const r=sE(n.levels||10,n.nice,!1!==n.zero);return"shared"!==n.resolve?r:r(t.map((t=>be(e(t).values))))}(r,i,t),s=null===t.as?null:t.as||"contour",u=[];return r.forEach((e=>{const n=i(e),r=o.size([n.width,n.height])(n.values,k(a)?a:a(n.values));!function(t,e,n,r){let i=r.scale||e.scale,o=r.translate||e.translate;J(i)&&(i=i(n,r));J(o)&&(o=o(n,r));if((1===i||null==i)&&!o)return;const a=(yt(i)?i:i[0])||1,s=(yt(i)?i:i[1])||1,u=o&&o[0]||0,l=o&&o[1]||0;t.forEach(lE(e,a,s,u,l))}(r,n,e,t),r.forEach((t=>{u.push(xa(e,va(null!=s?{[s]:t}:t)))}))})),this.value&&(n.rem=this.value),this.value=n.source=n.add=u,n}}),gE.Definition={type:"KDE2D",metadata:{generates:!0},params:[{name:"size",type:"number",array:!0,length:2,required:!0},{name:"x",type:"field",required:!0},{name:"y",type:"field",required:!0},{name:"weight",type:"field"},{name:"groupby",type:"field",array:!0},{name:"cellSize",type:"number"},{name:"bandwidth",type:"number",array:!0,length:2},{name:"counts",type:"boolean",default:!1},{name:"as",type:"string",default:"grid"}]};const mE=["x","y","weight","size","cellSize","bandwidth"];function yE(t,e){return mE.forEach((n=>null!=e[n]?t[n](e[n]):0)),t}function vE(t){Xa.call(this,null,t)}ht(gE,Xa,{transform(t,e){if(this.value&&!e.changed()&&!t.modified())return e.StopPropagation;var r,i=e.fork(e.NO_SOURCE|e.NO_FIELDS),o=function(t,e){var n,r,i,o,a,s,u=[],l=t=>t(o);if(null==e)u.push(t);else for(n={},r=0,i=t.length;rva(function(t,e){for(let n=0;nUb})).map(u)).concat(Fe(Zb(o/d)*d,i,d).filter((function(t){return Gb(t%g)>Ub})).map(l))}return y.lines=function(){return v().map((function(t){return{type:"LineString",coordinates:t}}))},y.outline=function(){return{type:"Polygon",coordinates:[c(r).concat(f(a).slice(1),c(n).reverse().slice(1),f(s).reverse().slice(1))]}},y.extent=function(t){return arguments.length?y.extentMajor(t).extentMinor(t):y.extentMinor()},y.extentMajor=function(t){return arguments.length?(r=+t[0][0],n=+t[1][0],s=+t[0][1],a=+t[1][1],r>n&&(t=r,r=n,n=t),s>a&&(t=s,s=a,a=t),y.precision(m)):[[r,s],[n,a]]},y.extentMinor=function(n){return arguments.length?(e=+n[0][0],t=+n[1][0],o=+n[0][1],i=+n[1][1],e>t&&(n=e,e=t,t=n),o>i&&(n=o,o=i,i=n),y.precision(m)):[[e,o],[t,i]]},y.step=function(t){return arguments.length?y.stepMajor(t).stepMinor(t):y.stepMinor()},y.stepMajor=function(t){return arguments.length?(p=+t[0],g=+t[1],y):[p,g]},y.stepMinor=function(t){return arguments.length?(h=+t[0],d=+t[1],y):[h,d]},y.precision=function(h){return arguments.length?(m=+h,u=Jk(o,i,90),l=Zk(e,t,m),c=Jk(s,a,90),f=Zk(r,n,m),y):m},y.extentMajor([[-180,-90+Ub],[180,90-Ub]]).extentMinor([[-180,-80-Ub],[180,80+Ub]])}()}function EE(t){Xa.call(this,null,t)}function DE(t){if(!J(t))return!1;const e=Tt(r(t));return e.$x||e.$y||e.$value||e.$max}function CE(t){Xa.call(this,null,t),this.modified(!0)}function FE(t,e,n){J(t[e])&&t[e](n)}bE.Definition={type:"GeoJSON",metadata:{},params:[{name:"fields",type:"field",array:!0,length:2},{name:"geojson",type:"field"}]},ht(bE,Xa,{transform(t,e){var n,i=this._features,o=this._points,a=t.fields,s=a&&a[0],u=a&&a[1],l=t.geojson||!a&&f,c=e.ADD;n=t.modified()||e.changed(e.REM)||e.modified(r(l))||s&&e.modified(r(s))||u&&e.modified(r(u)),this.value&&!n||(c=e.SOURCE,this._features=i=[],this._points=o=[]),l&&e.visit(c,(t=>i.push(l(t)))),s&&u&&(e.visit(c,(t=>{var e=s(t),n=u(t);null!=e&&null!=n&&(e=+e)===e&&(n=+n)===n&&o.push([e,n])})),i=i.concat({type:_E,geometry:{type:"MultiPoint",coordinates:o}})),this.value={type:xE,features:i}}}),wE.Definition={type:"GeoPath",metadata:{modifies:!0},params:[{name:"projection",type:"projection"},{name:"field",type:"field"},{name:"pointRadius",type:"number",expr:!0},{name:"as",type:"string",default:"path"}]},ht(wE,Xa,{transform(t,e){var n=e.fork(e.ALL),r=this.value,i=t.field||f,o=t.as||"path",a=n.SOURCE;!r||t.modified()?(this.value=r=KM(t.projection),n.materialize().reflow()):a=i===f||e.modified(i.fields)?n.ADD_MOD:n.ADD;const s=function(t,e){const n=t.pointRadius();t.context(null),null!=e&&t.pointRadius(e);return n}(r,t.pointRadius);return n.visit(a,(t=>t[o]=r(i(t)))),r.pointRadius(s),n.modifies(o)}}),kE.Definition={type:"GeoPoint",metadata:{modifies:!0},params:[{name:"projection",type:"projection",required:!0},{name:"fields",type:"field",array:!0,required:!0,length:2},{name:"as",type:"string",array:!0,length:2,default:["x","y"]}]},ht(kE,Xa,{transform(t,e){var n,r=t.projection,i=t.fields[0],o=t.fields[1],a=t.as||["x","y"],s=a[0],u=a[1];function l(t){const e=r([i(t),o(t)]);e?(t[s]=e[0],t[u]=e[1]):(t[s]=void 0,t[u]=void 0)}return t.modified()?e=e.materialize().reflow(!0).visit(e.SOURCE,l):(n=e.modified(i.fields)||e.modified(o.fields),e.visit(n?e.ADD_MOD:e.ADD,l)),e.modifies(a)}}),AE.Definition={type:"GeoShape",metadata:{modifies:!0,nomod:!0},params:[{name:"projection",type:"projection"},{name:"field",type:"field",default:"datum"},{name:"pointRadius",type:"number",expr:!0},{name:"as",type:"string",default:"shape"}]},ht(AE,Xa,{transform(t,e){var n=e.fork(e.ALL),r=this.value,i=t.as||"shape",o=n.ADD;return r&&!t.modified()||(this.value=r=function(t,e,n){const r=null==n?n=>t(e(n)):r=>{var i=t.pointRadius(),o=t.pointRadius(n)(e(r));return t.pointRadius(i),o};return r.context=e=>(t.context(e),r),r}(KM(t.projection),t.field||l("datum"),t.pointRadius),n.materialize().reflow(),o=n.SOURCE),n.visit(o,(t=>t[i]=r)),n.modifies(i)}}),ME.Definition={type:"Graticule",metadata:{changes:!0,generates:!0},params:[{name:"extent",type:"array",array:!0,length:2,content:{type:"number",array:!0,length:2}},{name:"extentMajor",type:"array",array:!0,length:2,content:{type:"number",array:!0,length:2}},{name:"extentMinor",type:"array",array:!0,length:2,content:{type:"number",array:!0,length:2}},{name:"step",type:"number",array:!0,length:2},{name:"stepMajor",type:"number",array:!0,length:2,default:[90,360]},{name:"stepMinor",type:"number",array:!0,length:2,default:[10,10]},{name:"precision",type:"number",default:2.5}]},ht(ME,Xa,{transform(t,e){var n,r=this.value,i=this.generator;if(!r.length||t.modified())for(const e in t)J(i[e])&&i[e](t[e]);return n=i(),r.length?e.mod.push(ba(r[0],n)):e.add.push(va(n)),r[0]=n,e}}),EE.Definition={type:"heatmap",metadata:{modifies:!0},params:[{name:"field",type:"field"},{name:"color",type:"string",expr:!0},{name:"opacity",type:"number",expr:!0},{name:"resolve",type:"enum",values:["shared","independent"],default:"independent"},{name:"as",type:"string",default:"image"}]},ht(EE,Xa,{transform(t,e){if(!e.changed()&&!t.modified())return e.StopPropagation;var n=e.materialize(e.SOURCE).source,r="shared"===t.resolve,i=t.field||f,o=function(t,e){let n;J(t)?(n=n=>t(n,e),n.dep=DE(t)):t?n=rt(t):(n=t=>t.$value/t.$max||0,n.dep=!0);return n}(t.opacity,t),a=function(t,e){let n;J(t)?(n=n=>of(t(n,e)),n.dep=DE(t)):n=rt(of(t||"#888"));return n}(t.color,t),s=t.as||"image",u={$x:0,$y:0,$value:0,$max:r?be(n.map((t=>be(i(t).values)))):0};return n.forEach((t=>{const e=i(t),n=ot({},t,u);r||(n.$max=be(e.values||[])),t[s]=function(t,e,n,r){const i=t.width,o=t.height,a=t.x1||0,s=t.y1||0,u=t.x2||i,l=t.y2||o,c=t.values,f=c?t=>c[t]:h,d=Sc(u-a,l-s),p=d.getContext("2d"),g=p.getImageData(0,0,u-a,l-s),m=g.data;for(let t=s,o=0;t{null!=t[e]&&FE(n,e,t[e])}))):ZM.forEach((e=>{t.modified(e)&&FE(n,e,t[e])})),null!=t.pointRadius&&n.path.pointRadius(t.pointRadius),t.fit&&function(t,e){const n=function(t){return t=V(t),1===t.length?t[0]:{type:xE,features:t.reduce(((t,e)=>t.concat(function(t){return t.type===xE?t.features:V(t).filter((t=>null!=t)).map((t=>t.type===_E?t:{type:_E,geometry:t}))}(e))),[])}}(e.fit);e.extent?t.fitExtent(e.extent,n):e.size&&t.fitSize(e.size,n)}(n,t),e.fork(e.NO_SOURCE|e.NO_FIELDS)}});var SE=Object.freeze({__proto__:null,contour:vE,geojson:bE,geopath:wE,geopoint:kE,geoshape:AE,graticule:ME,heatmap:EE,isocontour:uE,kde2d:gE,projection:CE});function $E(t,e,n,r){if(isNaN(e)||isNaN(n))return t;var i,o,a,s,u,l,c,f,h,d=t._root,p={data:r},g=t._x0,m=t._y0,y=t._x1,v=t._y1;if(!d)return t._root=p,t;for(;d.length;)if((l=e>=(o=(g+y)/2))?g=o:y=o,(c=n>=(a=(m+v)/2))?m=a:v=a,i=d,!(d=d[f=c<<1|l]))return i[f]=p,t;if(s=+t._x.call(null,d.data),u=+t._y.call(null,d.data),e===s&&n===u)return p.next=d,i?i[f]=p:t._root=p,t;do{i=i?i[f]=new Array(4):t._root=new Array(4),(l=e>=(o=(g+y)/2))?g=o:y=o,(c=n>=(a=(m+v)/2))?m=a:v=a}while((f=c<<1|l)==(h=(u>=a)<<1|s>=o));return i[h]=d,i[f]=p,t}function TE(t,e,n,r,i){this.node=t,this.x0=e,this.y0=n,this.x1=r,this.y1=i}function BE(t){return t[0]}function zE(t){return t[1]}function NE(t,e,n){var r=new OE(null==e?BE:e,null==n?zE:n,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function OE(t,e,n,r,i,o){this._x=t,this._y=e,this._x0=n,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function RE(t){for(var e={data:t.data},n=e;t=t.next;)n=n.next={data:t.data};return e}var LE=NE.prototype=OE.prototype;function UE(t){return function(){return t}}function qE(t){return 1e-6*(t()-.5)}function PE(t){return t.x+t.vx}function jE(t){return t.y+t.vy}function IE(t){return t.index}function WE(t,e){var n=t.get(e);if(!n)throw new Error("node not found: "+e);return n}LE.copy=function(){var t,e,n=new OE(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return n;if(!r.length)return n._root=RE(r),n;for(t=[{source:r,target:n._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(e=r.source[i])&&(e.length?t.push({source:e,target:r.target[i]=new Array(4)}):r.target[i]=RE(e));return n},LE.add=function(t){const e=+this._x.call(null,t),n=+this._y.call(null,t);return $E(this.cover(e,n),e,n,t)},LE.addAll=function(t){var e,n,r,i,o=t.length,a=new Array(o),s=new Array(o),u=1/0,l=1/0,c=-1/0,f=-1/0;for(n=0;nc&&(c=r),if&&(f=i));if(u>c||l>f)return this;for(this.cover(u,l).cover(c,f),n=0;nt||t>=i||r>e||e>=o;)switch(s=(eh||(o=u.y0)>d||(a=u.x1)=y)<<1|t>=m)&&(u=p[p.length-1],p[p.length-1]=p[p.length-1-l],p[p.length-1-l]=u)}else{var v=t-+this._x.call(null,g.data),_=e-+this._y.call(null,g.data),x=v*v+_*_;if(x=(s=(p+m)/2))?p=s:m=s,(c=a>=(u=(g+y)/2))?g=u:y=u,e=d,!(d=d[f=c<<1|l]))return this;if(!d.length)break;(e[f+1&3]||e[f+2&3]||e[f+3&3])&&(n=e,h=f)}for(;d.data!==t;)if(r=d,!(d=d.next))return this;return(i=d.next)&&delete d.next,r?(i?r.next=i:delete r.next,this):e?(i?e[f]=i:delete e[f],(d=e[0]||e[1]||e[2]||e[3])&&d===(e[3]||e[2]||e[1]||e[0])&&!d.length&&(n?n[h]=d:this._root=d),this):(this._root=i,this)},LE.removeAll=function(t){for(var e=0,n=t.length;e{}};function YE(){for(var t,e=0,n=arguments.length,r={};e=0&&(e=t.slice(n+1),t=t.slice(0,n)),t&&!r.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}}))),a=-1,s=o.length;if(!(arguments.length<2)){if(null!=e&&"function"!=typeof e)throw new Error("invalid callback: "+e);for(;++a0)for(var n,r,i=new Array(n),o=0;o=0&&e._call.call(void 0,t),e=e._next;--QE}()}finally{QE=0,function(){var t,e,n=JE,r=1/0;for(;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:JE=e);ZE=t,dD(r)}(),rD=0}}function hD(){var t=oD.now(),e=t-nD;e>eD&&(iD-=e,nD=t)}function dD(t){QE||(KE&&(KE=clearTimeout(KE)),t-rD>24?(t<1/0&&(KE=setTimeout(fD,t-oD.now()-iD)),tD&&(tD=clearInterval(tD))):(tD||(nD=oD.now(),tD=setInterval(hD,eD)),QE=1,aD(fD)))}lD.prototype=cD.prototype={constructor:lD,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?sD():+n)+(null==e?0:+e),this._next||ZE===this||(ZE?ZE._next=this:JE=this,ZE=this),this._call=t,this._time=n,dD()},stop:function(){this._call&&(this._call=null,this._time=1/0,dD())}};const pD=1664525,gD=1013904223,mD=4294967296;function yD(t){return t.x}function vD(t){return t.y}var _D=10,xD=Math.PI*(3-Math.sqrt(5));function bD(t){var e,n=1,r=.001,i=1-Math.pow(r,1/300),o=0,a=.6,s=new Map,u=cD(f),l=YE("tick","end"),c=function(){let t=1;return()=>(t=(pD*t+gD)%mD)/mD}();function f(){h(),l.call("tick",e),n1?(null==n?s.delete(t):s.set(t,p(n)),e):s.get(t)},find:function(e,n,r){var i,o,a,s,u,l=0,c=t.length;for(null==r?r=1/0:r*=r,l=0;l1?(l.on(t,n),e):l.on(t)}}}const wD={center:function(t,e){var n,r=1;function i(){var i,o,a=n.length,s=0,u=0;for(i=0;il+p||oc+p||au.index){var g=l-s.x-s.vx,m=c-s.y-s.vy,y=g*g+m*m;yt.r&&(t.r=t[e].r)}function u(){if(e){var r,i,o=e.length;for(n=new Array(o),r=0;r=s)){(t.data!==e||t.next)&&(0===f&&(p+=(f=qE(n))*f),0===h&&(p+=(h=qE(n))*h),p[s(t,e,r),t])));for(a=0,i=new Array(l);ae(t,n):e)}DD.Definition={type:"Force",metadata:{modifies:!0},params:[{name:"static",type:"boolean",default:!1},{name:"restart",type:"boolean",default:!1},{name:"iterations",type:"number",default:300},{name:"alpha",type:"number",default:1},{name:"alphaMin",type:"number",default:.001},{name:"alphaTarget",type:"number",default:0},{name:"velocityDecay",type:"number",default:.4},{name:"forces",type:"param",array:!0,params:[{key:{force:"center"},params:[{name:"x",type:"number",default:0},{name:"y",type:"number",default:0}]},{key:{force:"collide"},params:[{name:"radius",type:"number",expr:!0},{name:"strength",type:"number",default:.7},{name:"iterations",type:"number",default:1}]},{key:{force:"nbody"},params:[{name:"strength",type:"number",default:-30,expr:!0},{name:"theta",type:"number",default:.9},{name:"distanceMin",type:"number",default:1},{name:"distanceMax",type:"number"}]},{key:{force:"link"},params:[{name:"links",type:"data"},{name:"id",type:"field"},{name:"distance",type:"number",default:30,expr:!0},{name:"strength",type:"number",expr:!0},{name:"iterations",type:"number",default:1}]},{key:{force:"x"},params:[{name:"strength",type:"number",default:.1},{name:"x",type:"field"}]},{key:{force:"y"},params:[{name:"strength",type:"number",default:.1},{name:"y",type:"field"}]}]},{name:"as",type:"string",array:!0,modify:!1,default:ED}]},ht(DD,Xa,{transform(t,e){var n,r,i=this.value,o=e.changed(e.ADD_REM),a=t.modified(AD),s=t.iterations||300;if(i?(o&&(e.modifies("index"),i.nodes(e.source)),(a||e.changed(e.MOD))&&CD(i,t,0,e)):(this.value=i=function(t,e){const n=bD(t),r=n.stop,i=n.restart;let o=!1;return n.stopped=()=>o,n.restart=()=>(o=!1,i()),n.stop=()=>(o=!0,r()),CD(n,e,!0).on("end",(()=>o=!0))}(e.source,t),i.on("tick",(n=e.dataflow,r=this,()=>n.touch(r).run())),t.static||(o=!0,i.tick()),e.modifies("index")),a||o||t.modified(MD)||e.changed()&&t.restart)if(i.alpha(Math.max(i.alpha(),t.alpha||1)).alphaDecay(1-Math.pow(i.alphaMin(),1/s)),t.static)for(i.stop();--s>=0;)i.tick();else if(i.stopped()&&i.restart(),!o)return e.StopPropagation;return this.finish(t,e)},finish(t,e){const n=e.dataflow;for(let t,e=this._argops,s=0,u=e.length;s=0;)e+=n[r].value;else e=1;t.value=e}function RD(t,e){t instanceof Map?(t=[void 0,t],void 0===e&&(e=UD)):void 0===e&&(e=LD);for(var n,r,i,o,a,s=new jD(t),u=[s];n=u.pop();)if((i=e(n.data))&&(a=(i=Array.from(i)).length))for(n.children=i,o=a-1;o>=0;--o)u.push(r=i[o]=new jD(i[o])),r.parent=n,r.depth=n.depth+1;return s.eachBefore(PD)}function LD(t){return t.children}function UD(t){return Array.isArray(t)?t[1]:null}function qD(t){void 0!==t.data.value&&(t.value=t.data.value),t.data=t.data.data}function PD(t){var e=0;do{t.height=e}while((t=t.parent)&&t.height<++e)}function jD(t){this.data=t,this.depth=this.height=0,this.parent=null}function ID(t){return null==t?null:WD(t)}function WD(t){if("function"!=typeof t)throw new Error;return t}function HD(){return 0}function YD(t){return function(){return t}}jD.prototype=RD.prototype={constructor:jD,count:function(){return this.eachAfter(OD)},each:function(t,e){let n=-1;for(const r of this)t.call(e,r,++n,this);return this},eachAfter:function(t,e){for(var n,r,i,o=this,a=[o],s=[],u=-1;o=a.pop();)if(s.push(o),n=o.children)for(r=0,i=n.length;r=0;--r)o.push(n[r]);return this},find:function(t,e){let n=-1;for(const r of this)if(t.call(e,r,++n,this))return r},sum:function(t){return this.eachAfter((function(e){for(var n=+t(e.data)||0,r=e.children,i=r&&r.length;--i>=0;)n+=r[i].value;e.value=n}))},sort:function(t){return this.eachBefore((function(e){e.children&&e.children.sort(t)}))},path:function(t){for(var e=this,n=function(t,e){if(t===e)return t;var n=t.ancestors(),r=e.ancestors(),i=null;t=n.pop(),e=r.pop();for(;t===e;)i=t,t=n.pop(),e=r.pop();return i}(e,t),r=[e];e!==n;)e=e.parent,r.push(e);for(var i=r.length;t!==n;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,e=[t];t=t.parent;)e.push(t);return e},descendants:function(){return Array.from(this)},leaves:function(){var t=[];return this.eachBefore((function(e){e.children||t.push(e)})),t},links:function(){var t=this,e=[];return t.each((function(n){n!==t&&e.push({source:n.parent,target:n})})),e},copy:function(){return RD(this).eachBefore(qD)},[Symbol.iterator]:function*(){var t,e,n,r,i=this,o=[i];do{for(t=o.reverse(),o=[];i=t.pop();)if(yield i,e=i.children)for(n=0,r=e.length;n0&&n*n>r*r+i*i}function KD(t,e){for(var n=0;n1e-6?(D+Math.sqrt(D*D-4*E*C))/(2*E):C/D);return{x:r+w+k*F,y:i+A+M*F,r:F}}function rC(t,e,n){var r,i,o,a,s=t.x-e.x,u=t.y-e.y,l=s*s+u*u;l?(i=e.r+n.r,i*=i,a=t.r+n.r,i>(a*=a)?(r=(l+a-i)/(2*l),o=Math.sqrt(Math.max(0,a/l-r*r)),n.x=t.x-r*s-o*u,n.y=t.y-r*u+o*s):(r=(l+i-a)/(2*l),o=Math.sqrt(Math.max(0,i/l-r*r)),n.x=e.x+r*s-o*u,n.y=e.y+r*u+o*s)):(n.x=e.x+n.r,n.y=e.y)}function iC(t,e){var n=t.r+e.r-1e-6,r=e.x-t.x,i=e.y-t.y;return n>0&&n*n>r*r+i*i}function oC(t){var e=t._,n=t.next._,r=e.r+n.r,i=(e.x*n.r+n.x*e.r)/r,o=(e.y*n.r+n.y*e.r)/r;return i*i+o*o}function aC(t){this._=t,this.next=null,this.previous=null}function sC(t,e){if(!(o=(t=function(t){return"object"==typeof t&&"length"in t?t:Array.from(t)}(t)).length))return 0;var n,r,i,o,a,s,u,l,c,f,h;if((n=t[0]).x=0,n.y=0,!(o>1))return n.r;if(r=t[1],n.x=-r.r,r.x=n.r,r.y=0,!(o>2))return n.r+r.r;rC(r,n,i=t[2]),n=new aC(n),r=new aC(r),i=new aC(i),n.next=i.previous=r,r.next=n.previous=i,i.next=r.previous=n;t:for(u=3;ufunction(t){t=`${t}`;let e=t.length;bC(t,e-1)&&!bC(t,e-2)&&(t=t.slice(0,-1));return"/"===t[0]?t:`/${t}`}(t(e,n,r)))),n=e.map(xC),i=new Set(e).add("");for(const t of n)i.has(t)||(i.add(t),e.push(t),n.push(xC(t)),h.push(mC));d=(t,n)=>e[n],p=(t,e)=>n[e]}for(a=0,i=h.length;a=0&&(l=h[t]).data===mC;--t)l.data=null}if(s.parent=pC,s.eachBefore((function(t){t.depth=t.parent.depth+1,--i})).eachBefore(PD),s.parent=null,i>0)throw new Error("cycle");return s}return r.id=function(t){return arguments.length?(e=ID(t),r):e},r.parentId=function(t){return arguments.length?(n=ID(t),r):n},r.path=function(e){return arguments.length?(t=ID(e),r):t},r}function xC(t){let e=t.length;if(e<2)return"";for(;--e>1&&!bC(t,e););return t.slice(0,e)}function bC(t,e){if("/"===t[e]){let n=0;for(;e>0&&"\\"===t[--e];)++n;if(0==(1&n))return!0}return!1}function wC(t,e){return t.parent===e.parent?1:2}function kC(t){var e=t.children;return e?e[0]:t.t}function AC(t){var e=t.children;return e?e[e.length-1]:t.t}function MC(t,e,n){var r=n/(e.i-t.i);e.c-=r,e.s+=n,t.c+=r,e.z+=n,e.m+=n}function EC(t,e,n){return t.a.parent===e.parent?t.a:n}function DC(t,e){this._=t,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=e}function CC(t,e,n,r,i){for(var o,a=t.children,s=-1,u=a.length,l=t.value&&(i-n)/t.value;++sh&&(h=s),m=c*c*g,(d=Math.max(h/m,m/f))>p){c-=s;break}p=d}y.push(a={value:c,dice:u1?e:1)},n}(FC);var TC=function t(e){function n(t,n,r,i,o){if((a=t._squarify)&&a.ratio===e)for(var a,s,u,l,c,f=-1,h=a.length,d=t.value;++f1?e:1)},n}(FC);function BC(t,e,n){const r={};return t.each((t=>{const i=t.data;n(i)&&(r[e(i)]=t)})),t.lookup=r,t}function zC(t){Xa.call(this,null,t)}zC.Definition={type:"Nest",metadata:{treesource:!0,changes:!0},params:[{name:"keys",type:"field",array:!0},{name:"generate",type:"boolean"}]};const NC=t=>t.values;function OC(){const t=[],e={entries:t=>r(n(t,0),0),key:n=>(t.push(n),e)};function n(e,r){if(r>=t.length)return e;const i=e.length,o=t[r++],a={},s={};let u,l,c,f=-1;for(;++ft.length)return e;const i=[];for(const t in e)i.push({key:t,values:r(e[t],n)});return i}return e}function RC(t){Xa.call(this,null,t)}ht(zC,Xa,{transform(t,e){e.source||s("Nest transform requires an upstream data source.");var n=t.generate,r=t.modified(),i=e.clone(),o=this.value;return(!o||r||e.changed())&&(o&&o.each((t=>{t.children&&ga(t.data)&&i.rem.push(t.data)})),this.value=o=RD({values:V(t.keys).reduce(((t,e)=>(t.key(e),t)),OC()).entries(i.source)},NC),n&&o.each((t=>{t.children&&(t=va(t.data),i.add.push(t),i.source.push(t))})),BC(o,ma,ma)),i.source.root=o,i}});const LC=(t,e)=>t.parent===e.parent?1:2;ht(RC,Xa,{transform(t,e){e.source&&e.source.root||s(this.constructor.name+" transform requires a backing tree data source.");const n=this.layout(t.method),r=this.fields,i=e.source.root,o=t.as||r;t.field?i.sum(t.field):i.count(),t.sort&&i.sort(wa(t.sort,(t=>t.data))),function(t,e,n){for(let r,i=0,o=e.length;ifunction(t,e,n){const r=t.data,i=e.length-1;for(let o=0;o(t=(GD*t+VD)%XD)/XD}();return i.x=e/2,i.y=n/2,t?i.eachBefore(lC(t)).eachAfter(cC(r,.5,o)).eachBefore(fC(1)):i.eachBefore(lC(uC)).eachAfter(cC(HD,1,o)).eachAfter(cC(r,i.r/Math.min(e,n),o)).eachBefore(fC(Math.min(e,n)/(2*i.r))),i}return i.radius=function(e){return arguments.length?(t=ID(e),i):t},i.size=function(t){return arguments.length?(e=+t[0],n=+t[1],i):[e,n]},i.padding=function(t){return arguments.length?(r="function"==typeof t?t:YD(+t),i):r},i},params:["radius","size","padding"],fields:UC});const PC=["x0","y0","x1","y1","depth","children"];function jC(t){RC.call(this,t)}function IC(t){Xa.call(this,null,t)}jC.Definition={type:"Partition",metadata:{tree:!0,modifies:!0},params:[{name:"field",type:"field"},{name:"sort",type:"compare"},{name:"padding",type:"number",default:0},{name:"round",type:"boolean",default:!1},{name:"size",type:"number",array:!0,length:2},{name:"as",type:"string",array:!0,length:PC.length,default:PC}]},ht(jC,RC,{layout:function(){var t=1,e=1,n=0,r=!1;function i(i){var o=i.height+1;return i.x0=i.y0=n,i.x1=t,i.y1=e/o,i.eachBefore(function(t,e){return function(r){r.children&&dC(r,r.x0,t*(r.depth+1)/e,r.x1,t*(r.depth+2)/e);var i=r.x0,o=r.y0,a=r.x1-n,s=r.y1-n;a=0;--i)s.push(n=e.children[i]=new DC(r[i],i)),n.parent=e;return(a.parent=new DC(null,0)).children=[a],a}(i);if(u.eachAfter(o),u.parent.m=-u.z,u.eachBefore(a),r)i.eachBefore(s);else{var l=i,c=i,f=i;i.eachBefore((function(t){t.xc.x&&(c=t),t.depth>f.depth&&(f=t)}));var h=l===c?1:t(l,c)/2,d=h-l.x,p=e/(c.x+h+d),g=n/(f.depth||1);i.eachBefore((function(t){t.x=(t.x+d)*p,t.y=t.depth*g}))}return i}function o(e){var n=e.children,r=e.parent.children,i=e.i?r[e.i-1]:null;if(n){!function(t){for(var e,n=0,r=0,i=t.children,o=i.length;--o>=0;)(e=i[o]).z+=n,e.m+=n,n+=e.s+(r+=e.c)}(e);var o=(n[0].z+n[n.length-1].z)/2;i?(e.z=i.z+t(e._,i._),e.m=e.z-o):e.z=o}else i&&(e.z=i.z+t(e._,i._));e.parent.A=function(e,n,r){if(n){for(var i,o=e,a=e,s=n,u=o.parent.children[0],l=o.m,c=a.m,f=s.m,h=u.m;s=AC(s),o=kC(o),s&&o;)u=kC(u),(a=AC(a)).a=e,(i=s.z+f-o.z-l+t(s._,o._))>0&&(MC(EC(s,e,r),e,i),l+=i,c+=i),f+=s.m,l+=o.m,h+=u.m,c+=a.m;s&&!AC(a)&&(a.t=s,a.m+=f-c),o&&!kC(u)&&(u.t=o,u.m+=l-h,r=e)}return r}(e,i,e.parent.A||r[0])}function a(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function s(t){t.x*=e,t.y=t.depth*n}return i.separation=function(e){return arguments.length?(t=e,i):t},i.size=function(t){return arguments.length?(r=!1,e=+t[0],n=+t[1],i):r?null:[e,n]},i.nodeSize=function(t){return arguments.length?(r=!0,e=+t[0],n=+t[1],i):r?[e,n]:null},i},cluster:function(){var t=BD,e=1,n=1,r=!1;function i(i){var o,a=0;i.eachAfter((function(e){var n=e.children;n?(e.x=function(t){return t.reduce(zD,0)/t.length}(n),e.y=function(t){return 1+t.reduce(ND,0)}(n)):(e.x=o?a+=t(e,o):0,e.y=0,o=e)}));var s=function(t){for(var e;e=t.children;)t=e[0];return t}(i),u=function(t){for(var e;e=t.children;)t=e[e.length-1];return t}(i),l=s.x-t(s,u)/2,c=u.x+t(u,s)/2;return i.eachAfter(r?function(t){t.x=(t.x-i.x)*e,t.y=(i.y-t.y)*n}:function(t){t.x=(t.x-l)/(c-l)*e,t.y=(1-(i.y?t.y/i.y:1))*n})}return i.separation=function(e){return arguments.length?(t=e,i):t},i.size=function(t){return arguments.length?(r=!1,e=+t[0],n=+t[1],i):r?null:[e,n]},i.nodeSize=function(t){return arguments.length?(r=!0,e=+t[0],n=+t[1],i):r?[e,n]:null},i}},HC=["x","y","depth","children"];function YC(t){RC.call(this,t)}function GC(t){Xa.call(this,[],t)}YC.Definition={type:"Tree",metadata:{tree:!0,modifies:!0},params:[{name:"field",type:"field"},{name:"sort",type:"compare"},{name:"method",type:"enum",default:"tidy",values:["tidy","cluster"]},{name:"size",type:"number",array:!0,length:2},{name:"nodeSize",type:"number",array:!0,length:2},{name:"separation",type:"boolean",default:!0},{name:"as",type:"string",array:!0,length:HC.length,default:HC}]},ht(YC,RC,{layout(t){const e=t||"tidy";if(ut(WC,e))return WC[e]();s("Unrecognized Tree layout method: "+e)},params:["size","nodeSize"],fields:HC}),GC.Definition={type:"TreeLinks",metadata:{tree:!0,generates:!0,changes:!0},params:[]},ht(GC,Xa,{transform(t,e){const n=this.value,r=e.source&&e.source.root,i=e.fork(e.NO_SOURCE),o={};return r||s("TreeLinks transform requires a tree data source."),e.changed(e.ADD_REM)?(i.rem=n,e.visit(e.SOURCE,(t=>o[ma(t)]=1)),r.each((t=>{const e=t.data,n=t.parent&&t.parent.data;n&&o[ma(e)]&&o[ma(n)]&&i.add.push(va({source:n,target:e}))})),this.value=i.add):e.changed(e.MOD)&&(e.visit(e.MOD,(t=>o[ma(t)]=1)),n.forEach((t=>{(o[ma(t.source)]||o[ma(t.target)])&&i.mod.push(t)}))),i}});const VC={binary:function(t,e,n,r,i){var o,a,s=t.children,u=s.length,l=new Array(u+1);for(l[0]=a=o=0;o=n-1){var c=s[e];return c.x0=i,c.y0=o,c.x1=a,void(c.y1=u)}var f=l[e],h=r/2+f,d=e+1,p=n-1;for(;d>>1;l[g]u-o){var v=r?(i*y+a*m)/r:a;t(e,d,m,i,o,v,u),t(d,n,y,v,o,a,u)}else{var _=r?(o*y+u*m)/r:u;t(e,d,m,i,o,a,_),t(d,n,y,i,_,a,u)}}(0,u,t.value,e,n,r,i)},dice:dC,slice:CC,slicedice:function(t,e,n,r,i){(1&t.depth?CC:dC)(t,e,n,r,i)},squarify:$C,resquarify:TC},XC=["x0","y0","x1","y1","depth","children"];function JC(t){RC.call(this,t)}JC.Definition={type:"Treemap",metadata:{tree:!0,modifies:!0},params:[{name:"field",type:"field"},{name:"sort",type:"compare"},{name:"method",type:"enum",default:"squarify",values:["squarify","resquarify","binary","dice","slice","slicedice"]},{name:"padding",type:"number",default:0},{name:"paddingInner",type:"number",default:0},{name:"paddingOuter",type:"number",default:0},{name:"paddingTop",type:"number",default:0},{name:"paddingRight",type:"number",default:0},{name:"paddingBottom",type:"number",default:0},{name:"paddingLeft",type:"number",default:0},{name:"ratio",type:"number",default:1.618033988749895},{name:"round",type:"boolean",default:!1},{name:"size",type:"number",array:!0,length:2},{name:"as",type:"string",array:!0,length:XC.length,default:XC}]},ht(JC,RC,{layout(){const t=function(){var t=$C,e=!1,n=1,r=1,i=[0],o=HD,a=HD,s=HD,u=HD,l=HD;function c(t){return t.x0=t.y0=0,t.x1=n,t.y1=r,t.eachBefore(f),i=[0],e&&t.eachBefore(hC),t}function f(e){var n=i[e.depth],r=e.x0+n,c=e.y0+n,f=e.x1-n,h=e.y1-n;f{const n=t.tile();n.ratio&&t.tile(n.ratio(e))},t.method=e=>{ut(VC,e)?t.tile(VC[e]):s("Unrecognized Treemap layout method: "+e)},t},params:["method","ratio","size","round","padding","paddingInner","paddingOuter","paddingTop","paddingRight","paddingBottom","paddingLeft"],fields:XC});var ZC=Object.freeze({__proto__:null,nest:zC,pack:qC,partition:jC,stratify:IC,tree:YC,treelinks:GC,treemap:JC});const QC=4278190080;function KC(t,e,n){return new Uint32Array(t.getImageData(0,0,e,n).data.buffer)}function tF(t,e,n){if(!e.length)return;const r=e[0].mark.marktype;"group"===r?e.forEach((e=>{e.items.forEach((e=>tF(t,e.items,n)))})):Hy[r].draw(t,{items:n?e.map(eF):e})}function eF(t){const e=xa(t,{});return e.stroke&&0!==e.strokeOpacity||e.fill&&0!==e.fillOpacity?{...e,strokeOpacity:1,stroke:"#000",fillOpacity:0}:e}const nF=5,rF=31,iF=32,oF=new Uint32Array(iF+1),aF=new Uint32Array(iF+1);aF[0]=0,oF[0]=~aF[0];for(let t=1;t<=iF;++t)aF[t]=aF[t-1]<<1|1,oF[t]=~aF[t];function sF(t,e,n){const r=Math.max(1,Math.sqrt(t*e/1e6)),i=~~((t+2*n+r)/r),o=~~((e+2*n+r)/r),a=t=>~~((t+n)/r);return a.invert=t=>t*r-n,a.bitmap=()=>function(t,e){const n=new Uint32Array(~~((t*e+iF)/iF));function r(t,e){n[t]|=e}function i(t,e){n[t]&=e}return{array:n,get:(e,r)=>{const i=r*t+e;return n[i>>>nF]&1<<(i&rF)},set:(e,n)=>{const i=n*t+e;r(i>>>nF,1<<(i&rF))},clear:(e,n)=>{const r=n*t+e;i(r>>>nF,~(1<<(r&rF)))},getRange:(e,r,i,o)=>{let a,s,u,l,c=o;for(;c>=r;--c)if(a=c*t+e,s=c*t+i,u=a>>>nF,l=s>>>nF,u===l){if(n[u]&oF[a&rF]&aF[1+(s&rF)])return!0}else{if(n[u]&oF[a&rF])return!0;if(n[l]&aF[1+(s&rF)])return!0;for(let t=u+1;t{let a,s,u,l,c;for(;n<=o;++n)if(a=n*t+e,s=n*t+i,u=a>>>nF,l=s>>>nF,u===l)r(u,oF[a&rF]&aF[1+(s&rF)]);else for(r(u,oF[a&rF]),r(l,aF[1+(s&rF)]),c=u+1;c{let a,s,u,l,c;for(;n<=o;++n)if(a=n*t+e,s=n*t+r,u=a>>>nF,l=s>>>nF,u===l)i(u,aF[a&rF]|oF[1+(s&rF)]);else for(i(u,aF[a&rF]),i(l,oF[1+(s&rF)]),c=u+1;cn<0||r<0||o>=e||i>=t}}(i,o),a.ratio=r,a.padding=n,a.width=t,a.height=e,a}function uF(t,e,n,r,i,o){let a=n/2;return t-a<0||t+a>i||e-(a=r/2)<0||e+a>o}function lF(t,e,n,r,i,o,a,s){const u=i*o/(2*r),l=t(e-u),c=t(e+u),f=t(n-(o/=2)),h=t(n+o);return a.outOfBounds(l,f,c,h)||a.getRange(l,f,c,h)||s&&s.getRange(l,f,c,h)}const cF=[-1,-1,1,1],fF=[-1,1,-1,1];const hF=["right","center","left"],dF=["bottom","middle","top"];function pF(t,e,n,r,i,o,a,s,u,l,c,f){return!(i.outOfBounds(t,n,e,r)||(f&&o||i).getRange(t,n,e,r))}const gF={"top-left":0,top:1,"top-right":2,left:4,middle:5,right:6,"bottom-left":8,bottom:9,"bottom-right":10},mF={naive:function(t,e,n,r){const i=t.width,o=t.height;return function(t){const e=t.datum.datum.items[r].items,n=e.length,a=t.datum.fontSize,s=My.width(t.datum,t.datum.text);let u,l,c,f,h,d,p,g=0;for(let r=0;r=g&&(g=p,t.x=h,t.y=d);return h=s/2,d=a/2,u=t.x-h,l=t.x+h,c=t.y-d,f=t.y+d,t.align="center",u<0&&l<=i?t.align="left":0<=u&&i=1;)h=(d+p)/2,lF(t,c,f,l,u,h,a,s)?p=h:d=h;if(d>r)return[c,f,d,!0]}}return function(e){const s=e.datum.datum.items[r].items,l=s.length,c=e.datum.fontSize,f=My.width(e.datum,e.datum.text);let h,d,p,g,m,y,v,_,x,b,w,k,A,M,E,D,C,F=n?c:0,S=!1,$=!1,T=0;for(let r=0;rd&&(C=h,h=d,d=C),p>g&&(C=p,p=g,g=C),x=t(h),w=t(d),b=~~((x+w)/2),k=t(p),M=t(g),A=~~((k+M)/2),v=b;v>=x;--v)for(_=A;_>=k;--_)D=u(v,_,F,f,c),D&&([e.x,e.y,F,S]=D);for(v=b;v<=w;++v)for(_=A;_<=M;++_)D=u(v,_,F,f,c),D&&([e.x,e.y,F,S]=D);S||n||(E=Math.abs(d-h+g-p),m=(h+d)/2,y=(p+g)/2,E>=T&&!uF(m,y,f,c,i,o)&&!lF(t,m,y,c,f,c,a,null)&&(T=E,e.x=m,e.y=y,$=!0))}return!(!S&&!$)&&(m=f/2,y=c/2,a.setRange(t(e.x-m),t(e.y-y),t(e.x+m),t(e.y+y)),e.align="center",e.baseline="middle",!0)}},floodfill:function(t,e,n,r){const i=t.width,o=t.height,a=e[0],s=e[1],u=t.bitmap();return function(e){const l=e.datum.datum.items[r].items,c=l.length,f=e.datum.fontSize,h=My.width(e.datum,e.datum.text),d=[];let p,g,m,y,v,_,x,b,w,k,A,M,E=n?f:0,D=!1,C=!1,F=0;for(let r=0;r=1;)A=(w+k)/2,lF(t,v,_,f,h,A,a,s)?k=A:w=A;w>E&&(e.x=v,e.y=_,E=w,D=!0)}}D||n||(M=Math.abs(g-p+y-m),v=(p+g)/2,_=(m+y)/2,M>=F&&!uF(v,_,h,f,i,o)&&!lF(t,v,_,f,h,f,a,null)&&(F=M,e.x=v,e.y=_,C=!0))}return!(!D&&!C)&&(v=h/2,_=f/2,a.setRange(t(e.x-v),t(e.y-_),t(e.x+v),t(e.y+_)),e.align="center",e.baseline="middle",!0)}}};function yF(t,e,n,r,i,o,a,s,u,l,c){if(!t.length)return t;const f=Math.max(r.length,i.length),h=function(t,e){const n=new Float64Array(e),r=t.length;for(let e=0;e[t.x,t.x,t.x,t.y,t.y,t.y];return t?"line"===t||"area"===t?t=>i(t.datum):"line"===e?t=>{const e=t.datum.items[r].items;return i(e.length?e["start"===n?0:e.length-1]:{x:NaN,y:NaN})}:t=>{const e=t.datum.bounds;return[e.x1,(e.x1+e.x2)/2,e.x2,e.y1,(e.y1+e.y2)/2,e.y2]}:i}(p,g,s,u),v=null===l||l===1/0,_=m&&"naive"===c;var x;let b=-1,w=-1;const k=t.map((t=>{const e=v?My.width(t,t.text):void 0;return b=Math.max(b,e),w=Math.max(w,t.fontSize),{datum:t,opacity:0,x:void 0,y:void 0,align:void 0,baseline:void 0,boundary:y(t),textWidth:e}}));l=null===l||l===1/0?Math.max(b,w)+Math.max(...r):l;const A=sF(e[0],e[1],l);let M;if(!_){n&&k.sort(((t,e)=>n(t.datum,e.datum)));let e=!1;for(let t=0;tt.datum));M=o.length||r?function(t,e,n,r,i){const o=t.width,a=t.height,s=r||i,u=Sc(o,a).getContext("2d"),l=Sc(o,a).getContext("2d"),c=s&&Sc(o,a).getContext("2d");n.forEach((t=>tF(u,t,!1))),tF(l,e,!1),s&&tF(c,e,!0);const f=KC(u,o,a),h=KC(l,o,a),d=s&&KC(c,o,a),p=t.bitmap(),g=s&&t.bitmap();let m,y,v,_,x,b,w,k;for(y=0;yn.set(t(e.boundary[0]),t(e.boundary[3])))),[n,void 0]}(A,a&&k)}const E=m?mF[c](A,M,a,u):function(t,e,n,r){const i=t.width,o=t.height,a=e[0],s=e[1],u=r.length;return function(e){const l=e.boundary,c=e.datum.fontSize;if(l[2]<0||l[5]<0||l[0]>i||l[3]>o)return!1;let f,h,d,p,g,m,y,v,_,x,b,w,k,A,M,E=e.textWidth??0;for(let i=0;i>>2&3)-1,d=0===f&&0===h||r[i]<0,p=f&&h?Math.SQRT1_2:1,g=r[i]<0?-1:1,m=l[1+f]+r[i]*f*p,b=l[4+h]+g*c*h/2+r[i]*h*p,v=b-c/2,_=b+c/2,w=t(m),A=t(v),M=t(_),!E){if(!pF(w,w,A,M,a,s,0,0,0,0,0,d))continue;E=My.width(e.datum,e.datum.text)}if(x=m+g*E*f/2,m=x-E/2,y=x+E/2,w=t(m),k=t(y),pF(w,k,A,M,a,s,0,0,0,0,0,d))return e.x=f?f*g<0?y:m:x,e.y=h?h*g<0?_:v:b,e.align=hF[f*g+1],e.baseline=dF[h*g+1],a.setRange(w,A,k,M),!0}return!1}}(A,M,d,h);return k.forEach((t=>t.opacity=+E(t))),k}const vF=["x","y","opacity","align","baseline"],_F=["top-left","left","bottom-left","top","bottom","top-right","right","bottom-right"];function xF(t){Xa.call(this,null,t)}xF.Definition={type:"Label",metadata:{modifies:!0},params:[{name:"size",type:"number",array:!0,length:2,required:!0},{name:"sort",type:"compare"},{name:"anchor",type:"string",array:!0,default:_F},{name:"offset",type:"number",array:!0,default:[1]},{name:"padding",type:"number",default:0,null:!0},{name:"lineAnchor",type:"string",values:["start","end"],default:"end"},{name:"markIndex",type:"number",default:0},{name:"avoidBaseMark",type:"boolean",default:!0},{name:"avoidMarks",type:"data",array:!0},{name:"method",type:"string",default:"naive"},{name:"as",type:"string",array:!0,length:vF.length,default:vF}]},ht(xF,Xa,{transform(t,e){const n=t.modified();if(!(n||e.changed(e.ADD_REM)||function(n){const r=t[n];return J(r)&&e.modified(r.fields)}("sort")))return;t.size&&2===t.size.length||s("Size parameter should be specified as a [width, height] array.");const r=t.as||vF;return yF(e.materialize(e.SOURCE).source||[],t.size,t.sort,V(null==t.offset?1:t.offset),V(t.anchor||_F),t.avoidMarks||[],!1!==t.avoidBaseMark,t.lineAnchor||"end",t.markIndex||0,void 0===t.padding?0:t.padding,t.method||"naive").forEach((t=>{const e=t.datum;e[r[0]]=t.x,e[r[1]]=t.y,e[r[2]]=t.opacity,e[r[3]]=t.align,e[r[4]]=t.baseline})),e.reflow(n).modifies(r)}});var bF=Object.freeze({__proto__:null,label:xF});function wF(t,e){var n,r,i,o,a,s,u=[],l=function(t){return t(o)};if(null==e)u.push(t);else for(n={},r=0,i=t.length;r{Ls(e,t.x,t.y,t.bandwidth||.3).forEach((t=>{const n={};for(let t=0;t"poly"===t?e:"quad"===t?2:1)(a,u),c=t.as||[n(t.x),n(t.y)],f=AF[a],h=[];let d=t.extent;ut(AF,a)||s("Invalid regression method: "+a),null!=d&&"log"===a&&d[0]<=0&&(e.dataflow.warn("Ignoring extent with values <= 0 for log regression."),d=null),i.forEach((n=>{if(n.length<=l)return void e.dataflow.warn("Skipping regression with more parameters than data points.");const r=f(n,t.x,t.y,u);if(t.params)return void h.push(va({keys:n.dims,coef:r.coef,rSquared:r.rSquared}));const i=d||at(n,t.x),s=t=>{const e={};for(let t=0;ts([t,r.predict(t)]))):js(r.predict,i,25,200).forEach(s)})),this.value&&(r.rem=this.value),this.value=r.add=r.source=h}return r}});var EF=Object.freeze({__proto__:null,loess:kF,regression:MF});const DF=134217729,CF=33306690738754706e-32;function FF(t,e,n,r,i){let o,a,s,u,l=e[0],c=r[0],f=0,h=0;c>l==c>-l?(o=l,l=e[++f]):(o=c,c=r[++h]);let d=0;if(fl==c>-l?(a=l+o,s=o-(a-l),l=e[++f]):(a=c+o,s=o-(a-c),c=r[++h]),o=a,0!==s&&(i[d++]=s);fl==c>-l?(a=o+l,u=a-o,s=o-(a-u)+(l-u),l=e[++f]):(a=o+c,u=a-o,s=o-(a-u)+(c-u),c=r[++h]),o=a,0!==s&&(i[d++]=s);for(;f0!=s>0)return u;const l=Math.abs(a+s);return Math.abs(u)>=33306690738754716e-32*l?u:-function(t,e,n,r,i,o,a){let s,u,l,c,f,h,d,p,g,m,y,v,_,x,b,w,k,A;const M=t-i,E=n-i,D=e-o,C=r-o;x=M*C,h=DF*M,d=h-(h-M),p=M-d,h=DF*C,g=h-(h-C),m=C-g,b=p*m-(x-d*g-p*g-d*m),w=D*E,h=DF*D,d=h-(h-D),p=D-d,h=DF*E,g=h-(h-E),m=E-g,k=p*m-(w-d*g-p*g-d*m),y=b-k,f=b-y,BF[0]=b-(y+f)+(f-k),v=x+y,f=v-x,_=x-(v-f)+(y-f),y=_-w,f=_-y,BF[1]=_-(y+f)+(f-w),A=v+y,f=A-v,BF[2]=v-(A-f)+(y-f),BF[3]=A;let F=function(t,e){let n=e[0];for(let r=1;r=S||-F>=S)return F;if(f=t-M,s=t-(M+f)+(f-i),f=n-E,l=n-(E+f)+(f-i),f=e-D,u=e-(D+f)+(f-o),f=r-C,c=r-(C+f)+(f-o),0===s&&0===u&&0===l&&0===c)return F;if(S=TF*a+CF*Math.abs(F),F+=M*c+C*s-(D*l+E*u),F>=S||-F>=S)return F;x=s*C,h=DF*s,d=h-(h-s),p=s-d,h=DF*C,g=h-(h-C),m=C-g,b=p*m-(x-d*g-p*g-d*m),w=u*E,h=DF*u,d=h-(h-u),p=u-d,h=DF*E,g=h-(h-E),m=E-g,k=p*m-(w-d*g-p*g-d*m),y=b-k,f=b-y,RF[0]=b-(y+f)+(f-k),v=x+y,f=v-x,_=x-(v-f)+(y-f),y=_-w,f=_-y,RF[1]=_-(y+f)+(f-w),A=v+y,f=A-v,RF[2]=v-(A-f)+(y-f),RF[3]=A;const $=FF(4,BF,4,RF,zF);x=M*c,h=DF*M,d=h-(h-M),p=M-d,h=DF*c,g=h-(h-c),m=c-g,b=p*m-(x-d*g-p*g-d*m),w=D*l,h=DF*D,d=h-(h-D),p=D-d,h=DF*l,g=h-(h-l),m=l-g,k=p*m-(w-d*g-p*g-d*m),y=b-k,f=b-y,RF[0]=b-(y+f)+(f-k),v=x+y,f=v-x,_=x-(v-f)+(y-f),y=_-w,f=_-y,RF[1]=_-(y+f)+(f-w),A=v+y,f=A-v,RF[2]=v-(A-f)+(y-f),RF[3]=A;const T=FF($,zF,4,RF,NF);x=s*c,h=DF*s,d=h-(h-s),p=s-d,h=DF*c,g=h-(h-c),m=c-g,b=p*m-(x-d*g-p*g-d*m),w=u*l,h=DF*u,d=h-(h-u),p=u-d,h=DF*l,g=h-(h-l),m=l-g,k=p*m-(w-d*g-p*g-d*m),y=b-k,f=b-y,RF[0]=b-(y+f)+(f-k),v=x+y,f=v-x,_=x-(v-f)+(y-f),y=_-w,f=_-y,RF[1]=_-(y+f)+(f-w),A=v+y,f=A-v,RF[2]=v-(A-f)+(y-f),RF[3]=A;const B=FF(T,NF,4,RF,OF);return OF[B-1]}(t,e,n,r,i,o,l)}const UF=Math.pow(2,-52),qF=new Uint32Array(512);class PF{static from(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:GF,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:VF;const r=t.length,i=new Float64Array(2*r);for(let o=0;o>1;if(e>0&&"number"!=typeof t[0])throw new Error("Expected coords to contain numbers.");this.coords=t;const n=Math.max(2*e-5,0);this._triangles=new Uint32Array(3*n),this._halfedges=new Int32Array(3*n),this._hashSize=Math.ceil(Math.sqrt(e)),this._hullPrev=new Uint32Array(e),this._hullNext=new Uint32Array(e),this._hullTri=new Uint32Array(e),this._hullHash=new Int32Array(this._hashSize).fill(-1),this._ids=new Uint32Array(e),this._dists=new Float64Array(e),this.update()}update(){const{coords:t,_hullPrev:e,_hullNext:n,_hullTri:r,_hullHash:i}=this,o=t.length>>1;let a=1/0,s=1/0,u=-1/0,l=-1/0;for(let e=0;eu&&(u=n),r>l&&(l=r),this._ids[e]=e}const c=(a+u)/2,f=(s+l)/2;let h,d,p,g=1/0;for(let e=0;e0&&(d=e,g=n)}let v=t[2*d],_=t[2*d+1],x=1/0;for(let e=0;er&&(e[n++]=i,r=this._dists[i])}return this.hull=e.subarray(0,n),this.triangles=new Uint32Array(0),void(this.halfedges=new Uint32Array(0))}if(LF(m,y,v,_,b,w)<0){const t=d,e=v,n=_;d=p,v=b,_=w,p=t,b=e,w=n}const k=function(t,e,n,r,i,o){const a=n-t,s=r-e,u=i-t,l=o-e,c=a*a+s*s,f=u*u+l*l,h=.5/(a*l-s*u),d=t+(l*c-s*f)*h,p=e+(a*f-u*c)*h;return{x:d,y:p}}(m,y,v,_,b,w);this._cx=k.x,this._cy=k.y;for(let e=0;e0&&Math.abs(l-o)<=UF&&Math.abs(c-a)<=UF)continue;if(o=l,a=c,u===h||u===d||u===p)continue;let f=0;for(let t=0,e=this._hashKey(l,c);t=0;)if(m=g,m===f){m=-1;break}if(-1===m)continue;let y=this._addTriangle(m,u,n[m],-1,-1,r[m]);r[u]=this._legalize(y+2),r[m]=y,A++;let v=n[m];for(;g=n[v],LF(l,c,t[2*v],t[2*v+1],t[2*g],t[2*g+1])<0;)y=this._addTriangle(v,u,g,r[u],-1,r[v]),r[u]=this._legalize(y+2),n[v]=v,A--,v=g;if(m===f)for(;g=e[m],LF(l,c,t[2*g],t[2*g+1],t[2*m],t[2*m+1])<0;)y=this._addTriangle(g,u,m,-1,r[m],r[g]),this._legalize(y+2),r[g]=y,n[m]=m,A--,m=g;this._hullStart=e[u]=m,n[m]=e[v]=u,n[u]=v,i[this._hashKey(l,c)]=u,i[this._hashKey(t[2*m],t[2*m+1])]=m}this.hull=new Uint32Array(A);for(let t=0,e=this._hullStart;t0?3-n:1+n)/4}(t-this._cx,e-this._cy)*this._hashSize)%this._hashSize}_legalize(t){const{_triangles:e,_halfedges:n,coords:r}=this;let i=0,o=0;for(;;){const a=n[t],s=t-t%3;if(o=s+(t+2)%3,-1===a){if(0===i)break;t=qF[--i];continue}const u=a-a%3,l=s+(t+1)%3,c=u+(a+2)%3,f=e[o],h=e[t],d=e[l],p=e[c];if(IF(r[2*f],r[2*f+1],r[2*h],r[2*h+1],r[2*d],r[2*d+1],r[2*p],r[2*p+1])){e[t]=p,e[a]=f;const r=n[c];if(-1===r){let e=this._hullStart;do{if(this._hullTri[e]===c){this._hullTri[e]=t;break}e=this._hullPrev[e]}while(e!==this._hullStart)}this._link(t,r),this._link(a,n[o]),this._link(o,c);const s=u+(a+1)%3;i=n&&e[t[a]]>o;)t[a+1]=t[a--];t[a+1]=r}else{let i=n+1,o=r;YF(t,n+r>>1,i),e[t[n]]>e[t[r]]&&YF(t,n,r),e[t[i]]>e[t[r]]&&YF(t,i,r),e[t[n]]>e[t[i]]&&YF(t,n,i);const a=t[i],s=e[a];for(;;){do{i++}while(e[t[i]]s);if(o=o-n?(HF(t,e,i,r),HF(t,e,n,o-1)):(HF(t,e,n,o-1),HF(t,e,i,r))}}function YF(t,e,n){const r=t[e];t[e]=t[n],t[n]=r}function GF(t){return t[0]}function VF(t){return t[1]}const XF=1e-6;class JF{constructor(){this._x0=this._y0=this._x1=this._y1=null,this._=""}moveTo(t,e){this._+=`M${this._x0=this._x1=+t},${this._y0=this._y1=+e}`}closePath(){null!==this._x1&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")}lineTo(t,e){this._+=`L${this._x1=+t},${this._y1=+e}`}arc(t,e,n){const r=(t=+t)+(n=+n),i=e=+e;if(n<0)throw new Error("negative radius");null===this._x1?this._+=`M${r},${i}`:(Math.abs(this._x1-r)>XF||Math.abs(this._y1-i)>XF)&&(this._+="L"+r+","+i),n&&(this._+=`A${n},${n},0,1,1,${t-n},${e}A${n},${n},0,1,1,${this._x1=r},${this._y1=i}`)}rect(t,e,n,r){this._+=`M${this._x0=this._x1=+t},${this._y0=this._y1=+e}h${+n}v${+r}h${-n}Z`}value(){return this._||null}}class ZF{constructor(){this._=[]}moveTo(t,e){this._.push([t,e])}closePath(){this._.push(this._[0].slice())}lineTo(t,e){this._.push([t,e])}value(){return this._.length?this._:null}}let QF=class{constructor(t){let[e,n,r,i]=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[0,0,960,500];if(!((r=+r)>=(e=+e)&&(i=+i)>=(n=+n)))throw new Error("invalid bounds");this.delaunay=t,this._circumcenters=new Float64Array(2*t.points.length),this.vectors=new Float64Array(2*t.points.length),this.xmax=r,this.xmin=e,this.ymax=i,this.ymin=n,this._init()}update(){return this.delaunay.update(),this._init(),this}_init(){const{delaunay:{points:t,hull:e,triangles:n},vectors:r}=this;let i,o;const a=this.circumcenters=this._circumcenters.subarray(0,n.length/3*2);for(let r,s,u=0,l=0,c=n.length;u1;)i-=2;for(let t=2;t0){if(e>=this.ymax)return null;(i=(this.ymax-e)/r)0){if(t>=this.xmax)return null;(i=(this.xmax-t)/n)this.xmax?2:0)|(ethis.ymax?8:0)}_simplify(t){if(t&&t.length>4){for(let e=0;e1&&void 0!==arguments[1]?arguments[1]:eS,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:nS,r=arguments.length>3?arguments[3]:void 0;return new iS("length"in t?function(t,e,n,r){const i=t.length,o=new Float64Array(2*i);for(let a=0;a2&&function(t){const{triangles:e,coords:n}=t;for(let t=0;t1e-10)return!1}return!0}(t)){this.collinear=Int32Array.from({length:e.length/2},((t,e)=>e)).sort(((t,n)=>e[2*t]-e[2*n]||e[2*t+1]-e[2*n+1]));const t=this.collinear[0],n=this.collinear[this.collinear.length-1],r=[e[2*t],e[2*t+1],e[2*n],e[2*n+1]],i=1e-8*Math.hypot(r[3]-r[1],r[2]-r[0]);for(let t=0,n=e.length/2;t0&&(this.triangles=new Int32Array(3).fill(-1),this.halfedges=new Int32Array(3).fill(-1),this.triangles[0]=r[0],o[r[0]]=1,2===r.length&&(o[r[1]]=0,this.triangles[1]=r[1],this.triangles[2]=r[1]))}voronoi(t){return new QF(this,t)}*neighbors(t){const{inedges:e,hull:n,_hullIndex:r,halfedges:i,triangles:o,collinear:a}=this;if(a){const e=a.indexOf(t);return e>0&&(yield a[e-1]),void(e2&&void 0!==arguments[2]?arguments[2]:0;if((t=+t)!=t||(e=+e)!=e)return-1;const r=n;let i;for(;(i=this._step(n,t,e))>=0&&i!==n&&i!==r;)n=i;return i}_step(t,e,n){const{inedges:r,hull:i,_hullIndex:o,halfedges:a,triangles:s,points:u}=this;if(-1===r[t]||!u.length)return(t+1)%(u.length>>1);let l=t,c=tS(e-u[2*t],2)+tS(n-u[2*t+1],2);const f=r[t];let h=f;do{let r=s[h];const f=tS(e-u[2*r],2)+tS(n-u[2*r+1],2);if(f=f));)if(e.x=a+i,e.y=l+o,!(e.x+e.x0<0||e.y+e.y0<0||e.x+e.x1>s[0]||e.y+e.y1>s[1])&&(!n||!pS(e,t,s[0]))&&(!n||mS(e,n))){for(var g,m=e.sprite,y=e.width>>5,v=s[0]>>5,_=e.x-(y<<4),x=127&_,b=32-x,w=e.y1-e.y0,k=(e.y+e.y0)*v+(_>>5),A=0;A>>x:0);k+=v}return e.sprite=null,!0}return!1}return f.layout=function(){for(var u=function(t){t.width=t.height=1;var e=Math.sqrt(t.getContext("2d").getImageData(0,0,1,1).data.length>>2);t.width=(cS<<5)/e,t.height=fS/e;var n=t.getContext("2d");return n.fillStyle=n.strokeStyle="red",n.textAlign="center",{context:n,ratio:e}}(Sc()),f=function(t){var e=[],n=-1;for(;++n>5)*s[1]),d=null,p=l.length,g=-1,m=[],y=l.map((s=>({text:t(s),font:e(s),style:r(s),weight:i(s),rotate:o(s),size:~~(n(s)+1e-14),padding:a(s),xoff:0,yoff:0,x1:0,y1:0,x0:0,y0:0,hasText:!1,sprite:null,datum:s}))).sort(((t,e)=>e.size-t.size));++g>1,v.y=s[1]*(c()+.5)>>1,dS(u,v,y,g),v.hasText&&h(f,v,d)&&(m.push(v),d?gS(d,v):d=[{x:v.x+v.x0,y:v.y+v.y0},{x:v.x+v.x1,y:v.y+v.y1}],v.x-=s[0]>>1,v.y-=s[1]>>1)}return m},f.words=function(t){return arguments.length?(l=t,f):l},f.size=function(t){return arguments.length?(s=[+t[0],+t[1]],f):s},f.font=function(t){return arguments.length?(e=vS(t),f):e},f.fontStyle=function(t){return arguments.length?(r=vS(t),f):r},f.fontWeight=function(t){return arguments.length?(i=vS(t),f):i},f.rotate=function(t){return arguments.length?(o=vS(t),f):o},f.text=function(e){return arguments.length?(t=vS(e),f):t},f.spiral=function(t){return arguments.length?(u=_S[t]||t,f):u},f.fontSize=function(t){return arguments.length?(n=vS(t),f):n},f.padding=function(t){return arguments.length?(a=vS(t),f):a},f.random=function(t){return arguments.length?(c=t,f):c},f}function dS(t,e,n,r){if(!e.sprite){var i=t.context,o=t.ratio;i.clearRect(0,0,(cS<<5)/o,fS/o);var a,s,u,l,c,f=0,h=0,d=0,p=n.length;for(--r;++r>5<<5,u=~~Math.max(Math.abs(v+_),Math.abs(v-_))}else a=a+31>>5<<5;if(u>d&&(d=u),f+a>=cS<<5&&(f=0,h+=d,d=0),h+u>=fS)break;i.translate((f+(a>>1))/o,(h+(u>>1))/o),e.rotate&&i.rotate(e.rotate*lS),i.fillText(e.text,0,0),e.padding&&(i.lineWidth=2*e.padding,i.strokeText(e.text,0,0)),i.restore(),e.width=a,e.height=u,e.xoff=f,e.yoff=h,e.x1=a>>1,e.y1=u>>1,e.x0=-e.x1,e.y0=-e.y1,e.hasText=!0,f+=a}for(var b=i.getImageData(0,0,(cS<<5)/o,fS/o).data,w=[];--r>=0;)if((e=n[r]).hasText){for(s=(a=e.width)>>5,u=e.y1-e.y0,l=0;l>5),E=b[(h+c)*(cS<<5)+(f+l)<<2]?1<<31-l%32:0;w[M]|=E,k|=E}k?A=c:(e.y0++,u--,c--,h++)}e.y1=e.y0+A,e.sprite=w.slice(0,(e.y1-e.y0)*s)}}}function pS(t,e,n){n>>=5;for(var r,i=t.sprite,o=t.width>>5,a=t.x-(o<<4),s=127&a,u=32-s,l=t.y1-t.y0,c=(t.y+t.y0)*n+(a>>5),f=0;f>>s:0))&e[c+h])return!0;c+=n}return!1}function gS(t,e){var n=t[0],r=t[1];e.x+e.x0r.x&&(r.x=e.x+e.x1),e.y+e.y1>r.y&&(r.y=e.y+e.y1)}function mS(t,e){return t.x+t.x1>e[0].x&&t.x+t.x0e[0].y&&t.y+t.y0e(t(n))}i.forEach((t=>{t[a[0]]=NaN,t[a[1]]=NaN,t[a[3]]=0}));const c=o.words(i).text(e.text).size(e.size||[500,500]).padding(e.padding||1).spiral(e.spiral||"archimedean").rotate(e.rotate||0).font(e.font||"sans-serif").fontStyle(e.fontStyle||"normal").fontWeight(e.fontWeight||"normal").fontSize(l).random(t.random).layout(),f=o.size(),h=f[0]>>1,d=f[1]>>1,p=c.length;for(let t,e,n=0;nnew Uint8Array(t),MS=t=>new Uint16Array(t),ES=t=>new Uint32Array(t);function DS(t,e,n){const r=(e<257?AS:e<65537?MS:ES)(t);return n&&r.set(n),r}function CS(t,e,n){const r=1<{const r=t[e],i=t[n];return ri?1:0})),function(t,e){return Array.from(e,(e=>t[e]))}(t,e)}(h,u),a)l=e,c=t,e=Array(a+s),t=ES(a+s),function(t,e,n,r,i,o,a,s,u){let l,c=0,f=0;for(l=0;c0)for(f=0;ft,size:()=>n}}function SS(t){Xa.call(this,function(){let t=8,e=[],n=ES(0),r=DS(0,t),i=DS(0,t);return{data:()=>e,seen:()=>n=function(t,e,n){return t.length>=e?t:((n=n||new t.constructor(e)).set(t),n)}(n,e.length),add(t){for(let n,r=0,i=e.length,o=t.length;re.length,curr:()=>r,prev:()=>i,reset:t=>i[t]=r[t],all:()=>t<257?255:t<65537?65535:4294967295,set(t,e){r[t]|=e},clear(t,e){r[t]&=~e},resize(e,n){(e>r.length||n>t)&&(t=Math.max(n,t),r=DS(e,t,r),i=DS(e,t))}}}(),t),this._indices=null,this._dims=null}function $S(t){Xa.call(this,null,t)}SS.Definition={type:"CrossFilter",metadata:{},params:[{name:"fields",type:"field",array:!0,required:!0},{name:"query",type:"array",array:!0,required:!0,content:{type:"number",array:!0,length:2}}]},ht(SS,Xa,{transform(t,e){return this._dims?t.modified("fields")||t.fields.some((t=>e.modified(t.fields)))?this.reinit(t,e):this.eval(t,e):this.init(t,e)},init(t,e){const n=t.fields,r=t.query,i=this._indices={},o=this._dims=[],a=r.length;let s,u,l=0;for(;l{const t=i.remove(e,n);for(const e in r)r[e].reindex(t)}))},update(t,e,n){const r=this._dims,i=t.query,o=e.stamp,a=r.length;let s,u,l=0;for(n.filters=0,u=0;ud)for(m=d,y=Math.min(f,p);mp)for(m=Math.max(f,p),y=h;mc)for(d=c,p=Math.min(u,f);df)for(d=Math.max(u,f),p=l;ds[t]&n?null:a[t];return o.filter(o.MOD,l),i&i-1?(o.filter(o.ADD,(t=>{const e=s[t]&n;return!e&&e^u[t]&n?a[t]:null})),o.filter(o.REM,(t=>{const e=s[t]&n;return e&&!(e^e^u[t]&n)?a[t]:null}))):(o.filter(o.ADD,l),o.filter(o.REM,(t=>(s[t]&n)===i?a[t]:null))),o.filter(o.SOURCE,(t=>l(t._index)))}});var TS=Object.freeze({__proto__:null,crossfilter:SS,resolvefilter:$S});const BS="Literal",zS="Property",NS="ArrayExpression",OS="BinaryExpression",RS="CallExpression",LS="ConditionalExpression",US="LogicalExpression",qS="MemberExpression",PS="ObjectExpression",jS="UnaryExpression";function IS(t){this.type=t}var WS,HS,YS,GS,VS;IS.prototype.visit=function(t){let e,n,r;if(t(this))return 1;for(e=function(t){switch(t.type){case NS:return t.elements;case OS:case US:return[t.left,t.right];case RS:return[t.callee].concat(t.arguments);case LS:return[t.test,t.consequent,t.alternate];case qS:return[t.object,t.property];case PS:return t.properties;case zS:return[t.key,t.value];case jS:return[t.argument];default:return[]}}(this),n=0,r=e.length;n",WS[ZS]="Identifier",WS[QS]="Keyword",WS[KS]="Null",WS[t$]="Numeric",WS[e$]="Punctuator",WS[n$]="String",WS[9]="RegularExpression";var r$="ArrayExpression",i$="BinaryExpression",o$="CallExpression",a$="ConditionalExpression",s$="Identifier",u$="Literal",l$="LogicalExpression",c$="MemberExpression",f$="ObjectExpression",h$="Property",d$="UnaryExpression",p$="Unexpected token %0",g$="Unexpected number",m$="Unexpected string",y$="Unexpected identifier",v$="Unexpected reserved word",_$="Unexpected end of input",x$="Invalid regular expression",b$="Invalid regular expression: missing /",w$="Octal literals are not allowed in strict mode.",k$="Duplicate data property in object literal not allowed in strict mode",A$="ILLEGAL",M$="Disabled.",E$=new RegExp("[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B2\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),D$=new RegExp("[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0300-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u0483-\\u0487\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0610-\\u061A\\u0620-\\u0669\\u066E-\\u06D3\\u06D5-\\u06DC\\u06DF-\\u06E8\\u06EA-\\u06FC\\u06FF\\u0710-\\u074A\\u074D-\\u07B1\\u07C0-\\u07F5\\u07FA\\u0800-\\u082D\\u0840-\\u085B\\u08A0-\\u08B2\\u08E4-\\u0963\\u0966-\\u096F\\u0971-\\u0983\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CE\\u09D7\\u09DC\\u09DD\\u09DF-\\u09E3\\u09E6-\\u09F1\\u0A01-\\u0A03\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A59-\\u0A5C\\u0A5E\\u0A66-\\u0A75\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0B01-\\u0B03\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3C-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B5C\\u0B5D\\u0B5F-\\u0B63\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD0\\u0BD7\\u0BE6-\\u0BEF\\u0C00-\\u0C03\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C58\\u0C59\\u0C60-\\u0C63\\u0C66-\\u0C6F\\u0C81-\\u0C83\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBC-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CDE\\u0CE0-\\u0CE3\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D01-\\u0D03\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D57\\u0D60-\\u0D63\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DE6-\\u0DEF\\u0DF2\\u0DF3\\u0E01-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\u0E59\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB9\\u0EBB-\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDC-\\u0EDF\\u0F00\\u0F18\\u0F19\\u0F20-\\u0F29\\u0F35\\u0F37\\u0F39\\u0F3E-\\u0F47\\u0F49-\\u0F6C\\u0F71-\\u0F84\\u0F86-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1714\\u1720-\\u1734\\u1740-\\u1753\\u1760-\\u176C\\u176E-\\u1770\\u1772\\u1773\\u1780-\\u17D3\\u17D7\\u17DC\\u17DD\\u17E0-\\u17E9\\u180B-\\u180D\\u1810-\\u1819\\u1820-\\u1877\\u1880-\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1920-\\u192B\\u1930-\\u193B\\u1946-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u19D0-\\u19D9\\u1A00-\\u1A1B\\u1A20-\\u1A5E\\u1A60-\\u1A7C\\u1A7F-\\u1A89\\u1A90-\\u1A99\\u1AA7\\u1AB0-\\u1ABD\\u1B00-\\u1B4B\\u1B50-\\u1B59\\u1B6B-\\u1B73\\u1B80-\\u1BF3\\u1C00-\\u1C37\\u1C40-\\u1C49\\u1C4D-\\u1C7D\\u1CD0-\\u1CD2\\u1CD4-\\u1CF6\\u1CF8\\u1CF9\\u1D00-\\u1DF5\\u1DFC-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u200C\\u200D\\u203F\\u2040\\u2054\\u2071\\u207F\\u2090-\\u209C\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D7F-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2DE0-\\u2DFF\\u2E2F\\u3005-\\u3007\\u3021-\\u302F\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u3099\\u309A\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA62B\\uA640-\\uA66F\\uA674-\\uA67D\\uA67F-\\uA69D\\uA69F-\\uA6F1\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA827\\uA840-\\uA873\\uA880-\\uA8C4\\uA8D0-\\uA8D9\\uA8E0-\\uA8F7\\uA8FB\\uA900-\\uA92D\\uA930-\\uA953\\uA960-\\uA97C\\uA980-\\uA9C0\\uA9CF-\\uA9D9\\uA9E0-\\uA9FE\\uAA00-\\uAA36\\uAA40-\\uAA4D\\uAA50-\\uAA59\\uAA60-\\uAA76\\uAA7A-\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEF\\uAAF2-\\uAAF6\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABEA\\uABEC\\uABED\\uABF0-\\uABF9\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE00-\\uFE0F\\uFE20-\\uFE2D\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF10-\\uFF19\\uFF21-\\uFF3A\\uFF3F\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]");function C$(t,e){if(!t)throw new Error("ASSERT: "+e)}function F$(t){return t>=48&&t<=57}function S$(t){return"0123456789abcdefABCDEF".includes(t)}function $$(t){return"01234567".includes(t)}function T$(t){return 32===t||9===t||11===t||12===t||160===t||t>=5760&&[5760,6158,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8239,8287,12288,65279].includes(t)}function B$(t){return 10===t||13===t||8232===t||8233===t}function z$(t){return 36===t||95===t||t>=65&&t<=90||t>=97&&t<=122||92===t||t>=128&&E$.test(String.fromCharCode(t))}function N$(t){return 36===t||95===t||t>=65&&t<=90||t>=97&&t<=122||t>=48&&t<=57||92===t||t>=128&&D$.test(String.fromCharCode(t))}const O$={if:1,in:1,do:1,var:1,for:1,new:1,try:1,let:1,this:1,else:1,case:1,void:1,with:1,enum:1,while:1,break:1,catch:1,throw:1,const:1,yield:1,class:1,super:1,return:1,typeof:1,delete:1,switch:1,export:1,import:1,public:1,static:1,default:1,finally:1,extends:1,package:1,private:1,function:1,continue:1,debugger:1,interface:1,protected:1,instanceof:1,implements:1};function R$(){for(;YS1114111||"}"!==t)&&tT({},p$,A$),e<=65535?String.fromCharCode(e):(n=55296+(e-65536>>10),r=56320+(e-65536&1023),String.fromCharCode(n,r))}function q$(){var t,e;for(t=HS.charCodeAt(YS++),e=String.fromCharCode(t),92===t&&(117!==HS.charCodeAt(YS)&&tT({},p$,A$),++YS,(t=L$("u"))&&"\\"!==t&&z$(t.charCodeAt(0))||tT({},p$,A$),e=t);YS>>="===(r=HS.substr(YS,4))?{type:e$,value:r,start:i,end:YS+=4}:">>>"===(n=r.substr(0,3))||"<<="===n||">>="===n?{type:e$,value:n,start:i,end:YS+=3}:a===(e=n.substr(0,2))[1]&&"+-<>&|".includes(a)||"=>"===e?{type:e$,value:e,start:i,end:YS+=2}:("//"===e&&tT({},p$,A$),"<>=!+-*%&|^/".includes(a)?(++YS,{type:e$,value:a,start:i,end:YS}):void tT({},p$,A$))}function I$(){var t,e,n;if(C$(F$((n=HS[YS]).charCodeAt(0))||"."===n,"Numeric literal must start with a decimal digit or a decimal point"),e=YS,t="","."!==n){if(t=HS[YS++],n=HS[YS],"0"===t){if("x"===n||"X"===n)return++YS,function(t){let e="";for(;YS=0&&tT({},x$,n),{value:n,literal:e}}(),r=function(t,e){let n=t;e.includes("u")&&(n=n.replace(/\\u\{([0-9a-fA-F]+)\}/g,((t,e)=>{if(parseInt(e,16)<=1114111)return"x";tT({},x$)})).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,"x"));try{new RegExp(n)}catch(t){tT({},x$)}try{return new RegExp(t,e)}catch(t){return null}}(e.value,n.value),{literal:e.literal+n.literal,value:r,regex:{pattern:e.value,flags:n.value},start:t,end:YS}}function H$(){if(R$(),YS>=GS)return{type:JS,start:YS,end:YS};const t=HS.charCodeAt(YS);return z$(t)?P$():40===t||41===t||59===t?j$():39===t||34===t?function(){var t,e,n,r,i="",o=!1;for(C$("'"===(t=HS[YS])||'"'===t,"String literal must starts with a quote"),e=YS,++YS;YS(C$(e":case"<=":case">=":case"instanceof":case"in":e=7;break;case"<<":case">>":case">>>":e=8;break;case"+":case"-":e=9;break;case"*":case"/":case"%":e=11}return e}function yT(){var t,e;return t=function(){var t,e,n,r,i,o,a,s,u,l;if(t=VS,u=gT(),0===(i=mT(r=VS)))return u;for(r.prec=i,Y$(),e=[t,VS],o=[u,r,a=gT()];(i=mT(VS))>0;){for(;o.length>2&&i<=o[o.length-2].prec;)a=o.pop(),s=o.pop().value,u=o.pop(),e.pop(),n=V$(s,u,a),o.push(n);(r=Y$()).prec=i,o.push(r),e.push(VS),n=gT(),o.push(n)}for(n=o[l=o.length-1],e.pop();l>1;)e.pop(),n=V$(o[l-1].value,o[l-2],n),l-=2;return n}(),rT("?")&&(Y$(),e=yT(),nT(":"),t=function(t,e,n){const r=new IS(a$);return r.test=t,r.consequent=e,r.alternate=n,r}(t,e,yT())),t}function vT(){const t=yT();if(rT(","))throw new Error(M$);return t}function _T(t){YS=0,GS=(HS=t).length,VS=null,G$();const e=vT();if(VS.type!==JS)throw new Error("Unexpect token after expression.");return e}var xT={NaN:"NaN",E:"Math.E",LN2:"Math.LN2",LN10:"Math.LN10",LOG2E:"Math.LOG2E",LOG10E:"Math.LOG10E",PI:"Math.PI",SQRT1_2:"Math.SQRT1_2",SQRT2:"Math.SQRT2",MIN_VALUE:"Number.MIN_VALUE",MAX_VALUE:"Number.MAX_VALUE"};function bT(t){function e(e,n,r){return i=>function(e,n,r,i){let o=t(n[0]);return r&&(o=r+"("+o+")",0===r.lastIndexOf("new ",0)&&(o="("+o+")")),o+"."+e+(i<0?"":0===i?"()":"("+n.slice(1).map(t).join(",")+")")}(e,i,n,r)}const n="new Date",r="String",i="RegExp";return{isNaN:"Number.isNaN",isFinite:"Number.isFinite",abs:"Math.abs",acos:"Math.acos",asin:"Math.asin",atan:"Math.atan",atan2:"Math.atan2",ceil:"Math.ceil",cos:"Math.cos",exp:"Math.exp",floor:"Math.floor",hypot:"Math.hypot",log:"Math.log",max:"Math.max",min:"Math.min",pow:"Math.pow",random:"Math.random",round:"Math.round",sin:"Math.sin",sqrt:"Math.sqrt",tan:"Math.tan",clamp:function(e){e.length<3&&s("Missing arguments to clamp function."),e.length>3&&s("Too many arguments to clamp function.");const n=e.map(t);return"Math.max("+n[1]+", Math.min("+n[2]+","+n[0]+"))"},now:"Date.now",utc:"Date.UTC",datetime:n,date:e("getDate",n,0),day:e("getDay",n,0),year:e("getFullYear",n,0),month:e("getMonth",n,0),hours:e("getHours",n,0),minutes:e("getMinutes",n,0),seconds:e("getSeconds",n,0),milliseconds:e("getMilliseconds",n,0),time:e("getTime",n,0),timezoneoffset:e("getTimezoneOffset",n,0),utcdate:e("getUTCDate",n,0),utcday:e("getUTCDay",n,0),utcyear:e("getUTCFullYear",n,0),utcmonth:e("getUTCMonth",n,0),utchours:e("getUTCHours",n,0),utcminutes:e("getUTCMinutes",n,0),utcseconds:e("getUTCSeconds",n,0),utcmilliseconds:e("getUTCMilliseconds",n,0),length:e("length",null,-1),parseFloat:"parseFloat",parseInt:"parseInt",upper:e("toUpperCase",r,0),lower:e("toLowerCase",r,0),substring:e("substring",r),split:e("split",r),trim:e("trim",r,0),btoa:"btoa",atob:"atob",regexp:i,test:e("test",i),if:function(e){e.length<3&&s("Missing arguments to if function."),e.length>3&&s("Too many arguments to if function.");const n=e.map(t);return"("+n[0]+"?"+n[1]+":"+n[2]+")"}}}function wT(t){const e=(t=t||{}).allowed?Tt(t.allowed):{},n=t.forbidden?Tt(t.forbidden):{},r=t.constants||xT,i=(t.functions||bT)(h),o=t.globalvar,a=t.fieldvar,u=J(o)?o:t=>`${o}["${t}"]`;let l={},c={},f=0;function h(t){if(_t(t))return t;const e=d[t.type];return null==e&&s("Unsupported type: "+t.type),e(t)}const d={Literal:t=>t.raw,Identifier:t=>{const i=t.name;return f>0?i:ut(n,i)?s("Illegal identifier: "+i):ut(r,i)?r[i]:ut(e,i)?i:(l[i]=1,u(i))},MemberExpression:t=>{const e=!t.computed,n=h(t.object);e&&(f+=1);const r=h(t.property);return n===a&&(c[function(t){const e=t&&t.length-1;return e&&('"'===t[0]&&'"'===t[e]||"'"===t[0]&&"'"===t[e])?t.slice(1,-1):t}(r)]=1),e&&(f-=1),n+(e?"."+r:"["+r+"]")},CallExpression:t=>{"Identifier"!==t.callee.type&&s("Illegal callee type: "+t.callee.type);const e=t.callee.name,n=t.arguments,r=ut(i,e)&&i[e];return r||s("Unrecognized function: "+e),J(r)?r(n):r+"("+n.map(h).join(",")+")"},ArrayExpression:t=>"["+t.elements.map(h).join(",")+"]",BinaryExpression:t=>"("+h(t.left)+" "+t.operator+" "+h(t.right)+")",UnaryExpression:t=>"("+t.operator+h(t.argument)+")",ConditionalExpression:t=>"("+h(t.test)+"?"+h(t.consequent)+":"+h(t.alternate)+")",LogicalExpression:t=>"("+h(t.left)+t.operator+h(t.right)+")",ObjectExpression:t=>"{"+t.properties.map(h).join(",")+"}",Property:t=>{f+=1;const e=h(t.key);return f-=1,e+":"+h(t.value)}};function p(t){const e={code:h(t),globals:Object.keys(l),fields:Object.keys(c)};return l={},c={},e}return p.functions=i,p.constants=r,p}const kT=Symbol("vega_selection_getter");function AT(t){return t.getter&&t.getter[kT]||(t.getter=l(t.field),t.getter[kT]=!0),t.getter}const MT="intersect",ET="union",DT="_vgsid_",CT=l(DT),FT="E",ST="R",$T="R-E",TT="R-LE",BT="R-RE",zT="E-LT",NT="E-LTE",OT="E-GT",RT="E-GTE",LT="E-VALID",UT="E-ONE",qT="index:unit";function PT(t,e){for(var n,r,i=e.fields,o=e.values,a=i.length,s=0;s=o[s])return!1}else if(r.type===NT){if(n>o[s])return!1}else if(r.type===OT){if(n<=o[s])return!1}else if(r.type===RT){if(n1?e-1:0),r=1;re.includes(t))):e},R_union:function(t,e){var n=S(e[0]),r=S(e[1]);return n>r&&(n=e[1],r=e[0]),t.length?(t[0]>n&&(t[0]=n),t[1]r&&(n=e[1],r=e[0]),t.length?rr&&(t[1]=r),t):[n,r]}};function YT(t,e,n,r){e[0].type!==BS&&s("First argument to selection functions must be a string literal.");const i=e[0].value,o="unit",a="@"+o,u=":"+i;(e.length>=2&&F(e).value)!==MT||ut(r,a)||(r[a]=n.getData(i).indataRef(n,o)),ut(r,u)||(r[u]=n.getData(i).tuplesRef())}function GT(t){const e=this.context.data[t];return e?e.values.value:[]}const VT=t=>function(e,n){const r=this.context.dataflow.locale();return null===e?"null":r[t](n)(e)},XT=VT("format"),JT=VT("timeFormat"),ZT=VT("utcFormat"),QT=VT("timeParse"),KT=VT("utcParse"),tB=new Date(2e3,0,1);function eB(t,e,n){return Number.isInteger(t)&&Number.isInteger(e)?(tB.setYear(2e3),tB.setMonth(t),tB.setDate(e),JT.call(this,tB,n)):""}const nB="%",rB="$";function iB(t,e,n,r){e[0].type!==BS&&s("First argument to data functions must be a string literal.");const i=e[0].value,o=":"+i;if(!ut(o,r))try{r[o]=n.getData(i).tuplesRef()}catch(t){}}function oB(t,e,n,r){if(e[0].type===BS)aB(n,r,e[0].value);else for(t in n.scales)aB(n,r,t)}function aB(t,e,n){const r=nB+n;if(!ut(e,r))try{e[r]=t.scaleRef(n)}catch(t){}}function sB(t,e){if(_t(t)){const n=e.scales[t];return n&&op(n.value)?n.value:void 0}if(J(t))return op(t)?t:void 0}function uB(t,e,n){e.__bandwidth=t=>t&&t.bandwidth?t.bandwidth():0,n._bandwidth=oB,n._range=oB,n._scale=oB;const r=e=>"_["+(e.type===BS?Dt(nB+e.value):Dt(nB)+"+"+t(e))+"]";return{_bandwidth:t=>`this.__bandwidth(${r(t[0])})`,_range:t=>`${r(t[0])}.range()`,_scale:e=>`${r(e[0])}(${t(e[1])})`}}function lB(t,e){return function(n,r,i){if(n){const e=sB(n,(i||this).context);return e&&e.path[t](r)}return e(r)}}const cB=lB("area",(function(t){return Tw=new ae,pw(t,Bw),2*Tw})),fB=lB("bounds",(function(t){var e,n,r,i,o,a,s;if(kw=ww=-(xw=bw=1/0),Fw=[],pw(t,sk),n=Fw.length){for(Fw.sort(mk),e=1,o=[r=Fw[0]];egk(r[0],r[1])&&(r[1]=i[1]),gk(i[0],r[1])>gk(r[0],r[1])&&(r[0]=i[0])):o.push(r=i);for(a=-1/0,e=0,r=o[n=o.length-1];e<=n;r=i,++e)i=o[e],(s=gk(r[1],i[0]))>a&&(a=s,xw=i[0],ww=r[1])}return Fw=Sw=null,xw===1/0||bw===1/0?[[NaN,NaN],[NaN,NaN]]:[[xw,bw],[ww,kw]]})),hB=lB("centroid",(function(t){Hw=Yw=Gw=Vw=Xw=Jw=Zw=Qw=0,Kw=new ae,tk=new ae,ek=new ae,pw(t,vk);var e=+Kw,n=+tk,r=+ek,i=Kb(e,n,r);return iyB(t,e)}const _B={};function xB(t){return k(t)||ArrayBuffer.isView(t)?t:null}function bB(t){return xB(t)||(_t(t)?t:null)}const wB=t=>t.data;function kB(t,e){const n=GT.call(e,t);return n.root&&n.root.lookup||{}}const AB=()=>"undefined"!=typeof window&&window||null;function MB(t,e,n){if(!t)return[];const[r,i]=t,o=(new Vg).set(r[0],r[1],i[0],i[1]);return B_(n||this.context.dataflow.scenegraph().root,o,function(t){let e=null;if(t){const n=V(t.marktype),r=V(t.markname);e=t=>(!n.length||n.some((e=>t.marktype===e)))&&(!r.length||r.some((e=>t.name===e)))}return e}(e))}const EB={random:()=>t.random(),cumulativeNormal:fs,cumulativeLogNormal:ys,cumulativeUniform:ks,densityNormal:cs,densityLogNormal:ms,densityUniform:ws,quantileNormal:hs,quantileLogNormal:vs,quantileUniform:As,sampleNormal:ls,sampleLogNormal:gs,sampleUniform:bs,isArray:k,isBoolean:pt,isDate:gt,isDefined:t=>void 0!==t,isNumber:yt,isObject:A,isRegExp:vt,isString:_t,isTuple:ga,isValid:t=>null!=t&&t==t,toBoolean:Ct,toDate:t=>St(t),toNumber:S,toString:$t,indexof:function(t){for(var e=arguments.length,n=new Array(e>1?e-1:0),r=1;r1?e-1:0),r=1;r1?e-1:0),r=1;r1?e-1:0),r=1;rat(t),inScope:function(t){const e=this.context.group;let n=!1;if(e)for(;t;){if(t===e){n=!0;break}t=t.mark.group}return n},intersect:MB,clampRange:X,pinchDistance:function(t){const e=t.touches,n=e[0].clientX-e[1].clientX,r=e[0].clientY-e[1].clientY;return Math.hypot(n,r)},pinchAngle:function(t){const e=t.touches;return Math.atan2(e[0].clientY-e[1].clientY,e[0].clientX-e[1].clientX)},screen:function(){const t=AB();return t?t.screen:{}},containerSize:function(){const t=this.context.dataflow,e=t.container&&t.container();return e?[e.clientWidth,e.clientHeight]:[void 0,void 0]},windowSize:function(){const t=AB();return t?[t.innerWidth,t.innerHeight]:[void 0,void 0]},bandspace:function(t,e,n){return Sd(t||0,e||0,n||0)},setdata:function(t,e){const n=this.context.dataflow,r=this.context.data[t].input;return n.pulse(r,n.changeset().remove(p).insert(e)),1},pathShape:function(t){let e=null;return function(n){return n?yg(n,e=e||ag(t)):t}},panLinear:R,panLog:L,panPow:U,panSymlog:q,zoomLinear:j,zoomLog:I,zoomPow:W,zoomSymlog:H,encode:function(t,e,n){if(t){const n=this.context.dataflow,r=t.mark.source;n.pulse(r,n.changeset().encode(t,e))}return void 0!==n?n:t},modify:function(t,e,n,r,i,o){const a=this.context.dataflow,s=this.context.data[t],u=s.input,l=a.stamp();let c,f,h=s.changes;if(!1===a._trigger||!(u.value.length||e||r))return 0;if((!h||h.stamp{s.modified=!0,a.pulse(u,h).run()}),!0,1)),n&&(c=!0===n?p:k(n)||ga(n)?n:vB(n),h.remove(c)),e&&h.insert(e),r&&(c=vB(r),u.value.some(c)?h.remove(c):h.insert(r)),i)for(f in o)h.modify(i,f,o[f]);return 1},lassoAppend:function(t,e,n){let r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:5;const i=(t=V(t))[t.length-1];return void 0===i||Math.hypot(i[0]-e,i[1]-n)>r?[...t,[e,n]]:t},lassoPath:function(t){return V(t).reduce(((e,n,r)=>{let[i,o]=n;return e+(0==r?`M ${i},${o} `:r===t.length-1?" Z":`L ${i},${o} `)}),"")},intersectLasso:function(t,e,n){const{x:r,y:i,mark:o}=n,a=(new Vg).set(Number.MAX_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER,Number.MIN_SAFE_INTEGER);for(const[t,n]of e)ta.x2&&(a.x2=t),na.y2&&(a.y2=n);return a.translate(r,i),MB([[a.x1,a.y1],[a.x2,a.y2]],t,o).filter((t=>function(t,e,n){let r=0;for(let i=0,o=n.length-1;ie!=s>e&&t<(a-u)*(e-l)/(s-l)+u&&r++}return 1&r}(t.x,t.y,e)))}},DB=["view","item","group","xy","x","y"],CB="this.",FB={},SB={forbidden:["_"],allowed:["datum","event","item"],fieldvar:"datum",globalvar:t=>`_[${Dt(rB+t)}]`,functions:function(t){const e=bT(t);DB.forEach((t=>e[t]="event.vega."+t));for(const t in EB)e[t]=CB+t;return ot(e,uB(t,EB,FB)),e},constants:xT,visitors:FB},$B=wT(SB);function TB(t,e,n){return 1===arguments.length?EB[t]:(EB[t]=e,n&&(FB[t]=n),$B&&($B.functions[t]=CB+t),this)}function BB(t,e){const n={};let r;try{r=_T(t=_t(t)?t:Dt(t)+"")}catch(e){s("Expression parse error: "+t)}r.visit((t=>{if(t.type!==RS)return;const r=t.callee.name,i=SB.visitors[r];i&&i(r,t.arguments,e,n)}));const i=$B(r);return i.globals.forEach((t=>{const r=rB+t;!ut(n,r)&&e.getSignal(t)&&(n[r]=e.signalRef(t))})),{$expr:ot({code:i.code},e.options.ast?{ast:r}:null),$fields:i.fields,$params:n}}TB("bandwidth",(function(t,e){const n=sB(t,(e||this).context);return n&&n.bandwidth?n.bandwidth():0}),oB),TB("copy",(function(t,e){const n=sB(t,(e||this).context);return n?n.copy():void 0}),oB),TB("domain",(function(t,e){const n=sB(t,(e||this).context);return n?n.domain():[]}),oB),TB("range",(function(t,e){const n=sB(t,(e||this).context);return n&&n.range?n.range():[]}),oB),TB("invert",(function(t,e,n){const r=sB(t,(n||this).context);return r?k(e)?(r.invertRange||r.invert)(e):(r.invert||r.invertExtent)(e):void 0}),oB),TB("scale",(function(t,e,n){const r=sB(t,(n||this).context);return r?r(e):void 0}),oB),TB("gradient",(function(t,e,n,r,i){t=sB(t,(i||this).context);const o=Qp(e,n);let a=t.domain(),s=a[0],u=F(a),l=f;return u-s?l=_p(t,s,u):t=(t.interpolator?ap("sequential")().interpolator(t.interpolator()):ap("linear")().interpolate(t.interpolate()).range(t.range())).domain([s=0,u=1]),t.ticks&&(a=t.ticks(+r||15),s!==a[0]&&a.unshift(s),u!==F(a)&&a.push(u)),a.forEach((e=>o.stop(l(e),t(e)))),o}),oB),TB("geoArea",cB,oB),TB("geoBounds",fB,oB),TB("geoCentroid",hB,oB),TB("geoShape",(function(t,e,n){const r=sB(t,(n||this).context);return function(t){return r?r.path.context(t)(e):""}}),oB),TB("geoScale",(function(t,e){const n=sB(t,(e||this).context);return n&&n.scale()}),oB),TB("indata",(function(t,e,n){const r=this.context.data[t]["index:"+e],i=r?r.value.get(n):void 0;return i?i.count:i}),(function(t,e,n,r){e[0].type!==BS&&s("First argument to indata must be a string literal."),e[1].type!==BS&&s("Second argument to indata must be a string literal.");const i=e[0].value,o=e[1].value,a="@"+o;ut(a,r)||(r[a]=n.getData(i).indataRef(n,o))})),TB("data",GT,iB),TB("treePath",(function(t,e,n){const r=kB(t,this),i=r[e],o=r[n];return i&&o?i.path(o).map(wB):void 0}),iB),TB("treeAncestors",(function(t,e){const n=kB(t,this)[e];return n?n.ancestors().map(wB):void 0}),iB),TB("vlSelectionTest",(function(t,e,n){for(var r,i,o,a,s,u=this.context.data[t],l=u?u.values.value:[],c=u?u[qT]&&u[qT].value:void 0,f=n===MT,h=l.length,d=0;d(t[o[n].field]=e,t)),{}))}else u=DT,l=CT(i),(f=(c=v[u]||(v[u]={}))[s]||(c[s]=[])).push(l),n&&(f=_[s]||(_[s]=[])).push({[DT]:l});if(e=e||ET,v[DT]?v[DT]=HT[`${DT}_${e}`](...Object.values(v[DT])):Object.keys(v).forEach((t=>{v[t]=Object.keys(v[t]).map((e=>v[t][e])).reduce(((n,r)=>void 0===n?r:HT[`${x[t]}_${e}`](n,r)))})),y=Object.keys(_),n&&y.length){v[r?"vlPoint":"vlMulti"]=e===ET?{or:y.reduce(((t,e)=>(t.push(..._[e]),t)),[])}:{and:y.map((t=>({or:_[t]})))}}return v}),YT),TB("vlSelectionTuples",(function(t,e){return t.map((t=>ot(e.fields?{values:e.fields.map((e=>AT(e)(t.datum)))}:{[DT]:CT(t.datum)},e)))}));const zB=Tt(["rule"]),NB=Tt(["group","image","rect"]);function OB(t){return(t+"").toLowerCase()}function RB(t,e,n){n.endsWith(";")||(n="return("+n+");");const r=Function(...e.concat(n));return t&&t.functions?r.bind(t.functions):r}var LB={operator:(t,e)=>RB(t,["_"],e.code),parameter:(t,e)=>RB(t,["datum","_"],e.code),event:(t,e)=>RB(t,["event"],e.code),handler:(t,e)=>RB(t,["_","event"],`var datum=event.item&&event.item.datum;return ${e.code};`),encode:(t,e)=>{const{marktype:n,channels:r}=e;let i="var o=item,datum=o.datum,m=0,$;";for(const t in r){const e="o["+Dt(t)+"]";i+=`$=${r[t].code};if(${e}!==$)${e}=$,m=1;`}return i+=function(t,e){let n="";return zB[e]||(t.x2&&(t.x?(NB[e]&&(n+="if(o.x>o.x2)$=o.x,o.x=o.x2,o.x2=$;"),n+="o.width=o.x2-o.x;"):n+="o.x=o.x2-(o.width||0);"),t.xc&&(n+="o.x=o.xc-(o.width||0)/2;"),t.y2&&(t.y?(NB[e]&&(n+="if(o.y>o.y2)$=o.y,o.y=o.y2,o.y2=$;"),n+="o.height=o.y2-o.y;"):n+="o.y=o.y2-(o.height||0);"),t.yc&&(n+="o.y=o.yc-(o.height||0)/2;")),n}(r,n),i+="return m;",RB(t,["item","_"],i)},codegen:{get(t){const e=`[${t.map(Dt).join("][")}]`,n=Function("_",`return _${e};`);return n.path=e,n},comparator(t,e){let n;const r=Function("a","b","var u, v; return "+t.map(((t,r)=>{const i=e[r];let o,a;return t.path?(o=`a${t.path}`,a=`b${t.path}`):((n=n||{})["f"+r]=t,o=`this.f${r}(a)`,a=`this.f${r}(b)`),function(t,e,n,r){return`((u = ${t}) < (v = ${e}) || u == null) && v != null ? ${n}\n : (u > v || v == null) && u != null ? ${r}\n : ((v = v instanceof Date ? +v : v), (u = u instanceof Date ? +u : u)) !== u && v === v ? ${n}\n : v !== v && u === u ? ${r} : `}(o,a,-i,i)})).join("")+"0;");return n?r.bind(n):r}}};function UB(t,e,n){if(!t||!A(t))return t;for(let r,i=0,o=qB.length;it&&t.$tupleid?ma:t));return e.fn[n]||(e.fn[n]=Q(r,t.$order,e.expr.codegen))}},{key:"$context",parse:function(t,e){return e}},{key:"$subflow",parse:function(t,e){const n=t.$subflow;return function(t,r,i){const o=e.fork().parse(n),a=o.get(n.operators[0].id),s=o.signals.parent;return s&&s.set(i),a.detachSubflow=()=>e.detach(o),a}}},{key:"$tupleid",parse:function(){return ma}}];const PB={skip:!0};function jB(t,e,n,r){return new IB(t,e,n,r)}function IB(t,e,n,r){this.dataflow=t,this.transforms=e,this.events=t.events.bind(t),this.expr=r||LB,this.signals={},this.scales={},this.nodes={},this.data={},this.fn={},n&&(this.functions=Object.create(n),this.functions.context=this)}function WB(t){this.dataflow=t.dataflow,this.transforms=t.transforms,this.events=t.events,this.expr=t.expr,this.signals=Object.create(t.signals),this.scales=Object.create(t.scales),this.nodes=Object.create(t.nodes),this.data=Object.create(t.data),this.fn=Object.create(t.fn),t.functions&&(this.functions=Object.create(t.functions),this.functions.context=this)}function HB(t,e){t&&(null==e?t.removeAttribute("aria-label"):t.setAttribute("aria-label",e))}IB.prototype=WB.prototype={fork(){const t=new WB(this);return(this.subcontext||(this.subcontext=[])).push(t),t},detach(t){this.subcontext=this.subcontext.filter((e=>e!==t));const e=Object.keys(t.nodes);for(const n of e)t.nodes[n]._targets=null;for(const n of e)t.nodes[n].detach();t.nodes=null},get(t){return this.nodes[t]},set(t,e){return this.nodes[t]=e},add(t,e){const n=this,r=n.dataflow,i=t.value;if(n.set(t.id,e),function(t){return"collect"===OB(t)}(t.type)&&i&&(i.$ingest?r.ingest(e,i.$ingest,i.$format):i.$request?r.preload(e,i.$request,i.$format):r.pulse(e,r.changeset().insert(i))),t.root&&(n.root=e),t.parent){let i=n.get(t.parent.$ref);i?(r.connect(i,[e]),e.targets().add(i)):(n.unresolved=n.unresolved||[]).push((()=>{i=n.get(t.parent.$ref),r.connect(i,[e]),e.targets().add(i)}))}if(t.signal&&(n.signals[t.signal]=e),t.scale&&(n.scales[t.scale]=e),t.data)for(const r in t.data){const i=n.data[r]||(n.data[r]={});t.data[r].forEach((t=>i[t]=e))}},resolve(){return(this.unresolved||[]).forEach((t=>t())),delete this.unresolved,this},operator(t,e){this.add(t,this.dataflow.add(t.value,e))},transform(t,e){this.add(t,this.dataflow.add(this.transforms[OB(e)]))},stream(t,e){this.set(t.id,e)},update(t,e,n,r,i){this.dataflow.on(e,n,r,i,t.options)},operatorExpression(t){return this.expr.operator(this,t)},parameterExpression(t){return this.expr.parameter(this,t)},eventExpression(t){return this.expr.event(this,t)},handlerExpression(t){return this.expr.handler(this,t)},encodeExpression(t){return this.expr.encode(this,t)},parse:function(t){const e=this,n=t.operators||[];return t.background&&(e.background=t.background),t.eventConfig&&(e.eventConfig=t.eventConfig),t.locale&&(e.locale=t.locale),n.forEach((t=>e.parseOperator(t))),n.forEach((t=>e.parseOperatorParameters(t))),(t.streams||[]).forEach((t=>e.parseStream(t))),(t.updates||[]).forEach((t=>e.parseUpdate(t))),e.resolve()},parseOperator:function(t){const e=this;!function(t){return"operator"===OB(t)}(t.type)&&t.type?e.transform(t,t.type):e.operator(t,t.update?e.operatorExpression(t.update):null)},parseOperatorParameters:function(t){const e=this;if(t.params){const n=e.get(t.id);n||s("Invalid operator id: "+t.id),e.dataflow.connect(n,n.parameters(e.parseParameters(t.params),t.react,t.initonly))}},parseParameters:function(t,e){e=e||{};const n=this;for(const r in t){const i=t[r];e[r]=k(i)?i.map((t=>UB(t,n,e))):UB(i,n,e)}return e},parseStream:function(t){var e,n=this,r=null!=t.filter?n.eventExpression(t.filter):void 0,i=null!=t.stream?n.get(t.stream):void 0;t.source?i=n.events(t.source,t.type,r):t.merge&&(i=(e=t.merge.map((t=>n.get(t))))[0].merge.apply(e[0],e.slice(1))),t.between&&(e=t.between.map((t=>n.get(t))),i=i.between(e[0],e[1])),t.filter&&(i=i.filter(r)),null!=t.throttle&&(i=i.throttle(+t.throttle)),null!=t.debounce&&(i=i.debounce(+t.debounce)),null==i&&s("Invalid stream definition: "+JSON.stringify(t)),t.consume&&i.consume(!0),n.stream(t,i)},parseUpdate:function(t){var e,n=this,r=A(r=t.source)?r.$ref:r,i=n.get(r),o=t.update,a=void 0;i||s("Source not defined: "+t.source),e=t.target&&t.target.$expr?n.eventExpression(t.target.$expr):n.get(t.target),o&&o.$expr&&(o.$params&&(a=n.parseParameters(o.$params)),o=n.handlerExpression(o.$expr)),n.update(t,i,e,o,a)},getState:function(t){var e=this,n={};if(t.signals){var r=n.signals={};Object.keys(e.signals).forEach((n=>{const i=e.signals[n];t.signals(n,i)&&(r[n]=i.value)}))}if(t.data){var i=n.data={};Object.keys(e.data).forEach((n=>{const r=e.data[n];t.data(n,r)&&(i[n]=r.input.value)}))}return e.subcontext&&!1!==t.recurse&&(n.subcontext=e.subcontext.map((e=>e.getState(t)))),n},setState:function(t){var e=this,n=e.dataflow,r=t.data,i=t.signals;Object.keys(i||{}).forEach((t=>{n.update(e.signals[t],i[t],PB)})),Object.keys(r||{}).forEach((t=>{n.pulse(e.data[t].input,n.changeset().remove(p).insert(r[t]))})),(t.subcontext||[]).forEach(((t,n)=>{const r=e.subcontext[n];r&&r.setState(t)}))}};const YB="default";function GB(t,e){const n=t.globalCursor()?"undefined"!=typeof document&&document.body:t.container();if(n)return null==e?n.style.removeProperty("cursor"):n.style.cursor=e}function VB(t,e){var n=t._runtime.data;return ut(n,e)||s("Unrecognized data set: "+e),n[e]}function XB(t,e){ka(e)||s("Second argument to changes must be a changeset.");const n=VB(this,t);return n.modified=!0,this.pulse(n.input,e)}function JB(t){var e=t.padding();return Math.max(0,t._viewWidth+e.left+e.right)}function ZB(t){var e=t.padding();return Math.max(0,t._viewHeight+e.top+e.bottom)}function QB(t){var e=t.padding(),n=t._origin;return[e.left+n[0],e.top+n[1]]}function KB(t,e,n){var r,i,o=t._renderer,a=o&&o.canvas();return a&&(i=QB(t),(r=av(e.changedTouches?e.changedTouches[0]:e,a))[0]-=i[0],r[1]-=i[1]),e.dataflow=t,e.item=n,e.vega=function(t,e,n){const r=e?"group"===e.mark.marktype?e:e.mark.group:null;function i(t){var n,i=r;if(t)for(n=e;n;n=n.mark.group)if(n.mark.name===t){i=n;break}return i&&i.mark&&i.mark.interactive?i:{}}function o(t){if(!t)return n;_t(t)&&(t=i(t));const e=n.slice();for(;t;)e[0]-=t.x||0,e[1]-=t.y||0,t=t.mark&&t.mark.group;return e}return{view:rt(t),item:rt(e||{}),group:i,xy:o,x:t=>o(t)[0],y:t=>o(t)[1]}}(t,n,r),e}const tz="view",ez={trap:!1};function nz(t,e,n,r){t._eventListeners.push({type:n,sources:V(e),handler:r})}function rz(t,e,n){const r=t._eventConfig&&t._eventConfig[e];return!(!1===r||A(r)&&!r[n])||(t.warn(`Blocked ${e} ${n} event listener.`),!1)}function iz(t){return t.item}function oz(t){return t.item.mark.source}function az(t){return function(e,n){return n.vega.view().changeset().encode(n.item,t)}}function sz(t,e,n){const r=document.createElement(t);for(const t in e)r.setAttribute(t,e[t]);return null!=n&&(r.textContent=n),r}const uz="vega-bind",lz="vega-bind-name",cz="vega-bind-radio";function fz(t,e,n,r){const i=n.event||"input",o=()=>t.update(e.value);r.signal(n.signal,e.value),e.addEventListener(i,o),nz(r,e,i,o),t.set=t=>{e.value=t,e.dispatchEvent(function(t){return"undefined"!=typeof Event?new Event(t):{type:t}}(i))}}function hz(t,e,n,r){const i=r.signal(n.signal),o=sz("div",{class:uz}),a="radio"===n.input?o:o.appendChild(sz("label"));a.appendChild(sz("span",{class:lz},n.name||n.signal)),e.appendChild(o);let s=dz;switch(n.input){case"checkbox":s=pz;break;case"select":s=gz;break;case"radio":s=mz;break;case"range":s=yz}s(t,a,n,i)}function dz(t,e,n,r){const i=sz("input");for(const t in n)"signal"!==t&&"element"!==t&&i.setAttribute("input"===t?"type":t,n[t]);i.setAttribute("name",n.signal),i.value=r,e.appendChild(i),i.addEventListener("input",(()=>t.update(i.value))),t.elements=[i],t.set=t=>i.value=t}function pz(t,e,n,r){const i={type:"checkbox",name:n.signal};r&&(i.checked=!0);const o=sz("input",i);e.appendChild(o),o.addEventListener("change",(()=>t.update(o.checked))),t.elements=[o],t.set=t=>o.checked=!!t||null}function gz(t,e,n,r){const i=sz("select",{name:n.signal}),o=n.labels||[];n.options.forEach(((t,e)=>{const n={value:t};vz(t,r)&&(n.selected=!0),i.appendChild(sz("option",n,(o[e]||t)+""))})),e.appendChild(i),i.addEventListener("change",(()=>{t.update(n.options[i.selectedIndex])})),t.elements=[i],t.set=t=>{for(let e=0,r=n.options.length;e{const s={type:"radio",name:n.signal,value:e};vz(e,r)&&(s.checked=!0);const u=sz("input",s);u.addEventListener("change",(()=>t.update(e)));const l=sz("label",{},(o[a]||e)+"");return l.prepend(u),i.appendChild(l),u})),t.set=e=>{const n=t.elements,r=n.length;for(let t=0;t{u.textContent=s.value,t.update(+s.value)};s.addEventListener("input",l),s.addEventListener("change",l),t.elements=[s],t.set=t=>{s.value=t,u.textContent=t}}function vz(t,e){return t===e||t+""==e+""}function _z(t,e,n,r,i,o){return(e=e||new r(t.loader())).initialize(n,JB(t),ZB(t),QB(t),i,o).background(t.background())}function xz(t,e){return e?function(){try{e.apply(this,arguments)}catch(e){t.error(e)}}:null}function bz(t,e,n){if("string"==typeof e){if("undefined"==typeof document)return t.error("DOM document instance not found."),null;if(!(e=document.querySelector(e)))return t.error("Signal bind element not found: "+e),null}if(e&&n)try{e.textContent=""}catch(n){e=null,t.error(n)}return e}const wz=t=>+t||0;function kz(t){return A(t)?{top:wz(t.top),bottom:wz(t.bottom),left:wz(t.left),right:wz(t.right)}:(t=>({top:t,bottom:t,left:t,right:t}))(wz(t))}async function Az(t,e,n,r){const i=T_(e),o=i&&i.headless;return o||s("Unrecognized renderer type: "+e),await t.runAsync(),_z(t,null,null,o,n,r).renderAsync(t._scenegraph.root)}var Mz="width",Ez="height",Dz="padding",Cz={skip:!0};function Fz(t,e){var n=t.autosize(),r=t.padding();return e-(n&&n.contains===Dz?r.left+r.right:0)}function Sz(t,e){var n=t.autosize(),r=t.padding();return e-(n&&n.contains===Dz?r.top+r.bottom:0)}function $z(t,e){return e.modified&&k(e.input.value)&&!t.startsWith("_:vega:_")}function Tz(t,e){return!("parent"===t||e instanceof Ja.proxy)}function Bz(t,e,n,r){const i=t.element();i&&i.setAttribute("title",function(t){return null==t?"":k(t)?zz(t):A(t)&&!gt(t)?(e=t,Object.keys(e).map((t=>{const n=e[t];return t+": "+(k(n)?zz(n):Nz(n))})).join("\n")):t+"";var e}(r))}function zz(t){return"["+t.map(Nz).join(", ")+"]"}function Nz(t){return k(t)?"[…]":A(t)&&!gt(t)?"{…}":t}function Oz(t,e){const n=this;if(e=e||{},Ga.call(n),e.loader&&n.loader(e.loader),e.logger&&n.logger(e.logger),null!=e.logLevel&&n.logLevel(e.logLevel),e.locale||t.locale){const r=ot({},t.locale,e.locale);n.locale(Oo(r.number,r.time))}n._el=null,n._elBind=null,n._renderType=e.renderer||S_.Canvas,n._scenegraph=new Ky;const r=n._scenegraph.root;n._renderer=null,n._tooltip=e.tooltip||Bz,n._redraw=!0,n._handler=(new Sv).scene(r),n._globalCursor=!1,n._preventDefault=!1,n._timers=[],n._eventListeners=[],n._resizeListeners=[],n._eventConfig=function(t){const e=ot({defaults:{}},t),n=(t,e)=>{e.forEach((e=>{k(t[e])&&(t[e]=Tt(t[e]))}))};return n(e.defaults,["prevent","allow"]),n(e,["view","window","selector"]),e}(t.eventConfig),n.globalCursor(n._eventConfig.globalCursor);const i=function(t,e,n){return jB(t,Ja,EB,n).parse(e)}(n,t,e.expr);n._runtime=i,n._signals=i.signals,n._bind=(t.bindings||[]).map((t=>({state:null,param:ot({},t)}))),i.root&&i.root.set(r),r.source=i.data.root.input,n.pulse(i.data.root.input,n.changeset().insert(r.items)),n._width=n.width(),n._height=n.height(),n._viewWidth=Fz(n,n._width),n._viewHeight=Sz(n,n._height),n._origin=[0,0],n._resize=0,n._autosize=1,function(t){var e=t._signals,n=e[Mz],r=e[Ez],i=e[Dz];function o(){t._autosize=t._resize=1}t._resizeWidth=t.add(null,(e=>{t._width=e.size,t._viewWidth=Fz(t,e.size),o()}),{size:n}),t._resizeHeight=t.add(null,(e=>{t._height=e.size,t._viewHeight=Sz(t,e.size),o()}),{size:r});const a=t.add(null,o,{pad:i});t._resizeWidth.rank=n.rank+1,t._resizeHeight.rank=r.rank+1,a.rank=i.rank+1}(n),function(t){t.add(null,(e=>(t._background=e.bg,t._resize=1,e.bg)),{bg:t._signals.background})}(n),function(t){const e=t._signals.cursor||(t._signals.cursor=t.add({user:YB,item:null}));t.on(t.events("view","pointermove"),e,((t,n)=>{const r=e.value,i=r?_t(r)?r:r.user:YB,o=n.item&&n.item.cursor||null;return r&&i===r.user&&o==r.item?r:{user:i,item:o}})),t.add(null,(function(e){let n=e.cursor,r=this.value;return _t(n)||(r=n.item,n=n.user),GB(t,n&&n!==YB?n:r||n),r}),{cursor:e})}(n),n.description(t.description),e.hover&&n.hover(),e.container&&n.initialize(e.container,e.bind),e.watchPixelRatio&&n._watchPixelRatio()}function Rz(t,e){return ut(t._signals,e)?t._signals[e]:s("Unrecognized signal name: "+Dt(e))}function Lz(t,e){const n=(t._targets||[]).filter((t=>t._update&&t._update.handler===e));return n.length?n[0]:null}function Uz(t,e,n,r){let i=Lz(n,r);return i||(i=xz(t,(()=>r(e,n.value))),i.handler=r,t.on(n,null,i)),t}function qz(t,e,n){const r=Lz(e,n);return r&&e._targets.remove(r),t}ht(Oz,Ga,{async evaluate(t,e,n){if(await Ga.prototype.evaluate.call(this,t,e),this._redraw||this._resize)try{this._renderer&&(this._resize&&(this._resize=0,function(t){var e=QB(t),n=JB(t),r=ZB(t);t._renderer.background(t.background()),t._renderer.resize(n,r,e),t._handler.origin(e),t._resizeListeners.forEach((e=>{try{e(n,r)}catch(e){t.error(e)}}))}(this)),await this._renderer.renderAsync(this._scenegraph.root)),this._redraw=!1}catch(t){this.error(t)}return n&&ha(this,n),this},dirty(t){this._redraw=!0,this._renderer&&this._renderer.dirty(t)},description(t){if(arguments.length){const e=null!=t?t+"":null;return e!==this._desc&&HB(this._el,this._desc=e),this}return this._desc},container(){return this._el},scenegraph(){return this._scenegraph},origin(){return this._origin.slice()},signal(t,e,n){const r=Rz(this,t);return 1===arguments.length?r.value:this.update(r,e,n)},width(t){return arguments.length?this.signal("width",t):this.signal("width")},height(t){return arguments.length?this.signal("height",t):this.signal("height")},padding(t){return arguments.length?this.signal("padding",kz(t)):kz(this.signal("padding"))},autosize(t){return arguments.length?this.signal("autosize",t):this.signal("autosize")},background(t){return arguments.length?this.signal("background",t):this.signal("background")},renderer(t){return arguments.length?(T_(t)||s("Unrecognized renderer type: "+t),t!==this._renderType&&(this._renderType=t,this._resetRenderer()),this):this._renderType},tooltip(t){return arguments.length?(t!==this._tooltip&&(this._tooltip=t,this._resetRenderer()),this):this._tooltip},loader(t){return arguments.length?(t!==this._loader&&(Ga.prototype.loader.call(this,t),this._resetRenderer()),this):this._loader},resize(){return this._autosize=1,this.touch(Rz(this,"autosize"))},_resetRenderer(){this._renderer&&(this._renderer=null,this.initialize(this._el,this._elBind))},_resizeView:function(t,e,n,r,i,o){this.runAfter((a=>{let s=0;a._autosize=0,a.width()!==n&&(s=1,a.signal(Mz,n,Cz),a._resizeWidth.skip(!0)),a.height()!==r&&(s=1,a.signal(Ez,r,Cz),a._resizeHeight.skip(!0)),a._viewWidth!==t&&(a._resize=1,a._viewWidth=t),a._viewHeight!==e&&(a._resize=1,a._viewHeight=e),a._origin[0]===i[0]&&a._origin[1]===i[1]||(a._resize=1,a._origin=i),s&&a.run("enter"),o&&a.runAfter((t=>t.resize()))}),!1,1)},addEventListener(t,e,n){let r=e;return n&&!1===n.trap||(r=xz(this,e),r.raw=e),this._handler.on(t,r),this},removeEventListener(t,e){for(var n,r,i=this._handler.handlers(t),o=i.length;--o>=0;)if(r=i[o].type,n=i[o].handler,t===r&&(e===n||e===n.raw)){this._handler.off(r,n);break}return this},addResizeListener(t){const e=this._resizeListeners;return e.includes(t)||e.push(t),this},removeResizeListener(t){var e=this._resizeListeners,n=e.indexOf(t);return n>=0&&e.splice(n,1),this},addSignalListener(t,e){return Uz(this,t,Rz(this,t),e)},removeSignalListener(t,e){return qz(this,Rz(this,t),e)},addDataListener(t,e){return Uz(this,t,VB(this,t).values,e)},removeDataListener(t,e){return qz(this,VB(this,t).values,e)},globalCursor(t){if(arguments.length){if(this._globalCursor!==!!t){const e=GB(this,null);this._globalCursor=!!t,e&&GB(this,e)}return this}return this._globalCursor},preventDefault(t){return arguments.length?(this._preventDefault=t,this):this._preventDefault},timer:function(t,e){this._timers.push(function(t,e,n){var r=new lD,i=e;return null==e?(r.restart(t,e,n),r):(r._restart=r.restart,r.restart=function(t,e,n){e=+e,n=null==n?sD():+n,r._restart((function o(a){a+=i,r._restart(o,i+=e,n),t(a)}),e,n)},r.restart(t,e,n),r)}((function(e){t({timestamp:Date.now(),elapsed:e})}),e))},events:function(t,e,n){var r,i=this,o=new Ta(n),a=function(n,r){i.runAsync(null,(()=>{t===tz&&function(t,e){var n=t._eventConfig.defaults,r=n.prevent,i=n.allow;return!1!==r&&!0!==i&&(!0===r||!1===i||(r?r[e]:i?!i[e]:t.preventDefault()))}(i,e)&&n.preventDefault(),o.receive(KB(i,n,r))}))};if("timer"===t)rz(i,"timer",e)&&i.timer(a,e);else if(t===tz)rz(i,"view",e)&&i.addEventListener(e,a,ez);else if("window"===t?rz(i,"window",e)&&"undefined"!=typeof window&&(r=[window]):"undefined"!=typeof document&&rz(i,"selector",e)&&(r=Array.from(document.querySelectorAll(t))),r){for(var s=0,u=r.length;s=0;)a[t].stop();for(t=u.length;--t>=0;)for(e=(n=u[t]).sources.length;--e>=0;)n.sources[e].removeEventListener(n.type,n.handler);for(o&&o.call(this,this._handler,null,null,null),t=s.length;--t>=0;)i=s[t].type,r=s[t].handler,this._handler.off(i,r);return this},hover:function(t,e){return e=[e||"update",(t=[t||"hover"])[0]],this.on(this.events("view","pointerover",iz),oz,az(t)),this.on(this.events("view","pointerout",iz),oz,az(e)),this},data:function(t,e){return arguments.length<2?VB(this,t).values.value:XB.call(this,t,Aa().remove(p).insert(e))},change:XB,insert:function(t,e){return XB.call(this,t,Aa().insert(e))},remove:function(t,e){return XB.call(this,t,Aa().remove(e))},scale:function(t){var e=this._runtime.scales;return ut(e,t)||s("Unrecognized scale or projection: "+t),e[t].value},initialize:function(t,e){const n=this,r=n._renderType,i=n._eventConfig.bind,o=T_(r);t=n._el=t?bz(n,t,!0):null,function(t){const e=t.container();e&&(e.setAttribute("role","graphics-document"),e.setAttribute("aria-roleDescription","visualization"),HB(e,t.description()))}(n),o||n.error("Unrecognized renderer type: "+r);const a=o.handler||Sv,s=t?o.renderer:o.headless;return n._renderer=s?_z(n,n._renderer,t,s):null,n._handler=function(t,e,n,r){const i=new r(t.loader(),xz(t,t.tooltip())).scene(t.scenegraph().root).initialize(n,QB(t),t);return e&&e.handlers().forEach((t=>{i.on(t.type,t.handler)})),i}(n,n._handler,t,a),n._redraw=!0,t&&"none"!==i&&(e=e?n._elBind=bz(n,e,!0):t.appendChild(sz("form",{class:"vega-bindings"})),n._bind.forEach((t=>{t.param.element&&"container"!==i&&(t.element=bz(n,t.param.element,!!t.param.input))})),n._bind.forEach((t=>{!function(t,e,n){if(!e)return;const r=n.param;let i=n.state;i||(i=n.state={elements:null,active:!1,set:null,update:e=>{e!=t.signal(r.signal)&&t.runAsync(null,(()=>{i.source=!0,t.signal(r.signal,e)}))}},r.debounce&&(i.update=it(r.debounce,i.update))),(null==r.input&&r.element?fz:hz)(i,e,r,t),i.active||(t.on(t._signals[r.signal],null,(()=>{i.source?i.source=!1:i.set(t.signal(r.signal))})),i.active=!0)}(n,t.element||e,t)}))),n},toImageURL:async function(t,e){t!==S_.Canvas&&t!==S_.SVG&&t!==S_.PNG&&s("Unrecognized image type: "+t);const n=await Az(this,t,e);return t===S_.SVG?function(t,e){const n=new Blob([t],{type:e});return window.URL.createObjectURL(n)}(n.svg(),"image/svg+xml"):n.canvas().toDataURL("image/png")},toCanvas:async function(t,e){return(await Az(this,S_.Canvas,t,e)).canvas()},toSVG:async function(t){return(await Az(this,S_.SVG,t)).svg()},getState:function(t){return this._runtime.getState(t||{data:$z,signals:Tz,recurse:!0})},setState:function(t){return this.runAsync(null,(e=>{e._trigger=!1,e._runtime.setState(t)}),(t=>{t._trigger=!0})),this},_watchPixelRatio:function(){if("canvas"===this.renderer()&&this._renderer._canvas){let t=null;const e=()=>{null!=t&&t();const n=matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);n.addEventListener("change",e),t=()=>{n.removeEventListener("change",e)},this._renderer._canvas.getContext("2d").pixelRatio=window.devicePixelRatio||1,this._redraw=!0,this._resize=1,this.resize().runAsync()};e()}}});const Pz="view",jz="[",Iz="]",Wz="{",Hz="}",Yz=":",Gz=",",Vz="@",Xz=">",Jz=/[[\]{}]/,Zz={"*":1,arc:1,area:1,group:1,image:1,line:1,path:1,rect:1,rule:1,shape:1,symbol:1,text:1,trail:1};let Qz,Kz;function tN(t,e,n){return Qz=e||Pz,Kz=n||Zz,nN(t.trim()).map(rN)}function eN(t,e,n,r,i){const o=t.length;let a,s=0;for(;e' after between selector: "+t;n=n.map(rN);const i=rN(t.slice(1).trim());if(i.between)return{between:n,stream:i};i.between=n;return i}(t):function(t){const e={source:Qz},n=[];let r,i,o=[0,0],a=0,s=0,u=t.length,l=0;if(t[u-1]===Hz){if(l=t.lastIndexOf(Wz),!(l>=0))throw"Unmatched right brace: "+t;try{o=function(t){const e=t.split(Gz);if(!t.length||e.length>2)throw t;return e.map((e=>{const n=+e;if(n!=n)throw t;return n}))}(t.substring(l+1,u-1))}catch(e){throw"Invalid throttle specification: "+t}u=(t=t.slice(0,l).trim()).length,l=0}if(!u)throw t;t[0]===Vz&&(a=++l);r=eN(t,l,Yz),r1?(e.type=n[1],a?e.markname=n[0].slice(1):!function(t){return Kz[t]}(n[0])?e.source=n[0]:e.marktype=n[0]):e.type=n[0];"!"===e.type.slice(-1)&&(e.consume=!0,e.type=e.type.slice(0,-1));null!=i&&(e.filter=i);o[0]&&(e.throttle=o[0]);o[1]&&(e.debounce=o[1]);return e}(t)}function iN(t){return A(t)?t:{type:t||"pad"}}const oN=t=>+t||0,aN=t=>({top:t,bottom:t,left:t,right:t});function sN(t){return A(t)?t.signal?t:{top:oN(t.top),bottom:oN(t.bottom),left:oN(t.left),right:oN(t.right)}:aN(oN(t))}const uN=t=>A(t)&&!k(t)?ot({},t):{value:t};function lN(t,e,n,r){if(null!=n){return A(n)&&!k(n)||k(n)&&n.length&&A(n[0])?t.update[e]=n:t[r||"enter"][e]={value:n},1}return 0}function cN(t,e,n){for(const n in e)lN(t,n,e[n]);for(const e in n)lN(t,e,n[e],"update")}function fN(t,e,n){for(const r in e)n&&ut(n,r)||(t[r]=ot(t[r]||{},e[r]));return t}function hN(t,e){return e&&(e.enter&&e.enter[t]||e.update&&e.update[t])}const dN="mark",pN="frame",gN="scope",mN="axis",yN="axis-domain",vN="axis-grid",_N="axis-label",xN="axis-tick",bN="axis-title",wN="legend",kN="legend-band",AN="legend-entry",MN="legend-gradient",EN="legend-label",DN="legend-symbol",CN="legend-title",FN="title",SN="title-text",$N="title-subtitle";function TN(t,e,n){t[e]=n&&n.signal?{signal:n.signal}:{value:n}}const BN=t=>_t(t)?Dt(t):t.signal?`(${t.signal})`:RN(t);function zN(t){if(null!=t.gradient)return function(t){const e=[t.start,t.stop,t.count].map((t=>null==t?null:Dt(t)));for(;e.length&&null==F(e);)e.pop();return e.unshift(BN(t.gradient)),`gradient(${e.join(",")})`}(t);let e=t.signal?`(${t.signal})`:t.color?function(t){return t.c?NN("hcl",t.h,t.c,t.l):t.h||t.s?NN("hsl",t.h,t.s,t.l):t.l||t.a?NN("lab",t.l,t.a,t.b):t.r||t.g||t.b?NN("rgb",t.r,t.g,t.b):null}(t.color):null!=t.field?RN(t.field):void 0!==t.value?Dt(t.value):void 0;return null!=t.scale&&(e=function(t,e){const n=BN(t.scale);null!=t.range?e=`lerp(_range(${n}), ${+t.range})`:(void 0!==e&&(e=`_scale(${n}, ${e})`),t.band&&(e=(e?e+"+":"")+`_bandwidth(${n})`+(1==+t.band?"":"*"+ON(t.band)),t.extra&&(e=`(datum.extra ? _scale(${n}, datum.extra.value) : ${e})`)),null==e&&(e="0"));return e}(t,e)),void 0===e&&(e=null),null!=t.exponent&&(e=`pow(${e},${ON(t.exponent)})`),null!=t.mult&&(e+=`*${ON(t.mult)}`),null!=t.offset&&(e+=`+${ON(t.offset)}`),t.round&&(e=`round(${e})`),e}const NN=(t,e,n,r)=>`(${t}(${[e,n,r].map(zN).join(",")})+'')`;function ON(t){return A(t)?"("+zN(t)+")":t}function RN(t){return LN(A(t)?t:{datum:t})}function LN(t){let e,n,r;if(t.signal)e="datum",r=t.signal;else if(t.group||t.parent){for(n=Math.max(1,t.level||1),e="item";n-- >0;)e+=".mark.group";t.parent?(r=t.parent,e+=".datum"):r=t.group}else t.datum?(e="datum",r=t.datum):s("Invalid field reference: "+Dt(t));return t.signal||(r=_t(r)?u(r).map(Dt).join("]["):LN(r)),e+"["+r+"]"}function UN(t,e,n,r,i,o){const a={};(o=o||{}).encoders={$encode:a},t=function(t,e,n,r,i){const o={},a={};let s,u,l,c;for(u in u="lineBreak","text"!==e||null==i[u]||hN(u,t)||TN(o,u,i[u]),("legend"==n||String(n).startsWith("axis"))&&(n=null),c=n===pN?i.group:n===dN?ot({},i.mark,i[e]):null,c)l=hN(u,t)||("fill"===u||"stroke"===u)&&(hN("fill",t)||hN("stroke",t)),l||TN(o,u,c[u]);for(u in V(r).forEach((e=>{const n=i.style&&i.style[e];for(const e in n)hN(e,t)||TN(o,e,n[e])})),t=ot({},t),o)c=o[u],c.signal?(s=s||{})[u]=c:a[u]=c;return t.enter=ot(a,t.enter),s&&(t.update=ot(s,t.update)),t}(t,e,n,r,i.config);for(const n in t)a[n]=qN(t[n],e,o,i);return o}function qN(t,e,n,r){const i={},o={};for(const e in t)null!=t[e]&&(i[e]=PN((a=t[e],k(a)?function(t){let e="";return t.forEach((t=>{const n=zN(t);e+=t.test?`(${t.test})?${n}:`:n})),":"===F(e)&&(e+="null"),e}(a):zN(a)),r,n,o));var a;return{$expr:{marktype:e,channels:i},$fields:Object.keys(o),$output:Object.keys(t)}}function PN(t,e,n,r){const i=BB(t,e);return i.$fields.forEach((t=>r[t]=1)),ot(n,i.$params),i.$expr}const jN="outer",IN=["value","update","init","react","bind"];function WN(t,e){s(t+' for "outer" push: '+Dt(e))}function HN(t,e){const n=t.name;if(t.push===jN)e.signals[n]||WN("No prior signal definition",n),IN.forEach((e=>{void 0!==t[e]&&WN("Invalid property ",e)}));else{const r=e.addSignal(n,t.value);!1===t.react&&(r.react=!1),t.bind&&e.addBinding(n,t.bind)}}function YN(t,e,n,r){this.id=-1,this.type=t,this.value=e,this.params=n,r&&(this.parent=r)}function GN(t,e,n,r){return new YN(t,e,n,r)}function VN(t,e){return GN("operator",t,e)}function XN(t){const e={$ref:t.id};return t.id<0&&(t.refs=t.refs||[]).push(e),e}function JN(t,e){return e?{$field:t,$name:e}:{$field:t}}const ZN=JN("key");function QN(t,e){return{$compare:t,$order:e}}const KN="descending";function tO(t,e){return(t&&t.signal?"$"+t.signal:t||"")+(t&&e?"_":"")+(e&&e.signal?"$"+e.signal:e||"")}const eO="scope",nO="view";function rO(t){return t&&t.signal}function iO(t){if(rO(t))return!0;if(A(t))for(const e in t)if(iO(t[e]))return!0;return!1}function oO(t,e){return null!=t?t:e}function aO(t){return t&&t.signal||t}const sO="timer";function uO(t,e){return(t.merge?lO:t.stream?cO:t.type?fO:s("Invalid stream specification: "+Dt(t)))(t,e)}function lO(t,e){const n=hO({merge:t.merge.map((t=>uO(t,e)))},t,e);return e.addStream(n).id}function cO(t,e){const n=hO({stream:uO(t.stream,e)},t,e);return e.addStream(n).id}function fO(t,e){let n;t.type===sO?(n=e.event(sO,t.throttle),t={between:t.between,filter:t.filter}):n=e.event(function(t){return t===eO?nO:t||nO}(t.source),t.type);const r=hO({stream:n},t,e);return 1===Object.keys(r).length?n:e.addStream(r).id}function hO(t,e,n){let r=e.between;return r&&(2!==r.length&&s('Stream "between" parameter must have 2 entries: '+Dt(e)),t.between=[uO(r[0],n),uO(r[1],n)]),r=e.filter?[].concat(e.filter):[],(e.marktype||e.markname||e.markrole)&&r.push(function(t,e,n){const r="event.item";return r+(t&&"*"!==t?"&&"+r+".mark.marktype==='"+t+"'":"")+(n?"&&"+r+".mark.role==='"+n+"'":"")+(e?"&&"+r+".mark.name==='"+e+"'":"")}(e.marktype,e.markname,e.markrole)),e.source===eO&&r.push("inScope(event.item)"),r.length&&(t.filter=BB("("+r.join(")&&(")+")",n).$expr),null!=(r=e.throttle)&&(t.throttle=+r),null!=(r=e.debounce)&&(t.debounce=+r),e.consume&&(t.consume=!0),t}const dO={code:"_.$value",ast:{type:"Identifier",value:"value"}};function pO(t,e,n){const r=t.encode,i={target:n};let o=t.events,a=t.update,u=[];o||s("Signal update missing events specification."),_t(o)&&(o=tN(o,e.isSubscope()?eO:nO)),o=V(o).filter((t=>t.signal||t.scale?(u.push(t),0):1)),u.length>1&&(u=[gO(u)]),o.length&&u.push(o.length>1?{merge:o}:o[0]),null!=r&&(a&&s("Signal encode and update are mutually exclusive."),a="encode(item(),"+Dt(r)+")"),i.update=_t(a)?BB(a,e):null!=a.expr?BB(a.expr,e):null!=a.value?a.value:null!=a.signal?{$expr:dO,$params:{$value:e.signalRef(a.signal)}}:s("Invalid signal update specification."),t.force&&(i.options={force:!0}),u.forEach((t=>e.addUpdate(ot(function(t,e){return{source:t.signal?e.signalRef(t.signal):t.scale?e.scaleRef(t.scale):uO(t,e)}}(t,e),i))))}function gO(t){return{signal:"["+t.map((t=>t.scale?'scale("'+t.scale+'")':t.signal))+"]"}}const mO=t=>(e,n,r)=>GN(t,n,e||void 0,r),yO=mO("aggregate"),vO=mO("axisticks"),_O=mO("bound"),xO=mO("collect"),bO=mO("compare"),wO=mO("datajoin"),kO=mO("encode"),AO=mO("expression"),MO=mO("facet"),EO=mO("field"),DO=mO("key"),CO=mO("legendentries"),FO=mO("load"),SO=mO("mark"),$O=mO("multiextent"),TO=mO("multivalues"),BO=mO("overlap"),zO=mO("params"),NO=mO("prefacet"),OO=mO("projection"),RO=mO("proxy"),LO=mO("relay"),UO=mO("render"),qO=mO("scale"),PO=mO("sieve"),jO=mO("sortitems"),IO=mO("viewlayout"),WO=mO("values");let HO=0;const YO={min:"min",max:"max",count:"sum"};function GO(t,e){const n=e.getScale(t.name).params;let r;for(r in n.domain=ZO(t.domain,t,e),null!=t.range&&(n.range=oR(t,e,n)),null!=t.interpolate&&function(t,e){e.interpolate=VO(t.type||t),null!=t.gamma&&(e.interpolateGamma=VO(t.gamma))}(t.interpolate,n),null!=t.nice&&(n.nice=function(t,e){return t.signal?e.signalRef(t.signal):A(t)?{interval:VO(t.interval),step:VO(t.step)}:VO(t)}(t.nice,e)),null!=t.bins&&(n.bins=function(t,e){return t.signal||k(t)?XO(t,e):e.objectProperty(t)}(t.bins,e)),t)ut(n,r)||"name"===r||(n[r]=VO(t[r],e))}function VO(t,e){return A(t)?t.signal?e.signalRef(t.signal):s("Unsupported object: "+Dt(t)):t}function XO(t,e){return t.signal?e.signalRef(t.signal):t.map((t=>VO(t,e)))}function JO(t){s("Can not find data set: "+Dt(t))}function ZO(t,e,n){if(t)return t.signal?n.signalRef(t.signal):(k(t)?QO:t.fields?tR:KO)(t,e,n);null==e.domainMin&&null==e.domainMax||s("No scale domain defined for domainMin/domainMax to override.")}function QO(t,e,n){return t.map((t=>VO(t,n)))}function KO(t,e,n){const r=n.getData(t.data);return r||JO(t.data),cp(e.type)?r.valuesRef(n,t.field,nR(t.sort,!1)):pp(e.type)?r.domainRef(n,t.field):r.extentRef(n,t.field)}function tR(t,e,n){const r=t.data,i=t.fields.reduce(((t,e)=>(e=_t(e)?{data:r,field:e}:k(e)||e.signal?function(t,e){const n="_:vega:_"+HO++,r=xO({});if(k(t))r.value={$ingest:t};else if(t.signal){const i="setdata("+Dt(n)+","+t.signal+")";r.params.input=e.signalRef(i)}return e.addDataPipeline(n,[r,PO({})]),{data:n,field:"data"}}(e,n):e,t.push(e),t)),[]);return(cp(e.type)?eR:pp(e.type)?rR:iR)(t,n,i)}function eR(t,e,n){const r=nR(t.sort,!0);let i,o;const a=n.map((t=>{const n=e.getData(t.data);return n||JO(t.data),n.countsRef(e,t.field,r)})),s={groupby:ZN,pulse:a};r&&(i=r.op||"count",o=r.field?tO(i,r.field):"count",s.ops=[YO[i]],s.fields=[e.fieldRef(o)],s.as=[o]),i=e.add(yO(s));const u=e.add(xO({pulse:XN(i)}));return o=e.add(WO({field:ZN,sort:e.sortRef(r),pulse:XN(u)})),XN(o)}function nR(t,e){return t&&(t.field||t.op?t.field||"count"===t.op?e&&t.field&&t.op&&!YO[t.op]&&s("Multiple domain scales can not be sorted using "+t.op):s("No field provided for sort aggregate op: "+t.op):A(t)?t.field="key":t={field:"key"}),t}function rR(t,e,n){const r=n.map((t=>{const n=e.getData(t.data);return n||JO(t.data),n.domainRef(e,t.field)}));return XN(e.add(TO({values:r})))}function iR(t,e,n){const r=n.map((t=>{const n=e.getData(t.data);return n||JO(t.data),n.extentRef(e,t.field)}));return XN(e.add($O({extents:r})))}function oR(t,e,n){const r=e.config.range;let i=t.range;if(i.signal)return e.signalRef(i.signal);if(_t(i)){if(r&&ut(r,i))return oR(t=ot({},t,{range:r[i]}),e,n);"width"===i?i=[0,{signal:"width"}]:"height"===i?i=cp(t.type)?[0,{signal:"height"}]:[{signal:"height"},0]:s("Unrecognized scale range value: "+Dt(i))}else{if(i.scheme)return n.scheme=k(i.scheme)?XO(i.scheme,e):VO(i.scheme,e),i.extent&&(n.schemeExtent=XO(i.extent,e)),void(i.count&&(n.schemeCount=VO(i.count,e)));if(i.step)return void(n.rangeStep=VO(i.step,e));if(cp(t.type)&&!k(i))return ZO(i,t,e);k(i)||s("Unsupported range type: "+Dt(i))}return i.map((t=>(k(t)?XO:VO)(t,e)))}function aR(t,e,n){return k(t)?t.map((t=>aR(t,e,n))):A(t)?t.signal?n.signalRef(t.signal):"fit"===e?t:s("Unsupported parameter object: "+Dt(t)):t}const sR="top",uR="left",lR="right",cR="bottom",fR="center",hR="vertical",dR="start",pR="end",gR="index",mR="label",yR="offset",vR="perc",_R="perc2",xR="value",bR="guide-label",wR="guide-title",kR="group-title",AR="group-subtitle",MR="symbol",ER="gradient",DR="discrete",CR="size",FR=[CR,"shape","fill","stroke","strokeWidth","strokeDash","opacity"],SR={name:1,style:1,interactive:1},$R={value:0},TR={value:1},BR="group",zR="rect",NR="rule",OR="symbol",RR="text";function LR(t){return t.type=BR,t.interactive=t.interactive||!1,t}function UR(t,e){const n=(n,r)=>oO(t[n],oO(e[n],r));return n.isVertical=n=>hR===oO(t.direction,e.direction||(n?e.symbolDirection:e.gradientDirection)),n.gradientLength=()=>oO(t.gradientLength,e.gradientLength||e.gradientWidth),n.gradientThickness=()=>oO(t.gradientThickness,e.gradientThickness||e.gradientHeight),n.entryColumns=()=>oO(t.columns,oO(e.columns,+n.isVertical(!0))),n}function qR(t,e){const n=e&&(e.update&&e.update[t]||e.enter&&e.enter[t]);return n&&n.signal?n:n?n.value:null}function PR(t,e,n){return`item.anchor === '${dR}' ? ${t} : item.anchor === '${pR}' ? ${e} : ${n}`}const jR=PR(Dt(uR),Dt(lR),Dt(fR));function IR(t,e){return e?t?A(t)?Object.assign({},t,{offset:IR(t.offset,e)}):{value:t,offset:e}:e:t}function WR(t,e){return e?(t.name=e.name,t.style=e.style||t.style,t.interactive=!!e.interactive,t.encode=fN(t.encode,e,SR)):t.interactive=!1,t}function HR(t,e,n,r){const i=UR(t,n),o=i.isVertical(),a=i.gradientThickness(),s=i.gradientLength();let u,l,c,f,h;o?(l=[0,1],c=[0,0],f=a,h=s):(l=[0,0],c=[1,0],f=s,h=a);const d={enter:u={opacity:$R,x:$R,y:$R,width:uN(f),height:uN(h)},update:ot({},u,{opacity:TR,fill:{gradient:e,start:l,stop:c}}),exit:{opacity:$R}};return cN(d,{stroke:i("gradientStrokeColor"),strokeWidth:i("gradientStrokeWidth")},{opacity:i("gradientOpacity")}),WR({type:zR,role:MN,encode:d},r)}function YR(t,e,n,r,i){const o=UR(t,n),a=o.isVertical(),s=o.gradientThickness(),u=o.gradientLength();let l,c,f,h,d="";a?(l="y",f="y2",c="x",h="width",d="1-"):(l="x",f="x2",c="y",h="height");const p={opacity:$R,fill:{scale:e,field:xR}};p[l]={signal:d+"datum."+vR,mult:u},p[c]=$R,p[f]={signal:d+"datum."+_R,mult:u},p[h]=uN(s);const g={enter:p,update:ot({},p,{opacity:TR}),exit:{opacity:$R}};return cN(g,{stroke:o("gradientStrokeColor"),strokeWidth:o("gradientStrokeWidth")},{opacity:o("gradientOpacity")}),WR({type:zR,role:kN,key:xR,from:i,encode:g},r)}const GR=`datum.${vR}<=0?"${uR}":datum.${vR}>=1?"${lR}":"${fR}"`,VR=`datum.${vR}<=0?"${cR}":datum.${vR}>=1?"${sR}":"middle"`;function XR(t,e,n,r){const i=UR(t,e),o=i.isVertical(),a=uN(i.gradientThickness()),s=i.gradientLength();let u,l,c,f,h=i("labelOverlap"),d="";const p={enter:u={opacity:$R},update:l={opacity:TR,text:{field:mR}},exit:{opacity:$R}};return cN(p,{fill:i("labelColor"),fillOpacity:i("labelOpacity"),font:i("labelFont"),fontSize:i("labelFontSize"),fontStyle:i("labelFontStyle"),fontWeight:i("labelFontWeight"),limit:oO(t.labelLimit,e.gradientLabelLimit)}),o?(u.align={value:"left"},u.baseline=l.baseline={signal:VR},c="y",f="x",d="1-"):(u.align=l.align={signal:GR},u.baseline={value:"top"},c="x",f="y"),u[c]=l[c]={signal:d+"datum."+vR,mult:s},u[f]=l[f]=a,a.offset=oO(t.labelOffset,e.gradientLabelOffset)||0,h=h?{separation:i("labelSeparation"),method:h,order:"datum."+gR}:void 0,WR({type:RR,role:EN,style:bR,key:xR,from:r,encode:p,overlap:h},n)}function JR(t,e,n,r,i){const o=UR(t,e),a=n.entries,s=!(!a||!a.interactive),u=a?a.name:void 0,l=o("clipHeight"),c=o("symbolOffset"),f={data:"value"},h=`(${i}) ? datum.${yR} : datum.${CR}`,d=l?uN(l):{field:CR},p=`datum.${gR}`,g=`max(1, ${i})`;let m,y,v,_,x;d.mult=.5,m={enter:y={opacity:$R,x:{signal:h,mult:.5,offset:c},y:d},update:v={opacity:TR,x:y.x,y:y.y},exit:{opacity:$R}};let b=null,w=null;t.fill||(b=e.symbolBaseFillColor,w=e.symbolBaseStrokeColor),cN(m,{fill:o("symbolFillColor",b),shape:o("symbolType"),size:o("symbolSize"),stroke:o("symbolStrokeColor",w),strokeDash:o("symbolDash"),strokeDashOffset:o("symbolDashOffset"),strokeWidth:o("symbolStrokeWidth")},{opacity:o("symbolOpacity")}),FR.forEach((e=>{t[e]&&(v[e]=y[e]={scale:t[e],field:xR})}));const k=WR({type:OR,role:DN,key:xR,from:f,clip:!!l||void 0,encode:m},n.symbols),A=uN(c);A.offset=o("labelOffset"),m={enter:y={opacity:$R,x:{signal:h,offset:A},y:d},update:v={opacity:TR,text:{field:mR},x:y.x,y:y.y},exit:{opacity:$R}},cN(m,{align:o("labelAlign"),baseline:o("labelBaseline"),fill:o("labelColor"),fillOpacity:o("labelOpacity"),font:o("labelFont"),fontSize:o("labelFontSize"),fontStyle:o("labelFontStyle"),fontWeight:o("labelFontWeight"),limit:o("labelLimit")});const M=WR({type:RR,role:EN,style:bR,key:xR,from:f,encode:m},n.labels);return m={enter:{noBound:{value:!l},width:$R,height:l?uN(l):$R,opacity:$R},exit:{opacity:$R},update:v={opacity:TR,row:{signal:null},column:{signal:null}}},o.isVertical(!0)?(_=`ceil(item.mark.items.length / ${g})`,v.row.signal=`${p}%${_}`,v.column.signal=`floor(${p} / ${_})`,x={field:["row",p]}):(v.row.signal=`floor(${p} / ${g})`,v.column.signal=`${p} % ${g}`,x={field:p}),v.column.signal=`(${i})?${v.column.signal}:${p}`,LR({role:gN,from:r={facet:{data:r,name:"value",groupby:gR}},encode:fN(m,a,SR),marks:[k,M],name:u,interactive:s,sort:x})}const ZR='item.orient === "left"',QR='item.orient === "right"',KR=`(${ZR} || ${QR})`,tL=`datum.vgrad && ${KR}`,eL=PR('"top"','"bottom"','"middle"'),nL=`datum.vgrad && ${QR} ? (${PR('"right"','"left"','"center"')}) : (${KR} && !(datum.vgrad && ${ZR})) ? "left" : ${jR}`,rL=`item._anchor || (${KR} ? "middle" : "start")`,iL=`${tL} ? (${ZR} ? -90 : 90) : 0`,oL=`${KR} ? (datum.vgrad ? (${QR} ? "bottom" : "top") : ${eL}) : "top"`;function aL(t,e){let n;return A(t)&&(t.signal?n=t.signal:t.path?n="pathShape("+sL(t.path)+")":t.sphere&&(n="geoShape("+sL(t.sphere)+', {type: "Sphere"})')),n?e.signalRef(n):!!t}function sL(t){return A(t)&&t.signal?t.signal:Dt(t)}function uL(t){const e=t.role||"";return e.startsWith("axis")||e.startsWith("legend")||e.startsWith("title")?e:t.type===BR?gN:e||dN}function lL(t){return{marktype:t.type,name:t.name||void 0,role:t.role||uL(t),zindex:+t.zindex||void 0,aria:t.aria,description:t.description}}function cL(t,e){return t&&t.signal?e.signalRef(t.signal):!1!==t}function fL(t,e){const n=Za(t.type);n||s("Unrecognized transform type: "+Dt(t.type));const r=GN(n.type.toLowerCase(),null,hL(n,t,e));return t.signal&&e.addSignal(t.signal,e.proxy(r)),r.metadata=n.metadata||{},r}function hL(t,e,n){const r={},i=t.params.length;for(let o=0;ogL(t,e,n)))):gL(t,r,n)}(t,e,n):"projection"===r?n.projectionRef(e[t.name]):t.array&&!rO(i)?i.map((e=>pL(t,e,n))):pL(t,i,n):void(t.required&&s("Missing required "+Dt(e.type)+" parameter: "+Dt(t.name)))}function pL(t,e,n){const r=t.type;if(rO(e))return _L(r)?s("Expression references can not be signals."):xL(r)?n.fieldRef(e):bL(r)?n.compareRef(e):n.signalRef(e.signal);{const i=t.expr||xL(r);return i&&mL(e)?n.exprRef(e.expr,e.as):i&&yL(e)?JN(e.field,e.as):_L(r)?BB(e,n):vL(r)?XN(n.getData(e).values):xL(r)?JN(e):bL(r)?n.compareRef(e):e}}function gL(t,e,n){const r=t.params.length;let i;for(let n=0;nt&&t.expr,yL=t=>t&&t.field,vL=t=>"data"===t,_L=t=>"expr"===t,xL=t=>"field"===t,bL=t=>"compare"===t;function wL(t,e){return t.$ref?t:t.data&&t.data.$ref?t.data:XN(e.getData(t.data).output)}function kL(t,e,n,r,i){this.scope=t,this.input=e,this.output=n,this.values=r,this.aggregate=i,this.index={}}function AL(t){return _t(t)?t:null}function ML(t,e,n){const r=tO(n.op,n.field);let i;if(e.ops){for(let t=0,n=e.as.length;tnull==t?"null":t)).join(",")+"),0)",e);u.update=l.$expr,u.params=l.$params}function CL(t,e){const n=uL(t),r=t.type===BR,i=t.from&&t.from.facet,o=t.overlap;let a,u,l,c,f,h,d,p=t.layout||n===gN||n===pN;const g=n===dN||p||i,m=function(t,e,n){let r,i,o,a,u;return t?(r=t.facet)&&(e||s("Only group marks can be faceted."),null!=r.field?a=u=wL(r,n):(t.data?u=XN(n.getData(t.data).aggregate):(o=fL(ot({type:"aggregate",groupby:V(r.groupby)},r.aggregate),n),o.params.key=n.keyRef(r.groupby),o.params.pulse=wL(r,n),a=u=XN(n.add(o))),i=n.keyRef(r.groupby,!0))):a=XN(n.add(xO(null,[{}]))),a||(a=wL(t,n)),{key:i,pulse:a,parent:u}}(t.from,r,e);u=e.add(wO({key:m.key||(t.key?JN(t.key):void 0),pulse:m.pulse,clean:!r}));const y=XN(u);u=l=e.add(xO({pulse:y})),u=e.add(SO({markdef:lL(t),interactive:cL(t.interactive,e),clip:aL(t.clip,e),context:{$context:!0},groups:e.lookup(),parent:e.signals.parent?e.signalRef("parent"):null,index:e.markpath(),pulse:XN(u)}));const v=XN(u);u=c=e.add(kO(UN(t.encode,t.type,n,t.style,e,{mod:!1,pulse:v}))),u.params.parent=e.encode(),t.transform&&t.transform.forEach((t=>{const n=fL(t,e),r=n.metadata;(r.generates||r.changes)&&s("Mark transforms should not generate new data."),r.nomod||(c.params.mod=!0),n.params.pulse=XN(u),e.add(u=n)})),t.sort&&(u=e.add(jO({sort:e.compareRef(t.sort),pulse:XN(u)})));const _=XN(u);(i||p)&&(p=e.add(IO({layout:e.objectProperty(t.layout),legends:e.legends,mark:v,pulse:_})),h=XN(p));const x=e.add(_O({mark:v,pulse:h||_}));d=XN(x),r&&(g&&(a=e.operators,a.pop(),p&&a.pop()),e.pushState(_,h||d,y),i?function(t,e,n){const r=t.from.facet,i=r.name,o=wL(r,e);let a;r.name||s("Facet must have a name: "+Dt(r)),r.data||s("Facet must reference a data set: "+Dt(r)),r.field?a=e.add(NO({field:e.fieldRef(r.field),pulse:o})):r.groupby?a=e.add(MO({key:e.keyRef(r.groupby),group:XN(e.proxy(n.parent)),pulse:o})):s("Facet must specify groupby or field: "+Dt(r));const u=e.fork(),l=u.add(xO()),c=u.add(PO({pulse:XN(l)}));u.addData(i,new kL(u,l,l,c)),u.addSignal("parent",null),a.params.subflow={$subflow:u.parse(t).toRuntime()}}(t,e,m):g?function(t,e,n){const r=e.add(NO({pulse:n.pulse})),i=e.fork();i.add(PO()),i.addSignal("parent",null),r.params.subflow={$subflow:i.parse(t).toRuntime()}}(t,e,m):e.parse(t),e.popState(),g&&(p&&a.push(p),a.push(x))),o&&(d=function(t,e,n){const r=t.method,i=t.bound,o=t.separation,a={separation:rO(o)?n.signalRef(o.signal):o,method:rO(r)?n.signalRef(r.signal):r,pulse:e};t.order&&(a.sort=n.compareRef({field:t.order}));if(i){const t=i.tolerance;a.boundTolerance=rO(t)?n.signalRef(t.signal):+t,a.boundScale=n.scaleRef(i.scale),a.boundOrient=i.orient}return XN(n.add(BO(a)))}(o,d,e));const b=e.add(UO({pulse:d})),w=e.add(PO({pulse:XN(b)},void 0,e.parent()));null!=t.name&&(f=t.name,e.addData(f,new kL(e,l,b,w)),t.on&&t.on.forEach((t=>{(t.insert||t.remove||t.toggle)&&s("Marks only support modify triggers."),DL(t,e,f)})))}function FL(t,e){const n=e.config.legend,r=t.encode||{},i=UR(t,n),o=r.legend||{},a=o.name||void 0,u=o.interactive,l=o.style,c={};let f,h,d,p=0;FR.forEach((e=>t[e]?(c[e]=t[e],p=p||t[e]):0)),p||s("Missing valid scale for legend.");const g=function(t,e){let n=t.type||MR;t.type||1!==function(t){return FR.reduce(((e,n)=>e+(t[n]?1:0)),0)}(t)||!t.fill&&!t.stroke||(n=lp(e)?ER:fp(e)?DR:MR);return n!==ER?n:fp(e)?DR:ER}(t,e.scaleType(p)),m={title:null!=t.title,scales:c,type:g,vgrad:"symbol"!==g&&i.isVertical()},y=XN(e.add(xO(null,[m]))),v=XN(e.add(CO(h={type:g,scale:e.scaleRef(p),count:e.objectProperty(i("tickCount")),limit:e.property(i("symbolLimit")),values:e.objectProperty(t.values),minstep:e.property(t.tickMinStep),formatType:e.property(t.formatType),formatSpecifier:e.property(t.format)})));return g===ER?(d=[HR(t,p,n,r.gradient),XR(t,n,r.labels,v)],h.count=h.count||e.signalRef(`max(2,2*floor((${aO(i.gradientLength())})/100))`)):g===DR?d=[YR(t,p,n,r.gradient,v),XR(t,n,r.labels,v)]:(f=function(t,e){const n=UR(t,e);return{align:n("gridAlign"),columns:n.entryColumns(),center:{row:!0,column:!1},padding:{row:n("rowPadding"),column:n("columnPadding")}}}(t,n),d=[JR(t,n,r,v,aO(f.columns))],h.size=function(t,e,n){const r=aO($L("size",t,n)),i=aO($L("strokeWidth",t,n)),o=aO(function(t,e,n){return qR("fontSize",t)||function(t,e,n){const r=e.config.style[n];return r&&r[t]}("fontSize",e,n)}(n[1].encode,e,bR));return BB(`max(ceil(sqrt(${r})+${i}),${o})`,e)}(t,e,d[0].marks)),d=[LR({role:AN,from:y,encode:{enter:{x:{value:0},y:{value:0}}},marks:d,layout:f,interactive:u})],m.title&&d.push(function(t,e,n,r){const i=UR(t,e),o={enter:{opacity:$R},update:{opacity:TR,x:{field:{group:"padding"}},y:{field:{group:"padding"}}},exit:{opacity:$R}};return cN(o,{orient:i("titleOrient"),_anchor:i("titleAnchor"),anchor:{signal:rL},angle:{signal:iL},align:{signal:nL},baseline:{signal:oL},text:t.title,fill:i("titleColor"),fillOpacity:i("titleOpacity"),font:i("titleFont"),fontSize:i("titleFontSize"),fontStyle:i("titleFontStyle"),fontWeight:i("titleFontWeight"),limit:i("titleLimit"),lineHeight:i("titleLineHeight")},{align:i("titleAlign"),baseline:i("titleBaseline")}),WR({type:RR,role:CN,style:wR,from:r,encode:o},n)}(t,n,r.title,y)),CL(LR({role:wN,from:y,encode:fN(SL(i,t,n),o,SR),marks:d,aria:i("aria"),description:i("description"),zindex:i("zindex"),name:a,interactive:u,style:l}),e)}function SL(t,e,n){const r={enter:{},update:{}};return cN(r,{orient:t("orient"),offset:t("offset"),padding:t("padding"),titlePadding:t("titlePadding"),cornerRadius:t("cornerRadius"),fill:t("fillColor"),stroke:t("strokeColor"),strokeWidth:n.strokeWidth,strokeDash:n.strokeDash,x:t("legendX"),y:t("legendY"),format:e.format,formatType:e.formatType}),r}function $L(t,e,n){return e[t]?`scale("${e[t]}",datum)`:qR(t,n[0].encode)}kL.fromEntries=function(t,e){const n=e.length,r=e[n-1],i=e[n-2];let o=e[0],a=null,s=1;for(o&&"load"===o.type&&(o=e[1]),t.add(e[0]);s{n.push(fL(t,e))})),t.on&&t.on.forEach((n=>{DL(n,e,t.name)})),e.addDataPipeline(t.name,function(t,e,n){const r=[];let i,o,a,s,u,l=null,c=!1,f=!1;t.values?rO(t.values)||iO(t.format)?(r.push(RL(e,t)),r.push(l=OL())):r.push(l=OL({$ingest:t.values,$format:t.format})):t.url?iO(t.url)||iO(t.format)?(r.push(RL(e,t)),r.push(l=OL())):r.push(l=OL({$request:t.url,$format:t.format})):t.source&&(l=i=V(t.source).map((t=>XN(e.getData(t).output))),r.push(null));for(o=0,a=n.length;ot===cR||t===sR,UL=(t,e,n)=>rO(t)?YL(t.signal,e,n):t===uR||t===sR?e:n,qL=(t,e,n)=>rO(t)?WL(t.signal,e,n):LL(t)?e:n,PL=(t,e,n)=>rO(t)?HL(t.signal,e,n):LL(t)?n:e,jL=(t,e,n)=>rO(t)?GL(t.signal,e,n):t===sR?{value:e}:{value:n},IL=(t,e,n)=>rO(t)?VL(t.signal,e,n):t===lR?{value:e}:{value:n},WL=(t,e,n)=>XL(`${t} === '${sR}' || ${t} === '${cR}'`,e,n),HL=(t,e,n)=>XL(`${t} !== '${sR}' && ${t} !== '${cR}'`,e,n),YL=(t,e,n)=>ZL(`${t} === '${uR}' || ${t} === '${sR}'`,e,n),GL=(t,e,n)=>ZL(`${t} === '${sR}'`,e,n),VL=(t,e,n)=>ZL(`${t} === '${lR}'`,e,n),XL=(t,e,n)=>(e=null!=e?uN(e):e,n=null!=n?uN(n):n,JL(e)&&JL(n)?{signal:`${t} ? (${e=e?e.signal||Dt(e.value):null}) : (${n=n?n.signal||Dt(n.value):null})`}:[ot({test:t},e)].concat(n||[])),JL=t=>null==t||1===Object.keys(t).length,ZL=(t,e,n)=>({signal:`${t} ? (${KL(e)}) : (${KL(n)})`}),QL=(t,e,n,r,i)=>({signal:(null!=r?`${t} === '${uR}' ? (${KL(r)}) : `:"")+(null!=n?`${t} === '${cR}' ? (${KL(n)}) : `:"")+(null!=i?`${t} === '${lR}' ? (${KL(i)}) : `:"")+(null!=e?`${t} === '${sR}' ? (${KL(e)}) : `:"")+"(null)"}),KL=t=>rO(t)?t.signal:null==t?null:Dt(t),tU=(t,e)=>0===e?0:rO(t)?{signal:`(${t.signal}) * ${e}`}:{value:t*e},eU=(t,e)=>{const n=t.signal;return n&&n.endsWith("(null)")?{signal:n.slice(0,-6)+e.signal}:t};function nU(t,e,n,r){let i;if(e&&ut(e,t))return e[t];if(ut(n,t))return n[t];if(t.startsWith("title")){switch(t){case"titleColor":i="fill";break;case"titleFont":case"titleFontSize":case"titleFontWeight":i=t[5].toLowerCase()+t.slice(6)}return r[wR][i]}if(t.startsWith("label")){switch(t){case"labelColor":i="fill";break;case"labelFont":case"labelFontSize":i=t[5].toLowerCase()+t.slice(6)}return r[bR][i]}return null}function rU(t){const e={};for(const n of t)if(n)for(const t in n)e[t]=1;return Object.keys(e)}function iU(t,e){return{scale:t.scale,range:e}}function oU(t,e,n,r,i){const o=UR(t,e),a=t.orient,s=t.gridScale,u=UL(a,1,-1),l=function(t,e){if(1===e);else if(A(t)){let n=t=ot({},t);for(;null!=n.mult;){if(!A(n.mult))return n.mult=rO(e)?{signal:`(${n.mult}) * (${e.signal})`}:n.mult*e,t;n=n.mult=ot({},n.mult)}n.mult=e}else t=rO(e)?{signal:`(${e.signal}) * (${t||0})`}:e*(t||0);return t}(t.offset,u);let c,f,h;const d={enter:c={opacity:$R},update:h={opacity:TR},exit:f={opacity:$R}};cN(d,{stroke:o("gridColor"),strokeCap:o("gridCap"),strokeDash:o("gridDash"),strokeDashOffset:o("gridDashOffset"),strokeOpacity:o("gridOpacity"),strokeWidth:o("gridWidth")});const p={scale:t.scale,field:xR,band:i.band,extra:i.extra,offset:i.offset,round:o("tickRound")},g=qL(a,{signal:"height"},{signal:"width"}),m=s?{scale:s,range:0,mult:u,offset:l}:{value:0,offset:l},y=s?{scale:s,range:1,mult:u,offset:l}:ot(g,{mult:u,offset:l});return c.x=h.x=qL(a,p,m),c.y=h.y=PL(a,p,m),c.x2=h.x2=PL(a,y),c.y2=h.y2=qL(a,y),f.x=qL(a,p),f.y=PL(a,p),WR({type:NR,role:vN,key:xR,from:r,encode:d},n)}function aU(t,e,n,r,i){return{signal:'flush(range("'+t+'"), scale("'+t+'", datum.value), '+e+","+n+","+r+","+i+")"}}function sU(t,e,n,r){const i=UR(t,e),o=t.orient,a=UL(o,-1,1);let s,u;const l={enter:s={opacity:$R,anchor:uN(i("titleAnchor",null)),align:{signal:jR}},update:u=ot({},s,{opacity:TR,text:uN(t.title)}),exit:{opacity:$R}},c={signal:`lerp(range("${t.scale}"), ${PR(0,1,.5)})`};return u.x=qL(o,c),u.y=PL(o,c),s.angle=qL(o,$R,tU(a,90)),s.baseline=qL(o,jL(o,cR,sR),{value:cR}),u.angle=s.angle,u.baseline=s.baseline,cN(l,{fill:i("titleColor"),fillOpacity:i("titleOpacity"),font:i("titleFont"),fontSize:i("titleFontSize"),fontStyle:i("titleFontStyle"),fontWeight:i("titleFontWeight"),limit:i("titleLimit"),lineHeight:i("titleLineHeight")},{align:i("titleAlign"),angle:i("titleAngle"),baseline:i("titleBaseline")}),function(t,e,n,r){const i=(t,e)=>null!=t?(n.update[e]=eU(uN(t),n.update[e]),!1):!hN(e,r),o=i(t("titleX"),"x"),a=i(t("titleY"),"y");n.enter.auto=a===o?uN(a):qL(e,uN(a),uN(o))}(i,o,l,n),l.update.align=eU(l.update.align,s.align),l.update.angle=eU(l.update.angle,s.angle),l.update.baseline=eU(l.update.baseline,s.baseline),WR({type:RR,role:bN,style:wR,from:r,encode:l},n)}function uU(t,e){const n=function(t,e){var n,r,i,o=e.config,a=o.style,s=o.axis,u="band"===e.scaleType(t.scale)&&o.axisBand,l=t.orient;if(rO(l)){const t=rU([o.axisX,o.axisY]),e=rU([o.axisTop,o.axisBottom,o.axisLeft,o.axisRight]);for(i of(n={},t))n[i]=qL(l,nU(i,o.axisX,s,a),nU(i,o.axisY,s,a));for(i of(r={},e))r[i]=QL(l.signal,nU(i,o.axisTop,s,a),nU(i,o.axisBottom,s,a),nU(i,o.axisLeft,s,a),nU(i,o.axisRight,s,a))}else n=l===sR||l===cR?o.axisX:o.axisY,r=o["axis"+l[0].toUpperCase()+l.slice(1)];return n||r||u?ot({},s,n,r,u):s}(t,e),r=t.encode||{},i=r.axis||{},o=i.name||void 0,a=i.interactive,s=i.style,u=UR(t,n),l=function(t){const e=t("tickBand");let n,r,i=t("tickOffset");return e?e.signal?(n={signal:`(${e.signal}) === 'extent' ? 1 : 0.5`},r={signal:`(${e.signal}) === 'extent'`},A(i)||(i={signal:`(${e.signal}) === 'extent' ? 0 : ${i}`})):"extent"===e?(n=1,r=!0,i=0):(n=.5,r=!1):(n=t("bandPosition"),r=t("tickExtra")),{extra:r,band:n,offset:i}}(u),c={scale:t.scale,ticks:!!u("ticks"),labels:!!u("labels"),grid:!!u("grid"),domain:!!u("domain"),title:null!=t.title},f=XN(e.add(xO({},[c]))),h=XN(e.add(vO({scale:e.scaleRef(t.scale),extra:e.property(l.extra),count:e.objectProperty(t.tickCount),values:e.objectProperty(t.values),minstep:e.property(t.tickMinStep),formatType:e.property(t.formatType),formatSpecifier:e.property(t.format)}))),d=[];let p;return c.grid&&d.push(oU(t,n,r.grid,h,l)),c.ticks&&(p=u("tickSize"),d.push(function(t,e,n,r,i,o){const a=UR(t,e),s=t.orient,u=UL(s,-1,1);let l,c,f;const h={enter:l={opacity:$R},update:f={opacity:TR},exit:c={opacity:$R}};cN(h,{stroke:a("tickColor"),strokeCap:a("tickCap"),strokeDash:a("tickDash"),strokeDashOffset:a("tickDashOffset"),strokeOpacity:a("tickOpacity"),strokeWidth:a("tickWidth")});const d=uN(i);d.mult=u;const p={scale:t.scale,field:xR,band:o.band,extra:o.extra,offset:o.offset,round:a("tickRound")};return f.y=l.y=qL(s,$R,p),f.y2=l.y2=qL(s,d),c.x=qL(s,p),f.x=l.x=PL(s,$R,p),f.x2=l.x2=PL(s,d),c.y=PL(s,p),WR({type:NR,role:xN,key:xR,from:r,encode:h},n)}(t,n,r.ticks,h,p,l))),c.labels&&(p=c.ticks?p:0,d.push(function(t,e,n,r,i,o){const a=UR(t,e),s=t.orient,u=t.scale,l=UL(s,-1,1),c=aO(a("labelFlush")),f=aO(a("labelFlushOffset")),h=a("labelAlign"),d=a("labelBaseline");let p,g=0===c||!!c;const m=uN(i);m.mult=l,m.offset=uN(a("labelPadding")||0),m.offset.mult=l;const y={scale:u,field:xR,band:.5,offset:IR(o.offset,a("labelOffset"))},v=qL(s,g?aU(u,c,'"left"','"right"','"center"'):{value:"center"},IL(s,"left","right")),_=qL(s,jL(s,"bottom","top"),g?aU(u,c,'"top"','"bottom"','"middle"'):{value:"middle"}),x=aU(u,c,`-(${f})`,f,0);g=g&&f;const b={opacity:$R,x:qL(s,y,m),y:PL(s,y,m)},w={enter:b,update:p={opacity:TR,text:{field:mR},x:b.x,y:b.y,align:v,baseline:_},exit:{opacity:$R,x:b.x,y:b.y}};cN(w,{dx:!h&&g?qL(s,x):null,dy:!d&&g?PL(s,x):null}),cN(w,{angle:a("labelAngle"),fill:a("labelColor"),fillOpacity:a("labelOpacity"),font:a("labelFont"),fontSize:a("labelFontSize"),fontWeight:a("labelFontWeight"),fontStyle:a("labelFontStyle"),limit:a("labelLimit"),lineHeight:a("labelLineHeight")},{align:h,baseline:d});const k=a("labelBound");let A=a("labelOverlap");return A=A||k?{separation:a("labelSeparation"),method:A,order:"datum.index",bound:k?{scale:u,orient:s,tolerance:k}:null}:void 0,p.align!==v&&(p.align=eU(p.align,v)),p.baseline!==_&&(p.baseline=eU(p.baseline,_)),WR({type:RR,role:_N,style:bR,key:xR,from:r,encode:w,overlap:A},n)}(t,n,r.labels,h,p,l))),c.domain&&d.push(function(t,e,n,r){const i=UR(t,e),o=t.orient;let a,s;const u={enter:a={opacity:$R},update:s={opacity:TR},exit:{opacity:$R}};cN(u,{stroke:i("domainColor"),strokeCap:i("domainCap"),strokeDash:i("domainDash"),strokeDashOffset:i("domainDashOffset"),strokeWidth:i("domainWidth"),strokeOpacity:i("domainOpacity")});const l=iU(t,0),c=iU(t,1);return a.x=s.x=qL(o,l,$R),a.x2=s.x2=qL(o,c),a.y=s.y=PL(o,l,$R),a.y2=s.y2=PL(o,c),WR({type:NR,role:yN,from:r,encode:u},n)}(t,n,r.domain,f)),c.title&&d.push(sU(t,n,r.title,f)),CL(LR({role:mN,from:f,encode:fN(lU(u,t),i,SR),marks:d,aria:u("aria"),description:u("description"),zindex:u("zindex"),name:o,interactive:a,style:s}),e)}function lU(t,e){const n={enter:{},update:{}};return cN(n,{orient:t("orient"),offset:t("offset")||0,position:oO(e.position,0),titlePadding:t("titlePadding"),minExtent:t("minExtent"),maxExtent:t("maxExtent"),range:{signal:`abs(span(range("${e.scale}")))`},translate:t("translate"),format:e.format,formatType:e.formatType}),n}function cU(t,e,n){const r=V(t.signals),i=V(t.scales);return n||r.forEach((t=>HN(t,e))),V(t.projections).forEach((t=>function(t,e){const n=e.config.projection||{},r={};for(const n in t)"name"!==n&&(r[n]=aR(t[n],n,e));for(const t in n)null==r[t]&&(r[t]=aR(n[t],t,e));e.addProjection(t.name,r)}(t,e))),i.forEach((t=>function(t,e){const n=t.type||"linear";sp(n)||s("Unrecognized scale type: "+Dt(n)),e.addScale(t.name,{type:n,domain:void 0})}(t,e))),V(t.data).forEach((t=>NL(t,e))),i.forEach((t=>GO(t,e))),(n||r).forEach((t=>function(t,e){const n=e.getSignal(t.name);let r=t.update;t.init&&(r?s("Signals can not include both init and update expressions."):(r=t.init,n.initonly=!0)),r&&(r=BB(r,e),n.update=r.$expr,n.params=r.$params),t.on&&t.on.forEach((t=>pO(t,e,n.id)))}(t,e))),V(t.axes).forEach((t=>uU(t,e))),V(t.marks).forEach((t=>CL(t,e))),V(t.legends).forEach((t=>FL(t,e))),t.title&&BL(t.title,e),e.parseLambdas(),e}const fU=t=>fN({enter:{x:{value:0},y:{value:0}},update:{width:{signal:"width"},height:{signal:"height"}}},t);function hU(t,e){const n=e.config,r=XN(e.root=e.add(VN())),i=function(t,e){const n=n=>oO(t[n],e[n]),r=[dU("background",n("background")),dU("autosize",iN(n("autosize"))),dU("padding",sN(n("padding"))),dU("width",n("width")||0),dU("height",n("height")||0)],i=r.reduce(((t,e)=>(t[e.name]=e,t)),{}),o={};return V(t.signals).forEach((t=>{ut(i,t.name)?t=ot(i[t.name],t):r.push(t),o[t.name]=t})),V(e.signals).forEach((t=>{ut(o,t.name)||ut(i,t.name)||r.push(t)})),r}(t,n);i.forEach((t=>HN(t,e))),e.description=t.description||n.description,e.eventConfig=n.events,e.legends=e.objectProperty(n.legend&&n.legend.layout),e.locale=n.locale;const o=e.add(xO()),a=e.add(kO(UN(fU(t.encode),BR,pN,t.style,e,{pulse:XN(o)}))),s=e.add(IO({layout:e.objectProperty(t.layout),legends:e.legends,autosize:e.signalRef("autosize"),mark:r,pulse:XN(a)}));e.operators.pop(),e.pushState(XN(a),XN(s),null),cU(t,e,i),e.operators.push(s);let u=e.add(_O({mark:r,pulse:XN(s)}));return u=e.add(UO({pulse:XN(u)})),u=e.add(PO({pulse:XN(u)})),e.addData("root",new kL(e,o,o,u)),e}function dU(t,e){return e&&e.signal?{name:t,update:e.signal}:{name:t,value:e}}function pU(t,e){this.config=t||{},this.options=e||{},this.bindings=[],this.field={},this.signals={},this.lambdas={},this.scales={},this.events={},this.data={},this.streams=[],this.updates=[],this.operators=[],this.eventConfig=null,this.locale=null,this._id=0,this._subid=0,this._nextsub=[0],this._parent=[],this._encode=[],this._lookup=[],this._markpath=[]}function gU(t){this.config=t.config,this.options=t.options,this.legends=t.legends,this.field=Object.create(t.field),this.signals=Object.create(t.signals),this.lambdas=Object.create(t.lambdas),this.scales=Object.create(t.scales),this.events=Object.create(t.events),this.data=Object.create(t.data),this.streams=[],this.updates=[],this.operators=[],this._id=0,this._subid=++t._nextsub[0],this._nextsub=t._nextsub,this._parent=t._parent.slice(),this._encode=t._encode.slice(),this._lookup=t._lookup.slice(),this._markpath=t._markpath}function mU(t){return(k(t)?yU:vU)(t)}function yU(t){const e=t.length;let n="[";for(let r=0;r0?",":"")+(A(e)?e.signal||mU(e):Dt(e))}return n+"]"}function vU(t){let e,n,r="{",i=0;for(e in t)n=t[e],r+=(++i>1?",":"")+Dt(e)+":"+(A(n)?n.signal||mU(n):Dt(n));return r+"}"}pU.prototype=gU.prototype={parse(t){return cU(t,this)},fork(){return new gU(this)},isSubscope(){return this._subid>0},toRuntime(){return this.finish(),{description:this.description,operators:this.operators,streams:this.streams,updates:this.updates,bindings:this.bindings,eventConfig:this.eventConfig,locale:this.locale}},id(){return(this._subid?this._subid+":":0)+this._id++},add(t){return this.operators.push(t),t.id=this.id(),t.refs&&(t.refs.forEach((e=>{e.$ref=t.id})),t.refs=null),t},proxy(t){const e=t instanceof YN?XN(t):t;return this.add(RO({value:e}))},addStream(t){return this.streams.push(t),t.id=this.id(),t},addUpdate(t){return this.updates.push(t),t},finish(){let t,e;for(t in this.root&&(this.root.root=!0),this.signals)this.signals[t].signal=t;for(t in this.scales)this.scales[t].scale=t;function n(t,e,n){let r,i;t&&(r=t.data||(t.data={}),i=r[e]||(r[e]=[]),i.push(n))}for(t in this.data){e=this.data[t],n(e.input,t,"input"),n(e.output,t,"output"),n(e.values,t,"values");for(const r in e.index)n(e.index[r],t,"index:"+r)}return this},pushState(t,e,n){this._encode.push(XN(this.add(PO({pulse:t})))),this._parent.push(e),this._lookup.push(n?XN(this.proxy(n)):null),this._markpath.push(-1)},popState(){this._encode.pop(),this._parent.pop(),this._lookup.pop(),this._markpath.pop()},parent(){return F(this._parent)},encode(){return F(this._encode)},lookup(){return F(this._lookup)},markpath(){const t=this._markpath;return++t[t.length-1]},fieldRef(t,e){if(_t(t))return JN(t,e);t.signal||s("Unsupported field reference: "+Dt(t));const n=t.signal;let r=this.field[n];if(!r){const t={name:this.signalRef(n)};e&&(t.as=e),this.field[n]=r=XN(this.add(EO(t)))}return r},compareRef(t){let e=!1;const n=t=>rO(t)?(e=!0,this.signalRef(t.signal)):function(t){return t&&t.expr}(t)?(e=!0,this.exprRef(t.expr)):t,r=V(t.field).map(n),i=V(t.order).map(n);return e?XN(this.add(bO({fields:r,orders:i}))):QN(r,i)},keyRef(t,e){let n=!1;const r=this.signals;return t=V(t).map((t=>rO(t)?(n=!0,XN(r[t.signal])):t)),n?XN(this.add(DO({fields:t,flat:e}))):function(t,e){const n={$key:t};return e&&(n.$flat=!0),n}(t,e)},sortRef(t){if(!t)return t;const e=tO(t.op,t.field),n=t.order||"ascending";return n.signal?XN(this.add(bO({fields:e,orders:this.signalRef(n.signal)}))):QN(e,n)},event(t,e){const n=t+":"+e;if(!this.events[n]){const r=this.id();this.streams.push({id:r,source:t,type:e}),this.events[n]=r}return this.events[n]},hasOwnSignal(t){return ut(this.signals,t)},addSignal(t,e){this.hasOwnSignal(t)&&s("Duplicate signal name: "+Dt(t));const n=e instanceof YN?e:this.add(VN(e));return this.signals[t]=n},getSignal(t){return this.signals[t]||s("Unrecognized signal name: "+Dt(t)),this.signals[t]},signalRef(t){return this.signals[t]?XN(this.signals[t]):(ut(this.lambdas,t)||(this.lambdas[t]=this.add(VN(null))),XN(this.lambdas[t]))},parseLambdas(){const t=Object.keys(this.lambdas);for(let e=0,n=t.length;er+Math.floor(o*t.random()),pdf:t=>t===Math.floor(t)&&t>=r&&t=i?1:(e-r+1)/o},icdf:t=>t>=0&&t<=1?r-1+Math.floor(t*o):NaN};return a.min(e).max(n)},t.randomKDE=ps,t.randomLCG=function(t){return function(){return(t=(1103515245*t+12345)%2147483647)/2147483647}},t.randomLogNormal=_s,t.randomMixture=xs,t.randomNormal=ds,t.randomUniform=Ms,t.read=la,t.regressionConstant=Es,t.regressionExp=Bs,t.regressionLinear=$s,t.regressionLoess=Ls,t.regressionLog=Ts,t.regressionPoly=Os,t.regressionPow=zs,t.regressionQuad=Ns,t.renderModule=T_,t.repeat=At,t.resetDefaultLocale=function(){return Do(),To(),Ro()},t.resetSVGClipId=Yg,t.resetSVGDefIds=function(){Yg(),Gp=0},t.responseType=ua,t.runtimeContext=jB,t.sampleCurve=js,t.sampleLogNormal=gs,t.sampleNormal=ls,t.sampleUniform=bs,t.scale=ap,t.sceneEqual=q_,t.sceneFromJSON=Zy,t.scenePickVisit=qm,t.sceneToJSON=Jy,t.sceneVisit=Um,t.sceneZOrder=Lm,t.scheme=Ap,t.serializeXML=r_,t.setHybridRendererOptions=function(t){A_.svgMarkTypes=t.svgMarkTypes??["text"],A_.svgOnTop=t.svgOnTop??!0,A_.debug=t.debug??!1},t.setRandom=function(e){t.random=e},t.span=Et,t.splitAccessPath=u,t.stringValue=Dt,t.textMetrics=My,t.timeBin=Xr,t.timeFloor=br,t.timeFormatLocale=zo,t.timeInterval=Dr,t.timeOffset=Sr,t.timeSequence=Br,t.timeUnitSpecifier=nr,t.timeUnits=tr,t.toBoolean=Ct,t.toDate=St,t.toNumber=S,t.toSet=Tt,t.toString=$t,t.transform=Qa,t.transforms=Ja,t.truncate=Bt,t.truthy=p,t.tupleid=ma,t.typeParsers=Jo,t.utcFloor=Ar,t.utcInterval=Cr,t.utcOffset=$r,t.utcSequence=zr,t.utcdayofyear=fr,t.utcquarter=G,t.utcweek=hr,t.version="5.33.0",t.visitArray=zt,t.week=ar,t.writeConfig=D,t.zero=h,t.zoomLinear=j,t.zoomLog=I,t.zoomPow=W,t.zoomSymlog=H})); +//# sourceMappingURL=vega.min.js.map diff --git a/tests/browser_retained_analysis.cjs b/tests/browser_retained_analysis.cjs new file mode 100644 index 00000000..c1569378 --- /dev/null +++ b/tests/browser_retained_analysis.cjs @@ -0,0 +1,121 @@ +// Actual Chromium renderer/CSP test over authored boundary data. No DB or Runs claim. +'use strict'; +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const os = require('node:os'); +const path = require('node:path'); +const {spawn} = require('node:child_process'); +const {waitForDebugger} = require('./browser_startup.cjs'); +const root = path.resolve(__dirname, '..'); +const profile = fs.mkdtempSync(path.join(os.tmpdir(), 'tuldok-retained-renderer-')); +const children = []; +const pause = ms => new Promise(resolve => setTimeout(resolve, ms)); +async function until(test) { for (let i = 0; i < 200; ++i) { if (await test()) return; await pause(50); } throw Error('Renderer assertion timed out'); } +(async () => { + let output = '', serverError = ''; + const server = spawn(process.env.PYTHON || 'python3', ['-u', 'tests/retained_analysis_browser_fixture.py'], {cwd: root}); children.push(server); + server.stdout.on('data', chunk => output += chunk); server.stderr.on('data', chunk => serverError += chunk); + await until(() => /^\d+\n/.test(output)); + const base = 'http://127.0.0.1:' + output.trim(); + const browser = spawn(process.env.BROWSER || '/usr/bin/chromium', ['--headless', '--no-sandbox', '--disable-gpu', '--remote-debugging-port=0', '--user-data-dir=' + profile, 'about:blank'], {stdio: 'ignore'}); children.push(browser); + // Headless/no-sandbox is confined to this isolated disposable browser fixture; + // it is not a product startup configuration or an application sandbox claim. + const port = await waitForDebugger(browser, path.join(profile, 'DevToolsActivePort')); + const targets = await (await fetch(`http://127.0.0.1:${port}/json`)).json(); + const ws = new WebSocket(targets.find(target => target.type === 'page').webSocketDebuggerUrl); + await new Promise(resolve => ws.addEventListener('open', resolve)); + let id = 0; const calls = new Map(), errors = [], external = []; + ws.addEventListener('message', event => { + const value = JSON.parse(event.data); + if (value.id) { const call = calls.get(value.id); calls.delete(value.id); value.error ? call.reject(Error(JSON.stringify(value.error))) : call.resolve(value.result); } + if (value.method === 'Runtime.exceptionThrown') errors.push(value.params.exceptionDetails.text); + if (value.method === 'Network.requestWillBeSent' && !value.params.request.url.startsWith(base) && !value.params.request.url.startsWith('data:')) external.push(value.params.request.url); + }); + const send = (method, params = {}) => new Promise((resolve, reject) => { const next = ++id; calls.set(next, {resolve, reject}); ws.send(JSON.stringify({id: next, method, params})); }); + const evaluate = async expression => { + const result = await send('Runtime.evaluate', {expression, returnByValue: true, awaitPromise: true}); + if (result.exceptionDetails) throw Error(result.exceptionDetails.exception?.description || result.exceptionDetails.text); + return result.result.value; + }; + await send('Runtime.enable'); await send('Network.enable'); await send('Page.enable'); + await send('Page.navigate', {url: base}); + const ready = () => evaluate('!!document.querySelector("svg") && document.querySelector("#analysis").getAttribute("aria-busy")==="false"'); + await until(async () => { + const alert = await evaluate('document.querySelector("[role=alert]")?.textContent'); + if (alert) throw Error(alert); + return ready(); + }); + assert.equal(await evaluate('document.querySelector("[role=alert]")?.textContent || ""'), ''); + assert.match(await evaluate('document.body.textContent'), /Epoch 1: 0.125/); + assert.match(await evaluate('document.querySelector("tbody").textContent'), /frozen-example-first/); + await evaluate('document.querySelectorAll("button")[1].focus()'); + await send('Input.dispatchKeyEvent', {type: 'keyDown', key: 'Enter', code: 'Enter', text: '\r', windowsVirtualKeyCode: 13}); + await send('Input.dispatchKeyEvent', {type: 'keyUp', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13}); + await until(() => evaluate('document.querySelector("tbody")?.textContent.includes("frozen-example-second") && document.querySelector("#analysis").getAttribute("aria-busy")==="false"')).catch(async error => { + throw Error(error.message + ' ' + JSON.stringify(await evaluate('({text:document.body.textContent,csp:fixtureCsp,requests:fixtureRequests,selection:fixtureSelections})')) + ' errors=' + JSON.stringify(errors)); + }); + assert.equal(await evaluate('document.activeElement.tagName'), 'H3'); + assert.equal(await evaluate('fixtureSelections.length'), 1); + const point = await evaluate('(()=>{const b=document.querySelector("g.mark-symbol path").getBoundingClientRect();return {x:b.x+b.width/2,y:b.y+b.height/2}})()'); + await send('Input.dispatchMouseEvent', {type: 'mousePressed', button: 'left', clickCount: 1, ...point}); + await send('Input.dispatchMouseEvent', {type: 'mouseReleased', button: 'left', clickCount: 1, ...point}); + await until(() => evaluate('document.querySelector("tbody")?.textContent.includes("frozen-example-first") && document.querySelector("#analysis").getAttribute("aria-busy")==="false"')); + assert.equal(await evaluate('fixtureSelections.length'), 2); + await evaluate('[...document.querySelectorAll("button")].find(button=>button.textContent==="Next examples").click()'); + await until(() => evaluate('fixtureAdapter.selection()?.offset === 1')); + assert.match(await evaluate('document.querySelector("tbody").textContent'), /frozen-example-first-1/); + await evaluate('document.querySelector("input").click()'); await until(ready); + assert.equal(await evaluate('fixtureAdapter.selection().errors_only'), true); + await send('Emulation.setDeviceMetricsOverride', {width: 390, height: 844, deviceScaleFactor: 1, mobile: false}); await pause(200); + assert.equal(await evaluate('document.documentElement.scrollWidth <= 390'), true); + await evaluate('fixtureMode="stale"; void fixtureStart()'); + await until(() => evaluate('fixturePending.length === 1')); + await evaluate('fixtureMode="revoked"; void fixtureStart()'); + await until(() => evaluate('!!document.querySelector("[role=alert]")')); + await evaluate('fixturePending.shift()()'); await pause(100); + assert.equal(await evaluate('!!document.querySelector("svg,tbody")'), false); + assert.equal(await evaluate('fixtureAdapter.selection()'), null); + for (const mode of ['malformed', 'oversized', 'support-mismatch', 'ordinal-mismatch', 'count-mismatch', 'missing-provenance', 'missing-definition', 'missing-column-type']) { + await evaluate(`fixtureMode=${JSON.stringify(mode)}; void fixtureStart()`); + await until(() => evaluate('document.querySelector("[role=alert]")?.textContent.includes("invalid")')); + assert.equal(await evaluate('!!document.querySelector("svg,tbody")'), false); + } + for (const mode of ['malformed', 'oversized']) { + await evaluate(`fixtureMode="normal"; fixtureSpecMode=${JSON.stringify(mode)}; void fixtureStart()`); + await until(() => evaluate('!!document.querySelector("[role=alert]")')); + assert.match(await evaluate('document.querySelector("[role=alert]").textContent'), mode === 'oversized' ? /specification exceeds/ : /specification identity/); + assert.equal(await evaluate('!!document.querySelector("svg,tbody")'), false); + assert.equal(await evaluate('fixtureRequests.at(-1).aborted()'), true); + } + await evaluate('fixtureSpecMode="normal"'); + await evaluate('fixtureMode="normal"; void fixtureStart()'); await until(ready); + const downloadPath = path.join(profile, 'downloads'); fs.mkdirSync(downloadPath); + await send('Browser.setDownloadBehavior', {behavior: 'allow', downloadPath}); + await evaluate('[...document.querySelectorAll("button")].find(button=>button.textContent==="Export this page").click()'); + await until(() => fs.existsSync(path.join(downloadPath, 'retained-analysis-page.json'))); + const exported = JSON.parse(fs.readFileSync(path.join(downloadPath, 'retained-analysis-page.json'), 'utf8')); + assert.deepEqual(exported.curve.map(point => point.value), [.125, .375]); + assert.equal(exported.provenance.evaluation_sha256, 'd'.repeat(64)); + await evaluate('fixtureMode="revoked"; [...document.querySelectorAll("button")].find(button=>button.textContent==="Export this page").click()'); + await until(() => evaluate('document.querySelector("[role=alert]")?.textContent.includes("export failed")')); + assert.equal(await evaluate('!!document.querySelector("svg,tbody")'), false); + assert.equal(await evaluate('fixtureRequests.at(-1).exported'), true); + await send('Page.reload', {ignoreCache: true}); await until(ready); + assert.match(await evaluate('document.querySelector("tbody").textContent'), /frozen-example-first/); + assert.deepEqual(await evaluate('fixtureCsp'), []); + assert.deepEqual(errors, []); assert.deepEqual(external, []); + await evaluate('fixtureAdapter.dispose()'); + assert.equal(await evaluate('document.querySelector("#analysis").childElementCount'), 0); + console.log(JSON.stringify({status: 'passed', evidence: 'actual-headless-Chromium-authored-renderer-fixture', checks: ['strict CSP/interpreter', 'self-hosted/offline external assets', 'exact numbers', 'keyboard linked selection/focus', 'visible error filter', '390px layout', 'stale reply after revocation', 'malformed/oversized response and spec rejection', 'support/ordinal/provenance/type validation', 'fresh export authorization path', 'cold page reopen', 'dispose']}, null, 2)); + ws.close(); +})().catch(error => { console.error(error); process.exitCode = 1; }).finally(async () => { + for (const child of children.reverse()) { + if (child.exitCode !== null || child.signalCode !== null) continue; + await new Promise(resolve => { + const timer = setTimeout(() => child.kill('SIGKILL'), 3000); + child.once('exit', () => { clearTimeout(timer); resolve(); }); + child.kill('SIGTERM'); + }); + } + fs.rmSync(profile, {recursive: true, force: true}); +}); diff --git a/tests/fixtures/retained-analysis-browser.css b/tests/fixtures/retained-analysis-browser.css new file mode 100644 index 00000000..85535bce --- /dev/null +++ b/tests/fixtures/retained-analysis-browser.css @@ -0,0 +1,7 @@ +body { font: 16px system-ui; margin: 16px; color: #17223b; } +main, #analysis { max-width: 900px; min-width: 0; width: 100%; } +button { margin: 4px; padding: 8px; } +table { border-collapse: collapse; width: 100%; font-size: 12px; table-layout: fixed; } +td, th { padding: 6px; border: 1px solid #aab; overflow-wrap: anywhere; } +pre { white-space: pre-wrap; overflow-wrap: anywhere; } +button:focus-visible, input:focus-visible { outline: 3px solid #d97706; } diff --git a/tests/fixtures/retained-analysis-browser.js b/tests/fixtures/retained-analysis-browser.js new file mode 100644 index 00000000..776b5105 --- /dev/null +++ b/tests/fixtures/retained-analysis-browser.js @@ -0,0 +1,42 @@ +'use strict'; +window.fixtureRequests = []; +window.fixtureMode = 'normal'; +window.fixturePending = []; +window.fixtureSelections = []; +window.fixtureCsp = []; +window.fixtureSpecMode = 'normal'; +const originalFetch = window.fetch.bind(window); +window.fetch = (url, options) => { + if (url === '/static/retained-checkpoint-curve.vl.json' && window.fixtureSpecMode !== 'normal') { + return Promise.resolve(new Response(window.fixtureSpecMode === 'oversized' ? ' '.repeat(16385) : '{"data":{"url":"https://example.invalid/private"}}')); + } + return originalFetch(url, options); +}; +document.addEventListener('securitypolicyviolation', event => window.fixtureCsp.push(event.violatedDirective)); +const cp = ['b'.repeat(64), 'c'.repeat(64)]; +window.fixtureRequest = {query_id: 'retained_checkpoint_examples', query_version: 1, run_id: 'a'.repeat(32), evaluation_sha256: 'd'.repeat(64), checkpoint_sha256: cp[0], metric_id: 'accuracy', metric_definition_sha256: 'e'.repeat(64), limit: 1, offset: 0}; +function response(request) { + const ordinal = request.errors_only ? 1 : (request.offset ?? 0); + const count = request.errors_only ? 1 : 2; + const row = {example_id: (request.checkpoint_sha256 === cp[0] ? 'frozen-example-first' : 'frozen-example-second') + '-' + ordinal, ordinal, truth_index: ordinal, predicted_index: 0, confidence: ordinal === 0 ? .875 : .75, error: ordinal !== 0}; + row.frozen_reference = {id: row.example_id, revision: 3}; + return {state: 'verified', query_id: 'retained_checkpoint_examples', query_version: 1, mode: 'frozen', provenance: {catalog_id: 'renderer-fixture', run_id: request.run_id, evaluation_sha256: request.evaluation_sha256, checkpoint_sha256: request.checkpoint_sha256, metric_definition_sha256: request.metric_definition_sha256, population_sha256: '1'.repeat(64), probe_sha256: '2'.repeat(64), data_sha256: '3'.repeat(64), producer: {catalog_id: 'renderer-fixture', run_id: request.run_id, material_sha256: '4'.repeat(64), adapter_sha256: '5'.repeat(64)}}, metric: {id: 'accuracy', units: 'dimensionless', support: 2, definition: {id: 'accuracy', split: 'validation', units: 'dimensionless', population_sha256: '1'.repeat(64)}}, curve: [{checkpoint_sha256: cp[0], epoch: 1, value: .125, support: 2}, {checkpoint_sha256: cp[1], epoch: 2, value: .375, support: 2}], columns: ['example_id', 'truth_index', 'predicted_index', 'confidence', 'error'].map((field, index) => ({field, type: ['string', 'integer', 'integer', 'number', 'boolean'][index], units: field === 'confidence' ? 'dimensionless' : null})), examples: {rows: request.offset >= count ? [] : [row], population_support: 2, filtered_support: count, offset: request.offset ?? 0, limit: request.limit ?? 50, next_offset: (request.offset ?? 0) + 1 < count ? (request.offset ?? 0) + 1 : null, filters: {errors_only: request.errors_only ?? false}}, sampling: {method: 'none', population: 'frozen_validation_probe'}, selection_sha256: 'f'.repeat(64)}; +} +async function load(request, options) { + window.fixtureRequests.push({request, exported: options.export, aborted: () => options.signal.aborted}); + if (window.fixtureMode === 'revoked') throw Error('Credential is unavailable, expired or revoked.'); + if (window.fixtureMode === 'stale') return new Promise(resolve => window.fixturePending.push(() => resolve(response(request)))); + const result = response(request); + if (window.fixtureMode === 'malformed') result.spec = {data: {url: 'https://example.invalid/private'}}; + if (window.fixtureMode === 'oversized') result.curve = Array(129).fill(result.curve[0]); + if (window.fixtureMode === 'support-mismatch') result.curve[0].support = 999; + if (window.fixtureMode === 'ordinal-mismatch') result.examples.rows[0].ordinal = 999; + if (window.fixtureMode === 'count-mismatch') result.examples.filtered_support = 0; + if (window.fixtureMode === 'missing-provenance') delete result.provenance.probe_sha256; + if (window.fixtureMode === 'missing-definition') delete result.metric.definition; + if (window.fixtureMode === 'missing-column-type') delete result.columns[0].type; + return result; +} +window.fixtureAdapter = window.WorkspaceRetainedAnalysis.mount(document.querySelector('#analysis'), {load, onSelection: value => window.fixtureSelections.push(value)}); +window.fixtureStart = () => window.fixtureAdapter.update(window.fixtureRequest, 'authority-1'); +void window.fixtureStart(); diff --git a/tests/retained_analysis_browser_fixture.py b/tests/retained_analysis_browser_fixture.py new file mode 100644 index 00000000..9fd08603 --- /dev/null +++ b/tests/retained_analysis_browser_fixture.py @@ -0,0 +1,35 @@ +"""Isolated renderer fixture, not an application/authorization server.""" +from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer +from pathlib import Path +import sys + +ROOT = Path(__file__).resolve().parents[1] +HTML = b'''Retained analysis renderer fixture
''' + + +class Handler(SimpleHTTPRequestHandler): + def __init__(self, *args, **kwargs): + super().__init__(*args, directory=str(ROOT), **kwargs) + + def end_headers(self): + self.send_header('Content-Security-Policy', "default-src 'none'; script-src 'self'; style-src 'self'; connect-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'") + super().end_headers() + + def do_GET(self): + if self.path == '/': + self.send_response(200) + self.send_header('Content-Type', 'text/html; charset=utf-8') + self.end_headers() + self.wfile.write(HTML) + elif self.path.startswith('/static/vendor/retained-analysis/') or self.path in ( + '/static/retained-analysis.js', '/static/retained-checkpoint-curve.vl.json', + '/tests/fixtures/retained-analysis-browser.js', '/tests/fixtures/retained-analysis-browser.css'): + super().do_GET() + else: + self.send_error(404) + + +if __name__ == '__main__': + server = ThreadingHTTPServer(('127.0.0.1', 0), Handler) + print(server.server_port, flush=True) + server.serve_forever() diff --git a/tests/test_retained_analysis.py b/tests/test_retained_analysis.py new file mode 100644 index 00000000..15c4c30b --- /dev/null +++ b/tests/test_retained_analysis.py @@ -0,0 +1,289 @@ +"""Query-boundary fixtures; actual PostgreSQL assertions are separately gated. + +Auth/evidence substitutes test orchestration only. They do not qualify actual +Runs custody, SQL behavior or end-to-end application acceptance. +""" +import copy +from contextlib import contextmanager +import json +import os +from pathlib import Path +import sys +import unittest +from types import SimpleNamespace +from unittest.mock import patch + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import retained_analysis as analysis +from access import AccessError +from model_evidence import canonical, digest +from psycopg.pq import TransactionStatus +from workbench import WorkbenchError + +RUN = 'a' * 32 +CHECKPOINTS = ['b' * 64, 'c' * 64] +EVALUATION = 'd' * 64 + + +def fixture(): + definition = {'id': 'accuracy', 'units': 'dimensionless', 'split': 'validation', + 'population_sha256': 'e' * 64, 'reduction': 'diagonal_over_population'} + body = {'query_id': analysis.QUERY_ID, 'query_version': 1, 'run_id': RUN, + 'evaluation_sha256': EVALUATION, 'checkpoint_sha256': CHECKPOINTS[1], + 'metric_id': 'accuracy', 'metric_definition_sha256': digest(definition)} + evidence = {'state': 'verified', 'manifest': {'format': 'model_evidence_v1', + 'probe': {'sha256': 'f' * 64}, 'data_sha256': '1' * 64, + 'producer': {'run_id': RUN, 'adapter_sha256': '2' * 64}}, + 'metric_definitions': [definition], + 'checkpoint_index': {'entries': [{'checkpoint': {'sha256': sha}, 'clocks': {'epoch': i}} + for i, sha in enumerate(CHECKPOINTS, 1)]}, + 'probe': {'members': [{'ordinal': i, 'frozen_reference': {'id': f'example-{i}', 'revision': 3}} + for i in range(2)]}, + 'predictions': {'checkpoint_sha256': CHECKPOINTS[1], 'probe_sha256': 'f' * 64, + 'rows': [{'ordinal': 0, 'truth_index': 0, 'predicted_index': 0, 'probabilities': [.875, .125]}, + {'ordinal': 1, 'truth_index': 1, 'predicted_index': 0, 'probabilities': [.75, .25]}]}, + 'observations': [{'checkpoint_sha256': sha, 'metric_id': 'accuracy', 'split': 'validation', + 'state': 'observed', 'clocks': {'epoch': epoch}, 'value': value, 'sample_count': 2} + for sha, epoch, value in zip(CHECKPOINTS, (1, 2), (.0, .5))]} + return body, evidence + + +class Cursor: + def __init__(self, rows): + self.rows = rows + + def fetchone(self): + return self.rows[0] if self.rows else None + + def __iter__(self): + return iter(self.rows) + + +class OwnerFixture: + """A controlled boundary fixture, intentionally not a SQL implementation.""" + def __init__(self): + self.body, self.evidence = fixture() + self.reading = False + self.events = [] + self.revoke_after_read = False + self.artifact_reads = 0 + self.document = {'id': RUN, 'state': 'completed', + 'artifacts': [{'name': 'model-evidence.json', 'sha256': EVALUATION}]} + self.curve = [{'checkpoint_sha256': CHECKPOINTS[0], 'epoch': 1, 'value': .0, 'support': 2}, + {'checkpoint_sha256': CHECKPOINTS[1], 'epoch': 2, 'value': .5, 'support': 2}] + self.page = {'filtered_support': 2, 'rows': [ + {'ordinal': 0, 'example_id': 'example-0', 'truth_index': 0, 'predicted_index': 0, + 'confidence': .875, 'error': False, 'frozen_reference': {'id': 'example-0', 'revision': 3}}, + {'ordinal': 1, 'example_id': 'example-1', 'truth_index': 1, 'predicted_index': 0, + 'confidence': .75, 'error': True, 'frozen_reference': {'id': 'example-1', 'revision': 3}}]} + self.db = SimpleNamespace(dataset_id='catalog-fixture', execute=self.execute, + lock=SimpleNamespace(bounded=self.bounded), + connection=SimpleNamespace(transaction=self.transaction, + info=SimpleNamespace(transaction_status=TransactionStatus.IDLE))) + self.access = SimpleNamespace(require=self.require) + + @contextmanager + def bounded(self, deadline): + yield + + @contextmanager + def transaction(self): + self.reading = True + try: + yield + finally: + self.reading = False + + def require(self, scope, action, run_id): + self.events.append((scope, action, run_id, self.reading)) + if self.revoke_after_read and len(self.events) > 1: + raise AccessError('Credential is unavailable, expired or revoked.', 'unauthenticated', 401) + + def model_evidence(self, run_id, selectors, *, contract_version): + self.artifact_reads += 1 + assert (run_id, selectors, contract_version) == (RUN, {'checkpoint_sha256': CHECKPOINTS[1]}, 1) + return copy.deepcopy(self.evidence) + + def execute(self, sql, params=None): + if 'octet_length(document)' in sql: + return Cursor([{'document': json.dumps(self.document)}]) + if sql == analysis.CURVE_SQL: + return Cursor(copy.deepcopy(self.curve)) + if sql == analysis.EXAMPLES_SQL: + return Cursor([copy.deepcopy(self.page)]) + return Cursor([]) + + +class RequestTests(unittest.TestCase): + def test_defaults_and_explicit_field_projection(self): + body, _ = fixture() + value = analysis.validate_request(body) + self.assertEqual((value['limit'], value['offset'], value['errors_only']), (50, 0, False)) + self.assertEqual(value['fields'], list(analysis.FIELDS)) + self.assertEqual(analysis.validate_request(dict(body, fields=['example_id']))['fields'], ['example_id']) + self.assertNotIn('limit', body) + + def test_closed_bounds_and_types_before_evidence_read(self): + changes = [({'sql': 'SELECT secret'}, 'invalid'), ({'query_version': True}, 'unsupported'), + ({'query_id': 'raw_sql'}, 'unsupported'), ({'limit': True}, 'invalid'), + ({'limit': 101}, 'invalid'), ({'limit': 0}, 'invalid'), ({'offset': -1}, 'invalid'), + ({'offset': 10001}, 'invalid'), ({'errors_only': 1}, 'invalid'), + ({'fields': ['example_id', 'probabilities']}, 'invalid'), + ({'fields': ['confidence']}, 'invalid'), ({'fields': ['example_id'] * 2}, 'invalid'), + ({'fields': [[]]}, 'invalid'), ({'metric_id': []}, 'invalid'), + ({'metric_id': "accuracy'); DROP TABLE workspace_runs;--"}, 'invalid'), + ({'run_id': '../catalog'}, 'invalid'), ({'checkpoint_sha256': 'B' * 64}, 'invalid')] + for changed, code in changes: + with self.subTest(changed=changed): + owner = OwnerFixture() + with self.assertRaises(WorkbenchError) as caught: + analysis.query(owner, dict(owner.body, **changed)) + self.assertEqual(caught.exception.code, code) + self.assertEqual(owner.artifact_reads, 0) + self.assertEqual(owner.events, []) + for value in (None, [], 'query'): + with self.subTest(value=value), self.assertRaises(WorkbenchError): + analysis.validate_request(value) + + +class ProjectionTests(unittest.TestCase): + def test_exact_frozen_examples_and_retained_confidence(self): + body, evidence = fixture() + definition, checkpoints, raw = analysis._projection(evidence, body) + rows = json.loads(raw) + self.assertEqual([row['example_id'] for row in rows], ['example-0', 'example-1']) + self.assertEqual([row['error'] for row in rows], [False, True]) + self.assertEqual([row['confidence'] for row in rows], [.875, .75]) + self.assertEqual(rows[1]['frozen_reference'], {'id': 'example-1', 'revision': 3}) + self.assertEqual(checkpoints[1], {'checkpoint_sha256': CHECKPOINTS[1], 'epoch': 2}) + self.assertEqual(definition['units'], 'dimensionless') + + def test_foreign_metric_checkpoint_and_population_are_distinct_failures(self): + body, evidence = fixture() + for changed, code in (({'metric_definition_sha256': '0' * 64}, 'stale'), + ({'checkpoint_sha256': '0' * 64}, 'not_found')): + with self.subTest(changed=changed), self.assertRaises(WorkbenchError) as caught: + analysis._projection(evidence, dict(body, **changed)) + self.assertEqual(caught.exception.code, code) + evidence['predictions']['probe_sha256'] = '0' * 64 + with self.assertRaisesRegex(WorkbenchError, 'Selected checkpoint predictions differ'): + analysis._projection(evidence, body) + + def test_unsupported_task_and_oversize_are_explicit(self): + body, evidence = fixture() + evidence['checkpoint_index']['entries'][0]['clocks']['epoch'] = None + with self.assertRaises(WorkbenchError) as caught: + analysis._projection(evidence, body) + self.assertEqual(caught.exception.code, 'unsupported') + body, evidence = fixture() + with patch.object(analysis, 'MAX_EXAMPLES', 1), self.assertRaises(WorkbenchError) as caught: + analysis._projection(evidence, body) + self.assertEqual((caught.exception.code, caught.exception.status), ('limit', 413)) + + +class QueryBoundaryTests(unittest.TestCase): + def test_exact_provenance_and_values_with_fresh_access_outside_snapshot(self): + owner = OwnerFixture() + result = analysis.query(owner, owner.body) + self.assertEqual([p['value'] for p in result['curve']], [.0, .5]) + self.assertEqual(result['provenance']['evaluation_sha256'], EVALUATION) + self.assertEqual(result['metric']['support'], 2) + self.assertEqual(result['examples']['population_support'], 2) + self.assertEqual(result['sampling'], {'method': 'none', 'population': 'frozen_validation_probe'}) + self.assertEqual(len(owner.events), 2) + self.assertTrue(all(event == ('inspect', 'runs.retained_analysis', RUN, False) for event in owner.events)) + + def test_export_and_repeated_retrieval_do_not_bypass_current_authority(self): + owner = OwnerFixture() + analysis.query(owner, owner.body) + owner.revoke_after_read = True + with self.assertRaises(AccessError) as caught: + analysis.query(owner, owner.body, export=True) + self.assertEqual(caught.exception.status, 401) + self.assertEqual(owner.artifact_reads, 1) + self.assertEqual(owner.events[-1][1], 'runs.export_retained_analysis') + + def test_revocation_during_read_prevents_return(self): + owner = OwnerFixture() + owner.revoke_after_read = True + with self.assertRaises(AccessError) as caught: + analysis.query(owner, owner.body) + self.assertEqual(caught.exception.code, 'unauthenticated') + self.assertEqual(owner.artifact_reads, 1) + self.assertFalse(owner.reading) + + def test_error_filter_does_not_change_metric_population_and_page_identity(self): + owner = OwnerFixture() + owner.page = {'filtered_support': 1, 'rows': [owner.page['rows'][1]]} + result = analysis.query(owner, dict(owner.body, errors_only=True, fields=['example_id'], limit=1)) + self.assertEqual(result['metric']['support'], 2) + self.assertEqual(result['examples']['filtered_support'], 1) + self.assertEqual(result['examples']['rows'], [{'example_id': 'example-1', 'ordinal': 1, + 'frozen_reference': {'id': 'example-1', 'revision': 3}}]) + self.assertIsNone(result['examples']['next_offset']) + self.assertEqual(result['examples']['filters'], {'errors_only': True}) + + def test_catalog_mismatch_is_refused(self): + for field, value in (('value', .25), ('support', 3), ('epoch', 3)): + owner = OwnerFixture() + owner.curve[0][field] = value + with self.subTest(field=field), self.assertRaisesRegex(WorkbenchError, 'Catalog curve differs'): + analysis.query(owner, owner.body) + owner = OwnerFixture() + owner.document['artifacts'][0]['sha256'] = '0' * 64 + with self.assertRaises(WorkbenchError) as caught: + analysis.query(owner, owner.body) + self.assertEqual(caught.exception.code, 'stale') + self.assertEqual(owner.artifact_reads, 0) + + def test_nested_transaction_and_oversized_response_refused(self): + owner = OwnerFixture() + owner.db.connection.info.transaction_status = TransactionStatus.INTRANS + with self.assertRaises(WorkbenchError) as caught: + analysis.query(owner, owner.body) + self.assertEqual(caught.exception.code, 'unavailable') + self.assertEqual(owner.artifact_reads, 0) + owner = OwnerFixture() + with patch.object(analysis, 'MAX_RESPONSE_BYTES', 1), self.assertRaises(WorkbenchError) as caught: + analysis.query(owner, owner.body) + self.assertEqual(caught.exception.status, 413) + + def test_malformed_catalog_envelope_preserves_typed_failure(self): + for document in ({'artifacts': None}, {'artifacts': [{'sha256': '0' * 64}]}, [], None): + owner = OwnerFixture() + owner.document = document + with self.subTest(document=document), self.assertRaises(WorkbenchError) as caught: + analysis.query(owner, owner.body) + self.assertEqual((caught.exception.code, caught.exception.status), ('unavailable', 409)) + self.assertEqual(str(caught.exception), 'Retained Run envelope is unavailable.') + self.assertEqual(owner.artifact_reads, 0) + + +@unittest.skipUnless(os.environ.get('TULDOK_DATABASE_URL'), 'Existing authorized PostgreSQL configuration required; no credentials created.') +class ActualPostgresSqlTests(unittest.TestCase): + def test_parameterized_curve_and_stable_error_page_on_actual_postgres(self): + import psycopg + from psycopg.rows import dict_row + from metadata import connection_info + with psycopg.connect(connection_info(), row_factory=dict_row) as db: + # A rollback-only temporary relation never changes application schema. + with db.transaction(force_rollback=True): + db.execute('CREATE TEMP TABLE workspace_runs(id text, document text) ON COMMIT DROP') + doc = {'metrics': {'history': [{'epoch': 1, 'validation': {'accuracy': .125, 'examples': 8}}, + {'epoch': 2, 'validation': {'accuracy': .375, 'examples': 8}}]}} + db.execute('INSERT INTO workspace_runs VALUES (%s,%s)', (RUN, json.dumps(doc))) + cp = [{'checkpoint_sha256': sha, 'epoch': i} for i, sha in enumerate(CHECKPOINTS, 1)] + rows = db.execute(analysis.CURVE_SQL, (json.dumps(cp), 'accuracy', RUN, 129)).fetchall() + self.assertEqual([row['value'] for row in rows], [.125, .375]) + self.assertEqual([row['support'] for row in rows], [8, 8]) + body, evidence = fixture() + _, _, raw = analysis._projection(evidence, body) + page = db.execute(analysis.EXAMPLES_SQL, (raw, True, 1, 0)).fetchone() + self.assertEqual(page['filtered_support'], 1) + self.assertEqual(page['rows'][0]['example_id'], 'example-1') + empty = db.execute(analysis.EXAMPLES_SQL, (raw, True, 1, 1)).fetchone() + self.assertEqual(empty, {'filtered_support': 1, 'rows': []}) + + +if __name__ == '__main__': + unittest.main() From 78e23f4497cf9c97bd7059d47decc81ce804f971 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Oct 2026 00:17:49 +0000 Subject: [PATCH 2/8] Qualify retained queries against actual PostgreSQL and native Runs --- docs/contracts/retained-analysis-renderer.md | 15 +- .../retained-analysis/execution-ledger.md | 16 ++ docs/plans/retained-analysis/issues.md | 2 +- docs/plans/retained-analysis/plan.md | 20 +- .../reports/m3-actual/environment.json | 52 +++++ .../reports/m3-actual/fixture.json | 137 ++++++++++++++ .../m3-actual/original-query-tests.log | 18 ++ .../reports/m3-actual/preparation.log | 1 + .../reports/m3-actual/qualification.md | 94 +++++++++ .../m3-actual/retained-query-tests.log | 11 ++ tests/browser_retained_analysis_actual.cjs | 98 ++++++++++ tests/retained_analysis_actual_fixture.py | 81 ++++++++ tests/test_retained_analysis_actual.py | 178 ++++++++++++++++++ tests/test_retained_analysis_http.py | 119 ++++++++++++ 14 files changed, 829 insertions(+), 13 deletions(-) create mode 100644 docs/plans/retained-analysis/reports/m3-actual/environment.json create mode 100644 docs/plans/retained-analysis/reports/m3-actual/fixture.json create mode 100644 docs/plans/retained-analysis/reports/m3-actual/original-query-tests.log create mode 100644 docs/plans/retained-analysis/reports/m3-actual/preparation.log create mode 100644 docs/plans/retained-analysis/reports/m3-actual/qualification.md create mode 100644 docs/plans/retained-analysis/reports/m3-actual/retained-query-tests.log create mode 100644 tests/browser_retained_analysis_actual.cjs create mode 100644 tests/retained_analysis_actual_fixture.py create mode 100644 tests/test_retained_analysis_actual.py create mode 100644 tests/test_retained_analysis_http.py diff --git a/docs/contracts/retained-analysis-renderer.md b/docs/contracts/retained-analysis-renderer.md index 0de61d68..f049c2d7 100644 --- a/docs/contracts/retained-analysis-renderer.md +++ b/docs/contracts/retained-analysis-renderer.md @@ -78,8 +78,11 @@ does not establish an application execution sandbox. This test uses authored responses and access-failure substitutes. It establishes renderer behavior only. It does not establish actual Runs custody, PostgreSQL execution, real credential revocation, full application accessibility, or -cold-process retained result reproducibility. These remain blocked gates until -the shared hooks and an authorized existing DB/training environment are supplied. +cold-process retained result reproducibility. The follow-up actual PostgreSQL/ +retained native Run tests now qualify the direct query boundary, including real +Access revocation and fresh-process reopening. They are distinct from these +authored renderer tests. The full authenticated API-to-Runs browser gate remains +pending shared-hook integration. ## Pending API dependency and shared hook proposal @@ -90,9 +93,11 @@ lead agreement before implementation: `runs.export_retained_analysis/1`, each with explicit closed request/response schema hashes. Keep existing operations/versions unchanged. 2. Add POST `/api/workspace/runs//retained-analysis` and an explicit - `/retained-analysis/export` sibling. Require the chosen new contract; reject - route/body run mismatch. Delegate to `retained_analysis.query(dataset.runs, - body, export=host_route_choice)`. No user-controlled export flag. + `/retained-analysis/export` sibling. Require the chosen new contract. Existing + selected-contract rules place run_id in the path only: reject any duplicate + body run_id, then inject the path ID when delegating to + `retained_analysis.query(dataset.runs, body_with_route_id, + export=host_route_choice)`. No user-controlled export flag. 3. In the existing verified native classifier Runs section, build the request from its exact artifact/metric/checkpoint inventory. Mount a separate root; load through authenticated transport. Dispose on navigation, credential or diff --git a/docs/plans/retained-analysis/execution-ledger.md b/docs/plans/retained-analysis/execution-ledger.md index 4d554947..1ac22356 100644 --- a/docs/plans/retained-analysis/execution-ledger.md +++ b/docs/plans/retained-analysis/execution-ledger.md @@ -20,3 +20,19 @@ actual-store or authenticated application acceptance. Review identified and closed preflight typed-error and frontend count/provenance/type-decoding gaps. Full objective remains Verifying pending shared hook agreement and a provisioned authorized PostgreSQL/training environment. Nothing merged. + +2026-10-20 00:12 UTC: Parent clarified disposable local PostgreSQL/dependency setup +is within implementation scope; no new user permission is required. Downloaded +official Debian PG17.11 packages into task-owned storage, extracted without a +system package/service change, and initialized the existing repository helper +under `/tmp/tuldok-analysis-pg`. Provisioned the repository-pinned CPU training +packages in `/tmp/tuldok-training-runtime/venv`; the normal runtime probe reports +available. One normal six-image classifier Run completed with two retained +checkpoints. The original query suite now passes 13/13 against actual PostgreSQL; +six new actual retained-query tests pass, covering exact bytes/numbers, stable +pages/support, real credential revocation including final-check fault timing, +artifact re-verification, inert reads/exports and a fresh-process cold reopen. +The earlier 12-pass/one-skip log remains retained as historical evidence. +No shared handler has been edited; authenticated API/Run UI acceptance still +awaits lead ownership agreement. After a reported disconnect, shell/service state +was verified available; existing workers/fixtures were reused, not duplicated. diff --git a/docs/plans/retained-analysis/issues.md b/docs/plans/retained-analysis/issues.md index afd6d272..63bd10aa 100644 --- a/docs/plans/retained-analysis/issues.md +++ b/docs/plans/retained-analysis/issues.md @@ -3,5 +3,5 @@ | ID | Finding | Owner | State / disposition | | --- | --- | --- | --- | | V1 | Shared API/Run/UI hooks overlap PR102–110 | parent/repository lead | pending coordination; continue additive M1 | -| V2 | No PostgreSQL binaries/configuration or qualified training runtime in selected environment | environment/parent | actual-store acceptance blocked; do not create credentials | +| V2 | Initial PostgreSQL/runtime absence | environment/parent | resolved for local tests after parent clarified disposable setup scope; PG17.11 and pinned CPU runtime provisioned under /tmp; actual direct-query tests pass | | V3 | General results and saved view revisions are later milestones | visualization owner | preserve immutable result boundary; no early persistence engine | diff --git a/docs/plans/retained-analysis/plan.md b/docs/plans/retained-analysis/plan.md index 1dfda5ee..c597bb24 100644 --- a/docs/plans/retained-analysis/plan.md +++ b/docs/plans/retained-analysis/plan.md @@ -23,9 +23,9 @@ access, numeric, lifecycle and provenance guarantees. View opening is inert. | ID | Observable criterion | Kind | Environment | Mode | Status | Evidence | | --- | --- | --- | --- | --- | --- | --- | | A1 | Closed named query rejects malformed identities, unknown fields and unbounded requests before reads; exact substitutions fail before result return | contract | not-applicable | automated | passed | [focused tests](reports/m1/focused-tests.log) | -| A2 | Exact metric values, stable examples, pagination/support and frozen identity agree with retained bytes and actual PostgreSQL | integration | required-real | automated | blocked | existing DB configuration absent | +| A2 | Exact metric values, stable examples, pagination/support and frozen identity agree with retained bytes and actual PostgreSQL | integration | required-real | automated | passed | [actual retained query tests](reports/m3-actual/retained-query-tests.log) | | A3 | Actual Runs browser supports keyboard, linked selections, narrow layout, stale replies, revocation, malformed/large specs, offline assets and cold reopen | user-workflow | required-real | automated | partial | [isolated actual Chromium renderer](reports/m2/browser.json); shared Runs hooks pending | -| A4 | Query/export reauthorize every retrieval, no cache authority, no computation or mutation on opening | integration | required-real | automated | pending | query tests and actual-store qualification | +| A4 | Query/export reauthorize every retrieval, no cache authority, no computation or mutation on opening | integration | required-real | automated | partial | [real direct-query/credential tests](reports/m3-actual/retained-query-tests.log); authenticated HTTP/UI still pending | ## Scope @@ -63,10 +63,13 @@ accessibility/frontend guidance from Coding-Standards dcc56f26. No callable Standards Engine is exposed; this is source-guided routing, not certification. Brief `libfile_e94877d6735c8191a6e5d78c82d1151b` read in full (five pages). -Current source lacks PostgreSQL binaries, TULDOK_DATABASE_URL and a qualified -training runtime. Do not manufacture credentials or claim actual-store evidence. -The first query is useful independently of UI hook coordination; tests separate -controlled owner fixtures from required-real PostgreSQL and retained Runs. +Initial source environment lacked PostgreSQL/configuration and a qualified CPU +runtime. The parent clarified that a disposable local test database and ordinary +official dependency setup are within scope. Task-owned PostgreSQL 17.11 now runs +under `/tmp`, using the existing local_postgres helper; pinned CPU packages are +provisioned in a separate test runtime. Six actual retained-query tests and all +13 original query tests pass. Initial skipped evidence remains unchanged. +No production catalog, credential, role or system-service change is involved. ## Simplicity And Ownership Review @@ -97,6 +100,8 @@ controlled owner fixtures from required-real PostgreSQL and retained Runs. ### M1: Authorized bounded retained query **Allowed write set:** `retained_analysis.py`, `tests/test_retained_analysis.py`, +`tests/retained_analysis_actual_fixture.py`, `tests/test_retained_analysis_actual.py`, +`tests/test_retained_analysis_http.py`, `tests/browser_retained_analysis_actual.cjs`, `docs/contracts/retained-analysis-query.md`, `docs/plans/retained-analysis/**`. Implement closed validation, exact retained identity, owned bounded SQL, @@ -124,7 +129,8 @@ use interpreter under strict CSP. Gate A3 plus actual A2/A4. - Parent relay/lead coordination is pending. Cross-thread collaboration send to source_thread_id returns `agent ... not found`; no shared-file edits authorized by coordination yet. No GitHub comment to another person is substituted. -- Actual PostgreSQL/training environment unavailable. No credentials created. +- Authenticated API-to-Runs acceptance awaits shared hooks. The disposable + PostgreSQL/native retained Run and direct-query acceptance are now available. ## Re-Plan Triggers diff --git a/docs/plans/retained-analysis/reports/m3-actual/environment.json b/docs/plans/retained-analysis/reports/m3-actual/environment.json new file mode 100644 index 00000000..3cf5557c --- /dev/null +++ b/docs/plans/retained-analysis/reports/m3-actual/environment.json @@ -0,0 +1,52 @@ +{ + "postgres": "17.11 (Debian 17.11-0+deb13u1)", + "listen_addresses": "", + "application_role": { + "superuser": false, + "createdb": false, + "createrole": false + }, + "postgres_scope": "Task-owned disposable local instance; no production configuration selected", + "training_probe": { + "schema_version": 1, + "available": true, + "adapter": { + "name": "tinycnn_cpu", + "version": 2 + }, + "runtime": { + "python": "3.12.14", + "device": "cpu", + "threads": 1, + "torch": "2.8.0+cpu", + "torchvision": "0.23.0+cpu", + "scikit_learn": "1.7.2" + }, + "problems": [] + }, + "deb_sha256": { + "postgresql-17_17.11-0+deb13u1_amd64.deb": "d2ce1ddffafa783f9acda4c92c86fc21e8288bff3782d739294f14fa797d7886", + "postgresql-client-17_17.11-0+deb13u1_amd64.deb": "9d8558f8dd57c8e92e218a20698383575d53742ca3f9e7c2b7fe5f246d5216ae" + }, + "fixture": { + "catalog_id": "8622700dae5345e68c77ac26a7c54d71", + "run_id": "3b55365925ed45b391072918503f7c5f", + "artifact_count": 22 + }, + "source_sha256": { + "retained_analysis.py": "317ba63b0f89367ba26dd62b8157910654943eb8a9d3ab1442f09f09827f218b", + "tests/retained_analysis_actual_fixture.py": "5e8759c7715de85b8df886727d11335cc913d78d178b3d787e09778aab29ff55", + "tests/test_retained_analysis_actual.py": "255abedd2980dd36deee27ae0a12c1f1e3870c3c92c3203bea334ae7bfd8e651" + }, + "claims": [ + "Actual PostgreSQL SQL", + "Normal retained native classifier Run", + "Original artifact numeric oracle", + "Real Access revocation; final-check timing fault injected", + "Fresh Python process reopen" + ], + "unqualified": [ + "Authenticated production API-to-Runs UI hooks pending lead coordination" + ], + "original_skipped_log_preserved": true +} diff --git a/docs/plans/retained-analysis/reports/m3-actual/fixture.json b/docs/plans/retained-analysis/reports/m3-actual/fixture.json new file mode 100644 index 00000000..b7010dc2 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m3-actual/fixture.json @@ -0,0 +1,137 @@ +{ + "format": "retained_analysis_actual_fixture_v1", + "scope": "Authored transport fixture; no model-quality claim", + "catalog_path": "/tmp/tuldok-analysis-real-run/catalog", + "catalog_id": "8622700dae5345e68c77ac26a7c54d71", + "run_id": "3b55365925ed45b391072918503f7c5f", + "release_sha256": "57e7d1e2abb2e46e50b1f22e3a210f77058b6d7e8e1835df2f6cdb7941a4a25a", + "request": { + "query_id": "retained_checkpoint_examples", + "query_version": 1, + "run_id": "3b55365925ed45b391072918503f7c5f", + "evaluation_sha256": "6cb8e64a1834bd1479735acd67a1a3426a49addf945cc03774e40ee30b69fd01", + "checkpoint_sha256": "73d96dc058a33810f87e67cf6097883b59266dee287c35df855b33666bb027c7", + "metric_id": "accuracy", + "metric_definition_sha256": "77c3f8b930e3fdf39f4db928432abe3fc56dcca47ebb257e3755c13a7c81a81f", + "limit": 1, + "offset": 0 + }, + "artifacts": [ + { + "name": "metrics.json", + "sha256": "3d503a3717a8ee8c9cc6079676297b986216dd5d7b9ea83838d0aa70ff80a646", + "bytes": 1635 + }, + { + "name": "test-metrics.json", + "sha256": "1650ec79b25db20031bf085b69c80513c14145afcfb9052f348dd34bdcbb2df1", + "bytes": 583 + }, + { + "name": "predictions-validation.json", + "sha256": "a43883680f82d078febaf20984cc7c211bf66a0eac4acd0e0b6b919b11cd0bdb", + "bytes": 1698 + }, + { + "name": "predictions-test.json", + "sha256": "4d1f23e0a606280fdf0a0851380c167ec07f618addcef0797f1ef6cb04462d38", + "bytes": 1680 + }, + { + "name": "checkpoint.pt", + "sha256": "b53a5aac7978fc02d6a3b5409b14bb2cdf98502a4c9bccde2ca30b050c102254", + "bytes": 9895 + }, + { + "name": "checkpoint-epoch-0001.json", + "sha256": "73d96dc058a33810f87e67cf6097883b59266dee287c35df855b33666bb027c7", + "bytes": 526 + }, + { + "name": "checkpoint-epoch-0002.json", + "sha256": "daeb53dc1671f9b35ddece10f92364068e526dd61274deb8a134d3ac45e168a8", + "bytes": 526 + }, + { + "name": "checkpoints.json", + "sha256": "7547aeb68ff0171de775a2c3b309ed2f9e9c32c76f8356ea75bc2eb0a0ccb82a", + "bytes": 1060 + }, + { + "name": "fitted-transform.json", + "sha256": "6ef6f1167d13ea15822909c8e88a04deeebad848012d4c0c3ca4e7edf17f63bc", + "bytes": 68 + }, + { + "name": "metric-definitions.json", + "sha256": "f07af3fc0b9813be8372cf2a0a90eeb49b44a1220ec8e4a744c25ca37da89545", + "bytes": 1724 + }, + { + "name": "model-definition.json", + "sha256": "30100b577a37dad313ec1ed3c5f9a515ee2dece0ce6929f4cd9455ccea678b4d", + "bytes": 450 + }, + { + "name": "model-evidence.json", + "sha256": "6cb8e64a1834bd1479735acd67a1a3426a49addf945cc03774e40ee30b69fd01", + "bytes": 2316 + }, + { + "name": "observations.json", + "sha256": "dc3166b7143c4ee022a61bcdf7f3a2751e3adb8360af694a8f7353c38d3a80a6", + "bytes": 2508 + }, + { + "name": "output-policy.json", + "sha256": "ee8f417a377b4c02aeafda8d604525de180fe0712ca0a97359806ab7b904b5ab", + "bytes": 65 + }, + { + "name": "probe.json", + "sha256": "63b0a150c9a43a8bbdb15a339ad89bad1cce9a0c23ef4ea39d0b2f56b9c01a9c", + "bytes": 1368 + }, + { + "name": "probes-epoch-0001.json", + "sha256": "fd2ce83def4c4f7e13caf06f5d5739d5423e9328d4d98a99407ab95dadf96c52", + "bytes": 436 + }, + { + "name": "probes-epoch-0002.json", + "sha256": "076e3bbe95d3eb4c7634f3e452c0984bfb1ff3e32d542bfac0de95e425448dfe", + "bytes": 434 + }, + { + "name": "profile.json", + "sha256": "17d3b8c1d75dc1fbd211b6cdfc41cc81e93bd555d7fff8801b825de37eff7e5a", + "bytes": 898 + }, + { + "name": "validation-logits.json", + "sha256": "997156a0e81ecf3ce277bf1f8b78b19bf18036535f287988af2119dff414a6b7", + "bytes": 853 + }, + { + "name": "weights-epoch-0001.pt", + "sha256": "d94283cf333d8b83095da3f300f88c3b4c388466b697b3e9cdb86bd48a289b6f", + "bytes": 9895 + }, + { + "name": "weights-epoch-0002.pt", + "sha256": "b53a5aac7978fc02d6a3b5409b14bb2cdf98502a4c9bccde2ca30b050c102254", + "bytes": 9895 + }, + { + "name": "artifact-manifest.json", + "sha256": "332df4a2baae09fab5d8b64d9fc8a3363cac15f2d1c3cbca6b37f23d845d5701", + "bytes": 3959 + } + ], + "source_sha256": { + "retained_analysis.py": "317ba63b0f89367ba26dd62b8157910654943eb8a9d3ab1442f09f09827f218b", + "tests/retained_analysis_actual_fixture.py": "5e8759c7715de85b8df886727d11335cc913d78d178b3d787e09778aab29ff55", + "runs.py": "ae126e0d6493d925b171d2c9da874f16d7b76e881160e98f6f6b2e2f144ad0c2", + "model_evidence.py": "04012022740f45fc03ad11351a7efe4946e574890bb814fcdf5871b873a5701b" + } +} diff --git a/docs/plans/retained-analysis/reports/m3-actual/original-query-tests.log b/docs/plans/retained-analysis/reports/m3-actual/original-query-tests.log new file mode 100644 index 00000000..8c1b6610 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m3-actual/original-query-tests.log @@ -0,0 +1,18 @@ +test_parameterized_curve_and_stable_error_page_on_actual_postgres (test_retained_analysis.ActualPostgresSqlTests.test_parameterized_curve_and_stable_error_page_on_actual_postgres) ... ok +test_exact_frozen_examples_and_retained_confidence (test_retained_analysis.ProjectionTests.test_exact_frozen_examples_and_retained_confidence) ... ok +test_foreign_metric_checkpoint_and_population_are_distinct_failures (test_retained_analysis.ProjectionTests.test_foreign_metric_checkpoint_and_population_are_distinct_failures) ... ok +test_unsupported_task_and_oversize_are_explicit (test_retained_analysis.ProjectionTests.test_unsupported_task_and_oversize_are_explicit) ... ok +test_catalog_mismatch_is_refused (test_retained_analysis.QueryBoundaryTests.test_catalog_mismatch_is_refused) ... ok +test_error_filter_does_not_change_metric_population_and_page_identity (test_retained_analysis.QueryBoundaryTests.test_error_filter_does_not_change_metric_population_and_page_identity) ... ok +test_exact_provenance_and_values_with_fresh_access_outside_snapshot (test_retained_analysis.QueryBoundaryTests.test_exact_provenance_and_values_with_fresh_access_outside_snapshot) ... ok +test_export_and_repeated_retrieval_do_not_bypass_current_authority (test_retained_analysis.QueryBoundaryTests.test_export_and_repeated_retrieval_do_not_bypass_current_authority) ... ok +test_malformed_catalog_envelope_preserves_typed_failure (test_retained_analysis.QueryBoundaryTests.test_malformed_catalog_envelope_preserves_typed_failure) ... ok +test_nested_transaction_and_oversized_response_refused (test_retained_analysis.QueryBoundaryTests.test_nested_transaction_and_oversized_response_refused) ... ok +test_revocation_during_read_prevents_return (test_retained_analysis.QueryBoundaryTests.test_revocation_during_read_prevents_return) ... ok +test_closed_bounds_and_types_before_evidence_read (test_retained_analysis.RequestTests.test_closed_bounds_and_types_before_evidence_read) ... ok +test_defaults_and_explicit_field_projection (test_retained_analysis.RequestTests.test_defaults_and_explicit_field_projection) ... ok + +---------------------------------------------------------------------- +Ran 13 tests in 0.024s + +OK diff --git a/docs/plans/retained-analysis/reports/m3-actual/preparation.log b/docs/plans/retained-analysis/reports/m3-actual/preparation.log new file mode 100644 index 00000000..15572f24 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m3-actual/preparation.log @@ -0,0 +1 @@ +{"artifacts": [{"bytes": 1635, "name": "metrics.json", "sha256": "3d503a3717a8ee8c9cc6079676297b986216dd5d7b9ea83838d0aa70ff80a646"}, {"bytes": 583, "name": "test-metrics.json", "sha256": "1650ec79b25db20031bf085b69c80513c14145afcfb9052f348dd34bdcbb2df1"}, {"bytes": 1698, "name": "predictions-validation.json", "sha256": "a43883680f82d078febaf20984cc7c211bf66a0eac4acd0e0b6b919b11cd0bdb"}, {"bytes": 1680, "name": "predictions-test.json", "sha256": "4d1f23e0a606280fdf0a0851380c167ec07f618addcef0797f1ef6cb04462d38"}, {"bytes": 9895, "name": "checkpoint.pt", "sha256": "b53a5aac7978fc02d6a3b5409b14bb2cdf98502a4c9bccde2ca30b050c102254"}, {"bytes": 526, "name": "checkpoint-epoch-0001.json", "sha256": "73d96dc058a33810f87e67cf6097883b59266dee287c35df855b33666bb027c7"}, {"bytes": 526, "name": "checkpoint-epoch-0002.json", "sha256": "daeb53dc1671f9b35ddece10f92364068e526dd61274deb8a134d3ac45e168a8"}, {"bytes": 1060, "name": "checkpoints.json", "sha256": "7547aeb68ff0171de775a2c3b309ed2f9e9c32c76f8356ea75bc2eb0a0ccb82a"}, {"bytes": 68, "name": "fitted-transform.json", "sha256": "6ef6f1167d13ea15822909c8e88a04deeebad848012d4c0c3ca4e7edf17f63bc"}, {"bytes": 1724, "name": "metric-definitions.json", "sha256": "f07af3fc0b9813be8372cf2a0a90eeb49b44a1220ec8e4a744c25ca37da89545"}, {"bytes": 450, "name": "model-definition.json", "sha256": "30100b577a37dad313ec1ed3c5f9a515ee2dece0ce6929f4cd9455ccea678b4d"}, {"bytes": 2316, "name": "model-evidence.json", "sha256": "6cb8e64a1834bd1479735acd67a1a3426a49addf945cc03774e40ee30b69fd01"}, {"bytes": 2508, "name": "observations.json", "sha256": "dc3166b7143c4ee022a61bcdf7f3a2751e3adb8360af694a8f7353c38d3a80a6"}, {"bytes": 65, "name": "output-policy.json", "sha256": "ee8f417a377b4c02aeafda8d604525de180fe0712ca0a97359806ab7b904b5ab"}, {"bytes": 1368, "name": "probe.json", "sha256": "63b0a150c9a43a8bbdb15a339ad89bad1cce9a0c23ef4ea39d0b2f56b9c01a9c"}, {"bytes": 436, "name": "probes-epoch-0001.json", "sha256": "fd2ce83def4c4f7e13caf06f5d5739d5423e9328d4d98a99407ab95dadf96c52"}, {"bytes": 434, "name": "probes-epoch-0002.json", "sha256": "076e3bbe95d3eb4c7634f3e452c0984bfb1ff3e32d542bfac0de95e425448dfe"}, {"bytes": 898, "name": "profile.json", "sha256": "17d3b8c1d75dc1fbd211b6cdfc41cc81e93bd555d7fff8801b825de37eff7e5a"}, {"bytes": 853, "name": "validation-logits.json", "sha256": "997156a0e81ecf3ce277bf1f8b78b19bf18036535f287988af2119dff414a6b7"}, {"bytes": 9895, "name": "weights-epoch-0001.pt", "sha256": "d94283cf333d8b83095da3f300f88c3b4c388466b697b3e9cdb86bd48a289b6f"}, {"bytes": 9895, "name": "weights-epoch-0002.pt", "sha256": "b53a5aac7978fc02d6a3b5409b14bb2cdf98502a4c9bccde2ca30b050c102254"}, {"bytes": 3959, "name": "artifact-manifest.json", "sha256": "332df4a2baae09fab5d8b64d9fc8a3363cac15f2d1c3cbca6b37f23d845d5701"}], "catalog_id": "8622700dae5345e68c77ac26a7c54d71", "catalog_path": "/tmp/tuldok-analysis-real-run/catalog", "format": "retained_analysis_actual_fixture_v1", "release_sha256": "57e7d1e2abb2e46e50b1f22e3a210f77058b6d7e8e1835df2f6cdb7941a4a25a", "request": {"checkpoint_sha256": "73d96dc058a33810f87e67cf6097883b59266dee287c35df855b33666bb027c7", "evaluation_sha256": "6cb8e64a1834bd1479735acd67a1a3426a49addf945cc03774e40ee30b69fd01", "limit": 1, "metric_definition_sha256": "77c3f8b930e3fdf39f4db928432abe3fc56dcca47ebb257e3755c13a7c81a81f", "metric_id": "accuracy", "offset": 0, "query_id": "retained_checkpoint_examples", "query_version": 1, "run_id": "3b55365925ed45b391072918503f7c5f"}, "run_id": "3b55365925ed45b391072918503f7c5f", "scope": "Authored transport fixture; no model-quality claim", "source_sha256": {"model_evidence.py": "04012022740f45fc03ad11351a7efe4946e574890bb814fcdf5871b873a5701b", "retained_analysis.py": "317ba63b0f89367ba26dd62b8157910654943eb8a9d3ab1442f09f09827f218b", "runs.py": "ae126e0d6493d925b171d2c9da874f16d7b76e881160e98f6f6b2e2f144ad0c2", "tests/retained_analysis_actual_fixture.py": "5e8759c7715de85b8df886727d11335cc913d78d178b3d787e09778aab29ff55"}} diff --git a/docs/plans/retained-analysis/reports/m3-actual/qualification.md b/docs/plans/retained-analysis/reports/m3-actual/qualification.md new file mode 100644 index 00000000..9f2fd61a --- /dev/null +++ b/docs/plans/retained-analysis/reports/m3-actual/qualification.md @@ -0,0 +1,94 @@ +# Actual PostgreSQL and retained Run qualification + +Date: 2026-10-20. This follow-up resolves the initial environment absence after +the parent confirmed ordinary disposable test infrastructure is in scope. +The earlier [12-pass/one-skip record](../m1/focused-tests.log) is unchanged. + +## Observed boundaries + +- Official Debian PostgreSQL 17.11 packages were downloaded and extracted under + `/tmp/tuldok-pg-bin`; no system package or service was changed. The existing + `scripts/local_postgres.py` owns the private service at + `/tmp/tuldok-analysis-pg`. It listens on its private Unix socket only. The + application role is not superuser and cannot create databases or roles. +- Repository-pinned Torch 2.8.0+cpu, torchvision 0.23.0+cpu and scikit-learn 1.7.2 + were installed in `/tmp/tuldok-training-runtime/venv`. The normal model-aware + runtime probe reports available. [Environment](environment.json) records + observed versions and official package hashes, without credentials. +- `tests/retained_analysis_actual_fixture.py` used the normal Dataset owner, + six authored images, frozen release, Pipeline validation and supervised native + classifier Run. Two epochs produced 22 retained artifacts. This is transport + evidence, not a model-quality or scientific separation claim. +- [Fixture receipt](fixture.json) contains exact Run/result/artifact identities + and source hashes. The retained catalog/artifacts remain in the task-owned + directory `/tmp/tuldok-analysis-real-run`; its token is private and is never + copied to a report or command argument. + +## Results + +The original query suite now passes **13/13**, including the formerly skipped +actual PostgreSQL SQL test: [log](original-query-tests.log). + +The new actual retained-query suite passes **6/6**: [log](retained-query-tests.log). +It reads metric observations, checkpoint inventory, probe membership and +probabilities directly from original retained artifact bytes and compares them +against the actual SQL query output. It exercises all three metric definitions, +both checkpoints, stable paginated example IDs, support/error filtering, units, +inert query/export behavior, unchanged Run document/artifact hashes, restored +session timeout, real issued/revoked inspect credentials, artifact tamper +re-verification and a fresh Python process reopening the same exact result. + +Final-check revocation uses an explicitly fault-injected timing wrapper around +Access.require; the revocation and credential check themselves use the real +Access owner and PostgreSQL. The repeated-tamper test restores exact original +bytes in finally. No verifier/authentication/query data is substituted. + +Separate GPT-6.1 Sol High review found no blocking evidence/oracle defect. The +reviewer independently reran the original 13 tests and the three non-mutating +actual tests: **16 passed, zero skips**. It inspected the mutation tests without +repeating them, verified source/receipt hashes and private file modes, and did +not create another service, fixture or training Run. + +Reviewed source SHA256: + +| File | SHA256 | +| --- | --- | +| retained_analysis.py | 317ba63b0f89367ba26dd62b8157910654943eb8a9d3ab1442f09f09827f218b | +| tests/retained_analysis_actual_fixture.py | 5e8759c7715de85b8df886727d11335cc913d78d178b3d787e09778aab29ff55 | +| tests/test_retained_analysis_actual.py | 255abedd2980dd36deee27ae0a12c1f1e3870c3c92c3203bea334ae7bfd8e651 | + +## Reproduce in this retained task environment + +Select the task-owned PG binaries and normal helper environment, then run with +the base application dependencies and the existing fixture: + +```sh +export PATH="/tmp/tuldok-pg-bin/usr/lib/postgresql/17/bin:/tmp/tuldok-analysis-venv/bin:$PATH" +eval "$(python scripts/local_postgres.py env --directory /tmp/tuldok-analysis-pg)" +export TULDOK_TRAINING_PYTHON=/tmp/tuldok-training-runtime/venv/bin/python +export TULDOK_ANALYSIS_ACTUAL=1 +export TULDOK_ANALYSIS_FIXTURE=/tmp/tuldok-analysis-real-run +python -m unittest discover -s tests -p test_retained_analysis_actual.py -v +``` + +For a fresh task-owned instance, provision the ordinary repository requirements, +use the existing local-service helper with a new private directory, then prepare +one fixture explicitly. The preparation refuses an existing destination. Do not +point these fixtures at a production catalog or repeat training just to reopen +the retained result. + +## Remaining acceptance + +`tests/test_retained_analysis_http.py` and +`tests/browser_retained_analysis_actual.cjs` are prepared for the coordinated +new operation contracts/routes and Runs mount. They have syntax checks only; +they are **not yet executed or accepted** because those shared hooks have not +been approved/integrated. The HTTP test requires explicit +`TULDOK_ANALYSIS_HTTP=1`; it must fail if the exact new contracts are absent. +The actual-browser test uses normal app.py/authentication and retained data, +without test-only routes. Its selectors and operation paths must be confirmed +against the eventual agreed integration before execution. + +The existing isolated renderer test remains actual Chromium evidence over +authored data. It does not become authenticated Runs evidence merely because +the direct query now passes actual PostgreSQL tests. diff --git a/docs/plans/retained-analysis/reports/m3-actual/retained-query-tests.log b/docs/plans/retained-analysis/reports/m3-actual/retained-query-tests.log new file mode 100644 index 00000000..c01147a1 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m3-actual/retained-query-tests.log @@ -0,0 +1,11 @@ +test_actual_sql_curve_and_examples_equal_original_retained_artifacts (test_retained_analysis_actual.ActualRetainedAnalysisTests.test_actual_sql_curve_and_examples_equal_original_retained_artifacts) ... ok +test_new_process_cold_reopen_preserves_exact_result (test_retained_analysis_actual.ActualRetainedAnalysisTests.test_new_process_cold_reopen_preserves_exact_result) ... ok +test_query_and_export_are_inert_and_restore_session_settings (test_retained_analysis_actual.ActualRetainedAnalysisTests.test_query_and_export_are_inert_and_restore_session_settings) ... ok +test_real_credential_revocation_blocks_repeated_query_and_export (test_retained_analysis_actual.ActualRetainedAnalysisTests.test_real_credential_revocation_blocks_repeated_query_and_export) ... ok +test_repeated_query_reverifies_hash_bound_artifact (test_retained_analysis_actual.ActualRetainedAnalysisTests.test_repeated_query_reverifies_hash_bound_artifact) ... ok +test_revocation_at_final_authorization_uses_current_real_credential (test_retained_analysis_actual.ActualRetainedAnalysisTests.test_revocation_at_final_authorization_uses_current_real_credential) ... ok + +---------------------------------------------------------------------- +Ran 6 tests in 0.693s + +OK diff --git a/tests/browser_retained_analysis_actual.cjs b/tests/browser_retained_analysis_actual.cjs new file mode 100644 index 00000000..6a882b58 --- /dev/null +++ b/tests/browser_retained_analysis_actual.cjs @@ -0,0 +1,98 @@ +// Prepared authenticated Runs acceptance. Requires the coordinated production hooks. +// Uses the existing retained fixture and normal app.py; no handler/data substitutes. +'use strict'; +const assert = require('node:assert/strict'), fs = require('node:fs'), os = require('node:os'), path = require('node:path'); +const {spawn} = require('node:child_process'); +const {waitForDebugger} = require('./browser_startup.cjs'); +const fixtureAuth = require('./auth_helpers.cjs').authenticatedFixture(); +const root = path.resolve(__dirname, '..'), children = [], profile = fs.mkdtempSync(path.join(os.tmpdir(), 'tuldok-retained-actual-browser-')); +const pause = ms => new Promise(resolve => setTimeout(resolve, ms)); +async function until(check, message) { for (let i = 0; i < 300; i++) { if (await check()) return; await pause(50); } throw Error(message || 'Actual Runs acceptance timed out'); } +async function stop(child) { + if (child.exitCode !== null || child.signalCode !== null) return; + await new Promise(resolve => { + const timer = setTimeout(() => child.kill('SIGKILL'), 5000); + child.once('exit', () => { clearTimeout(timer); resolve(); }); child.kill('SIGINT'); + }); +} +(async () => { + if (process.env.TULDOK_ANALYSIS_HTTP !== '1' || !process.env.TULDOK_ANALYSIS_FIXTURE) throw Error('Explicit integrated acceptance and a prepared actual retained fixture are required.'); + const fixture = JSON.parse(fs.readFileSync(path.join(process.env.TULDOK_ANALYSIS_FIXTURE, 'fixture.json'), 'utf8')); + let output = '', serverErrors = ''; + const server = spawn(process.env.PYTHON || 'python3', ['-u', 'app.py', '--port', '0', '--data', fixture.catalog_path], {cwd: root}); children.push(server); + server.stdout.on('data', chunk => output += chunk); server.stderr.on('data', chunk => serverErrors += chunk); + await until(() => /127\.0\.0\.1:(\d+)/.test(output), 'Actual app did not publish its local endpoint'); + const base = 'http://127.0.0.1:' + output.match(/127\.0\.0\.1:(\d+)/)[1]; + await fixtureAuth.register(base, fixture.catalog_path, root); + const response = await fixtureAuth.fetch(base + '/api/agent/capabilities'); + assert.equal(response.status, 200); + const capabilities = await response.json(); + const operation = capabilities.operations.find(item => item.id === 'runs.retained_analysis' || item.operation_id === 'runs.retained_analysis'); + assert.ok(operation, 'The coordinated retained-analysis operation must be registered before actual browser acceptance'); + const contract = operation.contracts.find(item => item.version === 1); + assert.ok(contract?.sha256, 'The browser must use the exact named v1 contract'); + const query = async body => { + const {run_id, ...arguments_} = body; + const reply = await fixtureAuth.fetch(base + '/api/workspace/runs/' + run_id + '/retained-analysis', { + method: 'POST', headers: {'Content-Type': 'application/json', 'Tuldok-Operation-Contract': 'runs.retained_analysis/1/' + contract.sha256}, body: JSON.stringify(arguments_) + }); + assert.equal(reply.status, 200); return reply.json(); + }; + const expected = await query(fixture.request); + const browser = spawn(process.env.BROWSER || '/usr/bin/chromium', ['--headless', '--no-sandbox', '--disable-gpu', '--remote-debugging-port=0', '--user-data-dir=' + profile, 'about:blank'], {stdio: 'ignore'}); children.push(browser); + const debuggerPort = await waitForDebugger(browser, path.join(profile, 'DevToolsActivePort')); + const targets = await (await fetch(`http://127.0.0.1:${debuggerPort}/json`)).json(); + const ws = new WebSocket(targets.find(item => item.type === 'page').webSocketDebuggerUrl); + await new Promise(resolve => ws.addEventListener('open', resolve)); + let sequence = 0, held; const calls = new Map(), errors = [], remote = [], actualReplies = []; + const send = (method, params = {}) => new Promise((resolve, reject) => { const id = ++sequence; calls.set(id, {resolve, reject}); ws.send(JSON.stringify({id, method, params})); }); + ws.addEventListener('message', event => { + const value = JSON.parse(event.data); + if (value.id) { const pending = calls.get(value.id); calls.delete(value.id); value.error ? pending.reject(Error(JSON.stringify(value.error))) : pending.resolve(value.result); } + if (value.method === 'Runtime.exceptionThrown') errors.push(value.params.exceptionDetails.text); + if (value.method === 'Network.requestWillBeSent' && /^https?:/.test(value.params.request.url) && !value.params.request.url.startsWith(base)) remote.push(value.params.request.url); + if (value.method === 'Fetch.requestPaused') held = value.params; + if (value.method === 'Network.responseReceived' && value.params.response.url.endsWith('/retained-analysis')) actualReplies.push(value.params.response.status); + }); + const evaluate = async expression => { + const value = await send('Runtime.evaluate', {expression, returnByValue: true, awaitPromise: true}); + if (value.exceptionDetails) throw Error(value.exceptionDetails.exception?.description || value.exceptionDetails.text); + return value.result.value; + }; + const host = '([...document.querySelectorAll("#real-runs-root h3")].find(node=>node.textContent==="Retained checkpoint analysis")?.parentElement)'; + const ready = () => evaluate(`!!${host}?.querySelector('svg') && ${host}?.getAttribute('aria-busy')==='false'`); + await send('Runtime.enable'); await send('Network.enable'); await send('Page.enable'); + await fixtureAuth.browser(send, base); + await send('Page.navigate', {url: base + '/workspaces'}); + await until(() => evaluate('!!document.querySelector("#dataset") && !document.querySelector("#dataset").disabled')); + await evaluate('document.querySelector("#dataset").value="catalog";document.querySelector("#dataset").dispatchEvent(new Event("change",{bubbles:true}))'); + await until(() => evaluate('document.querySelector("#notice")?.textContent==="Collection ready."')); + await evaluate('document.querySelector("#nav-runs").click()'); + await until(ready, 'Actual authenticated Runs did not mount the retained renderer'); + for (const point of expected.curve) assert.ok((await evaluate(`${host}.textContent`)).includes(`Epoch ${point.epoch}: ${point.value}`)); + await evaluate(`${host}.querySelectorAll('button')[0].focus()`); + await send('Input.dispatchKeyEvent', {type: 'keyDown', key: 'Enter', code: 'Enter', text: '\r', windowsVirtualKeyCode: 13}); + await send('Input.dispatchKeyEvent', {type: 'keyUp', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13}); + await until(ready); + for (const row of expected.examples.rows) assert.ok((await evaluate(`${host}.querySelector('tbody').textContent`)).includes(row.example_id)); + await send('Emulation.setDeviceMetricsOverride', {width: 390, height: 844, deviceScaleFactor: 1, mobile: false}); await pause(100); + assert.equal(await evaluate('document.documentElement.scrollWidth<=390'), true); + // Hold an actual response after dispatch, navigate away, then release it. + await send('Fetch.enable', {patterns: [{urlPattern: base + '/api/workspace/runs/' + fixture.run_id + '/retained-analysis', requestStage: 'Response'}]}); + await evaluate(`${host}.querySelectorAll('button')[1].click()`); + await until(() => !!held, 'Expected an actual retained query response to pause'); + await evaluate('document.querySelector("#nav-data").click()'); + await send('Fetch.continueRequest', {requestId: held.requestId}); await send('Fetch.disable'); held = null; + await pause(100); + assert.equal(await evaluate('document.querySelector("#view-runs").hidden'), true); + await evaluate('document.querySelector("#nav-runs").click()'); await until(ready); + await send('Page.reload', {ignoreCache: true}); await until(ready); + for (const point of expected.curve) assert.ok((await evaluate(`${host}.textContent`)).includes(`Epoch ${point.epoch}: ${point.value}`)); + assert.deepEqual(errors, []); assert.deepEqual(remote, []); + assert.ok(actualReplies.includes(200)); + console.log(JSON.stringify({status: 'passed', evidence: 'actual-PostgreSQL-native-Run-authenticated-Runs-browser', run_id: fixture.run_id, evaluation_sha256: fixture.request.evaluation_sha256, exact_curve: expected.curve, checks: ['actual named query', 'retained numeric oracle', 'linked keyboard example table', '390px layout', 'held real response after navigation', 'cache-bypassed page reopen', 'local chart assets']}, null, 2)); + ws.close(); +})().catch(error => { console.error(error); process.exitCode = 1; }).finally(async () => { + for (const child of children.reverse()) await stop(child); + fs.rmSync(profile, {recursive: true, force: true}); +}); diff --git a/tests/retained_analysis_actual_fixture.py b/tests/retained_analysis_actual_fixture.py new file mode 100644 index 00000000..2e63548e --- /dev/null +++ b/tests/retained_analysis_actual_fixture.py @@ -0,0 +1,81 @@ +"""Prepare a small actual native classifier Run for query/HTTP/browser acceptance. + +Uses the normal PostgreSQL catalog, explicit local test owner, frozen release, +Pipeline validation and supervised CPU Run. No retained document is manufactured. +The six authored images establish transport/numeric behavior, not model quality. +""" +import argparse +import copy +import hashlib +import json +import os +from pathlib import Path +import sys +import time + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT)) +sys.path.insert(0, str(ROOT / 'tests')) +sys.path.insert(0, str(ROOT / 'tests' / 'fixtures')) +from app import Dataset +from auth_helpers import ExplicitOwnerFixture +from image_classification_fixture import populate +import image_training + + +def prepare(directory): + directory = Path(directory).resolve() + directory.mkdir(mode=0o700, parents=True, exist_ok=False) + dataset = Dataset(directory / 'catalog') + try: + owner = ExplicitOwnerFixture.bootstrap(dataset) + with owner.bound(dataset): + rows = populate(dataset) + selection = {'format': 'image_classification_v1', + 'items': [{key: row[key] for key in ('id', 'revision', 'source_revision')} for row in rows], + 'ratios': {'train': 34, 'validation': 33, 'test': 33}, 'seed': 42} + preview = dataset.releases.preview(selection) + release = dataset.releases.create(dict(selection, preview_token=preview['preview_token'])) + graph = dataset.pipelines.create({'name': 'Retained analysis actual fixture', + 'release_id': release['id'], 'recipe': image_training.MODEL_RECIPE}) + changed = copy.deepcopy(graph) + next(node for node in changed['nodes'] if node['type'] == 'train')['parameters'].update( + epochs=2, widths=[4, 8, 12], input_size=32) + graph = dataset.pipelines.save(graph['id'], {'revision': graph['revision'], 'document': changed}) + validation = dataset.pipelines.validate(graph['id'], {'revision': graph['revision']}) + run = dataset.runs.submit({'request_key': 'retained-analysis-actual-v1', 'graph_id': graph['id'], + 'graph_revision': graph['revision'], 'validation_token': validation['validation_token']}) + deadline = time.monotonic() + 120 + while run['state'] in ('queued', 'running', 'cancelling') and time.monotonic() < deadline: + time.sleep(.1) + run = dataset.runs.get(run['id']) + if run['state'] != 'completed': + raise AssertionError('Actual retained fixture did not complete: ' + str(run.get('error'))) + evidence = dataset.runs.model_evidence(run['id']) + evaluation = next(item['sha256'] for item in run['artifacts'] if item['name'] == 'model-evidence.json') + request = {'query_id': 'retained_checkpoint_examples', 'query_version': 1, 'run_id': run['id'], + 'evaluation_sha256': evaluation, + 'checkpoint_sha256': evidence['checkpoint_index']['entries'][0]['checkpoint']['sha256'], + 'metric_id': 'accuracy', 'metric_definition_sha256': evidence['metric_definition_hashes']['accuracy'], + 'limit': 1, 'offset': 0} + # Secret bytes remain in a private task-owned file, never a report or argv. + descriptor = os.open(directory / 'owner-token', os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) + with os.fdopen(descriptor, 'w') as handle: + handle.write(owner.token) + receipt = {'format': 'retained_analysis_actual_fixture_v1', 'scope': 'Authored transport fixture; no model-quality claim', + 'catalog_path': str(dataset.path), 'catalog_id': dataset.db.dataset_id, + 'run_id': run['id'], 'release_sha256': run['release_sha256'], 'request': request, + 'artifacts': [{key: item[key] for key in ('name', 'sha256', 'bytes')} for item in run['artifacts']], + 'source_sha256': {name: hashlib.sha256((ROOT / name).read_bytes()).hexdigest() for name in + ('retained_analysis.py', 'tests/retained_analysis_actual_fixture.py', 'runs.py', 'model_evidence.py')}} + (directory / 'fixture.json').write_text(json.dumps(receipt, indent=2) + '\n') + return receipt + finally: + dataset.close() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--directory', required=True, type=Path) + arguments = parser.parse_args() + print(json.dumps(prepare(arguments.directory), sort_keys=True)) diff --git a/tests/test_retained_analysis_actual.py b/tests/test_retained_analysis_actual.py new file mode 100644 index 00000000..aecec870 --- /dev/null +++ b/tests/test_retained_analysis_actual.py @@ -0,0 +1,178 @@ +"""Actual PostgreSQL/retained Run acceptance, separate from renderer fixtures. + +Enable explicitly with TULDOK_ANALYSIS_ACTUAL=1 and the normal local DB/CPU +runtime configuration. An optional TULDOK_ANALYSIS_FIXTURE reuses an already +prepared task-owned fixture; no production catalog is selected implicitly. +""" +import copy +import hashlib +import json +import os +from pathlib import Path +import subprocess +import sys +import tempfile +import unittest +from unittest.mock import patch + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT)) +sys.path.insert(0, str(ROOT / 'tests')) +from app import Dataset +from access import AccessError +from auth_helpers import ExplicitOwnerFixture +from model_evidence import digest +from retained_analysis_actual_fixture import prepare +import retained_analysis +from workbench import WorkbenchError + + +@unittest.skipUnless(os.environ.get('TULDOK_ANALYSIS_ACTUAL') == '1', 'Explicit real retained-analysis acceptance required.') +class ActualRetainedAnalysisTests(unittest.TestCase): + @classmethod + def setUpClass(cls): + if not os.environ.get('TULDOK_DATABASE_URL') or not os.environ.get('TULDOK_TRAINING_PYTHON'): + raise RuntimeError('Actual acceptance requires explicitly configured local PostgreSQL and pinned CPU runtime.') + cls.temporary = None + location = os.environ.get('TULDOK_ANALYSIS_FIXTURE') + if location: + cls.fixture = Path(location).resolve() + cls.receipt = json.loads((cls.fixture / 'fixture.json').read_text()) + else: + cls.temporary = tempfile.TemporaryDirectory(prefix='tuldok-analysis-actual-') + cls.fixture = Path(cls.temporary.name) / 'fixture' + cls.receipt = prepare(cls.fixture) + cls.dataset = Dataset(cls.receipt['catalog_path']) + token = (cls.fixture / 'owner-token').read_text() + with cls.dataset.access.bind(token): + identity = cls.dataset.access.identity() + cls.owner = ExplicitOwnerFixture(cls.receipt['catalog_id'], token, identity) + cls.request = cls.receipt['request'] + cls.output = cls.dataset.runs.path / cls.receipt['run_id'] + + @classmethod + def tearDownClass(cls): + cls.dataset.close() + if cls.temporary: + cls.temporary.cleanup() + + def setUp(self): + self.enterContext(self.owner.bound(self.dataset)) + + def test_actual_sql_curve_and_examples_equal_original_retained_artifacts(self): + observations = json.loads((self.output / 'observations.json').read_bytes()) + definitions = json.loads((self.output / 'metric-definitions.json').read_bytes()) + probe = json.loads((self.output / 'probe.json').read_bytes()) + checkpoints = json.loads((self.output / 'checkpoints.json').read_bytes())['entries'] + for definition in definitions: + request = dict(self.request, metric_id=definition['id'], metric_definition_sha256=digest(definition)) + result = retained_analysis.query(self.dataset.runs, request) + self.assertEqual(result['metric']['definition'], definition) + self.assertEqual(result['metric']['units'], definition['units']) + self.assertEqual([point['value'] for point in result['curve']], + [item['value'] for item in observations if item['metric_id'] == definition['id']]) + self.assertEqual([point['checkpoint_sha256'] for point in result['curve']], + [item['checkpoint']['sha256'] for item in checkpoints]) + for checkpoint in checkpoints: + request = dict(self.request, checkpoint_sha256=checkpoint['checkpoint']['sha256']) + predictions = json.loads((self.output / f"probes-epoch-{checkpoint['clocks']['epoch']:04d}.json").read_bytes()) + pages = [] + for offset in range(len(probe['members'])): + result = retained_analysis.query(self.dataset.runs, dict(request, offset=offset)) + self.assertEqual(len(result['examples']['rows']), 1) + pages.extend(result['examples']['rows']) + self.assertEqual([row['example_id'] for row in pages], [item['frozen_reference']['id'] for item in probe['members']]) + for row, original, member in zip(pages, predictions['rows'], probe['members'], strict=True): + self.assertEqual(row['frozen_reference'], member['frozen_reference']) + self.assertEqual(row['confidence'], original['probabilities'][original['predicted_index']]) + self.assertEqual(row['error'], original['truth_index'] != original['predicted_index']) + errors = retained_analysis.query(self.dataset.runs, dict(request, errors_only=True, limit=100)) + self.assertEqual(errors['examples']['filtered_support'], sum(row['error'] for row in pages)) + self.assertTrue(all(row['error'] for row in errors['examples']['rows'])) + self.assertEqual(errors['metric']['support'], len(probe['members'])) + + def test_query_and_export_are_inert_and_restore_session_settings(self): + run_before = self.dataset.db.execute('SELECT document FROM workspace_runs WHERE id=%s', (self.request['run_id'],)).fetchone()[0] + before = {p.name: hashlib.sha256(p.read_bytes()).hexdigest() for p in self.output.iterdir() if p.is_file()} + timeout = self.dataset.db.execute('SHOW statement_timeout').fetchone()[0] + with patch('subprocess.Popen', side_effect=AssertionError('Reading a view must not launch a process')): + result = retained_analysis.query(self.dataset.runs, self.request) + exported = retained_analysis.query(self.dataset.runs, self.request, export=True) + self.assertEqual(result, exported) + self.assertEqual(self.dataset.db.execute('SHOW statement_timeout').fetchone()[0], timeout) + self.assertEqual(self.dataset.db.execute('SELECT document FROM workspace_runs WHERE id=%s', (self.request['run_id'],)).fetchone()[0], run_before) + self.assertEqual({p.name: hashlib.sha256(p.read_bytes()).hexdigest() for p in self.output.iterdir() if p.is_file()}, before) + self.assertFalse(self.dataset.runs.get(self.request['run_id'])['test_exposure']['exposed']) + + def test_real_credential_revocation_blocks_repeated_query_and_export(self): + credential = self.dataset.access.issue({'label': 'Actual analysis revocation fixture', 'scopes': ['inspect']}) + with self.dataset.access.bind(credential['token']): + retained_analysis.query(self.dataset.runs, self.request) + self.dataset.access.require('inspect', 'runs.retained_analysis', self.request['run_id']) + # Revoke through the actual owner while this credential is still + # bound, then exercise both fresh retrieval paths in that context. + with self.owner.bound(self.dataset): + self.dataset.access.revoke(credential['identity']['credential_id']) + for export in (False, True): + with self.subTest(export=export), self.assertRaises(AccessError) as caught: + retained_analysis.query(self.dataset.runs, self.request, export=export) + self.assertEqual((caught.exception.code, caught.exception.status), ('unauthenticated', 401)) + + def test_revocation_at_final_authorization_uses_current_real_credential(self): + credential = self.dataset.access.issue({'label': 'Actual final-check revocation fixture', 'scopes': ['inspect']}) + original = self.dataset.access.require + calls = 0 + + def require(scope, action, target=None, **options): + nonlocal calls + if action == 'runs.retained_analysis': + calls += 1 + if calls == 2: + # Fault-injected timing only: both revocation and the final + # check use the real Access owner and actual PostgreSQL. + with self.owner.bound(self.dataset): + self.dataset.access.revoke(credential['identity']['credential_id']) + return original(scope, action, target, **options) + + with self.dataset.access.bind(credential['token']), patch.object(self.dataset.access, 'require', side_effect=require): + with self.assertRaises(AccessError) as caught: + retained_analysis.query(self.dataset.runs, self.request) + self.assertEqual(calls, 2) + self.assertEqual((caught.exception.code, caught.exception.status), ('unauthenticated', 401)) + + def test_repeated_query_reverifies_hash_bound_artifact(self): + retained_analysis.query(self.dataset.runs, self.request) + path = self.output / 'probes-epoch-0001.json' + original = path.read_bytes() + try: + path.write_bytes(original + b' ') + with self.assertRaises(WorkbenchError): + retained_analysis.query(self.dataset.runs, self.request) + finally: + path.write_bytes(original) + retained_analysis.query(self.dataset.runs, self.request) + + def test_new_process_cold_reopen_preserves_exact_result(self): + expected = retained_analysis.query(self.dataset.runs, self.request) + # A fresh Python process opens the actual retained catalog, authenticates + # with the private fixture token and performs an inert read. No copied + # in-process result is supplied to the child as expected output. + script = '''import json,sys +from pathlib import Path +from unittest.mock import patch +from app import Dataset +import retained_analysis +root=Path(sys.argv[1]); receipt=json.loads((root/'fixture.json').read_text()) +dataset=Dataset(receipt['catalog_path']) +try: + with dataset.access.bind((root/'owner-token').read_text()), patch('subprocess.Popen',side_effect=AssertionError('Cold query must remain inert')): + print(json.dumps(retained_analysis.query(dataset.runs,receipt['request']),sort_keys=True)) +finally: dataset.close() +''' + completed = subprocess.run([sys.executable, '-c', script, str(self.fixture)], cwd=ROOT, + capture_output=True, text=True, timeout=60, check=True) + self.assertEqual(json.loads(completed.stdout), expected) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_retained_analysis_http.py b/tests/test_retained_analysis_http.py new file mode 100644 index 00000000..fe9b11bb --- /dev/null +++ b/tests/test_retained_analysis_http.py @@ -0,0 +1,119 @@ +"""Prepared real authenticated transport acceptance for the coordinated hooks. + +Enable TULDOK_ANALYSIS_HTTP=1 only after the additive operations are registered. +Reuses a prepared actual retained fixture; never patches an application handler +or substitutes query data. No test-only endpoint is installed. +""" +from http.server import ThreadingHTTPServer +import json +import os +from pathlib import Path +import sys +import threading +import unittest +from urllib.error import HTTPError +from urllib.request import Request, urlopen + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT)) +from app import Dataset, make_handler +import agent_api +import retained_analysis + + +@unittest.skipUnless(os.environ.get('TULDOK_ANALYSIS_HTTP') == '1', 'Shared retained-analysis HTTP hooks are not yet integrated.') +class ActualRetainedAnalysisHttpTests(unittest.TestCase): + @classmethod + def setUpClass(cls): + fixture = Path(os.environ['TULDOK_ANALYSIS_FIXTURE']) + cls.receipt = json.loads((fixture / 'fixture.json').read_text()) + cls.token = (fixture / 'owner-token').read_text() + cls.contracts = {name: agent_api.contract(name, 1) for name in + ('runs.retained_analysis', 'runs.export_retained_analysis')} + cls.dataset = Dataset(cls.receipt['catalog_path']) + cls.server = ThreadingHTTPServer(('127.0.0.1', 0), make_handler(cls.dataset)) + cls.thread = threading.Thread(target=cls.server.serve_forever, daemon=True) + cls.thread.start() + cls.endpoint = f'http://127.0.0.1:{cls.server.server_port}' + + @classmethod + def tearDownClass(cls): + cls.server.shutdown() + cls.server.server_close() + cls.thread.join(timeout=5) + cls.dataset.close() + + def request(self, *, token=None, export=False, body=None, selected=True): + name = 'runs.export_retained_analysis' if export else 'runs.retained_analysis' + arguments = dict(self.receipt['request']) + run_id = arguments.pop('run_id') + if body is not None: + arguments.update(body) + headers = {'Content-Type': 'application/json', 'Origin': self.endpoint, + 'Authorization': 'Bearer ' + (self.token if token is None else token)} + if selected: + headers['Tuldok-Operation-Contract'] = name + '/1/' + self.contracts[name]['sha256'] + target = self.endpoint + '/api/workspace/runs/' + run_id + '/retained-analysis' + ('/export' if export else '') + request = Request(target, data=json.dumps(arguments).encode(), headers=headers) + try: + response = urlopen(request, timeout=30) + except HTTPError as error: + response = error + with response: + raw = response.read(retained_analysis.MAX_RESPONSE_BYTES + 1) + self.assertLessEqual(len(raw), retained_analysis.MAX_RESPONSE_BYTES) + return response.status, json.loads(raw) + + def test_explicit_contract_and_route_bound_run_are_required(self): + status, value = self.request(selected=False) + self.assertEqual((status, value['code']), (409, 'contract_mismatch')) + # Existing selected-contract rules place Run ID in the path only; + # duplicate body IDs cannot bypass the route's authority even if equal. + status, value = self.request(body={'run_id': self.receipt['run_id']}) + self.assertEqual((status, value['code']), (409, 'contract_mismatch')) + self.assertNotIn('curve', value) + + def test_authenticated_http_and_export_equal_real_query(self): + with self.dataset.access.bind(self.token): + expected = retained_analysis.query(self.dataset.runs, self.receipt['request']) + for export in (False, True): + with self.subTest(export=export): + status, value = self.request(export=export) + self.assertEqual(status, 200) + self.assertEqual(value, expected) + self.assertLessEqual(len(value['examples']['rows']), 1) + self.assertNotIn('probabilities', value['examples']['rows'][0]) + + def test_stale_and_foreign_selection_never_returns_dataset(self): + for body, status, code in (({'evaluation_sha256': '0' * 64}, 409, 'stale'), + ({'metric_definition_sha256': '0' * 64}, 409, 'stale'), + ({'checkpoint_sha256': '0' * 64}, 404, 'not_found')): + with self.subTest(body=body): + actual_status, value = self.request(body=body) + self.assertEqual((actual_status, value['code']), (status, code)) + self.assertNotIn('curve', value) + + def test_closed_request_rejects_sql_and_holdout_without_exposure(self): + for body in ({'sql': 'SELECT arbitrary_data'}, {'split': 'test'}, {'limit': 101}): + with self.subTest(body=body): + status, value = self.request(body=body) + self.assertEqual((status, value['code']), (409, 'contract_mismatch')) + self.assertNotIn('examples', value) + with self.dataset.access.bind(self.token): + self.assertFalse(self.dataset.runs.get(self.receipt['run_id'])['test_exposure']['exposed']) + + def test_actual_revocation_blocks_fresh_http_and_export(self): + with self.dataset.access.bind(self.token): + credential = self.dataset.access.issue({'label': 'Retained HTTP revocation fixture', 'scopes': ['inspect']}) + self.assertEqual(self.request(token=credential['token'])[0], 200) + with self.dataset.access.bind(self.token): + self.dataset.access.revoke(credential['identity']['credential_id']) + for export in (False, True): + with self.subTest(export=export): + status, value = self.request(token=credential['token'], export=export) + self.assertEqual((status, value['code']), (401, 'unauthenticated')) + self.assertNotIn('provenance', value) + + +if __name__ == '__main__': + unittest.main() From 08620a57f926da65cb382c5392b14b40cbceaa3a Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Oct 2026 00:38:51 +0000 Subject: [PATCH 3/8] Integrate authorized retained analysis into Runs with reviewed browser qualification --- .github/workflows/tests.yml | 14 + agent_api.py | 6 + app.py | 14 + docs/contracts/retained-analysis-query.md | 26 +- docs/contracts/retained-analysis-renderer.md | 90 ++-- .../retained-analysis/execution-ledger.md | 42 ++ docs/plans/retained-analysis/issues.md | 5 +- docs/plans/retained-analysis/plan.md | 47 +- .../reports/m4-integrated/acceptance.md | 52 ++ .../m4-integrated/active-pr-write-sets.json | 469 ++++++++++++++++++ .../m4-integrated/browser-abort-initial.log | 11 + .../reports/m4-integrated/browser-errors.log | 0 .../reports/m4-integrated/browser.json | 34 ++ .../reports/m4-integrated/controllers.log | 13 + .../m4-integrated/existing-runs-browsers.log | 2 + .../reports/m4-integrated/http-initial.log | 58 +++ .../reports/m4-integrated/http-tests.log | 10 + .../independent/browser-errors.log | 0 .../m4-integrated/independent/browser.json | 34 ++ .../m4-integrated/independent/contracts.log | 8 + .../m4-integrated/independent/http-tests.log | 10 + .../independent/identity-compatibility.json | 10 + .../independent/model-controller.log | 1 + .../m4-integrated/independent/review.md | 23 + .../independent/source-sha256.json | 20 + .../m4-integrated/query-http-tests.log | 32 ++ .../reports/m4-integrated/regressions.log | 56 +++ .../reports/m4-integrated/renderer.json | 18 + .../m4-integrated/source-checkpoint.json | 89 ++++ retained_analysis.py | 4 +- retained_analysis_schema.py | 55 ++ static/retained-analysis.js | 4 + static/workspace-real.js | 31 +- static/workspace-service.js | 52 +- static/workspaces.css | 7 + static/workspaces.html | 8 +- tests/browser_retained_analysis_actual.cjs | 72 ++- tests/test_retained_analysis_contracts.py | 47 ++ tests/test_retained_analysis_http.py | 5 +- tests/test_workspace_model_controller.cjs | 20 +- 40 files changed, 1411 insertions(+), 88 deletions(-) create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/acceptance.md create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/active-pr-write-sets.json create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/browser-abort-initial.log create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/browser-errors.log create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/browser.json create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/controllers.log create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/existing-runs-browsers.log create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/http-initial.log create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/http-tests.log create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/independent/browser-errors.log create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/independent/browser.json create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/independent/contracts.log create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/independent/http-tests.log create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/independent/identity-compatibility.json create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/independent/model-controller.log create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/independent/review.md create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/independent/source-sha256.json create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/query-http-tests.log create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/regressions.log create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/renderer.json create mode 100644 docs/plans/retained-analysis/reports/m4-integrated/source-checkpoint.json create mode 100644 retained_analysis_schema.py create mode 100644 tests/test_retained_analysis_contracts.py diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index be6b2dda..703bbaf6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -307,6 +307,20 @@ jobs: env: PYTHON: python BROWSER: /usr/bin/google-chrome + - name: Qualify retained query and authenticated Runs over one actual checkpoint fixture + run: | + mkdir -p build/qa/retained-analysis + python tests/retained_analysis_actual_fixture.py --directory build/retained-analysis-fixture > build/qa/retained-analysis/fixture.json + python -m unittest discover -s tests -p 'test_retained_analysis*.py' -v > build/qa/retained-analysis/query-http-tests.log 2>&1 + node tests/test_workspace_model_controller.cjs + node tests/browser_retained_analysis.cjs > build/qa/retained-analysis/renderer.json + node tests/browser_retained_analysis_actual.cjs > build/qa/retained-analysis/runs-browser.json + env: + PYTHON: python + BROWSER: /usr/bin/google-chrome + TULDOK_ANALYSIS_ACTUAL: '1' + TULDOK_ANALYSIS_HTTP: '1' + TULDOK_ANALYSIS_FIXTURE: ${{ github.workspace }}/build/retained-analysis-fixture - name: Verify exact retained scientific comparison in the existing workspace run: node tests/browser_scientific_comparison.cjs env: diff --git a/agent_api.py b/agent_api.py index 116de002..021860b9 100644 --- a/agent_api.py +++ b/agent_api.py @@ -477,6 +477,12 @@ def model_operation(name,method,path,properties=None,required=None,*,output=None 'predictions':{'oneOf':[{'type':'null'},_EVIDENCE_DOCUMENT]}})]} model_operation('runs.model_evidence','POST','/api/workspace/runs/{run_id}/model-evidence', {'run_id':ID,'checkpoint_sha256':SHA},['run_id'],output=_EVIDENCE_RESULT) +from retained_analysis_schema import schemas as _retained_analysis_schemas +_retained_request, _retained_result = _retained_analysis_schemas(obj, text, integer, array, const, ID, SHA) +for _name, _suffix in (('runs.retained_analysis', ''), ('runs.export_retained_analysis', '/export')): + model_operation(_name, 'POST', '/api/workspace/runs/{run_id}/retained-analysis' + _suffix, + _retained_request['properties'], _retained_request['required'], output=_retained_result, + description='Read one exact retained classifier curve and bounded example page; current inspect access required.') model_operation('runs.compare_model_evidence','POST','/api/workspace/runs/{run_id}/compare-model-evidence', {'run_id':ID,'other_run_id':ID},output=obj({ 'state':{'enum':['compatible','incompatible']},'run_ids':array(ID,2,2), diff --git a/app.py b/app.py index df2ca426..267a8f98 100644 --- a/app.py +++ b/app.py @@ -958,6 +958,12 @@ def _get(self): '/workspace-external.js': ('workspace-external.js', 'text/javascript'), '/workspace-phase-timings.js': ('workspace-phase-timings.js', 'text/javascript'), '/workspace-service.js': ('workspace-service.js', 'text/javascript'), + '/static/retained-analysis.js': ('retained-analysis.js', 'text/javascript'), + '/static/retained-checkpoint-curve.vl.json': ('retained-checkpoint-curve.vl.json', 'application/json'), + '/static/vendor/retained-analysis/vega.min.js': ('vendor/retained-analysis/vega.min.js', 'text/javascript'), + '/static/vendor/retained-analysis/vega-lite.min.js': ('vendor/retained-analysis/vega-lite.min.js', 'text/javascript'), + '/static/vendor/retained-analysis/vega-embed.min.js': ('vendor/retained-analysis/vega-embed.min.js', 'text/javascript'), + '/static/vendor/retained-analysis/vega-interpreter.min.js': ('vendor/retained-analysis/vega-interpreter.min.js', 'text/javascript'), '/workspace-scientific-comparison.js': ('workspace-scientific-comparison.js', 'text/javascript'), '/workspace-fixtures.json': ('workspace-fixtures.json', 'application/json'), '/pipeline-editor.js': ('pipeline-editor.js', 'text/javascript'), @@ -1173,6 +1179,14 @@ def graph_guard(graph): self._graph_snapshot_contract_access(body['graph_id'],body['graph_revision'], 'runs.submit_external',2,graph=graph) return self.reply(dataset.runs.submit_external(body,_graph_guard=graph_guard), 201) + if (len(parts) == 3 or len(parts) == 4 and parts[3] == 'export') and parts[0] == 'runs' and parts[2] == 'retained-analysis': + import retained_analysis + operation = 'runs.export_retained_analysis' if len(parts) == 4 else 'runs.retained_analysis' + agent_api.require_selection(self._contract_selection, operation) + # The selected-contract decoder rejects all duplicate + # body Run IDs before this path-owned identity is added. + return self.reply(retained_analysis.query(dataset.runs, dict(body, run_id=parts[1]), + export=len(parts) == 4)) if len(parts) == 3 and parts[0] == 'runs': if parts[2] == 'model-evidence': agent_api.require_selection(self._contract_selection,'runs.model_evidence') diff --git a/docs/contracts/retained-analysis-query.md b/docs/contracts/retained-analysis-query.md index 85a57053..c24024e5 100644 --- a/docs/contracts/retained-analysis-query.md +++ b/docs/contracts/retained-analysis-query.md @@ -1,8 +1,13 @@ # Retained checkpoint examples query v1 -Status: additive implementation under review, **not registered in HTTP/agent/UI**. -Production consumers must wait for coordinated integration and actual-store -qualification. Python entry point: `retained_analysis.query(runs, body)`. +Status: implemented and qualified in the verified native classifier Runs view. +Python entry point: `retained_analysis.query(runs, body)`. HTTP consumers select +`runs.retained_analysis/1` or `runs.export_retained_analysis/1` explicitly with +its published capability hash. POST routes are +`/api/workspace/runs//retained-analysis` and its `/export` sibling. +HTTP bodies omit run_id: the selected decoder rejects duplicate body IDs and +the handler injects the validated URL ID. The Python example below includes it +because the direct query entry point receives the full exact request. ```json { @@ -72,10 +77,19 @@ Failures use WorkbenchError: invalid request 400; unsupported query/task 409; stale evaluation/metric 409; foreign checkpoint/not-found Run 404; limit 413; unavailable standalone/read state 503 where applicable. Existing Access and storage errors propagate with their established boundaries. A failed or revoked -request must clear the future renderer, cancel obsolete requests, and exclude +request clears the renderer, cancel obsolete requests, and exclude late replies. Already returned bytes cannot be recalled. -The future renderer consumes an immutable base spec/result and revisioned -allowlisted display overrides separately. Changed analysis creates a new result; +The renderer consumes an immutable base spec/result and transient allowlisted +selections. Persisted revisioned display overrides remain a later milestone. +Changed analysis creates a new result; series/color/range/display filters cannot silently redefine metric meaning. No renderer or spec is accepted merely because it is JSON. + + +Qualification: 27 query/contract/actual PostgreSQL/authenticated HTTP tests pass +without skips; the actual Runs browser uses the normal app, retained native Run, +real session revocations and a fresh application process. See +[acceptance evidence](../plans/retained-analysis/reports/m4-integrated/acceptance.md). +The two-epoch six-image fixture proves custody, transport and numeric behavior; +it makes no model-quality or production-scale claim. diff --git a/docs/contracts/retained-analysis-renderer.md b/docs/contracts/retained-analysis-renderer.md index f049c2d7..9868ebcc 100644 --- a/docs/contracts/retained-analysis-renderer.md +++ b/docs/contracts/retained-analysis-renderer.md @@ -1,7 +1,7 @@ # Retained checkpoint renderer adapter -Status: isolated implementation under review. Not mounted in production Runs. -The existing Runs/API/contract registry hooks await repository-lead coordination. +Status: mounted in existing Runs for verified completed native classifier +results, with lead-approved additive HTTP/contract and lifecycle hooks. `WorkspaceRetainedAnalysis.mount(root, {load, onSelection})` returns: @@ -57,8 +57,13 @@ Self-hosted unmodified upstream browser distributions: The v5 family matches the v5 schema emitted by Altair 5.5 and supplies UMD distributions without a new application bundler. Load in the table order before retained-analysis.js. The interpreter extends window.vega. Embed passes ast true -and expressionInterpreter; strict CSP does not need unsafe-eval or unsafe-inline. -Do not weaken app CSP. `static/vendor/retained-analysis/manifest.json` records +and expressionInterpreter. The renderer runs with script-src self, without +unsafe-eval or inline scripts. Its isolated fixture also uses style-src self. +The deployed /workspaces policy retains unsafe-inline for existing application +CSS; this grants no inline script/eval permission. The meta policy precedes all +assets and restricts data connections to the same origin, objects/base to none, +images/media to existing local/data/blob needs, and frames/forms to self. +No pre-existing CSP was relaxed. `static/vendor/retained-analysis/manifest.json` records exact asset/tarball hashes, upstream URLs, and retained notices for packages in the upstream source maps. Notice-source resolution versions do not claim exact embedded transitive versions. BSD, MIT and ISC notices are retained with the @@ -75,39 +80,50 @@ cache-bypassed page reload and disposal. No external chart-asset request or CSP violation is permitted. Headless/no-sandbox/software rendering is test-only and does not establish an application execution sandbox. -This test uses authored responses and access-failure substitutes. It establishes -renderer behavior only. It does not establish actual Runs custody, PostgreSQL -execution, real credential revocation, full application accessibility, or -cold-process retained result reproducibility. The follow-up actual PostgreSQL/ -retained native Run tests now qualify the direct query boundary, including real -Access revocation and fresh-process reopening. They are distinct from these -authored renderer tests. The full authenticated API-to-Runs browser gate remains -pending shared-hook integration. - -## Pending API dependency and shared hook proposal - -No shared-file changes are part of this branch. Proposed additive contracts for -lead agreement before implementation: - -1. Register new inspect operations `runs.retained_analysis/1` and - `runs.export_retained_analysis/1`, each with explicit closed request/response - schema hashes. Keep existing operations/versions unchanged. -2. Add POST `/api/workspace/runs//retained-analysis` and an explicit - `/retained-analysis/export` sibling. Require the chosen new contract. Existing - selected-contract rules place run_id in the path only: reject any duplicate - body run_id, then inject the path ID when delegating to - `retained_analysis.query(dataset.runs, body_with_route_id, - export=host_route_choice)`. No user-controlled export flag. -3. In the existing verified native classifier Runs section, build the request - from its exact artifact/metric/checkpoint inventory. Mount a separate root; - load through authenticated transport. Dispose on navigation, credential or - Run replacement; never change coordinator/phase/publication/scientific - comparison controllers. Include adapter cleanup in existing authority-failure - paths and exclude obsolete replies before any DOM update. -4. Load self-hosted assets with the agreed current CSP; add actual authenticated - application/DB/browser tests and CI only after coordinated write-set approval. - The lead owns serial integration and merge; no approval or schema migration - is inferred from this proposal. +The authored renderer test establishes malformed/oversized spec and response +rejection, precise widget lifecycle and strict-CSP compatibility. It does not +substitute for custody or access acceptance. + +`node tests/browser_retained_analysis_actual.cjs` separately opens the normal +application with the existing PostgreSQL catalog and a normally trained, +retained two-epoch native classifier fixture. It checks the actual named query, +exact retained numbers, keyboard-linked table, 390px layout, actual response +cancellation, authorized JSON download, real credential revocation, and a fresh +application-process/cache-bypassed reopen. It also revokes access immediately +before normal Run detail, prediction and model-evidence requests, proving that +denials clear previously rendered private content even after identity becomes +null. Deployed CSP violations are captured; ordinary runtime code generation +is explicitly checked with the DevTools CSP bypass disabled. No remote chart +asset is requested. These are bounded workflow checks, not full-application +accessibility or performance certification. + +## Integrated host contract + +Two new inspect/read operations, `runs.retained_analysis/1` and +`runs.export_retained_analysis/1`, have closed typed request/response schemas and +exact browser pins. Every prior contract/discovery document remains unchanged. +POST `/api/workspace/runs//retained-analysis` and its `/export` sibling +require an explicitly selected contract. Bodies omit run_id and reject any +duplicate; the handler supplies the validated URL ID. The export flag is owned +by the route. + +The existing verified native classifier section constructs requests from its +exact artifact/metric/checkpoint inventory. The widget owns a separate root and +uses authenticated bounded transport with timeout/caller-abort wiring. Mount, +Run replacement, navigation, session change and access failure dispose its +view. Old responses cannot update a new selection or authority. Failed access +also clears the containing private Run. The model transport captures Run, +credential and generation before dispatch and forwards access denials before +local catches, including old checkpoint/candidate/package/comparison reads. +Aborted or invalidated-generation replies cannot trigger cleanup. Existing coordinator/phase/publication/ +scientific controllers retain their ownership; no new computation starts on +view opening. The Dataset selector starts disabled until existing initialization +attaches its handlers, including during local vendor-asset loading. + +The branch composes reliability baseline 83a1e128 and adds CI commands using one +actual retained fixture outside uploaded QA artifacts; private login material +stays outside evidence. The repository lead alone merges this dependent PR. +See [acceptance](../plans/retained-analysis/reports/m4-integrated/acceptance.md). Official references checked 2026-10-19/20: [Altair serialization](https://altair-viz.github.io/user_guide/saving_charts.html), diff --git a/docs/plans/retained-analysis/execution-ledger.md b/docs/plans/retained-analysis/execution-ledger.md index 1ac22356..823f28cd 100644 --- a/docs/plans/retained-analysis/execution-ledger.md +++ b/docs/plans/retained-analysis/execution-ledger.md @@ -36,3 +36,45 @@ The earlier 12-pass/one-skip log remains retained as historical evidence. No shared handler has been edited; authenticated API/Run UI acceptance still awaits lead ownership agreement. After a reported disconnect, shell/service state was verified available; existing workers/fixtures were reused, not duplicated. + + +2026-10-20 M4: Parent relayed the lead's explicit shared-hunk approval; composed +83a1e128 in merge252a68c without conflicts. Registered two closed inspect/read +contracts, exact asset paths and selected authenticated POST routes; mounted the +pinned adapter in verified native classifier Runs with bounded transport and +disposal. Added scoped script CSP, preserving existing inline CSS. Independent +review found swallowed ordinary Run access denials and null-identity cleanup; +fixed propagation and generation/session-aware clearing. Actual Chromium now +revokes at export plus detail/predictions/model-evidence boundaries and verifies +private Run removal. It checks exact numeric/linked/narrow/cancellation behavior +and reopening in a fresh application process. Query/actual/contract/HTTP suite +passes27/27, 11 controller suites pass, isolated renderer Chromium passes. +Initial HTTP expectation (400 versus contract mismatch) and already-cancelled +CDP interception handling were corrected; initial failure logs are retained. +The Dataset selector now begins disabled until existing listeners are ready. +CI reuses one normal actual fixture and keeps its private catalog/login material +outside uploaded build/qa. No production migration, role, credential, schema or +compute-on-open path was added. Integration acceptance and independent review +are retained under reports/m4-integrated. Lead alone owns merge. + + +Final review follow-up: a central captured-Run/credential/generation transport +wrapper forwards WorkspaceModel401/403 before any local presentation catch, +including old checkpoint/candidate/package/comparison paths. It excludes aborted +retained requests and invalidated generations. Nested saved-candidate/package +loads rethrow denials. The actual browser holds an old checkpoint read until its +rerendered retained query succeeds, then revokes/releases it and verifies all +private Run content clears. Controlled tests cover null identity versus changed +navigation/session. All11 controller suites pass after the change. Existing +actual coordinator and scientific Runs browsers pass under the scoped CSP; +36 relevant Python regression tests pass. + + +Final independent GPT-6.1 Sol High review approved with no remaining blocking +findings. It reran contracts3, actual HTTP5, model controller and actual Runs +Chromium, verified all124 old contract/discovery identities, and retained a final +18-file source SHA256 manifest. All hashes match publication sources. Main and +reliability dependency were refetched and remain8c9c0b0/83a1e128. Active PR102–110 +write sets were rechecked; only the explicitly approved shared hunks changed. +Implementation acceptance is complete for this bounded slice; merge belongs to +the repository lead. No production gate was crossed. diff --git a/docs/plans/retained-analysis/issues.md b/docs/plans/retained-analysis/issues.md index 63bd10aa..93fa7f29 100644 --- a/docs/plans/retained-analysis/issues.md +++ b/docs/plans/retained-analysis/issues.md @@ -2,6 +2,9 @@ | ID | Finding | Owner | State / disposition | | --- | --- | --- | --- | -| V1 | Shared API/Run/UI hooks overlap PR102–110 | parent/repository lead | pending coordination; continue additive M1 | +| V1 | Shared API/Run/UI hooks overlap PR102–110 | parent/repository lead | resolved: parent relayed explicit lead-approved hunks; reliability83a1e128 composed without conflicts | | V2 | Initial PostgreSQL/runtime absence | environment/parent | resolved for local tests after parent clarified disposable setup scope; PG17.11 and pinned CPU runtime provisioned under /tmp; actual direct-query tests pass | | V3 | General results and saved view revisions are later milestones | visualization owner | preserve immutable result boundary; no early persistence engine | +| V4 | Normal Run loader swallowed access denials and skipped cleanup after identity became null | Runs/visualization | resolved: propagate401/403; generation/session-aware cleanup; actual browser revokes at detail/predictions/model-evidence boundaries | +| V5 | Isolated strict CSP did not establish deployed policy | renderer/host | resolved: scoped /workspaces policy before assets; actual browser asserts no runtime code generation or unexpected violations; existing inline CSS remains allowed | +| V6 | Dataset selector accepted input before initialization during pinned asset loading | workspace host | resolved: initial markup disabled; existing initializer enables after setup | diff --git a/docs/plans/retained-analysis/plan.md b/docs/plans/retained-analysis/plan.md index c597bb24..d06daa59 100644 --- a/docs/plans/retained-analysis/plan.md +++ b/docs/plans/retained-analysis/plan.md @@ -1,12 +1,12 @@ # Plan: Retained checkpoint curve and linked examples -**Plan status:** `Verifying` +**Plan status:** `Accepted` -**Current phase:** M2 isolated renderer qualified; shared integration pending +**Current phase:** M4 complete; independently reviewed; lead-owned integration -**Next slice:** Coordinate additive HTTP/contracts and Runs mount hooks with the repository lead via the parent. +**Next slice:** Lead review and serial integration of the completed dependent PR. -**Acceptance status:** `pending` +**Acceptance status:** `accepted for this bounded slice` **Execution ledger:** [execution-ledger.md](execution-ledger.md) @@ -24,8 +24,8 @@ access, numeric, lifecycle and provenance guarantees. View opening is inert. | --- | --- | --- | --- | --- | --- | --- | | A1 | Closed named query rejects malformed identities, unknown fields and unbounded requests before reads; exact substitutions fail before result return | contract | not-applicable | automated | passed | [focused tests](reports/m1/focused-tests.log) | | A2 | Exact metric values, stable examples, pagination/support and frozen identity agree with retained bytes and actual PostgreSQL | integration | required-real | automated | passed | [actual retained query tests](reports/m3-actual/retained-query-tests.log) | -| A3 | Actual Runs browser supports keyboard, linked selections, narrow layout, stale replies, revocation, malformed/large specs, offline assets and cold reopen | user-workflow | required-real | automated | partial | [isolated actual Chromium renderer](reports/m2/browser.json); shared Runs hooks pending | -| A4 | Query/export reauthorize every retrieval, no cache authority, no computation or mutation on opening | integration | required-real | automated | partial | [real direct-query/credential tests](reports/m3-actual/retained-query-tests.log); authenticated HTTP/UI still pending | +| A3 | Actual Runs browser supports keyboard, linked selections, narrow layout, stale replies, revocation, malformed/large specs, offline assets and cold reopen | user-workflow | required-real | automated | passed | [actual Runs browser](reports/m4-integrated/browser.json), [strict isolated renderer](reports/m4-integrated/renderer.json); complementary scopes documented | +| A4 | Query/export reauthorize every retrieval, no cache authority, no computation or mutation on opening | integration | required-real | automated | passed | [query/HTTP tests](reports/m4-integrated/query-http-tests.log), [real Run revocation/export/cold reopen](reports/m4-integrated/browser.json) | ## Scope @@ -51,7 +51,7 @@ view persistence. Revisioned overrides follow the completed immutable slice. | `retained_checkpoint_examples` v1 selects explicit run, evaluation, metric definition and checkpoint hashes | retained_analysis | [contract](../../contracts/retained-analysis-query.md) | none | | Existing text Run document remains authoritative; JSONB casts are disposable query projections | Metadata/Runs | schema v10; raw artifact hashes retained | none | | Vega-Lite/vega-embed with interpreter and self-hosted pinned assets | renderer | official upstream docs; later asset/browser qualification required | none | -| Lead alone merges; shared-file hooks wait for parent coordination | repository lead | delegation; PR102–110 write-set snapshot | none | +| Lead alone merges; shared hooks approved after composing reliability83a1e128 | repository lead | parent relay 2026-10-20; explicit approved hunks | initial pending coordination | ## Design Observations And Remaining Evidence @@ -124,13 +124,28 @@ Shared integration candidates `app.py`, Define mount/resize/update/selection/export/dispose; deny external loaders/editor, use interpreter under strict CSP. Gate A3 plus actual A2/A4. +### M4: Authenticated integration, approved through parent + +Composed dependency: `83a1e1289f3f7e4f8c3e697c1748a862a69d0897`, reliability +PR108 branch (including its composed PR102–110 history). Local composition merge +`252a68c5b90afdd8660f652cfa0094233ef9f64f`; no conflict resolution or reliability +rewrites. The PR must declare this dependency until the lead integrates it. + +Allowed shared hunks: `agent_api.py` two new inspect contracts; `app.py` POST +handlers and exact static asset mappings; `static/workspace-real.js` bounded +authenticated transport; `static/workspace-service.js` verified native classifier +mount/disposal; `static/workspaces.html` (scoped CSP before assets; initially disabled selector), scoped CSS and additive CI commands. +Normal Run read catches propagate access denials to generation/session-aware +private-content cleanup; no non-auth reliability fallback changes. +New `retained_analysis_schema.py` owns the narrow schema. Preserve all existing +coordinator/phase/publication/batch/scientific-comparison behavior and old +operation identities. HTTP bodies omit run_id; validated path ID is injected. +Execute actual SQL, authenticated HTTP, Runs browser, real revocation/export and +cold-reopen acceptance, then independent review before publication readiness. + ## Blockers -- Parent relay/lead coordination is pending. Cross-thread collaboration send to - source_thread_id returns `agent ... not found`; no shared-file edits authorized - by coordination yet. No GitHub comment to another person is substituted. -- Authenticated API-to-Runs acceptance awaits shared hooks. The disposable - PostgreSQL/native retained Run and direct-query acceptance are now available. +- `none` for implementation or local acceptance. Lead-owned integration remains; no new user permission is needed. ## Re-Plan Triggers @@ -146,6 +161,8 @@ retain source/evidence and branch for its review. No worktree deletion planned. ## Final Acceptance -- Acceptance status: `pending` -- Deferred follow-ups: M2 integration and actual-store/browser qualification -- Final status: `Verifying` +- Acceptance status: `accepted for this bounded slice` +- Evidence: [M4 acceptance](reports/m4-integrated/acceptance.md) +- Deferred follow-ups: general query recipes, persisted revisioned view overrides, + benchmark manifests and later scientific workflows; outside this first slice +- Final status: `Accepted` for the implemented slice; lead alone owns merge diff --git a/docs/plans/retained-analysis/reports/m4-integrated/acceptance.md b/docs/plans/retained-analysis/reports/m4-integrated/acceptance.md new file mode 100644 index 00000000..3ca494b7 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/acceptance.md @@ -0,0 +1,52 @@ +# Authenticated retained analysis acceptance + +The first vertical slice is implemented in existing Runs: a retained native +classifier curve linked to stable per-example/error pages, through two explicitly +selected, closed inspect/read operations. Opening it starts no new computation. +Implementation composes reliability83a1e128 (merge252a68c), with shared hunks +approved by the repository lead through the parent. Lead alone owns merge. + +| Evidence | Result | Scope | +| --- | --- | --- | +| [Query/contract/HTTP suite](query-http-tests.log) | 27 passed, no skips | Original13 query tests, 6 actual retained PostgreSQL tests, 3 contracts, 5 normal authenticated HTTP tests | +| [Actual Runs Chromium](browser.json) | passed | Normal app/PG/retained native Run, exact numbers, keyboard-linked table,390px, real response cancellation, fresh export, actual revocations and fresh app process reopen | +| [Authored renderer Chromium](renderer.json) | passed | Local assets/interpreter under stricter CSP, pointer/keyboard/focus, spec/response bounds and tampering, stale failure replies, disposal and downloaded JSON | +| [Controller regressions](controllers.log) | 11 suites passed | Existing model, coordinator, external/import/package, phase, scientific, lineage/publication, field and candidate behavior; controlled transports | +| [Python regressions](regressions.log) | 36 passed | Owner phase14, agent API17, access HTTP4, phase contract pins1 | +| [Existing Runs browsers](existing-runs-browsers.log) | passed | Actual coordinator recovery/lost reply and scientific-comparison workflows, including their own revocation checks | +| [Independent review](independent/review.md) | approved; no blocking findings | Separate GPT-6.1 Sol High source review and actual HTTP/Chromium rerun | + +The actual browser revokes a real session before export and before ordinary Run +detail, prediction and model-evidence reads. It also holds an existing checkpoint +action, allows the rerendered retained query to succeed, then revokes/releases the +checkpoint read; both private metric grid and retained graph disappear. A shared +WorkspaceModel transport wrapper forwards current-generation denials before local +presentation catches, preserving credential/navigation/signal fences. + +The /workspaces meta CSP precedes every asset. Script execution is self-only; +inline scripts and runtime code generation remain blocked. Existing application +inline CSS remains allowed. Browser acceptance collects unexpected violations +and verifies blocked Function construction with the DevTools CSP bypass disabled. +The isolated renderer additionally proves compatibility with self-only styles. + +The source checkpoint records SHA256 for the implementation/test/assets and +explicit dependency. [Earlier environment receipt](../m3-actual/environment.json) +records task-owned PostgreSQL17.11, non-superuser app role, pinned CPU runtime and +the single normal six-image/two-epoch fixture. Its then-pending integration note +is historical and superseded here. This authored material makes no model-quality +claim. No production credential/configuration/role/schema migration is involved. +Private owner/session bytes stay in task-owned /tmp files or non-uploaded CI +fixture storage. Reports contain public IDs/hashes only. + +Initial failure logs are retained: HTTP malformed request expectation corrected +to existing400 invalid semantics; CDP continue after actual request cancellation +accepts only the specific invalid-interception outcome and separately requires +observed cancellation. The Dataset selector starts disabled until its existing +initializer installs listeners, avoiding input loss during local asset loading. + +Limits: native epoch classifier/validation-probe evidence only; one exact frozen +result,100 rows per page,128 checkpoints,10000 fixed examples. This is not a new +statistics warehouse, arbitrary SQL/spec engine, notebook service or persisted +view revision store. General recipes, saved view overrides, benchmarks and later +scientific analyses remain separate milestones. Full-repository CI still runs +on GitHub; local evidence qualifies the listed boundaries. No merge performed. diff --git a/docs/plans/retained-analysis/reports/m4-integrated/active-pr-write-sets.json b/docs/plans/retained-analysis/reports/m4-integrated/active-pr-write-sets.json new file mode 100644 index 00000000..d8d1e46e --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/active-pr-write-sets.json @@ -0,0 +1,469 @@ +[ + { + "number": 110, + "head": "feature/lab-batch-client-20261019", + "base": "feature/lab-bounded-collection-20261019", + "files": [ + "docs/contracts/project-cli.md", + "docs/contracts/workflow-client.md", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-01/actual-http-cli.log", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-01/cleanup-independent.json", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-01/cleanup-publication.json", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-01/cleanup-twenty.json", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-01/source.json", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/actual-affected.log", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/cleanup-independent.json", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/cleanup-publication.json", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/cleanup-twenty.json", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/preparation.json", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/source-before-comment.json", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/actual-attempt-02/source.json", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/consumer-independent-final-review.json", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/pure-composed.log", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/pure-initial.log", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/qualification.md", + "docs/plans/lab-workflow-reliability/reports/m4-batch-client/validation.json", + "project_cli.py", + "tests/test_workflow_batch_client.py", + "tests/test_workflow_batch_client_http.py", + "tuldok_client.py" + ] + }, + { + "number": 109, + "head": "feature/lab-bounded-collection-20261019", + "base": "feature/lab-field-comparison-20261019", + "files": [ + "agent_api.py", + "app.py", + "docs/contracts/run-artifact-segments.md", + "docs/plans/lab-workflow-reliability/execution-ledger.md", + "docs/plans/lab-workflow-reliability/plan.md", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/actual-initial.log", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/before.log", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02.log", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02/environment-start.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02/raw/artifacts-1-setup-integrity.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02/raw/publication-artifacts-1-history-2-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02/raw/run-artifacts-1-history-1-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02/raw/unavailable-artifacts-1-history-0-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pilot-02/summary.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/composed-pure-final.log", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/initial-validation.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/legacy-regressions.log", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/analyze_pairs.py", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/environment-start.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/parent-cleanup-independent.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/qualified-pairs.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/artifacts-1-setup-integrity.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/artifacts-20-setup-integrity.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/publication-artifacts-1-history-56-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/publication-artifacts-1-history-56-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/publication-artifacts-1-history-56-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/publication-artifacts-20-history-56-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/publication-artifacts-20-history-56-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/publication-artifacts-20-history-56-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-1-history-55-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-1-history-55-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-1-history-55-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-1-history-8-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-1-history-8-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-1-history-8-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-20-history-55-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-20-history-55-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-20-history-55-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-20-history-8-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-20-history-8-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/run-artifacts-20-history-8-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/unavailable-artifacts-1-history-0-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/unavailable-artifacts-1-history-0-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/unavailable-artifacts-1-history-0-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/unavailable-artifacts-20-history-0-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/unavailable-artifacts-20-history-0-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/raw/unavailable-artifacts-20-history-0-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/results.md", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/stdout.log", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/summary.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-9838022/validation.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/analyze_pairs.py", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/environment-start.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/producer-independent-review.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/qualified-pairs.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/artifacts-1-setup-integrity.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/artifacts-20-setup-integrity.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/publication-artifacts-1-history-56-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/publication-artifacts-1-history-56-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/publication-artifacts-1-history-56-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/publication-artifacts-20-history-56-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/publication-artifacts-20-history-56-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/publication-artifacts-20-history-56-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-1-history-55-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-1-history-55-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-1-history-55-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-1-history-8-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-1-history-8-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-1-history-8-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-20-history-55-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-20-history-55-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-20-history-55-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-20-history-8-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-20-history-8-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/run-artifacts-20-history-8-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/unavailable-artifacts-1-history-0-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/unavailable-artifacts-1-history-0-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/unavailable-artifacts-1-history-0-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/unavailable-artifacts-20-history-0-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/unavailable-artifacts-20-history-0-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/raw/unavailable-artifacts-20-history-0-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/refinement-independent-review.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/results.md", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/stdout.log", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/summary.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-99741e5/validation.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-harness-tests.log", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01.log", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01/environment-start.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01/raw/artifacts-2-setup-integrity.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01/raw/publication-artifacts-2-history-2-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01/raw/run-artifacts-2-history-1-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01/raw/unavailable-artifacts-2-history-0-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/paired-pilot-01/summary.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/pure-initial.log", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/refinement/actual-attempt01-source.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/refinement/actual-attempt01.log", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/refinement/before.log", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/refinement/independent-review.json", + "docs/plans/lab-workflow-reliability/reports/m4-bounded-collection/refinement/parent-997-cleanup-independent.json" + ] + }, + { + "number": 108, + "head": "feature/lab-indexed-diagnostics-20261019", + "base": "feature/lab-batch-client-20261019", + "files": [ + "docs/contracts/indexed-diagnostics.md", + "docs/contracts/run-preflight-publication.md", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/indexed-final-9d563ceb-independent-review.json", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/qualification.md", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/tuldok-indexed-composed-actual.log", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/tuldok-indexed-composed-qualification.json", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/tuldok-indexed-composed-readers-70dcaeb-independent-review.json", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/tuldok-indexed-composed-source.json", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/tuldok-refined-indexed-cleanup-independent.json", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/composed-readers/validation.json", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/owner-roundtrip-final.log", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/owner-roundtrip-first.log", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/owner-roundtrip-receipt.json", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/owner-roundtrip-second.log", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/pure-tests-final.log", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/pure-tests.log", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/report.md", + "docs/plans/lab-workflow-reliability/reports/m1-indexed-diagnostics/source-sha256.txt", + "extension_evidence.py", + "recipe_contract.py", + "tests/test_indexed_diagnostics.py", + "tests/test_indexed_diagnostics_publication.py", + "tuldok_extension_sdk/diagnostics.py", + "tuldok_extension_sdk/evidence.py" + ] + }, + { + "number": 107, + "head": "test/lab-workflow-baseline-20261019", + "base": "feature/lab-phase-timing-20261019", + "files": [ + "docs/contracts/lab-workflow-baseline.md", + "docs/plans/lab-workflow-reliability/execution-ledger.md", + "docs/plans/lab-workflow-reliability/plan.md", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/analysis-verification.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/analysis.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/README.md", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-exploratory-preflight.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-01.log", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-01/environment-start.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-01/failure.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-02.log", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-02/environment-start.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-02/raw/artifacts-1-history-0-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-02/raw/artifacts-1-history-2-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-02/raw/artifacts-1-real-history-population.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-02/summary.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03.log", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03/environment-start.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03/failure.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03/raw/artifacts-1-history-0-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03/raw/artifacts-1-history-2-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03/raw/artifacts-1-real-history-population.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-03/raw/artifacts-2-history-0-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04.log", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04/environment-start.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04/raw/artifacts-2-fresh-workflow-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04/raw/artifacts-2-history-0-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04/raw/artifacts-2-history-2-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04/raw/artifacts-2-real-history-population.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pilot-04/summary.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pure-final.log", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/exploratory/tuldok-m4-harness-pure.log", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f.log", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/environment-start.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-fresh-workflow-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-fresh-workflow-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-fresh-workflow-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-0-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-0-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-0-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-55-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-55-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-55-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-8-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-8-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-history-8-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-1-real-history-population.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-fresh-workflow-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-fresh-workflow-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-fresh-workflow-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-0-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-0-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-0-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-55-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-55-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-55-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-8-process-0.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-8-process-1.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-history-8-process-2.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/raw/artifacts-20-real-history-population.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/frozen-83d7e8f/summary.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/qualified-distributions.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/reporting-tests-final.log", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/results.md", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/root-cleanup-independent.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/tooling.json", + "docs/plans/lab-workflow-reliability/reports/m4-workflow-baseline/validation.json", + "tests/benchmark_lab_workflow.py", + "tests/test_benchmark_lab_workflow.py" + ] + }, + { + "number": 106, + "head": "feature/lab-field-comparison-20261019", + "base": "feature/lab-workflow-client-20261019", + "files": [ + ".github/workflows/tests.yml", + "agent_api.py", + "app.py", + "docs/contracts/model-development.md", + "docs/contracts/run-preflight-publication.md", + "docs/contracts/scientific-comparison.md", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/agent-api-green.log", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/browser-first-red.log", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/browser-green.log", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/browser-receipt.json", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/controller-green.log", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/coordinator-green.log", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/domain-receipt.json", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/external-controller-green.log", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/field-controller-green.log", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/pure-green.log", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/reader-first-red.log", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/reader-green.log", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/retained-green.log", + "docs/plans/lab-workflow-reliability/reports/m6/evidence/schema-cleanup.json", + "docs/plans/lab-workflow-reliability/reports/m6/integration-source.md", + "docs/plans/lab-workflow-reliability/reports/m6/qualification.md", + "docs/plans/lab-workflow-reliability/reports/m6/recovery-browser-fixture/tuldok-pr106-browser-composition-green.log", + "docs/plans/lab-workflow-reliability/reports/m6/recovery-browser-fixture/tuldok-pr106-browser-composition-red.log", + "docs/plans/lab-workflow-reliability/reports/m6/recovery-browser-fixture/validation.json", + "docs/plans/lab-workflow-reliability/reports/m6/source-review.md", + "docs/plans/lab-workflow-reliability/reports/m6/validation.json", + "extension_evidence.py", + "run_publication.py", + "runs.py", + "static/workspace-real.js", + "static/workspace-scientific-comparison.js", + "static/workspaces.css", + "static/workspaces.html", + "tests/browser_scientific_comparison.cjs", + "tests/browser_workspace_recovery.cjs", + "tests/scientific_comparison_fixture.py", + "tests/test_scientific_comparison.py", + "tests/test_scientific_comparison_client.py", + "tests/test_scientific_comparison_controller.cjs", + "tests/test_workspace_external_controller.cjs" + ] + }, + { + "number": 105, + "head": "feature/lab-workflow-client-20261019", + "base": "feature/lab-phase-panel-20261019", + "files": [ + "README.md", + "agent_api.py", + "docs/contracts/agent-operations.md", + "docs/contracts/project-cli.md", + "docs/contracts/workflow-client.md", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/batch-consumer-independent-review.json", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/comparison-guard-focused.log", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/comparison-guard-http-source.json", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/comparison-guard-http.log", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/comparison-guard-red.log", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/comparison-guard-source.json", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/focused-comparison.log", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/focused-followup.log", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/focused-inventory-fix.log", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/focused-review-fixes.log", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/focused.log", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/http-attempt-01-source.json", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/http-attempt-01.log", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/http-attempt-02-source.json", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/http-attempt-02.log", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/http-review-fixes-source.json", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/http-review-fixes.log", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/legacy-client-cli-contracts-source.json", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/legacy-client-cli-contracts.log", + "docs/plans/lab-workflow-reliability/reports/m5-workflow-client/qualification.md", + "project_cli.py", + "tests/test_workflow_client.py", + "tests/test_workflow_client_http.py", + "tuldok_client.py" + ] + }, + { + "number": 104, + "head": "feature/lab-phase-panel-20261019", + "base": "test/lab-workflow-baseline-20261019", + "files": [ + ".github/workflows/tests.yml", + "app.py", + "docs/contracts/run-phase-timings.md", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/coordinator-regression/coordinator-1440.jpg", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/coordinator-regression/coordinator-390.jpg", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/coordinator-regression/domain-receipt.json", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/coordinator-regression/receipt.json", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/external-controller-fixture/tuldok-pr104-external-composition-final-source.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/external-controller-fixture/tuldok-pr104-external-composition-green.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/external-controller-fixture/tuldok-pr104-external-composition-red.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/external-controller-fixture/validation.json", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/final-phase-browser/domain-receipt.json", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/final-phase-browser/phases-1440.jpg", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/final-phase-browser/phases-390.jpg", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/final-phase-browser/receipt.json", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/publication-regression/domain-receipt.json", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/publication-regression/publication-1440.jpg", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/publication-regression/publication-390.jpg", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/publication-regression/receipt.json", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/recovery-browser-fixture/tuldok-pr104-browser-composition-green.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/recovery-browser-fixture/tuldok-pr104-browser-composition-red.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/recovery-browser-fixture/validation.json", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-same-selection-stale-fixed-repro.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-same-selection-stale-repro.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-browser-final-predicate-source.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-browser-final-source.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-browser-first.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-browser-reviewed-window-source.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-browser-second.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-controller-same-selection-sequential.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-coordinator-ready-regression.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-coordinator-regression-final-source.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-native-ancestor-regression.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-pins-final-source.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/tuldok-m3-ui-publication-regression-final-source.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-ui/validation.json", + "static/workspace-external.js", + "static/workspace-phase-timings.js", + "static/workspace-real.js", + "static/workspaces.css", + "static/workspaces.html", + "tests/browser_run_phase_timings.cjs", + "tests/browser_workspace_coordinator.cjs", + "tests/browser_workspace_recovery.cjs", + "tests/phase_timing_browser_fixture.py", + "tests/test_run_phase_controller.cjs", + "tests/test_workspace_external_controller.cjs", + "tests/test_workspace_phase_timings.py" + ] + }, + { + "number": 103, + "head": "feature/lab-phase-timing-20261019", + "base": "feature/lab-coordinator-panel-20261019", + "files": [ + ".github/workflows/tests.yml", + "agent_api.py", + "app.py", + "docs/contracts/run-phase-timings.md", + "docs/plans/lab-workflow-reliability/execution-ledger.md", + "docs/plans/lab-workflow-reliability/plan.md", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/integration-validation.json", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/selected-contracts.json", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/source-manifest.json", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-affected-qualified.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-core-composed-final.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-correlated-final-module.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-exact-source-qualified.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-expanded-actual.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-final-closed-evidence-qualified.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-final-qualified.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-final-reader-qualified.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-first-actual-and-m2-followup.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-first-compatibility.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-owner-final-shapes.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-owner-first.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-root-independent-qualification.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/tuldok-m3-second-compatibility.log", + "docs/plans/lab-workflow-reliability/reports/m3-phase-timing-core/validation.json", + "phase_timings.py", + "pipeline.py", + "project_cli.py", + "recipe_process.py", + "run_publication.py", + "runs.py", + "tests/fixtures/agent_contract_hashes_phase5a1feac.json", + "tests/test_run_phase_timings.py" + ] + }, + { + "number": 102, + "head": "feature/lab-coordinator-panel-20261019", + "base": "main", + "files": [ + ".github/workflows/tests.yml", + "docs/contracts/run-coordinator-recovery.md", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/README.md", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/ci-controller-fixture/tuldok-pr102-controller-composition-green.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/ci-controller-fixture/tuldok-pr102-controller-composition-red.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/ci-controller-fixture/tuldok-pr102-controller-fixture-independent-review.json", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/ci-controller-fixture/tuldok-pr102-controller-independent-green.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/ci-controller-fixture/tuldok-pr102-independent-lifecycle-job-118328520352.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/ci-controller-fixture/validation.json", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/coordinator-coordinator-1440.jpg", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/coordinator-coordinator-390.jpg", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/coordinator-domain-receipt.json", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/coordinator-receipt.json", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/publication-domain-receipt.json", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/publication-publication-1440.jpg", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/publication-publication-390.jpg", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/publication-receipt.json", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/reviewed-source-browser/coordinator-1440.jpg", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/reviewed-source-browser/coordinator-390.jpg", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/reviewed-source-browser/domain-receipt.json", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/reviewed-source-browser/receipt.json", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-browser-final-source.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-browser-first.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-controller-final-source.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-delivery-boundary-qualified.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-existing-recovery.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-pins-final-source.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-publication-regression.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-reviewed-source-browser.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-undelivered-new-key-after.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/tuldok-m2-coordinator-ui-undelivered-new-key-before.log", + "docs/plans/lab-workflow-reliability/reports/m2-coordinator-ui/validation.json", + "static/workspace-real.js", + "tests/browser_workspace_coordinator.cjs", + "tests/coordinator_browser_fixture.py", + "tests/test_workspace_coordinator.py", + "tests/test_workspace_coordinator_controller.cjs", + "tests/test_workspace_external_controller.cjs" + ] + } +] diff --git a/docs/plans/retained-analysis/reports/m4-integrated/browser-abort-initial.log b/docs/plans/retained-analysis/reports/m4-integrated/browser-abort-initial.log new file mode 100644 index 00000000..c1319103 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/browser-abort-initial.log @@ -0,0 +1,11 @@ +Error: {"code":-32602,"message":"Invalid InterceptionId."} + at WebSocket. (/workspace/Tuldok/tests/browser_retained_analysis_actual.cjs:51:111) + at [nodejs.internal.kHybridDispatch] (node:internal/event_target:856:20) + at WebSocket.dispatchEvent (node:internal/event_target:789:26) + at fireEvent (node:internal/deps/undici/undici:14403:14) + at #onMessage (node:internal/deps/undici/undici:15726:9) + at Object.onMessage (node:internal/deps/undici/undici:15433:76) + at websocketMessageReceived (node:internal/deps/undici/undici:14407:15) + at node:internal/deps/undici/undici:15135:21 + at node:internal/deps/undici/undici:14915:11 + at afterWrite (node:internal/streams/writable:708:5) diff --git a/docs/plans/retained-analysis/reports/m4-integrated/browser-errors.log b/docs/plans/retained-analysis/reports/m4-integrated/browser-errors.log new file mode 100644 index 00000000..e69de29b diff --git a/docs/plans/retained-analysis/reports/m4-integrated/browser.json b/docs/plans/retained-analysis/reports/m4-integrated/browser.json new file mode 100644 index 00000000..6a7db2ee --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/browser.json @@ -0,0 +1,34 @@ +{ + "status": "passed", + "evidence": "actual-PostgreSQL-native-Run-authenticated-Runs-browser", + "run_id": "3b55365925ed45b391072918503f7c5f", + "evaluation_sha256": "6cb8e64a1834bd1479735acd67a1a3426a49addf945cc03774e40ee30b69fd01", + "exact_curve": [ + { + "checkpoint_sha256": "73d96dc058a33810f87e67cf6097883b59266dee287c35df855b33666bb027c7", + "epoch": 1, + "support": 2, + "value": 0.5 + }, + { + "checkpoint_sha256": "daeb53dc1671f9b35ddece10f92364068e526dd61274deb8a134d3ac45e168a8", + "epoch": 2, + "support": 2, + "value": 0.5 + } + ], + "checks": [ + "actual named query", + "retained numeric oracle", + "linked keyboard example table", + "390px layout", + "held real response cancellation after navigation", + "authorized exact JSON export", + "real credential revocation clears private Run content", + "fresh application process and cache-bypassed page reopen", + "local chart assets", + "deployed script CSP blocks runtime code generation", + "actual denial during detail/predictions/model-evidence clears private Run content", + "held existing checkpoint action denial clears already-authorized retained view" + ] +} diff --git a/docs/plans/retained-analysis/reports/m4-integrated/controllers.log b/docs/plans/retained-analysis/reports/m4-integrated/controllers.log new file mode 100644 index 00000000..35ebbc64 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/controllers.log @@ -0,0 +1,13 @@ +PASS model UI: exact frozen probe correction, honest legacy history, observed zero, query ordering, navigation/session exclusion and denied evidence clearing. Controlled transport only. +PASS coordinator owner controls, exact generation/request identity, immutable completion, unknown-ack retention, stale read/write/session fences and storage refusal +PASS project/frozen/Run-artifact binding and generic progress controllers: exact old/new union, unavailable and oversized refusal, dirty approval invalidation, save/reopen projection, stale/session choice fences, escaped logs, truthful evidence, restored verified summaries, held polling view/session fences and session cache clearing. Mock transport only. +PASS scientific artifact import controller: exact hash/route, draft navigation, session/view/run-selection fences, non-completed/unavailable role refusal, edit permission and no replay after uncertain acknowledgement. Mock transport only. +PASS external controller: actor-bound unresolved key survives ambiguous→403; no cross-actor request; late save/reload/clone/grant/submit preserve navigation/session; initial authoritative rejection clears key. Mock transport only. +PASS phase identity/clock/duration/wait validation, latest-preparation labeling, bounded sequential refresh, abort and stale delivery/session cleanup +Scientific comparison controller: diagnostic table, exact identity, stale overlap, invalidation, revocation and session fences passed +PASS explicit pinned lineage publication status, original state, exact Ref navigation, no mutations/fanout, shared closed identity decoder and late session/navigation fences +PASS candidate UI: known admission rejection refreshes intent; response loss and later denial or package-state failure preserve actor-bound original preparation. Controlled transport only. +PASS lineage layout, cycles, read fences, busy ownership, actor-isolated writes, approval acknowledgement, remount retention and applied cohort pagination +PASS external field UI: exact declared selectors, shared display range, exact numeric probes, stale selector/navigation exclusion, revoked-value clearing and unsupported legacy/physical time. Controlled transport only. +PASS publication metadata, pinned status2, owner/actor controls, unknown-ack stable request, source/hash identity, stale reads/writes and polling cleanup +PASS controlled external package view: owned discovery, pending versus fresh state, source identity, denial/stale clearing and passive-only reads. diff --git a/docs/plans/retained-analysis/reports/m4-integrated/existing-runs-browsers.log b/docs/plans/retained-analysis/reports/m4-integrated/existing-runs-browsers.log new file mode 100644 index 00000000..124e7888 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/existing-runs-browsers.log @@ -0,0 +1,2 @@ +PASS coordinator browser: /workspace/Tuldok/build/qa/workspace-coordinator/run-QaqeLX +{"state":"passed","report":"/workspace/Tuldok/build/qa/scientific-comparison/run-Lz4m8U","checks":["Actual lineage opens exact ordered operands; selection causes no comparison/admission; keyboard submission returns independent expected delta 2 and explicit unknown criteria/memory.","1440/390px tables retain all values and keyboard scrolling without page overflow.","Actual overlapping HTTP responses clear pending values and fence stale delivery after exact point changes.","Exact attached publication Ref uses real publication readers and preserves original interrupted state.","Removed retained root refuses fresh candidate selection and clears prior values.","Actual browser credential revocation clears the session and all cached scientific values after the refused read."]} diff --git a/docs/plans/retained-analysis/reports/m4-integrated/http-initial.log b/docs/plans/retained-analysis/reports/m4-integrated/http-initial.log new file mode 100644 index 00000000..ec083201 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/http-initial.log @@ -0,0 +1,58 @@ +test_actual_revocation_blocks_fresh_http_and_export (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_actual_revocation_blocks_fresh_http_and_export) ... ok +test_authenticated_http_and_export_equal_real_query (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_authenticated_http_and_export_equal_real_query) ... ok +test_closed_request_rejects_sql_and_holdout_without_exposure (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_closed_request_rejects_sql_and_holdout_without_exposure) ... + test_closed_request_rejects_sql_and_holdout_without_exposure (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_closed_request_rejects_sql_and_holdout_without_exposure) (body={'sql': 'SELECT arbitrary_data'}) ... FAIL + test_closed_request_rejects_sql_and_holdout_without_exposure (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_closed_request_rejects_sql_and_holdout_without_exposure) (body={'split': 'test'}) ... FAIL + test_closed_request_rejects_sql_and_holdout_without_exposure (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_closed_request_rejects_sql_and_holdout_without_exposure) (body={'limit': 101}) ... FAIL +test_explicit_contract_and_route_bound_run_are_required (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_explicit_contract_and_route_bound_run_are_required) ... ok +test_stale_and_foreign_selection_never_returns_dataset (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_stale_and_foreign_selection_never_returns_dataset) ... ok + +====================================================================== +FAIL: test_closed_request_rejects_sql_and_holdout_without_exposure (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_closed_request_rejects_sql_and_holdout_without_exposure) (body={'sql': 'SELECT arbitrary_data'}) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/workspace/Tuldok/tests/test_retained_analysis_http.py", line 100, in test_closed_request_rejects_sql_and_holdout_without_exposure + self.assertEqual((status, value['code']), (409, 'contract_mismatch')) +AssertionError: Tuples differ: (400, 'invalid') != (409, 'contract_mismatch') + +First differing element 0: +400 +409 + +- (400, 'invalid') ++ (409, 'contract_mismatch') + +====================================================================== +FAIL: test_closed_request_rejects_sql_and_holdout_without_exposure (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_closed_request_rejects_sql_and_holdout_without_exposure) (body={'split': 'test'}) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/workspace/Tuldok/tests/test_retained_analysis_http.py", line 100, in test_closed_request_rejects_sql_and_holdout_without_exposure + self.assertEqual((status, value['code']), (409, 'contract_mismatch')) +AssertionError: Tuples differ: (400, 'invalid') != (409, 'contract_mismatch') + +First differing element 0: +400 +409 + +- (400, 'invalid') ++ (409, 'contract_mismatch') + +====================================================================== +FAIL: test_closed_request_rejects_sql_and_holdout_without_exposure (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_closed_request_rejects_sql_and_holdout_without_exposure) (body={'limit': 101}) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "/workspace/Tuldok/tests/test_retained_analysis_http.py", line 100, in test_closed_request_rejects_sql_and_holdout_without_exposure + self.assertEqual((status, value['code']), (409, 'contract_mismatch')) +AssertionError: Tuples differ: (400, 'invalid') != (409, 'contract_mismatch') + +First differing element 0: +400 +409 + +- (400, 'invalid') ++ (409, 'contract_mismatch') + +---------------------------------------------------------------------- +Ran 5 tests in 0.970s + +FAILED (failures=3) diff --git a/docs/plans/retained-analysis/reports/m4-integrated/http-tests.log b/docs/plans/retained-analysis/reports/m4-integrated/http-tests.log new file mode 100644 index 00000000..32b2d635 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/http-tests.log @@ -0,0 +1,10 @@ +test_actual_revocation_blocks_fresh_http_and_export (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_actual_revocation_blocks_fresh_http_and_export) ... ok +test_authenticated_http_and_export_equal_real_query (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_authenticated_http_and_export_equal_real_query) ... ok +test_closed_request_rejects_sql_and_holdout_without_exposure (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_closed_request_rejects_sql_and_holdout_without_exposure) ... ok +test_explicit_contract_and_route_bound_run_are_required (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_explicit_contract_and_route_bound_run_are_required) ... ok +test_stale_and_foreign_selection_never_returns_dataset (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_stale_and_foreign_selection_never_returns_dataset) ... ok + +---------------------------------------------------------------------- +Ran 5 tests in 0.896s + +OK diff --git a/docs/plans/retained-analysis/reports/m4-integrated/independent/browser-errors.log b/docs/plans/retained-analysis/reports/m4-integrated/independent/browser-errors.log new file mode 100644 index 00000000..e69de29b diff --git a/docs/plans/retained-analysis/reports/m4-integrated/independent/browser.json b/docs/plans/retained-analysis/reports/m4-integrated/independent/browser.json new file mode 100644 index 00000000..6a7db2ee --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/independent/browser.json @@ -0,0 +1,34 @@ +{ + "status": "passed", + "evidence": "actual-PostgreSQL-native-Run-authenticated-Runs-browser", + "run_id": "3b55365925ed45b391072918503f7c5f", + "evaluation_sha256": "6cb8e64a1834bd1479735acd67a1a3426a49addf945cc03774e40ee30b69fd01", + "exact_curve": [ + { + "checkpoint_sha256": "73d96dc058a33810f87e67cf6097883b59266dee287c35df855b33666bb027c7", + "epoch": 1, + "support": 2, + "value": 0.5 + }, + { + "checkpoint_sha256": "daeb53dc1671f9b35ddece10f92364068e526dd61274deb8a134d3ac45e168a8", + "epoch": 2, + "support": 2, + "value": 0.5 + } + ], + "checks": [ + "actual named query", + "retained numeric oracle", + "linked keyboard example table", + "390px layout", + "held real response cancellation after navigation", + "authorized exact JSON export", + "real credential revocation clears private Run content", + "fresh application process and cache-bypassed page reopen", + "local chart assets", + "deployed script CSP blocks runtime code generation", + "actual denial during detail/predictions/model-evidence clears private Run content", + "held existing checkpoint action denial clears already-authorized retained view" + ] +} diff --git a/docs/plans/retained-analysis/reports/m4-integrated/independent/contracts.log b/docs/plans/retained-analysis/reports/m4-integrated/independent/contracts.log new file mode 100644 index 00000000..c6922ce2 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/independent/contracts.log @@ -0,0 +1,8 @@ +test_closed_bounded_arguments (test_retained_analysis_contracts.RetainedAnalysisContractTests.test_closed_bounded_arguments) ... ok +test_new_inspect_contracts_match_browser_pins (test_retained_analysis_contracts.RetainedAnalysisContractTests.test_new_inspect_contracts_match_browser_pins) ... ok +test_registry_and_existing_contract_bytes_are_unchanged (test_retained_analysis_contracts.RetainedAnalysisContractTests.test_registry_and_existing_contract_bytes_are_unchanged) ... ok + +---------------------------------------------------------------------- +Ran 3 tests in 1.891s + +OK diff --git a/docs/plans/retained-analysis/reports/m4-integrated/independent/http-tests.log b/docs/plans/retained-analysis/reports/m4-integrated/independent/http-tests.log new file mode 100644 index 00000000..cd833120 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/independent/http-tests.log @@ -0,0 +1,10 @@ +test_actual_revocation_blocks_fresh_http_and_export (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_actual_revocation_blocks_fresh_http_and_export) ... ok +test_authenticated_http_and_export_equal_real_query (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_authenticated_http_and_export_equal_real_query) ... ok +test_closed_request_rejects_sql_and_holdout_without_exposure (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_closed_request_rejects_sql_and_holdout_without_exposure) ... ok +test_explicit_contract_and_route_bound_run_are_required (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_explicit_contract_and_route_bound_run_are_required) ... ok +test_stale_and_foreign_selection_never_returns_dataset (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_stale_and_foreign_selection_never_returns_dataset) ... ok + +---------------------------------------------------------------------- +Ran 5 tests in 0.949s + +OK diff --git a/docs/plans/retained-analysis/reports/m4-integrated/independent/identity-compatibility.json b/docs/plans/retained-analysis/reports/m4-integrated/independent/identity-compatibility.json new file mode 100644 index 00000000..9b276ae9 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/independent/identity-compatibility.json @@ -0,0 +1,10 @@ +{ + "comparison_base": "83a1e1289f3f7e4f8c3e697c1748a862a69d0897", + "checked_prior_contract_documents": 124, + "changed_prior_contract_documents": [], + "legacy_discovery_exact_equal": true, + "added_operations": [ + "runs.export_retained_analysis", + "runs.retained_analysis" + ] +} diff --git a/docs/plans/retained-analysis/reports/m4-integrated/independent/model-controller.log b/docs/plans/retained-analysis/reports/m4-integrated/independent/model-controller.log new file mode 100644 index 00000000..97e906b3 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/independent/model-controller.log @@ -0,0 +1 @@ +PASS model UI: exact frozen probe correction, honest legacy history, observed zero, query ordering, navigation/session exclusion and denied evidence clearing. Controlled transport only. diff --git a/docs/plans/retained-analysis/reports/m4-integrated/independent/review.md b/docs/plans/retained-analysis/reports/m4-integrated/independent/review.md new file mode 100644 index 00000000..f9c42773 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/independent/review.md @@ -0,0 +1,23 @@ +# Final independent review + +Reviewer: separate GPT-6.1 Sol High Codex instance (`query_review`). +Verdict: **Approved; no remaining blocking findings** against reliability83a1e128. + +Reviewed the query, new registry contracts and selected route, bounded transport, +Run lifecycle/authority, pinned assets/spec, scoped CSP and additive CI/test +changes. Earlier review findings (ordinary Run denial propagation, null identity +cleanup, deployed CSP, and old checkpoint/candidate denial paths) are resolved. +The central model wrapper captures source Run, credential and generation before +dispatch; forwards current denials before presentation catches; excludes aborted +or invalidated requests; and preserves the original transport arguments. + +Independent execution: contracts3 passed; actual authenticated HTTP5 passed; +model controller passed; actual Runs Chromium passed with empty browser errors. +The browser included the held checkpoint denial after successful retained-query +rerender, deployed CSP, cancellation, authorized export and fresh-process reopen. +All124 prior contract documents and legacy discovery match the reliability base +exactly. See adjacent logs, compatibility receipt and source-sha256.json. The +final18-file source manifest was verified against the publication files. + +Only review evidence was written by the reviewer. No implementation, service, +credential or training changes were made. Lead alone owns merge. diff --git a/docs/plans/retained-analysis/reports/m4-integrated/independent/source-sha256.json b/docs/plans/retained-analysis/reports/m4-integrated/independent/source-sha256.json new file mode 100644 index 00000000..81bd5544 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/independent/source-sha256.json @@ -0,0 +1,20 @@ +{ + ".github/workflows/tests.yml": "100feb4cbcbd84cddc991602c24d196ee1a1f3e4b23b383adbcb49366453e38d", + "agent_api.py": "bb14a25c63840f1701b13657fa1bce4659a2c6a180068e95f461e5fa7f9327b4", + "app.py": "c71b8b903fa8905ff5fd3ccaef1b86d3df3ddda5393f33bf3ec9661a98d02417", + "retained_analysis.py": "d41f805419f6acff08175b61d3bce9a611de8025cbf5bccc3ccf08e809479501", + "retained_analysis_schema.py": "8d6a743567eab6b99e9132721eabd12e7a381c742c84911e6ef58478a0ea43d3", + "runs.py": "b701532d0bf5c77ee87676fa3bbfbf9759ae45370c28d45765b2eac538a4547e", + "model_evidence.py": "04012022740f45fc03ad11351a7efe4946e574890bb814fcdf5871b873a5701b", + "static/retained-analysis.js": "d9dab53d15e6e50ecf8f1b9e182c43eb330c4731e574758a0e3026f44acb44df", + "static/retained-checkpoint-curve.vl.json": "6603c860ce76a434a11e6c96cf7418246ce2dd5da3d7a56a5f2448a0537ec183", + "static/workspace-real.js": "de4036bab21c3ca2702488658a9fa8733cf0adb822f4ec3322d5e101a96b60a2", + "static/workspace-service.js": "568b8258c35e6b3ca2cfe08b64d914111e16ae98d45f5d40f7aa40a20c20098b", + "static/workspaces.html": "a85e465d317e8aaa14c5349ef1ae6b2dc75ac440e0cea2c5c5a313dbd4fb828e", + "static/workspaces.css": "3d0eacbd50425b4cd2ce9cfacdf5bcdb8fe533d7a57248f16325242f625cd278", + "tests/test_retained_analysis_contracts.py": "44811b92c4ae847888d34d949eea8b22a79d4bd0edfc0e27e0963377a0103e5f", + "tests/test_retained_analysis_http.py": "eff09d89bdad94c78af4c558d79d0dabf7bd9d502f0ced6df83163023f2dee44", + "tests/test_workspace_model_controller.cjs": "a4ac7eab2546d4e9d27c0350219cf5bcdbe82cc29193a9553958b4e2ea650245", + "tests/browser_retained_analysis_actual.cjs": "615e24368965ce4e97f75a0c05d63f9ae06cc28c13d864130691141ac8eefc3d", + "static/vendor/retained-analysis/manifest.json": "298dbcaf1a3852db247cd781ef60c620d67c6ddfdcd646cae38a321368a280a5" +} diff --git a/docs/plans/retained-analysis/reports/m4-integrated/query-http-tests.log b/docs/plans/retained-analysis/reports/m4-integrated/query-http-tests.log new file mode 100644 index 00000000..b7ab673a --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/query-http-tests.log @@ -0,0 +1,32 @@ +test_parameterized_curve_and_stable_error_page_on_actual_postgres (test_retained_analysis.ActualPostgresSqlTests.test_parameterized_curve_and_stable_error_page_on_actual_postgres) ... ok +test_exact_frozen_examples_and_retained_confidence (test_retained_analysis.ProjectionTests.test_exact_frozen_examples_and_retained_confidence) ... ok +test_foreign_metric_checkpoint_and_population_are_distinct_failures (test_retained_analysis.ProjectionTests.test_foreign_metric_checkpoint_and_population_are_distinct_failures) ... ok +test_unsupported_task_and_oversize_are_explicit (test_retained_analysis.ProjectionTests.test_unsupported_task_and_oversize_are_explicit) ... ok +test_catalog_mismatch_is_refused (test_retained_analysis.QueryBoundaryTests.test_catalog_mismatch_is_refused) ... ok +test_error_filter_does_not_change_metric_population_and_page_identity (test_retained_analysis.QueryBoundaryTests.test_error_filter_does_not_change_metric_population_and_page_identity) ... ok +test_exact_provenance_and_values_with_fresh_access_outside_snapshot (test_retained_analysis.QueryBoundaryTests.test_exact_provenance_and_values_with_fresh_access_outside_snapshot) ... ok +test_export_and_repeated_retrieval_do_not_bypass_current_authority (test_retained_analysis.QueryBoundaryTests.test_export_and_repeated_retrieval_do_not_bypass_current_authority) ... ok +test_malformed_catalog_envelope_preserves_typed_failure (test_retained_analysis.QueryBoundaryTests.test_malformed_catalog_envelope_preserves_typed_failure) ... ok +test_nested_transaction_and_oversized_response_refused (test_retained_analysis.QueryBoundaryTests.test_nested_transaction_and_oversized_response_refused) ... ok +test_revocation_during_read_prevents_return (test_retained_analysis.QueryBoundaryTests.test_revocation_during_read_prevents_return) ... ok +test_closed_bounds_and_types_before_evidence_read (test_retained_analysis.RequestTests.test_closed_bounds_and_types_before_evidence_read) ... ok +test_defaults_and_explicit_field_projection (test_retained_analysis.RequestTests.test_defaults_and_explicit_field_projection) ... ok +test_actual_sql_curve_and_examples_equal_original_retained_artifacts (test_retained_analysis_actual.ActualRetainedAnalysisTests.test_actual_sql_curve_and_examples_equal_original_retained_artifacts) ... ok +test_new_process_cold_reopen_preserves_exact_result (test_retained_analysis_actual.ActualRetainedAnalysisTests.test_new_process_cold_reopen_preserves_exact_result) ... ok +test_query_and_export_are_inert_and_restore_session_settings (test_retained_analysis_actual.ActualRetainedAnalysisTests.test_query_and_export_are_inert_and_restore_session_settings) ... ok +test_real_credential_revocation_blocks_repeated_query_and_export (test_retained_analysis_actual.ActualRetainedAnalysisTests.test_real_credential_revocation_blocks_repeated_query_and_export) ... ok +test_repeated_query_reverifies_hash_bound_artifact (test_retained_analysis_actual.ActualRetainedAnalysisTests.test_repeated_query_reverifies_hash_bound_artifact) ... ok +test_revocation_at_final_authorization_uses_current_real_credential (test_retained_analysis_actual.ActualRetainedAnalysisTests.test_revocation_at_final_authorization_uses_current_real_credential) ... ok +test_closed_bounded_arguments (test_retained_analysis_contracts.RetainedAnalysisContractTests.test_closed_bounded_arguments) ... ok +test_new_inspect_contracts_match_browser_pins (test_retained_analysis_contracts.RetainedAnalysisContractTests.test_new_inspect_contracts_match_browser_pins) ... ok +test_registry_and_existing_contract_bytes_are_unchanged (test_retained_analysis_contracts.RetainedAnalysisContractTests.test_registry_and_existing_contract_bytes_are_unchanged) ... ok +test_actual_revocation_blocks_fresh_http_and_export (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_actual_revocation_blocks_fresh_http_and_export) ... ok +test_authenticated_http_and_export_equal_real_query (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_authenticated_http_and_export_equal_real_query) ... ok +test_closed_request_rejects_sql_and_holdout_without_exposure (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_closed_request_rejects_sql_and_holdout_without_exposure) ... ok +test_explicit_contract_and_route_bound_run_are_required (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_explicit_contract_and_route_bound_run_are_required) ... ok +test_stale_and_foreign_selection_never_returns_dataset (test_retained_analysis_http.ActualRetainedAnalysisHttpTests.test_stale_and_foreign_selection_never_returns_dataset) ... ok + +---------------------------------------------------------------------- +Ran 27 tests in 3.852s + +OK diff --git a/docs/plans/retained-analysis/reports/m4-integrated/regressions.log b/docs/plans/retained-analysis/reports/m4-integrated/regressions.log new file mode 100644 index 00000000..9e66a275 --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/regressions.log @@ -0,0 +1,56 @@ +test_actual_catalog_mutex_wait_is_measured_by_owner_without_reconstructing_events (test_run_phase_timings.ActualPhaseTimingTests.test_actual_catalog_mutex_wait_is_measured_by_owner_without_reconstructing_events) ... ok +test_actual_queue_copy_fault_recovery_and_cold_read_preserve_original_authority (test_run_phase_timings.ActualPhaseTimingTests.test_actual_queue_copy_fault_recovery_and_cold_read_preserve_original_authority) ... ok +test_missing_or_foreign_custodian_diagnostics_cannot_change_completed_result (test_run_phase_timings.ActualPhaseTimingTests.test_missing_or_foreign_custodian_diagnostics_cannot_change_completed_result) ... ok +test_overlapping_same_actor_preparations_expose_latest_clock_without_rebinding_old_reply (test_run_phase_timings.ActualPhaseTimingTests.test_overlapping_same_actor_preparations_expose_latest_clock_without_rebinding_old_reply) ... ok +test_pre_run_preparation_is_live_actor_revision_scoped_and_has_no_run_effect (test_run_phase_timings.ActualPhaseTimingTests.test_pre_run_preparation_is_live_actor_revision_scoped_and_has_no_run_effect) ... ok +test_real_capacity_wait_single_go_and_active_cancel_keep_observations_separate (test_run_phase_timings.ActualPhaseTimingTests.test_real_capacity_wait_single_go_and_active_cancel_keep_observations_separate) ... ok +test_selected_http_cli_old_run_unknown_and_bounded_catalog_wait (test_run_phase_timings.ActualPhaseTimingTests.test_selected_http_cli_old_run_unknown_and_bounded_catalog_wait) ... ok +test_all_open_span_cap_reports_each_missing_observation_without_closing_owners (test_run_phase_timings.OwnerPhaseTimingTests.test_all_open_span_cap_reports_each_missing_observation_without_closing_owners) ... ok +test_client_correlates_exact_run_catalog_graph_revision_and_never_retries (test_run_phase_timings.OwnerPhaseTimingTests.test_client_correlates_exact_run_catalog_graph_revision_and_never_retries) ... ok +test_closed_wire_refuses_duplicate_clocks_forged_durations_and_waits (test_run_phase_timings.OwnerPhaseTimingTests.test_closed_wire_refuses_duplicate_clocks_forged_durations_and_waits) ... ok +test_full_baseline_contracts_and_legacy_discovery_are_identical (test_run_phase_timings.OwnerPhaseTimingTests.test_full_baseline_contracts_and_legacy_discovery_are_identical) ... ok +test_history_and_long_lived_open_span_are_bounded_without_false_duration (test_run_phase_timings.OwnerPhaseTimingTests.test_history_and_long_lived_open_span_are_bounded_without_false_duration) ... ok +test_open_snapshot_cold_reopen_and_failed_phase_never_invent_an_end (test_run_phase_timings.OwnerPhaseTimingTests.test_open_snapshot_cold_reopen_and_failed_phase_never_invent_an_end) ... ok +test_overlapping_owner_spans_use_monotonic_time_and_are_not_added (test_run_phase_timings.OwnerPhaseTimingTests.test_overlapping_owner_spans_use_monotonic_time_and_are_not_added) ... ok + +---------------------------------------------------------------------- +Ran 14 tests in 16.878s + +OK +test_absolute_header_deadline_includes_trickle (test_agent_api.ClientTests.test_absolute_header_deadline_includes_trickle) ... ok +test_authenticated_discovery_proxy_ignored_and_one_mutation (test_agent_api.ClientTests.test_authenticated_discovery_proxy_ignored_and_one_mutation) ... ok +test_fixed_endpoint_and_private_configuration (test_agent_api.ClientTests.test_fixed_endpoint_and_private_configuration) ... ok +test_framing_identity_registry_refusals (test_agent_api.ClientTests.test_framing_identity_registry_refusals) ... ok +test_three_file_sequence_is_unsupported_before_http_dispatch (test_agent_api.ClientTests.test_three_file_sequence_is_unsupported_before_http_dispatch) ... ok +test_unknown_commit_is_not_retried_or_secret_echoed (test_agent_api.ClientTests.test_unknown_commit_is_not_retried_or_secret_echoed) ... ok +test_segment_reassembly_and_whole_hash_tamper (test_agent_api.OutputTests.test_segment_reassembly_and_whole_hash_tamper) ... ok +test_typed_error_and_success_shapes (test_agent_api.OutputTests.test_typed_error_and_success_shapes) ... ok +test_image_forwards_exact_raw_base64 (test_agent_api.ParityRegressionTests.test_image_forwards_exact_raw_base64) ... ok +test_revoked_discovery_preserves_http_status_and_code_without_mutation (test_agent_api.ParityRegressionTests.test_revoked_discovery_preserves_http_status_and_code_without_mutation) ... ok +test_all_operation_schemas_and_route_projections (test_agent_api.RegistryTests.test_all_operation_schemas_and_route_projections) ... ok +test_bindings_known_graph_drafts_and_no_executable_topology_requirement (test_agent_api.RegistryTests.test_bindings_known_graph_drafts_and_no_executable_topology_requirement) ... ok +test_discovery_is_stdlib_only_in_cold_process (test_agent_api.RegistryTests.test_discovery_is_stdlib_only_in_cold_process) ... ok +test_draft_tasks_and_no_human_or_programmatic_review (test_agent_api.RegistryTests.test_draft_tasks_and_no_human_or_programmatic_review) ... ok +test_exposure_grant_and_projection (test_agent_api.RegistryTests.test_exposure_grant_and_projection) ... ok +test_import_bytes_bound_is_aggregate (test_agent_api.RegistryTests.test_import_bytes_bound_is_aggregate) ... ok +test_integer_unicode_nonfinite_and_closed_subobjects (test_agent_api.RegistryTests.test_integer_unicode_nonfinite_and_closed_subobjects) ... ok + +---------------------------------------------------------------------- +Ran 17 tests in 37.883s + +OK +test_agent_review_and_execution_denied_before_mutation (test_access_http.AccessHTTP.test_agent_review_and_execution_denied_before_mutation) ... ok +test_all_legacy_and_current_reads_require_real_credentials (test_access_http.AccessHTTP.test_all_legacy_and_current_reads_require_real_credentials) ... ok +test_cookie_origin_mixed_transport_and_bootstrap_replay (test_access_http.AccessHTTP.test_cookie_origin_mixed_transport_and_bootstrap_replay) ... ok +test_denial_audit_storage_outage_still_returns_structured_error (test_access_http.AccessHTTP.test_denial_audit_storage_outage_still_returns_structured_error) ... ok + +---------------------------------------------------------------------- +Ran 4 tests in 2.453s + +OK +test_phase_contract_pins_match_complete_selected_contracts (test_workspace_phase_timings.PhasePanelPins.test_phase_contract_pins_match_complete_selected_contracts) ... ok + +---------------------------------------------------------------------- +Ran 1 test in 0.001s + +OK diff --git a/docs/plans/retained-analysis/reports/m4-integrated/renderer.json b/docs/plans/retained-analysis/reports/m4-integrated/renderer.json new file mode 100644 index 00000000..a4122f3d --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/renderer.json @@ -0,0 +1,18 @@ +{ + "status": "passed", + "evidence": "actual-headless-Chromium-authored-renderer-fixture", + "checks": [ + "strict CSP/interpreter", + "self-hosted/offline external assets", + "exact numbers", + "keyboard linked selection/focus", + "visible error filter", + "390px layout", + "stale reply after revocation", + "malformed/oversized response and spec rejection", + "support/ordinal/provenance/type validation", + "fresh export authorization path", + "cold page reopen", + "dispose" + ] +} diff --git a/docs/plans/retained-analysis/reports/m4-integrated/source-checkpoint.json b/docs/plans/retained-analysis/reports/m4-integrated/source-checkpoint.json new file mode 100644 index 00000000..77e3016f --- /dev/null +++ b/docs/plans/retained-analysis/reports/m4-integrated/source-checkpoint.json @@ -0,0 +1,89 @@ +{ + "format": "retained_analysis_source_checkpoint_v1", + "branch": "feature/retained-analysis-query-20261019", + "reliability_dependency": "83a1e1289f3f7e4f8c3e697c1748a862a69d0897", + "composition_merge": "252a68c5b90afdd8660f652cfa0094233ef9f64f", + "main": "8c9c0b07d90fd78657539cdcbcd23fbf289c4f95", + "files": { + ".github/workflows/tests.yml": "100feb4cbcbd84cddc991602c24d196ee1a1f3e4b23b383adbcb49366453e38d", + "agent_api.py": "bb14a25c63840f1701b13657fa1bce4659a2c6a180068e95f461e5fa7f9327b4", + "app.py": "c71b8b903fa8905ff5fd3ccaef1b86d3df3ddda5393f33bf3ec9661a98d02417", + "examples/analysis/requirements.txt": "4d9f3531962ab894b827643750dbcedd56c2c25d5a18339c69ce9b8f913433eb", + "examples/analysis/retained_checkpoint_curve.py": "dce74b88c13f85f272734da5876d96bfcef746074ece0027f9f57532de767f8f", + "retained_analysis.py": "d41f805419f6acff08175b61d3bce9a611de8025cbf5bccc3ccf08e809479501", + "retained_analysis_schema.py": "8d6a743567eab6b99e9132721eabd12e7a381c742c84911e6ef58478a0ea43d3", + "static/retained-analysis.js": "d9dab53d15e6e50ecf8f1b9e182c43eb330c4731e574758a0e3026f44acb44df", + "static/retained-checkpoint-curve.vl.json": "6603c860ce76a434a11e6c96cf7418246ce2dd5da3d7a56a5f2448a0537ec183", + "static/vendor/retained-analysis/licenses/d3-array.txt": "552e22a104bb752daf35286bfc180b7bb6c206cc6502853979bd19390102d644", + "static/vendor/retained-analysis/licenses/d3-color.txt": "decfad6f87be1e200338d792b77793997db27b3f4e610f870370393ed53daf4b", + "static/vendor/retained-analysis/licenses/d3-delaunay.txt": "718da82757e9041ac674c157d9fc70435543b32f4c1baf4a9f08b71c5fa6495e", + "static/vendor/retained-analysis/licenses/d3-dispatch.txt": "2127431ebe97ddcbabb32b1049bade99e4c4b2412d3f8b39ec161814f5e2e11e", + "static/vendor/retained-analysis/licenses/d3-dsv.txt": "2823e0d11f6e134bfe32ec3b60f042db2d7be3e4eb3e7f09b7c93a3bef502ec3", + "static/vendor/retained-analysis/licenses/d3-force.txt": "2127431ebe97ddcbabb32b1049bade99e4c4b2412d3f8b39ec161814f5e2e11e", + "static/vendor/retained-analysis/licenses/d3-format.txt": "dfd3916622f5f66f001a5c9ec0beb6d4b0208b9ba41a81206bf6fa0940b6e980", + "static/vendor/retained-analysis/licenses/d3-geo-projection.txt": "8d78a83093868a5a6d86835807514b0f5bda66403a0d75cbf804ad72a3619463", + "static/vendor/retained-analysis/licenses/d3-geo.txt": "e3243e2788023f118b725d27189d529d13da89dca0801380a9ecf96da3a5fa67", + "static/vendor/retained-analysis/licenses/d3-hierarchy.txt": "2127431ebe97ddcbabb32b1049bade99e4c4b2412d3f8b39ec161814f5e2e11e", + "static/vendor/retained-analysis/licenses/d3-interpolate.txt": "2127431ebe97ddcbabb32b1049bade99e4c4b2412d3f8b39ec161814f5e2e11e", + "static/vendor/retained-analysis/licenses/d3-path.txt": "16d2d2a1800677ddece729f5acb30205b5acbc21529df90cd8bf3d202c08d0b7", + "static/vendor/retained-analysis/licenses/d3-quadtree.txt": "2127431ebe97ddcbabb32b1049bade99e4c4b2412d3f8b39ec161814f5e2e11e", + "static/vendor/retained-analysis/licenses/d3-scale-chromatic.txt": "b982e295bd298c8d3e328a7cc623396e6e708fb6fba5b35e2dc4daf36728c8ed", + "static/vendor/retained-analysis/licenses/d3-scale.txt": "2127431ebe97ddcbabb32b1049bade99e4c4b2412d3f8b39ec161814f5e2e11e", + "static/vendor/retained-analysis/licenses/d3-shape.txt": "decfad6f87be1e200338d792b77793997db27b3f4e610f870370393ed53daf4b", + "static/vendor/retained-analysis/licenses/d3-time-format.txt": "2127431ebe97ddcbabb32b1049bade99e4c4b2412d3f8b39ec161814f5e2e11e", + "static/vendor/retained-analysis/licenses/d3-time.txt": "decfad6f87be1e200338d792b77793997db27b3f4e610f870370393ed53daf4b", + "static/vendor/retained-analysis/licenses/d3-timer.txt": "2127431ebe97ddcbabb32b1049bade99e4c4b2412d3f8b39ec161814f5e2e11e", + "static/vendor/retained-analysis/licenses/delaunator.txt": "9994d103e3af6ded25bad0ae99f08f6758f08cb9b261ab921ae7a6279769cdf0", + "static/vendor/retained-analysis/licenses/fast-json-patch.txt": "488a71c4303f0860094c1e59fa32e3302e9e79e2b63b8731761c22c2101c1dc9", + "static/vendor/retained-analysis/licenses/internmap.txt": "c596ec7154f49d5b5354b5483891de003b9af0f127aa007a6c5cea659e53d7c4", + "static/vendor/retained-analysis/licenses/json-stringify-pretty-compact.txt": "0454b235e715629194c3a1efb8b5a1b5c4a26bea9e8d54f4061b603d34cbea18", + "static/vendor/retained-analysis/licenses/robust-predicates.txt": "4731daf16265d7f0acd5c305a2dc745cf4c7562e027d44c206ab38637d8558ab", + "static/vendor/retained-analysis/licenses/semver.txt": "3ef9e4a3ab62e8eebd271519b275803e13e59a790cbdca7f617cbff34c56ed80", + "static/vendor/retained-analysis/licenses/topojson-client.txt": "140e4489d9507aedeb615404008fe1d51b418b7cdb428ea840481105c14eda97", + "static/vendor/retained-analysis/licenses/vega-canvas.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-crossfilter.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-embed.txt": "9ba0f1b61d8bb4c228264ed5305c543914fa0fd3f3e302623138a3f93d649304", + "static/vendor/retained-analysis/licenses/vega-encode.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-event-selector.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-force.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-geo.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-hierarchy.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-interpreter.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-label.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-lite.txt": "1d88c9e50bf518513f0db4b4faff48d26fce5591025277a79f687f1961fe5ed8", + "static/vendor/retained-analysis/licenses/vega-parser.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-projection.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-regression.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-runtime.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-schema-url-parser.txt": "886fb7d90ade30e3ddb1509c644b649738f4461427d128d278b41e0894175881", + "static/vendor/retained-analysis/licenses/vega-statistics.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-themes.txt": "0344cdac38613ef402506fb143f7e37fb4cd91aead07a51ebfe916a32909f3d6", + "static/vendor/retained-analysis/licenses/vega-tooltip.txt": "6dbbe75e03459c41a0d380bbf85c2221d817733e603960d674c0de546f7daee1", + "static/vendor/retained-analysis/licenses/vega-transforms.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-view-transforms.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-view.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-voronoi.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega-wordcloud.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/licenses/vega.txt": "b686cdefc306925f182fce89952147997ef214e8c2a8c9b7bb3f5084edffcc76", + "static/vendor/retained-analysis/manifest.json": "298dbcaf1a3852db247cd781ef60c620d67c6ddfdcd646cae38a321368a280a5", + "static/vendor/retained-analysis/vega-embed.min.js": "12d02acfbe3ec59ef9a37dd4822a2e04e2961b5bbb671bbe661d2221715b99da", + "static/vendor/retained-analysis/vega-interpreter.min.js": "13002339c7e6231ef919584cbdf7391b246ea5073f686ffd707c62628b7f87df", + "static/vendor/retained-analysis/vega-lite.min.js": "58c27358e26f2d319cf62f45bc17a4c8362f08645001df2ec8d341eee4097c7f", + "static/vendor/retained-analysis/vega.min.js": "a71f14828abacac82fbe8adb07ce65cbb82561d8eef188053c4a1c09e0164dcb", + "static/workspace-real.js": "de4036bab21c3ca2702488658a9fa8733cf0adb822f4ec3322d5e101a96b60a2", + "static/workspace-service.js": "568b8258c35e6b3ca2cfe08b64d914111e16ae98d45f5d40f7aa40a20c20098b", + "static/workspaces.css": "3d0eacbd50425b4cd2ce9cfacdf5bcdb8fe533d7a57248f16325242f625cd278", + "static/workspaces.html": "a85e465d317e8aaa14c5349ef1ae6b2dc75ac440e0cea2c5c5a313dbd4fb828e", + "tests/browser_retained_analysis.cjs": "822d6df2d8c29e909f6f0dcee42595f90c9eae70306ff9c8b20eba042bdd05ce", + "tests/browser_retained_analysis_actual.cjs": "615e24368965ce4e97f75a0c05d63f9ae06cc28c13d864130691141ac8eefc3d", + "tests/fixtures/retained-analysis-browser.css": "9210e84315e07086621a859a18ba7e9744ed4fc5b267119ecccbee4ec3ec99fb", + "tests/fixtures/retained-analysis-browser.js": "20693914724c187875e53b79198280c197b93256cc542bbdb74e7799b9789e8b", + "tests/retained_analysis_actual_fixture.py": "5e8759c7715de85b8df886727d11335cc913d78d178b3d787e09778aab29ff55", + "tests/retained_analysis_browser_fixture.py": "ececc679267b6e8671ab3fb189ca093f53bf874ad5d9469df0b36ff008f7ad62", + "tests/test_retained_analysis.py": "10ab4c7ad35c9df868320add066799a18896538ee59593156d4b52b0b2d1a11a", + "tests/test_retained_analysis_actual.py": "255abedd2980dd36deee27ae0a12c1f1e3870c3c92c3203bea334ae7bfd8e651", + "tests/test_retained_analysis_contracts.py": "44811b92c4ae847888d34d949eea8b22a79d4bd0edfc0e27e0963377a0103e5f", + "tests/test_retained_analysis_http.py": "eff09d89bdad94c78af4c558d79d0dabf7bd9d502f0ced6df83163023f2dee44", + "tests/test_workspace_model_controller.cjs": "a4ac7eab2546d4e9d27c0350219cf5bcdbe82cc29193a9553958b4e2ea650245" + } +} diff --git a/retained_analysis.py b/retained_analysis.py index 45297dcd..43f68880 100644 --- a/retained_analysis.py +++ b/retained_analysis.py @@ -14,10 +14,9 @@ from model_evidence import canonical, digest from pipeline import closed, identifier +from retained_analysis_schema import QUERY_ID, QUERY_VERSION, FIELDS from workbench import WorkbenchError -QUERY_ID = 'retained_checkpoint_examples' -QUERY_VERSION = 1 MAX_PAGE = 100 MAX_OFFSET = 10000 MAX_EXAMPLES = 10000 @@ -27,7 +26,6 @@ MAX_DOCUMENT_BYTES = 16 * 1024 * 1024 SQL_TIMEOUT_MS = 2000 LOCK_SECONDS = 2 -FIELDS = ('example_id', 'truth_index', 'predicted_index', 'confidence', 'error') METRICS = ('accuracy', 'loss', 'macro_f1') HASH = re.compile(r'^[a-f0-9]{64}$') diff --git a/retained_analysis_schema.py b/retained_analysis_schema.py new file mode 100644 index 00000000..3d511f5a --- /dev/null +++ b/retained_analysis_schema.py @@ -0,0 +1,55 @@ +"""Closed v1 retained classifier query schemas; standard-library-only discovery.""" +QUERY_ID = 'retained_checkpoint_examples' +QUERY_VERSION = 1 +FIELDS = ('example_id', 'truth_index', 'predicted_index', 'confidence', 'error') + + +def schemas(obj, text, integer, array, const, identifier, sha): + """Use the operation registry's ordinary schema constructors without imports.""" + natural = integer(0, 2**53 - 1) + support = integer(0, 10000) + nullable_offset = {'oneOf': [integer(0, 10000), {'type': 'null'}]} + metric_id = {'enum': ['accuracy', 'loss', 'macro_f1']} + fields = dict(array({'enum': list(FIELDS)}, len(FIELDS), 1), uniqueItems=True, + contains=const('example_id')) + request = obj({'query_id': const(QUERY_ID), 'query_version': const(QUERY_VERSION), + 'run_id': identifier, 'evaluation_sha256': sha, 'checkpoint_sha256': sha, + 'metric_id': metric_id, 'metric_definition_sha256': sha, 'fields': fields, + 'errors_only': {'type': 'boolean'}, 'limit': integer(1, 100), 'offset': integer(0, 10000)}, + ['query_id', 'query_version', 'run_id', 'evaluation_sha256', 'checkpoint_sha256', + 'metric_id', 'metric_definition_sha256']) + definition = obj({'id': metric_id, 'semantic_version': const(1), 'split': const('validation'), + 'units': const('dimensionless'), 'direction': {'enum': ['minimize', 'maximize']}, + 'reduction': {'enum': ['mean_cross_entropy', 'diagonal_over_population', + 'macro_over_frozen_vocabulary_zero_division_0']}, + 'population_sha256': sha, 'domain': obj({'minimum': {'type': 'number'}, 'maximum': {'type': 'number'}}), + 'undefined_rule': const('not_applicable'), 'evaluator_sha256': sha, + 'preprocessing_sha256': sha, 'class_order_sha256': sha}) + frozen = obj({'id': identifier, 'revision': integer(1, 2**53 - 1), + 'source_revision': integer(1, 2**53 - 1), 'source_sha256': sha, + 'asset_sha256': sha, 'exported_pixel_sha256': sha}) + row = obj({'example_id': identifier, 'ordinal': integer(0, 9999), 'frozen_reference': frozen, + 'truth_index': natural, 'predicted_index': natural, + 'confidence': {'type': 'number', 'minimum': 0, 'maximum': 1}, 'error': {'type': 'boolean'}}, + ['example_id', 'ordinal', 'frozen_reference']) + columns = {'oneOf': [obj({'field': const(field), 'type': const(kind), + 'units': const('dimensionless' if field == 'confidence' else None)}) + for field, kind in zip(FIELDS, ('string', 'integer', 'integer', 'number', 'boolean'))]} + result = obj({'state': const('verified'), 'query_id': const(QUERY_ID), 'query_version': const(QUERY_VERSION), + 'mode': const('frozen'), 'provenance': obj({'catalog_id': identifier, 'run_id': identifier, + 'evaluation_sha256': sha, 'checkpoint_sha256': sha, 'metric_definition_sha256': sha, + 'population_sha256': sha, 'probe_sha256': sha, 'data_sha256': sha, + 'producer': obj({'catalog_id': identifier, 'run_id': identifier, + 'material_sha256': sha, 'adapter_sha256': sha})}), + 'metric': obj({'id': metric_id, 'units': const('dimensionless'), + 'definition': definition, 'support': support}), + 'curve': array(obj({'checkpoint_sha256': sha, 'epoch': integer(1, 128), + 'value': {'type': 'number'}, 'support': support}), 128, 1), + 'columns': array(columns, len(FIELDS), 1), + 'examples': obj({'rows': array(row, 100), 'population_support': support, + 'filtered_support': support, 'offset': integer(0, 10000), + 'limit': integer(1, 100), 'next_offset': nullable_offset, + 'filters': obj({'errors_only': {'type': 'boolean'}})}), + 'sampling': obj({'method': const('none'), 'population': const('frozen_validation_probe')}), + 'selection_sha256': sha}) + return request, result diff --git a/static/retained-analysis.js b/static/retained-analysis.js index 4617bba0..11475136 100644 --- a/static/retained-analysis.js +++ b/static/retained-analysis.js @@ -1,6 +1,10 @@ /* Host-owned renderer for one pinned Altair recipe. No dynamic chart plugins. */ (() => { 'use strict'; + window.WorkspaceRetainedContracts = Object.freeze({ + 'runs.retained_analysis/1': '8ec28793a0603b206cb720d0ece573793c474fed901fb8ce99133d0154526cd5', + 'runs.export_retained_analysis/1': '0994932e96aab5d9561a63e3447bb8ec1f6345607e247ddb5a9cadaccffc57fb' + }); const SPEC_PATH = '/static/retained-checkpoint-curve.vl.json'; const SPEC_SHA256 = '6603c860ce76a434a11e6c96cf7418246ce2dd5da3d7a56a5f2448a0537ec183'; const HASH = /^[a-f0-9]{64}$/; diff --git a/static/workspace-real.js b/static/workspace-real.js index 99b41fa4..2617c4a0 100644 --- a/static/workspace-real.js +++ b/static/workspace-real.js @@ -117,7 +117,12 @@ window.WorkspaceCoordinator = function ({api, render, identity=()=>window.Tuldok const publicationOperation=path[0]==='publication-results'?(path.length===1?'runs.publication_result':path[1]==='model-evidence'?'runs.publication_model_evidence':path[1]==='artifact-segment'?'runs.publication_artifact_chunk':null):path[0]==='runs'?({'publication':'runs.publication_status','recover-publication':'runs.recover_publication','cancel-publication':'runs.cancel_publication'})[path[2]]:null; const coordinatorOperation=path[0]==='coordinator'?(path.length===1?'runs.coordinator_health':path[1]==='recover'?'runs.recover_coordinator':null):null; const phaseOperation=path[0]==='runs'&&path[2]==='phase-timings'?'runs.phase_timings':path[0]==='graphs'&&path[2]==='preparation-timings'?'graphs.preparation_timings':null; - if(operation==='runs.compare_scientific_evidence'){ + const retainedOperation=path[0]==='runs'&&path[2]==='retained-analysis'?(path.length===3?'runs.retained_analysis':path.length===4&&path[3]==='export'?'runs.export_retained_analysis':null):null; + if(retainedOperation){ + const pin=window.WorkspaceRetainedContracts?.[retainedOperation+'/1']; + if(selectedVersion!==1||!pin)throw Error('The exact retained analysis contract is unavailable.'); + headers['Tuldok-Operation-Contract']=retainedOperation+'/1/'+pin; + } else if(operation==='runs.compare_scientific_evidence'){ const pin=window.WorkspaceScientificContracts?.[operation+'/1']; if(selectedVersion!==1||!pin)throw Error('The exact scientific comparison contract is unavailable.'); headers['Tuldok-Operation-Contract']=operation+'/1/'+pin; @@ -148,7 +153,7 @@ window.WorkspaceCoordinator = function ({api, render, identity=()=>window.Tuldok if (!sha) throw Error('This model operation has no supported local contract: ' + operation); headers['Tuldok-Operation-Contract'] = operation + '/' + version + '/' + sha; } - const controller=publicationOperation||coordinatorOperation||phaseOperation||operation==='runs.compare_scientific_evidence'?new AbortController():null; + const controller=retainedOperation||publicationOperation||coordinatorOperation||phaseOperation||operation==='runs.compare_scientific_evidence'?new AbortController():null; const deadline=controller?setTimeout(()=>controller.abort(),Math.min(75000,Math.max(1,timeout))):null; const abort=()=>controller?.abort(); if(requestSignal?.aborted)abort();else requestSignal?.addEventListener('abort',abort,{once:true}); @@ -156,9 +161,9 @@ window.WorkspaceCoordinator = function ({api, render, identity=()=>window.Tuldok const response = await (globalThis.TuldokAuth?.fetch || fetch)("/api/workspace/" + route, { ...(body === undefined ? {} : {method: "POST", body: JSON.stringify(body)}), headers, ...(controller?{signal:controller.signal}:{}), }); - if(publicationOperation||coordinatorOperation||phaseOperation||operation==='runs.compare_scientific_evidence'){ + if(retainedOperation||publicationOperation||coordinatorOperation||phaseOperation||operation==='runs.compare_scientific_evidence'){ const length=response.headers.get('Content-Length'); - if(!/^\d+$/.test(length||'')||Number(length)>(operation==='runs.compare_scientific_evidence'?2*1024**2:phaseOperation?48*1024:coordinatorOperation?16*1024:16*1024**2))throw Error('Selected response has no supported bounded length.'); + if(!/^\d+$/.test(length||'')||Number(length)>(retainedOperation?256*1024:operation==='runs.compare_scientific_evidence'?2*1024**2:phaseOperation?48*1024:coordinatorOperation?16*1024:16*1024**2))throw Error('Selected response has no supported bounded length.'); } const value = await response.json(); if (!response.ok) { @@ -182,6 +187,11 @@ window.WorkspaceCoordinator = function ({api, render, identity=()=>window.Tuldok onImported:openImportedRecord,observePreparation:restart=>observePreparation(restart), onRun:result=>{run=result;runId=result.id;predictions=null;predictionError=null;remember();status("External attempt admitted with exact material approval.");openRun();}}); const model = WorkspaceModel({api, announce, openRecord, getIntent:()=>loadGeneration, getView:()=>view, + onAccessFailure:(error,id,credential)=>{ + const currentCredential=window.TuldokAuth?.identity()?.credential_id; + if(view!=='runs'||runId!==id||currentCredential&¤tCredential!==credential)return; + ++runGeneration;run=null;runs=[];predictions=null;model.invalidate();fieldEvidence.invalidate();scientific.invalidate();candidatePackages.invalidate();publication.invalidate();coordinator.invalidate();phases.invalidate();preparation.invalidate();renderRuns();status(error.message,true); + }, openRun:result=>{run=result;runId=result.id;remember();if(view==='runs')loadRuns(runId);else openRun();}}); const publication = window.WorkspacePublication({api,render:()=>{if(view==='runs')renderRuns();}}); const coordinator = window.WorkspaceCoordinator({api,render:renderCoordinator}); @@ -469,6 +479,7 @@ window.WorkspaceCoordinator = function ({api, render, identity=()=>window.Tuldok if (id) { try { detail = await api("runs/" + encoded(id)); } catch (error) { + if ([401,403].includes(error.status)) throw error; // The list's durable receipt remains useful when verifying its // artifacts fails. Keep other runs reachable; never trust cached // metrics or offer artifacts from the failed detail read. @@ -483,7 +494,7 @@ window.WorkspaceCoordinator = function ({api, render, identity=()=>window.Tuldok } if (detail?.state === "completed" && !integrityKind(detail.graph) && !external.isGraph(detail.graph) && !detail.artifact_status) { try { rows = await api("runs/" + encoded(id) + "/predictions?split=" + split); } - catch (error) { rowsError = error.message; } + catch (error) { if ([401,403].includes(error.status)) throw error; rowsError = error.message; } } if (!current()) return; await model.load(detail,current); @@ -500,8 +511,14 @@ window.WorkspaceCoordinator = function ({api, render, identity=()=>window.Tuldok packageRead.then(()=>{if(current())renderRuns();}); coordinatorRead.then(()=>{if(current())renderCoordinator();}); } catch (error) { - if (!current()) return; - if ([401,403].includes(error.status)) {run=null;runs=[];predictions=null;model.invalidate();fieldEvidence.invalidate();scientific.invalidate();candidatePackages.invalidate();publication.invalidate();coordinator.invalidate();phases.invalidate();preparation.invalidate();renderRuns();status(error.message,true);return;} + // A denied fetch may already have cleared the session identity. It must + // still clear this generation's private DOM, while an old credential's + // late denial cannot invalidate a newer session or navigation. + const credential=window.TuldokAuth?.identity()?.credential_id; + const denied=[401,403].includes(error.status); + const currentDenial=denied&&generation===runGeneration&&view==='runs'&&(!credential||credential===session); + if (!current()&&!currentDenial) return; + if (denied) {++runGeneration;run=null;runs=[];predictions=null;model.invalidate();fieldEvidence.invalidate();scientific.invalidate();candidatePackages.invalidate();publication.invalidate();coordinator.invalidate();phases.invalidate();preparation.invalidate();renderRuns();status(error.message,true);return;} if (!quiet) {runsRoot.innerHTML = `
${coordinator.html()}
`;coordinator.bind(runsRoot);coordinatorRead.then(()=>{if(current())renderCoordinator();});} else status("Run refresh failed: " + error.message + " Saved results are retained; use Refresh to retry.", true); runsRoot.querySelector("#real-runs-retry")?.addEventListener("click", () => loadRuns(chosen)); diff --git a/static/workspace-service.js b/static/workspace-service.js index 64617ab6..772361d3 100644 --- a/static/workspace-service.js +++ b/static/workspace-service.js @@ -676,15 +676,52 @@ const packages=state.packages||[],verified=state.state==='fresh_verified'; return `

Package: ${packages.length?'complete':'not exported'}. Fresh inference: ${verified?'verified in a separate consumer Run':'not verified'}.

${packages.map(item=>`

Download verified package · ${esc(item.bytes.toLocaleString())} bytes · SHA256 ${esc(item.sha256)}
Completed package Run ${esc(item.run_id)}

`).join('')}${verified?'

Fresh inference reproduced the retained fixed probes. The candidate remains diagnostic.

':''}${(state.verifications||[]).map(item=>`

Separate fresh verifier Run ${esc(item.run_id)} · package ${esc(item.receipt.package_sha256)}

`).join('')}${state.verifications?.length?`
Fresh consumer verification receipts
${esc(JSON.stringify(state.verifications,null,2))}
`:''}
`; }; - window.WorkspaceModel = function ({api, announce, openRun, openRecord, getIntent, getView}) { + window.WorkspaceModel = function ({api:transport, announce, openRun, openRecord, getIntent, getView, onAccessFailure=()=>{}}) { let definition = null, releases = [], studies = [], root = null, busy = false, message = '', failed = false, evidence = null, evidenceError = '', comparison = null, checkpoint = null, probe = null, compareId = '', generation = 0, queryIntent = 0, detailPredictions = null, studyDetail = null, candidate = null, candidateBusy = false, candidateError = '', foreignPending = false, compareTarget = null, compareTargetRun = null, compareCheckpoint = '', compareMetric = '', compareMode = 'paired', compareBusy = false, compareIntent = 0, compareTargetIntent = 0, checkpointBusy = false, checkpointIntent = 0, packageState = null, packageError = '', exportSetup = null, exportJob = null, exportBusy = false, exportDraft = {mode:'package',root:'',directory:'',runtime:'',packageRun:''}; let pendingComparison=null; + let retainedView=null,activeRun=null; let config = {name: 'TinyCNN experiment', release: '', widths: [16,32,64], input_size: 96, epochs: 3, seed: 17}; let journal = history.state?.modelTrial || null; const identity = () => window.TuldokAuth?.identity(); const owner = () => identity()?.kind === 'owner'; + // Denials must reach the Runs owner before local presentation catches can + // absorb them, including after auth.js clears a revoked session identity. + async function api(...args){ + const runId=activeRun,credential=identity()?.credential_id,version=generation; + try{return await transport(...args);} + catch(error){ + if(runId&&activeRun===runId&&version===generation&&!args[4]?.aborted&&[401,403].includes(error.status))onAccessFailure(error,runId,credential); + throw error; + } + } + function disposeRetained(){retainedView?.dispose();retainedView=null;} + function retainedHTML(run){ + return run?.graph?.recipe===recipe&&run.state==='completed'&&evidence?.state==='verified'&& + evidence.metric_definition_hashes?.accuracy&&run.artifacts?.some(item=>item.name==='model-evidence.json')? + '
':''; + } + function bindRetained(node,run,current){ + disposeRetained(); + const target=node.querySelector('[data-retained-analysis]'); + if(!target||!current()||!retainedHTML(run))return; + if(!window.WorkspaceRetainedAnalysis){target.textContent='Retained chart assets are unavailable. Refresh to retry.';return;} + const artifact=run.artifacts.find(item=>item.name==='model-evidence.json'); + const selected=evidence.checkpoint_index.entries.find(item=>item.checkpoint.sha256===checkpoint)||evidence.checkpoint_index.entries[0]; + const authority=JSON.stringify([identity()?.catalog_id,identity()?.actor_id,identity()?.credential_id]); + const valid=()=>current()&&authority===JSON.stringify([identity()?.catalog_id,identity()?.actor_id,identity()?.credential_id]); + retainedView=window.WorkspaceRetainedAnalysis.mount(target,{load:async(request,options)=>{ + if(!valid())throw Error('Retained result authority changed.'); + const {run_id,...body}=request; + const value=await api('runs/'+enc(run_id)+'/retained-analysis'+(options.export?'/export':''),body,1,10000,options.signal); + if(!valid())throw Error('Retained result authority changed.'); + return value; + }}); + void retainedView.update({query_id:'retained_checkpoint_examples',query_version:1,run_id:run.id, + evaluation_sha256:artifact.sha256,checkpoint_sha256:selected.checkpoint.sha256, + metric_id:'accuracy',metric_definition_sha256:evidence.metric_definition_hashes.accuracy,limit:1,offset:0},authority); + } const remember = () => history.replaceState({...history.state, modelTrial: journal}, ''); function notice(text, error = false) { message = text; failed = error; announce(text,error); } function scope() { @@ -791,8 +828,9 @@ sessionChanged() {pendingComparison=null;studies=[];studyDetail=null;message='';exportDraft={mode:'package',root:'',directory:'',runtime:'',packageRun:''};config={name:'TinyCNN experiment',release:'',widths:[16,32,64],input_size:96,epochs:3,seed:17};const saved=history.state?.modelTrial;foreignPending=!!(saved&&saved.actor!==identity()?.actor_id&&(saved.admission||saved.uncertain));if(journal?.actor!==identity()?.actor_id)journal=null;}, mount(node) {root=node;render();}, async refresh(current) {try{const result=await api('studies');if(current())studies=result.studies;}catch(error){if(current())notice('Saved studies unavailable: '+error.message,true);}}, - invalidate(preserveComparison=false) {if(!preserveComparison)pendingComparison=null;generation++;queryIntent++;compareIntent++;compareTargetIntent++;checkpointIntent++;checkpointBusy=false;evidence=null;comparison=null;checkpoint=null;probe=null;evidenceError='';detailPredictions=null;candidate=null;candidateError='';compareTarget=null;compareTargetRun=null;compareCheckpoint='';compareBusy=false;packageState=null;packageError='';exportSetup=null;exportJob=null;}, + invalidate(preserveComparison=false) {activeRun=null;disposeRetained();if(!preserveComparison)pendingComparison=null;generation++;queryIntent++;compareIntent++;compareTargetIntent++;checkpointIntent++;checkpointBusy=false;evidence=null;comparison=null;checkpoint=null;probe=null;evidenceError='';detailPredictions=null;candidate=null;candidateError='';compareTarget=null;compareTargetRun=null;compareCheckpoint='';compareBusy=false;packageState=null;packageError='';exportSetup=null;exportJob=null;}, async load(run,current) { + disposeRetained();activeRun=run?.id||null; if(pendingComparison&&(pendingComparison.runId!==run?.id||pendingComparison.credential!==identity()?.credential_id))pendingComparison=null; const intent=++queryIntent;compareIntent++;compareTargetIntent++;checkpointIntent++;checkpointBusy=false; evidence=null;comparison=null;evidenceError='';candidate=null;candidateError='';packageState=null;packageError='';exportJob=null;compareTarget=null;compareTargetRun=null;compareCheckpoint='';compareId='';compareBusy=false; @@ -805,8 +843,8 @@ } evidence=value; const savedCandidate=history.state?.modelCandidates?.[run.id]; - if(savedCandidate?.actor===identity()?.actor_id){try{const saved=await api('candidates/'+enc(savedCandidate.id));if(current()&&intent===queryIntent){candidate=saved;await loadPackage(saved,current,intent);}}catch(error){if(current()&&intent===queryIntent)candidateError=error.message;}} - }catch(error){if(current()&&intent===queryIntent)evidenceError=error.message;} + if(savedCandidate?.actor===identity()?.actor_id){try{const saved=await api('candidates/'+enc(savedCandidate.id));if(current()&&intent===queryIntent){candidate=saved;await loadPackage(saved,current,intent);}}catch(error){if([401,403].includes(error.status))throw error;if(current()&&intent===queryIntent)candidateError=error.message;}} + }catch(error){if([401,403].includes(error.status))throw error;if(current()&&intent===queryIntent)evidenceError=error.message;} }, html(run,predictions) { detailPredictions=predictions; @@ -814,9 +852,9 @@ if(evidenceError)return `

Model evidence unavailable

No cached checkpoint or probe values are shown. Refresh saved runs to retry.

`; if(!evidence)return '

Model evidence has not been published yet.

'; if(evidence.state==='unsupported')return `

${esc(evidence.reason)}

`; - return evidenceHTML(evidence,run); + return evidenceHTML(evidence,run)+retainedHTML(run); }, - bind(node,run,runs,rerender,current) {bindEvidence(node,run,runs,rerender,current);}, + bind(node,run,runs,rerender,current) {bindEvidence(node,run,runs,rerender,current);bindRetained(node,run,current);}, }; function evidenceHTML(value,run) { // Index and checkpoint/probe projections are supplied by the same Runs query. @@ -846,7 +884,7 @@ const saved=history.state?.modelExports?.[value.ref.id];exportJob=saved?.actor===identity()?.actor_id?saved:null; if(!contracts['studies.package_state'])return; try{const state=await api('candidates/'+enc(value.ref.id)+'/package-state');if(!current()||intent!==queryIntent)return;packageState=state;} - catch(error){if(current()&&intent===queryIntent)packageError=error.message;} + catch(error){if([401,403].includes(error.status))throw error;if(current()&&intent===queryIntent)packageError=error.message;} } function exportHTML() { if(!contracts['studies.package_state'])return '

Package preparation is unavailable in this installed interface. No package or fresh verification is claimed.

'; diff --git a/static/workspaces.css b/static/workspaces.css index c5cfb282..cfd02034 100644 --- a/static/workspaces.css +++ b/static/workspaces.css @@ -1158,3 +1158,10 @@ details > p { .scientific-comparison th:first-child { white-space:normal; overflow-wrap:anywhere; min-width:10rem; max-width:24rem; } .scientific-comparison details { margin:12px 0; } .scientific-comparison input { max-width:100%; } +.retained-analysis { min-width:0; max-width:100%; margin-block:1rem; } +.retained-analysis > div { min-width:0; max-width:100%; } +.retained-analysis table { width:100%; table-layout:fixed; border-collapse:collapse; font-size:.8rem; } +.retained-analysis th,.retained-analysis td { padding:.4rem; vertical-align:top; overflow-wrap:anywhere; border-bottom:1px solid var(--line,#b6bfcb); } +.retained-analysis pre { white-space:pre-wrap; overflow-wrap:anywhere; } +.retained-analysis button { max-width:100%; margin:.25rem; white-space:normal; } +.retained-analysis button:focus-visible,.retained-analysis input:focus-visible { outline:3px solid var(--accent,#fbbf24); outline-offset:2px; } diff --git a/static/workspaces.html b/static/workspaces.html index 733346cc..b299d345 100644 --- a/static/workspaces.html +++ b/static/workspaces.html @@ -3,6 +3,7 @@ + Tuldok · Dataset workspaces @@ -24,7 +25,7 @@
CONTEXT @@ -133,6 +134,11 @@

Unsaved fixture edits

+ + + + + diff --git a/tests/browser_retained_analysis_actual.cjs b/tests/browser_retained_analysis_actual.cjs index 6a882b58..aec6388a 100644 --- a/tests/browser_retained_analysis_actual.cjs +++ b/tests/browser_retained_analysis_actual.cjs @@ -1,4 +1,4 @@ -// Prepared authenticated Runs acceptance. Requires the coordinated production hooks. +// Authenticated Runs acceptance over the production hooks and scoped CSP. // Uses the existing retained fixture and normal app.py; no handler/data substitutes. 'use strict'; const assert = require('node:assert/strict'), fs = require('node:fs'), os = require('node:os'), path = require('node:path'); @@ -19,7 +19,7 @@ async function stop(child) { if (process.env.TULDOK_ANALYSIS_HTTP !== '1' || !process.env.TULDOK_ANALYSIS_FIXTURE) throw Error('Explicit integrated acceptance and a prepared actual retained fixture are required.'); const fixture = JSON.parse(fs.readFileSync(path.join(process.env.TULDOK_ANALYSIS_FIXTURE, 'fixture.json'), 'utf8')); let output = '', serverErrors = ''; - const server = spawn(process.env.PYTHON || 'python3', ['-u', 'app.py', '--port', '0', '--data', fixture.catalog_path], {cwd: root}); children.push(server); + let server = spawn(process.env.PYTHON || 'python3', ['-u', 'app.py', '--port', '0', '--data', fixture.catalog_path], {cwd: root}); children.push(server); server.stdout.on('data', chunk => output += chunk); server.stderr.on('data', chunk => serverErrors += chunk); await until(() => /127\.0\.0\.1:(\d+)/.test(output), 'Actual app did not publish its local endpoint'); const base = 'http://127.0.0.1:' + output.match(/127\.0\.0\.1:(\d+)/)[1]; @@ -44,13 +44,15 @@ async function stop(child) { const targets = await (await fetch(`http://127.0.0.1:${debuggerPort}/json`)).json(); const ws = new WebSocket(targets.find(item => item.type === 'page').webSocketDebuggerUrl); await new Promise(resolve => ws.addEventListener('open', resolve)); - let sequence = 0, held; const calls = new Map(), errors = [], remote = [], actualReplies = []; + let sequence = 0, held, aborted=0; const calls = new Map(), errors = [], remote = [], actualReplies = [], urls = new Map(); const send = (method, params = {}) => new Promise((resolve, reject) => { const id = ++sequence; calls.set(id, {resolve, reject}); ws.send(JSON.stringify({id, method, params})); }); ws.addEventListener('message', event => { const value = JSON.parse(event.data); if (value.id) { const pending = calls.get(value.id); calls.delete(value.id); value.error ? pending.reject(Error(JSON.stringify(value.error))) : pending.resolve(value.result); } if (value.method === 'Runtime.exceptionThrown') errors.push(value.params.exceptionDetails.text); if (value.method === 'Network.requestWillBeSent' && /^https?:/.test(value.params.request.url) && !value.params.request.url.startsWith(base)) remote.push(value.params.request.url); + if (value.method === 'Network.requestWillBeSent') urls.set(value.params.requestId,value.params.request.url); + if (value.method === 'Network.loadingFailed' && value.params.canceled && urls.get(value.params.requestId)?.endsWith('/retained-analysis')) aborted++; if (value.method === 'Fetch.requestPaused') held = value.params; if (value.method === 'Network.responseReceived' && value.params.response.url.endsWith('/retained-analysis')) actualReplies.push(value.params.response.status); }); @@ -62,13 +64,21 @@ async function stop(child) { const host = '([...document.querySelectorAll("#real-runs-root h3")].find(node=>node.textContent==="Retained checkpoint analysis")?.parentElement)'; const ready = () => evaluate(`!!${host}?.querySelector('svg') && ${host}?.getAttribute('aria-busy')==='false'`); await send('Runtime.enable'); await send('Network.enable'); await send('Page.enable'); + await send('Page.addScriptToEvaluateOnNewDocument',{source:"window.retainedCSPViolations=[];document.addEventListener('securitypolicyviolation',event=>window.retainedCSPViolations.push(event.violatedDirective));"}); await fixtureAuth.browser(send, base); await send('Page.navigate', {url: base + '/workspaces'}); - await until(() => evaluate('!!document.querySelector("#dataset") && !document.querySelector("#dataset").disabled')); + await until(() => evaluate('!!document.querySelector("#fixture-label") && !document.querySelector("#dataset").disabled')); await evaluate('document.querySelector("#dataset").value="catalog";document.querySelector("#dataset").dispatchEvent(new Event("change",{bubbles:true}))'); - await until(() => evaluate('document.querySelector("#notice")?.textContent==="Collection ready."')); + await until(() => evaluate('document.querySelector("#dataset")?.value==="catalog" && !!document.querySelector("#catalog-frame")?.contentWindow?.TuldokWorkspaceData')).catch(async error => { + throw Error(error.message+' '+JSON.stringify(await evaluate('({notice:document.querySelector("#notice")?.textContent,select:document.querySelector("#dataset")?.value,frame:document.querySelector("#catalog-frame")?.src,body:document.body.textContent.slice(0,1000)})'))+' errors='+JSON.stringify(errors)+' server='+serverErrors.slice(-2000)); + }); await evaluate('document.querySelector("#nav-runs").click()'); await until(ready, 'Actual authenticated Runs did not mount the retained renderer'); + assert.match(await evaluate(`document.querySelector('meta[http-equiv="Content-Security-Policy"]').content`), /script-src 'self';/); + assert.deepEqual(await evaluate('window.retainedCSPViolations'),[]); + const cspProbe=await send('Runtime.evaluate',{expression:"(()=>{try{new Function('return 1')();return false}catch(error){return error instanceof EvalError}})()",returnByValue:true,allowUnsafeEvalBlockedByCSP:false}); + assert.equal(cspProbe.result.value,true,'Ordinary runtime code generation must be blocked by the deployed CSP'); + await evaluate('window.retainedCSPViolations=[]'); for (const point of expected.curve) assert.ok((await evaluate(`${host}.textContent`)).includes(`Epoch ${point.epoch}: ${point.value}`)); await evaluate(`${host}.querySelectorAll('button')[0].focus()`); await send('Input.dispatchKeyEvent', {type: 'keyDown', key: 'Enter', code: 'Enter', text: '\r', windowsVirtualKeyCode: 13}); @@ -82,15 +92,63 @@ async function stop(child) { await evaluate(`${host}.querySelectorAll('button')[1].click()`); await until(() => !!held, 'Expected an actual retained query response to pause'); await evaluate('document.querySelector("#nav-data").click()'); - await send('Fetch.continueRequest', {requestId: held.requestId}); await send('Fetch.disable'); held = null; + try{await send('Fetch.continueRequest', {requestId: held.requestId});} + catch(error){if(!error.message.includes('Invalid InterceptionId'))throw error;await until(()=>aborted>0,'Obsolete request did not report cancellation');} + await send('Fetch.disable'); held = null; await pause(100); assert.equal(await evaluate('document.querySelector("#view-runs").hidden'), true); await evaluate('document.querySelector("#nav-runs").click()'); await until(ready); + const downloadPath=path.join(profile,'downloads');fs.mkdirSync(downloadPath); + await send('Browser.setDownloadBehavior',{behavior:'allow',downloadPath}); + await evaluate(`[...${host}.querySelectorAll('button')].find(button=>button.textContent==='Export this page').click()`); + await until(()=>fs.existsSync(path.join(downloadPath,'retained-analysis-page.json')),'Actual authorized export did not download'); + const exported=JSON.parse(fs.readFileSync(path.join(downloadPath,'retained-analysis-page.json'),'utf8')); + assert.equal(exported.provenance.evaluation_sha256,fixture.request.evaluation_sha256); + assert.deepEqual(exported.curve,expected.curve); + const credential=await evaluate('TuldokAuth.identity().credential_id'); + const ownerToken=fs.readFileSync(path.join(process.env.TULDOK_ANALYSIS_FIXTURE,'owner-token'),'utf8'); + const revoked=await fetch(base+'/api/access/credentials/'+credential+'/revoke',{method:'POST',headers:{Authorization:'Bearer '+ownerToken,Origin:base,'Content-Type':'application/json'},body:'{}'}); + assert.equal(revoked.status,200); + await evaluate(`[...${host}.querySelectorAll('button')].find(button=>button.textContent==='Export this page').click()`); + await until(()=>evaluate('!document.querySelector("#real-runs-root [data-retained-analysis]") && !document.querySelector("#real-runs-root .metric-grid")'),'Revoked export did not clear private Run content'); + const reauth=require('./auth_helpers.cjs').authenticatedFixture();await reauth.register(base,fixture.catalog_path,root);await reauth.browser(send,base); + // Reopen the same catalog in a fresh application process, then reload the + // real browser with the newly authenticated retained session and exact result. + await stop(server); + let restarted='';server=spawn(process.env.PYTHON||'python3',['-u','app.py','--port',new URL(base).port,'--data',fixture.catalog_path],{cwd:root});children.push(server); + server.stdout.on('data',chunk=>restarted+=chunk);server.stderr.on('data',chunk=>serverErrors+=chunk); + await until(()=>restarted.includes(base),'Cold application process did not reopen the retained catalog'); await send('Page.reload', {ignoreCache: true}); await until(ready); for (const point of expected.curve) assert.ok((await evaluate(`${host}.textContent`)).includes(`Epoch ${point.epoch}: ${point.value}`)); + // Denial during each ordinary Run read must clear previously rendered private + // content even when auth.js has already set its current identity to null. + for(const suffix of ['', '/predictions?split=validation', '/model-evidence']){ + await send('Fetch.enable',{patterns:[{urlPattern:base+'/api/workspace/runs/'+fixture.run_id+suffix,requestStage:'Request'}]}); + await evaluate('document.querySelector("#real-runs-refresh").click()'); + await until(()=>!!held,'Ordinary Run read did not pause: '+suffix); + const deniedCredential=await evaluate('TuldokAuth.identity().credential_id'); + const deny=await fetch(base+'/api/access/credentials/'+deniedCredential+'/revoke',{method:'POST',headers:{Authorization:'Bearer '+ownerToken,Origin:base,'Content-Type':'application/json'},body:'{}'}); + assert.equal(deny.status,200); + await send('Fetch.continueRequest',{requestId:held.requestId});held=null;await send('Fetch.disable'); + await until(()=>evaluate('!TuldokAuth.identity() && !document.querySelector("#real-runs-root [data-retained-analysis]") && !document.querySelector("#real-runs-root .metric-grid")'),'Denied ordinary read retained private Run content: '+suffix); + const nextAuth=require('./auth_helpers.cjs').authenticatedFixture();await nextAuth.register(base,fixture.catalog_path,root);await nextAuth.browser(send,base); + await send('Page.reload',{ignoreCache:true});await until(ready); + } + await send('Fetch.enable',{patterns:[{urlPattern:base+'/api/workspace/runs/'+fixture.run_id+'/model-evidence',requestStage:'Request'}]}); + await evaluate('document.querySelectorAll("[data-model-checkpoint]")[0].click()'); + await until(()=>!!held,'Existing checkpoint action did not dispatch its exact read'); + // The checkpoint action rerenders and starts a fresh retained query; let that + // succeed first so its authorization failure cannot mask the old action's. + await until(ready); + const checkpointCredential=await evaluate('TuldokAuth.identity().credential_id'); + const checkpointDenied=await fetch(base+'/api/access/credentials/'+checkpointCredential+'/revoke',{method:'POST',headers:{Authorization:'Bearer '+ownerToken,Origin:base,'Content-Type':'application/json'},body:'{}'}); + assert.equal(checkpointDenied.status,200); + await send('Fetch.continueRequest',{requestId:held.requestId});held=null;await send('Fetch.disable'); + await until(()=>evaluate('!TuldokAuth.identity() && !document.querySelector("#real-runs-root [data-retained-analysis]") && !document.querySelector("#real-runs-root .metric-grid")'),'Denied checkpoint action retained private Run content'); + assert.deepEqual(await evaluate('window.retainedCSPViolations'),[]); assert.deepEqual(errors, []); assert.deepEqual(remote, []); assert.ok(actualReplies.includes(200)); - console.log(JSON.stringify({status: 'passed', evidence: 'actual-PostgreSQL-native-Run-authenticated-Runs-browser', run_id: fixture.run_id, evaluation_sha256: fixture.request.evaluation_sha256, exact_curve: expected.curve, checks: ['actual named query', 'retained numeric oracle', 'linked keyboard example table', '390px layout', 'held real response after navigation', 'cache-bypassed page reopen', 'local chart assets']}, null, 2)); + console.log(JSON.stringify({status: 'passed', evidence: 'actual-PostgreSQL-native-Run-authenticated-Runs-browser', run_id: fixture.run_id, evaluation_sha256: fixture.request.evaluation_sha256, exact_curve: expected.curve, checks: ['actual named query', 'retained numeric oracle', 'linked keyboard example table', '390px layout', 'held real response cancellation after navigation', 'authorized exact JSON export', 'real credential revocation clears private Run content', 'fresh application process and cache-bypassed page reopen', 'local chart assets', 'deployed script CSP blocks runtime code generation', 'actual denial during detail/predictions/model-evidence clears private Run content', 'held existing checkpoint action denial clears already-authorized retained view']}, null, 2)); ws.close(); })().catch(error => { console.error(error); process.exitCode = 1; }).finally(async () => { for (const child of children.reverse()) await stop(child); diff --git a/tests/test_retained_analysis_contracts.py b/tests/test_retained_analysis_contracts.py new file mode 100644 index 00000000..14d89c80 --- /dev/null +++ b/tests/test_retained_analysis_contracts.py @@ -0,0 +1,47 @@ +"""Retained query contract closure and compatibility without a database.""" +import hashlib +import json +from pathlib import Path +import re +import sys +import unittest + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT)) +import agent_api + + +class RetainedAnalysisContractTests(unittest.TestCase): + def test_registry_and_existing_contract_bytes_are_unchanged(self): + agent_api.validate_registry() + baseline = json.loads((ROOT / 'tests/fixtures/agent_contract_hashes_phase5a1feac.json').read_text()) + for name, versions in baseline['contracts'].items(): + for version, digest in versions.items(): + self.assertEqual(hashlib.sha256(agent_api.encoded(agent_api.contract(name, int(version)))).hexdigest(), digest) + self.assertEqual(hashlib.sha256(agent_api.encoded(agent_api.discovery())).hexdigest(), baseline['legacy_discovery_sha256']) + + def test_new_inspect_contracts_match_browser_pins(self): + source = (ROOT / 'static/retained-analysis.js').read_text() + for name in ('runs.retained_analysis', 'runs.export_retained_analysis'): + contract = agent_api.contract(name, 1) + pin = re.search("'" + re.escape(name) + "/1': '([a-f0-9]{64})'", source) + self.assertIsNotNone(pin) + self.assertEqual(pin[1], contract['sha256']) + self.assertEqual(contract['scopes'], ['inspect']) + self.assertEqual(contract['effects'], 'read') + + def test_closed_bounded_arguments(self): + arguments = dict(query_id='retained_checkpoint_examples', query_version=1, + run_id='a'*32, evaluation_sha256='b'*64, checkpoint_sha256='c'*64, + metric_id='accuracy', metric_definition_sha256='d'*64) + for name in ('runs.retained_analysis', 'runs.export_retained_analysis'): + agent_api.validate_arguments(name, arguments, version=1) + for changes in ({'sql': 'select 1'}, {'limit': 101}, {'offset': -1}, + {'fields': ['confidence']}, {'fields': ['example_id', 'example_id']}, + {'errors_only': 1}, {'query_version': 2}): + with self.subTest(name=name, changes=changes), self.assertRaises(agent_api.AgentAPIError): + agent_api.validate_arguments(name, dict(arguments, **changes), version=1) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_retained_analysis_http.py b/tests/test_retained_analysis_http.py index fe9b11bb..6fd336fe 100644 --- a/tests/test_retained_analysis_http.py +++ b/tests/test_retained_analysis_http.py @@ -13,6 +13,7 @@ import unittest from urllib.error import HTTPError from urllib.request import Request, urlopen +from jsonschema import Draft202012Validator ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)) @@ -81,6 +82,8 @@ def test_authenticated_http_and_export_equal_real_query(self): status, value = self.request(export=export) self.assertEqual(status, 200) self.assertEqual(value, expected) + name = 'runs.export_retained_analysis' if export else 'runs.retained_analysis' + Draft202012Validator(self.contracts[name]['output_schema']).validate({'status': status, 'result': value}) self.assertLessEqual(len(value['examples']['rows']), 1) self.assertNotIn('probabilities', value['examples']['rows'][0]) @@ -97,7 +100,7 @@ def test_closed_request_rejects_sql_and_holdout_without_exposure(self): for body in ({'sql': 'SELECT arbitrary_data'}, {'split': 'test'}, {'limit': 101}): with self.subTest(body=body): status, value = self.request(body=body) - self.assertEqual((status, value['code']), (409, 'contract_mismatch')) + self.assertEqual((status, value['code']), (400, 'invalid')) self.assertNotIn('examples', value) with self.dataset.access.bind(self.token): self.assertFalse(self.dataset.runs.get(self.receipt['run_id'])['test_exposure']['exposed']) diff --git a/tests/test_workspace_model_controller.cjs b/tests/test_workspace_model_controller.cjs index 5a516a7b..fe58ff59 100644 --- a/tests/test_workspace_model_controller.cjs +++ b/tests/test_workspace_model_controller.cjs @@ -6,19 +6,33 @@ const deferred=()=>{let resolve,reject;const promise=new Promise((yes,no)=>{reso const entry=(epoch,sha)=>({checkpoint:{sha256:sha,name:'checkpoint-'+epoch+'.json'},clocks:{epoch},selected:epoch===2,state:'retained'}); const value=(sha='b')=>({state:'verified',manifest:{producer:{run_id:'run'}},checkpoint_index:{entries:[entry(1,'a'),entry(2,'b')]},probe:{members:[{ordinal:0,frozen_reference:{id:'example',revision:3,source_revision:1}}]},observations:[{checkpoint_sha256:sha,metric_id:'accuracy',value:0,state:'observed'}],checkpoint:{clocks:{epoch:sha==='a'?1:2,optimizer_update:2,wall_elapsed_ms:50},weights:{name:'weights-'+sha+'.pt'}},predictions:{rows:[{ordinal:0,truth_index:0,predicted_index:1,probabilities:[0.2,0.8]}]}}); function fixture(){ - const calls=[],notes=[],opened=[];let handler,view='runs',intent=0,actor={kind:'owner',actor_id:'owner',credential_id:'one'}; + const calls=[],notes=[],opened=[],failures=[];let handler,view='runs',intent=0,actor={kind:'owner',actor_id:'owner',credential_id:'one'}; const nodes={},buttons=[{dataset:{modelCheckpoint:'a'}},{dataset:{modelCheckpoint:'b'}}]; const node=id=>nodes[id]||(nodes[id]={value:'example',addEventListener(type,fn){this[type]=fn;}}); const root={querySelector:node,querySelectorAll:selector=>selector==='[data-model-checkpoint]'?buttons:[]}; const window={workspaceEscape:value=>String(value??'').replaceAll('<','<'),TuldokAuth:{identity:()=>actor}}; const context={window,history:{state:{},replaceState(value){this.state=value;}},structuredClone,crypto:globalThis.crypto,CSS:{escape:String},document:{activeElement:null}}; vm.runInNewContext(source,context); - const ui=window.WorkspaceModel({api:async(route,body)=>{calls.push({route,body});return handler(route,body);},announce:text=>notes.push(text),openRun:()=>{},openRecord:value=>opened.push(value),getView:()=>view,getIntent:()=>intent}); + const ui=window.WorkspaceModel({api:async(route,body)=>{calls.push({route,body});return handler(route,body);},announce:text=>notes.push(text),openRun:()=>{},openRecord:value=>opened.push(value),getView:()=>view,getIntent:()=>intent,onAccessFailure:(...args)=>failures.push(args)}); const run={id:'run',state:'completed',graph:{recipe:'image_classification_model_v2'},metrics:{class_vocabulary:[{label:'circle'},{label:'square'}]}}; let rendered='';const render=()=>{rendered=ui.html(run);ui.bind(root,run,[],render,()=>view==='runs');}; - return {ui,run,calls,notes,opened,nodes,buttons,history:context.history,render,html:()=>rendered,handler:fn=>handler=fn,navigate(){view='pipeline';intent++;ui.invalidate();},session(){actor=null;ui.invalidate();ui.sessionChanged();}}; + return {ui,run,calls,notes,opened,failures,nodes,buttons,expired(){actor=null;},history:context.history,render,html:()=>rendered,handler:fn=>handler=fn,navigate(){view='pipeline';intent++;ui.invalidate();},session(){actor=null;ui.invalidate();ui.sessionChanged();}}; } (async()=>{ + for(const status of [401,403]){ + const denied=fixture(),failure=Object.assign(Error('Current access denied'),{status}); + denied.handler(async()=>{throw failure;}); + await assert.rejects(denied.ui.load(denied.run,()=>true),error=>error===failure, + 'Model evidence denial must reach the Runs owner before detail/predictions can commit'); + assert.doesNotMatch(denied.ui.html(denied.run),/Linked epoch evidence/); + } + for(const change of ['expired','navigate','session']){ + const late=fixture();late.handler(async(route,body)=>value(body.checkpoint_sha256||'b'));await late.ui.load(late.run,()=>true);late.render(); + const held=deferred();late.handler(()=>held.promise);const loading=late.buttons[0].onclick();late[change](); + held.reject(Object.assign(Error('Denied checkpoint'),{status:401}));await loading; + assert.equal(late.failures.length,change==='expired'?1:0,'Only a current model generation reports denial after '+change); + if(change==='expired'){assert.equal(late.failures[0][1],'run');assert.equal(late.failures[0][2],'one');} + } const f=fixture();f.handler(async(route,body)=>value(body.checkpoint_sha256||'b'));await f.ui.load(f.run,()=>true);f.render(); assert.match(f.html(),/Linked epoch evidence/);assert.match(f.html(),/circle/);assert.match(f.html(),/square/);assert.match(f.html(),/>0\.0000<\/td>/,'Observed zero remains zero'); assert.match(f.ui.html({graph:{recipe:'image_classification'}}),/was not captured/); From d161d244270f10128c171ca6d4ecca52faac9274 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Oct 2026 02:37:53 +0000 Subject: [PATCH 4/8] test: qualify Runs denial recovery in CPU browser --- .../ci-qualification-20261020/acceptance.md | 58 ++ .../corrected-evidence-1440.jpg | Bin 0 -> 97692 bytes .../corrected-evidence-390.jpg | Bin 0 -> 55828 bytes .../model-controller.log | 1 + .../model-development.log | 14 + .../original-failures.json | 132 +++++ .../qualification.json | 62 ++ .../ci-qualification-20261020/receipt.json | 528 ++++++++++++++++++ .../schema-cleanup.json | 25 + .../schema-reservation.json | 8 + tests/browser_model_development.cjs | 17 +- 11 files changed, 839 insertions(+), 6 deletions(-) create mode 100644 docs/plans/retained-analysis/reports/ci-qualification-20261020/acceptance.md create mode 100644 docs/plans/retained-analysis/reports/ci-qualification-20261020/corrected-evidence-1440.jpg create mode 100644 docs/plans/retained-analysis/reports/ci-qualification-20261020/corrected-evidence-390.jpg create mode 100644 docs/plans/retained-analysis/reports/ci-qualification-20261020/model-controller.log create mode 100644 docs/plans/retained-analysis/reports/ci-qualification-20261020/model-development.log create mode 100644 docs/plans/retained-analysis/reports/ci-qualification-20261020/original-failures.json create mode 100644 docs/plans/retained-analysis/reports/ci-qualification-20261020/qualification.json create mode 100644 docs/plans/retained-analysis/reports/ci-qualification-20261020/receipt.json create mode 100644 docs/plans/retained-analysis/reports/ci-qualification-20261020/schema-cleanup.json create mode 100644 docs/plans/retained-analysis/reports/ci-qualification-20261020/schema-reservation.json diff --git a/docs/plans/retained-analysis/reports/ci-qualification-20261020/acceptance.md b/docs/plans/retained-analysis/reports/ci-qualification-20261020/acceptance.md new file mode 100644 index 00000000..80db0db6 --- /dev/null +++ b/docs/plans/retained-analysis/reports/ci-qualification-20261020/acceptance.md @@ -0,0 +1,58 @@ +# PR111 captured CPU browser qualification + +Base: `beead92d54e33e70eb9df82e872adf14ff314c91`. Repair owner: +`fix/retained-analysis-ci-qualification-20261020`; root owns serial integration. +The write set is the existing `tests/browser_model_development.cjs` gate and +this evidence directory. Production code and operation contracts are unchanged. + +Both original captured CPU jobs reach actual training, branching, correction +and comparison, then time out at line 556. The obsolete assertion waits for +`Evidence access revoked` inside `.model-evidence`. The accepted Runs owner in +`static/workspace-real.js` removes that private panel and puts the denial in +`.real-status`. Its exact original output shows the denial, no Run rows and no +private result content. The next explicit Refresh action was never reached. +[Original failures](original-failures.json) retain all four run/job identities, +exact failure excerpts, checkout/source bindings, timestamps, full decoded-log +hashes and local raw MCP response/metadata paths. + +The repaired assertion still injects the same 403. It waits for the Runs-owned +status and requires zero private model panels, metric grids, retained charts, +Run rows, checkpoint controls and probe controls. Only an explicit Refresh may +restore the exact third Run, its two checkpoints, metrics and rendered retained +SVG. The browser receipt records the observed denial and recovered result. + +[Actual browser receipt](receipt.json) and [execution log](model-development.log): +passed, including all existing checks and the strengthened H5 denial/recovery. +[Qualification](qualification.json) binds the exact tested source hashes. +`node --check tests/browser_model_development.cjs` and the existing +[model controller suite](model-controller.log) passed. +This browser uses normal app/HTTP/PostgreSQL, authored image import and review, +frozen release creation, real CPU training, correction and exact comparison. +The denial itself is a controlled HTTP substitution; actual credential +revocation/export enforcement remains separately attributed to the existing +[authenticated integration acceptance](../m4-integrated/acceptance.md). +The supporting model controller suite uses controlled transport and is not +runtime training evidence. + +Local qualification uses PostgreSQL 17.6, Python 3.12.14, Torch 2.8.0+cpu and +headless Chromium with the existing no-sandbox/software rendering flags and +an isolated browser profile. Only preregistered fresh schema +`catalog_8faa508de2e54448925420da15fa406c` is owned here. A local launcher creates +that catalog through normal `Metadata(dataset_id=...)` before executing the +normal app. All authored image data enters through the normal UI. Runtime source trees +remain unchanged. [Exact schema cleanup](schema-cleanup.json) confirms all three +observed Runs completed, the app stopped and only this schema was removed. +This local environment supports the affected browser claim; +GitHub's distro runtime provisioning and downstream package capture/fresh +consumer steps are separate CI claims and are not represented as rerun here. + +The shared lifecycle failure is the canonical author fixture's equality check +against a now-evolved SDK. PR108 owns its separate frozen-source-authority test +repair; root propagates it through the predecessor integration. It is not part +of this repair. No model quality, scientific acceptance or CUDA claim is made. +No remote push, rerun, cancellation or merge is performed by this worker. + +The task-created worktree `/workspace/Tuldok-retained-ci-repair-20261020` is +retained-protected by the named repair branch for root's review/integration. +Root owns its next disposition and safe cleanup after serial acceptance; +unrelated worktrees are outside this worker's ownership. diff --git a/docs/plans/retained-analysis/reports/ci-qualification-20261020/corrected-evidence-1440.jpg b/docs/plans/retained-analysis/reports/ci-qualification-20261020/corrected-evidence-1440.jpg new file mode 100644 index 0000000000000000000000000000000000000000..db9c45b1a0a5d4423303d39d5da2492ea89e36f6 GIT binary patch literal 97692 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 bw~{=ucy@@>A2eM)PjQ`3#om4V*WCXBG2Cu$ literal 0 HcmV?d00001 diff --git a/docs/plans/retained-analysis/reports/ci-qualification-20261020/model-controller.log b/docs/plans/retained-analysis/reports/ci-qualification-20261020/model-controller.log new file mode 100644 index 00000000..97e906b3 --- /dev/null +++ b/docs/plans/retained-analysis/reports/ci-qualification-20261020/model-controller.log @@ -0,0 +1 @@ +PASS model UI: exact frozen probe correction, honest legacy history, observed zero, query ordering, navigation/session exclusion and denied evidence clearing. Controlled transport only. diff --git a/docs/plans/retained-analysis/reports/ci-qualification-20261020/model-development.log b/docs/plans/retained-analysis/reports/ci-qualification-20261020/model-development.log new file mode 100644 index 00000000..ed1b5674 --- /dev/null +++ b/docs/plans/retained-analysis/reports/ci-qualification-20261020/model-development.log @@ -0,0 +1,14 @@ +PASS keyboard navigation reaches honest empty real runs and returns to retained Data +PASS 12 authored independent images imported, labelled and explicitly reviewed using Data controls +PASS invalid held-out class coverage blocks release before training +PASS fixed split preview, exact reviewed source release and immutable ZIP download +PASS Selected checkpoint candidate is retained as diagnostic with separate unfulfilled package and fresh-verifier states +PASS H1 real finite training produces three checkpoint/probe sets; keyboard epoch selection preserves exact example; test remains locked +PASS Root intent precedes actual CPU admission; exact retained parent branches into a second Study, edits and prepares inertly, then trains once without a retry edge +PASS Compatible frozen validation membership supports measured comparison across actual trained models +PASS Interactive lineage retains two Studies, authored hypothesis/goal/change, exact baseline and real completed child outcome after reload +PASS Exact comparison requests bind both evaluations/checkpoints/metric definitions and explicit paired or side-by-side mode +PASS H4 keyboard model-probe correction creates reviewed current revision, new release and trained trial; original evidence is immutable; changed membership refuses paired deltas +PASS H5 delayed query cannot override navigation; denied evidence clears all private Runs content and explicit refresh recovers the exact Run, checkpoints, metrics and retained chart +PASS Automatic dark workspace preference has visible keyboard focus, measured text/focus contrast and bounded 1440/390 evidence layout +PASS real model development gate: /tmp/pr111-ci-repair/qa/model-development/run-XscB4e diff --git a/docs/plans/retained-analysis/reports/ci-qualification-20261020/original-failures.json b/docs/plans/retained-analysis/reports/ci-qualification-20261020/original-failures.json new file mode 100644 index 00000000..d37be50a --- /dev/null +++ b/docs/plans/retained-analysis/reports/ci-qualification-20261020/original-failures.json @@ -0,0 +1,132 @@ +[ + { + "run_id": 39349565476, + "job_id": 118390287531, + "kind": "captured-cpu", + "url": "https://github.com/MrScripty/Tuldok/actions/runs/39349565476", + "head_sha": "beead92d54e33e70eb9df82e872adf14ff314c91", + "created_at": "2026-10-20T00:45:52Z", + "updated_at": "2026-10-20T01:21:53Z", + "conclusion": "failure", + "event": "pull_request", + "checkout": "2026-10-20T01:16:02.0254269Z HEAD is now at e3ac61f Merge beead92d54e33e70eb9df82e872adf14ff314c91 into de5a3a8c8a2767141ac45ffbe8d1bb89c9cf4b70", + "decoded_log_bytes": 57720, + "decoded_log_sha256": "7ef508d44895af471dee68d56c247fbaf97b27881e79ab3f25496bc8216eb77e", + "preserved_decoded_log": "/tmp/pr111-ci-repair/original-job-118390287531.log", + "raw_mcp_response_sha256": "09059eb3650c663fb7c1bd28724817fcb419f528e8954717985c423413fa7cd9", + "raw_mcp_response": "/tmp/pr111-job-118390287531-raw.json", + "run_metadata_sha256": "fbfe1c6828f58b707aee03e921dcad980d0fa649fd9beee03388f088b6fcddde", + "run_metadata": "/tmp/pr111-run-39349565476-metadata.json", + "failure": [ + "2026-10-20T01:18:46.9134170Z PASS Exact comparison requests bind both evaluations/checkpoints/metric definitions and explicit paired or side-by-side mode", + "2026-10-20T01:18:47.0095062Z PASS H4 keyboard model-probe correction creates reviewed current revision, new release and trained trial; original evidence is immutable; changed membership refuses paired deltas", + "2026-10-20T01:21:49.5906705Z Error: Timed out", + "2026-10-20T01:21:49.5910237Z at until (/home/runner/work/Tuldok/Tuldok/tests/browser_model_development.cjs:32:9)", + "2026-10-20T01:21:49.5911768Z at async /home/runner/work/Tuldok/Tuldok/tests/browser_model_development.cjs:556:3", + "2026-10-20T01:21:49.5914426Z Application stderr: ", + "2026-10-20T01:21:49.5947431Z {\"url\":\"http://127.0.0.1:33609/workspaces#runs\",\"status\":\"Evidence access revoked\",\"body\":\"Local owner \u00b7 owner\\nSession\\nSign out\\nSkip to workspace\\nt.\\nTuldok\\n\u25cf Local\\nClassic workbench \u2197\\nCorner studio \u2197\\nCONTEXT\\nDataset\\nInterface fixtures\\nCurrent local catalog\\nOpen project\\n12 exact revisions selected \u00b7 authored-09-circle.png \u00b7 saved state \u00b7 catalog 9e50f02c68fd\\nLocal preview\\n01\\nData\\n02\\nPipeline\\n03\\nRuns\\n\\nEvidence access revoked\\n\\nEVIDENCE, AT EACH STEP\\nRuns\\n\\nReal local runs. Results retain their saved graph and exact admitted inputs. Classification, integrity and external execution receipts retain their own scope and limitations.\\n\\nEvidence access revoked\\n\\nRefresh saved runs\\nOpen Pipeline\\nRun coordinator\\n\\nCurrent coordinator health is unavailable.\\n\\nRefresh coordinator health\\nNo real runs yet\\n\\nSave and validate a recipe in Pipeline, then run it on the local CPU.\\n\\nTuldok \u00b7 Dataset-centered workspaces\\nFixtures are isolated examples. Current catalog runs use an optional local CPU runtime.\",\"frame\":\"nent:ed72938560e04ca12b5de4c86771fe2d2df86da26234ed02d3cda65d34e58282 \u00b7 members: 6b591301df2c4521ab374ac3fa0d4ed71 selected / 1 related records \u00b7 0 deleted sources \u00b7 fixed splits: noneFamily component:f89839597071b285a2bba0e1b187b60dac1188624a0c0b3cb919178310b9e66f \u00b7 members: d645768c965146fa9ec089265b65ed74Warning: Opaque class folders are model indices. Use manifest.json class_vocabulary to recover exact labels. The mapping is frozen per release, not shared automatically across releases.Warning: Exact matches and protected lineage do not establish semantic independence or training quality.Freeze & export ZIPDownload 12-record frozen releaseFreeze selected answersAnswer selection is separate from record selection and collection filters. Select individual answer revisions; edits and newly added answers never replace these fixed pairs.0 answers selectedClear answer selectionDownload fixed answer selectionDownload selection JSONOpen fixed answer selectionTrain %Validation %Test %Answer split seedWhole source families stay together. Percentages weight examples, including multiple answers to one prompt. Draft or stale selections block export. The complete archive is bounded to 40 MiB.Preview selected answersSelect exact reviewed answers to preview.Freeze answers & export ZIPFreeze selected preference pairsSelections retain exact stored judgment, prompt and answer revisions. Reviewed ties and abstentions are excluded with reasons. Stale, draft or conflicting current directional judgments block export. Refresh/rejudge deliberately after edits.Clear selected judgmentsTrain %Validation %Test %Preference split seedWhole source families stay together. Percentages weight emitted pairs; ties and abstentions do not weight splits. 5,000 judgments and 40 MiB per release.Preview selected judgmentsFreeze preference pairs & export ZIP\\nLocal sessionOne-time login codeSign inKeep editsGenerate a private code with python access.py login --data CATALOG --out FILE. Do not share that file.\"}", + "2026-10-20T01:21:49.6327808Z ##[error]Process completed with exit code 1.", + "2026-10-20T01:21:49.6436158Z ##[group]Run actions/upload-artifact@v4" + ] + }, + { + "run_id": 39349515814, + "job_id": 118390126254, + "kind": "captured-cpu", + "url": "https://github.com/MrScripty/Tuldok/actions/runs/39349515814", + "head_sha": "beead92d54e33e70eb9df82e872adf14ff314c91", + "created_at": "2026-10-20T00:45:22Z", + "updated_at": "2026-10-20T01:11:11Z", + "conclusion": "failure", + "event": "pull_request", + "checkout": "2026-10-20T01:06:03.4587376Z HEAD is now at e3ac61f Merge beead92d54e33e70eb9df82e872adf14ff314c91 into de5a3a8c8a2767141ac45ffbe8d1bb89c9cf4b70", + "decoded_log_bytes": 56160, + "decoded_log_sha256": "97dfa1619349a4d4be89a9d8b2c17180175b9cf0ad6703f5fa18e9d1cdb28a53", + "preserved_decoded_log": "/tmp/pr111-ci-repair/original-job-118390126254.log", + "raw_mcp_response_sha256": "f8e95462072ad7981e14703024241285863bf958427d584e69d9d3991ff7a6f6", + "raw_mcp_response": "/tmp/pr111-job-118390126254-raw.json", + "run_metadata_sha256": "56225ff35ee15b1342cc72571617a38004b14720359f65e27e26fd8adb549dc0", + "run_metadata": "/tmp/pr111-run-39349515814-metadata.json", + "failure": [ + "2026-10-20T01:08:04.7732115Z PASS Exact comparison requests bind both evaluations/checkpoints/metric definitions and explicit paired or side-by-side mode", + "2026-10-20T01:08:04.8714745Z PASS H4 keyboard model-probe correction creates reviewed current revision, new release and trained trial; original evidence is immutable; changed membership refuses paired deltas", + "2026-10-20T01:11:06.8901448Z Error: Timed out", + "2026-10-20T01:11:06.8902059Z at until (/home/runner/work/Tuldok/Tuldok/tests/browser_model_development.cjs:32:9)", + "2026-10-20T01:11:06.8902748Z at async /home/runner/work/Tuldok/Tuldok/tests/browser_model_development.cjs:556:3", + "2026-10-20T01:11:06.8903285Z Application stderr: ", + "2026-10-20T01:11:06.8933181Z {\"url\":\"http://127.0.0.1:46829/workspaces#runs\",\"status\":\"Evidence access revoked\",\"body\":\"Local owner \u00b7 owner\\nSession\\nSign out\\nSkip to workspace\\nt.\\nTuldok\\n\u25cf Local\\nClassic workbench \u2197\\nCorner studio \u2197\\nCONTEXT\\nDataset\\nInterface fixtures\\nCurrent local catalog\\nOpen project\\n12 exact revisions selected \u00b7 authored-05-circle.png \u00b7 saved state \u00b7 catalog d035b4817849\\nLocal preview\\n01\\nData\\n02\\nPipeline\\n03\\nRuns\\n\\nEvidence access revoked\\n\\nEVIDENCE, AT EACH STEP\\nRuns\\n\\nReal local runs. Results retain their saved graph and exact admitted inputs. Classification, integrity and external execution receipts retain their own scope and limitations.\\n\\nEvidence access revoked\\n\\nRefresh saved runs\\nOpen Pipeline\\nRun coordinator\\n\\nCurrent coordinator health is unavailable.\\n\\nRefresh coordinator health\\nNo real runs yet\\n\\nSave and validate a recipe in Pipeline, then run it on the local CPU.\\n\\nTuldok \u00b7 Dataset-centered workspaces\\nFixtures are isolated examples. Current catalog runs use an optional local CPU runtime.\",\"frame\":\"nent:f503b2468c16f4fed2e3cf02584cbbdbd1d7401507746f0c8061b0fdee90fabf \u00b7 members: 9db63a7dbc074299aeb96ad80908d9f21 selected / 1 related records \u00b7 0 deleted sources \u00b7 fixed splits: noneFamily component:f5b1dd9a3de1bd7a7afa2c3cbc5f9cbcca319b4bcd0ade5de52622817593c0be \u00b7 members: 5c5bed5adf3742baa00682f5dabd51c4Warning: Opaque class folders are model indices. Use manifest.json class_vocabulary to recover exact labels. The mapping is frozen per release, not shared automatically across releases.Warning: Exact matches and protected lineage do not establish semantic independence or training quality.Freeze & export ZIPDownload 12-record frozen releaseFreeze selected answersAnswer selection is separate from record selection and collection filters. Select individual answer revisions; edits and newly added answers never replace these fixed pairs.0 answers selectedClear answer selectionDownload fixed answer selectionDownload selection JSONOpen fixed answer selectionTrain %Validation %Test %Answer split seedWhole source families stay together. Percentages weight examples, including multiple answers to one prompt. Draft or stale selections block export. The complete archive is bounded to 40 MiB.Preview selected answersSelect exact reviewed answers to preview.Freeze answers & export ZIPFreeze selected preference pairsSelections retain exact stored judgment, prompt and answer revisions. Reviewed ties and abstentions are excluded with reasons. Stale, draft or conflicting current directional judgments block export. Refresh/rejudge deliberately after edits.Clear selected judgmentsTrain %Validation %Test %Preference split seedWhole source families stay together. Percentages weight emitted pairs; ties and abstentions do not weight splits. 5,000 judgments and 40 MiB per release.Preview selected judgmentsFreeze preference pairs & export ZIP\\nLocal sessionOne-time login codeSign inKeep editsGenerate a private code with python access.py login --data CATALOG --out FILE. Do not share that file.\"}", + "2026-10-20T01:11:06.9359130Z ##[error]Process completed with exit code 1.", + "2026-10-20T01:11:06.9432381Z ##[group]Run actions/upload-artifact@v4" + ] + }, + { + "run_id": 39349565452, + "job_id": 118390287291, + "kind": "dataset-lifecycle", + "url": "https://github.com/MrScripty/Tuldok/actions/runs/39349565452", + "head_sha": "beead92d54e33e70eb9df82e872adf14ff314c91", + "created_at": "2026-10-20T00:45:52Z", + "updated_at": "2026-10-20T02:15:14Z", + "conclusion": "failure", + "event": "pull_request", + "checkout": "2026-10-20T00:59:45.3436399Z HEAD is now at e3ac61f Merge beead92d54e33e70eb9df82e872adf14ff314c91 into de5a3a8c8a2767141ac45ffbe8d1bb89c9cf4b70", + "decoded_log_bytes": 248235, + "decoded_log_sha256": "616ee5c44b0b9f06a1cee7376c5fd895cbbf76e29d6490bf9c1d7ec6c128959d", + "preserved_decoded_log": "/tmp/pr111-ci-repair/original-job-118390287291.log", + "raw_mcp_response_sha256": "734046f0552390637e5476d807d581c7d7a967ef46da146953c276cde093544d", + "raw_mcp_response": "/tmp/pr111-job-118390287291-raw.json", + "run_metadata_sha256": "f481d4816a7849ae1f512cc909785013aea47abd28542f986665d02703ddc290", + "run_metadata": "/tmp/pr111-run-39349565452-metadata.json", + "failure": [ + "2026-10-20T02:15:09.5746651Z FAIL: test_new_project_exact_sources_full_catalog_and_model_controls_are_inert (test_extension_canonical_author.CanonicalAuthorTests.test_new_project_exact_sources_full_catalog_and_model_controls_are_inert)", + "2026-10-20T02:15:09.5748130Z ----------------------------------------------------------------------", + "2026-10-20T02:15:09.5748695Z Traceback (most recent call last):", + "2026-10-20T02:15:09.5749933Z File \"/home/runner/work/Tuldok/Tuldok/tests/test_extension_canonical_author.py\", line 79, in test_new_project_exact_sources_full_catalog_and_model_controls_are_inert", + "2026-10-20T02:15:09.5751724Z self.assertEqual((PACKAGE/'tuldok_extension_sdk'/name).read_bytes(),(Path(__file__).resolve().parents[1]/'tuldok_extension_sdk'/name).read_bytes())", + "2026-10-20T02:15:09.5753637Z AssertionError: b'\"\"\"[18141 chars]]\\n\\n\\n@boundary\\ndef validate_projection(valu[6164 chars]')\\n' != b'\"\"\"[18141 chars]]\\n\\n @boundary\\n def diagnostics(self, [6665 chars]')\\n'", + "2026-10-20T02:15:09.5754329Z ", + "2026-10-20T02:15:09.5754584Z ----------------------------------------------------------------------", + "2026-10-20T02:15:09.5754999Z Ran 1771 tests in 2857.629s", + "2026-10-20T02:15:09.5755166Z ", + "2026-10-20T02:15:09.5755325Z FAILED (failures=1, skipped=83)", + "2026-10-20T02:15:09.5767684Z INDEXED_DIAGNOSTIC_QUALIFICATION {\"accounting_and_events_unchanged\": true, \"artifacts\": [{\"bytes\": 948, \"media_type\": \"application/octet-stream\", \"name\": \"diagnostic-index.json\", \"role\": \"diagnostic_index_v1\", \"sha256\": \"44cbf1666b4766cb6b9228c98fc470ec713b906cfc32237dc56f873346b9142e\"}, {\"bytes\": 983, \"media_type\": \"application/octet-stream\", \"name\": \"diagnostic-0.json\", \"role\": \"diagnostic_shard_v1\", \"sha256\": \"0f33a7857dc7581f5a09d8474ca04f9ac5885e2972a2b1741f62e96d0de88b07\"}, {\"bytes\": 443, \"media_type\": \"application/octet-stream\", \"name\": \"diagnostic-1.json\", \"role\": \"diagnostic_shard_v1\", \"sha256\": \"675191758d32bca9a9c25e838346277bcefe4f5bbe68aaacd08d4b92f32ccdd8\"}], \"captured_python_producer_executed\": false, \"composed_readers\": {\"batch_calls\": 1, \"batch_collected_exact_artifacts\": [\"diagnostic-index.json\", \"diagnostic-0.json\", \"diagnostic-1.json\"], \"comparison\": \"same exact Ref diagnostic delta zero; no scientific acceptance\", \"individual_segment_calls\": 0}, \"counts_after\": {\"access_execution_consumptions\": 1, \"access_execution_grants\": 1, \"model_attempt_reservations\": 1, \"workspace_graphs\": 1, \"workspace_runs\": 1}, \"counts_before\": {\"access_execution_consumptions\": 1, \"access_execution_grants\": 1, \"model_attempt_reservations\": 1, \"workspace_graphs\": 1, \"workspace_runs\": 1}, \"coverage\": {\"omitted\": [{\"count\": 1, \"reason\": \"capture_budget\", \"start\": 2}], \"omitted_count\": 1, \"optional_count\": 3, \"required_count\": 2, \"retained_optional_count\": 2, \"retained_required_count\": 2, \"total_count\": 5}, \"custody_outcome\": \"completed\", \"numerical_acceptance\": \"not_evaluated\", \"original_state\": \"interrupted\", \"result_ref\": {\"catalog_id\": \"f8954cca18804647b1ae12c680ddb015\", \"custody_receipt_sha256\": \"d97860c24a71974141971b7d2ba9ca41d9a87206ff900e8bfb4becc9f17d159b\", \"inventory_sha256\": \"dba11f7c64fba5cd6dc7ce6994193145c86f045c3a0a2b0f41f9ee26f2b93c75\", \"kind\": \"recovered_publication_result\", \"material_sha256\": \"302f8642743dac36b62280f726733e1893dc94089201d92d17f98c25e2be63fb\", \"run_id\": \"7e14bf527d114f00bbf7d103dfbb9a51\", \"schema_version\": 1, \"sha256\": \"8b0c1bdb9c0554ce2ad75bf3771d8b61e979f0e34060d402c32304f6a2a117d4\"}, \"run_id\": \"7e14bf527d114f00bbf7d103dfbb9a51\", \"runtime_packages\": {\"numpy\": \"0.0\", \"torch\": \"0.0\"}, \"runtime_snapshot_sha256\": \"284d6e5bf4da87a42b80175720e7e3c6213c906b684dfed4a16f212b61b81d22\", \"schema\": \"catalog_f8954cca18804647b1ae12c680ddb015\", \"scope\": \"harness SDK serialization; actual no-op metadata runtime custody and semantic recovery\", \"training_executed\": false, \"verification_scope\": \"source_destination_and_cold_exact_ref_reader\"}", + "2026-10-20T02:15:09.5776919Z Removed exact recorded fresh schema: catalog_f8954cca18804647b1ae12c680ddb015", + "2026-10-20T02:15:09.7284731Z ##[error]Process completed with exit code 1." + ] + }, + { + "run_id": 39349515815, + "job_id": 118390126097, + "kind": "dataset-lifecycle", + "url": "https://github.com/MrScripty/Tuldok/actions/runs/39349515815", + "head_sha": "beead92d54e33e70eb9df82e872adf14ff314c91", + "created_at": "2026-10-20T00:45:22Z", + "updated_at": "2026-10-20T01:39:08Z", + "conclusion": "failure", + "event": "pull_request", + "checkout": "2026-10-20T00:54:49.0102114Z HEAD is now at e3ac61f Merge beead92d54e33e70eb9df82e872adf14ff314c91 into de5a3a8c8a2767141ac45ffbe8d1bb89c9cf4b70", + "decoded_log_bytes": 245509, + "decoded_log_sha256": "b077b531c5d646a915642b39fcb1c1939369e836b7fe7f518b6065f80ec41763", + "preserved_decoded_log": "/tmp/pr111-ci-repair/original-job-118390126097.log", + "raw_mcp_response_sha256": "e6a7c503a7bc1c0f3ed3b80dbb21702cdc447528f9257fafd05b2f2100d8504e", + "raw_mcp_response": "/tmp/pr111-job-118390126097-raw.json", + "run_metadata_sha256": "3740017b39d6b9652372fff34c88b1086486290bd17bdc33391c4b54a4214ff1", + "run_metadata": "/tmp/pr111-run-39349515815-metadata.json", + "failure": [ + "2026-10-20T01:39:03.5200676Z FAIL: test_new_project_exact_sources_full_catalog_and_model_controls_are_inert (test_extension_canonical_author.CanonicalAuthorTests.test_new_project_exact_sources_full_catalog_and_model_controls_are_inert)", + "2026-10-20T01:39:03.5201544Z ----------------------------------------------------------------------", + "2026-10-20T01:39:03.5201885Z Traceback (most recent call last):", + "2026-10-20T01:39:03.5202621Z File \"/home/runner/work/Tuldok/Tuldok/tests/test_extension_canonical_author.py\", line 79, in test_new_project_exact_sources_full_catalog_and_model_controls_are_inert", + "2026-10-20T01:39:03.5203607Z self.assertEqual((PACKAGE/'tuldok_extension_sdk'/name).read_bytes(),(Path(__file__).resolve().parents[1]/'tuldok_extension_sdk'/name).read_bytes())", + "2026-10-20T01:39:03.5204683Z AssertionError: b'\"\"\"[18141 chars]]\\n\\n\\n@boundary\\ndef validate_projection(valu[6164 chars]')\\n' != b'\"\"\"[18141 chars]]\\n\\n @boundary\\n def diagnostics(self, [6665 chars]')\\n'", + "2026-10-20T01:39:03.5205205Z ", + "2026-10-20T01:39:03.5205407Z ----------------------------------------------------------------------", + "2026-10-20T01:39:03.5205717Z Ran 1771 tests in 1759.736s", + "2026-10-20T01:39:03.5205859Z ", + "2026-10-20T01:39:03.5205983Z FAILED (failures=1, skipped=83)", + "2026-10-20T01:39:03.6296286Z ##[error]Process completed with exit code 1.", + "2026-10-20T01:39:03.6552564Z ##[group]Run actions/upload-artifact@v4", + "2026-10-20T01:39:03.6552726Z with:" + ] + } +] diff --git a/docs/plans/retained-analysis/reports/ci-qualification-20261020/qualification.json b/docs/plans/retained-analysis/reports/ci-qualification-20261020/qualification.json new file mode 100644 index 00000000..9366b91c --- /dev/null +++ b/docs/plans/retained-analysis/reports/ci-qualification-20261020/qualification.json @@ -0,0 +1,62 @@ +{ + "base_commit": "beead92d54e33e70eb9df82e872adf14ff314c91", + "observed_at": "2026-10-20T02:36:44Z", + "browser": "Chrome/151.0.7922.173", + "python": "3.12.14 (main, Aug 25 2026, 14:00:49) [Clang 22.1.3 ]", + "node": "v24.19.0", + "kernel": "Linux-6.18.55-x86_64-with-glibc2.41", + "headless": true, + "browser_flags": [ + "--no-sandbox", + "--disable-gpu" + ], + "display": "headless; isolated temporary profile", + "sandbox": "selected managed workspace sandbox", + "shared_memory_bytes": 9441337344, + "full_qa": "/tmp/pr111-ci-repair/qa/model-development/run-XscB4e", + "source_sha256": { + "static/workspace-service.js": "568b8258c35e6b3ca2cfe08b64d914111e16ae98d45f5d40f7aa40a20c20098b", + "static/workspace-real.js": "de4036bab21c3ca2702488658a9fa8733cf0adb822f4ec3322d5e101a96b60a2", + "static/experiment-lineage.js": "085ee3cc990f1986db357e1e8f7bace0c16a2257bca9443ff412c464d91a53db", + "static/experiment-lineage.css": "232fec3043b92ae7aa91db499a14e8cdb9ebe5598c8d7f01d805e3e3d8d4859d", + "static/workspaces.css": "3d0eacbd50425b4cd2ce9cfacdf5bcdb8fe533d7a57248f16325242f625cd278", + "static/workspaces.html": "a85e465d317e8aaa14c5349ef1ae6b2dc75ac440e0cea2c5c5a313dbd4fb828e", + "experiment_lineage.py": "5cdac7aec893bff832406b44ae04af587118990b1b803ec11cea1458d8ed3234", + "agent_api.py": "bb14a25c63840f1701b13657fa1bce4659a2c6a180068e95f461e5fa7f9327b4", + "app.py": "c71b8b903fa8905ff5fd3ccaef1b86d3df3ddda5393f33bf3ec9661a98d02417", + "experiments.py": "05c88fa658408c7750aecda37461abfec54537c8b9dbe6143ea90313b72420df", + "pipeline.py": "07f5b491767941bf68668da8e82282b78858fe310e9ec74c6d91a8e38534faeb", + "runs.py": "b701532d0bf5c77ee87676fa3bbfbf9759ae45370c28d45765b2eac538a4547e", + "metadata.py": "893d489f8e5d323ac1eed61350d206bbc1c0375801402f52cc586ac8423d62e4", + "upgrade_metadata.py": "f78f6113b3687d808536f873153c83893ed91bf1e247986b29ac00d4c226af8f", + "tests/browser_model_development.cjs": "b52c9355398a8862225b665fc379fde4916a2c6d265e371e2386832144b48d6e" + }, + "checks": [ + "keyboard navigation reaches honest empty real runs and returns to retained Data", + "12 authored independent images imported, labelled and explicitly reviewed using Data controls", + "invalid held-out class coverage blocks release before training", + "fixed split preview, exact reviewed source release and immutable ZIP download", + "Selected checkpoint candidate is retained as diagnostic with separate unfulfilled package and fresh-verifier states", + "H1 real finite training produces three checkpoint/probe sets; keyboard epoch selection preserves exact example; test remains locked", + "Root intent precedes actual CPU admission; exact retained parent branches into a second Study, edits and prepares inertly, then trains once without a retry edge", + "Compatible frozen validation membership supports measured comparison across actual trained models", + "Interactive lineage retains two Studies, authored hypothesis/goal/change, exact baseline and real completed child outcome after reload", + "Exact comparison requests bind both evaluations/checkpoints/metric definitions and explicit paired or side-by-side mode", + "H4 keyboard model-probe correction creates reviewed current revision, new release and trained trial; original evidence is immutable; changed membership refuses paired deltas", + "H5 delayed query cannot override navigation; denied evidence clears all private Runs content and explicit refresh recovers the exact Run, checkpoints, metrics and retained chart", + "Automatic dark workspace preference has visible keyboard focus, measured text/focus contrast and bounded 1440/390 evidence layout" + ], + "training": true, + "private_projection": { + "status": "Evidence access revoked", + "privateNodes": 0 + }, + "restored_projection": { + "run_id": "b14204732d8740babe198a5cb1fe2779", + "checkpoint_count": 2, + "retained_chart": true + }, + "app_stopped": true, + "scope": "Actual app/HTTP/PostgreSQL native classifier browser; no model-quality or downstream package-capture claim", + "injected_denial_status": 403 +} diff --git a/docs/plans/retained-analysis/reports/ci-qualification-20261020/receipt.json b/docs/plans/retained-analysis/reports/ci-qualification-20261020/receipt.json new file mode 100644 index 00000000..7675907f --- /dev/null +++ b/docs/plans/retained-analysis/reports/ci-qualification-20261020/receipt.json @@ -0,0 +1,528 @@ +{ + "source_commit": "beead92d54e33e70eb9df82e872adf14ff314c91", + "dirty": true, + "command": "node tests/browser_model_development.cjs", + "source_sha256": { + "static/workspace-service.js": "568b8258c35e6b3ca2cfe08b64d914111e16ae98d45f5d40f7aa40a20c20098b", + "static/workspace-real.js": "de4036bab21c3ca2702488658a9fa8733cf0adb822f4ec3322d5e101a96b60a2", + "static/experiment-lineage.js": "085ee3cc990f1986db357e1e8f7bace0c16a2257bca9443ff412c464d91a53db", + "static/experiment-lineage.css": "232fec3043b92ae7aa91db499a14e8cdb9ebe5598c8d7f01d805e3e3d8d4859d", + "static/workspaces.css": "3d0eacbd50425b4cd2ce9cfacdf5bcdb8fe533d7a57248f16325242f625cd278", + "static/workspaces.html": "a85e465d317e8aaa14c5349ef1ae6b2dc75ac440e0cea2c5c5a313dbd4fb828e", + "experiment_lineage.py": "5cdac7aec893bff832406b44ae04af587118990b1b803ec11cea1458d8ed3234", + "agent_api.py": "bb14a25c63840f1701b13657fa1bce4659a2c6a180068e95f461e5fa7f9327b4", + "app.py": "c71b8b903fa8905ff5fd3ccaef1b86d3df3ddda5393f33bf3ec9661a98d02417", + "experiments.py": "05c88fa658408c7750aecda37461abfec54537c8b9dbe6143ea90313b72420df", + "pipeline.py": "07f5b491767941bf68668da8e82282b78858fe310e9ec74c6d91a8e38534faeb", + "runs.py": "b701532d0bf5c77ee87676fa3bbfbf9759ae45370c28d45765b2eac538a4547e", + "metadata.py": "893d489f8e5d323ac1eed61350d206bbc1c0375801402f52cc586ac8423d62e4", + "upgrade_metadata.py": "f78f6113b3687d808536f873153c83893ed91bf1e247986b29ac00d4c226af8f", + "tests/browser_model_development.cjs": "b52c9355398a8862225b665fc379fde4916a2c6d265e371e2386832144b48d6e" + }, + "dark_checks": [ + { + "width": 1440, + "dark": true, + "focus": "model-checkpoint-646b11aa9ef1cf77f2444e5f32cf6ffae7321c3e223c2110bc5d85b7c482937f", + "outline": "solid", + "outlineWidth": "3px", + "outlineColor": "rgb(158, 198, 255)", + "text": "rgb(229, 237, 248)", + "background": "rgb(12, 20, 32)", + "textContrast": 15.662057908741831, + "focusContrast": 10.536654698975951 + }, + { + "width": 390, + "dark": true, + "focus": "model-checkpoint-646b11aa9ef1cf77f2444e5f32cf6ffae7321c3e223c2110bc5d85b7c482937f", + "outline": "solid", + "outlineWidth": "3px", + "outlineColor": "rgb(158, 198, 255)", + "text": "rgb(229, 237, 248)", + "background": "rgb(12, 20, 32)", + "textContrast": 15.662057908741831, + "focusContrast": 10.536654698975951 + } + ], + "catalog_path": "/tmp/tuldok-model-development-ESKMk7/data", + "browser": "Chrome/151.0.7922.173", + "checks": [ + "keyboard navigation reaches honest empty real runs and returns to retained Data", + "12 authored independent images imported, labelled and explicitly reviewed using Data controls", + "invalid held-out class coverage blocks release before training", + "fixed split preview, exact reviewed source release and immutable ZIP download", + "Selected checkpoint candidate is retained as diagnostic with separate unfulfilled package and fresh-verifier states", + "H1 real finite training produces three checkpoint/probe sets; keyboard epoch selection preserves exact example; test remains locked", + "Root intent precedes actual CPU admission; exact retained parent branches into a second Study, edits and prepares inertly, then trains once without a retry edge", + "Compatible frozen validation membership supports measured comparison across actual trained models", + "Interactive lineage retains two Studies, authored hypothesis/goal/change, exact baseline and real completed child outcome after reload", + "Exact comparison requests bind both evaluations/checkpoints/metric definitions and explicit paired or side-by-side mode", + "H4 keyboard model-probe correction creates reviewed current revision, new release and trained trial; original evidence is immutable; changed membership refuses paired deltas", + "H5 delayed query cannot override navigation; denied evidence clears all private Runs content and explicit refresh recovers the exact Run, checkpoints, metrics and retained chart", + "Automatic dark workspace preference has visible keyboard focus, measured text/focus contrast and bounded 1440/390 evidence layout" + ], + "captures": [ + { + "file": "catalog-data-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "catalog-data-390.jpg", + "width": 390, + "height": 844, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "prepared-First TinyCNN-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "prepared-First TinyCNN-390.jpg", + "width": 390, + "height": 844, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "lineage-root-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "lineage-root-390.jpg", + "width": 390, + "height": 844, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "linked-evidence-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "linked-evidence-390.jpg", + "width": 390, + "height": 844, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "lineage-prepared-branch-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "lineage-prepared-branch-390.jpg", + "width": 390, + "height": 844, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "lineage-two-studies-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "lineage-two-studies-390.jpg", + "width": 390, + "height": 844, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "lineage-detail-completed-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "lineage-detail-completed-390.jpg", + "width": 390, + "height": 844, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "current-correction-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "prepared-Corrected TinyCNN-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "prepared-Corrected TinyCNN-390.jpg", + "width": 390, + "height": 844, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "corrected-evidence-390.jpg", + "width": 390, + "height": 844, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "corrected-evidence-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "dark-linked-evidence-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "dark-linked-evidence-390.jpg", + "width": 390, + "height": 844, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "lineage-dark-two-studies-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "lineage-detail-dark-1440.jpg", + "width": 1440, + "height": 900, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "lineage-dark-two-studies-390.jpg", + "width": 390, + "height": 844, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + }, + { + "file": "lineage-detail-dark-390.jpg", + "width": 390, + "height": 844, + "mode": "real execution on explicitly authored CC0 inputs; no model-quality claim", + "quality": 85 + } + ], + "lineage": { + "parent_before_admission": { + "attempt_count": 0, + "lineage": { + "actor_id": "cb39e89a7e904dbb9d0138ac5a43f088", + "format": "trial_lineage_v1", + "intent": { + "ancestry": "root", + "baseline": null, + "change_summary": "Root: three actual CPU epochs with frozen authored validation membership.", + "cohort": "Authored same-release CPU lineage", + "hypothesis": "Changing the finite trainer schedule preserves exact validation membership.", + "parent": null, + "target": { + "acceptance": "Diagnostic workflow fixture: inspect exact validation evidence; no model-quality claim.", + "direction": "minimize", + "metric_definition_sha256": null, + "metric_id": "loss", + "threshold": 0.5 + } + }, + "recorded_at": "2026-10-20T02:34:28.680041+00:00", + "timing": "before_admission", + "trial": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "material_sha256": "ce261f61190d0083c6a819f83c9adffc836c73ef8d3dd1aed1a60397cd92d1ae", + "trial_id": "c3a2131c37dc4c16ab458914a48597ee" + } + }, + "model": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "id": "44cfa2b5c6754ddca6b2894432697b6a", + "kind": "model", + "revision": 1, + "sha256": "47f2923c3cdc124cd8338533fb280367601d51fd4ea8f2904172e7c8f5cd1ade" + }, + "recipe": { + "id": "3d1ce71e8fa04031b402fb14fded4584", + "revision": 2 + }, + "runs": [], + "runs_truncated": false, + "study": { + "id": "11bdcd83c37c4446b8ce6a7c7a486f25", + "name": "First TinyCNN" + }, + "trial": { + "format": "trial_v1", + "id": "c3a2131c37dc4c16ab458914a48597ee", + "material": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "id": "ce261f61190d0083c6a819f83c9adffc836c73ef8d3dd1aed1a60397cd92d1ae", + "kind": "recipe_material", + "sha256": "ce261f61190d0083c6a819f83c9adffc836c73ef8d3dd1aed1a60397cd92d1ae" + }, + "replicate": 0, + "study_id": "11bdcd83c37c4446b8ce6a7c7a486f25" + } + }, + "child_before_admission": { + "attempt_count": 0, + "lineage": { + "actor_id": "cb39e89a7e904dbb9d0138ac5a43f088", + "format": "trial_lineage_v1", + "intent": { + "ancestry": "derived", + "baseline": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "material_sha256": "ce261f61190d0083c6a819f83c9adffc836c73ef8d3dd1aed1a60397cd92d1ae", + "trial_id": "c3a2131c37dc4c16ab458914a48597ee" + }, + "change_summary": "Derived branch: two epochs and seed 23; unchanged frozen Model and validation population.", + "cohort": "Authored same-release CPU lineage", + "hypothesis": "Changing the finite trainer schedule preserves exact validation membership.", + "parent": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "material_sha256": "ce261f61190d0083c6a819f83c9adffc836c73ef8d3dd1aed1a60397cd92d1ae", + "trial_id": "c3a2131c37dc4c16ab458914a48597ee" + }, + "target": { + "acceptance": "Diagnostic workflow fixture: inspect exact validation evidence; no model-quality claim.", + "direction": "minimize", + "metric_definition_sha256": null, + "metric_id": "loss", + "threshold": 0.5 + } + }, + "recorded_at": "2026-10-20T02:35:02.793059+00:00", + "timing": "before_admission", + "trial": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "material_sha256": "ed07a8901949d2246b46daf8585bb65a5006e676fe3c13e47a9cc0ea9c2d9f31", + "trial_id": "246f2d57f3b844dabb5959c75a928b36" + } + }, + "model": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "id": "44cfa2b5c6754ddca6b2894432697b6a", + "kind": "model", + "revision": 1, + "sha256": "47f2923c3cdc124cd8338533fb280367601d51fd4ea8f2904172e7c8f5cd1ade" + }, + "recipe": { + "id": "bf74a20bbad24f1693c5ee1ce22e5b99", + "revision": 2 + }, + "runs": [], + "runs_truncated": false, + "study": { + "id": "54dc40b1dd5e4a5d9e1464adc157e52b", + "name": "Separate CPU branch Study" + }, + "trial": { + "format": "trial_v1", + "id": "246f2d57f3b844dabb5959c75a928b36", + "material": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "id": "ed07a8901949d2246b46daf8585bb65a5006e676fe3c13e47a9cc0ea9c2d9f31", + "kind": "recipe_material", + "sha256": "ed07a8901949d2246b46daf8585bb65a5006e676fe3c13e47a9cc0ea9c2d9f31" + }, + "replicate": 0, + "study_id": "54dc40b1dd5e4a5d9e1464adc157e52b" + } + }, + "parent_run_id": "f0f1b8a599044db19c8734c81fc78c59", + "child_run_id": "29e102331db74dbc8c3e39cdba2149d5", + "child_completed": { + "attempt_count": 1, + "lineage": { + "actor_id": "cb39e89a7e904dbb9d0138ac5a43f088", + "format": "trial_lineage_v1", + "intent": { + "ancestry": "derived", + "baseline": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "material_sha256": "ce261f61190d0083c6a819f83c9adffc836c73ef8d3dd1aed1a60397cd92d1ae", + "trial_id": "c3a2131c37dc4c16ab458914a48597ee" + }, + "change_summary": "Derived branch: two epochs and seed 23; unchanged frozen Model and validation population.", + "cohort": "Authored same-release CPU lineage", + "hypothesis": "Changing the finite trainer schedule preserves exact validation membership.", + "parent": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "material_sha256": "ce261f61190d0083c6a819f83c9adffc836c73ef8d3dd1aed1a60397cd92d1ae", + "trial_id": "c3a2131c37dc4c16ab458914a48597ee" + }, + "target": { + "acceptance": "Diagnostic workflow fixture: inspect exact validation evidence; no model-quality claim.", + "direction": "minimize", + "metric_definition_sha256": null, + "metric_id": "loss", + "threshold": 0.5 + } + }, + "recorded_at": "2026-10-20T02:35:02.793059+00:00", + "timing": "before_admission", + "trial": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "material_sha256": "ed07a8901949d2246b46daf8585bb65a5006e676fe3c13e47a9cc0ea9c2d9f31", + "trial_id": "246f2d57f3b844dabb5959c75a928b36" + } + }, + "model": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "id": "44cfa2b5c6754ddca6b2894432697b6a", + "kind": "model", + "revision": 1, + "sha256": "47f2923c3cdc124cd8338533fb280367601d51fd4ea8f2904172e7c8f5cd1ade" + }, + "recipe": { + "id": "bf74a20bbad24f1693c5ee1ce22e5b99", + "revision": 2 + }, + "runs": [ + { + "created_at": "2026-10-20T02:35:07.967528+00:00", + "finished_at": "2026-10-20T02:35:23.440120+00:00", + "id": "29e102331db74dbc8c3e39cdba2149d5", + "parent_run_id": null, + "state": "completed", + "validation": { + "accuracy": 0.3333333333333333, + "loss": 0.7301838397979736, + "macro_f1": 0.25 + } + } + ], + "runs_truncated": false, + "study": { + "id": "54dc40b1dd5e4a5d9e1464adc157e52b", + "name": "Separate CPU branch Study" + }, + "trial": { + "format": "trial_v1", + "id": "246f2d57f3b844dabb5959c75a928b36", + "material": { + "catalog_id": "8faa508de2e54448925420da15fa406c", + "id": "ed07a8901949d2246b46daf8585bb65a5006e676fe3c13e47a9cc0ea9c2d9f31", + "kind": "recipe_material", + "sha256": "ed07a8901949d2246b46daf8585bb65a5006e676fe3c13e47a9cc0ea9c2d9f31" + }, + "replicate": 0, + "study_id": "54dc40b1dd5e4a5d9e1464adc157e52b" + } + }, + "dark_checks": [ + { + "width": 1440, + "text": "rgb(229, 237, 248)", + "background": "rgb(21, 30, 45)", + "outline": "solid", + "outlineWidth": "3px", + "outlineColor": "rgb(56, 107, 206)", + "textContrast": 14.178348680001829, + "focusContrast": 3.315425185528663 + }, + { + "width": 390, + "text": "rgb(229, 237, 248)", + "background": "rgb(21, 30, 45)", + "outline": "solid", + "outlineWidth": "3px", + "outlineColor": "rgb(56, 107, 206)", + "textContrast": 14.178348680001829, + "focusContrast": 3.315425185528663 + } + ] + }, + "compare_selectors": [ + { + "other_run_id": "f0f1b8a599044db19c8734c81fc78c59", + "checkpoint_sha256": "c700a7e3866266b644f2ddbf2e69fa0d5230b32a76b0697ac37b225189d86db0", + "other_checkpoint_sha256": "50236279861b2280d34e0875e6e671f5cb6cb8c4c56e54c9dd2d367a2f40b9bb", + "evaluation_sha256": "a68bcab9ce163d6dd4f02ba691fe3bf08a882641fb9f497b359d9333cb72802f", + "other_evaluation_sha256": "016692bef7dd714c1ba7f2b3d7db8a0e38db59745176011ee6b3151e8fca8860", + "metric_id": "loss", + "metric_definition_sha256": "ffb7e85d94549dee93f799571ef73b2db74d61b37cf20019994f663b1d69392e", + "other_metric_definition_sha256": "ffb7e85d94549dee93f799571ef73b2db74d61b37cf20019994f663b1d69392e", + "mode": "paired" + }, + { + "other_run_id": "f0f1b8a599044db19c8734c81fc78c59", + "checkpoint_sha256": "4e7207afbfd9ae78f0c0c419a1273aa6ab2644d434369f75ce3570cc74a5d059", + "other_checkpoint_sha256": "50236279861b2280d34e0875e6e671f5cb6cb8c4c56e54c9dd2d367a2f40b9bb", + "evaluation_sha256": "0f30c63f5e6c00a8eb7cf90171c803bc1c5d1fe99ab6539817c087a8096d7b3f", + "other_evaluation_sha256": "016692bef7dd714c1ba7f2b3d7db8a0e38db59745176011ee6b3151e8fca8860", + "metric_id": "loss", + "metric_definition_sha256": "4bb2d60d944786b533939c5d7d53e0ab30f03ee049e902734b6345cc500fd73f", + "other_metric_definition_sha256": "ffb7e85d94549dee93f799571ef73b2db74d61b37cf20019994f663b1d69392e", + "mode": "paired" + }, + { + "other_run_id": "f0f1b8a599044db19c8734c81fc78c59", + "checkpoint_sha256": "4e7207afbfd9ae78f0c0c419a1273aa6ab2644d434369f75ce3570cc74a5d059", + "other_checkpoint_sha256": "50236279861b2280d34e0875e6e671f5cb6cb8c4c56e54c9dd2d367a2f40b9bb", + "evaluation_sha256": "0f30c63f5e6c00a8eb7cf90171c803bc1c5d1fe99ab6539817c087a8096d7b3f", + "other_evaluation_sha256": "016692bef7dd714c1ba7f2b3d7db8a0e38db59745176011ee6b3151e8fca8860", + "metric_id": "loss", + "metric_definition_sha256": "4bb2d60d944786b533939c5d7d53e0ab30f03ee049e902734b6345cc500fd73f", + "other_metric_definition_sha256": "ffb7e85d94549dee93f799571ef73b2db74d61b37cf20019994f663b1d69392e", + "mode": "side_by_side" + } + ], + "run_ids": [ + "f0f1b8a599044db19c8734c81fc78c59", + "29e102331db74dbc8c3e39cdba2149d5", + "b14204732d8740babe198a5cb1fe2779" + ], + "release_ids": [ + "4024b110e8fc453bc2376cef4c416d89af29a7e4fa887569d43764989ec04b27", + "5c417159660a0a0ea20d23857f2ce5d01fe7ebb794d8627c525c1c6106f68601" + ], + "training": true, + "quality_claim": false, + "fixture_provenance": "12 CC0 authored independent images imported and reviewed through ordinary Data UI", + "access_projection_test": "403 transport substitution; backend tests own actual revoke enforcement", + "denied_projection": { + "status": "Evidence access revoked", + "privateNodes": 0 + }, + "recovered_projection": { + "run_id": "b14204732d8740babe198a5cb1fe2779", + "checkpoint_count": 2, + "retained_chart": true + } +} \ No newline at end of file diff --git a/docs/plans/retained-analysis/reports/ci-qualification-20261020/schema-cleanup.json b/docs/plans/retained-analysis/reports/ci-qualification-20261020/schema-cleanup.json new file mode 100644 index 00000000..e1afc379 --- /dev/null +++ b/docs/plans/retained-analysis/reports/ci-qualification-20261020/schema-cleanup.json @@ -0,0 +1,25 @@ +{ + "schema": "catalog_8faa508de2e54448925420da15fa406c", + "dataset_id": "8faa508de2e54448925420da15fa406c", + "reserved_before_creation": true, + "expected_owner": "tuldok_task", + "app_stopped_before_drop": true, + "observed_runs": [ + { + "id": "29e102331db74dbc8c3e39cdba2149d5", + "state": "completed" + }, + { + "id": "b14204732d8740babe198a5cb1fe2779", + "state": "completed" + }, + { + "id": "f0f1b8a599044db19c8734c81fc78c59", + "state": "completed" + } + ], + "scope": "only exact preregistered task-owned fresh schema", + "removed": true, + "observed_at": "2026-10-20T02:37:29.683141+00:00", + "local_catalog_directory": "retained inert under /tmp; PostgreSQL schema removed" +} diff --git a/docs/plans/retained-analysis/reports/ci-qualification-20261020/schema-reservation.json b/docs/plans/retained-analysis/reports/ci-qualification-20261020/schema-reservation.json new file mode 100644 index 00000000..d9e0feaf --- /dev/null +++ b/docs/plans/retained-analysis/reports/ci-qualification-20261020/schema-reservation.json @@ -0,0 +1,8 @@ +{ + "schema": "catalog_8faa508de2e54448925420da15fa406c", + "dataset_id": "8faa508de2e54448925420da15fa406c", + "owner": "PR111 CI qualification", + "state": "created-by-normal-Metadata", + "server": "PostgreSQL 17.6 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0, 64-bit", + "catalog_path": "/tmp/tuldok-model-development-ESKMk7/data" +} diff --git a/tests/browser_model_development.cjs b/tests/browser_model_development.cjs index 62087636..6f907fa4 100644 --- a/tests/browser_model_development.cjs +++ b/tests/browser_model_development.cjs @@ -553,11 +553,16 @@ function launch(command, args, options) { pausedRequest=null;await click('[data-model-checkpoint]');await until(()=>pausedRequest); await send('Fetch.fulfillRequest',{requestId:pausedRequest,responseCode:403,responseHeaders:[{name:'Content-Type',value:'application/json'}],body:Buffer.from(JSON.stringify({error:'Evidence access revoked',code:'forbidden'})).toString('base64')}); await send('Fetch.disable');pausedRequest=null; - await until(()=>text('.model-evidence').then(value=>value?.includes('Evidence access revoked'))); - assert.equal(await evaluate('document.querySelectorAll("[data-model-checkpoint]").length'),0); - assert.equal(await evaluate('!!document.getElementById("model-probe")'),false); - await click('#real-runs-refresh');await until(()=>evaluate('document.querySelectorAll("[data-model-checkpoint]").length===2')); - check('H5 delayed query cannot override navigation; denied evidence clears checkpoint/probe values and explicit refresh recovers'); + // Runs owns current denials and removes every private projection, including + // the model panel that used to contain this error. Refresh is an explicit read. + await until(()=>text('#real-runs-root .real-status').then(value=>value?.includes('Evidence access revoked'))); + const deniedProjection=await evaluate(`({status:document.querySelector('#real-runs-root .real-status')?.textContent, + privateNodes:document.querySelectorAll('#real-runs-root .model-evidence,#real-runs-root .metric-grid,#real-runs-root [data-retained-analysis],#real-runs-root [data-real-run],#real-runs-root [data-model-checkpoint],#real-runs-root #model-probe').length})`); + assert.equal(deniedProjection.privateNodes,0,'A current evidence denial clears all private Runs content'); + await click('#real-runs-refresh'); + await until(()=>evaluate(`!!document.querySelector('[data-real-run="${third.id}"][aria-current="true"]')&&document.querySelectorAll('[data-model-checkpoint]').length===2&&!!document.querySelector('#real-runs-root .metric-grid')&&!!document.querySelector('#real-runs-root [data-retained-analysis] svg')`)); + const recoveredProjection={run_id:third.id,checkpoint_count:await evaluate('document.querySelectorAll("[data-model-checkpoint]").length'),retained_chart:true}; + check('H5 delayed query cannot override navigation; denied evidence clears all private Runs content and explicit refresh recovers the exact Run, checkpoints, metrics and retained chart'); await screenshot('corrected-evidence-390',390,844);await screenshot('corrected-evidence-1440',1440,900); // Native system preference, keyboard focus and real retained evidence at both requested widths. await send('Emulation.setEmulatedMedia',{features:[{name:'prefers-color-scheme',value:'dark'}]}); @@ -587,7 +592,7 @@ function launch(command, args, options) { (lineageProof.dark_checks??=[]).push(colors); } assert.deepEqual(errors,[]);assert.ok(!serverErrors.includes('Traceback'),serverErrors); - fs.writeFileSync(path.join(report,'receipt.json'),JSON.stringify({source_commit:execFileSync('git',['rev-parse','HEAD'],{cwd:root,encoding:'utf8'}).trim(),dirty:!!execFileSync('git',['status','--porcelain'],{cwd:root,encoding:'utf8'}).trim(),command:'node tests/browser_model_development.cjs',source_sha256:sourceHashes,dark_checks:darkChecks,catalog_path:path.join(temporary,'data'),browser:(await send('Browser.getVersion')).product,checks,captures,lineage:lineageProof,compare_selectors:compareRequests,run_ids:[run.id,second.id,third.id],release_ids:[releaseId,correctedId],training:true,quality_claim:false,fixture_provenance:'12 CC0 authored independent images imported and reviewed through ordinary Data UI',access_projection_test:'403 transport substitution; backend tests own actual revoke enforcement'},null,2)); + fs.writeFileSync(path.join(report,'receipt.json'),JSON.stringify({source_commit:execFileSync('git',['rev-parse','HEAD'],{cwd:root,encoding:'utf8'}).trim(),dirty:!!execFileSync('git',['status','--porcelain'],{cwd:root,encoding:'utf8'}).trim(),command:'node tests/browser_model_development.cjs',source_sha256:sourceHashes,dark_checks:darkChecks,catalog_path:path.join(temporary,'data'),browser:(await send('Browser.getVersion')).product,checks,captures,lineage:lineageProof,compare_selectors:compareRequests,run_ids:[run.id,second.id,third.id],release_ids:[releaseId,correctedId],training:true,quality_claim:false,fixture_provenance:'12 CC0 authored independent images imported and reviewed through ordinary Data UI',access_projection_test:'403 transport substitution; backend tests own actual revoke enforcement',denied_projection:deniedProjection,recovered_projection:recoveredProjection},null,2)); console.log('PASS real model development gate:',report); })().catch(async error=>{ console.error(error);console.error('Application stderr:',serverErrors); From abbae728434fa0670478e12216a1d94603a97daf Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Oct 2026 03:31:05 +0000 Subject: [PATCH 5/8] test: synchronize caption browser dialogs and bound failures --- .../caption-dialog-ci-20261020/acceptance.md | 63 ++++++++++++++++ .../actual-captions.log | 35 +++++++++ .../captions-desktop.jpg | Bin 0 -> 103658 bytes .../captions-narrow.jpg | Bin 0 -> 45674 bytes .../cdp-regression.log | 3 + .../caption-dialog-ci-20261020/cleanup.json | 17 +++++ .../original-failure-excerpt.log | 6 ++ .../original-task-observation.json | 29 ++++++++ .../owned-cleanup-regression.log | 1 + .../qualification.json | 45 ++++++++++++ .../caption-dialog-ci-20261020/receipt.json | 41 +++++++++++ .../schema-cleanup-attempt-01.json | 13 ++++ .../schema-cleanup.json | 15 ++++ .../schema-reservation-attempt-01.json | 8 +++ .../schema-reservation.json | 8 +++ tests/browser_captions.cjs | 65 +++++++++++------ tests/browser_cdp_session.cjs | 58 +++++++++++++++ tests/test_browser_cdp_session.cjs | 67 ++++++++++++++++++ 18 files changed, 453 insertions(+), 21 deletions(-) create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/acceptance.md create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/actual-captions.log create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/captions-desktop.jpg create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/captions-narrow.jpg create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/cdp-regression.log create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/cleanup.json create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/original-failure-excerpt.log create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/original-task-observation.json create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/owned-cleanup-regression.log create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/qualification.json create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/receipt.json create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/schema-cleanup-attempt-01.json create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/schema-cleanup.json create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/schema-reservation-attempt-01.json create mode 100644 docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/schema-reservation.json create mode 100644 tests/browser_cdp_session.cjs create mode 100644 tests/test_browser_cdp_session.cjs diff --git a/docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/acceptance.md b/docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/acceptance.md new file mode 100644 index 00000000..449dd98e --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/acceptance.md @@ -0,0 +1,63 @@ +# Caption browser dialog CI repair + +The cancelled obsolete PR105 duplicate run39349523584/job118390149863 reported +`No dialog is showing` at02:06:23, with no runtime exceptions. It produced no +completed page diagnostics before manual cancellation at03:22:40. The original +[observation](original-task-observation.json) and [failure excerpt](original-failure-excerpt.log) +retain its cancelled outcome and exact full-log/raw-response identities. A +same-head primary passed. This is a nondeterministic harness failure, with no +product-failure claim. A late modal blocking the old diagnostic evaluation is a +source-supported hypothesis; the hosted log contains no modal-event trace. + +The repair starts from published PR111 head +`0ba4db01f04a77c262eb4b397f88849e9688b5ab` on +`fix/captions-dialog-ci-qualification-20261020`. Its implementation write set is +`tests/browser_captions.cjs`, `tests/browser_cdp_session.cjs` and +`tests/test_browser_cdp_session.cjs`. Product code and all original assertions +are unchanged. The existing caption CI entrypoint awaits the focused regression +before launching the browser, so no workflow change is needed. + +Each modal expectation is armed before the triggering click. The helper waits +for the fresh exact confirm type/message, handles the selected decision once, +then awaits the original click command. Cancel retains the unsaved caption; +accept restores the saved caption; discard after a keyboard edit restores human +review. Unexpected and absent dialogs fail. No autoaccept or ignored protocol +error replaces these witnesses. + +CDP requests expire, timed-out replies are ignored, timers clear on terminal +outcomes, and socket closure/error drains pending requests. Click rejections +are observed immediately. Diagnostics skip a known open modal and otherwise +have a separate one-second deadline. The caption fixture reuses the accepted +browser startup and owned-child shutdown helpers, then removes only its own +temporary directory with bounded retries after all children exit. + +[Controlled protocol regression](cdp-regression.log) passed: a180ms delayed +opening reliably defeats the old100ms handling and yields the original-32602 +error; a blocked diagnostic expires. Event-owned cancel/accept/discard, +missing/wrong dialogs, trigger rejection, request timeout, late reply and +socket close/error cases pass. This controlled protocol reproduction does not +claim to reconstruct the original hosted browser scheduling. + +[Actual caption entrypoint](actual-captions.log), [source-bound receipt](receipt.json) +and [qualification](qualification.json) passed using PostgreSQL17.6, +Python3.12.14 and Chromium151. All original edit/draft/review/reopen/filter, +keyboard review reset, repeated-submit, cancel/discard, four-record exact ZIP +and390px assertions remain. The real browser observes modal decisions +`false,true,true`. The fixture uses the existing local controlled generation +provider; it is actual app/HTTP/PostgreSQL/Chromium evidence, with no live-model +or training claim. Desktop and narrow captures are retained beside the receipt. + +The existing [owned-child regression](owned-cleanup-regression.log), all three +Node syntax checks and `git diff --check` passed. [Child cleanup](cleanup.json) +confirms both owned handles exited before temporary removal. +[Schema cleanup](schema-cleanup.json) confirms the final preregistered fresh +schema was dropped and queried absent, with five records and zero workspace +Runs before disposal. The preliminary complete browser run used a different +preregistered schema, also dropped and queried absent. Its source predates the +CI-entrypoint regression call; only the final run is the source-bound acceptance. + +No heavy CPU suite, performance comparison, model-quality, scientific acceptance +or CUDA claim is made. Original failures and source attributions remain intact. +Root owns independent review, serial publication/integration after PR111 and +cleanup. The task worktree `/workspace/Tuldok-captions-dialog-ci-repair-20261020` +is retained-protected by its named branch until root accepts and disposes it. diff --git a/docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/actual-captions.log b/docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/actual-captions.log new file mode 100644 index 00000000..8fa4b2e7 --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/actual-captions.log @@ -0,0 +1,35 @@ +PASS reproduced fixed100ms race: delayed180ms confirm rejects premature handling; blocked diagnostics time out +PASS fresh delayed cancel/accept/discard, absent dialog, trigger failure, bounded request, late reply and socket-close drainage +PASS unexpected dialog fails closed and socket error drains owned requests +[112014:112041:1020/032849.559242:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory +[112014:112041:1020/032849.565241:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix") +[112014:112041:1020/032849.565717:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory +[112014:112041:1020/032849.565746:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory +[112014:112041:1020/032849.565752:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix") +[112014:112053:1020/032849.581169:ERROR:content/browser/zygote_host/zygote_host_impl_linux.cc:279] Failed to adjust OOM score of renderer with pid 112055: Read-only file system (30) +[112014:112041:1020/032850.176012:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix") +[112014:112041:1020/032850.250225:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix") +[112014:112053:1020/032850.254782:ERROR:content/browser/zygote_host/zygote_host_impl_linux.cc:279] Failed to adjust OOM score of renderer with pid 112125: Read-only file system (30) +[112014:112014:1020/032850.278305:ERROR:dbus/object_proxy.cc:572] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: +[112014:112014:1020/032850.278374:ERROR:dbus/object_proxy.cc:572] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: + +DevTools listening on ws://127.0.0.1:46283/devtools/browser/5e6d27b3-ae4d-4450-985f-00473484f268 +[112014:112041:1020/032850.280676:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix") +[112014:112041:1020/032850.280695:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix") +[112014:112014:1020/032850.281416:ERROR:dbus/object_proxy.cc:572] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: +[112014:112014:1020/032850.285386:ERROR:dbus/object_proxy.cc:572] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: +[112014:112041:1020/032850.287808:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory +[112014:112041:1020/032850.287830:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Failed to connect to socket /run/dbus/system_bus_socket: No such file or directory +[112014:112053:1020/032850.338429:ERROR:content/browser/zygote_host/zygote_host_impl_linux.cc:279] Failed to adjust OOM score of renderer with pid 112151: Read-only file system (30) +[112014:112053:1020/032850.379160:ERROR:content/browser/zygote_host/zygote_host_impl_linux.cc:279] Failed to adjust OOM score of renderer with pid 112160: Read-only file system (30) +[112014:112053:1020/032850.384271:ERROR:content/browser/zygote_host/zygote_host_impl_linux.cc:279] Failed to adjust OOM score of renderer with pid 112161: Read-only file system (30) +[112014:112014:1020/032850.405991:ERROR:dbus/object_proxy.cc:572] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: +[112014:112014:1020/032850.407079:ERROR:dbus/object_proxy.cc:572] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: +[112014:112041:1020/032850.407536:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix") +[112014:112014:1020/032850.415146:ERROR:dbus/object_proxy.cc:572] Failed to call method: org.freedesktop.DBus.Properties.GetAll: object_path= /org/freedesktop/UPower/devices/DisplayDevice: unknown error type: +[112014:112014:1020/032850.441651:ERROR:dbus/object_proxy.cc:572] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: +[112014:112041:1020/032850.441785:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix") +[112014:112014:1020/032850.465917:ERROR:dbus/object_proxy.cc:572] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: +[112014:112041:1020/032850.466040:ERROR:dbus/bus.cc:405] Failed to connect to the bus: Could not parse server address: Unknown address type (examples of valid types are "tcp" and on UNIX "unix") +[112014:112014:1020/032850.475312:ERROR:dbus/object_proxy.cc:572] Failed to call method: org.freedesktop.DBus.NameHasOwner: object_path= /org/freedesktop/DBus: unknown error type: +Caption Chromium edit/draft/review/reopen/filter/export, keyboard review reset, discard, repeated-submit and narrow layout passed. /tmp/tuldok-caption-dialog-repair/qa/image-caption-exports/run-Gj153o diff --git a/docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/captions-desktop.jpg b/docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/captions-desktop.jpg new file mode 100644 index 0000000000000000000000000000000000000000..51d8745ba94bfbf51b5e1135e3844a4a88a8d570 GIT binary patch literal 103658 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

ssY8tp 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

ns5thH$u=ft>WYZxVhImV|?w(kP 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

*FM|mO5oHO=Q%YbQqV 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 literal 0 HcmV?d00001 diff --git a/docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/captions-narrow.jpg b/docs/plans/lab-workflow-reliability/reports/caption-dialog-ci-20261020/captions-narrow.jpg new file mode 100644 index 0000000000000000000000000000000000000000..28a1549efe1fa6b77a2e4737f46337f93575f981 GIT binary patch literal 45674 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[file,require('node:crypto').createHash('sha256').update(fs.readFileSync(path.join(root,file))).digest('hex')])); +let ws, session, inspect; +const dialogChecks=[]; const errors=[]; const pause=ms=>new Promise(resolve=>setTimeout(resolve,ms)); -async function until(fn){for(let i=0;i<150;i++){const value=await fn();if(value)return value;await pause(100);}throw Error('Timed out');} +async function until(fn){const deadline=performance.now()+15000;while(performance.now(){ - fs.mkdirSync(qaDirectory(root,'image-caption-exports'),{recursive:true}); + await require('./test_browser_cdp_session.cjs').verifyCDPSession(); const server=launch('python3',['-u','tests/browser_server.py','--port','0','--data',path.join(temporary,'data')],{cwd:root,stdio:['ignore','pipe','pipe']}); let output='',stderr='';server.stdout.on('data',data=>output+=data);server.stderr.on('data',data=>stderr+=data); const port=await until(()=>output.match(/127\.0\.0\.1:(\d+)/)?.[1]); await fixtureAuth.register('http://127.0.0.1:'+port,path.join(temporary,'data'),root); - launch(process.env.BROWSER||'/usr/bin/chromium',['--headless','--no-sandbox','--disable-gpu','--no-first-run','--no-default-browser-check','--remote-debugging-port=0','--window-size=1400,950','--user-data-dir='+path.join(temporary,'browser'),'about:blank'],{stdio:['ignore','ignore','inherit'],env:{...process.env,HOME:temporary,XDG_CONFIG_HOME:temporary,XDG_CACHE_HOME:temporary}}); + const browser=launch(process.env.BROWSER||'/usr/bin/chromium',['--headless','--no-sandbox','--disable-gpu','--no-first-run','--no-default-browser-check','--remote-debugging-port=0','--window-size=1400,950','--user-data-dir='+path.join(temporary,'browser'),'about:blank'],{stdio:['ignore','ignore','inherit'],env:{...process.env,XDG_CONFIG_HOME:temporary,XDG_CACHE_HOME:temporary}}); const active=path.join(temporary,'browser','DevToolsActivePort'); - const debugPort=await until(()=>fs.existsSync(active)&&fs.readFileSync(active,'utf8').split('\n')[0]); - const tabs=await(await fetch('http://127.0.0.1:'+debugPort+'/json')).json(); + const debugPort=await waitForDebugger(browser,active); + const tabs=await(await fetch('http://127.0.0.1:'+debugPort+'/json',{signal:AbortSignal.timeout(10000)})).json(); const target=tabs.find(tab=>tab.type==='page' && tab.url==='about:blank'); assert.ok(target,'Expected the explicitly launched blank page target'); ws=new WebSocket(target.webSocketDebuggerUrl); - await new Promise((resolve,reject)=>{ws.onopen=resolve;ws.onerror=reject;}); - let id=0;const pending=new Map(); - ws.onmessage=event=>{const message=JSON.parse(event.data);loads.observe(message);if(message.id){const task=pending.get(message.id);pending.delete(message.id);message.error?task.reject(message.error):task.resolve(message.result);}if(message.method==='Runtime.exceptionThrown')errors.push(message.params.exceptionDetails);}; - const send=(method,params={})=>new Promise((resolve,reject)=>{pending.set(++id,{resolve,reject});ws.send(JSON.stringify({id,method,params}));}); + await new Promise((resolve,reject)=>{ + const timer=setTimeout(()=>reject(Error('CDP connection timed out')),10000); + ws.onopen=()=>{clearTimeout(timer);resolve();};ws.onerror=()=>{clearTimeout(timer);reject(Error('CDP connection failed'));}; + }); + session=cdpSession(ws,{onEvent:message=>{loads.observe(message);if(message.method==='Runtime.exceptionThrown')errors.push(message.params.exceptionDetails);}}); + const {send}=session; const evaluate=async expression=>{const result=await send('Runtime.evaluate',{expression,awaitPromise:true,returnByValue:true});if(result.exceptionDetails)throw Error(JSON.stringify(result.exceptionDetails));return result.result.value;}; - inspect=()=>evaluate('JSON.stringify({url:location.href,ready:document.readyState,notice:document.getElementById("notice")?.textContent,body:document.body?.innerText.slice(0,1500),viewport:innerWidth,documentWidth:document.documentElement.scrollWidth,overflow:[...document.querySelectorAll("body *")].filter(e=>e.getBoundingClientRect().right>innerWidth || e.scrollWidth>e.clientWidth+1).map(e=>({tag:e.tagName,id:e.id,class:e.className,right:e.getBoundingClientRect().right,width:e.getBoundingClientRect().width})).slice(0,30)})'); + inspect=()=>send('Runtime.evaluate',{expression:'JSON.stringify({url:location.href,ready:document.readyState,notice:document.getElementById("notice")?.textContent,body:document.body?.innerText.slice(0,1500),viewport:innerWidth,documentWidth:document.documentElement.scrollWidth,overflow:[...document.querySelectorAll("body *")].filter(e=>e.getBoundingClientRect().right>innerWidth || e.scrollWidth>e.clientWidth+1).map(e=>({tag:e.tagName,id:e.id,class:e.className,right:e.getBoundingClientRect().right,width:e.getBoundingClientRect().width})).slice(0,30)})',awaitPromise:true,returnByValue:true},1000).then(value=>value.result?.value); const click=id=>evaluate('document.getElementById('+JSON.stringify(id)+').click()'); const fill=(id,value)=>evaluate('(()=>{const e=document.getElementById('+JSON.stringify(id)+');e.value='+JSON.stringify(value)+';e.dispatchEvent(new Event("input",{bubbles:true}));e.dispatchEvent(new Event("change",{bubbles:true}));})()'); await send('Page.enable');await send('Page.setLifecycleEventsEnabled',{enabled:true});await send('Runtime.enable'); @@ -67,10 +75,14 @@ function launch(command,args,options={}){const child=spawn(command,args,options) assert.equal(await evaluate('document.getElementById("caption").value'),'A dark canvas in a procedural rectangle test scene.'); // Unsaved caption changes survive cancellation of a navigation prompt. await fill('caption','Keep this unsaved caption'); - const blockedNavigation=click('reload'); - await pause(100);await send('Page.handleJavaScriptDialog',{accept:false});await blockedNavigation; + const discardMessage='Discard unsaved annotation, rights-note, response or judgment edits?'; + const answerDiscard=async accept=>{ + const event=await session.withDialog(()=>click('reload'),{accept,message:discardMessage}); + dialogChecks.push({type:event.type,message:event.message,accept}); + }; + await answerDiscard(false); assert.equal(await evaluate('document.getElementById("caption").value'),'Keep this unsaved caption'); - const reload=click('reload');await pause(100);await send('Page.handleJavaScriptDialog',{accept:true});await reload; + await answerDiscard(true); await until(()=>evaluate('document.getElementById("caption").value==="A dark canvas in a procedural rectangle test scene."')); await fill('record-review','human_reviewed'); await evaluate('document.getElementById("editor").requestSubmit();document.getElementById("editor").requestSubmit();'); @@ -84,7 +96,7 @@ function launch(command,args,options={}){const child=spawn(command,args,options) await evaluate('document.getElementById("caption").focus();document.getElementById("caption").setSelectionRange(0,0)'); await send('Input.insertText',{text:'A test view. '}); assert.equal(await evaluate('document.getElementById("record-review").value'),'draft'); - const discard=click('reload');await pause(100);await send('Page.handleJavaScriptDialog',{accept:true});await discard; + await answerDiscard(true); await until(()=>evaluate('document.getElementById("record-review").value==="human_reviewed"')); // A matching draft caption is visible before review filtering and must be excluded afterward. await openName(names[4]);await fill('task','image_caption');await fill('caption','A dark canvas in a procedural rectangle test scene.'); @@ -101,14 +113,25 @@ function launch(command,args,options={}){const child=spawn(command,args,options) const release=await evaluate('document.querySelector("#release-result a").href'); const archive=await fetch(release);assert.equal(archive.status,200); const zipPath=path.join(temporary,'captions.zip');fs.writeFileSync(zipPath,Buffer.from(await archive.arrayBuffer())); - const {execFileSync}=require('node:child_process'); execFileSync('python3',['-c',`import json,zipfile;z=zipfile.ZipFile(${JSON.stringify(zipPath)});m=json.loads(z.read('manifest.json'));assert m['format']=='image_caption_v1';assert len(m['records'])==4;assert len(m['warnings'])==4;assert all(w.startswith('Small image:') for w in m['warnings']);assert set(m['split_mapping'].values())=={'train','val','test'};[(lambda rows: (len(rows)>0 or (_ for _ in ()).throw(AssertionError('Empty split'))))([json.loads(x) for x in z.read(s+'/metadata.jsonl').splitlines()]) for s in ('train','val','test')]`]); assert.ok((await evaluate('document.getElementById("notice").textContent')).includes('4 export warnings; inspect manifest.json.')); const desktop=await send('Page.captureScreenshot',screenshotOptions); - fs.writeFileSync(path.join(qaDirectory(root,'image-caption-exports'),'captions-desktop.jpg'),Buffer.from(desktop.data,'base64')); + fs.writeFileSync(path.join(report,'captions-desktop.jpg'),Buffer.from(desktop.data,'base64')); await send('Emulation.setDeviceMetricsOverride',{width:390,height:844,deviceScaleFactor:1,mobile:false}); const shot=await send('Page.captureScreenshot',screenshotOptions); - fs.writeFileSync(path.join(qaDirectory(root,'image-caption-exports'),'captions-narrow.jpg'),Buffer.from(shot.data,'base64')); + fs.writeFileSync(path.join(report,'captions-narrow.jpg'),Buffer.from(shot.data,'base64')); assert.ok(await evaluate('document.documentElement.scrollWidth<=innerWidth'), 'Narrow caption layout must not overflow'); - assert.deepEqual(errors,[]);console.log('Caption Chromium edit/draft/review/reopen/filter/export, keyboard review reset, discard, repeated-submit and narrow layout passed.'); -})().catch(async error=>{console.error(error);console.error('Runtime errors:',JSON.stringify(errors));if(inspect)try{console.error('Page diagnostics:',await inspect());}catch(diagnostic){console.error('Diagnostics failed:',diagnostic);}process.exitCode=1;}).finally(async()=>{if(ws)ws.close();for(const child of children)child.kill();await pause(200);fs.rmSync(temporary,{recursive:true,force:true});}); + assert.deepEqual(errors,[]); + fs.writeFileSync(path.join(report,'receipt.json'),JSON.stringify({status:'passed',command:'node tests/browser_captions.cjs',source_commit:execFileSync('git',['rev-parse','HEAD'],{cwd:root,encoding:'utf8'}).trim(),source_sha256:sourceHashes,browser:(await send('Browser.getVersion')).product,catalog_id:JSON.parse(fs.readFileSync(path.join(temporary,'data','.tuldok.json'),'utf8')).dataset_id,dialog_checks:dialogChecks,exported_records:4,zip_sha256:require('node:crypto').createHash('sha256').update(fs.readFileSync(zipPath)).digest('hex'),checks:['cancel preserves unsaved caption','discard restores saved caption','keyboard edit resets review; discard restores human review','draft exclusion and exact caption ZIP','reopen, filters, repeated submit and390px layout'],scope:'Actual app/PostgreSQL/Chromium caption journey with existing controlled generation provider; no model-quality claim'},null,2)+'\n'); + console.log('Caption Chromium edit/draft/review/reopen/filter/export, keyboard review reset, discard, repeated-submit and narrow layout passed.',report); +})().catch(async error=>{ + console.error(error);console.error('Runtime errors:',JSON.stringify(errors)); + if(session?.hasDialog())console.error('Page diagnostics skipped: JavaScript dialog is open.'); + else if(inspect)try{console.error('Page diagnostics:',await inspect());}catch(diagnostic){console.error('Diagnostics failed:',diagnostic);} + process.exitCode=1; +}).finally(async()=>{ + if(session)session.close();else if(ws)ws.close(); + await stopOwnedChildren(children); + fs.rmSync(temporary,{recursive:true,force:true,maxRetries:10,retryDelay:100}); + fs.writeFileSync(path.join(report,'cleanup.json'),JSON.stringify({temporary,removed:!fs.existsSync(temporary),children:children.map(child=>({pid:child.pid,exit_code:child.exitCode,signal:child.signalCode})),scope:'Only test-owned child handles; all exited before temporary removal'},null,2)+'\n'); +}).catch(error=>{console.error('Owned caption fixture cleanup failed:',error);process.exitCode=1;}); diff --git a/tests/browser_cdp_session.cjs b/tests/browser_cdp_session.cjs new file mode 100644 index 00000000..0be82af4 --- /dev/null +++ b/tests/browser_cdp_session.cjs @@ -0,0 +1,58 @@ +'use strict'; +// Test-owned protocol requests and modal expectations share one socket lifetime. +function cdpSession(socket,{timeoutMs=15000,onEvent=()=>{}}={}){ + let sequence=0,closed=false,dialog=null,expectation=null; + const pending=new Map(); + function fail(error){ + closed=true; + for(const task of pending.values()){clearTimeout(task.timer);task.reject(error);} + pending.clear();expectation?.reject(error); + } + function send(method,params={},budgetMs=timeoutMs){ + return new Promise((resolve,reject)=>{ + if(closed){reject(Error('CDP socket is closed'));return;} + const id=++sequence; + const timer=setTimeout(()=>{pending.delete(id);reject(Error('CDP timeout: '+method));},budgetMs); + pending.set(id,{resolve,reject,timer}); + try{socket.send(JSON.stringify({id,method,params}));} + catch(error){clearTimeout(timer);pending.delete(id);reject(error);} + }); + } + socket.addEventListener('message',event=>{ + const message=JSON.parse(event.data); + if(message.id){ + const task=pending.get(message.id); + if(!task)return; // Replies may arrive after the owning request timed out. + pending.delete(message.id);clearTimeout(task.timer); + message.error?task.reject(Object.assign(Error(message.error.message),{code:message.error.code})):task.resolve(message.result); + return; + } + if(message.method==='Page.javascriptDialogOpening'){ + dialog=message.params;expectation?.resolve(dialog); + } + if(message.method==='Page.javascriptDialogClosed')dialog=null; + onEvent(message); + }); + socket.addEventListener('close',()=>fail(Error('CDP socket closed'))); + socket.addEventListener('error',()=>fail(Error('CDP socket failed'))); + async function withDialog(action,{accept,type='confirm',message:expectedMessage,waitMs=timeoutMs}={}){ + if(expectation||dialog)throw Error('A CDP dialog is already owned'); + let timer,triggered,own; + const opened=new Promise((resolve,reject)=>{ + own={resolve,reject};expectation=own; + timer=setTimeout(()=>reject(Error('CDP dialog opening timed out')),waitMs); + }); + try{ + // Arm the event before triggering. The action itself may wait for dismissal. + triggered=Promise.resolve().then(action); + triggered.catch(error=>own.reject(error)); + const event=await opened; + if(event.type!==type||event.message!==expectedMessage)throw Error('Unexpected CDP dialog: '+JSON.stringify(event)); + await send('Page.handleJavaScriptDialog',{accept}); + await triggered; + return event; + }finally{clearTimeout(timer);if(expectation===own)expectation=null;} + } + return {send,withDialog,hasDialog:()=>dialog!==null,close(){fail(Error('CDP session disposed'));socket.close();}}; +} +module.exports={cdpSession}; diff --git a/tests/test_browser_cdp_session.cjs b/tests/test_browser_cdp_session.cjs new file mode 100644 index 00000000..2f05d359 --- /dev/null +++ b/tests/test_browser_cdp_session.cjs @@ -0,0 +1,67 @@ +'use strict'; +// Controlled protocol timing proves synchronization/deadlines, not product UI. +const assert=require('node:assert/strict'); +const {cdpSession}=require('./browser_cdp_session.cjs'); +const pause=ms=>new Promise(resolve=>setTimeout(resolve,ms)); +const message='Discard unsaved annotation, rights-note, response or judgment edits?'; +class Socket extends EventTarget{ + constructor(){super();this.dialog=false;this.decisions=[];this.held=[];this.timers=[];} + receive(value){this.dispatchEvent(new MessageEvent('message',{data:JSON.stringify(value)}));} + send(raw){ + const {id,method,params}=JSON.parse(raw);this.lastId=id; + if(method==='Runtime.evaluate'&¶ms.expression==='open'){ + this.held.push(id); + this.timers.push(setTimeout(()=>{this.dialog=true;this.receive({method:'Page.javascriptDialogOpening',params:{type:'confirm',message}});},180));return; + } + if(method==='Runtime.never'||method==='Runtime.evaluate'&&this.dialog){this.held.push(id);return;} + if(method==='Page.handleJavaScriptDialog'){ + if(!this.dialog){this.receive({id,error:{code:-32602,message:'No dialog is showing'}});return;} + this.decisions.push(params.accept);this.dialog=false;this.receive({method:'Page.javascriptDialogClosed',params:{result:params.accept}}); + for(const held of this.held.splice(0))this.receive({id:held,result:{result:{value:true}}}); + } + this.receive({id,result:{result:{value:true}}}); + } + close(){this.timers.forEach(clearTimeout);this.dispatchEvent(new Event('close'));} +} +async function verifyCDPSession(){ + const oldSocket=new Socket(),old=cdpSession(oldSocket,{timeoutMs:500}); + try{ + const click=old.send('Runtime.evaluate',{expression:'open'});click.catch(()=>{}); + await pause(100); + await assert.rejects(old.send('Page.handleJavaScriptDialog',{accept:false}),error=>error.code===-32602&&error.message==='No dialog is showing'); + await pause(100);assert.equal(old.hasDialog(),true,'The real protocol opening arrives after the obsolete fixed wait'); + const started=performance.now(); + await assert.rejects(old.send('Runtime.evaluate',{expression:'diagnostics'},25),/CDP timeout: Runtime.evaluate/); + assert.ok(performance.now()-started<250,'Late-modal diagnostics must terminate within their own budget'); + console.log('PASS reproduced fixed100ms race: delayed180ms confirm rejects premature handling; blocked diagnostics time out'); + }finally{old.close();} + const socket=new Socket(),session=cdpSession(socket,{timeoutMs:500}); + try{ + for(const accept of [false,true,true]){ + const event=await session.withDialog(()=>session.send('Runtime.evaluate',{expression:'open'}),{accept,message}); + assert.equal(event.type,'confirm');assert.equal(session.hasDialog(),false); + } + assert.deepEqual(socket.decisions,[false,true,true],'Each newly observed dialog is handled exactly once with its selected decision'); + await assert.rejects(session.withDialog(()=>Promise.resolve(),{accept:true,message,waitMs:20}),/dialog opening timed out/); + await assert.rejects(session.withDialog(()=>Promise.reject(Error('Trigger failed')),{accept:true,message}),/Trigger failed/); + await assert.rejects(session.send('Runtime.never',{},20),/CDP timeout/); + assert.doesNotThrow(()=>socket.receive({id:socket.lastId,result:{}}),'Late timed-out replies are harmless'); + await session.send('Browser.getVersion'); + const pending=session.send('Runtime.never');const rejected=assert.rejects(pending,/socket closed/);socket.close();await rejected; + console.log('PASS fresh delayed cancel/accept/discard, absent dialog, trigger failure, bounded request, late reply and socket-close drainage'); + }finally{session.close();} + for(const kind of ['wrong','error']){ + const socket=new Socket(),session=cdpSession(socket,{timeoutMs:500}); + try{ + if(kind==='wrong'){ + await assert.rejects(session.withDialog(()=>session.send('Runtime.evaluate',{expression:'open'}),{accept:true,message:'Wrong prompt'}),/Unexpected CDP dialog/); + assert.deepEqual(socket.decisions,[],'An unexpected prompt is never autoaccepted'); + }else{ + const pending=session.send('Runtime.never'),rejected=assert.rejects(pending,/socket failed/);socket.dispatchEvent(new Event('error'));await rejected; + } + }finally{session.close();} + } + console.log('PASS unexpected dialog fails closed and socket error drains owned requests'); +} +module.exports={verifyCDPSession}; +if(require.main===module)verifyCDPSession().catch(error=>{console.error(error);process.exitCode=1;}); From 29011daea37f101ee30be9bc10aab702a16c830a Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Oct 2026 04:28:43 +0000 Subject: [PATCH 6/8] fix: enable project opening after its controller binds --- .../project-startup-ci-20261020/acceptance.md | 57 +++ .../project-startup-ci-20261020/cleanup.json | 21 + .../controller.log | 1 + .../delay-project-module.cjs | 31 ++ .../green-cleanup.json | 17 + .../hosted-failure-disposition.json | 27 ++ .../hosted-failure-excerpt.log | 8 + .../original-entrypoint-delayed-red.log | 9 + .../project-startup-ci-20261020/page-load.log | 1 + .../post-exit-temporary-cleanup.json | 12 + .../qualification.json | 71 ++++ .../project-startup-ci-20261020/receipt.json | 390 ++++++++++++++++++ .../red-cleanup.json | 10 + .../red-schema-reservation.json | 6 + .../red-temporary-cleanup.json | 14 + .../red1-cleanup.json | 5 + .../schema-reservation.json | 7 + .../scientific-fields-green.log | 8 + .../scientific-inspector-1440.jpg | Bin 0 -> 97427 bytes .../scientific-inspector-390.jpg | Bin 0 -> 47976 bytes static/workspace-projects.js | 1 + static/workspaces.html | 2 +- tests/browser_scientific_fields.cjs | 23 +- tests/test_workspace_project_startup.cjs | 33 ++ 24 files changed, 749 insertions(+), 5 deletions(-) create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/acceptance.md create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/cleanup.json create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/controller.log create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/delay-project-module.cjs create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/green-cleanup.json create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/hosted-failure-disposition.json create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/hosted-failure-excerpt.log create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/original-entrypoint-delayed-red.log create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/page-load.log create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/post-exit-temporary-cleanup.json create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/qualification.json create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/receipt.json create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/red-cleanup.json create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/red-schema-reservation.json create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/red-temporary-cleanup.json create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/red1-cleanup.json create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/schema-reservation.json create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/scientific-fields-green.log create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/scientific-inspector-1440.jpg create mode 100644 docs/plans/retained-analysis/reports/project-startup-ci-20261020/scientific-inspector-390.jpg create mode 100644 tests/test_workspace_project_startup.cjs diff --git a/docs/plans/retained-analysis/reports/project-startup-ci-20261020/acceptance.md b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/acceptance.md new file mode 100644 index 00000000..858f31ff --- /dev/null +++ b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/acceptance.md @@ -0,0 +1,57 @@ +# Project action startup qualification + +Base is the failed published PR111 head +`0ba4db01f04a77c262eb4b397f88849e9688b5ab`; branch +`fix/workspace-project-startup-ci-20261020` is owned by this repair. Root owns +serial publication and composition into the caption descendant. The production +write set is one initial `disabled` attribute in `static/workspaces.html` and +one owner-controlled enable in `static/workspace-projects.js`, after its action, +form and disposal listeners are installed. No API, source-data or scientific +contract changes. + +The [hosted failure disposition](hosted-failure-disposition.json) is the preserved +historical observation: run39360310903/job118424712559 failed the first project +open wait at59:77. Its [excerpt](hosted-failure-excerpt.log), exact raw/log hashes +and paths remain bound in [qualification](qualification.json). The hosted log +has no pointer/listener trace; its exact cause remains untraced. + +The [controlled red](original-entrypoint-delayed-red.log) runs the unmodified +0ba4 default scientific entrypoint with only actual module delivery delayed by +[the qualification driver](delay-project-module.cjs). It observes an enabled +button with null handler, an exact native pointer hit on `open-project`, and a +closed dialog. After the actual module bytes are released, the handler exists +and fixtures are ready, but the original missed action still times out at the +same59:77/64 path. No responses, handlers or source data are replaced. This proves +the controlled startup failure and excludes a geometry miss for that journey; +it does not invent a trace of the hosted scheduling. + +The [complete green default entrypoint](scientific-fields-green.log) holds the +actual owning module, verifies disabled initial markup and exact pointer hit, +proves an early disabled pointer cannot open a partial flow, releases the module +and runs the original native open/import/scientific journey. It passes all five +original checks plus the startup check: stale-hash refusal, exact time/stage/ +dtype/planes/signed-zero geometry, human review and frozen release, independent +cold NumPy custody, held import navigation fencing and actual app restart. +No scientific or model-quality acceptance is claimed. The [receipt](receipt.json) +binds all four changed source files and actual before/after control states. + +The [controller regression](controller.log), also awaited by the existing CI +entrypoint, proves module evaluation leaves the control disabled and owning +construction installs action/form/teardown before enabling. It then opens the +dialog synchronously and performs only an inspection read. The existing +[page-load barrier](page-load.log), three Node syntax checks and diff check pass. + +Local qualification uses actual PostgreSQL17.6, Python3.12.14, Chromium151 and +normal app/HTTP with existing headless/no-sandbox/disable-gpu flags. All three +exact preregistered schemas are [queried absent](green-cleanup.json); green had +two records, one project and zero Runs before disposal. Main owned children +exited before [initial temporary removal](cleanup.json). Brief Chrome descendant +cache recreation was observed; [post-exit exact-path cleanup](post-exit-temporary-cleanup.json) +records final removal after no matching processes remained. No process was +killed by inferred PID, and no unrelated catalog or path was touched. + +The clean task worktree `/workspace/Tuldok-project-startup-ci-repair-20261020` +is retained-protected by the repair branch for root's review and serial +integration. Root owns its later safe disposition. No108/112 source or ref was +changed. Independent review and new GitHub lifecycle execution remain separate +from these local evidence claims. diff --git a/docs/plans/retained-analysis/reports/project-startup-ci-20261020/cleanup.json b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/cleanup.json new file mode 100644 index 00000000..6d198929 --- /dev/null +++ b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/cleanup.json @@ -0,0 +1,21 @@ +{ + "temporary": "/tmp/tuldok-fields-browser-XT8B2u", + "removed": true, + "children": [ + { + "pid": 114816, + "exit_code": 0, + "signal": null + }, + { + "pid": 114823, + "exit_code": 0, + "signal": null + }, + { + "pid": 115078, + "exit_code": null, + "signal": "SIGTERM" + } + ] +} diff --git a/docs/plans/retained-analysis/reports/project-startup-ci-20261020/controller.log b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/controller.log new file mode 100644 index 00000000..52f31f69 --- /dev/null +++ b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/controller.log @@ -0,0 +1 @@ +PASS project startup markup disabled; owning constructor binds action, form and teardown before enable; first action opens synchronously and reads only diff --git a/docs/plans/retained-analysis/reports/project-startup-ci-20261020/delay-project-module.cjs b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/delay-project-module.cjs new file mode 100644 index 00000000..4e6812bf --- /dev/null +++ b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/delay-project-module.cjs @@ -0,0 +1,31 @@ +'use strict'; +// Qualification-only protocol timing: no responses or application handlers are substituted. +const Native=globalThis.WebSocket; +globalThis.WebSocket=class extends Native{ + constructor(...args){ + super(...args);this.nextInternal=100000000;this.callbacks=new Map();this.held=null;this.armed=false;this.witnessed=false;this.firstReleased=false;this.continued=false; + this.addEventListener('message',event=>{ + const value=JSON.parse(event.data); + if(this.callbacks.has(value.id)){const callback=this.callbacks.get(value.id);this.callbacks.delete(value.id);callback(value);} + if(value.method==='Fetch.requestPaused'&&value.params.request.url.endsWith('/workspace-projects.js')){this.held=value.params.requestId;console.log('STARTUP held actual workspace-projects.js response');this.releaseIfClicked();} + }); + } + own(method,params,callback=()=>{}){const id=++this.nextInternal;this.callbacks.set(id,callback);super.send(JSON.stringify({id,method,params}));} + send(raw){ + const value=JSON.parse(raw); + if(value.method==='Page.navigate'&&value.params.url.endsWith('/workspaces')&&!this.armed){this.armed=true;this.own('Fetch.enable',{patterns:[{urlPattern:'*/workspace-projects.js',requestStage:'Response'}]},()=>super.send(raw));return;} + if(value.method==='Input.dispatchMouseEvent'&&value.params.type==='mousePressed'&&!this.witnessed){ + this.witnessed=true;this.own('Runtime.evaluate',{expression:`JSON.stringify({disabled:document.getElementById('open-project').disabled,handler:typeof document.getElementById('open-project').onclick,dialog:document.getElementById('project-open-dialog').open,hit:document.elementFromPoint(${value.params.x},${value.params.y})?.id})`,returnByValue:true},reply=>{console.log('STARTUP before original first pointer click',reply.result?.result?.value);super.send(raw);});return; + } + super.send(raw); + if(this.witnessed&&value.method==='Input.dispatchMouseEvent'&&value.params.type==='mouseReleased'){this.firstReleased=true;this.releaseIfClicked();} + } + releaseIfClicked(){ + if(!this.held||!this.firstReleased||this.continued)return; + this.continued=true;const requestId=this.held;this.held=null; + setTimeout(()=>this.own('Fetch.continueRequest',{requestId},()=>{ + this.own('Fetch.disable',{}); + setTimeout(()=>this.own('Runtime.evaluate',{expression:"JSON.stringify({disabled:document.getElementById('open-project').disabled,handler:typeof document.getElementById('open-project').onclick,dialog:document.getElementById('project-open-dialog').open,status:document.getElementById('workspace-status').textContent})",returnByValue:true},reply=>console.log('STARTUP after original click and actual module release',reply.result?.result?.value)),500); + }),500); + } +}; diff --git a/docs/plans/retained-analysis/reports/project-startup-ci-20261020/green-cleanup.json b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/green-cleanup.json new file mode 100644 index 00000000..4aa10ba5 --- /dev/null +++ b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/green-cleanup.json @@ -0,0 +1,17 @@ +{ + "schema": "catalog_b15679e0a444459a83f1acce6dd3909d", + "reserved_before_creation": true, + "owned_children_exited": true, + "final_temporary_removed": true, + "counts": { + "workbench_records": 2, + "workspace_runs": 0, + "workspace_projects": 1 + }, + "removed_and_queried_absent": true, + "prior_red_schemas_rechecked_absent": [ + "catalog_a91651e7b01d45148d63ee0e3d87c82d", + "catalog_978e63d9ab6a49bc9b673eb0569f8f11" + ], + "observed_at": "2026-10-20T04:27:51.019863+00:00" +} diff --git a/docs/plans/retained-analysis/reports/project-startup-ci-20261020/hosted-failure-disposition.json b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/hosted-failure-disposition.json new file mode 100644 index 00000000..9611d2b6 --- /dev/null +++ b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/hosted-failure-disposition.json @@ -0,0 +1,27 @@ +{ + "observed_utc": "2026-10-20T04:20:09.421507+00:00", + "head": "0ba4db01f04a77c262eb4b397f88849e9688b5ab", + "run": 39360310903, + "job": 118424712559, + "conclusion": "failure", + "failed_steps": [ + { + "name": "Run node tests/browser_scientific_fields.cjs", + "status": "completed", + "conclusion": "failure", + "number": 44, + "started_at": "2026-10-20T04:15:40Z", + "completed_at": "2026-10-20T04:16:43Z" + } + ], + "successful_steps": 48, + "skipped_steps": 124, + "failure_location": "browser_scientific_fields.cjs openProject line59column77: firstdialog.open&&!submit.disabled wait", + "caption_race_equivalence": false, + "diagnosis": "Possible open-project control interactive before initializer handler ready; cause remains unproven until deterministic actual browser reproduction. Alternative dialog/roots availability still under independent examination.", + "decoded_log_sha256": "0c279bc15ca1488a9445b03763192fd6f4ab85c9c8ec1b8acb36d538a18b0e2b", + "source_author": "/root/pr111_ci_repair", + "independent_diagnosis_and_review": "/root/mcp_contract_ci_review", + "merge_clearance": false, + "other_pending_lifecycle_is_not_acceptance": true +} diff --git a/docs/plans/retained-analysis/reports/project-startup-ci-20261020/hosted-failure-excerpt.log b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/hosted-failure-excerpt.log new file mode 100644 index 00000000..7553362d --- /dev/null +++ b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/hosted-failure-excerpt.log @@ -0,0 +1,8 @@ +2026-10-20T04:16:43.4038356Z Error: Timed out +2026-10-20T04:16:43.4039321Z at until (/home/runner/work/Tuldok/Tuldok/tests/browser_scientific_fields.cjs:23:138) +2026-10-20T04:16:43.4040950Z at async openProject (/home/runner/work/Tuldok/Tuldok/tests/browser_scientific_fields.cjs:59:77) +2026-10-20T04:16:43.4042783Z at async /home/runner/work/Tuldok/Tuldok/tests/browser_scientific_fields.cjs:64:3 +2026-10-20T04:16:43.4043678Z Application stderr: +2026-10-20T04:16:43.4075107Z {"url":"http://127.0.0.1:33627/workspaces","body":"Local owner · owner\nSession\nSign out\nSkip to workspace\nt.\nTuldok\n/ Workspaces\n● Local\nClassic workbench ↗\nCorner studio ↗\nCONTEXT\nDataset\nInterface fixtures\nCurrent local catalog\nOpen project\nfixture-dataset-v1 · 0 selected · authored CC0 examples · release fixture-release-v1\nLocal preview\n01\nData\n02\nPipeline\n03\nRuns\nInspect → compose → understand\n\nFixture workspace ready.\n\nYOUR SOURCE OF TRUTH\nData\n\nInspect records, keep their evidence, review deliberately.\n\nAuthored fixtures · isolated from your catalog. These seven tiny examples show contracts and capability states. Choose “Current local catalog” above to import, annotate, review and freeze real data.\n\nRecords\n7 fixtures\n▧\nShapes / blue square\nimage · fixture\nT\nA short field note\ntext · fixture\n≋\nTwo synthetic pulses\naudio · fixture\n◇\nAuthored tetrahedron\nmesh · fixture\n∴\nFour indexed points\npoint cloud · fixture\n▦\nAnisotropic grid\nvolume · fixture\n↝\nThree authored frames\nsequence · fixture\n0 selected · source and annotation r1\nFixture selection never freezes a real release.\nShapes / blue square\nFixture\n128 × 128 · authored representation\nimage_classification_v1\nSaved: draft · r1\nSource identity\nfixture-image · source r1\nRights note\nAuthored demonstration data; CC0-1.0.\nReview\nAuthored draft. No human review or release admission is implied.\nRepresentation, hash and source provenance\nANNOTATION\nClass draft\nClass label\nSaved fixture draft\nSave fixture draft\n\nSaves a new browser-local draft revision. It does not create review evidence or a frozen release.\n\nCURRENT CATALOG CAPABILITY\nAvailable in bounded scope\nClass, caption, detection and corner editors in the current catalog. Reviewed image releases support the bounded TinyCNN CPU recipe.\nNext qualification\nOther image tasks need their own qualified training recipes\nOpen current catalog →\nTuldok · Dataset-centered workspaces\nFixtures are isolated examples. Current catalog runs use an optional local CPU runtime.","frame":""} +2026-10-20T04:16:43.4490513Z ##[error]Process completed with exit code 1. +2026-10-20T04:16:43.4923379Z ##[group]Run actions/upload-artifact@v4 diff --git a/docs/plans/retained-analysis/reports/project-startup-ci-20261020/original-entrypoint-delayed-red.log b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/original-entrypoint-delayed-red.log new file mode 100644 index 00000000..6cfc96b4 --- /dev/null +++ b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/original-entrypoint-delayed-red.log @@ -0,0 +1,9 @@ +STARTUP before original first pointer click {"disabled":false,"handler":"object","dialog":false,"hit":"open-project"} +STARTUP held actual workspace-projects.js response +STARTUP after original click and actual module release {"disabled":false,"handler":"function","dialog":false,"status":"Fixture workspace ready."} +Error: Timed out + at until (/workspace/Tuldok-project-startup-ci-repair-20261020/tests/browser_scientific_fields.cjs:23:138) + at async openProject (/workspace/Tuldok-project-startup-ci-repair-20261020/tests/browser_scientific_fields.cjs:59:77) + at async /workspace/Tuldok-project-startup-ci-repair-20261020/tests/browser_scientific_fields.cjs:64:3 +Application stderr: +{"url":"http://127.0.0.1:32885/workspaces","body":"Local owner · owner\nSession\nSign out\nSkip to workspace\nt.\nTuldok\n/ Workspaces\n● Local\nClassic workbench ↗\nCorner studio ↗\nCONTEXT\nDataset\nInterface fixtures\nCurrent local catalog\nOpen project\nfixture-dataset-v1 · 0 selected · authored CC0 examples · release fixture-release-v1\nLocal preview\n01\nData\n02\nPipeline\n03\nRuns\nInspect → compose → understand\n\nFixture workspace ready.\n\nYOUR SOURCE OF TRUTH\nData\n\nInspect records, keep their evidence, review deliberately.\n\nAuthored fixtures · isolated from your catalog. These seven tiny examples show contracts and capability states. Choose “Current local catalog” above to import, annotate, review and freeze real data.\n\nRecords\n7 fixtures\n▧\nShapes / blue square\nimage · fixture\nT\nA short field note\ntext · fixture\n≋\nTwo synthetic pulses\naudio · fixture\n◇\nAuthored tetrahedron\nmesh · fixture\n∴\nFour indexed points\npoint cloud · fixture\n▦\nAnisotropic grid\nvolume · fixture\n↝\nThree authored frames\nsequence · fixture\n0 selected · source and annotation r1\nFixture selection never freezes a real release.\nShapes / blue square\nFixture\n128 × 128 · authored representation\nimage_classification_v1\nSaved: draft · r1\nSource identity\nfixture-image · source r1\nRights note\nAuthored demonstration data; CC0-1.0.\nReview\nAuthored draft. No human review or release admission is implied.\nRepresentation, hash and source provenance\nANNOTATION\nClass draft\nClass label\nSaved fixture draft\nSave fixture draft\n\nSaves a new browser-local draft revision. It does not create review evidence or a frozen release.\n\nCURRENT CATALOG CAPABILITY\nAvailable in bounded scope\nClass, caption, detection and corner editors in the current catalog. Reviewed image releases support the bounded TinyCNN CPU recipe.\nNext qualification\nOther image tasks need their own qualified training recipes\nOpen current catalog →\nTuldok · Dataset-centered workspaces\nFixtures are isolated examples. Current catalog runs use an optional local CPU runtime.","frame":""} diff --git a/docs/plans/retained-analysis/reports/project-startup-ci-20261020/page-load.log b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/page-load.log new file mode 100644 index 00000000..fdf5a678 --- /dev/null +++ b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/page-load.log @@ -0,0 +1 @@ +CDP reopen barrier rejects old documents, subframes and mismatched lifecycle events. diff --git a/docs/plans/retained-analysis/reports/project-startup-ci-20261020/post-exit-temporary-cleanup.json b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/post-exit-temporary-cleanup.json new file mode 100644 index 00000000..579fdb74 --- /dev/null +++ b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/post-exit-temporary-cleanup.json @@ -0,0 +1,12 @@ +{ + "temporary": "/tmp/tuldok-fields-browser-XT8B2u", + "immediate_harness_removed": true, + "late_browser_cache_reappearance_observed": true, + "late_files": [ + "browser/Default/Cache/Cache_Data/index-dir/the-real-index", + "browser/Default/Network Persistent State" + ], + "matching_catalog_browser_or_crashpad_processes": [], + "exact_owned_path_removed_after_post_exit_recheck": true, + "limit": "Main owned handles exited before initial removal; brief browser descendants recreated cache after initial cleanup. No process was killed or unrelated path removed." +} diff --git a/docs/plans/retained-analysis/reports/project-startup-ci-20261020/qualification.json b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/qualification.json new file mode 100644 index 00000000..3a38b39d --- /dev/null +++ b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/qualification.json @@ -0,0 +1,71 @@ +{ + "base_head": "0ba4db01f04a77c262eb4b397f88849e9688b5ab", + "source_sha256": { + "static/workspaces.html": "c16bf3ad0872b8f40f9d00ad6f2ae6366d2c3193aafa80bb496bbf3a41c183cd", + "static/workspace-projects.js": "3f465ad13a9f6bea9c7e812507510b4b5469e7569d7a1c22884115b6628a4747", + "tests/browser_scientific_fields.cjs": "9803d43c119bff759a771171b115f5878a22a1941ebf8de8c0e2a4361f3e0636", + "tests/test_workspace_project_startup.cjs": "0e4d00fbd3f67a8c5839864f2ad406597d91b253f116f526e551221d9f1ebd0a" + }, + "hosted_failure": { + "run": 39360310903, + "job": 118424712559, + "head": "0ba4db01f04a77c262eb4b397f88849e9688b5ab", + "decoded_log": "/tmp/tuldok-pr111-0ba4-failed-lifecycle-job-118424712559.log", + "decoded_log_sha256": "0c279bc15ca1488a9445b03763192fd6f4ab85c9c8ec1b8acb36d538a18b0e2b", + "raw_response": "/tmp/tuldok-pr111-0ba4-failed-lifecycle-job-118424712559-raw.json", + "raw_response_sha256": "cf1345c3cda4b58bd5053e29b4a5dd643e662b502eaf15c2558b67722401fec7", + "causal_limit": "Original host supplied no pointer/listener trace; startup cause is proven for controlled real reproduction, not asserted as traced host cause.", + "excerpt_projection": "Same excerpt lines with trailing whitespace removed; full exact raw/decoded logs preserved at their recorded paths." + }, + "controlled_original_entrypoint_red": { + "command": "node --require /tmp/tuldok-project-startup-repair/delay-project-module.cjs tests/browser_scientific_fields.cjs", + "entrypoint_source": "Unmodified exact0ba4", + "exit_code": 1, + "pointer_hit": "open-project", + "pre_click_disabled": false, + "pre_click_handler": "object/null", + "after_actual_module_release": { + "handler": "function", + "dialog_open": false, + "workspace_status": "Fixture workspace ready." + }, + "failed_assertion": "same first openProject wait at59:77 and entrypoint64", + "mechanism": "Hold/release actual module bytes through Fetch; no fulfilled responses or application callback substitution", + "raw_log": { + "path": "/tmp/tuldok-project-startup-repair/original-entrypoint-delayed-red.log", + "sha256": "b799d3a232afa255cd79de8c5f3210c879dc1097ebb059f54e183c3b75f3b413", + "committed_projection": "Same lines with trailing whitespace removed; exact raw preserved at this path." + } + }, + "green": { + "command": "node tests/browser_scientific_fields.cjs", + "exit_code": 0, + "startup_native_pointer": { + "before": { + "disabled": true, + "handler": "object", + "dialog": false, + "hit": "open-project", + "x": 348.2734375, + "y": 98 + }, + "after": { + "disabled": false, + "handler": "function", + "project": "project:cccccccccccccccccccccccccccccccc" + } + }, + "original_scientific_checks_retained": true, + "controller_regression_in_existing_CI_entrypoint": true, + "physics_acceptance": false, + "model_or_training_acceptance": false + }, + "environment": { + "postgres": "PostgreSQL 17.6 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0, 64-bit", + "python": "Python 3.12.14", + "browser": "Chrome/151.0.7922.173", + "node": "v24.19.0", + "mode": "Headless existing no-sandbox/disable-gpu flags; isolated profile; actual app/HTTP/PostgreSQL/NumPy independent cold reader" + }, + "resource_disposition": "All3 preregistered owned schemas queried absent. Main owned children stopped before initial removal. Brief browser descendant cache recreation was observed; final exact-path removal after no matching processes is recorded separately. No unrelated paths/processes touched." +} diff --git a/docs/plans/retained-analysis/reports/project-startup-ci-20261020/receipt.json b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/receipt.json new file mode 100644 index 00000000..044e8179 --- /dev/null +++ b/docs/plans/retained-analysis/reports/project-startup-ci-20261020/receipt.json @@ -0,0 +1,390 @@ +{ + "source_commit": "0ba4db01f04a77c262eb4b397f88849e9688b5ab", + "dirty": true, + "command": "node tests/browser_scientific_fields.cjs", + "capture_receipt_sha256": null, + "qualification": "Producer-neutral authored rotated noncubic fields; transport/UI/custody only", + "physics_acceptance": false, + "model_or_training_acceptance": false, + "source_files_sha256": { + "static/workspaces.html": "c16bf3ad0872b8f40f9d00ad6f2ae6366d2c3193aafa80bb496bbf3a41c183cd", + "static/workspace-projects.js": "3f465ad13a9f6bea9c7e812507510b4b5469e7569d7a1c22884115b6628a4747", + "tests/browser_scientific_fields.cjs": "9803d43c119bff759a771171b115f5878a22a1941ebf8de8c0e2a4361f3e0636", + "tests/test_workspace_project_startup.cjs": "0e4d00fbd3f67a8c5839864f2ad406597d91b253f116f526e551221d9f1ebd0a" + }, + "startup": { + "before": { + "disabled": true, + "handler": "object", + "dialog": false, + "hit": "open-project", + "x": 348.2734375, + "y": 98 + }, + "after": { + "disabled": false, + "handler": "function", + "project": "project:cccccccccccccccccccccccccccccccc" + } + }, + "checks": [ + "Delayed actual project module keeps the pointer-hit control disabled; its owner enables the original first open and full project inspection", + "Opening remains read-only; explicit import refuses stale observed hash before catalog writes, then imports exact bytes", + "All authored fields and X/Y/Z planes retain exact time/stage/dtype; rotated noncubic origin and signed zero inspected", + "Wholeasset human inspection freezes canonical release; separate NumPy reader verifies exact recovered original payload and opaque sources", + "Held import refresh preserves a newer explicit clean-record selection instead of opening the newly imported record", + "Restart retains reviewed field record and exact release; original project bytes unchanged and no execution submitted" + ], + "captures": [ + { + "file": "scientific-inspector-1440.jpg", + "width": 1440, + "height": 900, + "qualification": "Transport, inspection and custody only; no physics or model qualification" + }, + { + "file": "scientific-inspector-390.jpg", + "width": 390, + "height": 900, + "qualification": "Transport, inspection and custody only; no physics or model qualification" + } + ], + "source_sha256": "32d79d5e4c8881fcfd6c858b70e485c61a636ac1e8ea7d4dbd6c52c7bdc47ed7", + "cold": { + "scope": "Cold NumPy dtype/shape/element bytes, declared coordinates/time/stages and opaque source custody only", + "numpy": "2.5.4", + "bundle_sha256": "32d79d5e4c8881fcfd6c858b70e485c61a636ac1e8ea7d4dbd6c52c7bdc47ed7", + "native_capture": false, + "model_or_training_acceptance": false, + "physics_acceptance": false, + "arrays": [ + { + "frame": 0, + "field": "scalar", + "dtype": "1`G&DXcBq? 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


ZZin~xplRAs~N#O|bl3d4v@!J5& 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 Qd%e%dIIGggn0Jf%H@vWnfB*mh literal 0 HcmV?d00001 diff --git a/static/workspace-projects.js b/static/workspace-projects.js index 7ccb33be..641d5098 100644 --- a/static/workspace-projects.js +++ b/static/workspace-projects.js @@ -185,6 +185,7 @@ window.WorkspaceProjects = function ({select, roots, announce, switchSource, con finally{opening=false;$('project-open-submit').disabled=!aliases.length;} }; window.addEventListener('pagehide',()=>{activityView.stop();generation++;listGeneration++;openGeneration++;importGeneration++;controller?.abort();evidenceController?.abort();}); + $('open-project').disabled=false; return { initialize:refreshList, label:()=>detail?.name||entries.find(entry=>'project:'+entry.id===currentSource())?.name||'Project', diff --git a/static/workspaces.html b/static/workspaces.html index b299d345..b9bd23ee 100644 --- a/static/workspaces.html +++ b/static/workspaces.html @@ -30,7 +30,7 @@ - +
Loading workspace…
Local preview diff --git a/tests/browser_scientific_fields.cjs b/tests/browser_scientific_fields.cjs index 7e2e3d37..85d42245 100644 --- a/tests/browser_scientific_fields.cjs +++ b/tests/browser_scientific_fields.cjs @@ -7,6 +7,7 @@ const assert=require('node:assert/strict'),fs=require('node:fs'),os=require('nod const {spawn,execFileSync}=require('node:child_process'); const {pageLoadTracker}=require('./browser_page_load.cjs'); const {waitForDebugger}=require('./browser_startup.cjs'); +const {stopOwnedChildren}=require('./browser_owned_cleanup.cjs'); const {qaDirectory,screenshotOptions}=require('./qa_artifacts.cjs'); const root=path.resolve(__dirname,'..'),captureIndex=process.argv.indexOf('--capture-root'); assert.ok(captureIndex<0||process.argv[captureIndex+1],'--capture-root needs a directory'); @@ -19,11 +20,13 @@ const fixtureArgs=['tests/qualify_scientific_fields.py','--output',bundlePath,'- execFileSync('python3',fixtureArgs,{cwd:root});const source=fs.readFileSync(bundlePath),sourceHash=sha(source); const first={schema_version:2,extensions:[],id:'c'.repeat(32),name:captureRoot?'Native capture transport only':'Rotated noncubic authored fields',data:[{id:'fields',label:'Generic scientific bundle',path:'fields.zip'}],recipes:[],evidence:[],requirements:[]}; const manifestRaw=JSON.stringify(first);fs.writeFileSync(path.join(projectRoot,'tuldok.project.json'),manifestRaw); +const sourceFiles=Object.fromEntries(['static/workspaces.html','static/workspace-projects.js','tests/browser_scientific_fields.cjs','tests/test_workspace_project_startup.cjs'].map(file=>[file,sha(fs.readFileSync(path.join(root,file)))])); const inspections=[],captures=[],checks=[],requests=[],errors=[],children=[],tracker=pageLoadTracker();const pause=ms=>new Promise(resolve=>setTimeout(resolve,ms));let ws,send,evaluate,serverErrors=''; async function until(fn,message='Timed out'){for(let i=0;i<600;i++){const value=await fn();if(value)return value;await pause(100);}throw Error(message);} function launch(command,args,options){const child=spawn(command,args,options);children.push(child);return child;} const serverArgs=port=>['-u','app.py','--port',String(port),'--data',path.join(temporary,'data'),'--project-root','sample='+projectRoot]; (async()=>{ + require('./test_workspace_project_startup.cjs').verifyProjectStartup(); let server=launch('python3',serverArgs(0),{cwd:root,stdio:['ignore','pipe','pipe']}); let output='';server.stdout.on('data',chunk=>output+=chunk);server.stderr.on('data',chunk=>serverErrors+=chunk); const port=await until(()=>{if(server.exitCode!==null)throw Error('Project server exited: '+serverErrors);return output.match(/127\.0\.0\.1:(\d+)/)?.[1];}); @@ -33,9 +36,9 @@ const serverArgs=port=>['-u','app.py','--port',String(port),'--data',path.join(t const debugPort=await waitForDebugger(browser,path.join(temporary,'browser','DevToolsActivePort')); const tabs=await(await fetch('http://127.0.0.1:'+debugPort+'/json')).json(),target=tabs.find(tab=>tab.type==='page'&&tab.url==='about:blank');assert.ok(target); ws=new WebSocket(target.webSocketDebuggerUrl);await new Promise((resolve,reject)=>{ws.onopen=resolve;ws.onerror=reject;}); - let next=0;const pending=new Map(); + let next=0,startupResponse=null;const pending=new Map(); send=(method,params={})=>new Promise((resolve,reject)=>{const id=++next,timer=setTimeout(()=>{pending.delete(id);reject(Error('CDP timeout '+method));},20000);pending.set(id,{resolve:value=>{clearTimeout(timer);resolve(value);},reject:error=>{clearTimeout(timer);reject(error);}});ws.send(JSON.stringify({id,method,params}));}); - ws.onmessage=event=>{const message=JSON.parse(event.data);tracker.observe(message);if(message.id){const task=pending.get(message.id);pending.delete(message.id);if(task)message.error?task.reject(message.error):task.resolve(message.result);}if(message.method==='Runtime.exceptionThrown')errors.push(message.params.exceptionDetails);if(message.method==='Network.requestWillBeSent')requests.push({url:message.params.request.url,method:message.params.request.method});}; + ws.onmessage=event=>{const message=JSON.parse(event.data);tracker.observe(message);if(message.id){const task=pending.get(message.id);pending.delete(message.id);if(task)message.error?task.reject(message.error):task.resolve(message.result);}if(message.method==='Runtime.exceptionThrown')errors.push(message.params.exceptionDetails);if(message.method==='Fetch.requestPaused')startupResponse=message.params;if(message.method==='Network.requestWillBeSent')requests.push({url:message.params.request.url,method:message.params.request.method});}; evaluate=async expression=>{const result=await send('Runtime.evaluate',{expression,awaitPromise:true,returnByValue:true});if(result.exceptionDetails)throw Error(JSON.stringify(result.exceptionDetails));return result.result.value;}; const doc=frame=>frame?'document.getElementById("catalog-frame").contentDocument':'document'; const element=(selector,frame=false)=>`${doc(frame)}.querySelector(${JSON.stringify(selector)})`,text=(selector,frame=false)=>evaluate(`${element(selector,frame)}?.textContent`); @@ -60,8 +63,20 @@ const serverArgs=port=>['-u','app.py','--port',String(port),'--data',path.join(t await send('Page.enable');await send('Page.setLifecycleEventsEnabled',{enabled:true});await send('Runtime.enable');await send('Network.enable'); const offlineCanary=process.env.LD_PRELOAD?JSON.parse(execFileSync('python3',['-c',"import sys;sys.path.insert(0,'tests');from test_workspace_offline import CANARY;exec(CANARY)"],{cwd:root,encoding:'utf8'})):null; await fixtureAuth.browser(send,'http://127.0.0.1:'+port); + // Delay the actual owning module; keep the initial HTML and real pointer path. + await send('Fetch.enable',{patterns:[{urlPattern:base+'/workspace-projects.js',requestStage:'Response'}]}); await send('Page.navigate',{url:base+'/workspaces'});await until(()=>evaluate('!!document.getElementById("open-project")')); + await until(()=>startupResponse,'Owning project module response was not held'); + const startupBefore=await evaluate(`(()=>{const e=document.getElementById('open-project'),b=e.getBoundingClientRect();return {disabled:e.disabled,handler:typeof e.onclick,dialog:document.getElementById('project-open-dialog').open,hit:document.elementFromPoint(b.x+b.width/2,b.y+b.height/2)?.id,x:b.x+b.width/2,y:b.y+b.height/2};})()`); + assert.equal(startupBefore.disabled,true,'Open project stays unavailable until its owner binds the action'); + assert.equal(startupBefore.handler,'object');assert.equal(startupBefore.hit,'open-project'); + for(const type of ['mousePressed','mouseReleased'])await send('Input.dispatchMouseEvent',{type,button:'left',clickCount:1,x:startupBefore.x,y:startupBefore.y}); + assert.equal(await evaluate('document.getElementById("project-open-dialog").open'),false,'The disabled startup control cannot open a partial project flow'); + await send('Fetch.continueRequest',{requestId:startupResponse.requestId});startupResponse=null;await send('Fetch.disable'); await openProject('tuldok.project.json',first.name,first.id); + const startupAfter=await evaluate('({disabled:document.getElementById("open-project").disabled,handler:typeof document.getElementById("open-project").onclick,project:document.getElementById("dataset").value})'); + assert.equal(startupAfter.disabled,false);assert.equal(startupAfter.handler,'function'); + check('Delayed actual project module keeps the pointer-hit control disabled; its owner enables the original first open and full project inspection'); assert.equal((await(await fetch(base+'/api/workbench/records')).json()).items.length,0,'Opening does not import'); await click('[data-project-import="fields"]'); await until(()=>evaluate('document.getElementById("project-import-dialog").open')); @@ -144,6 +159,6 @@ const serverArgs=port=>['-u','app.py','--port',String(port),'--data',path.join(t check('Held import refresh preserves a newer explicit clean-record selection instead of opening the newly imported record'); assert.deepEqual(await(await fetch(base+'/api/workspace/runs')).json(),[]);assert.deepEqual(errors,[]);assert.ok(!serverErrors.includes('Traceback'),serverErrors); check('Restart retains reviewed field record and exact release; original project bytes unchanged and no execution submitted'); - fs.writeFileSync(path.join(report,'receipt.json'),JSON.stringify({source_commit:execFileSync('git',['rev-parse','HEAD'],{cwd:root,encoding:'utf8'}).trim(),dirty:!!execFileSync('git',['status','--porcelain'],{cwd:root,encoding:'utf8'}).trim(),command:'node tests/browser_scientific_fields.cjs'+(captureRoot?' --capture-root ':''),capture_receipt_sha256:captureRoot?sha(fs.readFileSync(path.join(captureRoot,'receipt.json'))):null,qualification:captureRoot?'Actual saved native capture converted without element conversion; transport/UI/custody only':'Producer-neutral authored rotated noncubic fields; transport/UI/custody only',physics_acceptance:false,model_or_training_acceptance:false,checks,captures,source_sha256:sourceHash,cold,frozenSummary,offline_canary:offlineCanary,browser:(await send('Browser.getVersion')).product},null,2)); + fs.writeFileSync(path.join(report,'receipt.json'),JSON.stringify({source_commit:execFileSync('git',['rev-parse','HEAD'],{cwd:root,encoding:'utf8'}).trim(),dirty:!!execFileSync('git',['status','--porcelain'],{cwd:root,encoding:'utf8'}).trim(),command:'node tests/browser_scientific_fields.cjs'+(captureRoot?' --capture-root ':''),capture_receipt_sha256:captureRoot?sha(fs.readFileSync(path.join(captureRoot,'receipt.json'))):null,qualification:captureRoot?'Actual saved native capture converted without element conversion; transport/UI/custody only':'Producer-neutral authored rotated noncubic fields; transport/UI/custody only',physics_acceptance:false,model_or_training_acceptance:false,source_files_sha256:sourceFiles,startup:{before:startupBefore,after:startupAfter},checks,captures,source_sha256:sourceHash,cold,frozenSummary,offline_canary:offlineCanary,browser:(await send('Browser.getVersion')).product},null,2)); console.log('PASS scientific field browser:',report); -})().catch(async error=>{console.error(error);console.error('Application stderr:',serverErrors);if(evaluate)try{console.error(await evaluate('JSON.stringify({url:location.href,body:document.body.innerText.slice(-9000),frame:document.getElementById("catalog-frame")?.contentDocument?.body.innerText.slice(-5000)})'));}catch{}process.exitCode=1;}).finally(()=>{ws?.close();for(const child of children.reverse())child.kill('SIGTERM');}); +})().catch(async error=>{console.error(error);console.error('Application stderr:',serverErrors);if(evaluate)try{console.error(await evaluate('JSON.stringify({url:location.href,body:document.body.innerText.slice(-9000),frame:document.getElementById("catalog-frame")?.contentDocument?.body.innerText.slice(-5000)})'));}catch{}process.exitCode=1;}).finally(async()=>{ws?.close();await stopOwnedChildren(children);fs.rmSync(temporary,{recursive:true,force:true,maxRetries:10,retryDelay:100});fs.writeFileSync(path.join(report,'cleanup.json'),JSON.stringify({temporary,removed:!fs.existsSync(temporary),children:children.map(child=>({pid:child.pid,exit_code:child.exitCode,signal:child.signalCode}))},null,2)+'\n');}).catch(error=>{console.error('Owned scientific fixture cleanup failed:',error);process.exitCode=1;}); diff --git a/tests/test_workspace_project_startup.cjs b/tests/test_workspace_project_startup.cjs new file mode 100644 index 00000000..3202d3c1 --- /dev/null +++ b/tests/test_workspace_project_startup.cjs @@ -0,0 +1,33 @@ +'use strict'; +// Controller construction only; browser_scientific_fields owns real startup/pointer evidence. +const assert=require('node:assert/strict'),fs=require('node:fs'),path=require('node:path'),vm=require('node:vm'); +function verifyProjectStartup(){ + const html=fs.readFileSync(path.join(__dirname,'../static/workspaces.html'),'utf8'); + assert.match(html.match(/]*id="open-project"[^>]*>/)[0],/\bdisabled\b/,'The initial server markup must withhold the unbound action'); + const nodes=new Map(),listeners=[],requests=[]; + function node(id){ + if(!nodes.has(id))nodes.set(id,{disabled:id==='open-project',open:false,addEventListener(){},showModal(){this.open=true;},close(){this.open=false;},focus(){}}); + return nodes.get(id); + } + const button=node('open-project');let disabled=true,enables=0; + Object.defineProperty(button,'disabled',{get:()=>disabled,set:value=>{ + if(!value){ + assert.equal(typeof button.onclick,'function','The controller installs the action before exposing it'); + assert.equal(typeof node('project-open-form').onsubmit,'function','The complete open form is owned before exposure'); + assert.ok(listeners.includes('pagehide'),'Controller disposal is owned before exposure'); + enables++; + } + disabled=value; + }}); + const window={workspaceEscape:String,addEventListener:event=>listeners.push(event)}; + const context={window,document:{getElementById:node},WorkspaceProjectActivity:()=>({stop(){}}),WorkspaceExternalProject:()=>({cancel(){}}),WorkspaceExtensionModelAuthor:()=>({cancel(){}}),fetch:url=>{requests.push(url);return new Promise(()=>{});}}; + vm.runInNewContext(fs.readFileSync(path.join(__dirname,'../static/workspace-projects.js'),'utf8'),context); + assert.equal(button.disabled,true,'Loading the module alone does not expose an unconstructed controller'); + window.WorkspaceProjects({select:{value:'fixtures'},roots:{},announce(){},switchSource(){},contextChanged(){}}); + assert.equal(button.disabled,false);assert.equal(enables,1); + button.onclick();assert.equal(node('project-open-dialog').open,true,'The enabled first action opens its dialog synchronously'); + assert.deepEqual(requests,['/api/workspace/project-snapshots']); + console.log('PASS project startup markup disabled; owning constructor binds action, form and teardown before enable; first action opens synchronously and reads only'); +} +module.exports={verifyProjectStartup}; +if(require.main===module)verifyProjectStartup(); From cd77bc3d9f148a7c7b80a5cf19e974ed5285c0e2 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Oct 2026 06:59:32 +0000 Subject: [PATCH 7/8] test: synchronize access browser navigation and shutdown --- .../access-browser-ci-20261020/acceptance.md | 68 +++++++ .../actual-access.log | 3 + .../access-browser-ci-20261020/cleanup.json | 17 ++ .../independent-review.json | 171 ++++++++++++++++++ .../independent-source-review.json | 75 ++++++++ .../original-failure-disposition.json | 113 ++++++++++++ .../original-failure-excerpt.log | 32 ++++ .../post-run-cleanup.json | 35 ++++ .../qualification.json | 114 ++++++++++++ .../access-browser-ci-20261020/receipt.json | 47 +++++ .../runner-receipt.json | 17 ++ .../schema-reservation.json | 7 + .../session-1280.jpg | Bin 0 -> 92512 bytes .../session-390.jpg | Bin 0 -> 46763 bytes tests/browser_access.cjs | 37 +++- tests/browser_access_session.cjs | 46 +++++ tests/test_browser_access_navigation.cjs | 61 +++++++ 17 files changed, 834 insertions(+), 9 deletions(-) create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/acceptance.md create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/actual-access.log create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/cleanup.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-review.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-source-review.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-disposition.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-excerpt.log create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/post-run-cleanup.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/qualification.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/receipt.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/runner-receipt.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/schema-reservation.json create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/session-1280.jpg create mode 100644 docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/session-390.jpg create mode 100644 tests/browser_access_session.cjs create mode 100644 tests/test_browser_access_navigation.cjs diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/acceptance.md b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/acceptance.md new file mode 100644 index 00000000..709f8b4b --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/acceptance.md @@ -0,0 +1,68 @@ +# Access browser navigation and shutdown qualification + +The local repair descends from PR112 at +`0dedbc953902ac89389dca0693006aaa02a0a87c` on +`fix/access-browser-ci-qualification-20261020`. Root owns subsequent serial +integration. This branch is unpublished and retained for review; no remote PR, +workflow, branch or hosting state changed. + +The implementation changes three test files only. Both the initial workbench +navigation and scoped-agent reload capture the previous main frame/loader and +wait for a changed main loader with its matching load event before reading DOM. +The helper reuses the existing CDP session and load tracker. Request, connection +and document-load waits are bounded; failure context contains phase, method and +bounded frame/loader identities without command parameters. All 14 original +assertions remain, with one added assertion selecting the explicitly launched +blank page. No authentication or product behavior changes. + +Shutdown now awaits the existing supplied-child helper before bounded removal of +the exact test profile. Primary access failures and secondary cleanup failures +retain separate labels and a nonzero outcome. Main-handle termination does not +establish an unconditional Chromium-descendant shutdown guarantee. + +## Evidence + +- [Controlled regression](../../../../../tests/test_browser_access_navigation.cjs) + reproduces the old navigation/reload acknowledgement ordering with the exact + `-32000` error. The corrected sequence issues no DOM read before the changed + main loader's load; old-loader, subframe and DOMContentLoaded events cannot + release the gate. Target closure and request/load timeout cases remain failures. + This is a controlled protocol reproduction, not the original hosted trace. +- Three syntax checks, the new regression, the existing page-load regression, + owned-child delayed-write/ignored-TERM regression and diff check passed. +- The unchanged default command `node tests/browser_access.cjs` passed against + actual existing PostgreSQL17.6, Python3.12.14, Node24.19.0 and Chromium151 in + 8.605350 seconds. It includes the new regression before its real browser journey. + [Raw log](actual-access.log), [actual receipt](receipt.json), [runner](runner-receipt.json) + and desktop/narrow screenshots retain the result. +- The initial owner login still uses an actual one-time CLI code and interactive + browser form, not a preinstalled fixture cookie. Anonymous denials, HttpOnly/code + clearing, retained drafts, no mutation replay, deliberate commit and final + scoped-agent review denial all pass. The final scoped-agent switch installs its + separately issued real credential as in the original test. +- [Cleanup](post-run-cleanup.json) records the exact preregistered schema queried + absent after disposal, zero workspace Runs, terminal supplied app/browser + handles, absent exact profile and no matching task process at observation. + Only the disposable fixture was removed; no service or package was installed + or reconfigured. Reviewer inspected these receipts, not a second PG/browser run. +- [Independent review](independent-review.json) clears source, focused checks and + actual evidence. It rechecks all three tested source hashes. The actual receipt + records precommit HEAD0ded with dirty source; file hashes bind the tested repair + bytes and must match the eventual local commit. It does not claim 0ded already + contained the repair. + +## Original failure and remaining gates + +Original run39370107550/job118455819881 remains failed at access step41. +Its [excerpt](original-failure-excerpt.log), full decoded-log SHA and source +identity are retained in [qualification](qualification.json). The log provides +no failing command/phase trace, so exact navigation versus target closure/crash +remains unproven. Cleanup ENOTEMPTY followed the primary error and is separate. +The artifact ZIP was proxy403 blocked and its contents remain uninspected. + +The running sibling CI was untouched. No cancellation, rerun, source publication, +merge or branch/worktree cleanup occurred. This local access qualification is +not a passing full repaired-head lifecycle; fresh hosted gates and independent +integration review remain necessary when publication is authorized. PUB-1 original +diagnostic evidence and SCI-1 owned criterion/compatible real lab pair remain +missing. No training, scientific, CUDA or model-quality acceptance is inferred. diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/actual-access.log b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/actual-access.log new file mode 100644 index 00000000..0515b4c7 --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/actual-access.log @@ -0,0 +1,3 @@ +PASS access navigation/reload reproduction: old acknowledgement permits failing DOM read; changed main loader plus its load gates the original assertion +PASS access phase-specific timeout/target-close failures are bounded; diagnostics omit command parameters +PASS access browser /tmp/tuldok-access-browser-ci-repair-20261020/qa/access/run-vVR332 diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/cleanup.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/cleanup.json new file mode 100644 index 00000000..ddf102bc --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/cleanup.json @@ -0,0 +1,17 @@ +{ + "temporary": "/tmp/tuldok-access-browser-7VR9Z3", + "removed": true, + "children": [ + { + "pid": 119512, + "exit_code": null, + "signal": "SIGTERM" + }, + { + "pid": 119521, + "exit_code": 0, + "signal": null + } + ], + "scope": "Supplied test-owned main handles exited before bounded profile removal" +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-review.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-review.json new file mode 100644 index 00000000..e6112e9e --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-review.json @@ -0,0 +1,171 @@ +{ + "actual_qualification_review": { + "auth_scope": "Actual default entrypoint uses ordinary CLI one-time owner login, verifies replay denial, HttpOnly/code clearance, preserved unsaved drafts, no mutation replay and explicit successful retry. Existing final scoped-agent branch deliberately installs a real issued agent credential cookie and verifies human-review controls disabled; no fixture owner-cookie bootstrap is substituted.", + "checks": { + "actual_exit_zero": true, + "all3_original_auth_checks_complete": true, + "both_new_main_loads_recorded": true, + "exact_schema_absence_recorded": true, + "exact_schema_and_path_bound": true, + "exact_temporary_absence_and_no_matching_processes_recorded": true, + "three_source_hashes_exact_review_actual_and_current": true, + "two_supplied_main_handles_terminal_and_match": true, + "zero_workspace_runs": true + }, + "cleanup_limit": "Receipts support exact preregistered schema absent,0workspaceRuns, two supplied main handles terminal before rm, exact profile absent/no taskprocess matches at recorded observation. No blanket all-Chrome-descendant guarantee.", + "command": "node tests/browser_access.cjs", + "environment": "Root reports existing Python3.12.14, PostgreSQL17.6 and Chromium151; no installation/service/config change. Version commands not independently rerun by reviewer.", + "evidence": [ + { + "bytes": 763, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/runner-receipt.json", + "sha256": "b247a3d1147a47f0304649ae2a110969c2da7c1d6e4cd5a0abe8d82430753ef9" + }, + { + "bytes": 346, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/actual-access.log", + "sha256": "ae63a93687389ad38ed33d1ecbe7fe8916db65afff8222c4a9acfe8b07f4b2f4" + }, + { + "bytes": 1433, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/post-run-cleanup.json", + "sha256": "3fefda92278099fc5e93f1c05f363277b72469535a8dbd9cd83f5832023a6fc1" + }, + { + "bytes": 1693, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/qa/access/run-vVR332/receipt.json", + "sha256": "57b652807e1ac0e89d9f422c0c551051e33782ec779a016f0046c3ed48c6268d" + }, + { + "bytes": 341, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/qa/access/run-vVR332/cleanup.json", + "sha256": "06b2c257bca7797d663ad809335504a2a2d56a7b41eae4edf77b2049b110538e" + }, + { + "bytes": 92512, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/qa/access/run-vVR332/session-1280.jpg", + "sha256": "ae5ecddb60cd751033a62eb24ee383daa4d56da85439115b080178b18b5c5580" + }, + { + "bytes": 46763, + "path": "/tmp/tuldok-access-browser-ci-repair-20261020/qa/access/run-vVR332/session-390.jpg", + "sha256": "71f975c51592a0a92669c3d5213b21561acbc83cd4450a532b9e1a2cb7907519" + } + ], + "execution_owner": "Root executed actual PostgreSQL/HTTP/Chromium journey; this reviewer inspected retained bytes/receipts, did not repeat browser/server/PG.", + "exit": 0, + "finished_utc": "2026-10-20T06:56:00.320089+00:00", + "historical_failure_limit": "No new host event trace: controlled old-red/new-green and actual successful repair do not retroactively prove original failed-host cause.", + "loader_events": [ + { + "event": "load", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "C704421B4745793C1F166C7CC67C83F8" + }, + { + "event": "main-frame", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7534733FE54346FBED7374DBFE2EEB98" + }, + { + "event": "load", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7534733FE54346FBED7374DBFE2EEB98" + }, + { + "event": "main-frame", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7B0CA169AEB6A2150994309812BCD5B7" + }, + { + "event": "load", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7B0CA169AEB6A2150994309812BCD5B7" + } + ], + "reviewed_utc": "2026-10-20T06:57:54.185655+00:00", + "seconds": 8.60535, + "source_attribution": "Actual run used base0ded checkout with reviewed modified file bytes. Three file hashes agree in source-review/currentfiles/browserreceipt/postcleanup; do not claim base0ded includes repair or a later commit was literally executed.", + "source_dirty_at_execution": true, + "source_head_at_execution": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "started_utc": "2026-10-20T06:55:51.714739+00:00" + }, + "base": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "blocking_findings": [], + "cleanup_review": { + "limit": "Existing helper confirms supplied main child handles only, not an unconditional Chrome-descendant extinction guarantee; actual fixture run and final cleanup observation pending.", + "order": "Dispose session/socket; await existing stopOwnedChildren only on supplied children; bounded recursive removal maxRetries10/retryDelay100; write terminal-main-handle receipt.", + "primary_preservation": "Original failure printed as Primary access failure and recorded phase/protocol metadata; exitCode1 set before finally. Cleanup failure separately prints Secondary access cleanup failure and retains nonzero exit." + }, + "disposition": "CLEAR within reviewed three-file test-harness source plus actual default access qualification scope; external publication/CI acceptance remain parent-owned", + "historical_failure": { + "cause_limit": "Source race is demonstrated in controlled mock protocol scheduling; original hosted execution had no phase/pointer/context trace. Target closure/crash remains unexcluded. Original failed run is not reclassified.", + "head": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "job": 118455819881, + "primary": "Inspected target navigated or closed", + "run": 39370107550, + "secondary": "ENOTEMPTY after unawaited TERM/removal" + }, + "independent_tests": { + "command": "node --check tests/browser_access.cjs && node --check tests/browser_access_session.cjs && node --check tests/test_browser_access_navigation.cjs && node tests/test_browser_access_navigation.cjs && node tests/test_browser_page_load.cjs", + "exit": 0, + "not_run_by_reviewer": [ + "Actual browser/HTTP/PostgreSQL", + "Owned-child regression(no need duplicate existingroot pass)", + "Heavy suites/CI" + ], + "results": [ + "Controlled old navigation/reload ACK\u2192departing-DOM read produces -32000", + "New helper issues zero DOM reads until changed main loader matchingload; oldloader/subframe/DOMContentLoaded insufficient", + "Navigation load timeout and targetclose fail within configured bounds", + "Request timeout and snapshots omit MUST_NOT_APPEAR command token", + "Existing fresh-document helper regression passes" + ] + }, + "limits": [ + "No product/API/domain changes; exact source diff limited to three test files.", + "No remote mutation/CI polling/source edit or server/browser execution by reviewer.", + "PUB-1 and SCI-1 unchanged.", + "Actual evidence inspected, not independently rerun; no performance claim from8.605350s descriptive single-run wall time. Parent prohibits external publication, merging, branch cleanup or environment changes." + ], + "navigation_review": { + "both_transitions": [ + "Initial Page.navigate to workbench", + "Scoped-agent Page.reload after exact cookie replacement" + ], + "diagnostics": "Bounded last12main-frame/load identities plus phase and last method; command parameters absent. contextual errors preserve underlying code/cause.", + "exact_target": "Initial page target must type page and url about:blank; connection deadline10000ms.", + "failure_boundaries": "Default CDP requests15000ms; new-load wait20000ms with25ms polling; explicit errorText/target close/error refuse. No blanket navigation-error suppression or mutation retry.", + "fresh_dom_checks": "Original session dialog/identity/Collection-ready checks remain after fresh-document gate.", + "owner": "accessSession captures Page.getFrameTree previous main id+loader before command; pageLoadTracker observes Page.frameNavigated and lifecycle load. Only changed main loader with matching load releases DOM checks." + }, + "original_assertions": { + "all14_original_calls_present_verbatim": true, + "base_calls": 14, + "current_calls": 15, + "extra": "Explicitly launched about:blank target assertion", + "preserved_semantics": [ + "Anonymous legacy/current denied writes", + "One-time CLI login consumed/code cleared/HttpOnly cookie", + "Signout and rejected mutation preserve unsaved draft", + "Reauthentication never replays original mutation", + "Only deliberate retry changes revision", + "Real scoped agent cannot use owner human-review controls", + "No runtime exceptions or application stderr" + ] + }, + "reviewed_utc": "2026-10-20T06:54:04.651464+00:00", + "source_only_review_history": { + "old_disposition": "CLEAR within test-harness source/focused-test scope; actual default PostgreSQL/Chromium access qualification remains pending", + "path": "/tmp/tuldok-access-browser-ci-independent-review-source-only.json", + "sha256": "3b8d598bd31f575c0d8b20780a275abd9b0df10d7ee8a589b21a4968eccf56e3" + }, + "source_sha256": { + "tests/browser_access.cjs": "e3c1bcd19d73981a39a3adcc0d32d7e67029907e0cfd689e2739348efbf0e56f", + "tests/browser_access_session.cjs": "d61b7cf0c366134050d6bba3542fd209005c5ad22f10a3659afe0ca8f948e1a5", + "tests/test_browser_access_navigation.cjs": "56ae9b76f1aaa3803a90f03468129f243d0b37f6a50110bcf7c13840da18f80e" + }, + "source_state": "Uncommitted exact three test-file repair; root owns final commit/publication.", + "status_porcelain": " M tests/browser_access.cjs\n?? tests/browser_access_session.cjs\n?? tests/test_browser_access_navigation.cjs\n", + "worktree": "/workspace/Tuldok-access-browser-ci-repair-20261020" +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-source-review.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-source-review.json new file mode 100644 index 00000000..9aa653c4 --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/independent-source-review.json @@ -0,0 +1,75 @@ +{ + "base": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "blocking_findings": [], + "cleanup_review": { + "limit": "Existing helper confirms supplied main child handles only, not an unconditional Chrome-descendant extinction guarantee; actual fixture run and final cleanup observation pending.", + "order": "Dispose session/socket; await existing stopOwnedChildren only on supplied children; bounded recursive removal maxRetries10/retryDelay100; write terminal-main-handle receipt.", + "primary_preservation": "Original failure printed as Primary access failure and recorded phase/protocol metadata; exitCode1 set before finally. Cleanup failure separately prints Secondary access cleanup failure and retains nonzero exit." + }, + "disposition": "CLEAR within test-harness source/focused-test scope; actual default PostgreSQL/Chromium access qualification remains pending", + "historical_failure": { + "cause_limit": "Source race is demonstrated in controlled mock protocol scheduling; original hosted execution had no phase/pointer/context trace. Target closure/crash remains unexcluded. Original failed run is not reclassified.", + "head": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "job": 118455819881, + "primary": "Inspected target navigated or closed", + "run": 39370107550, + "secondary": "ENOTEMPTY after unawaited TERM/removal" + }, + "independent_tests": { + "command": "node --check tests/browser_access.cjs && node --check tests/browser_access_session.cjs && node --check tests/test_browser_access_navigation.cjs && node tests/test_browser_access_navigation.cjs && node tests/test_browser_page_load.cjs", + "exit": 0, + "not_run_by_reviewer": [ + "Actual browser/HTTP/PostgreSQL", + "Owned-child regression(no need duplicate existingroot pass)", + "Heavy suites/CI" + ], + "results": [ + "Controlled old navigation/reload ACK\u2192departing-DOM read produces -32000", + "New helper issues zero DOM reads until changed main loader matchingload; oldloader/subframe/DOMContentLoaded insufficient", + "Navigation load timeout and targetclose fail within configured bounds", + "Request timeout and snapshots omit MUST_NOT_APPEAR command token", + "Existing fresh-document helper regression passes" + ] + }, + "limits": [ + "No product/API/domain changes; exact source diff limited to three test files.", + "Root must execute and retain actual default access journey against these exact source hashes before broader acceptance.", + "No remote mutation/CI polling/source edit or server/browser execution by reviewer.", + "PUB-1 and SCI-1 unchanged." + ], + "navigation_review": { + "both_transitions": [ + "Initial Page.navigate to workbench", + "Scoped-agent Page.reload after exact cookie replacement" + ], + "diagnostics": "Bounded last12main-frame/load identities plus phase and last method; command parameters absent. contextual errors preserve underlying code/cause.", + "exact_target": "Initial page target must type page and url about:blank; connection deadline10000ms.", + "failure_boundaries": "Default CDP requests15000ms; new-load wait20000ms with25ms polling; explicit errorText/target close/error refuse. No blanket navigation-error suppression or mutation retry.", + "fresh_dom_checks": "Original session dialog/identity/Collection-ready checks remain after fresh-document gate.", + "owner": "accessSession captures Page.getFrameTree previous main id+loader before command; pageLoadTracker observes Page.frameNavigated and lifecycle load. Only changed main loader with matching load releases DOM checks." + }, + "original_assertions": { + "all14_original_calls_present_verbatim": true, + "base_calls": 14, + "current_calls": 15, + "extra": "Explicitly launched about:blank target assertion", + "preserved_semantics": [ + "Anonymous legacy/current denied writes", + "One-time CLI login consumed/code cleared/HttpOnly cookie", + "Signout and rejected mutation preserve unsaved draft", + "Reauthentication never replays original mutation", + "Only deliberate retry changes revision", + "Real scoped agent cannot use owner human-review controls", + "No runtime exceptions or application stderr" + ] + }, + "reviewed_utc": "2026-10-20T06:54:04.651464+00:00", + "source_sha256": { + "tests/browser_access.cjs": "e3c1bcd19d73981a39a3adcc0d32d7e67029907e0cfd689e2739348efbf0e56f", + "tests/browser_access_session.cjs": "d61b7cf0c366134050d6bba3542fd209005c5ad22f10a3659afe0ca8f948e1a5", + "tests/test_browser_access_navigation.cjs": "56ae9b76f1aaa3803a90f03468129f243d0b37f6a50110bcf7c13840da18f80e" + }, + "source_state": "Uncommitted exact three test-file repair; root owns final commit/publication.", + "status_porcelain": " M tests/browser_access.cjs\n?? tests/browser_access_session.cjs\n?? tests/test_browser_access_navigation.cjs\n", + "worktree": "/workspace/Tuldok-access-browser-ci-repair-20261020" +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-disposition.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-disposition.json new file mode 100644 index 00000000..2858438f --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-disposition.json @@ -0,0 +1,113 @@ +{ + "observed_utc": "2026-10-20T06:41:53.697361+00:00", + "scope": "Read-only source/log diagnosis; local evidence files only. No browser/PG reproduction, tests, source edits or external mutations.", + "pr": 112, + "head": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "tested_checkout": "fb6c6c6c55b6ece1d6eab0eae20bef630b9fdf46", + "tested_source_attribution": "Hosted checkout merge message binds0ded into29011; remote comparison from0ded tofb6 has no changed files.", + "run": 39370107550, + "job": 118455819881, + "conclusion": "failure", + "successful_steps": 45, + "skipped_steps": 127, + "failed_steps": [ + { + "name": "Run node tests/browser_access.cjs", + "status": "completed", + "conclusion": "failure", + "number": 41 + } + ], + "prior_full_unittest": { + "tests": 1771, + "skips": 83, + "non_skipped": 1688, + "seconds": 2989.096, + "result": "OK" + }, + "log": { + "path": "/tmp/tuldok-pr112-0ded-access-failed-job-118455819881.log", + "bytes": 251955, + "sha256": "dce0386ccf600104e93c6129a28bbd4844ee5d73921b64567d3a2234a9748f6e" + }, + "source": { + "path": "tests/browser_access.cjs", + "git_blob": "bae9bae294fd3245d7f099e6185924308c7233bc", + "sha256": "b19ba3559cc8321c3a4d932f0c14a08c3763ca41ac8640fd965d346f95213159", + "exact_local_committed_bytes_match_remote": true + }, + "primary": { + "time": "2026-10-20T06:37:39.7616902Z", + "code": -32000, + "message": "Inspected target navigated or closed", + "command_and_phase": "Unknown: raw CDP error object has no method/phase/call stack.", + "source_findings": [ + "line31:Page.navigate acknowledgement immediately followed by Runtime.evaluate polling", + "line49:Page.reload acknowledgement immediately followed by Runtime.evaluate polling", + "No pageLoadTracker, no lifecycle subscription, no changed-main-loader barrier", + "line22 selects first page target without explicit about:blank identity", + "line23 rejects plain protocol object, losing method/phase/stack; requests have no timer or socket-close drainage" + ], + "causal_status": "The source has an exposed departing-document window compatible with the error. Exact hosted navigation versus target crash/closure and failing command remain unproven." + }, + "secondary": { + "time": "2026-10-20T06:37:39.7890264Z", + "error": "ENOTEMPTY", + "location": "browser_access.cjs53:141", + "path": "/tmp/tuldok-access-browser-aOJaTf", + "source_findings": [ + "finally sends SIGTERM to supplied ChildProcess handles and synchronously removes profile immediately", + "It does not await exit; a still-writing process can race removal", + "Thrown cleanup error obscures final primary diagnostic; no exited-process evidence is retained" + ], + "causal_status": "Missing shutdown-before-remove ordering is established in source; exact descendant write responsible for hosted ENOTEMPTY was not observed." + }, + "artifact": { + "id": 12245483273, + "metadata_digest": "sha256:0b60815d2c44a77b1b082d38280acd4d185907c6d11729a3735c0a175481cba6", + "metadata_bytes": 110805, + "reference_returned": true, + "contents_inspected": false, + "reason": "One local read failed: Tunnel connection failed:403 Forbidden. No retry or bypass. Screenshot/progress contents are unknown." + }, + "independent_reviewer": "/root/mcp_contract_ci_review", + "independent_findings": "Agrees navigation barrier absent and cleanup separate; exact hostcause unproven. No tests or changes.", + "proposed_smallest_repair": [ + "In access harness only: observe accepted pageLoadTracker events, enable Page lifecycle events, capture previous main frame/loader before both initial navigate and scoped-agent reload, and await changed MAIN loader plus matching load before DOM assertions. Keep every existing auth and mutation assertion.", + "Select explicitly launched about:blank page; reuse existing bounded cdpSession or equivalent method-tagged request timeouts/close drainage so target loss remains a finite failure. No blanket navigation-error catch/retry, no privileged-action replay.", + "Await existing stopOwnedChildren on supplied handles before bounded exact-owned-path removal. Retain directory when shutdown cannot be confirmed. Report primary and secondary failures separately, retaining exit1 and bounded phase/loader/method diagnostics without credentials." + ], + "verification_required_before_causal_claim": [ + "Existing pure page-load cases must continue refusing old-document, subframe, wrong-loader and DOMContentLoaded-only readiness.", + "Controlled delayed actual navigation/reload reproduction should demonstrate original failure and fixed absence of DOM reads until the exact new loader load; force target close to remain a bounded failure.", + "Owned-child delayed-final-write and ignored-TERM tests; ensure cleanup diagnostics cannot replace the recorded primary failure.", + "Once separately authorized for implementation/runtime execution: full unchanged access entrypoint on actual app/PostgreSQL/Chromium: real CLI one-time login, HttpOnly cookie, no mutation replay, preserved drafts, explicit commit, scoped-agent review denial,1280/390 captures, exact resource/schema cleanup.", + "Fresh exact repaired-head lifecycle and independent review; sibling success never erases this exact-head failure." + ], + "sibling_untouched": { + "run": 39370108074, + "job": 118455821471, + "status": "in_progress", + "active_steps": [ + { + "name": "Run python -m unittest discover -s tests", + "status": "in_progress", + "conclusion": null, + "number": 37 + } + ], + "cancelled_or_rerun": false, + "observed_utc": "2026-10-20 06:42:19 UTC", + "conclusion": null + }, + "PUB_1": "Original failed diagnostic bytes/path/profile/caps/receipt still missing", + "SCI_1": "Owned qualified criterion and compatible real lab pair still missing", + "external_mutations": [], + "system_integration_block": "Remains in force; no denied operation retried", + "same_as_predecessor_29011_sources": [ + "tests/browser_access.cjs", + "tests/browser_page_load.cjs", + "tests/browser_owned_cleanup.cjs", + "static/auth.js" + ] +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-excerpt.log b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-excerpt.log new file mode 100644 index 00000000..777038ac --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/original-failure-excerpt.log @@ -0,0 +1,32 @@ +2026-10-20T06:37:15.2772080Z ##[group]Run node tests/browser_access.cjs +2026-10-20T06:37:15.2772426Z node tests/browser_access.cjs +2026-10-20T06:37:15.2825753Z shell: /usr/bin/bash -e {0} +2026-10-20T06:37:15.2826003Z env: +2026-10-20T06:37:15.2826392Z TULDOK_TRAINING_PYTHON: /home/runner/work/Tuldok/Tuldok/build/workspace-training/bin/python +2026-10-20T06:37:15.2827074Z TULDOK_NATIVE_READER_PYTHON: /home/runner/work/Tuldok/Tuldok/build/workspace-training/bin/python +2026-10-20T06:37:15.2827855Z TULDOK_DATABASE_URL: ***127.0.0.1:5432/tuldok_test +2026-10-20T06:37:15.2828258Z pythonLocation: /opt/hostedtoolcache/Python/3.12.15/x64 +2026-10-20T06:37:15.2828711Z PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.12.15/x64/lib/pkgconfig +2026-10-20T06:37:15.2829143Z Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.12.15/x64 +2026-10-20T06:37:15.2829525Z Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.12.15/x64 +2026-10-20T06:37:15.2829903Z Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.12.15/x64 +2026-10-20T06:37:15.2830328Z LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.12.15/x64/lib +2026-10-20T06:37:15.2830686Z BROWSER: /usr/bin/google-chrome +2026-10-20T06:37:15.2830939Z ##[endgroup] +2026-10-20T06:37:39.7616902Z { code: -32000, message: 'Inspected target navigated or closed' } +2026-10-20T06:37:39.7886304Z node:fs:1282 +2026-10-20T06:37:39.7887476Z return binding.rmSync(getValidatedPath(path), opts.maxRetries, opts.recursive, opts.retryDelay); +2026-10-20T06:37:39.7889224Z ^ +2026-10-20T06:37:39.7889560Z +2026-10-20T06:37:39.7890264Z Error: ENOTEMPTY, Directory not empty: '/tmp/tuldok-access-browser-aOJaTf' +2026-10-20T06:37:39.7891130Z at Object.rmSync (node:fs:1282:18) +2026-10-20T06:37:39.7892007Z at /home/runner/work/Tuldok/Tuldok/tests/browser_access.cjs:53:141 +2026-10-20T06:37:39.7894084Z at { +2026-10-20T06:37:39.7894665Z errno: 39, +2026-10-20T06:37:39.7895114Z code: 'ENOTEMPTY', +2026-10-20T06:37:39.7895754Z path: '/tmp/tuldok-access-browser-aOJaTf', +2026-10-20T06:37:39.7896347Z syscall: 'rm' +2026-10-20T06:37:39.7896775Z } +2026-10-20T06:37:39.7897797Z +2026-10-20T06:37:39.7898074Z Node.js v24.22.0 +2026-10-20T06:37:39.8035099Z ##[error]Process completed with exit code 1. diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/post-run-cleanup.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/post-run-cleanup.json new file mode 100644 index 00000000..00a8746d --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/post-run-cleanup.json @@ -0,0 +1,35 @@ +{ + "observed_utc": "2026-10-20T06:56:29.403793+00:00", + "schema": "catalog_82698c551bbd413a878d83de58438931", + "counts_before_disposal": { + "workspace_runs": 0 + }, + "schema_absent": true, + "temporary": "/tmp/tuldok-access-browser-7VR9Z3", + "temporary_absent": true, + "matching_task_processes": [], + "owned_main_handles": [ + { + "pid": 119512, + "exit_code": null, + "signal": "SIGTERM" + }, + { + "pid": 119521, + "exit_code": 0, + "signal": null + } + ], + "source_hashes": { + "tests/browser_access.cjs": "e3c1bcd19d73981a39a3adcc0d32d7e67029907e0cfd689e2739348efbf0e56f", + "tests/browser_access_session.cjs": "d61b7cf0c366134050d6bba3542fd209005c5ad22f10a3659afe0ca8f948e1a5", + "tests/test_browser_access_navigation.cjs": "56ae9b76f1aaa3803a90f03468129f243d0b37f6a50110bcf7c13840da18f80e" + }, + "checks": [ + "Anonymous legacy/current APIs denied; real one-time login consumed; cookie is HttpOnly and code cleared", + "Sign out and rejected mutation preserve draft; reauthentication does not replay mutation; deliberate retry commits", + "Real scoped agent identity cannot use owner human-review controls" + ], + "report": "/tmp/tuldok-access-browser-ci-repair-20261020/qa/access/run-vVR332", + "scope": "Exact preregistered test schema only; supplied main handles terminal and exact profile absent at post-exit observation; no blanket descendant shutdown guarantee." +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/qualification.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/qualification.json new file mode 100644 index 00000000..d371e0bd --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/qualification.json @@ -0,0 +1,114 @@ +{ + "base": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "branch": "fix/access-browser-ci-qualification-20261020", + "worktree": "/workspace/Tuldok-access-browser-ci-repair-20261020", + "retention": "retained-protected; unpublished local repair pending serial integration authority; no cleanup authorized", + "source_sha256": { + "tests/browser_access.cjs": "e3c1bcd19d73981a39a3adcc0d32d7e67029907e0cfd689e2739348efbf0e56f", + "tests/browser_access_session.cjs": "d61b7cf0c366134050d6bba3542fd209005c5ad22f10a3659afe0ca8f948e1a5", + "tests/test_browser_access_navigation.cjs": "56ae9b76f1aaa3803a90f03468129f243d0b37f6a50110bcf7c13840da18f80e" + }, + "companion_source_sha256": { + "tests/browser_cdp_session.cjs": "ecfac048e343e0be85a02d22d284ea2c731617ec80807762a0691276f2bec40f", + "tests/browser_page_load.cjs": "bb74bd6ad97e0ff7c4545c747df698d0466d143764b0ccb52ed26b2051a13318", + "tests/browser_owned_cleanup.cjs": "1cddb8bfe88999c89193b2c3f11f57ce842cb04e25dcdd99ba4f2f9ff28b3988" + }, + "actual_command": "node tests/browser_access.cjs", + "actual_exit": 0, + "actual_seconds": 8.60535, + "actual_attribution": "Precommit HEAD0ded plus three modified/new file hashes; actual receipt is not a literal repaired-commit execution.", + "original_failure": { + "run": 39370107550, + "job": 118455819881, + "decoded_log": "/tmp/tuldok-pr112-0ded-access-failed-job-118455819881.log", + "decoded_log_sha256": "dce0386ccf600104e93c6129a28bbd4844ee5d73921b64567d3a2234a9748f6e", + "primary": "Inspected target navigated or closed", + "secondary": "ENOTEMPTY", + "original_cause_proven": false, + "artifact_contents_inspected": false + }, + "focused_checks": { + "syntax": 3, + "new_controlled_navigation_reload_regression": "passed; mock CDP ordering only", + "existing_page_load_regression": "passed", + "owned_child_delayed_write_ignored_TERM_regression": "passed", + "diff_check": "passed" + }, + "preservation": { + "original_refs": 82, + "original_worktree_records": 96, + "unchanged": true, + "running_sibling_untouched": true + }, + "external_mutations": [], + "hosted_repaired_head_gate": "not run; publication outside current scope", + "PUB_1": "missing original evidence", + "SCI_1": "missing owned criterion and real lab pair", + "evidence": [ + { + "path": "acceptance.md", + "bytes": 4413, + "sha256": "ee8529aecfc71963e768cfc98c72a847680fe10de8b8930d21b4d9b394f85c74" + }, + { + "path": "actual-access.log", + "bytes": 346, + "sha256": "ae63a93687389ad38ed33d1ecbe7fe8916db65afff8222c4a9acfe8b07f4b2f4" + }, + { + "path": "cleanup.json", + "bytes": 341, + "sha256": "06b2c257bca7797d663ad809335504a2a2d56a7b41eae4edf77b2049b110538e" + }, + { + "path": "independent-review.json", + "bytes": 10086, + "sha256": "ce616c44d452ef18a96df683fd9ce6b524ac6eb97a40c497c91164ec480182c5" + }, + { + "path": "independent-source-review.json", + "bytes": 4965, + "sha256": "3b8d598bd31f575c0d8b20780a275abd9b0df10d7ee8a589b21a4968eccf56e3" + }, + { + "path": "original-failure-disposition.json", + "bytes": 6212, + "sha256": "3abe25f69e93b32459308ec15dae8e32e35c504447414faa0e657c1a0d9f5696" + }, + { + "path": "original-failure-excerpt.log", + "bytes": 2275, + "sha256": "7a92c80edc4a25e16424b63efcbad9b04cb2b53e45a9559733aa8d1724b72c87" + }, + { + "path": "post-run-cleanup.json", + "bytes": 1433, + "sha256": "3fefda92278099fc5e93f1c05f363277b72469535a8dbd9cd83f5832023a6fc1" + }, + { + "path": "receipt.json", + "bytes": 1693, + "sha256": "57b652807e1ac0e89d9f422c0c551051e33782ec779a016f0046c3ed48c6268d" + }, + { + "path": "runner-receipt.json", + "bytes": 763, + "sha256": "b247a3d1147a47f0304649ae2a110969c2da7c1d6e4cd5a0abe8d82430753ef9" + }, + { + "path": "schema-reservation.json", + "bytes": 234, + "sha256": "20bc035c94c464cfd13179a32bfdf069e49302f7d6f1369e8f7c2081ba15e5a5" + }, + { + "path": "session-1280.jpg", + "bytes": 92512, + "sha256": "ae5ecddb60cd751033a62eb24ee383daa4d56da85439115b080178b18b5c5580" + }, + { + "path": "session-390.jpg", + "bytes": 46763, + "sha256": "71f975c51592a0a92669c3d5213b21561acbc83cd4450a532b9e1a2cb7907519" + } + ] +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/receipt.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/receipt.json new file mode 100644 index 00000000..e2b89d92 --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/receipt.json @@ -0,0 +1,47 @@ +{ + "checks": [ + "Anonymous legacy/current APIs denied; real one-time login consumed; cookie is HttpOnly and code cleared", + "Sign out and rejected mutation preserve draft; reauthentication does not replay mutation; deliberate retry commits", + "Real scoped agent identity cannot use owner human-review controls" + ], + "anonymous_denied": true, + "real_cli_login": true, + "no_mutation_replay": true, + "source_commit": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "source_sha256": { + "tests/browser_access.cjs": "e3c1bcd19d73981a39a3adcc0d32d7e67029907e0cfd689e2739348efbf0e56f", + "tests/browser_access_session.cjs": "d61b7cf0c366134050d6bba3542fd209005c5ad22f10a3659afe0ca8f948e1a5", + "tests/test_browser_access_navigation.cjs": "56ae9b76f1aaa3803a90f03468129f243d0b37f6a50110bcf7c13840da18f80e" + }, + "navigation": { + "phase": "scoped-agent-reload", + "last_method": "Runtime.evaluate", + "events": [ + { + "event": "load", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "C704421B4745793C1F166C7CC67C83F8" + }, + { + "event": "main-frame", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7534733FE54346FBED7374DBFE2EEB98" + }, + { + "event": "load", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7534733FE54346FBED7374DBFE2EEB98" + }, + { + "event": "main-frame", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7B0CA169AEB6A2150994309812BCD5B7" + }, + { + "event": "load", + "frame": "429B7ADFD788931A1DAC0F8F1B79610A", + "loader": "7B0CA169AEB6A2150994309812BCD5B7" + } + ] + } +} \ No newline at end of file diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/runner-receipt.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/runner-receipt.json new file mode 100644 index 00000000..08de421c --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/runner-receipt.json @@ -0,0 +1,17 @@ +{ + "command": "node tests/browser_access.cjs", + "exit_code": 0, + "started_utc": "2026-10-20T06:55:51.714739+00:00", + "finished_utc": "2026-10-20T06:56:00.320089+00:00", + "source_head_at_run": "0dedbc953902ac89389dca0693006aaa02a0a87c", + "source_dirty_at_run": true, + "log": "/tmp/tuldok-access-browser-ci-repair-20261020/actual-access.log", + "schema_reservation": { + "dataset_id": "82698c551bbd413a878d83de58438931", + "schema": "catalog_82698c551bbd413a878d83de58438931", + "state": "created", + "owner": "access-browser-ci-20261020", + "catalog_path": "/tmp/tuldok-access-browser-7VR9Z3/data" + }, + "environment_changes": "None: existing runtime/Chromium/PG17 only; child environment and preregistered disposable fixture are task-scoped." +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/schema-reservation.json b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/schema-reservation.json new file mode 100644 index 00000000..98671362 --- /dev/null +++ b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/schema-reservation.json @@ -0,0 +1,7 @@ +{ + "dataset_id": "82698c551bbd413a878d83de58438931", + "schema": "catalog_82698c551bbd413a878d83de58438931", + "state": "created", + "owner": "access-browser-ci-20261020", + "catalog_path": "/tmp/tuldok-access-browser-7VR9Z3/data" +} diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/session-1280.jpg b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/session-1280.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2fb51729944307bef6890fa43bf4558d7bafab2a GIT binary patch literal 92512 zcmeFZ1yo#HwkTQz4Hn#8LI@J9a0$WP-9id4tSBr25+K2$a0njUivWc~@G2m|p>Tq` zCV>zL;c@z$bG!e4-97H_fA1UjjnS*dnl<-aYt1>=TrPXx%-*a3NYs_plmQqR0074A z4{)=FF{`GaV56(AqpYT>^n1Vn;MQRY003_8-d_4DPgqRN%vo?(eoygRm@NqE`P=_L zaJPKV(Z6vA04DkVL7aa^zH4U>1>HtCx%C`gx596grMSf@9Dm0j{DwdK9hd$M_w)Aj zzKx^%8}4POuW*ao-Qo`%{|0~dH#o@C>$mu^w{fK1Tz!6%^_%-mV?uj(BZJ$2yj#xz zfCBUZDu5@y<^T5i)_D{F0ODr=0A|8pY0okMfTl12fM))$G>&%wz`ZvBK;!6NX@9ke zr>&RmU)W*Y!aEKQ0Kk`00D#C003aU&0PrpT5_Svzfo?3fK@7KgdEEXS0j>ah01H43 z;0^!*_-`>GfB--cAbPU^Pyk?KVqsxnV&4L6Y-}7{LOk4CcaMPJE+OeXGBVP8q@?6j z4AkTlbd;o|G^{jqjEv08%;eN;9BfP+3{1>SzcInMO^Sk<637?PU{_Fh%bV_2>R;TSf^UodH{Lk6VPd4WaxiWc!Nj_S zxWC1~AiaZ0M!_nmheb|lkc2I-&n9F$o(KtH2YQ_dizwFCb@$xN0|+s16Ov+*0^|U5 ziKO=1{>OKU4R5^*nWCa1DJcdi$^UGiU}d7Cq<)!MZb6|*3(fY!78;ilkvV*?4}`PU zl=Vi$H*j6DOKdjLrYW939uHPsO*%S#a#Xy%i>oY~F827SxL?mDSDQ=B<(g#&HL4Yhq_ZUjOYdcK%%*H{J7S*k3A#s7!U zmivh^Uu^alzf()Sk+%Dh{n!|PGTfS-XXDW3Pj!;Ny)I{v-UB>0zeR%%}F!dt_Ab+m+i3KQEEUp*0zluELO}_m_9L5@ApMQUFdYE1>vS5#ltH z?cSbPie{ewv+JU%h8d4YXy!8Aa0((>bNzJ{1F8>4da3370k~!gk!tYd;-L+r1lWZO zgaIQvAYts3RwNJh#2cY*k_vL2Q3r=%yU9qu@8;mFH^?ww`7W>xT?hr@#>ZJqo0jHG zYx+Rxbu3Ny2KwliSI~$(M)xUkkvn*P^AW%$;9M$jnqul(s=iPTQsN<|Ir|JIXCXhD ztGgK_O9_H>3^^CU9z1+dkzZDH&u-ZEzJw!KNWfCyvHxkjP|DoiJWu&bizuCBFV9Dd zy9>(S<2Gy1NFeN`cHrJbx{?`2In<%}&6I5FCgNL`Xk2WGHs3QfUr#j|)$F-|)DcPU zwNf{rmXTsLbb*2hd%hZ34^ssY#uID%*_)0Qiw=}IR`)BcML#G$G+U6VBg4UvSTsL) z9s9KMW88=5mH9OV74|Zk5Lq(27$=lqf6)f6$Ocs`!-WoAtwXGVP{k5U&PX(jONGP3 z-FM@4==w@GbVLvtNTZPHQq5WtjTrA&GcgjKu^T5aSIDV%eRIbWchGa$^R+6sjg}5C zMMLtScw!HZvS=)6o6%-h0uEza{PVS;=;6XnT%p%Mc+R())Z>7{?sQ9+*yE*Oz{xff zHnwrJf-oz@hvDm!%Lrm><@>Qw_Cg@tW(F9G{Oxc;vNfP@!wu$PFDVQ!D72>8o)>&4 zSUW&m8O7lbJCYNl>$KOrSDBWWgek2BULGY-sDJ&_M`y8`FAX_v^ihhD#5F+yFIv2T zW;nNrWMsvsxt->uDwK!hnx)uHqi|)~JyO$oLHz052fYMSv26+L7IxaDRN9Fchr2fb zdXtqKz#CwLvZ((^4f7E4=OZ&vfP<^UdpfG=Ok{W6;d$8R#morM2L`FkldPj-B`G2C zoN(PD-XfU0u|uS4WS63|JF25gzB8 zm>qmq?xpk`Jvwi$@|rm2Jny>LJ*~nT)3vx@-c4MZH^znrJ?%t`dL88)l-W79)9HKz znAfM7zE0Yflu**L@me|4m#LcT7`Af*^1Md6i=m2k(W1uknmYwi?M&}c z0;KycTUu5(fCt+RD5}-q##2yZOO;C%(9pYX)B-3YJ7Us<7H`gA8WA8cSBdad9m?b( zd~fAkww(lX-dx`E+NG}`&o#gmgx-A^THA=~|rTgdIxA1_?@GZ`%)T z=%MKtv5-5E>;y4v%S#ypO8N?MEAr)e2O~+Gjshl zca8={kEMV>1YsH|AQ%GJAnJwaeK@O@p73C-^|npMJ7_~K)CIDkF!bd#>iWp>uh$ZM&%(Ka@dTBfe$s24;yQp?pRVEEOv0u=XE z=!Nq;H;FRW@#eIFv6CL0#}ZhlBqY}Nde71ov&=t~j71NOoXEG{UO8fBv$0OZlLie^7r?xb*3GlU0Po=#nP-ixO@`RzH)65 zG~{qv=F~QFZ@Ou*#Di|@Qn#Fx!g*SxO?@BX`1qTbl>2Z4Fy(fhw@_V%Mt)jhoI8wQ zGR%qep4cybLgByWpD6X#9(fvI{|<2@JGwO~nApB!3+VdCEK+pK|0VF>^zS6`*$jqSTx^{PHt&>_!e&!`EgZOJc{8a=T(HDDk`s=@9HMyw(lqwRlv*{&nsd|m8Z3K!U5biWijV)V2J$Vw=08gFU%k)k4bz*&-Hx+4`u>Z< z<-;W8iiu8Atxa?fGB(KjAdDKHrH;>BHQb|g`Q ziPL zD7?Cj)W?O(HsZ~aRO#bXnn};Mu^^yWYnw+vs`2?z9qEMHaQ`_q_ByrC3nGa$$kXan zo&L*7ic`tDke)&lmu>w|+v14LQq$4w*L~2O-ahK&okP1rs6%zWKUBe*Nc!R>4u;>w zbuE2Uc22j1uz5=Bg?fcl@9w^+_ZXOzK$HLeQ~K;i&An~Nq3XzHT*(AMjy-FpB$VEv zIB>ju{1ZI}5!wlw6W+<*Ga+`-({Vwy*&7CeQ|P3^`JIBKk3g2nLNt!kxLC)SJtiq= zjW`KkWNTOzRKwSj4n%?*i$i;+a&mXjLD)*~qnCRu{%a0OU^~4t^Mz71WO@J#Oy+l* z9si!!ZeE8U@l~EsyF_HJ7&2m)X9OdZx`2%r-T)egeuXah<(IetfyiLR&q>T`JSWnR zTfH8Ch47eu^DR$7e5=YuvzFv}5cpGcRDRJ8_;9@)d32SWD7D9J*%S~9F+}g_XPTRb zU?tuT2MG$6E6|YkBX?p5s>9;5%YG&Ai^nsb{=4NFA}lUR-){incoHMH%#qul;C6K; zAIhd$>z3fw98e{Oe3(Cy!K`VT0@}tiO=N2gwTHMXLwO?Hh87W1^)2U7w8X=wZ^{e#l_>W@h)Ab{! z3CX?=$;Mym;to^RW7M`TW0;@8h z5=}A@j}6{F1WW*TWp4Kp zS-4Z^4Ozhtb3{IYm-^F1wCRpmk@)iVEed8mbDjm>3ul@slkLLNFY+f7KCj&IGX3oO z$xCxD1LPxNr%A+{Zc6e6ng|n&TYL$up0M0(T0Bac9_B@i29{8@^zD5RATA6v@9qUW z=d?c;JFcqkyu`f$ELIiQnWzJjO3(*}(fOIQe(G{dOC8zjPc~a$u-4YCb7pQ58TCN) zhthEe7?YOA;ZSp(L0S$%h(DE$%JL6a(I55!x!))Hwk1%Ueedm(*Nqbv;Ny4ue9-8q zWt&I8l(pyj06M<6wStomn{hr(oP`qoiwF;lNw0X~gL8mOtNqho`&G1BtY%P}XiUe5 zQ?(JWx=>(I`<*MFr?>kQG-QyAWiMxzW|US>=*o*KCdjU~i=&yUQ52=aktI7m0*!R$ z_f_x{!HB;r?b2o)Z!{*a?7ZhRCqfd=Sf&4I?CY28ZiJJ2;4p4HvP9G(AK z$PSw#{}X#;gxi;Uc@iecg0vHv7H0~g`issNGE#4bA9+8DO;-knU|g`mpF+CnW3<0i z$8Et=8z_Myy3zGoYOSKu3A=WQ`9*|D^lO+L+eksE3~W_~z^Q`Ai7Tw;-W_wZ+=F=f z*dKDQsE#-}&SO%JbG{nQFFS&0`JFfpU*F}s0qnbXLnP=Y6V2X*UYpUs-J1n+XX&yh z`5CC;K`l`vD>KJ5p3~BSwnmN}Xtb7^hBT>?0Y|*|C%}0vUhll}FS%28tW!rb&i6CJ z@_dA6-=LF2E8C4O&zIG(NINEz#9%B&)0}mUQk^}*h6|tB3rST$MF9+3nAvyiSv*eG zyRy^RrEFTw6Ctj5l0}eg+lFp9+Z%vkYngQ}S$iuhBN>io>KPdX1g|lkBh}XMjcl!S zpqU2mE8p2kU{__vO^B0rN|1^5c1Ed~wQjVAR%H57b?XtrF*yWRvR`4xG-o{g7D@oF za0tydko3c|f5~=K#RGh>vx`zsA;3dwTmdhfguUg zbH{jM*Ol1oGNg&%IB%WNBwF67Np<2nX4`w(ej-PA1=GKqiz_y#%ioZqDIm-nAuy?; zMX(*}IJAr54=PNo5(mVFs-61ZdwX%k*ng^svUI*1Nirx(ehA>=03V)3N;Q$M;G4Rc zh;xRkx*WQClhS~u-zDI@PfHSPMA54(*4%%kkFx~NSbgNij7?3hY)W_NHOc=;N&@K@ zH+y=_pfMzMX0O#>4NFp)lq~;tSzVOQO9XKr8;pA*B;HQDKG2i35|D-h_42i5v%gsn z(O3eWowYTkb~0!T9L$LC4IBF5KUlW3-m1%Vs2!2Ed#_WWll^AH7~FV7)nXH~~Z{kSaT0@9Ug=A@Xm%M+q6<`!?W#ji(?<{# zM7JQ|_TJh_GLfEwBpA~YTo#aZnkxzswB(*Gfo*w1!+TL>q&Q)bh^p7=Ytf$xMGa;Z zJ1%pAhK%6Y}ljcf^rXk7R*P+cSn% z4=gdL8r!ptt#WPv>&CDkAEk*m7t@7#R(js~o>*F?l*U7)S4?V)uuA1A0!0K;AB8^Az_6&>9Zo zyd75||7al`!zA1sOMXr5UJ1?65T5tks_kQzrE=ijnV9+AH58qaX$K8yi|m%xNZ1gGiLJ)MUK)o`-~_Agem`PQb~}z>1q)PjY?3S{n$K8PPhl6den?Ac+c+!%3!mFn1`Ho9 zxzr8%mF3iwfW0Q^U&rRMEM0J1mo*Nup%#vfE3W+RmDZGaW4s$Utk)h$%ocwg?03q& z<1Tu6vaVpIVMza_QK;eK%2T&th)2+;A#((W-_W6m!PWP0W;Dh`!g|{B5Ya$XTG6a8 zFZ@f>OB3CE9i08HO(}AMk-cHIxG;KEw6J1}v_3%jowSFqYOl(hs#qiMdcEj@3frW& zh<43642QCH$wkvAlWcWC%ae=*JfEQjZXB>_yDi_yMZY8Bk-Lj8*NTID$RFAk2iZ$G z=CqFW*<*YmmPR;o1V!?bnv3qb`q&n@A!Da8U*l!8u3R)gQw_i4<8gVDqbHSk*ymf~ zQ}c%%AXV~mTvGLYp_^1SdPVht0S#u(L>yC;2w3)~#TFFC#k8k5%0(Jmr?^#xvPlK* zlQxw3Fms5}%0H&}?5@8%13KY$IR@e6?6p;jtzG5@@9gyM?TUL(jSq85anKF(J8?CP zJYI%_-HrFS=^5>Nk}{5e@TEDtZ#%#$nBS$Kq(pd6C^0Hol6-JI$l?eozMvJyjmPXO z&u`W>iJ+s~b9vVr;c5>)d%4IsM37>fWW|>_9WB8x;#$sihgy5=OOWLz7;VM7;Ea74 zy${4@Dgaz~c)MjA;jmZfOu)(3!2%n99TLg2;;?);bT@;!T*&toVHY|wzZ|a}_ zey30H_+a5zgu<21uZgC!cfM{n0EPVP(i?!Yv1AMQ?ou|=J$$H2Z@M*U?GJ&z9n%bGa)%st=N#Q7uHK6&#u8GK3YC4r;0NNiz{1g#3y!lAbA*TJYr0VToTo2&Qim+NO8=x?a{DT3i;GOjuOTUCr%W&{bv#nS#VCX zF_Xlb!h)a^m4=B+9Qh^Hl+a4?lt8rP6TMs;|O5<>fOJ9TcM8n$r;rSyhL0A`QLg z#RAI9b93p)wkMlK^>2?)Ed9f4#W^lQEI2Yv?8Th+S=@Ytn`K7|Om}a$%ZJGha*E8R zk@yn zj-!oBiG3bLCR~kFp^}67@koV*9(&}wx!Kc(Q-iQa-5Y=LHc8Na4a-bdW}8P0w2N-8L3>#$wBvXs++tetLv^Q4R4BFMd|(IN%dopCmrh@oRf(qU3pb)B$;dS9Zd?{(a3)7Z98V#T6y z%X`io72%&*!?|SYq+6<|cz-8Db-{ zfxSrlUTcwXx@%@13`*jh?-D#5&`fm0u;IzZ>FI-Yhl2rfdP6Jphi4Bh~>y~k9M(c#_GX)wP!6B)oFv= z*mjU`AmS7u(9o6Rh*@<5ApY9FW+bd}NZ6@wO|NCXtHn}W88vL{kpP#s`RM5xe|Jc> z-KsC_qnuF1D>LS=*hp>;SD@$6iiYWV^Ljj>JYKn7=h(IBn$!(DfDd6bX>1~EOJbMO zhPRZK+^QmFn9CY3i9{7rqdw#cJ~qFM$|K|pj0NYOJDLKtJq7$ud5@BuiIPtJqT%X? ztRg=->po=6wMW(E#WnVoKNK11z^= zx?a}JfED8GUinxYc>}nsxDeqh`Z?cksC1Me<*+2saFIpSq@lPgTf{@ATwK~8DRx2C zA>tA4*w2D-009TH9Mi*2k&Qfz=i#~Q&waX6wM$z1Iqb)AGH9y~UWa^Np}zI_$Eg&5!iE;6}ch{zuIxlz+?SJKbQKywr9FwIBMoPjSXfU%s9x)AYXHA0i z_rV{El;B#jRmM%?ElJsDzSUP8enMlBHb7h-i54HgYl9qhtAX13)qsYLdu8h(!>*a9 z62&c8uS3P(i~n3l<|i#cqE716@k?Z1Zp=Jcu{-ngSZ7c_r)zVQq158=GSXxg0TOyA z09!|5RS6h?BN#L5gKKMMlEa*(X)C)KK($cEPuu<7Y;ohX>`>tAd9N?P<`LoeW@BFL zp(P^^H;KyFz8~vCc#9JZV+>p8U2!Nrt^-yNtJhcO+n3GPN9I<0b-5)3ffOS-hef3V z>7T|Xj!&5myU0T#Fi7T&ZXm@s?$OL^w4eMN+hti?AqJr)BDT-pQc@+(7D1iv-O&0EfK3KtM{=u32M>` z@yo4RZk(LnIJu2!_;1y)P$IU691wS@6mO~p9{^i;Xj-}y3`tcl=V{EDft)8!x8$zy zMrvpxM5$V%6R6Qv-JVcYTtYx>?!v5bhXT2a6s{#BhgRaZ>6SNX8%Tonk(xJE!o7vT+7nq@a439!HWc6eOJhbF?3eIn@((zMrJ1Q z5gn=|)yKj`{o>1pSJ^NLTpDz{6ea*tDOFAIbndv*;o9=FdwwYJE|=(C#hQL3bzj^Sl` z!-N&Vn_=gX$^r=#m0;|JG{O6cc|OAi2DY?0C9K6FPayoNYv{aj(gmJTZ@loJ!rrOZ zMuaFJVpdf{3ua&JjX+FY66tv*CBa$F>k6vsdDBQtEvhVqEGpExzrwS?7oq`%&*ta- zbR~*wBh9hwTUdf|4j|tZX zn9q$T1U$Ei7_ONNJY54FR@pc9-5Sm#<|<>K|J--$SYU1QHEPhaTAxSEoA0g@v&eL{ zudH|9ZbEc>yH$YB2HmX;pA-!)g2N z>2t%p7{6b{OELf2_&a+#1%*MbKBGk;(|S!t$#1(83tz4r35ex&C~y``vR5#2!lRDL zk&CT4MISq58jlwIabK7<4AP&FmW_=Uc84A}#)KVwt;wCSvANiPMR-AJg6}uwT$0oa z&Fm$tdCBhc*_4!Yq&zYdAU^%|6x7ptV7wn_6v+RO&e)J@@6du=;dE_8I7}-DKIa)= zW8+>}3B{pv45{I}5)$JqLGiX*^rc;6HX5OoJj2d(B0rMnRC3rK0Pc7~D(9;@;GqOM z_7!^?ii9PgL#5%kPA&^RC0>CP3f!7%zrzVVN}9Ld*bO6Q=$aV<{eMXeWuojFtwkm^ zwUDU|^wc3Vepea|bt-wD%dI@s#wg?HZ40MiT?z8H^oY@T3tD}71tqM>QEWzO{V9e| z=gOExXOZjc(l15o1YLr{mbaZaFh)2;oiPJ@E##)%qv;+>s?%W0Q1ViYg{s16dg+r_ zyB16I%_Gb5Nh$RH4_*xh2Ngb^xNv1}xSVyJDEFrBIG#fH;j z8$(gP!uK-uf&ktYDry{aWrNaoNa{RFZ|I&meo4n2_|^#Jv)nry)!yv@O_mPnLpe-~PkmjA%HF&hto+ z9+K)?FYKY5mix*1tGyxFq@kLQFabwgKODEqP-ExCK4oSr2x#A!`TQPzZkKw~MP*^0 z{)BITpF5&)2&6$ z7T2!j)TQs$q$P6~#ghSEO5QE07~5-Ju?@&H|ANbeF=z=45?EoFm;uPsuv{3kY0-}V z;1E)CEQDrzsm0nAY4O8jx5dbQ{GfjIXJ%v{?rcvXtVm3t=>+M10Hx2r{vhZ?w@RGx zQ7e)|dN!B3NN;yG|0MjO7uKR@i=QXf?X9jq34ihwW8k-1#Q5K3Xrca@2DOuAn5fp8jQ0D_ZlVBYGtKLsG*uQE^6H=5tM<71D}Rq*!H& zQh>=1>%RHUq4S5-@leyA?+IvxUGfTE`EO~W8eXLy=qa&tMkOIvwq){$*?aDhTGJM+ z-pR9S)9*PMC5GQlbKYgS+yHoHvu+vnV~d14(Q-$t#>^8J1>=f+g5>NeQXblD29WlXTEd-uB!hBY?9o1f}id zWDhDq7z!2DzDXafWP*3b&7qNgr`7$GjlK=yd_v42ie zeHDis8wO71f}PkMfZEz>GhFn|)5Z@mD0@B{K^s+n{35cmaGXeQmB>^X^1bVfdb56L zk;IuY!8gU4lD7JyaoW&8XpWvO^6~e#TZ8D2k3U)}moPwL8CR_=4(g21dUaRod&!LD zu?Zj3#hk1BM@c=InB?#m^mylI%AGgTAD5RO;WSE!^SY($i^)D!7GDU}p*oFQ=V2PI ztrtz1;|>$7fGP|(YCRe2QWzFL4B_HKWyz8>QD|@%>2>=x&F$GLeUO#`l!BnK_15hJssC636?AIC?(wX%u*(iJ`vkbnzp^we;UTmcrT# z%o+-I8SkdiPx+)>4(-RrdECjAbZmBUofnwF2>0#YXky8}@S@r!Tr=B#qa;ko4`?}H ztr@`OlO^qBcFCZqV|$~h^gsI*roYag)pWj$&KBxV{wxR_C{H9ca<}@sTLd+AGs7|j z*Kd9?JcM=0N#71gex0Z6=6a8|G~*`gb4oe^Gax7)L~N7miBJj%ZVF2*bA7q(Y;D|5*fp$?hx9|N(*gn@763V zId|=iq<3jm+tik{Ao6~Kar;v zR=3BfX?rnYc3I*qwgF39OphdI5U^IR}0M`7c$RH-~Jq7Mt$CGUoQ5HO|dG1U1uSQKTG|dd^8yeNIvq zY_1j-9VsdE=UyEIGjKQLRI%QFMgYBQ}O1n zD^NzcgmWv_4XV4aMQvnDoNm}Les-XkA%N1)UN)RpzG>13fFER*C+JD$RL7e2quzS!libgMPl&lEppqoyv!E znwIkebM^eR(vFRuOY?F2dK0f={M=F0HPMZ;A8lvbTP1~=RQ(5O0ZH`L$!nYnf$;j7 zId5$X9*`?h$7G$BswT*Z4%kE@AcLE`k5uk9B9wiu88g-YI~U(7mb`DZF z(*N7m=;D4JGsU#Y2FvOwIKypGMX)rZ4J>vX;8iI~I+z3-&#_kS2`s+~4IlJrTCP5* zX*9%-c1#*OnOIs`i6y}^k9SaC;}a28Ehx+R{xB_yt<<3%7WGDA{v9MQ>HQ^_kI1C6 zPaU256^J9$B8~zmNMj$*%Q{QD^tv*Z`3~aK=17hfHA_)>r|vAmM)h-%30)Kq7*vv$ zt0qhun?Pk!J%ovhv>ZdaoEYr#0G1u;AN!X_^U=HfsT9h4_LN4R33H6~;sB{Go%S$nAEUub ziIOz6qXwUZ`36xS|Er65;t_<0-&OeG4FL695g>$AM0hi4X*s+^B;sv9S`wegGuRq# z;~-l4a6*#Q7O7>zz8TA+e8*+BE|?+q;*s6_6AsPq8MDn6(MRkAC2-0+Dl`)!t_XROGz#hb35TQUZR${WpM}Mk3q@b#9SRQ#fIBmLXz(7-IK2zHB7MLhPgM|)4`m4iNm~o7m zzTQtX+;vli=}ucaz!sE9A}5Vi2$Px{TGCXcRo~KXAZjcnP4P^e&(fr5QPkj`3#tpB-{YMa8=5OGobN>Vj}SwXk^WywqEX;z_^RQMr541=&7u)@10VrBUdkrw zJGHgbBg=o2rzG++fPqS_x+*F3j;3DA5$BsEZN?m1WZ=WK&xPmUpb`rs&JQ$Yn^+oD zcV`B=(Ol1$*3Cqo@q#1JVeMk>GH2dVIBlCl75Lc8M zXgrHCsYE@-9f%4V(0^fzoNi~)a&ZC4wN8s=k!vryf zZw}S_c`&V+TT^3_1FG(mzBI1b1Z{78cBrvENtx-Cx!W0aG`JmcIgO}-vZh=08j6!B z3%^GC_cVTRnudMnx!-REH}8L&fm1ByO2`Kgo}(8gJvYhe>fNVcK}a;D{?M z0wMjO#DQErMb)+Ql`Q$81qqUpcWF6!6c)$n-wI4NAEP2S?Go|BiBAj6rTnUZ=>(Qu zBP*E8Ok33JF&2h#9&2!(Z!boz3_Qv!3S5&GB1Paco^y$zVwjy9FzKoSR$b(TX|-W` zMb@wki+zxRk3+f@%GCXYJfu%NBE&9{RPq1xyPB0qCe!{`A*L9bPhou(4{c`PP>5?d6*$zDKGxekM)`(H-#K zvzjJ1|G@Df^Dk_kaV?$_lKqFWfe*KHi$MG(F`5&Hyk+%TEJbPI?+k>5MTlW0Y7730 z%hPRHqyYN^uWFG)%xKd^$(5%#aAiIzc!f+rz2hnTNpT^`}9a zg8h0L{+Vfdw45*~eS4GCX$P4P8zTm_Sl#EX`Z@0M@&enm#!bU<_VvKHSl}F&QBFPV z7fapPuGVselobO7i97_J<^VPX9!BDY`@Gg>@WSgdj+~BiS8bp&-la!;ApmdZyJ|Iw zK3@l0n?qT^F@CSBn^$sXPk0Dq&f$`DlJxeJ6hNcz_-|*eZR(!de$4huQaiQt(EZB# zpKFoR}H#f?PnXV(C2)+5(AV)ZecA8Jxj)!~9*SRs0P=%)|6hcJd*5f!9bB&rx9UzFnx>)1{zofeTNyb!ml> z6!!=fCHQbqheBbkC3C^FHaxIRSb^d2`P0u4)Swv86MsW%Dzm)%SNi@ER<((lxXKlLj5?M*ZQTf_w^Q zw{v+darQ=u!EXBYJuc_7>Q<^l4gpP|{Vbg$3Df;A!si~NG2J;s`bXi*F^P*cJ|^%1 zIxbGPH2AbICzqq_$yOT;%Zg*hYoVmibpiKhjPAW-Xe#wO}mszT1_Bel2um0!ZtXa z3bAeCt9nXN=q)BpAflal!bj|5c~%k=;&x)e!gW3Wfkm2$k`JZLRWkA7nyGmF zGV^lCL2x|Mo+g0`SG?5+nC`%0BiBFCDW z6MXoUU|!0pDIv{qY!IxT$^5kW=+Hm@%`uIIJxX(J9684~u~1U6YDg5oNKp6XWQ?wB z(POY{B=F&cNBB{Uak|>0XZ=c6RFN}kM*80yrn0OI@UT|e(~bsc*K{pJhQK)$$F=o_ z3cii88j8Dg+S-pOW8~&cSQ8>0#qEdbLAy`w>w;!3XAaxDtfWPM~N>~%{ zQC(U!R0}L6hJs2fa)!NwBWLfq^j2&`P96PXS5{bED|m^%{G2_U)@iDHZaoBH$rZgb z@G;yXJLl@XA7<>a*;|Ks4PjCJdb^b+M=^}6kdJ|&m$GBJ>M>Z4912#SutXO~nkm9( z0_ZD+%@;$LHsYCn+FKheX=xGga34iTvGa!R z^dnDcx;;GzkaTDw)uWR1>gRHG-iwf=x5IqKn0?y*U=78hJM1GbjZcKc?A9Mt74RzA z?`4Guspg22P2vZi3l`NDAqYbu$<_T^vYeLbP8-o}_LLfC>T{UePPQ1sxGZ;|d5EX^ zt_8e?>8(y`#L>m4NZO`s0T)F}47!D{ee&YCwAMexaPhsRZ{Or;xRWvILL|@1f`Q8U zL4O*zWAPw*Wb1NZZQejjjev$>*G7tA1#pFjig=Na={`@@|{4a#nr-SKa3@jdL#)&R?;6VR)nV4_-@%>%j*F<5*1tGuKgX)OvklS^Y8z-dvLEi7yYC=s(LLgG^20BmHja}}-LHpoQ_{bZUa z2Uc~>5mpZ~Yz{xC8F*fXzU{$H5iS+?_3F3}3Ee2dRWY47>EP0KH-PvB<|ZCTMV&`X z!}?m}nd%sdKdO~+J~=v37~leLUpSR|WB2M#Djm0s5|)Utq4`EQF11po#M!J4?Y&jH z<>`h3v(5FnN=B-3AcYSD8=A8KY=+s-(ADs612Y;n>-fqoRpXn!<5)D8ma{;Vm9Wa4 zEVCLv`qzy=n7gX0NxqyOpxMSN$}*G(N)dtxeOeZxcPTE-r^&zMTwg9$<%G`hA<(oO z#m_6UN3P#IiWg!|(MH6tcP$FwQ0b9^@L-{A>`(sQ4k)a&qxkGzi|QX6H}d#wyiw(C z^N(}`ZkJSlY}|~EUESV-Ju<%16hQzfZ5s}S8Xsi;6vHBe^ihb2R>Toc9?T!s4};o7 zM77@Vzrs#{+ zdj<8&<%h`p8vveO7hV|@!yW$kb11MW=odCM=t@b6+0MLm$JLL(tuX*Hi=X2twJBgb z!m)}n%(2|So*d`%{n|v6UvEu6YyBYvoq1}y9~|I3EOj2%67TOW9EW<9;cD*V)@*2j zkV%=MG@yGCso5iLxlV%7!r!&jziLHEHVoG&z7*y5-h=N$#w!-C>ss?Q{#N13U5txUUu$= z$5@t*XI|pJaJJ+S5=fe1w0h=eU%e=xE!^R5{>mx$ssMQ2YJwqM?HtbqXn_-BUaT|s zJL>WIws5+MChaO!pbCX{HnlnsWXdiTC5xW~TQfZ3S(4kNPS4A|M^)fn=Sp)Ex>FzB z+9Wg1yz01U=E{C8n1+P3w0vH-G9#M=r3kCQJq}9dO~$5T6vb%yp9Cd0Y6rYUJ(Z#v zsegQhe$g*)!R)~Ezu0^0xVWA)UAz-CXbA2e5}+Y?;}E2g0Kq+hpiSdWumlpk(Le&h z-Mw)Q?%ue&OK<}D^-l8Lnc1CtclX|%&%O6I^I!EjZ&g>*e@NNo(5-N&UdcZCa1f^{(!kIlJ4k4k)RQZzjrAlz==rAn8US z7VT2BwY3utWFoK7svu~D#agU4o>XMl2@rZ{#6u1U;70T0$+!$?K;!MpgU->dua#Q$ zP`TqGVg0zqdL`Ro{7;U)vq>$nrE^8_!!d8%TpKjSw46-bWJ&DMH$pj1;m^j-i$g+Y zg$=%!yYL~r8Q`Bs<_ijOVRMhMT@~ja-#x=Tb^oz5SvH?s<#(1@?2=r*sHBRb#KVkm zU7?b433uEhh>G#AbskqVY}g;zh%sQ&% z*x?A)YZMs*bjT{uI#B1p793PG@~FG>!{0$EFwUveoTwcttl{mZkA9MZiq1X!!!)MQ zsU1{W@x&huJ%axUn@*2W@EHU5{71126VC@gS8hiq|AtG@4+R+2`{Pj)zdmLWVFs%_ z=>Z=(=9yYDS4T(u4~07n>KOVa2|D?y*+n4dq--}>5n zzA|;{eh71V53Bn!P6i0ObX!Aa+p;p0eu`5FGL-9@gdeGv9k;Zi9hXukJsOA63sI4V~bm^xJ^ym2ak~c3}bR5D5M~b82l5!y_~Bk9D@?-kAAyE zD%{bvp{b>7mS33cVP#}KO3nZYNrbO~jG*=U)hI2`NX(G)i|f7Mch}dVR8r5iV&pO# z1VZ&(43j76Q>py2Tne7`(JaXks@?zdDHgXNYVxvJ~EH9g*!PP7qm)$7S+ zz3ZMr9(x?-&!HxHRie(?w%)gET zWn+{W3(Ci}C6&Nc*?CJR+=^i~fuTYJpTa=CIJxmTVQ~X?B{`LSBC#%m=~G}~`9}bU z`~#Nz5{or#-#MHG)tP+YUcXg#bP z+P3>7ADT;x~>DFDHj!}NY-P9W>?mb0_8?1%rzp`$u}QQ4Gs@s!9#be}WV zyPIBGCW=qMQ)UO>F$%1-F!I)aE>jOxqefh`AORz(_O75`alPWp+hMJcus=1%9$i^) z&{PtqXZ&ikH|Yxo7NJ?@{%UY>#tj zeP3QAZf|KnSi%Hw3NnORzv=1nF+pe;{kS&hjZ@OJ;(_1Q`uMD46xC*Ow1i$-%v2g9 z^BCs1xx(!9sYg^a=Plw8~G`z!qhJ>e)@*0jt61cwg=`5QS@W z+Y#$Xk9Yn^h`e1%gQTHDdhS>C5Bv#62$j4Omri_t*F9TR#dMNs;8~?|av@mPL4X|7 z(~*e-0|kC19B?2mG_b4X_|UoQBpYr)kMY8nmH5GkWRY&SzoheiclL9B`TO1|L+*4(X<2~C*j$*!)U#IBb87P=Hvh5 z%e(uiHRcBfOs3lHvEbq~>Q?G(bBvwv&ExqWUp*G56$#V*ZSRyC4)?ygo!D&pnwAMY z;XhoP9lYzQ_I(A`P>5a!GLGeEDC^JJuh+u)Njw{8sbF zOYgrk(MM8qJ`bs-c8GVc3;E^LkKR@O1Te~Hwq({xA&!Mi!s zUyh0uS1mJ3x)^*aD>or>STC{1}G8=Gh^W*jBMCB^l!;XUr%vWR}l4>Ng(O7MOb zC6cG!gR(*Lt4xqz(>n7Eh1*CgkzLMAWAT^W3XZNAKXB+w@u8E7ibY}a7Xc_0hm%WE zn32OV4HIb){B3+rcBPiAp@<8^%=TG_$y)28AND)CgTXzM;8)rZY9P?7@?dJ`+j+SX zWM-Os&nwQM1}7|Ofyx4tC#dwGVQ{khy99_=^LhM>(x%R3sWPpm>8Lo>So(9X&T(ymPi(MP927Ij_ zzDXxD%3a3G0Y<0tKa+APe+4GNJhJe8gfqh?EaRokO0P}=KsZsM_y_3O+sm$q$msW} zGHKVPm3*0&p=_glTySsFMkMTB(9ZQdhaHHJ@*q&S|zr7$t(~ z;q$uWo7OkE#FYbn?uL{ut}SJ)YXM1)=;*77uqnxSnUbmlwzZ6h-JP|uD^Fc{pk+(# z7q<4DU{bPGY-W9Zb{B_{(J_9Hxi)&d7}X+6I)|l0rUSB@$kz<*t?tqJdhU6aXDRH; zk^4*&I1@evNX7%&N3}ItifGbA-ZQS(RSE*1>!e|_QL&t zK-LmO!AkGiC`%nBgsW-jFY>b*^*sAdN^VI%7N1C3n z)rYDeH)zDwwCMAN{b8uv0Oi&jm`iEzdBlQ&qm|Fv|wx{v;* zUGR+R8MOtM7z+eE?vmJXs=!S1&#V8i>#z};6t{0<3-@kHPihjVa4dcO5}~e+P!~(i zCsD%gr0NRuYjPihDq7bmYD$s|^VjQ%T(Ja`_fZ(D63G5e9gt)e=ykurZ&XgrK8U!% zI8!f@0OIXt3Im^dOVrdxs%e0gA^wAfVQn8G7=t3^x~8f-jQV71L-XXteSj@l+Di>4pdjD`xIr@*QPlR(hDYDLf<;iu9 zBRc$#_@85wDGKmjqJOU+tm?KobQDgPMRlS{#s) z_B9`gxH2z2rdH$m@iM!@A-}M2&zt&qA~sS>wq>r3=gXvTXhEUGDid20ds5ZZlfq-e z{JgLeA$eBQq>epH3>5tc)FofE@(F!QE1Q5>ps*6XrEO1UrO`u)`3Ov`GARX)$E)Q? zswT23z4fj&3s9%MK$?=mvOaT{M7(=QRWU^_1FmbQ+cVNY^ynqf58n=hZDQU}u27%O zWe2?Ia{k(lyz7pVRq`Q{{RQSEmxP%eg?x3TJ6wYR-Ra^z!FE3tngjZdkNdr2k`5tH z3K+b?KCHh}IA6NFQR9A@&ETNwFq*d?UQ&>iot14eHO0*C{NX2{ratU_d)cS~+uCqn zkc)Mvp56gYZ?>@Jp=Ff6K4ZU}K3{L2bxoZBLfwXz(nar>F=5ZW9FyfTzX`M2iwx)& zTa<}P{Z*c_wObHF#25>zAt1Es2G`5qjDkB?^bpJ8(Y=_DXZJYv6F5978qigOrY0aW zniTASu1TSTGj04v6xtZ-tv2J-Dxm*`18Y;do7oZr}RF}0Zrts%- zea56H?sAX(X>tzWCmwtzBPe<$3heU6r$Zbk{>nJMF zMiY{qXIkXBeqZku)*iu$z#(PLMIN;Tn*I)5es0c8jhGgX27C=5u*y5#7{Eyl5voeJ@$59J#5esNdIz(mm-&z9(!-IF4TB^pdg9#ifTSnLU}O zQ*-gJ=Ke9&tQ@@!NAhHaB2YuXy~inW^P!uAS=Us9cRq&b3BPVe>{$FPqg)@A9)&{` zQo(wt+4a{0WSA1a$VD>Q4K&G_K+iue*NuW!wLt(QyOpl@s`}8Jf;e3>=l7#rVIW2n z)%AVhE*h0Uw|JGdCwHGQ7gvsMqcXW3JIU{p-(0FK>}yRzowU(Y0ciQ*fIsG;c_Bd< zDQWM((w6v2Se{{yD6(b#w>sG zRrJq%@M}#UR&J&K?_b!#I#^mnbp6=>y~%THJAx)V-l|hhng8l@kXWcr9f8os0?$>HQ6M8+# zgDe;0qT@Vv6BJaC`oEJVTJzdmC57-VTio#=^y9hd)v@@F$;DH4D`!YPe?5_0ticP7Yf3&BYa2XoQIY6M+6Pd1 znsxWQIDSRKm8i6SPep^VcF9#N+*dsrT6Md`Kr>HT&DZKE=Fw%N!qDQ4O`yGKF8Lh# zeyi@RbHLFoaa0)?*UV5;W8BUwvr<^y66HixLU}c5mqp2_PE|G31<5ppi!GaJgCV-XO+Z59sc>2B={?k&_P`f&DeTeFEW^eL@s z3oFgl3UoFfWx6)C=Ae~)P#NqWY_d}sDi@z&A-9rUbtK4VNQ5^z0}r>ybqcpvK9U1? z7ntP2gG){?)cLm{neRG~sX=pNiJK!UT^}t4OjMX-R?afyluX~4cc@5G3tYB6Ldm~4 z4yg9%K?#NFJYH_xI$b&k=Y5bQH0a)b5DA3}bNZ|{labB81NB~Sdu5nbSyy(?yIw7e z&;XNjdd58j2i-RHJC{jI0TMMe~|5NGNR@fPbDe#j=|XF7^Eh0C{rw ze9yYm)yy$f?$c8;-OEu;J0-B}D8@_+K0PCy9HNBw&5Y_(g;9jHGS|B9AsrgH-z86J zR|daqyGH(a`t6QuyhE(bIIr~#C4dhe-sDnq1d2l`cYCutn1n#6Yj2kYf~`^rJ1S@B zqvf!rq^i_wc6oHFS=>H^Glc5OiX?2B(F|w;zk19t^tds(2*zU-X-K*GA zN?)>Edo(ULvpq8j&z3c*M5&?->K+Ot*M%|c#bi%-N2iV8qE}9{QR==4*;Ntk7?owf zV`09|sY11S2f*N1u+J^tBV})XFb&~dSq7(7D;!X2o0w6Ve*TO>QswB9FbA(8JF*+1 zn0w-UpMs-ze=NlFohf@c{|I%1WGxKZ=6{~BKp%#L%@Z;3fTzTjc6l$JC%M+XL>3fQ z(ghN0ysY_h9@eSo)J$f7l!ABG2oxxL?C&L6IyrMkbP4`Amt8z#?;V#tEKu25Q2~1; za_Jto7XD@4iGYCUKMO@P;H+R73Pv8Kw6$(B-)^|QE>q69Za&5F3Gt3gt9Jh$=8?J^ z_}2eAZ=7g; zk*+OQQjYBqlE{hqQ;HQ1+pLi6gzV2y6)J8plVIc{n#tp1TgHgD^V^kDV8~5ugMXP9 zAbyQW_JH5du*N;mzcnm_7YvS>xvq zzMzJrm6$APME%>nSsrZ%?!y+A2yMy$f!Gu+4cB}uMVRKd1l(AeS2*h>t_9sILbaV< zm%WXux&PV4MYB_%&p0zY#9IEtn;QL8TIPQRblSRSc(SOva8#^W`A6fuv2Qx@`7{Hc z=BJs)8gJf%;48pE_hJP12(S67L#3rzhTK|FesOrQE7*ZA_K{+FSoa3f_1Pu|8lusb z_tZNV3`bT{!2Aw$yvg|PrG8m!6cB=?OSbj;+p7!fRabf7DsxL>SjtLef7g6K%nMG( zQMHMYG5vmR?E2i?u(Ty1`bZ`RjIbJajE5R3IRX?`59snTvMv>b)2i#_W*L{~_~32& zpOY5%DG_Q{>FfnnIzZ=dG#ECyCRx_uKu%Z@-72z(!)EJw;pYx0Mk_7q530cj@L8+f zdVR?H?xw!}P-424f;0c2u6wl#(B-M0r4={wqs_NGc&{Z%D-y}; zsJ59wny>?;%grutv*G&`Io2vgHFADn(#pwXoZ-6M%v$C+cOaxan4WGc8YCz89_+J=Iyp;oL_XCW5Z3{>?sT z^*loUzzNWThyowU8NpxULjF@xr~jw)ZLB#lkAO-JSlAIMZ%zHsyXQ48^_$1Ge*!cX z?Ik7(*O#_bHk9-RU*UbYGZUio*Q)sJpC%s92NiS|BE0&v<%j$0p6PE<^>obN_hNpF zDhJX1gA7A#v+x=xImj3y-o>m)ILlrkscTw{X#+!@&B}|n5fAUEM2r^mw3Bnx@qc;vP1|sgqORCRr`|9~d z_04n%mb&Jk4MH77$n9w-2=-!mN9wf{g1#&-Ikm7R|8fvy!NOo^g_f2y%xbK7f8{ek z?ykSGwTZU;{@VmHLv+?DM&!C8D3vv>7IM)^UW^1n;hC4M_GIF38J7Q!ws&aqx$!9U zEWcXj)J`_XFJv`S8|4LCc96o1<*d<7Kh>UTdy}-lJ(J7DjP=S|H{xk)A8dn8;Vp9*sy$eZw-YZYl z*=)X*IgXb4+2P>={qi8XHu#1^EPV&!94KRD?R+wo;**s)QJ&hTF#G@kl^A!$b8+sE7RE(J^ZhE(nQ)FBpg2Z#-O>+;Gqs&Kpls3j2ZyH4CMPs)|{+>9>u<{jeCViK?! z3t<7^$}XVrI}8JKKLd$QNfh5lTm&)7BOF6|qOLXEY=yk8`GQ-o4RNJ795lX6jo!1~ zGwSDTdp{v~bl6RAFel8sz*f(^HJ>3>bSm(bd2o?WKOa{o)C$o}w#gfpXk|QKEc^yZ z(Y>dKHnp*s23Lw+^lF+IlX(!39A56eh=beRS2KTLN z_4T$^6Z~8&poBpju;l?)J%^>%#m*C}&2G^h{0E||f6X@)`u#^7nuf&UCLq+* z3m4W2Rpv^%O7bFaumUUZ6>cc|;X`H9*sn)!4)9d0>Crx?LldM=iVC(?9Ny5NOG89P^8gA9xu%>+z zaQ)-)S51%VThqUHq-(8eOxr!udL}xH9(}=&10{(by*KD(#O@taL1`Mj_&CZEZWtY~ zZH^Xli{WT(gZg(NR)!$ZO!Q0AXY15nKxi{)7;%Y&~I zL`h8*Z&%A@KP+%))!kB;YR(iB4}35{9YH*wlA30m>Ng%B1KEQRWFqcUp48`7RogzF z^sNV~C0}rqD)C{b*LJ9~xtcInv=1DCs+sO9+k1h@amn_CGZ1XC#nsC&`dTD+g(#4n z6sxljn=Uq?I8^(kajFGb>v1#yg+8?rW|Kf|NQLN|Kev+8*-#(WRH0n@AdCbwh`Y*> zJ3MFPKL`ri`g5rHf7V*|ju-P%x&Ct7SI0p*9kbc~6It0{F0(9eBs-lU{0~?}^w&D^ zJ=%%Ch}%5@E^eRx1mxS*JRK)FJiYdv5SV+Y12J>4sp`GX$4rYhX18uH0RjY7u5%h4E+u|hBUOUgMxi|Dn`i^iAZsmzSb?^!q=`kCf(081_NZFEb!7NL#_yO}nX zSh7Pc$m)5egj2nCGcX(M%(QyazyMwSq!%KBT_9G=K*Z(e^+vpgT7IMh#e5Vz!x zGN(iOeTLIln&R`6dx)a~@i4r?vL3xl1|#d!z3DMTQUUfl)WvlFo-z5t{1rL*Lb>BK zC10=5PAJSen^g4lSlFBrJ8^VWPYNY`lM4DsY$;WUPlY~Nq3(L7cJtY;(&K?*+z_P< zJwCD#n5{_I;p)qcZ#~+tINTC?H{^`7OLDS4mKvB^S~~cwXG2HO*XnQu+mHZey$`qO*fb9yh z;zaF@%2BG0u{B&Wb|NgZfLq8)Lbt*x8Pfqn+rTvOz@A(q&v@6l&KT@!#_qb!_GIg| z#=uAW_;&(f;N$;giGl)j<5rk)bxHr2MGq!ZPW z+YVoSCpu==Vxv?7qC{@TlCJ1d7D1nzljaR&49_qu=V~y~*D!90N@};8Q>d?+x7w(y zn}2Ox2?tsjm$#y~DIG<%?=54~;?gBO_Yl`-Z9d+JtBQFQ4^`Z$& z+IBx>bf=Gzyj+wOwt7Re{3rlh+2TBVSNDp<2ntTV(Z4iB{~RE|#?7jJTTk62{DEW> zG1f)5Y#hG78cMl<5lGqmV}a+11S5vKWYN~ar)oJ)?hZ(%b5$6|qb@9bVW{q@)|FwD$=NwmdxrgrBtTTT!TK+YQ>(dTa@}c7O*pG1ad_EhYQ4Bp= zMKnQ*w8j=abUuf)WJ4LpdC7>T;E6d`Q&<0y@Ahv8@c2JeeQ>J}VqMQzcw}C+RbjQihG!wO`VIpPfh6m4t zAW6LCxG{+rf~i!2&yaLQbLb+J)lVucH<}fx5ee_c)SnFy(pJV5sFrXH>Jv;bJm*R@ zb@*uRJQ%thBQc@?##xe}sM@cpofzyRA4kk5ZnlN7P4imCk82=~^>zBZa9|A&$@*w> zB~hclEjQpSw;HO?$nZfovq}p6$eEo-)dgO5UetSrpMS>?=-?D=N;KH` z_(?0+y=F}IDv5`pm9Xk<$Dosb5qY1ygJ_jpODop-h$LF^JTWeRSvZ}&0TSBJlxVvk zFI@ek3|jdoLQ{z5j5{!v7;%%8?_M0$6T)g)eylS|^$b3BbA17vkm6%zpLjN*s6x2u zFZ`5h*q}d*iWXh<@m-%Dgf%;>s?Sh)=50=-S#Svg$8}(u{HP$|ckoc*_f}H){aI3| zvat5$2trMDLWBQl0o6v!D88*k5BUm}4-KCy{Fb>2J8NMPwM+rhPkisBl=dj;j@;z^ z5r`ma6H}3oSmV)ziXv5f0$_~M-qX-XZn53{Q=ep9ikuY$xh;~lG=rZqM$5LlSm|`R z9vGq3we~OQVG8#-Vx_8T&u$IOAbMD{a`J>(<%*(5;qQ;XbVHe#c0QBM$<5EitZD*> zRV_8D^o!VI^qx{aGpma8c*1IciJzb|Lm5atjmKkwzzQ|YA=31N>};>PFq$M|=}RAj znsqZpJ`1jB<1X!N(#2xi#i$T*21j=zge-Ps@o$p+_VAZRef^>=@zVm{Qd-07gbBB{ z4s20npiZulU#R%b(Xs|8)>FeADrp}reub&Ne-E224JEWw{pJ6aRD9JXH~>vhRHnMO zfXCA)sdX-vRBV#4ToqxJt3QsK@smhGr z)u!~5jumXMy}nN3+>QUy>Mc|#1i9@i)QPcx?p{tRla`-ToDonS zr`3nrj}Kc7@+;(YeyL$K+Qd&*;J>|LD*z&!TT)3RIle+vObMmSR|1b4+pDm;I)|Q3 zKpPL(C}=D`9P4bEC9a1%@Q@C^c~g?I@OWl?dWDxoi!02r^UdSB7b-^!lh}Jb-&cIc zyABLT?3?;i#8_@$_^h9;e|Py0BV%^Yr6AMyKwd~LzM}&wt7S0zvp!g%YEL-O+|N(? zrM-}Ny5z`*C1+o0{|rnP84Q$+YbI(kWeo7CoX|5QuH_$6fH`UpmNjH=NyA4?X)q;h z?6)a6b!>*Tc{TTt6=Cc3gxtR@FGB&W8h_uo8k!DW2ZsRoaYfUBns|PEF&;Stl@^n2 z0z2=if#Z&)yci*w#)}ZVU(YHLFJddw*%*n;`Sma#v~1l4W5_;K{%;q+h>l`@0W=;Q z=s4)|htuI(o!8e0oR$3q2y2v;MOABtLG@QGTjX`78QER!z2sPB(5+_c)yPE|PDXtL zu>KE#sK$xsJDQ6ku4euKd6Bb+LvwH}A>B}UK{0N70>a#1%(wqafv52#sQmG7+S@1F zzqlMipU?Olc&i?=#%kQoU1uz4vfgKS@+TvT!^U^Vxw+WlJKE{aRmkLBj^g!(@3Ys+ z1$YU*u52%wEMNH=r5w${7dmM9_Fh+LBF!Z!t&Z&1yqw~tDwno;hi@Vh&N-)%93OXS z1?%fS0X$uI$T0YN=oXSd(&Db>CtyZ<#^(EH$!1^0pMdk3^~xfBr6$KMfx~UzyIF&( z*t1t;$TYK%|Cs~lf0Vz9Ega}Q+YAx^$S_)u;x$}w+xQa@NHK3qePMf>c}Engu!sBo zdCB?39TjxlJ>@DO@Y(`7v;EhoS0*Gy7(7{k#9NCsx zGz&Nv6PkhGAV^Gk&^qW=@Z!K_;zfz6YMne4Md$rZ&@lkiyEa)z`Qf~PPqh>gvX#f@ zgSS-PqtqmIw^6Uhvg-4_=Aj6-`bUi-y5WGgkSD!M}*etD-!2tgRG3Ry_pEq z`X~+dZ5LG|IP8V1!^QCc-_(@VcFP*X_!}(n0AU5VO!Z?r)?@Qfa-JoBZQU|}flDF< zS2PAW4e=1AWkVI)<;bje?=0c|NT)8BlOa&febVWH@X3I2A*e@-M~}mC3wBjm$=5$C z^I}AL)_LUqdGF|};R{gh6oyU&{K-5=dr-*Vot_PCxBNwQ5$Zqag}ewn5MAYE2-c@xtOdO?zadqassyG=zgY`Z z$9_SoNIq8ne&^@?N<7s-mHq`}G?+nZ)Z4xWLmSxJ6W@tTZk0cu_1_saC23Lf-tE2m z3?CX1ZbKHZd#MaKPWl>GF_kP^FU$T#{4s0IP@y><$^p54-^^rb**+dJ1x7@gL+=_| z^=@*!gSg2vIYL7oZXA@9CEVaaC2dPC9FBh6z!|mbn1Z`fdaMiH%IkzC8MGtSk{niV zar}ssw73r{J2hYKtX7g9*Uf|V)uq(c@kaF?49M`ngQmORc*)F$-;HXAQNgZO0ijv_ zfu^(1$ed@Szkz1UvO#w&Z+&74Q{+ZD{Nn8<#ZnI1#J;ZFB57F+`c9KfuVtg0iF&S; z%e@)p>aa}DhH`F7-`a(quaBuZagMsgY*WY#tFvqi^_;>Oww}iPOaIpGCeGQgnEJ{H#IMGU0JiT4(^})41 z_P(BgbrF;`U@*O@1Vu~aklfB{WVQ4AiXow__31eqGanMK%TIDX#E5nv+}9jz;Ot`3 z<=*d7*=$ZAax7#GM67HPVycJ`aqUzeU{-&0=)<)ym26xhZi8hfi}=8NDevXbaqm( zajR#qcJKe>T&D2GGylw_6+m?y6+Y#z%0WJ^)r>hiAi_r__Su97&JbfguS?yqoC9KU zm=lqCdDEB;T8_F9dR*?avMMYQGaFq2O6U20o$iW!^c$-V`6z393RUo8@!7KU&4FY9vkj+hIRL4 z5q@EuA$>3-VeU|rcx>USaq8j>FMY7JW1JUsfFHcPFW%0O{kL<7(Wq_`Cf%iG_d$30 zGSpxvntI)0d_wA*$Id`4S zx(MH`%pLI4$+1o=$3P94-k$)KTbNHp;ZMMb{CLWrMWk1Fo1gpyaO8%@-lg17+*%;f z0O>J#;(s9>NRV{}zH*T^D0KDRvr@TEvbYOT&T6(Sj+(AaN6f}X*9p}*+AAubrx4KG zhnW-vIOz#AAp(=4igA>u;FB>2VDuzs~-Ufc#g-d@7q!<}(91u4~ zdCT$ki}6i%k|-(Lt@t_L^xGH5dAJh>z->p(^RKtiA73GwErORr{*s9-Wn+ zN}%8wxw$$`Y9&!Kc1?{6ZcAoMCnn==dodzA+!s8z6%bVd%Kwm3;?GXAdD4Gj5T<>i7^bpGYiW_tXk3 z>(H|%0sTa)zz~w3oT0#)mp8{YAK}05>5#wrqH|YPc}c!cF))+{E!ZVaeox>_dMKns zrl933BrYlYrHlVhK)aLwVkh@lv+Es``8{eI|VBO-OuYxXV-TY_(;^(DKe_R(l4R7`jte5@Cl5yWTcBxz?v}6~d-*CZTY& z7CHW}KiUM3-8F%Y3?s!=A$7hVx7km_b26MOqpjny!|ZI8$N5sL_3bGJAgHhfVkw&w z?%{c3QBC;dW3lXTO4IRu)92jS`q;rv@kn$9`s%Fh>hsxHYG+MNm&y_N@~LChQ|x!G zkNF!+d`W1;!_~G8iR&UY`X_4xbkf@ZEZlMkJf4ovI9GA?8N4nIUu!F+XAK@{^Bq-{ z2d@c-TifrM-vzAPSiK6}H=mqEoD{=sQK_;|f_2Ig>fQ#2hs`-W92K&L~rO|Jk-U&5P z8<n~-2^6Avb817u8$^4P!OMfD6tr{?`J z%B7@tC z#q>C`So;4M=N}o36C;rL{sP|ZrW@%;XC20eE!_#5HC$>iB1}nZR}+@O1P?d(D3~)T-+mrb4{CZ?l%G@JIuTD4-8+c^yQ90E^R9kW;~Fv_ zFGFWm_tYd%F00s#aNW}Sh4N{Wh)LWbIU92oVn zR6QWBUbuy6)7@6{tzr6SWU&;FqEpV~d3EU-n^>+K;}7>8hnXqgul7B2tP^7XYMc)# z3NLOh8;`Skf~#a={4t6jT&)vVTPxIs0>bb)#3~&XrLGxrYm}FKzJRa#hBwlx5r%H) z=;9C+F2+-9Czn3R1*C}XaZDTSlNnla-$}cCOu_2M6eg6cRYOSMvtKIUS}PpKBXg?! zUCJ}V%v)43J)=KZJZnPP zo^U4S9E0^76m18P{^R#*^SOJr0mnoRD%Boge1&+^2NRsr=XDDr9&s%p>?Y6uc18x4 zQ22%@(uMU5Sp`T;;%xRuE9&p+9LO3#zvyOB|Jz)Y4g|!`K0c7slW|DLiEgHI1mAbw z+AfxRYxqXknB~_t-v_U5Ix~)`s;%}>N@s7#R3XB%nF3D>p7hVLzAqCBkF#EqdL~-a z+G&_l3Iu~Us+2vj2<+?Y>6koJk5Q&Phw?h&3nOG7Y|)?#(}o(FKku-og!{1 zFlp`=AqxxW$sEOO!A8IF0dX3He8^lG;)j5U$%)QAQg^s}uy8E=glBIvsEQgiLKz-3 zG16wJDy2L=zoN?X!;^sS~hu z{&;9%b$CJYBl2FWh+IF!jEBo$uE!f63I3g47XUJ3a|^$jGIlq2gFaePnY+I#<7 zvXJ%ELp+T3L>-*f1V4U%-eq)L*>GQM{W#=?4awap{v)yEHaq3`{uMrWYo+FO(J7(e zen@uylUF(t_R!>eonFFYq_1Zout>kp*mAr`&_vZcT&)G+zF6@Uhv#dMY%zhNT6naT-L$v#)Oz_E2JcB5M7c@N_ zhlj}XEpw~uQ{K$erEygU>h2_S5a{QBRZ@Fpxf!`!^cg9N_m z5F_4h<+6SRLZ4WLMPz$iF)vjb3A>62U%Yb+782~5&PbniR+QkR07Jt!sm+S#<@t2d zv!k0*yS}k73iAUVu(&VSi|m^2c~9jxsq{L-$4#?E0yjVz;*_e~f@rsZZ#WSqx^y^$W0ea4I`>h8Gmq29bGJKEi#VS) z#HJEsvMz7GtqP&u3E<{)mjLT4H2dU;59;H4rtC9g&94NOR)KCG+(T}#e*&-;eb-n*X?)g9K7=IbBV}>ci_y~v`e`_nKpZ>tFp$RzqPKoCy zS>2PgJ;d_mRifz-de_GGU`heOo48Y((Bl2|UrfCM-M-f0l>P*GVgvPqAKgeoxgrZr zjOV`GRtU!yP5sy`JBq$oSpwdyjvM{-X@@F9)v2dL%NUvd-_qF?St+e(AzU zce@tLLxFh4m4S-_pga2m3io#*7IQxj6u@x%K(M4?Zd|V=;Bgjo_fak+=({)zt;pG9 zi?!9w2WHEMQ79q=KQ>8@08+$=%T#c9zTW5;wr5c`;FJ-*9=_3%yZ7+gNJ8cKHO%Tud z>|RVXDm$H@nIOogoH27jibJ~sC(hmaF}@y`?4;b6LE+9DvahYAZd)N^`x%@HpHMTf zyZ=c8Gs5a}19-1^KX^h6|AD5f)YzyVGNav1j#ej31(U1WJPa9rCLCoEr^W~=sx^>ifPwG!|M3h?nbLmcUt9xJ#zb^ z<+brz3FCWjs;mD56r2cb_M8`62P-=iBr46Cjsc%uc0fmVXzsQ8pjY#UzP2f;YGu)< z$Uufbd}r#A-Lb_Hr!nW2;_-c(tqn_@*}g|^8IuZ_oTRt;f7q|g+*kPxA z6VixlXAWR_#sTK{VcdEAr`a4-AP$nx0bFZ!~5S{J?s%eTMmE zBKVG)QeK#K$Tz!j%m9cNEmU_t2ejq$@Gdug=OS-mI|@Lnv0T-qX4{*#ZyYT<8rD`d zKpj@z#I9J&;tbyR*>M~OFuz;XS$5RWN`A$to+9w3_FRub)4QTgl-Z?Rz;N4&HHmNi zWE5T$mAN9oi;i=+p!}>zm;;<%IFsa*blrZu6zS&Qr}~ufwHgD%Jo>Ai=p#MQ zQbm;@gg5D0qN^@L=aFF)0Y!%WNkwxz@p^N)VYI(;fpc-73-js|Sbi~bIf0AVlBpuXopP|_|!cTb{eReCh zspWV_eUE_Twdvn>zM%dqFErY}g0(+8{{@I!-b6h^Nm_>LH-R*g*6Y_fC;8jZ)_W(d z(`V!2VkVubI#wPhxb~svn}MlNIB+mKTOewkt|z_JW@SNFcwRVzXm3Uy9z3$#^b&!> z=tkBH&udoiP?we+^Vi^i@mXEIk~uBYsv22CwB==$8F6ln>Q}pO46X@=O4-9Gu-CLO zN#M>bk+oM$W08+sKj#%AY)=1c^SXn_u&Ju<4`y)NM{F~v%@zk7*dQ)OsBVjK?f1y^ zkPGWi3c8w6RJM`PU4RV%*Z`Aji~H;+aw470g`y%@G-utJ>{Byu41bx_1h=X<(7e@G`b9OqbxNlgJ+`w})KB4QB=XVlqjecz~l zG*E9sl@6hf*PDC%yp?yl=tnjFHKcV=HFIf>Eyf1J3B$GtU5PAJBh+@6h;~< zq>b;OsxPnd9GaB`%f`i-@oVF>3&X4d!t?0>fOR3a5M%UXPK4^r8yf32VskO;+!UY7^I`?4OJA}#X7H-wS*rp>Us|~ZJejXi? zP@~RaF&4f7#Fc0sAo22*aWDCZObDN5D3}e>ujV;&OZFeQ7 z@y0UIhpQXg0e+RE18(EPem$jk^=03fsgLm#4w#5sxog%`7>0(a6-5=P>i(WA;SvAv z>3Pn)=+|1CV;OGAZR6i_ea-cvhQ{}|9u;DSO5bj!nEsxtkI6IV2`diJ`zbaVYIw;Y z==txtwi7IGzZ@$Qt$wfQ&F{JEB^j6Al+KU7`)ff3zvpJkYLuw_G}`}f~dEw1Rr_4Xz6i21o6s2Y4&b%b9bu}f*ukt$CcwWBzp=8UB!Wq{0+T^Og zHZyO|FL&k^bQmP=Ppx1^)~eS-(@D(ub1L+&glX zjcFgYq_O3Zw6G9OeW5;VNm21qh6KiY!viqv+NGj`rG**kYd_1Kd6|5ZRu$DKqG84!Wo(C22Ah;I)yLA3$%68CcEh3X zhnNIYRYc|97L_IE1(jHHaU1fYKA}3%vfrDhy-#utSSNwlS`X{>-jlwENO(CK01?Ej z*1P^l^5WnnXQxuj3D<0(C8aj3Mn!(NH%Ne@^>O7|?=Xxz_=hwcyJiW{VW z!XNq4IR&H}@E6xpm-Yv4^@Rn*lAVA*T+aG>zc{#Dc36B|awaiD6KwDmJOdLEjIQkEUEbXzE8wio;jn~E)A1fr zr-YkbqIr_>Ik&F(9;bLNr_1N8xiVjN^gJPvE+YpG{*b4LuOG`vR}0-ctQOhxq!={SY$k1xI+Q$H05<`nlU zsI@3?)&tvKNd)+$H3sf5w2h5fw&D~;p$-o5Lq6hu5rcxt$V2d+9YReyx~A*~T7fTQ zv{_1yzOg5c@|K2h$sS?g8FF!HTjBK-#hSCvhKfDC*d2oHyttv60(a|EM=^4F!q@q! zx6-~)J|*Cu!VQ8NZ|!q^F0rYMWmGT1I4S!I^fKNO-_O>TW--8;CWRf-l$9IJ(~aVK zug>Tjqr;olfEZ#)$FLY_C{4Y;=>z6X_^nyb?R z3VrF5`Eo~eHjq7_h)D`H#=95YJ8LW~Y{;G)-#vbBc&?IJ2v&Q^!wUG2o+ zFH;+rbPjDN&vZD3nnSnox55cv1hd@|wj!q{Yc(y!rzH5eKQSPN3E0*Y7rLWHhDY%Q zI2VIt&xZpseS!!d3P9D;S%}(|+V{BOza^}Go9l{3|E`$p6f(1dGXEoA>hj&XFUI%( z1UTM}y_{clWeE6g{@{nsWX@{-Lk-Q$OVt7Wq1wUijg}+72h?w7qSjTlcbtAXGUzoFU_s;>)VV$z-`Hp*n4)&N|SZ8U2;_CHgALa_i zE7OH}qp&r;H!k)Y-tlrZ@lMXUL!YY-y~Db=efoiM=wNNU8oH*&BM1lFY=CSnSHxJq zx*BC9MUiZGA`2eh{FxW4-4F^lbSkqmQx)@!leZXxcG&8E6Q6&Vl)c~HZL+0$lFY}g z>f@wQu%vi?Gb7hef-9pduc!%br8o@+SH90Us18lz-UjysE-IBymIW z)?YtN!4f>Sa1W=(;LhIe&(;QRn1@u-oD^k|#LXTAHw_Qjv_la_$+EM$cDuZ3@eO31yvgMsy4 zDi1EO`*xST)DzXrW8jE64!|_d3A=UC`{lOaN>+UW8lB-JA1W~$0(=^m-h9AY>@)b%1Q^w{zA8uY((4lYxr~R;K=#I5Gz`c5r;J> z0*yZk--TURr!r5f`rZ**`^Wby`@raDg~KEYm!j82jYsAdCK$AiTYPm@8oH_~C%~;+ zUi=9+U-N^u6MsxI&n2_2Um(T`#HtrNxu$hs-&PQi1&<_scn^J`5A5me`Iq=BwAbI4 z8a~Y$vUWxw6NQRmBI?F$U9jav$t4`*ia2bjZ?QR>;$2U4wK;gt{5;eKQ3w2ROo(=*^{7#p798I9mR-w#P&$ z3}4;33I0MSTW1UKzF`%%B%iaH_WI5M1g|&qupdre=Z|Wfb04rZhC!+v+W2sX8-P!x zaHU(1%h=mQW{nk)7RDx8WGJoSA}yIRAwAk2GcD^n$bOD`Jlo8 ztBa|gn^G)TMOm(UfHE*g&=ylnlk8~Bnh|%IOF@Ze#icHEx>Ti=@~F6ImDFn(f&_XSGHq5 z6^n0iC|XMsRG6{n#6g$6!9^X>t$QSr$-0~2S@Je-3`BViatvq1NQj=8%?ZEU%cyC= z`PyMCfa}RK;oI3hPEQtLpX%OKqYN;23zG`o`YWHQu7gi42x`-7gE%Q?iJ*`+~L_l9(v;mP}f9UtlHa6MM>$WjbO60aK7!mJv;Ocz(2O` z6#T*ND!~>(dg}ZdqgZ~ON?h%QK1XG&n3$8O^`x53p^a+Bk_W9nceH$t}4~D*%!VUDxalr^z!1YtO}UMwz~3)AkD|F&BHaI>+PS_AF1PE z%5I}|q&oV=iqpHnT7=IR>vD+$Cfr5h!lTO3g!c3PEeziFx*=A@>YCK+YlB>LK!Mv6 zh^k8u8I~Lw_CF@3+Wg{tXXWls+zV>yGBhy`49;QD-*TxaPRJ7;?c;MTWt2oW30xwm znOstyULYzZC<_MI@irLxB?PyK%Sag+(wv_X;Hu=X3>kqT59$R+c zbN2Cek9<^3E8qwZ1V^HW^6?i1AXZ!# z?~A~s%W+yhXYT2kv!J6>;l@Q*km0A=`bRd>`LJUi8|0 zt$zT+U@sO|_Z3}kXE)ethZ5qt^7^T)ew~1mezy088vyS2F21iACg%!I_5T>X8VzgPHTVMAjL zUIT>VnYR{X$e2MT3k3FpYIFy_(o0FX+sGg$ok(0`NzUBM=6I}98LnVh)VEZ`;}&0f z(9QC)((eVVxM0dk=$`-tFrew@+e}2aR*Lti2)Q91kxudo5FL!0fo&z)!ycKEVg~5b z`Z->tyTY79l_P{mI0??Vdtz%wq{R3c4?He?eSoRSUV>$kRI=@5VWAulB`R11v*AQO z0gDKgOdxbFQlCXO))K$F7mg_Hz}Js_8x~}q6hW7<6(L7Mrli16sJ3JU$0cXDTCqYoDJ>*L(U<=q~R7rp4x~qf# z)px2FteKF2cKyg{^^n(ds7co=LEL)oN5A=8OL&ZvfY2asphe|l(Tw)h>Ce!e?dvkb zlU5J7VsgK5zq*mC9dAELyaxnQ%nj=R($Z0nl)Q8r2IG{D)jf7YkwvZc2#eEM$Z?t;| z^|mQReI#CT-foHRZZq~Fj+11(2=(BGa$!u`?>>*r2BOd2YE3bfU@g(k8n^n*>3uN3A%Z7|Q5+BU$p1N}iy^fg}s|MIzj zx;O6a?o)Bg45&=ZPwm_7PRll0({kMTvO0=Mkt4Ix7K5C9iXsa&#|4s*imw&{k>X62 z_R!+W%2s{ERH!O6A*W_S8#G6gqzu@OMQ1-xV(|)i2Bw0$zA!`5mtbSojD6l|!-8Kz zyaH%EpHaj+DPc*oQs`;?V6e=V4=3R>q6j|qO8{N2yxMDHc9+oiMt#;j%x zlBm_q1u0GX6Hu?HIkzJ+IPaU=Fkr{P^_}dDdk9V|SuT~xe^lP=wP!z;miBJX77gpt z7x&S&DyTbhhkboH-u@ZJ)yHs+ath(0&Nzdq=&76R12Dk9SqDn6y+A`sN4^)-$pxXL z{QNU7CuZZn6)iEdU$dxA3Ffe$?jEN|E1w1IIUDZ(C{57P2RX;@1#?MF$$Vm7rGoxM zY5Mo5ZzQih%_C~6jMZR@X8l8rcyH9X(K0w?pM0vfb=U`eNpEb8nglxxqo{LV>F$(x zx+bWHmcZ9tfgWee&!jNA`p2cOTFq*q4*g)sca%*zTkP0rV$rHq-Yf8VLIUCP2egU# zIK8f_sB2)1HiEOCLIu69pKkW`jjKs#_iGbo1+ZVb+k`99N9FVaH-*CK4MsQC z29B-6V(j|2LB{lC$C}+P&bh?fB)qbyK z*5N^a%q@fHB*_NGG0F&R`O*Ek}|!qw5y+a7N;t}x zRKT3h;wm8_y?E){E%EU|2e_tWa_RW(_6+P z!b9GZz}d|3s4;`n`}^!u?MDv;<{kr(uO9AM$|Ob7toAJsx(sTxugb0kThB#gaxrXB zkfQGZZ_^Z4l*9ntvivW|N{tdZZFgT!biIdPDPYUrbXtBf!A6)e1WCvWJ~wa{XPlfs zl3lY=KWsJOrmAVxqdM!=D9Xk`1;7DCw8!UDr*f>#z^JqX&5p7gS$QYyJ42EZbv;$ zI44zso6j8K(|rscJ>`9QW78zk&EkWkI&)d0iH~vj_3s3$K7hEn*l6l^> z4tc_7Xo1i8ajTogCD}0O=c|4lKm+Q*o4XMenfYQH-2mkl-vK(;f+E@E2=8&wzo_CCn zD&USlTMxTSqiCJ=M1xAestu0g?o+#O?0L|BGi|Q*wJ&7uAxGpK6XqKb9jcYo-PR+biT$Ya$6x2(p;zPy@j z4cDlR>1o>d6A-UtaV+y={kZsd=&4~EwDHB89w^@IZA-562=hW-Tnj${0LJ(X{n z#r~&V7pV!fX)%fZ&NjG3Tj-*u&!IEv+t9i;ktSXdqNXtL&p55N-+v)b3&S`T_#+c` zEXpQ4;DcL!=~`{98Ok(Sy|WeH$PS2c6yhL^uEb@c!I+cg$8x_EeK^TC?2e5<0|C>f zZe^l_C`=twwy$*O7na7IdPL+{I%`R3tpyj^rEh*kwmta6S6n!zC_1A_q^TBKw$Q@> zw|*?9Y;|F25@EEIv>$s0oF)@I;} zBGfnFLZt5da($U!tI$}Tax771Hm6B@aFF0;73b{NB&-AO_E5ILdL~W!@E#~Iwu5rt z@vooj&phdO9u1l`D4KJsAMY@o+$7_YvGh6PZd_`!5!Wi&}G0F*(zN^ktk>W2| z@Z>kkdP?@RXNJS`Cca98y)3peqI$TivyThlHS;E-TYODQqDd}T)rzEk2+;~!ZgoN$ISeHgh~I=-148sN@1+hLsV4vLc3d^7FA+6 zY(V_CsVbj#JQ=12OZnF$=A&!NZNv#%^hJ7?tzO1SW!@jdX)`1Dez>8Sqw1#S5RCPj z?Td^P8NqJUTJ}gYS(F-kRMb08(4Yzx=Og>Al5N8J8j?L z8QIi8Tt+iSB+yBWk$%DfnA;=KlPGvGB+&ZQhL9O!^yNI>vs|L~zW zA4(BxKJQjbYmagsk;jo>+Cr&6A}Nh2#9^|!NQJgZ&hMA|CI;;8lWd%ErReB1e7`7& z`MGryYSr8&iAGa-z5z;b=z_>jrDl9lz!dLU1I)tEJ+ zosSFdS_S1mHX^}upPZhq9PTD3%j?Y8f#{}bU~vm`M@whY;kipPDq<6dN?}au)OOGP z4?{S+9~QN!3#}InYwh&Uwr?t!W#3xu=aQ9YSQOkj7&O}JbkT-{mY)GJ1X>Zfz5JLw zWOwh$y=FJU?ZtOt>jx11TT4k*H8dnA*MTetAa3)`tNcmbLM#p17A^p>t{_It{C@O_8YAxwEv>zH{a3z~vA+>sfCBH+pI3YR$(Hlc3Qzy$2``7$nl zq^UA8MA7|Ez}LA-265?^0t_lbHF&9e)^|=KlCE=fuL-Q8_MP5rL6ltOdix8Nxi$Nd!gqY6kHE3-pSu3*XdNQ>!ratC3a6(RFfRQ`Z?i2ptfQOFmL=0t>(JfbC2Ul^e7D+v08(87o7*+PYwY{jfPe*pL zbh7oqGA>uptoB5>pkx)Hh;}hf%4Z%72b4?)^}Jl)GF%ltVqbKR38=&DwGJ7jE*x=P zY2Y(-#kB5NvGUV8vfX}rrOzGEtOL~Pozoe-#I9rCA#)s{?4;S;F0dym-tCS0{j((FydpmrOmvZOT6y*=$I9T3+iHyUyZlk%qr17tW`h}di{zsS zRL}1HtYEv)kn~v(mok=`R$btEs8$3GgKs_aJ0EvwpYl+|16^NSLGA2q`O8y=#wvjE zTG!!8mI2oW2e%}r6wUx92)+4>G;_5g5o=DFHxgRi6gelarLZ{mg{usz0^Ia6l8uFj zgzGPW>M->|pcJ(h;{gjRdidM?13GeveY?|f>_Rx$?i~k@#O)>A1Ve(b-ZuycB$zc7 z=uS1g(s#IQ`Olg-|E+2pmz{mw0U^a)R7SnmUworI?mZQ38NL39oZmAQ5ty#+xuLU< z|NEhijD9~J;>r;qj{W^G9v7*asPe=wdB^bY2QmzPB6id_s*IKU`#~q}e|iY{PHj(p z-EP`J)`Z{fP3ph9nRNaVaa8{=*f7WqH5_Mq%@ngwjpM#}Ch)A4HSt&$a z;MjVgBBBSuHHl}iet%^gup#6xsFD2``~xE~`A9^9Fgrgv2@`fc#((X;_Q3R{x}yJC zS~DJ9jTMS6*iKrD~iC1v&Vn6*$zjyMIEcy}y#m;3SaTajJQ_H8(c3ws^Q-46nzx_M1q_Chg z0S5{uT%;c0*n3pLPdYl8p6d2(0--;|nah;NI+cO)5yD@>T5LaI3C1wbS|GCZ_3OuU zqz*2_zJ5r{`6s7A-{6qp#L&r_Rmle1Qr;%n3Zm&)ZyOs7JYaCwCVHU%&Zv_wE#P8+ zcrMc{gU4zv60?JN{!mxk)_V&iD{_Kxmt=@?_!DrY?){!M;co|z(NLbMoKNA`E+k*fg6b+ba$M&xY)QvJ>+p789Me!Q7kDB^sDT< zLEr`WWc&C4a3lY#NzMN|_WW-^=l?smDoRbJsZ^Nk8tTx2{*BsKmb?_#U-rh0ExNUT z+`cilP{6|f|DX7$`(dhez>@hi`_k9T1O>(1j`paD-w?`wi=h?Q@3-xnYx}9^e*(Vi zrI~!JR0;^JMe1T}2=P-&Qk&1bH5QL-va*ayxq|x??grY4Tzcu?oQyiUCd1ORYSVbg z#Uk}Ka{d8TsAju}^(!kA6rR-5bO@kO6T8r8$FE@^6M8kFUT0f$e%HB|7}r6lT#h4AjVw%4DClSFUu$EWAYe~2n- z7o7r|rW5FbA88-P=lg<;CDX8%%s)6&xB^t*tL-zt#Am{y{{-w`rwy<=9m?$4UHKvc z$(Pfz8<4y51ehMgC7h0w0cUCa0M8uzExKIoZraRuK#LIYp(*?oG~7SCfVP;@Jx$ zlwAB-Kq(jVTG$wC7zjPC*GueH6F4hfqT6@UxH|~+PKD%ptI^nUoI8C0p64ra9ck6O%R>q zTY68~5UD$YVO!NG#9gM9l`l69469_$A-1y?owm*dQ`?*ST(mgxv=Ke;D;^`6&y)7Q zh{=+bCQSYqIad@}iGOaoCCEA`DY*+fRA-#{!*fARpan6Zbo+6s^ByJ^;$>CDfWp#B$yPwA^f8sqjKPNqn}Sdg$V?Ffca

F)HzmS<+gq)i_21rG4a2yER@PgPJWs$L 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 literal 0 HcmV?d00001 diff --git a/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/session-390.jpg b/docs/plans/lab-workflow-reliability/reports/access-browser-ci-20261020/session-390.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2e9d449cb275ab6b0774c83db85f01c217822750 GIT binary patch literal 46763 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 literal 0 HcmV?d00001 diff --git a/tests/browser_access.cjs b/tests/browser_access.cjs index bae9bae2..eba38f48 100644 --- a/tests/browser_access.cjs +++ b/tests/browser_access.cjs @@ -4,14 +4,19 @@ const assert=require('node:assert/strict'),fs=require('node:fs'),path=require('n const {spawn,execFileSync}=require('node:child_process'); const {authenticatedFixture}=require('./auth_helpers.cjs'); const {waitForDebugger}=require('./browser_startup.cjs'); +const {accessSession}=require('./browser_access_session.cjs'); +const {stopOwnedChildren}=require('./browser_owned_cleanup.cjs'); const {qaDirectory,screenshotOptions}=require('./qa_artifacts.cjs'); const root=path.resolve(__dirname,'..'),temporary=fs.mkdtempSync(path.join(os.tmpdir(),'tuldok-access-browser-')),data=path.join(temporary,'data'); const report=qaDirectory(root,'access'),children=[],errors=[],checks=[],fixture=authenticatedFixture(); -const pause=ms=>new Promise(resolve=>setTimeout(resolve,ms));let ws,send,evaluate; +const pause=ms=>new Promise(resolve=>setTimeout(resolve,ms));let ws,session,send,evaluate,phase='startup'; +function setPhase(value){phase=value;session?.setPhase(value);} async function until(fn){for(let n=0;n<200;n++){const value=await fn();if(value)return value;await pause(100);}throw Error('Access browser wait timed out');} function launch(command,args,options){const child=spawn(command,args,options);children.push(child);return child;} function code(){const file=path.join(temporary,'login-'+Date.now());execFileSync('python3',['access.py','login','--data',data,'--out',file],{cwd:root});const value=fs.readFileSync(file,'utf8').trim();fs.unlinkSync(file);return value;} (async()=>{ + await require('./test_browser_access_navigation.cjs').verifyAccessNavigation(); + setPhase('application-startup'); const server=launch('python3',['-u','app.py','--port','0','--data',data],{cwd:root,stdio:['ignore','pipe','pipe']});let output='',serverErrors='';server.stdout.on('data',chunk=>output+=chunk);server.stderr.on('data',chunk=>serverErrors+=chunk); const port=await until(()=>output.match(/127\.0\.0\.1:(\d+)/)?.[1]),base='http://127.0.0.1:'+port; assert.equal((await fetch(base+'/api/workbench/records')).status,401); @@ -19,19 +24,22 @@ function code(){const file=path.join(temporary,'login-'+Date.now());execFileSync await fixture.register(base,data,root); const response=await fixture.fetch(base+'/api/workbench/import',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({kind:'text',name:'Retained owner draft',text:'Original immutable source',groups:['auth-fixture'],rights:'Authored test fixture'})});assert.equal(response.status,201);const record=await response.json(); const browser=launch(process.env.BROWSER||'/usr/bin/chromium',['--headless','--no-sandbox','--disable-gpu','--no-first-run','--remote-debugging-port=0','--window-size=1280,900','--user-data-dir='+path.join(temporary,'browser'),'about:blank'],{stdio:'ignore'}); - const debug=await waitForDebugger(browser,path.join(temporary,'browser','DevToolsActivePort')),tabs=await(await fetch('http://127.0.0.1:'+debug+'/json')).json();ws=new WebSocket(tabs.find(tab=>tab.type==='page').webSocketDebuggerUrl);await new Promise((resolve,reject)=>{ws.onopen=resolve;ws.onerror=reject;}); - let counter=0;const pending=new Map();ws.onmessage=event=>{const value=JSON.parse(event.data);if(value.id){const task=pending.get(value.id);pending.delete(value.id);value.error?task.reject(value.error):task.resolve(value.result);}else if(value.method==='Runtime.exceptionThrown')errors.push(value.params.exceptionDetails.text);}; - send=(method,params={})=>new Promise((resolve,reject)=>{pending.set(++counter,{resolve,reject});ws.send(JSON.stringify({id:counter,method,params}));}); + const debug=await waitForDebugger(browser,path.join(temporary,'browser','DevToolsActivePort')),tabs=await(await fetch('http://127.0.0.1:'+debug+'/json')).json(); + const target=tabs.find(tab=>tab.type==='page'&&tab.url==='about:blank');assert.ok(target,'Expected the explicitly launched blank page'); + ws=new WebSocket(target.webSocketDebuggerUrl);await new Promise((resolve,reject)=>{const timer=setTimeout(()=>reject(Error('Access CDP connection timed out')),10000);ws.onopen=()=>{clearTimeout(timer);resolve();};ws.onerror=()=>{clearTimeout(timer);reject(Error('Access CDP connection failed'));};}); + session=accessSession(ws,{onEvent:value=>{if(value.method==='Runtime.exceptionThrown')errors.push(value.params.exceptionDetails.text);}});session.setPhase(phase);send=session.send; evaluate=async expression=>{const value=await send('Runtime.evaluate',{expression,awaitPromise:true,returnByValue:true});if(value.exceptionDetails)throw Error(JSON.stringify(value.exceptionDetails));return value.result.value;}; async function click(selector){const box=await evaluate(`(()=>{const el=document.querySelector(${JSON.stringify(selector)});el.scrollIntoView({block:'center'});const r=el.getBoundingClientRect();return {x:r.x+r.width/2,y:r.y+r.height/2}})()`);await send('Input.dispatchMouseEvent',{type:'mousePressed',button:'left',clickCount:1,...box});await send('Input.dispatchMouseEvent',{type:'mouseReleased',button:'left',clickCount:1,...box});} async function fill(selector,value){await click(selector);await evaluate(`document.querySelector(${JSON.stringify(selector)}).select()`);await send('Input.insertText',{text:value});} async function login(){const token=code();await fill('#session-token',token);await click('#session-submit');await until(()=>evaluate('!document.getElementById("session-dialog").open'));assert.equal(await evaluate('document.getElementById("session-token").value'),'');assert.equal(await evaluate('document.cookie.includes("tuldok_session")'),false);return token;} - await send('Page.enable');await send('Runtime.enable');await send('Network.enable'); + await send('Page.enable');await send('Page.setLifecycleEventsEnabled',{enabled:true});await send('Runtime.enable');await send('Network.enable'); // No fixture cookie is installed: this suite exercises actual interactive login. - await send('Page.navigate',{url:base+'/workbench'});await until(()=>evaluate('document.getElementById("session-dialog")?.open')); + setPhase('initial-navigation');await session.navigate('Page.navigate',{url:base+'/workbench'});await until(()=>evaluate('document.getElementById("session-dialog")?.open')); + setPhase('one-time-owner-login'); const oneTime=await login();await until(()=>evaluate('document.getElementById("notice").textContent==="Collection ready."')); assert.equal((await fetch(base+'/api/access/session',{method:'POST',headers:{Origin:base,'Content-Type':'application/json'},body:JSON.stringify({token:oneTime})})).status,401); checks.push('Anonymous legacy/current APIs denied; real one-time login consumed; cookie is HttpOnly and code cleared'); + setPhase('draft-and-reauthentication'); await click('#records .record button');await until(()=>evaluate('!document.getElementById("editor").hidden'));await fill('#label','retained-draft'); const before=(await(await fixture.fetch(base+'/api/workbench/records/'+record.id)).json()).revision; await click('#session-logout');await until(()=>evaluate('document.getElementById("session-dialog").open'));await click('#session-close'); @@ -42,12 +50,23 @@ function code(){const file=path.join(temporary,'login-'+Date.now());execFileSync assert.equal(await evaluate('document.getElementById("label").value'),'retained-draft'); await click('#save');await until(async()=>((await(await fixture.fetch(base+'/api/workbench/records/'+record.id)).json()).revision)>before); checks.push('Sign out and rejected mutation preserve draft; reauthentication does not replay mutation; deliberate retry commits'); + setPhase('session-layout-captures'); for(const [width,height] of [[1280,900],[390,844]]){await send('Emulation.setDeviceMetricsOverride',{width,height,deviceScaleFactor:1,mobile:false});await click('#session-open');await pause(100);const shot=await send('Page.captureScreenshot',screenshotOptions);fs.writeFileSync(path.join(report,'session-'+width+'.jpg'),Buffer.from(shot.data,'base64'));await click('#session-close');} const issued=await fixture.fetch(base+'/api/access/credentials',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({label:'Scoped browser agent',scopes:['inspect','edit']})});assert.equal(issued.status,201);const agent=await issued.json(); const cookies=await send('Network.getCookies',{urls:[base]});const sessionCookie=cookies.cookies.find(cookie=>cookie.httpOnly&&cookie.name==='tuldok_session');assert.ok(sessionCookie); await send('Network.setCookie',{name:sessionCookie.name,value:agent.token,url:base+'/',httpOnly:true,sameSite:'Strict',path:'/'}); - await send('Page.reload');await until(()=>evaluate('document.getElementById("session-identity")?.textContent.includes("Scoped browser agent")'));await until(()=>evaluate('document.getElementById("notice").textContent==="Collection ready."'));await click('#records .record button');await until(()=>evaluate('!document.getElementById("editor").hidden')); + setPhase('scoped-agent-reload');await session.navigate('Page.reload');await until(()=>evaluate('document.getElementById("session-identity")?.textContent.includes("Scoped browser agent")'));await until(()=>evaluate('document.getElementById("notice").textContent==="Collection ready."'));await click('#records .record button');await until(()=>evaluate('!document.getElementById("editor").hidden')); assert.equal(await evaluate('document.getElementById("record-review").disabled'),true); checks.push('Real scoped agent identity cannot use owner human-review controls'); - assert.deepEqual(errors,[]);assert.equal(serverErrors,'');fs.writeFileSync(path.join(report,'receipt.json'),JSON.stringify({checks,anonymous_denied:true,real_cli_login:true,no_mutation_replay:true},null,2));console.log('PASS access browser '+report); -})().catch(error=>{console.error(error);process.exitCode=1;}).finally(()=>{ws?.close();for(const child of children)child.kill('SIGTERM');fs.rmSync(temporary,{recursive:true,force:true});}); + assert.deepEqual(errors,[]);assert.equal(serverErrors,'');fs.writeFileSync(path.join(report,'receipt.json'),JSON.stringify({checks,anonymous_denied:true,real_cli_login:true,no_mutation_replay:true,source_commit:execFileSync('git',['rev-parse','HEAD'],{cwd:root,encoding:'utf8'}).trim(),source_sha256:Object.fromEntries(['tests/browser_access.cjs','tests/browser_access_session.cjs','tests/test_browser_access_navigation.cjs'].map(file=>[file,require('node:crypto').createHash('sha256').update(fs.readFileSync(path.join(root,file))).digest('hex')])),navigation:session.snapshot()},null,2));console.log('PASS access browser '+report); +})().catch(error=>{ + console.error('Primary access failure:',error);process.exitCode=1; + const failure={phase,protocol:session?.snapshot(),error:{name:error.name,message:error.message,code:error.code}}; + console.error('Access failure context:',JSON.stringify(failure)); + fs.writeFileSync(path.join(report,'failure.json'),JSON.stringify(failure,null,2)+'\n'); +}).finally(async()=>{ + if(session)session.close();else ws?.close(); + await stopOwnedChildren(children); + fs.rmSync(temporary,{recursive:true,force:true,maxRetries:10,retryDelay:100}); + fs.writeFileSync(path.join(report,'cleanup.json'),JSON.stringify({temporary,removed:!fs.existsSync(temporary),children:children.map(child=>({pid:child.pid,exit_code:child.exitCode,signal:child.signalCode})),scope:'Supplied test-owned main handles exited before bounded profile removal'},null,2)+'\n'); +}).catch(error=>{console.error('Secondary access cleanup failure:',error);process.exitCode=1;}); diff --git a/tests/browser_access_session.cjs b/tests/browser_access_session.cjs new file mode 100644 index 00000000..3c7bbaa2 --- /dev/null +++ b/tests/browser_access_session.cjs @@ -0,0 +1,46 @@ +'use strict'; +const {cdpSession}=require('./browser_cdp_session.cjs'); +const {pageLoadTracker}=require('./browser_page_load.cjs'); + +// Access-test diagnostics contain phase/method/loader identity, never command parameters. +function accessSession(socket,{timeoutMs=15000,loadTimeoutMs=20000,pollMs=25,onEvent=()=>{}}={}){ + const loads=pageLoadTracker(),events=[]; + let phase='startup',lastMethod=null,terminal=null; + const session=cdpSession(socket,{timeoutMs,onEvent:message=>{ + loads.observe(message); + if(message.method==='Page.frameNavigated'&&!message.params.frame.parentId){ + const {id,loaderId}=message.params.frame;events.push({event:'main-frame',frame:id,loader:loaderId}); + } + if(message.method==='Page.lifecycleEvent'&&message.params.name==='load'){ + events.push({event:'load',frame:message.params.frameId,loader:message.params.loaderId}); + } + if(events.length>12)events.splice(0,events.length-12); + onEvent(message); + }}); + socket.addEventListener('close',()=>{terminal='CDP socket closed';}); + socket.addEventListener('error',()=>{terminal='CDP socket failed';}); + function contextual(error,owner,method){ + return Object.assign(new Error(`Access browser [${owner}] ${method}: ${error.message}`,{cause:error}),{code:error.code}); + } + async function send(method,params={},budgetMs){ + const owner=phase;lastMethod=method; + try{return await session.send(method,params,budgetMs);} + catch(error){throw contextual(error,owner,method);} + } + async function navigate(method,params={}){ + if(!['Page.navigate','Page.reload'].includes(method))throw Error('Unsupported access navigation'); + const owner=phase,previous=(await send('Page.getFrameTree')).frameTree.frame; + if(!previous.id||!previous.loaderId)throw Error(`Access browser [${owner}] missing previous main loader`); + const result=await send(method,params); + if(result.errorText)throw Error(`Access browser [${owner}] ${method}: ${result.errorText}`); + const deadline=performance.now()+loadTimeoutMs; + // Navigation acknowledgement can precede document replacement. Never poll that old DOM. + while(!loads.reloaded(previous)){ + if(terminal)throw contextual(Error(terminal),owner,method); + if(performance.now()>=deadline)throw Error(`Access browser [${owner}] ${method}: new main document load timed out`); + await new Promise(resolve=>setTimeout(resolve,pollMs)); + } + } + return {send,navigate,setPhase(value){phase=value;},snapshot(){return {phase,last_method:lastMethod,events:[...events]};},close(){terminal='CDP session disposed';session.close();}}; +} +module.exports={accessSession}; diff --git a/tests/test_browser_access_navigation.cjs b/tests/test_browser_access_navigation.cjs new file mode 100644 index 00000000..a097d5bb --- /dev/null +++ b/tests/test_browser_access_navigation.cjs @@ -0,0 +1,61 @@ +'use strict'; +// Controlled CDP scheduling reproduces the departing-document window; not a hosted trace. +const assert=require('node:assert/strict'); +const {cdpSession}=require('./browser_cdp_session.cjs'); +const {accessSession}=require('./browser_access_session.cjs'); +const tick=()=>new Promise(resolve=>setImmediate(resolve)); +class Socket extends EventTarget{ + constructor(){super();this.reads=0;this.loaded=false;this.requested=new Promise(resolve=>{this.acknowledged=resolve;});} + receive(value){this.dispatchEvent(new MessageEvent('message',{data:JSON.stringify(value)}));} + send(raw){ + const {id,method}=JSON.parse(raw); + if(method==='Page.getFrameTree'){this.receive({id,result:{frameTree:{frame:{id:'main',loaderId:'old'}}}});return;} + if(method==='Page.navigate'||method==='Page.reload'){this.receive({id,result:{}});this.acknowledged();return;} + if(method==='Runtime.never')return; + if(method==='Runtime.evaluate'){ + this.reads++; + if(!this.loaded){this.receive({id,error:{code:-32000,message:'Inspected target navigated or closed'}});return;} + } + this.receive({id,result:{result:{value:true}}}); + } + frame(id,loaderId,parentId){this.receive({method:'Page.frameNavigated',params:{frame:{id,loaderId,parentId}}});} + load(frameId,loaderId,name='load'){this.receive({method:'Page.lifecycleEvent',params:{frameId,loaderId,name}});} + close(){this.dispatchEvent(new Event('close'));} +} +async function verifyAccessNavigation(){ + for(const method of ['Page.navigate','Page.reload']){ + const oldSocket=new Socket(),old=cdpSession(oldSocket); + try{ + await old.send(method); + await assert.rejects(old.send('Runtime.evaluate',{expression:'original access assertion'}),error=>error.code===-32000&&error.message==='Inspected target navigated or closed'); + }finally{old.close();} + const socket=new Socket(),current=accessSession(socket,{pollMs:1,loadTimeoutMs:1000}); + current.setPhase(method==='Page.reload'?'scoped-agent-reload':'initial-navigation'); + try{ + let finished=false; + const action=(async()=>{await current.navigate(method);await current.send('Runtime.evaluate',{expression:'original access assertion'});finished=true;})(); + await socket.requested;await tick();assert.equal(socket.reads,0);assert.equal(finished,false); + socket.frame('child','child-new','main');socket.load('child','child-new'); + socket.frame('main','new');socket.load('main','old');socket.load('main','new','DOMContentLoaded'); + await tick();assert.equal(socket.reads,0);assert.equal(finished,false,'Old/subframe/DOMContentLoaded events never permit access DOM reads'); + socket.loaded=true;socket.load('main','new');await action;assert.equal(socket.reads,1);assert.equal(finished,true); + }finally{current.close();} + } + console.log('PASS access navigation/reload reproduction: old acknowledgement permits failing DOM read; changed main loader plus its load gates the original assertion'); + for(const kind of ['timeout','close']){ + const socket=new Socket(),current=accessSession(socket,{pollMs:1,loadTimeoutMs:25});current.setPhase('scoped-agent-reload'); + try{ + const navigation=current.navigate('Page.reload'); + const rejected=assert.rejects(navigation,kind==='close'?/\[scoped-agent-reload\] Page.reload: CDP socket closed/:/\[scoped-agent-reload\] Page.reload: new main document load timed out/); + await socket.requested;if(kind==='close')socket.close();await rejected;assert.equal(socket.reads,0); + }finally{current.close();} + } + const socket=new Socket(),current=accessSession(socket,{timeoutMs:20});current.setPhase('private-operation'); + try{ + await assert.rejects(current.send('Runtime.never',{token:'MUST_NOT_APPEAR'}),error=>error.message==='Access browser [private-operation] Runtime.never: CDP timeout: Runtime.never'&&!error.message.includes('MUST_NOT_APPEAR')); + assert.ok(!JSON.stringify(current.snapshot()).includes('MUST_NOT_APPEAR')); + }finally{current.close();} + console.log('PASS access phase-specific timeout/target-close failures are bounded; diagnostics omit command parameters'); +} +module.exports={verifyAccessNavigation}; +if(require.main===module)verifyAccessNavigation().catch(error=>{console.error(error);process.exitCode=1;}); From 8fac1adb1c17c070cef7b1545c365c053584cede Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Oct 2026 10:27:39 +0000 Subject: [PATCH 8/8] test: wait for started custody event before helper fault --- tests/test_recipe_process.py | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/tests/test_recipe_process.py b/tests/test_recipe_process.py index 81135555..9a8402eb 100644 --- a/tests/test_recipe_process.py +++ b/tests/test_recipe_process.py @@ -9,7 +9,7 @@ import tempfile import time import unittest -from unittest.mock import patch +from unittest.mock import Mock, patch import uuid import recipe_process as custody @@ -46,13 +46,37 @@ def start(self,spec): self.until(handle,lambda:handle.ready is not None) return handle - def until(self,handle,predicate,timeout=15): + def until(self,handle,predicate,timeout=15,*,event_type=None): deadline=time.monotonic()+timeout;events=[] while time.monotonic()