sneakoscope 4.8.7 → 5.3.0
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 +51 -726
- package/config/bench-baseline.json +7 -0
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/bin/install.js +35 -0
- package/dist/bin/sks.js +1 -1
- package/dist/cli/cli-theme.js +51 -0
- package/dist/cli/command-registry.js +15 -4
- package/dist/cli/help-fast.js +18 -8
- package/dist/cli/insane-search-command.js +36 -8
- package/dist/cli/install-helpers.js +32 -0
- package/dist/commands/codex-lb.js +2 -0
- package/dist/commands/doctor.js +94 -9
- package/dist/commands/proof.js +6 -3
- package/dist/config/skills-manifest.json +82 -54
- package/dist/core/agents/agent-conflict-graph.js +5 -0
- package/dist/core/agents/agent-lease.js +5 -0
- package/dist/core/agents/agent-ledger-schemas.js +1 -0
- package/dist/core/agents/agent-lifecycle.js +5 -3
- package/dist/core/agents/agent-orchestrator.js +268 -62
- package/dist/core/agents/agent-output-validator.js +14 -3
- package/dist/core/agents/agent-patch-queue-store.js +95 -2
- package/dist/core/agents/agent-patch-queue.js +6 -3
- package/dist/core/agents/agent-patch-schema.js +13 -0
- package/dist/core/agents/agent-proof-evidence.js +6 -1
- package/dist/core/agents/agent-runner-fake.js +40 -0
- package/dist/core/agents/agent-worker-pipeline.js +36 -2
- package/dist/core/agents/codex-exec-worker-adapter.js +2 -0
- package/dist/core/agents/native-cli-worker.js +0 -1
- package/dist/core/agents/native-worker-backend-router.js +58 -1
- package/dist/core/codex-app/sks-menubar.js +477 -132
- package/dist/core/codex-app.js +1 -0
- package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
- package/dist/core/codex-control/codex-sdk-env-policy.js +1 -1
- package/dist/core/codex-control/schemas/agent-worker-result.schema.js +12 -3
- package/dist/core/codex-hooks/codex-hook-managed-install.js +5 -0
- package/dist/core/codex-hooks/codex-hook-state-writer.js +70 -11
- package/dist/core/codex-hooks/codex-hook-trust-doctor.js +2 -2
- package/dist/core/codex-lb/codex-lb-env.js +20 -1
- package/dist/core/commands/basic-cli.js +18 -1
- package/dist/core/commands/check-command.js +37 -5
- package/dist/core/commands/computer-use-command.js +62 -7
- package/dist/core/commands/db-command.js +31 -5
- package/dist/core/commands/fast-mode-command.js +3 -0
- package/dist/core/commands/gate-result-contract.js +43 -0
- package/dist/core/commands/gates-command.js +6 -1
- package/dist/core/commands/gc-command.js +29 -2
- package/dist/core/commands/goal-command.js +9 -2
- package/dist/core/commands/gx-command.js +79 -7
- package/dist/core/commands/image-ux-review-command.js +188 -13
- package/dist/core/commands/mad-db-command.js +85 -176
- package/dist/core/commands/mad-sks-command.js +230 -29
- package/dist/core/commands/menubar-command.js +24 -2
- package/dist/core/commands/naruto-command.js +64 -10
- package/dist/core/commands/plan-command.js +76 -0
- package/dist/core/commands/ppt-command.js +159 -24
- package/dist/core/commands/qa-loop-command.js +6 -2
- package/dist/core/commands/release-command.js +55 -2
- package/dist/core/commands/research-command.js +1 -1
- package/dist/core/commands/review-command.js +217 -0
- package/dist/core/commands/route-success-helpers.js +59 -0
- package/dist/core/commands/run-command.js +19 -7
- package/dist/core/commands/seo-command.js +49 -1
- package/dist/core/commands/ui-command.js +161 -0
- package/dist/core/commands/uninstall-command.js +15 -1
- package/dist/core/db-safety.js +2 -2
- package/dist/core/doctor/doctor-dirty-planner.js +51 -7
- package/dist/core/doctor/doctor-transaction.js +8 -0
- package/dist/core/doctor/doctor-zellij-repair.js +1 -0
- package/dist/core/doctor/imagegen-repair.js +161 -0
- package/dist/core/feature-fixture-runner.js +2 -2
- package/dist/core/feature-fixtures.js +58 -37
- package/dist/core/feature-registry.js +102 -2
- package/dist/core/fsx.js +39 -6
- package/dist/core/image-ux-review/imagegen-adapter.js +48 -11
- package/dist/core/image-ux-review.js +16 -0
- package/dist/core/imagegen/imagegen-capability.js +11 -5
- package/dist/core/imagegen/require-imagegen.js +57 -0
- package/dist/core/init/skills.js +10 -5
- package/dist/core/mad-db/mad-db-coordinator.js +94 -18
- package/dist/core/mad-db/mad-db-policy.js +12 -10
- package/dist/core/mad-sks/executors/executor-base.js +8 -2
- package/dist/core/mad-sks/executors/index.js +4 -0
- package/dist/core/mad-sks/executors/sql-plane-executor.js +194 -0
- package/dist/core/naruto/naruto-active-pool.js +15 -4
- package/dist/core/naruto/naruto-real-worker-child.js +11 -1
- package/dist/core/naruto/naruto-role-policy.js +3 -0
- package/dist/core/naruto/naruto-task-hints.js +10 -0
- package/dist/core/naruto/naruto-work-graph.js +8 -2
- package/dist/core/naruto/naruto-work-item.js +6 -0
- package/dist/core/naruto/solution-tournament.js +101 -0
- package/dist/core/permission-gates.js +30 -0
- package/dist/core/pipeline-internals/runtime-core.js +11 -3
- package/dist/core/pipeline-internals/runtime-gates.js +27 -0
- package/dist/core/ppt-review/index.js +6 -1
- package/dist/core/ppt-review/slide-imagegen-review.js +75 -10
- package/dist/core/ppt.js +70 -2
- package/dist/core/proof/auto-finalize.js +70 -11
- package/dist/core/proof/proof-schema.js +2 -0
- package/dist/core/proof/route-adapter.js +5 -1
- package/dist/core/proof/route-finalizer.js +8 -5
- package/dist/core/proof/selftest-proof-fixtures.js +18 -5
- package/dist/core/proof/validation.js +2 -0
- package/dist/core/provider/model-router.js +53 -0
- package/dist/core/release/release-gate-node.js +3 -0
- package/dist/core/release/release-gate-resource-governor.js +1 -0
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes.js +65 -18
- package/dist/core/safety/mutation-guard.js +5 -1
- package/dist/core/stop-gate/gate-evaluator.js +102 -0
- package/dist/core/stop-gate/stop-gate-check.js +16 -1
- package/dist/core/stop-gate/stop-gate-writer.js +4 -0
- package/dist/core/triwiki/agents-md-projector.js +184 -0
- package/dist/core/triwiki-wrongness/wrongness-schema.js +3 -1
- package/dist/core/trust-kernel/trust-kernel-schema.js +1 -0
- package/dist/core/trust-kernel/trust-report.js +1 -1
- package/dist/core/trust-kernel/trust-status.js +2 -0
- package/dist/core/ui/dashboard-html.js +111 -0
- package/dist/core/update/update-migration-state.js +386 -15
- package/dist/core/update-check.js +178 -81
- package/dist/core/verification/diff-quality.js +100 -0
- package/dist/core/verification/impact-scan.js +164 -0
- package/dist/core/verification/machine-feedback.js +146 -0
- package/dist/core/verification/mistake-rule-compiler.js +195 -0
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-self-heal.js +9 -6
- package/dist/core/zellij/zellij-slot-telemetry.js +1 -1
- package/dist/scripts/check-feature-quality.js +2 -2
- package/dist/scripts/cli-output-consistency-check.js +57 -0
- package/dist/scripts/coding-bench-check.js +136 -0
- package/dist/scripts/doctor-imagegen-repair-check.js +62 -0
- package/dist/scripts/ensure-bin-executable.js +11 -3
- package/dist/scripts/harness-benchmark-check.js +104 -0
- package/dist/scripts/legacy-update-e2e-check.js +228 -0
- package/dist/scripts/mad-db-command-check.js +11 -8
- package/dist/scripts/mad-db-route-identity-check.js +8 -6
- package/dist/scripts/mad-db-safety-conflict-matrix-check.js +31 -8
- package/dist/scripts/mad-db-skill-policy-snapshot-check.js +4 -5
- package/dist/scripts/naruto-real-active-pool-runtime-check.js +26 -1
- package/dist/scripts/ppt-real-imagegen-wiring-check.js +5 -1
- package/dist/scripts/proof-root-cause-policy-check.js +2 -0
- package/dist/scripts/release-dag-full-coverage-check.js +13 -4
- package/dist/scripts/release-gate-dag-runner.js +14 -0
- package/dist/scripts/release-gate-existence-audit.js +2 -1
- package/dist/scripts/release-gate-planner.js +2 -1
- package/dist/scripts/release-gate-script-parity-check.js +45 -17
- package/dist/scripts/release-metadata-1-19-check.js +2 -1
- package/dist/scripts/seo-geo-feature-fixture-quality-check.js +1 -1
- package/dist/scripts/sks-1-11-gate-lib.js +8 -6
- package/dist/scripts/sks-menubar-install-check.js +57 -20
- package/dist/scripts/ux-review-real-loop-fixture-check.js +9 -4
- package/dist/scripts/ux-review-run-wires-imagegen-check.js +4 -0
- package/dist/scripts/zellij-slot-telemetry-runtime-check.js +1 -0
- package/docs/assets/sneakoscope-architecture-pipeline.jpg +0 -0
- package/docs/demo.tape +28 -0
- package/package.json +31 -24
- package/schemas/codex/completion-proof.schema.json +3 -2
- package/schemas/release/release-gate-node.schema.json +2 -1
- package/dist/scripts/agent-backfill-route-blackbox.js +0 -5
- package/dist/scripts/agent-dynamic-pool-route-blackbox.js +0 -5
- package/dist/scripts/agent-parallel-write-blackbox.js +0 -56
- package/dist/scripts/agent-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/agent-route-blackbox-lib.js +0 -132
- package/dist/scripts/blackbox-command-import-smoke.js +0 -143
- package/dist/scripts/blackbox-global-shim.js +0 -77
- package/dist/scripts/blackbox-matrix.js +0 -70
- package/dist/scripts/blackbox-npx-one-shot.js +0 -69
- package/dist/scripts/blackbox-pack-install.js +0 -174
- package/dist/scripts/brand-neutrality-zero-leakage-blackbox.js +0 -4
- package/dist/scripts/build-once-runner-blackbox.js +0 -34
- package/dist/scripts/codex-0140-integration-blackbox.js +0 -13
- package/dist/scripts/codex-agent-type-blackbox.js +0 -4
- package/dist/scripts/codex-app-harness-blackbox.js +0 -4
- package/dist/scripts/codex-app-skill-agent-blackbox.js +0 -4
- package/dist/scripts/codex-hook-approval-blackbox.js +0 -4
- package/dist/scripts/codex-init-deep-directory-local-blackbox.js +0 -4
- package/dist/scripts/codex-native-feature-broker-blackbox.js +0 -4
- package/dist/scripts/codex-native-pattern-analysis-blackbox.js +0 -4
- package/dist/scripts/codex-native-read-repair-split-blackbox.js +0 -55
- package/dist/scripts/codex-native-reference-cache-blackbox.js +0 -41
- package/dist/scripts/core-skill-integrity-blackbox.js +0 -32
- package/dist/scripts/dfix-fast-blackbox-check.js +0 -37
- package/dist/scripts/dfix-parallel-write-blackbox.js +0 -48
- package/dist/scripts/dfix-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/doctor-dirty-repair-blackbox.js +0 -22
- package/dist/scripts/doctor-dirty-semantic-blackbox.js +0 -8
- package/dist/scripts/doctor-native-capability-repair-blackbox.js +0 -39
- package/dist/scripts/doctor-transaction-engine-blackbox.js +0 -28
- package/dist/scripts/doctor-zellij-fix-blackbox.js +0 -4
- package/dist/scripts/doctor-zellij-no-homebrew-blackbox.js +0 -4
- package/dist/scripts/doctor-zellij-upgrade-blackbox.js +0 -4
- package/dist/scripts/gate-pack-runner-blackbox.js +0 -27
- package/dist/scripts/gate-pack-v2-blackbox.js +0 -18
- package/dist/scripts/geo-cli-blackbox-check.js +0 -18
- package/dist/scripts/loop-collision-blackbox.js +0 -3
- package/dist/scripts/loop-concurrency-oversubscription-blackbox.js +0 -3
- package/dist/scripts/loop-fixture-production-misuse-blackbox.js +0 -3
- package/dist/scripts/loop-kill-interrupt-real-blackbox.js +0 -3
- package/dist/scripts/loop-merge-strategy-blackbox.js +0 -3
- package/dist/scripts/loop-mesh-production-e2e-blackbox.js +0 -3
- package/dist/scripts/loop-side-effect-blackbox.js +0 -3
- package/dist/scripts/mad-db-operation-lifecycle-blackbox.js +0 -29
- package/dist/scripts/mad-sks-actual-executor-blackbox.js +0 -5
- package/dist/scripts/mad-zellij-headless-fallback-blackbox.js +0 -4
- package/dist/scripts/mad-zellij-self-heal-blackbox.js +0 -4
- package/dist/scripts/naruto-loop-mesh-blackbox.js +0 -3
- package/dist/scripts/naruto-real-parallelism-blackbox.js +0 -307
- package/dist/scripts/naruto-worktree-coding-blackbox.js +0 -29
- package/dist/scripts/parallel-runtime-real-blackbox.js +0 -44
- package/dist/scripts/pipeline-codex-native-doctor-mad-routing-real-blackbox.js +0 -77
- package/dist/scripts/pipeline-codex-native-e2e-blackbox.js +0 -13
- package/dist/scripts/pipeline-codex-native-image-routing-real-blackbox.js +0 -50
- package/dist/scripts/pipeline-codex-native-loop-routing-real-blackbox.js +0 -74
- package/dist/scripts/pipeline-codex-native-qa-routing-real-blackbox.js +0 -51
- package/dist/scripts/pipeline-codex-native-research-routing-real-blackbox.js +0 -45
- package/dist/scripts/pipeline-execution-profile-routing-blackbox.js +0 -4
- package/dist/scripts/postinstall-global-doctor-blackbox.js +0 -12
- package/dist/scripts/ppt-full-e2e-blackbox-check.js +0 -109
- package/dist/scripts/ppt-imagegen-blackbox-check.js +0 -46
- package/dist/scripts/qa-backfill-route-blackbox.js +0 -5
- package/dist/scripts/qa-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/release-full-parallelism-blackbox.js +0 -41
- package/dist/scripts/release-triwiki-first-runner-blackbox.js +0 -48
- package/dist/scripts/release-wiring-3110-blackbox.js +0 -27
- package/dist/scripts/release-wiring-3112-blackbox.js +0 -17
- package/dist/scripts/release-wiring-3113-blackbox.js +0 -17
- package/dist/scripts/research-backfill-route-blackbox.js +0 -5
- package/dist/scripts/research-final-reviewer-blackbox.js +0 -70
- package/dist/scripts/research-stage-cycle-runtime-blackbox.js +0 -40
- package/dist/scripts/research-synthesis-writer-blackbox.js +0 -24
- package/dist/scripts/route-blackbox-realism-check.js +0 -21
- package/dist/scripts/scheduler-resource-claim-blackbox.js +0 -24
- package/dist/scripts/seo-cli-blackbox-check.js +0 -18
- package/dist/scripts/sks-3110-all-feature-regression-blackbox.js +0 -116
- package/dist/scripts/sks-3112-all-feature-regression-blackbox.js +0 -29
- package/dist/scripts/sks-3113-all-feature-regression-blackbox.js +0 -17
- package/dist/scripts/sks-400-all-feature-regression-blackbox.js +0 -21
- package/dist/scripts/sks-400-extreme-parallel-blackbox.js +0 -8
- package/dist/scripts/sks-400-five-minute-blackbox.js +0 -9
- package/dist/scripts/sks-400-legacy-purge-blackbox.js +0 -8
- package/dist/scripts/sks-401-all-feature-regression-blackbox.js +0 -46
- package/dist/scripts/sks-401-five-minute-actual-blackbox.js +0 -23
- package/dist/scripts/sks-402-all-feature-regression-blackbox.js +0 -9
- package/dist/scripts/sks-402-five-minute-real-blackbox.js +0 -22
- package/dist/scripts/sksd-warm-cache-blackbox.js +0 -12
- package/dist/scripts/team-backfill-route-blackbox.js +0 -5
- package/dist/scripts/team-parallel-write-blackbox.js +0 -55
- package/dist/scripts/team-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/triwiki-affected-graph-blackbox.js +0 -28
- package/dist/scripts/triwiki-proof-bank-blackbox.js +0 -30
- package/dist/scripts/triwiki-proof-bank-lock-blackbox.js +0 -7
- package/dist/scripts/ux-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/ux-review-imagegen-blackbox-check.js +0 -67
- package/dist/scripts/zellij-initial-main-only-blackbox.js +0 -28
- package/dist/scripts/zellij-pane-lock-concurrency-blackbox.js +0 -80
- package/dist/scripts/zellij-pane-lock-open-worker-integration-blackbox.js +0 -137
- package/dist/scripts/zellij-self-heal-typed-blackbox.js +0 -4
- package/dist/scripts/zellij-slot-telemetry-real-blackbox.js +0 -20
- package/dist/scripts/zellij-stacked-fallback-integration-blackbox.js +0 -81
- package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +0 -202
package/dist/core/codex-app.js
CHANGED
|
@@ -582,6 +582,7 @@ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, re
|
|
|
582
582
|
}
|
|
583
583
|
else if (appInstalled || codex?.bin) {
|
|
584
584
|
lines.push('Codex image_generation was not visible from `codex features list`. Required imagegen/gpt-image-2 evidence must stay blocked or unverified until $imagegen is available in Codex App.');
|
|
585
|
+
lines.push('Run: sks doctor --fix to attempt Codex CLI/App image_generation repair, then rerun the blocked visual route.');
|
|
585
586
|
}
|
|
586
587
|
if (computerUseReady && !computerUseMcpListed) {
|
|
587
588
|
lines.push('Computer Use plugin files are installed, but this check cannot prove the current thread exposes the live Computer Use tools. Start a new Codex App thread and invoke @Computer or @AppName only for native Mac/non-web target apps or screens; web/browser/webapp verification must use the Chrome Extension gate.');
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export function buildCodexSdkConfig(input) {
|
|
2
2
|
const model = String(input.model || process.env.SKS_CODEX_MODEL || process.env.CODEX_MODEL || 'gpt-5.5');
|
|
3
|
+
const serviceTier = String(input.serviceTier || process.env.SKS_SERVICE_TIER || 'fast');
|
|
3
4
|
const config = {
|
|
4
5
|
model,
|
|
5
|
-
service_tier: 'fast',
|
|
6
|
+
service_tier: serviceTier === 'standard' ? 'standard' : 'fast',
|
|
6
7
|
model_reasoning_effort: String(input.modelReasoningEffort || input.reasoningEffort || process.env.SKS_CODEX_REASONING || process.env.CODEX_MODEL_REASONING_EFFORT || 'medium'),
|
|
7
8
|
mcp_servers: {},
|
|
8
9
|
sks: {
|
|
@@ -30,7 +30,7 @@ export function buildCodexSdkEnv(input) {
|
|
|
30
30
|
env.SKS_AGENT_SESSION_ID = input.sessionId;
|
|
31
31
|
if (input.generationIndex !== undefined)
|
|
32
32
|
env.SKS_AGENT_GENERATION_INDEX = String(input.generationIndex);
|
|
33
|
-
env.SKS_SERVICE_TIER = 'fast';
|
|
33
|
+
env.SKS_SERVICE_TIER = String(input.serviceTier || 'fast');
|
|
34
34
|
const isolatedRoot = path.resolve(input.mutationLedgerRoot, 'codex-sdk-home');
|
|
35
35
|
env.HOME = path.join(isolatedRoot, 'home');
|
|
36
36
|
env.CODEX_HOME = path.join(isolatedRoot, 'codex');
|
|
@@ -3,7 +3,7 @@ const patchOperationSchema = {
|
|
|
3
3
|
type: 'object',
|
|
4
4
|
required: ['op', 'path', 'search', 'replace', 'content', 'diff'],
|
|
5
5
|
properties: {
|
|
6
|
-
op: { type: 'string', enum: ['replace', 'write', 'unified_diff'] },
|
|
6
|
+
op: { type: 'string', enum: ['replace', 'write', 'unified_diff', 'git_apply_patch'] },
|
|
7
7
|
path: { type: 'string' },
|
|
8
8
|
search: { type: 'string' },
|
|
9
9
|
replace: { type: 'string' },
|
|
@@ -38,7 +38,12 @@ const patchEnvelopeSchema = {
|
|
|
38
38
|
lease_id: { type: 'string' },
|
|
39
39
|
allowed_paths: { type: 'array', items: { type: 'string' } },
|
|
40
40
|
operations: { type: 'array', items: patchOperationSchema },
|
|
41
|
-
rationale: { type: 'string' }
|
|
41
|
+
rationale: { type: 'string' },
|
|
42
|
+
cochange_acknowledged: { type: 'boolean' },
|
|
43
|
+
cochange_acknowledged_reason: { type: 'string' },
|
|
44
|
+
regression_proof: { type: 'object', additionalProperties: true },
|
|
45
|
+
repair_hypothesis: { type: 'object', additionalProperties: true },
|
|
46
|
+
tournament: { type: 'object', additionalProperties: true }
|
|
42
47
|
},
|
|
43
48
|
additionalProperties: false
|
|
44
49
|
};
|
|
@@ -70,7 +75,11 @@ export const codexAgentWorkerResultSchema = {
|
|
|
70
75
|
additionalProperties: false
|
|
71
76
|
},
|
|
72
77
|
rollback_notes: { type: 'array', items: { type: 'string' } },
|
|
73
|
-
blockers: { type: 'array', items: { type: 'string' } }
|
|
78
|
+
blockers: { type: 'array', items: { type: 'string' } },
|
|
79
|
+
work_item_kind: { type: 'string' },
|
|
80
|
+
regression_proof: { type: 'object', additionalProperties: true },
|
|
81
|
+
repair_hypothesis: { type: 'object', additionalProperties: true },
|
|
82
|
+
tournament: { type: 'object', additionalProperties: true }
|
|
74
83
|
},
|
|
75
84
|
additionalProperties: false
|
|
76
85
|
};
|
|
@@ -3,6 +3,7 @@ import { ensureDir, nowIso, readText, writeTextAtomic } from '../fsx.js';
|
|
|
3
3
|
import { CODEX_HOOK_EVENTS } from '../codex-compat/codex-hook-events.js';
|
|
4
4
|
import { buildCodexCommandHookToml, matcherApplies } from './codex-hook-config-writer.js';
|
|
5
5
|
import { readCodexHookActualState } from './codex-hook-actual-discovery.js';
|
|
6
|
+
import { writeTrustedHashStateForHooksFile } from './codex-hook-state-writer.js';
|
|
6
7
|
const HOOK_SUBCOMMANDS = {
|
|
7
8
|
SessionStart: 'session-start',
|
|
8
9
|
UserPromptSubmit: 'user-prompt-submit',
|
|
@@ -39,6 +40,9 @@ export async function installManagedCodexHooks(root, opts = {}) {
|
|
|
39
40
|
await writeTextAtomic(tomlPath, hooksToml);
|
|
40
41
|
await writeTextAtomic(requirementsPath, requirementsToml);
|
|
41
42
|
}
|
|
43
|
+
const trust = opts.dryRun === true
|
|
44
|
+
? null
|
|
45
|
+
: await writeTrustedHashStateForHooksFile({ hooksFilePath: tomlPath, managed: true }, { allowSksHashFallback: true });
|
|
42
46
|
const actual = opts.dryRun === true
|
|
43
47
|
? null
|
|
44
48
|
: await readCodexHookActualState(root);
|
|
@@ -62,6 +66,7 @@ export async function installManagedCodexHooks(root, opts = {}) {
|
|
|
62
66
|
dual_representation: actual.dual_representation.length,
|
|
63
67
|
blockers: actual.blockers
|
|
64
68
|
} : null,
|
|
69
|
+
trust,
|
|
65
70
|
policy: {
|
|
66
71
|
official_hash_available: false,
|
|
67
72
|
trusted_hash_writer_policy: 'managed_install_required_when_official_hash_is_unavailable',
|
|
@@ -2,35 +2,94 @@ import path from 'node:path';
|
|
|
2
2
|
import { readJson, readText, writeTextAtomic } from '../fsx.js';
|
|
3
3
|
import { CODEX_HOOK_EVENTS } from '../codex-compat/codex-hook-events.js';
|
|
4
4
|
import { codexCommandHookCurrentHash, codexHookStateKey } from './codex-hook-hash.js';
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import { entriesFromInlineHooksToml } from './codex-hook-actual-discovery.js';
|
|
6
|
+
export async function writeTrustedHashStateForHooksFile(input, hooksPathOrOpts, statePath, opts = {}) {
|
|
7
|
+
const resolved = resolveWriterInput(input, hooksPathOrOpts, statePath, opts);
|
|
8
|
+
const isSksManagedHook = resolved.managed === true || resolved.hooksPath.includes('sks-managed-hooks');
|
|
9
|
+
if (resolved.opts.allowSksHashFallback !== true && !isSksManagedHook) {
|
|
7
10
|
return {
|
|
8
11
|
schema: 'sks.codex-hook-state-writer.v2',
|
|
9
12
|
ok: false,
|
|
10
|
-
hooks_path: hooksPath,
|
|
11
|
-
state_path: statePath,
|
|
13
|
+
hooks_path: resolved.hooksPath,
|
|
14
|
+
state_path: resolved.statePath,
|
|
12
15
|
updated: 0,
|
|
13
16
|
blocks: [],
|
|
14
17
|
blocked: true,
|
|
15
18
|
blocker: 'official_codex_hook_hash_unavailable',
|
|
16
19
|
policy: 'use_sks_hooks_install_managed_instead_of_writing_sks_only_trusted_hashes',
|
|
17
20
|
repair_action: 'sks hooks install --managed --json',
|
|
18
|
-
reason: opts.reason || 'SKS refuses to write trusted_hash values from its own canonicalJson hash unless official Codex hash parity is proven.'
|
|
21
|
+
reason: resolved.opts.reason || 'SKS refuses to write trusted_hash values from its own canonicalJson hash unless official Codex hash parity is proven.'
|
|
19
22
|
};
|
|
20
23
|
}
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
await writeTextAtomic(statePath, next);
|
|
24
|
+
const blocks = await trustedHashBlocksForHooksPath(resolved.hooksPath, isSksManagedHook);
|
|
25
|
+
const next = upsertTrustBlocks(await readText(resolved.statePath, ''), blocks);
|
|
26
|
+
await writeTextAtomic(resolved.statePath, next);
|
|
25
27
|
return {
|
|
26
28
|
schema: 'sks.codex-hook-state-writer.v1',
|
|
27
29
|
ok: true,
|
|
28
|
-
hooks_path: hooksPath,
|
|
29
|
-
state_path: statePath,
|
|
30
|
+
hooks_path: resolved.hooksPath,
|
|
31
|
+
state_path: resolved.statePath,
|
|
30
32
|
updated: blocks.length,
|
|
31
33
|
blocks
|
|
32
34
|
};
|
|
33
35
|
}
|
|
36
|
+
function resolveWriterInput(input, hooksPathOrOpts, statePath, opts) {
|
|
37
|
+
if (typeof input === 'string') {
|
|
38
|
+
const root = path.resolve(input);
|
|
39
|
+
const resolvedOpts = typeof hooksPathOrOpts === 'object' && hooksPathOrOpts !== null
|
|
40
|
+
? hooksPathOrOpts
|
|
41
|
+
: opts;
|
|
42
|
+
const hooksPath = typeof hooksPathOrOpts === 'string'
|
|
43
|
+
? hooksPathOrOpts
|
|
44
|
+
: path.join(root, '.codex', 'hooks.json');
|
|
45
|
+
return {
|
|
46
|
+
root,
|
|
47
|
+
hooksPath: path.resolve(hooksPath),
|
|
48
|
+
statePath: path.resolve(statePath || path.join(root, '.codex', 'config.toml')),
|
|
49
|
+
managed: resolvedOpts.managed === true,
|
|
50
|
+
opts: resolvedOpts
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const hooksPath = path.resolve(input.hooksFilePath || input.hooksPath || path.join(input.root || process.cwd(), '.codex', 'hooks.json'));
|
|
54
|
+
const root = path.resolve(input.root || rootFromHooksPath(hooksPath));
|
|
55
|
+
const resolvedOpts = typeof hooksPathOrOpts === 'object' && hooksPathOrOpts !== null
|
|
56
|
+
? hooksPathOrOpts
|
|
57
|
+
: opts;
|
|
58
|
+
return {
|
|
59
|
+
root,
|
|
60
|
+
hooksPath,
|
|
61
|
+
statePath: path.resolve(input.statePath || statePathForHooksPath(root, hooksPath)),
|
|
62
|
+
managed: input.managed === true || resolvedOpts.managed === true,
|
|
63
|
+
opts: resolvedOpts
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function rootFromHooksPath(hooksPath) {
|
|
67
|
+
const dir = path.dirname(hooksPath);
|
|
68
|
+
if (path.basename(dir) === '.codex')
|
|
69
|
+
return path.dirname(dir);
|
|
70
|
+
if (path.basename(dir) === 'managed-hooks')
|
|
71
|
+
return path.dirname(path.dirname(dir));
|
|
72
|
+
return process.cwd();
|
|
73
|
+
}
|
|
74
|
+
function statePathForHooksPath(root, hooksPath) {
|
|
75
|
+
const dir = path.dirname(hooksPath);
|
|
76
|
+
if (path.basename(dir) === '.codex' || path.basename(dir) === 'managed-hooks') {
|
|
77
|
+
return path.join(path.basename(dir) === '.codex' ? dir : path.dirname(dir), 'config.toml');
|
|
78
|
+
}
|
|
79
|
+
return path.join(root, '.codex', 'config.toml');
|
|
80
|
+
}
|
|
81
|
+
async function trustedHashBlocksForHooksPath(hooksPath, managed) {
|
|
82
|
+
if (/\.toml$/i.test(hooksPath)) {
|
|
83
|
+
const parsed = entriesFromInlineHooksToml(hooksPath, 'project', await readText(hooksPath, ''), {}, managed, managed ? 'managed_dir_toml' : 'config_toml');
|
|
84
|
+
return parsed.entries.map((entry) => ({
|
|
85
|
+
key: entry.key,
|
|
86
|
+
trusted_hash: entry.current_hash,
|
|
87
|
+
block: `[hooks.state."${tomlQuotedKey(entry.key)}"]\ntrusted_hash = "${entry.current_hash}"`
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
const hooksFile = await readJson(hooksPath, {});
|
|
91
|
+
return trustedHashBlocksForHooksFile(hooksPath, hooksFile);
|
|
92
|
+
}
|
|
34
93
|
export function trustedHashBlocksForHooksFile(hooksPath, hooksFile) {
|
|
35
94
|
const blocks = [];
|
|
36
95
|
const hooksRoot = hooksFile?.hooks && typeof hooksFile.hooks === 'object' && !Array.isArray(hooksFile.hooks) ? hooksFile.hooks : {};
|
|
@@ -8,7 +8,7 @@ export async function codexHookTrustDoctor(root, opts = {}) {
|
|
|
8
8
|
const fix = opts.fix === true;
|
|
9
9
|
const trustOpts = opts.managed === undefined ? {} : { managed: opts.managed };
|
|
10
10
|
const before = await readCodexHookTrustEntries(root, trustOpts);
|
|
11
|
-
const fixed = fix ? await writeTrustedHashStateForHooksFile(root,
|
|
11
|
+
const fixed = fix ? await writeTrustedHashStateForHooksFile({ root, managed: opts.managed === true }, { allowSksHashFallback: opts.managed === true }).catch((err) => ({
|
|
12
12
|
ok: false,
|
|
13
13
|
error: err instanceof Error ? err.message : String(err)
|
|
14
14
|
})) : null;
|
|
@@ -74,7 +74,7 @@ async function codexHookActualTrustDoctor(root, opts = {}) {
|
|
|
74
74
|
policy: {
|
|
75
75
|
official_hash_available: false,
|
|
76
76
|
trusted_hash_writer_policy: 'managed_install_required_when_official_hash_is_unavailable',
|
|
77
|
-
sks_hash_fallback_allowed:
|
|
77
|
+
sks_hash_fallback_allowed: opts.managed === true
|
|
78
78
|
}
|
|
79
79
|
};
|
|
80
80
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import os from 'node:os';
|
|
3
|
-
import { exists, readText, runProcess, which } from '../fsx.js';
|
|
3
|
+
import { exists, readJson, readText, runProcess, which } from '../fsx.js';
|
|
4
4
|
export function codexLbEnvPath(home = process.env.HOME || os.homedir()) {
|
|
5
5
|
return path.join(String(home || os.homedir()), '.codex', 'sks-codex-lb.env');
|
|
6
6
|
}
|
|
@@ -10,6 +10,25 @@ export function legacyCodexLbEnvPath(home = process.env.HOME || os.homedir()) {
|
|
|
10
10
|
export function codexLbMetadataPath(home = process.env.HOME || os.homedir()) {
|
|
11
11
|
return path.join(String(home || os.homedir()), '.codex', 'sks-codex-lb.json');
|
|
12
12
|
}
|
|
13
|
+
export function codexLbHealthPath(home = process.env.HOME || os.homedir()) {
|
|
14
|
+
return path.join(String(home || os.homedir()), '.codex', 'sks-codex-lb-health.json');
|
|
15
|
+
}
|
|
16
|
+
export async function readLbHealth(home = process.env.HOME || os.homedir()) {
|
|
17
|
+
const file = codexLbHealthPath(home);
|
|
18
|
+
const raw = await readJson(file, null);
|
|
19
|
+
if (!raw || typeof raw !== 'object')
|
|
20
|
+
return null;
|
|
21
|
+
const degraded = Array.isArray(raw.degraded_models)
|
|
22
|
+
? raw.degraded_models.map((model) => String(model)).filter(Boolean)
|
|
23
|
+
: [];
|
|
24
|
+
return {
|
|
25
|
+
ok: raw.ok !== false,
|
|
26
|
+
degraded_models: degraded,
|
|
27
|
+
quota_low: raw.quota_low === true,
|
|
28
|
+
source: file,
|
|
29
|
+
updated_at: typeof raw.updated_at === 'string' ? raw.updated_at : null
|
|
30
|
+
};
|
|
31
|
+
}
|
|
13
32
|
export function normalizeCodexLbBaseUrl(input = '') {
|
|
14
33
|
let host = String(input || '').trim();
|
|
15
34
|
if (!host)
|
|
@@ -3,6 +3,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
3
3
|
import { COMMANDS, LEGACY_COMMAND_ALIASES } from '../../cli/command-registry.js';
|
|
4
4
|
import { flag } from '../../cli/args.js';
|
|
5
5
|
import { printJson, sksTextLogo } from '../../cli/output.js';
|
|
6
|
+
import { ui as cliUi } from '../../cli/cli-theme.js';
|
|
6
7
|
import { PACKAGE_VERSION, ensureDir, exists, nowIso, projectRoot, readJson, sksRoot, tmpdir, writeJsonAtomic } from '../fsx.js';
|
|
7
8
|
import { COMMAND_CATALOG, DOLLAR_COMMAND_ALIASES, DOLLAR_COMMANDS, USAGE_TOPICS, routePrompt, routeReasoning, reasoningInstruction } from '../routes.js';
|
|
8
9
|
import { initProject, normalizeInstallScope, sksCommandPrefix } from '../init.js';
|
|
@@ -111,6 +112,8 @@ export async function updateCheckCommand(args = []) {
|
|
|
111
112
|
const result = await runSksUpdateCheck();
|
|
112
113
|
if (flag(args, '--json'))
|
|
113
114
|
return printJson(result);
|
|
115
|
+
cliUi.banner('update');
|
|
116
|
+
result.update_available ? cliUi.warn('update available') : cliUi.ok('already current or no update required');
|
|
114
117
|
console.log(`${sksTextLogo()}\n\n${formatSksUpdateCheckText(result)}`);
|
|
115
118
|
}
|
|
116
119
|
export async function updateCommand(sub = 'now', args = []) {
|
|
@@ -132,11 +135,15 @@ export async function updateCommand(sub = 'now', args = []) {
|
|
|
132
135
|
version: valueAfter(effectiveArgs, '--version') || valueAfter(effectiveArgs, '-v'),
|
|
133
136
|
dryRun: flag(effectiveArgs, '--dry-run'),
|
|
134
137
|
projectRoot: root,
|
|
138
|
+
json: flag(effectiveArgs, '--json'),
|
|
139
|
+
quiet: flag(effectiveArgs, '--quiet'),
|
|
135
140
|
timeoutMs: 10 * 60 * 1000,
|
|
136
141
|
maxOutputBytes: 128 * 1024
|
|
137
142
|
}));
|
|
138
143
|
if (flag(effectiveArgs, '--json'))
|
|
139
144
|
return printJson(result);
|
|
145
|
+
cliUi.banner('update');
|
|
146
|
+
result.ok ? cliUi.ok(result.status) : result.status === 'updated_with_issues' ? cliUi.warn(result.status) : cliUi.fail(result.status || 'failed');
|
|
140
147
|
console.log(`${sksTextLogo()}\n`);
|
|
141
148
|
console.log(`SKS update ${result.status}`);
|
|
142
149
|
if (result.command)
|
|
@@ -153,6 +160,16 @@ export async function updateCommand(sub = 'now', args = []) {
|
|
|
153
160
|
console.log(`SKS menu bar: ${result.sks_menubar.status}${result.sks_menubar.app_path ? ` (${result.sks_menubar.app_path})` : ''}`);
|
|
154
161
|
for (const stage of result.stages || [])
|
|
155
162
|
console.log(`Stage ${stage.id}: ${stage.ok ? 'ok' : 'failed'} ${stage.status}`);
|
|
163
|
+
if (result.verification?.length) {
|
|
164
|
+
console.log('Self verification:');
|
|
165
|
+
cliUi.table([
|
|
166
|
+
['check', 'status', 'detail'],
|
|
167
|
+
...result.verification.map((item) => [item.id, item.ok ? 'ok' : 'failed', item.detail || ''])
|
|
168
|
+
]);
|
|
169
|
+
const remediation = [...new Set(result.verification.filter((item) => !item.ok).map((item) => item.remediation).filter((value) => Boolean(value)))];
|
|
170
|
+
for (const action of remediation)
|
|
171
|
+
console.log(`Remediation: ${action}`);
|
|
172
|
+
}
|
|
156
173
|
if (result.error)
|
|
157
174
|
console.log(`Error: ${result.error}`);
|
|
158
175
|
if (!result.ok)
|
|
@@ -264,7 +281,7 @@ export async function postinstallCommand(args = []) {
|
|
|
264
281
|
export async function selftestCommand(args = []) {
|
|
265
282
|
process.env.CI = 'true';
|
|
266
283
|
const root = await projectRoot();
|
|
267
|
-
const tmp = tmpdir();
|
|
284
|
+
const tmp = tmpdir('sks-selftest-');
|
|
268
285
|
await ensureDir(tmp);
|
|
269
286
|
const registry = await buildFeatureRegistry({ root });
|
|
270
287
|
const coverage = validateFeatureRegistry(registry);
|
|
@@ -4,6 +4,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
4
4
|
import { flag } from '../../cli/args.js';
|
|
5
5
|
import { printJson } from '../../cli/output.js';
|
|
6
6
|
import { projectRoot } from '../fsx.js';
|
|
7
|
+
import { evaluateGateProcessOutput } from './gate-result-contract.js';
|
|
7
8
|
const CHECK_SCHEMA = 'sks.check.v1';
|
|
8
9
|
export async function checkCommand(args = []) {
|
|
9
10
|
const root = await projectRoot();
|
|
@@ -31,10 +32,41 @@ export async function checkCommand(args = []) {
|
|
|
31
32
|
shell: false,
|
|
32
33
|
env: { ...process.env, CI: process.env.CI || 'true' }
|
|
33
34
|
});
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
const stdout = String(result.stdout || '');
|
|
36
|
+
let ok = result.status === 0;
|
|
37
|
+
let reason;
|
|
38
|
+
let contract;
|
|
39
|
+
let gateResult = null;
|
|
40
|
+
if (step.name === 'proof-bank-summary') {
|
|
41
|
+
proofBankSummary = parseJsonObject(stdout);
|
|
42
|
+
if (!proofBankSummary) {
|
|
43
|
+
ok = false;
|
|
44
|
+
reason = 'invalid_json_output';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (step.output_contract === 'sks.gate-result.v1') {
|
|
48
|
+
const gateEval = evaluateGateProcessOutput({ status: result.status, stdout, requiresContract: true });
|
|
49
|
+
ok = gateEval.ok;
|
|
50
|
+
reason = gateEval.reason;
|
|
51
|
+
contract = gateEval.contract;
|
|
52
|
+
gateResult = gateEval.gate_result;
|
|
53
|
+
}
|
|
54
|
+
else if (step.name.startsWith('release:')) {
|
|
55
|
+
const gateEval = evaluateGateProcessOutput({ status: result.status, stdout });
|
|
56
|
+
ok = gateEval.ok;
|
|
57
|
+
reason = gateEval.reason;
|
|
58
|
+
contract = gateEval.contract;
|
|
59
|
+
gateResult = gateEval.gate_result;
|
|
60
|
+
}
|
|
61
|
+
steps.push({
|
|
62
|
+
name: step.name,
|
|
63
|
+
ok,
|
|
64
|
+
status: result.status,
|
|
65
|
+
stderr_tail: tail(String(result.stderr || '')),
|
|
66
|
+
...(reason ? { reason } : {}),
|
|
67
|
+
...(contract ? { contract } : {}),
|
|
68
|
+
...(gateResult ? { gate_result: gateResult } : {})
|
|
69
|
+
});
|
|
38
70
|
if (!json) {
|
|
39
71
|
if (result.stdout)
|
|
40
72
|
process.stdout.write(result.stdout);
|
|
@@ -69,7 +101,7 @@ function buildCheckPlan(input) {
|
|
|
69
101
|
}
|
|
70
102
|
else {
|
|
71
103
|
steps.push({ name: buildScript, command: 'npm', args: ['run', buildScript, '--silent'] });
|
|
72
|
-
steps.push({ name: `release:${tier}`, command: process.execPath, args: dagArgs(tier, input.changedSince, input.sla) });
|
|
104
|
+
steps.push({ name: `release:${tier}`, command: process.execPath, args: dagArgs(tier, input.changedSince, input.sla), output_contract: 'sks.gate-result.v1' });
|
|
73
105
|
}
|
|
74
106
|
return {
|
|
75
107
|
tier,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import
|
|
2
|
+
import fsp from 'node:fs/promises';
|
|
3
|
+
import { nowIso, projectRoot, readJson, writeJsonAtomic } from '../fsx.js';
|
|
3
4
|
import { createMission, findLatestMission } from '../mission.js';
|
|
4
5
|
import { flag, readOption } from '../../cli/args.js';
|
|
5
6
|
import { printJson } from '../../cli/output.js';
|
|
@@ -130,17 +131,23 @@ export async function computerUseCommand(command, args = []) {
|
|
|
130
131
|
return;
|
|
131
132
|
}
|
|
132
133
|
const route = command === 'cu' ? '$CU' : '$Computer-Use';
|
|
134
|
+
const gate = await evaluateComputerUseGate(root, missionId);
|
|
135
|
+
await writeJsonAtomic(path.join(root, '.sneakoscope', 'missions', missionId, 'computer-use-gate.json'), gate);
|
|
133
136
|
const proof = await maybeFinalizeRoute(root, {
|
|
134
137
|
missionId,
|
|
135
138
|
route,
|
|
139
|
+
gateFile: 'computer-use-gate.json',
|
|
140
|
+
gate,
|
|
136
141
|
mock: flag(args, '--mock'),
|
|
137
142
|
visual: true,
|
|
138
143
|
requireRelation: flag(args, '--fix-claim') || flag(args, '--require-relation'),
|
|
139
144
|
artifacts: ['computer-use-evidence-ledger.json', 'screen-capture-ledger.json', 'image-voxel-ledger.json', 'visual-anchors.json'],
|
|
140
145
|
claims: [{ id: 'computer-use-evidence', status: flag(args, '--mock') ? 'verified_partial' : 'supported' }],
|
|
141
|
-
|
|
146
|
+
blockers: gate.blockers || [],
|
|
147
|
+
statusHint: gate.passed ? undefined : 'blocked',
|
|
148
|
+
command: { cmd: `sks ${command} ${args.join(' ')}`.trim(), status: gate.passed ? 0 : 1 }
|
|
142
149
|
});
|
|
143
|
-
const result = { schema: 'sks.computer-use-evidence.v1', ok: proof.ok, mission_id: missionId, route, proof: proof.validation };
|
|
150
|
+
const result = { schema: 'sks.computer-use-evidence.v1', ok: proof.ok && gate.passed === true, mission_id: missionId, route, gate, proof: proof.validation };
|
|
144
151
|
if (flag(args, '--json'))
|
|
145
152
|
return printJson(result);
|
|
146
153
|
console.log(`Computer Use evidence: ${proof.ok ? 'ok' : 'blocked'} ${missionId}`);
|
|
@@ -170,7 +177,18 @@ async function importFixture(root, command, args) {
|
|
|
170
177
|
};
|
|
171
178
|
await writeJsonAtomic(path.join(dir, 'computer-use-evidence-ledger.json'), evidence);
|
|
172
179
|
await writeJsonAtomic(path.join(dir, 'screen-capture-ledger.json'), captures);
|
|
173
|
-
const gate = {
|
|
180
|
+
const gate = {
|
|
181
|
+
schema: 'sks.computer-use-gate.v1',
|
|
182
|
+
schema_version: 1,
|
|
183
|
+
passed: false,
|
|
184
|
+
ok: false,
|
|
185
|
+
status: 'blocked',
|
|
186
|
+
execution_class: 'mock_fixture',
|
|
187
|
+
computer_use_evidence: false,
|
|
188
|
+
screen_capture_evidence: false,
|
|
189
|
+
mock: true,
|
|
190
|
+
blockers: ['computer_use_fixture_mode_cannot_claim_real']
|
|
191
|
+
};
|
|
174
192
|
await writeJsonAtomic(path.join(dir, 'computer-use-gate.json'), gate);
|
|
175
193
|
const proof = await maybeFinalizeRoute(root, {
|
|
176
194
|
missionId: id,
|
|
@@ -182,11 +200,48 @@ async function importFixture(root, command, args) {
|
|
|
182
200
|
requireRelation: flag(args, '--fix-claim') || flag(args, '--require-relation'),
|
|
183
201
|
artifacts: ['computer-use-evidence-ledger.json', 'screen-capture-ledger.json', 'image-voxel-ledger.json', 'visual-anchors.json', 'completion-proof.json'],
|
|
184
202
|
claims: [{ id: 'computer-use-import-fixture', status: 'verified_partial' }],
|
|
185
|
-
|
|
203
|
+
statusHint: 'blocked',
|
|
204
|
+
blockers: gate.blockers,
|
|
205
|
+
command: { cmd: `sks ${command} import-fixture --mock`, status: 1 }
|
|
186
206
|
});
|
|
187
|
-
const result = { schema: 'sks.computer-use-import-fixture.v1', ok:
|
|
207
|
+
const result = { schema: 'sks.computer-use-import-fixture.v1', ok: false, mission_id: id, route, gate, proof: proof.validation };
|
|
208
|
+
process.exitCode = 1;
|
|
188
209
|
if (flag(args, '--json'))
|
|
189
210
|
return printJson(result);
|
|
190
|
-
console.log(`Computer Use fixture imported:
|
|
211
|
+
console.log(`Computer Use fixture imported: blocked ${id}`);
|
|
212
|
+
}
|
|
213
|
+
async function evaluateComputerUseGate(root, missionId) {
|
|
214
|
+
const dir = path.join(root, '.sneakoscope', 'missions', missionId);
|
|
215
|
+
const evidence = await readJson(path.join(dir, 'computer-use-evidence-ledger.json'), null);
|
|
216
|
+
const captures = await readJson(path.join(dir, 'screen-capture-ledger.json'), null);
|
|
217
|
+
const blockers = new Set();
|
|
218
|
+
const actions = Array.isArray(evidence?.actions) ? evidence.actions : [];
|
|
219
|
+
const captureRows = Array.isArray(captures?.captures) ? captures.captures : [];
|
|
220
|
+
if (!actions.length)
|
|
221
|
+
blockers.add('computer_use_actions_missing');
|
|
222
|
+
if (actions.some((action) => action?.status === 'mocked' || action?.mock === true) || evidence?.mock === true)
|
|
223
|
+
blockers.add('computer_use_mock_actions_not_evidence');
|
|
224
|
+
if (!captureRows.length)
|
|
225
|
+
blockers.add('screen_capture_evidence_missing');
|
|
226
|
+
for (const capture of captureRows) {
|
|
227
|
+
const rel = String(capture?.path || '');
|
|
228
|
+
const abs = path.isAbsolute(rel) ? rel : path.join(root, rel);
|
|
229
|
+
const stat = await fsp.stat(abs).catch(() => null);
|
|
230
|
+
if (!stat || stat.size < 256)
|
|
231
|
+
blockers.add(`screen_capture_file_missing_or_too_small:${capture?.id || rel || 'unknown'}`);
|
|
232
|
+
if (capture?.status === 'mocked' || capture?.mock === true || captures?.mock === true)
|
|
233
|
+
blockers.add('screen_capture_mock_not_evidence');
|
|
234
|
+
}
|
|
235
|
+
const passed = blockers.size === 0;
|
|
236
|
+
return {
|
|
237
|
+
schema: 'sks.computer-use-gate.v1',
|
|
238
|
+
schema_version: 1,
|
|
239
|
+
passed,
|
|
240
|
+
ok: passed,
|
|
241
|
+
status: passed ? 'pass' : 'blocked',
|
|
242
|
+
computer_use_evidence: actions.length > 0 && ![...blockers].includes('computer_use_mock_actions_not_evidence'),
|
|
243
|
+
screen_capture_evidence: captureRows.length > 0 && ![...blockers].some((blocker) => blocker.startsWith('screen_capture_')),
|
|
244
|
+
blockers: [...blockers]
|
|
245
|
+
};
|
|
191
246
|
}
|
|
192
247
|
//# sourceMappingURL=computer-use-command.js.map
|
|
@@ -6,6 +6,7 @@ import { maybeFinalizeRoute } from '../proof/auto-finalize.js';
|
|
|
6
6
|
import { recordDbSafetyMismatchWrongness } from '../triwiki-wrongness/wrongness-ledger.js';
|
|
7
7
|
import { flag, readOption } from './command-utils.js';
|
|
8
8
|
import { writeRouteCollaborationArtifacts } from '../agents/route-collaboration-ledger.js';
|
|
9
|
+
import { context7EvidenceStatus } from './route-success-helpers.js';
|
|
9
10
|
export async function dbCommand(sub, args = []) {
|
|
10
11
|
const root = await sksRoot();
|
|
11
12
|
if (sub === 'policy') {
|
|
@@ -79,7 +80,9 @@ async function recordDbExpectation(root, input = {}) {
|
|
|
79
80
|
async function finalizeDbCheck(root, { action, args, result, exitCode }) {
|
|
80
81
|
const prompt = `sks db ${action} ${args.join(' ')}`.trim();
|
|
81
82
|
const { id, dir } = await createMission(root, { mode: 'db', prompt });
|
|
82
|
-
const
|
|
83
|
+
const context7 = await context7EvidenceStatus(root, id);
|
|
84
|
+
const destructiveOperationZero = result.level !== 'destructive';
|
|
85
|
+
const blocked = exitCode !== 0 || result.action === 'block' || result.level === 'destructive' || !context7.ok;
|
|
83
86
|
const report = {
|
|
84
87
|
schema: 'sks.db-operation-report.v1',
|
|
85
88
|
mission_id: id,
|
|
@@ -91,11 +94,34 @@ async function finalizeDbCheck(root, { action, args, result, exitCode }) {
|
|
|
91
94
|
ok: !blocked,
|
|
92
95
|
level: result.level || result.risk || result.status || null,
|
|
93
96
|
action: result.action || action,
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
destructive_operation_zero: destructiveOperationZero,
|
|
98
|
+
destructive_blocked: !destructiveOperationZero || (blocked && /drop|delete|truncate|reset|destructive/i.test(JSON.stringify(result))),
|
|
99
|
+
context7_policy: context7.policy,
|
|
100
|
+
context7_evidence: context7.evidence
|
|
101
|
+
},
|
|
102
|
+
blockers: [
|
|
103
|
+
...(!destructiveOperationZero ? ['destructive_operation_found'] : []),
|
|
104
|
+
...(context7.ok ? [] : [context7.blocker])
|
|
105
|
+
]
|
|
96
106
|
};
|
|
97
107
|
await writeJsonAtomic(path.join(dir, 'db-operation-report.json'), report);
|
|
98
|
-
const
|
|
108
|
+
const gateBlockers = [
|
|
109
|
+
...(blocked && destructiveOperationZero ? ['db_operation_blocked'] : []),
|
|
110
|
+
...(!destructiveOperationZero ? ['destructive_operation_found'] : []),
|
|
111
|
+
...(context7.ok ? [] : [context7.blocker])
|
|
112
|
+
];
|
|
113
|
+
const gate = {
|
|
114
|
+
schema: 'sks.db-gate.v1',
|
|
115
|
+
schema_version: 1,
|
|
116
|
+
passed: !blocked,
|
|
117
|
+
ok: !blocked,
|
|
118
|
+
status: blocked ? 'blocked' : 'pass',
|
|
119
|
+
db_operation_report: 'db-operation-report.json',
|
|
120
|
+
destructive_operation_zero: destructiveOperationZero,
|
|
121
|
+
context7_policy: context7.policy,
|
|
122
|
+
context7_evidence: context7.evidence,
|
|
123
|
+
blockers: [...new Set(gateBlockers)]
|
|
124
|
+
};
|
|
99
125
|
await writeJsonAtomic(path.join(dir, 'db-gate.json'), gate);
|
|
100
126
|
const native = await writeRouteCollaborationArtifacts(root, {
|
|
101
127
|
missionId: id,
|
|
@@ -112,7 +138,7 @@ async function finalizeDbCheck(root, { action, args, result, exitCode }) {
|
|
|
112
138
|
artifacts: ['db-operation-report.json', 'completion-proof.json', ...Object.values(native.artifacts || {})],
|
|
113
139
|
dbEvidence: report.db_safety,
|
|
114
140
|
statusHint: blocked ? 'blocked' : 'verified_partial',
|
|
115
|
-
blockers:
|
|
141
|
+
blockers: gate.blockers,
|
|
116
142
|
command: { cmd: prompt, status: exitCode }
|
|
117
143
|
});
|
|
118
144
|
return { ...completion, native_agent_collaboration: native };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { flag } from '../../cli/args.js';
|
|
3
3
|
import { printJson } from '../../cli/output.js';
|
|
4
|
+
import { ui as cliUi } from '../../cli/cli-theme.js';
|
|
4
5
|
import { projectRoot, readText } from '../fsx.js';
|
|
5
6
|
import { clearFastModePreference, fastModePreferencePath, readFastModePreference, resolveFastModePolicy, writeFastModePreference } from '../agents/fast-mode-policy.js';
|
|
6
7
|
import { codexFastModeDesktopStatus, codexLbConfigPath, ensureGlobalCodexFastModeDuringInstall } from '../../cli/install-helpers.js';
|
|
@@ -76,6 +77,8 @@ export async function fastModeCommand(args = []) {
|
|
|
76
77
|
};
|
|
77
78
|
if (flag(args, '--json'))
|
|
78
79
|
return printJson(result);
|
|
80
|
+
cliUi.banner('fast-mode');
|
|
81
|
+
cliUi.ok(`project workers ${result.fast_mode ? 'fast' : 'standard'}`);
|
|
79
82
|
console.log('SKS Fast Mode');
|
|
80
83
|
console.log(`Root: ${root}`);
|
|
81
84
|
console.log(`Global (desktop): ${globalStatus.on ? 'on' : 'off'} (default_profile=${globalStatus.default_profile || 'none'}, top-level ${globalStatus.top_level_default_profile ? 'OK' : 'none'})`);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export const GATE_RESULT_CONTRACT = 'sks.gate-result.v1';
|
|
2
|
+
export function parseGateResultFromStdout(stdout) {
|
|
3
|
+
const lines = String(stdout || '').trim().split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
4
|
+
const last = lines.at(-1);
|
|
5
|
+
if (!last)
|
|
6
|
+
return null;
|
|
7
|
+
try {
|
|
8
|
+
const parsed = JSON.parse(last);
|
|
9
|
+
if (parsed?.schema === GATE_RESULT_CONTRACT && typeof parsed.ok === 'boolean' && Array.isArray(parsed.blockers)) {
|
|
10
|
+
return parsed;
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function evaluateGateProcessOutput({ status, stdout, requiresContract = false }) {
|
|
19
|
+
const gateResult = parseGateResultFromStdout(stdout);
|
|
20
|
+
if (!gateResult) {
|
|
21
|
+
if (requiresContract) {
|
|
22
|
+
return {
|
|
23
|
+
ok: false,
|
|
24
|
+
contract: GATE_RESULT_CONTRACT,
|
|
25
|
+
gate_result: null,
|
|
26
|
+
reason: 'gate_output_contract_violation'
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
ok: status === 0,
|
|
31
|
+
contract: 'legacy_exit_code_only',
|
|
32
|
+
gate_result: null,
|
|
33
|
+
...(status === 0 ? { reason: 'legacy_exit_code_only' } : {})
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
ok: status === 0 && gateResult.ok === true,
|
|
38
|
+
contract: GATE_RESULT_CONTRACT,
|
|
39
|
+
gate_result: gateResult,
|
|
40
|
+
...(gateResult.ok === true ? {} : { reason: 'gate_result_not_ok' })
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=gate-result-contract.js.map
|
|
@@ -2,6 +2,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
2
2
|
import { flag } from '../../cli/args.js';
|
|
3
3
|
import { printJson } from '../../cli/output.js';
|
|
4
4
|
import { projectRoot } from '../fsx.js';
|
|
5
|
+
import { evaluateGateProcessOutput } from './gate-result-contract.js';
|
|
5
6
|
export async function gatesCommand(args = []) {
|
|
6
7
|
const root = await projectRoot();
|
|
7
8
|
const sub = args[0] && !args[0].startsWith('-') ? args[0] : 'run';
|
|
@@ -29,12 +30,16 @@ export async function gatesCommand(args = []) {
|
|
|
29
30
|
maxBuffer: 1024 * 1024 * 20,
|
|
30
31
|
env: { ...process.env, CI: process.env.CI || 'true' }
|
|
31
32
|
});
|
|
33
|
+
const gateEval = evaluateGateProcessOutput({ status: result.status, stdout: String(result.stdout || '') });
|
|
32
34
|
const report = {
|
|
33
35
|
schema: 'sks.gates-command.v1',
|
|
34
|
-
ok:
|
|
36
|
+
ok: gateEval.ok,
|
|
35
37
|
target,
|
|
36
38
|
mode: isPreset ? 'preset' : 'gate',
|
|
37
39
|
status: result.status,
|
|
40
|
+
contract: gateEval.contract,
|
|
41
|
+
gate_result: gateEval.gate_result,
|
|
42
|
+
...(gateEval.reason ? { reason: gateEval.reason } : {}),
|
|
38
43
|
stdout_tail: tail(String(result.stdout || '')),
|
|
39
44
|
stderr_tail: tail(String(result.stderr || ''))
|
|
40
45
|
};
|