sneakoscope 2.0.4 → 2.0.6
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 +18 -11
- 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/.sks-build-stamp.json +4 -4
- package/dist/bin/sks.js +1 -1
- package/dist/build-manifest.json +78 -8
- package/dist/cli/install-helpers.js +23 -0
- package/dist/commands/codex-app.js +25 -3
- package/dist/commands/doctor.js +33 -4
- package/dist/commands/mad-sks.js +2 -2
- package/dist/core/agents/agent-orchestrator.js +22 -3
- package/dist/core/agents/agent-proof-evidence.js +59 -2
- package/dist/core/agents/agent-roster.js +35 -6
- package/dist/core/agents/agent-schema.js +1 -1
- package/dist/core/agents/agent-worker-pipeline.js +9 -1
- package/dist/core/agents/native-worker-backend-router.js +50 -10
- package/dist/core/agents/ollama-worker-config.js +164 -15
- package/dist/core/codex/codex-0-137-compat.js +119 -0
- package/dist/core/codex-app.js +124 -2
- package/dist/core/codex-control/codex-control-proof.js +4 -1
- package/dist/core/codex-control/codex-sdk-capability.js +1 -1
- package/dist/core/codex-control/codex-task-runner.js +329 -5
- package/dist/core/codex-control/python-codex-sdk-adapter.js +197 -0
- package/dist/core/codex-control/python-codex-sdk-event-translator.js +14 -0
- package/dist/core/commands/local-model-command.js +65 -19
- package/dist/core/commands/naruto-command.js +124 -8
- package/dist/core/commands/run-command.js +1 -1
- package/dist/core/doctor/doctor-readiness-matrix.js +21 -2
- package/dist/core/fsx.js +1 -1
- package/dist/core/hooks-runtime.js +2 -233
- package/dist/core/init.js +8 -8
- package/dist/core/local-llm/local-llm-backpressure.js +20 -0
- package/dist/core/local-llm/local-llm-capability.js +29 -0
- package/dist/core/local-llm/local-llm-client.js +100 -0
- package/dist/core/local-llm/local-llm-config.js +6 -1
- package/dist/core/local-llm/local-llm-context-cache.js +21 -0
- package/dist/core/local-llm/local-llm-control-adapter.js +101 -0
- package/dist/core/local-llm/local-llm-json-repair.js +52 -0
- package/dist/core/local-llm/local-llm-metrics.js +42 -0
- package/dist/core/local-llm/local-llm-ollama-client.js +67 -0
- package/dist/core/local-llm/local-llm-openai-compatible-client.js +30 -0
- package/dist/core/local-llm/local-llm-prompt-cache.js +12 -0
- package/dist/core/local-llm/local-llm-scheduler.js +29 -0
- package/dist/core/local-llm/local-llm-schema-enforcer.js +15 -0
- package/dist/core/local-llm/local-llm-smoke.js +83 -0
- package/dist/core/local-llm/local-llm-warmup.js +20 -0
- package/dist/core/local-llm/local-worker-eligibility.js +27 -0
- package/dist/core/naruto/hardware-capacity-probe.js +36 -0
- package/dist/core/naruto/naruto-active-pool.js +134 -0
- package/dist/core/naruto/naruto-backpressure.js +13 -0
- package/dist/core/naruto/naruto-concurrency-governor.js +65 -0
- package/dist/core/naruto/naruto-finalizer.js +18 -0
- package/dist/core/naruto/naruto-generation-scheduler.js +18 -0
- package/dist/core/naruto/naruto-gpt-final-pack.js +49 -0
- package/dist/core/naruto/naruto-parallel-patch-apply.js +95 -0
- package/dist/core/naruto/naruto-patch-transaction-batch.js +42 -0
- package/dist/core/naruto/naruto-role-policy.js +107 -0
- package/dist/core/naruto/naruto-verification-dag.js +42 -0
- package/dist/core/naruto/naruto-verification-pool.js +18 -0
- package/dist/core/naruto/naruto-work-graph.js +198 -0
- package/dist/core/naruto/naruto-work-item.js +40 -0
- package/dist/core/naruto/naruto-work-stealing.js +11 -0
- package/dist/core/naruto/resource-pressure-monitor.js +32 -0
- package/dist/core/pipeline/finalize-pipeline-result.js +58 -0
- package/dist/core/pipeline/gpt-final-required.js +12 -0
- package/dist/core/pipeline-internals/runtime-core.js +1 -1
- package/dist/core/ppt.js +31 -8
- package/dist/core/product-design-app-server.js +410 -0
- package/dist/core/product-design-plugin.js +139 -0
- package/dist/core/prompt/prompt-placeholder-guard.js +30 -0
- package/dist/core/router/capability-card.js +13 -0
- package/dist/core/router/route-cache.js +3 -0
- package/dist/core/router/ultra-router.js +2 -1
- package/dist/core/routes.js +12 -12
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-lane-runtime.js +2 -2
- package/dist/core/zellij/zellij-naruto-dashboard.js +36 -0
- package/dist/core/zellij/zellij-worker-pane-manager.js +4 -4
- package/dist/scripts/blackbox-command-import-smoke.js +10 -1
- package/dist/scripts/check-package-boundary.js +12 -3
- package/dist/scripts/codex-0-137-compat-check.js +27 -0
- package/dist/scripts/codex-environment-scoped-approvals-check.js +10 -0
- package/dist/scripts/codex-plugin-list-json-check.js +8 -0
- package/dist/scripts/codex-thread-runtime-choice-check.js +10 -0
- package/dist/scripts/local-collab-all-pipelines-final-gpt-check.js +21 -0
- package/dist/scripts/local-llm-all-pipelines-check.js +11 -0
- package/dist/scripts/local-llm-cache-performance-check.js +10 -0
- package/dist/scripts/local-llm-capability-check.js +14 -0
- package/dist/scripts/local-llm-smoke-check.js +23 -0
- package/dist/scripts/local-llm-structured-output-check.js +11 -0
- package/dist/scripts/local-llm-throughput-check.js +10 -0
- package/dist/scripts/local-llm-tool-call-repair-check.js +10 -0
- package/dist/scripts/local-llm-warmup-check.js +11 -0
- package/dist/scripts/naruto-active-pool-check.js +39 -0
- package/dist/scripts/naruto-concurrency-governor-check.js +52 -0
- package/dist/scripts/naruto-gpt-final-pack-check.js +34 -0
- package/dist/scripts/naruto-parallel-patch-apply-check.js +41 -0
- package/dist/scripts/naruto-readonly-routing-check.js +116 -0
- package/dist/scripts/naruto-real-local-gpt-final-smoke.js +16 -0
- package/dist/scripts/naruto-role-distribution-check.js +23 -0
- package/dist/scripts/naruto-shadow-clone-swarm-check.js +13 -0
- package/dist/scripts/naruto-verification-pool-check.js +36 -0
- package/dist/scripts/naruto-work-graph-check.js +24 -0
- package/dist/scripts/naruto-zellij-massive-ui-check.js +23 -0
- package/dist/scripts/product-design-auto-install-check.js +119 -0
- package/dist/scripts/product-design-plugin-routing-check.js +101 -0
- package/dist/scripts/prompt-placeholder-guard-check.js +33 -0
- package/dist/scripts/python-codex-sdk-all-pipelines-check.js +47 -0
- package/dist/scripts/python-codex-sdk-capability-check.js +75 -0
- package/dist/scripts/python-codex-sdk-sandbox-policy-check.js +10 -0
- package/dist/scripts/python-codex-sdk-stream-bridge-check.js +12 -0
- package/dist/scripts/release-parallel-check.js +16 -2
- package/dist/scripts/release-provenance-check.js +21 -0
- package/dist/scripts/release-real-check.js +5 -0
- package/dist/scripts/zellij-worker-pane-manager-check.js +1 -1
- package/package.json +36 -4
- package/schemas/local-llm/local-model-config.schema.json +74 -0
- package/schemas/naruto/naruto-concurrency-governor.schema.json +21 -0
- package/schemas/naruto/naruto-work-graph.schema.json +22 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './lib/codex-sdk-gate-lib.js';
|
|
4
|
+
const scheduler = await importDist('core/local-llm/local-llm-scheduler.js');
|
|
5
|
+
const plan = scheduler.planLocalLlmSchedule({ workItems: Array.from({ length: 20 }, (_, i) => ({ id: i })), maxParallelRequests: 4 });
|
|
6
|
+
assertGate(plan.ok === true, 'local scheduler must not exceed max parallel requests');
|
|
7
|
+
assertGate(plan.active_requests <= plan.max_parallel_requests, 'active requests exceeded max_parallel_requests');
|
|
8
|
+
assertGate(plan.queued_count === 16, '20 worker fixture should queue work beyond max parallel requests');
|
|
9
|
+
emitGate('local-llm:throughput', { active_requests: plan.active_requests, queued_count: plan.queued_count, backpressure: plan.backpressure });
|
|
10
|
+
//# sourceMappingURL=local-llm-throughput-check.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './lib/codex-sdk-gate-lib.js';
|
|
4
|
+
const mod = await importDist('core/local-llm/local-llm-json-repair.js');
|
|
5
|
+
const repaired = mod.parseOrRepairLocalLlmJson('Here is JSON: {"status":"ok","summary":"done"} thanks');
|
|
6
|
+
const failed = mod.parseOrRepairLocalLlmJson('not json at all');
|
|
7
|
+
assertGate(repaired.ok === true && repaired.repaired === true && repaired.attempts === 1, 'bounded JSON repair should recover one object');
|
|
8
|
+
assertGate(failed.ok === false && failed.attempts === 1, 'invalid local JSON must fail after one repair attempt');
|
|
9
|
+
emitGate('local-llm:tool-call-repair', { repaired: repaired.ok, failed: failed.ok });
|
|
10
|
+
//# sourceMappingURL=local-llm-tool-call-repair-check.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './lib/codex-sdk-gate-lib.js';
|
|
4
|
+
const cfg = await importDist('core/agents/ollama-worker-config.js');
|
|
5
|
+
const warmup = await importDist('core/local-llm/local-llm-warmup.js');
|
|
6
|
+
const state = warmup.buildLocalLlmWarmupState(cfg.normalizeLocalModelConfig({ enabled: true, status: 'enabled_unverified' }), { ok: true, ttlMs: 1000 });
|
|
7
|
+
assertGate(state.explicit_only === true, 'local warmup must be explicit only');
|
|
8
|
+
assertGate(state.postinstall_allowed === false, 'postinstall must not run local warmup');
|
|
9
|
+
assertGate(state.release_check_real_warmup_allowed === false, 'release:check must not run real warmup');
|
|
10
|
+
emitGate('local-llm:warmup', { explicit_only: state.explicit_only, expires_at: state.expires_at });
|
|
11
|
+
//# sourceMappingURL=local-llm-warmup-check.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const workGraph = await importDist('core/naruto/naruto-work-graph.js');
|
|
5
|
+
const governorMod = await importDist('core/naruto/naruto-concurrency-governor.js');
|
|
6
|
+
const activePool = await importDist('core/naruto/naruto-active-pool.js');
|
|
7
|
+
const graph = workGraph.buildNarutoWorkGraph({ requestedClones: 20, totalWorkItems: 20, writeCapable: true, maxActiveWorkers: 5 });
|
|
8
|
+
const governor = governorMod.decideNarutoConcurrency({
|
|
9
|
+
requestedClones: 20,
|
|
10
|
+
totalWorkItems: 20,
|
|
11
|
+
pendingWorkQueueSize: 20,
|
|
12
|
+
backend: 'fake',
|
|
13
|
+
hardware: { remoteApiRateLimitBudget: 5, fileDescriptorLimit: 4096, freeMemoryBytes: 8 * 1024 * 1024 * 1024, totalMemoryBytes: 16 * 1024 * 1024 * 1024 }
|
|
14
|
+
});
|
|
15
|
+
const report = activePool.simulateNarutoActivePool({ graph, governor: { ...governor, safe_active_workers: 5 } });
|
|
16
|
+
assertGate(report.ok === true, 'active pool must drain cleanly', report);
|
|
17
|
+
assertGate(report.max_observed_active_workers <= 5, 'active pool must never exceed safe cap', report);
|
|
18
|
+
assertGate(report.max_observed_write_lease_conflicts === 0, 'active pool must never run overlapping write leases concurrently', report);
|
|
19
|
+
assertGate(report.completed_count >= graph.total_work_items, 'active pool must complete all base work items', report);
|
|
20
|
+
assertGate(report.refill_events >= 5, 'active pool must refill slots as work drains', report);
|
|
21
|
+
assertGate(report.duplicate_execution_count === 0, 'active pool must not duplicate work without retry', report);
|
|
22
|
+
const sameLeaseGraph = workGraph.buildNarutoWorkGraph({
|
|
23
|
+
requestedClones: 10,
|
|
24
|
+
totalWorkItems: 10,
|
|
25
|
+
writeCapable: true,
|
|
26
|
+
targetPaths: ['src/shared-fixture.ts'],
|
|
27
|
+
maxActiveWorkers: 5
|
|
28
|
+
});
|
|
29
|
+
const sameLeaseReport = activePool.simulateNarutoActivePool({ graph: sameLeaseGraph, governor: { ...governor, safe_active_workers: 5 } });
|
|
30
|
+
assertGate(sameLeaseReport.ok === true, 'same-file work graph must drain without overlapping write leases', sameLeaseReport);
|
|
31
|
+
assertGate(sameLeaseReport.max_observed_write_lease_conflicts === 0, 'same-file write items must be serialized or interleaved with read-only work only', sameLeaseReport);
|
|
32
|
+
emitGate('naruto:active-pool', {
|
|
33
|
+
safe_active_workers: report.safe_active_workers,
|
|
34
|
+
completed_count: report.completed_count,
|
|
35
|
+
refill_events: report.refill_events,
|
|
36
|
+
max_observed_active_workers: report.max_observed_active_workers,
|
|
37
|
+
same_lease_max_write_conflicts: sameLeaseReport.max_observed_write_lease_conflicts
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=naruto-active-pool-check.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const governorMod = await importDist('core/naruto/naruto-concurrency-governor.js');
|
|
5
|
+
const normal = governorMod.decideNarutoConcurrency({
|
|
6
|
+
requestedClones: 200,
|
|
7
|
+
totalWorkItems: 340,
|
|
8
|
+
pendingWorkQueueSize: 340,
|
|
9
|
+
backend: 'codex-sdk',
|
|
10
|
+
zellijVisiblePaneCap: 12,
|
|
11
|
+
hardware: {
|
|
12
|
+
cores: 32,
|
|
13
|
+
freeMemoryBytes: 48 * 1024 * 1024 * 1024,
|
|
14
|
+
totalMemoryBytes: 64 * 1024 * 1024 * 1024,
|
|
15
|
+
fileDescriptorLimit: 4096,
|
|
16
|
+
localLlmMaxParallelRequests: 4,
|
|
17
|
+
remoteApiRateLimitBudget: 32,
|
|
18
|
+
terminalRows: 40,
|
|
19
|
+
terminalColumns: 140
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const pressure = governorMod.decideNarutoConcurrency({
|
|
23
|
+
requestedClones: 200,
|
|
24
|
+
totalWorkItems: 340,
|
|
25
|
+
pendingWorkQueueSize: 340,
|
|
26
|
+
backend: 'codex-sdk',
|
|
27
|
+
zellijVisiblePaneCap: 12,
|
|
28
|
+
hardware: {
|
|
29
|
+
cores: 8,
|
|
30
|
+
loadAverage: [16, 16, 16],
|
|
31
|
+
freeMemoryBytes: 256 * 1024 * 1024,
|
|
32
|
+
totalMemoryBytes: 4 * 1024 * 1024 * 1024,
|
|
33
|
+
fileDescriptorLimit: 128,
|
|
34
|
+
localLlmMaxParallelRequests: 4,
|
|
35
|
+
remoteApiRateLimitBudget: 32,
|
|
36
|
+
zellijPaneCount: 12,
|
|
37
|
+
diskIoPressure: 0.9
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
assertGate(normal.safe_active_workers <= 32, 'requested_clones=200 fixture must cap active workers safely', { normal });
|
|
41
|
+
assertGate(normal.safe_zellij_visible_panes === 12 && normal.headless_workers === normal.safe_active_workers - 12, 'zellij visible panes must stay within UI cap', { normal });
|
|
42
|
+
assertGate(normal.local_llm_parallel <= 4, 'local LLM active requests must respect max_parallel_requests=4', { normal });
|
|
43
|
+
assertGate(pressure.safe_active_workers < normal.safe_active_workers, 'memory/load pressure fixture must decrease active workers', { normal: normal.safe_active_workers, pressure: pressure.safe_active_workers });
|
|
44
|
+
assertGate(pressure.backpressure === 'saturated' || pressure.backpressure === 'throttled', 'pressure fixture must report backpressure', { pressure });
|
|
45
|
+
emitGate('naruto:concurrency-governor', {
|
|
46
|
+
requested_clones: normal.requested_clones,
|
|
47
|
+
total_work_items: normal.total_work_items,
|
|
48
|
+
safe_active_workers: normal.safe_active_workers,
|
|
49
|
+
safe_zellij_visible_panes: normal.safe_zellij_visible_panes,
|
|
50
|
+
pressure_safe_active_workers: pressure.safe_active_workers
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=naruto-concurrency-governor-check.js.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const workGraph = await importDist('core/naruto/naruto-work-graph.js');
|
|
5
|
+
const roles = await importDist('core/naruto/naruto-role-policy.js');
|
|
6
|
+
const packMod = await importDist('core/naruto/naruto-gpt-final-pack.js');
|
|
7
|
+
const graph = workGraph.buildNarutoWorkGraph({ requestedClones: 100, totalWorkItems: 120, writeCapable: true });
|
|
8
|
+
const roleDistribution = roles.buildNarutoRoleDistribution(graph.work_items);
|
|
9
|
+
const patchEnvelopes = Array.from({ length: 120 }, (_, index) => ({ id: index, token: 'sk-testsecret1234567890', file: `f-${index}.ts` }));
|
|
10
|
+
const logs = Array.from({ length: 40 }, (_, index) => `log ${index} api_key=secret-${index}`);
|
|
11
|
+
const pack = packMod.buildNarutoGptFinalPack({
|
|
12
|
+
missionId: 'M-naruto-pack',
|
|
13
|
+
graph,
|
|
14
|
+
roleDistribution,
|
|
15
|
+
changedFiles: ['src/a.ts', 'src/a.ts', 'src/b.ts'],
|
|
16
|
+
patchEnvelopes,
|
|
17
|
+
verificationResults: [{ ok: true }],
|
|
18
|
+
failedShards: [{ id: 'failed-1' }],
|
|
19
|
+
conflictMap: [{ path: 'src/a.ts' }],
|
|
20
|
+
rollbackPlan: { token: 'sk-abc12345678901234567' },
|
|
21
|
+
logs
|
|
22
|
+
});
|
|
23
|
+
const serialized = JSON.stringify(pack);
|
|
24
|
+
assertGate(pack.bounded === true && pack.secrets_redacted === true, 'GPT final pack must be bounded and redacted', pack);
|
|
25
|
+
assertGate(pack.patch_envelopes.length === 100, '100 worker results must compress to bounded patch envelope count', { count: pack.patch_envelopes.length });
|
|
26
|
+
assertGate(pack.representative_logs.length === 12, 'representative logs must be bounded', { count: pack.representative_logs.length });
|
|
27
|
+
assertGate(!serialized.includes('secret-') && !serialized.includes('sk-testsecret'), 'secrets must be redacted from final pack', pack);
|
|
28
|
+
assertGate(pack.role_distribution.ok === true && pack.work_graph_summary.write_allowed_count > 0, 'final pack must include role distribution and write work summary', pack);
|
|
29
|
+
emitGate('naruto:gpt-final-pack', {
|
|
30
|
+
patch_envelopes: pack.patch_envelopes.length,
|
|
31
|
+
representative_logs: pack.representative_logs.length,
|
|
32
|
+
changed_files: pack.changed_files
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=naruto-gpt-final-pack-check.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
const patchApply = await importDist('core/naruto/naruto-parallel-patch-apply.js');
|
|
8
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-naruto-patch-'));
|
|
9
|
+
const envelopes = Array.from({ length: 10 }, (_, index) => {
|
|
10
|
+
const file = `file-${index}.txt`;
|
|
11
|
+
return envelope(index + 1, file, `after-${index}`);
|
|
12
|
+
});
|
|
13
|
+
const result = await patchApply.applyNarutoPatchEnvelopes(root, envelopes, { dryRun: false });
|
|
14
|
+
assertGate(result.ok === true, 'non-overlapping patch fixture must apply', result);
|
|
15
|
+
assertGate(result.batch_count === 1 && result.parallel_apply_count === 1, 'non-overlapping patch fixture must group into a parallel batch', result);
|
|
16
|
+
assertGate(result.results.every((row) => row.changed_files.length === 1 && Object.keys(row.before_hashes).length === 1 && Object.keys(row.after_hashes).length === 1), 'patch results must include before/after hashes and changed files', result);
|
|
17
|
+
const rollback = await patchApply.rollbackNarutoPatchResult(root, result.results[0]);
|
|
18
|
+
assertGate(rollback.ok === true && rollback.restored.length === 1, 'rollback must restore before content for a patch result', rollback);
|
|
19
|
+
const conflict = await patchApply.applyNarutoPatchEnvelopes(root, [envelope(99, 'same.txt', 'a'), envelope(100, 'same.txt', 'b')], { dryRun: true });
|
|
20
|
+
assertGate(conflict.conflicts.length >= 1, 'overlapping patch fixture must serialize or mark conflict', conflict);
|
|
21
|
+
emitGate('naruto:parallel-patch-apply', {
|
|
22
|
+
batch_count: result.batch_count,
|
|
23
|
+
parallel_apply_count: result.parallel_apply_count,
|
|
24
|
+
conflict_count: conflict.conflicts.length,
|
|
25
|
+
rollback_restored: rollback.restored.length
|
|
26
|
+
});
|
|
27
|
+
function envelope(index, file, content) {
|
|
28
|
+
return {
|
|
29
|
+
schema: 'sks.agent-patch-envelope.v1',
|
|
30
|
+
source: 'fixture',
|
|
31
|
+
agent_id: `naruto-${index}`,
|
|
32
|
+
session_id: `session-${index}`,
|
|
33
|
+
slot_id: `slot-${index}`,
|
|
34
|
+
generation_index: 1,
|
|
35
|
+
task_slice_id: `NW-${index}`,
|
|
36
|
+
lease_id: `lease-${index}`,
|
|
37
|
+
allowed_paths: [file],
|
|
38
|
+
operations: [{ op: 'write', path: file, content }]
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=naruto-parallel-patch-apply-check.js.map
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { assertGate, emitGate, exists, importDist, root } from './sks-1-18-gate-lib.js';
|
|
7
|
+
const worker = await importDist('core/agents/agent-worker-pipeline.js');
|
|
8
|
+
const cli = path.join(root, 'dist', 'bin', 'sks.js');
|
|
9
|
+
assertGate(exists('dist/bin/sks.js'), 'dist/bin/sks.js missing (build first)');
|
|
10
|
+
const readOnlyWorker = worker.validateAgentWorkerResult({
|
|
11
|
+
mission_id: 'M-readonly-routing',
|
|
12
|
+
agent_id: 'readonly-agent',
|
|
13
|
+
session_id: 'readonly-session',
|
|
14
|
+
persona_id: 'verifier',
|
|
15
|
+
task_slice_id: 'readonly-slice',
|
|
16
|
+
status: 'done',
|
|
17
|
+
backend: 'codex-sdk',
|
|
18
|
+
summary: 'Read-only worker inspected files without proposing a patch.',
|
|
19
|
+
findings: ['read-only inspection completed'],
|
|
20
|
+
proposed_changes: [],
|
|
21
|
+
changed_files: ['src/core/agents/agent-proof-evidence.ts'],
|
|
22
|
+
lease_compliance: { ok: true, violations: [] },
|
|
23
|
+
artifacts: [],
|
|
24
|
+
blockers: [],
|
|
25
|
+
confidence: 'fixture',
|
|
26
|
+
handoff_notes: '',
|
|
27
|
+
unverified: [],
|
|
28
|
+
writes: [],
|
|
29
|
+
no_patch_reason: {
|
|
30
|
+
ok: true,
|
|
31
|
+
reason: 'read_only_or_no_write_paths',
|
|
32
|
+
read_only_or_noop_evidence: true
|
|
33
|
+
},
|
|
34
|
+
verification: { status: 'passed', checks: ['readonly-no-patch-routing'] }
|
|
35
|
+
});
|
|
36
|
+
assertGate(readOnlyWorker.status === 'done' && !readOnlyWorker.blockers.includes('no_patch_generated'), 'read-only/no-write worker changed_files must not require patch envelopes', readOnlyWorker);
|
|
37
|
+
const writeWorker = worker.validateAgentWorkerResult({
|
|
38
|
+
...readOnlyWorker,
|
|
39
|
+
agent_id: 'write-agent',
|
|
40
|
+
session_id: 'write-session',
|
|
41
|
+
task_slice_id: 'write-slice',
|
|
42
|
+
changed_files: ['src/core/agents/agent-proof-evidence.ts'],
|
|
43
|
+
no_patch_reason: undefined
|
|
44
|
+
});
|
|
45
|
+
assertGate(writeWorker.status === 'blocked' && writeWorker.blockers.includes('no_patch_generated'), 'write-capable changed_files without patch envelope must still block', writeWorker);
|
|
46
|
+
const readonlyRun = spawnSync(process.execPath, [
|
|
47
|
+
cli,
|
|
48
|
+
'naruto',
|
|
49
|
+
'run',
|
|
50
|
+
'readonly routing must inspect `src/core/agents/agent-proof-evidence.ts` and `package.json` without writes',
|
|
51
|
+
'--clones',
|
|
52
|
+
'4',
|
|
53
|
+
'--work-items',
|
|
54
|
+
'4',
|
|
55
|
+
'--backend',
|
|
56
|
+
'fake',
|
|
57
|
+
'--readonly',
|
|
58
|
+
'--json'
|
|
59
|
+
], { cwd: root, encoding: 'utf8', timeout: 120000, maxBuffer: 6 * 1024 * 1024 });
|
|
60
|
+
const readonlyJson = parseJson(readonlyRun.stdout);
|
|
61
|
+
assertGate(readonlyRun.status === 0 && readonlyJson?.ok === true, 'readonly Naruto fake blackbox must exit ok', { status: readonlyRun.status, stdout: tail(readonlyRun.stdout), stderr: tail(readonlyRun.stderr) });
|
|
62
|
+
assertGate(readonlyJson.proof === 'passed', 'readonly Naruto proof must pass', { proof: readonlyJson.proof, blockers: readonlyJson.run?.proof?.blockers });
|
|
63
|
+
assertGate(readonlyJson.work_graph?.write_allowed_count === 0, 'readonly Naruto work graph must have zero write-allowed items', readonlyJson.work_graph);
|
|
64
|
+
assertGate(Number(readonlyJson.role_distribution?.implementation_like_workers || 0) === 0, 'readonly Naruto role distribution must have zero implementation-like workers', readonlyJson.role_distribution);
|
|
65
|
+
assertGate((readonlyJson.role_distribution?.entries || []).every((entry) => entry.write_allowed === false), 'readonly Naruto role distribution must deny writes for every role', readonlyJson.role_distribution);
|
|
66
|
+
const readonlyRoot = path.join(root, '.sneakoscope', 'missions', readonlyJson.mission_id, 'agents');
|
|
67
|
+
const readonlyProof = readJson(path.join(readonlyRoot, 'agent-proof-evidence.json'));
|
|
68
|
+
const readonlyStrategy = readJson(path.join(readonlyRoot, 'user-request-strategy.json'));
|
|
69
|
+
const readonlyPolicy = readJson(path.join(readonlyRoot, 'agent-parallel-write-policy.json'));
|
|
70
|
+
assertGate(readonlyPolicy.write_mode === 'off' && readonlyPolicy.readonly === true, 'readonly run must force native write policy off', readonlyPolicy);
|
|
71
|
+
assertGate(readonlyStrategy.gate?.write_task_count === 0, 'readonly strategy must not infer write targets from file mentions', readonlyStrategy.gate);
|
|
72
|
+
assertGate(readonlyProof.changed_files_lease_checked === false, 'readonly no-write proof must skip changed_files write-lease checks', readonlyProof);
|
|
73
|
+
assertGate(!(readonlyProof.blockers || []).some((blocker) => /no_patch_generated|lease_changed_file_violation/.test(String(blocker))), 'readonly proof must not contain patch/lease write blockers', readonlyProof.blockers || []);
|
|
74
|
+
const writeRun = spawnSync(process.execPath, [
|
|
75
|
+
cli,
|
|
76
|
+
'naruto',
|
|
77
|
+
'run',
|
|
78
|
+
'write-capable routing must patch `README.md` through leased envelopes',
|
|
79
|
+
'--clones',
|
|
80
|
+
'3',
|
|
81
|
+
'--work-items',
|
|
82
|
+
'3',
|
|
83
|
+
'--backend',
|
|
84
|
+
'fake',
|
|
85
|
+
'--parallel-write',
|
|
86
|
+
'--json'
|
|
87
|
+
], { cwd: root, encoding: 'utf8', timeout: 120000, maxBuffer: 6 * 1024 * 1024 });
|
|
88
|
+
const writeJson = parseJson(writeRun.stdout);
|
|
89
|
+
assertGate(writeRun.status === 0 && writeJson?.ok === true, 'write-capable Naruto fake blackbox must exit ok', { status: writeRun.status, stdout: tail(writeRun.stdout), stderr: tail(writeRun.stderr) });
|
|
90
|
+
const writeRoot = path.join(root, '.sneakoscope', 'missions', writeJson.mission_id, 'agents');
|
|
91
|
+
const writeStrategy = readJson(path.join(writeRoot, 'user-request-strategy.json'));
|
|
92
|
+
const writePolicy = readJson(path.join(writeRoot, 'agent-parallel-write-policy.json'));
|
|
93
|
+
assertGate(writePolicy.write_mode === 'parallel' && writePolicy.readonly === false, 'write-capable Naruto run must carry parallel write policy', writePolicy);
|
|
94
|
+
assertGate(writeStrategy.gate?.write_task_count >= 1, 'write-capable strategy must retain explicit write target inference', writeStrategy.gate);
|
|
95
|
+
emitGate('naruto:readonly-routing', {
|
|
96
|
+
readonly_mission_id: readonlyJson.mission_id,
|
|
97
|
+
write_mission_id: writeJson.mission_id,
|
|
98
|
+
readonly_write_tasks: readonlyStrategy.gate?.write_task_count,
|
|
99
|
+
write_write_tasks: writeStrategy.gate?.write_task_count
|
|
100
|
+
});
|
|
101
|
+
function readJson(file) {
|
|
102
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
103
|
+
}
|
|
104
|
+
function parseJson(text) {
|
|
105
|
+
try {
|
|
106
|
+
return JSON.parse(text);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function tail(value, limit = 2000) {
|
|
113
|
+
const text = String(value || '');
|
|
114
|
+
return text.length <= limit ? text : text.slice(-limit);
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=naruto-readonly-routing-check.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const finalizer = await importDist('core/naruto/naruto-finalizer.js');
|
|
5
|
+
const draft = finalizer.evaluateNarutoFinalizer({ localParticipated: true, gptFinalStatus: null, applyPatches: true });
|
|
6
|
+
const approved = finalizer.evaluateNarutoFinalizer({ localParticipated: true, gptFinalStatus: 'approved', applyPatches: true });
|
|
7
|
+
const deterministic = finalizer.evaluateNarutoFinalizer({ localParticipated: false, applyPatches: true });
|
|
8
|
+
assertGate(draft.ok === false && draft.blockers.includes('naruto_local_worker_output_needs_gpt_final_arbiter'), 'local worker patch must be blocked until GPT final arbiter', draft);
|
|
9
|
+
assertGate(approved.ok === true && approved.final_patch_source === 'gpt_final_arbiter', 'GPT-approved local output must become final patch source', approved);
|
|
10
|
+
assertGate(deterministic.ok === true && deterministic.gpt_final_required === false, 'no-local deterministic run must not require GPT final', deterministic);
|
|
11
|
+
emitGate('naruto:real-local-gpt-final-smoke', {
|
|
12
|
+
require_real_env: process.env.SKS_REQUIRE_LOCAL_LLM === '1' || process.env.SKS_REQUIRE_GPT_FINAL === '1',
|
|
13
|
+
draft_status: draft.final_status,
|
|
14
|
+
approved_status: approved.final_status
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=naruto-real-local-gpt-final-smoke.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const workGraph = await importDist('core/naruto/naruto-work-graph.js');
|
|
5
|
+
const roles = await importDist('core/naruto/naruto-role-policy.js');
|
|
6
|
+
const roster = await importDist('core/agents/agent-roster.js');
|
|
7
|
+
const graph = workGraph.buildNarutoWorkGraph({ requestedClones: 30, totalWorkItems: 30, writeCapable: true });
|
|
8
|
+
const distribution = roles.buildNarutoRoleDistribution(graph.work_items);
|
|
9
|
+
const cloneRoster = roster.buildNarutoCloneRoster({ clones: 30, prompt: 'implement, modify, test, verify, document, and resolve conflicts' });
|
|
10
|
+
const writeCapableRoster = cloneRoster.roster.filter((row) => row.write_allowed === true);
|
|
11
|
+
assertGate(distribution.ok === true, 'write-capable Naruto role distribution must pass', distribution);
|
|
12
|
+
assertGate(distribution.verifier_only === false, 'default Naruto must not be verifier-only', distribution);
|
|
13
|
+
assertGate(distribution.implementation_like_ratio >= 0.4, 'default Naruto must keep at least 40% implementation/modification/test roles', distribution);
|
|
14
|
+
assertGate(writeCapableRoster.length >= Math.floor(cloneRoster.roster.length * 0.4), 'Naruto roster must include write-capable clone roles by default', { writeCapableRoster: writeCapableRoster.length, total: cloneRoster.roster.length });
|
|
15
|
+
const readonlyGraph = workGraph.buildNarutoWorkGraph({ requestedClones: 8, readonly: true, writeCapable: false });
|
|
16
|
+
const readonlyDistribution = roles.buildNarutoRoleDistribution(readonlyGraph.work_items, { readonly: true });
|
|
17
|
+
assertGate(readonlyDistribution.ok === true, 'readonly Naruto route may use read-only verifier/research roles', readonlyDistribution);
|
|
18
|
+
emitGate('naruto:role-distribution', {
|
|
19
|
+
implementation_like_ratio: distribution.implementation_like_ratio,
|
|
20
|
+
entries: distribution.entries,
|
|
21
|
+
write_capable_roster_count: writeCapableRoster.length
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=naruto-role-distribution-check.js.map
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// changing it for any other route, and that an end-to-end `sks naruto run` actually
|
|
6
6
|
// schedules >20 concurrent clone sessions to completion with proof.
|
|
7
7
|
import { spawnSync } from 'node:child_process';
|
|
8
|
+
import fs from 'node:fs';
|
|
8
9
|
import path from 'node:path';
|
|
9
10
|
import { assertGate, emitGate, importDist, root, exists } from './sks-1-18-gate-lib.js';
|
|
10
11
|
const schema = await importDist('core/agents/agent-schema.js');
|
|
@@ -71,6 +72,9 @@ assertGate(bigMemoryHost.cap >= 64, 'a 64 GB host must allow >= 64 parallel code
|
|
|
71
72
|
const proofClones = 24;
|
|
72
73
|
const cli = path.join(root, 'dist', 'bin', 'sks.js');
|
|
73
74
|
assertGate(exists('dist/bin/sks.js'), 'dist/bin/sks.js missing (build first)');
|
|
75
|
+
const helpRun = spawnSync(process.execPath, [cli, 'naruto', '--help', '--json'], { cwd: root, encoding: 'utf8', timeout: 30000, maxBuffer: 1024 * 1024 });
|
|
76
|
+
const helpParsed = parseJson(helpRun.stdout);
|
|
77
|
+
assertGate(helpRun.status === 0 && helpParsed?.action === 'help', 'sks naruto --help must emit help instead of launching a run', { status: helpRun.status, stdout: tail(helpRun.stdout), stderr: tail(helpRun.stderr) });
|
|
74
78
|
const run = spawnSync(process.execPath, [
|
|
75
79
|
cli, 'naruto', 'run', 'shadow clone swarm gate proof',
|
|
76
80
|
'--clones', String(proofClones),
|
|
@@ -94,6 +98,15 @@ assertGate(parsed.target_active_slots <= fakeSafe.cap, 'active slots must be thr
|
|
|
94
98
|
assertGate(typeof parsed.concurrency_capped === 'boolean', 'naruto run must report concurrency_capped', { concurrency_capped: parsed.concurrency_capped });
|
|
95
99
|
assertGate(parsed.concurrency_capped === (parsed.clones > parsed.target_active_slots), 'concurrency_capped must reflect clones > live slots', { clones: parsed.clones, target_active_slots: parsed.target_active_slots, concurrency_capped: parsed.concurrency_capped });
|
|
96
100
|
assertGate(parsed.system && Number(parsed.system.safe_concurrency) >= 1, 'naruto run must report system safe_concurrency (host-derived cap)', { system: parsed.system });
|
|
101
|
+
assertGate(parsed.work_graph?.write_allowed_count > 0 && parsed.work_graph?.mixed_work_kinds?.length > 1, 'naruto run must report a mixed work graph with write-capable items', { work_graph: parsed.work_graph });
|
|
102
|
+
assertGate(Number(parsed.work_graph?.parallel_write_wave_count || 0) > 0, 'naruto run must expose at least one parallel write-capable wave with non-overlapping leases', { work_graph: parsed.work_graph });
|
|
103
|
+
assertGate(parsed.role_distribution?.verifier_only === false, 'naruto run proof/status must distinguish active worker roles beyond verifier-only', { role_distribution: parsed.role_distribution });
|
|
104
|
+
assertGate(Number(parsed.role_distribution?.implementation_like_ratio || 0) >= 0.4, 'naruto run must include implementation-like role distribution', { role_distribution: parsed.role_distribution });
|
|
105
|
+
const commandGraphPath = path.join(root, '.sneakoscope', 'missions', parsed.mission_id, 'agents', 'naruto-work-graph.json');
|
|
106
|
+
const commandGraph = JSON.parse(fs.readFileSync(commandGraphPath, 'utf8'));
|
|
107
|
+
const writePaths = commandGraph.work_items.filter((row) => row.write_allowed).flatMap((row) => row.write_paths);
|
|
108
|
+
assertGate(new Set(writePaths).size > 1, 'naruto command default patch-envelope leases must be per work item, not one shared write path', { sample: writePaths.slice(0, 8), unique: new Set(writePaths).size });
|
|
109
|
+
assertGate(commandGraph.active_waves.some((wave) => wave.write_paths.length > 1), 'naruto command graph must contain a parallel write wave when route-local patch envelopes do not overlap', { waves: commandGraph.active_waves.slice(0, 3) });
|
|
97
110
|
const state = parsed.run?.scheduler?.state || parsed.run?.scheduler || {};
|
|
98
111
|
assertGate(Number(state.completed_count) === proofClones, 'all clone work items must complete despite throttling', { completed_count: state.completed_count });
|
|
99
112
|
const explicitConcurrency = spawnSync(process.execPath, [cli, 'naruto', 'run', 'explicit concurrency', '--clones', '6', '--backend', 'fake', '--work-items', '6', '--concurrency', '6', '--json'], { cwd: root, encoding: 'utf8', timeout: 120000, maxBuffer: 4 * 1024 * 1024 });
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist, root } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const workGraph = await importDist('core/naruto/naruto-work-graph.js');
|
|
5
|
+
const governorMod = await importDist('core/naruto/naruto-concurrency-governor.js');
|
|
6
|
+
const verificationDag = await importDist('core/naruto/naruto-verification-dag.js');
|
|
7
|
+
const verificationPool = await importDist('core/naruto/naruto-verification-pool.js');
|
|
8
|
+
const graph = workGraph.buildNarutoWorkGraph({ requestedClones: 8, totalWorkItems: 12, writeCapable: true });
|
|
9
|
+
const governor = governorMod.decideNarutoConcurrency({
|
|
10
|
+
requestedClones: 8,
|
|
11
|
+
totalWorkItems: 12,
|
|
12
|
+
backend: 'fake',
|
|
13
|
+
hardware: {
|
|
14
|
+
cores: 4,
|
|
15
|
+
loadAverage: [0, 0, 0],
|
|
16
|
+
remoteApiRateLimitBudget: 8,
|
|
17
|
+
fileDescriptorLimit: 4096,
|
|
18
|
+
processCount: 1,
|
|
19
|
+
zellijPaneCount: 0,
|
|
20
|
+
diskIoPressure: 0,
|
|
21
|
+
freeMemoryBytes: 8 * 1024 * 1024 * 1024,
|
|
22
|
+
totalMemoryBytes: 16 * 1024 * 1024 * 1024
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const dag = verificationDag.buildNarutoVerificationDag(graph, { cwd: root, command: 'node -e "process.exit(0)"' });
|
|
26
|
+
const report = await verificationPool.runNarutoVerificationPool(dag, { ...governor, verification_parallel: 4 }, { cwd: root });
|
|
27
|
+
assertGate(report.ok === true, 'verification pool must pass all fixture shards', report);
|
|
28
|
+
assertGate(report.safe_concurrency === 4, 'verification pool must use its own safe concurrency', report);
|
|
29
|
+
assertGate(report.task_count > 1, 'verification pool must run multiple shards', report);
|
|
30
|
+
assertGate(report.cpu_heavy_cap_respected && report.io_heavy_cap_respected && report.api_rate_cap_respected, 'verification pool must respect resource caps', report);
|
|
31
|
+
emitGate('naruto:verification-pool', {
|
|
32
|
+
task_count: report.task_count,
|
|
33
|
+
safe_concurrency: report.safe_concurrency,
|
|
34
|
+
passed: report.passed
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=naruto-verification-pool-check.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const workGraph = await importDist('core/naruto/naruto-work-graph.js');
|
|
5
|
+
const graph = workGraph.buildNarutoWorkGraph({
|
|
6
|
+
requestedClones: 24,
|
|
7
|
+
totalWorkItems: 30,
|
|
8
|
+
writeCapable: true,
|
|
9
|
+
targetPaths: Array.from({ length: 30 }, (_, index) => `src/fixture-${index}.ts`),
|
|
10
|
+
maxActiveWorkers: 8
|
|
11
|
+
});
|
|
12
|
+
const validation = workGraph.validateNarutoWorkGraph(graph);
|
|
13
|
+
assertGate(graph.ok === true && validation.ok === true, 'Naruto work graph must validate', { graph_blockers: graph.blockers, validation });
|
|
14
|
+
assertGate(graph.total_work_items >= graph.requested_clones, 'work graph must create at least requested clone count', { total: graph.total_work_items, requested: graph.requested_clones });
|
|
15
|
+
assertGate(graph.mixed_work_kinds.length > 4, 'work graph must contain mixed work kinds, not only verification', { kinds: graph.mixed_work_kinds });
|
|
16
|
+
assertGate(graph.write_allowed_count > 0, 'write-capable Naruto graph must include write_allowed work items', { write_allowed_count: graph.write_allowed_count });
|
|
17
|
+
assertGate(graph.active_waves.every((wave) => wave.conflict_count === 0), 'active waves must not overlap write leases', { waves: graph.active_waves });
|
|
18
|
+
emitGate('naruto:work-graph', {
|
|
19
|
+
total_work_items: graph.total_work_items,
|
|
20
|
+
mixed_work_kinds: graph.mixed_work_kinds,
|
|
21
|
+
write_allowed_count: graph.write_allowed_count,
|
|
22
|
+
wave_count: graph.active_waves.length
|
|
23
|
+
});
|
|
24
|
+
//# sourceMappingURL=naruto-work-graph-check.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const dashboardMod = await importDist('core/zellij/zellij-naruto-dashboard.js');
|
|
5
|
+
const plan = dashboardMod.planNarutoZellijDashboard({
|
|
6
|
+
targetActiveWorkers: 32,
|
|
7
|
+
visiblePaneCap: 12,
|
|
8
|
+
completed: 8,
|
|
9
|
+
failed: 1,
|
|
10
|
+
backpressure: 'normal',
|
|
11
|
+
roles: ['implementer', 'modifier', 'test_writer', 'verifier'],
|
|
12
|
+
backend: 'codex-sdk'
|
|
13
|
+
});
|
|
14
|
+
assertGate(plan.ok === true, 'Naruto Zellij dashboard plan must pass', plan);
|
|
15
|
+
assertGate(plan.visible_worker_panes === 12, 'targetActiveWorkers=32 and visiblePaneCap=12 must create 12 visible panes', plan);
|
|
16
|
+
assertGate(plan.headless_workers === 20, 'remaining active workers must be listed as headless', plan);
|
|
17
|
+
assertGate(plan.pane_titles.every((title) => /slot-\d+\/gen-1 · .+ · codex-sdk · active/.test(title)), 'pane titles must include slot/gen/role/backend/status', plan);
|
|
18
|
+
emitGate('naruto:zellij-massive-ui', {
|
|
19
|
+
visible_worker_panes: plan.visible_worker_panes,
|
|
20
|
+
headless_workers: plan.headless_workers,
|
|
21
|
+
dashboard: plan.dashboard
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=naruto-zellij-massive-ui-check.js.map
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { ensureProductDesignPluginInstalledWithRequest, findProductDesignPluginSummaryFromMarketplaces, productDesignAutoInstallRequested } from '../core/product-design-app-server.js';
|
|
4
|
+
import { PRODUCT_DESIGN_PLUGIN, PRODUCT_DESIGN_REQUIRED_SKILLS } from '../core/product-design-plugin.js';
|
|
5
|
+
import { assertGate, emitGate, readText } from './lib/codex-sdk-gate-lib.js';
|
|
6
|
+
function pluginReadResponse({ installed, enabled }) {
|
|
7
|
+
return {
|
|
8
|
+
plugin: {
|
|
9
|
+
marketplaceName: PRODUCT_DESIGN_PLUGIN.marketplace,
|
|
10
|
+
marketplacePath: null,
|
|
11
|
+
summary: {
|
|
12
|
+
id: PRODUCT_DESIGN_PLUGIN.id,
|
|
13
|
+
remotePluginId: PRODUCT_DESIGN_PLUGIN.remote_plugin_id,
|
|
14
|
+
name: PRODUCT_DESIGN_PLUGIN.name,
|
|
15
|
+
installed,
|
|
16
|
+
enabled,
|
|
17
|
+
interface: {
|
|
18
|
+
displayName: PRODUCT_DESIGN_PLUGIN.display_name
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
skills: PRODUCT_DESIGN_REQUIRED_SKILLS.map((name) => ({ name, enabled: true }))
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
let installed = false;
|
|
26
|
+
const installCalls = [];
|
|
27
|
+
const installResult = await ensureProductDesignPluginInstalledWithRequest(async (method, params) => {
|
|
28
|
+
installCalls.push({ method, params });
|
|
29
|
+
if (method === 'plugin/read')
|
|
30
|
+
return pluginReadResponse({ installed, enabled: installed });
|
|
31
|
+
if (method === 'plugin/install') {
|
|
32
|
+
assertGate(params.pluginName === PRODUCT_DESIGN_PLUGIN.remote_plugin_id, 'plugin/install must use Product Design remote plugin id', params);
|
|
33
|
+
installed = true;
|
|
34
|
+
return { authPolicy: 'ON_USE', appsNeedingAuth: [] };
|
|
35
|
+
}
|
|
36
|
+
if (method === 'plugin/installed')
|
|
37
|
+
return { marketplaces: [], marketplaceLoadErrors: [] };
|
|
38
|
+
throw new Error(`unexpected method: ${method}`);
|
|
39
|
+
}, { autoInstallProductDesign: true, env: {} });
|
|
40
|
+
assertGate(installResult.ok, 'Product Design ensure must pass after fake plugin/install', installResult);
|
|
41
|
+
assertGate(installResult.install_attempted === true, 'Product Design ensure must attempt install when read evidence is not ready', installResult);
|
|
42
|
+
assertGate(installCalls.some((call) => call.method === 'plugin/install'), 'Product Design ensure did not call plugin/install', installCalls);
|
|
43
|
+
assertGate(installResult.after_evidence.ok, 'Product Design after_evidence must be ready after install', installResult);
|
|
44
|
+
installed = false;
|
|
45
|
+
const dryCalls = [];
|
|
46
|
+
const dryResult = await ensureProductDesignPluginInstalledWithRequest(async (method, params) => {
|
|
47
|
+
dryCalls.push({ method, params });
|
|
48
|
+
if (method === 'plugin/read')
|
|
49
|
+
return pluginReadResponse({ installed: false, enabled: false });
|
|
50
|
+
throw new Error(`unexpected dry method: ${method}`);
|
|
51
|
+
}, { autoInstallProductDesign: false, env: {} });
|
|
52
|
+
assertGate(!dryResult.ok, 'Product Design dry ensure must not claim ready when read evidence is not ready', dryResult);
|
|
53
|
+
assertGate(dryResult.install_attempted === false, 'Product Design dry ensure must not attempt install', dryResult);
|
|
54
|
+
assertGate(!dryCalls.some((call) => call.method === 'plugin/install'), 'Product Design dry ensure must not call plugin/install', dryCalls);
|
|
55
|
+
const marketplaceList = {
|
|
56
|
+
marketplaces: [{
|
|
57
|
+
name: PRODUCT_DESIGN_PLUGIN.marketplace,
|
|
58
|
+
plugins: [{
|
|
59
|
+
id: PRODUCT_DESIGN_PLUGIN.id,
|
|
60
|
+
remotePluginId: PRODUCT_DESIGN_PLUGIN.remote_plugin_id,
|
|
61
|
+
name: PRODUCT_DESIGN_PLUGIN.name,
|
|
62
|
+
installed: true,
|
|
63
|
+
enabled: true,
|
|
64
|
+
interface: {
|
|
65
|
+
displayName: PRODUCT_DESIGN_PLUGIN.display_name
|
|
66
|
+
}
|
|
67
|
+
}]
|
|
68
|
+
}],
|
|
69
|
+
marketplaceLoadErrors: []
|
|
70
|
+
};
|
|
71
|
+
const discovered = findProductDesignPluginSummaryFromMarketplaces(marketplaceList);
|
|
72
|
+
assertGate(discovered?.remotePluginId === PRODUCT_DESIGN_PLUGIN.remote_plugin_id, 'Product Design vertical plugin/list discovery must return remote id', discovered);
|
|
73
|
+
let readCount = 0;
|
|
74
|
+
const listCalls = [];
|
|
75
|
+
const listFallbackResult = await ensureProductDesignPluginInstalledWithRequest(async (method, params) => {
|
|
76
|
+
listCalls.push({ method, params });
|
|
77
|
+
if (method === 'plugin/read') {
|
|
78
|
+
readCount += 1;
|
|
79
|
+
if (readCount === 1)
|
|
80
|
+
throw new Error('simulated stale read id');
|
|
81
|
+
return pluginReadResponse({ installed: true, enabled: true });
|
|
82
|
+
}
|
|
83
|
+
if (method === 'plugin/list')
|
|
84
|
+
return marketplaceList;
|
|
85
|
+
throw new Error(`unexpected list fallback method: ${method}`);
|
|
86
|
+
}, { autoInstallProductDesign: true, env: {} });
|
|
87
|
+
assertGate(listFallbackResult.ok, 'Product Design ensure must recover through vertical plugin/list discovery', listFallbackResult);
|
|
88
|
+
assertGate(listFallbackResult.install_attempted === false, 'Product Design ensure must not install when list-discovered read is already ready', listFallbackResult);
|
|
89
|
+
assertGate(listCalls.some((call) => call.method === 'plugin/list'), 'Product Design ensure must query vertical plugin/list when direct read fails', listCalls);
|
|
90
|
+
assertGate(productDesignAutoInstallRequested({ env: { SKS_PRODUCT_DESIGN_AUTO_INSTALL: '1' } }), 'Product Design auto-install env gate must be honored');
|
|
91
|
+
const codexAppSource = readText('src/core/codex-app.ts');
|
|
92
|
+
const commandSource = readText('src/commands/codex-app.ts');
|
|
93
|
+
const appServerSource = readText('src/core/product-design-app-server.ts');
|
|
94
|
+
const pkg = JSON.parse(readText('package.json'));
|
|
95
|
+
const releaseCheck = String(pkg.scripts?.['release:check'] || '');
|
|
96
|
+
for (const token of [
|
|
97
|
+
'ensureProductDesignPluginInstalled',
|
|
98
|
+
'PRODUCT_DESIGN_AUTO_INSTALL_ENV',
|
|
99
|
+
'autoInstallProductDesign'
|
|
100
|
+
]) {
|
|
101
|
+
assertGate(codexAppSource.includes(token) || appServerSource.includes(token), `Product Design auto-install source missing token: ${token}`);
|
|
102
|
+
}
|
|
103
|
+
for (const token of [
|
|
104
|
+
'product-design',
|
|
105
|
+
'ensure-product-design',
|
|
106
|
+
'--check-only',
|
|
107
|
+
'--install-product-design'
|
|
108
|
+
]) {
|
|
109
|
+
assertGate(commandSource.includes(token), `sks codex-app command missing Product Design token: ${token}`);
|
|
110
|
+
}
|
|
111
|
+
assertGate(Boolean(pkg.scripts?.['codex:product-design-auto-install']), 'package script missing codex:product-design-auto-install');
|
|
112
|
+
assertGate(releaseCheck.includes('codex:product-design-auto-install'), 'release:check must include Product Design auto-install gate');
|
|
113
|
+
emitGate('codex:product-design-auto-install', {
|
|
114
|
+
install_calls: installCalls.map((call) => call.method),
|
|
115
|
+
dry_calls: dryCalls.map((call) => call.method),
|
|
116
|
+
list_fallback_calls: listCalls.map((call) => call.method),
|
|
117
|
+
env_gate: true
|
|
118
|
+
});
|
|
119
|
+
//# sourceMappingURL=product-design-auto-install-check.js.map
|