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
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { appendJsonl, appendJsonlMany, readJson, writeJsonAtomic } from '../fsx.js';
|
|
2
|
+
import { appendJsonl, appendJsonlMany, ensureDir, readJson, writeJsonAtomic } from '../fsx.js';
|
|
3
3
|
import { AGENT_PATCH_QUEUE_SCHEMA, InMemoryAgentPatchQueue, buildAgentPatchOwnershipLedger } from './agent-patch-queue.js';
|
|
4
4
|
import { AgentPatchTransactionJournal } from './agent-patch-transaction-journal.js';
|
|
5
|
+
import { normalizeAgentPatchEnvelope } from './agent-patch-schema.js';
|
|
6
|
+
import { scanImpact } from '../verification/impact-scan.js';
|
|
7
|
+
import { runMachineFeedback } from '../verification/machine-feedback.js';
|
|
8
|
+
import { analyzeDiffQuality } from '../verification/diff-quality.js';
|
|
5
9
|
export const AGENT_PATCH_QUEUE_ARTIFACT = 'agent-patch-queue.json';
|
|
6
10
|
export const AGENT_PATCH_QUEUE_EVENTS_ARTIFACT = 'agent-patch-queue-events.jsonl';
|
|
7
11
|
export const AGENT_PATCH_OWNERSHIP_LEDGER_ARTIFACT = 'agent-patch-ownership-ledger.json';
|
|
@@ -15,7 +19,13 @@ export class PersistentAgentPatchQueueStore {
|
|
|
15
19
|
this.journal = new AgentPatchTransactionJournal(artifactDir);
|
|
16
20
|
}
|
|
17
21
|
async enqueue(input, context = {}) {
|
|
18
|
-
const
|
|
22
|
+
const preflight = await this.runQualityPreflight(input, context);
|
|
23
|
+
const entry = this.queue.enqueue(input, {
|
|
24
|
+
...(context.mission_id ? { mission_id: context.mission_id } : {}),
|
|
25
|
+
...(context.route ? { route: context.route } : {}),
|
|
26
|
+
preflight_violations: preflight.violations,
|
|
27
|
+
preflight_reports: preflight.reports
|
|
28
|
+
});
|
|
19
29
|
await this.persistSnapshot();
|
|
20
30
|
await this.appendEvent(this.queue.events.at(-1));
|
|
21
31
|
await this.journal.append({
|
|
@@ -29,6 +39,43 @@ export class PersistentAgentPatchQueueStore {
|
|
|
29
39
|
});
|
|
30
40
|
return entry;
|
|
31
41
|
}
|
|
42
|
+
async runQualityPreflight(input, context = {}) {
|
|
43
|
+
const envelope = normalizeAgentPatchEnvelope(input);
|
|
44
|
+
const changedFiles = changedFilesForEnvelope(envelope);
|
|
45
|
+
const patchText = patchTextForEnvelope(envelope);
|
|
46
|
+
const root = envelope.git_worktree?.worktree_path || context.root || process.cwd();
|
|
47
|
+
const reportDir = path.join(this.artifactDir, 'patch-quality', safeName(`${envelope.agent_id}-${envelope.session_id}-${Date.now()}`));
|
|
48
|
+
await ensureDir(reportDir);
|
|
49
|
+
const [impact, diffQuality, feedback] = await Promise.all([
|
|
50
|
+
scanImpact(root, changedFiles, patchText).catch((err) => ({ schema: 'sks.impact-scan.v1', changed_symbols: [], references: [], cochange_required: [], tool: 'builtin', error: errorMessage(err) })),
|
|
51
|
+
analyzeDiffQuality({
|
|
52
|
+
root,
|
|
53
|
+
changedFiles,
|
|
54
|
+
patchText,
|
|
55
|
+
plannedFiles: envelope.allowed_paths || envelope.lease_proof?.allowed_paths || []
|
|
56
|
+
}).catch((err) => ({ schema: 'sks.diff-quality.v1', minimality: { plan_files: 0, touched_files: changedFiles.length, ratio: 1 }, dead_additions: [], comment_noise: 0, guard_bloat: 0, warnings: [], errors: [`diff_quality_failed:${errorMessage(err)}`] })),
|
|
57
|
+
runMachineFeedback(root, changedFiles, { timeoutMs: 60_000 }).catch((err) => ({ schema: 'sks.machine-feedback.v1', ok: false, typecheck: { ok: false, errors: [errorMessage(err)] }, lint: { ok: true, errors: [] }, tests: { ok: true, selected: [], failed: [], skipped_reason: 'machine_feedback_exception' }, duration_ms: 0 }))
|
|
58
|
+
]);
|
|
59
|
+
await writeJsonAtomic(path.join(reportDir, 'impact-scan.json'), impact);
|
|
60
|
+
await writeJsonAtomic(path.join(reportDir, 'diff-quality.json'), diffQuality);
|
|
61
|
+
await writeJsonAtomic(path.join(reportDir, 'machine-feedback.json'), feedback);
|
|
62
|
+
const cochangeAck = envelope.cochange_acknowledged === true && String(envelope.cochange_acknowledged_reason || '').trim().length > 0;
|
|
63
|
+
const violations = [
|
|
64
|
+
...(impact.cochange_required?.length && !cochangeAck ? [`impact_scan_cochange_missing:${impact.cochange_required.slice(0, 5).join(',')}`] : []),
|
|
65
|
+
...((diffQuality.errors || []).map((issue) => `diff_quality:${issue}`)),
|
|
66
|
+
...(feedback.ok === false ? ['machine_feedback_failed'] : []),
|
|
67
|
+
...(isBugfixKind(context.work_item_kind, envelope.task_slice_id) && !validRegressionProof(envelope.regression_proof || context.regression_proof) ? ['tdd_evidence_missing'] : []),
|
|
68
|
+
...(isRepairKind(context.work_item_kind, envelope.task_slice_id) && !(envelope.repair_hypothesis || context.repair_hypothesis) ? ['repair_without_hypothesis'] : [])
|
|
69
|
+
];
|
|
70
|
+
return {
|
|
71
|
+
violations,
|
|
72
|
+
reports: {
|
|
73
|
+
impact_scan: path.relative(this.artifactDir, path.join(reportDir, 'impact-scan.json')),
|
|
74
|
+
diff_quality: path.relative(this.artifactDir, path.join(reportDir, 'diff-quality.json')),
|
|
75
|
+
machine_feedback: path.relative(this.artifactDir, path.join(reportDir, 'machine-feedback.json'))
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
32
79
|
async markApplying(id) {
|
|
33
80
|
await this.transition(id, () => this.queue.markApplying(id));
|
|
34
81
|
}
|
|
@@ -98,4 +145,50 @@ export class PersistentAgentPatchQueueStore {
|
|
|
98
145
|
await appendJsonlMany(path.join(this.artifactDir, AGENT_PATCH_QUEUE_EVENTS_ARTIFACT), events.filter(Boolean));
|
|
99
146
|
}
|
|
100
147
|
}
|
|
148
|
+
function isBugfixKind(kind, id) {
|
|
149
|
+
const text = `${String(kind || '')} ${String(id || '')}`.toLowerCase();
|
|
150
|
+
return /\b(bugfix|fix|bug|regression|broken|failure|crash|error)\b|버그|회귀/.test(text);
|
|
151
|
+
}
|
|
152
|
+
function isRepairKind(kind, id) {
|
|
153
|
+
const text = `${String(kind || '')} ${String(id || '')}`.toLowerCase();
|
|
154
|
+
return /\b(conflict_resolution|repair|conflict|rebase|rollback)\b|수리|충돌/.test(text);
|
|
155
|
+
}
|
|
156
|
+
function validRegressionProof(proof) {
|
|
157
|
+
return Boolean(proof && proof.failed_before === true && proof.passed_after === true && String(proof.test_file || '').trim());
|
|
158
|
+
}
|
|
159
|
+
function changedFilesForEnvelope(envelope) {
|
|
160
|
+
const files = envelope.git_worktree?.changed_files?.length
|
|
161
|
+
? envelope.git_worktree.changed_files
|
|
162
|
+
: envelope.operations.map((operation) => operation.path);
|
|
163
|
+
return [...new Set(files.map(normalizePath).filter(Boolean))];
|
|
164
|
+
}
|
|
165
|
+
function patchTextForEnvelope(envelope) {
|
|
166
|
+
return envelope.operations.map((operation) => {
|
|
167
|
+
if (operation.diff)
|
|
168
|
+
return operation.diff;
|
|
169
|
+
if (operation.op === 'replace')
|
|
170
|
+
return [
|
|
171
|
+
`--- a/${operation.path}`,
|
|
172
|
+
`+++ b/${operation.path}`,
|
|
173
|
+
`-${operation.search || ''}`,
|
|
174
|
+
`+${operation.replace || ''}`
|
|
175
|
+
].join('\n');
|
|
176
|
+
if (operation.op === 'write')
|
|
177
|
+
return [
|
|
178
|
+
`--- /dev/null`,
|
|
179
|
+
`+++ b/${operation.path}`,
|
|
180
|
+
...String(operation.content || '').split(/\r?\n/).map((line) => `+${line}`)
|
|
181
|
+
].join('\n');
|
|
182
|
+
return '';
|
|
183
|
+
}).join('\n');
|
|
184
|
+
}
|
|
185
|
+
function normalizePath(value) {
|
|
186
|
+
return String(value || '').replace(/\\/g, '/').replace(/^\.\/+/, '');
|
|
187
|
+
}
|
|
188
|
+
function safeName(value) {
|
|
189
|
+
return String(value || 'patch').replace(/[^A-Za-z0-9_.-]+/g, '-').slice(0, 160);
|
|
190
|
+
}
|
|
191
|
+
function errorMessage(err) {
|
|
192
|
+
return err instanceof Error ? err.message : String(err);
|
|
193
|
+
}
|
|
101
194
|
//# sourceMappingURL=agent-patch-queue-store.js.map
|
|
@@ -6,6 +6,7 @@ export class InMemoryAgentPatchQueue {
|
|
|
6
6
|
enqueue(input, context = {}) {
|
|
7
7
|
const envelope = normalizeAgentPatchEnvelope(input);
|
|
8
8
|
const validation = validateAgentPatchEnvelope(envelope);
|
|
9
|
+
const preflightViolations = Array.isArray(context.preflight_violations) ? context.preflight_violations.map(String) : [];
|
|
9
10
|
const now = new Date().toISOString();
|
|
10
11
|
const leaseId = envelope.lease_id || envelope.lease_proof?.lease_id;
|
|
11
12
|
const entry = {
|
|
@@ -19,8 +20,9 @@ export class InMemoryAgentPatchQueue {
|
|
|
19
20
|
...(leaseId ? { lease_id: leaseId } : {}),
|
|
20
21
|
write_paths: envelope.operations.map((operation) => operation.path),
|
|
21
22
|
envelope,
|
|
22
|
-
status: validation.ok ? 'pending' : 'rejected',
|
|
23
|
-
violations: validation.violations,
|
|
23
|
+
status: validation.ok && preflightViolations.length === 0 ? 'pending' : 'rejected',
|
|
24
|
+
violations: [...validation.violations, ...preflightViolations],
|
|
25
|
+
...(context.preflight_reports ? { quality_reports: context.preflight_reports } : {}),
|
|
24
26
|
created_at: now,
|
|
25
27
|
updated_at: now
|
|
26
28
|
};
|
|
@@ -97,7 +99,8 @@ export function buildAgentPatchOwnershipLedger(entries) {
|
|
|
97
99
|
status: entry.status,
|
|
98
100
|
created_at: entry.created_at,
|
|
99
101
|
updated_at: entry.updated_at,
|
|
100
|
-
violations: [...entry.violations]
|
|
102
|
+
violations: [...entry.violations],
|
|
103
|
+
quality_reports: entry.quality_reports || null
|
|
101
104
|
}));
|
|
102
105
|
}
|
|
103
106
|
//# sourceMappingURL=agent-patch-queue.js.map
|
|
@@ -31,6 +31,11 @@ export function normalizeAgentPatchEnvelope(input) {
|
|
|
31
31
|
...(input?.rationale ? { rationale: String(input.rationale) } : {}),
|
|
32
32
|
...(input?.verification_hint ? { verification_hint: normalizeHint(input.verification_hint) } : {}),
|
|
33
33
|
...(input?.rollback_hint ? { rollback_hint: normalizeHint(input.rollback_hint) } : {}),
|
|
34
|
+
...(input?.cochange_acknowledged === undefined ? {} : { cochange_acknowledged: Boolean(input.cochange_acknowledged) }),
|
|
35
|
+
...(input?.cochange_acknowledged_reason === undefined ? {} : { cochange_acknowledged_reason: String(input.cochange_acknowledged_reason) }),
|
|
36
|
+
...(input?.regression_proof ? { regression_proof: normalizeRegressionProof(input.regression_proof) } : {}),
|
|
37
|
+
...(input?.repair_hypothesis && typeof input.repair_hypothesis === 'object' ? { repair_hypothesis: input.repair_hypothesis } : {}),
|
|
38
|
+
...(input?.tournament && typeof input.tournament === 'object' ? { tournament: input.tournament } : {}),
|
|
34
39
|
operations: Array.isArray(input?.operations) ? input.operations.map(normalizeOperation) : []
|
|
35
40
|
};
|
|
36
41
|
}
|
|
@@ -135,6 +140,14 @@ function normalizeHint(input) {
|
|
|
135
140
|
...(input?.notes === undefined ? {} : { notes: String(input.notes) })
|
|
136
141
|
};
|
|
137
142
|
}
|
|
143
|
+
function normalizeRegressionProof(input) {
|
|
144
|
+
return {
|
|
145
|
+
...(input?.test_file === undefined ? {} : { test_file: String(input.test_file) }),
|
|
146
|
+
...(input?.failed_before === undefined ? {} : { failed_before: Boolean(input.failed_before) }),
|
|
147
|
+
...(input?.passed_after === undefined ? {} : { passed_after: Boolean(input.passed_after) }),
|
|
148
|
+
...(input?.output_digest === undefined ? {} : { output_digest: String(input.output_digest) })
|
|
149
|
+
};
|
|
150
|
+
}
|
|
138
151
|
function pathAllowedByLease(operationPath, allowedPaths) {
|
|
139
152
|
const rel = normalizePatchPath(operationPath);
|
|
140
153
|
return allowedPaths.map(normalizePatchPath).some((allowed) => rel === allowed || rel.startsWith(`${allowed}/`));
|
|
@@ -129,6 +129,11 @@ export async function writeAgentProofEvidence(root, input) {
|
|
|
129
129
|
narutoWorkGraph
|
|
130
130
|
});
|
|
131
131
|
const changedFileLeaseBlockers = readOnlyNoWriteLeaseMode ? [] : agentChangedFileLeaseViolations(input.results || [], input.partition?.leases || []);
|
|
132
|
+
const schedulerBackfillSatisfied = !scheduler
|
|
133
|
+
|| Number(scheduler.expected_backfill_count || 0) <= Number(scheduler.backfill_count || 0)
|
|
134
|
+
|| (scheduler.pending_queue_drained === true
|
|
135
|
+
&& Number(scheduler.active_slot_count || 0) === 0
|
|
136
|
+
&& Number(scheduler.max_observed_active_slots || 0) >= Number(scheduler.target_active_slots || 0));
|
|
132
137
|
const blockers = [
|
|
133
138
|
...(lifecycle.ok ? [] : ['agent_lifecycle_not_all_closed']),
|
|
134
139
|
...(lifecycle.ok ? [] : lifecycle.open_sessions.map((id) => 'session_open:' + id)),
|
|
@@ -144,7 +149,7 @@ export async function writeAgentProofEvidence(root, input) {
|
|
|
144
149
|
...(scheduler && scheduler.pending_count > 0 && scheduler.active_slot_count === 0 ? ['scheduler_pending_queue_without_active_sessions'] : []),
|
|
145
150
|
...(scheduler && scheduler.pending_queue_drained !== true ? ['scheduler_pending_queue_not_drained'] : []),
|
|
146
151
|
...(scheduler && Number(scheduler.active_slot_count || 0) !== 0 ? ['scheduler_active_slots_not_zero_at_finalization'] : []),
|
|
147
|
-
...(
|
|
152
|
+
...(schedulerBackfillSatisfied ? [] : ['scheduler_backfill_count_below_expected']),
|
|
148
153
|
...(scheduler && Number(scheduler.total_work_items || 0) >= Number(scheduler.target_active_slots || 0) && Number(scheduler.max_observed_active_slots || 0) !== Number(scheduler.target_active_slots || 0) ? ['scheduler_max_observed_active_slots_mismatch'] : []),
|
|
149
154
|
...(taskGraph && !taskGraphMatchesCliOptions ? ['task_graph_cli_options_mismatch'] : []),
|
|
150
155
|
...(workQueue && taskGraph && !workQueueMatchesTaskGraph ? ['work_queue_task_graph_mismatch'] : []),
|
|
@@ -23,6 +23,10 @@ export async function runFakeAgent(agent, slice, opts = {}) {
|
|
|
23
23
|
unverified: ['fake backend does not prove real parallel execution'],
|
|
24
24
|
writes: [],
|
|
25
25
|
...(patchEnvelopes.length ? { patch_envelopes: patchEnvelopes } : {}),
|
|
26
|
+
...(isBugfixSlice(slice) && patchEnvelopes.length ? { regression_proof: fixtureRegressionProof(slice) } : {}),
|
|
27
|
+
...(isRepairSlice(slice) && patchEnvelopes.length ? { repair_hypothesis: fixtureRepairHypothesis(slice) } : {}),
|
|
28
|
+
...(slice?.work_item_kind ? { work_item_kind: String(slice.work_item_kind) } : {}),
|
|
29
|
+
...(slice?.tournament_group_id ? { tournament: fixtureTournament(slice) } : {}),
|
|
26
30
|
source_intelligence_refs: agent.source_intelligence_refs || null,
|
|
27
31
|
goal_mode_ref: agent.goal_mode_ref || null,
|
|
28
32
|
...(opts.emitFollowUpWorkItems ? { follow_up_work_items: [buildFixtureFollowUp(agent, slice)] } : {}),
|
|
@@ -94,10 +98,46 @@ export function buildFixturePatchEnvelopes(agent, slice, opts = {}) {
|
|
|
94
98
|
path: file,
|
|
95
99
|
content: `patched by ${String(agent.id)} for ${String(slice?.id || 'fixture')}\n`
|
|
96
100
|
}],
|
|
101
|
+
...(isBugfixSlice(slice) ? { regression_proof: fixtureRegressionProof(slice) } : {}),
|
|
102
|
+
...(isRepairSlice(slice) ? { repair_hypothesis: fixtureRepairHypothesis(slice) } : {}),
|
|
103
|
+
...(slice?.tournament_group_id ? { tournament: fixtureTournament(slice) } : {}),
|
|
97
104
|
rationale: 'Fixture patch envelope emitted by fake backend for a leased write task.',
|
|
98
105
|
verification_hint: { node_id: verificationNodeId, expected_status: 'applied_hashes_recorded' },
|
|
99
106
|
rollback_hint: { node_id: rollbackNodeId, strategy: 'restore content_before or delete newly created file' }
|
|
100
107
|
};
|
|
101
108
|
});
|
|
102
109
|
}
|
|
110
|
+
function isBugfixSlice(slice) {
|
|
111
|
+
const text = `${String(slice?.work_item_kind || '')} ${String(slice?.title || '')}`.toLowerCase();
|
|
112
|
+
return /\b(bugfix|fix|bug|regression|broken|failure|crash|error)\b|버그|회귀/.test(text);
|
|
113
|
+
}
|
|
114
|
+
function isRepairSlice(slice) {
|
|
115
|
+
const text = `${String(slice?.work_item_kind || '')} ${String(slice?.title || '')}`.toLowerCase();
|
|
116
|
+
return /\b(conflict_resolution|repair|conflict|rebase|rollback)\b|수리|충돌/.test(text);
|
|
117
|
+
}
|
|
118
|
+
function fixtureRegressionProof(slice) {
|
|
119
|
+
return {
|
|
120
|
+
test_file: String(slice?.target_paths?.[0] || slice?.write_paths?.[0] || 'fixture.test.js'),
|
|
121
|
+
failed_before: true,
|
|
122
|
+
passed_after: true,
|
|
123
|
+
output_digest: 'fixture-regression-proof'
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function fixtureRepairHypothesis(slice) {
|
|
127
|
+
return {
|
|
128
|
+
failure: 'fixture repair target',
|
|
129
|
+
hypotheses: [{ cause: 'fixture conflict', evidence_for: 'simulated failed worker', evidence_against: 'none' }],
|
|
130
|
+
chosen: 'fixture conflict',
|
|
131
|
+
minimal_probe: String(slice?.id || 'fixture')
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function fixtureTournament(slice) {
|
|
135
|
+
return {
|
|
136
|
+
schema: 'sks.solution-tournament-candidate.v1',
|
|
137
|
+
group_id: String(slice.tournament_group_id),
|
|
138
|
+
candidate_index: Number(slice.tournament_candidate_index || 1),
|
|
139
|
+
candidate_count: Number(slice.tournament_candidate_count || 1),
|
|
140
|
+
approach: String(slice.approach_directive || '')
|
|
141
|
+
};
|
|
142
|
+
}
|
|
103
143
|
//# sourceMappingURL=agent-runner-fake.js.map
|
|
@@ -27,6 +27,7 @@ export function validateAgentWorkerResult(result) {
|
|
|
27
27
|
session_id: String(result?.session_id || 'unknown'),
|
|
28
28
|
persona_id: String(result?.persona_id || result?.agent_id || 'unknown'),
|
|
29
29
|
task_slice_id: String(result?.task_slice_id || 'unknown'),
|
|
30
|
+
...(result?.work_item_kind === undefined ? {} : { work_item_kind: String(result.work_item_kind) }),
|
|
30
31
|
status: guard.ok ? (result?.status === undefined ? 'done' : String(result.status)) : 'blocked',
|
|
31
32
|
backend: result?.backend || 'fake',
|
|
32
33
|
summary: String(result?.summary || ''),
|
|
@@ -52,6 +53,10 @@ export function validateAgentWorkerResult(result) {
|
|
|
52
53
|
...(result?.model_authored_patch_envelopes === undefined ? {} : { model_authored_patch_envelopes: Boolean(result.model_authored_patch_envelopes) }),
|
|
53
54
|
...(result?.fixture_patch_envelopes === undefined ? {} : { fixture_patch_envelopes: Boolean(result.fixture_patch_envelopes) }),
|
|
54
55
|
...(result?.no_patch_reason === undefined ? {} : { no_patch_reason: result.no_patch_reason }),
|
|
56
|
+
...(result?.machine_feedback === undefined ? {} : { machine_feedback: result.machine_feedback }),
|
|
57
|
+
...(result?.regression_proof === undefined ? {} : { regression_proof: result.regression_proof }),
|
|
58
|
+
...(result?.repair_hypothesis === undefined ? {} : { repair_hypothesis: result.repair_hypothesis }),
|
|
59
|
+
...(result?.tournament === undefined ? {} : { tournament: result.tournament }),
|
|
55
60
|
...(result?.source_intelligence_refs === undefined ? {} : { source_intelligence_refs: result.source_intelligence_refs }),
|
|
56
61
|
...(result?.goal_mode_ref === undefined ? {} : { goal_mode_ref: result.goal_mode_ref }),
|
|
57
62
|
...(result?.follow_up_work_items === undefined ? {} : { follow_up_work_items: followUps.accepted }),
|
|
@@ -69,6 +74,12 @@ export function validateAgentWorkerResult(result) {
|
|
|
69
74
|
normalized.blockers.push(...patchEnvelopeValidation.blockers.map((issue) => 'patch_envelope_invalid:' + issue));
|
|
70
75
|
normalized.verification = { status: 'failed', checks: [...normalized.verification.checks, 'agent-patch-envelope-schema'] };
|
|
71
76
|
}
|
|
77
|
+
const protocolBlockers = qualityProtocolBlockers(normalized);
|
|
78
|
+
if (protocolBlockers.length) {
|
|
79
|
+
normalized.status = 'blocked';
|
|
80
|
+
normalized.blockers.push(...protocolBlockers);
|
|
81
|
+
normalized.verification = { status: 'failed', checks: [...normalized.verification.checks, 'agent-worker-quality-protocol'] };
|
|
82
|
+
}
|
|
72
83
|
const readOnlyOrNoopWithoutPatch = acceptsNoPatchReadOnlyOrNoop(result?.no_patch_reason);
|
|
73
84
|
if (patchEnvelopeValidation.envelopes.length === 0 && (normalized.writes.length > 0 || (!readOnlyOrNoopWithoutPatch && normalized.changed_files.length > 0))) {
|
|
74
85
|
normalized.status = 'blocked';
|
|
@@ -83,6 +94,24 @@ export function validateAgentWorkerResult(result) {
|
|
|
83
94
|
}
|
|
84
95
|
return normalized;
|
|
85
96
|
}
|
|
97
|
+
function qualityProtocolBlockers(result) {
|
|
98
|
+
const writesPatch = result.writes.length > 0 || result.changed_files.length > 0 || Boolean(result.patch_envelopes?.length);
|
|
99
|
+
if (!writesPatch)
|
|
100
|
+
return [];
|
|
101
|
+
const kind = String(result.work_item_kind || result.naruto_runtime?.work_item_kind || '').toLowerCase();
|
|
102
|
+
const text = [kind, result.task_slice_id].join(' ').toLowerCase();
|
|
103
|
+
const proof = result.regression_proof || result.patch_envelopes?.find((envelope) => envelope.regression_proof)?.regression_proof || null;
|
|
104
|
+
const repair = result.repair_hypothesis || result.patch_envelopes?.find((envelope) => envelope.repair_hypothesis)?.repair_hypothesis || null;
|
|
105
|
+
const blockers = [];
|
|
106
|
+
if ((kind === 'bugfix' || /\b(fix|bug|regression|broken|failure|crash|error)\b|버그|회귀/.test(text)) && !validRegressionProof(proof))
|
|
107
|
+
blockers.push('tdd_evidence_missing');
|
|
108
|
+
if ((kind === 'conflict_resolution' || /\b(repair|conflict|rebase|rollback)\b|수리|충돌/.test(text)) && !repair)
|
|
109
|
+
blockers.push('repair_without_hypothesis');
|
|
110
|
+
return blockers;
|
|
111
|
+
}
|
|
112
|
+
function validRegressionProof(proof) {
|
|
113
|
+
return Boolean(proof && proof.failed_before === true && proof.passed_after === true && String(proof.test_file || '').trim());
|
|
114
|
+
}
|
|
86
115
|
export function agentWorkerPipelineContract() {
|
|
87
116
|
return {
|
|
88
117
|
schema: 'sks.agent-worker-pipeline.v1',
|
|
@@ -97,7 +126,7 @@ export function agentWorkerPipelineContract() {
|
|
|
97
126
|
required_for_write_tasks: true,
|
|
98
127
|
envelope_schema: 'sks.agent-patch-envelope.v1',
|
|
99
128
|
metadata: ['agent_id', 'session_id', 'slot_id', 'generation_index', 'lease_id_or_lease_proof'],
|
|
100
|
-
optional_hints: ['rationale', 'verification_hint', 'rollback_hint']
|
|
129
|
+
optional_hints: ['rationale', 'verification_hint', 'rollback_hint', 'cochange_acknowledged_reason', 'regression_proof', 'repair_hypothesis']
|
|
101
130
|
}
|
|
102
131
|
};
|
|
103
132
|
}
|
|
@@ -111,7 +140,12 @@ function normalizePatchEnvelopes(value) {
|
|
|
111
140
|
...(raw?.generation_index === undefined ? {} : { generation_index: Number(raw.generation_index) }),
|
|
112
141
|
...(raw?.task_slice_id === undefined ? {} : { task_slice_id: String(raw.task_slice_id) }),
|
|
113
142
|
...(raw?.verification_hint === undefined ? {} : { verification_hint: raw.verification_hint }),
|
|
114
|
-
...(raw?.rollback_hint === undefined ? {} : { rollback_hint: raw.rollback_hint })
|
|
143
|
+
...(raw?.rollback_hint === undefined ? {} : { rollback_hint: raw.rollback_hint }),
|
|
144
|
+
...(raw?.cochange_acknowledged === undefined ? {} : { cochange_acknowledged: Boolean(raw.cochange_acknowledged) }),
|
|
145
|
+
...(raw?.cochange_acknowledged_reason === undefined ? {} : { cochange_acknowledged_reason: String(raw.cochange_acknowledged_reason) }),
|
|
146
|
+
...(raw?.regression_proof === undefined ? {} : { regression_proof: raw.regression_proof }),
|
|
147
|
+
...(raw?.repair_hypothesis === undefined ? {} : { repair_hypothesis: raw.repair_hypothesis }),
|
|
148
|
+
...(raw?.tournament === undefined ? {} : { tournament: raw.tournament })
|
|
115
149
|
})) : [];
|
|
116
150
|
const blockers = envelopes.flatMap((envelope, index) => {
|
|
117
151
|
const validation = validateAgentPatchEnvelope(envelope);
|
|
@@ -112,6 +112,8 @@ function buildWorkerPrompt(slice) {
|
|
|
112
112
|
`Write-capable slice. write_paths=${JSON.stringify(writePaths)}.`,
|
|
113
113
|
'Return at least one patch_envelopes item with source "model_authored".',
|
|
114
114
|
`Use a write operation for ${JSON.stringify(writePaths[0])}, allowed_paths equal to write_paths, lease_proof.protected_path_check "passed", and non-empty verification_hint and rollback_hint.`,
|
|
115
|
+
'Impact-scan, machine-feedback, diff-quality, and compiled mistake rules run before queue acceptance; exported signature changes must include cochanged callers or a concrete cochange_acknowledged_reason.',
|
|
116
|
+
'For bugfix work, add a regression test first and include regression_proof with failed_before true and passed_after true. For repair work, include repair_hypothesis before patching.',
|
|
115
117
|
'For patch envelope runtime ids you cannot know yet, use numeric 0 or empty strings; SKS will bind actual worker and Codex child process ids from the process report.',
|
|
116
118
|
'Set changed_files and writes consistently with the patch envelope operation.'
|
|
117
119
|
].join('\n')
|
|
@@ -10,6 +10,8 @@ import { normalizeAgentPatchEnvelope } from './agent-patch-schema.js';
|
|
|
10
10
|
import { runCodexTask } from '../codex-control/codex-control-plane.js';
|
|
11
11
|
import { CODEX_AGENT_WORKER_RESULT_SCHEMA_ID, codexAgentWorkerResultSchema } from '../codex-control/schemas/agent-worker-result.schema.js';
|
|
12
12
|
import { leanEngineeringCompactText, leanPolicyReference } from '../lean-engineering-policy.js';
|
|
13
|
+
import { readLbHealth } from '../codex-lb/codex-lb-env.js';
|
|
14
|
+
import { categoryForWorkerRole, modelRouteReason, routeModel } from '../provider/model-router.js';
|
|
13
15
|
export const NATIVE_WORKER_BACKEND_ROUTER_SCHEMA = 'sks.native-worker-backend-router.v1';
|
|
14
16
|
export async function runNativeWorkerBackendRouter(input) {
|
|
15
17
|
const root = path.resolve(input.agentRoot);
|
|
@@ -23,6 +25,7 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
23
25
|
let patchEnvelopes = [];
|
|
24
26
|
let proofLevel = 'blocked';
|
|
25
27
|
let outputLastMessagePath = null;
|
|
28
|
+
let modelRouting = null;
|
|
26
29
|
if (!input.guard?.ok) {
|
|
27
30
|
result = validateAgentWorkerResult(blockedResult(input, ['native_cli_worker_recursion_guard_missing']));
|
|
28
31
|
}
|
|
@@ -91,6 +94,7 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
91
94
|
}
|
|
92
95
|
else if (backend === 'codex-sdk' || backend === 'zellij' || backend === 'local-llm') {
|
|
93
96
|
const localPreferred = backend === 'local-llm';
|
|
97
|
+
modelRouting = await resolveWorkerModelRouting(input);
|
|
94
98
|
const sdkTask = await runCodexTask({
|
|
95
99
|
route: String(input.intake.route || '$Agent'),
|
|
96
100
|
tier: 'worker',
|
|
@@ -101,6 +105,10 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
101
105
|
sessionId: String(input.agent.session_id || ''),
|
|
102
106
|
cwd: String(input.intake.cwd || root),
|
|
103
107
|
prompt: buildWorkerPrompt(input.slice),
|
|
108
|
+
model: modelRouting.choice.model,
|
|
109
|
+
reasoningEffort: modelRouting.choice.reasoning,
|
|
110
|
+
modelReasoningEffort: modelRouting.choice.reasoning,
|
|
111
|
+
serviceTier: modelRouting.choice.serviceTier,
|
|
104
112
|
inputFiles: input.intake.input_files || [],
|
|
105
113
|
inputImages: input.intake.input_images || [],
|
|
106
114
|
outputSchemaId: CODEX_AGENT_WORKER_RESULT_SCHEMA_ID,
|
|
@@ -112,6 +120,8 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
112
120
|
read_only: !hasWriteLease(input.slice, input.intake),
|
|
113
121
|
allowed_paths: writePaths(input.slice, input.intake),
|
|
114
122
|
write_paths: writePaths(input.slice, input.intake),
|
|
123
|
+
model_route_reason: modelRouting.reason,
|
|
124
|
+
service_tier: modelRouting.choice.serviceTier,
|
|
115
125
|
user_confirmed_full_access: false,
|
|
116
126
|
mad_sks_authorized: input.intake.mad_sks_authorized === true || process.env.SKS_MAD_SKS_ACTIVE === '1'
|
|
117
127
|
},
|
|
@@ -143,6 +153,10 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
143
153
|
structured_output_valid: sdkTask.structuredOutputValid,
|
|
144
154
|
worker_result_path: sdkTask.workerResultPath,
|
|
145
155
|
patch_envelope_path: sdkTask.patchEnvelopePath || null,
|
|
156
|
+
model: modelRouting.choice.model,
|
|
157
|
+
model_reasoning_effort: modelRouting.choice.reasoning,
|
|
158
|
+
service_tier: modelRouting.choice.serviceTier,
|
|
159
|
+
model_route_reason: modelRouting.reason,
|
|
146
160
|
blockers: sdkTask.blockers
|
|
147
161
|
};
|
|
148
162
|
childReports = [sdkReport];
|
|
@@ -219,7 +233,11 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
219
233
|
proof_level: proofLevel,
|
|
220
234
|
lean_engineering_policy: leanPolicyReference(),
|
|
221
235
|
fast_mode: input.fastModePolicy.fast_mode,
|
|
222
|
-
service_tier: input.fastModePolicy.service_tier,
|
|
236
|
+
service_tier: modelRouting?.choice.serviceTier || input.fastModePolicy.service_tier,
|
|
237
|
+
model: modelRouting?.choice.model || input.agent.model || null,
|
|
238
|
+
model_reasoning_effort: modelRouting?.choice.reasoning || input.agent.model_reasoning_effort || null,
|
|
239
|
+
model_route_reason: modelRouting?.reason || null,
|
|
240
|
+
model_route_category: modelRouting?.category || null,
|
|
223
241
|
sdk_thread_id: childReports.find((report) => report?.sdk_thread_id)?.sdk_thread_id || null,
|
|
224
242
|
sdk_run_id: childReports.find((report) => report?.sdk_run_id)?.sdk_run_id || null,
|
|
225
243
|
stream_event_count: Number(childReports.find((report) => report?.stream_event_count)?.stream_event_count || 0),
|
|
@@ -239,6 +257,39 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
239
257
|
patchEnvelopes
|
|
240
258
|
};
|
|
241
259
|
}
|
|
260
|
+
async function resolveWorkerModelRouting(input) {
|
|
261
|
+
const category = categoryForWorkerRole(String(input.agent?.role || input.slice?.role || input.slice?.type || input.agent?.persona_id || 'executor'));
|
|
262
|
+
const lbHealth = await readLbHealth().catch(() => null);
|
|
263
|
+
const explicitModel = String(process.env.SKS_WORKER_MODEL || process.env.SKS_AGENT_MODEL || '').trim();
|
|
264
|
+
const explicitReasoning = normalizeModelReasoning(process.env.SKS_WORKER_REASONING || process.env.SKS_WORKER_MODEL_REASONING || '');
|
|
265
|
+
const explicitTier = normalizeServiceTier(process.env.SKS_WORKER_SERVICE_TIER || process.env.SKS_SERVICE_TIER || '');
|
|
266
|
+
const routed = explicitModel
|
|
267
|
+
? {
|
|
268
|
+
model: explicitModel,
|
|
269
|
+
reasoning: explicitReasoning || normalizeModelReasoning(input.agent?.model_reasoning_effort) || 'medium',
|
|
270
|
+
serviceTier: explicitTier || input.fastModePolicy.service_tier || 'fast'
|
|
271
|
+
}
|
|
272
|
+
: await routeModel(category, { lbHealth });
|
|
273
|
+
return {
|
|
274
|
+
category,
|
|
275
|
+
choice: routed,
|
|
276
|
+
explicit: Boolean(explicitModel),
|
|
277
|
+
lb_health: lbHealth,
|
|
278
|
+
reason: modelRouteReason(category, routed, {
|
|
279
|
+
explicit: Boolean(explicitModel),
|
|
280
|
+
quotaLow: lbHealth?.quota_low === true,
|
|
281
|
+
degraded: lbHealth?.degraded_models || []
|
|
282
|
+
})
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function normalizeModelReasoning(value) {
|
|
286
|
+
const text = String(value || '').toLowerCase();
|
|
287
|
+
return text === 'low' || text === 'medium' || text === 'high' || text === 'xhigh' ? text : null;
|
|
288
|
+
}
|
|
289
|
+
function normalizeServiceTier(value) {
|
|
290
|
+
const text = String(value || '').toLowerCase();
|
|
291
|
+
return text === 'standard' ? 'standard' : text === 'fast' || text === 'priority' ? 'fast' : null;
|
|
292
|
+
}
|
|
242
293
|
async function maybeAutoSelectOllamaBackend(backend, input) {
|
|
243
294
|
if (backend !== 'codex-sdk')
|
|
244
295
|
return backend;
|
|
@@ -286,6 +337,12 @@ function buildWorkerPrompt(slice) {
|
|
|
286
337
|
write.length
|
|
287
338
|
? `Write-capable slice. Return JSON matching ${CODEX_AGENT_WORKER_RESULT_SCHEMA_ID}; include patch_envelopes for write_paths=${JSON.stringify(write)}.`
|
|
288
339
|
: `Read-only slice. Return JSON matching ${CODEX_AGENT_WORKER_RESULT_SCHEMA_ID}; do not report pre-existing repository dirtiness as changed_files.`,
|
|
340
|
+
write.length
|
|
341
|
+
? 'Quality gates run before queue acceptance: impact-scan requires cochanged callers for exported signature changes, machine-feedback runs type/lint/related tests, diff-quality blocks dead exports, and compiled mistake rules block repeated mistakes.'
|
|
342
|
+
: '',
|
|
343
|
+
write.length
|
|
344
|
+
? 'If this is a bugfix, create a regression test first and include regression_proof with failed_before true and passed_after true. For repair work, include repair_hypothesis before patching.'
|
|
345
|
+
: '',
|
|
289
346
|
leanEngineeringCompactText(),
|
|
290
347
|
'Required JSON fields: status, summary, findings, changed_files, patch_envelopes, verification, rollback_notes, blockers.'
|
|
291
348
|
].join('\n');
|
|
@@ -3,6 +3,7 @@ import os from 'node:os';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { ensureDir, exists, PACKAGE_VERSION, readJson, readText, runProcess, sha256, which, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
|
|
6
|
+
import { withHeartbeat } from '../../cli/cli-theme.js';
|
|
6
7
|
export const SKS_MENUBAR_LABEL = 'com.sneakoscope.sks-menubar';
|
|
7
8
|
const LABEL = SKS_MENUBAR_LABEL;
|
|
8
9
|
const CONTROL_CENTER_DOMAIN = 'com.apple.controlcenter';
|
|
@@ -16,6 +17,7 @@ const MENU_ITEMS = [
|
|
|
16
17
|
'Fast Check',
|
|
17
18
|
'SKS Version Check',
|
|
18
19
|
'Update SKS Now',
|
|
20
|
+
'Open Dashboard',
|
|
19
21
|
'Open Codex Settings',
|
|
20
22
|
'Restart Codex',
|
|
21
23
|
'Quit SKS Menu'
|
|
@@ -208,7 +210,8 @@ export async function installSksMenuBar(opts = {}) {
|
|
|
208
210
|
codesign,
|
|
209
211
|
swiftSource,
|
|
210
212
|
infoPlist,
|
|
211
|
-
actions
|
|
213
|
+
actions,
|
|
214
|
+
quiet: opts.quiet === true
|
|
212
215
|
});
|
|
213
216
|
}
|
|
214
217
|
catch (err) {
|
|
@@ -245,7 +248,7 @@ export async function installSksMenuBar(opts = {}) {
|
|
|
245
248
|
warnings.push(preferredPosition.warning);
|
|
246
249
|
}
|
|
247
250
|
const launch = launchRequested && launchctl && !(stampMatches && runningBeforeLaunch)
|
|
248
|
-
? await launchWithLaunchctl({ launchctl, open, paths, skipIfRunning: stampMatches })
|
|
251
|
+
? await launchWithLaunchctl({ launchctl, open, paths, skipIfRunning: stampMatches, quiet: opts.quiet === true })
|
|
249
252
|
: {
|
|
250
253
|
requested: launchRequested && !(stampMatches && runningBeforeLaunch),
|
|
251
254
|
method: 'skipped',
|
|
@@ -724,6 +727,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
|
|
724
727
|
add(menu, "SKS Version Check", #selector(sksVersionCheck))
|
|
725
728
|
add(menu, "Update SKS Now", #selector(updateSksNow))
|
|
726
729
|
menu.addItem(NSMenuItem.separator())
|
|
730
|
+
add(menu, "Open Dashboard", #selector(openDashboard))
|
|
727
731
|
add(menu, "Open Codex Settings", #selector(openCodexSettings))
|
|
728
732
|
add(menu, "Restart Codex", #selector(restartCodex))
|
|
729
733
|
menu.addItem(NSMenuItem.separator())
|
|
@@ -844,6 +848,12 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
|
|
844
848
|
runSksInTerminal(["update"], tail: "echo; echo 'SKS update finished.'")
|
|
845
849
|
}
|
|
846
850
|
|
|
851
|
+
@objc func openDashboard() {
|
|
852
|
+
let command = "\\(shellQuote(actionScript)) ui; echo; echo 'SKS dashboard requested.'"
|
|
853
|
+
runInTerminal(command)
|
|
854
|
+
runProcess("/usr/bin/open", ["http://127.0.0.1:4477"])
|
|
855
|
+
}
|
|
856
|
+
|
|
847
857
|
@objc func openCodexSettings() {
|
|
848
858
|
runProcess("/usr/bin/open", ["codex://settings"])
|
|
849
859
|
}
|
|
@@ -916,10 +926,11 @@ async function buildMenuBarAppAtomically(input) {
|
|
|
916
926
|
input.actions.push(`wrote ${input.paths.source_path}`);
|
|
917
927
|
await writeTextAtomic(path.join(input.paths.staging_app_path, 'Contents', 'Info.plist'), input.infoPlist);
|
|
918
928
|
const stagingExecutable = path.join(input.paths.staging_app_path, 'Contents', 'MacOS', 'SKSMenuBar');
|
|
919
|
-
const
|
|
929
|
+
const compileWork = runProcess(input.swiftc, ['-framework', 'Cocoa', input.paths.source_path, '-o', stagingExecutable], {
|
|
920
930
|
timeoutMs: 60_000,
|
|
921
931
|
maxOutputBytes: 64 * 1024
|
|
922
932
|
}).catch((err) => ({ code: 1, stdout: '', stderr: err?.message || String(err) }));
|
|
933
|
+
const compile = input.quiet === true ? await compileWork : await withHeartbeat('swiftc SKS menu bar', compileWork, { warnAfterMs: 30_000 });
|
|
923
934
|
if (compile.code !== 0) {
|
|
924
935
|
throw new MenuBarBuildError('swift_compile_failed', String(compile.stderr || compile.stdout || '').trim());
|
|
925
936
|
}
|
|
@@ -956,7 +967,8 @@ async function launchWithLaunchctl(input) {
|
|
|
956
967
|
stdoutFile: path.join(input.paths.install_dir, 'launchctl.out.log'),
|
|
957
968
|
stderrFile: path.join(input.paths.install_dir, 'launchctl.err.log')
|
|
958
969
|
};
|
|
959
|
-
const
|
|
970
|
+
const alreadyWork = waitForLaunchctlRunning(input.launchctl, service);
|
|
971
|
+
const already = input.quiet === true ? await alreadyWork : await withHeartbeat('launchctl SKS menu bar wait', alreadyWork, { warnAfterMs: 10_000 });
|
|
960
972
|
if (input.skipIfRunning && already.running) {
|
|
961
973
|
return { requested: true, method: 'launchctl', ok: true, print_code: already.code, error: null };
|
|
962
974
|
}
|
|
@@ -975,7 +987,8 @@ async function launchWithLaunchctl(input) {
|
|
|
975
987
|
...stdio
|
|
976
988
|
}).catch((err) => ({ code: 1, stdout: '', stderr: err?.message || String(err) }));
|
|
977
989
|
if (kickstart.code !== 0) {
|
|
978
|
-
const
|
|
990
|
+
const printedWork = waitForLaunchctlRunning(input.launchctl, service);
|
|
991
|
+
const printed = input.quiet === true ? await printedWork : await withHeartbeat('launchctl SKS menu bar wait', printedWork, { warnAfterMs: 10_000 });
|
|
979
992
|
if (printed.running) {
|
|
980
993
|
return {
|
|
981
994
|
requested: true,
|
package/dist/core/codex-app.js
CHANGED
|
@@ -582,6 +582,7 @@ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, re
|
|
|
582
582
|
}
|
|
583
583
|
else if (appInstalled || codex?.bin) {
|
|
584
584
|
lines.push('Codex image_generation was not visible from `codex features list`. Required imagegen/gpt-image-2 evidence must stay blocked or unverified until $imagegen is available in Codex App.');
|
|
585
|
+
lines.push('Run: sks doctor --fix to attempt Codex CLI/App image_generation repair, then rerun the blocked visual route.');
|
|
585
586
|
}
|
|
586
587
|
if (computerUseReady && !computerUseMcpListed) {
|
|
587
588
|
lines.push('Computer Use plugin files are installed, but this check cannot prove the current thread exposes the live Computer Use tools. Start a new Codex App thread and invoke @Computer or @AppName only for native Mac/non-web target apps or screens; web/browser/webapp verification must use the Chrome Extension gate.');
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export function buildCodexSdkConfig(input) {
|
|
2
2
|
const model = String(input.model || process.env.SKS_CODEX_MODEL || process.env.CODEX_MODEL || 'gpt-5.5');
|
|
3
|
+
const serviceTier = String(input.serviceTier || process.env.SKS_SERVICE_TIER || 'fast');
|
|
3
4
|
const config = {
|
|
4
5
|
model,
|
|
5
|
-
service_tier: 'fast',
|
|
6
|
+
service_tier: serviceTier === 'standard' ? 'standard' : 'fast',
|
|
6
7
|
model_reasoning_effort: String(input.modelReasoningEffort || input.reasoningEffort || process.env.SKS_CODEX_REASONING || process.env.CODEX_MODEL_REASONING_EFFORT || 'medium'),
|
|
7
8
|
mcp_servers: {},
|
|
8
9
|
sks: {
|
|
@@ -30,7 +30,7 @@ export function buildCodexSdkEnv(input) {
|
|
|
30
30
|
env.SKS_AGENT_SESSION_ID = input.sessionId;
|
|
31
31
|
if (input.generationIndex !== undefined)
|
|
32
32
|
env.SKS_AGENT_GENERATION_INDEX = String(input.generationIndex);
|
|
33
|
-
env.SKS_SERVICE_TIER = 'fast';
|
|
33
|
+
env.SKS_SERVICE_TIER = String(input.serviceTier || 'fast');
|
|
34
34
|
const isolatedRoot = path.resolve(input.mutationLedgerRoot, 'codex-sdk-home');
|
|
35
35
|
env.HOME = path.join(isolatedRoot, 'home');
|
|
36
36
|
env.CODEX_HOME = path.join(isolatedRoot, 'codex');
|
|
@@ -3,7 +3,7 @@ const patchOperationSchema = {
|
|
|
3
3
|
type: 'object',
|
|
4
4
|
required: ['op', 'path', 'search', 'replace', 'content', 'diff'],
|
|
5
5
|
properties: {
|
|
6
|
-
op: { type: 'string', enum: ['replace', 'write', 'unified_diff'] },
|
|
6
|
+
op: { type: 'string', enum: ['replace', 'write', 'unified_diff', 'git_apply_patch'] },
|
|
7
7
|
path: { type: 'string' },
|
|
8
8
|
search: { type: 'string' },
|
|
9
9
|
replace: { type: 'string' },
|
|
@@ -38,7 +38,12 @@ const patchEnvelopeSchema = {
|
|
|
38
38
|
lease_id: { type: 'string' },
|
|
39
39
|
allowed_paths: { type: 'array', items: { type: 'string' } },
|
|
40
40
|
operations: { type: 'array', items: patchOperationSchema },
|
|
41
|
-
rationale: { type: 'string' }
|
|
41
|
+
rationale: { type: 'string' },
|
|
42
|
+
cochange_acknowledged: { type: 'boolean' },
|
|
43
|
+
cochange_acknowledged_reason: { type: 'string' },
|
|
44
|
+
regression_proof: { type: 'object', additionalProperties: true },
|
|
45
|
+
repair_hypothesis: { type: 'object', additionalProperties: true },
|
|
46
|
+
tournament: { type: 'object', additionalProperties: true }
|
|
42
47
|
},
|
|
43
48
|
additionalProperties: false
|
|
44
49
|
};
|
|
@@ -70,7 +75,11 @@ export const codexAgentWorkerResultSchema = {
|
|
|
70
75
|
additionalProperties: false
|
|
71
76
|
},
|
|
72
77
|
rollback_notes: { type: 'array', items: { type: 'string' } },
|
|
73
|
-
blockers: { type: 'array', items: { type: 'string' } }
|
|
78
|
+
blockers: { type: 'array', items: { type: 'string' } },
|
|
79
|
+
work_item_kind: { type: 'string' },
|
|
80
|
+
regression_proof: { type: 'object', additionalProperties: true },
|
|
81
|
+
repair_hypothesis: { type: 'object', additionalProperties: true },
|
|
82
|
+
tournament: { type: 'object', additionalProperties: true }
|
|
74
83
|
},
|
|
75
84
|
additionalProperties: false
|
|
76
85
|
};
|