@xoxoai/checkmate 0.6.7 → 0.7.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/dist/checkmate.js +13375 -0
- package/package.json +14 -100
- package/plugin/.claude-plugin/plugin.json +10 -0
- package/plugin/bin/checkmate.ts +3 -0
- package/plugin/contracts/finding.schema.json +78 -0
- package/plugin/contracts/gap.schema.json +56 -0
- package/plugin/contracts/plan-candidate.schema.json +103 -0
- package/plugin/contracts/plan-delta.schema.json +63 -0
- package/plugin/contracts/plan-patch.schema.json +116 -0
- package/plugin/contracts/plan-request.schema.json +108 -0
- package/plugin/contracts/plan.schema.json +313 -0
- package/plugin/contracts/profile.schema.json +154 -0
- package/plugin/contracts/response.schema.json +25 -0
- package/plugin/contracts/result.schema.json +410 -0
- package/plugin/dist/checkmate.js +13012 -0
- package/plugin/package.json +4 -0
- package/plugin/references/browser.md +35 -0
- package/plugin/references/http.md +30 -0
- package/plugin/references/workflow.md +122 -0
- package/plugin/skills/execute/SKILL.md +92 -0
- package/plugin/skills/plan/SKILL.md +94 -0
- package/plugin/skills/report/SKILL.md +28 -0
- package/plugin/skills/revise/SKILL.md +43 -0
- package/plugin/skills/setup/SKILL.md +82 -0
- package/plugin/skills/status/SKILL.md +20 -0
- package/plugin/skills/ui/SKILL.md +26 -0
- package/plugin/src/actor.ts +21 -0
- package/plugin/src/cli.ts +1133 -0
- package/plugin/src/contracts.ts +342 -0
- package/plugin/src/index.ts +52 -0
- package/plugin/src/plans.ts +1028 -0
- package/plugin/src/render.ts +544 -0
- package/plugin/src/runs.ts +868 -0
- package/plugin/src/store.ts +384 -0
- package/plugin/src/targets.ts +205 -0
- package/plugin/src/types.ts +319 -0
- package/plugin/src/ui/assets/client.js +501 -0
- package/plugin/src/ui/assets/favicon.svg +1 -0
- package/plugin/src/ui/assets/fonts/inter-OFL.txt +93 -0
- package/plugin/src/ui/assets/fonts/inter.woff2 +0 -0
- package/plugin/src/ui/assets/fonts/jetbrains-mono-OFL.txt +93 -0
- package/plugin/src/ui/assets/fonts/jetbrains-mono.woff2 +0 -0
- package/plugin/src/ui/assets/fonts/space-grotesk-OFL.txt +93 -0
- package/plugin/src/ui/assets/fonts/space-grotesk.woff2 +0 -0
- package/plugin/src/ui/assets/style.css +1926 -0
- package/plugin/src/ui/edit.ts +305 -0
- package/plugin/src/ui/forms.ts +209 -0
- package/plugin/src/ui/html.ts +130 -0
- package/plugin/src/ui/layout.ts +198 -0
- package/plugin/src/ui/lists.ts +645 -0
- package/plugin/src/ui/plan.ts +577 -0
- package/plugin/src/ui/run.ts +489 -0
- package/plugin/src/ui/server.ts +684 -0
- package/plugin/src/validators.d.ts +13 -0
- package/plugin/src/validators.js +1 -0
- package/plugin/src/views.ts +839 -0
- package/LICENSE +0 -21
- package/README.md +0 -294
- package/bin/checkmate.js +0 -13
- package/dist/ai/client.d.ts +0 -64
- package/dist/ai/client.d.ts.map +0 -1
- package/dist/ai/client.js +0 -313
- package/dist/ai/client.js.map +0 -1
- package/dist/ai/message-handler.d.ts +0 -9
- package/dist/ai/message-handler.d.ts.map +0 -1
- package/dist/ai/message-handler.js +0 -50
- package/dist/ai/message-handler.js.map +0 -1
- package/dist/ai/message-history.d.ts +0 -17
- package/dist/ai/message-history.d.ts.map +0 -1
- package/dist/ai/message-history.js +0 -45
- package/dist/ai/message-history.js.map +0 -1
- package/dist/ai/prompts.d.ts +0 -4
- package/dist/ai/prompts.d.ts.map +0 -1
- package/dist/ai/prompts.js +0 -24
- package/dist/ai/prompts.js.map +0 -1
- package/dist/ai/rate-limit-policy.d.ts +0 -9
- package/dist/ai/rate-limit-policy.d.ts.map +0 -1
- package/dist/ai/rate-limit-policy.js +0 -34
- package/dist/ai/rate-limit-policy.js.map +0 -1
- package/dist/ai/tool-response-handler.d.ts +0 -16
- package/dist/ai/tool-response-handler.d.ts.map +0 -1
- package/dist/ai/tool-response-handler.js +0 -85
- package/dist/ai/tool-response-handler.js.map +0 -1
- package/dist/ai/turn-processor.d.ts +0 -34
- package/dist/ai/turn-processor.d.ts.map +0 -1
- package/dist/ai/turn-processor.js +0 -107
- package/dist/ai/turn-processor.js.map +0 -1
- package/dist/api/allocate-run-identity.d.ts +0 -8
- package/dist/api/allocate-run-identity.d.ts.map +0 -1
- package/dist/api/allocate-run-identity.js +0 -10
- package/dist/api/allocate-run-identity.js.map +0 -1
- package/dist/api/execute-prepared-run.d.ts +0 -22
- package/dist/api/execute-prepared-run.d.ts.map +0 -1
- package/dist/api/execute-prepared-run.js +0 -184
- package/dist/api/execute-prepared-run.js.map +0 -1
- package/dist/api/index.d.ts +0 -25
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js +0 -69
- package/dist/api/index.js.map +0 -1
- package/dist/api/prepare-run.d.ts +0 -44
- package/dist/api/prepare-run.d.ts.map +0 -1
- package/dist/api/prepare-run.js +0 -261
- package/dist/api/prepare-run.js.map +0 -1
- package/dist/cli/diagnostic-relay.d.ts +0 -6
- package/dist/cli/diagnostic-relay.d.ts.map +0 -1
- package/dist/cli/diagnostic-relay.js +0 -6
- package/dist/cli/diagnostic-relay.js.map +0 -1
- package/dist/cli/main.d.ts +0 -21
- package/dist/cli/main.d.ts.map +0 -1
- package/dist/cli/main.js +0 -166
- package/dist/cli/main.js.map +0 -1
- package/dist/cli/protocol.d.ts +0 -57
- package/dist/cli/protocol.d.ts.map +0 -1
- package/dist/cli/protocol.js +0 -116
- package/dist/cli/protocol.js.map +0 -1
- package/dist/cli/reconcile-result.d.ts +0 -13
- package/dist/cli/reconcile-result.d.ts.map +0 -1
- package/dist/cli/reconcile-result.js +0 -300
- package/dist/cli/reconcile-result.js.map +0 -1
- package/dist/cli/run-parent.d.ts +0 -37
- package/dist/cli/run-parent.d.ts.map +0 -1
- package/dist/cli/run-parent.js +0 -491
- package/dist/cli/run-parent.js.map +0 -1
- package/dist/cli/signals.d.ts +0 -36
- package/dist/cli/signals.d.ts.map +0 -1
- package/dist/cli/signals.js +0 -85
- package/dist/cli/signals.js.map +0 -1
- package/dist/cli/static-commands.d.ts +0 -11
- package/dist/cli/static-commands.d.ts.map +0 -1
- package/dist/cli/static-commands.js +0 -83
- package/dist/cli/static-commands.js.map +0 -1
- package/dist/cli/worker-stream-guard.d.ts +0 -20
- package/dist/cli/worker-stream-guard.d.ts.map +0 -1
- package/dist/cli/worker-stream-guard.js +0 -41
- package/dist/cli/worker-stream-guard.js.map +0 -1
- package/dist/cli/worker.d.ts +0 -3
- package/dist/cli/worker.d.ts.map +0 -1
- package/dist/cli/worker.js +0 -111
- package/dist/cli/worker.js.map +0 -1
- package/dist/config/ingestion.d.ts +0 -58
- package/dist/config/ingestion.d.ts.map +0 -1
- package/dist/config/ingestion.js +0 -283
- package/dist/config/ingestion.js.map +0 -1
- package/dist/config/manifest.d.ts +0 -20
- package/dist/config/manifest.d.ts.map +0 -1
- package/dist/config/manifest.js +0 -91
- package/dist/config/manifest.js.map +0 -1
- package/dist/config/model-egress.d.ts +0 -10
- package/dist/config/model-egress.d.ts.map +0 -1
- package/dist/config/model-egress.js +0 -62
- package/dist/config/model-egress.js.map +0 -1
- package/dist/config/package-resolution.d.ts +0 -4
- package/dist/config/package-resolution.d.ts.map +0 -1
- package/dist/config/package-resolution.js +0 -24
- package/dist/config/package-resolution.js.map +0 -1
- package/dist/config/policy.d.ts +0 -44
- package/dist/config/policy.d.ts.map +0 -1
- package/dist/config/policy.js +0 -141
- package/dist/config/policy.js.map +0 -1
- package/dist/config/record.d.ts +0 -4
- package/dist/config/record.d.ts.map +0 -1
- package/dist/config/record.js +0 -10
- package/dist/config/record.js.map +0 -1
- package/dist/config/secrets.d.ts +0 -11
- package/dist/config/secrets.d.ts.map +0 -1
- package/dist/config/secrets.js +0 -42
- package/dist/config/secrets.js.map +0 -1
- package/dist/contracts/diagnostics.d.ts +0 -4
- package/dist/contracts/diagnostics.d.ts.map +0 -1
- package/dist/contracts/diagnostics.js +0 -31
- package/dist/contracts/diagnostics.js.map +0 -1
- package/dist/contracts/serialize.d.ts +0 -2
- package/dist/contracts/serialize.d.ts.map +0 -1
- package/dist/contracts/serialize.js +0 -90
- package/dist/contracts/serialize.js.map +0 -1
- package/dist/contracts/types.d.ts +0 -316
- package/dist/contracts/types.d.ts.map +0 -1
- package/dist/contracts/types.js +0 -74
- package/dist/contracts/types.js.map +0 -1
- package/dist/contracts/validator.d.ts +0 -8
- package/dist/contracts/validator.d.ts.map +0 -1
- package/dist/contracts/validator.js +0 -71
- package/dist/contracts/validator.js.map +0 -1
- package/dist/driver.d.ts +0 -97
- package/dist/driver.d.ts.map +0 -1
- package/dist/driver.js +0 -24
- package/dist/driver.js.map +0 -1
- package/dist/drivers/descriptor.d.ts +0 -15
- package/dist/drivers/descriptor.d.ts.map +0 -1
- package/dist/drivers/descriptor.js +0 -122
- package/dist/drivers/descriptor.js.map +0 -1
- package/dist/drivers/loader.d.ts +0 -18
- package/dist/drivers/loader.d.ts.map +0 -1
- package/dist/drivers/loader.js +0 -97
- package/dist/drivers/loader.js.map +0 -1
- package/dist/drivers/web/checkmate-driver.json +0 -47
- package/dist/drivers/web/index.d.ts +0 -6
- package/dist/drivers/web/index.d.ts.map +0 -1
- package/dist/drivers/web/index.js +0 -27
- package/dist/drivers/web/index.js.map +0 -1
- package/dist/drivers/web/session.d.ts +0 -25
- package/dist/drivers/web/session.d.ts.map +0 -1
- package/dist/drivers/web/session.js +0 -132
- package/dist/drivers/web/session.js.map +0 -1
- package/dist/drivers/web/tools/network-request-recorder.d.ts +0 -46
- package/dist/drivers/web/tools/network-request-recorder.d.ts.map +0 -1
- package/dist/drivers/web/tools/network-request-recorder.js +0 -164
- package/dist/drivers/web/tools/network-request-recorder.js.map +0 -1
- package/dist/drivers/web/tools/screenshot-service.d.ts +0 -10
- package/dist/drivers/web/tools/screenshot-service.d.ts.map +0 -1
- package/dist/drivers/web/tools/screenshot-service.js +0 -23
- package/dist/drivers/web/tools/screenshot-service.js.map +0 -1
- package/dist/drivers/web/tools/snapshot-filter/index.d.ts +0 -4
- package/dist/drivers/web/tools/snapshot-filter/index.d.ts.map +0 -1
- package/dist/drivers/web/tools/snapshot-filter/index.js +0 -4
- package/dist/drivers/web/tools/snapshot-filter/index.js.map +0 -1
- package/dist/drivers/web/tools/snapshot-filter/semantic-scorer.d.ts +0 -15
- package/dist/drivers/web/tools/snapshot-filter/semantic-scorer.d.ts.map +0 -1
- package/dist/drivers/web/tools/snapshot-filter/semantic-scorer.js +0 -99
- package/dist/drivers/web/tools/snapshot-filter/semantic-scorer.js.map +0 -1
- package/dist/drivers/web/tools/snapshot-filter/snapshot-filter.d.ts +0 -5
- package/dist/drivers/web/tools/snapshot-filter/snapshot-filter.d.ts.map +0 -1
- package/dist/drivers/web/tools/snapshot-filter/snapshot-filter.js +0 -56
- package/dist/drivers/web/tools/snapshot-filter/snapshot-filter.js.map +0 -1
- package/dist/drivers/web/tools/snapshot-filter/tree-reconstructor.d.ts +0 -3
- package/dist/drivers/web/tools/snapshot-filter/tree-reconstructor.d.ts.map +0 -1
- package/dist/drivers/web/tools/snapshot-filter/tree-reconstructor.js +0 -85
- package/dist/drivers/web/tools/snapshot-filter/tree-reconstructor.js.map +0 -1
- package/dist/drivers/web/tools/snapshot-service.d.ts +0 -31
- package/dist/drivers/web/tools/snapshot-service.d.ts.map +0 -1
- package/dist/drivers/web/tools/snapshot-service.js +0 -96
- package/dist/drivers/web/tools/snapshot-service.js.map +0 -1
- package/dist/drivers/web/tools/tool.d.ts +0 -76
- package/dist/drivers/web/tools/tool.d.ts.map +0 -1
- package/dist/drivers/web/tools/tool.js +0 -562
- package/dist/drivers/web/tools/tool.js.map +0 -1
- package/dist/drivers/web/tools/transient-state-tracker.d.ts +0 -26
- package/dist/drivers/web/tools/transient-state-tracker.d.ts.map +0 -1
- package/dist/drivers/web/tools/transient-state-tracker.js +0 -301
- package/dist/drivers/web/tools/transient-state-tracker.js.map +0 -1
- package/dist/drivers/web/tools/types.d.ts +0 -11
- package/dist/drivers/web/tools/types.d.ts.map +0 -1
- package/dist/drivers/web/tools/types.js +0 -2
- package/dist/drivers/web/tools/types.js.map +0 -1
- package/dist/evidence/atomic-file.d.ts +0 -23
- package/dist/evidence/atomic-file.d.ts.map +0 -1
- package/dist/evidence/atomic-file.js +0 -104
- package/dist/evidence/atomic-file.js.map +0 -1
- package/dist/evidence/layout.d.ts +0 -30
- package/dist/evidence/layout.d.ts.map +0 -1
- package/dist/evidence/layout.js +0 -152
- package/dist/evidence/layout.js.map +0 -1
- package/dist/evidence/retention.d.ts +0 -5
- package/dist/evidence/retention.d.ts.map +0 -1
- package/dist/evidence/retention.js +0 -10
- package/dist/evidence/retention.js.map +0 -1
- package/dist/evidence/store.d.ts +0 -101
- package/dist/evidence/store.d.ts.map +0 -1
- package/dist/evidence/store.js +0 -375
- package/dist/evidence/store.js.map +0 -1
- package/dist/evidence/terminal-finalizer.d.ts +0 -19
- package/dist/evidence/terminal-finalizer.d.ts.map +0 -1
- package/dist/evidence/terminal-finalizer.js +0 -56
- package/dist/evidence/terminal-finalizer.js.map +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -12
- package/dist/index.js.map +0 -1
- package/dist/logging/invocation-logger.d.ts +0 -4
- package/dist/logging/invocation-logger.d.ts.map +0 -1
- package/dist/logging/invocation-logger.js +0 -25
- package/dist/logging/invocation-logger.js.map +0 -1
- package/dist/logging/level-logger.d.ts +0 -11
- package/dist/logging/level-logger.d.ts.map +0 -1
- package/dist/logging/level-logger.js +0 -82
- package/dist/logging/level-logger.js.map +0 -1
- package/dist/logging/types.d.ts +0 -8
- package/dist/logging/types.d.ts.map +0 -1
- package/dist/logging/types.js +0 -7
- package/dist/logging/types.js.map +0 -1
- package/dist/redaction/diagnostic-sanitizer.d.ts +0 -7
- package/dist/redaction/diagnostic-sanitizer.d.ts.map +0 -1
- package/dist/redaction/diagnostic-sanitizer.js +0 -42
- package/dist/redaction/diagnostic-sanitizer.js.map +0 -1
- package/dist/redaction/redactor.d.ts +0 -40
- package/dist/redaction/redactor.d.ts.map +0 -1
- package/dist/redaction/redactor.js +0 -176
- package/dist/redaction/redactor.js.map +0 -1
- package/dist/redaction/scrub.d.ts +0 -29
- package/dist/redaction/scrub.d.ts.map +0 -1
- package/dist/redaction/scrub.js +0 -54
- package/dist/redaction/scrub.js.map +0 -1
- package/dist/runtime/config.d.ts +0 -16
- package/dist/runtime/config.d.ts.map +0 -1
- package/dist/runtime/config.js +0 -2
- package/dist/runtime/config.js.map +0 -1
- package/dist/runtime/driver-boundary.d.ts +0 -16
- package/dist/runtime/driver-boundary.d.ts.map +0 -1
- package/dist/runtime/driver-boundary.js +0 -71
- package/dist/runtime/driver-boundary.js.map +0 -1
- package/dist/runtime/driver-session.d.ts +0 -9
- package/dist/runtime/driver-session.d.ts.map +0 -1
- package/dist/runtime/driver-session.js +0 -64
- package/dist/runtime/driver-session.js.map +0 -1
- package/dist/runtime/internal-step-evidence.d.ts +0 -30
- package/dist/runtime/internal-step-evidence.d.ts.map +0 -1
- package/dist/runtime/internal-step-evidence.js +0 -82
- package/dist/runtime/internal-step-evidence.js.map +0 -1
- package/dist/runtime/result-adapter.d.ts +0 -9
- package/dist/runtime/result-adapter.d.ts.map +0 -1
- package/dist/runtime/result-adapter.js +0 -77
- package/dist/runtime/result-adapter.js.map +0 -1
- package/dist/runtime/runner.d.ts +0 -43
- package/dist/runtime/runner.d.ts.map +0 -1
- package/dist/runtime/runner.js +0 -72
- package/dist/runtime/runner.js.map +0 -1
- package/dist/runtime/scenario-control.d.ts +0 -40
- package/dist/runtime/scenario-control.d.ts.map +0 -1
- package/dist/runtime/scenario-control.js +0 -94
- package/dist/runtime/scenario-control.js.map +0 -1
- package/dist/runtime/scenario-runner.d.ts +0 -41
- package/dist/runtime/scenario-runner.d.ts.map +0 -1
- package/dist/runtime/scenario-runner.js +0 -274
- package/dist/runtime/scenario-runner.js.map +0 -1
- package/dist/runtime/scenario-state.d.ts +0 -55
- package/dist/runtime/scenario-state.d.ts.map +0 -1
- package/dist/runtime/scenario-state.js +0 -128
- package/dist/runtime/scenario-state.js.map +0 -1
- package/dist/runtime/step-execution.d.ts +0 -27
- package/dist/runtime/step-execution.d.ts.map +0 -1
- package/dist/runtime/step-execution.js +0 -143
- package/dist/runtime/step-execution.js.map +0 -1
- package/dist/runtime/text.d.ts +0 -10
- package/dist/runtime/text.d.ts.map +0 -1
- package/dist/runtime/text.js +0 -25
- package/dist/runtime/text.js.map +0 -1
- package/dist/runtime/types.d.ts +0 -53
- package/dist/runtime/types.d.ts.map +0 -1
- package/dist/runtime/types.js +0 -2
- package/dist/runtime/types.js.map +0 -1
- package/dist/runtime/usage-tracker.d.ts +0 -37
- package/dist/runtime/usage-tracker.d.ts.map +0 -1
- package/dist/runtime/usage-tracker.js +0 -110
- package/dist/runtime/usage-tracker.js.map +0 -1
- package/dist/tools/define-agent-tool.d.ts +0 -20
- package/dist/tools/define-agent-tool.d.ts.map +0 -1
- package/dist/tools/define-agent-tool.js +0 -30
- package/dist/tools/define-agent-tool.js.map +0 -1
- package/dist/tools/dispatcher.d.ts +0 -19
- package/dist/tools/dispatcher.d.ts.map +0 -1
- package/dist/tools/dispatcher.js +0 -91
- package/dist/tools/dispatcher.js.map +0 -1
- package/dist/tools/loop-detector.d.ts +0 -27
- package/dist/tools/loop-detector.d.ts.map +0 -1
- package/dist/tools/loop-detector.js +0 -76
- package/dist/tools/loop-detector.js.map +0 -1
- package/dist/tools/registry.d.ts +0 -19
- package/dist/tools/registry.d.ts.map +0 -1
- package/dist/tools/registry.js +0 -54
- package/dist/tools/registry.js.map +0 -1
- package/dist/tools/step/result-tool.d.ts +0 -7
- package/dist/tools/step/result-tool.d.ts.map +0 -1
- package/dist/tools/step/result-tool.js +0 -34
- package/dist/tools/step/result-tool.js.map +0 -1
- package/dist/tools/tool-contract.d.ts +0 -3
- package/dist/tools/tool-contract.d.ts.map +0 -1
- package/dist/tools/tool-contract.js +0 -2
- package/dist/tools/tool-contract.js.map +0 -1
- package/dist/tools/types.d.ts +0 -210
- package/dist/tools/types.d.ts.map +0 -1
- package/dist/tools/types.js +0 -4
- package/dist/tools/types.js.map +0 -1
- package/docs/CLI.md +0 -59
- package/docs/CONFIGURATION.md +0 -105
- package/docs/DRIVERS.md +0 -79
- package/docs/EVIDENCE.md +0 -64
- package/schemas/checkmate-config.v1.json +0 -176
- package/schemas/describe-result.v1.json +0 -414
- package/schemas/driver-descriptor.v1.json +0 -66
- package/schemas/run-request.v1.json +0 -67
- package/schemas/run-result.v1.json +0 -333
- package/schemas/validation-result.v1.json +0 -86
package/dist/evidence/layout.js
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from 'node:crypto';
|
|
2
|
-
import { mkdir } from 'node:fs/promises';
|
|
3
|
-
import { isAbsolute, relative, resolve, sep } from 'node:path';
|
|
4
|
-
import { syncDirectoryWhenSupported } from './atomic-file.js';
|
|
5
|
-
const DIRECTORY_MODE = 0o700;
|
|
6
|
-
const ID_ATTEMPTS = 100;
|
|
7
|
-
const defaultDirectoryOperations = {
|
|
8
|
-
mkdir: (path, options) => mkdir(path, options),
|
|
9
|
-
syncDirectory: syncDirectoryWhenSupported,
|
|
10
|
-
};
|
|
11
|
-
export async function allocateRunIdentity({ invocationRoot, outputDirectory, scenarioId, now = () => new Date(), random = () => randomBytes(8), directoryOperations, }) {
|
|
12
|
-
const root = resolve(invocationRoot);
|
|
13
|
-
const output = resolve(outputDirectory);
|
|
14
|
-
const operations = { ...defaultDirectoryOperations, ...directoryOperations };
|
|
15
|
-
assertContained(root, output);
|
|
16
|
-
await ensurePrivateDirectory(root, output, operations);
|
|
17
|
-
const startedAt = now().toISOString();
|
|
18
|
-
const prefix = `${utcPathTime(startedAt)}-${safeSlug(scenarioId)}`;
|
|
19
|
-
for (let attempt = 0; attempt < ID_ATTEMPTS; attempt++) {
|
|
20
|
-
const runId = Buffer.from(random()).toString('hex');
|
|
21
|
-
if (!/^[0-9a-f]{16}$/.test(runId)) {
|
|
22
|
-
throw new Error('Run identity source must return exactly eight bytes');
|
|
23
|
-
}
|
|
24
|
-
const runDirectory = resolveInside(output, `${prefix}-${runId}`);
|
|
25
|
-
try {
|
|
26
|
-
await operations.mkdir(runDirectory, { mode: DIRECTORY_MODE });
|
|
27
|
-
}
|
|
28
|
-
catch (error) {
|
|
29
|
-
if (isErrorCode(error, 'EEXIST'))
|
|
30
|
-
continue;
|
|
31
|
-
throw error;
|
|
32
|
-
}
|
|
33
|
-
await operations.syncDirectory(output);
|
|
34
|
-
return {
|
|
35
|
-
runId,
|
|
36
|
-
startedAt,
|
|
37
|
-
runDirectory,
|
|
38
|
-
relativeRunDirectory: toInvocationRelative(root, runDirectory),
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
throw new Error('Unable to allocate a unique run directory');
|
|
42
|
-
}
|
|
43
|
-
export async function ensurePrivateDirectory(root, path, directoryOperations = {}) {
|
|
44
|
-
const resolvedRoot = resolve(root);
|
|
45
|
-
const target = resolve(path);
|
|
46
|
-
const operations = { ...defaultDirectoryOperations, ...directoryOperations };
|
|
47
|
-
assertContained(resolvedRoot, target);
|
|
48
|
-
const members = relative(resolvedRoot, target).split(sep).filter(Boolean);
|
|
49
|
-
let parent = resolvedRoot;
|
|
50
|
-
for (const member of members) {
|
|
51
|
-
const child = resolveInside(parent, member);
|
|
52
|
-
try {
|
|
53
|
-
await operations.mkdir(child, { mode: DIRECTORY_MODE });
|
|
54
|
-
}
|
|
55
|
-
catch (error) {
|
|
56
|
-
if (!isErrorCode(error, 'EEXIST'))
|
|
57
|
-
throw error;
|
|
58
|
-
}
|
|
59
|
-
await operations.syncDirectory(parent);
|
|
60
|
-
parent = child;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
export function resolveInside(root, ...segments) {
|
|
64
|
-
for (const segment of segments)
|
|
65
|
-
assertSafeSegment(segment);
|
|
66
|
-
const resolvedRoot = resolve(root);
|
|
67
|
-
const path = resolve(resolvedRoot, ...segments);
|
|
68
|
-
assertContained(resolvedRoot, path);
|
|
69
|
-
return path;
|
|
70
|
-
}
|
|
71
|
-
export function toInvocationRelative(invocationRoot, path) {
|
|
72
|
-
const root = resolve(invocationRoot);
|
|
73
|
-
const target = resolve(path);
|
|
74
|
-
assertContained(root, target);
|
|
75
|
-
const reference = relative(root, target);
|
|
76
|
-
if (!reference)
|
|
77
|
-
throw new Error('A file reference cannot point at the invocation root');
|
|
78
|
-
return reference.split(sep).join('/');
|
|
79
|
-
}
|
|
80
|
-
export function safeSlug(value) {
|
|
81
|
-
const slug = value
|
|
82
|
-
.normalize('NFKD')
|
|
83
|
-
.replace(/[\u0300-\u036f]/g, '')
|
|
84
|
-
.toLowerCase()
|
|
85
|
-
.replace(/[^a-z0-9]+/g, '-')
|
|
86
|
-
.replace(/^-+|-+$/g, '')
|
|
87
|
-
.slice(0, 64)
|
|
88
|
-
.replace(/-+$/g, '');
|
|
89
|
-
return slug || 'item';
|
|
90
|
-
}
|
|
91
|
-
export function stepDirectoryName(ordinal, stepId) {
|
|
92
|
-
if (!Number.isSafeInteger(ordinal) || ordinal < 1)
|
|
93
|
-
throw new Error('Step ordinal must be a positive integer');
|
|
94
|
-
return `${String(ordinal).padStart(3, '0')}-${safeSlug(stepId)}`;
|
|
95
|
-
}
|
|
96
|
-
export function harnessEvidencePath(identity, ordinal, stepId, kind, turn) {
|
|
97
|
-
const directory = resolveInside(identity.runDirectory, 'evidence', 'harness', 'steps', stepDirectoryName(ordinal, stepId));
|
|
98
|
-
if (kind === 'transcript') {
|
|
99
|
-
if (turn !== undefined)
|
|
100
|
-
throw new Error('A transcript has no turn number');
|
|
101
|
-
return resolveInside(directory, 'transcript.md');
|
|
102
|
-
}
|
|
103
|
-
if (!Number.isSafeInteger(turn) || turn < 1)
|
|
104
|
-
throw new Error('A turn snapshot requires a positive turn number');
|
|
105
|
-
return resolveInside(directory, 'turns', `${String(turn).padStart(3, '0')}.yml`);
|
|
106
|
-
}
|
|
107
|
-
export function driverEvidenceDirectory(identity, driverId, ordinal, stepId) {
|
|
108
|
-
const directory = resolveInside(identity.runDirectory, 'evidence', 'driver', safeSlug(driverId));
|
|
109
|
-
if (ordinal === undefined && stepId === undefined)
|
|
110
|
-
return directory;
|
|
111
|
-
if (ordinal === undefined || stepId === undefined)
|
|
112
|
-
throw new Error('Driver step evidence needs an ordinal and step ID');
|
|
113
|
-
return resolveInside(directory, 'steps', stepDirectoryName(ordinal, stepId));
|
|
114
|
-
}
|
|
115
|
-
export function evidenceExtension(mediaType) {
|
|
116
|
-
switch (mediaType) {
|
|
117
|
-
case 'application/json':
|
|
118
|
-
return 'json';
|
|
119
|
-
case 'application/yaml':
|
|
120
|
-
return 'yml';
|
|
121
|
-
case 'image/jpeg':
|
|
122
|
-
return 'jpg';
|
|
123
|
-
case 'image/png':
|
|
124
|
-
return 'png';
|
|
125
|
-
case 'text/markdown':
|
|
126
|
-
return 'md';
|
|
127
|
-
case 'text/plain':
|
|
128
|
-
return 'txt';
|
|
129
|
-
default:
|
|
130
|
-
return 'bin';
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
function assertSafeSegment(segment) {
|
|
134
|
-
if (!segment || segment === '.' || segment === '..' || segment.includes('/') || segment.includes('\\')) {
|
|
135
|
-
throw new Error(`Unsafe evidence path segment '${segment}'`);
|
|
136
|
-
}
|
|
137
|
-
if (segment.includes('\0') || isAbsolute(segment))
|
|
138
|
-
throw new Error(`Unsafe evidence path segment '${segment}'`);
|
|
139
|
-
}
|
|
140
|
-
function assertContained(root, path) {
|
|
141
|
-
const candidate = relative(root, path);
|
|
142
|
-
if (candidate === '..' || candidate.startsWith(`..${sep}`) || isAbsolute(candidate)) {
|
|
143
|
-
throw new Error(`Path '${path}' escapes '${root}'`);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
function utcPathTime(iso) {
|
|
147
|
-
return iso.replaceAll(/[-:.]/g, '');
|
|
148
|
-
}
|
|
149
|
-
function isErrorCode(error, code) {
|
|
150
|
-
return error instanceof Error && 'code' in error && error.code === code;
|
|
151
|
-
}
|
|
152
|
-
//# sourceMappingURL=layout.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/evidence/layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { EvidencePolicyV1 } from '../contracts/types.js';
|
|
2
|
-
export type EvidenceContent = 'text' | 'opaque';
|
|
3
|
-
export type StepOutcome = 'passed' | 'failed';
|
|
4
|
-
export declare function retainsEvidence(policy: EvidencePolicyV1, outcome: StepOutcome, content: EvidenceContent): boolean;
|
|
5
|
-
//# sourceMappingURL=retention.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../src/evidence/retention.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAE7D,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,CAAA;AAC/C,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE7C,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAKjH"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export function retainsEvidence(policy, outcome, content) {
|
|
2
|
-
if (content === 'opaque' && !policy.allowOpaque)
|
|
3
|
-
return false;
|
|
4
|
-
if (policy.retention === 'off')
|
|
5
|
-
return false;
|
|
6
|
-
if (policy.retention === 'on')
|
|
7
|
-
return true;
|
|
8
|
-
return outcome === 'failed';
|
|
9
|
-
}
|
|
10
|
-
//# sourceMappingURL=retention.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"retention.js","sourceRoot":"","sources":["../../src/evidence/retention.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,eAAe,CAAC,MAAwB,EAAE,OAAoB,EAAE,OAAwB;IACvG,IAAI,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,WAAW;QAAE,OAAO,KAAK,CAAA;IAC7D,IAAI,MAAM,CAAC,SAAS,KAAK,KAAK;QAAE,OAAO,KAAK,CAAA;IAC5C,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAC1C,OAAO,OAAO,KAAK,QAAQ,CAAA;AAC5B,CAAC"}
|
package/dist/evidence/store.d.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import type { Diagnostic, DriverDescriptorV1, EvidencePolicyV1, EvidenceReference, ExecutedStepResult, ExecutionResultV1, RunRequestV1 } from '../contracts/types.js';
|
|
2
|
-
import { type RunIdentity } from './layout.js';
|
|
3
|
-
import { type StepOutcome } from './retention.js';
|
|
4
|
-
export declare const EVIDENCE_CAPTURE_LIMITS: Readonly<{
|
|
5
|
-
maxCandidateBytes: number;
|
|
6
|
-
maxInvocationBytes: number;
|
|
7
|
-
}>;
|
|
8
|
-
type AtomicWriter = (path: string, content: string | Uint8Array) => Promise<void>;
|
|
9
|
-
export type EvidenceStoreOptions = Readonly<{
|
|
10
|
-
invocationRoot: string;
|
|
11
|
-
identity: RunIdentity;
|
|
12
|
-
policy: EvidencePolicyV1;
|
|
13
|
-
stepIds: readonly string[];
|
|
14
|
-
driverDescriptor: DriverDescriptorV1;
|
|
15
|
-
exactSecrets?: Iterable<string>;
|
|
16
|
-
writeFile?: AtomicWriter;
|
|
17
|
-
now?: () => Date;
|
|
18
|
-
}>;
|
|
19
|
-
export type HarnessEvidenceCandidate = Readonly<{
|
|
20
|
-
stepId: string;
|
|
21
|
-
kind: 'transcript' | 'turn-snapshot';
|
|
22
|
-
mediaType: 'text/markdown' | 'application/yaml';
|
|
23
|
-
content: string | Uint8Array;
|
|
24
|
-
turn?: number;
|
|
25
|
-
}>;
|
|
26
|
-
export type DriverEvidenceCandidate = Readonly<{
|
|
27
|
-
stepId?: string;
|
|
28
|
-
kind: string;
|
|
29
|
-
mediaType: string;
|
|
30
|
-
content: string | Uint8Array;
|
|
31
|
-
}>;
|
|
32
|
-
export type FinalizedStepEvidence = Readonly<{
|
|
33
|
-
references: readonly EvidenceReference[];
|
|
34
|
-
diagnostics: readonly Diagnostic[];
|
|
35
|
-
}>;
|
|
36
|
-
export type CheckpointState = Readonly<{
|
|
37
|
-
completedSteps: readonly ExecutedStepResult[];
|
|
38
|
-
diagnostics?: readonly Diagnostic[];
|
|
39
|
-
}>;
|
|
40
|
-
export type PreparedTerminalResult = Readonly<{
|
|
41
|
-
result: ExecutionResultV1;
|
|
42
|
-
bytes: string;
|
|
43
|
-
}>;
|
|
44
|
-
export type CommittedResult = Readonly<{
|
|
45
|
-
result: ExecutionResultV1;
|
|
46
|
-
bytes: string;
|
|
47
|
-
path: string;
|
|
48
|
-
}>;
|
|
49
|
-
export declare class EvidenceStore {
|
|
50
|
-
private readonly invocationRoot;
|
|
51
|
-
private readonly identity;
|
|
52
|
-
private readonly policy;
|
|
53
|
-
private readonly driverDescriptor;
|
|
54
|
-
private readonly stepOrdinals;
|
|
55
|
-
private readonly redactor;
|
|
56
|
-
private readonly writeFile;
|
|
57
|
-
private readonly now;
|
|
58
|
-
private readonly pending;
|
|
59
|
-
private readonly references;
|
|
60
|
-
private readonly allocatedPaths;
|
|
61
|
-
private readonly finalizedSteps;
|
|
62
|
-
private readonly persistenceDiagnostics;
|
|
63
|
-
private lifecycle;
|
|
64
|
-
private bufferedBytes;
|
|
65
|
-
private evidencePartial;
|
|
66
|
-
private driverCandidateOrdinal;
|
|
67
|
-
private scenarioId;
|
|
68
|
-
constructor({ invocationRoot, identity, policy, stepIds, driverDescriptor, exactSecrets, writeFile, now, }: EvidenceStoreOptions);
|
|
69
|
-
get runIdentity(): RunIdentity;
|
|
70
|
-
get state(): 'complete' | 'partial';
|
|
71
|
-
get committedReferences(): readonly EvidenceReference[];
|
|
72
|
-
get acceptedBufferBytes(): number;
|
|
73
|
-
markPartial(): void;
|
|
74
|
-
writeInvocation(request: RunRequestV1): Promise<void>;
|
|
75
|
-
captureHarnessStep(candidate: HarnessEvidenceCandidate): void;
|
|
76
|
-
captureDriver(candidate: DriverEvidenceCandidate): void;
|
|
77
|
-
finalizeStep(stepId: string, outcome: StepOutcome): Promise<FinalizedStepEvidence>;
|
|
78
|
-
finalizeScenario(outcome: StepOutcome): Promise<FinalizedStepEvidence>;
|
|
79
|
-
recordCaptureFailure(artifact: string, error: unknown): Diagnostic;
|
|
80
|
-
private finalizeCandidates;
|
|
81
|
-
replaceCheckpoint(state: CheckpointState): Promise<Diagnostic | undefined>;
|
|
82
|
-
writeResult(prepared: PreparedTerminalResult): Promise<CommittedResult>;
|
|
83
|
-
prepareResult(candidate: ExecutionResultV1): PreparedTerminalResult;
|
|
84
|
-
sanitizeDiagnosticText(value: string): string;
|
|
85
|
-
dispose(): void;
|
|
86
|
-
private capture;
|
|
87
|
-
private redactTextBytes;
|
|
88
|
-
private assertCandidateSize;
|
|
89
|
-
private stepOrdinal;
|
|
90
|
-
private release;
|
|
91
|
-
private removeCandidates;
|
|
92
|
-
private assertActive;
|
|
93
|
-
private writeDiagnostic;
|
|
94
|
-
private recordPersistenceDiagnostic;
|
|
95
|
-
}
|
|
96
|
-
export declare class EvidenceCaptureError extends Error {
|
|
97
|
-
readonly code: string;
|
|
98
|
-
constructor(code: string, message: string);
|
|
99
|
-
}
|
|
100
|
-
export {};
|
|
101
|
-
//# sourceMappingURL=store.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/evidence/store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,MAAM,uBAAuB,CAAA;AAK9B,OAAO,EAQN,KAAK,WAAW,EAChB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAyC,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAExF,eAAO,MAAM,uBAAuB;;;EAGlC,CAAA;AAEF,KAAK,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEjF,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC3C,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,WAAW,CAAA;IACrB,MAAM,EAAE,gBAAgB,CAAA;IACxB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B,gBAAgB,EAAE,kBAAkB,CAAA;IACpC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC/B,SAAS,CAAC,EAAE,YAAY,CAAA;IACxB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CAChB,CAAC,CAAA;AAEF,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC/C,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,YAAY,GAAG,eAAe,CAAA;IACpC,SAAS,EAAE,eAAe,GAAG,kBAAkB,CAAA;IAC/C,OAAO,EAAE,MAAM,GAAG,UAAU,CAAA;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;CACb,CAAC,CAAA;AAEF,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAA;CAC5B,CAAC,CAAA;AAEF,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC5C,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACxC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAA;CAClC,CAAC,CAAA;AAEF,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACtC,cAAc,EAAE,SAAS,kBAAkB,EAAE,CAAA;IAC7C,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;CACnC,CAAC,CAAA;AAEF,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC7C,MAAM,EAAE,iBAAiB,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;CACb,CAAC,CAAA;AAEF,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACtC,MAAM,EAAE,iBAAiB,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACZ,CAAC,CAAA;AAiBF,qBAAa,aAAa;IACzB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAa;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAoB;IACrD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAC1D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0B;IACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoB;IACnD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoB;IACnD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAmB;IAC1D,OAAO,CAAC,SAAS,CAAmD;IACpE,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,sBAAsB,CAAI;IAClC,OAAO,CAAC,UAAU,CAAoB;gBAE1B,EACX,cAAc,EACd,QAAQ,EACR,MAAM,EACN,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,SAA2B,EAC3B,GAAsB,GACtB,EAAE,oBAAoB;IAavB,IAAI,WAAW,IAAI,WAAW,CAE7B;IAED,IAAI,KAAK,IAAI,UAAU,GAAG,SAAS,CAElC;IAED,IAAI,mBAAmB,IAAI,SAAS,iBAAiB,EAAE,CAEtD;IAED,IAAI,mBAAmB,IAAI,MAAM,CAEhC;IAED,WAAW,IAAI,IAAI;IAIb,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB3D,kBAAkB,CAAC,SAAS,EAAE,wBAAwB,GAAG,IAAI;IA4B7D,aAAa,CAAC,SAAS,EAAE,uBAAuB,GAAG,IAAI;IA6BjD,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,qBAAqB,CAAC;IASlF,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAK5E,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,UAAU;YAQpD,kBAAkB;IAkC1B,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAsB1E,WAAW,CAAC,QAAQ,EAAE,sBAAsB,GAAG,OAAO,CAAC,eAAe,CAAC;IAY7E,aAAa,CAAC,SAAS,EAAE,iBAAiB,GAAG,sBAAsB;IAiBnE,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAI7C,OAAO,IAAI,IAAI;IAMf,OAAO,CAAC,OAAO;IA8Cf,OAAO,CAAC,eAAe;IAiCvB,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,2BAA2B;CAGnC;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAE7C,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM;CAKhB"}
|
package/dist/evidence/store.js
DELETED
|
@@ -1,375 +0,0 @@
|
|
|
1
|
-
import { Buffer } from 'node:buffer';
|
|
2
|
-
import { dirname } from 'node:path';
|
|
3
|
-
import { serializeJson } from '../contracts/serialize.js';
|
|
4
|
-
import { Redactor } from '../redaction/redactor.js';
|
|
5
|
-
import { parseDocument, stringify as stringifyYaml } from 'yaml';
|
|
6
|
-
import { AtomicWriteError, writeAtomicFile } from './atomic-file.js';
|
|
7
|
-
import { ensurePrivateDirectory, driverEvidenceDirectory, evidenceExtension, harnessEvidencePath, resolveInside, safeSlug, toInvocationRelative, } from './layout.js';
|
|
8
|
-
import { retainsEvidence } from './retention.js';
|
|
9
|
-
export const EVIDENCE_CAPTURE_LIMITS = Object.freeze({
|
|
10
|
-
maxCandidateBytes: 10 * 1024 * 1024,
|
|
11
|
-
maxInvocationBytes: 64 * 1024 * 1024,
|
|
12
|
-
});
|
|
13
|
-
const harnessKinds = {
|
|
14
|
-
transcript: { mediaType: 'text/markdown', content: 'text' },
|
|
15
|
-
'turn-snapshot': { mediaType: 'application/yaml', content: 'text' },
|
|
16
|
-
};
|
|
17
|
-
export class EvidenceStore {
|
|
18
|
-
invocationRoot;
|
|
19
|
-
identity;
|
|
20
|
-
policy;
|
|
21
|
-
driverDescriptor;
|
|
22
|
-
stepOrdinals;
|
|
23
|
-
redactor;
|
|
24
|
-
writeFile;
|
|
25
|
-
now;
|
|
26
|
-
pending = [];
|
|
27
|
-
references = [];
|
|
28
|
-
allocatedPaths = new Set();
|
|
29
|
-
finalizedSteps = new Set();
|
|
30
|
-
persistenceDiagnostics = [];
|
|
31
|
-
lifecycle = 'allocated';
|
|
32
|
-
bufferedBytes = 0;
|
|
33
|
-
evidencePartial = false;
|
|
34
|
-
driverCandidateOrdinal = 0;
|
|
35
|
-
scenarioId;
|
|
36
|
-
constructor({ invocationRoot, identity, policy, stepIds, driverDescriptor, exactSecrets, writeFile = writeAtomicFile, now = () => new Date(), }) {
|
|
37
|
-
if (new Set(stepIds).size !== stepIds.length)
|
|
38
|
-
throw new Error('Evidence store step IDs must be unique');
|
|
39
|
-
this.invocationRoot = invocationRoot;
|
|
40
|
-
this.identity = identity;
|
|
41
|
-
this.policy = { ...policy };
|
|
42
|
-
this.driverDescriptor = structuredClone(driverDescriptor);
|
|
43
|
-
this.stepOrdinals = new Map(stepIds.map((id, index) => [id, index + 1]));
|
|
44
|
-
this.redactor = new Redactor({ mode: policy.redaction, exactSecrets });
|
|
45
|
-
this.writeFile = writeFile;
|
|
46
|
-
this.now = now;
|
|
47
|
-
toInvocationRelative(invocationRoot, identity.runDirectory);
|
|
48
|
-
}
|
|
49
|
-
get runIdentity() {
|
|
50
|
-
return this.identity;
|
|
51
|
-
}
|
|
52
|
-
get state() {
|
|
53
|
-
return this.evidencePartial ? 'partial' : 'complete';
|
|
54
|
-
}
|
|
55
|
-
get committedReferences() {
|
|
56
|
-
return this.references.map((reference) => ({ ...reference }));
|
|
57
|
-
}
|
|
58
|
-
get acceptedBufferBytes() {
|
|
59
|
-
return this.bufferedBytes;
|
|
60
|
-
}
|
|
61
|
-
markPartial() {
|
|
62
|
-
this.evidencePartial = true;
|
|
63
|
-
}
|
|
64
|
-
async writeInvocation(request) {
|
|
65
|
-
if (this.lifecycle !== 'allocated')
|
|
66
|
-
throw new Error('Invocation metadata has already been written');
|
|
67
|
-
const requestStepIds = request.scenario.steps.map((step) => step.id);
|
|
68
|
-
if (requestStepIds.length !== this.stepOrdinals.size ||
|
|
69
|
-
requestStepIds.some((stepId, index) => this.stepOrdinals.get(stepId) !== index + 1)) {
|
|
70
|
-
throw new Error('Invocation steps do not match the evidence store');
|
|
71
|
-
}
|
|
72
|
-
this.scenarioId = request.scenario.id;
|
|
73
|
-
this.lifecycle = 'active';
|
|
74
|
-
const path = resolveInside(this.identity.runDirectory, 'invocation.json');
|
|
75
|
-
const payload = this.redactor.redactInvocation({
|
|
76
|
-
layoutVersion: 1,
|
|
77
|
-
runId: this.identity.runId,
|
|
78
|
-
startedAt: this.identity.startedAt,
|
|
79
|
-
request,
|
|
80
|
-
});
|
|
81
|
-
await this.writeFile(path, serializeJson(payload));
|
|
82
|
-
}
|
|
83
|
-
captureHarnessStep(candidate) {
|
|
84
|
-
this.assertActive();
|
|
85
|
-
const declaration = harnessKinds[candidate.kind];
|
|
86
|
-
if (!declaration) {
|
|
87
|
-
throw new EvidenceCaptureError('evidence.undeclared-kind', `Harness evidence kind '${candidate.kind}' is not declared`);
|
|
88
|
-
}
|
|
89
|
-
if (candidate.mediaType !== declaration.mediaType) {
|
|
90
|
-
throw new EvidenceCaptureError('evidence.media-type-mismatch', `Harness evidence '${candidate.kind}' has an invalid media type`);
|
|
91
|
-
}
|
|
92
|
-
const ordinal = this.stepOrdinal(candidate.stepId);
|
|
93
|
-
let path;
|
|
94
|
-
try {
|
|
95
|
-
path = harnessEvidencePath(this.identity, ordinal, candidate.stepId, candidate.kind, candidate.turn);
|
|
96
|
-
}
|
|
97
|
-
catch (error) {
|
|
98
|
-
throw new EvidenceCaptureError('evidence.invalid-turn', error instanceof Error ? error.message : String(error));
|
|
99
|
-
}
|
|
100
|
-
this.capture({ ...candidate, producer: 'harness', contentType: declaration.content, path });
|
|
101
|
-
}
|
|
102
|
-
captureDriver(candidate) {
|
|
103
|
-
this.assertActive();
|
|
104
|
-
const declaration = this.driverDescriptor.evidenceKinds.find((entry) => entry.kind === candidate.kind);
|
|
105
|
-
if (!declaration) {
|
|
106
|
-
throw new EvidenceCaptureError('evidence.undeclared-kind', `Driver '${this.driverDescriptor.id}' does not declare evidence kind '${candidate.kind}'`);
|
|
107
|
-
}
|
|
108
|
-
if (declaration.mediaType !== candidate.mediaType) {
|
|
109
|
-
throw new EvidenceCaptureError('evidence.media-type-mismatch', `Driver evidence '${candidate.kind}' has an invalid media type`);
|
|
110
|
-
}
|
|
111
|
-
const fileOrdinal = ++this.driverCandidateOrdinal;
|
|
112
|
-
const filename = `${String(fileOrdinal).padStart(3, '0')}-${safeSlug(candidate.kind)}.${evidenceExtension(candidate.mediaType)}`;
|
|
113
|
-
const directory = candidate.stepId
|
|
114
|
-
? driverEvidenceDirectory(this.identity, this.driverDescriptor.id, this.stepOrdinal(candidate.stepId), candidate.stepId)
|
|
115
|
-
: driverEvidenceDirectory(this.identity, this.driverDescriptor.id);
|
|
116
|
-
const path = resolveInside(directory, filename);
|
|
117
|
-
this.capture({ ...candidate, producer: this.driverDescriptor.id, contentType: declaration.content, path });
|
|
118
|
-
}
|
|
119
|
-
async finalizeStep(stepId, outcome) {
|
|
120
|
-
this.assertActive();
|
|
121
|
-
this.stepOrdinal(stepId);
|
|
122
|
-
if (this.finalizedSteps.has(stepId))
|
|
123
|
-
throw new Error(`Evidence for step '${stepId}' has already been finalized`);
|
|
124
|
-
this.finalizedSteps.add(stepId);
|
|
125
|
-
const candidates = this.pending.filter((candidate) => candidate.stepId === stepId);
|
|
126
|
-
return this.finalizeCandidates(candidates, outcome);
|
|
127
|
-
}
|
|
128
|
-
async finalizeScenario(outcome) {
|
|
129
|
-
this.assertActive();
|
|
130
|
-
return this.finalizeCandidates([...this.pending], outcome);
|
|
131
|
-
}
|
|
132
|
-
recordCaptureFailure(artifact, error) {
|
|
133
|
-
this.assertActive();
|
|
134
|
-
this.evidencePartial = true;
|
|
135
|
-
const diagnostic = this.writeDiagnostic('evidence.capture-failed', artifact, error);
|
|
136
|
-
this.recordPersistenceDiagnostic(diagnostic);
|
|
137
|
-
return diagnostic;
|
|
138
|
-
}
|
|
139
|
-
async finalizeCandidates(candidates, outcome) {
|
|
140
|
-
const newReferences = [];
|
|
141
|
-
const diagnostics = [];
|
|
142
|
-
for (const candidate of candidates) {
|
|
143
|
-
try {
|
|
144
|
-
if (!retainsEvidence(this.policy, outcome, candidate.contentType))
|
|
145
|
-
continue;
|
|
146
|
-
await ensurePrivateDirectory(this.identity.runDirectory, dirname(candidate.path));
|
|
147
|
-
await this.writeFile(candidate.path, candidate.bytes);
|
|
148
|
-
const reference = {
|
|
149
|
-
kind: candidate.kind,
|
|
150
|
-
mediaType: candidate.mediaType,
|
|
151
|
-
path: toInvocationRelative(this.invocationRoot, candidate.path),
|
|
152
|
-
producer: candidate.producer,
|
|
153
|
-
...(candidate.stepId === undefined ? {} : { stepId: candidate.stepId }),
|
|
154
|
-
};
|
|
155
|
-
this.references.push(reference);
|
|
156
|
-
newReferences.push({ ...reference });
|
|
157
|
-
}
|
|
158
|
-
catch (error) {
|
|
159
|
-
this.evidencePartial = true;
|
|
160
|
-
const diagnostic = this.writeDiagnostic('evidence.write-failed', candidate.kind, error);
|
|
161
|
-
this.recordPersistenceDiagnostic(diagnostic);
|
|
162
|
-
diagnostics.push(diagnostic);
|
|
163
|
-
}
|
|
164
|
-
finally {
|
|
165
|
-
this.release(candidate);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
this.removeCandidates(candidates);
|
|
169
|
-
return { references: newReferences, diagnostics };
|
|
170
|
-
}
|
|
171
|
-
async replaceCheckpoint(state) {
|
|
172
|
-
this.assertActive();
|
|
173
|
-
const path = resolveInside(this.identity.runDirectory, 'checkpoint.json');
|
|
174
|
-
try {
|
|
175
|
-
const payload = this.redactor.redactCheckpoint({
|
|
176
|
-
layoutVersion: 1,
|
|
177
|
-
runId: this.identity.runId,
|
|
178
|
-
updatedAt: this.now().toISOString(),
|
|
179
|
-
state: 'partial',
|
|
180
|
-
completedSteps: state.completedSteps,
|
|
181
|
-
evidenceReferences: this.references,
|
|
182
|
-
diagnostics: mergeDiagnostics(state.diagnostics ?? [], this.persistenceDiagnostics),
|
|
183
|
-
});
|
|
184
|
-
await this.writeFile(path, serializeJson(payload));
|
|
185
|
-
return undefined;
|
|
186
|
-
}
|
|
187
|
-
catch (error) {
|
|
188
|
-
const diagnostic = this.writeDiagnostic('checkpoint.write-failed', 'checkpoint', error);
|
|
189
|
-
this.recordPersistenceDiagnostic(diagnostic);
|
|
190
|
-
return diagnostic;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
async writeResult(prepared) {
|
|
194
|
-
this.assertActive();
|
|
195
|
-
const absolutePath = resolveInside(this.identity.runDirectory, 'result.json');
|
|
196
|
-
await this.writeFile(absolutePath, prepared.bytes);
|
|
197
|
-
this.lifecycle = 'terminal';
|
|
198
|
-
return {
|
|
199
|
-
result: prepared.result,
|
|
200
|
-
bytes: prepared.bytes,
|
|
201
|
-
path: toInvocationRelative(this.invocationRoot, absolutePath),
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
prepareResult(candidate) {
|
|
205
|
-
this.assertActive();
|
|
206
|
-
if (this.pending.length > 0)
|
|
207
|
-
throw new Error('Cannot commit a result while evidence candidates are pending');
|
|
208
|
-
if (candidate.runId !== this.identity.runId || candidate.startedAt !== this.identity.startedAt) {
|
|
209
|
-
throw new Error('Execution result identity does not match the evidence store');
|
|
210
|
-
}
|
|
211
|
-
if (candidate.scenarioId !== this.scenarioId) {
|
|
212
|
-
throw new Error('Execution result scenario does not match the evidence store');
|
|
213
|
-
}
|
|
214
|
-
const result = this.redactor.redactExecutionResult({
|
|
215
|
-
...candidate,
|
|
216
|
-
evidence: { state: this.state, references: [...this.committedReferences] },
|
|
217
|
-
diagnostics: mergeDiagnostics(candidate.diagnostics, this.persistenceDiagnostics),
|
|
218
|
-
});
|
|
219
|
-
return { result, bytes: serializeJson(result) };
|
|
220
|
-
}
|
|
221
|
-
sanitizeDiagnosticText(value) {
|
|
222
|
-
return this.redactor.redactDiagnosticText(value);
|
|
223
|
-
}
|
|
224
|
-
dispose() {
|
|
225
|
-
for (const candidate of this.pending)
|
|
226
|
-
this.release(candidate);
|
|
227
|
-
this.pending.length = 0;
|
|
228
|
-
this.lifecycle = 'terminal';
|
|
229
|
-
}
|
|
230
|
-
capture(input) {
|
|
231
|
-
if (input.stepId !== undefined && this.finalizedSteps.has(input.stepId)) {
|
|
232
|
-
throw new EvidenceCaptureError('evidence.step-finalized', `Evidence for step '${input.stepId}' is already finalized`);
|
|
233
|
-
}
|
|
234
|
-
if (this.allocatedPaths.has(input.path)) {
|
|
235
|
-
throw new EvidenceCaptureError('evidence.duplicate-destination', 'Evidence destination is already allocated');
|
|
236
|
-
}
|
|
237
|
-
const inputBytes = candidateByteLength(input.content);
|
|
238
|
-
this.assertCandidateSize(inputBytes);
|
|
239
|
-
const raw = ownBytes(input.content);
|
|
240
|
-
const bytes = input.contentType === 'text' ? this.redactTextBytes(raw, input.mediaType) : raw;
|
|
241
|
-
this.assertCandidateSize(bytes.byteLength);
|
|
242
|
-
if (this.bufferedBytes + bytes.byteLength > EVIDENCE_CAPTURE_LIMITS.maxInvocationBytes) {
|
|
243
|
-
throw new EvidenceCaptureError('evidence.invocation-buffer-too-large', `Accepted evidence buffers must not exceed ${EVIDENCE_CAPTURE_LIMITS.maxInvocationBytes} bytes per invocation`);
|
|
244
|
-
}
|
|
245
|
-
this.pending.push({
|
|
246
|
-
stepId: input.stepId,
|
|
247
|
-
kind: input.kind,
|
|
248
|
-
mediaType: input.mediaType,
|
|
249
|
-
producer: input.producer,
|
|
250
|
-
contentType: input.contentType,
|
|
251
|
-
path: input.path,
|
|
252
|
-
bytes,
|
|
253
|
-
});
|
|
254
|
-
this.allocatedPaths.add(input.path);
|
|
255
|
-
this.bufferedBytes += bytes.byteLength;
|
|
256
|
-
}
|
|
257
|
-
redactTextBytes(raw, mediaType) {
|
|
258
|
-
if (this.policy.redaction === 'off')
|
|
259
|
-
return raw;
|
|
260
|
-
let value;
|
|
261
|
-
try {
|
|
262
|
-
value = new TextDecoder('utf-8', { fatal: true }).decode(raw);
|
|
263
|
-
}
|
|
264
|
-
catch {
|
|
265
|
-
throw new EvidenceCaptureError('evidence.invalid-text', 'Text evidence must contain valid UTF-8');
|
|
266
|
-
}
|
|
267
|
-
try {
|
|
268
|
-
const format = structuredFormat(mediaType);
|
|
269
|
-
if (format === 'json') {
|
|
270
|
-
const parsed = JSON.parse(value);
|
|
271
|
-
assertJsonValue(parsed);
|
|
272
|
-
return Buffer.from(serializeJson(this.redactor.redactContent(parsed)), 'utf8');
|
|
273
|
-
}
|
|
274
|
-
if (format === 'yaml') {
|
|
275
|
-
const document = parseDocument(value, { uniqueKeys: true });
|
|
276
|
-
if (document.errors.length > 0)
|
|
277
|
-
throw document.errors[0];
|
|
278
|
-
const parsed = document.toJS({ maxAliasCount: 100 });
|
|
279
|
-
assertJsonValue(parsed);
|
|
280
|
-
const redacted = this.redactor.redactContent(parsed);
|
|
281
|
-
return Buffer.from(stringifyYaml(redacted, { sortMapEntries: true }), 'utf8');
|
|
282
|
-
}
|
|
283
|
-
return Buffer.from(this.redactor.redactText(value), 'utf8');
|
|
284
|
-
}
|
|
285
|
-
catch (error) {
|
|
286
|
-
if (error instanceof EvidenceCaptureError)
|
|
287
|
-
throw error;
|
|
288
|
-
throw new EvidenceCaptureError('evidence.invalid-structured-content', `Structured ${mediaType} evidence could not be safely redacted`);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
assertCandidateSize(bytes) {
|
|
292
|
-
if (bytes > EVIDENCE_CAPTURE_LIMITS.maxCandidateBytes) {
|
|
293
|
-
throw new EvidenceCaptureError('evidence.candidate-too-large', `An evidence candidate must not exceed ${EVIDENCE_CAPTURE_LIMITS.maxCandidateBytes} bytes`);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
stepOrdinal(stepId) {
|
|
297
|
-
const ordinal = this.stepOrdinals.get(stepId);
|
|
298
|
-
if (ordinal === undefined) {
|
|
299
|
-
throw new EvidenceCaptureError('evidence.unknown-step', `Evidence references unknown step '${stepId}'`);
|
|
300
|
-
}
|
|
301
|
-
return ordinal;
|
|
302
|
-
}
|
|
303
|
-
release(candidate) {
|
|
304
|
-
this.bufferedBytes -= candidate.bytes.byteLength;
|
|
305
|
-
candidate.bytes = Buffer.alloc(0);
|
|
306
|
-
}
|
|
307
|
-
removeCandidates(candidates) {
|
|
308
|
-
const removed = new Set(candidates);
|
|
309
|
-
for (let index = this.pending.length - 1; index >= 0; index--) {
|
|
310
|
-
if (removed.has(this.pending[index]))
|
|
311
|
-
this.pending.splice(index, 1);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
assertActive() {
|
|
315
|
-
if (this.lifecycle !== 'active')
|
|
316
|
-
throw new Error('Evidence store is not accepting evidence');
|
|
317
|
-
}
|
|
318
|
-
writeDiagnostic(code, artifact, error) {
|
|
319
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
320
|
-
const durability = error instanceof AtomicWriteError && error.durability === 'uncertain'
|
|
321
|
-
? ' The destination was renamed, but durability was not confirmed; no reference was published.'
|
|
322
|
-
: '';
|
|
323
|
-
return {
|
|
324
|
-
code,
|
|
325
|
-
path: '/evidence',
|
|
326
|
-
message: this.redactor.redactDiagnosticText(`Could not commit ${artifact} evidence: ${detail}.${durability}`.trim()),
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
recordPersistenceDiagnostic(diagnostic) {
|
|
330
|
-
this.persistenceDiagnostics.push(diagnostic);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
export class EvidenceCaptureError extends Error {
|
|
334
|
-
code;
|
|
335
|
-
constructor(code, message) {
|
|
336
|
-
super(message);
|
|
337
|
-
this.code = code;
|
|
338
|
-
this.name = 'EvidenceCaptureError';
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
function ownBytes(content) {
|
|
342
|
-
return typeof content === 'string' ? Buffer.from(content, 'utf8') : Buffer.from(content);
|
|
343
|
-
}
|
|
344
|
-
function candidateByteLength(content) {
|
|
345
|
-
return typeof content === 'string' ? Buffer.byteLength(content, 'utf8') : content.byteLength;
|
|
346
|
-
}
|
|
347
|
-
function structuredFormat(mediaType) {
|
|
348
|
-
const normalized = mediaType.split(';', 1)[0].trim().toLowerCase();
|
|
349
|
-
if (normalized === 'application/json' || normalized.endsWith('+json'))
|
|
350
|
-
return 'json';
|
|
351
|
-
if (['application/yaml', 'application/x-yaml', 'text/yaml', 'text/x-yaml'].includes(normalized))
|
|
352
|
-
return 'yaml';
|
|
353
|
-
return undefined;
|
|
354
|
-
}
|
|
355
|
-
function assertJsonValue(value) {
|
|
356
|
-
try {
|
|
357
|
-
serializeJson(value);
|
|
358
|
-
}
|
|
359
|
-
catch {
|
|
360
|
-
throw new EvidenceCaptureError('evidence.invalid-structured-content', 'Structured evidence must contain only JSON-compatible values');
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
function mergeDiagnostics(left, right) {
|
|
364
|
-
const merged = [];
|
|
365
|
-
const seen = new Set();
|
|
366
|
-
for (const diagnostic of [...left, ...right]) {
|
|
367
|
-
const key = `${diagnostic.code}\0${diagnostic.path}\0${diagnostic.message}`;
|
|
368
|
-
if (seen.has(key))
|
|
369
|
-
continue;
|
|
370
|
-
seen.add(key);
|
|
371
|
-
merged.push({ ...diagnostic });
|
|
372
|
-
}
|
|
373
|
-
return merged;
|
|
374
|
-
}
|
|
375
|
-
//# sourceMappingURL=store.js.map
|