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
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { exists, readJson, readText } from '../fsx.js';
|
|
3
|
+
export async function context7EvidenceStatus(root, missionId = null) {
|
|
4
|
+
const candidates = [
|
|
5
|
+
missionId ? path.join(root, '.sneakoscope', 'missions', missionId, 'context7-evidence.jsonl') : null,
|
|
6
|
+
path.join(root, '.sneakoscope', 'state', 'context7-evidence.jsonl'),
|
|
7
|
+
path.join(root, '.sneakoscope', 'memory', 'q2_facts', 'stack-current-docs.md')
|
|
8
|
+
].filter(Boolean);
|
|
9
|
+
for (const file of candidates) {
|
|
10
|
+
if (!(await exists(file)))
|
|
11
|
+
continue;
|
|
12
|
+
const text = await readText(file, '');
|
|
13
|
+
if (/\S/.test(text) && /(context7|resolve[-_]?library|query[-_]?docs|get[-_]?library|official docs|vendor docs)/i.test(text)) {
|
|
14
|
+
return { ok: true, policy: 'required_satisfied', evidence: path.relative(root, file).split(path.sep).join('/') };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return { ok: false, policy: 'required_not_satisfied', evidence: null, blocker: 'context7_policy_required_not_satisfied' };
|
|
18
|
+
}
|
|
19
|
+
export async function artifactPresence(root, dir, artifacts) {
|
|
20
|
+
const rows = await Promise.all(artifacts.map(async (artifact) => {
|
|
21
|
+
const file = path.isAbsolute(artifact) ? artifact : path.join(dir, artifact);
|
|
22
|
+
return { artifact, present: await exists(file) };
|
|
23
|
+
}));
|
|
24
|
+
const missing = rows.filter((row) => !row.present).map((row) => row.artifact);
|
|
25
|
+
return { ok: missing.length === 0, rows, missing };
|
|
26
|
+
}
|
|
27
|
+
export async function evaluateLocalGate(input) {
|
|
28
|
+
const missionDir = input.dir || (input.missionId ? path.join(input.root, '.sneakoscope', 'missions', input.missionId) : input.root);
|
|
29
|
+
const gatePath = path.isAbsolute(input.gateFile) ? input.gateFile : path.join(missionDir, input.gateFile);
|
|
30
|
+
const gate = await readJson(gatePath, null);
|
|
31
|
+
const blockers = [];
|
|
32
|
+
if (!gate)
|
|
33
|
+
blockers.push(`${path.basename(input.gateFile)}_missing`);
|
|
34
|
+
if (gate) {
|
|
35
|
+
if (!(gate.passed === true || gate.ok === true || gate.status === 'pass' || gate.status === 'passed'))
|
|
36
|
+
blockers.push('gate_not_passed');
|
|
37
|
+
if (gate.ok === false)
|
|
38
|
+
blockers.push('gate_ok_false');
|
|
39
|
+
if (Array.isArray(gate.blockers) && gate.blockers.length)
|
|
40
|
+
blockers.push(...gate.blockers.map(String));
|
|
41
|
+
if (Array.isArray(gate.missing_fields) && gate.missing_fields.length)
|
|
42
|
+
blockers.push(...gate.missing_fields.map((field) => `missing_field:${field}`));
|
|
43
|
+
for (const section of input.requiredSections || []) {
|
|
44
|
+
if (gate[section] == null)
|
|
45
|
+
blockers.push(`missing_gate_section:${section}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const artifactCheck = await artifactPresence(input.root, missionDir, input.requiredArtifacts || []);
|
|
49
|
+
blockers.push(...artifactCheck.missing.map((artifact) => `missing_artifact:${artifact}`));
|
|
50
|
+
const uniqueBlockers = [...new Set(blockers)];
|
|
51
|
+
return {
|
|
52
|
+
ok: uniqueBlockers.length === 0,
|
|
53
|
+
gate,
|
|
54
|
+
gate_path: gatePath,
|
|
55
|
+
blockers: uniqueBlockers,
|
|
56
|
+
artifacts: artifactCheck
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=route-success-helpers.js.map
|
|
@@ -62,7 +62,15 @@ export async function runCommand(args = []) {
|
|
|
62
62
|
return finalizeMockRun(root, { id, route, prompt, args, classification, mode });
|
|
63
63
|
}
|
|
64
64
|
async function finalizeMockRun(root, { id, route, prompt, args, classification, mode, }) {
|
|
65
|
-
const gate = {
|
|
65
|
+
const gate = {
|
|
66
|
+
schema: 'sks.run-gate.v1',
|
|
67
|
+
ok: false,
|
|
68
|
+
passed: false,
|
|
69
|
+
route: route.command,
|
|
70
|
+
mock: true,
|
|
71
|
+
execution_class: 'mock_fixture',
|
|
72
|
+
blockers: ['run_mock_fixture_cannot_claim_real_completion']
|
|
73
|
+
};
|
|
66
74
|
await writeJsonAtomic(path.join(missionDir(root, id), 'run-gate.json'), gate);
|
|
67
75
|
const proof = await finalizeRoute(root, {
|
|
68
76
|
missionId: id,
|
|
@@ -76,19 +84,20 @@ async function finalizeMockRun(root, { id, route, prompt, args, classification,
|
|
|
76
84
|
command: { cmd: `sks run "${prompt}" --mock`, status: 0 },
|
|
77
85
|
});
|
|
78
86
|
const trust = await loadTrustReport(root, id);
|
|
87
|
+
const completionOk = proof.ok && proof.proof?.status !== 'mock_only' && gate.passed === true;
|
|
79
88
|
await setCurrent(root, {
|
|
80
89
|
mission_id: id,
|
|
81
90
|
mode: 'RUN',
|
|
82
91
|
route: route.id,
|
|
83
92
|
route_command: route.command,
|
|
84
|
-
phase:
|
|
93
|
+
phase: completionOk ? 'RUN_MOCK_FINALIZED' : 'RUN_MOCK_BLOCKED',
|
|
85
94
|
implementation_allowed: true,
|
|
86
95
|
completion_proof: 'completion-proof.json',
|
|
87
96
|
trust_report: 'trust-report.json',
|
|
88
97
|
});
|
|
89
98
|
const result = {
|
|
90
99
|
schema: 'sks.run.v2',
|
|
91
|
-
ok:
|
|
100
|
+
ok: completionOk,
|
|
92
101
|
mission_id: id,
|
|
93
102
|
route: route.command,
|
|
94
103
|
mode,
|
|
@@ -98,6 +107,8 @@ async function finalizeMockRun(root, { id, route, prompt, args, classification,
|
|
|
98
107
|
completion_proof: { ok: proof.ok, validation: proof.validation },
|
|
99
108
|
trust_report: trust,
|
|
100
109
|
};
|
|
110
|
+
if (!result.ok)
|
|
111
|
+
process.exitCode = 1;
|
|
101
112
|
if (flag(args, '--json')) {
|
|
102
113
|
console.log(JSON.stringify(result, null, 2));
|
|
103
114
|
return result;
|
|
@@ -235,7 +246,7 @@ async function executeRouteCommand(root, route, prompt, { auto = false } = {}) {
|
|
|
235
246
|
return routeExecutionResult(route, ['sks', ...commandArgs].join(' '), result, {
|
|
236
247
|
okStatus: 'completed',
|
|
237
248
|
trustStatus: 'verified_partial',
|
|
238
|
-
executionKind:
|
|
249
|
+
executionKind: 'live_route',
|
|
239
250
|
});
|
|
240
251
|
}
|
|
241
252
|
async function runAutoVerification(root, missionId) {
|
|
@@ -304,7 +315,7 @@ function routeExecutionResult(route, command, result, options = {}) {
|
|
|
304
315
|
schema: 'sks.run-route-execution.v1',
|
|
305
316
|
ok,
|
|
306
317
|
status: ok ? (options.okStatus || 'completed') : 'blocked',
|
|
307
|
-
execution_kind: ok ? (options.executionKind || '
|
|
318
|
+
execution_kind: ok ? (options.executionKind || 'live_route') : 'blocked',
|
|
308
319
|
route: route.command,
|
|
309
320
|
command,
|
|
310
321
|
exit_code: result.code,
|
|
@@ -314,7 +325,7 @@ function routeExecutionResult(route, command, result, options = {}) {
|
|
|
314
325
|
trust_status: ok ? options.trustStatus || 'verified_partial' : 'blocked',
|
|
315
326
|
blockers: ok ? [] : ['route_command_failed'],
|
|
316
327
|
unverified: ok
|
|
317
|
-
? options.unverified || ['sks run --execute
|
|
328
|
+
? options.unverified || ['sks run --execute ran the selected route command; route-specific gates remain authoritative for final trust.']
|
|
318
329
|
: [],
|
|
319
330
|
next_action: ok ? 'review completion proof and trust report' : 'inspect run-route-execution.json stderr_tail',
|
|
320
331
|
};
|
|
@@ -538,7 +549,7 @@ async function writeLightweightTrustReport(root, missionId, route, statusHint, p
|
|
|
538
549
|
const report = {
|
|
539
550
|
schema: TRUST_REPORT_SCHEMA,
|
|
540
551
|
...trustKernelMetadata(),
|
|
541
|
-
ok: proofOk && !['blocked', 'failed', 'not_verified'].includes(status),
|
|
552
|
+
ok: proofOk && !['blocked', 'failed', 'not_verified', 'mock_only'].includes(status),
|
|
542
553
|
mission_id: missionId,
|
|
543
554
|
route,
|
|
544
555
|
status,
|
|
@@ -551,6 +562,7 @@ async function writeLightweightTrustReport(root, missionId, route, statusHint, p
|
|
|
551
562
|
lightweight: true,
|
|
552
563
|
reason: 'safe_deterministic_run_wrapper'
|
|
553
564
|
},
|
|
565
|
+
trust_basis: 'lightweight',
|
|
554
566
|
evidence: {
|
|
555
567
|
completion_proof: `.sneakoscope/missions/${missionId}/completion-proof.json`,
|
|
556
568
|
route_contract: null,
|
|
@@ -2,7 +2,8 @@ import path from 'node:path';
|
|
|
2
2
|
import { printJson } from '../../cli/output.js';
|
|
3
3
|
import { projectRoot } from '../fsx.js';
|
|
4
4
|
import { flag, readOption } from './command-utils.js';
|
|
5
|
-
import { runSearchVisibilityApply, runSearchVisibilityAudit, runSearchVisibilityDoctor, runSearchVisibilityFixture, runSearchVisibilityPlan, runSearchVisibilityRollback, runSearchVisibilityStatus, runSearchVisibilityVerify, } from '../search-visibility/index.js';
|
|
5
|
+
import { runSearchVisibilityApply, runSearchVisibilityAudit, runSearchVisibilityDoctor, runSearchVisibilityFixture, runSearchVisibilityPlan, runSearchVisibilityRollback, runSearchVisibilityStatus, runSearchVisibilityVerify, resolveSearchVisibilityMission, } from '../search-visibility/index.js';
|
|
6
|
+
import { evaluateLocalGate } from './route-success-helpers.js';
|
|
6
7
|
export async function seoCommand(args = []) {
|
|
7
8
|
return runSearchVisibilityCommand('seo', args, 'seo');
|
|
8
9
|
}
|
|
@@ -15,6 +16,26 @@ export async function runSearchVisibilityCommand(mode, args = [], displayCommand
|
|
|
15
16
|
const rest = args.slice(1);
|
|
16
17
|
const options = await parseOptions(rest);
|
|
17
18
|
let result;
|
|
19
|
+
if (action === 'apply' && options.apply) {
|
|
20
|
+
const mission = await resolveSearchVisibilityMission(options.root, firstPositional(rest) || 'latest');
|
|
21
|
+
const blockers = [];
|
|
22
|
+
if (!mission)
|
|
23
|
+
blockers.push('mission_required_for_apply');
|
|
24
|
+
else {
|
|
25
|
+
const planGate = await evaluateLocalGate({ root: mission.root, dir: mission.dir, gateFile: mode === 'seo' ? 'seo-gate.json' : 'geo-gate.json', requiredArtifacts: ['search-visibility/mutation-plan.json'] });
|
|
26
|
+
blockers.push(...planGate.blockers.filter((blocker) => blocker !== 'gate_not_passed' && blocker !== 'gate_ok_false'));
|
|
27
|
+
}
|
|
28
|
+
if (blockers.length) {
|
|
29
|
+
result = { schema: 'sks.search-visibility.apply-command.v1', ok: false, route: mode === 'seo' ? '$SEO-GEO-OPTIMIZER' : '$SEO-GEO-OPTIMIZER', status: 'blocked', blockers };
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
if (options.json) {
|
|
32
|
+
printJson(result);
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
printHuman(mode, action, result);
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
18
39
|
if (action === 'doctor')
|
|
19
40
|
result = await runSearchVisibilityDoctor(mode, options);
|
|
20
41
|
else if (action === 'audit')
|
|
@@ -33,6 +54,7 @@ export async function runSearchVisibilityCommand(mode, args = [], displayCommand
|
|
|
33
54
|
result = await runSearchVisibilityFixture(mode, options);
|
|
34
55
|
else
|
|
35
56
|
return usage(mode, 2, displayCommand);
|
|
57
|
+
result = await applySearchVisibilityGateResult(mode, action, result, options);
|
|
36
58
|
if (isBlocked(result))
|
|
37
59
|
process.exitCode = 1;
|
|
38
60
|
if (options.json) {
|
|
@@ -42,6 +64,32 @@ export async function runSearchVisibilityCommand(mode, args = [], displayCommand
|
|
|
42
64
|
printHuman(mode, action, result);
|
|
43
65
|
return result;
|
|
44
66
|
}
|
|
67
|
+
async function applySearchVisibilityGateResult(mode, action, result, options) {
|
|
68
|
+
if (!result || typeof result !== 'object' || !result.mission_id)
|
|
69
|
+
return result;
|
|
70
|
+
const mission = await resolveSearchVisibilityMission(options.root, result.mission_id);
|
|
71
|
+
if (!mission)
|
|
72
|
+
return { ...result, ok: false, blockers: [...(result.blockers || []), 'mission_missing_for_gate_evaluation'] };
|
|
73
|
+
const requiredArtifacts = action === 'apply'
|
|
74
|
+
? ['search-visibility/mutation-plan.json', 'search-visibility/rollback-manifest.json', 'search-visibility/verification-report.json']
|
|
75
|
+
: action === 'status'
|
|
76
|
+
? []
|
|
77
|
+
: ['search-visibility/verification-report.json'];
|
|
78
|
+
const evaluated = await evaluateLocalGate({
|
|
79
|
+
root: mission.root,
|
|
80
|
+
dir: mission.dir,
|
|
81
|
+
gateFile: mode === 'seo' ? 'seo-gate.json' : 'geo-gate.json',
|
|
82
|
+
requiredArtifacts
|
|
83
|
+
});
|
|
84
|
+
const blockers = [...new Set([...(result.blockers || []), ...evaluated.blockers])];
|
|
85
|
+
return {
|
|
86
|
+
...result,
|
|
87
|
+
ok: result.ok === true && evaluated.ok === true,
|
|
88
|
+
status: result.ok === true && evaluated.ok === true ? result.status : 'blocked',
|
|
89
|
+
gate_evaluation: evaluated,
|
|
90
|
+
blockers
|
|
91
|
+
};
|
|
92
|
+
}
|
|
45
93
|
function normalizeOptimizerArgs(args) {
|
|
46
94
|
const out = [...args];
|
|
47
95
|
const first = String(out[0] || '').toLowerCase();
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import * as http from 'node:http';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { flag } from '../../cli/args.js';
|
|
4
|
+
import { printJson } from '../../cli/output.js';
|
|
5
|
+
import { ui } from '../../cli/cli-theme.js';
|
|
6
|
+
import { DASHBOARD_HTML } from '../ui/dashboard-html.js';
|
|
7
|
+
import { findLatestMission, missionDir } from '../mission.js';
|
|
8
|
+
import { nowIso, projectRoot, readJson, readText, runProcess } from '../fsx.js';
|
|
9
|
+
import { readZellijSlotTelemetrySnapshot } from '../zellij/zellij-slot-telemetry.js';
|
|
10
|
+
export async function uiCommand(args = []) {
|
|
11
|
+
const root = path.resolve(String(readOption(args, '--root', '') || await projectRoot()));
|
|
12
|
+
if (flag(args, '--once')) {
|
|
13
|
+
const state = await collectUiState(root, String(readOption(args, '--mission', 'latest') || 'latest'));
|
|
14
|
+
if (flag(args, '--json'))
|
|
15
|
+
return printJson(state);
|
|
16
|
+
ui.banner('ui');
|
|
17
|
+
ui.ok(`state ${state.mission_id || 'latest'} ${state.gates.length} gates`);
|
|
18
|
+
return state;
|
|
19
|
+
}
|
|
20
|
+
const requestedPort = Number(readOption(args, '--port', '4477'));
|
|
21
|
+
const port = Number.isFinite(requestedPort) && requestedPort > 0 ? Math.floor(requestedPort) : 4477;
|
|
22
|
+
const mission = String(readOption(args, '--mission', 'latest') || 'latest');
|
|
23
|
+
const server = http.createServer(async (req, res) => {
|
|
24
|
+
try {
|
|
25
|
+
const url = new URL(req.url || '/', 'http://127.0.0.1');
|
|
26
|
+
if (url.pathname === '/') {
|
|
27
|
+
res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
|
|
28
|
+
res.end(DASHBOARD_HTML);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (url.pathname === '/events')
|
|
32
|
+
return sseStream(res, root, String(url.searchParams.get('mission') || mission));
|
|
33
|
+
if (url.pathname === '/api/state') {
|
|
34
|
+
res.writeHead(200, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' });
|
|
35
|
+
res.end(JSON.stringify(await collectUiState(root, String(url.searchParams.get('mission') || mission))));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
res.writeHead(404);
|
|
39
|
+
res.end('not found');
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
res.writeHead(500, { 'content-type': 'application/json; charset=utf-8' });
|
|
43
|
+
res.end(JSON.stringify({ ok: false, error: sanitizeText(err?.message || String(err)) }));
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const actualPort = await listenLocal(server, port);
|
|
47
|
+
const url = `http://127.0.0.1:${actualPort}`;
|
|
48
|
+
ui.banner('ui');
|
|
49
|
+
ui.ok(`dashboard ${url}`);
|
|
50
|
+
void runProcess('/usr/bin/open', [url], { timeoutMs: 5000, maxOutputBytes: 4096 }).catch(() => undefined);
|
|
51
|
+
return new Promise(() => undefined);
|
|
52
|
+
}
|
|
53
|
+
export async function collectUiState(root, missionInput = 'latest') {
|
|
54
|
+
const missionId = missionInput === 'latest' ? await findLatestMission(root) : missionInput;
|
|
55
|
+
const snapshot = missionId ? await readZellijSlotTelemetrySnapshot(root, missionId).catch(() => null) : null;
|
|
56
|
+
const gates = missionId ? await readLatestGateSummaries(root, missionId) : [];
|
|
57
|
+
const events = missionId ? await tailJsonl(path.join(missionDir(root, missionId), 'events.jsonl'), 30) : [];
|
|
58
|
+
const mission = missionId ? await readJson(path.join(missionDir(root, missionId), 'mission.json'), null).catch(() => null) : null;
|
|
59
|
+
return sanitizeForUi({
|
|
60
|
+
schema: 'sks.ui-state.v1',
|
|
61
|
+
ok: true,
|
|
62
|
+
ts: nowIso(),
|
|
63
|
+
mission_id: missionId,
|
|
64
|
+
route: mission?.mode || mission?.route || null,
|
|
65
|
+
snapshot,
|
|
66
|
+
gates,
|
|
67
|
+
events
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async function sseStream(res, root, mission) {
|
|
71
|
+
res.writeHead(200, {
|
|
72
|
+
'content-type': 'text/event-stream',
|
|
73
|
+
'cache-control': 'no-cache, no-store',
|
|
74
|
+
connection: 'keep-alive'
|
|
75
|
+
});
|
|
76
|
+
const tick = async () => {
|
|
77
|
+
const state = await collectUiState(root, mission).catch((err) => ({ ok: false, ts: nowIso(), error: sanitizeText(err?.message || String(err)) }));
|
|
78
|
+
res.write(`data: ${JSON.stringify(state)}\n\n`);
|
|
79
|
+
};
|
|
80
|
+
await tick();
|
|
81
|
+
const timer = setInterval(tick, 1000);
|
|
82
|
+
res.on('close', () => clearInterval(timer));
|
|
83
|
+
}
|
|
84
|
+
async function readLatestGateSummaries(root, missionId) {
|
|
85
|
+
const dir = missionDir(root, missionId);
|
|
86
|
+
const files = ['stop-gate.json', 'naruto-gate.json', 'team-gate.json', 'qa-gate.json', 'reflection-gate.json', 'completion-proof.json'];
|
|
87
|
+
const rows = [];
|
|
88
|
+
for (const file of files) {
|
|
89
|
+
const gate = await readJson(path.join(dir, file), null).catch(() => null);
|
|
90
|
+
if (!gate)
|
|
91
|
+
continue;
|
|
92
|
+
rows.push({
|
|
93
|
+
id: file,
|
|
94
|
+
ok: gate.passed === true || gate.ok === true || gate.status === 'passed',
|
|
95
|
+
missing: Array.isArray(gate.missing) ? gate.missing : Array.isArray(gate.blockers) ? gate.blockers : [],
|
|
96
|
+
source: `.sneakoscope/missions/${missionId}/${file}`
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return rows;
|
|
100
|
+
}
|
|
101
|
+
async function tailJsonl(file, limit) {
|
|
102
|
+
const text = await readText(file, '').catch(() => '');
|
|
103
|
+
return String(text || '').split(/\r?\n/).filter(Boolean).slice(-limit).map((line) => {
|
|
104
|
+
try {
|
|
105
|
+
return JSON.parse(line);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return { ts: null, type: 'raw', text: line.slice(0, 500) };
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
async function listenLocal(server, startPort) {
|
|
113
|
+
for (let offset = 0; offset < 20; offset += 1) {
|
|
114
|
+
const port = startPort + offset;
|
|
115
|
+
const result = await new Promise((resolve) => {
|
|
116
|
+
const onError = (err) => {
|
|
117
|
+
server.off('listening', onListen);
|
|
118
|
+
resolve({ ok: false, code: err.code || 'listen_failed' });
|
|
119
|
+
};
|
|
120
|
+
const onListen = () => {
|
|
121
|
+
server.off('error', onError);
|
|
122
|
+
resolve({ ok: true });
|
|
123
|
+
};
|
|
124
|
+
server.once('error', onError);
|
|
125
|
+
server.once('listening', onListen);
|
|
126
|
+
server.listen(port, '127.0.0.1');
|
|
127
|
+
});
|
|
128
|
+
if (result.ok)
|
|
129
|
+
return port;
|
|
130
|
+
if (result.code !== 'EADDRINUSE')
|
|
131
|
+
throw new Error(`dashboard listen failed: ${result.code}`);
|
|
132
|
+
}
|
|
133
|
+
throw new Error('dashboard listen failed: no available localhost port');
|
|
134
|
+
}
|
|
135
|
+
function sanitizeForUi(value) {
|
|
136
|
+
if (Array.isArray(value))
|
|
137
|
+
return value.map((item) => sanitizeForUi(item));
|
|
138
|
+
if (!value || typeof value !== 'object')
|
|
139
|
+
return typeof value === 'string' ? sanitizeText(value) : value;
|
|
140
|
+
const out = {};
|
|
141
|
+
for (const [key, child] of Object.entries(value)) {
|
|
142
|
+
if (/(?:key|token|secret|password|credential|cookie|auth)/i.test(key))
|
|
143
|
+
continue;
|
|
144
|
+
out[key] = sanitizeForUi(child);
|
|
145
|
+
}
|
|
146
|
+
return out;
|
|
147
|
+
}
|
|
148
|
+
function sanitizeText(value) {
|
|
149
|
+
return String(value || '')
|
|
150
|
+
.replace(/sk-[A-Za-z0-9_-]{12,}/g, '[redacted]')
|
|
151
|
+
.replace(/(?:api[_-]?key|secret|token|password|credential)/ig, '[redacted-field]')
|
|
152
|
+
.slice(0, 2000);
|
|
153
|
+
}
|
|
154
|
+
function readOption(args = [], name, fallback = null) {
|
|
155
|
+
const index = args.indexOf(name);
|
|
156
|
+
if (index >= 0 && args[index + 1] && !String(args[index + 1]).startsWith('--'))
|
|
157
|
+
return args[index + 1];
|
|
158
|
+
const prefixed = args.find((arg) => String(arg).startsWith(`${name}=`));
|
|
159
|
+
return prefixed ? prefixed.slice(name.length + 1) : fallback;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=ui-command.js.map
|
|
@@ -4,10 +4,12 @@ import fsp from 'node:fs/promises';
|
|
|
4
4
|
import readline from 'node:readline/promises';
|
|
5
5
|
import { stdin as input, stdout as output } from 'node:process';
|
|
6
6
|
import { ensureDir, exists, readJson, readText, runProcess, writeJsonAtomic } from '../fsx.js';
|
|
7
|
+
import { ui as cliUi } from '../../cli/cli-theme.js';
|
|
7
8
|
import { uninstallSksMenuBar } from '../codex-app/sks-menubar.js';
|
|
8
9
|
import { writeCodexConfigGuarded } from '../codex/codex-config-guard.js';
|
|
9
10
|
import { sweepSksTempDirs } from '../retention.js';
|
|
10
11
|
import { reconcileSkills } from '../init/skills.js';
|
|
12
|
+
import { removeTriwikiAgentsMdBlocks } from '../triwiki/agents-md-projector.js';
|
|
11
13
|
export async function uninstallCommand(args = []) {
|
|
12
14
|
const opts = {
|
|
13
15
|
yes: hasFlag(args, '--yes') || hasFlag(args, '-y'),
|
|
@@ -24,8 +26,11 @@ export async function uninstallCommand(args = []) {
|
|
|
24
26
|
const result = { schema: 'sks.uninstall.v1', ok: true, dry_run: true, inventory };
|
|
25
27
|
if (opts.json)
|
|
26
28
|
console.log(JSON.stringify(result, null, 2));
|
|
27
|
-
else
|
|
29
|
+
else {
|
|
30
|
+
cliUi.banner('uninstall');
|
|
31
|
+
cliUi.warn('dry run only');
|
|
28
32
|
printInventoryTable(inventory);
|
|
33
|
+
}
|
|
29
34
|
return result;
|
|
30
35
|
}
|
|
31
36
|
if (!opts.yes && !(await confirmUninstall())) {
|
|
@@ -66,6 +71,8 @@ export async function uninstallCommand(args = []) {
|
|
|
66
71
|
if (opts.json)
|
|
67
72
|
console.log(JSON.stringify(report, null, 2));
|
|
68
73
|
else {
|
|
74
|
+
cliUi.banner('uninstall');
|
|
75
|
+
report.ok ? cliUi.ok('removed configured SKS surfaces') : cliUi.fail('uninstall completed with errors');
|
|
69
76
|
console.log('SKS uninstall complete.');
|
|
70
77
|
console.log('Final package removal command: npm uninstall -g sneakoscope');
|
|
71
78
|
}
|
|
@@ -84,6 +91,7 @@ async function collectSksInventory(opts) {
|
|
|
84
91
|
['hooks-json', path.join(home, '.codex', 'hooks.json'), 'strip SKS-managed hooks', '--keep-config'],
|
|
85
92
|
['sks-home', path.join(home, '.sneakoscope'), 'remove', '--keep-data'],
|
|
86
93
|
['sks-global-home', path.join(home, '.sneakoscope-global'), 'remove', '--keep-data'],
|
|
94
|
+
['agents-md-memory-block', path.join(opts.root, 'AGENTS.md'), 'strip SKS Project Memory block', '--purge-projects'],
|
|
87
95
|
['tmp', os.tmpdir(), 'sweep sks temp dirs', 'default']
|
|
88
96
|
];
|
|
89
97
|
const out = [];
|
|
@@ -263,6 +271,12 @@ async function purgeProjectArtifacts(report, opts) {
|
|
|
263
271
|
report.errors.push({ id: 'project-skills', root, error: err?.message || String(err) });
|
|
264
272
|
});
|
|
265
273
|
await fsp.rm(path.join(root, '.codex'), { recursive: true, force: true }).catch(() => null);
|
|
274
|
+
const removedBlocks = await removeTriwikiAgentsMdBlocks(root).catch((err) => {
|
|
275
|
+
report.errors.push({ id: 'agents-md-memory-block', root, error: err?.message || String(err) });
|
|
276
|
+
return [];
|
|
277
|
+
});
|
|
278
|
+
if (removedBlocks.length)
|
|
279
|
+
report.removed.push({ id: 'agents-md-memory-block', root, result: { ok: true, files: removedBlocks.length } });
|
|
266
280
|
await fsp.rm(path.join(root, 'SNEAKOSCOPE.md'), { force: true }).catch(() => null);
|
|
267
281
|
if (!opts.keepData)
|
|
268
282
|
await fsp.rm(path.join(root, '.sneakoscope'), { recursive: true, force: true }).catch(() => null);
|
package/dist/core/db-safety.js
CHANGED
|
@@ -609,8 +609,8 @@ export function dbBlockReason(decision) {
|
|
|
609
609
|
return [
|
|
610
610
|
'Sneakoscope Codex Database Safety Gate blocked this operation.',
|
|
611
611
|
`Reasons: ${(decision.reasons || []).join(', ') || 'unknown'}.`,
|
|
612
|
-
'Default DB mode is read-only. Destructive SQL-plane operations require an explicit active
|
|
613
|
-
'Use read-only/project-scoped Supabase MCP URLs outside
|
|
612
|
+
'Default DB mode is read-only. Destructive SQL-plane operations require an explicit active MAD-SKS sql-plane capability opened by $MAD-SKS/sks mad-sks sql|apply-migration or the deprecated $MAD-DB/sks mad-db redirect.',
|
|
613
|
+
'Use read-only/project-scoped Supabase MCP URLs outside MAD-SKS sql-plane. Supabase project/account/billing/credential control-plane operations remain denied even there.'
|
|
614
614
|
].join(' ');
|
|
615
615
|
}
|
|
616
616
|
export async function scanDbSafety(root, opts = {}) {
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { nowIso, writeJsonAtomic } from '../fsx.js';
|
|
3
3
|
import { isDoctorPhaseClean, markDoctorPhaseClean } from './doctor-dirty-planner.js';
|
|
4
|
+
import { ui as cliUi } from '../../cli/cli-theme.js';
|
|
4
5
|
export async function runDoctorFixTransaction(input) {
|
|
5
6
|
const startedAt = nowIso();
|
|
6
7
|
const phases = [];
|
|
7
8
|
const proofIdsUsed = [];
|
|
8
9
|
let rollbackPerformed = false;
|
|
10
|
+
const liveOutput = input.json !== true && input.machineOnly !== true;
|
|
9
11
|
for (const definition of input.phases) {
|
|
10
12
|
const phaseStarted = nowIso();
|
|
11
13
|
const startedMs = Date.now();
|
|
14
|
+
if (liveOutput)
|
|
15
|
+
cliUi.step(`▸ ${definition.id} ...`);
|
|
12
16
|
let phase = {
|
|
13
17
|
id: definition.id,
|
|
14
18
|
ok: false,
|
|
@@ -32,6 +36,8 @@ export async function runDoctorFixTransaction(input) {
|
|
|
32
36
|
completed_at: nowIso(),
|
|
33
37
|
duration_ms: Math.max(0, Date.now() - startedMs)
|
|
34
38
|
});
|
|
39
|
+
if (liveOutput)
|
|
40
|
+
cliUi.step(`✔ ${definition.id} (${Math.round((Date.now() - startedMs) / 1000)}s)`);
|
|
35
41
|
continue;
|
|
36
42
|
}
|
|
37
43
|
try {
|
|
@@ -71,6 +77,8 @@ export async function runDoctorFixTransaction(input) {
|
|
|
71
77
|
proofIdsUsed.push(proofId);
|
|
72
78
|
}
|
|
73
79
|
phases.push(phase);
|
|
80
|
+
if (liveOutput)
|
|
81
|
+
cliUi.step(`${phase.ok ? '✔' : '✖'} ${definition.id} (${Math.round((phase.duration_ms || 0) / 1000)}s)`);
|
|
74
82
|
}
|
|
75
83
|
const writeInput = {
|
|
76
84
|
root: input.root,
|
|
@@ -10,6 +10,7 @@ export async function runDoctorZellijRepair(input) {
|
|
|
10
10
|
autoApprove: args.includes('--yes') || args.includes('-y'),
|
|
11
11
|
installHomebrew: args.includes('--install-homebrew') || process.env.SKS_ALLOW_HOMEBREW_INSTALL === '1',
|
|
12
12
|
dryRun: args.includes('--dry-run'),
|
|
13
|
+
quiet: args.includes('--json') || args.includes('--machine-only'),
|
|
13
14
|
interactive: Boolean(process.stdin.isTTY && process.stdout.isTTY && process.env.SKS_NO_QUESTION !== '1'),
|
|
14
15
|
allowHeadlessFallback: false,
|
|
15
16
|
env: process.env
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { CODEX_APP_IMAGE_GENERATION_DOC_URL } from '../routes.js';
|
|
3
|
+
import { detectImagegenCapability } from '../imagegen/imagegen-capability.js';
|
|
4
|
+
import { ensureDir, nowIso, runProcess, which, writeJsonAtomic } from '../fsx.js';
|
|
5
|
+
export const DOCTOR_IMAGEGEN_REPAIR_SCHEMA = 'sks.doctor-imagegen-repair.v1';
|
|
6
|
+
export async function repairCodexImagegen(input) {
|
|
7
|
+
const root = path.resolve(input.root || process.cwd());
|
|
8
|
+
const apply = input.apply === true;
|
|
9
|
+
const steps = [];
|
|
10
|
+
const before = await detectImagegenCapability({
|
|
11
|
+
codexBin: input.codexBin || undefined,
|
|
12
|
+
timeoutMs: input.timeoutMs || 5000
|
|
13
|
+
}).catch((err) => ({ ok: false, core_ready: false, blockers: [messageOf(err)], codex_app: { available: false, blocker: messageOf(err) } }));
|
|
14
|
+
let codexBin = input.codexBin || await which('codex').catch(() => null);
|
|
15
|
+
let versionStep;
|
|
16
|
+
if (codexBin) {
|
|
17
|
+
const version = await runProcess(codexBin, ['--version'], { timeoutMs: input.timeoutMs || 5000, maxOutputBytes: 16 * 1024 })
|
|
18
|
+
.catch((err) => ({ code: 1, stdout: '', stderr: messageOf(err) }));
|
|
19
|
+
versionStep = {
|
|
20
|
+
id: 'codex_cli_version',
|
|
21
|
+
ok: version.code === 0,
|
|
22
|
+
attempted: true,
|
|
23
|
+
command: `${codexBin} --version`,
|
|
24
|
+
exit_code: version.code,
|
|
25
|
+
stdout_tail: tail(version.stdout),
|
|
26
|
+
stderr_tail: tail(version.stderr),
|
|
27
|
+
blocker: version.code === 0 ? null : 'codex_cli_version_failed'
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
versionStep = {
|
|
32
|
+
id: 'codex_cli_version',
|
|
33
|
+
ok: false,
|
|
34
|
+
attempted: false,
|
|
35
|
+
command: 'codex --version',
|
|
36
|
+
blocker: 'codex_binary_missing'
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
steps.push(versionStep);
|
|
40
|
+
if (!codexBin && apply && (input.autoInstallCodex === true || process.env.SKS_IMAGEGEN_AUTO_INSTALL_CODEX === '1')) {
|
|
41
|
+
const npmBin = await which('npm').catch(() => null);
|
|
42
|
+
if (npmBin) {
|
|
43
|
+
const install = await runProcess(npmBin, ['i', '-g', '@openai/codex@latest'], {
|
|
44
|
+
timeoutMs: 180000,
|
|
45
|
+
maxOutputBytes: 128 * 1024
|
|
46
|
+
}).catch((err) => ({ code: 1, stdout: '', stderr: messageOf(err) }));
|
|
47
|
+
steps.push({
|
|
48
|
+
id: 'codex_cli_install',
|
|
49
|
+
ok: install.code === 0,
|
|
50
|
+
attempted: true,
|
|
51
|
+
command: `${npmBin} i -g @openai/codex@latest`,
|
|
52
|
+
exit_code: install.code,
|
|
53
|
+
stdout_tail: tail(install.stdout),
|
|
54
|
+
stderr_tail: tail(install.stderr),
|
|
55
|
+
blocker: install.code === 0 ? null : 'codex_cli_install_failed'
|
|
56
|
+
});
|
|
57
|
+
codexBin = await which('codex').catch(() => null);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
steps.push({
|
|
61
|
+
id: 'codex_cli_install',
|
|
62
|
+
ok: false,
|
|
63
|
+
attempted: false,
|
|
64
|
+
command: 'npm i -g @openai/codex@latest',
|
|
65
|
+
blocker: 'npm_missing'
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if (!codexBin) {
|
|
70
|
+
steps.push({
|
|
71
|
+
id: 'codex_cli_install',
|
|
72
|
+
ok: false,
|
|
73
|
+
attempted: false,
|
|
74
|
+
command: 'npm i -g @openai/codex@latest',
|
|
75
|
+
blocker: apply ? 'auto_install_requires_SKS_IMAGEGEN_AUTO_INSTALL_CODEX_1' : 'doctor_fix_not_requested'
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (codexBin && before?.core_ready !== true && apply) {
|
|
79
|
+
const enable = await runProcess(codexBin, ['features', 'enable', 'image_generation'], {
|
|
80
|
+
timeoutMs: input.timeoutMs || 10000,
|
|
81
|
+
maxOutputBytes: 32 * 1024
|
|
82
|
+
}).catch((err) => ({ code: 1, stdout: '', stderr: messageOf(err) }));
|
|
83
|
+
steps.push({
|
|
84
|
+
id: 'image_generation_feature_enable',
|
|
85
|
+
ok: enable.code === 0,
|
|
86
|
+
attempted: true,
|
|
87
|
+
command: `${codexBin} features enable image_generation`,
|
|
88
|
+
exit_code: enable.code,
|
|
89
|
+
stdout_tail: tail(enable.stdout),
|
|
90
|
+
stderr_tail: tail(enable.stderr),
|
|
91
|
+
blocker: enable.code === 0 ? null : 'codex_feature_enable_unsupported_or_failed'
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
steps.push({
|
|
96
|
+
id: 'image_generation_feature_enable',
|
|
97
|
+
ok: before?.core_ready === true,
|
|
98
|
+
attempted: false,
|
|
99
|
+
command: codexBin ? `${codexBin} features enable image_generation` : 'codex features enable image_generation',
|
|
100
|
+
blocker: before?.core_ready === true ? null : apply ? 'codex_cli_missing' : 'doctor_fix_not_requested'
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const after = await detectImagegenCapability({
|
|
104
|
+
codexBin: codexBin || undefined,
|
|
105
|
+
timeoutMs: input.timeoutMs || 5000
|
|
106
|
+
}).catch((err) => ({ ok: false, core_ready: false, blockers: [messageOf(err)], codex_app: { available: false, blocker: messageOf(err) } }));
|
|
107
|
+
steps.push({
|
|
108
|
+
id: 'imagegen_capability_redetect',
|
|
109
|
+
ok: after?.core_ready === true,
|
|
110
|
+
attempted: true,
|
|
111
|
+
command: 'codex features list --json',
|
|
112
|
+
blocker: after?.core_ready === true ? null : 'codex_app_builtin_imagegen_capability_missing'
|
|
113
|
+
});
|
|
114
|
+
const recovered = after?.core_ready === true;
|
|
115
|
+
const blockers = recovered ? [] : [
|
|
116
|
+
...new Set([
|
|
117
|
+
...(after?.core_blockers || []),
|
|
118
|
+
...(after?.blockers || []),
|
|
119
|
+
'codex_imagegen_unavailable'
|
|
120
|
+
].map(String))
|
|
121
|
+
];
|
|
122
|
+
let report = {
|
|
123
|
+
schema: DOCTOR_IMAGEGEN_REPAIR_SCHEMA,
|
|
124
|
+
generated_at: nowIso(),
|
|
125
|
+
ok: recovered,
|
|
126
|
+
attempted: before?.core_ready !== true,
|
|
127
|
+
apply,
|
|
128
|
+
recovered,
|
|
129
|
+
before,
|
|
130
|
+
after,
|
|
131
|
+
steps,
|
|
132
|
+
blockers,
|
|
133
|
+
manual_actions: recovered ? [] : [
|
|
134
|
+
`Install/update Codex CLI if missing: npm i -g @openai/codex@latest`,
|
|
135
|
+
`Open Codex App settings and enable image_generation / $imagegen.`,
|
|
136
|
+
`Verify with: codex features list --json`,
|
|
137
|
+
`Docs: ${CODEX_APP_IMAGE_GENERATION_DOC_URL}`
|
|
138
|
+
],
|
|
139
|
+
docs_url: CODEX_APP_IMAGE_GENERATION_DOC_URL
|
|
140
|
+
};
|
|
141
|
+
if (input.reportPath !== null) {
|
|
142
|
+
const reportPath = input.reportPath || path.join(root, '.sneakoscope', 'reports', 'doctor-imagegen-repair.json');
|
|
143
|
+
try {
|
|
144
|
+
await ensureDir(path.dirname(reportPath));
|
|
145
|
+
await writeJsonAtomic(reportPath, report);
|
|
146
|
+
report = { ...report, report_path: reportPath };
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
report = { ...report, report_write_failed: true, report_write_error: messageOf(err) };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return report;
|
|
153
|
+
}
|
|
154
|
+
function tail(value, max = 2000) {
|
|
155
|
+
const text = String(value || '');
|
|
156
|
+
return text.length > max ? text.slice(-max) : text;
|
|
157
|
+
}
|
|
158
|
+
function messageOf(err) {
|
|
159
|
+
return err instanceof Error ? err.message : String(err);
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=imagegen-repair.js.map
|