sneakoscope 4.8.7 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -726
- package/config/bench-baseline.json +7 -0
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/bin/install.js +35 -0
- package/dist/bin/sks.js +1 -1
- package/dist/cli/cli-theme.js +51 -0
- package/dist/cli/command-registry.js +15 -4
- package/dist/cli/help-fast.js +18 -8
- package/dist/cli/insane-search-command.js +36 -8
- package/dist/cli/install-helpers.js +32 -0
- package/dist/commands/codex-lb.js +2 -0
- package/dist/commands/doctor.js +94 -9
- package/dist/commands/proof.js +6 -3
- package/dist/config/skills-manifest.json +82 -54
- package/dist/core/agents/agent-conflict-graph.js +5 -0
- package/dist/core/agents/agent-lease.js +5 -0
- package/dist/core/agents/agent-ledger-schemas.js +1 -0
- package/dist/core/agents/agent-lifecycle.js +5 -3
- package/dist/core/agents/agent-orchestrator.js +268 -62
- package/dist/core/agents/agent-output-validator.js +14 -3
- package/dist/core/agents/agent-patch-queue-store.js +95 -2
- package/dist/core/agents/agent-patch-queue.js +6 -3
- package/dist/core/agents/agent-patch-schema.js +13 -0
- package/dist/core/agents/agent-proof-evidence.js +6 -1
- package/dist/core/agents/agent-runner-fake.js +40 -0
- package/dist/core/agents/agent-worker-pipeline.js +36 -2
- package/dist/core/agents/codex-exec-worker-adapter.js +2 -0
- package/dist/core/agents/native-cli-worker.js +0 -1
- package/dist/core/agents/native-worker-backend-router.js +58 -1
- package/dist/core/codex-app/sks-menubar.js +477 -132
- package/dist/core/codex-app.js +1 -0
- package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
- package/dist/core/codex-control/codex-sdk-env-policy.js +1 -1
- package/dist/core/codex-control/schemas/agent-worker-result.schema.js +12 -3
- package/dist/core/codex-hooks/codex-hook-managed-install.js +5 -0
- package/dist/core/codex-hooks/codex-hook-state-writer.js +70 -11
- package/dist/core/codex-hooks/codex-hook-trust-doctor.js +2 -2
- package/dist/core/codex-lb/codex-lb-env.js +20 -1
- package/dist/core/commands/basic-cli.js +18 -1
- package/dist/core/commands/check-command.js +37 -5
- package/dist/core/commands/computer-use-command.js +62 -7
- package/dist/core/commands/db-command.js +31 -5
- package/dist/core/commands/fast-mode-command.js +3 -0
- package/dist/core/commands/gate-result-contract.js +43 -0
- package/dist/core/commands/gates-command.js +6 -1
- package/dist/core/commands/gc-command.js +29 -2
- package/dist/core/commands/goal-command.js +9 -2
- package/dist/core/commands/gx-command.js +79 -7
- package/dist/core/commands/image-ux-review-command.js +188 -13
- package/dist/core/commands/mad-db-command.js +85 -176
- package/dist/core/commands/mad-sks-command.js +230 -29
- package/dist/core/commands/menubar-command.js +24 -2
- package/dist/core/commands/naruto-command.js +64 -10
- package/dist/core/commands/plan-command.js +76 -0
- package/dist/core/commands/ppt-command.js +159 -24
- package/dist/core/commands/qa-loop-command.js +6 -2
- package/dist/core/commands/release-command.js +55 -2
- package/dist/core/commands/research-command.js +1 -1
- package/dist/core/commands/review-command.js +217 -0
- package/dist/core/commands/route-success-helpers.js +59 -0
- package/dist/core/commands/run-command.js +19 -7
- package/dist/core/commands/seo-command.js +49 -1
- package/dist/core/commands/ui-command.js +161 -0
- package/dist/core/commands/uninstall-command.js +15 -1
- package/dist/core/db-safety.js +2 -2
- package/dist/core/doctor/doctor-dirty-planner.js +51 -7
- package/dist/core/doctor/doctor-transaction.js +8 -0
- package/dist/core/doctor/doctor-zellij-repair.js +1 -0
- package/dist/core/doctor/imagegen-repair.js +161 -0
- package/dist/core/feature-fixture-runner.js +2 -2
- package/dist/core/feature-fixtures.js +58 -37
- package/dist/core/feature-registry.js +102 -2
- package/dist/core/fsx.js +39 -6
- package/dist/core/image-ux-review/imagegen-adapter.js +48 -11
- package/dist/core/image-ux-review.js +16 -0
- package/dist/core/imagegen/imagegen-capability.js +11 -5
- package/dist/core/imagegen/require-imagegen.js +57 -0
- package/dist/core/init/skills.js +10 -5
- package/dist/core/mad-db/mad-db-coordinator.js +94 -18
- package/dist/core/mad-db/mad-db-policy.js +12 -10
- package/dist/core/mad-sks/executors/executor-base.js +8 -2
- package/dist/core/mad-sks/executors/index.js +4 -0
- package/dist/core/mad-sks/executors/sql-plane-executor.js +194 -0
- package/dist/core/naruto/naruto-active-pool.js +15 -4
- package/dist/core/naruto/naruto-real-worker-child.js +11 -1
- package/dist/core/naruto/naruto-role-policy.js +3 -0
- package/dist/core/naruto/naruto-task-hints.js +10 -0
- package/dist/core/naruto/naruto-work-graph.js +8 -2
- package/dist/core/naruto/naruto-work-item.js +6 -0
- package/dist/core/naruto/solution-tournament.js +101 -0
- package/dist/core/permission-gates.js +30 -0
- package/dist/core/pipeline-internals/runtime-core.js +11 -3
- package/dist/core/pipeline-internals/runtime-gates.js +27 -0
- package/dist/core/ppt-review/index.js +6 -1
- package/dist/core/ppt-review/slide-imagegen-review.js +75 -10
- package/dist/core/ppt.js +70 -2
- package/dist/core/proof/auto-finalize.js +70 -11
- package/dist/core/proof/proof-schema.js +2 -0
- package/dist/core/proof/route-adapter.js +5 -1
- package/dist/core/proof/route-finalizer.js +8 -5
- package/dist/core/proof/selftest-proof-fixtures.js +18 -5
- package/dist/core/proof/validation.js +2 -0
- package/dist/core/provider/model-router.js +53 -0
- package/dist/core/release/release-gate-node.js +3 -0
- package/dist/core/release/release-gate-resource-governor.js +1 -0
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes.js +65 -18
- package/dist/core/safety/mutation-guard.js +5 -1
- package/dist/core/stop-gate/gate-evaluator.js +102 -0
- package/dist/core/stop-gate/stop-gate-check.js +16 -1
- package/dist/core/stop-gate/stop-gate-writer.js +4 -0
- package/dist/core/triwiki/agents-md-projector.js +184 -0
- package/dist/core/triwiki-wrongness/wrongness-schema.js +3 -1
- package/dist/core/trust-kernel/trust-kernel-schema.js +1 -0
- package/dist/core/trust-kernel/trust-report.js +1 -1
- package/dist/core/trust-kernel/trust-status.js +2 -0
- package/dist/core/ui/dashboard-html.js +111 -0
- package/dist/core/update/update-migration-state.js +386 -15
- package/dist/core/update-check.js +178 -81
- package/dist/core/verification/diff-quality.js +100 -0
- package/dist/core/verification/impact-scan.js +164 -0
- package/dist/core/verification/machine-feedback.js +146 -0
- package/dist/core/verification/mistake-rule-compiler.js +195 -0
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-self-heal.js +9 -6
- package/dist/core/zellij/zellij-slot-telemetry.js +1 -1
- package/dist/scripts/check-feature-quality.js +2 -2
- package/dist/scripts/cli-output-consistency-check.js +57 -0
- package/dist/scripts/coding-bench-check.js +136 -0
- package/dist/scripts/doctor-imagegen-repair-check.js +62 -0
- package/dist/scripts/ensure-bin-executable.js +11 -3
- package/dist/scripts/harness-benchmark-check.js +104 -0
- package/dist/scripts/legacy-update-e2e-check.js +228 -0
- package/dist/scripts/mad-db-command-check.js +11 -8
- package/dist/scripts/mad-db-route-identity-check.js +8 -6
- package/dist/scripts/mad-db-safety-conflict-matrix-check.js +31 -8
- package/dist/scripts/mad-db-skill-policy-snapshot-check.js +4 -5
- package/dist/scripts/naruto-real-active-pool-runtime-check.js +26 -1
- package/dist/scripts/ppt-real-imagegen-wiring-check.js +5 -1
- package/dist/scripts/proof-root-cause-policy-check.js +2 -0
- package/dist/scripts/release-dag-full-coverage-check.js +13 -4
- package/dist/scripts/release-gate-dag-runner.js +14 -0
- package/dist/scripts/release-gate-existence-audit.js +2 -1
- package/dist/scripts/release-gate-planner.js +2 -1
- package/dist/scripts/release-gate-script-parity-check.js +45 -17
- package/dist/scripts/release-metadata-1-19-check.js +2 -1
- package/dist/scripts/seo-geo-feature-fixture-quality-check.js +1 -1
- package/dist/scripts/sks-1-11-gate-lib.js +8 -6
- package/dist/scripts/sks-menubar-install-check.js +57 -20
- package/dist/scripts/ux-review-real-loop-fixture-check.js +9 -4
- package/dist/scripts/ux-review-run-wires-imagegen-check.js +4 -0
- package/dist/scripts/zellij-slot-telemetry-runtime-check.js +1 -0
- package/docs/assets/sneakoscope-architecture-pipeline.jpg +0 -0
- package/docs/demo.tape +28 -0
- package/package.json +31 -24
- package/schemas/codex/completion-proof.schema.json +3 -2
- package/schemas/release/release-gate-node.schema.json +2 -1
- package/dist/scripts/agent-backfill-route-blackbox.js +0 -5
- package/dist/scripts/agent-dynamic-pool-route-blackbox.js +0 -5
- package/dist/scripts/agent-parallel-write-blackbox.js +0 -56
- package/dist/scripts/agent-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/agent-route-blackbox-lib.js +0 -132
- package/dist/scripts/blackbox-command-import-smoke.js +0 -143
- package/dist/scripts/blackbox-global-shim.js +0 -77
- package/dist/scripts/blackbox-matrix.js +0 -70
- package/dist/scripts/blackbox-npx-one-shot.js +0 -69
- package/dist/scripts/blackbox-pack-install.js +0 -174
- package/dist/scripts/brand-neutrality-zero-leakage-blackbox.js +0 -4
- package/dist/scripts/build-once-runner-blackbox.js +0 -34
- package/dist/scripts/codex-0140-integration-blackbox.js +0 -13
- package/dist/scripts/codex-agent-type-blackbox.js +0 -4
- package/dist/scripts/codex-app-harness-blackbox.js +0 -4
- package/dist/scripts/codex-app-skill-agent-blackbox.js +0 -4
- package/dist/scripts/codex-hook-approval-blackbox.js +0 -4
- package/dist/scripts/codex-init-deep-directory-local-blackbox.js +0 -4
- package/dist/scripts/codex-native-feature-broker-blackbox.js +0 -4
- package/dist/scripts/codex-native-pattern-analysis-blackbox.js +0 -4
- package/dist/scripts/codex-native-read-repair-split-blackbox.js +0 -55
- package/dist/scripts/codex-native-reference-cache-blackbox.js +0 -41
- package/dist/scripts/core-skill-integrity-blackbox.js +0 -32
- package/dist/scripts/dfix-fast-blackbox-check.js +0 -37
- package/dist/scripts/dfix-parallel-write-blackbox.js +0 -48
- package/dist/scripts/dfix-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/doctor-dirty-repair-blackbox.js +0 -22
- package/dist/scripts/doctor-dirty-semantic-blackbox.js +0 -8
- package/dist/scripts/doctor-native-capability-repair-blackbox.js +0 -39
- package/dist/scripts/doctor-transaction-engine-blackbox.js +0 -28
- package/dist/scripts/doctor-zellij-fix-blackbox.js +0 -4
- package/dist/scripts/doctor-zellij-no-homebrew-blackbox.js +0 -4
- package/dist/scripts/doctor-zellij-upgrade-blackbox.js +0 -4
- package/dist/scripts/gate-pack-runner-blackbox.js +0 -27
- package/dist/scripts/gate-pack-v2-blackbox.js +0 -18
- package/dist/scripts/geo-cli-blackbox-check.js +0 -18
- package/dist/scripts/loop-collision-blackbox.js +0 -3
- package/dist/scripts/loop-concurrency-oversubscription-blackbox.js +0 -3
- package/dist/scripts/loop-fixture-production-misuse-blackbox.js +0 -3
- package/dist/scripts/loop-kill-interrupt-real-blackbox.js +0 -3
- package/dist/scripts/loop-merge-strategy-blackbox.js +0 -3
- package/dist/scripts/loop-mesh-production-e2e-blackbox.js +0 -3
- package/dist/scripts/loop-side-effect-blackbox.js +0 -3
- package/dist/scripts/mad-db-operation-lifecycle-blackbox.js +0 -29
- package/dist/scripts/mad-sks-actual-executor-blackbox.js +0 -5
- package/dist/scripts/mad-zellij-headless-fallback-blackbox.js +0 -4
- package/dist/scripts/mad-zellij-self-heal-blackbox.js +0 -4
- package/dist/scripts/naruto-loop-mesh-blackbox.js +0 -3
- package/dist/scripts/naruto-real-parallelism-blackbox.js +0 -307
- package/dist/scripts/naruto-worktree-coding-blackbox.js +0 -29
- package/dist/scripts/parallel-runtime-real-blackbox.js +0 -44
- package/dist/scripts/pipeline-codex-native-doctor-mad-routing-real-blackbox.js +0 -77
- package/dist/scripts/pipeline-codex-native-e2e-blackbox.js +0 -13
- package/dist/scripts/pipeline-codex-native-image-routing-real-blackbox.js +0 -50
- package/dist/scripts/pipeline-codex-native-loop-routing-real-blackbox.js +0 -74
- package/dist/scripts/pipeline-codex-native-qa-routing-real-blackbox.js +0 -51
- package/dist/scripts/pipeline-codex-native-research-routing-real-blackbox.js +0 -45
- package/dist/scripts/pipeline-execution-profile-routing-blackbox.js +0 -4
- package/dist/scripts/postinstall-global-doctor-blackbox.js +0 -12
- package/dist/scripts/ppt-full-e2e-blackbox-check.js +0 -109
- package/dist/scripts/ppt-imagegen-blackbox-check.js +0 -46
- package/dist/scripts/qa-backfill-route-blackbox.js +0 -5
- package/dist/scripts/qa-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/release-full-parallelism-blackbox.js +0 -41
- package/dist/scripts/release-triwiki-first-runner-blackbox.js +0 -48
- package/dist/scripts/release-wiring-3110-blackbox.js +0 -27
- package/dist/scripts/release-wiring-3112-blackbox.js +0 -17
- package/dist/scripts/release-wiring-3113-blackbox.js +0 -17
- package/dist/scripts/research-backfill-route-blackbox.js +0 -5
- package/dist/scripts/research-final-reviewer-blackbox.js +0 -70
- package/dist/scripts/research-stage-cycle-runtime-blackbox.js +0 -40
- package/dist/scripts/research-synthesis-writer-blackbox.js +0 -24
- package/dist/scripts/route-blackbox-realism-check.js +0 -21
- package/dist/scripts/scheduler-resource-claim-blackbox.js +0 -24
- package/dist/scripts/seo-cli-blackbox-check.js +0 -18
- package/dist/scripts/sks-3110-all-feature-regression-blackbox.js +0 -116
- package/dist/scripts/sks-3112-all-feature-regression-blackbox.js +0 -29
- package/dist/scripts/sks-3113-all-feature-regression-blackbox.js +0 -17
- package/dist/scripts/sks-400-all-feature-regression-blackbox.js +0 -21
- package/dist/scripts/sks-400-extreme-parallel-blackbox.js +0 -8
- package/dist/scripts/sks-400-five-minute-blackbox.js +0 -9
- package/dist/scripts/sks-400-legacy-purge-blackbox.js +0 -8
- package/dist/scripts/sks-401-all-feature-regression-blackbox.js +0 -46
- package/dist/scripts/sks-401-five-minute-actual-blackbox.js +0 -23
- package/dist/scripts/sks-402-all-feature-regression-blackbox.js +0 -9
- package/dist/scripts/sks-402-five-minute-real-blackbox.js +0 -22
- package/dist/scripts/sksd-warm-cache-blackbox.js +0 -12
- package/dist/scripts/team-backfill-route-blackbox.js +0 -5
- package/dist/scripts/team-parallel-write-blackbox.js +0 -55
- package/dist/scripts/team-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/triwiki-affected-graph-blackbox.js +0 -28
- package/dist/scripts/triwiki-proof-bank-blackbox.js +0 -30
- package/dist/scripts/triwiki-proof-bank-lock-blackbox.js +0 -7
- package/dist/scripts/ux-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/ux-review-imagegen-blackbox-check.js +0 -67
- package/dist/scripts/zellij-initial-main-only-blackbox.js +0 -28
- package/dist/scripts/zellij-pane-lock-concurrency-blackbox.js +0 -80
- package/dist/scripts/zellij-pane-lock-open-worker-integration-blackbox.js +0 -137
- package/dist/scripts/zellij-self-heal-typed-blackbox.js +0 -4
- package/dist/scripts/zellij-slot-telemetry-real-blackbox.js +0 -20
- package/dist/scripts/zellij-stacked-fallback-integration-blackbox.js +0 -81
- package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +0 -202
|
@@ -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')
|
|
@@ -327,7 +327,6 @@ function startWorkerProgressTelemetry(input) {
|
|
|
327
327
|
status: 'running',
|
|
328
328
|
backend: input.backend,
|
|
329
329
|
serviceTier: input.serviceTier,
|
|
330
|
-
progress: { done: tick, total: 0, label: 'heartbeat' },
|
|
331
330
|
artifacts: [input.heartbeatRel],
|
|
332
331
|
logTail: `backend running ${tick}`
|
|
333
332
|
}).catch(() => undefined);
|
|
@@ -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');
|