@gfdelarue/testkit 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +752 -462
- package/bin/testkit-windows-owner-arm64.exe +0 -0
- package/bin/testkit-windows-owner-x64.exe +0 -0
- package/dist/app/bugs/categories.js +1 -1
- package/dist/app/bugs/ci-report.js +2 -2
- package/dist/app/bugs/ci-summary.js +3 -3
- package/dist/app/bugs/draft.js +4 -4
- package/dist/app/bugs/facts.js +2 -2
- package/dist/app/bugs/file.js +1 -1
- package/dist/app/bugs/gate.js +1 -1
- package/dist/app/bugs/guide.js +3 -3
- package/dist/app/bugs/issue.js +4 -4
- package/dist/app/bugs/known-failures.js +1 -1
- package/dist/app/bugs/record.js +2 -2
- package/dist/app/bugs/run-reading.js +1 -1
- package/dist/app/bugs/supplied-reproduce.js +1 -0
- package/dist/app/campaigns/campaign.js +1 -1
- package/dist/app/cleanup/index.js +1 -1
- package/dist/app/db-schema/prepare.js +1 -1
- package/dist/app/destroy/index.js +1 -1
- package/dist/app/discover/index.js +2 -2
- package/dist/app/doctor/index.js +1 -1
- package/dist/app/environments/config-driven.js +1 -0
- package/dist/app/environments/environment-file.js +1 -0
- package/dist/app/environments/file-setup.js +1 -0
- package/dist/app/environments/routing.js +1 -0
- package/dist/app/environments/static-values.js +1 -0
- package/dist/app/environments/supplied-input.js +1 -0
- package/dist/app/environments/supplied.js +1 -0
- package/dist/app/environments/task-databases.js +2 -0
- package/dist/app/file-selection.js +1 -1
- package/dist/app/inspect/artifacts.js +1 -1
- package/dist/app/inspect/index.js +1 -1
- package/dist/app/lint/index.js +1 -1
- package/dist/app/lint/native.js +1 -1
- package/dist/app/lint/options.js +1 -1
- package/dist/app/lint/rules/data.js +1 -1
- package/dist/app/lint/rules/engine-imports.js +1 -1
- package/dist/app/lint/rules/syntax.js +1 -1
- package/dist/app/lint/rules/unit.js +1 -1
- package/dist/app/lint/shared.js +1 -1
- package/dist/app/package-inspection.js +1 -1
- package/dist/app/reports/files.js +1 -0
- package/dist/app/reports/prepare.js +2 -0
- package/dist/app/reports/publish.js +1 -0
- package/dist/app/run/caller-redaction.js +1 -0
- package/dist/app/run/engine-evidence-persistence.js +1 -1
- package/dist/app/run/engine-execution-failures.js +1 -1
- package/dist/app/run/engine-execution-reporting.js +1 -1
- package/dist/app/run/engine-execution.js +1 -1
- package/dist/app/run/engine-orchestration.js +1 -1
- package/dist/app/run/environment.js +1 -0
- package/dist/app/run/failure-details.js +1 -1
- package/dist/app/run/live-run.js +1 -1
- package/dist/app/run/orchestrator.js +1 -1
- package/dist/app/run/planning.js +1 -1
- package/dist/app/run/request.js +1 -1
- package/dist/app/run/results.js +1 -1
- package/dist/app/run/run-events.js +1 -1
- package/dist/app/run/run-finalization.js +1 -1
- package/dist/app/run/runtime-fixtures.js +1 -1
- package/dist/app/run/scheduler/estimates.js +1 -1
- package/dist/app/run/scheduler/identity.js +1 -1
- package/dist/app/run/scheduler/index.js +1 -1
- package/dist/app/run/scheduler/locks.js +1 -0
- package/dist/app/run/selection.js +1 -1
- package/dist/app/run/setup/runtime-node-setup-protocol.js +1 -1
- package/dist/app/run/setup/runtime-node-setup-worker.js +1 -1
- package/dist/app/run/setup/runtime-node-setup.js +2 -2
- package/dist/app/run/task-batches.js +1 -1
- package/dist/app/run/task-leases.js +1 -0
- package/dist/app/run/worker-loop.js +1 -1
- package/dist/app/status/runs.js +1 -1
- package/dist/app/tracker/index.js +1 -1
- package/dist/app/typecheck/index.js +4 -4
- package/dist/cli/command-catalog.js +1 -1
- package/dist/cli/command-flags.js +1 -1
- package/dist/cli/command-registry.js +1 -1
- package/dist/cli/commands/artifacts.js +2 -2
- package/dist/cli/commands/bug/file.js +2 -2
- package/dist/cli/commands/bug/record.js +2 -2
- package/dist/cli/commands/discover.js +1 -1
- package/dist/cli/commands/report/prepare.js +5 -0
- package/dist/cli/commands/report/publish.js +2 -0
- package/dist/cli/commands/run.js +2 -2
- package/dist/cli/commands/typecheck.js +1 -1
- package/dist/cli/commands/workspace.js +1 -1
- package/dist/cli/framework/errors.js +1 -1
- package/dist/cli/framework/execute.js +7 -6
- package/dist/cli/framework/parser.js +1 -1
- package/dist/cli/json-errors.js +1 -1
- package/dist/cli/operations/run/operation.js +2 -2
- package/dist/cli/renderers/bug/text.js +1 -1
- package/dist/cli/renderers/discover/report.js +1 -1
- package/dist/cli/renderers/doctor/text.js +1 -1
- package/dist/cli/renderers/run/events.js +2 -2
- package/dist/cli/renderers/run/formatting.js +1 -1
- package/dist/cli/renderers/run/status.js +1 -1
- package/dist/cli/renderers/run/text-reporter.js +24 -22
- package/dist/cli/terminal/colors.js +1 -1
- package/dist/cli/terminal/layout.js +2 -2
- package/dist/config/authoring/http-methods.js +1 -1
- package/dist/config/authoring/index.js +1 -1
- package/dist/config/authoring/preset-env.js +1 -1
- package/dist/config/loader/config-loader.js +1 -1
- package/dist/config/loader/database.js +1 -1
- package/dist/config/loader/decode-execution.js +1 -1
- package/dist/config/loader/dependencies.js +1 -1
- package/dist/config/loader/discover-tests.js +1 -1
- package/dist/config/loader/discovery-summary.js +1 -1
- package/dist/config/loader/discovery.js +2 -2
- package/dist/config/loader/env.js +1 -1
- package/dist/config/loader/execution-model.js +1 -1
- package/dist/config/loader/file-metadata.js +1 -1
- package/dist/config/loader/groups.js +1 -0
- package/dist/config/loader/index.js +1 -1
- package/dist/config/loader/load.js +1 -1
- package/dist/config/loader/managed-configs.js +1 -1
- package/dist/config/loader/owned-discovery.js +1 -0
- package/dist/config/loader/path-policy.js +1 -1
- package/dist/config/loader/runtime-isolation.js +1 -1
- package/dist/config/loader/runtime.js +1 -1
- package/dist/config/loader/skip-config.js +1 -1
- package/dist/config/loader/task-policy.js +1 -0
- package/dist/config/loader/test-selection.js +1 -1
- package/dist/config/loader/validation.js +1 -1
- package/dist/database/activity-gate.js +1 -1
- package/dist/database/admin.js +2 -2
- package/dist/database/bindings.js +1 -0
- package/dist/database/cleanup.js +1 -1
- package/dist/database/docker-metadata.js +3 -3
- package/dist/database/docker.js +3 -3
- package/dist/database/index.js +1 -1
- package/dist/database/lifecycle-cleanup.js +1 -1
- package/dist/database/local-postgres.js +1 -1
- package/dist/database/naming.js +1 -1
- package/dist/database/postgres/connection-check.js +1 -0
- package/dist/database/postgres/protocol.js +2 -0
- package/dist/database/schema-operations.js +1 -1
- package/dist/database/schema-source.js +3 -3
- package/dist/database/source-schema-env.js +1 -0
- package/dist/database/source-url.js +2 -2
- package/dist/database/state-files.js +1 -1
- package/dist/database/state.js +1 -1
- package/dist/database/steps.js +3 -3
- package/dist/domain/file-timeout.js +1 -1
- package/dist/domain/identifiers.js +1 -1
- package/dist/domain/operation-display.js +1 -1
- package/dist/domain/retired-test-types.js +1 -0
- package/dist/domain/runtime-isolation-contract.js +1 -1
- package/dist/domain/suite-selection.js +1 -1
- package/dist/domain/test-outcomes.js +1 -1
- package/dist/domain/test-types.js +1 -1
- package/dist/engines/adapters/evidence-files.js +1 -1
- package/dist/engines/adapters/evidence-identity.js +1 -1
- package/dist/engines/adapters/execution.js +1 -1
- package/dist/engines/adapters/json-bounds.js +2 -0
- package/dist/engines/adapters/native-report.js +1 -1
- package/dist/engines/api/execution-scope.js +1 -1
- package/dist/engines/api/execution.js +1 -1
- package/dist/engines/api/index.js +1 -1
- package/dist/engines/api/runtime-artifact.js +1 -1
- package/dist/engines/bundle-cache.js +1 -1
- package/dist/engines/catalog.js +1 -1
- package/dist/engines/contracts/environment-values.js +1 -0
- package/dist/engines/contracts/fixture-manifest.js +1 -1
- package/dist/engines/definitions.js +1 -1
- package/dist/engines/environment/handles.js +1 -0
- package/dist/engines/environment/index.js +1 -0
- package/dist/engines/factory.js +1 -1
- package/dist/engines/installations/node-vitest.js +1 -1
- package/dist/engines/installations/package-resolution.js +1 -1
- package/dist/engines/installations/playwright-resolution-child.js +1 -1
- package/dist/engines/installations/playwright.js +1 -1
- package/dist/engines/managed-module-resolution-policy-input.js +1 -1
- package/dist/engines/managed-module-resolution-policy.js +1 -1
- package/dist/engines/managed-module-resolution.js +2 -2
- package/dist/engines/manager.js +1 -1
- package/dist/engines/node-vitest/adapter/adapter.js +1 -1
- package/dist/engines/node-vitest/adapter/driver.js +2 -0
- package/dist/engines/node-vitest/adapter/evidence.js +2 -2
- package/dist/engines/node-vitest/adapter/failure-details.js +4 -2
- package/dist/engines/node-vitest/adapter/reporter.js +1 -1
- package/dist/engines/node-vitest/adapter/workspace.js +31 -192
- package/dist/engines/node-vitest/inventory/index.js +2 -0
- package/dist/engines/node-vitest/inventory/list-files.js +3 -0
- package/dist/engines/node-vitest/runtime/contract/index.js +1 -1
- package/dist/engines/node-vitest/runtime/data/http.js +1 -1
- package/dist/engines/node-vitest/runtime/data/index.js +1 -1
- package/dist/engines/node-vitest/runtime/data/report.js +5 -6
- package/dist/engines/node-vitest/runtime/data/scenario.js +2 -2
- package/dist/engines/node-vitest/runtime/runtime-input.js +1 -1
- package/dist/engines/node-vitest/selection.js +1 -0
- package/dist/engines/playwright/adapter/adapter.js +1 -1
- package/dist/engines/playwright/adapter/config.js +4 -4
- package/dist/engines/playwright/adapter/evidence-validation.js +1 -1
- package/dist/engines/playwright/adapter/evidence.js +1 -1
- package/dist/engines/playwright/adapter/reporter.js +1 -1
- package/dist/engines/playwright/runtime/config-file.js +1 -1
- package/dist/engines/playwright/runtime/config.js +1 -1
- package/dist/engines/playwright/runtime/runtime-input.js +43 -20
- package/dist/engines/runtime-input-file.js +1 -1
- package/dist/environment/lifecycle-artifacts.js +1 -1
- package/dist/environment/lifecycle-controller.js +1 -1
- package/dist/environment/lifecycle.js +1 -1
- package/dist/environment/ports.js +1 -0
- package/dist/environment/ready-environment.js +1 -1
- package/dist/environment/run-environment.js +1 -1
- package/dist/environment/run-stopping.js +1 -1
- package/dist/environment/runtime-contexts.js +1 -1
- package/dist/environment/runtime-manager.js +1 -1
- package/dist/environment/runtime-planning.js +1 -1
- package/dist/environment/runtime-preparation.js +1 -1
- package/dist/environment/services.js +3 -1
- package/dist/environment/state.js +1 -1
- package/dist/environment/template.js +1 -1
- package/dist/evidence/artifact-config.js +1 -1
- package/dist/evidence/artifact-validation.js +1 -1
- package/dist/evidence/artifacts.js +2 -2
- package/dist/evidence/bundles.js +1 -1
- package/dist/evidence/environment-record.js +1 -0
- package/dist/evidence/index.js +1 -1
- package/dist/evidence/logs.js +2 -2
- package/dist/evidence/operation-timings.js +1 -1
- package/dist/evidence/read-fields.js +1 -1
- package/dist/evidence/read-run.js +1 -1
- package/dist/evidence/reading.js +1 -1
- package/dist/evidence/redaction.js +4 -0
- package/dist/evidence/reporting.js +1 -1
- package/dist/evidence/run-model.js +1 -0
- package/dist/evidence/storage.js +2 -2
- package/dist/evidence/timing.js +1 -1
- package/dist/kernel/error-serialization.js +1 -1
- package/dist/kernel/redaction-targets.js +1 -0
- package/dist/kernel/redaction.js +4 -1
- package/dist/kernel/unknown-values.js +1 -1
- package/dist/process/environment.js +1 -1
- package/dist/process/execa-bundle.json +3 -3
- package/dist/process/files/json-file.js +1 -1
- package/dist/process/files/paths.js +1 -1
- package/dist/process/host/metadata.js +1 -1
- package/dist/process/host/platform.js +1 -1
- package/dist/process/host-process.js +1 -1
- package/dist/process/index.js +1 -1
- package/dist/process/lifecycle-fence.js +1 -1
- package/dist/process/locks.js +4 -4
- package/dist/process/port-listener.js +2 -0
- package/dist/process/process-group.js +1 -1
- package/dist/process/process-identity.js +1 -1
- package/dist/process/process.js +33 -33
- package/dist/process/readiness.js +1 -1
- package/dist/process/ready-deadline.js +1 -0
- package/dist/process/recovery.js +1 -1
- package/dist/process/runs/manifest.js +1 -1
- package/dist/process/runs/ownership.js +1 -1
- package/dist/process/runs/product-state.js +1 -1
- package/dist/process/runs/stop.js +1 -1
- package/dist/process/service-processes.js +1 -1
- package/dist/process/stoppable-settlement.js +1 -0
- package/dist/process/url-redaction.js +1 -0
- package/dist/process/windows-cli-owner.js +3 -3
- package/dist/process/windows-native.js +1 -1
- package/dist/repo/ci-environment.js +1 -1
- package/dist/repo/fingerprint-policy.js +1 -1
- package/dist/repo/managed-git.js +1 -1
- package/dist/repo/physical-tree.js +1 -1
- package/dist/repo/publish-directory.js +3 -0
- package/dist/repo/state.js +4 -4
- package/dist/steps/build-config.js +1 -1
- package/dist/steps/configured-step-testkit-modules.js +1 -1
- package/dist/steps/configured-steps.js +1 -1
- package/dist/steps/environment.js +1 -1
- package/dist/steps/index.js +1 -1
- package/dist/steps/run.js +2 -2
- package/dist/toolchains/archive.js +1 -1
- package/dist/toolchains/index.js +3 -3
- package/dist/toolchains/node-provisioning.js +2 -2
- package/dist/toolchains/semver.js +1 -1
- package/dist/toolchains/vitest/index.js +1 -1
- package/dist/tracker/redaction.js +1 -2
- package/dist/{config/runtime/build-assets.d.ts → types/config-build-assets.d.ts} +5 -3
- package/dist/{database/steps.d.ts → types/config-database-steps.d.ts} +7 -7
- package/dist/{config/runtime/next-runtime-tsconfig.d.ts → types/config-next-runtime-tsconfig.d.ts} +5 -3
- package/dist/types/config.d.ts +501 -0
- package/dist/types/drizzle.d.ts +13 -0
- package/dist/{config/runtime/env/index.d.ts → types/env.d.ts} +22 -20
- package/dist/types/environment.d.ts +40 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/node-vitest-contract.d.ts +75 -0
- package/dist/types/node-vitest-data.d.ts +407 -0
- package/dist/types/playwright.d.ts +130 -0
- package/dist/types/tooling-vitest.d.ts +13 -0
- package/dist/types/workspace.d.ts +617 -0
- package/docs/bug-records.md +83 -81
- package/docs/engines.md +213 -0
- package/docs/test-types.md +35 -33
- package/package.json +22 -29
- package/testkit-config-schema.md +403 -171
- package/dist/app/bugs/areas.d.ts +0 -38
- package/dist/app/bugs/assessment.d.ts +0 -9
- package/dist/app/bugs/categories.d.ts +0 -41
- package/dist/app/bugs/ci-report.d.ts +0 -21
- package/dist/app/bugs/ci-summary.d.ts +0 -13
- package/dist/app/bugs/draft.d.ts +0 -70
- package/dist/app/bugs/facts.d.ts +0 -48
- package/dist/app/bugs/file.d.ts +0 -45
- package/dist/app/bugs/gate.d.ts +0 -22
- package/dist/app/bugs/guide.d.ts +0 -20
- package/dist/app/bugs/issue.d.ts +0 -18
- package/dist/app/bugs/known-failures.d.ts +0 -49
- package/dist/app/bugs/record.d.ts +0 -14
- package/dist/app/bugs/run-reading.d.ts +0 -51
- package/dist/app/bugs/store.d.ts +0 -34
- package/dist/app/campaigns/brief.d.ts +0 -7
- package/dist/app/campaigns/campaign.d.ts +0 -14
- package/dist/app/campaigns/index.d.ts +0 -38
- package/dist/app/campaigns/store.d.ts +0 -5
- package/dist/app/campaigns/summary.d.ts +0 -13
- package/dist/app/cleanup/index.d.ts +0 -52
- package/dist/app/db-schema/prepare.d.ts +0 -11
- package/dist/app/db-schema/refresh.d.ts +0 -17
- package/dist/app/db-schema/verify.d.ts +0 -11
- package/dist/app/destroy/index.d.ts +0 -16
- package/dist/app/discover/index.d.ts +0 -8
- package/dist/app/doctor/index.d.ts +0 -17
- package/dist/app/file-selection.d.ts +0 -1
- package/dist/app/inspect/artifacts.d.ts +0 -30
- package/dist/app/inspect/index.d.ts +0 -112
- package/dist/app/lint/index.d.ts +0 -28
- package/dist/app/lint/native.d.ts +0 -10
- package/dist/app/lint/options.d.ts +0 -67
- package/dist/app/lint/policy.d.ts +0 -21
- package/dist/app/lint/rules/data.d.ts +0 -3
- package/dist/app/lint/rules/engine-imports.d.ts +0 -3
- package/dist/app/lint/rules/syntax.d.ts +0 -4
- package/dist/app/lint/rules/unit.d.ts +0 -3
- package/dist/app/lint/shared.d.ts +0 -36
- package/dist/app/package-inspection.d.ts +0 -20
- package/dist/app/run/endpoint-readiness.d.ts +0 -43
- package/dist/app/run/endpoint-readiness.js +0 -1
- package/dist/app/run/engine-evidence-persistence.d.ts +0 -39
- package/dist/app/run/engine-execution-cleanup.d.ts +0 -8
- package/dist/app/run/engine-execution-cleanup.js +0 -1
- package/dist/app/run/engine-execution-failures.d.ts +0 -41
- package/dist/app/run/engine-execution-observer.d.ts +0 -21
- package/dist/app/run/engine-execution-reporting.d.ts +0 -17
- package/dist/app/run/engine-execution.d.ts +0 -63
- package/dist/app/run/engine-failure-stack.d.ts +0 -1
- package/dist/app/run/engine-orchestration.d.ts +0 -49
- package/dist/app/run/failure-details.d.ts +0 -37
- package/dist/app/run/live-run.d.ts +0 -27
- package/dist/app/run/operation-progress.d.ts +0 -13
- package/dist/app/run/orchestrator.d.ts +0 -68
- package/dist/app/run/planning-types.d.ts +0 -68
- package/dist/app/run/planning.d.ts +0 -15
- package/dist/app/run/playwright-configuration.d.ts +0 -2
- package/dist/app/run/playwright-configuration.js +0 -1
- package/dist/app/run/request.d.ts +0 -30
- package/dist/app/run/results.d.ts +0 -161
- package/dist/app/run/run-events.d.ts +0 -144
- package/dist/app/run/run-finalization.d.ts +0 -52
- package/dist/app/run/run-guards.d.ts +0 -3
- package/dist/app/run/runtime-failures.d.ts +0 -18
- package/dist/app/run/runtime-fixtures.d.ts +0 -2
- package/dist/app/run/runtime-task-types.d.ts +0 -20
- package/dist/app/run/scheduler/estimates.d.ts +0 -32
- package/dist/app/run/scheduler/identity.d.ts +0 -9
- package/dist/app/run/scheduler/index.d.ts +0 -124
- package/dist/app/run/scheduler/observations.d.ts +0 -20
- package/dist/app/run/selection.d.ts +0 -10
- package/dist/app/run/setup/runtime-node-setup-errors.d.ts +0 -13
- package/dist/app/run/setup/runtime-node-setup-protocol.d.ts +0 -85
- package/dist/app/run/setup/runtime-node-setup-worker.d.ts +0 -1
- package/dist/app/run/setup/runtime-node-setup.d.ts +0 -48
- package/dist/app/run/task-batches.d.ts +0 -23
- package/dist/app/run/worker-loop.d.ts +0 -57
- package/dist/app/setup/playwright.d.ts +0 -22
- package/dist/app/status/index.d.ts +0 -9
- package/dist/app/status/model.d.ts +0 -29
- package/dist/app/status/runs.d.ts +0 -99
- package/dist/app/stop/index.d.ts +0 -14
- package/dist/app/tracker/index.d.ts +0 -8
- package/dist/app/tracker/remote.d.ts +0 -13
- package/dist/app/tracker/token.d.ts +0 -7
- package/dist/app/typecheck/index.d.ts +0 -63
- package/dist/cli/command-catalog.d.ts +0 -137
- package/dist/cli/command-flags.d.ts +0 -19
- package/dist/cli/command-registry.d.ts +0 -3
- package/dist/cli/commands/artifacts.d.ts +0 -48
- package/dist/cli/commands/bug/file.d.ts +0 -16
- package/dist/cli/commands/bug/guide.d.ts +0 -5
- package/dist/cli/commands/bug/record.d.ts +0 -9
- package/dist/cli/commands/campaign/finish.d.ts +0 -10
- package/dist/cli/commands/campaign/start.d.ts +0 -7
- package/dist/cli/commands/campaign/status.d.ts +0 -13
- package/dist/cli/commands/ci/report.d.ts +0 -15
- package/dist/cli/commands/cleanup.d.ts +0 -13
- package/dist/cli/commands/db/schema/refresh.d.ts +0 -2
- package/dist/cli/commands/db/schema/verify.d.ts +0 -2
- package/dist/cli/commands/destroy.d.ts +0 -9
- package/dist/cli/commands/discover.d.ts +0 -2
- package/dist/cli/commands/doctor.d.ts +0 -2
- package/dist/cli/commands/guard/unsafe-entrypoint.d.ts +0 -2
- package/dist/cli/commands/lint.d.ts +0 -2
- package/dist/cli/commands/run/status.d.ts +0 -5
- package/dist/cli/commands/run/stop.d.ts +0 -7
- package/dist/cli/commands/run.d.ts +0 -9
- package/dist/cli/commands/setup/playwright.d.ts +0 -2
- package/dist/cli/commands/status.d.ts +0 -5
- package/dist/cli/commands/stop.d.ts +0 -12
- package/dist/cli/commands/typecheck.d.ts +0 -2
- package/dist/cli/commands/workspace.d.ts +0 -2
- package/dist/cli/entrypoint.d.ts +0 -1
- package/dist/cli/framework/command.d.ts +0 -21
- package/dist/cli/framework/definitions.d.ts +0 -100
- package/dist/cli/framework/errors.d.ts +0 -6
- package/dist/cli/framework/execute.d.ts +0 -14
- package/dist/cli/framework/help.d.ts +0 -11
- package/dist/cli/framework/index.d.ts +0 -3
- package/dist/cli/framework/parser.d.ts +0 -6
- package/dist/cli/index.d.ts +0 -4
- package/dist/cli/json-errors.d.ts +0 -3
- package/dist/cli/operations/db/schema/refresh/operation.d.ts +0 -7
- package/dist/cli/operations/db/schema/verify/operation.d.ts +0 -7
- package/dist/cli/operations/run/operation.d.ts +0 -24
- package/dist/cli/process-signal.d.ts +0 -1
- package/dist/cli/renderers/bug/text.d.ts +0 -8
- package/dist/cli/renderers/campaign/text.d.ts +0 -2
- package/dist/cli/renderers/ci/text.d.ts +0 -2
- package/dist/cli/renderers/cleanup/format.d.ts +0 -14
- package/dist/cli/renderers/db-schema/text.d.ts +0 -4
- package/dist/cli/renderers/destroy/text.d.ts +0 -4
- package/dist/cli/renderers/discover/report.d.ts +0 -7
- package/dist/cli/renderers/discover/text.d.ts +0 -3
- package/dist/cli/renderers/doctor/text.d.ts +0 -2
- package/dist/cli/renderers/lint/text.d.ts +0 -2
- package/dist/cli/renderers/run/events.d.ts +0 -8
- package/dist/cli/renderers/run/failure.d.ts +0 -8
- package/dist/cli/renderers/run/formatting.d.ts +0 -79
- package/dist/cli/renderers/run/status.d.ts +0 -6
- package/dist/cli/renderers/run/text-reporter.d.ts +0 -19
- package/dist/cli/renderers/status/text.d.ts +0 -2
- package/dist/cli/renderers/stop/text.d.ts +0 -7
- package/dist/cli/renderers/typecheck/text.d.ts +0 -2
- package/dist/cli/terminal/colors.d.ts +0 -10
- package/dist/cli/terminal/layout.d.ts +0 -11
- package/dist/cli/version-drift.d.ts +0 -25
- package/dist/config/authoring/build-config-contract.d.ts +0 -27
- package/dist/config/authoring/configured-step-contract.d.ts +0 -18
- package/dist/config/authoring/http-execution-contract.d.ts +0 -70
- package/dist/config/authoring/http-methods.d.ts +0 -18
- package/dist/config/authoring/index.d.ts +0 -381
- package/dist/config/authoring/preset-env.d.ts +0 -19
- package/dist/config/authoring/runtime.d.ts +0 -64
- package/dist/config/loader/bugs.d.ts +0 -15
- package/dist/config/loader/config-loader.d.ts +0 -9
- package/dist/config/loader/database-materialization.d.ts +0 -19
- package/dist/config/loader/database-roles.d.ts +0 -2
- package/dist/config/loader/database.d.ts +0 -55
- package/dist/config/loader/decode-discovery.d.ts +0 -5
- package/dist/config/loader/decode-execution.d.ts +0 -9
- package/dist/config/loader/dependencies.d.ts +0 -7
- package/dist/config/loader/discover-tests.d.ts +0 -111
- package/dist/config/loader/discovery-summary.d.ts +0 -29
- package/dist/config/loader/discovery.d.ts +0 -54
- package/dist/config/loader/env.d.ts +0 -4
- package/dist/config/loader/execution-model.d.ts +0 -16
- package/dist/config/loader/file-metadata.d.ts +0 -19
- package/dist/config/loader/index.d.ts +0 -10
- package/dist/config/loader/load.d.ts +0 -91
- package/dist/config/loader/managed-configs.d.ts +0 -23
- package/dist/config/loader/path-policy.d.ts +0 -9
- package/dist/config/loader/paths.d.ts +0 -5
- package/dist/config/loader/runtime-isolation.d.ts +0 -44
- package/dist/config/loader/runtime.d.ts +0 -25
- package/dist/config/loader/skip-config.d.ts +0 -44
- package/dist/config/loader/test-selection.d.ts +0 -15
- package/dist/config/loader/validation.d.ts +0 -16
- package/dist/config/loader/values.d.ts +0 -4
- package/dist/config/loader/values.js +0 -1
- package/dist/database/activity-gate.d.ts +0 -22
- package/dist/database/admin.d.ts +0 -31
- package/dist/database/cleanup.d.ts +0 -36
- package/dist/database/configured-steps.d.ts +0 -27
- package/dist/database/constants.d.ts +0 -11
- package/dist/database/docker-metadata.d.ts +0 -3
- package/dist/database/docker.d.ts +0 -65
- package/dist/database/drizzle/index.d.ts +0 -13
- package/dist/database/fingerprint.d.ts +0 -12
- package/dist/database/index.d.ts +0 -39
- package/dist/database/lifecycle-cleanup.d.ts +0 -7
- package/dist/database/local-postgres.d.ts +0 -71
- package/dist/database/naming.d.ts +0 -17
- package/dist/database/postgres/index.d.ts +0 -71
- package/dist/database/progress.d.ts +0 -6
- package/dist/database/roles.d.ts +0 -19
- package/dist/database/runtime-config.d.ts +0 -16
- package/dist/database/runtime-reservations.d.ts +0 -19
- package/dist/database/schema-operations.d.ts +0 -18
- package/dist/database/schema-source.d.ts +0 -96
- package/dist/database/source-refresh-lock.d.ts +0 -8
- package/dist/database/source-url.d.ts +0 -22
- package/dist/database/state-files.d.ts +0 -13
- package/dist/database/state.d.ts +0 -26
- package/dist/database/template-steps.d.ts +0 -39
- package/dist/domain/file-timeout.d.ts +0 -28
- package/dist/domain/identifiers.d.ts +0 -9
- package/dist/domain/operation-display.d.ts +0 -10
- package/dist/domain/operation-reason.d.ts +0 -5
- package/dist/domain/postgres-route.d.ts +0 -4
- package/dist/domain/runtime-identity.d.ts +0 -1
- package/dist/domain/runtime-isolation-contract.d.ts +0 -5
- package/dist/domain/service-name.d.ts +0 -2
- package/dist/domain/suite-selection.d.ts +0 -20
- package/dist/domain/test-outcomes.d.ts +0 -3
- package/dist/domain/test-types.d.ts +0 -16
- package/dist/engines/adapters/evidence-files.d.ts +0 -32
- package/dist/engines/adapters/evidence-identity.d.ts +0 -12
- package/dist/engines/adapters/execution.d.ts +0 -42
- package/dist/engines/adapters/native-report.d.ts +0 -25
- package/dist/engines/adapters/node-startup-cache.d.ts +0 -8
- package/dist/engines/adapters/workspace.d.ts +0 -4
- package/dist/engines/api/capabilities.d.ts +0 -31
- package/dist/engines/api/capabilities.js +0 -1
- package/dist/engines/api/evidence.d.ts +0 -38
- package/dist/engines/api/execution-observer.d.ts +0 -8
- package/dist/engines/api/execution-scope.d.ts +0 -17
- package/dist/engines/api/execution.d.ts +0 -101
- package/dist/engines/api/index.d.ts +0 -5
- package/dist/engines/api/k6-runtime-input.d.ts +0 -26
- package/dist/engines/api/k6-runtime-input.js +0 -1
- package/dist/engines/api/runtime-artifact.d.ts +0 -19
- package/dist/engines/bundle-cache.d.ts +0 -32
- package/dist/engines/catalog.d.ts +0 -27
- package/dist/engines/contracts/fixture-manifest.d.ts +0 -34
- package/dist/engines/contracts/json-bounds.d.ts +0 -36
- package/dist/engines/contracts/json-bounds.js +0 -2
- package/dist/engines/contracts/k6-repository-configuration.d.ts +0 -12
- package/dist/engines/contracts/k6-repository-configuration.js +0 -1
- package/dist/engines/contracts/test-context.d.ts +0 -15
- package/dist/engines/contracts/test-context.js +0 -1
- package/dist/engines/definitions.d.ts +0 -22
- package/dist/engines/factory.d.ts +0 -6
- package/dist/engines/generated-performance.d.ts +0 -1
- package/dist/engines/installation-catalog.d.ts +0 -27
- package/dist/engines/installation-catalog.js +0 -1
- package/dist/engines/installations/k6.d.ts +0 -98
- package/dist/engines/installations/k6.js +0 -1
- package/dist/engines/installations/node-vitest.d.ts +0 -33
- package/dist/engines/installations/package-requirements.d.ts +0 -28
- package/dist/engines/installations/package-resolution.d.ts +0 -51
- package/dist/engines/installations/playwright-resolution-child.d.ts +0 -1
- package/dist/engines/installations/playwright.d.ts +0 -75
- package/dist/engines/installations/types.d.ts +0 -10
- package/dist/engines/k6/adapter/bundle.d.ts +0 -25
- package/dist/engines/k6/adapter/bundle.js +0 -112
- package/dist/engines/k6/adapter/evidence.d.ts +0 -15
- package/dist/engines/k6/adapter/evidence.js +0 -4
- package/dist/engines/k6/adapter/executor.d.ts +0 -13
- package/dist/engines/k6/adapter/executor.js +0 -1
- package/dist/engines/k6/adapter/index.d.ts +0 -1
- package/dist/engines/k6/adapter/index.js +0 -1
- package/dist/engines/k6/adapter/input.d.ts +0 -21
- package/dist/engines/k6/adapter/input.js +0 -1
- package/dist/engines/k6/adapter/native-summary.d.ts +0 -11
- package/dist/engines/k6/adapter/native-summary.js +0 -1
- package/dist/engines/k6/adapter/repository-configuration.d.ts +0 -2
- package/dist/engines/k6/adapter/repository-configuration.js +0 -1
- package/dist/engines/k6/authoring-type-paths.d.ts +0 -3
- package/dist/engines/k6/authoring-type-paths.js +0 -1
- package/dist/engines/k6/runtime/ambient-types/bundle-manifest.json +0 -146
- package/dist/engines/k6/runtime/ambient-types/k6/LICENSE +0 -21
- package/dist/engines/k6/runtime/ambient-types/k6/browser/index.d.ts +0 -6332
- package/dist/engines/k6/runtime/ambient-types/k6/crypto/index.d.ts +0 -218
- package/dist/engines/k6/runtime/ambient-types/k6/data/index.d.ts +0 -16
- package/dist/engines/k6/runtime/ambient-types/k6/encoding/index.d.ts +0 -46
- package/dist/engines/k6/runtime/ambient-types/k6/execution/index.d.ts +0 -127
- package/dist/engines/k6/runtime/ambient-types/k6/experimental/csv/index.d.ts +0 -96
- package/dist/engines/k6/runtime/ambient-types/k6/experimental/fs/index.d.ts +0 -104
- package/dist/engines/k6/runtime/ambient-types/k6/experimental/redis/index.d.ts +0 -821
- package/dist/engines/k6/runtime/ambient-types/k6/experimental/streams/index.d.ts +0 -198
- package/dist/engines/k6/runtime/ambient-types/k6/global.d.ts +0 -83
- package/dist/engines/k6/runtime/ambient-types/k6/html/index.d.ts +0 -1325
- package/dist/engines/k6/runtime/ambient-types/k6/http/index.d.ts +0 -806
- package/dist/engines/k6/runtime/ambient-types/k6/index.d.ts +0 -126
- package/dist/engines/k6/runtime/ambient-types/k6/metrics/index.d.ts +0 -66
- package/dist/engines/k6/runtime/ambient-types/k6/net/grpc/index.d.ts +0 -247
- package/dist/engines/k6/runtime/ambient-types/k6/options/index.d.ts +0 -459
- package/dist/engines/k6/runtime/ambient-types/k6/package.json +0 -79
- package/dist/engines/k6/runtime/ambient-types/k6/secrets/index.d.ts +0 -36
- package/dist/engines/k6/runtime/ambient-types/k6/timers/index.d.ts +0 -47
- package/dist/engines/k6/runtime/ambient-types/k6/websockets/index.d.ts +0 -324
- package/dist/engines/k6/runtime/ambient-types/k6/ws/index.d.ts +0 -283
- package/dist/engines/k6/runtime/ambient-types/xk6-sql/LICENSE +0 -201
- package/dist/engines/k6/runtime/ambient-types/xk6-sql/index.d.ts +0 -397
- package/dist/engines/k6/runtime/ambient-types/xk6-sql/package.json +0 -15
- package/dist/engines/k6/runtime/artifacts.d.ts +0 -2
- package/dist/engines/k6/runtime/artifacts.js +0 -1
- package/dist/engines/k6/runtime/checks.d.ts +0 -17
- package/dist/engines/k6/runtime/checks.js +0 -1
- package/dist/engines/k6/runtime/dal-fixtures.d.ts +0 -24
- package/dist/engines/k6/runtime/dal-fixtures.js +0 -1
- package/dist/engines/k6/runtime/dal-suite.d.ts +0 -24
- package/dist/engines/k6/runtime/dal-suite.js +0 -1
- package/dist/engines/k6/runtime/dal.d.ts +0 -10
- package/dist/engines/k6/runtime/dal.js +0 -1
- package/dist/engines/k6/runtime/fixtures.d.ts +0 -3
- package/dist/engines/k6/runtime/fixtures.js +0 -1
- package/dist/engines/k6/runtime/http-assertions.d.ts +0 -19
- package/dist/engines/k6/runtime/http-assertions.js +0 -1
- package/dist/engines/k6/runtime/http-checks.d.ts +0 -19
- package/dist/engines/k6/runtime/http-checks.js +0 -1
- package/dist/engines/k6/runtime/http-suite-runtime.d.ts +0 -103
- package/dist/engines/k6/runtime/http-suite-runtime.js +0 -1
- package/dist/engines/k6/runtime/http.d.ts +0 -15
- package/dist/engines/k6/runtime/http.js +0 -1
- package/dist/engines/k6/runtime/index.d.ts +0 -11
- package/dist/engines/k6/runtime/index.js +0 -1
- package/dist/engines/k6/runtime/input.d.ts +0 -3
- package/dist/engines/k6/runtime/input.js +0 -1
- package/dist/engines/k6/runtime/k6-repository-configuration.d.ts +0 -9
- package/dist/engines/k6/runtime/k6-repository-configuration.js +0 -1
- package/dist/engines/k6/runtime/node-setup.d.ts +0 -13
- package/dist/engines/k6/runtime/node-setup.js +0 -1
- package/dist/engines/k6/runtime/runtime-globals.d.ts +0 -10
- package/dist/engines/k6/runtime/runtime.d.ts +0 -54
- package/dist/engines/k6/runtime/runtime.js +0 -1
- package/dist/engines/k6/runtime/shared/assertion-details.d.ts +0 -19
- package/dist/engines/k6/runtime/shared/assertion-details.js +0 -2
- package/dist/engines/k6/runtime/shared/db-normalization.d.ts +0 -19
- package/dist/engines/k6/runtime/shared/db-normalization.js +0 -1
- package/dist/engines/k6/runtime/shared/error-body.d.ts +0 -3
- package/dist/engines/k6/runtime/shared/error-body.js +0 -1
- package/dist/engines/k6/runtime/shared/file-data.d.ts +0 -1
- package/dist/engines/k6/runtime/shared/file-data.js +0 -1
- package/dist/engines/k6/runtime/shared/fixture-engine.d.ts +0 -8
- package/dist/engines/k6/runtime/shared/fixture-engine.js +0 -2
- package/dist/engines/k6/runtime/shared/http-check-plan.d.ts +0 -29
- package/dist/engines/k6/runtime/shared/http-check-plan.js +0 -1
- package/dist/engines/k6/runtime/shared/http-parsing.d.ts +0 -10
- package/dist/engines/k6/runtime/shared/http-parsing.js +0 -3
- package/dist/engines/k6/runtime/shared/ordering.d.ts +0 -2
- package/dist/engines/k6/runtime/shared/ordering.js +0 -1
- package/dist/engines/k6/runtime/shared/properties.d.ts +0 -1
- package/dist/engines/k6/runtime/shared/properties.js +0 -1
- package/dist/engines/k6/runtime/suite.d.ts +0 -4
- package/dist/engines/k6/runtime/suite.js +0 -1
- package/dist/engines/k6/runtime/types.d.ts +0 -244
- package/dist/engines/k6/runtime/types.js +0 -1
- package/dist/engines/k6/runtime/xk6-sql-driver-postgres.d.ts +0 -7
- package/dist/engines/k6/runtime/xk6-sql-driver-postgres.js +0 -1
- package/dist/engines/managed-module-resolution-policy-input.d.ts +0 -9
- package/dist/engines/managed-module-resolution-policy.d.ts +0 -25
- package/dist/engines/managed-module-resolution.d.ts +0 -13
- package/dist/engines/manager.d.ts +0 -25
- package/dist/engines/node-vitest/adapter/adapter.d.ts +0 -16
- package/dist/engines/node-vitest/adapter/consumer-typescript-paths.d.ts +0 -17
- package/dist/engines/node-vitest/adapter/consumer-typescript-paths.js +0 -3
- package/dist/engines/node-vitest/adapter/evidence.d.ts +0 -33
- package/dist/engines/node-vitest/adapter/failure-details.d.ts +0 -3
- package/dist/engines/node-vitest/adapter/index.d.ts +0 -1
- package/dist/engines/node-vitest/adapter/reporter.d.ts +0 -7
- package/dist/engines/node-vitest/adapter/resolution.d.ts +0 -12
- package/dist/engines/node-vitest/adapter/resolution.js +0 -1
- package/dist/engines/node-vitest/adapter/workspace.d.ts +0 -19
- package/dist/engines/node-vitest/runtime/contract/index.d.ts +0 -64
- package/dist/engines/node-vitest/runtime/data/http.d.ts +0 -4
- package/dist/engines/node-vitest/runtime/data/index.d.ts +0 -8
- package/dist/engines/node-vitest/runtime/data/primitives.d.ts +0 -1
- package/dist/engines/node-vitest/runtime/data/report.d.ts +0 -3
- package/dist/engines/node-vitest/runtime/data/runner.d.ts +0 -4
- package/dist/engines/node-vitest/runtime/data/scenario.d.ts +0 -12
- package/dist/engines/node-vitest/runtime/data/types.d.ts +0 -412
- package/dist/engines/node-vitest/runtime/runtime-input.d.ts +0 -64
- package/dist/engines/playwright/adapter/adapter.d.ts +0 -18
- package/dist/engines/playwright/adapter/attachments.d.ts +0 -26
- package/dist/engines/playwright/adapter/config.d.ts +0 -45
- package/dist/engines/playwright/adapter/evidence-validation.d.ts +0 -12
- package/dist/engines/playwright/adapter/evidence.d.ts +0 -32
- package/dist/engines/playwright/adapter/failure-details.d.ts +0 -2
- package/dist/engines/playwright/adapter/index.d.ts +0 -3
- package/dist/engines/playwright/adapter/reporter.d.ts +0 -12
- package/dist/engines/playwright/runtime/config-file.d.ts +0 -2
- package/dist/engines/playwright/runtime/config.d.ts +0 -24
- package/dist/engines/playwright/runtime/index.d.ts +0 -4
- package/dist/engines/playwright/runtime/runtime-input.d.ts +0 -36
- package/dist/engines/playwright/runtime/sandbox.d.ts +0 -84
- package/dist/engines/runtime-input-file.d.ts +0 -27
- package/dist/environment/lifecycle-artifacts.d.ts +0 -7
- package/dist/environment/lifecycle-controller.d.ts +0 -70
- package/dist/environment/lifecycle.d.ts +0 -29
- package/dist/environment/maintenance.d.ts +0 -68
- package/dist/environment/planning-types.d.ts +0 -35
- package/dist/environment/readiness.d.ts +0 -12
- package/dist/environment/readiness.js +0 -1
- package/dist/environment/ready-environment.d.ts +0 -19
- package/dist/environment/run-environment.d.ts +0 -38
- package/dist/environment/run-stopping.d.ts +0 -13
- package/dist/environment/runtime-contexts.d.ts +0 -33
- package/dist/environment/runtime-manager.d.ts +0 -95
- package/dist/environment/runtime-planning.d.ts +0 -16
- package/dist/environment/runtime-preparation.d.ts +0 -30
- package/dist/environment/runtime-service.d.ts +0 -18
- package/dist/environment/services.d.ts +0 -48
- package/dist/environment/state.d.ts +0 -18
- package/dist/environment/status-runtime.d.ts +0 -53
- package/dist/environment/template.d.ts +0 -180
- package/dist/evidence/artifact-config.d.ts +0 -14
- package/dist/evidence/artifact-validation.d.ts +0 -5
- package/dist/evidence/artifacts.d.ts +0 -75
- package/dist/evidence/bundles.d.ts +0 -27
- package/dist/evidence/ci-provenance.d.ts +0 -9
- package/dist/evidence/contracts.d.ts +0 -154
- package/dist/evidence/file-evidence.d.ts +0 -23
- package/dist/evidence/finalization.d.ts +0 -9
- package/dist/evidence/index.d.ts +0 -8
- package/dist/evidence/logs.d.ts +0 -31
- package/dist/evidence/operation-timings.d.ts +0 -60
- package/dist/evidence/read-bundle.d.ts +0 -4
- package/dist/evidence/read-fields.d.ts +0 -22
- package/dist/evidence/read-provenance.d.ts +0 -2
- package/dist/evidence/read-redaction.d.ts +0 -2
- package/dist/evidence/read-retention.d.ts +0 -2
- package/dist/evidence/read-run.d.ts +0 -2
- package/dist/evidence/reading.d.ts +0 -28
- package/dist/evidence/reporting-types.d.ts +0 -330
- package/dist/evidence/reporting.d.ts +0 -3
- package/dist/evidence/secure-file-copy.d.ts +0 -24
- package/dist/evidence/setup-progress.d.ts +0 -63
- package/dist/evidence/step-output.d.ts +0 -16
- package/dist/evidence/storage-inventory.d.ts +0 -27
- package/dist/evidence/storage.d.ts +0 -27
- package/dist/evidence/timing.d.ts +0 -23
- package/dist/file.d.ts +0 -11
- package/dist/index.d.ts +0 -4
- package/dist/kernel/error-serialization.d.ts +0 -38
- package/dist/kernel/redaction.d.ts +0 -2
- package/dist/kernel/unknown-values.d.ts +0 -6
- package/dist/kernel/work-metrics.d.ts +0 -6
- package/dist/process/capture-output.d.ts +0 -7
- package/dist/process/command-shell.d.ts +0 -1
- package/dist/process/environment-overlay.d.ts +0 -17
- package/dist/process/environment.d.ts +0 -33
- package/dist/process/files/contained-path.d.ts +0 -8
- package/dist/process/files/directory-status.d.ts +0 -14
- package/dist/process/files/dotenv.d.ts +0 -2
- package/dist/process/files/file-snapshot.d.ts +0 -34
- package/dist/process/files/json-file.d.ts +0 -12
- package/dist/process/files/paths.d.ts +0 -1
- package/dist/process/files/product-dir.d.ts +0 -1
- package/dist/process/files/temp-dir.d.ts +0 -11
- package/dist/process/host/metadata.d.ts +0 -6
- package/dist/process/host/platform.d.ts +0 -57
- package/dist/process/host-command.d.ts +0 -4
- package/dist/process/host-inspection-command.d.ts +0 -13
- package/dist/process/host-process.d.ts +0 -19
- package/dist/process/index.d.ts +0 -9
- package/dist/process/lifecycle-fence.d.ts +0 -11
- package/dist/process/locks.d.ts +0 -28
- package/dist/process/process-contracts.d.ts +0 -78
- package/dist/process/process-group.d.ts +0 -12
- package/dist/process/process-identity.d.ts +0 -27
- package/dist/process/process-limits.d.ts +0 -6
- package/dist/process/process.d.ts +0 -12
- package/dist/process/readiness.d.ts +0 -37
- package/dist/process/recovery.d.ts +0 -3
- package/dist/process/runs/inspection.d.ts +0 -5
- package/dist/process/runs/manifest.d.ts +0 -86
- package/dist/process/runs/ownership.d.ts +0 -11
- package/dist/process/runs/product-state.d.ts +0 -2
- package/dist/process/runs/schema.d.ts +0 -3
- package/dist/process/runs/stop.d.ts +0 -19
- package/dist/process/runtime-socket.d.ts +0 -4
- package/dist/process/service-processes.d.ts +0 -13
- package/dist/process/shutdown.d.ts +0 -10
- package/dist/process/windows-cli-owner.d.ts +0 -2
- package/dist/process/windows-native.d.ts +0 -6
- package/dist/process/windows-process-identity.d.ts +0 -4
- package/dist/repo/ci-environment.d.ts +0 -7
- package/dist/repo/fingerprint-policy.d.ts +0 -15
- package/dist/repo/git-path.d.ts +0 -2
- package/dist/repo/history.d.ts +0 -17
- package/dist/repo/managed-git.d.ts +0 -10
- package/dist/repo/metadata.d.ts +0 -3
- package/dist/repo/physical-tree.d.ts +0 -37
- package/dist/repo/remote.d.ts +0 -6
- package/dist/repo/state.d.ts +0 -26
- package/dist/repo/tree-listing.d.ts +0 -10
- package/dist/steps/build-config.d.ts +0 -35
- package/dist/steps/configured-step-testkit-modules.d.ts +0 -19
- package/dist/steps/configured-steps.d.ts +0 -51
- package/dist/steps/environment.d.ts +0 -84
- package/dist/steps/index.d.ts +0 -2
- package/dist/steps/module-runner.d.ts +0 -1
- package/dist/steps/run.d.ts +0 -36
- package/dist/toolchains/archive.d.ts +0 -53
- package/dist/toolchains/esbuild.d.ts +0 -9
- package/dist/toolchains/host-node-support.d.ts +0 -3
- package/dist/toolchains/index.d.ts +0 -114
- package/dist/toolchains/managed-node-releases.d.ts +0 -28
- package/dist/toolchains/node-cache.d.ts +0 -20
- package/dist/toolchains/node-integrity.d.ts +0 -18
- package/dist/toolchains/node-provisioning.d.ts +0 -29
- package/dist/toolchains/semver.d.ts +0 -13
- package/dist/toolchains/shared-operation.d.ts +0 -11
- package/dist/toolchains/timeouts.d.ts +0 -1
- package/dist/toolchains/vitest/index.d.ts +0 -13
- package/dist/tracker/gitea.d.ts +0 -14
- package/dist/tracker/github.d.ts +0 -14
- package/dist/tracker/http.d.ts +0 -33
- package/dist/tracker/index.d.ts +0 -4
- package/dist/tracker/redaction.d.ts +0 -4
- package/dist/tracker/requests.d.ts +0 -17
- package/dist/tracker/responses.d.ts +0 -24
- package/dist/tracker/types.d.ts +0 -51
- package/docs/engine-architecture.md +0 -654
- /package/dist/engines/{k6/runtime/runtime-globals.js → api/profiles.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import{buildRuntimeIds as L}from"../domain/runtime-identity.js";import{formatError as h}from"../kernel/error-serialization.js";import{cleanupRuntimeInstanceContext as M,createRuntimeInstanceContext as S,ensureRuntimeInstanceReady as U}from"./runtime-contexts.js";import{timeOperation as N}from"../evidence/operation-timings.js";import{createReadyEnvironment as A}from"./ready-environment.js";import{buildRuntimeLabel as K}from"./template.js";export function createRuntimeManager({productDir:t,graphs:i,lifecycle:n,runtimeOptions:r={}}){const a=new Map(i.map(e=>[e.key,e])),u=new Map,o=G(i),c=new Map,d={...r,provisionedSharedDatabases:new Set};return{canAcquire(e){if(c.has(e.graphKey))return!1;const s=y(u,a,e);return F(s,e,o)!==null},async acquire(e,s={}){const p=y(u,a,e);if(n.isStopRequested())throw n.signal.reason||new Error("testkit run interrupted");const g=e.leaseId,m=await E(r,s,"testkit.runtime.slot_claim",{summary:"claim runtime slot",scope:{graphKey:e.graphKey,taskId:e.id,serviceName:e.serviceName||null,targetName:e.targetName||null},metadata:{decision:"claim",resourceCost:v(e).toString()}},()=>{const l=T(p,e,o);if(!l)throw new Error(`Task ${e.id.toString()} was claimed before runtime capacity was available`);return l});try{const l=K(m.graph.dirName,m.runtimeId);s.onRuntimeAssigned?.({runtimeId:m.runtimeId,services:m.graph.runtimeConfigs.map(({name:b})=>({serviceName:b,runtimeLabel:l}))});const R=await $(m,t,e,n,d,s);return n.signal.throwIfAborted(),{...A(R,g),resourceCost:v(e),slot:m,context:R}}catch(l){throw C(m,v(e)),m.context||w(m,o),await f(m,n,o),n.isStopRequested()||I(c,e.graphKey,h(l)),l}},async release(e,s={}){e?.slot&&(s.invalidate&&(e.slot.draining=!0),e.released||(C(e.slot,e.resourceCost),e.released=!0),e.slot.draining&&e.slot.activeLeaseCount===0&&await f(e.slot,n,o))},async cleanupAll(){const e=[];for(const s of u.values())for(const p of s.slots){p.draining=!0;try{await f(p,n,o)}catch(g){e.push({slot:p,error:g})}}if(e.length>0)throw new AggregateError(e.map(s=>s.error),`Failed to clean up ${e.length.toString()} runtime ${e.length===1?"slot":"slots"}: ${e.map(s=>`${s.slot.runtimeId}: ${h(s.error)}`).join("; ")}`)},getStats(){return[...u.values()].map(e=>({graphKey:e.slots[0]?.graph.key||null,targetNames:[...e.slots.at(0)?.graph.targetNames??[]],maxConcurrentTasks:Number.isFinite(e.slots[0]?.graph.maxConcurrentTasks)?e.slots[0]?.graph.maxConcurrentTasks??null:null,runtimeCount:e.slots.length,runtimes:e.slots.map(s=>({runtimeId:s.runtimeId,peakLeaseCount:s.peakLeaseCount,peakResourceUnits:s.peakResourceUnits,resourceReservations:s.resourceReservations.map(p=>({...p}))})),resourceBudgets:[...o.values()].filter(s=>e.slots.some(p=>p.graph.resourceReservations.some(g=>g.key===s.key))).map(s=>({key:s.key,capacity:s.capacity,reserved:s.reserved,available:s.available,active:s.active,peakActive:s.peakActive}))})).sort((e,s)=>(e.graphKey||"").localeCompare(s.graphKey||""))},getGraphFailure(e){return c.get(e)??null},getGraph(e){return a.get(e)||null},markGraphFailed(e,s){I(c,e,s)}}}function y(t,i,n){const r=t.get(n.graphKey);if(r)return r;const a=i.get(n.graphKey);if(!a)throw new Error(`Unknown graph "${n.graphKey}"`);const o={slots:L(a.instanceCount).map(c=>({graph:a,runtimeId:c,context:null,activeLeaseCount:0,activeResourceUnits:0,resourceReservations:[],peakLeaseCount:0,peakResourceUnits:0,draining:!1}))};return t.set(n.graphKey,o),o}function T(t,i,n){const r=v(i),a=t.slots.filter(o=>!o.draining);if(a.length===0)return null;const u=[...a].filter(o=>x(o,r)&&k(o,n)).sort((o,c)=>o.activeResourceUnits-c.activeResourceUnits||o.activeLeaseCount-c.activeLeaseCount||o.runtimeId.localeCompare(c.runtimeId)).at(0);return u?(q(u,n),u.activeLeaseCount+=1,u.activeResourceUnits+=r,u.peakLeaseCount=Math.max(u.peakLeaseCount,u.activeLeaseCount),u.peakResourceUnits=Math.max(u.peakResourceUnits,u.activeResourceUnits),u):null}function C(t,i){t.activeLeaseCount=Math.max(0,t.activeLeaseCount-1),t.activeResourceUnits=Math.max(0,t.activeResourceUnits-i)}async function $(t,i,n,r,a,u={}){t.context||(t.context=S(t.runtimeId,t.graph,i),r.trackGraphContext(t.context));const o=a.operationTimingRegistry||null,c=o?.start({name:"testkit.runtime.ensure",kind:"runtime",summary:"ensure runtime instance ready",parentId:u.operationTimingParentId||null,scope:{graphKey:t.graph.key,runtimeId:t.runtimeId,serviceName:n.serviceName,targetName:n.targetName}})??null;try{await U(t.context,r,a),o?.finish(c,{status:"passed"})}catch(d){throw o?.finish(c,{status:"failed",error:h(d)}),d}return t.context}function E(t,i,n,r,a){return N(t.operationTimingRegistry||null,{name:n,kind:"runtime",summary:r.summary||null,parentId:i.operationTimingParentId||null,scope:r.scope||null,metadata:r.metadata||null},a)}async function f(t,i,n){!t.context||t.activeLeaseCount>0||(await M(t.context,i),w(t,n),t.context=null,t.draining=!1)}function F(t,i,n){const r=v(i);return t.slots.find(a=>!a.draining&&x(a,r)&&k(a,n))||null}function x(t,i){return t.activeResourceUnits+i<=t.graph.maxConcurrentTasks}function G(t){const i=new Map;for(const n of t)for(const r of n.resourceReservations){const a=i.get(r.key)||{key:r.key,capacity:r.capacity||0,reserved:r.reserved||0,available:r.available||Math.max(0,(r.capacity||0)-(r.reserved||0)),active:0,peakActive:0};a.capacity=Math.max(a.capacity,r.capacity||0),a.reserved=Math.max(a.reserved,r.reserved||0),a.available=Math.max(0,a.capacity-a.reserved),i.set(r.key,a)}return i}function k(t,i){return t.resourceReservations.length>0?!0:t.graph.resourceReservations.every(n=>{const r=i.get(n.key);return r?r.active+n.perRuntime<=r.available:!0})}function q(t,i){if(t.resourceReservations.length>0)return;const n=[];for(const r of t.graph.resourceReservations){const a=i.get(r.key);a&&(a.active+=r.perRuntime,a.peakActive=Math.max(a.peakActive,a.active),n.push({key:r.key,units:r.perRuntime,services:r.services}))}t.resourceReservations=n}function w(t,i){for(const n of t.resourceReservations){const r=i.get(n.key);r&&(r.active=Math.max(0,r.active-n.units))}t.resourceReservations=[]}function I(t,i,n){!i||t.has(i)||t.set(i,n)}function v(t){return t.resourceCost??1}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resolveRuntimeInstanceConfigs as p}from"./template.js";import{buildGraphResourceReservations as
|
|
1
|
+
import{resolveRuntimeInstanceConfigs as p}from"./template.js";import{buildGraphResourceReservations as f}from"../database/runtime-reservations.js";import{resolveRuntimeConfigs as m}from"../config/loader/dependencies.js";export const runtimePlanning=Object.freeze({collectDesiredRuntimeGraphs,resolveRuntimeInstanceConfigs:p,buildRuntimeGraphs,resolveRuntimeConfigs:m,buildGraphDirName});export function buildRuntimeGraphs(n){const t=[],s=new Map;for(const e of n){const r=s.get(e.runtimeKey);if(r){r.targetNames.push(e.config.name),r.instanceCount=Math.max(r.instanceCount,u(e.uses)),r.maxConcurrentTasks=Math.min(r.maxConcurrentTasks,c(e.runtimeConfigs));continue}const a={key:e.runtimeKey,runtimeNames:e.runtimeNames,runtimeConfigs:e.runtimeConfigs,targetNames:[e.config.name],dirName:buildGraphDirName(e.runtimeNames),instanceCount:u(e.uses),maxConcurrentTasks:c(e.runtimeConfigs),resourceReservations:f(e.runtimeConfigs)};t.push(a),s.set(e.runtimeKey,a)}return t.sort((e,r)=>e.dirName.localeCompare(r.dirName))}export function buildGraphDirName(n){const t=n.map(C).join("__");return t.length>0?t:"graph"}function C(n){return n.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")||"svc"}function u(n){return n.reduce((t,s)=>Math.max(t,s.testkit.runtime.instances),1)}function c(n){return n.reduce((t,s)=>Math.min(t,s.testkit.runtime.maxConcurrentTasks),Number.POSITIVE_INFINITY)}export function collectDesiredRuntimeGraphs(n=[]){const t=new Map(n.map(e=>[e.name,e])),s=new Map;for(const e of n){const a=m(e,t).map(g=>g.name).sort(),o=a.join("|"),i=s.get(o);if(i){i.targetNames.push(e.name),i.targetNames.sort(),i.instanceCount=Math.max(i.instanceCount,e.testkit.runtime.instances);continue}s.set(o,{key:o,dirName:buildGraphDirName(a),runtimeNames:a,targetNames:[e.name],instanceCount:e.testkit.runtime.instances})}return[...s.values()].sort((e,r)=>e.dirName.localeCompare(r.dirName))}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import y from"crypto";import p from"fs";import S from"path";import{resolveServiceCwd as k}from"../config/loader/index.js";import{appendFileToHash as f}from"../repo/fingerprint-policy.js";import{announceResolvedToolchain as w,resolveConfiguredToolchain as v}from"../toolchains/index.js";import{buildExecutionEnv as x,buildTemplateExecutionEnv as D,collectConfiguredInputs as R,serviceDatabaseBinding as l}from"../steps/index.js";import{runConfiguredSteps as b}from"../database/configured-steps.js";import"../evidence/setup-progress.js";import{isUnknownRecord as g,readDynamicProperty as I}from"../kernel/unknown-values.js";const N="prepare-manifest.json";export async function prepareRuntimeServices(e,r={}){for(const t of e)await prepareRuntimeService(t,r)}export async function prepareRuntimeService(e,r={}){const t=e.testkit.runtime.prepare;if(!t||t.steps.length===0||!F(e))return;const n=e.testkit.prepareDir,i=await computeRuntimePrepareFingerprint(e,{signal:r.signal}),s=S.join(n,N);if(E(s)?.fingerprint===i){r.setupRegistry?.recordCached({config:e,stage:"runtime:prepare",kind:"runtime-prepare",summary:"runtime prepare cache hit"});return}p.rmSync(n,{recursive:!0,force:!0}),p.mkdirSync(n,{recursive:!0});const c={...x(e,{...e.testkit.local?.env||{},...r.extraEnv||{}},process.env)},m=l(e)?.url;m&&(c.DATABASE_URL=m);const u=r.setupRegistry?.start({config:e,stage:"runtime:prepare",kind:"runtime-prepare",summary:"runtime prepare",recordLog:!1}),o=r.setupRegistry;try{await w(e,await v(e,{signal:r.signal}),r.reporter),await b({config:e,steps:t.steps,env:c,labelPrefix:"runtime:prepare",reporter:r.reporter,setupRegistry:o||null,parentOperation:u,signal:r.signal});const a=u?o?.finish(u,{status:"passed",summary:"runtime prepare"}):null;a&&r.reporter?.setupOperationFinished?.(a),A(s,{fingerprint:i,preparedAt:new Date().toISOString(),runtimeId:e.runtimeId||null,serviceName:e.name})}catch(a){const d=u?o?.finish(u,{status:"failed",summary:"runtime prepare",error:I(a,"message")||a}):null;throw d&&r.reporter?.setupOperationFinished?.(d),p.rmSync(n,{recursive:!0,force:!0}),a}}function F(e){return e.testkit.runtime.prepare!=null}export async function computeRuntimePrepareFingerprint(e,r={}){const t=await v(e,{signal:r.signal}),n=y.createHash("sha256");n.update(JSON.stringify({prepare:e.testkit.runtime.prepare,toolchain:t?{kind:"node",install:t.install,nodeVersion:t.nodeVersion,npmVersion:t.npmVersion,nodeSource:t.nodeSource,npmSource:t.npmSource,fingerprint:t.fingerprint}:null,env:D(e,{},{},{includeTestkitControls:!1}),envTemplates:{service:e.testkit.serviceEnv||{},local:e.testkit.local?.env||{}},cwd:e.testkit.local?e.testkit.local.cwd:null})),n.update(JSON.stringify(O(e)));const i=e.testkit.fingerprints||{exclude:[],include:[]};for(const s of e.testkit.envFiles||[])f(n,e.productDir,k(e.productDir,s),i);for(const s of R(e.productDir,e.testkit.runtime.prepare))f(n,e.productDir,s,i);return n.digest("hex")}function O(e){const r=[],t=l(e)?.url;t&&r.push({service:e.name,url:t});const n=new Set;for(const i of Object.values(e.testkit.serviceEnv||{}))h(i,n,e.name);for(const i of Object.values(e.testkit.local?.env||{}))h(i,n,e.name);for(const i of[...n].sort())r.push({service:i,url:l(e,i)?.url??null});return r}function h(e,r,t){if(typeof e!="string")return;const n=/\{db(?:Url|Host|Port|Name|User|Password|Ssl)(?::([a-zA-Z0-9_-]+))?\}/g;let i=n.exec(e);for(;i;)r.add(i[1]||t),i=n.exec(e)}function E(e){if(!p.existsSync(e))return null;try{const r=JSON.parse(p.readFileSync(e,"utf8"));return g(r)?{fingerprint:r.fingerprint,...typeof r.preparedAt=="string"?{preparedAt:r.preparedAt}:{},...typeof r.runtimeId=="string"||typeof r.runtimeId=="number"||r.runtimeId===null?{runtimeId:r.runtimeId}:{},...typeof r.serviceName=="string"?{serviceName:r.serviceName}:{}}:null}catch{return null}}function A(e,r){p.writeFileSync(e,JSON.stringify(r,null,2))}
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
import{DEFAULT_READY_TIMEOUT_MS as x,waitForReady as M,serviceCompletionError as
|
|
1
|
+
import{DEFAULT_READY_TIMEOUT_MS as I,ServiceExitedBeforeReadyError as x,ServiceReadinessTimeoutError as B,waitForReady as M,serviceCompletionError as A}from"../process/readiness.js";import{resolveServiceCwd as j}from"../config/loader/index.js";import{startSupervisedProcess as N,ProcessExitedBeforeReadyError as F,DEFAULT_SHUTDOWN_TIMEOUT_MS as q}from"../process/index.js";import{announceResolvedToolchain as V,applyToolchainEnv as H,resolveConfiguredToolchain as W}from"../toolchains/index.js";import{buildExecutionEnv as X,serviceDatabaseBinding as Y}from"../steps/index.js";import{SERVICE_START_ATTEMPTS as z}from"./ports.js";import{captureOutput as O}from"../process/index.js";import{prepareServiceStartInvocation as G}from"../process/service-processes.js";import{portListenerOwner as J}from"../process/port-listener.js";import{toError as S}from"../kernel/error-serialization.js";const K=20;class y extends Error{outcome;output;constructor(t,r,o){super(o.message,{cause:o}),this.outcome=t,this.output=r,this.name="LocalServiceExitedBeforeReadyError"}}export async function startLocalServices(e,t,r={}){const o=e.configs.filter(_).map(a=>a.name),n=[],m=new Map,u=new Map,v=new Map,$=(a,s)=>{const d=P(a);m.set(a.name,[...m.get(a.name)??[],{port:d,outcome:s}]);let h=v.get(a.name);!h&&r.environmentRecord&&(h=r.environmentRecord.service({runtimeLabel:a.runtimeLabel,serviceName:a.name}),v.set(a.name,h)),h?.recordAttempt({baseUrl:a.testkit.local.baseUrl??null,outcome:s,port:d,readyUrl:typeof a.testkit.local.readyUrl=="string"?a.testkit.local.readyUrl:null})},L=(a,s,d)=>{const h=m.get(a.name)?.at(-1);if(!d||!h){$(a,s);return}h.outcome=s,v.get(a.name)?.amendLastOutcome(s)};try{for(;n.length<o.length;){const a=o[n.length],s=te(e.configs,a);let d=!1;const h=async()=>{await e.releasePort(a),$(s,"starting"),d=!0};try{n.push(await startLocalService(s,t,r,h)),L(s,"ready",d)}catch(l){if(L(s,Z(l,t),d),t.signal.aborted)throw l;if(!(l instanceof y))throw U(s,m.get(a)??[],l,2);const b=[...u.get(a)??[],l];if(u.set(a,b),b.length>=z)throw ee(s,m.get(a)??[],b);try{const g=await e.reassignPort(a,new Set(n.map(w=>w.name))),f=n.findIndex(w=>g.includes(w.name));if(f>=0){const w=n.splice(f);for(const T of w)v.get(T.name)?.amendLastOutcome(`ready, then restarted after ${a} moved to a fresh port`);await stopLocalServices(w,t)}await e.prepare(new Set(o.slice(n.length)))}catch(g){throw Q(t)?g:U(s,m.get(a)??[],g,1)}}}}catch(a){try{await stopLocalServices(n,t)}catch(s){throw new AggregateError([a,s],"Local service startup failed and its supervised cleanup also failed",{cause:s})}throw a}return n}function Q(e){return e.signal.aborted}function Z(e,t){return t.signal.aborted?"cancelled":e instanceof y?e.outcome:e instanceof B?"readiness timed out":"failed to start"}function ee(e,t,r){const o=r.at(-1),n=[`Service "${e.runtimeLabel}:${e.name}" exited before becoming ready on all ${r.length.toString()} attempts, each on a fresh OS-assigned port:`,...k(t),...o&&o.output.length>0?[`Last output from attempt ${t.length.toString()}:`,...o.output.map(m=>` ${m}`)]:[]];return new Error(n.join(`
|
|
2
|
+
`),{cause:o})}function U(e,t,r,o){if(t.length<o)return r;const n=S(r);return new Error([`Service "${e.runtimeLabel}:${e.name}" did not start after ${t.length.toString()} attempts, each on a fresh OS-assigned port:`,...k(t),n.message].join(`
|
|
3
|
+
`),{cause:n})}function k(e){return e.map((t,r)=>` attempt ${(r+1).toString()} on port ${t.port.toString()}: ${t.outcome}`)}function te(e,t){const r=e.find(o=>o.name===t);if(!r||!_(r))throw new Error(`Runtime has no local service "${t}"`);return r}function P(e){const t=e.testkit.local.assignedPort;if(t===void 0)throw new Error(`Testkit assigned no port to service "${e.runtimeLabel}:${e.name}"`);return t}export async function startLocalService(e,t,r={},o=()=>Promise.resolve()){const n=j(e.productDir,e.testkit.local.cwd),m=await W(e,{signal:t.signal});await V(e,m,r.reporter);const u=H(X(e,{...e.testkit.local.env||{},...r.extraEnv||{}},process.env),m),v=P(e);u.PORT=String(v);const $=Y(e)?.url;$&&(u.DATABASE_URL=$),r.reporter?.localServiceStarting?.({serviceName:e.name,runtimeLabel:e.runtimeLabel||e.name,command:e.testkit.local.start,port:v});const L=G(e.testkit.local.start,u),a=r.logRegistry?.ensureServiceLogRecord(e),s=r.reporter?.outputMode==="debug"?i=>r.reporter?.writeDebugLine?.(i):null,d=[],h=i=>{d.push(i),d.length>K&&d.shift()};await o();const l=N({args:L.args,windowsVerbatimArguments:L.windowsVerbatimArguments,cwd:n,displayLabel:`Testkit local service ${e.runtimeLabel}:${e.name}`,env:ae(u),executable:L.executable,outputMode:"caller-drained",signal:t.signal,shutdownTimeoutMs:e.testkit.local.shutdownTimeoutMs??q,timeoutMs:null}),b=[O(l.stdout,{livePrefix:`[${e.runtimeLabel}:${e.name}]`,liveWriter:s,onLine(i){h(i),a&&r.logRegistry?.append(a,"stdout",i)}}),O(l.stderr,{livePrefix:`[${e.runtimeLabel}:${e.name}]`,liveWriter:s,onLine(i){h(i),a&&r.logRegistry?.append(a,"stderr",i)}})];let g,f=!1,w=!1;try{g=await l.ready,f=!0,t.registerService(e,l,g,n);const i=e.testkit.local.readyTimeoutMs||I,c=Date.now()+i,{baseUrl:p,readyUrl:E}=e.testkit.local,R={name:`${e.runtimeLabel}:${e.name}`,process:l,signal:t.signal};if(typeof E=="string"&&await M({...R,url:E,timeoutMs:i}),p!==void 0&&!(typeof E=="string"&&ne(E,p))&&await M({...R,url:p,requirement:"response",timeoutMs:Math.max(1,c-Date.now())}),await J(v,l.pid)==="foreign"){const C=`Readiness for "${e.runtimeLabel}:${e.name}" came from another process on port ${String(v)}`;throw new x(C,"another process held the port")}}catch(i){const c=i instanceof F?A(`${e.runtimeLabel}:${e.name}`,i):i;w=!0;const p=[];try{p.push(...await D(l,b,!1))}catch(E){p.push(S(E))}if(f)try{t.unregisterService(l.pid)}catch(E){p.push(S(E))}throw p.length>0?new AggregateError([c,...p],`Local service ${e.runtimeLabel}:${e.name} startup and cleanup failed`,{cause:i}):c instanceof x?new y(c.outcome,d,c):c}return{completionMonitor:l.completion.then(i=>{if(w)return null;if(t.signal.aborted){if(f){f=!1;try{t.unregisterService(l.pid)}catch{}}return null}let c=A(`${e.runtimeLabel}:${e.name}`,i,"unexpectedly");if(f){f=!1;try{t.unregisterService(l.pid)}catch(p){c=new AggregateError([c,p],`Local service ${e.runtimeLabel}:${e.name} exited and its manifest entry could not be removed`)}}try{t.requestStop(c.message)}catch(p){c=new AggregateError([c,p],`Local service ${e.runtimeLabel}:${e.name} exited and the active run could not be interrupted`)}return c}),expectCompletion(){w=!0},name:e.name,outputDrains:b,ownership:g,supervisor:l}}export async function stopLocalServices(e,t){const r=[];for(const o of[...e].reverse()){o.expectCompletion();try{r.push(...await D(o.supervisor,o.outputDrains)),await o.completionMonitor}catch(n){r.push(S(n))}finally{try{t?.unregisterService(o.ownership.pid)}catch(n){r.push(S(n))}}}if(r.length>0)throw new AggregateError(r,"Could not stop all local services")}async function D(e,t,r=!0){const n=await e.stop().then(u=>({error:null,result:u}),u=>({error:S(u),result:null})),m=await Promise.allSettled(t);return[...n.result?re(n.result,r):[n.error],...m.flatMap(u=>u.status==="rejected"?[S(u.reason)]:[])]}function re(e,t=!0){return[...t?[e.error]:[],e.terminationError].filter(r=>r!==null)}function ae(e){return Object.fromEntries(Object.entries(e).filter(t=>t[1]!==void 0))}function _(e){return e.testkit.local!=null}function ne(e,t){try{return new URL(e).origin===new URL(t).origin}catch{return!1}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import u from"fs";import c from"path";import{isNullableString as l,isUnknownRecord as N}from"../kernel/unknown-values.js";const y="graph.json";export function findRuntimeStateDirs(e,t){const n=[],s=r=>{if(!u.existsSync(r))return;const i=u.readdirSync(r,{withFileTypes:!0});t(r)&&n.push(r);for(const a of i)a.isDirectory()&&s(c.join(r,a.name))};return s(e),n.sort((r,i)=>i.length-r.length)}export function findGraphDirsForService(e,t){const n=c.join(e,".testkit","_graphs");if(!u.existsSync(n))return[];const s=[];for(const r of u.readdirSync(n,{withFileTypes:!0})){if(!r.isDirectory())continue;const i=c.join(n,r.name),a=readGraphMetadata(i);a&&(a.runtimeServices??[]).includes(t)&&s.push(i)}return s.sort()}export function writeGraphMetadata(e,t){u.mkdirSync(e,{recursive:!0});const n={key:t.key||null,dirName:t.dirName||null,instanceCount:Number.isFinite(t.instanceCount)?t.instanceCount:null,maxConcurrentTasks:Number.isFinite(t.maxConcurrentTasks)?t.maxConcurrentTasks:null,runtimeNames:[...t.runtimeNames].sort(),runtimeServices:t.runtimeNames,targetServices:[...t.targetNames].sort()};u.writeFileSync(c.join(e,y),JSON.stringify(n,null,2))}export function readGraphMetadata(e){const t=c.join(e,y);if(!u.existsSync(t))return null;try{const n=JSON.parse(u.readFileSync(t,"utf8"));return p(n)}catch{return null}}function p(e){if(!N(e))return null;const{dirName:t,instanceCount:n,key:s,maxConcurrentTasks:r,runtimeNames:i,runtimeServices:a,targetServices:f,...S}=e,o={...S};return l(t)&&(o.dirName=t),d(n)&&(o.instanceCount=n),l(s)&&(o.key=s),d(r)&&(o.maxConcurrentTasks=r),Array.isArray(i)&&(o.runtimeNames=i.filter(m)),Array.isArray(a)&&(o.runtimeServices=a.filter(m)),Array.isArray(f)&&(o.targetServices=f.filter(m)),o}function d(e){return e===null||typeof e=="number"&&Number.isFinite(e)}function m(e){return typeof e=="string"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{finalizeRuntimeDatabaseConfig as
|
|
1
|
+
import{finalizeRuntimeDatabaseConfig as w}from"../database/runtime-config.js";import h from"path";import{finalizeConfiguredInputs as E,finalizeConfiguredSteps as U}from"../steps/configured-steps.js";import"../config/loader/index.js";import{finalizeString as b,resolveTemplateString as y}from"../steps/index.js";export function resolveRuntimeInstanceConfigs(e,n,r,s={}){const c=buildRuntimeLabel(s.graphDirName,n),p=s.ports??new Map,a=new Map,l=new Map,u=new Map,d=new Map,f=new Map,x=k(s.externalEndpoints),m=k(s.publicEndpoints),v=k(s.privateEndpoints),o=k(s.serviceContextEndpoints);for(const t of e)t.testkit.local&&(t.testkit.local.baseUrl!==void 0&&a.set(t.name,resolveRuntimeUrl(t.testkit.local.baseUrl,t.name,n,{runtimeId:n,runtimeLabel:c,runtimeDir:r,portMap:p,baseUrlByService:a,readyUrlByService:l})),t.testkit.local.readyUrl!==!1&&t.testkit.local.readyUrl!=null&&l.set(t.name,resolveRuntimeUrl(t.testkit.local.readyUrl,t.name,n,{runtimeId:n,runtimeLabel:c,runtimeDir:r,portMap:p,baseUrlByService:a,readyUrlByService:l})));for(const[t,i]of Object.entries(x))a.has(t)||a.set(t,i),l.has(t)||l.set(t,i);for(const[t,i]of Object.entries(m))u.set(t,i);for(const[t,i]of Object.entries(v))d.set(t,i);for(const[t,i]of Object.entries(o))f.set(t,i);for(const[t,i]of a.entries())u.has(t)||u.set(t,C(i,s.publicHost||null)),f.has(t)||f.set(t,i),d.has(t)||d.set(t,i);return e.map(t=>resolveRuntimeConfig(t,n,c,r,p,a,l,u,d,f,s.publicHost||null,s.databaseBindings??new Map))}function k(e){return Object.fromEntries(Object.entries(e??{}).map(([n,r])=>[n,(r??"").trim()]).filter(n=>n[1].length>0))}export function resolveRuntimeConfig(e,n,r,s,c,p,a,l,u,d,f,x){const m=resolveServiceStateDir(s,e),v=resolveServicePrepareDir(s,e),o={runtimeId:n,runtimeLabel:r,runtimeDir:s,productDir:e.productDir,serviceName:e.name,serviceCwd:e.testkit.local?.cwd||".",serviceStateDir:m,prepareDir:v,portMap:c,baseUrlByService:p,readyUrlByService:a,publicBaseUrlByService:l,privateBaseUrlByService:u,serviceContextUrlByService:d,publicHost:f,leaseId:null,leaseDir:null,databaseBindingsByService:x},t=w(e.testkit.database,o),i={...e.testkit.runtime,prepare:j(e.testkit.runtime.prepare,o)},S=e.testkit.local?{...e.testkit.local,start:b(e.testkit.local.start,o),cwd:e.testkit.local.cwd!==void 0?b(e.testkit.local.cwd,o):e.testkit.local.cwd,assignedPort:c.get(e.name),baseUrl:p.get(e.name),readyUrl:a.get(e.name),env:{...e.testkit.local.env||{}}}:void 0;return{...e,stateDir:m,runtimeId:n,runtimeLabel:r,testkit:{...e.testkit,database:t,prepareDir:v,templateContext:o,runtime:i,local:S}}}export function resolveServiceStateDir(e,n){return h.join(e,"services",n.name)}export function resolveServicePrepareDir(e,n){return h.join(resolveServiceStateDir(e,n),"prepared")}export function resolveRuntimeUrl(e,n,r,s){return y(e,{...s,runtimeId:r,serviceName:n})}function C(e,n){if(!n)return e;try{const r=new URL(e);r.hostname=n;let s=r.toString();return!e.endsWith("/")&&r.pathname==="/"&&s.endsWith("/")&&(s=s.slice(0,-1)),s}catch{return e}}function j(e,n){return e?{inputs:E(e.inputs,r=>b(r,n)),steps:U(e.steps,r=>b(r,n))}:{inputs:[],steps:[]}}export function buildRuntimeLabel(e,n){return e?`${e}/${n}`:n}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function normalizeArtifactArchiveConfig(r){const n=
|
|
1
|
+
import{isUnknownArray as e,isUnknownRecord as o}from"../kernel/unknown-values.js";export function normalizeArtifactArchiveConfig(r){const n=normalizeOptionalRecord(r,"artifacts"),i=normalizeOptionalRecord(n?.retention,"artifacts.retention"),t=normalizeOptionalRecord(n?.publication,"artifacts.publication");return{retention:{maxRuns:s(i?.maxRuns,"artifacts.retention.maxRuns"),maxAgeDays:a(i?.maxAgeDays,"artifacts.retention.maxAgeDays"),preserveSuites:u(i?.preserveSuites,"artifacts.retention.preserveSuites")},publication:t?{directory:f(t.directory,"artifacts.publication.directory"),required:m(t.required,"artifacts.publication.required")}:null}}function s(r,n){if(r==null)return null;if(typeof r!="number"||!Number.isInteger(r)||r<=0)throw new Error(`${n} must be a positive integer`);return r}function a(r,n){if(r==null)return null;if(typeof r!="number"||!Number.isFinite(r)||r<=0)throw new Error(`${n} must be a positive number`);return r}function u(r,n){if(r==null)return[];if(!e(r))throw new Error(`${n} must be an array of non-empty strings`);const i=r.map(t=>{if(typeof t!="string"||t.trim().length===0)throw new Error(`${n} must be an array of non-empty strings`);return t.trim()});return[...new Set(i)].sort()}function f(r,n){if(typeof r!="string"||r.trim().length===0)throw new Error(`${n} is required`);return r.trim()}function m(r,n){if(r===void 0)return!1;if(typeof r!="boolean")throw new Error(`${n} must be a boolean`);return r}export function normalizeOptionalRecord(r,n){if(r!=null){if(!o(r))throw new Error(`${n} must be an object`);return r}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{requireObjectRecord,
|
|
1
|
+
export{requireObjectRecord,requireStringArray as normalizeStringArray}from"./read-fields.js";export function readOptionalProperty(r,n){return r?.[n]}export function normalizeOptionalNonEmptyString(r,n){if(r==null||r==="")return null;if(typeof r!="string")throw new Error(`${n} must be a string or null`);return r}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{isPathWithin as
|
|
2
|
-
`,p=
|
|
1
|
+
import{isPathWithin as _}from"../process/files/paths.js";import{isUnknownArray as C,isUnknownRecord as M}from"../kernel/unknown-values.js";import{readRunDocument as B}from"./read-run.js";import l from"node:fs";import o from"node:path";import"../engines/api/index.js";import"../domain/identifiers.js";import{normalizeArtifactArchiveConfig as $}from"./artifact-config.js";import{applyRunBundleRetention as K,publishRunBundle as U,sealRunBundle as V}from"./bundles.js";import{RETENTION_DECISION_SCHEMA_VERSION as q}from"./contracts.js";import{redactedRunValue as A,runRedaction as J}from"./redaction.js";import{applyTimingUpdates as X,createEmptyTimings as x,normalizeTimings as G}from"./timing.js";import{normalizeOptionalNonEmptyString as k,normalizeStringArray as W,readOptionalProperty as j,requireObjectRecord as H}from"./artifact-validation.js";import{errorMessage as Q,serializeJson as N,writeJsonFileAtomicWithRetry as z,readJsonFileOrNull as Y}from"../process/files/json-file.js";import{copyRegularFileSecurely as Z}from"./secure-file-copy.js";import{hasErrorCode as O}from"../kernel/error-serialization.js";import{posixPath as w}from"../process/files/paths.js";const D="timings.json",S="artifacts",tt="logs",et="setup",I="live.json",rt=1e4,b=String;export function writeRunArtifact(t,e,r={},n={}){const i=e,a=o.join(t,".testkit","results");l.mkdirSync(a,{recursive:!0});const u=i.archive,s=r.archiveConfig??$(j(u,"request")||{}),c=r.declaredEnvironmentKeys??W(j(u,"declaredEnvironmentKeys")||[],"run artifact declaredEnvironmentKeys"),m=n.sealRunBundle??V,p=n.publishRunBundle??U,d=n.applyRunBundleRetention??K,y=n.writeLatestProjection??z,f=m(t,i,{env:r.env,archiveConfig:s,declaredEnvironmentKeys:c,redactKeys:r.redactKeys,redactionTargets:r.redactionTargets}),h=nt(t,f.archive.runId,s.publication,p),v=it(t,f.archive.runId,s.retention,d),{targets:g}=J({env:r.env,redactKeys:r.redactKeys,redactionTargets:r.redactionTargets}),R=A(i.finalizationFailure,g),P={...f,...R===void 0?{}:{finalizationFailure:R},run:h.status==="failed"&&h.required===!0||f.archive.cleanup?.status==="failed"||R!==void 0&&f.run.status!=="interrupted"?{...f.run,status:"failed"}:f.run,archive:{...f.archive,publication:A(h,g),retention:A(v,g)}};return at(a,P,y,g)}function nt(t,e,r,n){try{return n(t,e,r)}catch(i){return{bytesUploaded:0,configured:r!==null,error:E(i),recordedAt:new Date().toISOString(),required:r?.required??!1,runId:e,schemaVersion:1,status:"failed",target:r===null?null:o.resolve(t,r.directory)}}}function it(t,e,r,n){try{return n(t,e,r)}catch(i){return{currentRunId:e,decidedAt:new Date().toISOString(),error:E(i),garbageCollection:{failures:[],reclaimedBytes:0,removedObjects:0,status:"not_started"},policy:{maxAgeDays:r.maxAgeDays,maxRuns:r.maxRuns,preserveSuites:[...r.preserveSuites]},protectedRunIds:[e],removed:[],removalErrors:[],schemaVersion:q,status:"failed"}}}function at(t,e,r,n){const i=o.join(t,"latest.json"),a={path:w(o.relative(o.dirname(t),i)),status:"complete"},u={...e,archive:{...e.archive,latest:a}};try{return r(i,u),u}catch(s){return{...u,archive:{...u.archive,latest:{...a,error:A(E(s),n),status:"failed"}}}}}function E(t){try{return Q(t)}catch{return"Unknown post-seal archive operation failure"}}export function writeLiveRunArtifact(t,e){const r=e,n=o.join(t,".testkit","results");l.mkdirSync(n,{recursive:!0}),z(o.join(n,I),r)}export function finalizeLiveRunArtifact(t,e={}){const r=ut(e),n=o.join(t,".testkit","results",I),i=Y(n);if(i===null)return!1;const a=st(i,r);return a?(writeRunArtifact(t,a,{redactKeys:e.redactKeys,redactionTargets:e.redactionTargets}),!0):!1}function st(t,e){const r=B(t,"live run artifact"),n=r.run.id||null;if(e.runId&&n&&n!==e.runId)return null;const i=ct(e.finishedAt),a=new Date(i).toISOString(),u=lt(r.run.startedAt),s=u===null?r.run.durationMs:Math.max(0,i-u);return{...r,generatedAt:a,run:{...r.run,id:n??e.runId,status:e.status,finishedAt:a,durationMs:s,interruptReason:e.reason},timings:ot(r.timings,a,e.reason)}}function ot(t,e,r){if(t==null)return t;const n=H(t,"live run artifact.timings"),i=n.operations;if(i==null)return n;if(!C(i))throw new Error("live run artifact.timings.operations must be an array");return{...n,operations:i.map(a=>!M(a)||a.status!=="running"?a:{...a,status:"cancelled",finishedAt:k(a.finishedAt,"live run operation.finishedAt")??e,message:k(a.message,"live run operation.message")??r})}}function ut(t){return{runId:t.runId??null,reason:t.reason??"run interrupted",status:t.status??"interrupted",finishedAt:t.finishedAt??Date.now()}}function ct(t){if(t instanceof Date&&Number.isFinite(t.getTime()))return t.getTime();if(typeof t=="number"&&Number.isFinite(t))return t;if(typeof t=="string"){const e=Date.parse(t);if(Number.isFinite(e))return e}return Date.now()}function lt(t){if(typeof t!="string")return null;const e=Date.parse(t);return Number.isFinite(e)?e:null}export function resetResultArtifacts(t){l.rmSync(o.join(t,".testkit","results",S),{recursive:!0,force:!0}),l.rmSync(o.join(t,".testkit","results",tt),{recursive:!0,force:!0}),l.rmSync(o.join(t,".testkit","results",et),{recursive:!0,force:!0}),l.rmSync(o.join(t,".testkit","results",I),{force:!0})}export function persistTaskArtifacts(t,e,r){if(r.length===0)return[];const n=T(e.serviceName||"service"),i=F(t,n);return r.map((a,u)=>{const s=mt(a),c={schemaVersion:2,source:"testkit-runtime-artifact",service:e.serviceName,suite:{engineId:e.engineId,key:e.suiteKey,name:e.suiteName,profileId:e.profileId,testType:e.testType},file:e.file,taskId:e.id,index:u,name:s.name,kind:s.kind,summary:s.summary,contentType:s.contentType,emittedAt:s.emittedAt,data:s.data},m=`${N(c,"runtime artifact payload")}
|
|
2
|
+
`,p=L(i,e.id,u,s.name,".json",y=>{l.writeFileSync(y,m,{flag:"wx"})}),d=o.join(".testkit","results",S,n,p);return{name:c.name,kind:c.kind,summary:c.summary,contentType:c.contentType,path:w(d)}})}export function persistTaskFileArtifacts(t,e,r,n={}){if(r.length===0)return[];const i=T(e.serviceName||"service"),a=F(t,i);return r.map((u,s)=>{const c=ft(u),m=o.resolve(c.path),p=yt(m,c.contentType),d=[],y=L(a,e.id,s,c.name,p,v=>{d.push(Z(m,v,{...n.maxBytes===void 0?{}:{maxBytes:n.maxBytes},...n.sourceRoot===void 0?{}:{sourceRoot:n.sourceRoot},...n.sizeLimitDescription===void 0?{}:{sizeLimitDescription:n.sizeLimitDescription}}))}),f=d.at(0);if(f===void 0)throw new Error("File artifact copy completed without a result");n.copyResults?.push(f);const h=o.join(".testkit","results",S,i,y);return{name:c.name,kind:c.kind,summary:c.summary,contentType:c.contentType??ht(m),path:w(h)}})}export function persistTaskOutputArtifacts(t,e,r){if(r.length===0)return[];const n=[];for(const i of r){const a=i.text;a.trim().length!==0&&n.push({name:i.name||"task-output",kind:i.kind||"runtime.output",summary:i.summary||pt(a),contentType:i.contentType||"text/plain",emittedAt:i.emittedAt||new Date().toISOString(),data:{stream:i.stream||null,text:a}})}return persistTaskArtifacts(t,e,n)}export function loadTimings(t){const e=o.join(t,".testkit",D);if(!l.existsSync(e))return x();try{const r=JSON.parse(l.readFileSync(e,"utf8"));return G(r)}catch{return x()}}export function saveTimings(t,e,r){if(r.length===0)return;const n=X(e,r),i=o.join(t,".testkit");l.mkdirSync(i,{recursive:!0}),l.writeFileSync(o.join(i,D),N(n,"timings"))}function mt(t){return{name:t.name,kind:t.kind||null,summary:t.summary||null,contentType:t.contentType||"application/json",emittedAt:t.emittedAt||null,data:t.data}}function ft(t){return{path:t.path,name:t.name||"artifact",kind:t.kind||null,summary:t.summary||null,contentType:t.contentType||null}}function dt(t,e,r,n,i=0){const a=i===0?"":`-${(i+1).toString().padStart(2,"0")}`;return`task-${T(t)}-${(e+1).toString().padStart(2,"0")}-${T(r)}${a}${n}`}function L(t,e,r,n,i,a){for(let u=0;u<rt;u+=1){const s=dt(e,r,n,i,u),c=o.join(t,s);try{return a(c),s}catch(m){if(O(m,"EEXIST"))continue;throw l.rmSync(c,{force:!0}),m}}throw new Error(`Could not allocate a unique artifact path for task ${b(e)} and artifact ${n}`)}function F(t,e){const r=o.resolve(t);if(!l.statSync(r).isDirectory())throw new Error("Artifact product directory must be a directory");const i=l.realpathSync(r);let a=r;for(const u of[".testkit","results",S,e]){a=o.join(a,u);try{l.mkdirSync(a)}catch(m){if(!O(m,"EEXIST"))throw m}const s=l.lstatSync(a);if(s.isSymbolicLink()||!s.isDirectory())throw new Error(`Artifact output directory ${JSON.stringify(a)} must be a real directory below productDir`);const c=l.realpathSync(a);if(!_(i,c))throw new Error(`Artifact output directory ${JSON.stringify(a)} escapes productDir`)}return a}function T(t){return b(t).trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"artifact"}function pt(t){const e=t.split(/\r?\n/u).map(r=>r.trim()).find(Boolean);return e?e.slice(0,120):"captured task output"}function yt(t,e){const r=o.extname(t);if(r)return r;const n=(e??"").split(";",1)[0].trim().toLowerCase();return n==="text/markdown"?".md":n==="text/plain"?".txt":n==="application/json"?".json":n==="application/zip"?".zip":n==="image/png"?".png":n==="image/jpeg"?".jpg":n==="text/html"?".html":n==="video/webm"?".webm":".artifact"}function ht(t){const e=o.extname(t).toLowerCase();return e===".md"||e===".markdown"?"text/markdown":e===".txt"||e===".log"?"text/plain":e===".json"?"application/json":"application/octet-stream"}
|
package/dist/evidence/bundles.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{recordWork as H}from"../kernel/work-metrics.js";import{optionalString as A}from"../kernel/unknown-values.js";import{readRunProvenance as ue}from"./read-provenance.js";import{parseRunBundleArtifact as le,parseRunBundleManifest as J,readRunBundleArtifact as fe}from"./read-bundle.js";import{readRunDocument as de}from"./read-run.js";import me from"crypto";import c from"fs";import u from"path";import{redactSensitiveText as Y}from"../kernel/redaction.js";import{BUNDLE_SCHEMA_VERSION as G,OBJECTS_DIRNAME as Q,PROVENANCE_SCHEMA_VERSION as pe,RETENTION_DECISION_SCHEMA_VERSION as he,RUNS_DIRNAME as ge}from"./contracts.js";import{bundleRelativePath as x,errorMessage as k,hashFile as F,isObjectRecord as $,normalizePath as X,normalizeRunId as w,objectRecords as Z,optionalStringArray as z,optionalUnknownArray as ye,readJsonFile as P,requirePublicationPathOutsideResults as M,requireRunId as ve,runIncludesFile as Se,resolveManifestEntryPath as ee,resolveRunBundleDirectory as O,resolveRunsRoot as te,resultsRoot as U,sanitizeSegment as Re,sha256 as C,stableJson as q,treeBytes as ne,walkFiles as re,writeBufferAtomic as je,writeJson as N}from"./storage.js";import{resolveCiProvenance as be}from"./ci-provenance.js";const W=["artifacts","logs","setup"],Ie=/(?:PASSWORD|TOKEN|SECRET|PRIVATE_KEY|AUTH|COOKIE|SESSION|API_KEY)/iu,we=["package.json","package-lock.json","npm-shrinkwrap.json","pnpm-lock.yaml","yarn.lock","testkit.config.ts","testkit.config.mts","testkit.config.js","testkit.config.mjs"];export function sealRunBundle(e,n,t={},s={}){const r=n,o=ve(r),i=te(e,!0),a=u.dirname(i),f=u.join(i,o),m=s.cleanupActiveRunResults??ze,p=loadVerifiedRunBundleArtifactIfExists(e,o);if(p!==null)return{...p,archive:{...p.archive,cleanup:m(a)}};const d=u.join(i,`.${o}.${String(process.pid)}.${String(Date.now())}.${me.randomBytes(4).toString("hex")}.tmp`);c.mkdirSync(d,{recursive:!0});try{const R=Te(t.env??process.env),g=Ee({productDir:e,resultsDir:a,runId:o,tempDir:d,sensitiveValues:R}),h=Be(r,o,R),y=de(h.artifact,"run artifact");g.redaction.structuredReplacements=h.replacements,g.redaction.replacements+=h.replacements;const v=$e(e,y,o,{...t,redaction:g.redaction}),j={schemaVersion:G,runId:o,status:"complete",canonicalRunPath:x(o,"run.json"),manifestPath:x(o,"manifest.json"),provenancePath:x(o,"provenance.json"),integrity:"sha256",publication:{configured:!!t.archiveConfig?.publication,status:t.archiveConfig?.publication?"pending":"not_configured"},redaction:g.redaction};y.archive=j,N(u.join(d,"run.json"),y),N(u.join(d,"provenance.json"),v);const b=xe(d),D=C(Buffer.from(q(b))),E={schemaVersion:G,runId:o,createdAt:new Date().toISOString(),algorithm:"sha256",files:b,storage:{fileCount:b.length,logicalBytes:b.reduce((T,_)=>T+_.bytes,0),objectBytesWritten:g.objectBytesWritten,deduplicatedBytes:g.deduplicatedBytes},redaction:g.redaction,digest:D};return N(u.join(d,"manifest.json"),E),c.renameSync(d,f),{...y,archive:{...j,cleanup:m(a),manifestDigest:E.digest,storage:E.storage}}}catch(R){try{c.rmSync(d,{recursive:!0,force:!0})}catch{}try{Ce(e)}catch{}throw R}}export function loadVerifiedRunBundleArtifactIfExists(e,n){const t=w(n),s=O(e,t);if(!c.existsSync(s))return null;const r=verifyRunBundle(e,t);if(!r.ok)throw new Error(`Immutable run bundle ${t} already exists but failed integrity verification: ${r.errors.join("; ")}`);return loadRunBundleArtifact(e,t)}export function loadRunBundleArtifact(e,n){return se(e,n).artifact}function se(e,n){const t=w(n),s=fe(e,t),r=loadRunBundleManifest(e,t);return{manifest:r,artifact:{...s,archive:{...s.archive,manifestDigest:r.digest,storage:r.storage}}}}export function loadRunBundleManifest(e,n){const t=w(n),s=O(e,t),r=u.join(s,"manifest.json");if(!c.existsSync(r))throw new Error(`No immutable Testkit run manifest found for ${t}`);return J(P(r),r,t)}export function listRunBundles(e,n={}){return ie(e,n).map(({artifact:t,manifest:s,...r})=>r)}function ie(e,n={}){const t=te(e,!1);if(!c.existsSync(t))return[];const s=c.readdirSync(t,{withFileTypes:!0});return H("artifacts.runDirectoriesRead",1),H("artifacts.runEntriesVisited",s.length),s.filter(o=>o.isDirectory()&&!o.name.startsWith(".")).map(o=>{try{const{artifact:i,manifest:a}=se(e,o.name);return n.file&&!Se(i,n.file)?null:{artifact:i,manifest:a,runId:o.name,status:i.run.status,startedAt:i.run.startedAt,finishedAt:i.run.finishedAt??null,manifestDigest:i.archive.manifestDigest??null,canonicalRunPath:i.archive.canonicalRunPath}}catch{return null}}).filter(o=>o!==null).sort((o,i)=>(i.finishedAt??i.startedAt??"").localeCompare(o.finishedAt??o.startedAt??""))}export function verifyRunBundle(e,n){const t=w(n);try{return V(O(e,t),t)}catch(s){return{ok:!1,runId:t,errors:[k(s)],checkedFiles:0}}}export function publishRunBundle(e,n,t,s={}){const r=w(n),o=s.writePublicationReceipt??Pe;if(!t)return o(e,r,{status:"not_configured",required:!1,target:null,bytesUploaded:0});const i=u.resolve(e,t.directory);try{M(e,i)}catch(d){return o(e,r,{status:"failed",required:t.required,target:i,error:k(d),bytesUploaded:0})}const a=Re(u.basename(e)),f=u.join(i,a),m=u.join(f,r),p=u.join(f,`.${r}.${String(process.pid)}.${String(Date.now())}.tmp`);try{const d=O(e,r);if(c.mkdirSync(f,{recursive:!0}),M(e,f),c.existsSync(m)){const h=c.lstatSync(m);if(h.isSymbolicLink()||!h.isDirectory())throw new Error("Publication target must be a regular bundle directory");M(e,m);const y=V(d,r);if(!y.ok)throw new Error(`Source run bundle failed integrity verification: ${y.errors.join("; ")}`);const v=V(m,r);if(!v.ok)throw new Error(`Publication target failed integrity verification: ${v.errors.join("; ")}`);if(y.manifestDigest!==v.manifestDigest)throw new Error("Publication target already exists with a different manifest digest");return o(e,r,{status:"complete",required:t.required,target:m,manifestDigest:y.manifestDigest,reused:!0,bundleBytes:ne(d),bytesUploaded:0})}const R=ne(d);c.cpSync(d,p,{recursive:!0,preserveTimestamps:!0});const g=V(p,r);if(!g.ok)throw new Error(g.errors.join("; "));return c.renameSync(p,m),o(e,r,{status:"complete",required:t.required,target:m,manifestDigest:g.manifestDigest,reused:!1,bundleBytes:R,bytesUploaded:R})}catch(d){return c.rmSync(p,{recursive:!0,force:!0}),o(e,r,{status:"failed",required:t.required,target:m,error:k(d),bytesUploaded:0})}}export function applyRunBundleRetention(e,n,t={},s={}){const r=w(n),o=s.removeObject??ce,i=s.removeRunBundle??Ne,a=t.maxRuns??null,f=t.maxAgeDays??null,m=new Set(t.preserveSuites||[]),p=ie(e),d=new Set([r]);for(const l of p)Oe(l.artifact,m)&&d.add(l.runId);const R=new Set(a?p.slice(0,a).map(l=>l.runId):p.map(l=>l.runId)),g=f==null?null:Date.now()-f*24*60*60*1e3,h=[];for(const l of p){if(d.has(l.runId))continue;const S=g!=null&&Date.parse(l.finishedAt||l.startedAt||"")<g,I=!R.has(l.runId);if(!S&&!I)continue;const B=[];S&&B.push("max_age"),I&&B.push("max_runs"),h.push({path:u.join(U(e),ge,l.runId),reasons:B,runId:l.runId})}const y=new Map(p.map(l=>[l.runId,l.manifest.files.filter(S=>S.path.startsWith("files/")).map(S=>S.sha256)])),v=oe(e),j=[],b=[];for(const l of h){let S=null;try{i(l.path)}catch(B){S=L(B)}const I=!c.existsSync(l.path);!I&&S===null&&(S="Run bundle still exists after removal completed"),I&&j.push({reasons:l.reasons,runId:l.runId}),S!==null&&b.push({...l,error:S,removed:I})}const D=new Set(j.map(l=>l.runId)),E=new Set(p.filter(l=>!D.has(l.runId)).flatMap(l=>y.get(l.runId)??[])),T=ae(v,E,o),_=new Date().toISOString();return Ve({currentRunId:r,decidedAt:_,garbageCollection:T,policy:{maxRuns:a,maxAgeDays:f,preserveSuites:[...m].sort()},protectedRunIds:[...d].sort(),removed:j,removalErrors:b})}function Ee({resultsDir:e,tempDir:n,sensitiveValues:t}){let s=0,r=0,o=0,i=0,a=0;const f=u.join(e,Q,"sha256");c.mkdirSync(f,{recursive:!0});for(const m of W){const p=u.join(e,m);if(c.existsSync(p))for(const d of re(p)){const R=u.relative(p,d),g=c.readFileSync(d),h=De(g,d,t);h.scanned&&(o+=1),h.replacements>0&&(i+=1,a+=h.replacements);const y=C(h.buffer),v=u.join(f,y);c.existsSync(v)?r+=h.buffer.length:(je(v,h.buffer),c.chmodSync(v,292),s+=h.buffer.length);const j=u.join(n,"files",m,R);c.mkdirSync(u.dirname(j),{recursive:!0});try{c.linkSync(v,j)}catch{c.copyFileSync(v,j)}}}return{objectBytesWritten:s,deduplicatedBytes:r,redaction:{policyVersion:1,status:"applied",textualFilesScanned:o,filesRedacted:i,replacements:a,sensitiveEnvironmentKeys:t.map(m=>m.key).sort(),valuesStored:!1}}}function Be(e,n,t){const s=new Map(W.map(o=>[`.testkit/results/${o}/`,`${x(n,`files/${o}`)}/`])),r=K(e,s);return ke(Ae(r),t)}function Ae(e){if(!$(e))return e;const n={...e};if($(n.product)){const t={...n.product};delete t.directory,n.product=t}if($(n.git)){const t={...n.git};delete t.remoteUrl,delete t.repoRoot,delete t.worktreePath,n.git=t}return delete n.host,n}function K(e,n){if(Array.isArray(e))return e.map(s=>K(s,n));if($(e))return Object.fromEntries(Object.entries(e).map(([s,r])=>[s,K(r,n)]));if(typeof e!="string")return e;let t=e;for(const[s,r]of n)t.startsWith(s)&&(t=`${r}${t.slice(s.length)}`);return t}function ke(e,n){let t=0;function s(r){if(Array.isArray(r))return r.map(s);if($(r))return Object.fromEntries(Object.entries(r).map(([i,a])=>[i,s(a)]));if(typeof r!="string")return r;let o=Y(r);o!==r&&(t+=1);for(const i of n){if(!o.includes(i.value))continue;const a=o.split(i.value);t+=a.length-1,o=a.join("<redacted>")}return o}return{artifact:s(e),replacements:t}}function $e(e,n,t,s){const r=z(n.run.fileNames),o=[...new Set([...we,...r])].map(i=>Fe(e,i)).filter(i=>i!==null);return{schemaVersion:pe,runId:t,ci:be(s.env??process.env),source:{git:n.git??null,files:o},runtime:{controller:{testkitVersion:A(n.run.testkitVersion),node:process.versions.node,platform:process.platform,architecture:process.arch},runtimeStats:ye(n.run.runtimeStats)},scenario:{types:z(n.run.types),suiteSelectors:z(n.run.suiteSelectors),fileNames:r,serviceFilter:A(n.run.serviceFilter),planningDigest:C(Buffer.from(q(n.planning??null))),declaredEnvironmentKeys:[...new Set(s.declaredEnvironmentKeys??[])].sort()},redaction:s.redaction}}function xe(e){return re(e).map(n=>({path:X(u.relative(e,n)),bytes:c.statSync(n).size,sha256:F(n)})).sort((n,t)=>n.path.localeCompare(t.path))}function V(e,n){const t=u.join(e,"manifest.json"),s=J(P(t),t,n);le(P(u.join(e,"run.json")),u.join(e,"run.json"),n);const r=[];for(const i of s.files){let a;try{a=ee(e,i.path)}catch(m){r.push(k(m));continue}if(!c.existsSync(a)){r.push(`missing ${i.path}`);continue}const f=c.lstatSync(a);if(f.isSymbolicLink()){r.push(`symbolic link not allowed ${i.path}`);continue}if(!f.isFile()){r.push(`not a regular file ${i.path}`);continue}f.size!==i.bytes&&r.push(`size mismatch ${i.path}`),F(a)!==i.sha256&&r.push(`checksum mismatch ${i.path}`)}C(Buffer.from(q(s.files)))!==s.digest&&r.push("manifest digest mismatch"),s.storage.fileCount!==s.files.length&&r.push("manifest file count mismatch");for(const i of["run.json","provenance.json"])s.files.some(a=>a.path===i)||r.push(`manifest must include ${i}`);if(r.length===0){const i=ee(e,"provenance.json");ue(P(i),i,n)}return{runId:n,checkedFiles:s.files.length,storage:s.storage,ok:r.length===0,errors:r,manifestDigest:s.digest}}function Pe(e,n,t){const s={schemaVersion:1,runId:n,recordedAt:new Date().toISOString(),...t};return N(u.join(U(e),"publications",`${n}.json`),s),s}function Oe(e,n){return n.size===0?!1:Z(e.services).some(t=>Z(t.suites).some(s=>{const r=A(t.name)??"",o=A(s.name)??"",i=A(s.testType)??"";return[o,`${i}:${o}`,`${r}/${i}:${o}`].some(f=>n.has(f))}))}function Ce(e){const n=new Set;for(const t of listRunBundles(e)){const s=loadRunBundleManifest(e,t.runId);for(const r of s.files)r.path.startsWith("files/")&&n.add(r.sha256)}return ae(oe(e),n,ce)}function oe(e){const n=u.join(U(e),Q,"sha256");return c.existsSync(n)?c.readdirSync(n,{withFileTypes:!0}).filter(t=>t.isFile()).map(t=>{const s=u.join(n,t.name);return{bytes:c.statSync(s).size,digest:t.name,path:s}}):[]}function ae(e,n,t){const s=[];let r=0,o=0;for(const i of e){if(n.has(i.digest))continue;let a=null;try{t(i.path)}catch(m){a=L(m)}!c.existsSync(i.path)?(r+=1,o+=i.bytes):a===null&&(a="Object still exists after removal completed"),a!==null&&s.push({error:a,path:i.path})}return{failures:s,reclaimedBytes:o,removedObjects:r,status:s.length===0?"complete":"failed"}}function Ne(e){c.rmSync(e,{recursive:!0,force:!0})}function ce(e){c.rmSync(e,{force:!0})}function Ve({currentRunId:e,decidedAt:n,garbageCollection:t,policy:s,protectedRunIds:r,removed:o,removalErrors:i}){const a=[...i.map(f=>`remove ${f.runId}: ${f.error}`),...t.failures.map(f=>`garbage collect ${f.path}: ${f.error}`)];return{currentRunId:e,decidedAt:n,garbageCollection:t,policy:s,protectedRunIds:r,removed:o,removalErrors:i,schemaVersion:he,status:a.length===0?"complete":"failed",...a.length===0?{}:{error:a.join("; ")}}}function De(e,n,t){if(!_e(e,n)){for(const i of t)if(e.includes(Buffer.from(i.value)))throw new Error(`Refusing to archive binary file containing sensitive environment value: ${n}`);return{buffer:e,scanned:!1,replacements:0}}const s=e.toString("utf8");let r=Y(s),o=r===s?0:1;for(const i of t){if(!r.includes(i.value))continue;const a=r.split(i.value);o+=a.length-1,r=a.join("<redacted>")}return{buffer:Buffer.from(r),scanned:!0,replacements:o}}function Te(e){const n=[];for(const[t,s]of Object.entries(e))Ie.test(t)&&typeof s=="string"&&s.length>=8&&n.push({key:t,value:s});return n}function _e(e,n){if(e.includes(0))return!1;const t=u.extname(n).toLowerCase();return![".zip",".gz",".png",".jpg",".jpeg",".webm",".pdf"].includes(t)}function Fe(e,n){const t=u.resolve(e,n);return!t.startsWith(`${u.resolve(e)}${u.sep}`)||!c.existsSync(t)||!c.statSync(t).isFile()?null:{path:X(u.relative(e,t)),bytes:c.statSync(t).size,sha256:F(t)}}function ze(e){const n=[];for(const t of[...W.map(s=>u.join(e,s)),u.join(e,"live.json")])try{c.rmSync(t,{recursive:!0,force:!0})}catch(s){n.push(`${t}: ${L(s)}`)}return n.length===0?{status:"complete"}:{error:n.join("; "),status:"failed"}}function L(e){try{return k(e)}catch{return"Unknown post-seal archive operation failure"}}
|
|
1
|
+
import{recordWork as J}from"../kernel/work-metrics.js";import{isUnknownRecord as A,optionalString as H}from"../kernel/unknown-values.js";import{posixPath as K}from"../process/files/paths.js";import{readRunProvenance as oe}from"./read-provenance.js";import{parseRunBundleArtifact as ae,parseRunBundleManifest as Y,readRunBundleArtifact as ce}from"./read-bundle.js";import{readRunDocument as ue}from"./read-run.js";import{runModel as G}from"./run-model.js";import le from"crypto";import a from"fs";import u from"path";import{redactRunText as fe,redactRunValue as me,runRedaction as de}from"./redaction.js";import{BUNDLE_SCHEMA_VERSION as Q,OBJECTS_DIRNAME as X,PROVENANCE_SCHEMA_VERSION as pe,RETENTION_DECISION_SCHEMA_VERSION as he,RUNS_DIRNAME as ye}from"./contracts.js";import{bundleRelativePath as $,hashFile as z,normalizeRunId as I,optionalStringArray as D,optionalUnknownArray as ge,readJsonFile as x,requirePublicationPathOutsideResults as _,requireRunId as ve,runIncludesFile as Se,resolveManifestEntryPath as Z,resolveRunBundleDirectory as P,resolveRunsRoot as N,resultsRoot as T,sanitizeSegment as Re,sha256 as O,stableJson as M,treeBytes as ee,walkFiles as te,writeBufferAtomic as je,writeJson as C}from"./storage.js";import{resolveCiProvenance as be}from"./ci-provenance.js";import{errorMessage as B}from"../kernel/error-serialization.js";const U=["artifacts","logs","setup"],we=["package.json","package-lock.json","npm-shrinkwrap.json","pnpm-lock.yaml","yarn.lock","testkit.config.ts","testkit.config.mts","testkit.config.js","testkit.config.mjs"];export function sealRunBundle(e,n,t={},r={}){const s=n,o=ve(s),i=N(e,!0),c=u.dirname(i),f=u.join(i,o),l=r.cleanupActiveRunResults??_e,p=loadVerifiedRunBundleArtifactIfExists(e,o);if(p!==null)return{...p,archive:{...p.archive,cleanup:l(c)}};const m=u.join(i,`.${o}.${String(process.pid)}.${String(Date.now())}.${le.randomBytes(4).toString("hex")}.tmp`);a.mkdirSync(m,{recursive:!0});try{const S=de(t),y=Ie({productDir:e,resultsDir:c,runId:o,tempDir:m,redaction:S}),h=Be(s,o,S.targets),v=ue(h.artifact,"run artifact");y.redaction.structuredReplacements=h.replacements,y.redaction.replacements+=h.replacements;const g=ke(e,v,o,{...t,redaction:y.redaction}),j={schemaVersion:Q,runId:o,status:"complete",canonicalRunPath:$(o,"run.json"),manifestPath:$(o,"manifest.json"),provenancePath:$(o,"provenance.json"),integrity:"sha256",publication:{configured:!!t.archiveConfig?.publication,status:t.archiveConfig?.publication?"pending":"not_configured"},redaction:y.redaction};v.archive=j,C(u.join(m,"run.json"),v),C(u.join(m,"provenance.json"),g);const b=Ae(m),V=O(Buffer.from(M(b))),E={schemaVersion:Q,runId:o,createdAt:new Date().toISOString(),algorithm:"sha256",files:b,storage:{fileCount:b.length,logicalBytes:b.reduce((d,R)=>d+R.bytes,0),objectBytesWritten:y.objectBytesWritten,deduplicatedBytes:y.deduplicatedBytes},redaction:y.redaction,digest:V};return C(u.join(m,"manifest.json"),E),a.renameSync(m,f),{...v,archive:{...j,cleanup:l(c),manifestDigest:E.digest,storage:E.storage}}}catch(S){try{a.rmSync(m,{recursive:!0,force:!0})}catch{}try{Pe(e)}catch{}throw S}}export function loadVerifiedRunBundleArtifactIfExists(e,n){const t=I(n),r=P(e,t);if(!a.existsSync(r))return null;const s=verifyRunBundle(e,t);if(!s.ok)throw new Error(`Immutable run bundle ${t} already exists but failed integrity verification: ${s.errors.join("; ")}`);return loadRunBundleArtifact(e,t)}export function loadRunBundleArtifact(e,n){return ne(e,n).artifact}function ne(e,n){const t=I(n),r=ce(e,t),s=loadRunBundleManifest(e,t);return{manifest:s,artifact:{...r,archive:{...r.archive,manifestDigest:s.digest,storage:s.storage}}}}export function loadRunBundleManifest(e,n){const t=I(n),r=P(e,t),s=u.join(r,"manifest.json");if(!a.existsSync(s))throw new Error(`No immutable Testkit run manifest found for ${t}`);return Y(x(s),s,t)}export function listRunBundles(e,n={}){return q(e,n).map(({artifact:t,manifest:r,...s})=>s)}function q(e,n={}){const t=N(e,!1);if(!a.existsSync(t))return[];const r=a.readdirSync(t,{withFileTypes:!0});return J("artifacts.runDirectoriesRead",1),J("artifacts.runEntriesVisited",r.length),r.filter(o=>o.isDirectory()&&!o.name.startsWith(".")).map(o=>{try{const{artifact:i,manifest:c}=ne(e,o.name);return n.file&&!Se(G(i),n.file)?null:{artifact:i,manifest:c,runId:o.name,status:i.run.status,startedAt:i.run.startedAt,finishedAt:i.run.finishedAt??null,manifestDigest:i.archive.manifestDigest??null,canonicalRunPath:i.archive.canonicalRunPath}}catch{return null}}).filter(o=>o!==null).sort((o,i)=>(i.finishedAt??i.startedAt??"").localeCompare(o.finishedAt??o.startedAt??""))}export function verifyRunBundle(e,n){const t=I(n);try{return F(P(e,t),t)}catch(r){return{ok:!1,runId:t,errors:[B(r)],checkedFiles:0}}}export function publishRunBundle(e,n,t,r={}){const s=I(n),o=r.writePublicationReceipt??$e;if(!t)return o(e,s,{status:"not_configured",required:!1,target:null,bytesUploaded:0});const i=u.resolve(e,t.directory);try{_(e,i)}catch(m){return o(e,s,{status:"failed",required:t.required,target:i,error:B(m),bytesUploaded:0})}const c=Re(u.basename(e)),f=u.join(i,c),l=u.join(f,s),p=u.join(f,`.${s}.${String(process.pid)}.${String(Date.now())}.tmp`);try{const m=P(e,s);if(a.mkdirSync(f,{recursive:!0}),_(e,f),a.existsSync(l)){const h=a.lstatSync(l);if(h.isSymbolicLink()||!h.isDirectory())throw new Error("Publication target must be a regular bundle directory");_(e,l);const v=F(m,s);if(!v.ok)throw new Error(`Source run bundle failed integrity verification: ${v.errors.join("; ")}`);const g=F(l,s);if(!g.ok)throw new Error(`Publication target failed integrity verification: ${g.errors.join("; ")}`);if(v.manifestDigest!==g.manifestDigest)throw new Error("Publication target already exists with a different manifest digest");return o(e,s,{status:"complete",required:t.required,target:l,manifestDigest:v.manifestDigest,reused:!0,bundleBytes:ee(m),bytesUploaded:0})}const S=ee(m);a.cpSync(m,p,{recursive:!0,preserveTimestamps:!0});const y=F(p,s);if(!y.ok)throw new Error(y.errors.join("; "));return a.renameSync(p,l),o(e,s,{status:"complete",required:t.required,target:l,manifestDigest:y.manifestDigest,reused:!1,bundleBytes:S,bytesUploaded:S})}catch(m){return a.rmSync(p,{recursive:!0,force:!0}),o(e,s,{status:"failed",required:t.required,target:l,error:B(m),bytesUploaded:0})}}export function applyRunBundleRetention(e,n,t={},r={}){const s=I(n),o=r.removeObject??ie,i=r.removeRunBundle??Ce,c=t.maxRuns??null,f=t.maxAgeDays??null,l=new Set(t.preserveSuites||[]),p=q(e),m=new Set([s]);for(const d of p)xe(G(d.artifact),l)&&m.add(d.runId);const S=new Set(c?p.slice(0,c).map(d=>d.runId):p.map(d=>d.runId)),y=f==null?null:Date.now()-f*24*60*60*1e3,h=[];for(const d of p){if(m.has(d.runId))continue;const R=y!=null&&Date.parse(d.finishedAt||d.startedAt||"")<y,w=!S.has(d.runId);if(!R&&!w)continue;const k=[];R&&k.push("max_age"),w&&k.push("max_runs"),h.push({path:u.join(T(e),ye,d.runId),reasons:k,runId:d.runId})}const v=se(e),g=[],j=[];for(const d of h){let R=null;try{i(d.path)}catch(k){R=L(k)}const w=!a.existsSync(d.path);!w&&R===null&&(R="Run bundle still exists after removal completed"),w&&g.push({reasons:d.reasons,runId:d.runId}),R!==null&&j.push({...d,error:R,removed:w})}const b=new Set(g.map(d=>d.runId)),V=re(e,v,o,p.filter(d=>!b.has(d.runId))),E=new Date().toISOString();return Fe({currentRunId:s,decidedAt:E,garbageCollection:V,policy:{maxRuns:c,maxAgeDays:f,preserveSuites:[...l].sort()},protectedRunIds:[...m].sort(),removed:g,removalErrors:j})}function Ie({resultsDir:e,tempDir:n,redaction:t}){let r=0,s=0,o=0,i=0,c=0;const f=u.join(e,X,"sha256");a.mkdirSync(f,{recursive:!0});for(const l of U){const p=u.join(e,l);if(a.existsSync(p))for(const m of te(p)){const S=u.relative(p,m),y=a.readFileSync(m),h=Ve(y,m,t.targets);h.scanned&&(o+=1),h.replacements>0&&(i+=1,c+=h.replacements);const v=O(h.buffer),g=u.join(f,v);a.existsSync(g)?s+=h.buffer.length:(je(g,h.buffer),a.chmodSync(g,292),r+=h.buffer.length);const j=u.join(n,"files",l,S);a.mkdirSync(u.dirname(j),{recursive:!0});try{a.linkSync(g,j)}catch{a.copyFileSync(g,j)}}}return{objectBytesWritten:r,deduplicatedBytes:s,redaction:{policyVersion:1,status:t.status,textualFilesScanned:o,filesRedacted:i,replacements:c,sensitiveEnvironmentKeys:t.keys,valuesStored:!1}}}function Be(e,n,t){const r=new Map(U.map(i=>[`.testkit/results/${i}/`,`${$(n,`files/${i}`)}/`])),s=W(e,r),o=me(Ee(s),t);return{artifact:o.value,replacements:o.replacements}}function Ee(e){if(!A(e))return e;const n={...e};if(A(n.product)){const t={...n.product};delete t.directory,n.product=t}if(A(n.git)){const t={...n.git};delete t.remoteUrl,delete t.repoRoot,delete t.worktreePath,n.git=t}return delete n.host,n}function W(e,n){if(Array.isArray(e))return e.map(r=>W(r,n));if(A(e))return Object.fromEntries(Object.entries(e).map(([r,s])=>[r,W(s,n)]));if(typeof e!="string")return e;let t=e;for(const[r,s]of n)t.startsWith(r)&&(t=`${s}${t.slice(r.length)}`);return t}function ke(e,n,t,r){const s=D(n.run.fileNames),o=[...new Set([...we,...s])].map(i=>De(e,i)).filter(i=>i!==null);return{schemaVersion:pe,runId:t,ci:be(r.env??process.env),source:{git:n.git??null,files:o},runtime:{controller:{testkitVersion:H(n.run.testkitVersion),node:process.versions.node,platform:process.platform,architecture:process.arch},runtimeStats:n.schemaVersion===19?ge(n.run.runtimeStats):[...n.environment?.capacity?.runtimeStats??[]]},scenario:{types:D(n.run.types),suiteSelectors:D(n.run.suiteSelectors),fileNames:s,serviceFilter:H(n.schemaVersion===19?n.run.serviceFilter:n.run.groupFilter),planningDigest:O(Buffer.from(M(n.planning??null))),declaredEnvironmentKeys:[...new Set(r.declaredEnvironmentKeys??[])].sort()},redaction:r.redaction}}function Ae(e){return te(e).map(n=>({path:K(u.relative(e,n)),bytes:a.statSync(n).size,sha256:z(n)})).sort((n,t)=>n.path.localeCompare(t.path))}function F(e,n){const t=u.join(e,"manifest.json"),r=Y(x(t),t,n);ae(x(u.join(e,"run.json")),u.join(e,"run.json"),n);const s=[];for(const i of r.files){let c;try{c=Z(e,i.path)}catch(l){s.push(B(l));continue}if(!a.existsSync(c)){s.push(`missing ${i.path}`);continue}const f=a.lstatSync(c);if(f.isSymbolicLink()){s.push(`symbolic link not allowed ${i.path}`);continue}if(!f.isFile()){s.push(`not a regular file ${i.path}`);continue}f.size!==i.bytes&&s.push(`size mismatch ${i.path}`),z(c)!==i.sha256&&s.push(`checksum mismatch ${i.path}`)}O(Buffer.from(M(r.files)))!==r.digest&&s.push("manifest digest mismatch"),r.storage.fileCount!==r.files.length&&s.push("manifest file count mismatch");for(const i of["run.json","provenance.json"])r.files.some(c=>c.path===i)||s.push(`manifest must include ${i}`);if(s.length===0){const i=Z(e,"provenance.json");oe(x(i),i,n)}return{runId:n,checkedFiles:r.files.length,storage:r.storage,ok:s.length===0,errors:s,manifestDigest:r.digest}}function $e(e,n,t){const r={schemaVersion:1,runId:n,recordedAt:new Date().toISOString(),...t};return C(u.join(T(e),"publications",`${n}.json`),r),r}function xe(e,n){return n.size===0?!1:e.groups.some(t=>t.suites.some(r=>{const s=r.testType??"";return[r.name,`${s}:${r.name}`,`${t.name}/${s}:${r.name}`].some(i=>n.has(i))}))}function Pe(e){return re(e,se(e),ie,q(e))}function re(e,n,t,r){const s=N(e,!1),o=new Map(r.map(l=>[l.runId,l.manifest])),i=new Set,c=[],f=a.existsSync(s)?a.readdirSync(s,{withFileTypes:!0}):[];for(const l of f)if(!(!l.isDirectory()||l.name.startsWith(".")))try{for(const p of(o.get(l.name)??loadRunBundleManifest(e,l.name)).files)p.path.startsWith("files/")&&i.add(p.sha256)}catch(p){c.push({error:`No stored object was removed: ${B(p)}`,path:u.join(s,l.name)})}return c.length>0?{failures:c,reclaimedBytes:0,removedObjects:0,status:"not_started"}:Oe(n,i,t)}function se(e){const n=u.join(T(e),X,"sha256");return a.existsSync(n)?a.readdirSync(n,{withFileTypes:!0}).filter(t=>t.isFile()).map(t=>{const r=u.join(n,t.name);return{bytes:a.statSync(r).size,digest:t.name,path:r}}):[]}function Oe(e,n,t){const r=[];let s=0,o=0;for(const i of e){if(n.has(i.digest))continue;let c=null;try{t(i.path)}catch(l){c=L(l)}!a.existsSync(i.path)?(s+=1,o+=i.bytes):c===null&&(c="Object still exists after removal completed"),c!==null&&r.push({error:c,path:i.path})}return{failures:r,reclaimedBytes:o,removedObjects:s,status:r.length===0?"complete":"failed"}}function Ce(e){a.rmSync(e,{recursive:!0,force:!0})}function ie(e){a.rmSync(e,{force:!0})}function Fe({currentRunId:e,decidedAt:n,garbageCollection:t,policy:r,protectedRunIds:s,removed:o,removalErrors:i}){const c=[...i.map(f=>`remove ${f.runId}: ${f.error}`),...t.failures.map(f=>`garbage collect ${f.path}: ${f.error}`)];return{currentRunId:e,decidedAt:n,garbageCollection:t,policy:r,protectedRunIds:s,removed:o,removalErrors:i,schemaVersion:he,status:c.length===0?"complete":"failed",...c.length===0?{}:{error:c.join("; ")}}}function Ve(e,n,t){if(!ze(e,n)){for(const s of t)if(e.includes(Buffer.from(s)))throw new Error(`Refusing to archive binary file containing sensitive environment value: ${n}`);return{buffer:e,scanned:!1,replacements:0}}const r=fe(e.toString("utf8"),t);return r.replacements===0?{buffer:e,scanned:!0,replacements:0}:{buffer:Buffer.from(r.text),scanned:!0,replacements:r.replacements}}function ze(e,n){if(e.includes(0))return!1;const t=u.extname(n).toLowerCase();return![".zip",".gz",".png",".jpg",".jpeg",".webm",".pdf"].includes(t)}function De(e,n){const t=u.resolve(e,n);return!t.startsWith(`${u.resolve(e)}${u.sep}`)||!a.existsSync(t)||!a.statSync(t).isFile()?null:{path:K(u.relative(e,t)),bytes:a.statSync(t).size,sha256:z(t)}}function _e(e){const n=[];for(const t of[...U.map(r=>u.join(e,r)),u.join(e,"live.json")])try{a.rmSync(t,{recursive:!0,force:!0})}catch(r){n.push(`${t}: ${L(r)}`)}return n.length===0?{status:"complete"}:{error:n.join("; "),status:"failed"}}function L(e){try{return B(e)}catch{return"Unknown post-seal archive operation failure"}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{formatError as v}from"../kernel/error-serialization.js";import{jsonRedactionTargets as E,orderRedactionTargets as B,sensitiveKeyMatcher as I}from"../kernel/redaction-targets.js";import{redactUrlSecrets as C}from"../process/url-redaction.js";import{redactedRunValue as K}from"./redaction.js";export function publishEnvironmentRecord(a){return{...a,acquisitions:a.acquisitions.map(o=>({...o,settledAt:O(o.settledAt),setups:o.setups.map(p=>({...p,settledAt:O(p.settledAt),startedAt:new Date(p.startedAt).toISOString()})),startedAt:new Date(o.startedAt).toISOString()})),dbBackend:a.groups.some(o=>o.dbBackend==="local")?"local":null}}function O(a){return a===null?null:new Date(a).toISOString()}export function createRunEnvironmentRecord(a={}){const o=[],p=[],h=[],R=new Set,b=I(a.redactKeys);let y=[],m={instanceCount:0,resourceBudgets:[],runtimeStats:[]},k=null;const g=a.now??Date.now,f=()=>{a.onPublishedChange?.()},w=(e,t)=>({releaseFailed(r){e.releaseErrors.push(v(r)),e.failingReleases.add(t),e.releaseReported=!0},released(){e.failingReleases.delete(t),e.releaseReported=!0}});return{redactKeys:a.redactKeys??[],service({runtimeLabel:e,serviceName:t}){let r=null;return{recordAttempt({baseUrl:u,outcome:s,port:n,readyUrl:l}){const c={baseUrl:u===null?null:C(u),readyUrl:l===null?null:C(l)};r===null&&(r={serviceName:t,runtimeLabel:e,...c,port:n,attempts:[]},o.push(r)),Object.assign(r,c,{port:n}),r.attempts.push({port:n,outcome:s}),f()},amendLastOutcome(u){const s=r?.attempts.at(-1);s&&(s.outcome=u,f())}}},acquisition({graphKey:e,leaseId:t,source:r,tasks:u}){const s={source:r,graphKey:e,leaseId:t,runtimeId:null,services:[],status:"pending",startedAt:g(),settledAt:null,error:null,releaseErrors:[],failingReleases:new Set,releaseReported:!1,setups:[],tasks:u.map(l=>({...l})),values:null};p.push(s);const n=({runtimeId:l,services:c})=>{s.runtimeId=l,s.services=c.map(i=>({...i}))};return{...w(s,"source"),assigned:n,acquired(l){n(l),s.status="acquired",s.settledAt=g()},cancelled(l){s.status="cancelled",s.error=v(l),s.settledAt??=g()},failed(l){s.status="failed",s.error=v(l),s.settledAt??=g()},rendered(l){s.values=l,f()},setup({module:l,task:c}){const i={error:null,module:l,releaseErrors:[],releaseReported:!1,settledAt:null,startedAt:g(),status:"pending",task:{...c}};s.setups.push(i);const S=(d,A)=>{i.status=d,i.error=A===null?null:v(A),i.settledAt??=g()};return{prepared(d){S("prepared",null);for(const A of E("setupData",d,b))R.add(A);s.values!==null&&(s.values={...s.values,setupData:d}),f()},failed(d){S("failed",d)},cancelled(d){S("cancelled",d)},releaseFailed(d){i.releaseErrors.push(v(d)),i.releaseReported=!0},released(){i.releaseReported=!0}}}}},releaseFor(e){const t=p.find(r=>r.leaseId===e);return t===void 0?null:w(t,"lease")},recordCapacity({instanceCount:e,resourceBudgets:t}){m={...m,instanceCount:e,resourceBudgets:[...t]},f()},recordRuntimeStats(e){m={...m,runtimeStats:[...e]},f()},recordGroups(e){y=e.map(t=>({...t}))},recordMissingValues(e,t){for(const{kind:r,valueName:u}of t)h.push({kind:r,task:{...e},valueName:u})},recordCleanup(e){k=e==null?{status:"released"}:{status:"failed",errors:[v(e)],recovered:!1}},addRedactionTarget(e){e.length>0&&R.add(e)},redactionTargets(){return[...R]},snapshot(){const e={acquisitions:p.map(({failingReleases:t,releaseErrors:r,releaseReported:u,...s})=>({...s,services:s.services.map(n=>({...n})),setups:s.setups.map(({releaseErrors:n,releaseReported:l,...c})=>({...c,task:{...c.task},release:n.length>0?{status:"failed",errors:[...n],recovered:!1}:l?{status:"released"}:null})),tasks:s.tasks.map(n=>({...n})),values:s.values,release:r.length>0?{status:"failed",errors:[...r],recovered:t.size===0}:u?{status:"released"}:null})),capacity:{instanceCount:m.instanceCount,resourceBudgets:[...m.resourceBudgets],runtimeStats:[...m.runtimeStats]},cleanup:L(k),groups:y.map(t=>({...t})),logs:{services:a.logRegistry?.listServiceLogs()??[],setup:a.logRegistry?.listSetupLogs()??[]},missingValues:h.map(t=>({...t,task:{...t.task}})),services:o.map(t=>({...t,attempts:t.attempts.map(r=>({...r}))})).sort((t,r)=>t.runtimeLabel.localeCompare(r.runtimeLabel)||t.serviceName.localeCompare(r.serviceName)),setupOperations:a.setupRegistry?.listOperations()??[]};return K(e,B(R))}}}function L(a){return a===null||a.status==="released"?a:{status:"failed",errors:[...a.errors],recovered:a.recovered}}
|
package/dist/evidence/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{normalizeArtifactArchiveConfig}from"./artifact-config.js";export{finalizeLiveRunArtifact,loadTimings,persistTaskArtifacts,persistTaskFileArtifacts,persistTaskOutputArtifacts,resetResultArtifacts,saveTimings,writeLiveRunArtifact,writeRunArtifact}from"./artifacts.js";export{applyRunBundleRetention,listRunBundles,loadRunBundleArtifact,loadRunBundleManifest,loadVerifiedRunBundleArtifactIfExists,publishRunBundle,sealRunBundle,verifyRunBundle}from"./bundles.js";export{collectArtifactEntries,loadCurrentRunArtifact,loadLatestRunArtifact,loadRunArtifact}from"./reading.js";export{DEFAULT_REPORTED_ARCHIVE_CONFIG}from"./reporting-types.js";export{copyRegularFileSecurely,MAX_PERSISTED_FILE_ARTIFACT_BYTES}from"./secure-file-copy.js";export{collectTestkitStorageInventory}from"./storage-inventory.js";export{}from"./timing.js";
|
|
1
|
+
export{normalizeArtifactArchiveConfig}from"./artifact-config.js";export{finalizeLiveRunArtifact,loadTimings,persistTaskArtifacts,persistTaskFileArtifacts,persistTaskOutputArtifacts,resetResultArtifacts,saveTimings,writeLiveRunArtifact,writeRunArtifact}from"./artifacts.js";export{applyRunBundleRetention,listRunBundles,loadRunBundleArtifact,loadRunBundleManifest,loadVerifiedRunBundleArtifactIfExists,publishRunBundle,sealRunBundle,verifyRunBundle}from"./bundles.js";export{collectArtifactEntries,loadCurrentRunArtifact,loadLatestRunArtifact,loadRun,loadRunArtifact}from"./reading.js";export{DEFAULT_REPORTED_ARCHIVE_CONFIG}from"./reporting-types.js";export{runModel}from"./run-model.js";export{copyRegularFileSecurely,MAX_PERSISTED_FILE_ARTIFACT_BYTES}from"./secure-file-copy.js";export{collectTestkitStorageInventory}from"./storage-inventory.js";export{}from"./timing.js";
|
package/dist/evidence/logs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import p from"fs";import
|
|
2
|
-
`)},listServiceLogs(){return[...m.values()].map(e=>({serviceName:e.serviceName,runtimeLabel:e.runtimeLabel,path:e.path})).sort((e,t)=>e.serviceName.localeCompare(t.serviceName)||e.runtimeLabel.localeCompare(t.runtimeLabel))},listSetupLogs(){return[...s.values()].map(e=>({serviceName:e.serviceName,runtimeLabel:e.runtimeLabel,stage:e.stage,path:e.path})).sort((e,t)=>e.serviceName.localeCompare(t.serviceName)||e.runtimeLabel.localeCompare(t.runtimeLabel)||e.stage.localeCompare(t.stage))},async closeAll(){await Promise.all([...n].map(e=>$(e)))}}}function
|
|
1
|
+
import p from"fs";import u from"path";import{posixPath as b}from"../process/files/paths.js";const S="logs",N="setup";export function createRunLogRegistry(r){const m=new Map,s=new Map,n=new Set;function L(e){const t=u.join(r,e.path);p.mkdirSync(u.dirname(t),{recursive:!0});const a=p.createWriteStream(t,{fd:p.openSync(t,"a"),flags:"a"});return n.add(a),{...e,write(o){a.write(o)}}}return{ensureServiceLogRecord(e){const t=`${e.runtimeLabel||e.name}:${e.name}`,a=m.get(t);if(a)return a;const o=`${i(e.runtimeLabel||e.name)}__${i(e.name)}.log`,c=u.join(".testkit","results",S,o),l=L({serviceName:e.name,runtimeLabel:e.runtimeLabel||e.name,path:b(c)});return m.set(t,l),l},ensureSetupLogRecord(e,t){const a=`${e.runtimeLabel||e.name}:${e.name}:${t}`,o=s.get(a);if(o)return o;const c=`${i(e.runtimeLabel||e.name)}__${i(e.name)}__${i(t)}.log`,l=u.join(".testkit","results",N,c),v=L({serviceName:e.name,runtimeLabel:e.runtimeLabel||e.name,stage:t,path:b(l)});return s.set(a,v),v},append(e,t,a){!e||typeof a!="string"||e.write(`${new Date().toISOString()} [${t}] ${a}
|
|
2
|
+
`)},listServiceLogs(){return[...m.values()].map(e=>({serviceName:e.serviceName,runtimeLabel:e.runtimeLabel,path:e.path})).sort((e,t)=>e.serviceName.localeCompare(t.serviceName)||e.runtimeLabel.localeCompare(t.runtimeLabel))},listSetupLogs(){return[...s.values()].map(e=>({serviceName:e.serviceName,runtimeLabel:e.runtimeLabel,stage:e.stage,path:e.path})).sort((e,t)=>e.serviceName.localeCompare(t.serviceName)||e.runtimeLabel.localeCompare(t.runtimeLabel)||e.stage.localeCompare(t.stage))},async closeAll(){await Promise.all([...n].map(e=>$(e)))}}}function i(r){return r.trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"log"}function $(r){return!r||r.destroyed||r.closed?Promise.resolve():new Promise(m=>{let s=!1;const n=()=>{s||(s=!0,r.off("close",n),r.off("error",n),m())};r.once("close",n),r.once("error",n),r.end()})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{performance as
|
|
1
|
+
import{performance as M}from"node:perf_hooks";import{attachErrorOperation as R}from"../kernel/error-serialization.js";import{formatOperationSummary as x}from"../domain/operation-display.js";import{isUnknownRecord as k}from"../kernel/unknown-values.js";const g=String;export function createOperationTimingRegistry({onChange:t=null}={}){const r=[],i=new Map;let m=1;function d(e=[]){if(!t)return;const a=[],u=new Set;for(const s of e)!s||u.has(s.id)||(u.add(s.id),a.push(p(s)));t(a,I())}function f({name:e,kind:a="operation",source:u="testkit",summary:s=null,scope:o=null,parentId:n=null,metadata:l=null}){const c={id:`operation-${g(m++)}`,source:u,name:D(e),kind:a,summary:s,scope:h(o),parentId:n,status:"running",startedAt:new Date().toISOString(),updatedAt:null,finishedAt:null,durationMs:null,error:null,message:null,logRefs:[],metadata:h(l),_startedMonotonicMs:M.now()};return r.push(c),i.set(c.id,c),d([c,...w(c)]),c}function A(e,{summary:a,message:u,metadata:s=null,logRefs:o=null}={}){const n=typeof e=="string"?i.get(e):e;return n?(n.updatedAt=new Date().toISOString(),a!==void 0&&(n.summary=a),u!==void 0&&(n.message=u),s!==null&&(n.metadata={...n.metadata,...h(s)}),o!==null&&(n.logRefs=S(o)),d([n,...w(n)]),p(n)):null}function O(e,{status:a="passed",summary:u,error:s=null,metadata:o=null}={}){const n=typeof e=="string"?i.get(e):e;return n?(n.finishedAt=new Date().toISOString(),n.updatedAt=n.finishedAt,n.durationMs=Math.max(0,Math.round(M.now()-n._startedMonotonicMs)),n.status=a,u!==void 0&&(n.summary=u),s!==null&&(n.error=g(s)),o!==null&&(n.metadata={...n.metadata,...h(o)}),d([n,...w(n)]),p(n)):null}function $(e={}){const a=b(e,m++),u=i.get(a.id);return u?(Object.assign(u,a),d([u,...w(u)]),p(u)):(r.push(a),i.set(a.id,a),d([a,...w(a)]),p(a))}function I(){return r.map(e=>p(e))}return{start:f,update:A,finish:O,record:$,listOperations:I,countOperations(){return r.length}};function w(e){if(!e.parentId)return[];const a=[],u=new Date().toISOString();let s=i.get(e.parentId);const o=new Set([e.id]);for(;s&&s.status==="running"&&!o.has(s.id);){o.add(s.id),s.updatedAt=u;const n=e.status||"unknown",l=n==="running"?"activeChild":"lastChild";s.message=z(e),s.metadata={...s.metadata,[`${l}OperationId`]:e.id,[`${l}OperationName`]:e.name,[`${l}OperationKind`]:e.kind,[`${l}OperationStatus`]:n,[`${l}OperationSummary`]:e.summary||""},a.push(s),s=s.parentId?i.get(s.parentId):void 0}return a}}export async function timeOperation(t,r,i){if(!t)return i();const m=t.start(r);try{const d=await i(m);return t.finish(m,{status:"passed"}),d}catch(d){const f=t.finish(m,{status:"failed",error:N(d)});throw R(d,f),d}}function b(t,r){const i=y(t.startedAt)||new Date().toISOString(),m=t.status||"passed",d=m==="running"?null:y(t.finishedAt)||i,f=t.durationMs,A=Number(f),O=f!=null&&Number.isFinite(A)?Math.max(0,Math.round(A)):d?Math.max(0,Date.parse(d)-Date.parse(i)):null;return{id:t.id||`operation-${g(r)}`,source:t.source||"testkit",name:D(t.name),kind:t.kind||"operation",summary:t.summary||null,scope:h(t.scope),parentId:t.parentId||null,status:m,startedAt:i,updatedAt:y(t.updatedAt)||null,finishedAt:d,durationMs:O,error:t.error||null,message:t.message||null,logRefs:S(t.logRefs),metadata:h(t.metadata),_startedMonotonicMs:M.now()-(O||0)}}function p(t){return{id:t.id,source:t.source,name:t.name,kind:t.kind,summary:t.summary,scope:t.scope,parentId:t.parentId,status:t.status,startedAt:t.startedAt,updatedAt:t.updatedAt,finishedAt:t.finishedAt,durationMs:t.durationMs,error:t.error,message:t.message,logRefs:S(t.logRefs),metadata:t.metadata}}function D(t){const r=g(t||"").trim();if(!r)throw new Error("operation timing name is required");return r}function h(t){return k(t)?{...t}:{}}function S(t){return Array.isArray(t)?t.map(r=>k(r)?{...r}:r):[]}function z(t){const r=x(t),i=typeof r=="string"?r:"";return i?`${t.name} ${t.status||"unknown"} - ${i}`:`${t.name} ${t.status||"unknown"}`}function y(t){const r=Date.parse(t||"");return Number.isFinite(r)?new Date(r).toISOString():null}function N(t){return(typeof t!="object"||t===null)&&typeof t!="function"?g(t):Reflect.get(t,"message")||g(t)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import i from"path";export function requireObjectRecord(r,n){if(!
|
|
1
|
+
import i from"path";import{isUnknownRecord as u}from"../kernel/unknown-values.js";export function requireObjectRecord(r,n){if(!u(r))throw new Error(`${n} must be an object`);return r}export function requireUnknownArray(r,n){if(!Array.isArray(r))throw new Error(`${n} must be an array`);return r}export function requireString(r,n){if(typeof r!="string"||r.length===0)throw new Error(`${n} must be a non-empty string`);return r}export function requireResultsReferencePath(r,n){const e=requireString(r,n),t=e.split("/");if(i.isAbsolute(e)||i.win32.isAbsolute(e)||e.includes("\\")||e.includes("\0")||i.posix.normalize(e)!==e||t.some(o=>o==="."||o==="..")||!e.startsWith(".testkit/results/"))throw new Error(`${n} must be a normalized relative path within .testkit/results`);return e}export function optionalStringValue(r,n){if(r!==void 0){if(typeof r!="string")throw new Error(`${n} must be a string`);return r}}export function optionalNullableStringValue(r,n){if(r!==void 0){if(r===null)return null;if(typeof r!="string")throw new Error(`${n} must be a string or null`);return r}}export function requireNumber(r,n){if(typeof r!="number"||!Number.isFinite(r))throw new Error(`${n} must be a finite number`);return r}export function optionalNumberOrStringValue(r,n){if(r!==void 0)return typeof r=="string"?r:requireNumber(r,n)}export function optionalNullableNumberValue(r,n){if(r!==void 0)return r===null?null:requireNumber(r,n)}export function requireExactString(r,n,e){const t=requireString(r,n);if(t!==e)throw new Error(`${n} must be "${e}"`);return t}export function requireSha256(r,n){const e=requireString(r,n);if(!/^[a-f0-9]{64}$/u.test(e))throw new Error(`${n} must be a lowercase SHA-256 digest`);return e}export function requireManifestRelativePath(r,n){const e=requireString(r,n),t=e.split("/");if(i.isAbsolute(e)||i.win32.isAbsolute(e)||e.includes("\\")||e.includes("\0")||i.posix.normalize(e)!==e||t.some(o=>o==="."||o===".."))throw new Error(`${n} must be a normalized relative bundle path`);return e}export function requireNonNegativeNumber(r,n){if(typeof r!="number"||!Number.isFinite(r)||r<0)throw new Error(`${n} must be a non-negative number`);return r}export function requireNonNegativeInteger(r,n){const e=requireNonNegativeNumber(r,n);if(!Number.isInteger(e))throw new Error(`${n} must be a non-negative integer`);return e}export function optionalNonNegativeNumber(r,n){if(r!==void 0)return requireNonNegativeNumber(r,n)}export function optionalNullableNumber(r,n){return r==null?null:requireNonNegativeNumber(r,n)}export function requireBoolean(r,n){if(typeof r!="boolean")throw new Error(`${n} must be a boolean`);return r}export function optionalBoolean(r,n){if(r!==void 0)return requireBoolean(r,n)}export function requireStringArray(r,n){if(!Array.isArray(r))throw new Error(`${n} must be an array of strings`);const e=[];for(const t of r){if(typeof t!="string")throw new Error(`${n} must be an array of strings`);e.push(t)}return e}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isEngineId as w,isPublicTestType as q,isRunnerProfileId as S}from"../domain/identifiers.js";import{isEngineProfileIdentity as T}from"../engines/definitions.js";import{requireObjectRecord as r,requireNumber as m,requireStringArray as B,optionalBoolean as y,optionalNonNegativeNumber as p,isObjectRecord as E,requireUnknownArray as h,requireString as c,requireResultsReferencePath as k,optionalStringValue as s,optionalNullableStringValue as a,optionalNumberOrStringValue as L,optionalNullableNumberValue as v}from"./read-fields.js";export function readRunDocument(n,t){const e=r(n,t);if(e.schemaVersion!==19)throw new Error(`${t}.schemaVersion must be 19`);const i=M(e.run,`${t}.run`),o=f(e.services,`${t}.services`,P)??[];e.archive!==void 0&&r(e.archive,`${t}.archive`),e.finalizationFailure!==void 0&&X(e.finalizationFailure,`${t}.finalizationFailure`),s(e.generatedAt,`${t}.generatedAt`);const d=K(e.summary,`${t}.summary`),u=e.logs===void 0?void 0:x(e.logs,`${t}.logs`),g=e.setup===void 0?void 0:V(e.setup,`${t}.setup`);return{...e,schemaVersion:19,...d===void 0?{}:{summary:d},run:i,services:o,...u===void 0?{}:{logs:u},...g===void 0?{}:{setup:g}}}function M(n,t){const e=r(n,t);return v(e.durationMs,`${t}.durationMs`),f(e.types,`${t}.types`,c),{...e,finishedAt:a(e.finishedAt,`${t}.finishedAt`)??null,id:a(e.id,`${t}.id`)??null,startedAt:c(e.startedAt,`${t}.startedAt`),status:c(e.status,`${t}.status`)}}function x(n,t){const e=r(n,t),i=f(e.services,`${t}.services`,H),o=f(e.setup,`${t}.setup`,F);return{...e,...i===void 0?{}:{services:i},...o===void 0?{}:{setup:o}}}function V(n,t){const e=r(n,t),i=f(e.operations,`${t}.operations`,J);return{...e,...i===void 0?{}:{operations:i}}}function P(n,t){const e=r(n,t),i=f(e.suites,`${t}.suites`,D)??[];return{...e,name:c(e.name,`${t}.name`),suites:i}}function D(n,t){const e=r(n,t);if(e.testType!=="scenario"&&!q(e.testType))throw new Error(`${t}.testType must be a public test type`);if(!w(e.engineId))throw new Error(`${t}.engineId must be a supported engine id`);if(!S(e.profileId))throw new Error(`${t}.profileId must be a supported runner profile id`);if(!(e.testType==="scenario"?e.engineId==="k6"&&e.profileId==="k6-http":T(e)))throw new Error(`${t}.profileId does not match ${e.engineId}/${e.testType}`);const o=f(e.files,`${t}.files`,O);return y(e.failed,`${t}.failed`),A(e.diagnostics,`${t}.diagnostics`),p(e.completedFileCount,`${t}.completedFileCount`),p(e.failedFileCount,`${t}.failedFileCount`),p(e.fileCount,`${t}.fileCount`),p(e.passedFileCount,`${t}.passedFileCount`),p(e.skippedFileCount,`${t}.skippedFileCount`),{...e,files:o,name:c(e.name,`${t}.name`),testType:e.testType,engineId:e.engineId,profileId:e.profileId}}function O(n,t){const e=r(n,t),i=f(e.artifacts,`${t}.artifacts`,j),o=f(e.failureDetails,`${t}.failureDetails`,z);return y(e.blockedByRuntime,`${t}.blockedByRuntime`),y(e.failed,`${t}.failed`),y(e.infraFailed,`${t}.infraFailed`),a(e.reason,`${t}.reason`),a(e.runtimeIsolation,`${t}.runtimeIsolation`),e.runtimeBatch!=null&&Q(e.runtimeBatch,`${t}.runtimeBatch`),f(e.runtimeResets,`${t}.runtimeResets`,W),{...e,error:a(e.error,`${t}.error`),artifacts:i,durationMs:v(e.durationMs,`${t}.durationMs`),failureDetails:o,path:c(e.path,`${t}.path`),status:c(e.status,`${t}.status`)}}function j(n,t){const e=r(n,t);return{...e,contentType:a(e.contentType,`${t}.contentType`),kind:a(e.kind,`${t}.kind`),summary:a(e.summary,`${t}.summary`),name:c(e.name,`${t}.name`),path:k(e.path,`${t}.path`)}}function z(n,t){const e=r(n,t),i=e.request===void 0?void 0:U(e.request,`${t}.request`),o=e.response===void 0?void 0:G(e.response,`${t}.response`),d=e.location===void 0?void 0:r(e.location,`${t}.location`);return d!==void 0&&(s(d.path,`${t}.location.path`),d.line!==void 0&&m(d.line,`${t}.location.line`),d.column!==void 0&&m(d.column,`${t}.location.column`)),{...e,key:s(e.key,`${t}.key`),kind:s(e.kind,`${t}.kind`),message:s(e.message,`${t}.message`),stack:s(e.stack,`${t}.stack`),location:d,request:i,response:o,title:c(e.title,`${t}.title`)}}function U(n,t){const e=r(n,t);return{...e,method:s(e.method,`${t}.method`),path:s(e.path,`${t}.path`),requestId:s(e.requestId,`${t}.requestId`)}}function G(n,t){const e=r(n,t);return{...e,bodyPreview:s(e.bodyPreview,`${t}.bodyPreview`),contentType:s(e.contentType,`${t}.contentType`),status:L(e.status,`${t}.status`)}}function H(n,t){const e=r(n,t);return{...e,path:k(e.path,`${t}.path`),runtimeLabel:c(e.runtimeLabel,`${t}.runtimeLabel`),serviceName:c(e.serviceName,`${t}.serviceName`)}}function J(n,t){const e=r(n,t),i=e.logRef==null?e.logRef:F(e.logRef,`${t}.logRef`);return{...e,durationMs:v(e.durationMs,`${t}.durationMs`),error:a(e.error,`${t}.error`),summary:a(e.summary,`${t}.summary`),logRef:i,serviceName:c(e.serviceName,`${t}.serviceName`),stage:c(e.stage,`${t}.stage`),startedAt:s(e.startedAt,`${t}.startedAt`),status:c(e.status,`${t}.status`)}}function F(n,t){const e=r(n,t);return s(e.runtimeLabel,`${t}.runtimeLabel`),s(e.serviceName,`${t}.serviceName`),s(e.stage,`${t}.stage`),{...e,path:k(e.path,`${t}.path`)}}function K(n,t){if(n===void 0)return;const e=r(n,t),i=e.files===void 0?{}:r(e.files,`${t}.files`),o=e.services===void 0?{}:r(e.services,`${t}.services`),d=e.suites===void 0?{}:r(e.suites,`${t}.suites`),u=(g,I,N)=>{const $=g[I];if($===void 0)return 0;if(typeof $!="number"||!Number.isFinite($)||$<0)throw new Error(`${t}.${N}.${I} must be a non-negative finite number`);return $};return A(e.diagnostics,`${t}.diagnostics`),{...e,files:{blockedByRuntime:u(i,"blockedByRuntime","files"),cancelled:u(i,"cancelled","files"),failed:u(i,"failed","files"),infraFailed:u(i,"infraFailed","files"),interrupted:u(i,"interrupted","files"),notRun:u(i,"notRun","files"),passed:u(i,"passed","files"),skipped:u(i,"skipped","files"),total:u(i,"total","files")},services:{blockedByRuntime:u(o,"blockedByRuntime","services"),failed:u(o,"failed","services"),infraFailed:u(o,"infraFailed","services"),passed:u(o,"passed","services"),skipped:u(o,"skipped","services"),total:u(o,"total","services")},suites:{completed:u(d,"completed","suites"),failed:u(d,"failed","suites"),passed:u(d,"passed","suites"),skipped:u(d,"skipped","suites"),total:u(d,"total","suites")}}}function A(n,t){if(n!==void 0)return h(n,t).map((e,i)=>{const o=`${t}[${String(i)}]`,d=r(e,o);return{...d,code:c(d.code,`${o}.code`),message:c(d.message,`${o}.message`),service:s(d.service,`${o}.service`),suite:s(d.suite,`${o}.suite`)}})}function Q(n,t){const e=r(n,t);return{...e,id:s(e.id,`${t}.id`),fileCount:p(e.fileCount,`${t}.fileCount`),index:p(e.index,`${t}.index`),files:e.files===void 0?void 0:B(e.files,`${t}.files`)}}function W(n,t){const e=r(n,t);return{...e,position:s(e.position,`${t}.position`),reason:s(e.reason,`${t}.reason`),runtimeIsolation:s(e.runtimeIsolation,`${t}.runtimeIsolation`),trigger:s(e.trigger,`${t}.trigger`)}}function X(n,t){const e=r(n,t),i=e.operation===void 0?void 0:r(e.operation,`${t}.operation`);return{...e,name:c(e.name,`${t}.name`),message:c(e.message,`${t}.message`),code:s(e.code,`${t}.code`),stack:s(e.stack,`${t}.stack`),phase:s(e.phase,`${t}.phase`),exitCode:e.exitCode===void 0?void 0:m(e.exitCode,`${t}.exitCode`),status:e.status===void 0?void 0:m(e.status,`${t}.status`),diagnostics:e.diagnostics===void 0?void 0:R(e.diagnostics,`${t}.diagnostics`),operation:i===void 0?void 0:{...i,id:s(i.id,`${t}.operation.id`),source:c(i.source,`${t}.operation.source`),name:c(i.name,`${t}.operation.name`),kind:c(i.kind,`${t}.operation.kind`),summary:s(i.summary,`${t}.operation.summary`),status:s(i.status,`${t}.operation.status`),error:s(i.error,`${t}.operation.error`),scope:R(i.scope,`${t}.operation.scope`)}}}function R(n,t){return Object.fromEntries(Object.entries(r(n,t)).map(([e,i])=>[e,C(i,`${t}.${e}`)]))}function C(n,t){return n===null||typeof n=="string"||typeof n=="boolean"?n:Array.isArray(n)?h(n,t).map((e,i)=>C(e,`${t}[${String(i)}]`)):E(n)?R(n,t):m(n,t)}function f(n,t,e){return n===void 0?void 0:h(n,t).map((i,o)=>e(i,`${t}[${String(o)}]`))}
|
|
1
|
+
import{isEngineId as O,isPublicTestType as U,isRunnerProfileId as x}from"../domain/identifiers.js";import{isEngineProfileIdentity as P}from"../engines/definitions.js";import{isUnknownRecord as z}from"../kernel/unknown-values.js";import{requireObjectRecord as u,requireNumber as g,requireStringArray as j,optionalBoolean as I,optionalNonNegativeNumber as y,requireUnknownArray as k,requireString as c,requireResultsReferencePath as R,optionalStringValue as o,optionalNullableStringValue as m,optionalNumberOrStringValue as _,optionalNullableNumberValue as F}from"./read-fields.js";export function readRunDocument(t,e){const n=u(t,e);if(n.schemaVersion===19)return H(n,e);if(n.schemaVersion===20)return G(n,e);throw new Error(`${e}.schemaVersion must be 19 or 20`)}function G(t,e){const n=w(t.run,`${e}.run`),i=a(t.groups,`${e}.groups`,(d,p)=>C(d,p,!0))??[];N(t,e);const s=t.summary===void 0?void 0:D(t.summary,`${e}.summary`,"group"),r=t.environment===void 0?void 0:J(t.environment,`${e}.environment`);return{...t,schemaVersion:20,...s===void 0?{}:{summary:{...s.record,files:s.files,groups:s.owners,suites:s.suites}},run:n,groups:i,...r===void 0?{}:{environment:r}}}function H(t,e){const n=w(t.run,`${e}.run`),i=a(t.services,`${e}.services`,C)??[];N(t,e);const s=t.summary===void 0?void 0:D(t.summary,`${e}.summary`,"service"),r=t.environment===void 0?void 0:K(t.environment,`${e}.environment`),d=t.logs===void 0?void 0:E(t.logs,`${e}.logs`),p=t.setup===void 0?void 0:Q(t.setup,`${e}.setup`);return{...t,schemaVersion:19,...s===void 0?{}:{summary:{...s.record,files:s.files,services:s.owners,suites:s.suites}},run:n,services:i,...r===void 0?{}:{environment:r},...d===void 0?{}:{logs:d},...p===void 0?{}:{setup:p}}}function w(t,e){const n=u(t,e);return F(n.durationMs,`${e}.durationMs`),a(n.types,`${e}.types`,c),{...n,finishedAt:m(n.finishedAt,`${e}.finishedAt`)??null,id:m(n.id,`${e}.id`)??null,startedAt:c(n.startedAt,`${e}.startedAt`),status:c(n.status,`${e}.status`)}}function N(t,e){t.archive!==void 0&&u(t.archive,`${e}.archive`),t.finalizationFailure!==void 0&&se(t.finalizationFailure,`${e}.finalizationFailure`),o(t.generatedAt,`${e}.generatedAt`)}function J(t,e){const n=u(t,e),i=n.capacity===void 0?void 0:u(n.capacity,`${e}.capacity`),s=i?.runtimeStats===void 0?void 0:k(i.runtimeStats,`${e}.capacity.runtimeStats`),r=n.logs===void 0?void 0:E(n.logs,`${e}.logs`),d=a(n.services,`${e}.services`,A),p=a(n.setupOperations,`${e}.setupOperations`,q);return{...n,...i===void 0?{}:{capacity:{...i,...s===void 0?{}:{runtimeStats:s}}},...r===void 0?{}:{logs:r},...d===void 0?{}:{services:d},...p===void 0?{}:{setupOperations:p}}}function K(t,e){const n=u(t,e),i=a(n.services,`${e}.services`,A);return{...n,...i===void 0?{}:{services:i}}}function A(t,e){const n=u(t,e);return{...n,attempts:a(n.attempts,`${e}.attempts`,(i,s)=>{const r=u(i,s);return{...r,outcome:c(r.outcome,`${s}.outcome`),port:g(r.port,`${s}.port`)}})??[],baseUrl:m(n.baseUrl,`${e}.baseUrl`)??null,port:g(n.port,`${e}.port`),readyUrl:m(n.readyUrl,`${e}.readyUrl`)??null,runtimeLabel:c(n.runtimeLabel,`${e}.runtimeLabel`),serviceName:c(n.serviceName,`${e}.serviceName`)}}function E(t,e){const n=u(t,e),i=a(n.services,`${e}.services`,ne),s=a(n.setup,`${e}.setup`,B);return{...n,...i===void 0?{}:{services:i},...s===void 0?{}:{setup:s}}}function Q(t,e){const n=u(t,e),i=a(n.operations,`${e}.operations`,q);return{...n,...i===void 0?{}:{operations:i}}}function C(t,e,n=!1){const i=u(t,e),s=a(i.suites,`${e}.suites`,(r,d)=>X(r,d,n))??[];return{...i,name:c(i.name,`${e}.name`),suites:s}}const W=Object.freeze([...["int","e2e","load","scenario"].map(t=>({engineId:"k6",profileId:"k6-http",testType:t})),{engineId:"k6",profileId:"k6-dal",testType:"dal"},{engineId:"node-vitest",profileId:"node-vitest-contract",testType:"contract"},{engineId:"node-vitest",profileId:"node-vitest-data",testType:"data"}]);function X(t,e,n){const i=u(t,e),s=W.find($=>$.testType===i.testType),r=s?.testType??(U(i.testType)?i.testType:void 0);if(r===void 0&&!(n&&i.testType===void 0))throw new Error(`${e}.testType must be a public test type`);const d=s!==void 0&&i.engineId===s.engineId?s.engineId:O(i.engineId)?i.engineId:void 0;if(d===void 0)throw new Error(`${e}.engineId must be a supported engine id`);const p=s!==void 0&&i.profileId===s.profileId?s.profileId:x(i.profileId)?i.profileId:void 0;if(p===void 0)throw new Error(`${e}.profileId must be a supported runner profile id`);if(!(s===void 0?P(i):d===s.engineId&&p===s.profileId))throw new Error(`${e}.profileId does not match ${d}/${r??"untyped"}`);const f=a(i.files,`${e}.files`,Y);return I(i.failed,`${e}.failed`),L(i.diagnostics,`${e}.diagnostics`),y(i.completedFileCount,`${e}.completedFileCount`),y(i.failedFileCount,`${e}.failedFileCount`),y(i.fileCount,`${e}.fileCount`),y(i.passedFileCount,`${e}.passedFileCount`),y(i.skippedFileCount,`${e}.skippedFileCount`),{...i,files:f,name:c(i.name,`${e}.name`),...r===void 0?{}:{testType:r},engineId:d,profileId:p}}function Y(t,e){const n=u(t,e),i=a(n.artifacts,`${e}.artifacts`,Z),s=a(n.failureDetails,`${e}.failureDetails`,l);return I(n.blockedByRuntime,`${e}.blockedByRuntime`),I(n.failed,`${e}.failed`),I(n.infraFailed,`${e}.infraFailed`),m(n.reason,`${e}.reason`),m(n.runtimeIsolation,`${e}.runtimeIsolation`),n.runtimeBatch!=null&&te(n.runtimeBatch,`${e}.runtimeBatch`),a(n.runtimeResets,`${e}.runtimeResets`,ie),{...n,error:m(n.error,`${e}.error`),artifacts:i,durationMs:F(n.durationMs,`${e}.durationMs`),failureDetails:s,path:c(n.path,`${e}.path`),status:c(n.status,`${e}.status`)}}function Z(t,e){const n=u(t,e);return{...n,contentType:m(n.contentType,`${e}.contentType`),kind:m(n.kind,`${e}.kind`),summary:m(n.summary,`${e}.summary`),name:c(n.name,`${e}.name`),path:R(n.path,`${e}.path`)}}function l(t,e){const n=u(t,e),i=n.request===void 0?void 0:b(n.request,`${e}.request`),s=n.response===void 0?void 0:ee(n.response,`${e}.response`),r=n.location===void 0?void 0:u(n.location,`${e}.location`);return r!==void 0&&(o(r.path,`${e}.location.path`),r.line!==void 0&&g(r.line,`${e}.location.line`),r.column!==void 0&&g(r.column,`${e}.location.column`)),{...n,key:o(n.key,`${e}.key`),kind:o(n.kind,`${e}.kind`),message:o(n.message,`${e}.message`),stack:o(n.stack,`${e}.stack`),location:r,request:i,response:s,title:c(n.title,`${e}.title`)}}function b(t,e){const n=u(t,e);return{...n,method:o(n.method,`${e}.method`),path:o(n.path,`${e}.path`),requestId:o(n.requestId,`${e}.requestId`)}}function ee(t,e){const n=u(t,e);return{...n,bodyPreview:o(n.bodyPreview,`${e}.bodyPreview`),contentType:o(n.contentType,`${e}.contentType`),status:_(n.status,`${e}.status`)}}function ne(t,e){const n=u(t,e);return{...n,path:R(n.path,`${e}.path`),runtimeLabel:c(n.runtimeLabel,`${e}.runtimeLabel`),serviceName:c(n.serviceName,`${e}.serviceName`)}}function q(t,e){const n=u(t,e),i=n.logRef==null?n.logRef:B(n.logRef,`${e}.logRef`);return{...n,durationMs:F(n.durationMs,`${e}.durationMs`),error:m(n.error,`${e}.error`),summary:m(n.summary,`${e}.summary`),logRef:i,serviceName:c(n.serviceName,`${e}.serviceName`),stage:c(n.stage,`${e}.stage`),startedAt:o(n.startedAt,`${e}.startedAt`),status:c(n.status,`${e}.status`)}}function B(t,e){const n=u(t,e);return o(n.runtimeLabel,`${e}.runtimeLabel`),o(n.serviceName,`${e}.serviceName`),o(n.stage,`${e}.stage`),{...n,path:R(n.path,`${e}.path`)}}function D(t,e,n){const i=u(t,e),s=n==="group"?"groups":"services",r=$=>i[$]===void 0?{}:u(i[$],`${e}.${$}`),[d,p,h]=[r("files"),r(s),r("suites")],f=($,T,M)=>{const v=$[T];if(v===void 0)return 0;if(typeof v!="number"||!Number.isFinite(v)||v<0)throw new Error(`${e}.${M}.${T} must be a non-negative finite number`);return v};return L(i.diagnostics,`${e}.diagnostics`),{record:i,files:{blockedByRuntime:f(d,"blockedByRuntime","files"),cancelled:f(d,"cancelled","files"),failed:f(d,"failed","files"),infraFailed:f(d,"infraFailed","files"),interrupted:f(d,"interrupted","files"),notRun:f(d,"notRun","files"),passed:f(d,"passed","files"),skipped:f(d,"skipped","files"),total:f(d,"total","files")},owners:{blockedByRuntime:f(p,"blockedByRuntime",s),failed:f(p,"failed",s),infraFailed:f(p,"infraFailed",s),passed:f(p,"passed",s),skipped:f(p,"skipped",s),total:f(p,"total",s)},suites:{completed:f(h,"completed","suites"),failed:f(h,"failed","suites"),passed:f(h,"passed","suites"),skipped:f(h,"skipped","suites"),total:f(h,"total","suites")}}}function L(t,e){if(t!==void 0)return k(t,e).map((n,i)=>{const s=`${e}[${String(i)}]`,r=u(n,s);return{...r,code:c(r.code,`${s}.code`),group:o(r.group,`${s}.group`),message:c(r.message,`${s}.message`),service:o(r.service,`${s}.service`),suite:o(r.suite,`${s}.suite`)}})}function te(t,e){const n=u(t,e);return{...n,id:o(n.id,`${e}.id`),fileCount:y(n.fileCount,`${e}.fileCount`),index:y(n.index,`${e}.index`),files:n.files===void 0?void 0:j(n.files,`${e}.files`)}}function ie(t,e){const n=u(t,e);return{...n,position:o(n.position,`${e}.position`),reason:o(n.reason,`${e}.reason`),runtimeIsolation:o(n.runtimeIsolation,`${e}.runtimeIsolation`),trigger:o(n.trigger,`${e}.trigger`)}}function se(t,e){const n=u(t,e),i=n.operation===void 0?void 0:u(n.operation,`${e}.operation`);return{...n,name:c(n.name,`${e}.name`),message:c(n.message,`${e}.message`),code:o(n.code,`${e}.code`),stack:o(n.stack,`${e}.stack`),phase:o(n.phase,`${e}.phase`),exitCode:n.exitCode===void 0?void 0:g(n.exitCode,`${e}.exitCode`),status:n.status===void 0?void 0:g(n.status,`${e}.status`),diagnostics:n.diagnostics===void 0?void 0:S(n.diagnostics,`${e}.diagnostics`),operation:i===void 0?void 0:{...i,id:o(i.id,`${e}.operation.id`),source:c(i.source,`${e}.operation.source`),name:c(i.name,`${e}.operation.name`),kind:c(i.kind,`${e}.operation.kind`),summary:o(i.summary,`${e}.operation.summary`),status:o(i.status,`${e}.operation.status`),error:o(i.error,`${e}.operation.error`),scope:S(i.scope,`${e}.operation.scope`)}}}function S(t,e){return Object.fromEntries(Object.entries(u(t,e)).map(([n,i])=>[n,V(i,`${e}.${n}`)]))}function V(t,e){return t===null||typeof t=="string"||typeof t=="boolean"?t:Array.isArray(t)?k(t,e).map((n,i)=>V(n,`${e}[${String(i)}]`)):z(t)?S(t,e):g(t,e)}function a(t,e,n){return t===void 0?void 0:k(t,e).map((i,s)=>n(i,`${e}[${String(s)}]`))}
|
package/dist/evidence/reading.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isWorkObserved as
|
|
1
|
+
import{isWorkObserved as S,recordWork as p}from"../kernel/work-metrics.js";import a from"fs";import{posixPath as g}from"../process/files/paths.js";import u from"path";import{normalizeEngineJsonValue as R}from"../engines/api/index.js";import{readJsonFile as h}from"./storage.js";import{loadRunBundleArtifact as A}from"./bundles.js";import{readRunDocument as y}from"./read-run.js";import{runModel as x}from"./run-model.js";import{requireObjectRecord as P,requireResultsReferencePath as E,optionalStringValue as w,optionalNullableStringValue as f}from"./read-fields.js";export function loadLatestRunArtifact(e){const t=u.join(e,".testkit","results","latest.json");if(!a.existsSync(t))throw new Error(`No run artifact found at ${u.relative(e,t)}`);return y(h(t),t)}export function loadLatestRun(e){return x(loadLatestRunArtifact(e))}export function loadCurrentRunArtifact(e){const t=u.join(e,".testkit","results","live.json");return a.existsSync(t)?y(h(t),t):loadLatestRunArtifact(e)}export function loadRunArtifact(e,t=null){return t?A(e,t):loadLatestRunArtifact(e)}export function loadRun(e,t=null){return x(loadRunArtifact(e,t))}export function resolveFileSubject(e,t=null,n=null){const r=v(e,n);if(r.length===0)throw new Error("No file results were found in the latest run artifact.");if(!t)return r.find(s=>s.file.status==="failed")||r[0];const o=g(t),i=r.filter(s=>s.file.path===o);if(i.length===1)return i[0];if(i.length>1)throw new Error(`Multiple files matched "${t}". Re-run with --service to disambiguate.`);const l=r.filter(s=>s.file.path.endsWith(`/${o}`));if(l.length===1)return l[0];throw l.length>1?new Error(`Multiple files matched "${t}". Re-run with --service to disambiguate.`):new Error(`No file matched "${t}".`)}export function collectArtifactEntries(e,t,n=null,r=null,o,i=!0){const l=n?[resolveFileSubject(t,n,r)]:v(t,r),s=[];for(const d of l)for(const c of d.file.artifacts||[]){if(o&&c.kind!==o)continue;const m=N(e,c.path,`artifact "${c.name}" path`),k=i&&a.existsSync(m)?j(m,c):null;s.push({...d,artifactRef:c,absolutePath:m,payload:k})}return s}function j(e,t){let n;if(S()){const o=a.readFileSync(e);p("artifacts.payloadFilesRead",1),p("artifacts.payloadBytesRead",o.byteLength),n=o.toString("utf8")}else n=a.readFileSync(e,"utf8");const r=t.contentType||"";if(r==="text/markdown"||r==="text/plain")return{contentType:r,kind:t.kind||null,name:t.name||null,summary:t.summary||null,text:n};try{const o=JSON.parse(n);return T(o,e)}catch{return{contentType:r||"text/plain",kind:t.kind||null,name:t.name||null,summary:t.summary||null,text:n}}}function v(e,t=null){const n=[];for(const r of e.groups)if(!(t&&r.name!==t))for(const o of r.suites)for(const i of o.files)n.push({group:r,suite:o,file:i});return n}function T(e,t){const n=P(e,t),r=w(n.emittedAt,`${t}.emittedAt`);return{...n,contentType:f(n.contentType,`${t}.contentType`),...n.data===void 0?{}:{data:R(n.data,`${t}.data`)},...r===void 0?{}:{emittedAt:r},kind:f(n.kind,`${t}.kind`),name:f(n.name,`${t}.name`),summary:f(n.summary,`${t}.summary`),text:w(n.text,`${t}.text`)}}function N(e,t,n){const r=E(t,n),o=u.resolve(e,".testkit","results"),i=u.resolve(e,r);if($(o,i,n),a.existsSync(i)){const l=a.realpathSync(o),s=a.realpathSync(i);$(l,s,n)}return i}function $(e,t,n){const r=u.relative(e,t);if(r.length===0||r===".."||r.startsWith(`..${u.sep}`)||u.isAbsolute(r))throw new Error(`${n} must resolve within .testkit/results`)}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{REDACTED as f,redactSensitiveText as m,SENSITIVE_KEY_PATTERN as E,sensitiveTextRanges as R}from"../kernel/redaction.js";import{isRedactionTarget as A,MIN_REDACTION_TARGET_LENGTH as N,orderRedactionTargets as _,redactionTargetSpans as S,replaceRedactionTargets as T,sensitiveKeyMatcher as I,urlRedactionTargets as L}from"../kernel/redaction-targets.js";import{isUnknownRecord as y}from"../kernel/unknown-values.js";import{recordWork as J}from"../kernel/work-metrics.js";const K=8,k="\uE010",P=new Set(["data","details","dimensions","metadata","native"]);export function runRedaction({env:e=process.env,redactKeys:n,redactionTargets:t}={}){const s=I(n),c=Object.entries(e).filter(r=>s(r[0])&&typeof r[1]=="string"&&A(r[1]));return{keys:c.map(([r])=>r).sort(),status:t===void 0?"source-targets-unavailable":"applied",targets:_([...c.flatMap(([,r])=>[r,...L(r)]),...t??[]])}}export function redactRunText(e,n){return redactJsonText(e,n)??W(e,n)}function W(e,n){const t=D(S(e,n)),s=[];let c=0,r=0;for(let a=0;a<e.length;){const l=e.indexOf(`
|
|
2
|
+
`,a),d=l===-1?e.length:l,p=e[d-1]==="\r"?d-1:d,o=C(e,a,p,n,t);if(o!==null){const u=b(e.slice(r,o.start),n);s.push(u.text,o.text),c+=u.replacements+o.replacements,r=p}a=d+1}const i=b(e.slice(r),n);return s.push(i.text),{replacements:c+i.replacements,text:s.join("")}}function C(e,n,t,s,c){const r=e.slice(n,t).search(/[[{]/u);if(r<0)return null;const i=n+r;if(c(i,t))return null;const a=e.slice(n,i),l=e.slice(i,t);if(m(a+l)!==m(a)+m(l))return null;const d=redactJsonText(l,s);return d===null?null:{...d,start:i}}function D(e){const n=[...e].sort((c,r)=>c.start-r.start);let t=0,s=-1;return(c,r)=>{let i=0;for(;t<n.length&&n[t].start<c;t+=1)s=Math.max(s,n[t].end),i+=1;let a=s>c;for(let l=t;!a&&l<n.length&&n[l].start<r;l+=1)a=n[l].end>r,i+=1;return J("redaction.spanEdgeSteps",i),a}}function b(e,n){let t=e,s=0;for(let c=0;c<K;c+=1){const r=G(t,n);if(r.text===t)return{replacements:s,text:t};s+=Math.max(r.replacements,1),t=r.text}return{replacements:s+1,text:f}}function G(e,n){const t=S(e,n),s=$(e,n);if(t.length===0&&s.length===0){const r=m(e);return{replacements:r===e?0:1,text:r}}const c=T(e,n,r=>k.repeat(r.length)).text;return F(e,[...R(e),...R(c),...t,...s])}const w=new WeakMap;function j(e){let n=w.get(e);return n===void 0&&(n=e.filter(t=>t.includes(k)||V(t)),w.set(e,n)),n}function V(e){if(e.includes(f)||f.includes(e))return!0;for(let n=1;n<f.length;n+=1)if(e.startsWith(f.slice(-n))||e.endsWith(f.slice(0,n)))return!0;return!1}function $(e,n){const t=j(n);if(t.length===0)return[];if(t.some(c=>/[\r\n]/u.test(c)))return g(e,n)?[O(e)]:[];const s=[];for(let c=0;c<=e.length;){const r=e.indexOf(`
|
|
3
|
+
`,c),i=r===-1?e.length:r,a=e[i-1]==="\r"?i-1:i;g(e.slice(c,a),n)&&s.push({end:a,start:c}),c=i+1}return s.length===0&&g(e,n)?[O(e)]:s}function O(e){const n=e.search(/[^\r\n]/u);let t=e.length;for(;t>n&&(e[t-1]===`
|
|
4
|
+
`||e[t-1]==="\r");)t-=1;return n<0?{end:0,start:0}:{end:t,start:n}}function g(e,n){const t=j(n);if(t.length===0||e.length===0)return!1;let s=!1;const c=r=>i=>(t.some(a=>a.startsWith(i))&&(s=!0),r(i));return T(e,n,c(()=>f)),T(m(e),n,c(()=>f)),T(e,n,c(r=>k.repeat(r.length))),s}function F(e,n){const t=[...n].sort((i,a)=>i.start-a.start||a.end-i.end),s=[];let c=0,r=0;for(let i=0;i<t.length;){const a=t[i].start;let l=t[i].end;for(i+=1;i<t.length&&t[i].start<=l;i+=1)l=Math.max(l,t[i].end);s.push(e.slice(c,a),f),e.slice(a,l)!==f&&(r+=1),c=l}return s.push(e.slice(c)),{replacements:r,text:s.join("")}}export function redactRunValue(e,n){let t=0;function s(l){const d=redactRunText(l,n);return t+=d.replacements,d.text}function c(l,d){if(Array.isArray(l))return l.map(p=>c(p,d));if(y(l)){const p=Object.entries(l),o=d?i(p.map(([u])=>u)):p.map(([u])=>u);return Object.fromEntries(p.map(([u,h],v)=>[o[v],d&&typeof h=="string"&&E.test(u)?r(h):c(h,d||P.has(u))]))}return typeof l=="string"?s(l):l}function r(l){return l!==f&&(t+=1),f}function i(l){const d=l.map(o=>redactRunText(o,n)),p=new Set(l.filter((o,u)=>d[u].text===o));return l.map((o,u)=>d[u].text===o?o:(t+=d[u].replacements,M(p,d[u].text)))}const a=c(e,!1);return{replacements:t,value:a}}export function redactedRunValue(e,n){return redactRunValue(e,n).value}export function redactJsonText(e,n){if(!/^\s*[[{"]/u.test(e))return null;try{JSON.parse(e)}catch{return null}const t=Y(e),s=new Set;for(const o of S(e,n)){const u=U(t,o.start,o.end);if(u===void 0)return null;H(e,o,n)||s.add(u)}const c=o=>s.has(o)||g(o.decoded,n)?{replacements:o.decoded===f?0:1,text:f}:redactRunText(o.decoded,n),r=new Map(t.filter(o=>o.key).map(o=>[o,c(o)])),i=new Map;for(const[o,u]of r)o.object===null||u.text!==o.decoded||i.set(o.object,(i.get(o.object)??new Set).add(o.decoded));const a=[];let l=0,d=0;for(const o of t){let u=r.get(o);if(u!==void 0&&u.text!==o.decoded&&o.object!==null){const h=i.get(o.object)??new Set;i.set(o.object,h),u={...u,text:M(h,u.text)}}else u===void 0&&o.member!==null&&E.test(o.member)?u={replacements:o.decoded===f?0:1,text:f}:u===void 0&&(u=c(o));u.text!==o.decoded&&(a.push(e.slice(l,o.start),JSON.stringify(u.text)),l=o.close+1,d+=u.replacements)}a.push(e.slice(l));const p=a.join("");return n.some(o=>p.includes(o))?null:{replacements:d,text:p}}function H(e,n,t){let s=0;for(;e[n.start-1-s]==="\\";)s+=1;if(s%2===1)return!1;const c=e.slice(n.start,n.end);if(!c.includes("\\"))return!0;let r;try{r=JSON.parse(`"${c}"`)}catch{return!1}return n.cut?r.length>=N&&t.some(i=>i.startsWith(r)):t.includes(r)}function U(e,n,t){let s=0,c=e.length-1;for(;s<=c;){const i=s+c>>1;e[i].start<n?s=i+1:c=i-1}const r=e.at(c);return r!==void 0&&r.start<n&&t<=r.close?r:void 0}function Y(e){const n=[],t=[];for(let s=0;s<e.length;s+=1){const c=e[s];if(c==="{"?t.push({id:s,key:null}):c==="["?t.push(null):(c==="}"||c==="]")&&t.pop(),c!=='"')continue;const r=q(e,s),i=JSON.parse(e.slice(s,r+1)),a=t.at(-1)??null,l=a!==null&&x(e,r+1)===":";n.push({close:r,decoded:i,key:l,member:l?null:a?.key??null,object:a?.id??null,start:s}),l&&(a.key=i),s=r}return n}function q(e,n){for(let t=n+1;t<e.length;t+=1)if(e[t]==="\\")t+=1;else if(e[t]==='"')return t;return e.length-1}function x(e,n){for(let t=n;t<e.length;t+=1)if(!/\s/u.test(e[t]))return e[t]}function M(e,n){let t=n;for(let s=2;e.has(t);s++)t=`${n} (${String(s)})`;return e.add(t),t}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import J from"path";import{publishEnvironmentRecord as K}from"./environment-record.js";import{DEFAULT_REPORTED_ARCHIVE_CONFIG as U}from"./reporting-types.js";export function buildRunArtifact({productDir:n,runId:e=null,results:i,startedAt:l,finishedAt:s,execution:o,workerCount:a,typeValues:d,suiteSelectors:R,fileNames:y,groupFilter:b,planning:f=null,archiveConfig:D=null,declaredEnvironmentKeys:M=[],metadata:r,environment:A,operationTimings:w=[],runInterruptReason:m=null,runStatus:B=null}){const u=i.filter(t=>!t.skipped),G=u.filter(S),g=u.filter(t=>t.failed),F=u.filter(t=>t.infraFailed),I=u.filter(t=>t.blockedByRuntime),O=u.filter(t=>Q(t)),C=Z(u),v=W(u),E=c(u,"totalFileCount"),T=c(u,"passedFileCount"),q=c(u,"failedFileCount"),x=c(u,"skippedFileCount"),N=c(u,"notRunFileCount"),k=p(u,t=>t.status==="cancelled"),h=p(u,t=>t.status==="interrupted"),V=Math.max(0,N-k-h),z=p(u,t=>t.infraFailed===!0),H=p(u,t=>t.blockedByRuntime===!0),_=new Date(s??Date.now()).toISOString(),L=s===null?null:new Date(s).toISOString(),P=s===null?null:s-l,j=D??U;return{schemaVersion:20,source:"testkit",generatedAt:_,product:{name:J.basename(n),directory:n},git:{branch:r.git.branch??null,commitSha:r.git.commitSha??null,dirty:r.git.dirty===!0,pullRequest:r.git.pullRequest??null,pullRequestHeadSha:r.git.pullRequestHeadSha??null,repository:r.git.repository??null},host:r.host,run:{id:e,status:B||(g.length>0||F.length>0?"failed":"passed"),startedAt:new Date(l).toISOString(),finishedAt:L,durationMs:P,workers:o.taskConcurrency,fileTimeoutSeconds:o.fileTimeoutSeconds,workerCount:a,types:[...d],suiteSelectors:R.map(t=>t.raw),fileNames:[...y],groupFilter:b,testkitVersion:r.testkitVersion,...m===null?{}:{interruptReason:m}},archive:{request:j,declaredEnvironmentKeys:[...new Set(M)].sort()},...f?{planning:f}:{},summary:{groups:{total:u.length,passed:O.length,failed:g.length,infraFailed:F.length,blockedByRuntime:I.length,skipped:G.length},suites:v,files:{total:E,passed:T,failed:q,skipped:x,notRun:V,cancelled:k,interrupted:h,infraFailed:z,blockedByRuntime:H},...C.length>0?{diagnostics:C}:{}},environment:K(A),timings:{operations:$(w)},groups:i.map(t=>({name:t.name,failed:t.failed,infraFailed:t.infraFailed===!0,blockedByRuntime:t.blockedByRuntime===!0,skipped:t.skipped,suiteCount:t.suiteCount,completedSuiteCount:t.completedSuiteCount,skippedSuiteCount:t.skippedSuiteCount,failedSuiteCount:t.failedSuiteCount,totalFileCount:t.totalFileCount,completedFileCount:t.completedFileCount,passedFileCount:t.passedFileCount,failedFileCount:t.failedFileCount,skippedFileCount:t.skippedFileCount,notRunFileCount:t.notRunFileCount,durationMs:t.durationMs,totalTaskDurationMs:t.totalTaskDurationMs,suites:t.suites,errors:t.errors,...t.diagnostics&&t.diagnostics.length>0?{diagnostics:t.diagnostics}:{},...t.errorDetails&&t.errorDetails.length>0?{errorDetails:t.errorDetails}:{}}))}}export function buildLiveRunArtifact({updatedAt:n,...e}){return{...buildRunArtifact({...e,finishedAt:null,runStatus:"running"}),generatedAt:new Date(n).toISOString()}}function S(n){return!n.skipped&&!n.failed&&n.skippedSuiteCount>0&&n.skippedSuiteCount===n.suiteCount&&n.notRunFileCount===0}function Q(n){return!n.failed&&!n.infraFailed&&!S(n)&&n.notRunFileCount===0}function p(n,e){let i=0;for(const l of n)for(const s of l.suites)for(const o of s.files??[])e(o)&&(i+=1);return i}function W(n){const e={total:0,completed:0,passed:0,failed:0,skipped:0};for(const i of n){const l=i.suites,s=i.suiteCount;if(l.length===0){const o=X(i,s);e.total+=o.total,e.completed+=o.completed,e.passed+=o.passed,e.failed+=o.failed,e.skipped+=o.skipped;continue}e.total+=s;for(const o of l){const a=Y(o);a==="passed"?(e.completed+=1,e.passed+=1):a==="failed"?(e.completed+=1,e.failed+=1):a==="skipped"&&(e.completed+=1,e.skipped+=1)}}return e}function X(n,e){const i=n.failedSuiteCount,l=n.skippedSuiteCount,s=n.completedSuiteCount;return{total:e,completed:s,passed:Math.max(0,s-i-l),failed:i,skipped:l}}function Y(n){const e=n.files??[],i=e.length,l=Math.max(n.fileCount??0,i),s=e.length>0?e.filter(d=>d.status==="failed"||d.failed===!0).length:n.failedFileCount??0,o=e.length>0?e.filter(d=>d.status==="skipped").length:n.skippedFileCount??0,a=e.length>0?e.filter(d=>d.status==="passed").length:n.passedFileCount??0;return s>0||n.failed===!0?"failed":l>0&&o>=l?"skipped":l>0&&a+o>=l?"passed":"pending"}function c(n,e){return n.reduce((i,l)=>i+l[e],0)}function Z(n){const e=[],i=new Set,l=s=>{const o=JSON.stringify(s);i.has(o)||(i.add(o),e.push(s))};for(const s of n){const o=s.diagnostics??[];for(const a of o)l({...a,group:a.group||s.name});if(!(o.length>0))for(const a of s.suites)for(const d of a.diagnostics??[])l({...d,group:d.group||s.name,suite:d.suite||a.name})}return e}function $(n){return n.map(e=>({id:e.id||null,source:e.source||"testkit",name:e.name||"operation",kind:e.kind||"operation",summary:e.summary||null,scope:e.scope?{...e.scope}:{},parentId:e.parentId||null,status:e.status||"unknown",startedAt:e.startedAt||null,updatedAt:e.updatedAt||null,finishedAt:e.finishedAt||null,durationMs:e.durationMs!==null&&e.durationMs!==void 0&&Number.isFinite(e.durationMs)?Math.max(0,Math.round(e.durationMs)):null,error:e.error||null,message:e.message||null,logRefs:(e.logRefs??[]).map(i=>ee(i)?{...i}:i),metadata:e.metadata?{...e.metadata}:{}}))}function ee(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{isUnknownRecord as e}from"../kernel/unknown-values.js";export function runModel(r){return r.schemaVersion===19?u(r):a(r)}function u(r){return{...n(r),groups:r.services.map(t),summary:r.summary===void 0?null:{files:r.summary.files,groups:r.summary.services,suites:r.summary.suites}}}function a(r){return{...n(r),groups:r.groups.map(t),summary:r.summary===void 0?null:{files:r.summary.files,groups:r.summary.groups,suites:r.summary.suites}}}function n(r){return{archive:f(r.archive),finalizationFailure:r.finalizationFailure??null,generatedAt:r.generatedAt??null,git:{commitSha:e(r.git)?p(r.git.commitSha):null},run:{durationMs:r.run.durationMs??null,finishedAt:r.run.finishedAt,id:r.run.id,startedAt:r.run.startedAt,status:r.run.status,types:r.run.types??[]},schemaVersion:r.schemaVersion}}function t(r){return{errors:Array.isArray(r.errors)?r.errors.filter(s=>typeof s=="string"):[],name:r.name,suites:r.suites.map(l)}}function l(r){return{engineId:r.engineId,files:r.files??[],name:r.name,profileId:r.profileId,...r.testType===void 0?{}:{testType:r.testType}}}function f(r){if(!e(r))return{cleanup:null,publication:null};const{cleanup:s,publication:i}=r;return{cleanup:e(s)&&typeof s.status=="string"?{status:s.status}:null,publication:e(i)&&typeof i.status=="string"?{required:i.required===!0,status:i.status}:null}}function p(r){return typeof r=="string"?r:null}
|