sneakoscope 2.0.11 → 2.0.13
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 +9 -3
- 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 +27 -8
- package/dist/core/agents/agent-orchestrator.js +279 -1
- package/dist/core/agents/agent-scheduler.js +12 -1
- package/dist/core/agents/agent-slot-pane-binding-proof.js +3 -3
- package/dist/core/agents/agent-work-queue.js +26 -2
- package/dist/core/agents/agent-worker-pipeline.js +2 -0
- package/dist/core/agents/native-cli-session-swarm.js +2 -2
- package/dist/core/codex-control/codex-sdk-adapter.js +10 -0
- package/dist/core/codex-control/codex-task-runner.js +4 -2
- package/dist/core/commands/naruto-command.js +104 -51
- package/dist/core/commands/research-command.js +43 -4
- package/dist/core/fsx.js +1 -1
- package/dist/core/git/git-worktree-merge-queue.js +34 -14
- package/dist/core/naruto/naruto-rebalance-policy.js +15 -3
- package/dist/core/naruto/naruto-work-graph.js +13 -0
- package/dist/core/research/claim-evidence-matrix.js +160 -0
- package/dist/core/research/experiment-plan.js +53 -0
- package/dist/core/research/falsification.js +18 -0
- package/dist/core/research/implementation-blueprint-markdown.js +31 -0
- package/dist/core/research/implementation-blueprint.js +66 -0
- package/dist/core/research/replication-pack.js +50 -0
- package/dist/core/research/research-cycle-runner.js +25 -0
- package/dist/core/research/research-final-reviewer.js +58 -0
- package/dist/core/research/research-handoff.js +51 -0
- package/dist/core/research/research-prompt-contract.js +24 -0
- package/dist/core/research/research-quality-contract.js +61 -0
- package/dist/core/research/research-report-quality.js +67 -0
- package/dist/core/research/research-stage-runner.js +16 -0
- package/dist/core/research/research-work-graph.js +75 -0
- package/dist/core/research/source-quality-report.js +94 -0
- package/dist/core/research.js +344 -44
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-slot-column-anchor.js +165 -4
- package/dist/core/zellij/zellij-slot-pane-renderer.js +259 -16
- package/dist/core/zellij/zellij-worker-pane-manager.js +13 -7
- package/dist/scripts/agent-real-codex-in-zellij-worker-pane-check.js +8 -2
- package/dist/scripts/agent-slot-pane-binding-proof-check.js +4 -4
- package/dist/scripts/codex-sdk-release-review-pipeline-check.js +2 -1
- package/dist/scripts/codex-sdk-research-pipeline-check.js +7 -0
- package/dist/scripts/codex-sdk-zellij-pane-binding-check.js +2 -2
- package/dist/scripts/git-worktree-cross-rebase-check.js +13 -1
- package/dist/scripts/git-worktree-merge-queue-check.js +1 -0
- package/dist/scripts/local-collab-worktree-gpt-final-apply-policy-check.js +63 -0
- package/dist/scripts/naruto-actual-worker-control-plane-check.js +30 -3
- package/dist/scripts/naruto-allocation-runtime-wiring-check.js +92 -0
- package/dist/scripts/naruto-orchestrator-runtime-source-check.js +65 -6
- package/dist/scripts/naruto-rebalance-policy-check.js +15 -2
- package/dist/scripts/naruto-shadow-clone-swarm-check.js +1 -1
- package/dist/scripts/packlist-performance-check.js +1 -1
- package/dist/scripts/release-dag-full-coverage-check.js +4 -0
- package/dist/scripts/release-real-check.js +258 -77
- package/dist/scripts/research-quality-gate-check.js +86 -0
- package/dist/scripts/zellij-first-slot-down-stack-check.js +1 -1
- package/dist/scripts/zellij-first-slot-down-stack-real-check.js +344 -4
- package/dist/scripts/zellij-right-column-manager-check.js +1 -1
- package/dist/scripts/zellij-slot-column-anchor-check.js +45 -3
- package/dist/scripts/zellij-slot-only-ui-check.js +3 -1
- package/dist/scripts/zellij-slot-pane-renderer-check.js +73 -5
- package/dist/scripts/zellij-slot-renderer-proof-semantics-check.js +59 -0
- package/dist/scripts/zellij-worker-pane-manager-check.js +23 -1
- package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +21 -4
- package/package.json +17 -2
- package/schemas/research/claim-evidence-matrix.schema.json +37 -0
- package/schemas/research/experiment-plan.schema.json +17 -0
- package/schemas/research/implementation-blueprint.schema.json +30 -0
- package/schemas/research/replication-pack.schema.json +17 -0
- package/schemas/research/research-final-review.schema.json +16 -0
- package/schemas/research/research-quality-contract.schema.json +37 -0
- package/schemas/research/source-quality-report.schema.json +18 -0
|
@@ -4,5 +4,12 @@ import { assertGate, emitGate, readText } from './lib/codex-sdk-gate-lib.js';
|
|
|
4
4
|
const source = readText('src/core/commands/research-command.ts');
|
|
5
5
|
assertGate(source.includes("backend: mock ? 'fake' : 'codex-sdk'"), 'Research pipeline must default native agents to codex-sdk');
|
|
6
6
|
assertGate(source.includes("flag(args, '--autoresearch') ? '$AutoResearch' : '$Research'"), 'Research/AutoResearch route selection missing');
|
|
7
|
+
assertGate(source.includes('narutoWorkGraph: researchWorkGraph'), 'Research pipeline must pass the stage-aware Naruto work graph');
|
|
8
|
+
assertGate(source.includes('readonly: true'), 'Research pipeline must force read-only native orchestration');
|
|
9
|
+
assertGate(source.includes('quality_metrics'), 'Research pipeline JSON output must include quality metrics');
|
|
10
|
+
const researchCore = readText('src/core/research.ts');
|
|
11
|
+
assertGate(researchCore.includes('readResearchQualityContract'), 'Research gate must read research-quality-contract.json');
|
|
12
|
+
assertGate(researchCore.includes('claim_evidence_matrix_missing'), 'Research gate must require claim-evidence-matrix.json');
|
|
13
|
+
assertGate(researchCore.includes('research_final_review_not_approved'), 'Research gate must require final reviewer approval');
|
|
7
14
|
emitGate('codex-sdk:research-pipeline', { route: '$Research' });
|
|
8
15
|
//# sourceMappingURL=codex-sdk-research-pipeline-check.js.map
|
|
@@ -7,7 +7,7 @@ const proofSource = readText('src/core/agents/agent-slot-pane-binding-proof.ts')
|
|
|
7
7
|
const managerSource = readText('src/core/zellij/zellij-worker-pane-manager.ts');
|
|
8
8
|
assertGate(fixture.proof.zellij_pane_id === 'pane-999', 'control proof must link zellij pane id', fixture.proof);
|
|
9
9
|
assertGate(swarmSource.includes('codex_sdk_thread_started'), 'swarm must emit SDK thread event');
|
|
10
|
-
assertGate(proofSource.includes('worker_codex_sdk'), 'slot-pane proof must
|
|
11
|
-
assertGate(managerSource.includes(
|
|
10
|
+
assertGate(proofSource.includes('worker_codex_sdk') && proofSource.includes('slot_status_renderer'), 'slot-pane proof must accept worker command panes and compact slot renderer panes');
|
|
11
|
+
assertGate(managerSource.includes('slot_status_renderer') && managerSource.includes('worker_codex_sdk'), 'worker pane manager must distinguish slot renderer and worker command pane kinds');
|
|
12
12
|
emitGate('codex-sdk:zellij-pane-binding', { zellij_pane_id: fixture.proof.zellij_pane_id, sdk_thread_id: fixture.proof.sdk_thread_id });
|
|
13
13
|
//# sourceMappingURL=codex-sdk-zellij-pane-binding-check.js.map
|
|
@@ -13,15 +13,27 @@ fs.writeFileSync(path.join(root, 'base.txt'), 'base\n');
|
|
|
13
13
|
await runGitCommand(root, ['add', 'base.txt']);
|
|
14
14
|
await runGitCommand(root, ['commit', '-m', 'base']);
|
|
15
15
|
const workerPath = path.join(root, '..', `worker-${process.pid}`);
|
|
16
|
+
const dirtyWorkerPath = path.join(root, '..', `worker-dirty-${process.pid}`);
|
|
17
|
+
const runningWorkerPath = path.join(root, '..', `worker-running-${process.pid}`);
|
|
16
18
|
await runGitCommand(root, ['worktree', 'add', workerPath, 'HEAD']);
|
|
19
|
+
await runGitCommand(root, ['worktree', 'add', dirtyWorkerPath, 'HEAD']);
|
|
20
|
+
await runGitCommand(root, ['worktree', 'add', runningWorkerPath, 'HEAD']);
|
|
21
|
+
fs.writeFileSync(path.join(dirtyWorkerPath, 'dirty.txt'), 'dirty\n');
|
|
17
22
|
fs.writeFileSync(path.join(root, 'integration.txt'), 'integration\n');
|
|
18
23
|
await runGitCommand(root, ['add', 'integration.txt']);
|
|
19
24
|
await runGitCommand(root, ['commit', '-m', 'integration']);
|
|
20
25
|
const head = gitOutputLine(await runGitCommand(root, ['rev-parse', 'HEAD']));
|
|
21
26
|
const report = await crossRebaseIdleWorktrees({
|
|
22
27
|
integrationHead: head,
|
|
23
|
-
workers: [
|
|
28
|
+
workers: [
|
|
29
|
+
{ worker_id: 'W1', worktree_path: workerPath, state: 'idle' },
|
|
30
|
+
{ worker_id: 'W-dirty', worktree_path: dirtyWorkerPath, state: 'idle' },
|
|
31
|
+
{ worker_id: 'W-running', worktree_path: runningWorkerPath, state: 'running' }
|
|
32
|
+
]
|
|
24
33
|
});
|
|
25
34
|
assertGate(report.ok && report.applied_count === 1, 'Idle worktrees must cross-rebase to the integration head', report);
|
|
35
|
+
assertGate(report.skipped_count === 2, 'Dirty and running worktrees must be skipped during cross-rebase', report);
|
|
36
|
+
assertGate(report.records.some((row) => row.worker_id === 'W-dirty' && row.status === 'skipped' && row.reason === 'dirty_worktree_skipped'), 'Dirty worktree must skip cross-rebase', report);
|
|
37
|
+
assertGate(report.records.some((row) => row.worker_id === 'W-running' && row.status === 'skipped' && row.reason === 'worker_not_idle'), 'Running worktree must skip cross-rebase', report);
|
|
26
38
|
emitGate('git:worktree-cross-rebase', report);
|
|
27
39
|
//# sourceMappingURL=git-worktree-cross-rebase-check.js.map
|
|
@@ -20,6 +20,7 @@ const diffB = await diffMod.exportGitWorktreeDiff({ mainRepoRoot: repo, worktree
|
|
|
20
20
|
const integration = await integrationMod.createGitIntegrationWorktree({ repoRoot: repo, missionId: 'M-merge' });
|
|
21
21
|
const report = await queueMod.applyGitWorktreeMergeQueue({ integrationWorktreePath: integration.worktree_path, diffs: [diffA, diffB] });
|
|
22
22
|
assertGate(report.ok === true && report.applied_count === 2, 'merge queue must apply non-conflicting worktree diffs', report);
|
|
23
|
+
assertGate((report.strategy_results || []).every((row) => row.strategy === 'diff-apply-3way'), 'merge queue must record the diff apply strategy for worktree diffs', report.strategy_results || []);
|
|
23
24
|
assertGate(fs.readFileSync(path.join(integration.worktree_path, 'a.txt'), 'utf8').includes('from-a'), 'integration worktree must include first diff');
|
|
24
25
|
assertGate(fs.readFileSync(path.join(integration.worktree_path, 'b.txt'), 'utf8').includes('from-b'), 'integration worktree must include second diff');
|
|
25
26
|
assertGate(fs.readFileSync(path.join(repo, 'a.txt'), 'utf8') === 'alpha\n', 'main worktree must remain unchanged before integration commit');
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
|
|
4
|
+
import { gptFinalRequiredForPipeline } from '../core/pipeline/gpt-final-required.js';
|
|
5
|
+
import { finalizePipelineResult } from '../core/pipeline/finalize-pipeline-result.js';
|
|
6
|
+
import { selectFinalGptPatchSource } from '../core/pipeline/final-gpt-patch-stage.js';
|
|
7
|
+
const worktreeEnvelope = {
|
|
8
|
+
schema: 'sks.agent-patch-envelope.v1',
|
|
9
|
+
source: 'git-worktree-diff',
|
|
10
|
+
git_worktree: {
|
|
11
|
+
worktree_path: '/tmp/sks-worker',
|
|
12
|
+
changed_files: ['src/core/example.ts']
|
|
13
|
+
},
|
|
14
|
+
operations: [{ op: 'git_apply_patch', path: '.', diff: 'diff --git a/src/core/example.ts b/src/core/example.ts\n' }]
|
|
15
|
+
};
|
|
16
|
+
const requirement = gptFinalRequiredForPipeline({
|
|
17
|
+
localParticipated: false,
|
|
18
|
+
candidateResults: [{ backend: 'codex-sdk', patch_envelopes: [worktreeEnvelope] }],
|
|
19
|
+
candidatePatchEnvelopes: [worktreeEnvelope]
|
|
20
|
+
});
|
|
21
|
+
const blocked = await finalizePipelineResult({
|
|
22
|
+
route: '$Naruto',
|
|
23
|
+
missionId: 'M-worktree-gpt-final-policy',
|
|
24
|
+
localParticipated: false,
|
|
25
|
+
candidateResults: [{ backend: 'codex-sdk', patch_envelopes: [worktreeEnvelope] }],
|
|
26
|
+
candidatePatchEnvelopes: [worktreeEnvelope],
|
|
27
|
+
verificationResults: [],
|
|
28
|
+
sideEffectReport: {},
|
|
29
|
+
mutationLedger: {},
|
|
30
|
+
rollbackPlan: {},
|
|
31
|
+
applyPatches: true,
|
|
32
|
+
forceGptFinalUnavailable: true
|
|
33
|
+
});
|
|
34
|
+
const modified = selectFinalGptPatchSource({
|
|
35
|
+
result: {
|
|
36
|
+
status: 'modified',
|
|
37
|
+
modified_patch_envelopes: [{ ...worktreeEnvelope, source: 'model_authored', operations: [{ op: 'replace', path: 'src/core/example.ts', search: 'old', replace: 'new' }] }]
|
|
38
|
+
}
|
|
39
|
+
}, [worktreeEnvelope]);
|
|
40
|
+
const rejected = selectFinalGptPatchSource({ result: { status: 'rejected' } }, [worktreeEnvelope]);
|
|
41
|
+
const ok = requirement.gpt_final_required === true
|
|
42
|
+
&& requirement.worktree_participated === true
|
|
43
|
+
&& blocked.ok === false
|
|
44
|
+
&& blocked.apply_allowed === false
|
|
45
|
+
&& blocked.blockers.includes('gpt_final_arbiter_required_not_passed')
|
|
46
|
+
&& modified.ok === true
|
|
47
|
+
&& modified.final_patch_source === 'gpt_final_arbiter'
|
|
48
|
+
&& modified.patch_envelopes[0]?.source === 'model_authored'
|
|
49
|
+
&& rejected.ok === false
|
|
50
|
+
&& rejected.final_patch_source === 'blocked';
|
|
51
|
+
assertGate(ok, 'Worktree/local candidate output must require GPT Final before apply, and GPT modified/rejected decisions must control final patch source', {
|
|
52
|
+
requirement,
|
|
53
|
+
blocked,
|
|
54
|
+
modified,
|
|
55
|
+
rejected
|
|
56
|
+
});
|
|
57
|
+
emitGate('local-collab:worktree-gpt-final-apply-policy', {
|
|
58
|
+
requirement,
|
|
59
|
+
blocked_apply_allowed: blocked.apply_allowed,
|
|
60
|
+
modified_source: modified.final_patch_source,
|
|
61
|
+
rejected_source: rejected.final_patch_source
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=local-collab-worktree-gpt-final-apply-policy-check.js.map
|
|
@@ -6,6 +6,7 @@ import path from 'node:path';
|
|
|
6
6
|
import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
|
|
7
7
|
import { buildNarutoWorkGraph } from '../core/naruto/naruto-work-graph.js';
|
|
8
8
|
import { collectActualNarutoWorker, spawnActualNarutoWorker } from '../core/naruto/naruto-real-worker-runtime.js';
|
|
9
|
+
import { narutoCommand } from '../core/commands/naruto-command.js';
|
|
9
10
|
process.env.SKS_CODEX_SDK_FAKE = '1';
|
|
10
11
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-naruto-actual-worker-'));
|
|
11
12
|
const graph = buildNarutoWorkGraph({ requestedClones: 1, totalWorkItems: 1, readonly: true, writeCapable: false });
|
|
@@ -20,10 +21,36 @@ const handle = await spawnActualNarutoWorker({
|
|
|
20
21
|
});
|
|
21
22
|
const collected = await collectActualNarutoWorker(handle);
|
|
22
23
|
const result = JSON.parse(fs.readFileSync(path.join(handle.worker_artifact_dir, 'worker-result.json'), 'utf8'));
|
|
24
|
+
const fullRoute = await narutoCommand([
|
|
25
|
+
'run',
|
|
26
|
+
'Naruto actual worker full command control plane check',
|
|
27
|
+
'--json',
|
|
28
|
+
'--backend',
|
|
29
|
+
'fake',
|
|
30
|
+
'--backend-explicit',
|
|
31
|
+
'--clones',
|
|
32
|
+
'2',
|
|
33
|
+
'--work-items',
|
|
34
|
+
'2',
|
|
35
|
+
'--readonly',
|
|
36
|
+
'--no-open-zellij',
|
|
37
|
+
'--smoke'
|
|
38
|
+
]);
|
|
39
|
+
const missionRoot = path.join(process.cwd(), '.sneakoscope', 'missions', fullRoute.mission_id || '', 'agents', 'naruto-real-workers');
|
|
40
|
+
const fullWorkerResults = fs.existsSync(missionRoot)
|
|
41
|
+
? fs.readdirSync(missionRoot).map((name) => {
|
|
42
|
+
const file = path.join(missionRoot, name, 'worker-result.json');
|
|
43
|
+
return fs.existsSync(file) ? JSON.parse(fs.readFileSync(file, 'utf8')) : null;
|
|
44
|
+
}).filter(Boolean)
|
|
45
|
+
: [];
|
|
23
46
|
const ok = collected.ok === true
|
|
24
47
|
&& result.ok === true
|
|
25
48
|
&& result.control_plane_result?.worker_result_path
|
|
26
|
-
&& result.control_plane_result?.structured_output_valid === true
|
|
27
|
-
|
|
28
|
-
|
|
49
|
+
&& result.control_plane_result?.structured_output_valid === true
|
|
50
|
+
&& fullRoute.active_pool?.real_runtime?.runtime_source_of_truth === 'pre_run_smoke_only'
|
|
51
|
+
&& fullRoute.runtime_source_of_truth === 'agent-orchestrator-scheduler'
|
|
52
|
+
&& fullWorkerResults.length >= 1
|
|
53
|
+
&& fullWorkerResults.every((row) => row.control_plane_result?.structured_output_valid === true);
|
|
54
|
+
assertGate(ok, 'Naruto actual worker must call Codex Control Plane directly and through the explicit full-route smoke path', { collected, result, fullRoute, fullWorkerResults });
|
|
55
|
+
emitGate('naruto:actual-worker-control-plane', { collected, result, full_route_mission_id: fullRoute.mission_id, full_worker_result_count: fullWorkerResults.length });
|
|
29
56
|
//# sourceMappingURL=naruto-actual-worker-control-plane-check.js.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
|
|
7
|
+
import { runNativeAgentOrchestrator } from '../core/agents/agent-orchestrator.js';
|
|
8
|
+
import { buildNarutoCloneRoster } from '../core/agents/agent-roster.js';
|
|
9
|
+
import { buildNarutoWorkGraph } from '../core/naruto/naruto-work-graph.js';
|
|
10
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-naruto-runtime-wiring-'));
|
|
11
|
+
const roster = buildNarutoCloneRoster({ clones: 3, readonly: true, prompt: 'runtime wiring check' });
|
|
12
|
+
const graph = buildNarutoWorkGraph({
|
|
13
|
+
requestedClones: 3,
|
|
14
|
+
totalWorkItems: 3,
|
|
15
|
+
readonly: true,
|
|
16
|
+
writeCapable: false,
|
|
17
|
+
allocationAssignments: [
|
|
18
|
+
assignment('NW-000001', 'naruto_clone_001', 42),
|
|
19
|
+
assignment('NW-000002', 'naruto_clone_002', 41),
|
|
20
|
+
assignment('NW-000003', 'naruto_clone_999', 1)
|
|
21
|
+
]
|
|
22
|
+
});
|
|
23
|
+
const result = await runNativeAgentOrchestrator({
|
|
24
|
+
root,
|
|
25
|
+
route: '$Naruto',
|
|
26
|
+
routeCommand: 'sks naruto run',
|
|
27
|
+
routeBlackboxKind: 'allocation_runtime_wiring_gate',
|
|
28
|
+
prompt: 'Naruto allocation runtime wiring check',
|
|
29
|
+
roster,
|
|
30
|
+
agents: 3,
|
|
31
|
+
concurrency: 2,
|
|
32
|
+
targetActiveSlots: 2,
|
|
33
|
+
desiredWorkItemCount: 3,
|
|
34
|
+
minimumWorkItems: 3,
|
|
35
|
+
backend: 'fake',
|
|
36
|
+
backendExplicit: true,
|
|
37
|
+
mock: true,
|
|
38
|
+
readonly: true,
|
|
39
|
+
nativeCliSwarm: false,
|
|
40
|
+
narutoMode: true,
|
|
41
|
+
narutoWorkGraph: graph,
|
|
42
|
+
narutoAllocationPolicy: { schema: 'sks.naruto-allocation-policy.v1', ok: true, assignments: graph.work_items.map((item) => ({ task_id: item.id, owner: item.owner })) },
|
|
43
|
+
narutoRebalancePolicy: { schema: 'sks.naruto-rebalance-policy.v1', ok: true, decisions: [] }
|
|
44
|
+
});
|
|
45
|
+
const ledgerRoot = path.join(root, result.ledger_root || '.');
|
|
46
|
+
const wiring = JSON.parse(fs.readFileSync(path.join(ledgerRoot, 'naruto-runtime-wiring.json'), 'utf8'));
|
|
47
|
+
const queue = JSON.parse(fs.readFileSync(path.join(ledgerRoot, 'agent-work-queue.json'), 'utf8'));
|
|
48
|
+
const owners = queue.items.map((item) => item.slice?.owner_agent_id);
|
|
49
|
+
const runtimeProofs = (result.results || []).map((row) => row.naruto_runtime).filter(Boolean);
|
|
50
|
+
const schedulerOk = result.scheduler?.state?.completed_count === 3
|
|
51
|
+
&& result.scheduler?.state?.failed_count === 0
|
|
52
|
+
&& result.scheduler?.state?.blocked_count === 0
|
|
53
|
+
&& result.scheduler?.state?.pending_queue_drained === true
|
|
54
|
+
&& Array.isArray(result.scheduler?.state?.blockers)
|
|
55
|
+
&& result.scheduler.state.blockers.length === 0;
|
|
56
|
+
const ok = schedulerOk
|
|
57
|
+
&& wiring.ok === true
|
|
58
|
+
&& wiring.scheduler_slice_count === 3
|
|
59
|
+
&& owners.includes('naruto_clone_001')
|
|
60
|
+
&& owners.includes('naruto_clone_002')
|
|
61
|
+
&& wiring.slice_owners.some((row) => row.original_owner === 'naruto_clone_999' && row.rebalanced === true)
|
|
62
|
+
&& runtimeProofs.length === 3
|
|
63
|
+
&& runtimeProofs.every((row) => row.source_of_truth === 'agent-orchestrator-scheduler');
|
|
64
|
+
assertGate(ok, 'Naruto allocation must be wired into scheduler slices, queue ownership, and worker runtime proof', {
|
|
65
|
+
result_ok: result.ok,
|
|
66
|
+
result_proof_blockers: result.proof?.blockers || [],
|
|
67
|
+
scheduler: result.scheduler?.state || null,
|
|
68
|
+
wiring,
|
|
69
|
+
owners,
|
|
70
|
+
runtimeProofs
|
|
71
|
+
});
|
|
72
|
+
emitGate('naruto:allocation-runtime-wiring', {
|
|
73
|
+
wiring,
|
|
74
|
+
owners,
|
|
75
|
+
scheduler_ok: schedulerOk,
|
|
76
|
+
runtime_proof_count: runtimeProofs.length
|
|
77
|
+
});
|
|
78
|
+
function assignment(taskId, owner, score) {
|
|
79
|
+
return {
|
|
80
|
+
task_id: taskId,
|
|
81
|
+
owner,
|
|
82
|
+
allocation_reason: `fixture owner ${owner}`,
|
|
83
|
+
allocation_score: score,
|
|
84
|
+
hints: {
|
|
85
|
+
role: 'verifier',
|
|
86
|
+
paths: ['src/core/naruto/runtime.ts'],
|
|
87
|
+
domains: ['src/core/naruto'],
|
|
88
|
+
writePaths: []
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=naruto-allocation-runtime-wiring-check.js.map
|
|
@@ -2,10 +2,69 @@
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
import { narutoCommand } from '../core/commands/naruto-command.js';
|
|
6
|
+
const summary = await narutoCommand([
|
|
7
|
+
'run',
|
|
8
|
+
'Naruto orchestrator runtime source artifact check',
|
|
9
|
+
'--json',
|
|
10
|
+
'--backend',
|
|
11
|
+
'fake',
|
|
12
|
+
'--clones',
|
|
13
|
+
'2',
|
|
14
|
+
'--work-items',
|
|
15
|
+
'2',
|
|
16
|
+
'--readonly',
|
|
17
|
+
'--no-open-zellij'
|
|
18
|
+
]);
|
|
19
|
+
const ledgerRoot = path.join(process.cwd(), '.sneakoscope', 'missions', summary.mission_id || '', 'agents');
|
|
20
|
+
const realPool = readJson(path.join(ledgerRoot, 'naruto-real-active-pool.json'));
|
|
21
|
+
const wiring = readJson(path.join(ledgerRoot, 'naruto-runtime-wiring.json'));
|
|
22
|
+
const artifactText = collectText(ledgerRoot);
|
|
23
|
+
const ok = summary.runtime_source_of_truth === 'agent-orchestrator-scheduler'
|
|
24
|
+
&& summary.pre_run_real_active_pool_source === 'skipped'
|
|
25
|
+
&& realPool?.status === 'skipped'
|
|
26
|
+
&& realPool?.runtime_source_of_truth === 'agent-orchestrator-scheduler'
|
|
27
|
+
&& realPool?.reason === 'pre_run_smoke_disabled_for_production'
|
|
28
|
+
&& wiring?.source_of_truth === 'naruto-work-graph'
|
|
29
|
+
&& artifactText.includes('agent-orchestrator-scheduler')
|
|
30
|
+
&& artifactText.includes('pre_run_smoke_never_owns_production_runtime');
|
|
31
|
+
assertGate(ok, 'Naruto production runtime source of truth must be proven by command artifacts, not source-string checks', {
|
|
32
|
+
summary,
|
|
33
|
+
realPool,
|
|
34
|
+
wiring
|
|
35
|
+
});
|
|
36
|
+
emitGate('naruto:orchestrator-runtime-source', {
|
|
37
|
+
mission_id: summary.mission_id,
|
|
38
|
+
runtime_source_of_truth: summary.runtime_source_of_truth,
|
|
39
|
+
pre_run_real_active_pool_source: summary.pre_run_real_active_pool_source,
|
|
40
|
+
real_pool_status: realPool?.status || null,
|
|
41
|
+
wiring_ok: wiring?.ok === true
|
|
42
|
+
});
|
|
43
|
+
function readJson(file) {
|
|
44
|
+
try {
|
|
45
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function collectText(root) {
|
|
52
|
+
const chunks = [];
|
|
53
|
+
const stack = [root];
|
|
54
|
+
while (stack.length) {
|
|
55
|
+
const current = stack.pop();
|
|
56
|
+
if (!current || !fs.existsSync(current))
|
|
57
|
+
continue;
|
|
58
|
+
const stat = fs.statSync(current);
|
|
59
|
+
if (stat.isDirectory()) {
|
|
60
|
+
for (const child of fs.readdirSync(current))
|
|
61
|
+
stack.push(path.join(current, child));
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (!/\.(json|jsonl)$/.test(current))
|
|
65
|
+
continue;
|
|
66
|
+
chunks.push(fs.readFileSync(current, 'utf8'));
|
|
67
|
+
}
|
|
68
|
+
return chunks.join('\n');
|
|
69
|
+
}
|
|
11
70
|
//# sourceMappingURL=naruto-orchestrator-runtime-source-check.js.map
|
|
@@ -23,6 +23,19 @@ const decisions = rebalanceNarutoReadyWork({
|
|
|
23
23
|
workers: [{ id: 'idle-1', role: 'verifier', lane: 'src/core', alive: true, state: 'idle' }],
|
|
24
24
|
completedTaskIds: []
|
|
25
25
|
});
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
const inactiveOwner = rebalanceNarutoReadyWork({
|
|
27
|
+
tasks: [{ ...item('C'), owner: 'missing-worker' }],
|
|
28
|
+
workers: [{ id: 'idle-2', role: 'verifier', lane: 'src/core', alive: true, state: 'idle' }],
|
|
29
|
+
completedTaskIds: []
|
|
30
|
+
});
|
|
31
|
+
const writeConflict = rebalanceNarutoReadyWork({
|
|
32
|
+
tasks: [{ ...item('D'), write_paths: ['src/core/naruto/runtime.ts'], write_allowed: true }],
|
|
33
|
+
workers: [{ id: 'idle-3', role: 'verifier', lane: 'src/core', alive: true, state: 'idle' }],
|
|
34
|
+
completedTaskIds: [],
|
|
35
|
+
activeWritePaths: ['src/core/naruto/runtime.ts']
|
|
36
|
+
});
|
|
37
|
+
assertGate(decisions.length === 1 && decisions[0]?.task_id === 'A'
|
|
38
|
+
&& inactiveOwner.length === 1 && inactiveOwner[0]?.worker_id === 'idle-2'
|
|
39
|
+
&& writeConflict.length === 0, 'Naruto rebalance must assign dependency-ready work, reassign inactive owners, and skip active write conflicts', { decisions, inactiveOwner, writeConflict });
|
|
40
|
+
emitGate('naruto:rebalance-policy', { decisions, inactiveOwner, writeConflict });
|
|
28
41
|
//# sourceMappingURL=naruto-rebalance-policy-check.js.map
|
|
@@ -114,7 +114,7 @@ const writePaths = commandGraph.work_items.filter((row) => row.write_allowed).fl
|
|
|
114
114
|
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 });
|
|
115
115
|
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) });
|
|
116
116
|
const state = parsed.run?.scheduler?.state || parsed.run?.scheduler || {};
|
|
117
|
-
assertGate(Number(state.completed_count) === proofClones, 'all clone work items must complete despite throttling', { completed_count: state.completed_count });
|
|
117
|
+
assertGate(Number(state.completed_count) === Number(parsed.work_graph?.total_work_items || 0) && Number(state.completed_count) >= proofClones, 'all clone work items must complete despite throttling', { completed_count: state.completed_count, total_work_items: parsed.work_graph?.total_work_items, proofClones });
|
|
118
118
|
const explicitConcurrency = spawnSync(process.execPath, [cli, 'naruto', 'run', 'explicit concurrency', '--clones', '6', '--backend', 'fake', '--work-items', '6', '--concurrency', '6', '--json'], { cwd: root, env: childEnv, encoding: 'utf8', timeout: 120000, maxBuffer: 4 * 1024 * 1024 });
|
|
119
119
|
const explicitParsed = parseJson(explicitConcurrency.stdout);
|
|
120
120
|
assertGate(explicitConcurrency.status === 0 && explicitParsed?.target_active_slots === 6, 'explicit --concurrency must let Naruto use the requested parallel slot count', { status: explicitConcurrency.status, target_active_slots: explicitParsed?.target_active_slots });
|
|
@@ -5,7 +5,7 @@ import os from 'node:os';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { spawnSync } from 'node:child_process';
|
|
7
7
|
import { assertGate, emitGate, root } from './sks-1-18-gate-lib.js';
|
|
8
|
-
const MAX_FILES = Number(process.env.SKS_MAX_PACK_FILES ||
|
|
8
|
+
const MAX_FILES = Number(process.env.SKS_MAX_PACK_FILES || 1250);
|
|
9
9
|
const MAX_UNPACKED = Number(process.env.SKS_MAX_UNPACKED_BYTES || 6 * 1024 * 1024);
|
|
10
10
|
const MAX_PACKED = Number(process.env.SKS_MAX_PACK_BYTES || 1536 * 1024);
|
|
11
11
|
function runNpmPack() {
|
|
@@ -19,12 +19,16 @@ const gateIds = new Set(manifest.gates.map((gate) => gate.id));
|
|
|
19
19
|
const releasePresetIds = new Set(manifest.gates.filter((gate) => Array.isArray(gate.preset) && gate.preset.includes('release')).map((gate) => gate.id));
|
|
20
20
|
const requiredReleasePresetIds = [
|
|
21
21
|
'zellij:first-slot-down-stack',
|
|
22
|
+
'zellij:slot-renderer-proof-semantics',
|
|
22
23
|
'naruto:allocation-policy',
|
|
23
24
|
'naruto:rebalance-policy',
|
|
25
|
+
'naruto:allocation-runtime-wiring',
|
|
24
26
|
'naruto:actual-worker-control-plane',
|
|
25
27
|
'naruto:orchestrator-runtime-source',
|
|
26
28
|
'git:worktree-checkpoint',
|
|
27
29
|
'git:worktree-cross-rebase',
|
|
30
|
+
'local-collab:worktree-gpt-final-apply-policy',
|
|
31
|
+
'release:cache-glob-hashing',
|
|
28
32
|
'release:dag-full-coverage'
|
|
29
33
|
];
|
|
30
34
|
const missing = legacyIds.filter((id) => !gateIds.has(id) && !allowlist.has(id));
|