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
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { inspectConfinedPath, removeManagedPathVerified } from '../managed-path-safety.js';
|
|
3
|
+
import { EMERGENCY_DENIAL_DIR, MAX_EMERGENCY_DENIALS, MAX_LIFECYCLE_GUARD_BYTES, SUBAGENT_SKILL_AVAILABILITY_BLOCKER_FILENAME, validBlocker } from './subagent-skill-availability-contract.js';
|
|
4
|
+
import { boundedDirectoryNames, readBoundedConfinedJson, safeWriteJson } from './subagent-skill-availability-guards.js';
|
|
5
|
+
import { sha256 } from '../fsx.js';
|
|
6
|
+
export function uniqueArtifactDirs(...values) {
|
|
7
|
+
return [...new Set(values
|
|
8
|
+
.map((value) => String(value || '').trim())
|
|
9
|
+
.filter(Boolean)
|
|
10
|
+
.map((value) => path.resolve(value)))];
|
|
11
|
+
}
|
|
12
|
+
export async function persistBlockerEvidence(input) {
|
|
13
|
+
const emergencyArtifactDirs = input.emergency
|
|
14
|
+
? uniqueArtifactDirs(input.artifactDir, input.sessionArtifactDir)
|
|
15
|
+
: [];
|
|
16
|
+
const [sharedWrite, emergencyWrites] = await Promise.all([
|
|
17
|
+
safeWriteJson(path.join(input.artifactDir, SUBAGENT_SKILL_AVAILABILITY_BLOCKER_FILENAME), path.resolve(input.root), input.blocker),
|
|
18
|
+
Promise.all(emergencyArtifactDirs.map((artifactDir) => (persistEmergencyDenial(path.resolve(input.root), artifactDir, input.blocker))))
|
|
19
|
+
]);
|
|
20
|
+
return sharedWrite && emergencyWrites.every(Boolean);
|
|
21
|
+
}
|
|
22
|
+
export async function clearMatchingBlockerEvidence(input) {
|
|
23
|
+
const root = path.resolve(input.root);
|
|
24
|
+
const artifactDir = path.resolve(input.artifactDir);
|
|
25
|
+
const file = path.join(artifactDir, SUBAGENT_SKILL_AVAILABILITY_BLOCKER_FILENAME);
|
|
26
|
+
try {
|
|
27
|
+
const emergencyCleared = (await Promise.all(uniqueArtifactDirs(artifactDir, input.sessionArtifactDir).map((candidate) => (clearMatchingEmergencyDenials(root, candidate, input.threadHash))))).every(Boolean);
|
|
28
|
+
const inspected = await inspectConfinedPath(root, file);
|
|
29
|
+
if (!inspected.exists)
|
|
30
|
+
return emergencyCleared;
|
|
31
|
+
if (inspected.leafSymlink || !inspected.stat?.isFile())
|
|
32
|
+
return false;
|
|
33
|
+
const blockerRead = await readBoundedConfinedJson(root, file, MAX_LIFECYCLE_GUARD_BYTES);
|
|
34
|
+
if (blockerRead.status !== 'value' || !validBlocker(blockerRead.value))
|
|
35
|
+
return false;
|
|
36
|
+
if (blockerRead.value.thread_id_hash !== input.threadHash)
|
|
37
|
+
return emergencyCleared;
|
|
38
|
+
await removeManagedPathVerified(root, file);
|
|
39
|
+
return emergencyCleared && !(await inspectConfinedPath(root, file)).exists;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export async function matchingArtifactBlockers(root, artifactDir, sessionHash, turnHash) {
|
|
46
|
+
const emergency = await matchingEmergencyDenial(root, artifactDir, sessionHash, turnHash);
|
|
47
|
+
if (emergency)
|
|
48
|
+
return emergency;
|
|
49
|
+
const file = path.join(path.resolve(artifactDir), SUBAGENT_SKILL_AVAILABILITY_BLOCKER_FILENAME);
|
|
50
|
+
const result = await readBoundedConfinedJson(path.resolve(root), file, MAX_LIFECYCLE_GUARD_BYTES);
|
|
51
|
+
if (result.status === 'missing')
|
|
52
|
+
return null;
|
|
53
|
+
if (result.status !== 'value' || !validBlocker(result.value)) {
|
|
54
|
+
return invalidArtifactEvidence();
|
|
55
|
+
}
|
|
56
|
+
const blocker = result.value;
|
|
57
|
+
return blocker.session_scope_hash === sessionHash && blocker.turn_id_hash === turnHash
|
|
58
|
+
? {
|
|
59
|
+
blockers: blocker.blockers,
|
|
60
|
+
missionId: blocker.mission_id,
|
|
61
|
+
workflowRunId: blocker.workflow_run_id
|
|
62
|
+
}
|
|
63
|
+
: null;
|
|
64
|
+
}
|
|
65
|
+
export async function emergencyRunBlockers(root, artifactDir, missionId, workflowRunId) {
|
|
66
|
+
const records = await readEmergencyDenials(root, artifactDir);
|
|
67
|
+
const blockers = [];
|
|
68
|
+
for (const record of records) {
|
|
69
|
+
if (!record) {
|
|
70
|
+
blockers.push('subagent_skill_availability_guard_invalid');
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (record.mission_id === missionId && record.workflow_run_id === workflowRunId) {
|
|
74
|
+
blockers.push(...record.blockers);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return blockers;
|
|
78
|
+
}
|
|
79
|
+
function emergencyDenialDir(artifactDir) {
|
|
80
|
+
return path.join(artifactDir, EMERGENCY_DENIAL_DIR);
|
|
81
|
+
}
|
|
82
|
+
function emergencyDenialPath(artifactDir, sessionHash, turnHash) {
|
|
83
|
+
return path.join(emergencyDenialDir(artifactDir), `deny-${sha256(`${sessionHash}:${turnHash}`)}.json`);
|
|
84
|
+
}
|
|
85
|
+
async function persistEmergencyDenial(root, artifactDir, blocker) {
|
|
86
|
+
const written = await safeWriteJson(emergencyDenialPath(artifactDir, blocker.session_scope_hash, blocker.turn_id_hash), root, blocker);
|
|
87
|
+
if (!written)
|
|
88
|
+
return false;
|
|
89
|
+
return pruneEmergencyDenials(root, artifactDir);
|
|
90
|
+
}
|
|
91
|
+
async function matchingEmergencyDenial(root, artifactDir, sessionHash, turnHash) {
|
|
92
|
+
const file = emergencyDenialPath(path.resolve(artifactDir), sessionHash, turnHash);
|
|
93
|
+
try {
|
|
94
|
+
const result = await readBoundedConfinedJson(path.resolve(root), file, MAX_LIFECYCLE_GUARD_BYTES);
|
|
95
|
+
if (result.status === 'missing')
|
|
96
|
+
return null;
|
|
97
|
+
if (result.status !== 'value' || !validBlocker(result.value)
|
|
98
|
+
|| result.value.session_scope_hash !== sessionHash
|
|
99
|
+
|| result.value.turn_id_hash !== turnHash) {
|
|
100
|
+
return invalidArtifactEvidence();
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
blockers: result.value.blockers,
|
|
104
|
+
missionId: result.value.mission_id,
|
|
105
|
+
workflowRunId: result.value.workflow_run_id
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async function clearMatchingEmergencyDenials(root, artifactDir, threadHash) {
|
|
113
|
+
const records = await readEmergencyDenialsWithFiles(root, artifactDir);
|
|
114
|
+
if (records === null)
|
|
115
|
+
return false;
|
|
116
|
+
let ok = records.every((entry) => Boolean(entry.blocker));
|
|
117
|
+
for (const { file, blocker } of records) {
|
|
118
|
+
if (!blocker || blocker.thread_id_hash !== threadHash)
|
|
119
|
+
continue;
|
|
120
|
+
try {
|
|
121
|
+
const entry = await inspectConfinedPath(root, file);
|
|
122
|
+
if (entry.leafSymlink || !entry.stat?.isFile() || entry.stat.size > MAX_LIFECYCLE_GUARD_BYTES) {
|
|
123
|
+
ok = false;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
await removeManagedPathVerified(root, file);
|
|
127
|
+
if ((await inspectConfinedPath(root, file)).exists)
|
|
128
|
+
ok = false;
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
ok = false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return ok;
|
|
135
|
+
}
|
|
136
|
+
async function pruneEmergencyDenials(root, artifactDir) {
|
|
137
|
+
const dir = emergencyDenialDir(artifactDir);
|
|
138
|
+
const records = await readEmergencyDenialsWithFiles(root, artifactDir);
|
|
139
|
+
if (records === null)
|
|
140
|
+
return false;
|
|
141
|
+
const ordered = records
|
|
142
|
+
.filter((entry) => (Boolean(entry.blocker)))
|
|
143
|
+
.sort((left, right) => right.blocker.recorded_at.localeCompare(left.blocker.recorded_at));
|
|
144
|
+
let ok = records.every((entry) => Boolean(entry.blocker));
|
|
145
|
+
for (const entry of ordered.slice(MAX_EMERGENCY_DENIALS)) {
|
|
146
|
+
try {
|
|
147
|
+
await removeManagedPathVerified(root, entry.file);
|
|
148
|
+
if ((await inspectConfinedPath(root, entry.file)).exists)
|
|
149
|
+
ok = false;
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
ok = false;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const inspected = await inspectConfinedPath(root, dir).catch(() => null);
|
|
156
|
+
return ok && Boolean(inspected?.exists && inspected.stat?.isDirectory() && !inspected.leafSymlink);
|
|
157
|
+
}
|
|
158
|
+
async function readEmergencyDenials(root, artifactDir) {
|
|
159
|
+
const records = await readEmergencyDenialsWithFiles(root, artifactDir);
|
|
160
|
+
return records === null ? [null] : records.map((entry) => entry.blocker);
|
|
161
|
+
}
|
|
162
|
+
async function readEmergencyDenialsWithFiles(root, artifactDir) {
|
|
163
|
+
const dir = emergencyDenialDir(artifactDir);
|
|
164
|
+
let inspected;
|
|
165
|
+
try {
|
|
166
|
+
inspected = await inspectConfinedPath(root, dir);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
if (!inspected.exists)
|
|
172
|
+
return [];
|
|
173
|
+
if (inspected.leafSymlink || !inspected.stat?.isDirectory())
|
|
174
|
+
return null;
|
|
175
|
+
const names = await boundedDirectoryNames(dir);
|
|
176
|
+
if (names === null)
|
|
177
|
+
return null;
|
|
178
|
+
const records = [];
|
|
179
|
+
for (const name of names.filter((item) => /^deny-[a-f0-9]{64}\.json$/.test(item)).sort()) {
|
|
180
|
+
const file = path.join(dir, name);
|
|
181
|
+
const result = await readBoundedConfinedJson(root, file, MAX_LIFECYCLE_GUARD_BYTES);
|
|
182
|
+
records.push({
|
|
183
|
+
file,
|
|
184
|
+
blocker: result.status === 'value' && validBlocker(result.value) ? result.value : null
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return records;
|
|
188
|
+
}
|
|
189
|
+
function invalidArtifactEvidence() {
|
|
190
|
+
return {
|
|
191
|
+
blockers: ['subagent_skill_availability_guard_invalid'],
|
|
192
|
+
missionId: null,
|
|
193
|
+
workflowRunId: null
|
|
194
|
+
};
|
|
195
|
+
}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { constants as fsConstants } from 'node:fs';
|
|
2
|
+
import fsp from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { sha256, writeJsonAtomic } from '../fsx.js';
|
|
6
|
+
import { ensureConfinedDirectory, inspectConfinedPath, removeManagedPathVerified } from '../managed-path-safety.js';
|
|
7
|
+
import { ADMISSION_SCHEMA, GUARD_DIR, MAX_LIFECYCLE_GUARD_BYTES, MAX_LIFECYCLE_GUARD_ENTRIES, MAX_SUBAGENT_PLAN_BYTES, SUBAGENT_ADMISSION_BLOCKER_RE, SubagentSkillAvailabilityGuardError } from './subagent-skill-availability-contract.js';
|
|
8
|
+
function rootGuardDir(root) {
|
|
9
|
+
return path.join(root, '.sneakoscope', 'guards', GUARD_DIR);
|
|
10
|
+
}
|
|
11
|
+
function artifactGuardDir(artifactDir) {
|
|
12
|
+
return path.join(artifactDir, GUARD_DIR);
|
|
13
|
+
}
|
|
14
|
+
function homeGuardDir(home, canonicalRoot) {
|
|
15
|
+
return path.join(home, '.sneakoscope', 'guards', GUARD_DIR, sha256(canonicalRoot));
|
|
16
|
+
}
|
|
17
|
+
export function threadGuardPath(guardRoot, threadHash) {
|
|
18
|
+
return path.join(guardRoot, `thread-${threadHash}.json`);
|
|
19
|
+
}
|
|
20
|
+
export function turnGuardPath(guardRoot, sessionHash, turnHash) {
|
|
21
|
+
return path.join(guardRoot, `turn-${sha256(`${sessionHash}:${turnHash}`)}.json`);
|
|
22
|
+
}
|
|
23
|
+
function validAdmission(value) {
|
|
24
|
+
const blockers = Array.isArray(value?.blockers) ? value.blockers : null;
|
|
25
|
+
return value?.schema === ADMISSION_SCHEMA
|
|
26
|
+
&& ['allowed', 'blocked'].includes(String(value?.status || ''))
|
|
27
|
+
&& (value?.mission_id === null || typeof value?.mission_id === 'string')
|
|
28
|
+
&& (value?.workflow_run_id === null || typeof value?.workflow_run_id === 'string')
|
|
29
|
+
&& /^[a-f0-9]{64}$/.test(String(value?.thread_id_hash || ''))
|
|
30
|
+
&& /^[a-f0-9]{64}$/.test(String(value?.session_scope_hash || ''))
|
|
31
|
+
&& /^[a-f0-9]{64}$/.test(String(value?.turn_id_hash || ''))
|
|
32
|
+
&& blockers !== null
|
|
33
|
+
&& (value.status === 'allowed'
|
|
34
|
+
? blockers.length === 0
|
|
35
|
+
: blockers.length > 0 && blockers.every((item) => (SUBAGENT_ADMISSION_BLOCKER_RE.test(String(item || '')))));
|
|
36
|
+
}
|
|
37
|
+
export async function readConfinedJson(boundary, file) {
|
|
38
|
+
const result = await readBoundedConfinedJson(path.resolve(boundary), path.resolve(file), MAX_SUBAGENT_PLAN_BYTES);
|
|
39
|
+
return result.status === 'value' ? result.value : null;
|
|
40
|
+
}
|
|
41
|
+
export async function admissionGuardRoots(root, artifactDir) {
|
|
42
|
+
const projectRoot = path.resolve(root);
|
|
43
|
+
const canonicalRoot = await fsp.realpath(projectRoot);
|
|
44
|
+
const home = path.resolve(process.env.HOME || os.homedir());
|
|
45
|
+
const roots = [
|
|
46
|
+
{ root: rootGuardDir(projectRoot), boundary: projectRoot, missionIndependent: true },
|
|
47
|
+
...(artifactDir ? [{
|
|
48
|
+
root: artifactGuardDir(path.resolve(artifactDir)),
|
|
49
|
+
boundary: projectRoot,
|
|
50
|
+
missionIndependent: false
|
|
51
|
+
}] : []),
|
|
52
|
+
{ root: homeGuardDir(home, canonicalRoot), boundary: home, missionIndependent: true }
|
|
53
|
+
];
|
|
54
|
+
const unique = new Map();
|
|
55
|
+
for (const entry of roots) {
|
|
56
|
+
const previous = unique.get(entry.root);
|
|
57
|
+
if (!previous || (!previous.missionIndependent && entry.missionIndependent)) {
|
|
58
|
+
unique.set(entry.root, entry);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return [...unique.values()];
|
|
62
|
+
}
|
|
63
|
+
export async function writeAdmissionPair(root, admission) {
|
|
64
|
+
const [threadWrite, turnWrite] = await Promise.all([
|
|
65
|
+
safeWriteJson(threadGuardPath(root.root, admission.thread_id_hash), root.boundary, admission),
|
|
66
|
+
safeWriteJson(turnGuardPath(root.root, admission.session_scope_hash, admission.turn_id_hash), root.boundary, admission)
|
|
67
|
+
]);
|
|
68
|
+
return threadWrite && turnWrite;
|
|
69
|
+
}
|
|
70
|
+
export async function readAdmissionPair(root, expectedThreadHash, expectedSessionHash, expectedTurnHash) {
|
|
71
|
+
const turnFile = turnGuardPath(root.root, expectedSessionHash, expectedTurnHash);
|
|
72
|
+
const turnAdmission = await readAdmission(turnFile, root.boundary);
|
|
73
|
+
if (expectedThreadHash) {
|
|
74
|
+
const threadFile = threadGuardPath(root.root, expectedThreadHash);
|
|
75
|
+
const threadAdmission = await readAdmission(threadFile, root.boundary);
|
|
76
|
+
if (!turnAdmission && !threadAdmission)
|
|
77
|
+
return null;
|
|
78
|
+
if (!turnAdmission || !threadAdmission)
|
|
79
|
+
throw invalidGuard(true);
|
|
80
|
+
validateAdmissionBinding(turnAdmission, expectedThreadHash, expectedSessionHash, expectedTurnHash);
|
|
81
|
+
validateAdmissionBinding(threadAdmission, expectedThreadHash, expectedSessionHash, expectedTurnHash);
|
|
82
|
+
if (admissionFingerprint(turnAdmission) !== admissionFingerprint(threadAdmission)) {
|
|
83
|
+
throw invalidGuard(true);
|
|
84
|
+
}
|
|
85
|
+
return turnAdmission;
|
|
86
|
+
}
|
|
87
|
+
if (!turnAdmission)
|
|
88
|
+
return null;
|
|
89
|
+
validateAdmissionBinding(turnAdmission, turnAdmission.thread_id_hash, expectedSessionHash, expectedTurnHash);
|
|
90
|
+
let threadAdmission;
|
|
91
|
+
try {
|
|
92
|
+
threadAdmission = await readAdmission(threadGuardPath(root.root, turnAdmission.thread_id_hash), root.boundary);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
throw invalidGuard(true);
|
|
96
|
+
}
|
|
97
|
+
if (!threadAdmission || admissionFingerprint(turnAdmission) !== admissionFingerprint(threadAdmission)) {
|
|
98
|
+
throw invalidGuard(true);
|
|
99
|
+
}
|
|
100
|
+
return turnAdmission;
|
|
101
|
+
}
|
|
102
|
+
async function readAdmission(file, boundary) {
|
|
103
|
+
const result = await readBoundedConfinedJson(boundary, file, MAX_LIFECYCLE_GUARD_BYTES);
|
|
104
|
+
if (result.status === 'missing')
|
|
105
|
+
return null;
|
|
106
|
+
if (result.status === 'invalid')
|
|
107
|
+
throw invalidGuard(result.childEvidence);
|
|
108
|
+
if (!validAdmission(result.value))
|
|
109
|
+
throw invalidGuard(true);
|
|
110
|
+
return result.value;
|
|
111
|
+
}
|
|
112
|
+
export async function blockedRunAdmissions(guardRoot, missionId, workflowRunId) {
|
|
113
|
+
let inspected;
|
|
114
|
+
try {
|
|
115
|
+
inspected = await inspectConfinedPath(guardRoot.boundary, guardRoot.root);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return ['subagent_skill_availability_guard_invalid'];
|
|
119
|
+
}
|
|
120
|
+
if (!inspected.exists)
|
|
121
|
+
return [];
|
|
122
|
+
if (inspected.leafSymlink || !inspected.stat?.isDirectory()) {
|
|
123
|
+
return ['subagent_skill_availability_guard_invalid'];
|
|
124
|
+
}
|
|
125
|
+
const names = await boundedDirectoryNames(guardRoot.root);
|
|
126
|
+
if (names === null)
|
|
127
|
+
return ['subagent_skill_availability_guard_invalid'];
|
|
128
|
+
const blockers = [];
|
|
129
|
+
for (const name of names.filter((item) => /^thread-[a-f0-9]{64}\.json$/.test(item)).sort()) {
|
|
130
|
+
let admission;
|
|
131
|
+
try {
|
|
132
|
+
admission = await readAdmission(path.join(guardRoot.root, name), guardRoot.boundary);
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
blockers.push('subagent_skill_availability_guard_invalid');
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (!admission
|
|
139
|
+
|| admission.mission_id !== missionId
|
|
140
|
+
|| admission.workflow_run_id !== workflowRunId
|
|
141
|
+
|| admission.status !== 'blocked')
|
|
142
|
+
continue;
|
|
143
|
+
blockers.push(...admission.blockers);
|
|
144
|
+
}
|
|
145
|
+
return blockers;
|
|
146
|
+
}
|
|
147
|
+
function validateAdmissionBinding(admission, expectedThreadHash, expectedSessionHash, expectedTurnHash) {
|
|
148
|
+
if (admission.thread_id_hash !== expectedThreadHash
|
|
149
|
+
|| admission.session_scope_hash !== expectedSessionHash
|
|
150
|
+
|| admission.turn_id_hash !== expectedTurnHash) {
|
|
151
|
+
throw invalidGuard(true);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
export function invalidGuard(childEvidence) {
|
|
155
|
+
return new SubagentSkillAvailabilityGuardError(childEvidence);
|
|
156
|
+
}
|
|
157
|
+
export function admissionFingerprint(admission) {
|
|
158
|
+
return sha256(JSON.stringify([
|
|
159
|
+
admission.schema,
|
|
160
|
+
admission.status,
|
|
161
|
+
admission.mission_id,
|
|
162
|
+
admission.workflow_run_id,
|
|
163
|
+
admission.thread_id_hash,
|
|
164
|
+
admission.session_scope_hash,
|
|
165
|
+
admission.turn_id_hash,
|
|
166
|
+
admission.blockers,
|
|
167
|
+
admission.recorded_at
|
|
168
|
+
]));
|
|
169
|
+
}
|
|
170
|
+
export async function safeWriteJson(file, boundary, value) {
|
|
171
|
+
try {
|
|
172
|
+
if (Buffer.byteLength(`${JSON.stringify(value, null, 2)}\n`, 'utf8') > MAX_LIFECYCLE_GUARD_BYTES) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
await ensureConfinedDirectory(boundary, path.dirname(file));
|
|
176
|
+
const before = await inspectConfinedPath(boundary, file);
|
|
177
|
+
if (before.exists && (before.leafSymlink || !before.stat?.isFile()))
|
|
178
|
+
return false;
|
|
179
|
+
await writeJsonAtomic(file, value);
|
|
180
|
+
const after = await inspectConfinedPath(boundary, file);
|
|
181
|
+
return after.exists && !after.leafSymlink && Boolean(after.stat?.isFile());
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
export async function safeRemoveGuard(file, boundary) {
|
|
188
|
+
try {
|
|
189
|
+
const inspected = await inspectConfinedPath(boundary, file);
|
|
190
|
+
if (!inspected.exists)
|
|
191
|
+
return;
|
|
192
|
+
if (inspected.leafSymlink || !inspected.stat?.isFile())
|
|
193
|
+
return;
|
|
194
|
+
await removeManagedPathVerified(boundary, file);
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
export async function boundedDirectoryNames(directory) {
|
|
201
|
+
let handle;
|
|
202
|
+
try {
|
|
203
|
+
handle = await fsp.opendir(directory);
|
|
204
|
+
const names = [];
|
|
205
|
+
for await (const entry of handle) {
|
|
206
|
+
names.push(entry.name);
|
|
207
|
+
if (names.length > MAX_LIFECYCLE_GUARD_ENTRIES)
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
return names.sort((left, right) => left.localeCompare(right));
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
finally {
|
|
216
|
+
await handle?.close().catch(() => undefined);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
export async function readBoundedConfinedJson(boundary, file, maxBytes) {
|
|
220
|
+
const absoluteBoundary = path.resolve(boundary);
|
|
221
|
+
const absoluteFile = path.resolve(file);
|
|
222
|
+
let childEvidence = false;
|
|
223
|
+
try {
|
|
224
|
+
const inspected = await inspectConfinedPath(absoluteBoundary, absoluteFile);
|
|
225
|
+
if (!inspected.exists)
|
|
226
|
+
return { status: 'missing' };
|
|
227
|
+
childEvidence = true;
|
|
228
|
+
if (inspected.leafSymlink || !inspected.stat?.isFile() || inspected.stat.size > maxBytes) {
|
|
229
|
+
return { status: 'invalid', childEvidence };
|
|
230
|
+
}
|
|
231
|
+
const handle = await fsp.open(absoluteFile, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
|
|
232
|
+
try {
|
|
233
|
+
const stat = await handle.stat();
|
|
234
|
+
if (!stat.isFile() || stat.size > maxBytes)
|
|
235
|
+
return { status: 'invalid', childEvidence };
|
|
236
|
+
const buffer = Buffer.alloc(maxBytes + 1);
|
|
237
|
+
const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
|
|
238
|
+
if (bytesRead > maxBytes || bytesRead !== stat.size) {
|
|
239
|
+
return { status: 'invalid', childEvidence };
|
|
240
|
+
}
|
|
241
|
+
return { status: 'value', value: JSON.parse(buffer.subarray(0, bytesRead).toString('utf8')) };
|
|
242
|
+
}
|
|
243
|
+
finally {
|
|
244
|
+
await handle.close().catch(() => undefined);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
return { status: 'invalid', childEvidence };
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
export function preToolBlockReason(blockers) {
|
|
252
|
+
return `SKS blocked this child tool call because managed skill availability failed (${blockers.join(', ')}). Return the blocker to the root parent without using tools.`;
|
|
253
|
+
}
|
|
254
|
+
export function boundedAgentThreadId(value) {
|
|
255
|
+
if (typeof value !== 'string')
|
|
256
|
+
return null;
|
|
257
|
+
const candidate = value.trim();
|
|
258
|
+
if (!candidate
|
|
259
|
+
|| Buffer.byteLength(candidate, 'utf8') > 512
|
|
260
|
+
|| /[\u0000-\u001f\u007f]/.test(candidate))
|
|
261
|
+
return null;
|
|
262
|
+
return candidate;
|
|
263
|
+
}
|
|
264
|
+
export async function officialSubagentThreadIdFromTranscript(value) {
|
|
265
|
+
const file = String(value || '').trim();
|
|
266
|
+
if (!file)
|
|
267
|
+
return null;
|
|
268
|
+
const sessionsRoot = path.resolve(process.env.CODEX_HOME
|
|
269
|
+
? path.join(process.env.CODEX_HOME, 'sessions')
|
|
270
|
+
: path.join(process.env.HOME || os.homedir(), '.codex', 'sessions'));
|
|
271
|
+
const [sessionsReal, fileReal] = await Promise.all([
|
|
272
|
+
fsp.realpath(sessionsRoot).catch(() => null),
|
|
273
|
+
fsp.realpath(file).catch(() => null)
|
|
274
|
+
]);
|
|
275
|
+
if (!sessionsReal || !fileReal || !pathIsInside(sessionsReal, fileReal))
|
|
276
|
+
return null;
|
|
277
|
+
const stat = await fsp.lstat(file).catch(() => null);
|
|
278
|
+
if (!stat || stat.isSymbolicLink() || !stat.isFile())
|
|
279
|
+
return null;
|
|
280
|
+
const handle = await fsp.open(file, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW).catch(() => null);
|
|
281
|
+
if (!handle)
|
|
282
|
+
return null;
|
|
283
|
+
try {
|
|
284
|
+
const statAfterOpen = await handle.stat();
|
|
285
|
+
if (!statAfterOpen.isFile() || statAfterOpen.size > 1024 * 1024)
|
|
286
|
+
return null;
|
|
287
|
+
const buffer = Buffer.alloc(1024 * 1024);
|
|
288
|
+
const read = await handle.read(buffer, 0, buffer.length, 0);
|
|
289
|
+
if (read.bytesRead < 1)
|
|
290
|
+
return null;
|
|
291
|
+
const text = buffer.subarray(0, read.bytesRead).toString('utf8');
|
|
292
|
+
const line = text.split(/\r?\n/, 1)[0]?.trim();
|
|
293
|
+
if (!line)
|
|
294
|
+
return null;
|
|
295
|
+
const row = JSON.parse(line);
|
|
296
|
+
const source = row?.payload?.source?.subagent;
|
|
297
|
+
const threadSpawn = source?.thread_spawn;
|
|
298
|
+
if (row?.type !== 'session_meta' || !source || typeof source !== 'object'
|
|
299
|
+
|| !threadSpawn || typeof threadSpawn !== 'object')
|
|
300
|
+
return null;
|
|
301
|
+
return String(row?.payload?.id || row?.payload?.session_id || '').trim() || null;
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
finally {
|
|
307
|
+
await handle.close().catch(() => undefined);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function pathIsInside(root, candidate) {
|
|
311
|
+
const relative = path.relative(root, candidate);
|
|
312
|
+
return Boolean(relative)
|
|
313
|
+
&& relative !== '..'
|
|
314
|
+
&& !relative.startsWith(`..${path.sep}`)
|
|
315
|
+
&& !path.isAbsolute(relative);
|
|
316
|
+
}
|