@bjoernrochel/sevro 0.1.0-rc.8 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +52 -6
- package/README.md +12 -7
- package/dist/examples/basic/graded.json +13 -0
- package/dist/examples/basic/host.js +9 -0
- package/dist/examples/basic/host.js.map +1 -0
- package/dist/examples/basic/prompt-only.json +7 -0
- package/dist/examples/recipes/candidate.js +23 -0
- package/dist/examples/recipes/candidate.js.map +1 -0
- package/dist/examples/recipes/cases/coding-change.json +21 -0
- package/dist/examples/recipes/cases/host-tools.json +21 -0
- package/dist/examples/recipes/cases/mise.json +21 -0
- package/dist/examples/recipes/cases/node.json +21 -0
- package/dist/examples/recipes/cases/python-uv.json +21 -0
- package/dist/examples/recipes/cases/semantic.json +17 -0
- package/dist/examples/recipes/coding-change/check.js +16 -0
- package/dist/examples/recipes/coding-change/check.js.map +1 -0
- package/dist/examples/recipes/executable.js +20 -0
- package/dist/examples/recipes/executable.js.map +1 -0
- package/dist/examples/recipes/extension-artifacts.js +56 -0
- package/dist/examples/recipes/extension-artifacts.js.map +1 -0
- package/dist/examples/recipes/extension-methods.js +167 -0
- package/dist/examples/recipes/extension-methods.js.map +1 -0
- package/dist/examples/recipes/extension.js +28 -0
- package/dist/examples/recipes/extension.js.map +1 -0
- package/dist/examples/recipes/modules.js +9 -0
- package/dist/examples/recipes/modules.js.map +1 -0
- package/dist/examples/recipes/repository-skill/.agents/skills/startup-guide/SKILL.md +7 -0
- package/dist/examples/recipes/repository-skill/.claude/skills/startup-guide/SKILL.md +7 -0
- package/dist/examples/recipes/repository-skill/README.md +3 -0
- package/dist/examples/recipes/run-inputs.js +144 -0
- package/dist/examples/recipes/run-inputs.js.map +1 -0
- package/dist/examples/recipes/run-options.js +103 -0
- package/dist/examples/recipes/run-options.js.map +1 -0
- package/dist/examples/recipes/run.js +62 -0
- package/dist/examples/recipes/run.js.map +1 -0
- package/dist/examples/recipes/runtime/empty.json +1 -0
- package/dist/examples/recipes/runtime/goals.json +1 -0
- package/dist/examples/recipes/runtime/mise.json +6 -0
- package/dist/examples/recipes/runtime/path.json +1 -0
- package/dist/examples/recipes/runtime/plugins.json +4 -0
- package/dist/examples/recipes/runtime/python-uv.json +10 -0
- package/dist/examples/recipes/semantic-judge.js +27 -0
- package/dist/examples/recipes/semantic-judge.js.map +1 -0
- package/dist/examples/templates/coding/adapter.js +14 -0
- package/dist/examples/templates/coding/adapter.js.map +1 -0
- package/dist/examples/templates/coding/case.json +15 -0
- package/dist/examples/templates/repository-skill/.agents/skills/startup-guide/SKILL.md +6 -0
- package/dist/examples/templates/repository-skill/extension-data.js +61 -0
- package/dist/examples/templates/repository-skill/extension-data.js.map +1 -0
- package/dist/examples/templates/repository-skill/extension.js +29 -0
- package/dist/examples/templates/repository-skill/extension.js.map +1 -0
- package/dist/examples/templates/response/adapter.js +13 -0
- package/dist/examples/templates/response/adapter.js.map +1 -0
- package/dist/examples/templates/response/case.json +13 -0
- package/dist/src/advisory.js +86 -0
- package/dist/src/advisory.js.map +1 -0
- package/dist/src/candidate-artifacts.js +139 -0
- package/dist/src/candidate-artifacts.js.map +1 -0
- package/dist/src/candidate-codex-state.js +110 -0
- package/dist/src/candidate-codex-state.js.map +1 -0
- package/dist/src/case-validation.js +92 -0
- package/dist/src/case-validation.js.map +1 -0
- package/dist/src/cli/cancellation.js +21 -0
- package/dist/src/cli/cancellation.js.map +1 -0
- package/dist/src/cli/command.js +60 -0
- package/dist/src/cli/command.js.map +1 -0
- package/dist/src/cli/completion.js +14 -0
- package/dist/src/cli/completion.js.map +1 -0
- package/dist/src/cli/demo.js +45 -0
- package/dist/src/cli/demo.js.map +1 -0
- package/dist/src/cli/evaluation.js +40 -0
- package/dist/src/cli/evaluation.js.map +1 -0
- package/dist/src/cli/extension.js +54 -0
- package/dist/src/cli/extension.js.map +1 -0
- package/dist/src/cli/help.js +190 -0
- package/dist/src/cli/help.js.map +1 -0
- package/dist/src/cli/hosts.js +33 -0
- package/dist/src/cli/hosts.js.map +1 -0
- package/dist/src/cli/init-settings.js +29 -0
- package/dist/src/cli/init-settings.js.map +1 -0
- package/dist/src/cli/init.js +82 -0
- package/dist/src/cli/init.js.map +1 -0
- package/dist/src/cli/invocation.js +431 -0
- package/dist/src/cli/invocation.js.map +1 -0
- package/dist/src/cli/loading.js +110 -0
- package/dist/src/cli/loading.js.map +1 -0
- package/dist/src/cli/preparation.js +88 -0
- package/dist/src/cli/preparation.js.map +1 -0
- package/dist/src/cli/presentation.js +61 -0
- package/dist/src/cli/presentation.js.map +1 -0
- package/dist/src/cli/progress.js +5 -0
- package/dist/src/cli/progress.js.map +1 -0
- package/dist/src/cli/run-manifest.js +108 -0
- package/dist/src/cli/run-manifest.js.map +1 -0
- package/dist/src/cli/run-options.js +367 -0
- package/dist/src/cli/run-options.js.map +1 -0
- package/dist/src/cli/run-overrides.js +51 -0
- package/dist/src/cli/run-overrides.js.map +1 -0
- package/dist/src/cli/settings.js +127 -0
- package/dist/src/cli/settings.js.map +1 -0
- package/dist/src/cli/summary.js +28 -0
- package/dist/src/cli/summary.js.map +1 -0
- package/dist/src/cli.js +20 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/contract-types.js +2 -0
- package/dist/src/contract-types.js.map +1 -0
- package/dist/src/engine.js +4 -0
- package/dist/src/engine.js.map +1 -0
- package/dist/src/evaluation/advisory.js +85 -0
- package/dist/src/evaluation/advisory.js.map +1 -0
- package/dist/src/evaluation/check-plan.js +292 -0
- package/dist/src/evaluation/check-plan.js.map +1 -0
- package/dist/src/evaluation/collection.js +61 -0
- package/dist/src/evaluation/collection.js.map +1 -0
- package/dist/src/evaluation/context.js +2 -0
- package/dist/src/evaluation/context.js.map +1 -0
- package/dist/src/evaluation/grading-host.js +28 -0
- package/dist/src/evaluation/grading-host.js.map +1 -0
- package/dist/src/evaluation/grading.js +154 -0
- package/dist/src/evaluation/grading.js.map +1 -0
- package/dist/src/evaluation/invocation-plan.js +312 -0
- package/dist/src/evaluation/invocation-plan.js.map +1 -0
- package/dist/src/evaluation/plan.js +376 -0
- package/dist/src/evaluation/plan.js.map +1 -0
- package/dist/src/evaluation/progress.js +14 -0
- package/dist/src/evaluation/progress.js.map +1 -0
- package/dist/src/evaluation/resources.js +159 -0
- package/dist/src/evaluation/resources.js.map +1 -0
- package/dist/src/evaluation/run.js +148 -0
- package/dist/src/evaluation/run.js.map +1 -0
- package/dist/src/evaluation/scheduler.js +27 -0
- package/dist/src/evaluation/scheduler.js.map +1 -0
- package/dist/src/evaluation/semantic.js +183 -0
- package/dist/src/evaluation/semantic.js.map +1 -0
- package/dist/src/evaluation/trial.js +593 -0
- package/dist/src/evaluation/trial.js.map +1 -0
- package/dist/src/evaluation/types.js +20 -0
- package/dist/src/evaluation/types.js.map +1 -0
- package/dist/src/evidence/host-results.js +67 -0
- package/dist/src/evidence/host-results.js.map +1 -0
- package/dist/src/evidence/retained-artifacts.js +17 -0
- package/dist/src/evidence/retained-artifacts.js.map +1 -0
- package/dist/src/evidence/trial-writer.js +131 -0
- package/dist/src/evidence/trial-writer.js.map +1 -0
- package/dist/src/evidence/usage.js +14 -0
- package/dist/src/evidence/usage.js.map +1 -0
- package/dist/src/executable.js +20 -0
- package/dist/src/executable.js.map +1 -0
- package/dist/src/extension-client.js +212 -0
- package/dist/src/extension-client.js.map +1 -0
- package/dist/src/extension-session.js +236 -0
- package/dist/src/extension-session.js.map +1 -0
- package/dist/src/fixtures/advisory.js +206 -0
- package/dist/src/fixtures/advisory.js.map +1 -0
- package/dist/src/fixtures/bin.js +41 -0
- package/dist/src/fixtures/bin.js.map +1 -0
- package/dist/src/fixtures/cleanup.js +43 -0
- package/dist/src/fixtures/cleanup.js.map +1 -0
- package/dist/src/fixtures/create.js +94 -0
- package/dist/src/fixtures/create.js.map +1 -0
- package/dist/src/fixtures/generated.js +181 -0
- package/dist/src/fixtures/generated.js.map +1 -0
- package/dist/src/fixtures/git-hooks.js +16 -0
- package/dist/src/fixtures/git-hooks.js.map +1 -0
- package/dist/src/fixtures/preparation.js +201 -0
- package/dist/src/fixtures/preparation.js.map +1 -0
- package/dist/src/fixtures/repository.js +255 -0
- package/dist/src/fixtures/repository.js.map +1 -0
- package/dist/src/fixtures/setup.js +175 -0
- package/dist/src/fixtures/setup.js.map +1 -0
- package/dist/src/fixtures/tools.js +57 -0
- package/dist/src/fixtures/tools.js.map +1 -0
- package/dist/src/fixtures/workspace-state.js +155 -0
- package/dist/src/fixtures/workspace-state.js.map +1 -0
- package/dist/src/generated/cli-result.cjs +2 -0
- package/dist/src/generated/extension.cjs +2 -0
- package/dist/src/generated/report.cjs +2 -0
- package/dist/src/generated/run-evidence.cjs +2 -0
- package/dist/src/generated/runtime.cjs +2 -0
- package/dist/src/git.js +72 -0
- package/dist/src/git.js.map +1 -0
- package/dist/src/graders/artifact.js +68 -0
- package/dist/src/graders/artifact.js.map +1 -0
- package/dist/src/graders/git-head.js +112 -0
- package/dist/src/graders/git-head.js.map +1 -0
- package/dist/src/graders/output.js +345 -0
- package/dist/src/graders/output.js.map +1 -0
- package/dist/src/graders/semantic.js +132 -0
- package/dist/src/graders/semantic.js.map +1 -0
- package/dist/src/graders/shell.js +321 -0
- package/dist/src/graders/shell.js.map +1 -0
- package/dist/src/host-diagnostic-redaction.js +52 -0
- package/dist/src/host-diagnostic-redaction.js.map +1 -0
- package/dist/src/host-diagnostics.js +248 -0
- package/dist/src/host-diagnostics.js.map +1 -0
- package/dist/src/hosts/claude-continuation.js +89 -0
- package/dist/src/hosts/claude-continuation.js.map +1 -0
- package/dist/src/hosts/claude-credential.js +121 -0
- package/dist/src/hosts/claude-credential.js.map +1 -0
- package/dist/src/hosts/claude-events.js +136 -0
- package/dist/src/hosts/claude-events.js.map +1 -0
- package/dist/src/hosts/claude-keychain.js +100 -0
- package/dist/src/hosts/claude-keychain.js.map +1 -0
- package/dist/src/hosts/claude-login-recovery.js +67 -0
- package/dist/src/hosts/claude-login-recovery.js.map +1 -0
- package/dist/src/hosts/claude-login-refresh.js +146 -0
- package/dist/src/hosts/claude-login-refresh.js.map +1 -0
- package/dist/src/hosts/claude-login-store.js +124 -0
- package/dist/src/hosts/claude-login-store.js.map +1 -0
- package/dist/src/hosts/claude-login.js +74 -0
- package/dist/src/hosts/claude-login.js.map +1 -0
- package/dist/src/hosts/claude-native-goal.js +138 -0
- package/dist/src/hosts/claude-native-goal.js.map +1 -0
- package/dist/src/hosts/claude-process.js +10 -0
- package/dist/src/hosts/claude-process.js.map +1 -0
- package/dist/src/hosts/claude-refresh-lock.js +76 -0
- package/dist/src/hosts/claude-refresh-lock.js.map +1 -0
- package/dist/src/hosts/claude-repository-invocation.js +229 -0
- package/dist/src/hosts/claude-repository-invocation.js.map +1 -0
- package/dist/src/hosts/claude-settings.js +156 -0
- package/dist/src/hosts/claude-settings.js.map +1 -0
- package/dist/src/hosts/claude-skill-activations.js +131 -0
- package/dist/src/hosts/claude-skill-activations.js.map +1 -0
- package/dist/src/hosts/claude-state.js +237 -0
- package/dist/src/hosts/claude-state.js.map +1 -0
- package/dist/src/hosts/claude-tool-calls.js +150 -0
- package/dist/src/hosts/claude-tool-calls.js.map +1 -0
- package/dist/src/hosts/claude.js +373 -0
- package/dist/src/hosts/claude.js.map +1 -0
- package/dist/src/hosts/codex-app-server.js +764 -0
- package/dist/src/hosts/codex-app-server.js.map +1 -0
- package/dist/src/hosts/codex-configuration.js +91 -0
- package/dist/src/hosts/codex-configuration.js.map +1 -0
- package/dist/src/hosts/codex-events.js +104 -0
- package/dist/src/hosts/codex-events.js.map +1 -0
- package/dist/src/hosts/codex-exec-controls.js +434 -0
- package/dist/src/hosts/codex-exec-controls.js.map +1 -0
- package/dist/src/hosts/codex-invocation.js +54 -0
- package/dist/src/hosts/codex-invocation.js.map +1 -0
- package/dist/src/hosts/codex-marketplace.js +185 -0
- package/dist/src/hosts/codex-marketplace.js.map +1 -0
- package/dist/src/hosts/codex-native-calls.js +516 -0
- package/dist/src/hosts/codex-native-calls.js.map +1 -0
- package/dist/src/hosts/codex-process.js +10 -0
- package/dist/src/hosts/codex-process.js.map +1 -0
- package/dist/src/hosts/codex-profile.js +206 -0
- package/dist/src/hosts/codex-profile.js.map +1 -0
- package/dist/src/hosts/codex-session-files.js +89 -0
- package/dist/src/hosts/codex-session-files.js.map +1 -0
- package/dist/src/hosts/codex-state.js +310 -0
- package/dist/src/hosts/codex-state.js.map +1 -0
- package/dist/src/hosts/codex.js +527 -0
- package/dist/src/hosts/codex.js.map +1 -0
- package/dist/src/hosts/isolation-common.js +43 -0
- package/dist/src/hosts/isolation-common.js.map +1 -0
- package/dist/src/hosts/isolation-roots.js +64 -0
- package/dist/src/hosts/isolation-roots.js.map +1 -0
- package/dist/src/hosts/isolation.js +12 -0
- package/dist/src/hosts/isolation.js.map +1 -0
- package/dist/src/hosts/linux-sandbox.js +127 -0
- package/dist/src/hosts/linux-sandbox.js.map +1 -0
- package/dist/src/hosts/mac-sandbox.js +137 -0
- package/dist/src/hosts/mac-sandbox.js.map +1 -0
- package/dist/src/hosts/native-controls.js +151 -0
- package/dist/src/hosts/native-controls.js.map +1 -0
- package/dist/src/hosts/native-request.js +33 -0
- package/dist/src/hosts/native-request.js.map +1 -0
- package/dist/src/hosts/process-lifecycle.js +167 -0
- package/dist/src/hosts/process-lifecycle.js.map +1 -0
- package/dist/src/hosts/protected-worktrees.js +81 -0
- package/dist/src/hosts/protected-worktrees.js.map +1 -0
- package/dist/src/hosts/skill-hook-catalog.js +100 -0
- package/dist/src/hosts/skill-hook-catalog.js.map +1 -0
- package/dist/src/hosts/skill-hook-handler.js +228 -0
- package/dist/src/hosts/skill-hook-handler.js.map +1 -0
- package/dist/src/hosts/skill-hooks.js +423 -0
- package/dist/src/hosts/skill-hooks.js.map +1 -0
- package/dist/src/hosts/workspace-fingerprint.js +72 -0
- package/dist/src/hosts/workspace-fingerprint.js.map +1 -0
- package/dist/src/identity.js +167 -0
- package/dist/src/identity.js.map +1 -0
- package/dist/src/instrumentation.js +83 -0
- package/dist/src/instrumentation.js.map +1 -0
- package/dist/src/native-transcript-state.js +85 -0
- package/dist/src/native-transcript-state.js.map +1 -0
- package/dist/src/native-transcript-view.js +65 -0
- package/dist/src/native-transcript-view.js.map +1 -0
- package/dist/src/native-transcripts.js +208 -0
- package/dist/src/native-transcripts.js.map +1 -0
- package/dist/src/paths.js +13 -0
- package/dist/src/paths.js.map +1 -0
- package/dist/src/process-lifecycle.js +101 -0
- package/dist/src/process-lifecycle.js.map +1 -0
- package/dist/src/provenance.js +263 -0
- package/dist/src/provenance.js.map +1 -0
- package/dist/src/prune.js +228 -0
- package/dist/src/prune.js.map +1 -0
- package/dist/src/report.js +276 -0
- package/dist/src/report.js.map +1 -0
- package/dist/src/resolved-case.js +29 -0
- package/dist/src/resolved-case.js.map +1 -0
- package/dist/src/results-lock.js +40 -0
- package/dist/src/results-lock.js.map +1 -0
- package/dist/src/results.js +127 -0
- package/dist/src/results.js.map +1 -0
- package/dist/src/run-owner.js +283 -0
- package/dist/src/run-owner.js.map +1 -0
- package/dist/src/runner-paths.js +11 -0
- package/dist/src/runner-paths.js.map +1 -0
- package/dist/src/runtime/config.js +323 -0
- package/dist/src/runtime/config.js.map +1 -0
- package/dist/src/runtime/discovery-apple.js +65 -0
- package/dist/src/runtime/discovery-apple.js.map +1 -0
- package/dist/src/runtime/discovery-providers.js +37 -0
- package/dist/src/runtime/discovery-providers.js.map +1 -0
- package/dist/src/runtime/discovery.js +40 -0
- package/dist/src/runtime/discovery.js.map +1 -0
- package/dist/src/runtime/hook-processes.js +81 -0
- package/dist/src/runtime/hook-processes.js.map +1 -0
- package/dist/src/runtime/hooks.js +304 -0
- package/dist/src/runtime/hooks.js.map +1 -0
- package/dist/src/runtime/paths.js +244 -0
- package/dist/src/runtime/paths.js.map +1 -0
- package/dist/src/runtime/query.js +76 -0
- package/dist/src/runtime/query.js.map +1 -0
- package/dist/src/runtime/seeds.js +98 -0
- package/dist/src/runtime/seeds.js.map +1 -0
- package/dist/src/runtime/shared-cache.js +81 -0
- package/dist/src/runtime/shared-cache.js.map +1 -0
- package/dist/src/runtime/state.js +106 -0
- package/dist/src/runtime/state.js.map +1 -0
- package/dist/src/runtime-process.js +148 -0
- package/dist/src/runtime-process.js.map +1 -0
- package/dist/src/schema-types.js +2 -0
- package/dist/src/schema-types.js.map +1 -0
- package/dist/src/schema.js +16 -0
- package/dist/src/schema.js.map +1 -0
- package/dist/src/shell.js +5 -0
- package/dist/src/shell.js.map +1 -0
- package/dist/src/sqlite-lock.js +18 -0
- package/dist/src/sqlite-lock.js.map +1 -0
- package/dist/src/storage.js +21 -0
- package/dist/src/storage.js.map +1 -0
- package/dist/src/transcript-retention.js +109 -0
- package/dist/src/transcript-retention.js.map +1 -0
- package/dist/src/value-guards.js +26 -0
- package/dist/src/value-guards.js.map +1 -0
- package/docs/README.md +19 -15
- package/docs/architecture.md +141 -17
- package/docs/assets/README.md +5 -4
- package/docs/builtin-graders-v1.md +9 -2
- package/docs/codex-host.md +155 -57
- package/docs/contracts.md +2 -1
- package/docs/creating-cases.md +10 -4
- package/docs/development-cli.md +197 -24
- package/docs/documentation-quality.md +16 -5
- package/docs/evaluation-workflow.md +110 -0
- package/docs/extension-protocol-v1.md +26 -3
- package/docs/getting-started.md +29 -7
- package/docs/guide-evaluation.md +34 -2
- package/docs/identity-v1.md +29 -3
- package/docs/installing.md +35 -17
- package/docs/licensing.md +2 -2
- package/docs/native-controls.md +76 -5
- package/docs/native-hosts.md +197 -8
- package/docs/reading-results.md +102 -0
- package/docs/recipes.md +490 -0
- package/docs/releases.md +48 -13
- package/docs/report-v1.md +29 -1
- package/docs/results-v1.md +122 -4
- package/docs/run-settings-v1.md +147 -0
- package/docs/runtime-v1.md +255 -22
- package/docs/specs/repository-guide.md +1 -1
- package/docs/troubleshooting.md +12 -12
- package/docs/typescript-quality.md +106 -26
- package/examples/recipes/candidate.ts +26 -0
- package/examples/recipes/cases/coding-change.json +21 -0
- package/examples/recipes/cases/host-tools.json +21 -0
- package/examples/recipes/cases/mise.json +21 -0
- package/examples/recipes/cases/node.json +21 -0
- package/examples/recipes/cases/python-uv.json +21 -0
- package/examples/recipes/cases/semantic.json +17 -0
- package/examples/recipes/coding-change/check.ts +23 -0
- package/examples/recipes/executable.ts +19 -0
- package/examples/recipes/extension-artifacts.ts +65 -0
- package/examples/recipes/extension-methods.ts +174 -0
- package/examples/recipes/extension.ts +38 -0
- package/examples/recipes/modules.ts +9 -0
- package/examples/recipes/repository-skill/.agents/skills/startup-guide/SKILL.md +7 -0
- package/examples/recipes/repository-skill/.claude/skills/startup-guide/SKILL.md +7 -0
- package/examples/recipes/repository-skill/README.md +3 -0
- package/examples/recipes/run-inputs.ts +183 -0
- package/examples/recipes/run-options.ts +132 -0
- package/examples/recipes/run.ts +77 -0
- package/examples/recipes/runtime/empty.json +1 -0
- package/examples/recipes/runtime/goals.json +1 -0
- package/examples/recipes/runtime/mise.json +6 -0
- package/examples/recipes/runtime/path.json +1 -0
- package/examples/recipes/runtime/plugins.json +4 -0
- package/examples/recipes/runtime/python-uv.json +10 -0
- package/examples/recipes/semantic-judge.ts +29 -0
- package/examples/templates/coding/adapter.ts +17 -0
- package/examples/templates/coding/case.json +15 -0
- package/examples/templates/repository-skill/.agents/skills/startup-guide/SKILL.md +6 -0
- package/examples/templates/repository-skill/extension-data.ts +64 -0
- package/examples/templates/repository-skill/extension.ts +32 -0
- package/examples/templates/response/adapter.ts +12 -0
- package/examples/templates/response/case.json +13 -0
- package/package.json +23 -9
- package/schemas/report-v1.schema.json +9 -0
- package/schemas/run-evidence-v1.schema.json +2 -1
- package/schemas/runtime-v1.schema.json +43 -7
- package/src/advisory.ts +2 -2
- package/src/candidate-artifacts.ts +42 -11
- package/src/candidate-codex-state.ts +185 -0
- package/src/case-validation.ts +73 -50
- package/src/cli/cancellation.ts +20 -0
- package/src/cli/command.ts +87 -0
- package/src/cli/completion.ts +15 -0
- package/src/cli/demo.ts +61 -0
- package/src/cli/evaluation.ts +55 -0
- package/src/cli/extension.ts +79 -0
- package/src/cli/help.ts +199 -0
- package/src/cli/hosts.ts +55 -0
- package/src/cli/init-settings.ts +31 -0
- package/src/cli/init.ts +112 -0
- package/src/{cli-invocation.ts → cli/invocation.ts} +215 -218
- package/src/cli/loading.ts +151 -0
- package/src/cli/preparation.ts +154 -0
- package/src/cli/presentation.ts +93 -0
- package/src/cli/progress.ts +6 -0
- package/src/cli/run-manifest.ts +128 -0
- package/src/cli/run-options.ts +403 -0
- package/src/cli/run-overrides.ts +69 -0
- package/src/cli/settings.ts +154 -0
- package/src/cli/summary.ts +43 -0
- package/src/cli.ts +14 -592
- package/src/contract-types.ts +94 -0
- package/src/engine.ts +9 -5
- package/src/evaluation/advisory.ts +150 -0
- package/src/{evaluation-check-plan.ts → evaluation/check-plan.ts} +103 -67
- package/src/evaluation/collection.ts +88 -0
- package/src/evaluation/context.ts +10 -0
- package/src/{evaluation-grading-host.ts → evaluation/grading-host.ts} +5 -5
- package/src/evaluation/grading.ts +235 -0
- package/src/{evaluation-invocation-plan.ts → evaluation/invocation-plan.ts} +147 -58
- package/src/{evaluation-plan.ts → evaluation/plan.ts} +208 -141
- package/src/evaluation/progress.ts +19 -0
- package/src/evaluation/resources.ts +241 -0
- package/src/evaluation/run.ts +206 -0
- package/src/{evaluation-semantic.ts → evaluation/semantic.ts} +77 -87
- package/src/evaluation/trial.ts +800 -0
- package/src/{evaluation-types.ts → evaluation/types.ts} +79 -29
- package/src/evidence/host-results.ts +85 -0
- package/src/evidence/retained-artifacts.ts +18 -0
- package/src/evidence/trial-writer.ts +203 -0
- package/src/evidence/usage.ts +17 -0
- package/src/executable.ts +19 -0
- package/src/extension-client.ts +40 -108
- package/src/extension-session.ts +24 -48
- package/src/{advisory-fixture.ts → fixtures/advisory.ts} +12 -72
- package/src/{fixture-bin.ts → fixtures/bin.ts} +1 -1
- package/src/{fixture-cleanup.ts → fixtures/cleanup.ts} +13 -7
- package/src/fixtures/create.ts +183 -0
- package/src/{generated-fixture.ts → fixtures/generated.ts} +10 -53
- package/src/{git-hooks.ts → fixtures/git-hooks.ts} +1 -1
- package/src/{preparation.ts → fixtures/preparation.ts} +6 -16
- package/src/{repository-fixture.ts → fixtures/repository.ts} +30 -64
- package/src/{fixture-setup.ts → fixtures/setup.ts} +36 -53
- package/src/{fixture-tools.ts → fixtures/tools.ts} +1 -1
- package/src/{workspace-state.ts → fixtures/workspace-state.ts} +5 -5
- package/src/generated/cli-result.d.cts +2 -1
- package/src/generated/extension.d.cts +2 -1
- package/src/generated/report.cjs +1 -1
- package/src/generated/report.d.cts +2 -1
- package/src/generated/run-evidence.cjs +1 -1
- package/src/generated/run-evidence.d.cts +2 -1
- package/src/generated/runtime.cjs +1 -1
- package/src/generated/runtime.d.cts +2 -1
- package/src/git.ts +94 -0
- package/src/graders/git-head.ts +31 -85
- package/src/graders/shell.ts +54 -71
- package/src/host-diagnostic-redaction.ts +52 -0
- package/src/host-diagnostics.ts +331 -0
- package/src/hosts/claude-continuation.ts +57 -40
- package/src/hosts/claude-credential.ts +160 -63
- package/src/hosts/claude-events.ts +34 -18
- package/src/hosts/claude-keychain.ts +79 -21
- package/src/hosts/claude-login-recovery.ts +85 -0
- package/src/hosts/claude-login-refresh.ts +179 -0
- package/src/hosts/claude-login-store.ts +162 -0
- package/src/hosts/claude-login.ts +107 -0
- package/src/hosts/claude-native-goal.ts +15 -12
- package/src/hosts/claude-process.ts +10 -50
- package/src/hosts/claude-refresh-lock.ts +82 -0
- package/src/hosts/claude-repository-invocation.ts +9 -34
- package/src/hosts/claude-settings.ts +46 -9
- package/src/hosts/claude-skill-activations.ts +169 -0
- package/src/hosts/claude-state.ts +28 -15
- package/src/hosts/claude-tool-calls.ts +13 -10
- package/src/hosts/claude.ts +121 -81
- package/src/hosts/codex-app-server.ts +78 -52
- package/src/hosts/codex-configuration.ts +5 -10
- package/src/hosts/codex-exec-controls.ts +516 -0
- package/src/hosts/codex-marketplace.ts +12 -10
- package/src/hosts/codex-native-calls.ts +15 -122
- package/src/hosts/codex-process.ts +10 -183
- package/src/hosts/codex-profile.ts +36 -21
- package/src/hosts/codex-session-files.ts +1 -9
- package/src/hosts/codex-state.ts +134 -18
- package/src/hosts/codex.ts +210 -183
- package/src/hosts/isolation-common.ts +8 -11
- package/src/hosts/isolation-roots.ts +5 -4
- package/src/hosts/linux-sandbox.ts +15 -2
- package/src/hosts/mac-sandbox.ts +87 -18
- package/src/hosts/native-controls.ts +72 -22
- package/src/hosts/native-request.ts +55 -0
- package/src/hosts/process-lifecycle.ts +215 -49
- package/src/hosts/protected-worktrees.ts +3 -2
- package/src/hosts/skill-hook-catalog.ts +131 -0
- package/src/hosts/skill-hook-handler.ts +374 -0
- package/src/hosts/skill-hooks.ts +585 -0
- package/src/instrumentation.ts +7 -8
- package/src/native-transcript-state.ts +22 -3
- package/src/native-transcript-view.ts +52 -13
- package/src/native-transcripts.ts +26 -11
- package/src/paths.ts +22 -0
- package/src/process-lifecycle.ts +150 -0
- package/src/provenance.ts +34 -13
- package/src/prune.ts +300 -0
- package/src/report.ts +63 -36
- package/src/resolved-case.ts +1 -1
- package/src/results-lock.ts +42 -0
- package/src/results.ts +14 -18
- package/src/run-owner.ts +15 -9
- package/src/runner-paths.ts +21 -0
- package/src/{runtime-config.ts → runtime/config.ts} +160 -46
- package/src/{runtime-discovery-apple.ts → runtime/discovery-apple.ts} +3 -3
- package/src/{runtime-discovery-providers.ts → runtime/discovery-providers.ts} +3 -9
- package/src/{runtime-discovery.ts → runtime/discovery.ts} +4 -4
- package/src/{runtime-hook-processes.ts → runtime/hook-processes.ts} +3 -2
- package/src/{runtime-hooks.ts → runtime/hooks.ts} +40 -28
- package/src/{runtime-paths.ts → runtime/paths.ts} +5 -19
- package/src/{runtime-query.ts → runtime/query.ts} +5 -5
- package/src/{runtime-seeds.ts → runtime/seeds.ts} +3 -3
- package/src/runtime/shared-cache.ts +130 -0
- package/src/{runtime-state.ts → runtime/state.ts} +28 -11
- package/src/runtime-process.ts +194 -0
- package/src/schema-types.ts +73 -161
- package/src/shell.ts +4 -0
- package/src/sqlite-lock.ts +25 -0
- package/src/transcript-retention.ts +146 -0
- package/src/value-guards.ts +22 -0
- package/docs/assets/sevro-logo.png +0 -0
- package/docs/assets/sevro-symbol.svg +0 -1
- package/docs/assets/sevro-wordmark.svg +0 -1
- package/docs/cache-ownership-validation.md +0 -49
- package/docs/claude-continuation-validation.md +0 -47
- package/docs/concurrency-validation.md +0 -86
- package/docs/configuration-root-validation.md +0 -70
- package/docs/engine-slice.md +0 -114
- package/docs/evidence/runtime-startup-30/README.md +0 -185
- package/docs/evidence/runtime-startup-30/after.json +0 -319
- package/docs/evidence/runtime-startup-30/baseline-timeout.jsonl +0 -2
- package/docs/evidence/runtime-startup-30/before.json +0 -403
- package/docs/evidence/runtime-startup-30/consumer-smoke.json +0 -63
- package/docs/evidence/runtime-startup-30/full-policy-diagnostic.jsonl +0 -3
- package/docs/evidence/runtime-startup-30/minimal-policy-diagnostic.jsonl +0 -3
- package/docs/evidence/runtime-startup-30/plugin-template-assessment.json +0 -20
- package/docs/evidence/runtime-startup-30/seedless-timeout.jsonl +0 -2
- package/docs/evidence.md +0 -17
- package/docs/fixture-cleanup-validation.md +0 -73
- package/docs/guide-verification.json +0 -239
- package/src/evaluation-context.ts +0 -259
- package/src/evaluation-fixture.ts +0 -302
- package/src/evaluation-run.ts +0 -200
- package/src/evaluation-trial.ts +0 -1016
- package/src/hosts/claude-nested-skills.ts +0 -272
- package/src/hosts/codex-command-output.ts +0 -510
- package/src/hosts/codex-executor-command.ts +0 -291
- package/src/hosts/codex-skill-reads.ts +0 -783
- /package/src/{trial-scheduler.ts → evaluation/scheduler.ts} +0 -0
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
+
import { gunzipSync } from "node:zlib";
|
|
3
4
|
import { allocateNativeState } from "./native-transcript-state";
|
|
4
|
-
import { fixtureParts } from "./preparation";
|
|
5
|
+
import { fixtureParts } from "./fixtures/preparation";
|
|
5
6
|
import { isRecord, isUnknownArray } from "./value-guards";
|
|
6
7
|
import { sha256 } from "./identity";
|
|
7
8
|
|
|
9
|
+
const MAX_NATIVE_BYTES = 5 * 1024 * 1024;
|
|
10
|
+
type NativeFormat =
|
|
11
|
+
"sevro.native-transcripts.v1" | "sevro.native-transcripts.v2";
|
|
12
|
+
|
|
8
13
|
export async function materializeNativeTranscriptView(
|
|
9
14
|
bytes: Uint8Array,
|
|
10
15
|
): Promise<string> {
|
|
@@ -12,19 +17,33 @@ export async function materializeNativeTranscriptView(
|
|
|
12
17
|
const bundle = nativeBundle(value);
|
|
13
18
|
const root = await allocateNativeState("view-");
|
|
14
19
|
await writeFile(join(root, "index.json"), bytes, { flag: "wx", mode: 0o600 });
|
|
20
|
+
const filesRoot = join(root, bundle.host);
|
|
21
|
+
let remainingBytes = MAX_NATIVE_BYTES;
|
|
15
22
|
for (const item of bundle.files)
|
|
16
|
-
await materializeNativeFile(
|
|
23
|
+
remainingBytes -= await materializeNativeFile(
|
|
24
|
+
filesRoot,
|
|
25
|
+
item,
|
|
26
|
+
bundle.format,
|
|
27
|
+
remainingBytes,
|
|
28
|
+
);
|
|
17
29
|
return root;
|
|
18
30
|
}
|
|
19
31
|
|
|
20
32
|
function nativeBundle(value: unknown) {
|
|
21
|
-
if (!isRecord(value) || value.format
|
|
33
|
+
if (!isRecord(value) || !nativeFormat(value.format))
|
|
22
34
|
throw new Error("invalid native transcript bundle");
|
|
23
35
|
if (!nativeHost(value.host))
|
|
24
36
|
throw new Error("invalid native transcript host");
|
|
25
37
|
if (!isUnknownArray(value.files))
|
|
26
38
|
throw new Error("invalid native transcript files");
|
|
27
|
-
return { host: value.host, files: value.files };
|
|
39
|
+
return { host: value.host, files: value.files, format: value.format };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function nativeFormat(value: unknown): value is NativeFormat {
|
|
43
|
+
return (
|
|
44
|
+
value === "sevro.native-transcripts.v1" ||
|
|
45
|
+
value === "sevro.native-transcripts.v2"
|
|
46
|
+
);
|
|
28
47
|
}
|
|
29
48
|
|
|
30
49
|
function nativeHost(value: unknown): value is "codex" | "claude" {
|
|
@@ -33,19 +52,39 @@ function nativeHost(value: unknown): value is "codex" | "claude" {
|
|
|
33
52
|
|
|
34
53
|
async function materializeNativeFile(
|
|
35
54
|
root: string,
|
|
36
|
-
host: string,
|
|
37
55
|
value: unknown,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
typeof value.bytesBase64 !== "string"
|
|
43
|
-
)
|
|
56
|
+
format: NativeFormat,
|
|
57
|
+
remainingBytes: number,
|
|
58
|
+
): Promise<number> {
|
|
59
|
+
if (!isRecord(value) || typeof value.path !== "string")
|
|
44
60
|
throw new Error("invalid native transcript file");
|
|
45
|
-
const path = join(root,
|
|
46
|
-
const bytes =
|
|
61
|
+
const path = join(root, ...fixtureParts(value.path));
|
|
62
|
+
const bytes = nativeFileBytes(value, format, remainingBytes);
|
|
63
|
+
if (bytes.length > remainingBytes)
|
|
64
|
+
throw new Error("native transcript byte limit exceeded");
|
|
47
65
|
if (sha256(bytes) !== value.sha256)
|
|
48
66
|
throw new Error("native transcript hash mismatch");
|
|
49
67
|
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
50
68
|
await writeFile(path, bytes, { flag: "wx", mode: 0o600 });
|
|
69
|
+
return bytes.length;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function nativeFileBytes(
|
|
73
|
+
value: Record<string, unknown>,
|
|
74
|
+
format: NativeFormat,
|
|
75
|
+
remainingBytes: number,
|
|
76
|
+
): Buffer {
|
|
77
|
+
const encoded =
|
|
78
|
+
format === "sevro.native-transcripts.v1"
|
|
79
|
+
? value.bytesBase64
|
|
80
|
+
: value.gzipBase64;
|
|
81
|
+
if (typeof encoded !== "string")
|
|
82
|
+
throw new Error("invalid native transcript file");
|
|
83
|
+
const bytes = Buffer.from(encoded, "base64");
|
|
84
|
+
if (format === "sevro.native-transcripts.v1") return bytes;
|
|
85
|
+
try {
|
|
86
|
+
return gunzipSync(bytes, { maxOutputLength: Math.max(1, remainingBytes) });
|
|
87
|
+
} catch (cause) {
|
|
88
|
+
throw new Error("invalid native transcript gzip", { cause });
|
|
89
|
+
}
|
|
51
90
|
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { lstat, readdir, readFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { gzipSync } from "node:zlib";
|
|
3
4
|
import { sha256 } from "./identity";
|
|
4
|
-
import type
|
|
5
|
-
import type { RuntimeRole } from "./runtime
|
|
6
|
-
import type { RuntimePolicy } from "./runtime
|
|
5
|
+
import { HostExecutionFailure, type HostResult } from "./evaluation/types";
|
|
6
|
+
import type { RuntimeRole } from "./runtime/state";
|
|
7
|
+
import type { RuntimePolicy } from "./runtime/config";
|
|
7
8
|
import { isRecord } from "./value-guards";
|
|
8
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
rethrowDiagnosticPersistenceError,
|
|
11
|
+
type HostDiagnostics,
|
|
12
|
+
} from "./host-diagnostics";
|
|
9
13
|
|
|
10
14
|
export function candidateTranscriptRoots(root: string | undefined): string[] {
|
|
11
15
|
return root ? [root] : [];
|
|
@@ -48,11 +52,13 @@ export async function failedNativeTranscripts(
|
|
|
48
52
|
policy: RuntimePolicy | undefined,
|
|
49
53
|
root: string,
|
|
50
54
|
host: "codex" | "claude",
|
|
51
|
-
role
|
|
55
|
+
role: RuntimeRole | undefined,
|
|
56
|
+
diagnostics: HostDiagnostics,
|
|
52
57
|
): Promise<HostResult> {
|
|
53
|
-
|
|
58
|
+
rethrowDiagnosticPersistenceError(cause);
|
|
59
|
+
requireFailureCapture(cause, policy, diagnostics);
|
|
54
60
|
const result: HostResult =
|
|
55
|
-
cause instanceof
|
|
61
|
+
cause instanceof HostExecutionFailure
|
|
56
62
|
? cause.result
|
|
57
63
|
: {
|
|
58
64
|
finalMessage: null,
|
|
@@ -60,14 +66,23 @@ export async function failedNativeTranscripts(
|
|
|
60
66
|
executionFailed: true,
|
|
61
67
|
actualCondition: "passive",
|
|
62
68
|
};
|
|
63
|
-
await
|
|
69
|
+
await diagnostics.retain(result, cause);
|
|
70
|
+
await retainEnabledNativeTranscripts(result, policy, root, host, role);
|
|
64
71
|
return result;
|
|
65
72
|
}
|
|
66
73
|
|
|
74
|
+
function requireFailureCapture(
|
|
75
|
+
cause: unknown,
|
|
76
|
+
policy: RuntimePolicy | undefined,
|
|
77
|
+
diagnostics: HostDiagnostics,
|
|
78
|
+
): void {
|
|
79
|
+
if (policy?.nativeTranscripts !== true && !diagnostics.enabled) throw cause;
|
|
80
|
+
}
|
|
81
|
+
|
|
67
82
|
const MAX_FILES = 4096;
|
|
68
83
|
const MAX_BYTES = 5 * 1024 * 1024;
|
|
69
84
|
const MAX_ENCODED_FILES_BYTES = 7 * 1024 * 1024;
|
|
70
|
-
type NativeFile = { path: string; sha256: string;
|
|
85
|
+
type NativeFile = { path: string; sha256: string; gzipBase64: string };
|
|
71
86
|
type Capture = {
|
|
72
87
|
files: NativeFile[];
|
|
73
88
|
bytes: number;
|
|
@@ -99,7 +114,7 @@ export async function retainNativeTranscripts(
|
|
|
99
114
|
observeCaptureRoot(capture, rootSessionId, host);
|
|
100
115
|
const completeness = captureCompleteness(capture, result);
|
|
101
116
|
const bundle = {
|
|
102
|
-
format: "sevro.native-transcripts.
|
|
117
|
+
format: "sevro.native-transcripts.v2",
|
|
103
118
|
host,
|
|
104
119
|
role,
|
|
105
120
|
rootSessionId,
|
|
@@ -212,7 +227,7 @@ async function captureFile(
|
|
|
212
227
|
const file = {
|
|
213
228
|
path,
|
|
214
229
|
sha256: sha256(bytes),
|
|
215
|
-
|
|
230
|
+
gzipBase64: gzipSync(bytes).toString("base64"),
|
|
216
231
|
};
|
|
217
232
|
const issue = nativeFileIssue(path, bytes);
|
|
218
233
|
if (issue && !capture.issues.includes(issue)) capture.issues.push(issue);
|
package/src/paths.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { isAbsolute, relative, sep } from "node:path";
|
|
2
|
+
|
|
3
|
+
/** Lexical containment includes the root itself; callers resolve symlinks first. */
|
|
4
|
+
export function insideRoot(root: string, path: string): boolean {
|
|
5
|
+
const child = relative(root, path);
|
|
6
|
+
return (
|
|
7
|
+
child === "" ||
|
|
8
|
+
(child !== ".." && !child.startsWith(`..${sep}`) && !isAbsolute(child))
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Keep outermost roots in input order, retaining the first equivalent spelling. */
|
|
13
|
+
export function minimalRoots(roots: string[]): string[] {
|
|
14
|
+
return roots.filter(
|
|
15
|
+
(root, index) =>
|
|
16
|
+
!roots.some(
|
|
17
|
+
(other, otherIndex) =>
|
|
18
|
+
insideRoot(other, root) &&
|
|
19
|
+
(!insideRoot(root, other) || otherIndex < index),
|
|
20
|
+
),
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
export type ProcessInterruptionReason = "timeout" | "cancelled";
|
|
2
|
+
|
|
3
|
+
interface DeadlineOptions {
|
|
4
|
+
timeoutMs: number;
|
|
5
|
+
signal?: AbortSignal;
|
|
6
|
+
interruption: (reason: ProcessInterruptionReason) => Error;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Keep the deadline active until the caller has finished failure cleanup. */
|
|
10
|
+
export class ProcessDeadline {
|
|
11
|
+
private timer: ReturnType<typeof setTimeout> | undefined;
|
|
12
|
+
private cancel: (() => void) | undefined;
|
|
13
|
+
|
|
14
|
+
constructor(private readonly options: DeadlineOptions) {}
|
|
15
|
+
|
|
16
|
+
wait<T>(completed: Promise<T> | (() => Promise<T>)): Promise<T> {
|
|
17
|
+
const timeout = this.timeout();
|
|
18
|
+
const aborted = this.aborted();
|
|
19
|
+
const completion =
|
|
20
|
+
typeof completed === "function" ? completed() : completed;
|
|
21
|
+
return Promise.race([completion, timeout, aborted]);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private timeout(): Promise<never> {
|
|
25
|
+
return new Promise((_resolve, reject) => {
|
|
26
|
+
this.timer = setTimeout(() => {
|
|
27
|
+
reject(this.options.interruption("timeout"));
|
|
28
|
+
}, this.options.timeoutMs);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private aborted(): Promise<never> {
|
|
33
|
+
return new Promise((_resolve, reject) => {
|
|
34
|
+
const signal = this.options.signal;
|
|
35
|
+
if (!signal) return;
|
|
36
|
+
this.cancel = () => {
|
|
37
|
+
reject(this.options.interruption("cancelled"));
|
|
38
|
+
};
|
|
39
|
+
if (signal.aborted) this.cancel();
|
|
40
|
+
else signal.addEventListener("abort", this.cancel, { once: true });
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
dispose(): void {
|
|
45
|
+
if (this.timer) clearTimeout(this.timer);
|
|
46
|
+
if (this.cancel)
|
|
47
|
+
this.options.signal?.removeEventListener("abort", this.cancel);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface OwnedProcess {
|
|
52
|
+
pid: number;
|
|
53
|
+
kill: (signal: "SIGKILL") => unknown;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface TerminationOptions {
|
|
57
|
+
alwaysGroup?: boolean;
|
|
58
|
+
fallbackError?: "ignore" | "propagate";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function killGroup(pid: number): boolean {
|
|
62
|
+
try {
|
|
63
|
+
process.kill(-pid, "SIGKILL");
|
|
64
|
+
return true;
|
|
65
|
+
} catch {
|
|
66
|
+
// The owned process group may already be gone.
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function useProcessGroup(options: TerminationOptions): boolean {
|
|
72
|
+
return options.alwaysGroup === true || process.platform !== "win32";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function killOwnedProcess(
|
|
76
|
+
proc: OwnedProcess,
|
|
77
|
+
options: TerminationOptions,
|
|
78
|
+
): void {
|
|
79
|
+
if (options.fallbackError === "propagate") {
|
|
80
|
+
proc.kill("SIGKILL");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
proc.kill("SIGKILL");
|
|
85
|
+
} catch {
|
|
86
|
+
// The owned process may already have exited.
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Only use for children spawned in a new, runner-owned process group. */
|
|
91
|
+
export function terminateOwnedProcessGroup(
|
|
92
|
+
proc: OwnedProcess,
|
|
93
|
+
options: TerminationOptions = {},
|
|
94
|
+
): void {
|
|
95
|
+
if (useProcessGroup(options) && killGroup(proc.pid)) return;
|
|
96
|
+
killOwnedProcess(proc, options);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
type RejectedCapture = {
|
|
100
|
+
overflow: "reject";
|
|
101
|
+
exceeded: () => Error;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
interface CaptureOptions {
|
|
105
|
+
limit: number;
|
|
106
|
+
observe?: (bytes: Uint8Array) => void;
|
|
107
|
+
cancelOnError?: boolean;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
type ByteCaptureOptions = CaptureOptions &
|
|
111
|
+
(RejectedCapture | { overflow: "truncate" });
|
|
112
|
+
|
|
113
|
+
function retainedChunk(
|
|
114
|
+
bytes: Uint8Array,
|
|
115
|
+
size: number,
|
|
116
|
+
options: ByteCaptureOptions,
|
|
117
|
+
): Uint8Array {
|
|
118
|
+
if (options.overflow === "reject" && size + bytes.byteLength > options.limit)
|
|
119
|
+
throw options.exceeded();
|
|
120
|
+
return bytes.subarray(0, Math.max(0, options.limit - size));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Truncation retains a byte prefix while still draining the entire stream. */
|
|
124
|
+
export async function captureBoundedBytes(
|
|
125
|
+
stream: ReadableStream<Uint8Array>,
|
|
126
|
+
options: ByteCaptureOptions,
|
|
127
|
+
): Promise<{ bytes: Uint8Array; truncated: boolean }> {
|
|
128
|
+
const chunks: Uint8Array[] = [];
|
|
129
|
+
let size = 0;
|
|
130
|
+
let truncated = false;
|
|
131
|
+
for await (const bytes of stream.values({
|
|
132
|
+
preventCancel: !options.cancelOnError,
|
|
133
|
+
})) {
|
|
134
|
+
options.observe?.(bytes);
|
|
135
|
+
const retained = retainedChunk(bytes, size, options);
|
|
136
|
+
if (retained.byteLength) chunks.push(retained);
|
|
137
|
+
size += retained.byteLength;
|
|
138
|
+
truncated ||= retained.byteLength !== bytes.byteLength;
|
|
139
|
+
}
|
|
140
|
+
return { bytes: Buffer.concat(chunks), truncated };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Reject oversize output before strictly decoding the complete UTF-8 stream. */
|
|
144
|
+
export async function captureBoundedText(
|
|
145
|
+
stream: ReadableStream<Uint8Array>,
|
|
146
|
+
options: CaptureOptions & RejectedCapture,
|
|
147
|
+
): Promise<string> {
|
|
148
|
+
const { bytes } = await captureBoundedBytes(stream, options);
|
|
149
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
150
|
+
}
|
package/src/provenance.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import { runnerRoot, sourceRuntime } from "./runner-paths";
|
|
2
|
+
import { spawnSync } from "./runtime-process";
|
|
1
3
|
import type { Stats } from "node:fs";
|
|
2
4
|
import { lstat, readFile, readdir, readlink, realpath } from "node:fs/promises";
|
|
3
5
|
import { tmpdir } from "node:os";
|
|
4
|
-
import { dirname,
|
|
6
|
+
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
7
|
+
import { insideRoot } from "./paths";
|
|
5
8
|
import { pathToFileURL } from "node:url";
|
|
6
|
-
import packageJson from "../package.json";
|
|
9
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
7
10
|
import { hashJson, sha256 } from "./identity";
|
|
11
|
+
import { insideRuntimeRoot } from "./runtime/paths";
|
|
8
12
|
|
|
9
13
|
const MAX_DIRTY_BYTES = 32 * 1024 * 1024;
|
|
10
14
|
const MAX_BUILD_BYTES = 64 * 1024 * 1024;
|
|
@@ -47,9 +51,7 @@ class BuildSnapshot {
|
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
/** Digest the packaged runtime and public contract files in path order. */
|
|
50
|
-
export async function packageBuildDigest(
|
|
51
|
-
root = join(import.meta.dir, ".."),
|
|
52
|
-
): Promise<string> {
|
|
54
|
+
export async function packageBuildDigest(root = runnerRoot): Promise<string> {
|
|
53
55
|
const snapshot = new BuildSnapshot(await realpath(root));
|
|
54
56
|
for (const path of [
|
|
55
57
|
"package.json",
|
|
@@ -58,6 +60,7 @@ export async function packageBuildDigest(
|
|
|
58
60
|
"examples",
|
|
59
61
|
"schemas",
|
|
60
62
|
"src",
|
|
63
|
+
...(!sourceRuntime ? ["dist"] : []),
|
|
61
64
|
])
|
|
62
65
|
await snapshot.collect(path);
|
|
63
66
|
return hashJson({
|
|
@@ -136,7 +139,7 @@ export async function projectIdentityDigest(
|
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
function git(root: string, ...arguments_: string[]): Buffer {
|
|
139
|
-
const result =
|
|
142
|
+
const result = spawnSync(["git", "-C", root, ...arguments_], {
|
|
140
143
|
env: { PATH: process.env.PATH ?? "/usr/bin:/bin", LC_ALL: "C" },
|
|
141
144
|
stdout: "pipe",
|
|
142
145
|
stderr: "ignore",
|
|
@@ -147,7 +150,10 @@ function git(root: string, ...arguments_: string[]): Buffer {
|
|
|
147
150
|
return Buffer.from(result.stdout);
|
|
148
151
|
}
|
|
149
152
|
|
|
150
|
-
async function dirtyPatchDigest(
|
|
153
|
+
async function dirtyPatchDigest(
|
|
154
|
+
gitRoot: string,
|
|
155
|
+
excludedRoots: string[],
|
|
156
|
+
): Promise<string | null> {
|
|
151
157
|
const trackedPatch = git(gitRoot, "diff", "--binary", "HEAD", "--");
|
|
152
158
|
const untrackedPaths = git(
|
|
153
159
|
gitRoot,
|
|
@@ -159,6 +165,12 @@ async function dirtyPatchDigest(gitRoot: string): Promise<string | null> {
|
|
|
159
165
|
.toString("utf8")
|
|
160
166
|
.split("\0")
|
|
161
167
|
.filter(Boolean)
|
|
168
|
+
.filter(
|
|
169
|
+
(path) =>
|
|
170
|
+
!excludedRoots.some((root) =>
|
|
171
|
+
insideRuntimeRoot(root, resolve(gitRoot, path)),
|
|
172
|
+
),
|
|
173
|
+
)
|
|
162
174
|
.sort();
|
|
163
175
|
let dirtyBytes = trackedPatch.byteLength;
|
|
164
176
|
const untracked: { path: string; sha256: string }[] = [];
|
|
@@ -175,8 +187,7 @@ async function dirtyPatchDigest(gitRoot: string): Promise<string | null> {
|
|
|
175
187
|
}
|
|
176
188
|
|
|
177
189
|
function requireSafeUntrackedPath(root: string, absolute: string): void {
|
|
178
|
-
|
|
179
|
-
if (isAbsolute(path) || path === ".." || path.startsWith(`..${sep}`))
|
|
190
|
+
if (!insideRoot(root, absolute))
|
|
180
191
|
throw new Error("Git checkout has an unsafe untracked path");
|
|
181
192
|
}
|
|
182
193
|
async function untrackedIdentityBytes(
|
|
@@ -209,7 +220,7 @@ export async function checkoutProvenance(root: string, buildDigest: string) {
|
|
|
209
220
|
source: "checkout" as const,
|
|
210
221
|
root: pathToFileURL(canonicalRoot).href,
|
|
211
222
|
revision,
|
|
212
|
-
dirtyPatchDigest: await dirtyPatchDigest(canonicalRoot),
|
|
223
|
+
dirtyPatchDigest: await dirtyPatchDigest(canonicalRoot, []),
|
|
213
224
|
buildDigest,
|
|
214
225
|
};
|
|
215
226
|
}
|
|
@@ -249,7 +260,10 @@ async function emptyTemporaryGitPlaceholder(
|
|
|
249
260
|
);
|
|
250
261
|
}
|
|
251
262
|
|
|
252
|
-
export async function projectProvenance(
|
|
263
|
+
export async function projectProvenance(
|
|
264
|
+
root: string,
|
|
265
|
+
excludedRoots?: string[],
|
|
266
|
+
) {
|
|
253
267
|
const canonicalRoot = await realpath(root);
|
|
254
268
|
const gitEntryRoot = await enclosingGitRoot(canonicalRoot);
|
|
255
269
|
if (!gitEntryRoot)
|
|
@@ -279,16 +293,23 @@ export async function projectProvenance(root: string) {
|
|
|
279
293
|
return {
|
|
280
294
|
root: pathToFileURL(canonicalRoot).href,
|
|
281
295
|
revision,
|
|
282
|
-
dirtyPatchDigest: await
|
|
296
|
+
dirtyPatchDigest: await projectDirtyDigest(gitRoot, excludedRoots),
|
|
283
297
|
};
|
|
284
298
|
}
|
|
285
299
|
|
|
300
|
+
async function projectDirtyDigest(
|
|
301
|
+
root: string,
|
|
302
|
+
excludedRoots: string[] | undefined,
|
|
303
|
+
) {
|
|
304
|
+
return dirtyPatchDigest(root, excludedRoots ?? []);
|
|
305
|
+
}
|
|
306
|
+
|
|
286
307
|
export async function runnerProvenance(
|
|
287
308
|
buildDigest: string,
|
|
288
309
|
checkoutRoot?: string,
|
|
289
310
|
) {
|
|
290
311
|
if (checkoutRoot) {
|
|
291
|
-
const actualRoot = await realpath(
|
|
312
|
+
const actualRoot = await realpath(runnerRoot);
|
|
292
313
|
if ((await realpath(checkoutRoot)) !== actualRoot)
|
|
293
314
|
throw new Error(
|
|
294
315
|
"local Sevro checkout root does not match the running package",
|