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,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { projectRoot, readJson,
|
|
2
|
+
import { projectRoot, readJson, writeJsonAtomic, appendJsonl, nowIso, runProcess, sha256, packageRoot, tmpdir } from './fsx.js';
|
|
3
3
|
import { looksInteractiveCommand, interactiveCommandReason } from './no-question-guard.js';
|
|
4
|
-
import { loadStateForSession, missionDir, setCurrent,
|
|
4
|
+
import { loadStateForSession, missionDir, sessionStateKey, setCurrent, stateFileForSession } from './mission.js';
|
|
5
5
|
import { checkDbOperation, dbBlockReason, handleMadSksUserConfirmation } from './db-safety.js';
|
|
6
6
|
import { maybeRecordMadSksSqlPlaneToolResultFromToolUse } from './mad-sks/sql-plane/result-lifecycle.js';
|
|
7
7
|
import { checkHarnessModification, harnessGuardBlockReason, isHarnessSourceProject } from './harness-guard.js';
|
|
@@ -10,46 +10,45 @@ import { classifyMadSksShellCommand } from './mad-sks/write-guard.js';
|
|
|
10
10
|
import { activeRouteContext, evaluateStop, prepareRoute, promptPipelineContext as routePipelineContext, recordContext7Evidence, recordSubagentEvidence, routePrompt } from './pipeline.js';
|
|
11
11
|
import { localizedFinalizationReason } from './language-preference.js';
|
|
12
12
|
import { classifyToolError } from './evaluation.js';
|
|
13
|
-
import { dollarCommand,
|
|
13
|
+
import { dollarCommand, managedSkillNamesForPrompt, stripVisibleDecisionAnswerBlocks } from './routes.js';
|
|
14
14
|
import { coreEngineeringDirectiveReferenceText } from './lean-engineering-policy.js';
|
|
15
15
|
import { scanAgentTextForRecursion } from './agents/agent-recursion-guard.js';
|
|
16
16
|
import { evaluateLoopContinuation } from './loops/loop-continuation-enforcer.js';
|
|
17
17
|
import { diagnosticPromptAllowedDuringNoQuestions } from './routes/diagnostic-allowlist.js';
|
|
18
|
-
import { closeWorkOrderLedgerForRouteResult } from './work-order-ledger.js';
|
|
19
|
-
import { maybeFinalizeRoute } from './proof/auto-finalize.js';
|
|
20
|
-
import { validateRouteCompletionProof } from './proof/route-proof-gate.js';
|
|
21
18
|
import { maybeReconcileProjectSkillsPreflight } from './hooks-runtime/skill-reconcile-preflight.js';
|
|
22
19
|
import { codePackFreshnessNote } from './hooks-runtime/code-pack-freshness-preflight.js';
|
|
23
20
|
import { claimHookInvocation } from './hooks-runtime/hook-invocation-dedupe.js';
|
|
24
21
|
import { armLightTurnStopBypass, clearLightTurnStopBypass, consumeLightTurnStopBypass, hasMatchingLightTurnStopBypass } from './hooks-runtime/light-turn.js';
|
|
25
22
|
import { evaluateHookNarutoDecisionGate, looksLikeActiveContinuationPrompt } from './hooks-runtime/naruto-decision-gate.js';
|
|
23
|
+
import { ensureOfficialSubagentArtifactDirConfined, officialSubagentArtifactDir, recordAndRefreshSubagentEvidence, refreshOfficialSubagentCompletionArtifacts } from './hooks-runtime/official-subagent-lifecycle.js';
|
|
26
24
|
import { finalizationRepeatDecision } from './hooks-runtime/stop-repeat-guard.js';
|
|
25
|
+
import { activeNarutoParentLaunchMissionId, claimStandaloneParentHostCapabilityRuntime } from './hooks-runtime/standalone-parent-host-capability.js';
|
|
27
26
|
import { classifyTaskProfile } from './runtime/task-profile.js';
|
|
28
27
|
import { resolveSubagentThreadBudget } from './subagents/thread-budget.js';
|
|
29
28
|
import { readOfficialSubagentConfig } from './subagents/official-subagent-config.js';
|
|
30
29
|
import { withFileLock } from './locks/file-lock.js';
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import { officialSubagentPreparationInProgress, withOfficialSubagentLifecycleLock, writeNarutoGate } from './subagents/official-subagent-preparation.js';
|
|
36
|
-
import { effectiveSubagentTarget, normalizeLegacySubagentCountFields, refreshSubagentWaveLifecycle, subagentCountContractBlockers } from './subagents/wave-lifecycle.js';
|
|
37
|
-
import { buildWaveParentGuidance, renderWaveParentGuidance } from './subagents/wave-parent-guidance.js';
|
|
38
|
-
import { managedOfficialSubagentRoleByName } from './managed-assets/managed-assets-manifest.js';
|
|
39
|
-
import { SSOT_GUARD_ARTIFACT, validateSsotGuardArtifact } from './safety/ssot-guard.js';
|
|
30
|
+
import { buildBoundWaveParentGuidance, renderWaveParentGuidance } from './subagents/wave-parent-guidance.js';
|
|
31
|
+
import { renderAuthoritativeSksSkillContext, resolveAuthoritativeSksSkillSources } from './codex-native/sks-skill-paths.js';
|
|
32
|
+
import { authoritativeSksSkillResolutionBlockers, clearSubagentSkillAvailabilityGuards, persistSubagentSkillAvailabilityBlocker, renderSubagentSkillAvailabilityHandoff, subagentSkillAvailabilityPreToolBlockReason } from './hooks-runtime/subagent-skill-availability.js';
|
|
33
|
+
import { HOST_CAPABILITY_HOOK_EVIDENCE_FILENAME, HOST_CAPABILITY_HOOK_OBSERVATIONS_FILENAME, HOST_CAPABILITY_HOOK_RUNTIME_FILENAME, acasHostToolName, authorizeAndMergeHostCapabilityPreToolObservation, buildHostCapabilityEvidenceFromHookObservations, explicitlyDeniedHostCapabilityTool, mergeHostCapabilityPostToolObservation, requestHostCapabilities, resolveHostCapabilityHookRuntimeBinding, sanitizeHostCapabilityPostToolUse, sanitizeHostCapabilityPreToolUse } from './agent-bridge/host-capability-runtime.js';
|
|
40
34
|
const LIGHT_ROUTE_STOP_ARTIFACT = 'light-route-stop.json';
|
|
41
35
|
const CODEX_GIT_ACTION_STOP_ARTIFACT = 'codex-git-action-stop-bypass.json';
|
|
42
36
|
const CODEX_GIT_ACTION_STOP_TTL_MS = 15 * 60 * 1000;
|
|
43
37
|
const UPDATE_CHECK_HOOK_INVOCATION_POLICY = 'function-only:no-runSksUpdateCheck-call-in-hooks';
|
|
44
|
-
// Update checks stay function-only in hooks: the policy marker above is checked
|
|
45
|
-
// by release readiness so ordinary Codex hook flow cannot grow a hidden update
|
|
46
|
-
// prompt path.
|
|
47
38
|
import { loadHookPayload, normalizeHookResult, visibleHookMessage } from './hooks-runtime/hook-io.js';
|
|
48
|
-
import { codexGitActionMetadataSignal, codexGitActionMetadataText, compactAnswerContext, conversationId, explicitConversationId, extractCommand, extractLastMessage, extractUserPrompt, hookTurnId, looksLikeCodexGitAction, looksLikeCodexGitActionStopCompletion, looksLikeCodexUiSettingsEvent, looksLikeMadSksConfirmationPrompt, observedParentModel,
|
|
39
|
+
import { codexGitActionMetadataSignal, codexGitActionMetadataText, compactAnswerContext, conversationId, explicitConversationId, extractCommand, extractLastMessage, extractUserPrompt, hookTurnId, looksLikeCodexGitAction, looksLikeCodexGitActionStopCompletion, looksLikeCodexUiSettingsEvent, looksLikeMadSksConfirmationPrompt, observedParentModel, toolFailed } from './hooks-runtime/payload-signals.js';
|
|
49
40
|
import { interruptedToolOutputRecoveryBlockReason, missingToolOutputCallId, missingToolOutputCallIdFromPayload, quarantineMissingToolOutput, readToolOutputQuarantine } from './hooks-runtime/tool-output-quarantine.js';
|
|
41
|
+
import { activeAuthoritativeSksSkillRefresh, activeGoalOverlayContext, attachAuthoritativeSksSkillContext, authoritativeSksSkillAdmission, hookActiveSkillContextRefresh, isBlockingClarificationAwaiting, looksLikeClarificationCancel, routeBypassesActiveContext, routeIsGitOnly, selectedSksSkillNamesForActiveState, shouldPrepareFreshRouteOnActivePrompt, standaloneParentManagedSkillNames } from './hooks-runtime/hook-context.js';
|
|
42
|
+
import { sealedSubagentRoutingContext, subagentRouteContext } from './hooks-runtime/subagent-context.js';
|
|
50
43
|
export { loadHookPayload, normalizeHookResult };
|
|
44
|
+
export { refreshOfficialSubagentCompletionArtifacts };
|
|
51
45
|
async function loadState(root, payload = {}) {
|
|
52
|
-
|
|
46
|
+
const sessionKey = conversationId(payload);
|
|
47
|
+
if (!explicitConversationId(payload))
|
|
48
|
+
return loadStateForSession(root, sessionKey);
|
|
49
|
+
const hashed = sessionStateKey(sessionKey);
|
|
50
|
+
const sessionState = await readJson(stateFileForSession(root, sessionKey), null).catch(() => null);
|
|
51
|
+
return sessionState ? { ...sessionState, _session_key: sessionState._session_key || hashed } : {};
|
|
53
52
|
}
|
|
54
53
|
function isNoQuestionRunning(state) {
|
|
55
54
|
return (state.mode === 'RESEARCH' && state.phase === 'RESEARCH_RUNNING_NO_QUESTIONS')
|
|
@@ -96,10 +95,6 @@ export async function evaluateHookPayload(name, payload = {}, opts = {}) {
|
|
|
96
95
|
hook: name
|
|
97
96
|
}).catch(() => null);
|
|
98
97
|
}
|
|
99
|
-
// Hook decisions use persisted session state. Codex hook payloads do not
|
|
100
|
-
// define a trusted `state` field; accepting a partial/spoofed value can hide
|
|
101
|
-
// an active mission or bypass route gates. Explicit opts.state remains for
|
|
102
|
-
// internal replay and focused tests.
|
|
103
98
|
const loadedState = opts.state || await loadState(root, payload);
|
|
104
99
|
const state = { ...loadedState, _session_key: loadedState?._session_key || sessionKey };
|
|
105
100
|
const noQuestion = isNoQuestionRunning(state);
|
|
@@ -114,7 +109,11 @@ export async function evaluateHookPayload(name, payload = {}, opts = {}) {
|
|
|
114
109
|
});
|
|
115
110
|
const withNarutoDecision = (result) => ({ ...result, sksNarutoDecision });
|
|
116
111
|
if (name === 'user-prompt-submit') {
|
|
117
|
-
|
|
112
|
+
const result = await hookUserPrompt(root, state, payload, noQuestion, sessionKey);
|
|
113
|
+
return withNarutoDecision(await attachAuthoritativeSksSkillContext(root, state, payload, result));
|
|
114
|
+
}
|
|
115
|
+
if (name === 'session-start' || name === 'pre-compact' || name === 'post-compact') {
|
|
116
|
+
return withNarutoDecision(await hookActiveSkillContextRefresh(root, state, name));
|
|
118
117
|
}
|
|
119
118
|
if (name === 'pre-tool')
|
|
120
119
|
return withNarutoDecision(await hookPreTool(root, state, payload, noQuestion, sessionKey));
|
|
@@ -132,11 +131,18 @@ export async function evaluateHookPayload(name, payload = {}, opts = {}) {
|
|
|
132
131
|
}
|
|
133
132
|
async function hookSubagentStart(root, state, payload = {}, sessionKey = null) {
|
|
134
133
|
const artifactDir = officialSubagentArtifactDir(root, state, sessionKey);
|
|
135
|
-
|
|
134
|
+
const sessionArtifactDir = officialSubagentArtifactDir(root, {}, sessionKey);
|
|
135
|
+
const artifactDirBlockers = [];
|
|
136
|
+
const artifactDirSafe = await ensureOfficialSubagentArtifactDirConfined(root, artifactDir)
|
|
137
|
+
.then(() => true)
|
|
138
|
+
.catch(() => false);
|
|
139
|
+
if (!artifactDirSafe)
|
|
140
|
+
artifactDirBlockers.push('subagent_skill_availability_artifact_dir_unsafe');
|
|
141
|
+
await clearSubagentSkillAvailabilityGuards(root, payload, artifactDir).catch(() => null);
|
|
136
142
|
const config = await readOfficialSubagentConfig(root);
|
|
137
143
|
const budget = resolveSubagentThreadBudget({ configuredMaxThreads: config.maxThreads });
|
|
138
144
|
const active = subagentRouteContext(state);
|
|
139
|
-
const routingContext = await sealedSubagentRoutingContext(artifactDir, payload);
|
|
145
|
+
const routingContext = artifactDirSafe ? await sealedSubagentRoutingContext(artifactDir, payload) : '';
|
|
140
146
|
const resourceGuard = [
|
|
141
147
|
`SKS subagent policy: Codex [agents].max_threads is ${budget.maxThreads}.`,
|
|
142
148
|
'Use max_depth=1. Subagents must not spawn subagents.',
|
|
@@ -144,180 +150,48 @@ async function hookSubagentStart(root, state, payload = {}, sessionKey = null) {
|
|
|
144
150
|
'Parallel writes require disjoint paths; serialize overlapping paths.',
|
|
145
151
|
'Finish only your assigned slice, return a concise result, then stop so the root parent can close this thread.'
|
|
146
152
|
].join(' ');
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const agentName = extractSubagentAgentName(payload);
|
|
155
|
-
const agents = plan.agents && typeof plan.agents === 'object' ? plan.agents : {};
|
|
156
|
-
const planned = agentName && agents[agentName] ? agents[agentName] : null;
|
|
157
|
-
const role = agentName ? managedOfficialSubagentRoleByName(agentName) : null;
|
|
158
|
-
const model = String(planned?.routed_model || planned?.model || role?.model || '').trim();
|
|
159
|
-
const effort = String(planned?.routed_model_reasoning_effort || planned?.model_reasoning_effort || role?.model_reasoning_effort || '').trim();
|
|
160
|
-
if (!agentName && !model)
|
|
161
|
-
return '';
|
|
162
|
-
return [
|
|
163
|
-
'SKS sealed child routing:',
|
|
164
|
-
agentName ? `- custom agent: ${agentName}` : null,
|
|
165
|
-
model ? `- model: ${model}` : null,
|
|
166
|
-
effort ? `- model_reasoning_effort: ${effort}` : null,
|
|
167
|
-
'- keep this sealed profile; do not retarget model/effort or spawn nested agents'
|
|
168
|
-
].filter(Boolean).join('\n');
|
|
169
|
-
}
|
|
170
|
-
function extractSubagentAgentName(payload = {}) {
|
|
171
|
-
const candidates = [
|
|
172
|
-
payload.agent_type,
|
|
173
|
-
payload.agentType,
|
|
174
|
-
payload.subagent_type,
|
|
175
|
-
payload.subagentType,
|
|
176
|
-
payload.agent_name,
|
|
177
|
-
payload.agentName,
|
|
178
|
-
payload.agent,
|
|
179
|
-
payload.role,
|
|
180
|
-
payload.payload?.agent_type,
|
|
181
|
-
payload.payload?.agentType,
|
|
182
|
-
payload.payload?.subagent_type,
|
|
183
|
-
payload.data?.agent_type,
|
|
184
|
-
payload.input?.agent_type
|
|
153
|
+
const skillNames = selectedSksSkillNamesForActiveState(state);
|
|
154
|
+
const resolution = skillNames.length
|
|
155
|
+
? await resolveAuthoritativeSksSkillSources({ root, skillNames }).catch(() => null)
|
|
156
|
+
: null;
|
|
157
|
+
const skillBlockers = [
|
|
158
|
+
...artifactDirBlockers,
|
|
159
|
+
...(skillNames.length ? authoritativeSksSkillResolutionBlockers(resolution) : [])
|
|
185
160
|
];
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
161
|
+
try {
|
|
162
|
+
await persistSubagentSkillAvailabilityBlocker({
|
|
163
|
+
root,
|
|
164
|
+
artifactDir,
|
|
165
|
+
sessionArtifactDir,
|
|
166
|
+
state,
|
|
167
|
+
payload,
|
|
168
|
+
blockers: skillBlockers
|
|
169
|
+
});
|
|
190
170
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const
|
|
202
|
-
?
|
|
203
|
-
:
|
|
204
|
-
|
|
171
|
+
catch (error) {
|
|
172
|
+
const blocker = error instanceof Error
|
|
173
|
+
&& error.message === 'subagent_skill_availability_blocker_artifact_write_failed'
|
|
174
|
+
? 'subagent_skill_availability_blocker_artifact_write_failed'
|
|
175
|
+
: 'subagent_skill_availability_guard_persistence_failed';
|
|
176
|
+
skillBlockers.push(blocker);
|
|
177
|
+
}
|
|
178
|
+
if (artifactDirSafe) {
|
|
179
|
+
await recordAndRefreshSubagentEvidence(root, state, payload, 'SubagentStart', sessionKey).catch(() => null);
|
|
180
|
+
}
|
|
181
|
+
const skillContext = skillBlockers.length
|
|
182
|
+
? renderSubagentSkillAvailabilityHandoff(skillBlockers)
|
|
183
|
+
: resolution
|
|
184
|
+
? renderAuthoritativeSksSkillContext(resolution)
|
|
185
|
+
: '';
|
|
186
|
+
const additionalContext = [coreEngineeringDirectiveReferenceText(), resourceGuard, routingContext, active, skillContext].filter(Boolean).join('\n\n');
|
|
187
|
+
return { continue: true, additionalContext, ...(skillBlockers.length ? { silent: true } : {}) };
|
|
205
188
|
}
|
|
206
189
|
async function hookSubagentStop(root, state, payload = {}, sessionKey = null) {
|
|
207
|
-
|
|
208
|
-
await
|
|
209
|
-
// SubagentStop is evidence collection only. It must never reuse the parent
|
|
210
|
-
// Stop hook's route gate or block a child thread from returning its result.
|
|
190
|
+
await recordAndRefreshSubagentEvidence(root, state, payload, 'SubagentStop', sessionKey).catch(() => null);
|
|
191
|
+
await clearSubagentSkillAvailabilityGuards(root, payload, officialSubagentArtifactDir(root, state, sessionKey)).catch(() => null);
|
|
211
192
|
return { continue: true, silent: true };
|
|
212
193
|
}
|
|
213
|
-
function officialSubagentArtifactDir(root, state = {}, sessionKey = null) {
|
|
214
|
-
if (state?.mission_id)
|
|
215
|
-
return missionDir(root, state.mission_id);
|
|
216
|
-
return path.join(root, '.sneakoscope', 'state', 'subagents', sha256(String(sessionKey || 'default')).slice(0, 32));
|
|
217
|
-
}
|
|
218
|
-
async function recordAndRefreshSubagentEvidence(root, artifactDir, state, payload, eventName) {
|
|
219
|
-
return withOfficialSubagentLifecycleLock(artifactDir, async () => {
|
|
220
|
-
if (await officialSubagentPreparationInProgress(artifactDir))
|
|
221
|
-
return null;
|
|
222
|
-
const plan = await readJson(path.join(artifactDir, 'subagent-plan.json'), {});
|
|
223
|
-
const workflowRunId = String(plan?.workflow_run_id || state?.official_subagent_run_id || '').trim();
|
|
224
|
-
const stateRunId = String(state?.official_subagent_run_id || '').trim();
|
|
225
|
-
if (!workflowRunId || (stateRunId && stateRunId !== workflowRunId))
|
|
226
|
-
return null;
|
|
227
|
-
const terminalGate = plan?.workflow === 'official_codex_subagent'
|
|
228
|
-
? await readJson(path.join(artifactDir, 'naruto-gate.json'), null).catch(() => null)
|
|
229
|
-
: null;
|
|
230
|
-
const terminalRunId = String(terminalGate?.workflow_run_id || '').trim();
|
|
231
|
-
if (workflowRunId
|
|
232
|
-
&& terminalRunId === workflowRunId
|
|
233
|
-
&& terminalGate?.passed === true
|
|
234
|
-
&& terminalGate?.terminal === true) {
|
|
235
|
-
return null;
|
|
236
|
-
}
|
|
237
|
-
const normalizedInputEvent = normalizeSubagentEvent(payload, eventName);
|
|
238
|
-
const explicitRunId = normalizedInputEvent?.run_id || null;
|
|
239
|
-
if (explicitRunId && explicitRunId !== workflowRunId)
|
|
240
|
-
return null;
|
|
241
|
-
let boundRunId = explicitRunId;
|
|
242
|
-
if (!boundRunId && eventName === 'SubagentStop' && normalizedInputEvent?.thread_id) {
|
|
243
|
-
const priorEvents = await readSubagentEvents(artifactDir);
|
|
244
|
-
const matchingStartRuns = [...new Set(priorEvents
|
|
245
|
-
.filter((row) => row.event_name === 'SubagentStart'
|
|
246
|
-
&& row.thread_id === normalizedInputEvent.thread_id
|
|
247
|
-
&& Boolean(row.run_id))
|
|
248
|
-
.map((row) => row.run_id))];
|
|
249
|
-
boundRunId = matchingStartRuns.length === 1
|
|
250
|
-
? matchingStartRuns[0] || null
|
|
251
|
-
: null;
|
|
252
|
-
if (!boundRunId)
|
|
253
|
-
return null;
|
|
254
|
-
}
|
|
255
|
-
else if (!boundRunId) {
|
|
256
|
-
boundRunId = workflowRunId || null;
|
|
257
|
-
}
|
|
258
|
-
const eventPayload = boundRunId && payload && typeof payload === 'object' && !Array.isArray(payload)
|
|
259
|
-
? { ...payload, workflow_run_id: boundRunId }
|
|
260
|
-
: payload;
|
|
261
|
-
const event = await recordSubagentEvent(artifactDir, eventPayload, eventName);
|
|
262
|
-
if (!event)
|
|
263
|
-
return null;
|
|
264
|
-
const zellijTelemetry = await recordOfficialSubagentZellijTelemetry({
|
|
265
|
-
root,
|
|
266
|
-
routeMissionId: plan?.mission_id || state?.mission_id || null,
|
|
267
|
-
event,
|
|
268
|
-
payload: eventPayload,
|
|
269
|
-
plan
|
|
270
|
-
}).catch(async (error) => {
|
|
271
|
-
await appendJsonl(path.join(artifactDir, 'zellij-telemetry-warnings.jsonl'), {
|
|
272
|
-
ts: nowIso(),
|
|
273
|
-
warning: 'official_subagent_zellij_telemetry_failed',
|
|
274
|
-
event_name: eventName,
|
|
275
|
-
thread_id: event.thread_id,
|
|
276
|
-
error: String(error?.message || error)
|
|
277
|
-
}).catch(() => null);
|
|
278
|
-
return null;
|
|
279
|
-
});
|
|
280
|
-
if (zellijTelemetry?.blocker) {
|
|
281
|
-
await appendJsonl(path.join(artifactDir, 'zellij-telemetry-warnings.jsonl'), {
|
|
282
|
-
ts: nowIso(),
|
|
283
|
-
warning: 'official_subagent_zellij_telemetry_incomplete',
|
|
284
|
-
event_name: eventName,
|
|
285
|
-
thread_id: event.thread_id,
|
|
286
|
-
blocker: zellijTelemetry.blocker,
|
|
287
|
-
failed_mission_ids: 'failed_mission_ids' in zellijTelemetry ? zellijTelemetry.failed_mission_ids : []
|
|
288
|
-
}).catch(() => null);
|
|
289
|
-
}
|
|
290
|
-
const lifecycle = await refreshSubagentWaveLifecycle(artifactDir, { plan, event }).catch(() => null);
|
|
291
|
-
const refreshedPlan = lifecycle ? { ...plan, wave_lifecycle: lifecycle } : plan;
|
|
292
|
-
const existing = await readJson(path.join(artifactDir, SUBAGENT_EVIDENCE_FILENAME), {});
|
|
293
|
-
const parentSummary = await readJson(path.join(artifactDir, SUBAGENT_PARENT_SUMMARY_FILENAME), null);
|
|
294
|
-
const countTarget = effectiveSubagentTarget(refreshedPlan, lifecycle?.cumulative_started || 0);
|
|
295
|
-
const requestedSubagents = countTarget.requestedSubagents
|
|
296
|
-
|| Number(state?.requested_subagents || existing?.requested_subagents || 0);
|
|
297
|
-
if (!Number.isFinite(requestedSubagents) || requestedSubagents < 1)
|
|
298
|
-
return event;
|
|
299
|
-
const evidence = await writeSubagentEvidence(artifactDir, {
|
|
300
|
-
requestedSubagents,
|
|
301
|
-
countPolicy: countTarget.countPolicy,
|
|
302
|
-
targetSubagents: countTarget.targetSubagents,
|
|
303
|
-
parentSummary,
|
|
304
|
-
parentSummaryPresent: parentSummary !== null,
|
|
305
|
-
workflowStatus: 'running',
|
|
306
|
-
preparationOnly: false,
|
|
307
|
-
runId: workflowRunId || null,
|
|
308
|
-
additionalBlockers: Array.isArray(plan?.config_blockers)
|
|
309
|
-
? [
|
|
310
|
-
...plan.config_blockers.map((item) => `official_subagent_config:${String(item)}`),
|
|
311
|
-
...subagentCountContractBlockers(refreshedPlan, lifecycle?.cumulative_started || 0)
|
|
312
|
-
]
|
|
313
|
-
: subagentCountContractBlockers(refreshedPlan, lifecycle?.cumulative_started || 0)
|
|
314
|
-
});
|
|
315
|
-
return event;
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
194
|
async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = null) {
|
|
319
|
-
// A receipt is scoped to exactly one submitted turn. Every later prompt,
|
|
320
|
-
// including Codex App git/settings events, invalidates it before returning.
|
|
321
195
|
await clearLightTurnStopBypass(root, { sessionKey }).catch(() => undefined);
|
|
322
196
|
const submittedPrompt = stripVisibleDecisionAnswerBlocks(extractUserPrompt(payload));
|
|
323
197
|
const explicitSession = explicitConversationId(payload);
|
|
@@ -346,6 +220,23 @@ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = nul
|
|
|
346
220
|
}
|
|
347
221
|
const parentLaunchMissionId = activeNarutoParentLaunchMissionId();
|
|
348
222
|
if (parentLaunchMissionId) {
|
|
223
|
+
const parentSkillNames = await standaloneParentManagedSkillNames(root, parentLaunchMissionId, state);
|
|
224
|
+
const skillAdmission = await authoritativeSksSkillAdmission(root, parentSkillNames);
|
|
225
|
+
if (skillAdmission.blocked)
|
|
226
|
+
return skillAdmission.blocked;
|
|
227
|
+
const parentHostCapability = await claimStandaloneParentHostCapabilityRuntime({
|
|
228
|
+
root,
|
|
229
|
+
missionId: parentLaunchMissionId,
|
|
230
|
+
sessionScope: sessionKey,
|
|
231
|
+
explicitSession
|
|
232
|
+
});
|
|
233
|
+
if (parentHostCapability.blocker) {
|
|
234
|
+
return {
|
|
235
|
+
decision: 'block',
|
|
236
|
+
permissionDecision: 'deny',
|
|
237
|
+
reason: `SKS blocked the standalone Naruto parent before host tool execution: ${parentHostCapability.blocker}`
|
|
238
|
+
};
|
|
239
|
+
}
|
|
349
240
|
const attachedState = {
|
|
350
241
|
...state,
|
|
351
242
|
mission_id: parentLaunchMissionId,
|
|
@@ -353,8 +244,11 @@ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = nul
|
|
|
353
244
|
route: 'Naruto',
|
|
354
245
|
route_command: '$Naruto',
|
|
355
246
|
route_closed: false,
|
|
247
|
+
required_skills: parentSkillNames,
|
|
356
248
|
subagents_required: true,
|
|
357
|
-
native_sessions_required: false
|
|
249
|
+
native_sessions_required: false,
|
|
250
|
+
official_subagent_run_id: parentHostCapability.workflowRunId || state?.official_subagent_run_id || null,
|
|
251
|
+
session_scope: sessionKey
|
|
358
252
|
};
|
|
359
253
|
await setCurrent(root, attachedState, { sessionKey, replace: true });
|
|
360
254
|
const activeContext = await activeRouteContext(root, attachedState);
|
|
@@ -400,6 +294,9 @@ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = nul
|
|
|
400
294
|
return { continue: true, silent: true, sksTaskProfile: taskProfile };
|
|
401
295
|
}
|
|
402
296
|
if (!explicitCommand && !clarificationPending && !madConfirmationPrompt && !activeContinuation && lightRoute?.id === 'Answer') {
|
|
297
|
+
const skillAdmission = await authoritativeSksSkillAdmission(root, lightRoute.requiredSkills || ['answer', 'honest-mode']);
|
|
298
|
+
if (skillAdmission.blocked)
|
|
299
|
+
return skillAdmission.blocked;
|
|
403
300
|
const turnId = hookTurnId(payload);
|
|
404
301
|
if (turnId) {
|
|
405
302
|
await armLightTurnStopBypass(root, {
|
|
@@ -428,7 +325,6 @@ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = nul
|
|
|
428
325
|
systemMessage: visibleHookMessage('user-prompt-submit', activeContext)
|
|
429
326
|
};
|
|
430
327
|
}
|
|
431
|
-
await maybeReconcileProjectSkillsPreflight(root).catch(() => null);
|
|
432
328
|
const updateContext = '';
|
|
433
329
|
const command = dollarCommand(prompt);
|
|
434
330
|
const route = routePrompt(prompt);
|
|
@@ -439,6 +335,10 @@ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = nul
|
|
|
439
335
|
systemMessage: `SKS: ${route.command} git action bypassed pipeline route gates.`
|
|
440
336
|
};
|
|
441
337
|
}
|
|
338
|
+
const skillAdmission = await authoritativeSksSkillAdmission(root, managedSkillNamesForPrompt(route, prompt));
|
|
339
|
+
if (skillAdmission.blocked)
|
|
340
|
+
return skillAdmission.blocked;
|
|
341
|
+
await maybeReconcileProjectSkillsPreflight(root).catch(() => null);
|
|
442
342
|
const bypassActiveRoute = routeBypassesActiveContext(route);
|
|
443
343
|
const goalOverlay = activeGoalOverlayContext(state, route);
|
|
444
344
|
const prepareFreshRoute = shouldPrepareFreshRouteOnActivePrompt(prompt, route, {
|
|
@@ -484,54 +384,28 @@ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = nul
|
|
|
484
384
|
reason: 'SKS no-question/no-interruption mode is active. User prompt has been queued until the run completes.'
|
|
485
385
|
};
|
|
486
386
|
}
|
|
487
|
-
function routeBypassesActiveContext(route = null) {
|
|
488
|
-
return ['DFix', 'Answer', 'Commit', 'CommitAndPush', 'Wiki', 'ComputerUse'].includes(String(route?.id || ''));
|
|
489
|
-
}
|
|
490
|
-
function routeIsGitOnly(route = null) {
|
|
491
|
-
return ['Commit', 'CommitAndPush'].includes(String(route?.id || ''));
|
|
492
|
-
}
|
|
493
|
-
function shouldPrepareFreshRouteOnActivePrompt(prompt, route = null, opts = {}) {
|
|
494
|
-
if (!route || opts.command || opts.bypassActiveRoute || opts.goalOverlay)
|
|
495
|
-
return false;
|
|
496
|
-
if (looksLikeActiveContinuationPrompt(prompt))
|
|
497
|
-
return false;
|
|
498
|
-
return routeRequiresSubagents(route, prompt);
|
|
499
|
-
}
|
|
500
|
-
function isClarificationAwaiting(state = {}) {
|
|
501
|
-
const phase = String(state.phase || '');
|
|
502
|
-
const stopGate = String(state.stop_gate || '');
|
|
503
|
-
const gateAwaiting = phase.includes('CLARIFICATION_AWAITING_ANSWERS') || stopGate === 'clarification-gate';
|
|
504
|
-
if (!gateAwaiting)
|
|
505
|
-
return false;
|
|
506
|
-
if (!state?.mission_id)
|
|
507
|
-
return false;
|
|
508
|
-
if (state.ambiguity_gate_required !== true || state.ambiguity_gate_passed === true)
|
|
509
|
-
return false;
|
|
510
|
-
return Boolean(state.clarification_required || state.implementation_allowed === false);
|
|
511
|
-
}
|
|
512
|
-
function activeNarutoParentLaunchMissionId() {
|
|
513
|
-
return process.env.SKS_NARUTO_PARENT_LAUNCH === '1'
|
|
514
|
-
? String(process.env.SKS_NARUTO_PARENT_MISSION_ID || '').trim()
|
|
515
|
-
: '';
|
|
516
|
-
}
|
|
517
|
-
function isBlockingClarificationAwaiting(state = {}) {
|
|
518
|
-
return isClarificationAwaiting(state);
|
|
519
|
-
}
|
|
520
|
-
function looksLikeClarificationCancel(prompt = '') {
|
|
521
|
-
return /^(cancel|reset|restart|new mission|새로|취소|중단|리셋|다시 시작)\b/i.test(String(prompt || '').trim());
|
|
522
|
-
}
|
|
523
|
-
function activeGoalOverlayContext(state = {}, route = null) {
|
|
524
|
-
if (state.mode !== 'GOAL' || !state.mission_id)
|
|
525
|
-
return '';
|
|
526
|
-
if (!route || route.id === 'Goal' || route.id === 'DFix' || route.id === 'Answer')
|
|
527
|
-
return '';
|
|
528
|
-
return [
|
|
529
|
-
`Legacy SKS Goal state ${state.mission_id} is non-authoritative and must not be updated.`,
|
|
530
|
-
`Do not let it hijack this new ${route.command || '$SKS'} prompt. The newly prepared route mission and gate are authoritative for this turn.`,
|
|
531
|
-
'Codex native Goal is the only persisted Goal owner; use native controls only when the user explicitly returns to Goal.'
|
|
532
|
-
].join('\n');
|
|
533
|
-
}
|
|
534
387
|
async function hookPreTool(root, state, payload, noQuestion, sessionKey = null) {
|
|
388
|
+
const skillAvailabilityBlock = await subagentSkillAvailabilityPreToolBlockReason(root, payload, officialSubagentArtifactDir(root, state, sessionKey), {
|
|
389
|
+
missionId: state?.mission_id,
|
|
390
|
+
workflowRunId: state?.official_subagent_run_id
|
|
391
|
+
}).catch((error) => {
|
|
392
|
+
const code = error instanceof Error && error.message === 'subagent_skill_availability_guard_invalid'
|
|
393
|
+
? 'subagent_skill_availability_guard_invalid'
|
|
394
|
+
: 'subagent_skill_availability_guard_check_failed';
|
|
395
|
+
return `SKS blocked this child tool call because managed skill availability failed (${code}). Return the blocker to the root parent without using tools.`;
|
|
396
|
+
});
|
|
397
|
+
if (skillAvailabilityBlock) {
|
|
398
|
+
return { decision: 'block', permissionDecision: 'deny', reason: skillAvailabilityBlock };
|
|
399
|
+
}
|
|
400
|
+
const skillRefresh = await activeAuthoritativeSksSkillRefresh(root, state);
|
|
401
|
+
if (skillRefresh.blocked) {
|
|
402
|
+
return {
|
|
403
|
+
decision: 'block',
|
|
404
|
+
permissionDecision: 'deny',
|
|
405
|
+
reason: skillRefresh.blocked.reason,
|
|
406
|
+
systemMessage: skillRefresh.blocked.systemMessage
|
|
407
|
+
};
|
|
408
|
+
}
|
|
535
409
|
if (needsMutationSafetyCheck(payload)) {
|
|
536
410
|
const madSksImmutableDecision = await checkMadSksImmutableModification(root, state, payload);
|
|
537
411
|
if (madSksImmutableDecision.action === 'block') {
|
|
@@ -555,12 +429,18 @@ async function hookPreTool(root, state, payload, noQuestion, sessionKey = null)
|
|
|
555
429
|
return agentRecursionDecision;
|
|
556
430
|
if (noQuestion && looksInteractiveCommand(command))
|
|
557
431
|
return { decision: 'block', reason: interactiveCommandReason(command) };
|
|
432
|
+
const hostCapabilityDecision = await enforceHostCapabilityPreTool(root, state, payload, sessionKey);
|
|
433
|
+
if (hostCapabilityDecision && hostCapabilityDecision.continue !== true)
|
|
434
|
+
return hostCapabilityDecision;
|
|
558
435
|
const waveGuidance = await parentWaveGuidanceContext(root, state, sessionKey).catch(() => '');
|
|
559
|
-
|
|
436
|
+
const additionalContext = [skillRefresh.context, waveGuidance].filter(Boolean).join('\n\n');
|
|
437
|
+
if (additionalContext) {
|
|
560
438
|
return {
|
|
561
439
|
continue: true,
|
|
562
|
-
additionalContext
|
|
563
|
-
|
|
440
|
+
additionalContext,
|
|
441
|
+
...(waveGuidance
|
|
442
|
+
? { systemMessage: visibleHookMessage('pre-tool', 'SKS Naruto wave lifecycle requires root-parent follow-up.') }
|
|
443
|
+
: { silent: true })
|
|
564
444
|
};
|
|
565
445
|
}
|
|
566
446
|
return { continue: true };
|
|
@@ -573,15 +453,14 @@ async function parentWaveGuidanceContext(root, state = {}, sessionKey = null) {
|
|
|
573
453
|
|| state?.subagents_required === true;
|
|
574
454
|
if (!isNaruto)
|
|
575
455
|
return '';
|
|
576
|
-
// Child worker hooks must not receive parent wave spawn instructions.
|
|
577
456
|
if (agentWorkerHookContext(state, {}))
|
|
578
457
|
return '';
|
|
579
458
|
const artifactDir = officialSubagentArtifactDir(root, state, sessionKey);
|
|
580
459
|
const plan = await readJson(path.join(artifactDir, 'subagent-plan.json'), null).catch(() => null);
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
460
|
+
const guidance = buildBoundWaveParentGuidance(plan, {
|
|
461
|
+
missionId: state?.mission_id,
|
|
462
|
+
workflowRunId: state?.official_subagent_run_id
|
|
463
|
+
});
|
|
585
464
|
if (!guidance?.required)
|
|
586
465
|
return '';
|
|
587
466
|
return renderWaveParentGuidance(guidance);
|
|
@@ -615,6 +494,7 @@ function agentWorkerHookContext(state = {}, payload = {}) {
|
|
|
615
494
|
async function hookPostTool(root, state, payload, noQuestion, sessionKey = null) {
|
|
616
495
|
state = { ...state, _session_key: state?._session_key || sessionKey };
|
|
617
496
|
await Promise.all([
|
|
497
|
+
recordHostCapabilityPostTool(root, state, payload, sessionKey).catch(() => null),
|
|
618
498
|
recordMadSksSqlPlanePostToolLifecycle(root, state, payload).catch(() => null),
|
|
619
499
|
recordContext7Evidence(root, state, payload).catch(() => null),
|
|
620
500
|
recordSubagentEvidence(root, state, payload).catch(() => null),
|
|
@@ -630,6 +510,134 @@ async function hookPostTool(root, state, payload, noQuestion, sessionKey = null)
|
|
|
630
510
|
}
|
|
631
511
|
return { continue: true };
|
|
632
512
|
}
|
|
513
|
+
async function enforceHostCapabilityPreTool(root, state = {}, payload = {}, sessionKey = null) {
|
|
514
|
+
const tool = acasHostToolName(payload.tool_name);
|
|
515
|
+
if (!tool)
|
|
516
|
+
return null;
|
|
517
|
+
if (explicitlyDeniedHostCapabilityTool(tool)) {
|
|
518
|
+
return {
|
|
519
|
+
decision: 'block',
|
|
520
|
+
permissionDecision: 'deny',
|
|
521
|
+
reason: `SKS denied acas-tools.${tool}; this tool is explicitly denied for model execution.`
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
const context = await loadHostCapabilityHookContext(root, state, payload, sessionKey);
|
|
525
|
+
if (!context) {
|
|
526
|
+
return {
|
|
527
|
+
decision: 'block',
|
|
528
|
+
permissionDecision: 'deny',
|
|
529
|
+
reason: 'SKS denied this acas-tools call because it has no valid task-scoped Naruto mission, run, and session context.'
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
if (!context.binding) {
|
|
533
|
+
return {
|
|
534
|
+
decision: 'block',
|
|
535
|
+
permissionDecision: 'deny',
|
|
536
|
+
reason: `SKS denied this acas-tools call because the current Naruto mission has no valid task-scoped host capability runtime: ${context.blocker}`
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
const observation = sanitizeHostCapabilityPreToolUse(context.binding.runtime, payload);
|
|
540
|
+
if (!observation) {
|
|
541
|
+
return {
|
|
542
|
+
decision: 'block',
|
|
543
|
+
permissionDecision: 'deny',
|
|
544
|
+
reason: 'SKS denied this acas-tools call because its official PreToolUse identity fields are invalid.'
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
let authorization = {
|
|
548
|
+
decision: observation.decision,
|
|
549
|
+
blocker: observation.blocker
|
|
550
|
+
};
|
|
551
|
+
try {
|
|
552
|
+
await withFileLock({
|
|
553
|
+
lockPath: path.join(context.dir, '.host-capability-hooks.lock'),
|
|
554
|
+
timeoutMs: 5_000,
|
|
555
|
+
staleMs: 60_000
|
|
556
|
+
}, async () => {
|
|
557
|
+
const current = await readJson(path.join(context.dir, HOST_CAPABILITY_HOOK_OBSERVATIONS_FILENAME), null).catch(() => null);
|
|
558
|
+
const result = authorizeAndMergeHostCapabilityPreToolObservation({
|
|
559
|
+
binding: context.binding,
|
|
560
|
+
current,
|
|
561
|
+
observation
|
|
562
|
+
});
|
|
563
|
+
authorization = result;
|
|
564
|
+
await writeJsonAtomic(path.join(context.dir, HOST_CAPABILITY_HOOK_OBSERVATIONS_FILENAME), result.observations);
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
catch {
|
|
568
|
+
return {
|
|
569
|
+
decision: 'block',
|
|
570
|
+
permissionDecision: 'deny',
|
|
571
|
+
reason: 'SKS denied this acas-tools call because its bounded PreToolUse evidence could not be persisted.'
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
if (authorization.decision === 'denied') {
|
|
575
|
+
return {
|
|
576
|
+
decision: 'block',
|
|
577
|
+
permissionDecision: 'deny',
|
|
578
|
+
reason: authorization.blocker
|
|
579
|
+
? `SKS denied acas-tools.${observation.tool}; ${authorization.blocker}.`
|
|
580
|
+
: `SKS denied acas-tools.${observation.tool}; it is outside runtime.allowed_tool_names for this mission, run, and session.`
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
return { continue: true };
|
|
584
|
+
}
|
|
585
|
+
async function recordHostCapabilityPostTool(root, state = {}, payload = {}, sessionKey = null) {
|
|
586
|
+
if (!acasHostToolName(payload.tool_name))
|
|
587
|
+
return null;
|
|
588
|
+
const context = await loadHostCapabilityHookContext(root, state, payload, sessionKey);
|
|
589
|
+
if (!context?.binding)
|
|
590
|
+
return null;
|
|
591
|
+
const observation = sanitizeHostCapabilityPostToolUse(payload);
|
|
592
|
+
if (!observation)
|
|
593
|
+
return null;
|
|
594
|
+
return withFileLock({
|
|
595
|
+
lockPath: path.join(context.dir, '.host-capability-hooks.lock'),
|
|
596
|
+
timeoutMs: 5_000,
|
|
597
|
+
staleMs: 60_000
|
|
598
|
+
}, async () => {
|
|
599
|
+
const current = await readJson(path.join(context.dir, HOST_CAPABILITY_HOOK_OBSERVATIONS_FILENAME), null).catch(() => null);
|
|
600
|
+
const next = mergeHostCapabilityPostToolObservation({
|
|
601
|
+
binding: context.binding,
|
|
602
|
+
current,
|
|
603
|
+
observation
|
|
604
|
+
});
|
|
605
|
+
const evidence = buildHostCapabilityEvidenceFromHookObservations({
|
|
606
|
+
binding: context.binding,
|
|
607
|
+
observations: next
|
|
608
|
+
});
|
|
609
|
+
await Promise.all([
|
|
610
|
+
writeJsonAtomic(path.join(context.dir, HOST_CAPABILITY_HOOK_OBSERVATIONS_FILENAME), next),
|
|
611
|
+
writeJsonAtomic(path.join(context.dir, HOST_CAPABILITY_HOOK_EVIDENCE_FILENAME), evidence)
|
|
612
|
+
]);
|
|
613
|
+
return evidence;
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
async function loadHostCapabilityHookContext(root, state = {}, payload = {}, sessionKey = null) {
|
|
617
|
+
const missionId = String(state?.mission_id || '').trim();
|
|
618
|
+
const workflowRunId = String(state?.official_subagent_run_id || '').trim();
|
|
619
|
+
const payloadSession = String(payload?.session_id || '').trim();
|
|
620
|
+
const expectedSession = String(state?.session_scope || sessionKey || '').trim();
|
|
621
|
+
const isNaruto = String(state?.mode || '').toUpperCase() === 'NARUTO'
|
|
622
|
+
|| String(state?.route || state?.route_command || '').replace(/^\$/, '').toUpperCase() === 'NARUTO'
|
|
623
|
+
|| state?.subagents_required === true;
|
|
624
|
+
if (!isNaruto || !missionId || !workflowRunId || !payloadSession || !expectedSession)
|
|
625
|
+
return null;
|
|
626
|
+
if (payloadSession !== expectedSession || (sessionKey && String(sessionKey) !== payloadSession))
|
|
627
|
+
return null;
|
|
628
|
+
const dir = missionDir(root, missionId);
|
|
629
|
+
const [raw, plan] = await Promise.all([
|
|
630
|
+
readJson(path.join(dir, HOST_CAPABILITY_HOOK_RUNTIME_FILENAME), null).catch(() => null),
|
|
631
|
+
readJson(path.join(dir, 'subagent-plan.json'), null).catch(() => null)
|
|
632
|
+
]);
|
|
633
|
+
const request = requestHostCapabilities(plan?.goal || state?.prompt || '');
|
|
634
|
+
return { dir, ...resolveHostCapabilityHookRuntimeBinding(raw, {
|
|
635
|
+
missionId,
|
|
636
|
+
workflowRunId,
|
|
637
|
+
sessionScope: payloadSession,
|
|
638
|
+
request
|
|
639
|
+
}) };
|
|
640
|
+
}
|
|
633
641
|
function needsMutationSafetyCheck(payload = {}) {
|
|
634
642
|
const toolName = String(payload.tool_name || payload.toolName || payload.name || payload.tool?.name || '');
|
|
635
643
|
const knownReadOnly = /^(Read|Grep|Glob|LS|TodoRead|WebFetch|WebSearch|BashOutput|NotebookRead|ListMcpResources|ReadMcpResource)$/i;
|
|
@@ -874,290 +882,6 @@ async function hookStop(root, state, payload, noQuestion, sessionKey = null) {
|
|
|
874
882
|
reason: 'SKS no-question run is not done. Continue autonomously, fix failing checks, update the active gate file, and do not ask the user.'
|
|
875
883
|
};
|
|
876
884
|
}
|
|
877
|
-
export async function refreshOfficialSubagentCompletionArtifacts(root, state = {}, parentSummary = '', sessionKey = null) {
|
|
878
|
-
const id = state?.mission_id;
|
|
879
|
-
if (!id)
|
|
880
|
-
return null;
|
|
881
|
-
const dir = missionDir(root, id);
|
|
882
|
-
const snapshot = await withOfficialSubagentLifecycleLock(dir, () => refreshOfficialSubagentCompletionArtifactsLocked(root, state, parentSummary, sessionKey, dir));
|
|
883
|
-
if (snapshot?.terminal?.passed === true) {
|
|
884
|
-
await finalizeNarutoTerminalProof(root, state, sessionKey, dir, snapshot.terminal);
|
|
885
|
-
}
|
|
886
|
-
return snapshot?.evidence ?? snapshot;
|
|
887
|
-
}
|
|
888
|
-
async function refreshOfficialSubagentCompletionArtifactsLocked(root, state, parentSummary, sessionKey, dir) {
|
|
889
|
-
if (await officialSubagentPreparationInProgress(dir))
|
|
890
|
-
return null;
|
|
891
|
-
const id = state?.mission_id;
|
|
892
|
-
const plan = await readJson(path.join(dir, 'subagent-plan.json'), null).catch(() => null);
|
|
893
|
-
if (plan?.workflow !== 'official_codex_subagent')
|
|
894
|
-
return null;
|
|
895
|
-
const workflowRunId = String(plan.workflow_run_id || state.official_subagent_run_id || '').trim();
|
|
896
|
-
if (!workflowRunId || String(state.official_subagent_run_id || '').trim() !== workflowRunId)
|
|
897
|
-
return null;
|
|
898
|
-
const [existingGate, existingSummary, rawExistingEvidence, existingParentSummary] = await Promise.all([
|
|
899
|
-
readJson(path.join(dir, 'naruto-gate.json'), null).catch(() => null),
|
|
900
|
-
readJson(path.join(dir, 'naruto-summary.json'), null).catch(() => null),
|
|
901
|
-
readJson(path.join(dir, SUBAGENT_EVIDENCE_FILENAME), null).catch(() => null),
|
|
902
|
-
readJson(path.join(dir, SUBAGENT_PARENT_SUMMARY_FILENAME), null).catch(() => null)
|
|
903
|
-
]);
|
|
904
|
-
const existingEvidence = normalizeLegacySubagentCountFields(rawExistingEvidence, plan);
|
|
905
|
-
if (completeNarutoTerminalBundle({
|
|
906
|
-
workflowRunId,
|
|
907
|
-
gate: existingGate,
|
|
908
|
-
summary: existingSummary,
|
|
909
|
-
evidence: existingEvidence,
|
|
910
|
-
parentSummary: existingParentSummary
|
|
911
|
-
})) {
|
|
912
|
-
return {
|
|
913
|
-
evidence: existingEvidence,
|
|
914
|
-
terminal: { passed: true, missionId: state.mission_id, workflowRunId, gate: existingGate }
|
|
915
|
-
};
|
|
916
|
-
}
|
|
917
|
-
const events = await readSubagentEvents(dir);
|
|
918
|
-
const lifecycle = await refreshSubagentWaveLifecycle(dir, { plan }).catch(() => plan.wave_lifecycle || null);
|
|
919
|
-
const refreshedPlan = lifecycle ? { ...plan, wave_lifecycle: lifecycle } : plan;
|
|
920
|
-
const countTarget = effectiveSubagentTarget(refreshedPlan, lifecycle?.cumulative_started || 0);
|
|
921
|
-
const requestedSubagents = countTarget.requestedSubagents || Number(state.requested_subagents || 0);
|
|
922
|
-
const runBoundParentSummary = bindTrustworthySubagentParentSummaryToRun(parentSummary, workflowRunId);
|
|
923
|
-
const effectiveParentSummary = await persistOrReuseTrustworthySubagentParentSummary(dir, runBoundParentSummary, {
|
|
924
|
-
workflowStatus: 'parent_completed',
|
|
925
|
-
runId: workflowRunId || null
|
|
926
|
-
});
|
|
927
|
-
const structuredParentSummary = normalizeSubagentParentSummary(effectiveParentSummary);
|
|
928
|
-
const evidence = await writeSubagentEvidence(dir, {
|
|
929
|
-
requestedSubagents,
|
|
930
|
-
countPolicy: countTarget.countPolicy,
|
|
931
|
-
targetSubagents: countTarget.targetSubagents,
|
|
932
|
-
events,
|
|
933
|
-
parentSummary: effectiveParentSummary,
|
|
934
|
-
workflowStatus: 'parent_completed',
|
|
935
|
-
preparationOnly: false,
|
|
936
|
-
runId: workflowRunId || null,
|
|
937
|
-
additionalBlockers: Array.isArray(plan.config_blockers)
|
|
938
|
-
? [
|
|
939
|
-
...plan.config_blockers.map((item) => `official_subagent_config:${String(item)}`),
|
|
940
|
-
...subagentCountContractBlockers(refreshedPlan, lifecycle?.cumulative_started || 0)
|
|
941
|
-
]
|
|
942
|
-
: subagentCountContractBlockers(refreshedPlan, lifecycle?.cumulative_started || 0)
|
|
943
|
-
});
|
|
944
|
-
if (structuredParentSummary.trustworthy) {
|
|
945
|
-
const parentTelemetry = await recordOfficialSubagentParentOutcomesTelemetry({
|
|
946
|
-
root,
|
|
947
|
-
routeMissionId: id,
|
|
948
|
-
parentSummary: structuredParentSummary.raw,
|
|
949
|
-
plan: refreshedPlan
|
|
950
|
-
}).catch(async (error) => {
|
|
951
|
-
await appendJsonl(path.join(dir, 'zellij-telemetry-warnings.jsonl'), {
|
|
952
|
-
ts: nowIso(),
|
|
953
|
-
warning: 'official_subagent_parent_outcome_telemetry_failed',
|
|
954
|
-
error: String(error?.message || error)
|
|
955
|
-
}).catch(() => null);
|
|
956
|
-
return null;
|
|
957
|
-
});
|
|
958
|
-
if (parentTelemetry?.blocker) {
|
|
959
|
-
await appendJsonl(path.join(dir, 'zellij-telemetry-warnings.jsonl'), {
|
|
960
|
-
ts: nowIso(),
|
|
961
|
-
warning: 'official_subagent_parent_outcome_telemetry_incomplete',
|
|
962
|
-
blocker: parentTelemetry.blocker,
|
|
963
|
-
failed_mission_ids: 'failed_mission_ids' in parentTelemetry ? parentTelemetry.failed_mission_ids : [],
|
|
964
|
-
skipped_thread_ids: 'skipped_thread_ids' in parentTelemetry ? parentTelemetry.skipped_thread_ids : []
|
|
965
|
-
}).catch(() => null);
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
const isNaruto = String(state?.mode || '').toUpperCase() === 'NARUTO'
|
|
969
|
-
|| String(state?.route || state?.route_command || '').replace(/^\$/, '').toUpperCase() === 'NARUTO';
|
|
970
|
-
if (!isNaruto) {
|
|
971
|
-
await updateCurrentIfMissionAndRun(root, id, workflowRunId, {
|
|
972
|
-
subagents_spawned: evidence.started_threads > 0,
|
|
973
|
-
subagents_reported: evidence.completed_threads > 0,
|
|
974
|
-
subagents_verified: evidence.ok,
|
|
975
|
-
subagent_evidence_file: SUBAGENT_EVIDENCE_FILENAME,
|
|
976
|
-
parent_summary_present: evidence.parent_summary_present
|
|
977
|
-
}, { sessionKey: sessionKey || state._session_key });
|
|
978
|
-
return { evidence, terminal: null };
|
|
979
|
-
}
|
|
980
|
-
const previousGate = existingGate || {};
|
|
981
|
-
const parentModel = plan.observed_parent_model || state.observed_parent_model || null;
|
|
982
|
-
const parentModelMismatch = previousGate.parent_model_match === false || observedParentModelMismatch(parentModel, NARUTO_PARENT_MODEL);
|
|
983
|
-
const blockers = [...new Set([
|
|
984
|
-
...evidence.blockers,
|
|
985
|
-
...(Array.isArray(previousGate.config_blockers) ? previousGate.config_blockers.map(String) : []),
|
|
986
|
-
...(Array.isArray(plan.config_blockers) ? plan.config_blockers.map((item) => `official_subagent_config:${String(item)}`) : []),
|
|
987
|
-
...(parentModelMismatch ? [`parent_model_mismatch:${String(parentModel || 'unknown')}`] : [])
|
|
988
|
-
])];
|
|
989
|
-
const ssotValidation = validateSsotGuardArtifact(await readJson(path.join(dir, SSOT_GUARD_ARTIFACT), null).catch(() => null));
|
|
990
|
-
blockers.push(...ssotValidation.issues.map((issue) => `${SSOT_GUARD_ARTIFACT}:${issue}`));
|
|
991
|
-
const uniqueBlockers = [...new Set(blockers)];
|
|
992
|
-
const passed = evidence.ok === true && ssotValidation.ok && uniqueBlockers.length === 0;
|
|
993
|
-
const updatedAt = nowIso();
|
|
994
|
-
const summary = {
|
|
995
|
-
schema: 'sks.naruto-subagent-workflow.v1',
|
|
996
|
-
ok: passed,
|
|
997
|
-
completion_evidence: passed,
|
|
998
|
-
workflow: 'official_codex_subagent',
|
|
999
|
-
workflow_run_id: workflowRunId || null,
|
|
1000
|
-
mission_id: id,
|
|
1001
|
-
route: '$Naruto',
|
|
1002
|
-
status: passed ? 'completed' : evidence.status,
|
|
1003
|
-
parent: {
|
|
1004
|
-
model: NARUTO_PARENT_MODEL,
|
|
1005
|
-
model_reasoning_effort: NARUTO_PARENT_EFFORT,
|
|
1006
|
-
observed_model: parentModel,
|
|
1007
|
-
observed_model_match: parentModel ? !parentModelMismatch : null
|
|
1008
|
-
},
|
|
1009
|
-
requested_subagents: requestedSubagents,
|
|
1010
|
-
count_policy: evidence.count_policy,
|
|
1011
|
-
target_subagents: evidence.target_subagents,
|
|
1012
|
-
wave_lifecycle: lifecycle,
|
|
1013
|
-
max_threads: Number(plan.max_threads || state.subagent_max_threads || 0),
|
|
1014
|
-
max_depth: 1,
|
|
1015
|
-
started_subagents: evidence.started_threads,
|
|
1016
|
-
completed_subagents: evidence.completed_threads,
|
|
1017
|
-
failed_subagents: evidence.failed_threads,
|
|
1018
|
-
agents: officialSubagentRolePlan(),
|
|
1019
|
-
verification: {
|
|
1020
|
-
budget: plan.verification?.budget || plan.verification_budget || 'affected',
|
|
1021
|
-
checks: Array.isArray(plan.verification?.checks)
|
|
1022
|
-
? plan.verification.checks
|
|
1023
|
-
: Array.isArray(plan.verification_checks)
|
|
1024
|
-
? plan.verification_checks
|
|
1025
|
-
: []
|
|
1026
|
-
},
|
|
1027
|
-
parent_summary_present: evidence.parent_summary_present,
|
|
1028
|
-
parent_summary: structuredParentSummary.summary,
|
|
1029
|
-
parent_thread_outcomes: structuredParentSummary.raw?.thread_outcomes || [],
|
|
1030
|
-
subagent_evidence: SUBAGENT_EVIDENCE_FILENAME,
|
|
1031
|
-
blockers: uniqueBlockers,
|
|
1032
|
-
updated_at: updatedAt
|
|
1033
|
-
};
|
|
1034
|
-
await writeJsonAtomic(path.join(dir, 'naruto-summary.json'), summary);
|
|
1035
|
-
const gate = await writeNarutoGate(dir, {
|
|
1036
|
-
missionId: id,
|
|
1037
|
-
workflowRunId,
|
|
1038
|
-
evidence,
|
|
1039
|
-
passed,
|
|
1040
|
-
blockers: uniqueBlockers,
|
|
1041
|
-
configBlockers: [
|
|
1042
|
-
...(Array.isArray(previousGate.config_blockers) ? previousGate.config_blockers.map(String) : []),
|
|
1043
|
-
...(Array.isArray(plan.config_blockers) ? plan.config_blockers.map((item) => `official_subagent_config:${String(item)}`) : [])
|
|
1044
|
-
],
|
|
1045
|
-
observedParentModel: parentModel,
|
|
1046
|
-
parentModelMatch: parentModel ? !parentModelMismatch : null
|
|
1047
|
-
});
|
|
1048
|
-
await updateCurrentIfMissionAndRun(root, id, workflowRunId, {
|
|
1049
|
-
subagents_spawned: evidence.started_threads > 0,
|
|
1050
|
-
subagents_reported: evidence.completed_threads > 0,
|
|
1051
|
-
subagents_verified: evidence.ok,
|
|
1052
|
-
subagent_evidence_file: SUBAGENT_EVIDENCE_FILENAME,
|
|
1053
|
-
parent_summary_present: evidence.parent_summary_present
|
|
1054
|
-
}, { sessionKey: sessionKey || state._session_key });
|
|
1055
|
-
return {
|
|
1056
|
-
evidence,
|
|
1057
|
-
terminal: passed ? { passed: true, missionId: id, workflowRunId, gate } : null
|
|
1058
|
-
};
|
|
1059
|
-
}
|
|
1060
|
-
function completeNarutoTerminalBundle(input) {
|
|
1061
|
-
const runId = String(input.workflowRunId || '').trim();
|
|
1062
|
-
const parent = normalizeSubagentParentSummary(input.parentSummary);
|
|
1063
|
-
return Boolean(runId
|
|
1064
|
-
&& input.gate?.workflow_run_id === runId
|
|
1065
|
-
&& input.gate?.passed === true
|
|
1066
|
-
&& input.gate?.terminal === true
|
|
1067
|
-
&& input.summary?.workflow_run_id === runId
|
|
1068
|
-
&& input.summary?.ok === true
|
|
1069
|
-
&& input.summary?.status === 'completed'
|
|
1070
|
-
&& input.evidence?.run_id === runId
|
|
1071
|
-
&& input.evidence?.ok === true
|
|
1072
|
-
&& input.evidence?.status === 'completed'
|
|
1073
|
-
&& parent.trustworthy
|
|
1074
|
-
&& parent.status === 'completed'
|
|
1075
|
-
&& parent.run_id === runId);
|
|
1076
|
-
}
|
|
1077
|
-
async function finalizeNarutoTerminalProof(root, state, sessionKey, dir, terminal) {
|
|
1078
|
-
// Lock order is finalization -> lifecycle -> session state. Preparation starts
|
|
1079
|
-
// at lifecycle -> session state and never acquires the finalization lock.
|
|
1080
|
-
await withFileLock({
|
|
1081
|
-
lockPath: path.join(dir, '.naruto-finalize.lock'),
|
|
1082
|
-
timeoutMs: 5_000,
|
|
1083
|
-
staleMs: 30_000
|
|
1084
|
-
}, () => withOfficialSubagentLifecycleLock(dir, async () => {
|
|
1085
|
-
if (await officialSubagentPreparationInProgress(dir))
|
|
1086
|
-
return;
|
|
1087
|
-
const [currentPlan, currentGate] = await Promise.all([
|
|
1088
|
-
readJson(path.join(dir, 'subagent-plan.json'), null).catch(() => null),
|
|
1089
|
-
readJson(path.join(dir, 'naruto-gate.json'), null).catch(() => null)
|
|
1090
|
-
]);
|
|
1091
|
-
if (String(currentPlan?.workflow_run_id || '').trim() !== terminal.workflowRunId
|
|
1092
|
-
|| String(currentGate?.workflow_run_id || '').trim() !== terminal.workflowRunId
|
|
1093
|
-
|| currentGate?.passed !== true
|
|
1094
|
-
|| currentGate?.terminal !== true)
|
|
1095
|
-
return;
|
|
1096
|
-
let proofStatus = await currentNarutoProofStatus(root, terminal.missionId, terminal.workflowRunId, state);
|
|
1097
|
-
if (!proofStatus.valid) {
|
|
1098
|
-
const finalized = await maybeFinalizeRoute(root, {
|
|
1099
|
-
missionId: terminal.missionId,
|
|
1100
|
-
route: '$Naruto',
|
|
1101
|
-
gateFile: 'naruto-gate.json',
|
|
1102
|
-
gate: currentGate,
|
|
1103
|
-
artifacts: [
|
|
1104
|
-
'subagent-plan.json',
|
|
1105
|
-
'subagent-events.jsonl',
|
|
1106
|
-
SUBAGENT_PARENT_SUMMARY_FILENAME,
|
|
1107
|
-
SUBAGENT_EVIDENCE_FILENAME,
|
|
1108
|
-
'naruto-summary.json',
|
|
1109
|
-
'naruto-gate.json'
|
|
1110
|
-
],
|
|
1111
|
-
claims: [{ id: 'naruto-official-subagent-completion', status: 'supported', evidence: 'naruto-gate.json' }],
|
|
1112
|
-
agents: true
|
|
1113
|
-
});
|
|
1114
|
-
if (finalized?.ok !== true) {
|
|
1115
|
-
throw new Error(`naruto_terminal_proof_finalize_failed:${String(finalized?.validation?.issues?.join(',') || finalized?.status || 'unknown')}`);
|
|
1116
|
-
}
|
|
1117
|
-
proofStatus = await currentNarutoProofStatus(root, terminal.missionId, terminal.workflowRunId, state);
|
|
1118
|
-
}
|
|
1119
|
-
if (!proofStatus.valid)
|
|
1120
|
-
throw new Error('naruto_terminal_proof_invalid_after_finalize');
|
|
1121
|
-
await closeWorkOrderLedgerForRouteResult(dir, { ok: true });
|
|
1122
|
-
await invalidateReflectionForNarutoProofOnce(root, state, sessionKey, terminal.workflowRunId, proofStatus.digest);
|
|
1123
|
-
}));
|
|
1124
|
-
}
|
|
1125
|
-
async function currentNarutoProofStatus(root, missionId, workflowRunId, state) {
|
|
1126
|
-
const validation = await validateRouteCompletionProof(root, {
|
|
1127
|
-
missionId,
|
|
1128
|
-
route: '$Naruto',
|
|
1129
|
-
state: {
|
|
1130
|
-
...state,
|
|
1131
|
-
mission_id: missionId,
|
|
1132
|
-
subagents_required: true,
|
|
1133
|
-
official_subagent_run_id: workflowRunId
|
|
1134
|
-
}
|
|
1135
|
-
}).catch(() => null);
|
|
1136
|
-
const proofRunId = String(validation?.proof?.evidence?.route_gate?.workflow_run_id || '').trim();
|
|
1137
|
-
const proofText = await readText(path.join(root, '.sneakoscope', 'missions', missionId, 'completion-proof.json'), '').catch(() => '');
|
|
1138
|
-
return {
|
|
1139
|
-
valid: validation?.ok === true && proofRunId === workflowRunId,
|
|
1140
|
-
proof: validation?.proof || null,
|
|
1141
|
-
digest: proofText ? `sha256:${sha256(proofText)}` : null
|
|
1142
|
-
};
|
|
1143
|
-
}
|
|
1144
|
-
async function invalidateReflectionForNarutoProofOnce(root, state, sessionKey, workflowRunId, proofDigest) {
|
|
1145
|
-
if (!workflowRunId || !proofDigest)
|
|
1146
|
-
return;
|
|
1147
|
-
const resolvedSessionKey = sessionKey || state?._session_key;
|
|
1148
|
-
await updateCurrentIfMissionAndRun(root, state?.mission_id, workflowRunId, (current) => {
|
|
1149
|
-
if (current?.reflection_invalidated_for_workflow_run_id === workflowRunId
|
|
1150
|
-
&& current?.reflection_invalidated_for_proof_digest === proofDigest)
|
|
1151
|
-
return null;
|
|
1152
|
-
return {
|
|
1153
|
-
reflection_invalidation_required: true,
|
|
1154
|
-
reflection_invalidated_at: nowIso(),
|
|
1155
|
-
reflection_invalidation_reason: 'naruto_terminal_proof_committed',
|
|
1156
|
-
reflection_invalidated_for_workflow_run_id: workflowRunId,
|
|
1157
|
-
reflection_invalidated_for_proof_digest: proofDigest
|
|
1158
|
-
};
|
|
1159
|
-
}, { sessionKey: resolvedSessionKey });
|
|
1160
|
-
}
|
|
1161
885
|
async function consumeLightRouteStop(root, payload = {}) {
|
|
1162
886
|
const file = path.join(root, '.sneakoscope', 'state', LIGHT_ROUTE_STOP_ARTIFACT);
|
|
1163
887
|
const record = await readJson(file, null).catch(() => null);
|