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,11 +1,13 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { nowIso, sha256, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
|
|
4
|
+
import { ensureConfinedDirectory, inspectConfinedPath, isLexicallyConfined } from '../managed-path-safety.js';
|
|
5
|
+
import { CORE_SKILL_TEMPLATE_VERSION, buildSksCoreSkillManifest, currentCoreSkillName, isCoreSkillName, isSksManagedCoreSkillContent, renderCoreSkillTemplate } from './core-skill-manifest.js';
|
|
5
6
|
import { canonicalSkillName } from './skill-name-canonicalizer.js';
|
|
6
7
|
export async function syncCoreSkillsIntegrity(input) {
|
|
7
8
|
const root = path.resolve(input.root);
|
|
8
|
-
const skillsRoot = input.skillsRoot || path.join(root, '.agents', 'skills');
|
|
9
|
+
const skillsRoot = path.resolve(input.skillsRoot || path.join(root, '.agents', 'skills'));
|
|
10
|
+
const skillsBoundary = coreSkillsBoundary(root, skillsRoot);
|
|
9
11
|
const apply = input.apply === true;
|
|
10
12
|
const manifest = buildSksCoreSkillManifest();
|
|
11
13
|
const rows = [];
|
|
@@ -13,19 +15,36 @@ export async function syncCoreSkillsIntegrity(input) {
|
|
|
13
15
|
const restored = [];
|
|
14
16
|
const skippedUserAuthored = [];
|
|
15
17
|
const blockers = [];
|
|
18
|
+
const reportPath = input.reportPath === null
|
|
19
|
+
? null
|
|
20
|
+
: path.resolve(input.reportPath || path.join(root, '.sneakoscope', 'reports', 'core-skill-integrity.json'));
|
|
21
|
+
const backupRoot = path.join(root, '.sneakoscope', 'backups', 'core-skills');
|
|
22
|
+
const reportPathBlocker = reportPath
|
|
23
|
+
? await inspectCoreSkillArtifactTarget(root, reportPath, 'report', 'file')
|
|
24
|
+
: null;
|
|
25
|
+
const backupPathBlocker = apply
|
|
26
|
+
? await inspectCoreSkillArtifactTarget(root, backupRoot, 'backup', 'directory')
|
|
27
|
+
: null;
|
|
28
|
+
const artifactPathBlockers = [reportPathBlocker, backupPathBlocker].filter((value) => Boolean(value));
|
|
29
|
+
blockers.push(...artifactPathBlockers);
|
|
30
|
+
const mutationAllowed = apply && artifactPathBlockers.length === 0;
|
|
16
31
|
for (const skill of manifest.skills) {
|
|
17
32
|
const skillDir = path.join(skillsRoot, skill.canonical_name);
|
|
18
33
|
const file = path.join(skillDir, 'SKILL.md');
|
|
19
34
|
const desired = renderCoreSkillTemplate(skill.canonical_name);
|
|
20
|
-
const
|
|
35
|
+
const safeCurrent = await readConfinedCoreSkill(skillsBoundary, skill.canonical_name, skillDir, file);
|
|
36
|
+
const current = safeCurrent.text;
|
|
21
37
|
const beforeSha = typeof current === 'string' ? sha256(current) : null;
|
|
22
38
|
let action = 'already-current';
|
|
23
39
|
let backupPath = null;
|
|
24
|
-
let blocker =
|
|
25
|
-
if (
|
|
40
|
+
let blocker = safeCurrent.blocker;
|
|
41
|
+
if (blocker) {
|
|
42
|
+
action = 'blocked';
|
|
43
|
+
}
|
|
44
|
+
else if (current === null) {
|
|
26
45
|
action = 'install-missing-managed-copy';
|
|
27
|
-
if (
|
|
28
|
-
await
|
|
46
|
+
if (mutationAllowed) {
|
|
47
|
+
await ensureConfinedDirectory(skillsBoundary, skillDir);
|
|
29
48
|
await writeTextAtomic(file, desired);
|
|
30
49
|
installed.push(file);
|
|
31
50
|
}
|
|
@@ -35,12 +54,19 @@ export async function syncCoreSkillsIntegrity(input) {
|
|
|
35
54
|
}
|
|
36
55
|
else if (isSksManagedCoreSkillContent(current)) {
|
|
37
56
|
action = 'restore-corrupted-managed-copy';
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
await
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
57
|
+
if (mutationAllowed) {
|
|
58
|
+
const candidateBackupPath = path.join(backupRoot, skill.canonical_name, `${Date.now()}-${process.pid}.SKILL.md.bak`);
|
|
59
|
+
const backupWriteBlocker = await writeConfinedCoreSkillArtifact(root, candidateBackupPath, current, 'backup');
|
|
60
|
+
if (backupWriteBlocker) {
|
|
61
|
+
action = 'blocked';
|
|
62
|
+
blocker = backupWriteBlocker;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
backupPath = candidateBackupPath;
|
|
66
|
+
await ensureConfinedDirectory(skillsBoundary, skillDir);
|
|
67
|
+
await writeTextAtomic(file, desired);
|
|
68
|
+
restored.push(file);
|
|
69
|
+
}
|
|
44
70
|
}
|
|
45
71
|
}
|
|
46
72
|
else {
|
|
@@ -48,7 +74,14 @@ export async function syncCoreSkillsIntegrity(input) {
|
|
|
48
74
|
blocker = `user_authored_core_skill_collision:${skill.canonical_name}`;
|
|
49
75
|
skippedUserAuthored.push(file);
|
|
50
76
|
}
|
|
51
|
-
const
|
|
77
|
+
const afterInspection = blocker && action === 'blocked'
|
|
78
|
+
? { text: null, blocker }
|
|
79
|
+
: await readConfinedCoreSkill(skillsBoundary, skill.canonical_name, skillDir, file);
|
|
80
|
+
if (!blocker && afterInspection.blocker) {
|
|
81
|
+
action = 'blocked';
|
|
82
|
+
blocker = afterInspection.blocker;
|
|
83
|
+
}
|
|
84
|
+
const after = afterInspection.text;
|
|
52
85
|
const afterSha = typeof after === 'string' ? sha256(after) : null;
|
|
53
86
|
rows.push({
|
|
54
87
|
canonical_name: skill.canonical_name,
|
|
@@ -81,13 +114,129 @@ export async function syncCoreSkillsIntegrity(input) {
|
|
|
81
114
|
skipped_user_authored: skippedUserAuthored,
|
|
82
115
|
blockers
|
|
83
116
|
};
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
117
|
+
if (reportPath && !reportPathBlocker) {
|
|
118
|
+
const reportWriteBlocker = await writeConfinedCoreSkillReport(root, reportPath, report);
|
|
119
|
+
if (reportWriteBlocker) {
|
|
120
|
+
blockers.push(reportWriteBlocker);
|
|
121
|
+
report.ok = false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
89
124
|
return report;
|
|
90
125
|
}
|
|
91
126
|
export function coreSkillPath(skillsRoot, name) {
|
|
92
127
|
return path.join(skillsRoot, currentCoreSkillName(canonicalSkillName(name)), 'SKILL.md');
|
|
93
128
|
}
|
|
129
|
+
function coreSkillsBoundary(root, skillsRoot) {
|
|
130
|
+
if (isLexicallyConfined(root, skillsRoot))
|
|
131
|
+
return root;
|
|
132
|
+
const parent = path.dirname(skillsRoot);
|
|
133
|
+
return ['.agents', '.codex'].includes(path.basename(parent)) ? path.dirname(parent) : parent;
|
|
134
|
+
}
|
|
135
|
+
async function readConfinedCoreSkill(boundary, skillName, skillDir, file) {
|
|
136
|
+
try {
|
|
137
|
+
const dirInspection = await inspectConfinedPath(boundary, skillDir);
|
|
138
|
+
if (dirInspection.exists && (dirInspection.leafSymlink || !dirInspection.stat?.isDirectory())) {
|
|
139
|
+
return { text: null, blocker: coreSkillPathBlocker(skillName, 'skill_directory_not_safe') };
|
|
140
|
+
}
|
|
141
|
+
const fileInspection = await inspectConfinedPath(boundary, file);
|
|
142
|
+
if (!fileInspection.exists)
|
|
143
|
+
return { text: null, blocker: null };
|
|
144
|
+
if (fileInspection.leafSymlink || !fileInspection.stat?.isFile()) {
|
|
145
|
+
return { text: null, blocker: coreSkillPathBlocker(skillName, 'skill_file_not_safe') };
|
|
146
|
+
}
|
|
147
|
+
return { text: await fs.readFile(file, 'utf8'), blocker: null };
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
return {
|
|
151
|
+
text: null,
|
|
152
|
+
blocker: coreSkillPathBlocker(skillName, coreSkillPathFailureReason(error))
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function coreSkillPathBlocker(skillName, reason) {
|
|
157
|
+
const canonical = canonicalSkillName(skillName);
|
|
158
|
+
const safeSkillName = isCoreSkillName(canonical) ? canonical : 'unknown';
|
|
159
|
+
return `core_skill_path_unsafe:${safeSkillName}:${reason}`;
|
|
160
|
+
}
|
|
161
|
+
function coreSkillPathFailureReason(error) {
|
|
162
|
+
const code = error && typeof error === 'object' && 'code' in error ? error.code : null;
|
|
163
|
+
if (code === 'managed_path_boundary_missing')
|
|
164
|
+
return 'boundary_missing';
|
|
165
|
+
if (code === 'managed_path_boundary_symlink_refused')
|
|
166
|
+
return 'boundary_symlink';
|
|
167
|
+
if (code === 'managed_path_boundary_not_directory')
|
|
168
|
+
return 'boundary_not_directory';
|
|
169
|
+
if (code === 'managed_path_escape_refused')
|
|
170
|
+
return 'escape_refused';
|
|
171
|
+
if (code === 'managed_path_ancestor_symlink_refused')
|
|
172
|
+
return 'ancestor_symlink';
|
|
173
|
+
if (code === 'managed_path_ancestor_not_directory')
|
|
174
|
+
return 'ancestor_not_directory';
|
|
175
|
+
return 'inspection_failed';
|
|
176
|
+
}
|
|
177
|
+
async function inspectCoreSkillArtifactTarget(root, target, scope, expected) {
|
|
178
|
+
if (!isLexicallyConfined(root, target))
|
|
179
|
+
return coreSkillArtifactBlocker(scope, 'escape_refused');
|
|
180
|
+
try {
|
|
181
|
+
const inspection = await inspectConfinedPath(root, target);
|
|
182
|
+
if (!inspection.exists)
|
|
183
|
+
return null;
|
|
184
|
+
if (inspection.leafSymlink)
|
|
185
|
+
return coreSkillArtifactBlocker(scope, 'leaf_symlink');
|
|
186
|
+
if (expected === 'directory' && !inspection.stat?.isDirectory()) {
|
|
187
|
+
return coreSkillArtifactBlocker(scope, 'not_directory');
|
|
188
|
+
}
|
|
189
|
+
if (expected === 'file' && !inspection.stat?.isFile()) {
|
|
190
|
+
return coreSkillArtifactBlocker(scope, 'not_file');
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
return coreSkillArtifactBlocker(scope, coreSkillArtifactFailureReason(error));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
async function writeConfinedCoreSkillArtifact(root, target, text, scope) {
|
|
199
|
+
try {
|
|
200
|
+
await ensureConfinedDirectory(root, path.dirname(target));
|
|
201
|
+
const blocker = await inspectCoreSkillArtifactTarget(root, target, scope, 'file');
|
|
202
|
+
if (blocker)
|
|
203
|
+
return blocker;
|
|
204
|
+
await writeTextAtomic(target, text);
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
return coreSkillArtifactBlocker(scope, 'write_failed');
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
async function writeConfinedCoreSkillReport(root, target, report) {
|
|
212
|
+
try {
|
|
213
|
+
await ensureConfinedDirectory(root, path.dirname(target));
|
|
214
|
+
const blocker = await inspectCoreSkillArtifactTarget(root, target, 'report', 'file');
|
|
215
|
+
if (blocker)
|
|
216
|
+
return blocker;
|
|
217
|
+
await writeJsonAtomic(target, report);
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return coreSkillArtifactBlocker('report', 'write_failed');
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function coreSkillArtifactBlocker(scope, reason) {
|
|
225
|
+
return `core_skill_artifact_path_unsafe:${scope}:${reason}`;
|
|
226
|
+
}
|
|
227
|
+
function coreSkillArtifactFailureReason(error) {
|
|
228
|
+
const code = error && typeof error === 'object' && 'code' in error ? error.code : null;
|
|
229
|
+
if (code === 'managed_path_boundary_missing')
|
|
230
|
+
return 'boundary_missing';
|
|
231
|
+
if (code === 'managed_path_boundary_symlink_refused')
|
|
232
|
+
return 'boundary_symlink';
|
|
233
|
+
if (code === 'managed_path_boundary_not_directory')
|
|
234
|
+
return 'boundary_not_directory';
|
|
235
|
+
if (code === 'managed_path_escape_refused')
|
|
236
|
+
return 'escape_refused';
|
|
237
|
+
if (code === 'managed_path_ancestor_symlink_refused')
|
|
238
|
+
return 'ancestor_symlink';
|
|
239
|
+
if (code === 'managed_path_ancestor_not_directory')
|
|
240
|
+
return 'ancestor_not_directory';
|
|
241
|
+
return 'inspection_failed';
|
|
242
|
+
}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
1
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
2
|
+
import { nowIso, writeJsonAtomic } from '../fsx.js';
|
|
3
|
+
import { ensureConfinedDirectory, inspectConfinedPath, isLexicallyConfined, moveConfinedPath, removeConfinedDirectoryIfEmpty, removeManagedPathVerified, uniqueConfinedPath } from '../managed-path-safety.js';
|
|
4
4
|
import { buildSkillRegistryLedger, groupByCanonical } from './skill-registry-ledger.js';
|
|
5
|
+
import { writeRootConfinedJsonReport } from './confined-report-writer.js';
|
|
5
6
|
export async function dedupeProjectSkills(input) {
|
|
6
7
|
const root = path.resolve(input.root);
|
|
7
8
|
const fix = input.fix === true;
|
|
8
9
|
const yes = input.yes === true;
|
|
9
|
-
const ledger = await buildSkillRegistryLedger({ root });
|
|
10
|
+
const ledger = await buildSkillRegistryLedger({ root, reportPath: null });
|
|
10
11
|
const grouped = groupByCanonical(ledger.entries);
|
|
11
12
|
const actions = [];
|
|
12
13
|
const unresolvedUserDuplicates = [];
|
|
13
14
|
for (const [canonical, group] of grouped.entries()) {
|
|
14
15
|
if (group.length <= 1)
|
|
15
16
|
continue;
|
|
16
|
-
group.sort(compareSkillPriority);
|
|
17
|
+
group.sort((a, b) => compareSkillPriority(root, a, b));
|
|
17
18
|
const userEntries = group.filter((entry) => !entry.managed_by_sks);
|
|
18
19
|
const managedEntries = group.filter((entry) => entry.managed_by_sks);
|
|
19
20
|
if (userEntries.length > 0 && managedEntries.length > 0) {
|
|
@@ -59,7 +60,9 @@ export async function dedupeProjectSkills(input) {
|
|
|
59
60
|
const duplicateNames = [...new Set(actions.filter((action) => action.action !== 'kept').map((action) => action.canonical_name))].sort();
|
|
60
61
|
const afterLedger = await buildSkillRegistryLedger({ root, reportPath: null });
|
|
61
62
|
const blockers = [
|
|
63
|
+
...ledger.blockers.filter((blocker) => !blocker.startsWith('duplicate_active_skill_name:')),
|
|
62
64
|
...unresolvedUserDuplicates.map((name) => `user_duplicate_requires_confirmation:${name}`),
|
|
65
|
+
...afterLedger.blockers.filter((blocker) => !blocker.startsWith('duplicate_active_skill_name:')),
|
|
63
66
|
...afterLedger.duplicate_active_canonical_names.map((name) => `duplicate_active_skill_name:${name}`)
|
|
64
67
|
];
|
|
65
68
|
const report = {
|
|
@@ -75,16 +78,25 @@ export async function dedupeProjectSkills(input) {
|
|
|
75
78
|
duplicate_active_canonical_names: afterLedger.duplicate_active_canonical_names,
|
|
76
79
|
duplicate_canonical_names: duplicateNames,
|
|
77
80
|
unresolved_user_duplicates: unresolvedUserDuplicates,
|
|
78
|
-
blockers
|
|
81
|
+
blockers: [...new Set(blockers)].sort()
|
|
79
82
|
};
|
|
80
83
|
const reportPath = input.reportPath === null
|
|
81
84
|
? null
|
|
82
85
|
: input.reportPath || path.join(root, '.sneakoscope', 'reports', 'project-skill-dedupe.json');
|
|
83
|
-
if (reportPath)
|
|
84
|
-
await
|
|
86
|
+
if (reportPath) {
|
|
87
|
+
const written = await writeRootConfinedJsonReport({ root, reportPath, value: report });
|
|
88
|
+
if (!written) {
|
|
89
|
+
report.ok = false;
|
|
90
|
+
report.blockers = [...new Set([...report.blockers, 'project_skill_dedupe_report_path_unsafe'])].sort();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
85
93
|
return report;
|
|
86
94
|
}
|
|
87
|
-
function compareSkillPriority(a, b) {
|
|
95
|
+
function compareSkillPriority(root, a, b) {
|
|
96
|
+
const confinedA = skillEntryIsLexicallyConfined(root, a) ? 1 : 0;
|
|
97
|
+
const confinedB = skillEntryIsLexicallyConfined(root, b) ? 1 : 0;
|
|
98
|
+
if (confinedA !== confinedB)
|
|
99
|
+
return confinedB - confinedA;
|
|
88
100
|
const currentA = a.status === 'managed-current' ? 1 : 0;
|
|
89
101
|
const currentB = b.status === 'managed-current' ? 1 : 0;
|
|
90
102
|
return currentB - currentA || b.active_priority - a.active_priority || a.path.localeCompare(b.path);
|
|
@@ -104,13 +116,23 @@ async function maybeQuarantine(root, canonical, entry, fix, reason) {
|
|
|
104
116
|
return quarantineSkill(root, canonical, entry, reason);
|
|
105
117
|
}
|
|
106
118
|
async function quarantineSkill(root, canonical, entry, reason) {
|
|
119
|
+
const boundary = path.resolve(root);
|
|
107
120
|
const sourceDir = path.dirname(entry.path);
|
|
121
|
+
if (!skillEntryIsProjectOwned(boundary, entry))
|
|
122
|
+
return null;
|
|
123
|
+
const sourceInspection = await inspectConfinedPath(boundary, sourceDir);
|
|
124
|
+
if (!sourceInspection.exists)
|
|
125
|
+
return null;
|
|
126
|
+
if (sourceInspection.leafSymlink || !sourceInspection.stat?.isDirectory()) {
|
|
127
|
+
throw new Error(`project_skill_source_not_safe_directory:${sourceDir}`);
|
|
128
|
+
}
|
|
108
129
|
const stamp = `${Date.now()}-${process.pid}`;
|
|
109
|
-
const
|
|
110
|
-
await
|
|
111
|
-
|
|
112
|
-
await
|
|
113
|
-
|
|
130
|
+
const base = path.join(boundary, '.sneakoscope', 'quarantine', 'skills', canonical, stamp);
|
|
131
|
+
const container = await uniqueConfinedPath(boundary, base);
|
|
132
|
+
const target = path.join(container, path.basename(sourceDir));
|
|
133
|
+
await ensureConfinedDirectory(boundary, container);
|
|
134
|
+
const recordPath = path.join(container, 'quarantine-record.json');
|
|
135
|
+
await writeJsonAtomic(recordPath, {
|
|
114
136
|
schema: 'sks.skill-quarantine-record.v1',
|
|
115
137
|
generated_at: nowIso(),
|
|
116
138
|
source_path: sourceDir,
|
|
@@ -119,5 +141,25 @@ async function quarantineSkill(root, canonical, entry, reason) {
|
|
|
119
141
|
reason,
|
|
120
142
|
content_sha256: entry.content_sha256
|
|
121
143
|
});
|
|
144
|
+
try {
|
|
145
|
+
await moveConfinedPath(boundary, sourceDir, target);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
await removeManagedPathVerified(boundary, recordPath).catch(() => undefined);
|
|
149
|
+
await removeConfinedDirectoryIfEmpty(boundary, container).catch(() => undefined);
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
122
152
|
return target;
|
|
123
153
|
}
|
|
154
|
+
function skillEntryIsLexicallyConfined(root, entry) {
|
|
155
|
+
return isLexicallyConfined(root, path.dirname(entry.path));
|
|
156
|
+
}
|
|
157
|
+
function skillEntryIsProjectOwned(root, entry) {
|
|
158
|
+
if (entry.scope !== 'project')
|
|
159
|
+
return false;
|
|
160
|
+
const sourceDir = path.dirname(entry.path);
|
|
161
|
+
return [
|
|
162
|
+
path.join(root, '.agents', 'skills'),
|
|
163
|
+
path.join(root, '.codex', 'skills')
|
|
164
|
+
].some((scanRoot) => isLexicallyConfined(scanRoot, sourceDir));
|
|
165
|
+
}
|
|
@@ -1,27 +1,54 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import os from 'node:os';
|
|
4
|
-
import { nowIso, readText, sha256
|
|
4
|
+
import { canonicalFilesystemPath, nowIso, readText, sha256 } from '../fsx.js';
|
|
5
|
+
import { inspectConfinedPath, isLexicallyConfined } from '../managed-path-safety.js';
|
|
5
6
|
import { buildSksCoreSkillManifest, isSksManagedCoreSkillContent } from './core-skill-manifest.js';
|
|
6
7
|
import { canonicalSkillName, skillDisplayNameFromMarkdown } from './skill-name-canonicalizer.js';
|
|
7
8
|
import { loadSkillsManifest } from '../init/skills.js';
|
|
9
|
+
import { writeRootConfinedJsonReport } from './confined-report-writer.js';
|
|
8
10
|
export async function buildSkillRegistryLedger(input) {
|
|
9
11
|
const root = path.resolve(input.root);
|
|
10
12
|
const codexHome = process.env.CODEX_HOME || path.join(os.homedir(), '.codex');
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
{ root: path.join(
|
|
15
|
-
{ root: path.join(
|
|
13
|
+
const home = os.homedir();
|
|
14
|
+
const codexHomeBoundary = isLexicallyConfined(home, codexHome) ? home : path.dirname(path.resolve(codexHome));
|
|
15
|
+
const scanRootResolution = await dedupeSkillRegistryScanRoots([
|
|
16
|
+
{ root: path.join(root, '.agents', 'skills'), boundary: root, scope: 'project', priority: 100 },
|
|
17
|
+
{ root: path.join(root, '.codex', 'skills'), boundary: root, scope: 'project', priority: 80 },
|
|
18
|
+
{ root: path.join(home, '.agents', 'skills'), boundary: home, scope: 'global', priority: 60 },
|
|
19
|
+
{ root: path.join(codexHome, 'skills'), boundary: codexHomeBoundary, scope: 'codex-home', priority: 60 },
|
|
16
20
|
...(input.extraRoots || [])
|
|
17
|
-
];
|
|
21
|
+
]);
|
|
22
|
+
const scanRoots = scanRootResolution.roots;
|
|
18
23
|
const manifest = await loadSkillsManifest().catch(() => null);
|
|
19
24
|
const officialNames = new Set((manifest?.skills || []).map((skill) => canonicalSkillName(skill.canonical_name)));
|
|
20
25
|
const aliasNames = new Set((manifest?.skills || []).flatMap((skill) => (skill.deprecated_aliases || []).map((name) => canonicalSkillName(name))));
|
|
21
|
-
const manifestByName = new Map(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
const manifestByName = new Map();
|
|
27
|
+
const managedDigestsByName = new Map();
|
|
28
|
+
const addManagedDigest = (name, digest) => {
|
|
29
|
+
const canonical = canonicalSkillName(String(name || ''));
|
|
30
|
+
const boundedDigest = String(digest || '').toLowerCase();
|
|
31
|
+
if (!canonical || !/^[a-f0-9]{64}$/.test(boundedDigest))
|
|
32
|
+
return;
|
|
33
|
+
const digests = managedDigestsByName.get(canonical) || new Set();
|
|
34
|
+
digests.add(boundedDigest);
|
|
35
|
+
managedDigestsByName.set(canonical, digests);
|
|
36
|
+
};
|
|
37
|
+
for (const skill of buildSksCoreSkillManifest().skills) {
|
|
38
|
+
manifestByName.set(skill.canonical_name, skill.content_sha256);
|
|
39
|
+
addManagedDigest(skill.canonical_name, skill.content_sha256);
|
|
40
|
+
}
|
|
41
|
+
for (const skill of manifest?.skills || []) {
|
|
42
|
+
const canonical = canonicalSkillName(skill?.canonical_name);
|
|
43
|
+
const currentDigest = String(skill?.content_sha256 || '').toLowerCase();
|
|
44
|
+
if (canonical && /^[a-f0-9]{64}$/.test(currentDigest))
|
|
45
|
+
manifestByName.set(canonical, currentDigest);
|
|
46
|
+
for (const name of [canonical, ...(skill?.deprecated_aliases || []).map((alias) => canonicalSkillName(String(alias || '')))]) {
|
|
47
|
+
addManagedDigest(name, currentDigest);
|
|
48
|
+
for (const digest of skill?.hash_history || [])
|
|
49
|
+
addManagedDigest(name, digest);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
25
52
|
const entries = [];
|
|
26
53
|
for (const scanRoot of scanRoots) {
|
|
27
54
|
const rows = await fs.readdir(scanRoot.root, { withFileTypes: true }).catch(() => []);
|
|
@@ -29,6 +56,11 @@ export async function buildSkillRegistryLedger(input) {
|
|
|
29
56
|
if (!row.isDirectory())
|
|
30
57
|
continue;
|
|
31
58
|
const skillPath = path.join(scanRoot.root, row.name, 'SKILL.md');
|
|
59
|
+
if (scanRoot.boundary) {
|
|
60
|
+
const inspection = await inspectConfinedPath(scanRoot.boundary, skillPath).catch(() => null);
|
|
61
|
+
if (!inspection?.exists || inspection.leafSymlink || !inspection.stat?.isFile())
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
32
64
|
const text = await readText(skillPath, null);
|
|
33
65
|
if (typeof text !== 'string')
|
|
34
66
|
continue;
|
|
@@ -36,7 +68,8 @@ export async function buildSkillRegistryLedger(input) {
|
|
|
36
68
|
const canonical = canonicalSkillName(displayName || row.name);
|
|
37
69
|
const hash = sha256(text);
|
|
38
70
|
const officialName = officialNames.has(canonical) || aliasNames.has(canonical);
|
|
39
|
-
const managed =
|
|
71
|
+
const managed = isRecognizedSksManagedSkillContent(text)
|
|
72
|
+
|| Boolean(officialName && managedDigestsByName.get(canonical)?.has(hash));
|
|
40
73
|
const expected = manifestByName.get(canonical);
|
|
41
74
|
const status = managed
|
|
42
75
|
? expected && expected === hash ? 'managed-current' : 'managed-drift'
|
|
@@ -70,11 +103,14 @@ export async function buildSkillRegistryLedger(input) {
|
|
|
70
103
|
const activeGrouped = groupByCanonical(activeEntries);
|
|
71
104
|
const duplicateActiveNames = [...activeGrouped.entries()].filter(([, group]) => group.length > 1).map(([name]) => name).sort();
|
|
72
105
|
const activeUnique = duplicateActiveNames.length === 0;
|
|
73
|
-
const blockers =
|
|
106
|
+
const blockers = [
|
|
107
|
+
...scanRootResolution.blockers,
|
|
108
|
+
...duplicateActiveNames.map((name) => `duplicate_active_skill_name:${name}`)
|
|
109
|
+
];
|
|
74
110
|
const ledger = {
|
|
75
111
|
schema: 'sks.skill-registry-ledger.v1',
|
|
76
112
|
generated_at: nowIso(),
|
|
77
|
-
ok: activeUnique,
|
|
113
|
+
ok: activeUnique && blockers.length === 0,
|
|
78
114
|
root,
|
|
79
115
|
entries,
|
|
80
116
|
active_unique_by_canonical_name: activeUnique,
|
|
@@ -86,10 +122,95 @@ export async function buildSkillRegistryLedger(input) {
|
|
|
86
122
|
const reportPath = input.reportPath === null
|
|
87
123
|
? null
|
|
88
124
|
: input.reportPath || path.join(root, '.sneakoscope', 'reports', 'skill-registry-ledger.json');
|
|
89
|
-
if (reportPath)
|
|
90
|
-
await
|
|
125
|
+
if (reportPath) {
|
|
126
|
+
const written = await writeRootConfinedJsonReport({ root, reportPath, value: ledger });
|
|
127
|
+
if (!written) {
|
|
128
|
+
ledger.ok = false;
|
|
129
|
+
ledger.blockers = [...new Set([...ledger.blockers, 'skill_registry_report_path_unsafe'])].sort();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
91
132
|
return ledger;
|
|
92
133
|
}
|
|
134
|
+
const SKS_MANAGED_SKILL_MARKER_RE = /BEGIN SKS (?:IMMUTABLE CORE|MANAGED) SKILL/;
|
|
135
|
+
function isRecognizedSksManagedSkillContent(text) {
|
|
136
|
+
return isSksManagedCoreSkillContent(text) || SKS_MANAGED_SKILL_MARKER_RE.test(text);
|
|
137
|
+
}
|
|
138
|
+
async function dedupeSkillRegistryScanRoots(candidates) {
|
|
139
|
+
const byPath = new Map();
|
|
140
|
+
const blockers = [];
|
|
141
|
+
for (const candidate of candidates) {
|
|
142
|
+
const normalized = {
|
|
143
|
+
...candidate,
|
|
144
|
+
root: path.resolve(candidate.root),
|
|
145
|
+
...(candidate.boundary ? { boundary: path.resolve(candidate.boundary) } : {})
|
|
146
|
+
};
|
|
147
|
+
if (normalized.boundary) {
|
|
148
|
+
try {
|
|
149
|
+
await fs.lstat(normalized.root);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT')
|
|
153
|
+
continue;
|
|
154
|
+
blockers.push(unsafeSkillScanRootBlocker(normalized.scope, 'lstat_failed'));
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
const inspection = await inspectConfinedPath(normalized.boundary, normalized.root);
|
|
159
|
+
if (!inspection.exists)
|
|
160
|
+
continue;
|
|
161
|
+
if (inspection.leafSymlink) {
|
|
162
|
+
blockers.push(unsafeSkillScanRootBlocker(normalized.scope, 'leaf_symlink'));
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (!inspection.stat?.isDirectory()) {
|
|
166
|
+
blockers.push(unsafeSkillScanRootBlocker(normalized.scope, 'not_directory'));
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
blockers.push(unsafeSkillScanRootBlocker(normalized.scope, skillScanRootInspectionFailureReason(error)));
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const identity = await canonicalFilesystemPath(candidate.root);
|
|
176
|
+
const current = byPath.get(identity);
|
|
177
|
+
if (!current || skillScanScopeRank(normalized.scope) > skillScanScopeRank(current.scope)) {
|
|
178
|
+
byPath.set(identity, normalized);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return { roots: [...byPath.values()], blockers: [...new Set(blockers)].sort() };
|
|
182
|
+
}
|
|
183
|
+
function unsafeSkillScanRootBlocker(scope, reason) {
|
|
184
|
+
return `unsafe_skill_scan_root:${skillScanRootScopeCode(scope)}:${reason}`;
|
|
185
|
+
}
|
|
186
|
+
function skillScanRootScopeCode(scope) {
|
|
187
|
+
if (scope === 'project' || scope === 'global' || scope === 'codex-home' || scope === 'user')
|
|
188
|
+
return scope;
|
|
189
|
+
return 'unknown';
|
|
190
|
+
}
|
|
191
|
+
function skillScanRootInspectionFailureReason(error) {
|
|
192
|
+
const code = error && typeof error === 'object' && 'code' in error ? error.code : null;
|
|
193
|
+
if (code === 'managed_path_boundary_missing')
|
|
194
|
+
return 'boundary_missing';
|
|
195
|
+
if (code === 'managed_path_boundary_symlink_refused')
|
|
196
|
+
return 'boundary_symlink';
|
|
197
|
+
if (code === 'managed_path_boundary_not_directory')
|
|
198
|
+
return 'boundary_not_directory';
|
|
199
|
+
if (code === 'managed_path_escape_refused')
|
|
200
|
+
return 'escape_refused';
|
|
201
|
+
if (code === 'managed_path_ancestor_symlink_refused')
|
|
202
|
+
return 'ancestor_symlink';
|
|
203
|
+
if (code === 'managed_path_ancestor_not_directory')
|
|
204
|
+
return 'ancestor_not_directory';
|
|
205
|
+
return 'inspection_failed';
|
|
206
|
+
}
|
|
207
|
+
function skillScanScopeRank(scope) {
|
|
208
|
+
if (scope === 'global' || scope === 'codex-home')
|
|
209
|
+
return 3;
|
|
210
|
+
if (scope === 'project')
|
|
211
|
+
return 2;
|
|
212
|
+
return 1;
|
|
213
|
+
}
|
|
93
214
|
function compareRegistryPriority(a, b, official) {
|
|
94
215
|
if (official) {
|
|
95
216
|
const globalA = a.scope === 'global' || a.scope === 'codex-home' ? 1 : 0;
|