sneakoscope 6.0.2 → 6.1.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 +5 -3
- package/config/codex-releases/{rust-v0.142.0.json → rust-v0.144.1.json} +6 -6
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/cli/install-helpers.js +255 -440
- package/dist/cli/router.js +53 -4
- package/dist/commands/codex-app.js +8 -3
- package/dist/commands/codex-lb.js +169 -40
- package/dist/commands/codex.js +6 -5
- package/dist/commands/doctor.js +60 -26
- package/dist/commands/versioning.js +7 -0
- package/dist/config/skills-manifest.json +57 -57
- package/dist/core/agents/agent-central-ledger.js +9 -0
- package/dist/core/agents/agent-cleanup-executor.js +334 -41
- package/dist/core/agents/agent-cleanup.js +20 -1
- package/dist/core/agents/agent-command-surface.js +2 -1
- package/dist/core/agents/agent-effort-policy.js +46 -33
- package/dist/core/agents/agent-janitor.js +9 -10
- package/dist/core/agents/agent-namespace-safety.js +56 -0
- package/dist/core/agents/agent-orchestrator.js +26 -4
- package/dist/core/agents/agent-output-validator.js +1 -1
- package/dist/core/agents/agent-proof-evidence.js +16 -2
- package/dist/core/agents/agent-role-config.js +3 -6
- package/dist/core/agents/agent-roster.js +2 -2
- package/dist/core/agents/agent-runner-codex-exec.js +2 -0
- package/dist/core/agents/agent-runner-process.js +1 -0
- package/dist/core/agents/fast-mode-policy.js +3 -5
- package/dist/core/agents/native-cli-session-swarm.js +18 -1
- package/dist/core/agents/native-worker-backend-router.js +180 -108
- package/dist/core/agents/parallel-write-fixture.js +15 -10
- package/dist/core/agents/runtime-proof-summary.js +21 -3
- package/dist/core/agents/work-partition/repo-inventory.js +68 -7
- package/dist/core/code-structure.js +5 -4
- package/dist/core/codex/codex-config-guard.js +31 -9
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +51 -20
- package/dist/core/codex-app/codex-app-restart.js +38 -8
- package/dist/core/codex-app/codex-app-ui-state-snapshot.js +11 -3
- package/dist/core/codex-app/sks-menubar.js +100 -40
- package/dist/core/codex-app.js +60 -17
- package/dist/core/codex-compat/codex-hook-warning-detector.js +10 -1
- package/dist/core/codex-compat/codex-release-manifest.js +6 -6
- package/dist/core/codex-control/codex-0139-doctor-real-probe.js +7 -1
- package/dist/core/codex-control/codex-0139-image-path-real-probe.js +14 -8
- package/dist/core/codex-control/codex-0139-probe-runner.js +103 -28
- package/dist/core/codex-control/codex-0139-real-probe-summary.js +7 -3
- package/dist/core/codex-control/codex-0139-real-probes.js +21 -6
- package/dist/core/codex-control/codex-0139-sandbox-real-probe.js +39 -13
- package/dist/core/codex-control/codex-0139-web-search-probe.js +11 -8
- package/dist/core/codex-control/{codex-0142-capability.js → codex-0144-capability.js} +22 -22
- package/dist/core/codex-control/codex-0144-collab-agent-real-probe.js +63 -0
- package/dist/core/codex-control/codex-model-metadata.js +8 -4
- package/dist/core/codex-control/codex-multi-agent-event-normalizer.js +5 -1
- package/dist/core/codex-control/codex-reliability-shield.js +4 -1
- package/dist/core/codex-control/codex-sdk-adapter.js +53 -6
- package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
- package/dist/core/codex-control/codex-sdk-sandbox-policy.js +6 -3
- package/dist/core/codex-lb/codex-lb-env.js +107 -0
- package/dist/core/codex-lb/codex-lb-tool-catalog.js +478 -0
- package/dist/core/codex-native/codex-native-feature-broker.js +22 -22
- package/dist/core/codex-native/codex-native-feature-matrix.js +2 -2
- package/dist/core/codex-native/native-capability-postcheck.js +16 -8
- package/dist/core/codex-native/native-capability-repair-matrix.js +76 -27
- package/dist/core/codex-plugins/codex-plugin-json.js +67 -21
- package/dist/core/codex-plugins/codex-plugin-repair.js +118 -0
- package/dist/core/codex-runtime/codex-desktop-config-policy.js +306 -0
- package/dist/core/commands/agent-command.js +19 -0
- package/dist/core/commands/basic-cli.js +45 -24
- package/dist/core/commands/gc-command.js +27 -4
- package/dist/core/commands/image-ux-review-command.js +55 -24
- package/dist/core/commands/mad-sks-command.js +152 -132
- package/dist/core/commands/naruto-command.js +41 -10
- package/dist/core/commands/pipeline-command.js +1 -0
- package/dist/core/commands/wiki-command.js +179 -83
- package/dist/core/computer-use-live-evidence.js +166 -3
- package/dist/core/computer-use-status.js +5 -2
- package/dist/core/daemon/sksd-hook-daemon-entrypoint.js +2 -2
- package/dist/core/daemon/sksd-hook-daemon.js +171 -28
- package/dist/core/daemon/sksd-hook-dispatch.js +2 -2
- package/dist/core/dfix/verification-selector.js +6 -4
- package/dist/core/doctor/browser-use-repair.js +54 -13
- package/dist/core/doctor/codex-0139-doctor.js +3 -2
- package/dist/core/doctor/computer-use-repair.js +28 -39
- package/dist/core/doctor/doctor-codex-startup-repair.js +19 -9
- package/dist/core/doctor/doctor-context7-repair.js +1 -1
- package/dist/core/doctor/doctor-dirty-planner.js +1 -1
- package/dist/core/doctor/doctor-native-capability-repair.js +74 -3
- package/dist/core/doctor/imagegen-repair.js +47 -12
- package/dist/core/doctor/legacy-global-hook-cleanup.js +179 -0
- package/dist/core/feature-registry.js +25 -31
- package/dist/core/fsx.js +54 -6
- package/dist/core/harness-conflicts.js +1 -1
- package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +5 -4
- package/dist/core/hooks-runtime/hook-invocation-dedupe.js +147 -0
- package/dist/core/hooks-runtime/hook-io.js +6 -0
- package/dist/core/hooks-runtime.js +17 -2
- package/dist/core/image/image-artifact-path-contract.js +8 -6
- package/dist/core/image/image-artifact-registry.js +5 -1
- package/dist/core/image-ux-review/imagegen-adapter.js +5 -2
- package/dist/core/imagegen/imagegen-capability.js +10 -13
- package/dist/core/imagegen/require-imagegen.js +37 -11
- package/dist/core/managed-assets/managed-assets-manifest.js +1 -5
- package/dist/core/naruto/naruto-work-graph.js +70 -4
- package/dist/core/naruto/naruto-write-e2e.js +3 -4
- package/dist/core/ops/reporting.js +3 -0
- package/dist/core/pipeline-internals/runtime-core.js +12 -7
- package/dist/core/pipeline-internals/runtime-gates.js +17 -1
- package/dist/core/ppt/style-tokens.js +1 -1
- package/dist/core/ppt-review/index.js +1 -1
- package/dist/core/ppt-review/slide-exporter.js +23 -17
- package/dist/core/ppt-review/slide-imagegen-review.js +1 -1
- package/dist/core/ppt-review/slide-issue-extraction.js +4 -2
- package/dist/core/product-design-plugin.js +2 -2
- package/dist/core/proof/route-finalizer.js +1 -1
- package/dist/core/proof-field.js +3 -3
- package/dist/core/provider/model-router.js +68 -3
- package/dist/core/release/gate-manifest.js +18 -12
- package/dist/core/release/gate-pack-manifest.js +1 -1
- package/dist/core/release/package-size-budget.js +2 -0
- package/dist/core/release/release-gate-affected-selector.js +1 -1
- package/dist/core/release/release-gate-dag.js +43 -3
- package/dist/core/release/release-gate-hermetic-env.js +28 -17
- package/dist/core/release/release-real-contract.js +416 -0
- package/dist/core/retention/retention-budget.js +25 -6
- package/dist/core/retention.js +980 -101
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/evidence.js +4 -4
- package/dist/core/routes/model-mode-router.js +3 -0
- package/dist/core/routes/ppt-policy.js +1 -1
- package/dist/core/routes.js +11 -12
- package/dist/core/secret-redaction.js +4 -0
- package/dist/core/triwiki/code-pack.js +8 -2
- package/dist/core/triwiki/triwiki-cache-key.js +108 -29
- package/dist/core/triwiki-attention.js +13 -6
- package/dist/core/triwiki-provenance.js +274 -0
- package/dist/core/triwiki-runtime.js +21 -7
- package/dist/core/triwiki-wrongness/wrongness-ledger.js +178 -59
- package/dist/core/triwiki-wrongness/wrongness-retrieval.js +11 -2
- package/dist/core/triwiki-wrongness/wrongness-trust-policy.js +2 -0
- package/dist/core/update/update-migration-state.js +1 -1
- package/dist/core/update/update-notice.js +23 -0
- package/dist/core/update-check.js +69 -25
- package/dist/core/version.js +1 -1
- package/dist/core/wiki-coordinate.js +128 -12
- package/dist/core/work-order-ledger.js +168 -9
- package/dist/core/zellij/zellij-command.js +12 -1
- package/dist/core/zellij/zellij-dashboard-pane.js +3 -3
- package/dist/core/zellij/zellij-launcher.js +15 -14
- package/dist/core/zellij/zellij-pane-proof.js +32 -6
- package/dist/core/zellij/zellij-worker-pane-manager.js +5 -3
- package/dist/scripts/agent-fast-mode-default-check.js +48 -29
- package/dist/scripts/agent-role-config-repair-check.js +25 -4
- package/dist/scripts/agent-wiki-context-proof-check.js +16 -2
- package/dist/scripts/all-feature-deep-completion-check.js +14 -4
- package/dist/scripts/build-dist.js +17 -5
- package/dist/scripts/canonical-test-runner.js +188 -0
- package/dist/scripts/check-command-module-budget.js +38 -16
- package/dist/scripts/check-legacy-free.js +1 -1
- package/dist/scripts/codex-0139-interrupt-agent-check.js +5 -1
- package/dist/scripts/{codex-0142-app-server-v2-check.js → codex-0144-app-server-v2-check.js} +11 -10
- package/dist/scripts/{codex-0142-binary-identity-check.js → codex-0144-binary-identity-check.js} +4 -4
- package/dist/scripts/codex-0144-capability-check.js +21 -0
- package/dist/scripts/{codex-0139-real-probes-check.js → codex-0144-core-real-probes-check.js} +19 -5
- package/dist/scripts/{codex-0142-doctor-wiring-check.js → codex-0144-doctor-wiring-check.js} +6 -6
- package/dist/scripts/{codex-0142-manifest-check.js → codex-0144-manifest-check.js} +11 -3
- package/dist/scripts/{codex-0142-policy-check.js → codex-0144-policy-check.js} +2 -2
- package/dist/scripts/{codex-0142-thread-store-check.js → codex-0144-thread-store-check.js} +3 -3
- package/dist/scripts/codex-app-provider-model-ui-check.js +57 -8
- package/dist/scripts/codex-app-ui-preservation-check.js +35 -4
- package/dist/scripts/codex-control-side-effect-scope-check.js +2 -2
- package/dist/scripts/codex-effort-auto-discovery-check.js +1 -1
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +1 -0
- package/dist/scripts/{codex-lb-gpt55-fast-profile-check.js → codex-lb-gpt56-fast-profile-check.js} +56 -5
- package/dist/scripts/codex-model-metadata-check.js +1 -1
- package/dist/scripts/codex-sdk-sandbox-policy-check.js +5 -1
- package/dist/scripts/codex-sdk-version-compat-check.js +2 -1
- package/dist/scripts/dfix-fixture-check.js +1 -1
- package/dist/scripts/docs-truthfulness-check.js +1 -1
- package/dist/scripts/doctor-codex-startup-repair-check.js +35 -10
- package/dist/scripts/doctor-context7-repair-check.js +2 -1
- package/dist/scripts/doctor-fix-proves-codex-read-check.js +1 -1
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +34 -7
- package/dist/scripts/doctor-imagegen-repair-check.js +14 -4
- package/dist/scripts/doctor-startup-config-repair-blackbox.js +1 -1
- package/dist/scripts/doctor-startup-config-repair-check.js +1 -1
- package/dist/scripts/gate-policy-audit-check.js +2 -2
- package/dist/scripts/install-update-preserves-config-check.js +1 -1
- package/dist/scripts/legacy-gate-inventory-check.js +7 -5
- package/dist/scripts/legacy-strong-inventory-check.js +7 -5
- package/dist/scripts/legacy-upgrade-matrix-check.js +5 -5
- package/dist/scripts/lib/native-cli-session-swarm-check-lib.js +175 -14
- package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +166 -6
- package/dist/scripts/mutation-callsite-coverage-check.js +0 -11
- package/dist/scripts/naruto-shadow-clone-swarm-check.js +88 -50
- package/dist/scripts/npm-publish-performance-check.js +2 -1
- package/dist/scripts/package-published-contract-check.js +9 -0
- package/dist/scripts/packlist-performance-check.js +5 -2
- package/dist/scripts/postinstall-safe-side-effects-check.js +8 -3
- package/dist/scripts/ppt-no-mock-as-real-check.js +3 -1
- package/dist/scripts/product-design-plugin-routing-check.js +1 -1
- package/dist/scripts/release-check-stamp.js +182 -2
- package/dist/scripts/release-dag-full-coverage-check.js +7 -7
- package/dist/scripts/release-dynamic-presets-check.js +8 -0
- package/dist/scripts/release-gate-dag-runner-check.js +3 -2
- package/dist/scripts/release-gate-dag-runner.js +24 -11
- package/dist/scripts/release-gate-existence-audit.js +8 -9
- package/dist/scripts/release-gate-script-parity-check.js +1 -1
- package/dist/scripts/release-real-check.js +368 -157
- package/dist/scripts/release-runtime-truth-matrix-check.js +22 -0
- package/dist/scripts/route-proof-artifact-structure-check.js +1 -0
- package/dist/scripts/scheduler-batch-dispatch-check.js +1 -1
- package/dist/scripts/search-visibility-gate-lib.js +1 -1
- package/dist/scripts/seo-geo-route-identity-check.js +30 -4
- package/dist/scripts/sizecheck.js +7 -2
- package/dist/scripts/sks-1-11-gate-lib.js +53 -6
- package/dist/scripts/sks-menubar-install-check.js +7 -0
- package/dist/scripts/sks-uninstall-regression-check.js +1 -1
- package/dist/scripts/sksd-daemon-check.js +16 -6
- package/dist/scripts/update-default-command-check.js +4 -2
- package/dist/scripts/write-build-manifest.js +2 -1
- package/dist/scripts/zellij-layout-valid-check.js +31 -6
- package/dist/scripts/zellij-pane-proof-check.js +33 -2
- package/dist/scripts/zellij-real-session-cleanup-check.js +122 -2
- package/dist/scripts/zellij-real-session-launch-check.js +76 -5
- package/dist/scripts/zellij-slot-pane-renderer-check.js +4 -4
- package/package.json +27 -30
- package/schemas/codex/{app-server-0.142 → app-server-0.144}/codex_app_server_protocol.v2.schemas.json +1146 -781
- package/schemas/codex/codex-0139-real-probe-result.schema.json +39 -5
- package/schemas/codex/ppt-slide-issue-ledger.schema.json +2 -1
- package/dist/core/codex-control/codex-0139-multi-agent-real-probe.js +0 -107
- package/dist/scripts/agent-native-release-gate.js +0 -274
- package/dist/scripts/codex-0142-capability-check.js +0 -21
- package/dist/scripts/command-performance-scorecard-check.js +0 -204
- package/dist/scripts/config-managed-merge-callsite-coverage-check.js +0 -212
- package/dist/scripts/dollar-performance-scorecard-check.js +0 -257
- package/dist/scripts/gate-timing-check.js +0 -16
- package/dist/scripts/ops-maturity-scorecard-check.js +0 -12
- package/dist/scripts/performance-baseline-check.js +0 -12
- package/dist/scripts/performance-improvement-report-check.js +0 -58
- package/dist/scripts/release-parallel-check.js +0 -389
- package/dist/scripts/release-runner-efficiency-check.js +0 -15
- package/dist/scripts/retention-long-run-smoke-check.js +0 -299
- package/docs/assets/sneakoscope-architecture-pipeline.jpg +0 -0
|
@@ -10,8 +10,9 @@ 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
|
+
import { readCodexLbModelCatalog, readLbHealth } from '../codex-lb/codex-lb-env.js';
|
|
14
|
+
import { categoryForWorkerRole, isNarutoGpt56Model, modelRouteReason, routeModel } from '../provider/model-router.js';
|
|
15
|
+
import { codexTimeoutClassForRoute } from '../codex-control/codex-reliability-shield.js';
|
|
15
16
|
export const NATIVE_WORKER_BACKEND_ROUTER_SCHEMA = 'sks.native-worker-backend-router.v1';
|
|
16
17
|
export async function runNativeWorkerBackendRouter(input) {
|
|
17
18
|
const root = path.resolve(input.agentRoot);
|
|
@@ -19,6 +20,7 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
19
20
|
const requestedBackend = String(input.backend || '');
|
|
20
21
|
let backend = normalizeBackend(requestedBackend);
|
|
21
22
|
backend = await maybeAutoSelectOllamaBackend(backend, input);
|
|
23
|
+
const narutoRequest = isNarutoWorkerRequest(input);
|
|
22
24
|
const reportRel = path.join(input.workerDirRel, 'worker-backend-router-report.json');
|
|
23
25
|
const startedAt = nowIso();
|
|
24
26
|
let result;
|
|
@@ -27,7 +29,12 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
27
29
|
let proofLevel = 'blocked';
|
|
28
30
|
let outputLastMessagePath = null;
|
|
29
31
|
let modelRouting = null;
|
|
30
|
-
|
|
32
|
+
const narutoBackendBlocker = narutoWorkerBackendBlocker(backend, narutoRequest);
|
|
33
|
+
if (narutoBackendBlocker) {
|
|
34
|
+
const blocker = narutoBackendBlocker;
|
|
35
|
+
result = validateAgentWorkerResult(blockedResult(input, [blocker]));
|
|
36
|
+
}
|
|
37
|
+
else if (!input.guard?.ok) {
|
|
31
38
|
result = validateAgentWorkerResult(blockedResult(input, ['native_cli_worker_recursion_guard_missing']));
|
|
32
39
|
}
|
|
33
40
|
else if (requestedBackend === 'codex-exec') {
|
|
@@ -96,104 +103,110 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
96
103
|
else if (backend === 'codex-sdk' || backend === 'zellij' || backend === 'local-llm') {
|
|
97
104
|
const localPreferred = backend === 'local-llm';
|
|
98
105
|
modelRouting = await resolveWorkerModelRouting(input);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
generationIndex: Number(input.agent.generation_index || 1),
|
|
106
|
-
sessionId: String(input.agent.session_id || ''),
|
|
107
|
-
cwd: String(input.intake.cwd || root),
|
|
108
|
-
prompt: buildWorkerPrompt(input.slice),
|
|
109
|
-
model: modelRouting.choice.model,
|
|
110
|
-
reasoningEffort: modelRouting.choice.reasoning,
|
|
111
|
-
modelReasoningEffort: modelRouting.choice.reasoning,
|
|
112
|
-
serviceTier: modelRouting.choice.serviceTier,
|
|
113
|
-
inputFiles: input.intake.input_files || [],
|
|
114
|
-
inputImages: input.intake.input_images || [],
|
|
115
|
-
outputSchemaId: CODEX_AGENT_WORKER_RESULT_SCHEMA_ID,
|
|
116
|
-
outputSchema: codexAgentWorkerResultSchema,
|
|
117
|
-
sandboxPolicy: hasWriteLease(input.slice, input.intake) ? 'workspace-write' : 'read-only',
|
|
118
|
-
requestedScopeContract: {
|
|
119
|
-
id: String(input.intake.lease_id || input.slice?.id || ''),
|
|
106
|
+
if (modelRouting.blockers.length) {
|
|
107
|
+
proofLevel = 'blocked';
|
|
108
|
+
result = validateAgentWorkerResult(blockedResult(input, modelRouting.blockers));
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
const sdkTask = await runCodexTask({
|
|
120
112
|
route: String(input.intake.route || '$Agent'),
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
113
|
+
tier: 'worker',
|
|
114
|
+
missionId: String(input.intake.mission_id || input.intake.parent_mission_id || ''),
|
|
115
|
+
workItemId: String(input.slice?.id || ''),
|
|
116
|
+
slotId: String(input.agent.slot_id || input.agent.id || ''),
|
|
117
|
+
generationIndex: Number(input.agent.generation_index || 1),
|
|
118
|
+
sessionId: String(input.agent.session_id || ''),
|
|
119
|
+
cwd: String(input.intake.cwd || root),
|
|
120
|
+
prompt: buildWorkerPrompt(input.slice),
|
|
121
|
+
model: modelRouting.choice.model,
|
|
122
|
+
reasoningEffort: modelRouting.choice.reasoning,
|
|
123
|
+
modelReasoningEffort: modelRouting.choice.reasoning,
|
|
124
|
+
serviceTier: modelRouting.choice.serviceTier,
|
|
125
|
+
inputFiles: input.intake.input_files || [],
|
|
126
|
+
inputImages: input.intake.input_images || [],
|
|
127
|
+
outputSchemaId: CODEX_AGENT_WORKER_RESULT_SCHEMA_ID,
|
|
128
|
+
outputSchema: codexAgentWorkerResultSchema,
|
|
129
|
+
sandboxPolicy: hasWriteLease(input.slice, input.intake) ? 'workspace-write' : 'read-only',
|
|
130
|
+
requestedScopeContract: {
|
|
131
|
+
id: String(input.intake.lease_id || input.slice?.id || ''),
|
|
132
|
+
route: String(input.intake.route || '$Agent'),
|
|
133
|
+
read_only: !hasWriteLease(input.slice, input.intake),
|
|
134
|
+
allowed_paths: writePaths(input.slice, input.intake),
|
|
135
|
+
write_paths: writePaths(input.slice, input.intake),
|
|
136
|
+
model_route_reason: modelRouting.reason,
|
|
137
|
+
service_tier: modelRouting.choice.serviceTier,
|
|
138
|
+
user_confirmed_full_access: false,
|
|
139
|
+
mad_sks_authorized: input.intake.mad_sks_authorized === true || process.env.SKS_MAD_SKS_ACTIVE === '1'
|
|
140
|
+
},
|
|
141
|
+
backendPreference: localPreferred ? ['local-llm', 'codex-sdk'] : ['codex-sdk'],
|
|
142
|
+
allowLocalLlm: localPreferred,
|
|
143
|
+
...(localPreferred ? { localLlmPolicy: {
|
|
144
|
+
mode: 'local_preferred',
|
|
145
|
+
requiresGptFinal: true
|
|
146
|
+
} } : {}),
|
|
147
|
+
mutationLedgerRoot: path.join(root, input.workerDirRel),
|
|
148
|
+
zellijPaneId: await readZellijPaneId(root, input.workerDirRel),
|
|
149
|
+
reliabilityPolicy: {
|
|
150
|
+
maxEmptyResultRetries: 1,
|
|
151
|
+
timeoutClass: codexTimeoutClassForRoute(input.intake.route, 'standard')
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
outputLastMessagePath = sdkTask.workerResultPath;
|
|
155
|
+
const sdkWorkerResult = normalizeSdkWorkerResultPaths(await readJson(sdkTask.workerResultPath, null), input, pathRoot);
|
|
156
|
+
patchEnvelopes = normalizeSdkPatchEnvelopes(sdkWorkerResult?.patch_envelopes || [], input, sdkTask.sdkThreadId, pathRoot);
|
|
157
|
+
proofLevel = sdkTask.ok ? (patchEnvelopes.length ? 'model_authored' : sdkTask.backend === 'local-llm' ? 'local_llm_worker_proven' : 'codex_sdk_thread_proven') : 'blocked';
|
|
158
|
+
const sdkReport = {
|
|
159
|
+
schema: 'sks.codex-sdk-worker-adapter.v1',
|
|
160
|
+
backend: sdkTask.backend,
|
|
161
|
+
backend_family: sdkTask.backend_family,
|
|
162
|
+
sdk_thread_id: sdkTask.sdkThreadId,
|
|
163
|
+
sdk_run_id: sdkTask.sdkRunId,
|
|
164
|
+
local_llm_proof_path: sdkTask.localLlmProofPath || null,
|
|
165
|
+
stream_event_count: sdkTask.streamEventCount,
|
|
166
|
+
structured_output_valid: sdkTask.structuredOutputValid,
|
|
167
|
+
worker_result_path: sdkTask.workerResultPath,
|
|
168
|
+
patch_envelope_path: sdkTask.patchEnvelopePath || null,
|
|
169
|
+
model: modelRouting.choice.model,
|
|
170
|
+
model_reasoning_effort: modelRouting.choice.reasoning,
|
|
125
171
|
service_tier: modelRouting.choice.serviceTier,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
result = validateAgentWorkerResult({
|
|
165
|
-
...sdkWorkerResult,
|
|
166
|
-
agent_id: workerOwnerId(input),
|
|
167
|
-
session_id: input.agent.session_id,
|
|
168
|
-
persona_id: input.agent.persona_id || input.agent.id,
|
|
169
|
-
task_slice_id: input.slice?.id || '',
|
|
170
|
-
backend: sdkTask.backend === 'local-llm' ? 'local-llm' : 'codex-sdk',
|
|
171
|
-
patch_envelopes: patchEnvelopes,
|
|
172
|
-
...(patchEnvelopes.length ? {} : { no_patch_reason: buildNoPatchReason(input, sdkTask.backend || backend) }),
|
|
173
|
-
codex_child_report: sdkReport,
|
|
174
|
-
codex_sdk_thread: sdkReport,
|
|
175
|
-
model_authored_patch_envelopes: patchEnvelopes.length > 0,
|
|
176
|
-
fixture_patch_envelopes: false,
|
|
177
|
-
artifacts: [...new Set([
|
|
178
|
-
...(sdkWorkerResult?.artifacts || []),
|
|
179
|
-
path.relative(root, sdkTask.workerResultPath),
|
|
180
|
-
path.join(input.workerDirRel, 'codex-control-proof.json'),
|
|
181
|
-
path.join(input.workerDirRel, 'codex-thread-registry.json'),
|
|
182
|
-
sdkTask.backend === 'local-llm' ? path.join(input.workerDirRel, 'local-llm-events.jsonl') : path.join(input.workerDirRel, 'codex-sdk-events.jsonl'),
|
|
183
|
-
...(sdkTask.localLlmProofPath ? [path.relative(root, sdkTask.localLlmProofPath)] : [])
|
|
184
|
-
])],
|
|
185
|
-
blockers: [...(sdkWorkerResult?.blockers || []), ...sdkTask.blockers],
|
|
186
|
-
verification: {
|
|
187
|
-
status: sdkTask.ok ? 'passed' : 'failed',
|
|
188
|
-
checks: [
|
|
189
|
-
...(sdkWorkerResult?.verification?.checks || []),
|
|
190
|
-
sdkTask.backend === 'local-llm' ? 'local-llm-control-plane' : 'codex-sdk-control-plane',
|
|
191
|
-
sdkTask.backend === 'local-llm' ? 'local-llm-event-stream' : 'codex-sdk-event-stream',
|
|
192
|
-
sdkTask.backend === 'local-llm' ? 'local-llm-structured-output' : 'codex-sdk-structured-output',
|
|
193
|
-
...(sdkTask.backend === 'local-llm' ? ['gpt-final-required-before-acceptance'] : [])
|
|
194
|
-
]
|
|
195
|
-
}
|
|
196
|
-
});
|
|
172
|
+
model_route_reason: modelRouting.reason,
|
|
173
|
+
blockers: sdkTask.blockers
|
|
174
|
+
};
|
|
175
|
+
childReports = [sdkReport];
|
|
176
|
+
result = validateAgentWorkerResult({
|
|
177
|
+
...sdkWorkerResult,
|
|
178
|
+
agent_id: workerOwnerId(input),
|
|
179
|
+
session_id: input.agent.session_id,
|
|
180
|
+
persona_id: input.agent.persona_id || input.agent.id,
|
|
181
|
+
task_slice_id: input.slice?.id || '',
|
|
182
|
+
backend: sdkTask.backend === 'local-llm' ? 'local-llm' : 'codex-sdk',
|
|
183
|
+
patch_envelopes: patchEnvelopes,
|
|
184
|
+
...(patchEnvelopes.length ? {} : { no_patch_reason: buildNoPatchReason(input, sdkTask.backend || backend) }),
|
|
185
|
+
codex_child_report: sdkReport,
|
|
186
|
+
codex_sdk_thread: sdkReport,
|
|
187
|
+
model_authored_patch_envelopes: patchEnvelopes.length > 0,
|
|
188
|
+
fixture_patch_envelopes: false,
|
|
189
|
+
artifacts: [...new Set([
|
|
190
|
+
...(sdkWorkerResult?.artifacts || []),
|
|
191
|
+
path.relative(root, sdkTask.workerResultPath),
|
|
192
|
+
path.join(input.workerDirRel, 'codex-control-proof.json'),
|
|
193
|
+
path.join(input.workerDirRel, 'codex-thread-registry.json'),
|
|
194
|
+
sdkTask.backend === 'local-llm' ? path.join(input.workerDirRel, 'local-llm-events.jsonl') : path.join(input.workerDirRel, 'codex-sdk-events.jsonl'),
|
|
195
|
+
...(sdkTask.localLlmProofPath ? [path.relative(root, sdkTask.localLlmProofPath)] : [])
|
|
196
|
+
])],
|
|
197
|
+
blockers: [...(sdkWorkerResult?.blockers || []), ...sdkTask.blockers],
|
|
198
|
+
verification: {
|
|
199
|
+
status: sdkTask.ok ? 'passed' : 'failed',
|
|
200
|
+
checks: [
|
|
201
|
+
...(sdkWorkerResult?.verification?.checks || []),
|
|
202
|
+
sdkTask.backend === 'local-llm' ? 'local-llm-control-plane' : 'codex-sdk-control-plane',
|
|
203
|
+
sdkTask.backend === 'local-llm' ? 'local-llm-event-stream' : 'codex-sdk-event-stream',
|
|
204
|
+
sdkTask.backend === 'local-llm' ? 'local-llm-structured-output' : 'codex-sdk-structured-output',
|
|
205
|
+
...(sdkTask.backend === 'local-llm' ? ['gpt-final-required-before-acceptance'] : [])
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
197
210
|
}
|
|
198
211
|
else {
|
|
199
212
|
const zellijRun = await runZellijAgent(input.agent, input.slice, {
|
|
@@ -262,24 +275,69 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
262
275
|
patchEnvelopes
|
|
263
276
|
};
|
|
264
277
|
}
|
|
265
|
-
async function resolveWorkerModelRouting(input) {
|
|
266
|
-
const
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
278
|
+
export async function resolveWorkerModelRouting(input, deps = {}) {
|
|
279
|
+
const narutoOnly = Boolean(input.agent?.naruto_role) || /\$?naruto/i.test(String(input.intake?.route || ''));
|
|
280
|
+
const taskKindText = [
|
|
281
|
+
input.slice?.work_item_kind,
|
|
282
|
+
input.slice?.kind,
|
|
283
|
+
input.slice?.type,
|
|
284
|
+
input.slice?.title,
|
|
285
|
+
input.slice?.required_role,
|
|
286
|
+
input.slice?.role,
|
|
287
|
+
input.agent?.naruto_role,
|
|
288
|
+
input.agent?.role,
|
|
289
|
+
input.agent?.persona_id
|
|
290
|
+
].map((value) => String(value || '')).join(' ');
|
|
291
|
+
const riskText = [taskKindText, input.slice?.risk, input.slice?.risk_focus, input.slice?.acceptance, input.slice?.parent_prompt, input.slice?.description, input.intake?.prompt].map((value) => String(value || '')).join(' ');
|
|
292
|
+
const category = categoryForWorkerRole(String(input.agent?.role || 'executor'), taskKindText);
|
|
293
|
+
const env = deps.env || process.env;
|
|
294
|
+
const lbHealth = Object.prototype.hasOwnProperty.call(deps, 'lbHealth') ? deps.lbHealth : await readLbHealth().catch(() => null);
|
|
295
|
+
const lbCatalog = narutoOnly
|
|
296
|
+
? Object.prototype.hasOwnProperty.call(deps, 'lbCatalog')
|
|
297
|
+
? deps.lbCatalog
|
|
298
|
+
: input.intake?.naruto_model_catalog || await readCodexLbModelCatalog().catch(() => null)
|
|
299
|
+
: null;
|
|
300
|
+
const explicitModel = String(env.SKS_WORKER_MODEL || env.SKS_AGENT_MODEL || '').trim();
|
|
301
|
+
const explicitReasoningRaw = String(env.SKS_WORKER_REASONING || env.SKS_WORKER_MODEL_REASONING || '').trim();
|
|
302
|
+
const explicitTierRaw = String(env.SKS_WORKER_SERVICE_TIER || env.SKS_SERVICE_TIER || '').trim();
|
|
303
|
+
const explicitReasoning = normalizeModelReasoning(explicitReasoningRaw);
|
|
304
|
+
const explicitTier = normalizeServiceTier(explicitTierRaw);
|
|
305
|
+
const explicitNarutoModelInvalid = narutoOnly && Boolean(explicitModel) && !isNarutoGpt56Model(explicitModel);
|
|
306
|
+
const explicitNarutoReasoningInvalid = narutoOnly && Boolean(explicitReasoningRaw) && !explicitReasoning;
|
|
307
|
+
const explicitNarutoTierInvalid = narutoOnly && Boolean(explicitTierRaw) && !explicitTier;
|
|
308
|
+
const routed = explicitModel && !narutoOnly
|
|
272
309
|
? {
|
|
273
310
|
model: explicitModel,
|
|
274
311
|
reasoning: explicitReasoning || normalizeModelReasoning(input.agent?.model_reasoning_effort) || 'medium',
|
|
275
312
|
serviceTier: explicitTier || input.fastModePolicy.service_tier || 'fast'
|
|
276
313
|
}
|
|
277
|
-
: await routeModel(category, {
|
|
314
|
+
: await routeModel(category, {
|
|
315
|
+
lbHealth,
|
|
316
|
+
...(narutoOnly ? {
|
|
317
|
+
narutoOnly: true,
|
|
318
|
+
taskText: taskKindText,
|
|
319
|
+
riskText,
|
|
320
|
+
availableModels: lbCatalog?.models || [],
|
|
321
|
+
availableModelEfforts: lbCatalog?.model_efforts || {},
|
|
322
|
+
...(explicitModel ? { model: explicitModel } : {})
|
|
323
|
+
} : { model: input.agent?.model || null })
|
|
324
|
+
});
|
|
325
|
+
const blockers = [
|
|
326
|
+
...(narutoOnly && !lbCatalog?.ok ? (lbCatalog?.blockers || ['codex_lb_model_catalog_unavailable']) : []),
|
|
327
|
+
...(explicitNarutoModelInvalid ? ['naruto_worker_model_outside_gpt_5_6_family'] : []),
|
|
328
|
+
...(explicitNarutoReasoningInvalid ? ['naruto_reasoning_override_invalid'] : []),
|
|
329
|
+
...(explicitNarutoTierInvalid ? ['naruto_service_tier_override_invalid'] : []),
|
|
330
|
+
...(narutoOnly && explicitReasoning && explicitReasoning !== routed.reasoning ? ['naruto_reasoning_override_conflicts_with_policy'] : []),
|
|
331
|
+
...(narutoOnly && explicitTier && explicitTier !== 'fast' ? ['naruto_service_tier_override_conflicts_with_policy'] : []),
|
|
332
|
+
...(narutoOnly && !routed.model ? ['naruto_required_gpt_5_6_model_unavailable'] : [])
|
|
333
|
+
];
|
|
278
334
|
return {
|
|
279
335
|
category,
|
|
280
336
|
choice: routed,
|
|
281
337
|
explicit: Boolean(explicitModel),
|
|
282
338
|
lb_health: lbHealth,
|
|
339
|
+
lb_catalog: lbCatalog,
|
|
340
|
+
blockers: [...new Set(blockers)],
|
|
283
341
|
reason: modelRouteReason(category, routed, {
|
|
284
342
|
explicit: Boolean(explicitModel),
|
|
285
343
|
quotaLow: lbHealth?.quota_low === true,
|
|
@@ -289,7 +347,7 @@ async function resolveWorkerModelRouting(input) {
|
|
|
289
347
|
}
|
|
290
348
|
function normalizeModelReasoning(value) {
|
|
291
349
|
const text = String(value || '').toLowerCase();
|
|
292
|
-
return text === 'low' || text === 'medium' || text === 'high' || text === 'xhigh' ? text : null;
|
|
350
|
+
return text === 'low' || text === 'medium' || text === 'high' || text === 'xhigh' || text === 'max' || text === 'ultra' ? text : null;
|
|
293
351
|
}
|
|
294
352
|
function normalizeServiceTier(value) {
|
|
295
353
|
const text = String(value || '').toLowerCase();
|
|
@@ -298,6 +356,8 @@ function normalizeServiceTier(value) {
|
|
|
298
356
|
async function maybeAutoSelectOllamaBackend(backend, input) {
|
|
299
357
|
if (backend !== 'codex-sdk')
|
|
300
358
|
return backend;
|
|
359
|
+
if (isNarutoWorkerRequest(input))
|
|
360
|
+
return backend;
|
|
301
361
|
if (input.intake?.backend_explicit === true || input.intake?.no_ollama === true)
|
|
302
362
|
return backend;
|
|
303
363
|
const config = await resolveOllamaWorkerConfig({
|
|
@@ -310,6 +370,18 @@ async function maybeAutoSelectOllamaBackend(backend, input) {
|
|
|
310
370
|
const policy = classifyOllamaWorkerSlice(input.slice, { route: input.intake?.route, agent: input.agent });
|
|
311
371
|
return policy.ok ? 'local-llm' : backend;
|
|
312
372
|
}
|
|
373
|
+
function isNarutoWorkerRequest(input) {
|
|
374
|
+
return Boolean(input.agent?.naruto_role) || /\$?naruto/i.test(String(input.intake?.route || ''));
|
|
375
|
+
}
|
|
376
|
+
export function narutoWorkerBackendBlocker(backend, narutoRequest = true) {
|
|
377
|
+
if (!narutoRequest)
|
|
378
|
+
return null;
|
|
379
|
+
if (backend === 'process')
|
|
380
|
+
return 'naruto_gpt_5_6_family_only_process_backend_forbidden';
|
|
381
|
+
if (backend === 'ollama' || backend === 'local-llm')
|
|
382
|
+
return 'naruto_gpt_5_6_family_only_local_backend_forbidden';
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
313
385
|
function normalizeBackend(value) {
|
|
314
386
|
return value === 'fake' || value === 'process' || value === 'codex-sdk' || value === 'zellij' || value === 'ollama' || value === 'local-llm' ? value : null;
|
|
315
387
|
}
|
|
@@ -175,24 +175,29 @@ async function runTypecheck(repoRoot) {
|
|
|
175
175
|
return runCommand([localTsc, '-p', 'tsconfig.json', '--noEmit'], repoRoot);
|
|
176
176
|
}
|
|
177
177
|
async function cleanupWorktreesAndBranches(repoRoot, tmpRoot, workers, before, keepTmp) {
|
|
178
|
+
const removeResults = [];
|
|
178
179
|
for (const worker of workers) {
|
|
179
|
-
await runCommand(['git', 'worktree', 'remove', '--force', path.join(tmpRoot, 'worktrees', worker.id)], repoRoot);
|
|
180
|
+
removeResults.push(await runCommand(['git', 'worktree', 'remove', '--force', path.join(tmpRoot, 'worktrees', worker.id)], repoRoot));
|
|
180
181
|
}
|
|
181
|
-
await runCommand(['git', 'worktree', 'prune'], repoRoot);
|
|
182
|
+
const prune = await runCommand(['git', 'worktree', 'prune'], repoRoot);
|
|
183
|
+
const branchResults = [];
|
|
182
184
|
for (const worker of workers) {
|
|
183
|
-
await runCommand(['git', 'branch', '-D', worker.branch], repoRoot);
|
|
185
|
+
branchResults.push(await runCommand(['git', 'branch', '-D', worker.branch], repoRoot));
|
|
184
186
|
}
|
|
185
187
|
const after = await runCommand(['git', 'worktree', 'list', '--porcelain'], repoRoot);
|
|
188
|
+
const branches = await runCommand(['git', 'branch', '--list', ...workers.map((worker) => worker.branch)], repoRoot);
|
|
186
189
|
const status = await runCommand(['git', 'status', '--short'], repoRoot);
|
|
187
190
|
if (!keepTmp)
|
|
188
|
-
await fsp.rm(tmpRoot, { recursive: true, force: true });
|
|
191
|
+
await fsp.rm(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 50 });
|
|
189
192
|
const tmpRemoved = keepTmp ? false : !(await exists(tmpRoot));
|
|
193
|
+
const workerWorktreesRemoved = after.ok && workers.every((worker) => !after.stdout_tail.includes(worker.id));
|
|
194
|
+
const workerBranchesRemoved = branches.ok && branches.stdout_tail.trim().length === 0;
|
|
190
195
|
return {
|
|
191
|
-
ok:
|
|
196
|
+
ok: removeResults.every((result) => result.ok) && prune.ok && branchResults.every((result) => result.ok) && workerWorktreesRemoved && workerBranchesRemoved && status.ok && status.stdout_tail.trim().length === 0 && tmpRemoved,
|
|
192
197
|
worktree_list_before_cleanup: before,
|
|
193
198
|
worktree_list_after_cleanup: after.stdout_tail,
|
|
194
|
-
worker_worktrees_removed:
|
|
195
|
-
worker_branches_removed:
|
|
199
|
+
worker_worktrees_removed: workerWorktreesRemoved,
|
|
200
|
+
worker_branches_removed: workerBranchesRemoved,
|
|
196
201
|
parent_dirty_after_cleanup: status.stdout_tail.trim().length > 0,
|
|
197
202
|
tmp_removed: tmpRemoved
|
|
198
203
|
};
|
|
@@ -200,12 +205,12 @@ async function cleanupWorktreesAndBranches(repoRoot, tmpRoot, workers, before, k
|
|
|
200
205
|
async function bestEffortCleanup(repoRoot, tmpRoot, keepTmp) {
|
|
201
206
|
const before = await runCommand(['git', 'worktree', 'list', '--porcelain'], repoRoot);
|
|
202
207
|
if (!keepTmp)
|
|
203
|
-
await fsp.rm(tmpRoot, { recursive: true, force: true });
|
|
208
|
+
await fsp.rm(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 50 });
|
|
204
209
|
return {
|
|
205
|
-
ok:
|
|
210
|
+
ok: false,
|
|
206
211
|
worktree_list_before_cleanup: before.stdout_tail,
|
|
207
212
|
worktree_list_after_cleanup: '',
|
|
208
|
-
worker_worktrees_removed:
|
|
213
|
+
worker_worktrees_removed: false,
|
|
209
214
|
worker_branches_removed: false,
|
|
210
215
|
parent_dirty_after_cleanup: false,
|
|
211
216
|
tmp_removed: !keepTmp && !(await exists(tmpRoot))
|
|
@@ -15,6 +15,7 @@ export async function buildRuntimeProofSummary(root, missionIdInput = 'latest',
|
|
|
15
15
|
const scheduler = await readJson(path.join(agentsDir, 'agent-scheduler-state.json'), null);
|
|
16
16
|
const swarm = await readJson(path.join(agentsDir, 'agent-native-cli-session-swarm.json'), null);
|
|
17
17
|
const telemetry = await readJson(path.join(dir, 'zellij', 'slot-telemetry.snapshot.json'), null);
|
|
18
|
+
const stopGate = await readJson(path.join(dir, 'stop-gate.json'), null);
|
|
18
19
|
const governor = await readJson(path.join(agentsDir, 'naruto-concurrency-governor.json'), null);
|
|
19
20
|
const messagesAll = await readAgentMessageBus(root, missionId, { max: 500 });
|
|
20
21
|
const recentMessages = await readAgentMessageBus(root, missionId, { max: opts.maxMessages || 8 });
|
|
@@ -23,15 +24,17 @@ export async function buildRuntimeProofSummary(root, missionIdInput = 'latest',
|
|
|
23
24
|
const failedMessages = messagesAll.filter((row) => row.event_type === 'worker_failed');
|
|
24
25
|
const errorMessages = messagesAll.filter((row) => row.level === 'error');
|
|
25
26
|
const telemetryAgeMs = telemetry?.updated_at ? Math.max(0, Date.now() - Date.parse(telemetry.updated_at)) : Number.MAX_SAFE_INTEGER;
|
|
27
|
+
const terminalProofAccepted = canonicalTerminalProofAccepted(stopGate, missionId);
|
|
26
28
|
const visiblePanes = Number(parallel?.visible_panes ?? swarm?.zellij_pane_worker_sessions ?? telemetryVisiblePaneCount(telemetry) ?? 0);
|
|
27
29
|
const targetActive = Number(scheduler?.target_active_slots ?? parallel?.target_active_slots ?? swarm?.target_active_slots ?? governor?.target_active_slots ?? 0);
|
|
28
30
|
const headlessWorkers = Number(parallel?.headless_workers ?? swarm?.headless_overflow_worker_count ?? Math.max(0, targetActive - visiblePanes));
|
|
31
|
+
const parallelBlockers = parallel?.passed === false ? parallel.blockers || ['parallel_runtime_proof_failed'] : [];
|
|
29
32
|
const blockers = [
|
|
30
33
|
...(!parallel ? ['parallel_runtime_proof_missing'] : []),
|
|
31
34
|
...(!scheduler ? ['agent_scheduler_state_missing'] : []),
|
|
32
|
-
...(
|
|
35
|
+
...(terminalProofAccepted ? parallelBlockers.filter((blocker) => String(blocker) !== 'speedup_ratio_below_target') : parallelBlockers),
|
|
33
36
|
...(errorMessages.length ? ['agent_message_bus_error_blockers'] : []),
|
|
34
|
-
...(telemetryAgeMs > 3000 ? ['zellij_telemetry_stale'] : []),
|
|
37
|
+
...(telemetryAgeMs > 3000 && !terminalProofAccepted ? ['zellij_telemetry_stale'] : []),
|
|
35
38
|
...(zellijSummary?.blockers || [])
|
|
36
39
|
].map(String);
|
|
37
40
|
const summary = {
|
|
@@ -76,6 +79,11 @@ export async function buildRuntimeProofSummary(root, missionIdInput = 'latest',
|
|
|
76
79
|
duplicate_slot_anchor_count: Number(zellijSummary?.duplicate_slot_anchor_count || 0)
|
|
77
80
|
},
|
|
78
81
|
loops: loopSummary,
|
|
82
|
+
terminal_proof: {
|
|
83
|
+
accepted: terminalProofAccepted,
|
|
84
|
+
gate_file: terminalProofAccepted ? 'stop-gate.json' : null,
|
|
85
|
+
terminal_state: terminalProofAccepted ? String(stopGate?.terminal_state || 'completed') : null
|
|
86
|
+
},
|
|
79
87
|
blockers
|
|
80
88
|
};
|
|
81
89
|
await writeJsonAtomic(path.join(agentsDir, 'runtime-proof-summary.json'), summary);
|
|
@@ -83,7 +91,8 @@ export async function buildRuntimeProofSummary(root, missionIdInput = 'latest',
|
|
|
83
91
|
}
|
|
84
92
|
export function renderRuntimeProofSummary(summary) {
|
|
85
93
|
return [
|
|
86
|
-
`Parallel proof: ${summary.parallel.proof_passed ? 'passed' : 'blocked'}`,
|
|
94
|
+
`Parallel proof: ${summary.parallel.proof_passed ? 'passed' : summary.terminal_proof?.accepted ? 'terminal gate accepted' : 'blocked'}`,
|
|
95
|
+
`Canonical terminal proof: ${summary.terminal_proof?.accepted ? 'accepted' : 'not available'}`,
|
|
87
96
|
`Active workers: ${summary.parallel.max_active_workers}`,
|
|
88
97
|
`Unique PIDs: ${summary.parallel.unique_worker_pids}`,
|
|
89
98
|
`Speedup: ${summary.parallel.speedup_ratio}x`,
|
|
@@ -102,6 +111,15 @@ export function renderRuntimeProofSummary(summary) {
|
|
|
102
111
|
...(summary.blockers.length ? [`Blockers: ${summary.blockers.join(', ')}`] : [])
|
|
103
112
|
].join('\n');
|
|
104
113
|
}
|
|
114
|
+
function canonicalTerminalProofAccepted(gate, missionId) {
|
|
115
|
+
const blockers = Array.isArray(gate?.blockers) ? gate.blockers : [];
|
|
116
|
+
return gate?.schema === 'sks.stop-gate.v1'
|
|
117
|
+
&& String(gate?.mission_id || '') === missionId
|
|
118
|
+
&& gate?.passed === true
|
|
119
|
+
&& gate?.terminal === true
|
|
120
|
+
&& String(gate?.terminal_state || '') === 'completed'
|
|
121
|
+
&& blockers.length === 0;
|
|
122
|
+
}
|
|
105
123
|
function messageStatusLabel(row) {
|
|
106
124
|
if (row.event_type === 'worker_completed')
|
|
107
125
|
return '[done]';
|
|
@@ -1,9 +1,50 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
const IGNORE = new Set([
|
|
3
|
+
const IGNORE = new Set([
|
|
4
|
+
'.agents', '.cache', '.claude', '.codex', '.git', '.git-worktrees', '.hg', '.mypy_cache', '.next', '.npm', '.nuxt',
|
|
5
|
+
'.nyc_output', '.parcel-cache', '.pnpm-store', '.pytest_cache', '.ruff_cache', '.sneakoscope', '.svelte-kit', '.svn',
|
|
6
|
+
'.tmp', '.turbo', '.venv', '.worktrees', '.yarn', '__pycache__', 'build', 'coverage', 'dist', 'logs', 'node_modules',
|
|
7
|
+
'out', 'target', 'temp', 'tmp', 'venv'
|
|
8
|
+
]);
|
|
9
|
+
const PRIORITY_DIRS = ['src', 'test', 'docs', 'schemas', 'scripts', 'crates', 'bin'];
|
|
10
|
+
const REPRESENTATIVE_DIRS = ['src', 'test', 'docs'];
|
|
11
|
+
const CORE_FILES = ['package.json', 'package-lock.json', 'README.md', 'CHANGELOG.md', 'LICENSE', 'tsconfig.json', 'release-gates.v2.json', 'runtime-required-scripts.json', 'AGENTS.md'];
|
|
4
12
|
export async function collectRepoInventory(root, opts = {}) {
|
|
5
13
|
const files = [];
|
|
6
|
-
|
|
14
|
+
const seen = new Set();
|
|
15
|
+
const requestedMax = Number(opts.maxFiles ?? process.env.SKS_AGENT_REPO_INVENTORY_MAX_FILES ?? 10000);
|
|
16
|
+
const maxFiles = Number.isFinite(requestedMax) ? Math.max(1, Math.floor(requestedMax)) : 10000;
|
|
17
|
+
const add = (file) => {
|
|
18
|
+
if (files.length >= maxFiles || seen.has(file))
|
|
19
|
+
return;
|
|
20
|
+
seen.add(file);
|
|
21
|
+
files.push(file);
|
|
22
|
+
};
|
|
23
|
+
// Seed representative source/test/docs entries before any large tree can
|
|
24
|
+
// exhaust the cap, then expand the priority roots in a stable order.
|
|
25
|
+
for (const name of REPRESENTATIVE_DIRS) {
|
|
26
|
+
const representative = await firstFile(root, path.join(root, name));
|
|
27
|
+
if (representative)
|
|
28
|
+
add(representative);
|
|
29
|
+
}
|
|
30
|
+
for (const name of CORE_FILES) {
|
|
31
|
+
const full = path.join(root, name);
|
|
32
|
+
if ((await fs.stat(full).catch(() => null))?.isFile())
|
|
33
|
+
add(name);
|
|
34
|
+
}
|
|
35
|
+
for (const name of PRIORITY_DIRS)
|
|
36
|
+
await walk(root, path.join(root, name), files, seen, maxFiles);
|
|
37
|
+
for (const entry of await sortedEntries(root)) {
|
|
38
|
+
if (files.length >= maxFiles)
|
|
39
|
+
break;
|
|
40
|
+
if (IGNORE.has(entry.name) || PRIORITY_DIRS.includes(entry.name) || CORE_FILES.includes(entry.name))
|
|
41
|
+
continue;
|
|
42
|
+
const full = path.join(root, entry.name);
|
|
43
|
+
if (entry.isDirectory())
|
|
44
|
+
await walk(root, full, files, seen, maxFiles);
|
|
45
|
+
else if (entry.isFile())
|
|
46
|
+
add(entry.name);
|
|
47
|
+
}
|
|
7
48
|
const classify = (re) => files.filter((file) => re.test(file));
|
|
8
49
|
return {
|
|
9
50
|
schema: 'sks.agent-repo-inventory.v1',
|
|
@@ -19,11 +60,10 @@ export async function collectRepoInventory(root, opts = {}) {
|
|
|
19
60
|
files
|
|
20
61
|
};
|
|
21
62
|
}
|
|
22
|
-
async function walk(root, dir, out, maxFiles) {
|
|
63
|
+
async function walk(root, dir, out, seen, maxFiles) {
|
|
23
64
|
if (out.length >= maxFiles)
|
|
24
65
|
return;
|
|
25
|
-
const
|
|
26
|
-
for (const entry of entries) {
|
|
66
|
+
for (const entry of await sortedEntries(dir)) {
|
|
27
67
|
if (out.length >= maxFiles)
|
|
28
68
|
return;
|
|
29
69
|
if (IGNORE.has(entry.name))
|
|
@@ -31,9 +71,30 @@ async function walk(root, dir, out, maxFiles) {
|
|
|
31
71
|
const full = path.join(dir, entry.name);
|
|
32
72
|
const rel = path.relative(root, full).replace(/\\/g, '/');
|
|
33
73
|
if (entry.isDirectory())
|
|
34
|
-
await walk(root, full, out, maxFiles);
|
|
35
|
-
else if (entry.isFile())
|
|
74
|
+
await walk(root, full, out, seen, maxFiles);
|
|
75
|
+
else if (entry.isFile() && !seen.has(rel)) {
|
|
76
|
+
seen.add(rel);
|
|
36
77
|
out.push(rel);
|
|
78
|
+
}
|
|
37
79
|
}
|
|
38
80
|
}
|
|
81
|
+
async function firstFile(root, dir) {
|
|
82
|
+
for (const entry of await sortedEntries(dir)) {
|
|
83
|
+
if (IGNORE.has(entry.name))
|
|
84
|
+
continue;
|
|
85
|
+
const full = path.join(dir, entry.name);
|
|
86
|
+
if (entry.isFile())
|
|
87
|
+
return path.relative(root, full).replace(/\\/g, '/');
|
|
88
|
+
if (entry.isDirectory()) {
|
|
89
|
+
const nested = await firstFile(root, full);
|
|
90
|
+
if (nested)
|
|
91
|
+
return nested;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
async function sortedEntries(dir) {
|
|
97
|
+
return (await fs.readdir(dir, { withFileTypes: true }).catch(() => []))
|
|
98
|
+
.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
99
|
+
}
|
|
39
100
|
//# sourceMappingURL=repo-inventory.js.map
|
|
@@ -194,10 +194,11 @@ async function collectChangedScope(root, opts) {
|
|
|
194
194
|
async function listSourceFiles(root, dir = root, out = []) {
|
|
195
195
|
const entries = await fsp.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
196
196
|
for (const entry of entries) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
// Hidden runtime/worktree directories can contain complete repository copies.
|
|
198
|
+
// Only .agents is a source-bearing project directory; all other hidden trees
|
|
199
|
+
// are state, caches, or external workspaces and must stay outside this scan.
|
|
200
|
+
if (entry.name.startsWith('.') && entry.name !== '.agents')
|
|
201
|
+
continue;
|
|
201
202
|
const full = path.join(dir, entry.name);
|
|
202
203
|
if (entry.isDirectory()) {
|
|
203
204
|
if (!SKIP_DIRS.has(entry.name))
|