clearotron 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +82 -1
- package/.nvmrc +1 -1
- package/CONTRIBUTING.md +3 -3
- package/INSTALL.md +64 -58
- package/README.md +11 -16
- package/THIRD-PARTY-NOTICES.md +1 -1
- package/bin/brandowner.mjs +1 -1
- package/bin/clearotron.mjs +26 -4
- package/bin/connect.mjs +2 -2
- package/bin/example.mjs +31 -11
- package/bin/grant.mjs +3 -3
- package/bin/key.mjs +1 -1
- package/bin/onboard.mjs +252 -136
- package/bin/start.mjs +176 -33
- package/bin/stop.mjs +65 -3
- package/bin/update.mjs +7 -7
- package/bin/uspto-sync.mjs +1 -1
- package/build-info.json +2 -2
- package/demo/full-country-search/run/_driver/framework.json +1 -1
- package/demo/global-preliminary-search/run/_driver/framework.json +1 -1
- package/demo/knockout-search/run/_driver/framework.json +1 -1
- package/demo/multi-country-focus-search/run/_driver/framework.json +1 -1
- package/docs/DELIVERY.md +6 -2
- package/docs/E2E.md +5 -5
- package/docs/PORTAL.md +2 -2
- package/docs/README.md +5 -4
- package/docs/SECURITY.md +17 -0
- package/docs/architecture/01-product-overview.md +2 -2
- package/docs/architecture/02-architecture.md +2 -2
- package/docs/architecture/04-configuration-reference.md +8 -3
- package/docs/architecture/05-config-governance.md +52 -5
- package/docs/architecture/05-customer-profiles.md +2 -2
- package/docs/architecture/06-operations-runbook.md +13 -1
- package/docs/architecture/09-security-and-data.md +1 -1
- package/docs/configuration.md +4 -3
- package/docs/decisions/0004-documentation-structure.md +1 -1
- package/driver/CHANGELOG.md +121 -1
- package/driver/README.md +2 -2
- package/driver/ask-ledger.mjs +3 -3
- package/driver/authority-trees.mjs +1 -1
- package/driver/call-capture.mjs +1 -1
- package/driver/card-frame.mjs +1 -1
- package/driver/case-law-ledger.mjs +1 -1
- package/driver/claim-liveness.mjs +1 -1
- package/driver/common-law-receipts.mjs +2 -2
- package/driver/commonlaw-carry.mjs +1 -1
- package/driver/config-inventory.mjs +1 -1
- package/driver/config-staleness.mjs +1 -1
- package/driver/connotation-search.mjs +12 -12
- package/driver/contract-audit.mjs +5 -5
- package/driver/contract-dictation-registry.mjs +4 -4
- package/driver/contract-dictation.mjs +2 -2
- package/driver/contract-e3-backlog.mjs +6 -6
- package/driver/contract-vocabulary.mjs +3 -3
- package/driver/corrections-feedforward.mjs +1 -1
- package/driver/coverage-form-io.mjs +2 -2
- package/driver/coverage-form.mjs +4 -4
- package/driver/coverage-ledger.mjs +3 -3
- package/driver/coverage-union.mjs +1 -1
- package/driver/declination-call.mjs +35 -3
- package/driver/declination-duty.mjs +1 -1
- package/driver/deliver-trigger.sh +3 -3
- package/driver/deploy-live-run-guard.mjs +6 -2
- package/driver/dev-portal.mjs +3 -3
- package/driver/disposition-call.mjs +4 -4
- package/driver/disposition-tool.mjs +4 -4
- package/driver/disposition-union.mjs +2 -2
- package/driver/doc-constants.mjs +1 -1
- package/driver/door-gates.mjs +2 -2
- package/driver/doubt-selection.mjs +2 -2
- package/driver/drainer-identity.mjs +1 -1
- package/driver/driver.config.mjs +64 -12
- package/driver/e2e-rounds.mjs +2 -2
- package/driver/effort-model.mjs +2 -2
- package/driver/engine/anthropic-agent.mjs +24 -24
- package/driver/engine/auth.mjs +1 -1
- package/driver/engine/cli-version.mjs +103 -0
- package/driver/engine/common.mjs +1 -1
- package/driver/engine/deny-authority-write.mjs +1 -1
- package/driver/engine/jx-turn.mjs +1 -1
- package/driver/engine/mcp/clarivate-server.mjs +1 -1
- package/driver/engine/mcp/corsearch-server.mjs +1 -1
- package/driver/engine/mcp/declination-server.mjs +1 -1
- package/driver/engine/mcp/dispositions-server.mjs +1 -1
- package/driver/engine/mcp/euipo-server.mjs +1 -1
- package/driver/engine/mcp/fetch-server.mjs +1 -1
- package/driver/engine/mcp/free-tier-server.mjs +2 -2
- package/driver/engine/mcp/gather-config.mjs +11 -11
- package/driver/engine/mcp/perplexity-server.mjs +1 -1
- package/driver/engine/mcp/recording-server.mjs +8 -4
- package/driver/engine/mcp/signa-server.mjs +1 -1
- package/driver/engine/mcp/uspto-local-server.mjs +1 -1
- package/driver/engine/openai-agent.mjs +2 -2
- package/driver/engine-build.mjs +2 -2
- package/driver/enqueue-schema.mjs +10 -10
- package/driver/enqueue.mjs +1 -1
- package/driver/envelope-settle.mjs +1 -1
- package/driver/evidence-claim-invariant.mjs +2 -2
- package/driver/feedback-store.mjs +1 -1
- package/driver/findings-model.mjs +60 -10
- package/driver/flag-snapshot.mjs +20 -0
- package/driver/floor-duty.mjs +1 -1
- package/driver/form-neighbourhood.mjs +1 -1
- package/driver/framework.mjs +2 -2
- package/driver/gateway.mjs +45 -23
- package/driver/grounds-grammar.mjs +1 -1
- package/driver/hit-list.mjs +1 -1
- package/driver/jurisdiction-systems.mjs +1 -1
- package/driver/jx-lanes.mjs +1 -1
- package/driver/jx-units.mjs +1 -1
- package/driver/jx.mjs +3 -3
- package/driver/knockout-assess-record.mjs +5 -1
- package/driver/narrative-refutation-record.mjs +3 -3
- package/driver/numeric-setting.mjs +1 -1
- package/driver/owner-use-check.mjs +184 -0
- package/driver/package.json +4 -4
- package/driver/party-facts.mjs +2 -2
- package/driver/phase0.mjs +2 -2
- package/driver/pipeline-knockout.mjs +52 -4
- package/driver/pipeline.mjs +180 -67
- package/driver/placement-diff.mjs +2 -2
- package/driver/placement-form.mjs +4 -4
- package/driver/placement-union.mjs +1 -1
- package/driver/plain-register.mjs +120 -0
- package/driver/portal-access.mjs +1 -1
- package/driver/portal-acks.mjs +1 -1
- package/driver/portal-config-view.mjs +42 -3
- package/driver/portal-families.mjs +1 -1
- package/driver/portal-local-auth.mjs +1 -1
- package/driver/portal-report.mjs +7 -7
- package/driver/portal-service.mjs +41 -22
- package/driver/portal-upstream.mjs +2 -2
- package/driver/predelivery-lint.mjs +149 -11
- package/driver/prelim-variants-record.mjs +2 -2
- package/driver/profile-page.html +11 -3
- package/driver/profile-selection.mjs +1 -1
- package/driver/profile-service.mjs +6 -6
- package/driver/profiles/README.md +3 -3
- package/driver/profiles.mjs +145 -13
- package/driver/progress.mjs +6 -6
- package/driver/provider-usage.mjs +1 -1
- package/driver/publish/demo-marking.mjs +1 -1
- package/driver/publish/index.mjs +49 -8
- package/driver/publish/knockout.mjs +42 -14
- package/driver/publish/parse.mjs +4 -4
- package/driver/publish/publish-inputs.mjs +2 -2
- package/driver/publish/register-presence.mjs +1 -1
- package/driver/publish/render-knockout.mjs +646 -144
- package/driver/publish/render.mjs +2 -2
- package/driver/publish/report-data.mjs +13 -3
- package/driver/queue-watch-probe.mjs +1 -1
- package/driver/queue-watch-verdict.mjs +1 -1
- package/driver/recall-reconciliation.mjs +1 -1
- package/driver/recipe-service.mjs +1 -1
- package/driver/record-carry.mjs +5 -5
- package/driver/recording-agreement.mjs +3 -3
- package/driver/reference-score.mjs +7 -7
- package/driver/reference-strip-signatures.mjs +20 -0
- package/driver/refusal-bound.mjs +3 -3
- package/driver/register-availability.mjs +2 -2
- package/driver/register-count.mjs +1 -1
- package/driver/register-grant-vocabulary.mjs +2 -2
- package/driver/register-plan.mjs +8 -8
- package/driver/register-records.mjs +2 -2
- package/driver/registry-fidelity.mjs +3 -3
- package/driver/remedy-accounting.mjs +1 -1
- package/driver/repair-composers.mjs +2 -2
- package/driver/repair-digest.mjs +3 -3
- package/driver/repairs.mjs +6 -6
- package/driver/replay-archive.mjs +2 -0
- package/driver/report-card-record.mjs +2 -2
- package/driver/result-noun-fields.mjs +10 -3
- package/driver/run-economics.mjs +2 -2
- package/driver/run-integrity.mjs +1 -1
- package/driver/runner.mjs +22 -22
- package/driver/scope-rules.mjs +1 -1
- package/driver/search-policy.mjs +5 -5
- package/driver/skeptic-search.mjs +1 -1
- package/driver/skills/blind-frame/SKILL.md +2 -2
- package/driver/skills/case-law-citation/SKILL.md +2 -2
- package/driver/skills/knockout-assess/SKILL.md +94 -4
- package/driver/skills/matter-frame/SKILL.md +6 -6
- package/driver/skills/matter-frame/watchlist-reference.md +2 -2
- package/driver/skills/prelim-common-law/SKILL.md +1 -1
- package/driver/skills/prelim-search/SKILL.md +3 -3
- package/driver/skills/prelim-search/report-prose.md +82 -0
- package/driver/skills/prelim-search/risk-framework-demo.manifest.json +1 -1
- package/driver/skills/prelim-search/risk-framework-triage.manifest.json +1 -1
- package/driver/skills/prelim-search/risk-framework.manifest.json +1 -1
- package/driver/skills/prelim-search/synthesis-rules.md +1 -1
- package/driver/skills/prelim-search/template-formatting.md +1 -1
- package/driver/skills/prelim-search/templates/email/generic.md +1 -1
- package/driver/skills/prelim-search/worked-examples.md +1 -1
- package/driver/skills/prelim-variants/SKILL.md +5 -5
- package/driver/stage-context.mjs +1 -1
- package/driver/stages-knockout.mjs +55 -4
- package/driver/stages.mjs +101 -44
- package/driver/stray-artifacts.mjs +2 -2
- package/driver/suite-census.json +275 -65
- package/driver/synthesis-record.mjs +1 -1
- package/driver/systemd/clearotron-client-mcp.service +1 -1
- package/driver/systemd/clearotron-portal.service +1 -1
- package/driver/systemd/render-units.mjs +1 -1
- package/driver/tokens.mjs +1 -1
- package/driver/tool-calls.mjs +1 -1
- package/driver/turnaround-bands.mjs +1 -1
- package/driver/unit-file-drift.mjs +1 -1
- package/driver/unit-inventory.mjs +297 -80
- package/driver/unit-state-verdict.mjs +20 -12
- package/driver/verify-knockout.mjs +10 -2
- package/driver/verify.mjs +13 -13
- package/driver/whatif-memo-run.mjs +72 -9
- package/driver/whatif-memo.mjs +19 -1
- package/driver/whatif-queue.mjs +1 -1
- package/driver/whatif-worker.mjs +1 -1
- package/examples/README.md +2 -2
- package/examples/grants.example.json +6 -7
- package/mcp-server/CHANGELOG.md +6 -0
- package/mcp-server/README.md +3 -3
- package/mcp-server/http-server.mjs +44 -1
- package/mcp-server/key-socket.mjs +184 -0
- package/mcp-server/lib/audit-view.mjs +69 -2
- package/mcp-server/lib/brief.mjs +15 -0
- package/mcp-server/lib/driver.mjs +7 -1
- package/mcp-server/lib/events.mjs +1 -1
- package/mcp-server/lib/http-handler.mjs +1 -1
- package/mcp-server/lib/knockout.mjs +435 -0
- package/mcp-server/lib/ops.mjs +4 -4
- package/mcp-server/lib/options.mjs +1 -1
- package/mcp-server/lib/plan.mjs +1 -1
- package/mcp-server/lib/runs.mjs +1 -1
- package/mcp-server/lib/scrub.mjs +2 -2
- package/mcp-server/lib/whatif.mjs +5 -5
- package/mcp-server/mint-token.mjs +1 -1
- package/mcp-server/package.json +2 -2
- package/mcp-server/packs/ops/EXAMPLES.md +2 -2
- package/mcp-server/server.mjs +77 -12
- package/package.json +30 -12
- package/portal-ui/dist/assets/{index-Ct3iQtZ2.css → index-1ziUJX1E.css} +43 -2
- package/portal-ui/dist/assets/{index-BUGgiYtF.js → index-CEYvXdqH.js} +226 -49
- package/portal-ui/dist/index.html +2 -2
- package/portal-ui/package.json +1 -1
- package/providers/_shared/enumerate.mjs +1 -1
- package/providers/_shared/ledger-path.mjs +3 -3
- package/providers/_shared/ledger.mjs +1 -1
- package/providers/_shared/result-shape.mjs +3 -3
- package/providers/_shared/term-shape.mjs +2 -2
- package/providers/corsearch/src/core.js +1 -1
- package/providers/jx-subclass/BUILDING.md +1 -1
- package/providers/oauth-mcp-bridge/CHANGELOG.md +6 -0
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/providers/oauth-mcp-bridge/stdin-guard.mjs +2 -2
- package/providers/uspto-local/src/index-store.js +2 -2
- package/scripts/README.md +1 -1
- package/scripts/added-reference-check.mjs +29 -1
- package/scripts/authority-boundary-probe.mjs +1 -1
- package/scripts/backfill-started-at.mjs +1 -1
- package/scripts/citation-line-check.mjs +124 -5
- package/scripts/compare.mjs +2 -2
- package/scripts/contract-dictation-scan.mjs +2 -2
- package/scripts/dead-names.mjs +1 -1
- package/scripts/drain-preflight.mjs +5 -5
- package/scripts/e2e-unread-terminals.mjs +1 -1
- package/scripts/e2e.mjs +8 -8
- package/scripts/env-audit.mjs +7 -7
- package/scripts/env-classify.mjs +206 -18
- package/scripts/freeze-example-run.mjs +3 -3
- package/scripts/head-arrived-gated.mjs +1 -1
- package/scripts/headless-page.mjs +51 -2
- package/scripts/live-surface-check.mjs +129 -19
- package/scripts/main-health.mjs +1 -1
- package/scripts/merge-presence-check.mjs +3 -3
- package/scripts/mint-suite-census.mjs +6 -6
- package/scripts/nightly-notice.mjs +1 -3
- package/scripts/preinstall-node-check.mjs +24 -0
- package/scripts/reconcile-runs.mjs +1 -1
- package/scripts/release-await-cut.mjs +6 -4
- package/scripts/release-version-pr-checks.mjs +1 -1
- package/scripts/release-version.mjs +2 -2
- package/scripts/render-check.mjs +66 -7
- package/scripts/report-frame-check.mjs +1 -1
- package/scripts/report-screenshot.mjs +1 -1
- package/scripts/revisit-render-check.mjs +1 -1
- package/scripts/score.mjs +4 -4
- package/scripts/strip-tracker-citations.mjs +139 -0
- package/scripts/test-run.mjs +19 -3
- package/scripts/third-party-notices.mjs +3 -3
- package/scripts/travelling-predicates.mjs +3 -3
- package/scripts/unexecuted-asserts.mjs +2 -2
- package/scripts/verify-publishable.mjs +2 -2
- package/scripts/write-up-form-census.mjs +1 -1
- package/shared/access-audience.mjs +1 -1
- package/shared/anon-overlay.mjs +3 -3
- package/shared/brand.mjs +13 -13
- package/shared/citation-scan.mjs +1 -1
- package/shared/client-door.mjs +7 -7
- package/shared/customer-store.mjs +1 -1
- package/shared/driver-dir.mjs +1 -1
- package/shared/env-aliases.mjs +0 -48
- package/shared/env-local.mjs +1 -1
- package/shared/identifier-scan.mjs +3 -3
- package/shared/invocation.mjs +29 -1
- package/shared/names-in-force.mjs +4 -0
- package/shared/node-floor.mjs +97 -0
- package/shared/product-owned-names.mjs +1 -1
- package/shared/register-selection.mjs +1 -1
- package/shared/scope.mjs +5 -5
- package/shared/server-units.mjs +4 -4
- package/shared/staff-domain.mjs +154 -0
- package/shared/store-in-repo.mjs +25 -4
- package/shared/suite-census.mjs +4 -4
- package/shared/tty-style.mjs +1 -1
- package/shared/uspto-index-size.mjs +1 -1
- package/shared/vacuous-pass.mjs +1 -1
- package/skills/clearotron-account/SKILL.md +42 -13
- package/skills/clearotron-ops/SKILL.md +1 -1
- package/driver/recipes/README.md +0 -49
- package/driver/skills/prelim-search/risk-framework-aurora.manifest.json +0 -19
- package/driver/skills/prelim-search/risk-framework-aurora.md +0 -77
- package/driver/skills/prelim-search/risk-framework-zephyr.manifest.json +0 -14
- package/driver/skills/prelim-search/risk-framework-zephyr.md +0 -33
- package/driver/skills/prelim-search/worked-examples-aurora.md +0 -10
- package/driver/skills/prelim-search/worked-examples-zephyr.md +0 -10
- package/driver/systemd/prelim-driver.path +0 -69
- package/driver/systemd/prelim-driver.service +0 -86
- package/driver/systemd/prelim-driver.timer +0 -14
- package/driver/systemd/prelim-outbox.path +0 -27
- package/driver/systemd/prelim-outbox.service +0 -37
- package/driver/systemd/prelim-outbox.timer +0 -21
- package/node_modules/exceljs/README_zh.md +0 -2878
- package/node_modules/exceljs/dist/LICENSE +0 -22
- package/node_modules/exceljs/dist/es5/csv/csv.js +0 -182
- package/node_modules/exceljs/dist/es5/csv/csv.js.map +0 -1
- package/node_modules/exceljs/dist/es5/csv/line-buffer.js +0 -68
- package/node_modules/exceljs/dist/es5/csv/line-buffer.js.map +0 -1
- package/node_modules/exceljs/dist/es5/csv/stream-converter.js +0 -110
- package/node_modules/exceljs/dist/es5/csv/stream-converter.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/anchor.js +0 -73
- package/node_modules/exceljs/dist/es5/doc/anchor.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/cell.js +0 -961
- package/node_modules/exceljs/dist/es5/doc/cell.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/column.js +0 -274
- package/node_modules/exceljs/dist/es5/doc/column.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/data-validations.js +0 -18
- package/node_modules/exceljs/dist/es5/doc/data-validations.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/defined-names.js +0 -173
- package/node_modules/exceljs/dist/es5/doc/defined-names.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/enums.js +0 -49
- package/node_modules/exceljs/dist/es5/doc/enums.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/image.js +0 -69
- package/node_modules/exceljs/dist/es5/doc/image.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/modelcontainer.js +0 -16
- package/node_modules/exceljs/dist/es5/doc/modelcontainer.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/note.js +0 -64
- package/node_modules/exceljs/dist/es5/doc/note.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/range.js +0 -229
- package/node_modules/exceljs/dist/es5/doc/range.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/row.js +0 -382
- package/node_modules/exceljs/dist/es5/doc/row.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/table.js +0 -443
- package/node_modules/exceljs/dist/es5/doc/table.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/workbook.js +0 -202
- package/node_modules/exceljs/dist/es5/doc/workbook.js.map +0 -1
- package/node_modules/exceljs/dist/es5/doc/worksheet.js +0 -900
- package/node_modules/exceljs/dist/es5/doc/worksheet.js.map +0 -1
- package/node_modules/exceljs/dist/es5/exceljs.bare.js +0 -14
- package/node_modules/exceljs/dist/es5/exceljs.bare.js.map +0 -1
- package/node_modules/exceljs/dist/es5/exceljs.browser.js +0 -36
- package/node_modules/exceljs/dist/es5/exceljs.browser.js.map +0 -1
- package/node_modules/exceljs/dist/es5/exceljs.nodejs.js +0 -15
- package/node_modules/exceljs/dist/es5/exceljs.nodejs.js.map +0 -1
- package/node_modules/exceljs/dist/es5/index.js +0 -15
- package/node_modules/exceljs/dist/es5/stream/xlsx/hyperlink-reader.js +0 -90
- package/node_modules/exceljs/dist/es5/stream/xlsx/hyperlink-reader.js.map +0 -1
- package/node_modules/exceljs/dist/es5/stream/xlsx/sheet-comments-writer.js +0 -94
- package/node_modules/exceljs/dist/es5/stream/xlsx/sheet-comments-writer.js.map +0 -1
- package/node_modules/exceljs/dist/es5/stream/xlsx/sheet-rels-writer.js +0 -94
- package/node_modules/exceljs/dist/es5/stream/xlsx/sheet-rels-writer.js.map +0 -1
- package/node_modules/exceljs/dist/es5/stream/xlsx/workbook-reader.js +0 -362
- package/node_modules/exceljs/dist/es5/stream/xlsx/workbook-reader.js.map +0 -1
- package/node_modules/exceljs/dist/es5/stream/xlsx/workbook-writer.js +0 -347
- package/node_modules/exceljs/dist/es5/stream/xlsx/workbook-writer.js.map +0 -1
- package/node_modules/exceljs/dist/es5/stream/xlsx/worksheet-reader.js +0 -392
- package/node_modules/exceljs/dist/es5/stream/xlsx/worksheet-reader.js.map +0 -1
- package/node_modules/exceljs/dist/es5/stream/xlsx/worksheet-writer.js +0 -652
- package/node_modules/exceljs/dist/es5/stream/xlsx/worksheet-writer.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/auto-drain.js +0 -18
- package/node_modules/exceljs/dist/es5/utils/auto-drain.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/browser-buffer-decode.js +0 -15
- package/node_modules/exceljs/dist/es5/utils/browser-buffer-decode.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/browser-buffer-encode.js +0 -18
- package/node_modules/exceljs/dist/es5/utils/browser-buffer-encode.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/cell-matrix.js +0 -149
- package/node_modules/exceljs/dist/es5/utils/cell-matrix.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/col-cache.js +0 -258
- package/node_modules/exceljs/dist/es5/utils/col-cache.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/copy-style.js +0 -43
- package/node_modules/exceljs/dist/es5/utils/copy-style.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/encryptor.js +0 -58
- package/node_modules/exceljs/dist/es5/utils/encryptor.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/iterate-stream.js +0 -46
- package/node_modules/exceljs/dist/es5/utils/iterate-stream.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/parse-sax.js +0 -47
- package/node_modules/exceljs/dist/es5/utils/parse-sax.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/shared-formula.js +0 -42
- package/node_modules/exceljs/dist/es5/utils/shared-formula.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/shared-strings.js +0 -32
- package/node_modules/exceljs/dist/es5/utils/shared-strings.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/stream-base64.js +0 -66
- package/node_modules/exceljs/dist/es5/utils/stream-base64.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/stream-buf.js +0 -343
- package/node_modules/exceljs/dist/es5/utils/stream-buf.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/string-buf.js +0 -73
- package/node_modules/exceljs/dist/es5/utils/string-buf.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/string-builder.js +0 -32
- package/node_modules/exceljs/dist/es5/utils/string-builder.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/stuttered-pipe.js +0 -61
- package/node_modules/exceljs/dist/es5/utils/stuttered-pipe.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/typed-stack.js +0 -23
- package/node_modules/exceljs/dist/es5/utils/typed-stack.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/under-dash.js +0 -168
- package/node_modules/exceljs/dist/es5/utils/under-dash.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/utils.js +0 -171
- package/node_modules/exceljs/dist/es5/utils/utils.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/xml-stream.js +0 -151
- package/node_modules/exceljs/dist/es5/utils/xml-stream.js.map +0 -1
- package/node_modules/exceljs/dist/es5/utils/zip-stream.js +0 -79
- package/node_modules/exceljs/dist/es5/utils/zip-stream.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/defaultnumformats.js +0 -230
- package/node_modules/exceljs/dist/es5/xlsx/defaultnumformats.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/rel-type.js +0 -18
- package/node_modules/exceljs/dist/es5/xlsx/rel-type.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/base-xform.js +0 -139
- package/node_modules/exceljs/dist/es5/xlsx/xform/base-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/book/defined-name-xform.js +0 -85
- package/node_modules/exceljs/dist/es5/xlsx/xform/book/defined-name-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/book/sheet-xform.js +0 -32
- package/node_modules/exceljs/dist/es5/xlsx/xform/book/sheet-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-calc-properties-xform.js +0 -24
- package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-calc-properties-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-properties-xform.js +0 -27
- package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-properties-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-view-xform.js +0 -51
- package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-view-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-xform.js +0 -234
- package/node_modules/exceljs/dist/es5/xlsx/xform/book/workbook-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/comment-xform.js +0 -103
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/comment-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/comments-xform.js +0 -76
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/comments-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/style/vml-position-xform.js +0 -35
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/style/vml-position-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/style/vml-protection-xform.js +0 -32
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/style/vml-protection-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-anchor-xform.js +0 -53
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-anchor-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-client-data-xform.js +0 -97
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-client-data-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-notes-xform.js +0 -107
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-notes-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-shape-xform.js +0 -92
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-shape-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-textbox-xform.js +0 -61
- package/node_modules/exceljs/dist/es5/xlsx/xform/comment/vml-textbox-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/composite-xform.js +0 -51
- package/node_modules/exceljs/dist/es5/xlsx/xform/composite-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-heading-pairs-xform.js +0 -30
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-heading-pairs-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-titles-of-parts-xform.js +0 -27
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-titles-of-parts-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-xform.js +0 -93
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/app-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/content-types-xform.js +0 -112
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/content-types-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/core-xform.js +0 -158
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/core-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/relationship-xform.js +0 -23
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/relationship-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/relationships-xform.js +0 -65
- package/node_modules/exceljs/dist/es5/xlsx/xform/core/relationships-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/base-cell-anchor-xform.js +0 -47
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/base-cell-anchor-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/blip-fill-xform.js +0 -61
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/blip-fill-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/blip-xform.js +0 -40
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/blip-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/c-nv-pic-pr-xform.js +0 -35
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/c-nv-pic-pr-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/c-nv-pr-xform.js +0 -62
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/c-nv-pr-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/cell-position-xform.js +0 -82
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/cell-position-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/drawing-xform.js +0 -98
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/drawing-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/ext-lst-xform.js +0 -40
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/ext-lst-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/ext-xform.js +0 -38
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/ext-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/hlink-click-xform.js +0 -38
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/hlink-click-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/nv-pic-pr-xform.js +0 -59
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/nv-pic-pr-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/one-cell-anchor-xform.js +0 -63
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/one-cell-anchor-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/pic-xform.js +0 -67
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/pic-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/sp-pr.js +0 -30
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/sp-pr.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/two-cell-anchor-xform.js +0 -62
- package/node_modules/exceljs/dist/es5/xlsx/xform/drawing/two-cell-anchor-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/list-xform.js +0 -91
- package/node_modules/exceljs/dist/es5/xlsx/xform/list-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/auto-filter-xform.js +0 -40
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/auto-filter-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cell-xform.js +0 -451
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cell-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/cf-rule-xform.js +0 -275
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/cf-rule-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/cfvo-xform.js +0 -25
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/cfvo-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/color-scale-xform.js +0 -38
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/color-scale-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/conditional-formatting-xform.js +0 -45
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/conditional-formatting-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/conditional-formattings-xform.js +0 -77
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/conditional-formattings-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/databar-xform.js +0 -42
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/databar-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/ext-lst-ref-xform.js +0 -71
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/ext-lst-ref-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/formula-xform.js +0 -22
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/formula-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/icon-set-xform.js +0 -43
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf/icon-set-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.js +0 -28
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cf-icon-ext-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js +0 -88
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cf-rule-ext-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.js +0 -38
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/cfvo-ext-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.js +0 -52
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.js +0 -43
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/databar-ext-xform.js +0 -75
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/databar-ext-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/f-ext-xform.js +0 -22
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/f-ext-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.js +0 -66
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/sqref-ext-xform.js +0 -22
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/cf-ext/sqref-ext-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/col-xform.js +0 -78
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/col-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/data-validations-xform.js +0 -247
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/data-validations-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/dimension-xform.js +0 -28
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/dimension-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/drawing-xform.js +0 -32
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/drawing-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/ext-lst-xform.js +0 -69
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/ext-lst-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/header-footer-xform.js +0 -126
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/header-footer-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/hyperlink-xform.js +0 -50
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/hyperlink-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/merge-cell-xform.js +0 -26
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/merge-cell-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/merges.js +0 -52
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/merges.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/outline-properties-xform.js +0 -35
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/outline-properties-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-breaks-xform.js +0 -24
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-breaks-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-margins-xform.js +0 -46
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-margins-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-setup-properties-xform.js +0 -32
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-setup-properties-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-setup-xform.js +0 -99
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/page-setup-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/picture-xform.js +0 -32
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/picture-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/print-options-xform.js +0 -45
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/print-options-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/row-breaks-xform.js +0 -37
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/row-breaks-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/row-xform.js +0 -128
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/row-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-format-properties-xform.js +0 -51
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-format-properties-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-properties-xform.js +0 -83
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-properties-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-protection-xform.js +0 -84
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-protection-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-view-xform.js +0 -190
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/sheet-view-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/table-part-xform.js +0 -32
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/table-part-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/worksheet-xform.js +0 -513
- package/node_modules/exceljs/dist/es5/xlsx/xform/sheet/worksheet-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/simple/boolean-xform.js +0 -27
- package/node_modules/exceljs/dist/es5/xlsx/xform/simple/boolean-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/simple/date-xform.js +0 -58
- package/node_modules/exceljs/dist/es5/xlsx/xform/simple/date-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/simple/float-xform.js +0 -47
- package/node_modules/exceljs/dist/es5/xlsx/xform/simple/float-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/simple/integer-xform.js +0 -53
- package/node_modules/exceljs/dist/es5/xlsx/xform/simple/integer-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/simple/string-xform.js +0 -47
- package/node_modules/exceljs/dist/es5/xlsx/xform/simple/string-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/static-xform.js +0 -61
- package/node_modules/exceljs/dist/es5/xlsx/xform/static-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/strings/phonetic-text-xform.js +0 -98
- package/node_modules/exceljs/dist/es5/xlsx/xform/strings/phonetic-text-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/strings/rich-text-xform.js +0 -92
- package/node_modules/exceljs/dist/es5/xlsx/xform/strings/rich-text-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/strings/shared-string-xform.js +0 -99
- package/node_modules/exceljs/dist/es5/xlsx/xform/strings/shared-string-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/strings/shared-strings-xform.js +0 -114
- package/node_modules/exceljs/dist/es5/xlsx/xform/strings/shared-strings-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/strings/text-xform.js +0 -39
- package/node_modules/exceljs/dist/es5/xlsx/xform/strings/text-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/alignment-xform.js +0 -139
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/alignment-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/border-xform.js +0 -185
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/border-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/color-xform.js +0 -66
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/color-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/dxf-xform.js +0 -106
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/dxf-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/fill-xform.js +0 -308
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/fill-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/font-xform.js +0 -175
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/font-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/numfmt-xform.js +0 -59
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/numfmt-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/protection-xform.js +0 -53
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/protection-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/style-xform.js +0 -118
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/style-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/styles-xform.js +0 -612
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/styles-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/underline-xform.js +0 -46
- package/node_modules/exceljs/dist/es5/xlsx/xform/style/underline-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/auto-filter-xform.js +0 -75
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/auto-filter-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/custom-filter-xform.js +0 -30
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/custom-filter-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/filter-column-xform.js +0 -89
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/filter-column-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/filter-xform.js +0 -28
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/filter-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-column-xform.js +0 -42
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-column-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-style-info-xform.js +0 -40
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-style-info-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-xform.js +0 -123
- package/node_modules/exceljs/dist/es5/xlsx/xform/table/table-xform.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xlsx.js +0 -697
- package/node_modules/exceljs/dist/es5/xlsx/xlsx.js.map +0 -1
- package/node_modules/exceljs/dist/es5/xlsx/xml/theme1.js +0 -5
- package/node_modules/exceljs/dist/es5/xlsx/xml/theme1.js.map +0 -1
- package/node_modules/exceljs/dist/exceljs.bare.js +0 -55253
- package/node_modules/exceljs/dist/exceljs.bare.js.map +0 -761
- package/node_modules/exceljs/dist/exceljs.bare.min.js +0 -45
- package/node_modules/exceljs/dist/exceljs.bare.min.js.map +0 -1
- package/node_modules/exceljs/dist/exceljs.js +0 -59900
- package/node_modules/exceljs/dist/exceljs.js.map +0 -1083
- package/node_modules/exceljs/dist/exceljs.min.js +0 -45
- package/node_modules/exceljs/dist/exceljs.min.js.map +0 -1
- package/scripts/ai-page-render-check.mjs +0 -532
- package/scripts/clearances-render-check.mjs +0 -480
- package/scripts/composer-render-check.mjs +0 -1027
- package/scripts/deploy-test.sh +0 -309
- package/scripts/home-render-check.mjs +0 -526
- package/scripts/portal-lifecycle-check.mjs +0 -639
|
@@ -1,526 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
-
// Copyright 2026 Cordillera Sàrl. Additional terms under section 7 of the AGPL-3.0 apply — see ADDITIONAL-TERMS.md
|
|
4
|
-
// home-render-check.mjs — draw Home in a real browser, in every state, in both themes.
|
|
5
|
-
//
|
|
6
|
-
// WHY THIS EXISTS. Every other test of this screen is a string assertion over its source. Those catch a
|
|
7
|
-
// missing data-anon and a hardcoded hex; they cannot see that a card overflowed, that a sentence wrapped
|
|
8
|
-
// to four lines, that the dark theme rendered light-mode band colours on a dark surface, or that the
|
|
9
|
-
// finished band's negative margins tore a hole in the frame. The portal has been bitten by exactly that
|
|
10
|
-
// class before — which is why scripts/render-check.mjs and composer-render-check.mjs exist, and this is
|
|
11
|
-
// their sibling, built on the same harness so there is one way to do this rather than three.
|
|
12
|
-
//
|
|
13
|
-
// MUST NOT run as a user with a virtual-memory ulimit (`ulimit -v`) — Chrome dumps core under one. Run
|
|
14
|
-
// it as a user with `ulimit -v unlimited`:
|
|
15
|
-
//
|
|
16
|
-
// node scripts/home-render-check.mjs [--shot-dir <dir>]
|
|
17
|
-
//
|
|
18
|
-
// Exits non-zero on the first state that fails to draw, scrolls sideways, or renders a pip count that
|
|
19
|
-
// contradicts the run it is drawn from.
|
|
20
|
-
|
|
21
|
-
import { navigateOrRefuse } from './headless-page.mjs' // tracker issue 227 — Page.navigate returns an errorText, and nothing read it
|
|
22
|
-
import { createServer } from 'node:http'
|
|
23
|
-
import { reapOnExit } from "../shared/reap-on-exit.mjs"; // — a detached group dies with this script
|
|
24
|
-
import { readFileSync, existsSync, writeFileSync, mkdtempSync, rmSync } from 'node:fs'
|
|
25
|
-
import { join, extname, dirname } from 'node:path'
|
|
26
|
-
import { fileURLToPath } from 'node:url'
|
|
27
|
-
import { spawn } from 'node:child_process'
|
|
28
|
-
import { tmpdir } from 'node:os'
|
|
29
|
-
// — the fixture derives its product NAME the way portal-service.mjs does, from the one resolver.
|
|
30
|
-
// Hardcoding the string here would let the fixture and the wire drift, which is the defect the comment
|
|
31
|
-
// on `product` below already records once.
|
|
32
|
-
import { reportIdentityFor } from '../driver/search-policy.mjs'
|
|
33
|
-
|
|
34
|
-
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
35
|
-
const DIST = join(HERE, '..', 'portal-ui', 'dist')
|
|
36
|
-
const shotDir = process.argv.includes('--shot-dir') ? process.argv[process.argv.indexOf('--shot-dir') + 1] : null
|
|
37
|
-
|
|
38
|
-
if (!existsSync(join(DIST, 'index.html'))) {
|
|
39
|
-
console.error(`no build at ${DIST} — run: npm run build:ui`)
|
|
40
|
-
process.exit(2)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const MIME = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.svg': 'image/svg+xml', '.ico': 'image/x-icon' }
|
|
44
|
-
|
|
45
|
-
// ── the states, shaped exactly as portal-service emits them ─────────────────────────────────────────
|
|
46
|
-
const now = Date.now()
|
|
47
|
-
const ago = (m) => new Date(now - m * 60_000).toISOString()
|
|
48
|
-
const run = (o) => ({
|
|
49
|
-
runId: o.runId, account: o.account ?? 'zephyr', title: o.mark, markName: o.mark,
|
|
50
|
-
projectKey: o.projectKey ?? null, projectName: o.projectName ?? null,
|
|
51
|
-
// `product` is meta.searchLevel off the wire, and it holds a PRODUCT ID. The fixtures said `prelim`
|
|
52
|
-
// — a RETIRED slug — for every state, so this check could not see that depthLabel had no case for any
|
|
53
|
-
// current product and the chip rendered EMPTY on every run the build creates. A fixture that speaks a
|
|
54
|
-
// vocabulary the build no longer produces certifies the bug.
|
|
55
|
-
// `productName` is what the CARD renders. It is resolved server-side by reportIdentityFor and
|
|
56
|
-
// sent on the wire; the browser maps nothing. Derived here from `product` through that same resolver,
|
|
57
|
-
// so this fixture cannot claim a name the service would not send. `stageLabel` stays on the row
|
|
58
|
-
// because the wire still carries it — it is INTERNAL now and no client surface may print it.
|
|
59
|
-
product: o.product ?? 'full-country-search',
|
|
60
|
-
productName: reportIdentityFor(o.product ?? 'full-country-search').identity,
|
|
61
|
-
stageLabel: reportIdentityFor(o.product ?? 'full-country-search').stageLabel,
|
|
62
|
-
kind: o.kind ?? 'clearance', state: o.state,
|
|
63
|
-
date: o.date ?? '2026-07-27', band: o.band ?? null, tone: o.tone ?? null, bands: [], marks: [],
|
|
64
|
-
reportSchema: 2, held: false, report: o.state === 'delivered' ? `/portal/report/${o.runId}/` : null,
|
|
65
|
-
step: o.step ?? null, stepN: o.stepN ?? null, stepTotal: o.stepTotal ?? null,
|
|
66
|
-
reason: o.reason ?? null, failedStage: o.failedStage ?? null,
|
|
67
|
-
pausedKind: o.pausedKind ?? null, resetsAt: o.resetsAt ?? null, startedAt: o.startedAt ?? null,
|
|
68
|
-
queuePos: o.queuePos ?? null,
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
// Three frameworks, three different ladders and three sets of words — the chip must take an arbitrary
|
|
72
|
-
// label, because Zephyr Beverages has four bands and Aurora Interactive's say something else entirely.
|
|
73
|
-
// Two of the three sit under projects, so "pick up where you left off" has something to draw. The
|
|
74
|
-
// project NAMES are deliberately long: a matter is called "Q3 packaging refresh — EU", not "spring",
|
|
75
|
-
// and a column tuned on a short slug tears the moment a real one arrives.
|
|
76
|
-
const FINISHED = [
|
|
77
|
-
run({ runId: 'f1', mark: 'VIBRANTE FROSTPLUM', state: 'delivered', band: 'Tier 3 — material', tone: 'high', date: '2026-07-26', projectKey: 'q3-packaging', projectName: 'Q3 packaging refresh — EU' }),
|
|
78
|
-
run({ runId: 'f2', mark: 'VANTOR LABS', state: 'delivered', band: 'Clear to file', tone: 'minimal', date: '2026-07-24' }),
|
|
79
|
-
run({ runId: 'f3', mark: 'AQUAPLUS', state: 'delivered', band: 'Proceed with conditions', tone: 'medium', date: '2026-07-21', projectKey: 'aqua-line', projectName: 'Aqua line extension' }),
|
|
80
|
-
]
|
|
81
|
-
|
|
82
|
-
const STATES = {
|
|
83
|
-
// A card of each kind at once, plus a queue deep enough that its ordinals mean something.
|
|
84
|
-
busy: {
|
|
85
|
-
runs: [
|
|
86
|
-
run({ runId: 'a', mark: 'CORAL FREEZE', state: 'running', step: 'Register sweeps', stepN: 2, stepTotal: 9, startedAt: ago(96) }),
|
|
87
|
-
run({ runId: 'b', mark: 'KINETIC BLOOM', state: 'paused', pausedKind: 'rate-limit', stepN: 5, stepTotal: 9, resetsAt: new Date(now + 42 * 60_000).toISOString() }),
|
|
88
|
-
run({ runId: 'c', mark: 'NORTHWIND', state: 'queued', queuePos: 1 }),
|
|
89
|
-
run({ runId: 'd', mark: 'EMBER FORGE', state: 'queued', queuePos: 2 }),
|
|
90
|
-
run({ runId: 'e', mark: 'CASTELLAN', state: 'queued', queuePos: 3 }),
|
|
91
|
-
...FINISHED,
|
|
92
|
-
],
|
|
93
|
-
expectCards: 2, expectQueue: 3, expectFirstCardPips: 9, expectStops: 2,
|
|
94
|
-
},
|
|
95
|
-
one: {
|
|
96
|
-
runs: [run({ runId: 'a', mark: 'CORAL FREEZE', state: 'running', step: 'Common-law grid', stepN: 4, stepTotal: 9, startedAt: ago(38) }), ...FINISHED],
|
|
97
|
-
expectCards: 1, expectQueue: 0, expectFirstCardPips: 9, expectStops: 1,
|
|
98
|
-
},
|
|
99
|
-
// A knockout has FIVE steps, or six with the register probe. The pip row follows the RUN.
|
|
100
|
-
knockout: {
|
|
101
|
-
runs: [run({ runId: 'k', mark: 'DRIVERS HAVEN', state: 'running', kind: 'knockout-batch', product: 'knockout-search', step: 'Marketplace sweep', stepN: 3, stepTotal: 5, startedAt: ago(14) }), ...FINISHED],
|
|
102
|
-
expectCards: 1, expectQueue: 0, expectFirstCardPips: 5, expectStops: 1,
|
|
103
|
-
},
|
|
104
|
-
// A failed card carries NO retry: re-running is command-line only, and a button would be a lie.
|
|
105
|
-
failed: {
|
|
106
|
-
runs: [run({ runId: 'x', mark: 'HALCYON', state: 'failed', failedStage: 'at register sweeps', reason: 'A register was unreachable. Nothing was delivered.' }), ...FINISHED],
|
|
107
|
-
expectCards: 1, expectQueue: 0, expectFirstCardPips: 0, expectStops: 0,
|
|
108
|
-
},
|
|
109
|
-
// Stopped on purpose — terminal, and never dressed as a failure.
|
|
110
|
-
stopped: {
|
|
111
|
-
runs: [run({ runId: 'z', mark: 'GLASSWING', state: 'cancelled' }), ...FINISHED],
|
|
112
|
-
expectCards: 1, expectQueue: 0, expectFirstCardPips: 0, expectStops: 0,
|
|
113
|
-
},
|
|
114
|
-
// THE LABEL MUST WRAP, NEVER CLIP — measured on the LONGEST string the switch can return, which is
|
|
115
|
-
// still a retired one: three of those differ only in their suffix, so an ellipsis makes "registers +
|
|
116
|
-
// marketplace" and "registers only" the same string. Kept deliberately as an ARCHIVED run: nothing can
|
|
117
|
-
// be ordered at that slug any more, and a card for a run that WAS must still say what it was.
|
|
118
|
-
longdepth: {
|
|
119
|
-
runs: [run({ runId: 'L', mark: 'MERIDIAN NORTHSTAR ASSURANCE', state: 'running', product: 'prelim-register-only', step: 'Register sweeps', stepN: 2, stepTotal: 9, startedAt: ago(20) }), ...FINISHED],
|
|
120
|
-
expectCards: 1, expectQueue: 0, expectFirstCardPips: 9, expectStops: 1,
|
|
121
|
-
},
|
|
122
|
-
// THE CAP IS THE SERVER'S, NOT A LITERAL IN THE UI. It was written in as `2`, which is right today
|
|
123
|
-
// and silently wrong the moment CLEAROTRON_MAX_CONCURRENT_RUNS is set to anything else.
|
|
124
|
-
cap3: {
|
|
125
|
-
runs: [run({ runId: 'a', mark: 'CORAL FREEZE', state: 'running', step: 'Register sweeps', stepN: 2, stepTotal: 9, startedAt: ago(96) }), ...FINISHED],
|
|
126
|
-
cap: 3,
|
|
127
|
-
expectCards: 1, expectQueue: 0, expectFirstCardPips: 9, expectStops: 1, expectCapNote: /Three runs at once/,
|
|
128
|
-
},
|
|
129
|
-
quiet: { runs: FINISHED, expectCards: 0, expectQueue: 0, expectFirstCardPips: 0, expectStops: 0 },
|
|
130
|
-
new: { runs: [], expectCards: 0, expectQueue: 0, expectFirstCardPips: 0, expectStops: 0, expectFirstRun: true },
|
|
131
|
-
// A MULTI-BRAND ACCOUNT. Home spans every owner it holds — this is the state the previous attempt
|
|
132
|
-
// emptied the moment someone picked one, with no way back.
|
|
133
|
-
firm: {
|
|
134
|
-
runs: [
|
|
135
|
-
run({ runId: 'a', account: 'zephyr', mark: 'CORAL FREEZE', state: 'running', step: 'Register sweeps', stepN: 2, stepTotal: 9, startedAt: ago(96) }),
|
|
136
|
-
run({ runId: 'b', account: 'aurora', mark: 'NORTHWIND', state: 'running', step: 'Framing the matter', stepN: 1, stepTotal: 9, startedAt: ago(6) }),
|
|
137
|
-
run({ runId: 'c', account: 'ridgeform', mark: 'EMBER FORGE', state: 'queued', queuePos: 1 }),
|
|
138
|
-
...FINISHED,
|
|
139
|
-
],
|
|
140
|
-
accounts: ['zephyr', 'aurora', 'ridgeform'],
|
|
141
|
-
expectCards: 2, expectQueue: 1, expectFirstCardPips: 9, expectStops: 2,
|
|
142
|
-
// A FIRM HOLDING THREE BRAND OWNERS HAS NO SINGLE ACCOUNT NAME the portal knows — it knows the
|
|
143
|
-
// owners they hold, not what the firm calls itself. So the account-scoped title says what is
|
|
144
|
-
// actually on screen ("All brand owners") and the Account block is absent rather than picking one
|
|
145
|
-
// of their own clients and labelling it their identity. Home still shows every owner's work; this
|
|
146
|
-
// is about what the bar can truthfully NAME, not about scope.
|
|
147
|
-
expectTitle: 'All brand owners', expectAccount: false,
|
|
148
|
-
// Several brand owners means several daily allowances and no single number. The line is ABSENT
|
|
149
|
-
// rather than reading "unavailable", which would claim a fault where there is none.
|
|
150
|
-
expectLimits: false,
|
|
151
|
-
},
|
|
152
|
-
// STILL WAITING FOR THE SERVER. A page that treats "not answered yet" as an answer shows an error or
|
|
153
|
-
// an empty state on every single load.
|
|
154
|
-
loading: {
|
|
155
|
-
runs: FINISHED, holdRunsMs: 9000,
|
|
156
|
-
expectCards: 0, expectQueue: 0, expectFirstCardPips: 0, expectStops: 0,
|
|
157
|
-
},
|
|
158
|
-
// A 429 must STATE the fault rather than rendering as "you have nothing".
|
|
159
|
-
limited: {
|
|
160
|
-
runs: [], status: 429,
|
|
161
|
-
expectCards: 0, expectQueue: 0, expectFirstCardPips: 0, expectStops: 0,
|
|
162
|
-
expectNotice: /Too many requests just now/,
|
|
163
|
-
},
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
let current = 'busy'
|
|
167
|
-
/** Requests deliberately left unanswered, so they can be cut loose before the next state runs. */
|
|
168
|
-
const held = new Set()
|
|
169
|
-
|
|
170
|
-
const server = createServer((req, res) => {
|
|
171
|
-
const path = new URL(req.url, 'http://localhost').pathname
|
|
172
|
-
const json = (o) => { res.writeHead(200, { 'content-type': 'application/json' }); res.end(JSON.stringify(o)) }
|
|
173
|
-
const s = STATES[current]
|
|
174
|
-
if (path === '/portal/api/me') {
|
|
175
|
-
const accounts = s.accounts ?? ['zephyr']
|
|
176
|
-
return json({ role: 'client', email: 'counsel@zephyr.com', accounts, concurrentRuns: s.cap ?? 2,
|
|
177
|
-
accountNames: { zephyr: 'Zephyr Beverages', aurora: 'Aurora Interactive', ridgeform: 'Ridgeform' } })
|
|
178
|
-
}
|
|
179
|
-
if (path === '/portal/api/runs') {
|
|
180
|
-
// What portal-service actually answers a multi-owner client who has named nobody. The browser
|
|
181
|
-
// decodes it to `pickAccount`, which is a UI state, never an error to print at someone.
|
|
182
|
-
if (s.status) {
|
|
183
|
-
res.writeHead(s.status, { 'content-type': 'application/json' })
|
|
184
|
-
return res.end(JSON.stringify({ error: 'rate_limited' }))
|
|
185
|
-
}
|
|
186
|
-
// Held: the page must be probed while it is still WAITING, which is the state a fixed settle delay
|
|
187
|
-
// can otherwise never see.
|
|
188
|
-
//
|
|
189
|
-
// TRACKED SO IT CAN BE CUT LOOSE. A browser opens six connections per host, and four held requests
|
|
190
|
-
// (two themes × navigate-then-reload) were still occupying them when the NEXT state loaded — so
|
|
191
|
-
// that state's own request queued behind them, never answered inside the settle window, and was
|
|
192
|
-
// probed mid-load. It read as the next state failing, which is the most expensive kind of harness
|
|
193
|
-
// bug: one that reports a fault in the code under test.
|
|
194
|
-
if (s.holdRunsMs) {
|
|
195
|
-
held.add(res)
|
|
196
|
-
return setTimeout(() => { if (held.delete(res)) json({ runs: s.runs }) }, s.holdRunsMs)
|
|
197
|
-
}
|
|
198
|
-
return json({ runs: s.runs })
|
|
199
|
-
}
|
|
200
|
-
if (path === '/portal/admin/roster') return json({ customers: [{ key: 'zephyr', name: 'Zephyr Beverages' }, { key: 'aurora', name: 'Aurora Interactive' }, { key: 'ridgeform', name: 'Ridgeform' }] })
|
|
201
|
-
if (path === '/portal/api/usage') {
|
|
202
|
-
return json({ account: 'zephyr', today: s.capped ? 2 : 1, thisMonth: 6, queued: 2, dailyRuns: 2, monthlyRuns: null, maxQueued: null, capped: true })
|
|
203
|
-
}
|
|
204
|
-
if (path.startsWith('/portal/api/') || path.startsWith('/portal/admin/')) return json({})
|
|
205
|
-
|
|
206
|
-
const base = path
|
|
207
|
-
const file = base === '/' || (base.startsWith('/portal') && !base.includes('.')) ? '/index.html' : base.replace(/^\/portal/, '')
|
|
208
|
-
const full = join(DIST, file)
|
|
209
|
-
if (!existsSync(full)) { res.writeHead(404); res.end('no'); return }
|
|
210
|
-
res.writeHead(200, { 'content-type': MIME[extname(full)] ?? 'application/octet-stream' })
|
|
211
|
-
res.end(readFileSync(full))
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
await new Promise((r) => server.listen(0, '127.0.0.1', r))
|
|
215
|
-
const origin = `http://127.0.0.1:${server.address().port}`
|
|
216
|
-
|
|
217
|
-
const userDir = mkdtempSync(join(tmpdir(), 'home-check-'))
|
|
218
|
-
const chrome = spawn('google-chrome', [
|
|
219
|
-
'--headless=new', '--disable-gpu', '--no-sandbox', '--hide-scrollbars',
|
|
220
|
-
`--user-data-dir=${userDir}`, '--window-size=1280,1000',
|
|
221
|
-
'--remote-debugging-port=0', 'about:blank',
|
|
222
|
-
// — DETACHED so Chrome LEADS A PROCESS GROUP. Its renderer, GPU and zygote processes are
|
|
223
|
-
// separate PIDs, and without a group there is nothing to signal them with.
|
|
224
|
-
], { stdio: ['ignore', 'pipe', 'pipe'], detached: true })
|
|
225
|
-
// — and the group dies with THIS script, on every exit it can observe.
|
|
226
|
-
// The teardown below runs on the paths somebody wrote a branch for; a cancelled CI job (SIGTERM),
|
|
227
|
-
// a Ctrl-C, or a throw elsewhere in this file are not among them — and that is where the measured
|
|
228
|
-
// eighty-eight-minute orphan came from.
|
|
229
|
-
reapOnExit(chrome);
|
|
230
|
-
|
|
231
|
-
let devtools = ''
|
|
232
|
-
const wsUrl = await new Promise((resolve, reject) => {
|
|
233
|
-
// 60s, not 20s. The 20s budget was set when CI ran on a paid 4-vCPU larger runner; this workflow now
|
|
234
|
-
// runs on the standard 2-vCPU ubuntu-latest, where a cold Chrome start has no margin in 20s — it
|
|
235
|
-
// failed once in the first 6 runs there with 'chrome did not report a devtools endpoint'.
|
|
236
|
-
//
|
|
237
|
-
// WHAT THE NUMBERS DO NOT SHOW, stated because the tempting claim is wrong: this is NOT established
|
|
238
|
-
// as a regression from the runner change. The same step failed 6 times in 34 runs on ubuntu-latest-m
|
|
239
|
-
// — but all 6 landed inside one 16-minute window on 2026-08-10, across several branches at once,
|
|
240
|
-
// which is an infrastructure incident and not a rate. Outside it: 0 in 28. So the evidence is
|
|
241
|
-
// consistent with the smaller runner being tighter and does not demonstrate it; n is small on both
|
|
242
|
-
// sides. The budget goes up because 20s for a cold Chrome start is thin on any 2-vCPU box, not
|
|
243
|
-
// because a measurement proved causation.
|
|
244
|
-
//
|
|
245
|
-
// And on timeout, SAY WHAT CHROME SAID — the bare message named a symptom and no cause, so the one
|
|
246
|
-
// thing the next reader needs was the one thing it withheld.
|
|
247
|
-
const t = setTimeout(
|
|
248
|
-
() => reject(new Error(`chrome did not report a devtools endpoint within 60s. Its stderr was:\n${devtools || '(nothing)'}`)),
|
|
249
|
-
60000,
|
|
250
|
-
)
|
|
251
|
-
chrome.stderr.on('data', (c) => {
|
|
252
|
-
devtools += c
|
|
253
|
-
const m = devtools.match(/ws:\/\/[^\s]+/)
|
|
254
|
-
if (m) { clearTimeout(t); resolve(m[0]) }
|
|
255
|
-
})
|
|
256
|
-
})
|
|
257
|
-
|
|
258
|
-
const ws = new WebSocket(wsUrl)
|
|
259
|
-
let id = 0
|
|
260
|
-
const pending = new Map()
|
|
261
|
-
ws.addEventListener('message', (e) => {
|
|
262
|
-
const msg = JSON.parse(e.data)
|
|
263
|
-
if (msg.id && pending.has(msg.id)) { pending.get(msg.id)(msg); pending.delete(msg.id) }
|
|
264
|
-
})
|
|
265
|
-
await new Promise((r) => ws.addEventListener('open', r))
|
|
266
|
-
const send = (method, params = {}) => new Promise((r) => { const i = ++id; pending.set(i, r); ws.send(JSON.stringify({ id: i, method, params })) })
|
|
267
|
-
const { result: targets } = await send('Target.getTargets')
|
|
268
|
-
const page = targets.targetInfos.find((t) => t.type === 'page')
|
|
269
|
-
const { result: sess } = await send('Target.attachToTarget', { targetId: page.targetId, flatten: true })
|
|
270
|
-
const sessionId = sess.sessionId
|
|
271
|
-
const cmd = (method, params = {}) => new Promise((r) => { const i = ++id; pending.set(i, r); ws.send(JSON.stringify({ id: i, sessionId, method, params })) })
|
|
272
|
-
const evalIn = async (expr) => {
|
|
273
|
-
const r = await cmd('Runtime.evaluate', { expression: expr, awaitPromise: true, returnByValue: true })
|
|
274
|
-
return r.result?.result?.value
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// What the page is asked about itself, once it has painted.
|
|
278
|
-
const PROBE = `(() => {
|
|
279
|
-
const q = (sel) => document.querySelector(sel)
|
|
280
|
-
const all = (sel) => [...document.querySelectorAll(sel)]
|
|
281
|
-
if (!q('.home2')) return { fatal: 'Home did not render' }
|
|
282
|
-
return {
|
|
283
|
-
cards: all('.home2-card').length,
|
|
284
|
-
queueRows: all('.home2-qrow').length,
|
|
285
|
-
queueCount: (q('.home2-queue-count')?.textContent ?? '').trim(),
|
|
286
|
-
// The ordinals, as drawn. They must read 1..N with no gaps — a gap would mean the screen is
|
|
287
|
-
// showing another tenant's place in the lane.
|
|
288
|
-
ordinals: all('.home2-pos').map((n) => n.textContent.trim()),
|
|
289
|
-
stops: all('.home2-stop').length,
|
|
290
|
-
cancels: all('.home2-cancel').length,
|
|
291
|
-
// FIRST CARD'S PIPS — N comes from the run, never a constant.
|
|
292
|
-
pips: q('.home2-card') ? [...q('.home2-card').querySelectorAll('.home2-pip')].length : 0,
|
|
293
|
-
// THE DEPTH LABEL MUST NOT BE CLIPPED. A string test cannot see this; only a browser can.
|
|
294
|
-
depthClipped: all('.home2-depth').filter((n) => n.scrollWidth > n.clientWidth + 1).length,
|
|
295
|
-
depthText: (q('.home2-depth')?.textContent ?? '').trim(),
|
|
296
|
-
// The band header is a GRID, so the button stays on the same row at every width.
|
|
297
|
-
newOnBandRow: (() => {
|
|
298
|
-
const band = q('.home2-band'), btn = q('.home2-band .home2-new')
|
|
299
|
-
if (!band || !btn) return null
|
|
300
|
-
return Math.abs(btn.getBoundingClientRect().top - band.getBoundingClientRect().top) < band.getBoundingClientRect().height
|
|
301
|
-
})(),
|
|
302
|
-
lastFinished: !!q('.home2-done'),
|
|
303
|
-
allClearances: all('.home2-all').length,
|
|
304
|
-
limits: (q('.home2-limits')?.textContent ?? '').trim(),
|
|
305
|
-
capNote: (q('.home2-band-note')?.textContent ?? '').trim(),
|
|
306
|
-
firstRun: !!q('.home2-firstrun'),
|
|
307
|
-
notice: (q('.home2-notice')?.textContent ?? '').trim(),
|
|
308
|
-
title: (q('.topbar h1')?.textContent ?? '').trim(),
|
|
309
|
-
accountLabelled: all('.topbar .eyebrow').some((n) => n.textContent.trim() === 'Account'),
|
|
310
|
-
// Every mark, owner and project must be blurrable — the class is not the contract, the attribute is.
|
|
311
|
-
untaggedMarks: all('.home2-card-mark, .home2-card-owner, .home2-qmark, .home2-qowner, .home2-done-mark')
|
|
312
|
-
.filter((n) => n.getAttribute('data-anon') !== 'mark').length,
|
|
313
|
-
sidewaysOverflow: document.documentElement.scrollWidth - document.documentElement.clientWidth,
|
|
314
|
-
// The sidebar's owner group must be labelled by the switcher, not floating above everything.
|
|
315
|
-
switcherInNav: !!q('.sidebar-scroll select[aria-label="Brand owner"]'),
|
|
316
|
-
theme: document.documentElement.getAttribute('data-theme') ?? 'light',
|
|
317
|
-
}
|
|
318
|
-
})()`
|
|
319
|
-
|
|
320
|
-
let failures = 0
|
|
321
|
-
const say = (ok, msg) => { if (!ok) failures++; console.log(`${ok ? ' ok ' : 'FAIL '}${msg}`) }
|
|
322
|
-
|
|
323
|
-
for (const [name, spec] of Object.entries(STATES)) {
|
|
324
|
-
// Free the previous state's held connections before this one asks for anything. See the note in the
|
|
325
|
-
// runs handler: without this, a deliberately-slow state starves the state that follows it.
|
|
326
|
-
for (const r of held) { try { r.destroy() } catch { /* already gone */ } }
|
|
327
|
-
held.clear()
|
|
328
|
-
current = name
|
|
329
|
-
for (const theme of ['light', 'dark']) {
|
|
330
|
-
await cmd('Page.navigate', { url: 'about:blank' })
|
|
331
|
-
await new Promise((r) => setTimeout(r, 120))
|
|
332
|
-
// — WAIT FOR THE PAGE TO GO QUIET, DO NOT SLEEP A GUESS AT IT.
|
|
333
|
-
//
|
|
334
|
-
// These were fixed 700ms and 1100ms waits. 1100ms is a guess and under load it is the wrong guess:
|
|
335
|
-
// on a box at load 18-22 `quiet/dark` read the page before it rendered and failed on PROBE's own
|
|
336
|
-
// fatal, `Home did not render`, while every other state in the same run passed. Same defect as
|
|
337
|
-
// FLAKE 2 and — measuring before the thing exists.
|
|
338
|
-
//
|
|
339
|
-
// THREE NARROWER WAITS WERE TRIED FIRST AND EACH WAS WORSE, which is why this one is a quiescence
|
|
340
|
-
// check and not a selector:
|
|
341
|
-
// 1. poll for `.home2` — returns against the OUTGOING document, because immediately after
|
|
342
|
-
// `Page.reload` the old one is still there. THREE states then failed where the sleep passed.
|
|
343
|
-
// 2. + require the document not be the stamped outgoing one — fixed that, and `one/dark` read
|
|
344
|
-
// 0 cards where 1 was expected: the shell mounts before its contents.
|
|
345
|
-
// 3. + require the expected card count — and the allowance line, the finished tail and the nav
|
|
346
|
-
// links were still arriving.
|
|
347
|
-
// Each fix revealed one more thing the 1100ms happened to cover. Enumerating them is a losing game;
|
|
348
|
-
// what the assertions actually need is a page that has STOPPED CHANGING.
|
|
349
|
-
//
|
|
350
|
-
// A SETTLE IS NOT A SLEEP. This returns as soon as the DOM is stable across two samples, so the
|
|
351
|
-
// common case is faster than the old fixed wait, and it cannot return before the page exists
|
|
352
|
-
// because a stamped or empty document never satisfies the preconditions.
|
|
353
|
-
const homeReady = async (after) => {
|
|
354
|
-
const deadline = Date.now() + 20000
|
|
355
|
-
let seen = { home: 0, ready: '', url: '', stale: true, size: 0 }
|
|
356
|
-
let stableFor = 0, lastSize = -1
|
|
357
|
-
for (;;) {
|
|
358
|
-
seen = await evalIn(`(() => ({
|
|
359
|
-
home: document.querySelectorAll('.home2').length,
|
|
360
|
-
ready: document.readyState,
|
|
361
|
-
url: String(location.pathname),
|
|
362
|
-
stale: window.__renderCheckDoc === 1,
|
|
363
|
-
size: document.documentElement.innerHTML.length,
|
|
364
|
-
}))()`) ?? seen
|
|
365
|
-
const usable = seen.home > 0 && !seen.stale && seen.ready === 'complete'
|
|
366
|
-
stableFor = usable && seen.size === lastSize ? stableFor + 1 : 0
|
|
367
|
-
lastSize = seen.size
|
|
368
|
-
if (stableFor >= 2) return true
|
|
369
|
-
if (Date.now() >= deadline) {
|
|
370
|
-
say(false, `${name}/${theme}: Home never settled within 20s after ${after} — `
|
|
371
|
-
+ `readyState=${seen.ready || '(unknown)'} path=${seen.url || '(unknown)'} `
|
|
372
|
-
+ `.home2=${seen.home} staleDoc=${seen.stale} lastSize=${seen.size}. `
|
|
373
|
-
+ `The wait is a deadline on a settling page, not a fixed sleep (#1854).`)
|
|
374
|
-
return false
|
|
375
|
-
}
|
|
376
|
-
await new Promise((r) => setTimeout(r, 60))
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
await evalIn(`window.__renderCheckDoc = 1`)
|
|
381
|
-
await navigateOrRefuse(cmd, `${origin}/portal/home`, { what: 'home-render-check' })
|
|
382
|
-
if (!await homeReady('navigate')) continue
|
|
383
|
-
await evalIn(`localStorage.setItem('cordillera-theme', ${JSON.stringify(theme)})`)
|
|
384
|
-
await evalIn(`window.__renderCheckDoc = 1`)
|
|
385
|
-
await cmd('Page.reload', { ignoreCache: false })
|
|
386
|
-
if (!await homeReady('reload')) continue
|
|
387
|
-
|
|
388
|
-
// The queue panel is collapsed by default — open it so its rows can be measured.
|
|
389
|
-
//
|
|
390
|
-
// FLAKE 2. This used to click and then sleep a FIXED 250ms before reading. The click has to
|
|
391
|
-
// survive a React re-render, a DOM insert and the panel's expand transition, and on a 2-vCPU
|
|
392
|
-
// ubuntu-latest runner that does not always fit. When it did not, all three queue assertions failed
|
|
393
|
-
// together — rows ABSENT rather than wrong, which is the signature of measuring too early:
|
|
394
|
-
// busy/light: 0 queue rows (expected 3) / every queued row can be cancelled (0/3) / ordinals []
|
|
395
|
-
// It failed on a PR whose entire diff was one driver test file, and the same SHA re-ran green.
|
|
396
|
-
//
|
|
397
|
-
// So: POLL for the rows instead of guessing how long they take. This file already sets the
|
|
398
|
-
// precedent — the devtools-endpoint wait polls, and its ceiling was widened from 20s to 60s for
|
|
399
|
-
// exactly this runner. A ceiling that expires still reads whatever is there and lets the assertion
|
|
400
|
-
// below report the real count, so a genuine "no rows" bug fails as loudly as it always did.
|
|
401
|
-
//
|
|
402
|
-
// — AND THE CLICK ITSELF WAS NEVER WAITED FOR, WHICH IS THE HOLE THE POLL LEFT. `?.click`
|
|
403
|
-
// fires ONCE and optional-chains: a queue bar that has not mounted yet is a silent no-op, and the
|
|
404
|
-
// loop then polls for rows in a panel nobody opened until the ceiling expires. That is an ABSENCE
|
|
405
|
-
// being read as "not yet". It reddened `main` on run 32702264758 for a diff of one driver test file
|
|
406
|
-
// and a census entry — the same tree the PR run had passed twenty minutes earlier.
|
|
407
|
-
//
|
|
408
|
-
// So poll the BAR and its own `aria-expanded`, and click only while it is closed. Not "re-click
|
|
409
|
-
// every iteration": the bar toggles, so a blind re-click closes a panel that had just opened and the
|
|
410
|
-
// read lands on whichever half of the oscillation it hit.
|
|
411
|
-
//
|
|
412
|
-
// AND A CEILING THAT EXPIRES MUST SAY WHICH OF THE TWO RAN OUT. "0 queue rows" is the same sentence
|
|
413
|
-
// for a panel that never mounted, a panel nobody opened, and a panel that opened empty — and only
|
|
414
|
-
// the third is a product defect. The state at the ceiling is printed, so the next reader is told
|
|
415
|
-
// rather than left to re-derive it from three failing assertions.
|
|
416
|
-
if (spec.expectQueue) {
|
|
417
|
-
const deadline = Date.now() + 20000
|
|
418
|
-
let last = { bar: 0, expanded: false, rows: 0 }
|
|
419
|
-
for (;;) {
|
|
420
|
-
last = await evalIn(`(() => {
|
|
421
|
-
const bar = document.querySelector('.home2-queue-bar')
|
|
422
|
-
return { bar: document.querySelectorAll('.home2-queue-bar').length,
|
|
423
|
-
expanded: bar?.getAttribute('aria-expanded') === 'true',
|
|
424
|
-
rows: document.querySelectorAll('.home2-qrow').length }
|
|
425
|
-
})()`) ?? last
|
|
426
|
-
if (last.rows >= spec.expectQueue) break
|
|
427
|
-
if (last.bar && !last.expanded) await evalIn(`document.querySelector('.home2-queue-bar')?.click()`)
|
|
428
|
-
if (Date.now() >= deadline) {
|
|
429
|
-
say(false, `${name}/${theme}: the queue panel never showed ${spec.expectQueue} rows in 20s — `
|
|
430
|
-
+ (!last.bar ? 'the queue BAR never mounted, so no click was ever possible'
|
|
431
|
-
: !last.expanded ? 'the bar mounted but never reported aria-expanded=true, so the panel stayed shut'
|
|
432
|
-
: `the panel WAS open and held ${last.rows} rows`))
|
|
433
|
-
break
|
|
434
|
-
}
|
|
435
|
-
await new Promise((r) => setTimeout(r, 100))
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
const out = await evalIn(PROBE)
|
|
440
|
-
if (!out || out.fatal) { say(false, `${name}/${theme}: ${out?.fatal ?? 'no probe result'}`); continue }
|
|
441
|
-
|
|
442
|
-
say(out.theme === theme, `${name}/${theme}: theme applied (${out.theme})`)
|
|
443
|
-
say(out.cards === spec.expectCards, `${name}/${theme}: ${out.cards} cards (expected ${spec.expectCards})`)
|
|
444
|
-
say(out.queueRows === spec.expectQueue, `${name}/${theme}: ${out.queueRows} queue rows (expected ${spec.expectQueue})`)
|
|
445
|
-
say(out.pips === spec.expectFirstCardPips, `${name}/${theme}: first card has ${out.pips} pips (expected ${spec.expectFirstCardPips})`)
|
|
446
|
-
|
|
447
|
-
// STOP APPEARS ONLY WHERE IT CAN DO SOMETHING. A failed or stopped run is terminal; a button on it
|
|
448
|
-
// would be a control that cannot act.
|
|
449
|
-
say(out.stops === spec.expectStops, `${name}/${theme}: ${out.stops} Stop buttons (expected ${spec.expectStops})`)
|
|
450
|
-
say(out.cancels === spec.expectQueue, `${name}/${theme}: every queued row can be cancelled (${out.cancels}/${spec.expectQueue})`)
|
|
451
|
-
|
|
452
|
-
// THE ORDINALS ARE DENSE, 1..N. A gap would be this account being told how much work other tenants
|
|
453
|
-
// have queued ahead of it.
|
|
454
|
-
if (spec.expectQueue) {
|
|
455
|
-
const want = Array.from({ length: spec.expectQueue }, (_, i) => String(i + 1))
|
|
456
|
-
say(JSON.stringify(out.ordinals) === JSON.stringify(want),
|
|
457
|
-
`${name}/${theme}: ordinals ${JSON.stringify(out.ordinals)} (expected ${JSON.stringify(want)})`)
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
// THE CHIP SAYS SOMETHING. The card renders the wire's `productName` verbatim, so an empty chip now
|
|
461
|
-
// means the SERVICE sent no name — which looks like a design choice rather than a defect, and shipped
|
|
462
|
-
// as one for as long as the browser held its own switch listing only the retired ladder.
|
|
463
|
-
if (spec.expectCards) say(out.depthText.length > 0, `${name}/${theme}: the card names its search ("${out.depthText}")`)
|
|
464
|
-
// AND IT SAYS NO RUNG. "Depth 4" / "Stage 1" are internal; a client screen must never carry either.
|
|
465
|
-
if (spec.expectCards) say(!/\b(Depth|Stage)\s*\d/i.test(out.depthText),
|
|
466
|
-
`${name}/${theme}: the chip carries no depth or stage number ("${out.depthText}")`)
|
|
467
|
-
// THE ONE A STRING TEST CANNOT SEE.
|
|
468
|
-
say(out.depthClipped === 0, `${name}/${theme}: no depth label is clipped (${out.depthClipped} clipped)`)
|
|
469
|
-
say(out.sidewaysOverflow === 0, `${name}/${theme}: no sideways scroll (${out.sidewaysOverflow}px)`)
|
|
470
|
-
say(out.untaggedMarks === 0, `${name}/${theme}: every mark and owner is blurrable (${out.untaggedMarks} untagged)`)
|
|
471
|
-
if (out.newOnBandRow !== null) {
|
|
472
|
-
say(out.newOnBandRow === true, `${name}/${theme}: New clearance stays on the section-header row`)
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
if (spec.expectNotice) {
|
|
476
|
-
say(spec.expectNotice.test(out.notice), `${name}/${theme}: the fault is stated ("${out.notice.slice(0, 48)}")`)
|
|
477
|
-
} else {
|
|
478
|
-
say(out.notice === '', `${name}/${theme}: no fault notice where there is no fault`)
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
// HOME NEVER RE-LISTS THE ARCHIVE: one finished line, and a way into Clearances.
|
|
482
|
-
const answered = spec.runs.some((r) => r.state === 'delivered') && !spec.holdRunsMs && !spec.status
|
|
483
|
-
say(out.lastFinished === answered, `${name}/${theme}: the finished tail is ${answered ? 'one line' : 'absent'}`)
|
|
484
|
-
if (answered) say(out.allClearances === 1, `${name}/${theme}: exactly one way into Clearances (${out.allClearances})`)
|
|
485
|
-
|
|
486
|
-
if (spec.expectLimits === false) {
|
|
487
|
-
say(out.limits === '', `${name}/${theme}: no allowance line where there is no single allowance ("${out.limits.slice(0, 40)}")`)
|
|
488
|
-
} else {
|
|
489
|
-
say(/runs? used today|No daily cap/.test(out.limits),
|
|
490
|
-
`${name}/${theme}: the allowance line states a real allowance ("${out.limits.slice(0, 44)}")`)
|
|
491
|
-
}
|
|
492
|
-
if (spec.expectCapNote) {
|
|
493
|
-
say(spec.expectCapNote.test(out.capNote), `${name}/${theme}: the cap comes from the server ("${out.capNote}")`)
|
|
494
|
-
}
|
|
495
|
-
if (spec.expectFirstRun) say(out.firstRun && out.cards === 0, `${name}/${theme}: first-run panel, no empty card slots`)
|
|
496
|
-
|
|
497
|
-
// The top bar names the SCOPE. Home is account-scoped, so it names the account — never one brand
|
|
498
|
-
// owner over a screen that is showing several.
|
|
499
|
-
const wantTitle = spec.expectTitle ?? 'Zephyr Beverages'
|
|
500
|
-
say(out.title === wantTitle, `${name}/${theme}: top bar reads "${out.title}" (expected "${wantTitle}")`)
|
|
501
|
-
const wantAccount = spec.expectAccount !== false
|
|
502
|
-
say(out.accountLabelled === wantAccount,
|
|
503
|
-
`${name}/${theme}: Account ${wantAccount ? 'is still labelled' : 'is absent — a firm has no single account to name'}`)
|
|
504
|
-
// The switcher belongs INSIDE the nav, as the header of the group it governs.
|
|
505
|
-
if (spec.accounts && spec.accounts.length > 1) {
|
|
506
|
-
say(out.switcherInNav, `${name}/${theme}: the brand-owner switcher labels its nav group`)
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
if (shotDir) {
|
|
510
|
-
const shot = await cmd('Page.captureScreenshot', { format: 'png', captureBeyondViewport: true })
|
|
511
|
-
const data = shot.result?.result?.data ?? shot.result?.data
|
|
512
|
-
if (data) writeFileSync(join(shotDir, `home-${name}-${theme}.png`), Buffer.from(data, 'base64'))
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// — SIGNAL THE GROUP, NOT THE PROCESS. `chrome.kill` reaches only the process spawned here;
|
|
518
|
-
// its renderer and GPU children survive and keep writing the profile directory, so the rmSync below
|
|
519
|
-
// races them. Here that loss is SILENT — the rmSync is wrapped — which is why this file never failed
|
|
520
|
-
// CI the way render-check.mjs did, and instead leaked a temp profile and stray processes per run.
|
|
521
|
-
try { process.kill(-chrome.pid, 'SIGKILL') }
|
|
522
|
-
catch { try { chrome.kill('SIGKILL') } catch { /* already gone */ } }
|
|
523
|
-
server.close()
|
|
524
|
-
try { rmSync(userDir, { recursive: true, force: true }) } catch { /* best effort */ }
|
|
525
|
-
console.log(failures ? `\n${failures} failed` : '\nall states drew correctly, in both themes')
|
|
526
|
-
process.exit(failures ? 1 : 0)
|