sneakoscope 4.8.7 → 5.1.2
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/bench/tasks/t01-off-by-one/repo/package.json +9 -0
- package/bench/tasks/t01-off-by-one/repo/src/pagination.js +5 -0
- package/bench/tasks/t01-off-by-one/repo/test.js +5 -0
- package/bench/tasks/t01-off-by-one/task.json +13 -0
- package/bench/tasks/t02-signature-cochange/repo/package.json +9 -0
- package/bench/tasks/t02-signature-cochange/repo/src/admin.js +5 -0
- package/bench/tasks/t02-signature-cochange/repo/src/audit.js +5 -0
- package/bench/tasks/t02-signature-cochange/repo/src/labels.js +3 -0
- package/bench/tasks/t02-signature-cochange/repo/src/profile.js +5 -0
- package/bench/tasks/t02-signature-cochange/repo/test.js +9 -0
- package/bench/tasks/t02-signature-cochange/task.json +12 -0
- package/bench/tasks/t03-type-puzzle/repo/package.json +9 -0
- package/bench/tasks/t03-type-puzzle/repo/src/config.js +4 -0
- package/bench/tasks/t03-type-puzzle/repo/test.js +6 -0
- package/bench/tasks/t03-type-puzzle/task.json +13 -0
- package/bench/tasks/t04-refactor-preserve/repo/package.json +9 -0
- package/bench/tasks/t04-refactor-preserve/repo/src/cart.js +8 -0
- package/bench/tasks/t04-refactor-preserve/repo/test.js +4 -0
- package/bench/tasks/t04-refactor-preserve/task.json +12 -0
- package/bench/tasks/t05-performance/repo/package.json +9 -0
- package/bench/tasks/t05-performance/repo/src/pairs.js +9 -0
- package/bench/tasks/t05-performance/repo/test.js +11 -0
- package/bench/tasks/t05-performance/task.json +12 -0
- package/bench/tasks/t06-mistake-rule/repo/package.json +9 -0
- package/bench/tasks/t06-mistake-rule/repo/src/loader.js +6 -0
- package/bench/tasks/t06-mistake-rule/repo/test.js +7 -0
- package/bench/tasks/t06-mistake-rule/task.json +12 -0
- 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 +62 -6
- 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-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-worker-backend-router.js +58 -1
- package/dist/core/codex-app/sks-menubar.js +18 -5
- 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 +21 -2
- 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 +22 -1
- 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-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 +10 -0
- 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 +366 -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/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/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 +1 -1
- 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/ux-review-real-loop-fixture-check.js +9 -4
- package/dist/scripts/ux-review-run-wires-imagegen-check.js +4 -0
- package/docs/assets/sneakoscope-architecture-pipeline.jpg +0 -0
- package/docs/demo.tape +28 -0
- package/package.json +67 -3
- 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-context7-mcp-repair-blackbox.js +0 -16
- package/dist/scripts/doctor-dirty-repair-blackbox.js +0 -22
- package/dist/scripts/doctor-dirty-semantic-blackbox.js +0 -8
- package/dist/scripts/doctor-fix-production-blackbox.js +0 -26
- package/dist/scripts/doctor-native-capability-repair-blackbox.js +0 -39
- package/dist/scripts/doctor-startup-config-repair-blackbox.js +0 -13
- package/dist/scripts/doctor-supabase-mcp-repair-blackbox.js +0 -14
- 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/project-skill-dedupe-blackbox.js +0 -36
- 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/supabase-secret-preservation-blackbox.js +0 -29
- 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/update-preserves-supabase-keys-blackbox.js +0 -27
- 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
|
@@ -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)
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import fsp from 'node:fs/promises';
|
|
2
4
|
import { spawnSync } from 'node:child_process';
|
|
3
5
|
import { COMMANDS, LEGACY_COMMAND_ALIASES } from '../../cli/command-registry.js';
|
|
4
6
|
import { flag } from '../../cli/args.js';
|
|
5
7
|
import { printJson, sksTextLogo } from '../../cli/output.js';
|
|
6
|
-
import {
|
|
8
|
+
import { ui as cliUi } from '../../cli/cli-theme.js';
|
|
9
|
+
import { PACKAGE_VERSION, ensureDir, exists, nowIso, projectRoot, readJson, sksRoot, writeJsonAtomic } from '../fsx.js';
|
|
7
10
|
import { COMMAND_CATALOG, DOLLAR_COMMAND_ALIASES, DOLLAR_COMMANDS, USAGE_TOPICS, routePrompt, routeReasoning, reasoningInstruction } from '../routes.js';
|
|
8
11
|
import { initProject, normalizeInstallScope, sksCommandPrefix } from '../init.js';
|
|
9
12
|
import { buildFeatureRegistry, validateFeatureRegistry } from '../feature-registry.js';
|
|
@@ -111,6 +114,8 @@ export async function updateCheckCommand(args = []) {
|
|
|
111
114
|
const result = await runSksUpdateCheck();
|
|
112
115
|
if (flag(args, '--json'))
|
|
113
116
|
return printJson(result);
|
|
117
|
+
cliUi.banner('update');
|
|
118
|
+
result.update_available ? cliUi.warn('update available') : cliUi.ok('already current or no update required');
|
|
114
119
|
console.log(`${sksTextLogo()}\n\n${formatSksUpdateCheckText(result)}`);
|
|
115
120
|
}
|
|
116
121
|
export async function updateCommand(sub = 'now', args = []) {
|
|
@@ -132,11 +137,15 @@ export async function updateCommand(sub = 'now', args = []) {
|
|
|
132
137
|
version: valueAfter(effectiveArgs, '--version') || valueAfter(effectiveArgs, '-v'),
|
|
133
138
|
dryRun: flag(effectiveArgs, '--dry-run'),
|
|
134
139
|
projectRoot: root,
|
|
140
|
+
json: flag(effectiveArgs, '--json'),
|
|
141
|
+
quiet: flag(effectiveArgs, '--quiet'),
|
|
135
142
|
timeoutMs: 10 * 60 * 1000,
|
|
136
143
|
maxOutputBytes: 128 * 1024
|
|
137
144
|
}));
|
|
138
145
|
if (flag(effectiveArgs, '--json'))
|
|
139
146
|
return printJson(result);
|
|
147
|
+
cliUi.banner('update');
|
|
148
|
+
result.ok ? cliUi.ok(result.status) : result.status === 'updated_with_issues' ? cliUi.warn(result.status) : cliUi.fail(result.status || 'failed');
|
|
140
149
|
console.log(`${sksTextLogo()}\n`);
|
|
141
150
|
console.log(`SKS update ${result.status}`);
|
|
142
151
|
if (result.command)
|
|
@@ -153,6 +162,16 @@ export async function updateCommand(sub = 'now', args = []) {
|
|
|
153
162
|
console.log(`SKS menu bar: ${result.sks_menubar.status}${result.sks_menubar.app_path ? ` (${result.sks_menubar.app_path})` : ''}`);
|
|
154
163
|
for (const stage of result.stages || [])
|
|
155
164
|
console.log(`Stage ${stage.id}: ${stage.ok ? 'ok' : 'failed'} ${stage.status}`);
|
|
165
|
+
if (result.verification?.length) {
|
|
166
|
+
console.log('Self verification:');
|
|
167
|
+
cliUi.table([
|
|
168
|
+
['check', 'status', 'detail'],
|
|
169
|
+
...result.verification.map((item) => [item.id, item.ok ? 'ok' : 'failed', item.detail || ''])
|
|
170
|
+
]);
|
|
171
|
+
const remediation = [...new Set(result.verification.filter((item) => !item.ok).map((item) => item.remediation).filter((value) => Boolean(value)))];
|
|
172
|
+
for (const action of remediation)
|
|
173
|
+
console.log(`Remediation: ${action}`);
|
|
174
|
+
}
|
|
156
175
|
if (result.error)
|
|
157
176
|
console.log(`Error: ${result.error}`);
|
|
158
177
|
if (!result.ok)
|
|
@@ -264,7 +283,7 @@ export async function postinstallCommand(args = []) {
|
|
|
264
283
|
export async function selftestCommand(args = []) {
|
|
265
284
|
process.env.CI = 'true';
|
|
266
285
|
const root = await projectRoot();
|
|
267
|
-
const tmp = tmpdir();
|
|
286
|
+
const tmp = await fsp.mkdtemp(path.join(os.tmpdir(), 'sks-selftest-'));
|
|
268
287
|
await ensureDir(tmp);
|
|
269
288
|
const registry = await buildFeatureRegistry({ root });
|
|
270
289
|
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
|
};
|
|
@@ -1,7 +1,27 @@
|
|
|
1
|
-
import { dirSize, formatBytes, packageRoot, sksRoot } from '../fsx.js';
|
|
1
|
+
import { dirSize, formatBytes, packageRoot, projectRoot, sksRoot } from '../fsx.js';
|
|
2
2
|
import { enforceRetention, storageReport } from '../retention.js';
|
|
3
3
|
import { flag } from './command-utils.js';
|
|
4
|
-
|
|
4
|
+
import { projectTriwikiToAgentsMd } from '../triwiki/agents-md-projector.js';
|
|
5
|
+
import { compileMistakeRules } from '../verification/mistake-rule-compiler.js';
|
|
6
|
+
export async function memoryCommand(sub, args = []) {
|
|
7
|
+
const action = String(sub || '').toLowerCase();
|
|
8
|
+
if (['build', 'project', 'agents', 'agents-md'].includes(action)) {
|
|
9
|
+
const root = await projectRoot();
|
|
10
|
+
const [result, rules] = await Promise.all([
|
|
11
|
+
projectTriwikiToAgentsMd(root, { maxLocalFiles: Number(readOption(args, '--max-local-files', 8)) }),
|
|
12
|
+
compileMistakeRules(root).catch((err) => ({ compiled: [], skipped: [`compile_failed:${err instanceof Error ? err.message : String(err)}`] }))
|
|
13
|
+
]);
|
|
14
|
+
const output = { ...result, mistake_rules: rules };
|
|
15
|
+
if (flag(args, '--json'))
|
|
16
|
+
return console.log(JSON.stringify(output, null, 2));
|
|
17
|
+
console.log(`SKS memory build: ${result.ok ? 'ok' : result.reason}`);
|
|
18
|
+
for (const file of result.written)
|
|
19
|
+
console.log(`- ${file}`);
|
|
20
|
+
console.log(`- mistake rules compiled: ${rules.compiled.length}, skipped: ${rules.skipped.length}`);
|
|
21
|
+
if (!result.ok)
|
|
22
|
+
process.exitCode = 1;
|
|
23
|
+
return output;
|
|
24
|
+
}
|
|
5
25
|
return gcCommand(args || []);
|
|
6
26
|
}
|
|
7
27
|
export async function gcCommand(args = []) {
|
|
@@ -16,6 +36,13 @@ export async function gcCommand(args = []) {
|
|
|
16
36
|
for (const a of res.actions.slice(0, 20))
|
|
17
37
|
console.log(`- ${a.action} ${a.path || a.mission || ''} ${a.bytes ? formatBytes(a.bytes) : ''}`);
|
|
18
38
|
}
|
|
39
|
+
function readOption(args = [], name, fallback = null) {
|
|
40
|
+
const index = args.indexOf(name);
|
|
41
|
+
if (index >= 0 && args[index + 1] && !String(args[index + 1]).startsWith('--'))
|
|
42
|
+
return args[index + 1];
|
|
43
|
+
const prefixed = args.find((arg) => String(arg).startsWith(`${name}=`));
|
|
44
|
+
return prefixed ? String(prefixed).slice(name.length + 1) : fallback;
|
|
45
|
+
}
|
|
19
46
|
export async function statsCommand(args = []) {
|
|
20
47
|
const root = await sksRoot();
|
|
21
48
|
const report = await storageReport(root);
|
|
@@ -6,6 +6,7 @@ import { GOAL_BRIDGE_ARTIFACT, GOAL_WORKFLOW_ARTIFACT, updateGoalWorkflow, write
|
|
|
6
6
|
import { flag, promptOf, resolveMissionId } from './command-utils.js';
|
|
7
7
|
import { compileGoalToLoopPlan } from '../loops/goal-to-loop-compat.js';
|
|
8
8
|
import { runLoopPlan } from '../loops/loop-runtime.js';
|
|
9
|
+
import { evaluateLocalGate } from './route-success-helpers.js';
|
|
9
10
|
export async function goalCommand(sub, args = []) {
|
|
10
11
|
const known = new Set(['create', 'pause', 'resume', 'clear', 'status', 'help', '--help', '-h']);
|
|
11
12
|
const action = known.has(sub) ? sub : 'create';
|
|
@@ -39,10 +40,16 @@ async function goalCreate(args) {
|
|
|
39
40
|
const workflow = await writeGoalWorkflow(dir, mission, { action: 'create', prompt });
|
|
40
41
|
const plan = await compileGoalToLoopPlan({ root, missionId: id, goalText: prompt, legacyGoalOptions: { native_goal: workflow.native_goal } });
|
|
41
42
|
const result = await runLoopPlan({ root, plan, parallelism: 'balanced' });
|
|
42
|
-
await
|
|
43
|
+
const gate = await evaluateLocalGate({ root, missionId: id, gateFile: 'loop-graph-proof.json' });
|
|
44
|
+
const ok = result.ok === true && gate.ok === true;
|
|
45
|
+
await setCurrent(root, { mission_id: id, mode: 'GOAL', route: 'Goal', route_command: '$Goal', phase: ok ? 'GOAL_LOOP_COMPLETED' : 'GOAL_LOOP_BLOCKED', questions_allowed: true, implementation_allowed: true, native_goal: workflow.native_goal, stop_gate: 'loop-graph-proof.json', stop_gate_blockers: gate.blockers }, { replace: true });
|
|
46
|
+
if (!ok)
|
|
47
|
+
process.exitCode = 1;
|
|
43
48
|
if (flag(args, '--json'))
|
|
44
|
-
return console.log(JSON.stringify({ schema: 'sks.goal-create.v1', ok
|
|
49
|
+
return console.log(JSON.stringify({ schema: 'sks.goal-create.v1', ok, mission_id: id, workflow, loop_plan: plan, loop_result: result, gate }, null, 2));
|
|
45
50
|
console.log(`Goal compiled to Loop Graph: ${id}`);
|
|
51
|
+
if (!ok)
|
|
52
|
+
console.log(`Gate blocked: ${gate.blockers.join(', ') || 'loop_result_not_ok'}`);
|
|
46
53
|
console.log('Use `sks loop status latest` to inspect.');
|
|
47
54
|
console.log(`Artifact: ${path.relative(root, path.join(dir, GOAL_WORKFLOW_ARTIFACT))}`);
|
|
48
55
|
console.log(`Bridge: ${path.relative(root, path.join(dir, GOAL_BRIDGE_ARTIFACT))}`);
|