sneakoscope 8.0.2 → 8.0.4
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 +150 -37
- package/config/skills-hash-ledger.v1.json +1 -1
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/bin/fast-inline.js +55 -27
- package/dist/bin/install.js +6 -32
- package/dist/bin/sks-dispatch.js +1 -1
- package/dist/cli/args.js +0 -2
- package/dist/cli/cli-theme.js +18 -9
- package/dist/cli/command-manifest-lite.js +6 -6
- package/dist/cli/command-registry.js +6 -6
- package/dist/cli/feature-commands.js +9 -7
- package/dist/cli/install-helpers-codex-lb-chain.js +198 -7
- package/dist/cli/install-helpers-codex-lb-config.js +78 -10
- package/dist/cli/install-helpers-install-support.js +9 -6
- package/dist/cli/install-helpers.js +101 -49
- package/dist/cli/install-tool-helpers.js +2 -82
- package/dist/cli/output.js +6 -1
- package/dist/cli/router.js +101 -2
- package/dist/commands/codex-lb.js +119 -19
- package/dist/commands/doctor-profile.js +1 -1
- package/dist/commands/doctor.js +727 -144
- package/dist/commands/mad-sks.js +1 -5
- package/dist/config/skills-manifest.json +4 -2
- package/dist/core/agents/agent-codex-cockpit.js +0 -3
- package/dist/core/agents/agent-effort-policy.js +5 -5
- package/dist/core/agents/agent-janitor.js +0 -20
- package/dist/core/agents/agent-orchestrator.js +9 -56
- package/dist/core/agents/agent-output-validator.js +2 -3
- package/dist/core/agents/agent-patch-schema.js +2 -2
- package/dist/core/agents/agent-proof-evidence.js +0 -65
- package/dist/core/agents/agent-recursion-guard.js +1 -1
- package/dist/core/agents/agent-runner-codex-exec.js +5 -3
- package/dist/core/agents/agent-scheduler.js +327 -85
- package/dist/core/agents/agent-schema.js +1 -1
- package/dist/core/agents/agent-trust-report.js +0 -36
- package/dist/core/agents/agent-worker-pipeline.js +0 -1
- package/dist/core/agents/fast-mode-policy.js +1 -3
- package/dist/core/agents/native-cli-worker-runtime-proof.js +1 -1
- package/dist/core/agents/native-cli-worker-runtime.js +69 -647
- package/dist/core/agents/native-cli-worker.js +6 -7
- package/dist/core/agents/native-worker-backend-router.js +2 -32
- package/dist/core/agents/no-subagent-scaling-policy.js +1 -1
- package/dist/core/agents/parallel-runtime-proof.js +1 -6
- package/dist/core/agents/runtime-proof-summary.js +1 -35
- package/dist/core/architecture-hardening/contracts/contracts.js +193 -0
- package/dist/core/architecture-hardening/migration/migration.js +111 -0
- package/dist/core/architecture-hardening/state/state-service.js +155 -0
- package/dist/core/artifact-schemas.js +0 -3
- package/dist/core/codex/codex-config-guard.js +238 -52
- package/dist/core/codex-adapter.js +5 -3
- package/dist/core/codex-app/auxiliary-oauth-policy.js +36 -0
- package/dist/core/codex-app/catalog-compat/catalog-service.js +104 -0
- package/dist/core/codex-app/child-policy/child-policy.js +35 -0
- package/dist/core/codex-app/codex-app-handoff.js +0 -1
- package/dist/core/codex-app/codex-hook-lifecycle.js +1 -1
- package/dist/core/codex-app/codex-init-deep.js +1 -1
- package/dist/core/codex-app/menubar/app-bundle.js +2 -0
- package/dist/core/codex-app/menubar/constants.js +14 -1
- package/dist/core/codex-app/menubar/global-install.js +288 -0
- package/dist/core/codex-app/menubar/installer.js +79 -14
- package/dist/core/codex-app/menubar/launch-agent.js +267 -45
- package/dist/core/codex-app/menubar/paths.js +3 -0
- package/dist/core/codex-app/menubar/rollback.js +55 -7
- package/dist/core/codex-app/menubar/status.js +75 -4
- package/dist/core/codex-app/provider-child-policy.js +64 -0
- package/dist/core/codex-app/provider-mode.js +91 -0
- package/dist/core/codex-app/provider-operation-stages.js +20 -0
- package/dist/core/codex-app/provider-session-policy.js +85 -0
- package/dist/core/codex-app/session-policy/session-pinning.js +68 -0
- package/dist/core/codex-app.js +3 -2
- package/dist/core/codex-control/codex-0139-image-path-real-probe.js +3 -1
- package/dist/core/codex-control/codex-0139-web-search-probe.js +3 -1
- package/dist/core/codex-control/codex-app-server-runtime-env.js +13 -4
- package/dist/core/codex-control/codex-app-server-v2-client.js +3 -3
- package/dist/core/codex-control/codex-control-proof.js +0 -1
- package/dist/core/codex-control/codex-task-runner.js +1 -4
- package/dist/core/codex-exec-output-schema.js +4 -1
- package/dist/core/codex-lb/codex-lb-env.js +63 -72
- package/dist/core/codex-lb/codex-lb-setup.js +15 -2
- package/dist/core/codex-lb/desktop-bridge/header-policy.js +6 -0
- package/dist/core/codex-lb/desktop-bridge/http-forward.js +48 -6
- package/dist/core/codex-lb/desktop-bridge/security.js +134 -0
- package/dist/core/codex-lb/desktop-bridge/server.js +9 -3
- package/dist/core/codex-lb/desktop-bridge/state.js +26 -6
- package/dist/core/codex-lb/desktop-bridge/types.js +1 -0
- package/dist/core/codex-lb/desktop-center-credentials.js +517 -58
- package/dist/core/codex-lb/desktop-controller.js +177 -56
- package/dist/core/codex-lb/desktop-service.js +179 -40
- package/dist/core/codex-lb/legacy-migration.js +1 -3
- package/dist/core/codex-lb/native-openai-transport/transport.js +68 -0
- package/dist/core/codex-lb/probes/cli-image-tool-probe.js +1 -1
- package/dist/core/codex-lb/provider-routing/provider-router.js +58 -0
- package/dist/core/codex-lb/routing-truth.js +327 -0
- package/dist/core/codex-native/codex-native-feature-broker.js +4 -0
- package/dist/core/codex-native/codex-native-pattern-analysis.js +1 -2
- package/dist/core/codex-native/core-skill-manifest.js +1 -1
- package/dist/core/codex-plugins/codex-plugin-json.js +26 -6
- package/dist/core/codex-plugins/codex-plugin-repair.js +32 -6
- package/dist/core/commands/basic-cli.js +9 -7
- package/dist/core/commands/computer-use-command.js +1 -1
- package/dist/core/commands/image-ux-review-command.js +16 -9
- package/dist/core/commands/install-package-command.js +105 -0
- package/dist/core/commands/intent-normalization/normalizer.js +96 -0
- package/dist/core/commands/mad-sks-command.js +23 -274
- package/dist/core/commands/mad-sks-headless.js +11 -30
- package/dist/core/commands/naruto-command.js +0 -25
- package/dist/core/commands/qa-loop-command.js +104 -22
- package/dist/core/commands/remote-command.js +2 -2
- package/dist/core/commands/research-command.js +10 -5
- package/dist/core/commands/telegram-command.js +407 -0
- package/dist/core/config-adopt/config-adopt-command.js +35 -0
- package/dist/core/config-adopt/config-adopt.js +346 -0
- package/dist/core/config-adopt/index.js +3 -0
- package/dist/core/doctor/command-alias-cleanup.js +4 -1
- package/dist/core/doctor/current-project-guidance-nested.js +37 -6
- package/dist/core/doctor/current-project-guidance.js +15 -9
- package/dist/core/doctor/doctor-dirty-planner.js +1 -4
- package/dist/core/doctor/doctor-readiness-matrix.js +15 -18
- package/dist/core/doctor/retired-managed-residue-private.js +4 -3
- package/dist/core/doctor/retired-managed-residue-runtime.js +2 -2
- package/dist/core/doctor/skill-legacy-surface.js +11 -10
- package/dist/core/doctor/sks-menubar-doctor.js +4 -0
- package/dist/core/evaluation.js +0 -19
- package/dist/core/evidence/v2/evidence-key.js +105 -0
- package/dist/core/feature-fixtures.js +12 -7
- package/dist/core/feature-registry.js +52 -21
- package/dist/core/hooks-runtime/hook-context.js +9 -0
- package/dist/core/hooks-runtime/managed-skill-admission.js +54 -4
- package/dist/core/hooks-runtime/official-subagent-lifecycle.js +69 -52
- package/dist/core/hooks-runtime/stop-finalization.js +226 -0
- package/dist/core/hooks-runtime/stop-repeat-guard.js +21 -2
- package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +2 -2
- package/dist/core/hooks-runtime/subagent-skill-availability-evidence.js +3 -3
- package/dist/core/hooks-runtime/subagent-skill-availability-guards.js +43 -5
- package/dist/core/hooks-runtime/subagent-skill-availability.js +64 -30
- package/dist/core/hooks-runtime/subagent-stop-hook.js +15 -2
- package/dist/core/hooks-runtime.js +179 -212
- package/dist/core/image/reference-evidence/reference-registry.js +145 -0
- package/dist/core/image-ux-review/imagegen-adapter.js +21 -9
- package/dist/core/image-ux-review/reference-policy/reference-policy.js +9 -0
- package/dist/core/imagegen/codex-lb-imagegen-target.js +8 -0
- package/dist/core/imagegen/imagegen-capability.js +59 -2
- package/dist/core/imagegen/require-imagegen.js +2 -2
- package/dist/core/init/skills.js +17 -3
- package/dist/core/init.js +3 -3
- package/dist/core/install/installed-package-smoke.js +23 -5
- package/dist/core/json/canonical.js +9 -0
- package/dist/core/locks/file-lock.js +0 -1
- package/dist/core/loops/loop-continuation-enforcer.js +65 -7
- package/dist/core/loops/loop-decomposer.js +0 -1
- package/dist/core/loops/loop-gate-runner.js +65 -4
- package/dist/core/loops/loop-gate-selector.js +0 -2
- package/dist/core/loops/loop-proof-validation.js +38 -0
- package/dist/core/loops/loop-risk-classifier.js +1 -1
- package/dist/core/loops/loop-runtime.js +14 -2
- package/dist/core/loops/loop-scheduler.js +7 -2
- package/dist/core/loops/loop-worker-runtime.js +0 -15
- package/dist/core/loops/loop-worktree-runtime.js +52 -4
- package/dist/core/managed-assets/managed-assets-manifest.js +14 -14
- package/dist/core/naruto/hardware-capacity-probe.js +9 -6
- package/dist/core/naruto/naruto-active-pool.js +2 -14
- package/dist/core/naruto/naruto-concurrency-governor.js +71 -31
- package/dist/core/naruto/naruto-loop-worker-router.js +0 -2
- package/dist/core/naruto/naruto-verification-dag.js +0 -1
- package/dist/core/naruto/naruto-write-e2e.js +1 -2
- package/dist/core/naruto/resource-pressure-monitor.js +0 -4
- package/dist/core/observability/architecture-hardening/safe-projection.js +65 -0
- package/dist/core/perf/import-graph-budget.js +0 -1
- package/dist/core/perf/release-latency-slo.js +3 -2
- package/dist/core/preflight/parallel-preflight-engine.js +2 -15
- package/dist/core/product-design-app-server.js +13 -1
- package/dist/core/proof/fake-real-proof-policy.js +2 -17
- package/dist/core/proof/route-proof-gate.js +2 -10
- package/dist/core/proof/route-proof-policy.js +1 -1
- package/dist/core/proof/runtime-evidence-policy.js +185 -0
- package/dist/core/proof/runtime-truth-matrix.js +64 -39
- package/dist/core/proof/validation.js +27 -11
- package/dist/core/provider/provider-context.js +18 -2
- package/dist/core/providers/openrouter/openrouter-account.js +3 -2
- package/dist/core/python-tools/python-tool-runner.js +1 -1
- package/dist/core/qa-loop/qa-execution-control.js +57 -0
- package/dist/core/questions.js +1 -1
- package/dist/core/release/extreme-parallel-scheduler.js +0 -3
- package/dist/core/release/gate-manifest.js +3 -7
- package/dist/core/release/gate-pack-manifest.js +3 -7
- package/dist/core/release/package-size-budget.js +2 -2
- package/dist/core/release/physical-release-gates.js +189 -0
- package/dist/core/release/publish-preflight.js +113 -0
- package/dist/core/release/release-gate-affected-selector.js +0 -2
- package/dist/core/release/release-gate-batch-runner.js +1 -1
- package/dist/core/release/release-gate-node.js +0 -1
- package/dist/core/release/release-gate-resource-governor.js +0 -1
- package/dist/core/release/release-pack-receipt.js +5 -8
- package/dist/core/release/release-real-contract.js +0 -6
- package/dist/core/release/resource-class-budget.js +0 -1
- package/dist/core/release/stage-publish.js +178 -36
- package/dist/core/research/research-adversarial-review.js +103 -9
- package/dist/core/research.js +1 -1
- package/dist/core/retention.js +0 -1
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/diagnostic-allowlist.js +0 -1
- package/dist/core/routes/dollar-manifest-lite.js +1 -1
- package/dist/core/routes.js +46 -15
- package/dist/core/runtime/execution-control.js +226 -0
- package/dist/core/runtime/progress-recovery/progress-recovery.js +89 -0
- package/dist/core/runtime/task-profile.js +10 -4
- package/dist/core/runtime/verification-budget.js +10 -1
- package/dist/core/safety/intent-contract/intent-contract.js +94 -0
- package/dist/core/safety/mutation-guard.js +0 -2
- package/dist/core/safety/mutation-ledger.js +0 -2
- package/dist/core/safety/requested-scope-contract.js +0 -0
- package/dist/core/search-visibility/discovery.js +1 -1
- package/dist/core/search-visibility/index.js +12 -0
- package/dist/core/search-visibility/verifier.js +112 -3
- package/dist/core/security/private-credential-file.js +209 -0
- package/dist/core/session/project-namespace.js +0 -5
- package/dist/core/skills/skill-agent-metadata.js +1 -3
- package/dist/core/strategy/adhd-orchestrating-gate.js +0 -1
- package/dist/core/subagents/agent-catalog.js +19 -34
- package/dist/core/subagents/model-policy.js +65 -24
- package/dist/core/subagents/naruto-help-contract.js +8 -8
- package/dist/core/subagents/naruto-host-credentials.js +13 -0
- package/dist/core/subagents/official-subagent-config.js +16 -6
- package/dist/core/subagents/official-subagent-preparation.js +35 -16
- package/dist/core/subagents/official-subagent-prompt.js +7 -7
- package/dist/core/subagents/official-subagent-runner.js +27 -4
- package/dist/core/subagents/role-model-preferences.js +1 -1
- package/dist/core/subagents/thread-budget.js +19 -12
- package/dist/core/subagents/wave-lifecycle.js +18 -6
- package/dist/core/telegram/access.js +58 -0
- package/dist/core/telegram/client.js +157 -0
- package/dist/core/telegram/confirmation.js +37 -0
- package/dist/core/telegram/doctor.js +154 -0
- package/dist/core/telegram/index.js +9 -0
- package/dist/core/telegram/keychain.js +317 -0
- package/dist/core/telegram/liveness.js +118 -0
- package/dist/core/telegram/poller.js +90 -0
- package/dist/core/telegram/redaction.js +15 -0
- package/dist/core/telegram/state-lock.js +416 -0
- package/dist/core/telegram/types.js +1 -0
- package/dist/core/text/strings.js +3 -0
- package/dist/core/triwiki/context-graph/store/evidence-write-lock.js +29 -0
- package/dist/core/triwiki/context-graph/store/fragment-cache.js +24 -0
- package/dist/core/triwiki/context-graph/store/snapshot-store.js +69 -21
- package/dist/core/triwiki/triwiki-gate-impact-map.js +2 -2
- package/dist/core/triwiki/triwiki-module-card.js +1 -2
- package/dist/core/update/installed-cli-resolution.js +170 -0
- package/dist/core/update/update-diagnostics.js +52 -0
- package/dist/core/update/update-migration-state.js +30 -12
- package/dist/core/update/update-operation.js +2 -1
- package/dist/core/update/update-stage-diagnostics.js +38 -0
- package/dist/core/update/update-status.js +2 -9
- package/dist/core/update-check.js +279 -91
- package/dist/core/version.js +1 -1
- package/dist/native/sks-menubar/Sources/AppDelegate.swift +19 -1
- package/dist/native/sks-menubar/Sources/AppIdentity.swift +7 -0
- package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +6 -2
- package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +159 -92
- package/dist/native/sks-menubar/Sources/OperationModels.swift +389 -0
- package/dist/native/sks-menubar/Sources/OverviewViewController.swift +57 -0
- package/dist/native/sks-menubar/Sources/ProcessClient.swift +3 -1
- package/dist/native/sks-menubar/Sources/ProvidersConnectTest.swift +115 -0
- package/dist/native/sks-menubar/Sources/ProvidersFastMode.swift +17 -0
- package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +3 -0
- package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +58 -17
- package/dist/native/sks-menubar/Sources/ProvidersReliability.swift +302 -0
- package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +5 -0
- package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +190 -0
- package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +158 -126
- package/dist/native/sks-menubar/Sources/RemoteCodingViewController.swift +462 -26
- package/dist/native/sks-menubar/Sources/SKSKeychainStore.swift +344 -0
- package/dist/native/sks-menubar/Sources/SecureProcessEnvelope.swift +27 -0
- package/dist/native/sks-menubar/Sources/SingletonInstanceGuard.swift +328 -0
- package/dist/native/sks-menubar/Sources/StatusItemController.swift +10 -2
- package/dist/native/sks-menubar/Sources/TelegramPrivateFileStore.swift +498 -0
- package/dist/native/sks-menubar/Sources/TelegramPrivateFileSupport.swift +236 -0
- package/dist/native/sks-menubar/Sources/TelegramProcessGateway.swift +454 -0
- package/dist/native/sks-menubar/Sources/TelegramRuntimeSupport.swift +56 -0
- package/dist/native/sks-menubar/Sources/TelegramStateLock.swift +448 -0
- package/dist/native/sks-menubar/Sources/TelegramSupport.swift +187 -0
- package/dist/native/sks-menubar/Sources/TelegramTransport.swift +499 -0
- package/dist/native/sks-menubar/Sources/main.swift +15 -1
- package/dist/scripts/all-feature-deep-completion-check.js +5 -1
- package/dist/scripts/check-publish-tag.js +56 -0
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +10 -3
- package/dist/scripts/codex-lb-fast-ui-preservation-check.js +12 -3
- package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +4 -2
- package/dist/scripts/codex-native-agent-role-content-check.js +3 -3
- package/dist/scripts/codex-native-gate-lib.js +14 -7
- package/dist/scripts/current-command-surface-check.js +7 -7
- package/dist/scripts/current-surface-update-e2e-check.js +4 -3
- package/dist/scripts/current-upgrade-matrix-check.js +5 -24
- package/dist/scripts/docs-truthfulness-check.js +17 -13
- package/dist/scripts/gate-lib.js +0 -2
- package/dist/scripts/gate-policy-audit-check.js +3 -2
- package/dist/scripts/harness-benchmark-check.js +1 -1
- package/dist/scripts/init-deep-backup-retention-check.js +1 -1
- package/dist/scripts/lib/codex-sdk-gate-lib.js +1 -2
- package/dist/scripts/loop-directive-check-lib.js +28 -38
- package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +14 -180
- package/dist/scripts/mad-sks-launch-sql-plane-boundary-check.js +2 -11
- package/dist/scripts/official-subagent-workflow-check.js +1 -1
- package/dist/scripts/packlist-performance-check.js +1 -2
- package/dist/scripts/prepublish-release-check-or-fast.js +32 -0
- package/dist/scripts/publish-preflight.js +12 -0
- package/dist/scripts/release-affected-selector-check.js +2 -2
- package/dist/scripts/release-gate-batch-runner-check.js +2 -2
- package/dist/scripts/release-metadata-check.js +8 -12
- package/dist/scripts/release-real-check.js +2 -54
- package/dist/scripts/runtime-domain-gate-lib.js +2 -96
- package/dist/scripts/runtime-proof-summary-check.js +2 -6
- package/dist/scripts/search-visibility-gate-lib.js +0 -1
- package/dist/scripts/sks-cli-gate-lib.js +1 -1
- package/dist/scripts/typed-routing-gate-lib.js +7 -59
- package/docs/demo.tape +1 -1
- package/infra-harness-gates.json +1 -1456
- package/package.json +10 -7
- package/release-gates.v2.json +0 -1
- package/schemas/agents/parallel-runtime-proof.schema.json +0 -2
- package/schemas/codex/agent-result.schema.json +0 -6
- package/schemas/naruto/naruto-concurrency-governor.schema.json +1 -3
- package/schemas/release/release-gate-node.schema.json +1 -1
- package/dist/commands/zellij-lane.js +0 -22
- package/dist/commands/zellij-monitor-pane.js +0 -26
- package/dist/commands/zellij-slot-column-anchor.js +0 -22
- package/dist/commands/zellij-slot-pane.js +0 -80
- package/dist/commands/zellij-viewport-pane.js +0 -57
- package/dist/commands/zellij.js +0 -422
- package/dist/core/agents/agent-runner-zellij.js +0 -164
- package/dist/core/agents/agent-slot-pane-binding-proof.js +0 -96
- package/dist/core/agents/parallel-write-fixture.js +0 -305
- package/dist/core/agents/worker-pane-communication-contract.js +0 -100
- package/dist/core/agents/zellij-lane-supervisor.js +0 -428
- package/dist/core/agents/zellij-right-lane-cockpit.js +0 -66
- package/dist/core/doctor/doctor-zellij-repair.js +0 -40
- package/dist/core/ops/upgrade-migration-fixtures.js +0 -119
- package/dist/core/proof/route-finalizer-fixtures.js +0 -21
- package/dist/core/zellij/homebrew-policy.js +0 -43
- package/dist/core/zellij/zellij-capability.js +0 -126
- package/dist/core/zellij/zellij-clipboard-config.js +0 -52
- package/dist/core/zellij/zellij-command.js +0 -149
- package/dist/core/zellij/zellij-fake-adapter.js +0 -186
- package/dist/core/zellij/zellij-lane-renderer.js +0 -706
- package/dist/core/zellij/zellij-lane-runtime.js +0 -189
- package/dist/core/zellij/zellij-launcher.js +0 -268
- package/dist/core/zellij/zellij-layout-builder.js +0 -191
- package/dist/core/zellij/zellij-monitor-renderer.js +0 -52
- package/dist/core/zellij/zellij-official-subagent-activity.js +0 -526
- package/dist/core/zellij/zellij-official-subagent-telemetry.js +0 -258
- package/dist/core/zellij/zellij-pane-proof.js +0 -226
- package/dist/core/zellij/zellij-right-column-manager.js +0 -308
- package/dist/core/zellij/zellij-screen-proof.js +0 -120
- package/dist/core/zellij/zellij-self-heal-types.js +0 -44
- package/dist/core/zellij/zellij-self-heal.js +0 -408
- package/dist/core/zellij/zellij-slot-column-anchor.js +0 -304
- package/dist/core/zellij/zellij-slot-pane-renderer.js +0 -521
- package/dist/core/zellij/zellij-slot-telemetry.js +0 -384
- package/dist/core/zellij/zellij-theme.js +0 -66
- package/dist/core/zellij/zellij-ui-mode.js +0 -34
- package/dist/core/zellij/zellij-update.js +0 -348
- package/dist/core/zellij/zellij-viewport-binder.js +0 -61
- package/dist/core/zellij/zellij-worker-pane-manager.js +0 -881
- package/dist/core/zellij/zellij-worker-pane-summary.js +0 -64
- package/dist/native/sks-menubar/Tests/AppRuntimeTestSupport.swift +0 -26
- package/dist/native/sks-menubar/Tests/OperationCoordinatorTests.swift +0 -174
- package/dist/native/sks-menubar/Tests/ProcessClientTests.swift +0 -20
- package/dist/native/sks-menubar/Tests/ProvidersViewControllerTests.swift +0 -142
- package/dist/scripts/zellij-pane-proof-check.js +0 -88
- package/dist/scripts/zellij-real-session-cleanup-check.js +0 -139
- package/dist/scripts/zellij-real-session-launch-check.js +0 -126
- package/dist/scripts/zellij-screen-proof-check.js +0 -43
- package/schemas/zellij/zellij-right-column-state.schema.json +0 -40
- package/schemas/zellij/zellij-slot-telemetry.schema.json +0 -89
- package/schemas/zellij/zellij-worker-pane.schema.json +0 -53
- package/scripts/build-clean-atomic.mjs +0 -323
package/dist/core/routes.js
CHANGED
|
@@ -5,7 +5,7 @@ import { CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_ONLY_POLICY, COD
|
|
|
5
5
|
import { getdesignReferencePolicyText, imageUxReviewPipelinePolicyText } from './routes/design-policy.js';
|
|
6
6
|
import { PPT_PIPELINE_SKILL_ALLOWLIST, pptPipelineAllowlistPolicyText } from './routes/ppt-policy.js';
|
|
7
7
|
import { normalizeDollarSkillName, prefixKnownSksDollarReferences, sksPrefixedDollarCommand, sksPrefixedSkillName, unprefixedSksSkillName } from './routes/dollar-prefix.js';
|
|
8
|
-
import { classifyTaskProfile, looksLikeDatabaseWorkRequest } from './runtime/task-profile.js';
|
|
8
|
+
import { classifyTaskProfile, isTaskProfile, looksLikeDatabaseWorkRequest } from './runtime/task-profile.js';
|
|
9
9
|
import { legacyCoreSkillNames } from './codex-native/core-skill-manifest.js';
|
|
10
10
|
export * from './routes/constants.js';
|
|
11
11
|
export * from './routes/design-policy.js';
|
|
@@ -249,7 +249,7 @@ export const ROUTES = [
|
|
|
249
249
|
command: '$Naruto',
|
|
250
250
|
mode: 'NARUTO',
|
|
251
251
|
route: 'Codex official subagent workflow',
|
|
252
|
-
description: '$Naruto prepares a lightweight Codex official subagent workflow. The Sol Max parent owns decomposition, delegates only defensible direct-child slices, reuses bounded query-aware TriWiki attention anchors, waits for every requested thread, integrates the results, and reports scoped verification. Automatic fan-out starts at four for bounded work, six for explicit parallel work, eight for large-scale work, and sixteen for mass cheap-model fan-out on the Luna/Terra lanes; normal expansion is capped at twelve, while the mass lane may expand to sixty-four. The default max_threads of twelve remains a frame budget (cap), never a target; the absolute hard frame cap is two hundred fifty-six, and multi-wave scheduling reuses capacity for requested counts beyond the first wave. Luna Max handles tiny mechanical shards, Terra
|
|
252
|
+
description: '$Naruto prepares a lightweight Codex official subagent workflow. The Sol Max parent owns decomposition, delegates only defensible direct-child slices, reuses bounded query-aware TriWiki attention anchors, waits for every requested thread, integrates the results, and reports scoped verification. Automatic fan-out starts at four for bounded work, six for explicit parallel work, eight for large-scale work, and sixteen for mass cheap-model fan-out on the Luna/Terra lanes; normal expansion is capped at twelve, while the mass lane may expand to sixty-four. The default max_threads of twelve remains a frame budget (cap), never a target; the absolute hard frame cap is two hundred fifty-six, and multi-wave scheduling reuses capacity for requested counts beyond the first wave. Luna Max handles tiny mechanical shards, Terra Max handles broad search and exploration shards, and Sol handles implementation and judgment; explicit --agents remains authoritative.',
|
|
253
253
|
requiredSkills: ['naruto', 'pipeline-runner', 'prompt-pipeline', 'honest-mode'],
|
|
254
254
|
dollarAliases: ['$Work'],
|
|
255
255
|
appSkillAliases: ['work', 'from-chat-img'],
|
|
@@ -640,20 +640,19 @@ export const COMMAND_CATALOG = [
|
|
|
640
640
|
{ name: 'review', usage: 'sks review [--staged|--diff <ref>] [--fix] [--json]', description: 'Review a diff with machine-evidence findings sorted above LLM review notes.' },
|
|
641
641
|
{ name: 'usage', usage: `sks usage [${USAGE_TOPICS}]`, description: 'Print copy-ready workflows for common tasks.' },
|
|
642
642
|
{ name: 'quickstart', usage: 'sks quickstart', description: 'Show the shortest safe setup and verification flow.' },
|
|
643
|
-
{ name: 'bootstrap', usage: 'sks bootstrap [--install-scope global|project] [--local-only] [--json]', description: 'Initialize the current project, install SKS Codex App files/skills, check Context7/Codex App/
|
|
643
|
+
{ name: 'bootstrap', usage: 'sks bootstrap [--install-scope global|project] [--local-only] [--json]', description: 'Initialize the current project, install SKS Codex App files/skills, check Context7/Codex App/Codex CLI, and print ready true/false.' },
|
|
644
644
|
{ name: 'root', usage: 'sks root [--json]', description: 'Show whether SKS is using a project root or the per-user global SKS runtime root.' },
|
|
645
645
|
{ name: 'update', usage: 'sks update status|check|review|now|rollback [--refresh] [--version <version>] [--json] [--dry-run]', description: 'Inspect update-status.v3, review the exact staged operation, update the global package, or run guarded rollback.' },
|
|
646
646
|
{ name: 'uninstall', usage: 'sks uninstall [--dry-run] [--yes] [--keep-config] [--keep-data] [--purge-projects] [--json]', description: 'Remove SKS global skills, hooks, menu bar, state, temp files, and optional project residue while preserving user-owned content by default.' },
|
|
647
|
-
{ name: 'deps', usage: 'sks deps check [--json] [--yes]', description: 'Check Node/npm
|
|
647
|
+
{ name: 'deps', usage: 'sks deps check [--json] [--yes]', description: 'Check Node/npm and Codex CLI readiness; pass --yes to repair missing Codex CLI tooling when supported.' },
|
|
648
648
|
{ name: 'codex', usage: 'sks codex compatibility|version|update-status [--refresh]|update|doctor|schema|0.144 [--json]', description: 'Check Codex CLI compatibility/version/update status, run the official `codex update`, and inspect current manifest, capability, and hook-schema evidence.' },
|
|
649
649
|
{ name: 'codex-app', usage: 'sks codex-app [check|set-openrouter-key --api-key-stdin|use-openrouter --model <id>|openrouter-status|product-design|chrome-extension|pat status|remote-control]', description: 'Check Codex App install, OpenRouter provider activation, codex-lb key-entry guidance, Product Design plugin readiness, Codex Chrome Extension web verification readiness, PAT-safe status, first-party MCP/plugin readiness, and Codex CLI remote-control availability.' },
|
|
650
650
|
{ name: 'codex-native', usage: 'sks codex-native status|feature-broker|invocation-plan|init-deep [--json]', description: 'Inspect Codex Native feature broker readiness, invocation routing, pattern evidence, and managed memory setup.' },
|
|
651
651
|
{ name: 'hooks', usage: 'sks hooks explain|status|trust-report|replay|codex-validate|warning-check ... [--json]', description: 'Explain Codex hook events, validate vendored latest 10-event output schemas, replay fixtures, and enforce warning-zero SKS hook policies under the 0.134 compatibility matrix.' },
|
|
652
|
-
{ name: 'codex-lb', usage: 'sks codex-lb status|health|metrics|doctor|circuit|repair|setup ...', description: 'Configure, health-check, repair, and record circuit evidence for codex-lb provider auth without confusing ChatGPT OAuth and proxy keys.' },
|
|
652
|
+
{ name: 'codex-lb', usage: 'sks codex-lb status|connect-test|health|metrics|doctor|circuit|repair|setup ...', description: 'Configure, run a one-request connection proof, health-check, repair, and record circuit evidence for codex-lb provider auth without confusing ChatGPT OAuth and proxy keys.' },
|
|
653
653
|
{ name: 'remote', usage: 'sks remote readiness|machines|worker ... [--json]', description: 'Inspect official Codex Remote readiness and the allowlisted proof-aware SSH stdio worker surface.' },
|
|
654
|
-
{ name: '
|
|
655
|
-
{ name: '
|
|
656
|
-
{ name: 'auto-review', usage: 'sks auto-review status|enable|start [--high] | sks --Auto-review --high', description: 'Enable Codex automatic approval review and launch SKS Zellij with the auto-review profile.' },
|
|
654
|
+
{ name: 'mad-sks', usage: 'sks mad-sks plan|run|apply|sql|apply-migration|status|close|rollback-apply ... | sks --mad [--high]', description: 'Open or inspect MAD-SKS scoped permission workflows, merged SQL-plane execution, and the native Codex permission launcher.' },
|
|
655
|
+
{ name: 'auto-review', usage: 'sks auto-review status|enable|start [--high] | sks --Auto-review --high', description: 'Enable Codex automatic approval review and launch the native Codex session with the auto-review profile.' },
|
|
657
656
|
{ name: 'dollar-commands', usage: 'sks dollar-commands [--json]', description: 'List Codex App $ commands such as $sks-dfix and $sks-naruto.' },
|
|
658
657
|
{ name: 'fast-mode', usage: 'sks fast-mode on|off|status|clear [--project] [--json]', description: 'Toggle the global Codex Desktop GPT-5.6 Fast default used by $sks-fast-on/$sks-fast-off and keep project worker preference in sync; pass --project for project-local only.' },
|
|
659
658
|
{ name: 'with-local-llm', usage: 'sks with-local-llm on|off|status|set-model [--json]', description: 'Toggle the optional local Ollama worker backend used by $sks-with-local-llm-on/$sks-with-local-llm-off and eligible simple worker slices.' },
|
|
@@ -688,7 +687,7 @@ export const COMMAND_CATALOG = [
|
|
|
688
687
|
{ name: 'seo-geo-optimizer', usage: 'sks seo-geo-optimizer [seo|geo] doctor|audit|research|strategy|plan|apply|verify|status|rollback|fixture [mission|latest] [--mode seo|geo] [--target auto|website|docs|package] [--include-marketing] [--json]', description: 'Run the unified SEO/GEO optimizer on the shared search-visibility kernel with mode-specific gates, marketing research/strategy, safe apply, and proof.' },
|
|
689
688
|
{ name: 'research', usage: 'sks research prepare|run|status ...', description: 'Run long-form real research missions with xhigh agent Eureka ideas, debate, layered sources, paper, novelty, and falsification gates.' },
|
|
690
689
|
{ name: 'eval', usage: 'sks eval run|compare|thresholds ...', description: 'Run deterministic context-quality and performance evidence checks.' },
|
|
691
|
-
{ name: 'harness', usage: 'sks harness fixture|review [--json]', description: 'Run Harness Growth Factory fixtures for forgetting, skills, experiments, tool taxonomy, permissions,
|
|
690
|
+
{ name: 'harness', usage: 'sks harness fixture|review [--json]', description: 'Run Harness Growth Factory fixtures for forgetting, skills, experiments, tool taxonomy, permissions, and MultiAgentV2.' },
|
|
692
691
|
{ name: 'perf', usage: 'sks perf run|workflow|cold-start [--json] [--iterations N]', description: 'Measure structured GPT-5.6/SKS performance budgets, including cold-start, Proof Field workflow decisions, and fast-lane evidence.' },
|
|
693
692
|
{ name: 'bench', usage: 'sks bench core|route-fixtures|blackbox|trust-kernel [--json]', description: 'Measure core trust-kernel hot paths and write performance budget artifacts.' },
|
|
694
693
|
{ name: 'proof', usage: 'sks proof show|latest|validate|export|smoke [--json|--md]', description: 'Show, validate, export, or smoke-write the unified Completion Proof Engine surface.' },
|
|
@@ -702,7 +701,7 @@ export const COMMAND_CATALOG = [
|
|
|
702
701
|
{ name: 'wiki', usage: 'sks wiki coords|pack|refresh|publish|rebuild-index|validate|validate-shared|wrongness ...', description: 'Build, refresh, publish shared shards, rebuild ignored indexes, validate, and attach wrongness-memory context to RGBA/trig LLM Wiki packs with attention.use_first and attention.hydrate_first for compact recall plus source hydration.' },
|
|
703
702
|
{ name: 'memory', usage: 'sks memory build [--json] | sks memory gc [--dry-run]', description: 'Project TriWiki context-pack memory into managed AGENTS.md blocks or run bounded memory cleanup.' },
|
|
704
703
|
{ name: 'hproof', usage: 'sks hproof check [mission-id|latest]', description: 'Evaluate the H-Proof done gate for a mission.' },
|
|
705
|
-
{ name: 'naruto', usage: 'sks naruto run \"task\" [--agents N] [--max-threads N] [--trusted-project] [--json] | sks naruto status|subagents|proof [latest|M-...] [--json] | sks naruto parent-summary --mission M-... --stdin [--json]', description: 'Run or inspect the Codex official subagent workflow with a Sol Max parent and fixed Luna Max mechanical, Sol High implementation, Sol Max judgment, and Terra
|
|
704
|
+
{ name: 'naruto', usage: 'sks naruto run \"task\" [--agents N] [--max-threads N] [--trusted-project] [--json] | sks naruto status|subagents|proof [latest|M-...] [--json] | sks naruto parent-summary --mission M-... --stdin [--json]', description: 'Run or inspect the Codex official subagent workflow with a Sol Max parent and fixed Luna Max mechanical, Sol High implementation, Sol Max judgment, and Terra Max long-context/tool profiles, max_depth=1, and structured parent-thread completion evidence.' },
|
|
706
705
|
{ name: 'reasoning', usage: 'sks reasoning ["prompt"] [--json]', description: 'Show SKS temporary reasoning-effort routing: medium for simple tasks, high for logic, xhigh for research.' },
|
|
707
706
|
{ name: 'gx', usage: 'sks gx init|render|validate|drift|snapshot [name]', description: 'Create and verify deterministic SVG/HTML visual context cartridges.' },
|
|
708
707
|
{ name: 'profile', usage: 'sks profile show|set <model>', description: 'Inspect or set the current SKS model profile metadata.' },
|
|
@@ -1213,7 +1212,10 @@ export function narutoDecisionForRoute(route, prompt = '', profile = classifyTas
|
|
|
1213
1212
|
if (profile === 'passthrough' || profile === 'answer' || profile === 'tiny-change') {
|
|
1214
1213
|
return narutoRouteDecision('none', routeId, profile, `task_profile_${profile}_bypass`, true);
|
|
1215
1214
|
}
|
|
1216
|
-
if (profile === 'bounded-work'
|
|
1215
|
+
if (profile === 'bounded-work') {
|
|
1216
|
+
return narutoRouteDecision('none', routeId, profile, 'task_profile_bounded_work_parent_owned', false);
|
|
1217
|
+
}
|
|
1218
|
+
if (profile === 'parallel-read' || profile === 'parallel-write' || profile === 'high-risk') {
|
|
1217
1219
|
return narutoRouteDecision('generic_naruto', routeId, profile, `task_profile_${profile}_default_parallel`, false);
|
|
1218
1220
|
}
|
|
1219
1221
|
return narutoRouteDecision('none', routeId, profile, `task_profile_${profile}_bypass`, true);
|
|
@@ -1262,6 +1264,24 @@ export function looksLikeCodeChangingWork(prompt = '') {
|
|
|
1262
1264
|
return /\b(implement|build|make|add|edit|modify|change|fix|refactor|rewrite|migrate|create|delete|remove|rename|update|patch)\b/i.test(text)
|
|
1263
1265
|
|| /(코드|구현|개발|수정|변경|추가|삭제|해결|고쳐|바꿔|리팩터|마이그레이션)/i.test(text);
|
|
1264
1266
|
}
|
|
1267
|
+
export function classifyPromptExecutionEffect(prompt = '') {
|
|
1268
|
+
const text = String(prompt || '').trim();
|
|
1269
|
+
const action = /(해줘|해라|진행|실행|적용|바꿔|수정|설치|삭제|배포|인증|로그인)/i.test(text)
|
|
1270
|
+
|| /\b(configure|execute|apply|change|modify|install|delete|remove|deploy|publish|authenticate)\b|\blog\s*in\b|\bsign\s*in\b/i.test(text);
|
|
1271
|
+
if (!action)
|
|
1272
|
+
return 'read';
|
|
1273
|
+
if (/(삭제|제거|지워|delete|remove|uninstall|purge)/i.test(text))
|
|
1274
|
+
return 'delete';
|
|
1275
|
+
if (/(배포|출시|게시|deploy|publish|release)/i.test(text))
|
|
1276
|
+
return 'deploy';
|
|
1277
|
+
if (/(인증|로그인|로그아웃|재연결|authenticate|log\s*(?:in|out)|sign\s*(?:in|out)|reconnect)/i.test(text))
|
|
1278
|
+
return 'auth';
|
|
1279
|
+
if (/(보안|권한|서명|키\s*회전|security|permission|signing|rotate\s+key)/i.test(text))
|
|
1280
|
+
return 'security';
|
|
1281
|
+
if (/(설치|업그레이드|의존성|install|upgrade|dependenc)/i.test(text))
|
|
1282
|
+
return 'dependency';
|
|
1283
|
+
return 'write';
|
|
1284
|
+
}
|
|
1265
1285
|
export function looksLikeExecutionWork(prompt = '') {
|
|
1266
1286
|
const text = String(prompt || '');
|
|
1267
1287
|
return looksLikeCodeChangingWork(text)
|
|
@@ -1284,7 +1304,7 @@ export function subagentExecutionPolicyText(route, prompt = '') {
|
|
|
1284
1304
|
return [
|
|
1285
1305
|
'Codex subagent workflow: required for this explicit Naruto or parallel task.',
|
|
1286
1306
|
'The parent agent owns decomposition, integration, scoped verification, and the final answer.',
|
|
1287
|
-
'Delegate only genuinely independent slices. Use Luna Max only for tiny short-context mechanical work, Sol High for ordinary implementation, Sol Max for review/debug/planning/architecture/integration/risk judgment, and Terra
|
|
1307
|
+
'Delegate only genuinely independent slices. Use Luna Max only for tiny short-context mechanical work, Sol High for ordinary implementation, Sol Max for review/debug/planning/architecture/integration/risk judgment, and Terra Max for long-context or Computer Use, Browser/Chrome, and image-generation execution.',
|
|
1288
1308
|
'Parallel writes require disjoint paths; serialize overlapping paths, prohibit nested delegation, avoid duplicate work, wait for all requested agent threads, and close completed threads after collecting results.',
|
|
1289
1309
|
'Completion evidence comes from official SubagentStart/SubagentStop events plus the parent integration summary, not process counts or PID evidence.'
|
|
1290
1310
|
].join(' ');
|
|
@@ -1297,7 +1317,7 @@ export function routeReasoning(route, prompt = '') {
|
|
|
1297
1317
|
if (/(?:^|\s)sks\s+--mad\b|(?:^|\s)--mad\b|\$MAD-SKS\b|\bmad-sks\b|\bmadsks\b/i.test(text))
|
|
1298
1318
|
return reasoning('xhigh', 'mad_sks_or_mad_launch_default');
|
|
1299
1319
|
if (route?.id === 'Naruto')
|
|
1300
|
-
return narutoRouteReasoning(text);
|
|
1320
|
+
return narutoRouteReasoning(route, text);
|
|
1301
1321
|
if (route?.id === 'Research' || route?.id === 'AutoResearch')
|
|
1302
1322
|
return reasoning('xhigh', 'research_or_experiment_route');
|
|
1303
1323
|
if (route?.id === 'SuperSearch')
|
|
@@ -1316,8 +1336,19 @@ export function routeReasoning(route, prompt = '') {
|
|
|
1316
1336
|
return reasoning('low', 'route_policy_low');
|
|
1317
1337
|
return reasoning('medium', 'simple_fulfillment');
|
|
1318
1338
|
}
|
|
1319
|
-
function narutoRouteReasoning(
|
|
1320
|
-
|
|
1339
|
+
function narutoRouteReasoning(route, text = '') {
|
|
1340
|
+
if (route?.explicit_invocation !== false)
|
|
1341
|
+
return reasoning('max', 'explicit_naruto_parent_sol_max');
|
|
1342
|
+
const profile = isTaskProfile(route?.task_profile)
|
|
1343
|
+
? route.task_profile
|
|
1344
|
+
: classifyTaskProfile(text);
|
|
1345
|
+
if (profile === 'parallel-read' || profile === 'parallel-write' || profile === 'high-risk') {
|
|
1346
|
+
return reasoning('max', `implicit_naruto_${profile}_sol_max`);
|
|
1347
|
+
}
|
|
1348
|
+
if (profile === 'tiny-change' || profile === 'passthrough' || profile === 'answer') {
|
|
1349
|
+
return reasoning('low', `implicit_naruto_${profile}_lightweight`);
|
|
1350
|
+
}
|
|
1351
|
+
return reasoning('medium', 'implicit_naruto_bounded_parent_medium');
|
|
1321
1352
|
}
|
|
1322
1353
|
export function reasoningProfileName(effort) {
|
|
1323
1354
|
if (effort === 'low')
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { nowIso, sha256 } from '../fsx.js';
|
|
2
|
+
export const EXECUTION_CONTROL_SCHEMA = 'sks.execution-control.v1';
|
|
3
|
+
const MAX_TRACKED_IDEMPOTENCY_KEYS = 128;
|
|
4
|
+
export function normalizeExecutionControlBudget(input = {}) {
|
|
5
|
+
return {
|
|
6
|
+
max_attempts: boundedInteger(input.max_attempts, 1, 10_000, 1),
|
|
7
|
+
max_elapsed_ms: boundedInteger(input.max_elapsed_ms, 1, 7 * 24 * 60 * 60 * 1000, 30 * 60 * 1000),
|
|
8
|
+
max_tool_calls: nullableBoundedInteger(input.max_tool_calls, 1, 1_000_000),
|
|
9
|
+
max_tokens: nullableBoundedInteger(input.max_tokens, 1, Number.MAX_SAFE_INTEGER),
|
|
10
|
+
max_no_progress: boundedInteger(input.max_no_progress, 1, 100, 2)
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function normalizeExecutionControlState(value, at = nowIso()) {
|
|
14
|
+
const row = record(value);
|
|
15
|
+
if (row?.schema !== EXECUTION_CONTROL_SCHEMA)
|
|
16
|
+
return newExecutionControlState(at);
|
|
17
|
+
const status = row.status === 'completed' || row.status === 'stopped' ? row.status : 'running';
|
|
18
|
+
const stopReason = isExecutionStopReason(row.stop_reason) ? row.stop_reason : null;
|
|
19
|
+
return {
|
|
20
|
+
schema: EXECUTION_CONTROL_SCHEMA,
|
|
21
|
+
status,
|
|
22
|
+
stop_reason: status === 'running' ? null : stopReason,
|
|
23
|
+
stop_detail: status === 'running' ? null : nonEmptyString(row.stop_detail),
|
|
24
|
+
created_at: nonEmptyString(row.created_at) || at,
|
|
25
|
+
updated_at: nonEmptyString(row.updated_at) || at,
|
|
26
|
+
attempts: nonNegativeInteger(row.attempts),
|
|
27
|
+
elapsed_ms: nonNegativeInteger(row.elapsed_ms),
|
|
28
|
+
tool_calls: nonNegativeInteger(row.tool_calls),
|
|
29
|
+
tokens: nonNegativeInteger(row.tokens),
|
|
30
|
+
no_progress_streak: nonNegativeInteger(row.no_progress_streak),
|
|
31
|
+
last_progress_fingerprint: nonEmptyString(row.last_progress_fingerprint),
|
|
32
|
+
seen_idempotency_keys: uniqueStrings(row.seen_idempotency_keys).slice(-MAX_TRACKED_IDEMPOTENCY_KEYS)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function preflightExecutionControl(current, rawBudget, at = nowIso()) {
|
|
36
|
+
const budget = normalizeExecutionControlBudget(rawBudget);
|
|
37
|
+
let state = normalizeExecutionControlState(current, at);
|
|
38
|
+
if (state.status !== 'running')
|
|
39
|
+
return decision(false, state, budget);
|
|
40
|
+
if (state.elapsed_ms >= budget.max_elapsed_ms)
|
|
41
|
+
state = stopExecutionControl(state, 'time_budget_exhausted', null, at);
|
|
42
|
+
else if (budget.max_tool_calls !== null && state.tool_calls >= budget.max_tool_calls)
|
|
43
|
+
state = stopExecutionControl(state, 'tool_budget_exhausted', null, at);
|
|
44
|
+
else if (budget.max_tokens !== null && state.tokens >= budget.max_tokens)
|
|
45
|
+
state = stopExecutionControl(state, 'token_budget_exhausted', null, at);
|
|
46
|
+
else if (state.attempts >= budget.max_attempts)
|
|
47
|
+
state = stopExecutionControl(state, 'attempt_budget_exhausted', null, at);
|
|
48
|
+
return decision(state.status === 'running', state, budget);
|
|
49
|
+
}
|
|
50
|
+
export function recordExecutionObservation(current, rawBudget, observation, at = nowIso()) {
|
|
51
|
+
const budget = normalizeExecutionControlBudget(rawBudget);
|
|
52
|
+
const state = normalizeExecutionControlState(current, at);
|
|
53
|
+
if (state.status !== 'running')
|
|
54
|
+
return state;
|
|
55
|
+
const fingerprint = executionProgressFingerprint(observation.fingerprint);
|
|
56
|
+
const idempotencyKey = nonEmptyString(observation.idempotencyKey);
|
|
57
|
+
const duplicate = Boolean(idempotencyKey && state.seen_idempotency_keys.includes(idempotencyKey));
|
|
58
|
+
const fingerprintChanged = state.last_progress_fingerprint === null || state.last_progress_fingerprint !== fingerprint;
|
|
59
|
+
const madeProgress = observation.madeProgress === true
|
|
60
|
+
|| (observation.madeProgress !== false && fingerprintChanged && !duplicate);
|
|
61
|
+
const noProgressStreak = madeProgress ? 0 : state.no_progress_streak + 1;
|
|
62
|
+
const seenIdempotencyKeys = idempotencyKey && !duplicate
|
|
63
|
+
? [...state.seen_idempotency_keys, idempotencyKey].slice(-MAX_TRACKED_IDEMPOTENCY_KEYS)
|
|
64
|
+
: [...state.seen_idempotency_keys];
|
|
65
|
+
let next = {
|
|
66
|
+
...state,
|
|
67
|
+
updated_at: at,
|
|
68
|
+
attempts: state.attempts + (observation.countAttempt === false ? 0 : 1),
|
|
69
|
+
elapsed_ms: state.elapsed_ms + nonNegativeInteger(observation.elapsedMs),
|
|
70
|
+
tool_calls: state.tool_calls + nonNegativeInteger(observation.toolCalls),
|
|
71
|
+
tokens: state.tokens + nonNegativeInteger(observation.tokens),
|
|
72
|
+
no_progress_streak: noProgressStreak,
|
|
73
|
+
last_progress_fingerprint: fingerprint,
|
|
74
|
+
seen_idempotency_keys: seenIdempotencyKeys
|
|
75
|
+
};
|
|
76
|
+
if (observation.userInputRequired === true) {
|
|
77
|
+
return stopExecutionControl(next, 'user_input_required', 'execution cannot advance without user input', at);
|
|
78
|
+
}
|
|
79
|
+
if (next.no_progress_streak >= budget.max_no_progress) {
|
|
80
|
+
return stopExecutionControl(next, 'no_progress', `same semantic result repeated ${next.no_progress_streak} time(s)`, at);
|
|
81
|
+
}
|
|
82
|
+
if (next.elapsed_ms >= budget.max_elapsed_ms)
|
|
83
|
+
return stopExecutionControl(next, 'time_budget_exhausted', null, at);
|
|
84
|
+
if (budget.max_tool_calls !== null && next.tool_calls >= budget.max_tool_calls)
|
|
85
|
+
return stopExecutionControl(next, 'tool_budget_exhausted', null, at);
|
|
86
|
+
if (budget.max_tokens !== null && next.tokens >= budget.max_tokens)
|
|
87
|
+
return stopExecutionControl(next, 'token_budget_exhausted', null, at);
|
|
88
|
+
if (next.attempts >= budget.max_attempts)
|
|
89
|
+
return stopExecutionControl(next, 'attempt_budget_exhausted', null, at);
|
|
90
|
+
return next;
|
|
91
|
+
}
|
|
92
|
+
export function completeExecutionControl(current, verified, detail = null, at = nowIso()) {
|
|
93
|
+
const state = normalizeExecutionControlState(current, at);
|
|
94
|
+
if (!verified)
|
|
95
|
+
return stopExecutionControl(state, 'unverified_completion', detail || 'completion lacked applicable runtime proof', at);
|
|
96
|
+
return {
|
|
97
|
+
...state,
|
|
98
|
+
status: 'completed',
|
|
99
|
+
stop_reason: 'completed',
|
|
100
|
+
stop_detail: detail,
|
|
101
|
+
no_progress_streak: 0,
|
|
102
|
+
updated_at: at
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export function stopExecutionControl(current, reason, detail = null, at = nowIso()) {
|
|
106
|
+
const state = normalizeExecutionControlState(current, at);
|
|
107
|
+
return {
|
|
108
|
+
...state,
|
|
109
|
+
status: reason === 'completed' ? 'completed' : 'stopped',
|
|
110
|
+
stop_reason: reason,
|
|
111
|
+
stop_detail: detail,
|
|
112
|
+
updated_at: at
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
export function resumeExecutionControl(current, rawBudget, currentFingerprint, at = nowIso()) {
|
|
116
|
+
const budget = normalizeExecutionControlBudget(rawBudget);
|
|
117
|
+
const state = normalizeExecutionControlState(current, at);
|
|
118
|
+
if (state.status === 'completed')
|
|
119
|
+
return state;
|
|
120
|
+
const hasBudget = state.attempts < budget.max_attempts
|
|
121
|
+
&& state.elapsed_ms < budget.max_elapsed_ms
|
|
122
|
+
&& (budget.max_tool_calls === null || state.tool_calls < budget.max_tool_calls)
|
|
123
|
+
&& (budget.max_tokens === null || state.tokens < budget.max_tokens);
|
|
124
|
+
if (!hasBudget)
|
|
125
|
+
return state;
|
|
126
|
+
const fingerprintChanged = state.last_progress_fingerprint !== executionProgressFingerprint(currentFingerprint);
|
|
127
|
+
const budgetExpanded = ['attempt_budget_exhausted', 'tool_budget_exhausted', 'token_budget_exhausted'].includes(String(state.stop_reason || ''));
|
|
128
|
+
if (!fingerprintChanged && !budgetExpanded)
|
|
129
|
+
return state;
|
|
130
|
+
return {
|
|
131
|
+
...state,
|
|
132
|
+
status: 'running',
|
|
133
|
+
stop_reason: null,
|
|
134
|
+
stop_detail: null,
|
|
135
|
+
no_progress_streak: fingerprintChanged ? 0 : state.no_progress_streak,
|
|
136
|
+
updated_at: at
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
export function executionProgressFingerprint(value) {
|
|
140
|
+
return `sha256:${sha256(stableJson(value))}`;
|
|
141
|
+
}
|
|
142
|
+
function newExecutionControlState(at) {
|
|
143
|
+
return {
|
|
144
|
+
schema: EXECUTION_CONTROL_SCHEMA,
|
|
145
|
+
status: 'running',
|
|
146
|
+
stop_reason: null,
|
|
147
|
+
stop_detail: null,
|
|
148
|
+
created_at: at,
|
|
149
|
+
updated_at: at,
|
|
150
|
+
attempts: 0,
|
|
151
|
+
elapsed_ms: 0,
|
|
152
|
+
tool_calls: 0,
|
|
153
|
+
tokens: 0,
|
|
154
|
+
no_progress_streak: 0,
|
|
155
|
+
last_progress_fingerprint: null,
|
|
156
|
+
seen_idempotency_keys: []
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function decision(allowed, state, budget) {
|
|
160
|
+
return {
|
|
161
|
+
allowed,
|
|
162
|
+
state,
|
|
163
|
+
stop_reason: state.stop_reason,
|
|
164
|
+
remaining_time_ms: Math.max(0, budget.max_elapsed_ms - state.elapsed_ms),
|
|
165
|
+
remaining_attempts: Math.max(0, budget.max_attempts - state.attempts)
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function stableJson(value) {
|
|
169
|
+
if (value === undefined)
|
|
170
|
+
return '"__undefined__"';
|
|
171
|
+
if (typeof value === 'number' && !Number.isFinite(value))
|
|
172
|
+
return JSON.stringify(String(value));
|
|
173
|
+
if (Array.isArray(value))
|
|
174
|
+
return `[${value.map(stableJson).join(',')}]`;
|
|
175
|
+
if (value && typeof value === 'object') {
|
|
176
|
+
const row = value;
|
|
177
|
+
return `{${Object.keys(row).sort().map((key) => `${JSON.stringify(key)}:${stableJson(row[key])}`).join(',')}}`;
|
|
178
|
+
}
|
|
179
|
+
const encoded = JSON.stringify(value);
|
|
180
|
+
return encoded === undefined ? '"__unserializable__"' : encoded;
|
|
181
|
+
}
|
|
182
|
+
function record(value) {
|
|
183
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
|
|
184
|
+
}
|
|
185
|
+
function nonNegativeInteger(value) {
|
|
186
|
+
const parsed = Number(value);
|
|
187
|
+
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
188
|
+
return 0;
|
|
189
|
+
return Math.min(Number.MAX_SAFE_INTEGER, Math.floor(parsed));
|
|
190
|
+
}
|
|
191
|
+
function boundedInteger(value, min, max, fallback) {
|
|
192
|
+
const parsed = Number(value);
|
|
193
|
+
if (!Number.isFinite(parsed))
|
|
194
|
+
return fallback;
|
|
195
|
+
return Math.max(min, Math.min(max, Math.floor(parsed)));
|
|
196
|
+
}
|
|
197
|
+
function nullableBoundedInteger(value, min, max) {
|
|
198
|
+
if (value === null || value === undefined || value === '')
|
|
199
|
+
return null;
|
|
200
|
+
const parsed = Number(value);
|
|
201
|
+
if (!Number.isFinite(parsed))
|
|
202
|
+
return null;
|
|
203
|
+
return Math.max(min, Math.min(max, Math.floor(parsed)));
|
|
204
|
+
}
|
|
205
|
+
function nonEmptyString(value) {
|
|
206
|
+
const text = String(value || '').trim();
|
|
207
|
+
return text || null;
|
|
208
|
+
}
|
|
209
|
+
function uniqueStrings(value) {
|
|
210
|
+
if (!Array.isArray(value))
|
|
211
|
+
return [];
|
|
212
|
+
return [...new Set(value.map(nonEmptyString).filter((item) => Boolean(item)))];
|
|
213
|
+
}
|
|
214
|
+
function isExecutionStopReason(value) {
|
|
215
|
+
return new Set([
|
|
216
|
+
'completed',
|
|
217
|
+
'attempt_budget_exhausted',
|
|
218
|
+
'time_budget_exhausted',
|
|
219
|
+
'tool_budget_exhausted',
|
|
220
|
+
'token_budget_exhausted',
|
|
221
|
+
'no_progress',
|
|
222
|
+
'user_input_required',
|
|
223
|
+
'unverified_completion',
|
|
224
|
+
'explicit_stop'
|
|
225
|
+
]).has(String(value || ''));
|
|
226
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { sha256 } from '../../fsx.js';
|
|
3
|
+
export function initialProgressRecoveryState(integritySnapshotHash) {
|
|
4
|
+
if (!/^[a-f0-9]{64}$/.test(integritySnapshotHash))
|
|
5
|
+
throw new Error('progress_integrity_snapshot_invalid');
|
|
6
|
+
return {
|
|
7
|
+
schema: 'sks.progress-recovery-state.v1', status: 'running', progress: [], last_progress_at: null,
|
|
8
|
+
warning_time_budget_exceeded: false, pause_cause: null, pause_reason: null, retry_count: 0,
|
|
9
|
+
integrity_snapshot_hash: integritySnapshotHash, resume_token_hash: null
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function recordProgress(state, signal) {
|
|
13
|
+
if (state.status !== 'running')
|
|
14
|
+
throw new Error('progress_signal_requires_running_state');
|
|
15
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$/.test(signal.id))
|
|
16
|
+
throw new Error('progress_signal_id_invalid');
|
|
17
|
+
if (!/^[a-f0-9]{64}$/.test(signal.digest) || !Number.isFinite(Date.parse(signal.observed_at)))
|
|
18
|
+
throw new Error('progress_signal_invalid');
|
|
19
|
+
const byIdentity = new Map(state.progress.map((entry) => [`${entry.kind}:${entry.id}:${entry.digest}`, entry]));
|
|
20
|
+
byIdentity.set(`${signal.kind}:${signal.id}:${signal.digest}`, signal);
|
|
21
|
+
return { ...state, progress: [...byIdentity.values()], last_progress_at: signal.observed_at };
|
|
22
|
+
}
|
|
23
|
+
export function applyTimeBudgetWarning(state, input) {
|
|
24
|
+
if (input.budgetMs <= 0)
|
|
25
|
+
throw new Error('progress_time_budget_invalid');
|
|
26
|
+
return { ...state, warning_time_budget_exceeded: input.nowMs - input.startedAtMs > input.budgetMs };
|
|
27
|
+
}
|
|
28
|
+
export function classifyRecoveryCause(error) {
|
|
29
|
+
const code = safeCode(error);
|
|
30
|
+
if (/^(?:econnreset|econnrefused|etimedout|enotfound|network_|upstream_network_)/.test(code))
|
|
31
|
+
return { cause: 'network', reason: code };
|
|
32
|
+
if (/^(?:auth_|credential_|unauthorized|forbidden)/.test(code))
|
|
33
|
+
return { cause: 'auth', reason: code };
|
|
34
|
+
if (/^mode_/.test(code))
|
|
35
|
+
return { cause: 'mode', reason: code };
|
|
36
|
+
if (/^account_/.test(code))
|
|
37
|
+
return { cause: 'account', reason: code };
|
|
38
|
+
if (/^(?:external_config_|catalog_)/.test(code))
|
|
39
|
+
return { cause: 'external-config', reason: code };
|
|
40
|
+
if (/^integrity_/.test(code))
|
|
41
|
+
return { cause: 'integrity', reason: code };
|
|
42
|
+
return { cause: 'unknown', reason: 'unknown_failure' };
|
|
43
|
+
}
|
|
44
|
+
export async function runWithProgressRecovery(input) {
|
|
45
|
+
const maxRetries = Math.max(0, Math.min(2, input.maxNetworkRetries ?? 2));
|
|
46
|
+
let state = input.state;
|
|
47
|
+
let firstNetworkReason = null;
|
|
48
|
+
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
|
|
49
|
+
try {
|
|
50
|
+
const value = await input.port.run(attempt);
|
|
51
|
+
return { value, state: { ...state, status: 'completed', pause_cause: null, pause_reason: null, resume_token_hash: null } };
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
const failure = input.port.classify(error);
|
|
55
|
+
const sameNetworkCause = failure.cause === 'network' && (firstNetworkReason === null || firstNetworkReason === failure.reason);
|
|
56
|
+
if (failure.cause === 'network' && firstNetworkReason === null)
|
|
57
|
+
firstNetworkReason = failure.reason;
|
|
58
|
+
if (sameNetworkCause && attempt < maxRetries) {
|
|
59
|
+
state = { ...state, retry_count: attempt + 1 };
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
return { value: null, state: pauseState(state, failure.cause, failure.reason, attempt) };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { value: null, state: pauseState(state, 'unknown', 'retry_loop_exhausted', maxRetries) };
|
|
66
|
+
}
|
|
67
|
+
export function issueManualResume(state) {
|
|
68
|
+
if (state.status !== 'paused')
|
|
69
|
+
throw new Error('progress_resume_requires_paused_state');
|
|
70
|
+
const token = randomBytes(24).toString('base64url');
|
|
71
|
+
return { state: { ...state, resume_token_hash: sha256(token) }, token };
|
|
72
|
+
}
|
|
73
|
+
export function confirmManualResume(state, token) {
|
|
74
|
+
if (state.status !== 'paused' || !state.resume_token_hash || sha256(token) !== state.resume_token_hash) {
|
|
75
|
+
throw new Error('progress_resume_token_invalid');
|
|
76
|
+
}
|
|
77
|
+
return { ...state, status: 'running', pause_cause: null, pause_reason: null, resume_token_hash: null };
|
|
78
|
+
}
|
|
79
|
+
function pauseState(state, cause, reason, retryCount) {
|
|
80
|
+
return { ...state, status: 'paused', pause_cause: cause, pause_reason: safeReason(reason), retry_count: retryCount, resume_token_hash: null };
|
|
81
|
+
}
|
|
82
|
+
function safeCode(error) {
|
|
83
|
+
const raw = error instanceof Error ? error.message : String(error || '');
|
|
84
|
+
const normalized = raw.trim().toLowerCase();
|
|
85
|
+
return /^[a-z][a-z0-9_]{1,99}$/.test(normalized) ? normalized : 'unknown_failure';
|
|
86
|
+
}
|
|
87
|
+
function safeReason(value) {
|
|
88
|
+
return /^[a-z][a-z0-9_]{1,99}$/.test(value) ? value : 'unknown_failure';
|
|
89
|
+
}
|
|
@@ -15,9 +15,11 @@ const STRONG_DATABASE_DOMAIN_RE = /\b(?:SQL|Supabase|Postgres|PostgreSQL|RLS|Pri
|
|
|
15
15
|
const GENERIC_DATABASE_DOMAIN_RE = /\bDB\b|디비/i;
|
|
16
16
|
const DATABASE_WORK_RE = /\b(?:apply|execute|run|fix|change|modify|migrate|audit|review|inspect|analy[sz]e|query|seed|backfill|optimi[sz]e|create|alter|drop|truncate|update|delete|repair)\b|적용|실행|수정|변경|검수|검토|점검|분석|조회|쿼리|시드|백필|최적화|생성|추가|삭제|복구|만들어/i;
|
|
17
17
|
const DATABASE_CONTROL_SURFACE_META_RE = /\bsks\s+db\b|\b(?:db|database|migrate|migrations?)\b[\s\S]{0,48}\b(?:command|cli|route|routing|parser|classifier|regex|help|usage|topic|docs?|documentation|constant|keyword|alias)\b|\b(?:command|cli|route|routing|parser|classifier|regex|help|usage|topic|docs?|documentation|constant|keyword|alias)\b[\s\S]{0,48}\b(?:db|database|migrate|migrations?)\b|(?:db|디비|데이터베이스|migration|migrate|마이그레이션)\s*(?:커맨드|명령|명령어|CLI|라우트|라우팅|파서|분류기|정규식|도움말|헬프|사용법|토픽|문서|상수|키워드|별칭)|(?:커맨드|명령|명령어|CLI|라우트|라우팅|파서|분류기|정규식|도움말|헬프|사용법|토픽|문서|상수|키워드|별칭)[\s\S]{0,32}(?:db|디비|데이터베이스|migration|migrate|마이그레이션)/i;
|
|
18
|
-
const PARALLEL_CUE_RE = /\b(parallel|subagents?|one agent per|fan out|
|
|
18
|
+
const PARALLEL_CUE_RE = /\b(parallel|subagents?|one agent per|fan out|independent slices?|naruto)\b|병렬|하위\s*에이전트|서브\s*에이전트|나루토|분담/i;
|
|
19
19
|
const CHANGE_RE = /\b(fix|implement|implementation|change|edit|add|remove|delete|drop|modify|refactor|build|create|write|update|rename|rewrite|patch|apply|execute|repair|resolve|solve|publish|release|deploy|migrate)\b|\bwork\s+on\b|고쳐|고치|수정|변경|추가|삭제|구현|리팩터|작성|생성|만들어|업데이트|적용|실행|해결|이름\s*변경|배포|출시|마이그레이션/i;
|
|
20
|
+
const BOUNDED_READ_WORK_RE = /\b(audit|review|inspect|analy[sz]e|diagnose|trace|map|verify|test|check|investigate|evaluate)\b|감사|검토|점검|분석|진단|추적|매핑|검증|테스트|조사|평가/i;
|
|
20
21
|
const TINY_CHANGE_RE = /\b(typo|copy|wording|label|spacing|whitespace|punctuation|spelling|one[-\s]?line|single[-\s]?(?:line|word)|rename only)\b|오타|문구|라벨|띄어쓰기|공백|맞춤법|구두점|한\s*줄|단어\s*하나|이름만\s*변경/i;
|
|
22
|
+
const NON_RUNTIME_TINY_SURFACE_RE = /\b(copy|wording|label|spacing|whitespace|punctuation|spelling|readme|docs?|documentation|comment)\b|문구|라벨|띄어쓰기|공백|맞춤법|구두점|문서|주석/i;
|
|
21
23
|
const EXPLANATION_QUESTION_RE = /^(how\s+(?:do|can|should|would)\s+(?:i|we|you)\b|what\b|why\b|when\b|where\b|which\b|explain\b|tell me how\b)|(?:어떻게|무엇|뭐가|왜|언제|어디|방법|설명)(?:.*(?:인가요|일까요|하나요|해요|할까|\?))?$/i;
|
|
22
24
|
const DIRECT_REQUEST_RE = /^(please\s+|can you\s+|could you\s+|would you\s+)|(?:해줘|해주세요|해\s*주세요|바꿔줘|고쳐줘|수정해줘|구현해줘)/i;
|
|
23
25
|
const EXPLANATION_REQUEST_RE = /^(?:can|could|would) you explain\b|(?:설명|알려)\s*(?:해\s*줘|해\s*주세요|해달라|줘)\s*[.!?]*$/i;
|
|
@@ -27,7 +29,11 @@ export function classifyTaskProfile(prompt) {
|
|
|
27
29
|
return 'passthrough';
|
|
28
30
|
if (looksLikeExplanationQuestion(text))
|
|
29
31
|
return 'answer';
|
|
30
|
-
|
|
32
|
+
const databaseWork = looksLikeDatabaseWorkRequest(text);
|
|
33
|
+
const highRiskMutation = databaseWork || (CHANGE_RE.test(text) && NON_DATABASE_HIGH_RISK_RE.test(text));
|
|
34
|
+
if (looksLikeTinyChange(text) && (!highRiskMutation || NON_RUNTIME_TINY_SURFACE_RE.test(text)))
|
|
35
|
+
return 'tiny-change';
|
|
36
|
+
if (highRiskMutation)
|
|
31
37
|
return 'high-risk';
|
|
32
38
|
if (PARALLEL_CUE_RE.test(text) && CHANGE_RE.test(text))
|
|
33
39
|
return 'parallel-write';
|
|
@@ -35,10 +41,10 @@ export function classifyTaskProfile(prompt) {
|
|
|
35
41
|
return 'parallel-read';
|
|
36
42
|
if (DATABASE_CONTROL_SURFACE_META_RE.test(text) && DATABASE_WORK_RE.test(text))
|
|
37
43
|
return 'bounded-work';
|
|
38
|
-
if (looksLikeTinyChange(text))
|
|
39
|
-
return 'tiny-change';
|
|
40
44
|
if (CHANGE_RE.test(text))
|
|
41
45
|
return 'bounded-work';
|
|
46
|
+
if (BOUNDED_READ_WORK_RE.test(text))
|
|
47
|
+
return 'bounded-work';
|
|
42
48
|
return 'answer';
|
|
43
49
|
}
|
|
44
50
|
export function gateProfileForTask(profileOrPrompt) {
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
export function chooseVerificationBudget(input) {
|
|
2
|
+
const changedFiles = input.changedFiles.map((file) => String(file || '').replace(/\\/g, '/'));
|
|
3
|
+
const failedChecks = (input.failedChecks || []).filter(Boolean);
|
|
4
|
+
const releaseSurface = changedFiles.some((file) => /(?:^|\/)(?:package(?:-lock)?\.json|CHANGELOG\.md|\.github\/workflows\/|src\/core\/release\/|src\/scripts\/(?:prepublish|publish|release))/.test(file));
|
|
2
5
|
if (input.taskProfile === 'passthrough')
|
|
3
6
|
return 'none';
|
|
4
7
|
if (input.taskProfile === 'answer')
|
|
5
8
|
return 'none';
|
|
9
|
+
if (releaseSurface)
|
|
10
|
+
return 'release';
|
|
11
|
+
if (failedChecks.length > 0)
|
|
12
|
+
return input.taskProfile === 'high-risk' ? 'release' : 'confidence';
|
|
6
13
|
if (input.taskProfile === 'tiny-change')
|
|
7
|
-
return 'single-check';
|
|
14
|
+
return changedFiles.length > 1 ? 'affected' : 'single-check';
|
|
8
15
|
if (input.taskProfile === 'high-risk')
|
|
9
16
|
return 'confidence';
|
|
17
|
+
if (changedFiles.length >= 8)
|
|
18
|
+
return 'confidence';
|
|
10
19
|
return 'affected';
|
|
11
20
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { canonicalJson } from '../../json/canonical.js';
|
|
3
|
+
export function buildIntentContract(input) {
|
|
4
|
+
const highRiskEffect = ['auth', 'security', 'delete', 'deploy', 'dependency'].includes(input.effect);
|
|
5
|
+
let risk = highRiskEffect ? 'HEAVY' : 'FAST';
|
|
6
|
+
if (input.requestedRisk === 'HEAVY')
|
|
7
|
+
risk = 'HEAVY';
|
|
8
|
+
if (input.requestedRisk === 'ULTRA') {
|
|
9
|
+
if (!input.explicitUltraOptIn)
|
|
10
|
+
throw new Error('intent_ultra_requires_explicit_opt_in');
|
|
11
|
+
risk = 'ULTRA';
|
|
12
|
+
}
|
|
13
|
+
const base = {
|
|
14
|
+
schema: 'sks.intent-contract.v1',
|
|
15
|
+
natural_language_effect: normalizeEffectText(input.naturalLanguageEffect),
|
|
16
|
+
effect: input.effect,
|
|
17
|
+
observed_changed_paths: [...new Set((input.observedChangedPaths || []).map(normalizeRelativePath))].sort(),
|
|
18
|
+
canonical_command: normalizeCommand(input.canonicalCommand),
|
|
19
|
+
target_hashes: [...new Set(input.targetHashes)].sort(),
|
|
20
|
+
policy_version: safeIdentifier(input.policyVersion, 'intent_policy_version_invalid'),
|
|
21
|
+
mode_snapshot: input.modeSnapshot,
|
|
22
|
+
evidence_state: input.evidenceState,
|
|
23
|
+
retry_budget: Math.max(0, Math.min(2, input.retryBudget ?? 0)),
|
|
24
|
+
risk,
|
|
25
|
+
risk_reason: highRiskEffect ? `effect_${input.effect}_requires_heavy` : risk === 'FAST' ? 'effect_is_fast_eligible' : 'user_requested_risk_raise',
|
|
26
|
+
force: input.force === true
|
|
27
|
+
};
|
|
28
|
+
if (!base.target_hashes.length || base.target_hashes.some((hash) => !/^[a-f0-9]{64}$/.test(hash)))
|
|
29
|
+
throw new Error('intent_target_hash_invalid');
|
|
30
|
+
const contract = { ...base, contract_hash: stableHash(base) };
|
|
31
|
+
return deepFreeze(contract);
|
|
32
|
+
}
|
|
33
|
+
export function decideIntentReplay(previous, current) {
|
|
34
|
+
const reasons = [];
|
|
35
|
+
if (previous.policy_version !== current.policy_version)
|
|
36
|
+
reasons.push('policy_version_changed');
|
|
37
|
+
if (previous.mode_snapshot !== current.mode_snapshot)
|
|
38
|
+
reasons.push('mode_snapshot_changed');
|
|
39
|
+
if (JSON.stringify(previous.target_hashes) !== JSON.stringify(current.target_hashes))
|
|
40
|
+
reasons.push('target_hash_changed');
|
|
41
|
+
if (previous.effect !== current.effect || previous.canonical_command !== current.canonical_command)
|
|
42
|
+
reasons.push('intent_effect_changed');
|
|
43
|
+
if (reasons.length)
|
|
44
|
+
return { action: 'replan', reasons };
|
|
45
|
+
if (current.evidence_state !== 'valid') {
|
|
46
|
+
if (current.risk === 'FAST')
|
|
47
|
+
return { action: 'refresh_direct_evidence', reasons: ['evidence_expired_or_missing'] };
|
|
48
|
+
return { action: 'blocked', reasons: ['heavy_evidence_required'] };
|
|
49
|
+
}
|
|
50
|
+
return { action: 'reuse', reasons: [] };
|
|
51
|
+
}
|
|
52
|
+
export function terminalStateForVerification(input) {
|
|
53
|
+
if (input.paused)
|
|
54
|
+
return 'paused';
|
|
55
|
+
if (!input.executionOk)
|
|
56
|
+
return 'failed';
|
|
57
|
+
if (input.verificationOk !== true)
|
|
58
|
+
return 'unverified';
|
|
59
|
+
return 'completed';
|
|
60
|
+
}
|
|
61
|
+
function normalizeEffectText(value) {
|
|
62
|
+
const text = String(value || '').trim().replace(/\s+/g, ' ');
|
|
63
|
+
if (!text || text.length > 1000)
|
|
64
|
+
throw new Error('intent_effect_text_invalid');
|
|
65
|
+
return text;
|
|
66
|
+
}
|
|
67
|
+
function normalizeRelativePath(value) {
|
|
68
|
+
const normalized = String(value || '').replace(/\\/g, '/').replace(/^\.\//, '');
|
|
69
|
+
if (!normalized || normalized.startsWith('/') || normalized.split('/').includes('..'))
|
|
70
|
+
throw new Error('intent_changed_path_invalid');
|
|
71
|
+
return normalized;
|
|
72
|
+
}
|
|
73
|
+
function normalizeCommand(value) {
|
|
74
|
+
const command = String(value || '').trim().replace(/\s+/g, ' ');
|
|
75
|
+
if (!/^sks(?:\s|$)/.test(command))
|
|
76
|
+
throw new Error('intent_canonical_command_invalid');
|
|
77
|
+
return command;
|
|
78
|
+
}
|
|
79
|
+
function safeIdentifier(value, code) {
|
|
80
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$/.test(String(value || '')))
|
|
81
|
+
throw new Error(code);
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
function stableHash(value) {
|
|
85
|
+
return createHash('sha256').update(canonicalJson(value)).digest('hex');
|
|
86
|
+
}
|
|
87
|
+
function deepFreeze(value) {
|
|
88
|
+
if (value && typeof value === 'object' && !Object.isFrozen(value)) {
|
|
89
|
+
Object.freeze(value);
|
|
90
|
+
for (const child of Object.values(value))
|
|
91
|
+
deepFreeze(child);
|
|
92
|
+
}
|
|
93
|
+
return value;
|
|
94
|
+
}
|