sneakoscope 7.0.2 → 7.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/bin/sks-dispatch.js +0 -3
- package/dist/cli/command-registry.js +0 -2
- package/dist/cli/install-helpers-codex-lb-chain.js +24 -2
- package/dist/cli/install-helpers-codex-lb-config.js +0 -7
- package/dist/cli/install-helpers-codex-lb-selftest-chain.js +0 -3
- package/dist/cli/install-helpers-codex-lb-selftest.js +0 -17
- package/dist/cli/install-helpers.js +81 -96
- package/dist/cli/router.js +0 -22
- package/dist/commands/codex-lb.js +176 -22
- package/dist/commands/codex.js +3 -8
- package/dist/commands/doctor.js +4 -14
- package/dist/commands/perf.js +5 -1
- package/dist/commands/zellij-slot-column-anchor.js +0 -2
- package/dist/commands/zellij-slot-pane.js +0 -7
- package/dist/commands/zellij.js +0 -2
- package/dist/config/skills-manifest.json +52 -52
- package/dist/core/agent-bridge/agent-manifest.js +192 -1
- package/dist/core/agent-bridge/agent-mode.js +0 -5
- package/dist/core/agent-bridge/host-capability-policy.js +189 -0
- package/dist/core/agent-bridge/host-capability-runtime.js +1395 -0
- package/dist/core/agent-bridge/mcp-server.js +1 -11
- package/dist/core/agents/agent-effort-policy.js +0 -3
- package/dist/core/agents/agent-orchestrator.js +0 -4
- package/dist/core/agents/agent-proof-evidence.js +0 -2
- package/dist/core/agents/agent-runner-ollama.js +0 -3
- package/dist/core/agents/agent-scheduler.js +0 -5
- package/dist/core/agents/native-cli-worker-runtime.js +5 -17
- package/dist/core/agents/work-partition/repo-inventory.js +0 -2
- package/dist/core/auto-review.js +0 -13
- package/dist/core/bench.js +0 -14
- package/dist/core/code-structure.js +0 -3
- package/dist/core/codex/agent-config-file-repair.js +0 -8
- package/dist/core/codex/codex-cli-update.js +122 -20
- package/dist/core/codex/codex-config-eperm-repair.js +0 -4
- package/dist/core/codex/codex-config-guard.js +0 -3
- package/dist/core/codex/codex-config-readability.js +0 -13
- package/dist/core/codex/codex-project-config-policy.js +0 -33
- package/dist/core/codex/official-goal-mode.js +0 -2
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +5 -7
- package/dist/core/codex-app/codex-app-ui-state-snapshot.js +44 -7
- package/dist/core/codex-app/sks-menubar.js +0 -1
- package/dist/core/codex-app.js +0 -9
- package/dist/core/codex-compat/codex-hook-output-builders.js +9 -1
- package/dist/core/codex-compat/codex-hook-output-normalizer.js +1 -1
- package/dist/core/codex-compat/codex-hook-semantic-validator.js +3 -2
- package/dist/core/codex-compat/codex-hook-warning-detector.js +10 -2
- package/dist/core/codex-control/codex-lb-launch-recovery.js +0 -3
- package/dist/core/codex-control/codex-reliability-shield.js +0 -8
- package/dist/core/codex-control/codex-sdk-adapter.js +0 -3
- package/dist/core/codex-control/codex-sdk-config-policy.js +0 -2
- package/dist/core/codex-control/codex-sdk-env-policy.js +61 -16
- package/dist/core/codex-control/codex-task-runner.js +0 -7
- package/dist/core/codex-control/codex-thread-registry.js +0 -4
- package/dist/core/codex-lb/codex-lb-env.js +118 -20
- package/dist/core/codex-lb/codex-lb-tool-catalog.js +0 -4
- package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +1 -1
- package/dist/core/codex-model-guard.js +0 -14
- package/dist/core/codex-native/codex-native-feature-broker.js +67 -22
- package/dist/core/codex-native/codex-native-interop-policy.js +81 -9
- package/dist/core/codex-native/confined-report-writer.js +21 -0
- package/dist/core/codex-native/core-skill-integrity.js +169 -20
- package/dist/core/codex-native/project-skill-dedupe.js +55 -13
- package/dist/core/codex-native/skill-registry-ledger.js +137 -16
- package/dist/core/codex-native/sks-skill-paths.js +185 -0
- package/dist/core/codex-runtime/codex-desktop-config-policy.js +0 -2
- package/dist/core/commands/agent-bridge-command.js +28 -8
- package/dist/core/commands/basic-cli.js +67 -26
- package/dist/core/commands/bench-command.js +5 -1
- package/dist/core/commands/command-utils.js +0 -5
- package/dist/core/commands/image-ux-review-command.js +0 -9
- package/dist/core/commands/mad-sks-command.js +0 -38
- package/dist/core/commands/naruto-command.js +46 -12
- package/dist/core/commands/ppt-command.js +0 -9
- package/dist/core/commands/run-command.js +8 -2
- package/dist/core/commands/seo-command.js +0 -6
- package/dist/core/commands/wiki-command.js +0 -14
- package/dist/core/computer-use-live-evidence.js +0 -5
- package/dist/core/config/secret-preservation.js +0 -11
- package/dist/core/daemon/sksd-hook-daemon-entrypoint.js +0 -2
- package/dist/core/daemon/sksd-hook-daemon.js +1 -29
- package/dist/core/daemon/sksd-hook-dispatch.js +0 -17
- package/dist/core/db-safety.js +0 -7
- package/dist/core/doctor/browser-use-repair.js +0 -2
- package/dist/core/doctor/doctor-codex-startup-repair.js +0 -3
- package/dist/core/doctor/doctor-readiness-matrix.js +12 -0
- package/dist/core/doctor/doctor-skill-reconcile.js +32 -0
- package/dist/core/doctor/imagegen-repair.js +0 -2
- package/dist/core/doctor/mcp-transport-collision-repair.js +0 -3
- package/dist/core/doctor/retired-managed-residue-private.js +0 -1
- package/dist/core/doctor/supabase-mcp-repair.js +0 -11
- package/dist/core/feature-fixture-executor.js +0 -48
- package/dist/core/feature-fixtures.js +0 -5
- package/dist/core/fsx.js +11 -12
- package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +0 -5
- package/dist/core/hooks-runtime/hook-context.js +202 -0
- package/dist/core/hooks-runtime/hook-io.js +1 -12
- package/dist/core/hooks-runtime/light-turn.js +0 -2
- package/dist/core/hooks-runtime/naruto-decision-gate.js +4 -1
- package/dist/core/hooks-runtime/naruto-terminal-finalization.js +91 -0
- package/dist/core/hooks-runtime/official-subagent-lifecycle.js +370 -0
- package/dist/core/hooks-runtime/standalone-parent-host-capability.js +98 -0
- package/dist/core/hooks-runtime/subagent-context.js +59 -0
- package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +29 -0
- package/dist/core/hooks-runtime/subagent-skill-availability-evidence.js +195 -0
- package/dist/core/hooks-runtime/subagent-skill-availability-guards.js +316 -0
- package/dist/core/hooks-runtime/subagent-skill-availability.js +217 -0
- package/dist/core/hooks-runtime.js +259 -535
- package/dist/core/image-ux-review/codex-app-generated-image-discovery.js +0 -17
- package/dist/core/image-ux-review/imagegen-adapter.js +0 -14
- package/dist/core/imagegen/imagegen-auth-readiness.js +0 -9
- package/dist/core/imagegen/imagegen-capability.js +0 -3
- package/dist/core/init/managed-skill-install.js +42 -0
- package/dist/core/init/skills.js +247 -74
- package/dist/core/init.js +15 -40
- package/dist/core/lean-engineering-policy.js +0 -2
- package/dist/core/locks/file-lock.js +0 -21
- package/dist/core/loops/loop-planner.js +0 -6
- package/dist/core/loops/loop-runtime.js +0 -1
- package/dist/core/loops/loop-worker-runtime.js +0 -19
- package/dist/core/mad-sks/executors/db-write-executor.js +0 -4
- package/dist/core/mad-sks/executors/executor-base.js +0 -10
- package/dist/core/mad-sks/immutable-harness-guard.js +0 -5
- package/dist/core/mad-sks/sql-plane/coordinator.js +0 -5
- package/dist/core/mad-sks/sql-plane/ledger.js +0 -4
- package/dist/core/mad-sks/sql-plane/lock.js +0 -4
- package/dist/core/mad-sks/sql-plane/mcp-executor.js +0 -9
- package/dist/core/mad-sks/sql-plane/policy-resolver.js +0 -2
- package/dist/core/mad-sks/sql-plane/postconditions.js +0 -4
- package/dist/core/mad-sks/sql-plane/recovery.js +0 -2
- package/dist/core/mad-sks/sql-plane/runtime-profile.js +0 -8
- package/dist/core/managed-assets/managed-assets-manifest.js +1 -7
- package/dist/core/mcp-config/health-check.js +10 -3
- package/dist/core/migration/migration-transaction-journal.js +0 -8
- package/dist/core/mission.js +0 -2
- package/dist/core/naruto/naruto-active-pool.js +0 -2
- package/dist/core/naruto/naruto-concurrency-governor.js +0 -1
- package/dist/core/naruto/naruto-real-write-proof.js +0 -4
- package/dist/core/naruto/naruto-write-e2e.js +0 -1
- package/dist/core/perf/perf-budget.js +0 -5
- package/dist/core/permission-gates.js +0 -2
- package/dist/core/pipeline-internals/runtime-core.js +15 -5
- package/dist/core/pipeline-internals/runtime-gates.js +0 -12
- package/dist/core/preflight/parallel-preflight-engine.js +0 -11
- package/dist/core/proof/evidence-collector.js +0 -2
- package/dist/core/proof/route-finalizer.js +0 -1
- package/dist/core/proof/selftest-proof-fixtures.js +0 -5
- package/dist/core/providers/glm/bench/glm-benchmark-runner.js +0 -2
- package/dist/core/providers/glm/glm-request-cache.js +0 -3
- package/dist/core/providers/glm/naruto/glm-naruto-command.js +0 -1
- package/dist/core/providers/glm/naruto/glm-naruto-decomposer.js +0 -1
- package/dist/core/providers/glm/naruto/glm-naruto-orchestrator.js +0 -6
- package/dist/core/providers/glm/naruto/glm-naruto-trace.js +0 -1
- package/dist/core/providers/glm/naruto/glm-naruto-worker-pool.js +0 -1
- package/dist/core/providers/glm/naruto/glm-naruto-worktree.js +0 -1
- package/dist/core/providers/openrouter/openrouter-secret-store.js +0 -1
- package/dist/core/providers/openrouter/openrouter-stream.js +0 -2
- package/dist/core/questions.js +3 -3
- package/dist/core/release/gate-manifest.js +0 -5
- package/dist/core/release/package-size-budget.js +1 -1
- package/dist/core/release/release-gate-batch-runner.js +11 -2
- package/dist/core/release/release-gate-cache-v2.js +0 -4
- package/dist/core/release/release-gate-hermetic-env.js +0 -5
- package/dist/core/release-parallel-full-coverage.js +0 -2
- package/dist/core/remote/ssh-worker-client.js +0 -3
- package/dist/core/research/research-adversarial-review.js +6 -2
- package/dist/core/responses-retry-policy.js +0 -10
- package/dist/core/retention.js +0 -7
- package/dist/core/routes/constants.js +0 -3
- package/dist/core/routes.js +89 -15
- package/dist/core/safety/command-contract/contracts.js +2 -0
- package/dist/core/safety/mutation-guard.js +0 -25
- package/dist/core/safety/mutation-ledger.js +0 -9
- package/dist/core/safety/requested-scope-contract.js +0 -0
- package/dist/core/security/high-risk-contracts.js +0 -1
- package/dist/core/skills/core-skill-card.js +0 -0
- package/dist/core/skills/core-skill-deployment.js +0 -13
- package/dist/core/skills/core-skill-epoch.js +0 -11
- package/dist/core/skills/core-skill-meta-update.js +0 -6
- package/dist/core/skills/core-skill-patch-apply.js +0 -7
- package/dist/core/skills/core-skill-patch.js +0 -8
- package/dist/core/skills/core-skill-reflection.js +0 -16
- package/dist/core/skills/core-skill-runtime.js +0 -6
- package/dist/core/skills/core-skill-scorer.js +0 -7
- package/dist/core/skills/core-skill-trainer.js +0 -11
- package/dist/core/skills/core-skill-types.js +0 -9
- package/dist/core/skills/core-skill-validation.js +0 -5
- package/dist/core/skills/rejected-skill-patch-buffer.js +0 -2
- package/dist/core/stop-gate/stop-gate-check.js +0 -8
- package/dist/core/stop-gate/stop-gate-resolver.js +0 -7
- package/dist/core/stop-gate/stop-gate-writer.js +0 -5
- package/dist/core/subagents/model-policy.js +0 -7
- package/dist/core/subagents/naruto-help-contract.js +1 -1
- package/dist/core/subagents/naruto-proof-projection.js +580 -12
- package/dist/core/subagents/official-subagent-config.js +0 -8
- package/dist/core/subagents/official-subagent-preparation.js +6 -5
- package/dist/core/subagents/official-subagent-prompt.js +29 -0
- package/dist/core/subagents/official-subagent-runner.js +343 -37
- package/dist/core/subagents/subagent-evidence.js +378 -9
- package/dist/core/subagents/thread-budget.js +5 -2
- package/dist/core/subagents/triwiki-attention.js +0 -4
- package/dist/core/subagents/wave-parent-guidance.js +54 -9
- package/dist/core/telegram/runtime.js +0 -1
- package/dist/core/triwiki/code-index-scanner.js +0 -3
- package/dist/core/triwiki/code-pack-head-freshness.js +0 -10
- package/dist/core/triwiki/code-pack.js +0 -2
- package/dist/core/triwiki/triwiki-cache-key.js +0 -1
- package/dist/core/triwiki/triwiki-proof-bank.js +0 -1
- package/dist/core/triwiki-attention.js +0 -10
- package/dist/core/triwiki-provenance.js +0 -5
- package/dist/core/triwiki-runtime.js +0 -12
- package/dist/core/triwiki-wrongness/wrongness-ledger.js +0 -7
- package/dist/core/triwiki-wrongness/wrongness-schema.js +0 -3
- package/dist/core/trust-kernel/trust-report.js +0 -7
- package/dist/core/update/update-migration-state.js +21 -39
- package/dist/core/update-check.js +2 -14
- package/dist/core/version-manager.js +2 -0
- package/dist/core/version.js +1 -1
- package/dist/core/work-order-ledger.js +0 -17
- package/dist/core/zellij/zellij-clipboard-config.js +0 -18
- package/dist/core/zellij/zellij-lane-renderer.js +5 -46
- package/dist/core/zellij/zellij-lane-runtime.js +0 -1
- package/dist/core/zellij/zellij-launcher.js +0 -26
- package/dist/core/zellij/zellij-official-subagent-activity.js +0 -5
- package/dist/core/zellij/zellij-official-subagent-telemetry.js +0 -5
- package/dist/core/zellij/zellij-screen-proof.js +0 -7
- package/dist/core/zellij/zellij-slot-column-anchor.js +0 -1
- package/dist/core/zellij/zellij-slot-pane-renderer.js +0 -9
- package/dist/core/zellij/zellij-slot-telemetry.js +0 -12
- package/dist/core/zellij/zellij-ui-mode.js +0 -7
- package/dist/core/zellij/zellij-update.js +0 -29
- package/dist/core/zellij/zellij-worker-pane-manager.js +0 -39
- package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +213 -27
- package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +95 -12
- package/dist/scripts/agent-message-bus-reader-check.js +0 -1
- package/dist/scripts/all-feature-deep-completion-check.js +0 -1
- package/dist/scripts/appshots-thread-attachment-discovery-check.js +0 -1
- package/dist/scripts/architecture-guard-check.js +0 -1
- package/dist/scripts/build-dist.js +0 -1
- package/dist/scripts/build-once-runner-check.js +0 -1
- package/dist/scripts/canonical-test-runner.js +0 -2
- package/dist/scripts/certificate-sla-check.js +0 -1
- package/dist/scripts/changelog-check.js +0 -1
- package/dist/scripts/check-cli-entrypoint.js +0 -1
- package/dist/scripts/check-command-module-budget.js +0 -7
- package/dist/scripts/check-feature-quality.js +0 -1
- package/dist/scripts/check-legacy-free.js +0 -1
- package/dist/scripts/check-pipeline-runtime.js +0 -1
- package/dist/scripts/check-runtime-schemas.js +0 -1
- package/dist/scripts/codex-0-134-runner-truth-check.js +0 -1
- package/dist/scripts/codex-0-137-compat-check.js +0 -1
- package/dist/scripts/codex-0138-capability-artifact-check.js +0 -1
- package/dist/scripts/codex-0138-capability-check.js +0 -1
- package/dist/scripts/codex-0138-doctor-check.js +0 -1
- package/dist/scripts/codex-0138-feature-probes-check.js +0 -1
- package/dist/scripts/codex-0144-core-real-probes-check.js +0 -1
- package/dist/scripts/codex-app-handoff-check.js +0 -1
- package/dist/scripts/codex-app-handoff-launch-check.js +0 -1
- package/dist/scripts/codex-config-load-probe.js +0 -5
- package/dist/scripts/codex-control-all-pipelines-check.js +0 -1
- package/dist/scripts/codex-control-event-stream-ledger-check.js +0 -1
- package/dist/scripts/codex-control-tool-output-continuity-audit-check.js +0 -1
- package/dist/scripts/codex-permission-profiles-check.js +0 -1
- package/dist/scripts/codex-plugin-app-template-policy-check.js +0 -1
- package/dist/scripts/codex-project-config-policy-splitter-check.js +0 -1
- package/dist/scripts/codex-sdk-all-pipelines-check.js +0 -1
- package/dist/scripts/codex-sdk-backend-router-check.js +0 -1
- package/dist/scripts/codex-sdk-capability-check.js +0 -1
- package/dist/scripts/codex-sdk-event-stream-ledger-check.js +0 -1
- package/dist/scripts/codex-sdk-real-smoke-check.js +0 -1
- package/dist/scripts/concurrent-session-collision-check.js +9 -0
- package/dist/scripts/context7-evidence-dedupe-check.js +0 -1
- package/dist/scripts/core-skill-card-schema-check.js +0 -11
- package/dist/scripts/core-skill-deployment-snapshot-check.js +0 -10
- package/dist/scripts/core-skill-heldout-validation-check.js +0 -11
- package/dist/scripts/core-skill-no-inference-optimizer-check.js +0 -11
- package/dist/scripts/core-skill-patch-check.js +0 -11
- package/dist/scripts/core-skill-route-runtime-integration-check.js +0 -11
- package/dist/scripts/current-surface-update-e2e-check.js +0 -4
- package/dist/scripts/current-upgrade-matrix-check.js +0 -1
- package/dist/scripts/dfix-fixture-check.js +0 -1
- package/dist/scripts/dfix-patch-handoff-check.js +0 -1
- package/dist/scripts/dfix-verification-check.js +0 -1
- package/dist/scripts/dfix-verification-recommendation-check.js +0 -1
- package/dist/scripts/docs-truthfulness-check.js +3 -3
- package/dist/scripts/doctor-fastpath-check.js +0 -1
- package/dist/scripts/doctor-fix-proves-codex-read-check.js +0 -11
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +0 -4
- package/dist/scripts/doctor-idempotence-check.js +0 -1
- package/dist/scripts/doctor-ops-semantics-check.js +0 -1
- package/dist/scripts/ensure-bin-executable.js +0 -1
- package/dist/scripts/evidence-flagship-coverage-check.js +0 -1
- package/dist/scripts/fast-codex-service-tier-proof-check.js +0 -1
- package/dist/scripts/fixtures/fake-codex-config-loader.js +0 -5
- package/dist/scripts/fsx-hotpath-check.js +0 -1
- package/dist/scripts/gate-policy-audit-check.js +1 -1
- package/dist/scripts/geo-claim-evidence-check.js +0 -1
- package/dist/scripts/geo-cli-blackbox-check.js +0 -1
- package/dist/scripts/geo-crawler-policy-check.js +0 -1
- package/dist/scripts/git-worktree-diff-envelope-check.js +0 -1
- package/dist/scripts/git-worktree-dirty-lock-check.js +0 -1
- package/dist/scripts/git-worktree-dirty-main-detection-check.js +0 -1
- package/dist/scripts/git-worktree-integration-primary-check.js +0 -1
- package/dist/scripts/git-worktree-manifest-append-check.js +0 -1
- package/dist/scripts/git-worktree-untracked-diff-check.js +0 -1
- package/dist/scripts/high-risk-contracts-check.js +0 -1
- package/dist/scripts/hook-latency-budget-check.js +0 -1
- package/dist/scripts/hook-latency-quantum-check.js +0 -1
- package/dist/scripts/image-artifact-path-contract-check.js +0 -1
- package/dist/scripts/imagegen-real-smoke-check.js +0 -1
- package/dist/scripts/import-graph-budget-check.js +0 -1
- package/dist/scripts/installed-package-smoke-check.js +0 -1
- package/dist/scripts/legacy-gate-purge-check.js +0 -1
- package/dist/scripts/lib/codex-sdk-gate-lib.js +0 -3
- package/dist/scripts/lib/ensure-dist-fresh.js +0 -1
- package/dist/scripts/lib/valid-png-fixture.js +0 -1
- package/dist/scripts/local-collab-all-pipelines-final-gpt-check.js +0 -1
- package/dist/scripts/loop-directive-check-lib.js +0 -1
- package/dist/scripts/loop-worker-fixture-child.js +0 -1
- package/dist/scripts/mad-preflight-blocks-unreadable-config-check.js +0 -10
- package/dist/scripts/mad-sks-sql-plane-lifecycle-hook-decision-check.js +0 -1
- package/dist/scripts/mad-sks-sql-plane-result-lifecycle-check.js +0 -1
- package/dist/scripts/mcp-plugin-inventory-check.js +0 -1
- package/dist/scripts/mcp-tool-naming-parity-check.js +0 -1
- package/dist/scripts/model-call-concurrency-check.js +0 -1
- package/dist/scripts/mutation-callsite-coverage-check.js +0 -5
- package/dist/scripts/naruto-codex-e2e-check.js +0 -1
- package/dist/scripts/naruto-worktree-coding-blackbox.js +0 -1
- package/dist/scripts/official-subagent-workflow-check.js +3 -1
- package/dist/scripts/ops-diagnostics-bundle-check.js +0 -1
- package/dist/scripts/packlist-performance-check.js +1 -3
- package/dist/scripts/perf-budget-check.js +0 -1
- package/dist/scripts/ppt-full-e2e-blackbox-check.js +0 -1
- package/dist/scripts/ppt-real-export-adapter-check.js +0 -1
- package/dist/scripts/ppt-real-imagegen-smoke-check.js +0 -1
- package/dist/scripts/ppt-real-imagegen-wiring-check.js +0 -1
- package/dist/scripts/ppt-reexport-rereview-check.js +0 -1
- package/dist/scripts/prepublish-fast-check.js +0 -23
- package/dist/scripts/prepublish-release-check-or-fast.js +0 -7
- package/dist/scripts/probe-memoization-check.js +0 -1
- package/dist/scripts/product-design-plugin-routing-check.js +0 -1
- package/dist/scripts/project-skill-dedupe-blackbox.js +36 -9
- package/dist/scripts/prompt-placeholder-guard-check.js +0 -1
- package/dist/scripts/python-codex-sdk-all-pipelines-check.js +0 -3
- package/dist/scripts/qa-loop-app-handoff-capability-check.js +0 -1
- package/dist/scripts/qa-loop-app-handoff-check.js +0 -1
- package/dist/scripts/qa-loop-app-handoff-cli-check.js +0 -1
- package/dist/scripts/qa-loop-app-handoff-confirmation-check.js +0 -1
- package/dist/scripts/qa-loop-app-handoff-gate-lifecycle-check.js +0 -1
- package/dist/scripts/qa-loop-app-handoff-launch-check.js +0 -1
- package/dist/scripts/qa-loop-app-handoff-status-lifecycle-check.js +0 -1
- package/dist/scripts/qa-loop-budget-policy-check.js +0 -1
- package/dist/scripts/qa-loop-effort-escalation-check.js +0 -1
- package/dist/scripts/qa-loop-image-path-exposure-check.js +0 -1
- package/dist/scripts/qa-loop-image-path-prompt-injection-check.js +0 -1
- package/dist/scripts/release-cache-glob-hashing-check.js +0 -1
- package/dist/scripts/release-cache-input-classifier-check.js +0 -1
- package/dist/scripts/release-cache-neutralization-report-check.js +0 -1
- package/dist/scripts/release-cache-version-neutral-fixture-check.js +0 -1
- package/dist/scripts/release-check-stamp.js +0 -4
- package/dist/scripts/release-dist-freshness-check.js +0 -1
- package/dist/scripts/release-full-parallelism-blackbox.js +3 -3
- package/dist/scripts/release-gate-batch-runner-check.js +22 -0
- package/dist/scripts/release-gate-budget-check.js +0 -6
- package/dist/scripts/release-gate-dag-runner-check.js +0 -1
- package/dist/scripts/release-latency-slo-check.js +0 -1
- package/dist/scripts/release-metadata-1-19-check.js +0 -1
- package/dist/scripts/release-metadata-check.js +0 -3
- package/dist/scripts/release-parallel-speed-budget-check.js +0 -5
- package/dist/scripts/release-proof-truth-check.js +0 -1
- package/dist/scripts/release-provenance-check.js +0 -1
- package/dist/scripts/release-real-check.js +0 -1
- package/dist/scripts/release-runtime-truth-matrix-check.js +0 -1
- package/dist/scripts/release-version-truth-check.js +0 -1
- package/dist/scripts/research-blueprint-densifier-check.js +0 -1
- package/dist/scripts/research-claim-builder-check.js +0 -1
- package/dist/scripts/research-complete-package-fixture-check.js +0 -1
- package/dist/scripts/research-final-reviewer-blackbox.js +0 -1
- package/dist/scripts/responses-retry-policy-centralized-check.js +0 -1
- package/dist/scripts/retention-apply-smoke-check.js +0 -1
- package/dist/scripts/retention-budget-check.js +0 -1
- package/dist/scripts/retention-dry-run-check.js +0 -1
- package/dist/scripts/rollback-recovery-smoke-check.js +0 -1
- package/dist/scripts/route-intent-regression-check.js +0 -1
- package/dist/scripts/runtime-current-terminal-check.js +0 -1
- package/dist/scripts/runtime-dist-parity-check.js +0 -1
- package/dist/scripts/runtime-no-src-mjs-check.js +0 -1
- package/dist/scripts/runtime-proof-summary-check.js +0 -1
- package/dist/scripts/runtime-ts-rust-boundary-check.js +0 -15
- package/dist/scripts/runtime-ts-source-of-truth-check.js +0 -1
- package/dist/scripts/scheduler-batch-dispatch-check.js +0 -1
- package/dist/scripts/scheduler-parallel-proof-consistency-check.js +0 -1
- package/dist/scripts/scheduler-utilization-integral-check.js +0 -1
- package/dist/scripts/search-visibility-gate-lib.js +0 -1
- package/dist/scripts/seo-audit-fixture-check.js +0 -1
- package/dist/scripts/seo-cli-blackbox-check.js +0 -1
- package/dist/scripts/seo-geo-geo-disambiguation-check.js +0 -1
- package/dist/scripts/seo-geo-route-identity-check.js +0 -1
- package/dist/scripts/seo-geo-skill-rich-content-check.js +0 -1
- package/dist/scripts/seo-marketing-truthfulness-check.js +0 -1
- package/dist/scripts/seo-metadata-sync-check.js +0 -1
- package/dist/scripts/seo-no-mutation-by-default-check.js +0 -1
- package/dist/scripts/shared-memory-fixture-check.js +0 -1
- package/dist/scripts/side-effect-runtime-report-check.js +0 -1
- package/dist/scripts/sizecheck.js +0 -1
- package/dist/scripts/sks-1-11-gate-lib.js +0 -1
- package/dist/scripts/sks-1-12-real-execution-check-lib.js +0 -1
- package/dist/scripts/sks-1-18-gate-lib.js +0 -1
- package/dist/scripts/sks-menubar-install-check.js +0 -3
- package/dist/scripts/sksd-daemon-check.js +0 -1
- package/dist/scripts/super-search-live-smoke-check.js +0 -1
- package/dist/scripts/super-search-local-http-smoke-check.js +0 -1
- package/dist/scripts/super-search-offline-contract-check.js +0 -1
- package/dist/scripts/super-search-provider-interface-check.js +0 -1
- package/dist/scripts/triwiki-cache-key-check.js +0 -1
- package/dist/scripts/triwiki-proof-bank-blackbox.js +0 -1
- package/dist/scripts/triwiki-proof-bank-check.js +0 -1
- package/dist/scripts/triwiki-proof-card-check.js +0 -1
- package/dist/scripts/trust-fixture-check.js +0 -1
- package/dist/scripts/ultra-router-auto-router-check.js +0 -1
- package/dist/scripts/update-fastpath-check.js +0 -1
- package/dist/scripts/upgrade-migration-matrix-check.js +0 -1
- package/dist/scripts/ux-review-extract-wires-real-extractor-check.js +0 -1
- package/dist/scripts/ux-review-imagegen-blackbox-check.js +0 -1
- package/dist/scripts/ux-review-patch-diff-recheck-check.js +0 -1
- package/dist/scripts/ux-review-real-imagegen-smoke-check.js +0 -1
- package/dist/scripts/ux-review-run-wires-imagegen-check.js +0 -1
- package/dist/scripts/write-build-manifest.js +0 -1
- package/dist/scripts/wrongness-fixture-check.js +0 -1
- package/dist/scripts/zellij-capability-check.js +0 -1
- package/dist/scripts/zellij-developer-controls-check.js +0 -1
- package/dist/scripts/zellij-doctor-readiness-check.js +0 -13
- package/dist/scripts/zellij-dynamic-pane-lifecycle-check.js +0 -1
- package/dist/scripts/zellij-fake-adapter-check.js +0 -1
- package/dist/scripts/zellij-initial-main-only-blackbox.js +0 -1
- package/dist/scripts/zellij-lane-renderer-check.js +0 -1
- package/dist/scripts/zellij-launch-command-truth-check.js +0 -12
- package/dist/scripts/zellij-layout-valid-check.js +0 -1
- package/dist/scripts/zellij-pane-creation-lock-metrics-check.js +0 -1
- package/dist/scripts/zellij-pane-lock-concurrency-blackbox.js +0 -1
- package/dist/scripts/zellij-pane-lock-does-not-block-worker-check.js +0 -1
- package/dist/scripts/zellij-pane-lock-open-worker-integration-blackbox.js +0 -1
- package/dist/scripts/zellij-pane-proof-check.js +0 -1
- package/dist/scripts/zellij-qa-app-handoff-status-check.js +0 -1
- package/dist/scripts/zellij-real-session-cleanup-check.js +0 -1
- package/dist/scripts/zellij-real-session-launch-check.js +0 -1
- package/dist/scripts/zellij-right-column-geometry-proof.js +0 -1
- package/dist/scripts/zellij-right-column-headless-overflow-check.js +0 -1
- package/dist/scripts/zellij-right-column-manager-check.js +0 -1
- package/dist/scripts/zellij-screen-proof-check.js +0 -1
- package/dist/scripts/zellij-slot-only-ui-check.js +0 -1
- package/dist/scripts/zellij-slot-pane-renderer-check.js +0 -1
- package/dist/scripts/zellij-slot-pane-stale-detection-check.js +0 -7
- package/dist/scripts/zellij-slot-telemetry-incremental-check.js +0 -1
- package/dist/scripts/zellij-slot-telemetry-live-flush-check.js +0 -1
- package/dist/scripts/zellij-slot-telemetry-performance-check.js +0 -1
- package/dist/scripts/zellij-stacked-capability-routing-check.js +0 -1
- package/dist/scripts/zellij-stacked-fallback-integration-blackbox.js +0 -1
- package/dist/scripts/zellij-stacked-version-matrix-check.js +0 -1
- package/dist/scripts/zellij-stacked-version-parser-check.js +0 -1
- package/dist/scripts/zellij-ui-design-check.js +0 -12
- package/dist/scripts/zellij-update-prompt-matrix-check.js +0 -1
- package/dist/scripts/zellij-update-prompt-mode-check.js +0 -1
- package/dist/scripts/zellij-update-prompt-safety-check.js +0 -1
- package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +0 -2
- package/package.json +1 -1
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { constants as fsConstants } from 'node:fs';
|
|
1
2
|
import fsp from 'node:fs/promises';
|
|
2
3
|
import path from 'node:path';
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
3
5
|
import { sha256 } from '../fsx.js';
|
|
4
|
-
import { SUBAGENT_EVIDENCE_FILENAME, SUBAGENT_EVENT_LOG_FILENAME, SUBAGENT_PARENT_SUMMARY_FILENAME, buildSubagentEvidence, normalizeSubagentEvent, normalizeSubagentParentSummary } from './subagent-evidence.js';
|
|
6
|
+
import { SUBAGENT_EVIDENCE_FILENAME, SUBAGENT_EVENT_LOG_FILENAME, SUBAGENT_PARENT_SUMMARY_FILENAME, buildSubagentEvidence, normalizeSubagentEvent, normalizeSubagentParentSummary, trustedHostCapabilityReceiptBindingBlockers } from './subagent-evidence.js';
|
|
5
7
|
import { NARUTO_GATE_FILENAME, NARUTO_RESULT_SCHEMA, NARUTO_SUMMARY_FILENAME, SUBAGENT_PLAN_FILENAME } from './official-subagent-preparation.js';
|
|
6
8
|
import { effectiveSubagentTarget, normalizeLegacySubagentCountFields, subagentCountContractBlockers } from './wave-lifecycle.js';
|
|
9
|
+
import { HOST_CAPABILITY_DESCRIPTORS, hostCapabilityDigest } from '../agent-bridge/agent-manifest.js';
|
|
10
|
+
import { HOST_CAPABILITY_EVIDENCE_SCHEMA, HOST_CAPABILITY_RUNTIME_SCHEMA } from '../agent-bridge/host-capability-runtime.js';
|
|
7
11
|
export const NARUTO_PROOF_ARTIFACT_FILENAMES = Object.freeze([
|
|
8
12
|
SUBAGENT_PLAN_FILENAME,
|
|
9
13
|
SUBAGENT_EVENT_LOG_FILENAME,
|
|
@@ -17,6 +21,25 @@ const MAX_CHANGED_FILES = 256;
|
|
|
17
21
|
const MAX_CHANGED_FILE_CHARS = 512;
|
|
18
22
|
const MAX_VERIFICATION_ROWS = 32;
|
|
19
23
|
const MAX_VERIFICATION_NAME_CHARS = 240;
|
|
24
|
+
const MAX_ARTIFACTS = 64;
|
|
25
|
+
const MAX_ARTIFACT_PATH_CHARS = 512;
|
|
26
|
+
const MAX_ARTIFACT_KIND_CHARS = 64;
|
|
27
|
+
const MAX_MEDIA_TYPE_CHARS = 160;
|
|
28
|
+
const MAX_CAPABILITY_USES = 64;
|
|
29
|
+
const MAX_CAPABILITY_ID_CHARS = 160;
|
|
30
|
+
const MAX_CAPABILITY_TOOL_NAMES = 64;
|
|
31
|
+
const MAX_CAPABILITY_TOOL_NAME_CHARS = 128;
|
|
32
|
+
const MAX_CANONICAL_PROOF_ARTIFACT_BYTES = 4 * 1024 * 1024;
|
|
33
|
+
const MAX_CANONICAL_PROOF_AGGREGATE_BYTES = 16 * 1024 * 1024;
|
|
34
|
+
const MAX_DELIVERABLE_ARTIFACT_BYTES = 128 * 1024 * 1024;
|
|
35
|
+
const MAX_DELIVERABLE_ARTIFACT_AGGREGATE_BYTES = 512 * 1024 * 1024;
|
|
36
|
+
const SHA256_RECEIPT_PATTERN = /^sha256:[a-f0-9]{64}$/;
|
|
37
|
+
const ARTIFACT_ROLES = new Set(['deliverable', 'scratch', 'temp', 'log']);
|
|
38
|
+
const NON_DELIVERABLE_ARTIFACT_KINDS = new Set(['scratch', 'temp', 'tmp', 'log']);
|
|
39
|
+
const NON_DELIVERABLE_PATH_SEGMENTS = new Set(['scratch', 'temp', 'tmp', 'log', 'logs']);
|
|
40
|
+
const ARTIFACT_RECEIPT_KEYS = new Set(['path', 'kind', 'media_type', 'sha256', 'bytes', 'role']);
|
|
41
|
+
const CAPABILITY_USE_KEYS = new Set(['id', 'status', 'tool_names', 'receipt_sha256']);
|
|
42
|
+
const HOST_CAPABILITY_BY_ID = new Map(HOST_CAPABILITY_DESCRIPTORS.map((descriptor) => [descriptor.id, descriptor]));
|
|
20
43
|
const INCOMPLETE_BLOCKER_PATTERNS = [
|
|
21
44
|
/^proof_artifact_missing:/,
|
|
22
45
|
/^requested_subagent_(?:starts|completions)_incomplete:/,
|
|
@@ -28,7 +51,14 @@ const INCOMPLETE_BLOCKER_PATTERNS = [
|
|
|
28
51
|
export async function readNarutoProofArtifactSnapshot(artifactDir) {
|
|
29
52
|
const rows = await Promise.all(NARUTO_PROOF_ARTIFACT_FILENAMES.map(async (filename) => {
|
|
30
53
|
try {
|
|
31
|
-
|
|
54
|
+
const file = path.join(artifactDir, filename);
|
|
55
|
+
const stat = await fsp.stat(file);
|
|
56
|
+
if (!stat.isFile())
|
|
57
|
+
return { filename, bytes: null, blocker: `proof_artifact_unreadable:${filename}` };
|
|
58
|
+
if (stat.size > MAX_CANONICAL_PROOF_ARTIFACT_BYTES) {
|
|
59
|
+
return { filename, bytes: null, blocker: `proof_artifact_too_large:${filename}` };
|
|
60
|
+
}
|
|
61
|
+
return { filename, bytes: await fsp.readFile(file), blocker: null };
|
|
32
62
|
}
|
|
33
63
|
catch (error) {
|
|
34
64
|
const code = errorCode(error);
|
|
@@ -44,24 +74,54 @@ export async function readNarutoProofArtifactSnapshot(artifactDir) {
|
|
|
44
74
|
const bytes = {};
|
|
45
75
|
const byteHashes = {};
|
|
46
76
|
const blockers = [];
|
|
77
|
+
let aggregateBytes = 0;
|
|
47
78
|
for (const row of rows) {
|
|
48
79
|
bytes[row.filename] = row.bytes;
|
|
49
80
|
byteHashes[row.filename] = row.bytes ? `sha256:${sha256(row.bytes)}` : null;
|
|
81
|
+
aggregateBytes += row.bytes?.length || 0;
|
|
50
82
|
if (row.blocker)
|
|
51
83
|
blockers.push(row.blocker);
|
|
52
84
|
}
|
|
85
|
+
if (aggregateBytes > MAX_CANONICAL_PROOF_AGGREGATE_BYTES)
|
|
86
|
+
blockers.push('proof_artifacts_aggregate_too_large');
|
|
53
87
|
return { bytes, byte_hashes: byteHashes, read_blockers: blockers };
|
|
54
88
|
}
|
|
55
89
|
export async function buildNarutoProofProjection(input) {
|
|
56
90
|
const snapshot = await readNarutoProofArtifactSnapshot(input.artifactDir);
|
|
57
|
-
|
|
91
|
+
const projected = projectNarutoProofSnapshot({ snapshot, missionId: input.missionId });
|
|
92
|
+
if (!projected.result.artifacts?.length)
|
|
93
|
+
return projected;
|
|
94
|
+
const artifactBlockers = await verifyProjectedArtifactFiles({
|
|
95
|
+
artifacts: projected.result.artifacts,
|
|
96
|
+
artifactDir: input.artifactDir,
|
|
97
|
+
workspaceRoot: input.workspaceRoot
|
|
98
|
+
});
|
|
99
|
+
if (artifactBlockers.length === 0)
|
|
100
|
+
return projected;
|
|
101
|
+
return projectNarutoProofSnapshot({
|
|
102
|
+
snapshot: {
|
|
103
|
+
...snapshot,
|
|
104
|
+
read_blockers: [...snapshot.read_blockers, ...artifactBlockers]
|
|
105
|
+
},
|
|
106
|
+
missionId: input.missionId
|
|
107
|
+
});
|
|
58
108
|
}
|
|
59
109
|
export function projectNarutoProofSnapshot(input) {
|
|
60
110
|
const missionId = String(input.missionId || '').trim();
|
|
61
|
-
const
|
|
111
|
+
const readBlockers = input.snapshot.read_blockers;
|
|
112
|
+
const blockers = Array.isArray(readBlockers)
|
|
113
|
+
? readBlockers.filter((blocker) => typeof blocker === 'string')
|
|
114
|
+
: ['proof_read_blockers_invalid'];
|
|
115
|
+
if (Array.isArray(readBlockers) && blockers.length !== readBlockers.length)
|
|
116
|
+
blockers.push('proof_read_blockers_invalid');
|
|
62
117
|
const plan = parseJsonArtifact(input.snapshot, SUBAGENT_PLAN_FILENAME, blockers);
|
|
63
118
|
const parentSummaryValue = parseJsonArtifact(input.snapshot, SUBAGENT_PARENT_SUMMARY_FILENAME, blockers);
|
|
64
119
|
const persistedEvidence = normalizeLegacySubagentCountFields(parseJsonArtifact(input.snapshot, SUBAGENT_EVIDENCE_FILENAME, blockers), isRecord(plan) ? plan : null);
|
|
120
|
+
const receiptProjectedPersistedEvidence = projectReceiptAdditiveFields(SUBAGENT_EVIDENCE_FILENAME, persistedEvidence);
|
|
121
|
+
const trustedHostCapabilityEvidence = projectTrustedHostCapabilityEvidence(recordValue(receiptProjectedPersistedEvidence, 'host_capability_evidence'), blockers);
|
|
122
|
+
const projectedPersistedEvidence = isRecord(receiptProjectedPersistedEvidence) && trustedHostCapabilityEvidence
|
|
123
|
+
? { ...receiptProjectedPersistedEvidence, host_capability_evidence: trustedHostCapabilityEvidence }
|
|
124
|
+
: receiptProjectedPersistedEvidence;
|
|
65
125
|
const summary = normalizeLegacySubagentCountFields(parseJsonArtifact(input.snapshot, NARUTO_SUMMARY_FILENAME, blockers), isRecord(plan) ? plan : null);
|
|
66
126
|
const gate = normalizeLegacySubagentCountFields(parseJsonArtifact(input.snapshot, NARUTO_GATE_FILENAME, blockers), isRecord(plan) ? plan : null);
|
|
67
127
|
const events = parseJsonlArtifact(input.snapshot, blockers);
|
|
@@ -100,6 +160,7 @@ export function projectNarutoProofSnapshot(input) {
|
|
|
100
160
|
workflowStatus: firstText(recordValue(summary, 'status')),
|
|
101
161
|
preparationOnly: recordValue(persistedEvidence, 'preparation_only') === true,
|
|
102
162
|
runId: workflowRunId,
|
|
163
|
+
...(trustedHostCapabilityEvidence ? { hostCapabilityEvidence: trustedHostCapabilityEvidence } : {}),
|
|
103
164
|
additionalBlockers: subagentCountContractBlockers(isRecord(plan) ? plan : null, observedStarts)
|
|
104
165
|
});
|
|
105
166
|
if (planRequestedSubagents === null && plan !== null)
|
|
@@ -108,9 +169,42 @@ export function projectNarutoProofSnapshot(input) {
|
|
|
108
169
|
&& input.snapshot.bytes[SUBAGENT_EVENT_LOG_FILENAME] !== null
|
|
109
170
|
&& input.snapshot.bytes[SUBAGENT_PARENT_SUMMARY_FILENAME] !== null;
|
|
110
171
|
if (evidenceInputsPresent)
|
|
111
|
-
validatePersistedEvidence(
|
|
172
|
+
validatePersistedEvidence(projectedPersistedEvidence, rebuiltEvidence, blockers);
|
|
112
173
|
const changedFiles = projectChangedFiles(normalizedParentSummary.raw?.changed_files, blockers);
|
|
113
174
|
const verification = projectVerification(normalizedParentSummary.raw?.verification, blockers);
|
|
175
|
+
const parentArtifacts = projectArtifacts(recordValue(parentSummaryValue, 'artifacts'), blockers);
|
|
176
|
+
const parentCapabilitiesUsed = projectCapabilityUses(recordValue(parentSummaryValue, 'capabilities_used'), blockers);
|
|
177
|
+
const trustedArtifacts = trustedHostCapabilityEvidence
|
|
178
|
+
? projectArtifacts(trustedHostCapabilityEvidence.artifacts, blockers) || []
|
|
179
|
+
: undefined;
|
|
180
|
+
const trustedCapabilitiesUsed = trustedHostCapabilityEvidence
|
|
181
|
+
? projectCapabilityUses(trustedHostCapabilityEvidence.capabilities_used, blockers) || []
|
|
182
|
+
: undefined;
|
|
183
|
+
const rawParentArtifacts = recordValue(parentSummaryValue, 'artifacts');
|
|
184
|
+
const rawParentCapabilitiesUsed = recordValue(parentSummaryValue, 'capabilities_used');
|
|
185
|
+
const parentHostClaimsPresent = hasNonEmptyHostCapabilityClaim(rawParentArtifacts)
|
|
186
|
+
|| hasNonEmptyHostCapabilityClaim(rawParentCapabilitiesUsed);
|
|
187
|
+
const trustedHostBindingRequired = Boolean(trustedHostCapabilityEvidence && (trustedHostCapabilityEvidence.runtime.requested_capability_ids.length > 0
|
|
188
|
+
|| trustedHostCapabilityEvidence.tool_calls.length > 0
|
|
189
|
+
|| trustedHostCapabilityEvidence.artifacts.length > 0
|
|
190
|
+
|| parentHostClaimsPresent));
|
|
191
|
+
if (trustedHostCapabilityEvidence) {
|
|
192
|
+
if (trustedHostBindingRequired && JSON.stringify(parentArtifacts || []) !== JSON.stringify(trustedArtifacts || [])) {
|
|
193
|
+
blockers.push('proof_parent_host_artifacts_mismatch');
|
|
194
|
+
}
|
|
195
|
+
if (trustedHostBindingRequired && JSON.stringify(parentCapabilitiesUsed || []) !== JSON.stringify(trustedCapabilitiesUsed || [])) {
|
|
196
|
+
blockers.push('proof_parent_host_capabilities_mismatch');
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else if (parentHostClaimsPresent) {
|
|
200
|
+
blockers.push('proof_host_capability_evidence_missing');
|
|
201
|
+
}
|
|
202
|
+
const artifacts = trustedHostBindingRequired ? trustedArtifacts : parentArtifacts;
|
|
203
|
+
const capabilitiesUsed = trustedHostBindingRequired ? trustedCapabilitiesUsed : parentCapabilitiesUsed;
|
|
204
|
+
for (const receipt of capabilitiesUsed || []) {
|
|
205
|
+
if (receipt.status !== 'passed')
|
|
206
|
+
blockers.push(`proof_capability_use_not_passed:${receipt.id}`);
|
|
207
|
+
}
|
|
114
208
|
const parentText = normalizedParentSummary.summary || '';
|
|
115
209
|
if (parentText.length > MAX_RESULT_SUMMARY_CHARS)
|
|
116
210
|
blockers.push('proof_result_summary_too_large');
|
|
@@ -123,11 +217,13 @@ export function projectNarutoProofSnapshot(input) {
|
|
|
123
217
|
? parentText
|
|
124
218
|
: '',
|
|
125
219
|
changed_files: changedFiles,
|
|
126
|
-
verification
|
|
220
|
+
verification,
|
|
221
|
+
...(artifacts === undefined ? {} : { artifacts }),
|
|
222
|
+
...(capabilitiesUsed === undefined ? {} : { capabilities_used: capabilitiesUsed })
|
|
127
223
|
};
|
|
128
224
|
const completed = gatePassed(gate)
|
|
129
|
-
&& recordValue(
|
|
130
|
-
&& firstText(recordValue(
|
|
225
|
+
&& recordValue(projectedPersistedEvidence, 'ok') === true
|
|
226
|
+
&& firstText(recordValue(projectedPersistedEvidence, 'status')).toLowerCase() === 'completed'
|
|
131
227
|
&& rebuiltEvidence?.ok === true
|
|
132
228
|
&& normalizedParentSummary.trustworthy
|
|
133
229
|
&& normalizedParentSummary.status === 'completed'
|
|
@@ -138,8 +234,8 @@ export function projectNarutoProofSnapshot(input) {
|
|
|
138
234
|
const explicitBlocked = !completed && isExplicitlyBlocked({
|
|
139
235
|
blockers,
|
|
140
236
|
parentStatus: normalizedParentSummary.status,
|
|
141
|
-
evidenceStatus: firstText(recordValue(
|
|
142
|
-
failedThreads: Number(recordValue(
|
|
237
|
+
evidenceStatus: firstText(recordValue(projectedPersistedEvidence, 'status')),
|
|
238
|
+
failedThreads: Number(recordValue(projectedPersistedEvidence, 'failed_threads') || 0),
|
|
143
239
|
summaryStatus: firstText(recordValue(summary, 'status')),
|
|
144
240
|
gate
|
|
145
241
|
});
|
|
@@ -151,7 +247,7 @@ export function projectNarutoProofSnapshot(input) {
|
|
|
151
247
|
status,
|
|
152
248
|
missionId,
|
|
153
249
|
workflowRunId,
|
|
154
|
-
artifactHashes: input.snapshot
|
|
250
|
+
artifactHashes: projectFingerprintArtifactHashes(input.snapshot),
|
|
155
251
|
result
|
|
156
252
|
});
|
|
157
253
|
return {
|
|
@@ -163,13 +259,16 @@ export function projectNarutoProofSnapshot(input) {
|
|
|
163
259
|
workflow: 'official_codex_subagent',
|
|
164
260
|
workflow_run_id: workflowRunId,
|
|
165
261
|
blockers: uniqueBlockers,
|
|
166
|
-
evidence:
|
|
262
|
+
evidence: projectedPersistedEvidence,
|
|
167
263
|
summary,
|
|
168
264
|
gate,
|
|
169
265
|
result,
|
|
170
266
|
proof_fingerprint: proofFingerprint
|
|
171
267
|
};
|
|
172
268
|
}
|
|
269
|
+
function hasNonEmptyHostCapabilityClaim(value) {
|
|
270
|
+
return Array.isArray(value) ? value.length > 0 : value !== undefined;
|
|
271
|
+
}
|
|
173
272
|
export function validateNarutoProofStatus(value) {
|
|
174
273
|
const status = String(value.status || '').trim();
|
|
175
274
|
if (status !== 'completed' && status !== 'blocked' && status !== 'incomplete') {
|
|
@@ -177,6 +276,202 @@ export function validateNarutoProofStatus(value) {
|
|
|
177
276
|
}
|
|
178
277
|
return value.ok === (status === 'completed') ? [] : ['proof_status_ok_inconsistent'];
|
|
179
278
|
}
|
|
279
|
+
function projectTrustedHostCapabilityEvidence(value, blockers) {
|
|
280
|
+
if (value === undefined || value === null)
|
|
281
|
+
return null;
|
|
282
|
+
if (!isRecord(value)
|
|
283
|
+
|| value.schema !== HOST_CAPABILITY_EVIDENCE_SCHEMA
|
|
284
|
+
|| typeof value.ok !== 'boolean'
|
|
285
|
+
|| !isRecord(value.runtime)
|
|
286
|
+
|| value.runtime.schema !== HOST_CAPABILITY_RUNTIME_SCHEMA
|
|
287
|
+
|| value.runtime.server !== 'acas-tools'
|
|
288
|
+
|| value.runtime.capability_digest !== hostCapabilityDigest(HOST_CAPABILITY_DESCRIPTORS)
|
|
289
|
+
|| !Array.isArray(value.runtime.requested_capability_ids)
|
|
290
|
+
|| !Array.isArray(value.runtime.blockers)
|
|
291
|
+
|| !Array.isArray(value.tool_calls)
|
|
292
|
+
|| !Array.isArray(value.capabilities_used)
|
|
293
|
+
|| !Array.isArray(value.artifacts)
|
|
294
|
+
|| !Array.isArray(value.blockers)) {
|
|
295
|
+
blockers.push('proof_host_capability_evidence_invalid');
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
const requestedIds = value.runtime.requested_capability_ids.map((id) => String(id || '').trim());
|
|
299
|
+
if (requestedIds.some((id) => !HOST_CAPABILITY_BY_ID.has(id))
|
|
300
|
+
|| new Set(requestedIds).size !== requestedIds.length
|
|
301
|
+
|| value.runtime.blockers.some((blocker) => !isBoundedBlockerCode(blocker))
|
|
302
|
+
|| value.blockers.some((blocker) => !isBoundedBlockerCode(blocker))) {
|
|
303
|
+
blockers.push('proof_host_capability_runtime_invalid');
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
const knownTools = new Set(HOST_CAPABILITY_DESCRIPTORS.flatMap((descriptor) => descriptor.tool_names));
|
|
307
|
+
if (value.tool_calls.length > 1024 || value.tool_calls.some((row) => {
|
|
308
|
+
if (!isRecord(row))
|
|
309
|
+
return true;
|
|
310
|
+
return row.server !== 'acas-tools'
|
|
311
|
+
|| typeof row.tool !== 'string'
|
|
312
|
+
|| !knownTools.has(row.tool)
|
|
313
|
+
|| (row.status !== 'passed' && row.status !== 'failed')
|
|
314
|
+
|| typeof row.event_sha256 !== 'string'
|
|
315
|
+
|| !SHA256_RECEIPT_PATTERN.test(row.event_sha256);
|
|
316
|
+
})) {
|
|
317
|
+
blockers.push('proof_host_capability_tool_calls_invalid');
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
const receiptBlockers = [];
|
|
321
|
+
const capabilities = projectCapabilityUses(value.capabilities_used, receiptBlockers);
|
|
322
|
+
const artifacts = projectArtifacts(value.artifacts, receiptBlockers);
|
|
323
|
+
if (!capabilities || !artifacts || receiptBlockers.length > 0
|
|
324
|
+
|| capabilities.length !== value.capabilities_used.length
|
|
325
|
+
|| artifacts.length !== value.artifacts.length) {
|
|
326
|
+
blockers.push(...receiptBlockers, 'proof_host_capability_receipts_invalid');
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
const observedIds = capabilities.map((receipt) => receipt.id);
|
|
330
|
+
if (JSON.stringify([...observedIds].sort()) !== JSON.stringify([...requestedIds].sort())) {
|
|
331
|
+
blockers.push('proof_host_capability_requested_receipts_mismatch');
|
|
332
|
+
}
|
|
333
|
+
const expectedOk = value.blockers.length === 0 && capabilities.every((receipt) => receipt.status === 'passed');
|
|
334
|
+
if (value.ok !== expectedOk)
|
|
335
|
+
blockers.push('proof_host_capability_evidence_status_inconsistent');
|
|
336
|
+
const bindingBlockers = trustedHostCapabilityReceiptBindingBlockers({
|
|
337
|
+
...value,
|
|
338
|
+
capabilities_used: capabilities,
|
|
339
|
+
artifacts
|
|
340
|
+
});
|
|
341
|
+
blockers.push(...bindingBlockers.map((blocker) => `proof_${blocker}`));
|
|
342
|
+
blockers.push(...value.blockers);
|
|
343
|
+
return {
|
|
344
|
+
...value,
|
|
345
|
+
capabilities_used: capabilities,
|
|
346
|
+
artifacts
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
async function verifyProjectedArtifactFiles(input) {
|
|
350
|
+
const workspaceRoot = await resolveArtifactWorkspaceRoot(input.artifactDir, input.workspaceRoot);
|
|
351
|
+
if (!workspaceRoot)
|
|
352
|
+
return ['proof_artifact_workspace_root_missing'];
|
|
353
|
+
const blockers = [];
|
|
354
|
+
for (const artifact of input.artifacts) {
|
|
355
|
+
blockers.push(...await verifyProjectedArtifactFile(workspaceRoot, artifact));
|
|
356
|
+
}
|
|
357
|
+
return uniqueStrings(blockers);
|
|
358
|
+
}
|
|
359
|
+
async function resolveArtifactWorkspaceRoot(artifactDir, explicitRoot) {
|
|
360
|
+
let candidate = explicitRoot ? path.resolve(explicitRoot) : '';
|
|
361
|
+
if (!candidate) {
|
|
362
|
+
let cursor = path.resolve(artifactDir);
|
|
363
|
+
while (true) {
|
|
364
|
+
if (path.basename(cursor) === '.sneakoscope') {
|
|
365
|
+
candidate = path.dirname(cursor);
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
const parent = path.dirname(cursor);
|
|
369
|
+
if (parent === cursor)
|
|
370
|
+
break;
|
|
371
|
+
cursor = parent;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (!candidate)
|
|
375
|
+
return null;
|
|
376
|
+
try {
|
|
377
|
+
const realRoot = await fsp.realpath(candidate);
|
|
378
|
+
return (await fsp.stat(realRoot)).isDirectory() ? realRoot : null;
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
async function verifyProjectedArtifactFile(workspaceRoot, artifact) {
|
|
385
|
+
if (artifact.bytes > MAX_DELIVERABLE_ARTIFACT_BYTES)
|
|
386
|
+
return ['proof_artifact_file_too_large'];
|
|
387
|
+
const segments = artifact.path.split('/');
|
|
388
|
+
const candidate = path.join(workspaceRoot, ...segments);
|
|
389
|
+
if (!pathWithinRoot(workspaceRoot, candidate))
|
|
390
|
+
return ['proof_artifact_file_escape'];
|
|
391
|
+
let cursor = workspaceRoot;
|
|
392
|
+
for (let index = 0; index < segments.length; index += 1) {
|
|
393
|
+
cursor = path.join(cursor, segments[index]);
|
|
394
|
+
try {
|
|
395
|
+
const stat = await fsp.lstat(cursor);
|
|
396
|
+
if (stat.isSymbolicLink())
|
|
397
|
+
return ['proof_artifact_file_symlink'];
|
|
398
|
+
if (index < segments.length - 1 && !stat.isDirectory())
|
|
399
|
+
return ['proof_artifact_file_not_regular'];
|
|
400
|
+
if (index === segments.length - 1 && !stat.isFile())
|
|
401
|
+
return ['proof_artifact_file_not_regular'];
|
|
402
|
+
}
|
|
403
|
+
catch (error) {
|
|
404
|
+
return [errorCode(error) === 'ENOENT' ? 'proof_artifact_file_missing' : 'proof_artifact_file_unreadable'];
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
try {
|
|
408
|
+
const realCandidate = await fsp.realpath(candidate);
|
|
409
|
+
if (!pathWithinRoot(workspaceRoot, realCandidate))
|
|
410
|
+
return ['proof_artifact_file_escape'];
|
|
411
|
+
const expected = await fsp.stat(realCandidate);
|
|
412
|
+
if (expected.size > MAX_DELIVERABLE_ARTIFACT_BYTES)
|
|
413
|
+
return ['proof_artifact_file_too_large'];
|
|
414
|
+
const handle = await fsp.open(candidate, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
|
|
415
|
+
try {
|
|
416
|
+
const before = await handle.stat();
|
|
417
|
+
if (!before.isFile())
|
|
418
|
+
return ['proof_artifact_file_not_regular'];
|
|
419
|
+
if (before.dev !== expected.dev || before.ino !== expected.ino) {
|
|
420
|
+
return ['proof_artifact_file_changed_during_hash'];
|
|
421
|
+
}
|
|
422
|
+
const header = Buffer.alloc(8);
|
|
423
|
+
const headerRead = await handle.read(header, 0, header.length, 0);
|
|
424
|
+
const digest = createHash('sha256');
|
|
425
|
+
for await (const chunk of handle.createReadStream({ autoClose: false, start: 0 }))
|
|
426
|
+
digest.update(chunk);
|
|
427
|
+
const after = await handle.stat();
|
|
428
|
+
const finalPathStat = await fsp.lstat(candidate);
|
|
429
|
+
if (finalPathStat.isSymbolicLink())
|
|
430
|
+
return ['proof_artifact_file_symlink'];
|
|
431
|
+
if (before.dev !== after.dev
|
|
432
|
+
|| before.ino !== after.ino
|
|
433
|
+
|| before.size !== after.size
|
|
434
|
+
|| before.mtimeMs !== after.mtimeMs
|
|
435
|
+
|| finalPathStat.dev !== after.dev
|
|
436
|
+
|| finalPathStat.ino !== after.ino) {
|
|
437
|
+
return ['proof_artifact_file_changed_during_hash'];
|
|
438
|
+
}
|
|
439
|
+
const blockers = [];
|
|
440
|
+
if (after.size !== artifact.bytes)
|
|
441
|
+
blockers.push('proof_artifact_file_bytes_mismatch');
|
|
442
|
+
if (`sha256:${digest.digest('hex')}` !== artifact.sha256)
|
|
443
|
+
blockers.push('proof_artifact_file_sha256_mismatch');
|
|
444
|
+
blockers.push(...artifactSignatureBlockers(artifact, header.subarray(0, headerRead.bytesRead)));
|
|
445
|
+
return blockers;
|
|
446
|
+
}
|
|
447
|
+
finally {
|
|
448
|
+
await handle.close();
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
catch (error) {
|
|
452
|
+
return [errorCode(error) === 'ELOOP' ? 'proof_artifact_file_symlink' : 'proof_artifact_file_unreadable'];
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
function artifactSignatureBlockers(artifact, header) {
|
|
456
|
+
if (artifact.media_type === 'application/pdf') {
|
|
457
|
+
return header.subarray(0, 5).equals(Buffer.from('%PDF-')) ? [] : ['proof_artifact_pdf_signature_invalid'];
|
|
458
|
+
}
|
|
459
|
+
if (artifact.media_type === 'image/png') {
|
|
460
|
+
const png = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
461
|
+
return header.subarray(0, png.length).equals(png) ? [] : ['proof_artifact_png_signature_invalid'];
|
|
462
|
+
}
|
|
463
|
+
if (artifact.media_type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
|
|
464
|
+
const zipLocalHeader = Buffer.from([0x50, 0x4b, 0x03, 0x04]);
|
|
465
|
+
return header.subarray(0, zipLocalHeader.length).equals(zipLocalHeader)
|
|
466
|
+
? []
|
|
467
|
+
: ['proof_artifact_xlsx_signature_invalid'];
|
|
468
|
+
}
|
|
469
|
+
return [];
|
|
470
|
+
}
|
|
471
|
+
function pathWithinRoot(root, candidate) {
|
|
472
|
+
const relative = path.relative(root, candidate);
|
|
473
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
474
|
+
}
|
|
180
475
|
function parseJsonArtifact(snapshot, filename, blockers) {
|
|
181
476
|
const bytes = snapshot.bytes[filename];
|
|
182
477
|
if (!bytes)
|
|
@@ -275,6 +570,9 @@ function validatePersistedEvidence(persisted, rebuilt, blockers) {
|
|
|
275
570
|
blockers.push(`proof_evidence_rebuild_mismatch:${key}`);
|
|
276
571
|
}
|
|
277
572
|
}
|
|
573
|
+
if (JSON.stringify(persisted.host_capability_evidence) !== JSON.stringify(rebuilt.host_capability_evidence)) {
|
|
574
|
+
blockers.push('proof_evidence_rebuild_mismatch:host_capability_evidence');
|
|
575
|
+
}
|
|
278
576
|
}
|
|
279
577
|
function validateCountContractArtifacts(input, blockers) {
|
|
280
578
|
for (const [label, value] of [
|
|
@@ -361,6 +659,210 @@ function projectVerificationRow(value) {
|
|
|
361
659
|
const rawStatus = isRecord(value) ? firstText(value.status) : '';
|
|
362
660
|
return { name, status: normalizeVerificationStatus(rawStatus, name) };
|
|
363
661
|
}
|
|
662
|
+
function projectArtifacts(value, blockers) {
|
|
663
|
+
if (value === undefined)
|
|
664
|
+
return undefined;
|
|
665
|
+
if (!Array.isArray(value)) {
|
|
666
|
+
blockers.push('proof_artifacts_invalid');
|
|
667
|
+
return [];
|
|
668
|
+
}
|
|
669
|
+
if (value.length > MAX_ARTIFACTS)
|
|
670
|
+
blockers.push('proof_artifacts_too_many');
|
|
671
|
+
const result = [];
|
|
672
|
+
const seenPaths = new Set();
|
|
673
|
+
let aggregateBytes = 0;
|
|
674
|
+
for (const row of value.slice(0, MAX_ARTIFACTS)) {
|
|
675
|
+
if (!isRecord(row)) {
|
|
676
|
+
blockers.push('proof_artifact_invalid');
|
|
677
|
+
continue;
|
|
678
|
+
}
|
|
679
|
+
const artifactPath = normalizeArtifactPath(row.path, blockers);
|
|
680
|
+
const kind = boundedToken(row.kind, MAX_ARTIFACT_KIND_CHARS, /^[a-z][a-z0-9_-]*$/);
|
|
681
|
+
const mediaType = boundedToken(row.media_type, MAX_MEDIA_TYPE_CHARS, /^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/i);
|
|
682
|
+
const artifactSha256 = typeof row.sha256 === 'string' && SHA256_RECEIPT_PATTERN.test(row.sha256)
|
|
683
|
+
? row.sha256
|
|
684
|
+
: null;
|
|
685
|
+
const bytes = typeof row.bytes === 'number' && Number.isSafeInteger(row.bytes) && row.bytes > 0
|
|
686
|
+
? row.bytes
|
|
687
|
+
: null;
|
|
688
|
+
const role = typeof row.role === 'string' && ARTIFACT_ROLES.has(row.role)
|
|
689
|
+
? row.role
|
|
690
|
+
: null;
|
|
691
|
+
if (!kind)
|
|
692
|
+
blockers.push('proof_artifact_kind_invalid');
|
|
693
|
+
if (!mediaType)
|
|
694
|
+
blockers.push('proof_artifact_media_type_invalid');
|
|
695
|
+
if (!artifactSha256)
|
|
696
|
+
blockers.push('proof_artifact_sha256_invalid');
|
|
697
|
+
if (bytes === null)
|
|
698
|
+
blockers.push('proof_artifact_bytes_invalid');
|
|
699
|
+
if (bytes !== null && bytes > MAX_DELIVERABLE_ARTIFACT_BYTES)
|
|
700
|
+
blockers.push('proof_artifact_bytes_too_large');
|
|
701
|
+
if (!role)
|
|
702
|
+
blockers.push('proof_artifact_role_invalid');
|
|
703
|
+
if (!artifactPath || !kind || !mediaType || !artifactSha256 || bytes === null || !role)
|
|
704
|
+
continue;
|
|
705
|
+
if (seenPaths.has(artifactPath)) {
|
|
706
|
+
blockers.push('proof_artifact_path_duplicate');
|
|
707
|
+
continue;
|
|
708
|
+
}
|
|
709
|
+
if (role === 'deliverable' && isNonDeliverableArtifact(artifactPath, kind)) {
|
|
710
|
+
blockers.push('proof_artifact_deliverable_role_invalid');
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
blockers.push(...artifactMediaConsistencyBlockers(artifactPath, mediaType));
|
|
714
|
+
seenPaths.add(artifactPath);
|
|
715
|
+
aggregateBytes += bytes;
|
|
716
|
+
result.push({ path: artifactPath, kind, media_type: mediaType, sha256: artifactSha256, bytes, role });
|
|
717
|
+
}
|
|
718
|
+
if (aggregateBytes > MAX_DELIVERABLE_ARTIFACT_AGGREGATE_BYTES)
|
|
719
|
+
blockers.push('proof_artifact_bytes_aggregate_too_large');
|
|
720
|
+
return result;
|
|
721
|
+
}
|
|
722
|
+
function normalizeArtifactPath(value, blockers) {
|
|
723
|
+
if (typeof value !== 'string') {
|
|
724
|
+
blockers.push('proof_artifact_path_invalid');
|
|
725
|
+
return null;
|
|
726
|
+
}
|
|
727
|
+
const original = value.trim();
|
|
728
|
+
if (!original || original.length > MAX_ARTIFACT_PATH_CHARS || /[\r\n\0]/.test(original)) {
|
|
729
|
+
blockers.push('proof_artifact_path_invalid');
|
|
730
|
+
return null;
|
|
731
|
+
}
|
|
732
|
+
if (original.includes('\\')) {
|
|
733
|
+
blockers.push('proof_artifact_path_not_posix');
|
|
734
|
+
return null;
|
|
735
|
+
}
|
|
736
|
+
if (path.posix.isAbsolute(original) || path.win32.isAbsolute(original)) {
|
|
737
|
+
blockers.push('proof_artifact_path_absolute');
|
|
738
|
+
return null;
|
|
739
|
+
}
|
|
740
|
+
const normalized = path.posix.normalize(original).replace(/^\.\//, '');
|
|
741
|
+
if (!normalized || normalized === '.' || normalized === '..' || normalized.startsWith('../')) {
|
|
742
|
+
blockers.push('proof_artifact_path_escape');
|
|
743
|
+
return null;
|
|
744
|
+
}
|
|
745
|
+
if (normalized.length > MAX_ARTIFACT_PATH_CHARS) {
|
|
746
|
+
blockers.push('proof_artifact_path_invalid');
|
|
747
|
+
return null;
|
|
748
|
+
}
|
|
749
|
+
return normalized;
|
|
750
|
+
}
|
|
751
|
+
function isNonDeliverableArtifact(artifactPath, kind) {
|
|
752
|
+
if (NON_DELIVERABLE_ARTIFACT_KINDS.has(kind.toLowerCase()))
|
|
753
|
+
return true;
|
|
754
|
+
const segments = artifactPath.toLowerCase().split('/');
|
|
755
|
+
return segments.some((segment) => NON_DELIVERABLE_PATH_SEGMENTS.has(segment))
|
|
756
|
+
|| artifactPath.toLowerCase().endsWith('.log');
|
|
757
|
+
}
|
|
758
|
+
function artifactMediaConsistencyBlockers(artifactPath, mediaType) {
|
|
759
|
+
const extension = path.posix.extname(artifactPath).toLowerCase();
|
|
760
|
+
const expectedByExtension = {
|
|
761
|
+
'.csv': 'text/csv',
|
|
762
|
+
'.pdf': 'application/pdf',
|
|
763
|
+
'.png': 'image/png',
|
|
764
|
+
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
765
|
+
};
|
|
766
|
+
const expectedExtensionsByMedia = {
|
|
767
|
+
'text/csv': ['.csv'],
|
|
768
|
+
'application/pdf': ['.pdf'],
|
|
769
|
+
'image/png': ['.png'],
|
|
770
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx']
|
|
771
|
+
};
|
|
772
|
+
const blockers = [];
|
|
773
|
+
const expectedMedia = expectedByExtension[extension];
|
|
774
|
+
if (expectedMedia && mediaType !== expectedMedia)
|
|
775
|
+
blockers.push('proof_artifact_media_extension_mismatch');
|
|
776
|
+
const expectedExtensions = expectedExtensionsByMedia[mediaType];
|
|
777
|
+
if (expectedExtensions && !expectedExtensions.includes(extension))
|
|
778
|
+
blockers.push('proof_artifact_extension_media_mismatch');
|
|
779
|
+
return blockers;
|
|
780
|
+
}
|
|
781
|
+
function projectCapabilityUses(value, blockers) {
|
|
782
|
+
if (value === undefined)
|
|
783
|
+
return undefined;
|
|
784
|
+
if (!Array.isArray(value)) {
|
|
785
|
+
blockers.push('proof_capabilities_used_invalid');
|
|
786
|
+
return [];
|
|
787
|
+
}
|
|
788
|
+
if (value.length > MAX_CAPABILITY_USES)
|
|
789
|
+
blockers.push('proof_capabilities_used_too_many');
|
|
790
|
+
const result = [];
|
|
791
|
+
const seenIds = new Set();
|
|
792
|
+
for (const row of value.slice(0, MAX_CAPABILITY_USES)) {
|
|
793
|
+
if (!isRecord(row)) {
|
|
794
|
+
blockers.push('proof_capability_use_invalid');
|
|
795
|
+
continue;
|
|
796
|
+
}
|
|
797
|
+
const id = boundedToken(row.id, MAX_CAPABILITY_ID_CHARS, /^[a-z][a-z0-9._-]*$/);
|
|
798
|
+
const descriptor = id ? HOST_CAPABILITY_BY_ID.get(id) : undefined;
|
|
799
|
+
const status = normalizeCapabilityStatus(row.status);
|
|
800
|
+
const toolNames = projectCapabilityToolNames(row.tool_names, descriptor?.tool_names || [], status, blockers);
|
|
801
|
+
const receiptSha256 = typeof row.receipt_sha256 === 'string' && SHA256_RECEIPT_PATTERN.test(row.receipt_sha256)
|
|
802
|
+
? row.receipt_sha256
|
|
803
|
+
: null;
|
|
804
|
+
if (!id)
|
|
805
|
+
blockers.push('proof_capability_use_id_invalid');
|
|
806
|
+
else if (!descriptor)
|
|
807
|
+
blockers.push('proof_capability_use_unknown_id');
|
|
808
|
+
if (!status)
|
|
809
|
+
blockers.push('proof_capability_use_status_invalid');
|
|
810
|
+
if (!receiptSha256)
|
|
811
|
+
blockers.push('proof_capability_use_receipt_sha256_invalid');
|
|
812
|
+
if (!id || !descriptor || !status || !toolNames || !receiptSha256)
|
|
813
|
+
continue;
|
|
814
|
+
if (seenIds.has(id)) {
|
|
815
|
+
blockers.push('proof_capability_use_duplicate');
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
seenIds.add(id);
|
|
819
|
+
result.push({ id, status, tool_names: toolNames, receipt_sha256: receiptSha256 });
|
|
820
|
+
}
|
|
821
|
+
return result;
|
|
822
|
+
}
|
|
823
|
+
function projectCapabilityToolNames(value, allowedToolNames, status, blockers) {
|
|
824
|
+
if (!Array.isArray(value) || (status === 'passed' && value.length === 0)) {
|
|
825
|
+
blockers.push('proof_capability_use_tool_names_invalid');
|
|
826
|
+
return null;
|
|
827
|
+
}
|
|
828
|
+
if (value.length > MAX_CAPABILITY_TOOL_NAMES) {
|
|
829
|
+
blockers.push('proof_capability_use_tool_names_too_many');
|
|
830
|
+
return null;
|
|
831
|
+
}
|
|
832
|
+
const result = [];
|
|
833
|
+
const seen = new Set();
|
|
834
|
+
const allowed = new Set(allowedToolNames);
|
|
835
|
+
for (const valueItem of value) {
|
|
836
|
+
const toolName = boundedToken(valueItem, MAX_CAPABILITY_TOOL_NAME_CHARS, /^[A-Za-z][A-Za-z0-9_.:-]*$/);
|
|
837
|
+
if (!toolName) {
|
|
838
|
+
blockers.push('proof_capability_use_tool_name_invalid');
|
|
839
|
+
return null;
|
|
840
|
+
}
|
|
841
|
+
if (seen.has(toolName)) {
|
|
842
|
+
blockers.push('proof_capability_use_tool_name_duplicate');
|
|
843
|
+
return null;
|
|
844
|
+
}
|
|
845
|
+
if (!allowed.has(toolName)) {
|
|
846
|
+
blockers.push('proof_capability_use_tool_name_not_declared');
|
|
847
|
+
return null;
|
|
848
|
+
}
|
|
849
|
+
seen.add(toolName);
|
|
850
|
+
result.push(toolName);
|
|
851
|
+
}
|
|
852
|
+
return result;
|
|
853
|
+
}
|
|
854
|
+
function normalizeCapabilityStatus(value) {
|
|
855
|
+
const status = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
856
|
+
return status === 'passed' || status === 'failed' ? status : null;
|
|
857
|
+
}
|
|
858
|
+
function boundedToken(value, maxChars, pattern) {
|
|
859
|
+
if (typeof value !== 'string')
|
|
860
|
+
return null;
|
|
861
|
+
const text = value.trim();
|
|
862
|
+
if (!text || text.length > maxChars || containsLeakageMarker(text) || !pattern.test(text))
|
|
863
|
+
return null;
|
|
864
|
+
return text;
|
|
865
|
+
}
|
|
364
866
|
function normalizeVerificationStatus(value, name) {
|
|
365
867
|
const normalized = value.trim().toLowerCase();
|
|
366
868
|
if (normalized === 'passed' || normalized === 'pass' || normalized === 'ok' || normalized === 'verified')
|
|
@@ -391,6 +893,12 @@ function containsLeakageMarker(value) {
|
|
|
391
893
|
return /(?:^|\s)(?:prompt|system_prompt|user_prompt|stdout|stderr|environment|env_dump)\s*[:=]/i.test(value)
|
|
392
894
|
|| /\b(?:api[_-]?key|access[_-]?token|secret|password)\s*[:=]/i.test(value);
|
|
393
895
|
}
|
|
896
|
+
function isBoundedBlockerCode(value) {
|
|
897
|
+
return typeof value === 'string'
|
|
898
|
+
&& value.length > 0
|
|
899
|
+
&& value.length <= 240
|
|
900
|
+
&& /^[A-Za-z0-9_.:-]+$/.test(value);
|
|
901
|
+
}
|
|
394
902
|
function isExplicitlyBlocked(input) {
|
|
395
903
|
if (input.parentStatus === 'blocked' || input.parentStatus === 'failed' || input.failedThreads > 0)
|
|
396
904
|
return true;
|
|
@@ -420,6 +928,66 @@ function fingerprintProof(input) {
|
|
|
420
928
|
};
|
|
421
929
|
return `sha256:${sha256(JSON.stringify(stableInput))}`;
|
|
422
930
|
}
|
|
931
|
+
function projectFingerprintArtifactHashes(snapshot) {
|
|
932
|
+
const hashes = { ...snapshot.byte_hashes };
|
|
933
|
+
for (const filename of [SUBAGENT_PARENT_SUMMARY_FILENAME, SUBAGENT_EVIDENCE_FILENAME]) {
|
|
934
|
+
const bytes = snapshot.bytes[filename];
|
|
935
|
+
if (!bytes)
|
|
936
|
+
continue;
|
|
937
|
+
let parsed;
|
|
938
|
+
try {
|
|
939
|
+
parsed = JSON.parse(bytes.toString('utf8'));
|
|
940
|
+
}
|
|
941
|
+
catch {
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
944
|
+
const projected = projectReceiptAdditiveFields(filename, parsed);
|
|
945
|
+
if (projected === parsed)
|
|
946
|
+
continue;
|
|
947
|
+
hashes[filename] = `sha256:${sha256(`${JSON.stringify(projected, null, 2)}\n`)}`;
|
|
948
|
+
}
|
|
949
|
+
return hashes;
|
|
950
|
+
}
|
|
951
|
+
function projectReceiptAdditiveFields(filename, value) {
|
|
952
|
+
if (!isRecord(value))
|
|
953
|
+
return value;
|
|
954
|
+
if (filename === SUBAGENT_PARENT_SUMMARY_FILENAME) {
|
|
955
|
+
return projectReceiptContainerAdditiveFields(value);
|
|
956
|
+
}
|
|
957
|
+
const hostEvidence = recordValue(value, 'host_capability_evidence');
|
|
958
|
+
if (!isRecord(hostEvidence))
|
|
959
|
+
return value;
|
|
960
|
+
const projectedHostEvidence = projectReceiptContainerAdditiveFields(hostEvidence);
|
|
961
|
+
return projectedHostEvidence === hostEvidence
|
|
962
|
+
? value
|
|
963
|
+
: { ...value, host_capability_evidence: projectedHostEvidence };
|
|
964
|
+
}
|
|
965
|
+
function projectReceiptContainerAdditiveFields(value) {
|
|
966
|
+
const artifacts = projectReceiptRowsAdditiveFields(value.artifacts, ARTIFACT_RECEIPT_KEYS);
|
|
967
|
+
const capabilitiesUsed = projectReceiptRowsAdditiveFields(value.capabilities_used, CAPABILITY_USE_KEYS);
|
|
968
|
+
if (artifacts === value.artifacts && capabilitiesUsed === value.capabilities_used)
|
|
969
|
+
return value;
|
|
970
|
+
return {
|
|
971
|
+
...value,
|
|
972
|
+
...(artifacts === value.artifacts ? {} : { artifacts }),
|
|
973
|
+
...(capabilitiesUsed === value.capabilities_used ? {} : { capabilities_used: capabilitiesUsed })
|
|
974
|
+
};
|
|
975
|
+
}
|
|
976
|
+
function projectReceiptRowsAdditiveFields(value, allowedKeys) {
|
|
977
|
+
if (!Array.isArray(value))
|
|
978
|
+
return value;
|
|
979
|
+
let changed = false;
|
|
980
|
+
const projected = value.map((row) => {
|
|
981
|
+
if (!isRecord(row))
|
|
982
|
+
return row;
|
|
983
|
+
const unknownKeys = Object.keys(row).filter((key) => !allowedKeys.has(key));
|
|
984
|
+
if (unknownKeys.length === 0)
|
|
985
|
+
return row;
|
|
986
|
+
changed = true;
|
|
987
|
+
return Object.fromEntries(Object.entries(row).filter(([key]) => allowedKeys.has(key)));
|
|
988
|
+
});
|
|
989
|
+
return changed ? projected : value;
|
|
990
|
+
}
|
|
423
991
|
function recordValue(value, key) {
|
|
424
992
|
return isRecord(value) ? value[key] : undefined;
|
|
425
993
|
}
|