sneakoscope 2.0.6 → 2.0.8
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 +6 -1
- 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 +56 -8
- package/dist/core/agents/agent-command-surface.js +4 -2
- package/dist/core/agents/agent-orchestrator.js +140 -4
- package/dist/core/agents/agent-patch-schema.js +20 -4
- package/dist/core/agents/agent-proof-evidence.js +3 -0
- package/dist/core/agents/native-cli-session-swarm.js +31 -5
- package/dist/core/agents/native-cli-worker.js +28 -1
- package/dist/core/codex-control/python-codex-sdk-adapter.js +28 -4
- package/dist/core/commands/mad-sks-command.js +25 -0
- package/dist/core/commands/naruto-command.js +68 -10
- package/dist/core/feature-registry.js +2 -0
- package/dist/core/fsx.js +1 -1
- package/dist/core/git/git-integration-worktree.js +15 -0
- package/dist/core/git/git-repo-detection.js +79 -0
- package/dist/core/git/git-worktree-cache-policy.js +36 -0
- package/dist/core/git/git-worktree-capability.js +54 -0
- package/dist/core/git/git-worktree-cleanup.js +62 -0
- package/dist/core/git/git-worktree-conflict-resolver.js +13 -0
- package/dist/core/git/git-worktree-diff.js +55 -0
- package/dist/core/git/git-worktree-manager.js +93 -0
- package/dist/core/git/git-worktree-merge-queue.js +55 -0
- package/dist/core/git/git-worktree-patch-envelope.js +35 -0
- package/dist/core/git/git-worktree-pool.js +23 -0
- package/dist/core/git/git-worktree-root.js +52 -0
- package/dist/core/git/git-worktree-runner.js +40 -0
- package/dist/core/naruto/naruto-active-pool.js +35 -0
- package/dist/core/naruto/naruto-gpt-final-pack.js +2 -0
- package/dist/core/naruto/naruto-work-graph.js +16 -1
- package/dist/core/release/release-gate-cache-v2.js +63 -0
- package/dist/core/release/release-gate-dag.js +179 -0
- package/dist/core/release/release-gate-hermetic-env.js +32 -0
- package/dist/core/release/release-gate-node.js +62 -0
- package/dist/core/release/release-gate-report.js +11 -0
- package/dist/core/release/release-gate-resource-governor.js +54 -0
- package/dist/core/release/release-gate-scheduler.js +15 -0
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-dashboard-pane.js +71 -0
- package/dist/core/zellij/zellij-dashboard-renderer.js +42 -0
- package/dist/core/zellij/zellij-naruto-dashboard.js +10 -1
- package/dist/core/zellij/zellij-worker-pane-manager.js +68 -6
- package/dist/scripts/git-worktree-cache-performance-check.js +25 -0
- package/dist/scripts/git-worktree-capability-check.js +27 -0
- package/dist/scripts/git-worktree-cleanup-check.js +27 -0
- package/dist/scripts/git-worktree-diff-envelope-check.js +17 -0
- package/dist/scripts/git-worktree-diff-export-check.js +43 -0
- package/dist/scripts/git-worktree-dirty-lock-check.js +17 -0
- package/dist/scripts/git-worktree-dirty-main-detection-check.js +14 -0
- package/dist/scripts/git-worktree-integration-primary-check.js +22 -0
- package/dist/scripts/git-worktree-manager-check.js +37 -0
- package/dist/scripts/git-worktree-manifest-append-check.js +18 -0
- package/dist/scripts/git-worktree-merge-queue-check.js +30 -0
- package/dist/scripts/git-worktree-pool-performance-check.js +20 -0
- package/dist/scripts/git-worktree-untracked-diff-check.js +18 -0
- package/dist/scripts/lib/git-worktree-fixture.js +33 -0
- package/dist/scripts/naruto-shadow-clone-swarm-check.js +9 -5
- package/dist/scripts/naruto-worktree-coding-blackbox.js +29 -0
- package/dist/scripts/naruto-worktree-coding-check.js +44 -0
- package/dist/scripts/naruto-worktree-gpt-final-check.js +45 -0
- package/dist/scripts/naruto-worktree-zellij-ui-check.js +28 -0
- package/dist/scripts/release-gate-dag-runner-check.js +17 -0
- package/dist/scripts/release-gate-dag-runner.js +32 -0
- package/dist/scripts/release-gate-worker.js +10 -0
- package/dist/scripts/release-metadata-1-19-check.js +8 -2
- package/dist/scripts/release-parallel-check.js +1 -1
- package/dist/scripts/release-parallel-speed-budget-check.js +25 -0
- package/dist/scripts/release-stability-report-check.js +99 -0
- package/dist/scripts/zellij-dashboard-pane-check.js +68 -0
- package/dist/scripts/zellij-dashboard-watch.js +41 -0
- package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +185 -0
- package/package.json +33 -5
- package/schemas/git/git-worktree-capability.schema.json +19 -0
- package/schemas/git/git-worktree-manifest.schema.json +36 -0
- package/schemas/release/release-gate-node.schema.json +52 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const policyMod = await importDist('core/git/git-worktree-cache-policy.js');
|
|
5
|
+
const now = Date.now();
|
|
6
|
+
const entries = Array.from({ length: 1000 }, (_, index) => ({
|
|
7
|
+
path: `/tmp/wt-${index}`,
|
|
8
|
+
updated_at_ms: now - index * 60000,
|
|
9
|
+
bytes: 1024 * (index + 1),
|
|
10
|
+
dirty: index % 137 === 0
|
|
11
|
+
}));
|
|
12
|
+
const start = Date.now();
|
|
13
|
+
const plan = policyMod.planGitWorktreeCachePolicy({ entries, nowMs: now, maxEntries: 120, maxBytes: 40 * 1024 * 1024, ttlMs: 2 * 60 * 60 * 1000 });
|
|
14
|
+
const elapsed = Date.now() - start;
|
|
15
|
+
assertGate(plan.ok === true, 'cache policy plan must pass', plan);
|
|
16
|
+
assertGate(plan.keep.length <= 120 || plan.dirty_retained.length > 0, 'cache policy must bound retained clean entries', plan);
|
|
17
|
+
assertGate(plan.dirty_retained.length > 0, 'dirty entries must be retained by cache policy', plan);
|
|
18
|
+
assertGate(elapsed < 250, 'cache policy must stay fast on 1000 entries', { elapsed });
|
|
19
|
+
emitGate('git:worktree-cache-performance', {
|
|
20
|
+
elapsed_ms: elapsed,
|
|
21
|
+
keep: plan.keep.length,
|
|
22
|
+
prune: plan.prune.length,
|
|
23
|
+
dirty_retained: plan.dirty_retained.length
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=git-worktree-cache-performance-check.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
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, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
import { makeGitFixture, makeNonGitFixture } from './lib/git-worktree-fixture.js';
|
|
8
|
+
const capabilityMod = await importDist('core/git/git-worktree-capability.js');
|
|
9
|
+
const nonGit = makeNonGitFixture('worktree-capability-non-git');
|
|
10
|
+
process.env.SKS_WORKTREE_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-wt-capability-'));
|
|
11
|
+
delete process.env.SKS_ALLOW_IN_REPO_WORKTREES;
|
|
12
|
+
const nonGitCapability = await capabilityMod.evaluateGitWorktreeCapability({ root: nonGit, missionId: 'M-non-git' });
|
|
13
|
+
assertGate(nonGitCapability.mode === 'patch-envelope-only', 'non-Git projects must degrade to patch-envelope-only', nonGitCapability);
|
|
14
|
+
assertGate(nonGitCapability.worktree_probe_attempted === false, 'non-Git projects must not probe git worktree', nonGitCapability);
|
|
15
|
+
const repo = makeGitFixture('worktree-capability-git');
|
|
16
|
+
const gitCapability = await capabilityMod.evaluateGitWorktreeCapability({ root: repo, missionId: 'M-git' });
|
|
17
|
+
assertGate(gitCapability.ok === true && gitCapability.mode === 'git-worktree', 'Git fixture must support worktree mode', gitCapability);
|
|
18
|
+
assertGate(gitCapability.root_resolution?.in_repo === false, 'default worktree root must be outside main repo', gitCapability.root_resolution);
|
|
19
|
+
process.env.SKS_WORKTREE_ROOT = path.join(repo, '.sneakoscope', 'worktrees');
|
|
20
|
+
const blocked = await capabilityMod.evaluateGitWorktreeCapability({ root: repo, missionId: 'M-in-repo' });
|
|
21
|
+
assertGate(blocked.ok === false && blocked.blockers.includes('git_worktree_root_inside_repo_blocked'), 'in-repo worktree root must be blocked by default', blocked);
|
|
22
|
+
emitGate('git:worktree-capability', {
|
|
23
|
+
non_git_mode: nonGitCapability.mode,
|
|
24
|
+
git_mode: gitCapability.mode,
|
|
25
|
+
in_repo_blocked: true
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=git-worktree-capability-check.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
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, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
import { makeGitFixture } from './lib/git-worktree-fixture.js';
|
|
8
|
+
const managerMod = await importDist('core/git/git-worktree-manager.js');
|
|
9
|
+
const cleanupMod = await importDist('core/git/git-worktree-cleanup.js');
|
|
10
|
+
const repo = makeGitFixture('worktree-cleanup');
|
|
11
|
+
process.env.SKS_WORKTREE_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-wt-cleanup-'));
|
|
12
|
+
const cleanAllocation = await managerMod.allocateWorkerWorktree({ repoRoot: repo, missionId: 'M-cleanup', workerId: 'clean', slotId: 'slot-001' });
|
|
13
|
+
const clean = await cleanupMod.cleanupGitWorktree({ repoRoot: repo, worktreePath: cleanAllocation.worktree_path, branch: cleanAllocation.branch, deleteBranch: true });
|
|
14
|
+
assertGate(clean.ok === true && clean.action === 'removed', 'clean worktree must be removed by cleanup manager', clean);
|
|
15
|
+
assertGate(!fs.existsSync(cleanAllocation.worktree_path), 'removed clean worktree path should be gone');
|
|
16
|
+
const dirtyAllocation = await managerMod.allocateWorkerWorktree({ repoRoot: repo, missionId: 'M-cleanup', workerId: 'dirty', slotId: 'slot-002' });
|
|
17
|
+
fs.writeFileSync(path.join(dirtyAllocation.worktree_path, 'a.txt'), 'dirty\n');
|
|
18
|
+
const dirty = await cleanupMod.cleanupGitWorktree({ repoRoot: repo, worktreePath: dirtyAllocation.worktree_path, branch: dirtyAllocation.branch, deleteBranch: true });
|
|
19
|
+
assertGate(dirty.ok === true && dirty.action === 'retained_dirty', 'dirty worktree must be retained', dirty);
|
|
20
|
+
assertGate(fs.existsSync(dirtyAllocation.worktree_path), 'dirty worktree path must still exist');
|
|
21
|
+
assertGate(dirty.retention_lock_path && fs.existsSync(dirty.retention_lock_path), 'dirty retention lock must be written outside the retained worktree', dirty);
|
|
22
|
+
emitGate('git:worktree-cleanup', {
|
|
23
|
+
clean_action: clean.action,
|
|
24
|
+
dirty_action: dirty.action,
|
|
25
|
+
retention_lock_path: dirty.retention_lock_path
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=git-worktree-cleanup-check.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const envelopeMod = await importDist('core/git/git-worktree-patch-envelope.js');
|
|
5
|
+
const schemaMod = await importDist('core/agents/agent-patch-schema.js');
|
|
6
|
+
const envelope = envelopeMod.buildGitWorktreePatchEnvelope({
|
|
7
|
+
diff: { schema: 'sks.git-worktree-diff.v1', mission_id: 'M-env', worker_id: 'worker-1', main_repo_root: '.', worktree_path: '.', branch: null, base_head: null, worktree_head: null, changed_files: ['a.txt', 'b.txt'], diff_bytes: 12, diff: 'diff --git a/a.txt b/a.txt\n', clean: false },
|
|
8
|
+
agentId: 'agent-1',
|
|
9
|
+
sessionId: 'session-1',
|
|
10
|
+
slotId: 'slot-001',
|
|
11
|
+
generationIndex: 1
|
|
12
|
+
});
|
|
13
|
+
const validation = schemaMod.validateAgentPatchEnvelope(schemaMod.normalizeAgentPatchEnvelope(envelope));
|
|
14
|
+
assertGate(envelope.operations.length === 1 && envelope.operations[0].op === 'git_apply_patch', 'git worktree envelope must use one git_apply_patch operation', envelope);
|
|
15
|
+
assertGate(validation.ok === true, 'git_apply_patch envelope must validate', validation);
|
|
16
|
+
emitGate('git:worktree-diff-envelope', { operations: envelope.operations.length, op: envelope.operations[0].op });
|
|
17
|
+
//# sourceMappingURL=git-worktree-diff-envelope-check.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
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, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
import { makeGitFixture, run } from './lib/git-worktree-fixture.js';
|
|
8
|
+
const managerMod = await importDist('core/git/git-worktree-manager.js');
|
|
9
|
+
const diffMod = await importDist('core/git/git-worktree-diff.js');
|
|
10
|
+
const envelopeMod = await importDist('core/git/git-worktree-patch-envelope.js');
|
|
11
|
+
const schemaMod = await importDist('core/agents/agent-patch-schema.js');
|
|
12
|
+
const cleanupMod = await importDist('core/git/git-worktree-cleanup.js');
|
|
13
|
+
const repo = makeGitFixture('worktree-diff');
|
|
14
|
+
process.env.SKS_WORKTREE_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-wt-diff-'));
|
|
15
|
+
const allocation = await managerMod.allocateWorkerWorktree({ repoRoot: repo, missionId: 'M-diff', workerId: 'worker-1', slotId: 'slot-001' });
|
|
16
|
+
fs.writeFileSync(path.join(allocation.worktree_path, 'a.txt'), 'alpha\nchanged\n');
|
|
17
|
+
const diff = await diffMod.exportGitWorktreeDiff({
|
|
18
|
+
mainRepoRoot: repo,
|
|
19
|
+
worktreePath: allocation.worktree_path,
|
|
20
|
+
missionId: 'M-diff',
|
|
21
|
+
workerId: 'worker-1'
|
|
22
|
+
});
|
|
23
|
+
const envelope = envelopeMod.buildGitWorktreePatchEnvelope({
|
|
24
|
+
diff,
|
|
25
|
+
agentId: 'agent-1',
|
|
26
|
+
sessionId: 'session-1',
|
|
27
|
+
slotId: 'slot-001',
|
|
28
|
+
generationIndex: 1
|
|
29
|
+
});
|
|
30
|
+
const validation = schemaMod.validateAgentPatchEnvelope(schemaMod.normalizeAgentPatchEnvelope(envelope));
|
|
31
|
+
assertGate(diff.ok === true && diff.clean === false, 'diff export must detect changed worktree', diff);
|
|
32
|
+
assertGate(diff.changed_files.includes('a.txt'), 'diff export must include changed file', diff);
|
|
33
|
+
assertGate(/index [0-9a-f]{40}\.\.[0-9a-f]{40}/.test(diff.diff), 'diff export must use full-index diff hashes', { diff: diff.diff });
|
|
34
|
+
assertGate(envelope.source === 'git-worktree-diff' && validation.ok === true, 'git worktree diff patch envelope must validate', { envelope, validation });
|
|
35
|
+
assertGate(run('git', ['status', '--porcelain=v1'], repo).trim() === '', 'main repo must stay clean after diff export');
|
|
36
|
+
run('git', ['checkout', '--', 'a.txt'], allocation.worktree_path);
|
|
37
|
+
await cleanupMod.cleanupGitWorktree({ repoRoot: repo, worktreePath: allocation.worktree_path, branch: allocation.branch, deleteBranch: true });
|
|
38
|
+
emitGate('git:worktree-diff-export', {
|
|
39
|
+
changed_files: diff.changed_files,
|
|
40
|
+
diff_bytes: diff.diff_bytes,
|
|
41
|
+
envelope_source: envelope.source
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=git-worktree-diff-export-check.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
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, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
import { makeGitFixture } from './lib/git-worktree-fixture.js';
|
|
8
|
+
const managerMod = await importDist('core/git/git-worktree-manager.js');
|
|
9
|
+
const cleanupMod = await importDist('core/git/git-worktree-cleanup.js');
|
|
10
|
+
const repo = makeGitFixture('dirty-lock');
|
|
11
|
+
process.env.SKS_WORKTREE_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-wt-lock-'));
|
|
12
|
+
const allocation = await managerMod.allocateWorkerWorktree({ repoRoot: repo, missionId: 'M-lock', workerId: 'worker-1', slotId: 'slot-001' });
|
|
13
|
+
fs.writeFileSync(path.join(allocation.worktree_path, 'a.txt'), 'dirty\n');
|
|
14
|
+
const cleanup = await cleanupMod.cleanupGitWorktree({ repoRoot: repo, worktreePath: allocation.worktree_path, branch: allocation.branch });
|
|
15
|
+
assertGate(cleanup.action === 'retained_dirty' && cleanup.git_locked === true, 'dirty retained worktree must be git locked', cleanup);
|
|
16
|
+
emitGate('git:worktree-dirty-lock', { git_locked: cleanup.git_locked, unlock_command: cleanup.unlock_command });
|
|
17
|
+
//# sourceMappingURL=git-worktree-dirty-lock-check.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
6
|
+
import { makeGitFixture } from './lib/git-worktree-fixture.js';
|
|
7
|
+
const detectionMod = await importDist('core/git/git-repo-detection.js');
|
|
8
|
+
const repo = makeGitFixture('dirty-main-detection');
|
|
9
|
+
fs.writeFileSync(path.join(repo, 'dirty.txt'), 'dirty\n');
|
|
10
|
+
const detection = await detectionMod.detectGitRepo(repo);
|
|
11
|
+
assertGate(detection.main_worktree_dirty === true, 'dirty main worktree must be detected', detection);
|
|
12
|
+
assertGate(String(detection.status_porcelain).includes('dirty.txt'), 'status_porcelain must include dirty file', detection);
|
|
13
|
+
emitGate('git:worktree-dirty-main-detection', { dirty: detection.main_worktree_dirty });
|
|
14
|
+
//# sourceMappingURL=git-worktree-dirty-main-detection-check.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
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, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
import { makeGitFixture } from './lib/git-worktree-fixture.js';
|
|
8
|
+
const managerMod = await importDist('core/git/git-worktree-manager.js');
|
|
9
|
+
const diffMod = await importDist('core/git/git-worktree-diff.js');
|
|
10
|
+
const mergeMod = await importDist('core/git/git-worktree-merge-queue.js');
|
|
11
|
+
const repo = makeGitFixture('integration-primary');
|
|
12
|
+
process.env.SKS_WORKTREE_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-wt-integration-'));
|
|
13
|
+
const allocation = await managerMod.allocateWorkerWorktree({ repoRoot: repo, missionId: 'M-integrate', workerId: 'worker-1', slotId: 'slot-001' });
|
|
14
|
+
fs.writeFileSync(path.join(allocation.worktree_path, 'a.txt'), 'alpha\nintegrated\n');
|
|
15
|
+
const diff = await diffMod.exportGitWorktreeDiff({ mainRepoRoot: repo, worktreePath: allocation.worktree_path, missionId: 'M-integrate', workerId: 'worker-1' });
|
|
16
|
+
const integrationPath = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-integration-'));
|
|
17
|
+
fs.rmSync(integrationPath, { recursive: true, force: true });
|
|
18
|
+
const integration = await managerMod.allocateWorkerWorktree({ repoRoot: repo, missionId: 'M-integrate', workerId: 'integration', slotId: 'integration' });
|
|
19
|
+
const report = await mergeMod.applyGitWorktreeMergeQueue({ integrationWorktreePath: integration.worktree_path, diffs: [diff] });
|
|
20
|
+
assertGate(report.ok === true && report.applied_count === 1, 'git-worktree-diff must apply through merge queue', report);
|
|
21
|
+
emitGate('git:worktree-integration-primary', { applied_count: report.applied_count });
|
|
22
|
+
//# sourceMappingURL=git-worktree-integration-primary-check.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
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, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
import { makeGitFixture, run } from './lib/git-worktree-fixture.js';
|
|
8
|
+
const managerMod = await importDist('core/git/git-worktree-manager.js');
|
|
9
|
+
const cleanupMod = await importDist('core/git/git-worktree-cleanup.js');
|
|
10
|
+
const repo = makeGitFixture('worktree-manager');
|
|
11
|
+
process.env.SKS_WORKTREE_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-wt-manager-'));
|
|
12
|
+
delete process.env.SKS_ALLOW_IN_REPO_WORKTREES;
|
|
13
|
+
const allocation = await managerMod.allocateWorkerWorktree({
|
|
14
|
+
repoRoot: repo,
|
|
15
|
+
missionId: 'M-manager',
|
|
16
|
+
workerId: 'worker-1',
|
|
17
|
+
slotId: 'slot-001',
|
|
18
|
+
generationIndex: 1
|
|
19
|
+
});
|
|
20
|
+
assertGate(allocation.ok === true, 'worker worktree allocation must pass', allocation);
|
|
21
|
+
assertGate(fs.existsSync(allocation.worktree_path), 'allocated worktree path must exist', allocation);
|
|
22
|
+
assertGate(!path.resolve(allocation.worktree_path).startsWith(path.resolve(repo) + path.sep), 'worktree must be outside main repo by default', allocation);
|
|
23
|
+
assertGate(fs.existsSync(allocation.manifest_path), 'worktree manifest must be written', allocation);
|
|
24
|
+
assertGate(run('git', ['status', '--porcelain=v1'], repo).trim() === '', 'main repo must stay clean after allocation');
|
|
25
|
+
const cleanup = await cleanupMod.cleanupGitWorktree({
|
|
26
|
+
repoRoot: repo,
|
|
27
|
+
worktreePath: allocation.worktree_path,
|
|
28
|
+
branch: allocation.branch,
|
|
29
|
+
deleteBranch: true
|
|
30
|
+
});
|
|
31
|
+
assertGate(cleanup.ok === true && cleanup.action === 'removed', 'clean worktree cleanup must remove allocation', cleanup);
|
|
32
|
+
emitGate('git:worktree-manager', {
|
|
33
|
+
worktree_outside_repo: true,
|
|
34
|
+
branch: allocation.branch,
|
|
35
|
+
cleanup: cleanup.action
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=git-worktree-manager-check.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
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, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
import { makeGitFixture } from './lib/git-worktree-fixture.js';
|
|
8
|
+
const managerMod = await importDist('core/git/git-worktree-manager.js');
|
|
9
|
+
const repo = makeGitFixture('worktree-manifest-append');
|
|
10
|
+
process.env.SKS_WORKTREE_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-wt-manifest-'));
|
|
11
|
+
const allocations = [];
|
|
12
|
+
for (let index = 0; index < 4; index += 1) {
|
|
13
|
+
allocations.push(await managerMod.allocateWorkerWorktree({ repoRoot: repo, missionId: 'M-manifest', workerId: `worker-${index}`, slotId: `slot-${index}` }));
|
|
14
|
+
}
|
|
15
|
+
const manifest = JSON.parse(fs.readFileSync(allocations[0].manifest_path, 'utf8'));
|
|
16
|
+
assertGate(manifest.allocations.length >= allocations.length, 'manifest append must preserve allocations', manifest);
|
|
17
|
+
emitGate('git:worktree-manifest-append', { allocations: manifest.allocations.length });
|
|
18
|
+
//# sourceMappingURL=git-worktree-manifest-append-check.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
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, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
import { makeGitFixture } from './lib/git-worktree-fixture.js';
|
|
8
|
+
const managerMod = await importDist('core/git/git-worktree-manager.js');
|
|
9
|
+
const diffMod = await importDist('core/git/git-worktree-diff.js');
|
|
10
|
+
const integrationMod = await importDist('core/git/git-integration-worktree.js');
|
|
11
|
+
const queueMod = await importDist('core/git/git-worktree-merge-queue.js');
|
|
12
|
+
const repo = makeGitFixture('worktree-merge');
|
|
13
|
+
process.env.SKS_WORKTREE_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-wt-merge-'));
|
|
14
|
+
const a = await managerMod.allocateWorkerWorktree({ repoRoot: repo, missionId: 'M-merge', workerId: 'a', slotId: 'slot-001' });
|
|
15
|
+
const b = await managerMod.allocateWorkerWorktree({ repoRoot: repo, missionId: 'M-merge', workerId: 'b', slotId: 'slot-002' });
|
|
16
|
+
fs.writeFileSync(path.join(a.worktree_path, 'a.txt'), 'alpha\nfrom-a\n');
|
|
17
|
+
fs.writeFileSync(path.join(b.worktree_path, 'b.txt'), 'bravo\nfrom-b\n');
|
|
18
|
+
const diffA = await diffMod.exportGitWorktreeDiff({ mainRepoRoot: repo, worktreePath: a.worktree_path, missionId: 'M-merge', workerId: 'a' });
|
|
19
|
+
const diffB = await diffMod.exportGitWorktreeDiff({ mainRepoRoot: repo, worktreePath: b.worktree_path, missionId: 'M-merge', workerId: 'b' });
|
|
20
|
+
const integration = await integrationMod.createGitIntegrationWorktree({ repoRoot: repo, missionId: 'M-merge' });
|
|
21
|
+
const report = await queueMod.applyGitWorktreeMergeQueue({ integrationWorktreePath: integration.worktree_path, diffs: [diffA, diffB] });
|
|
22
|
+
assertGate(report.ok === true && report.applied_count === 2, 'merge queue must apply non-conflicting worktree diffs', report);
|
|
23
|
+
assertGate(fs.readFileSync(path.join(integration.worktree_path, 'a.txt'), 'utf8').includes('from-a'), 'integration worktree must include first diff');
|
|
24
|
+
assertGate(fs.readFileSync(path.join(integration.worktree_path, 'b.txt'), 'utf8').includes('from-b'), 'integration worktree must include second diff');
|
|
25
|
+
assertGate(fs.readFileSync(path.join(repo, 'a.txt'), 'utf8') === 'alpha\n', 'main worktree must remain unchanged before integration commit');
|
|
26
|
+
emitGate('git:worktree-merge-queue', {
|
|
27
|
+
applied_count: report.applied_count,
|
|
28
|
+
changed_files: report.changed_files
|
|
29
|
+
});
|
|
30
|
+
//# sourceMappingURL=git-worktree-merge-queue-check.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const poolMod = await importDist('core/git/git-worktree-pool.js');
|
|
5
|
+
const workerIds = Array.from({ length: 100 }, (_, index) => `worker-${index + 1}`);
|
|
6
|
+
const reusable = Array.from({ length: 32 }, (_, index) => `/tmp/reuse-${index + 1}`);
|
|
7
|
+
const start = Date.now();
|
|
8
|
+
const plan = poolMod.planGitWorktreePool({ workerIds, reusableWorktrees: reusable });
|
|
9
|
+
const elapsed = Date.now() - start;
|
|
10
|
+
assertGate(plan.ok === true, 'pool plan must pass', plan);
|
|
11
|
+
assertGate(plan.assignments.length === 100, 'pool must assign every requested worker', plan);
|
|
12
|
+
assertGate(plan.assignments.filter((row) => row.action === 'reuse').length === 32, 'pool must reuse available worktrees first', plan);
|
|
13
|
+
assertGate(plan.allocate_count === 68, 'pool must allocate only the remaining workers', plan);
|
|
14
|
+
assertGate(elapsed < 100, 'pool plan must stay fast for 100 workers', { elapsed });
|
|
15
|
+
emitGate('git:worktree-pool-performance', {
|
|
16
|
+
elapsed_ms: elapsed,
|
|
17
|
+
reusable: 32,
|
|
18
|
+
allocate_count: plan.allocate_count
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=git-worktree-pool-performance-check.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
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, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
import { makeGitFixture } from './lib/git-worktree-fixture.js';
|
|
8
|
+
const managerMod = await importDist('core/git/git-worktree-manager.js');
|
|
9
|
+
const diffMod = await importDist('core/git/git-worktree-diff.js');
|
|
10
|
+
const repo = makeGitFixture('untracked-diff');
|
|
11
|
+
process.env.SKS_WORKTREE_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-wt-untracked-'));
|
|
12
|
+
const allocation = await managerMod.allocateWorkerWorktree({ repoRoot: repo, missionId: 'M-untracked', workerId: 'worker-1', slotId: 'slot-001' });
|
|
13
|
+
fs.writeFileSync(path.join(allocation.worktree_path, 'new-file.txt'), 'new content\n');
|
|
14
|
+
const diff = await diffMod.exportGitWorktreeDiff({ mainRepoRoot: repo, worktreePath: allocation.worktree_path, missionId: 'M-untracked', workerId: 'worker-1' });
|
|
15
|
+
assertGate(diff.changed_files.includes('new-file.txt'), 'changed files must include untracked file', diff);
|
|
16
|
+
assertGate(diff.diff.includes('new file mode') && diff.diff.includes('+new content'), 'git diff must include untracked file content', { diff: diff.diff });
|
|
17
|
+
emitGate('git:worktree-untracked-diff', { changed_files: diff.changed_files });
|
|
18
|
+
//# sourceMappingURL=git-worktree-untracked-diff-check.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
export function makeGitFixture(name) {
|
|
6
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), `sks-${name}-`));
|
|
7
|
+
run('git', ['init'], root);
|
|
8
|
+
run('git', ['config', 'user.email', 'sks@example.invalid'], root);
|
|
9
|
+
run('git', ['config', 'user.name', 'SKS Test'], root);
|
|
10
|
+
fs.writeFileSync(path.join(root, 'a.txt'), 'alpha\n');
|
|
11
|
+
fs.writeFileSync(path.join(root, 'b.txt'), 'bravo\n');
|
|
12
|
+
run('git', ['add', 'a.txt', 'b.txt'], root);
|
|
13
|
+
run('git', ['commit', '-m', 'fixture'], root);
|
|
14
|
+
return root;
|
|
15
|
+
}
|
|
16
|
+
export function makeNonGitFixture(name) {
|
|
17
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), `sks-${name}-`));
|
|
18
|
+
fs.writeFileSync(path.join(root, 'plain.txt'), 'not git\n');
|
|
19
|
+
return root;
|
|
20
|
+
}
|
|
21
|
+
export function run(command, args, cwd, input) {
|
|
22
|
+
const result = spawnSync(command, args, {
|
|
23
|
+
cwd,
|
|
24
|
+
input,
|
|
25
|
+
encoding: 'utf8',
|
|
26
|
+
stdio: input === undefined ? ['ignore', 'pipe', 'pipe'] : ['pipe', 'pipe', 'pipe']
|
|
27
|
+
});
|
|
28
|
+
if (result.status !== 0) {
|
|
29
|
+
throw new Error(`${command} ${args.join(' ')} failed in ${cwd}: ${result.stderr || result.stdout}`);
|
|
30
|
+
}
|
|
31
|
+
return result.stdout || '';
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=git-worktree-fixture.js.map
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// schedules >20 concurrent clone sessions to completion with proof.
|
|
7
7
|
import { spawnSync } from 'node:child_process';
|
|
8
8
|
import fs from 'node:fs';
|
|
9
|
+
import os from 'node:os';
|
|
9
10
|
import path from 'node:path';
|
|
10
11
|
import { assertGate, emitGate, importDist, root, exists } from './sks-1-18-gate-lib.js';
|
|
11
12
|
const schema = await importDist('core/agents/agent-schema.js');
|
|
@@ -71,8 +72,10 @@ assertGate(bigMemoryHost.cap >= 64, 'a 64 GB host must allow >= 64 parallel code
|
|
|
71
72
|
// concurrency is throttled to the host-safe cap (never the full 24 unless the host allows).
|
|
72
73
|
const proofClones = 24;
|
|
73
74
|
const cli = path.join(root, 'dist', 'bin', 'sks.js');
|
|
75
|
+
const isolatedWorktreeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-naruto-shadow-wt-'));
|
|
76
|
+
const childEnv = { ...process.env, SKS_WORKTREE_ROOT: isolatedWorktreeRoot };
|
|
74
77
|
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 });
|
|
78
|
+
const helpRun = spawnSync(process.execPath, [cli, 'naruto', '--help', '--json'], { cwd: root, env: childEnv, encoding: 'utf8', timeout: 30000, maxBuffer: 1024 * 1024 });
|
|
76
79
|
const helpParsed = parseJson(helpRun.stdout);
|
|
77
80
|
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) });
|
|
78
81
|
const run = spawnSync(process.execPath, [
|
|
@@ -81,7 +84,7 @@ const run = spawnSync(process.execPath, [
|
|
|
81
84
|
'--backend', 'fake',
|
|
82
85
|
'--work-items', String(proofClones),
|
|
83
86
|
'--json'
|
|
84
|
-
], { cwd: root, encoding: 'utf8', timeout: 240000, maxBuffer: 8 * 1024 * 1024 });
|
|
87
|
+
], { cwd: root, env: childEnv, encoding: 'utf8', timeout: 240000, maxBuffer: 8 * 1024 * 1024 });
|
|
85
88
|
assertGate(run.status === 0, 'sks naruto run must exit 0', { status: run.status, stderr: tail(run.stderr) });
|
|
86
89
|
const parsed = parseJson(run.stdout);
|
|
87
90
|
assertGate(parsed !== null, 'sks naruto run must emit JSON', { stdout: tail(run.stdout) });
|
|
@@ -109,11 +112,11 @@ assertGate(new Set(writePaths).size > 1, 'naruto command default patch-envelope
|
|
|
109
112
|
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) });
|
|
110
113
|
const state = parsed.run?.scheduler?.state || parsed.run?.scheduler || {};
|
|
111
114
|
assertGate(Number(state.completed_count) === proofClones, 'all clone work items must complete despite throttling', { completed_count: state.completed_count });
|
|
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 });
|
|
115
|
+
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 });
|
|
113
116
|
const explicitParsed = parseJson(explicitConcurrency.stdout);
|
|
114
117
|
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 });
|
|
115
118
|
// 7) A small request is NOT throttled below what was asked (cap only ever reduces, never inflates).
|
|
116
|
-
const small = spawnSync(process.execPath, [cli, 'naruto', 'run', 'tiny', '--clones', '2', '--backend', 'fake', '--work-items', '2', '--json'], { cwd: root, encoding: 'utf8', timeout: 120000, maxBuffer: 4 * 1024 * 1024 });
|
|
119
|
+
const small = spawnSync(process.execPath, [cli, 'naruto', 'run', 'tiny', '--clones', '2', '--backend', 'fake', '--work-items', '2', '--json'], { cwd: root, env: childEnv, encoding: 'utf8', timeout: 120000, maxBuffer: 4 * 1024 * 1024 });
|
|
117
120
|
const smallParsed = parseJson(small.stdout);
|
|
118
121
|
assertGate(small.status === 0 && smallParsed?.target_active_slots === 2, 'a 2-clone run must run 2 concurrently (no over-throttle)', { status: small.status, target_active_slots: smallParsed?.target_active_slots });
|
|
119
122
|
emitGate('naruto:shadow-clone-swarm', {
|
|
@@ -128,7 +131,8 @@ emitGate('naruto:shadow-clone-swarm', {
|
|
|
128
131
|
low_free_capable_cap: lowFreeButCapable.cap,
|
|
129
132
|
cores: heavySafe.cores,
|
|
130
133
|
completed_count: state.completed_count,
|
|
131
|
-
mission_id: parsed.mission_id
|
|
134
|
+
mission_id: parsed.mission_id,
|
|
135
|
+
isolated_worktree_root: isolatedWorktreeRoot
|
|
132
136
|
});
|
|
133
137
|
function parseJson(text) {
|
|
134
138
|
try {
|
|
@@ -0,0 +1,29 @@
|
|
|
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, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
import { makeGitFixture, run } from './lib/git-worktree-fixture.js';
|
|
8
|
+
const managerMod = await importDist('core/git/git-worktree-manager.js');
|
|
9
|
+
const diffMod = await importDist('core/git/git-worktree-diff.js');
|
|
10
|
+
const mergeMod = await importDist('core/git/git-worktree-merge-queue.js');
|
|
11
|
+
const repo = makeGitFixture('naruto-worktree-blackbox');
|
|
12
|
+
process.env.SKS_WORKTREE_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-naruto-blackbox-'));
|
|
13
|
+
const allocations = [];
|
|
14
|
+
for (const file of ['a.txt', 'b.txt']) {
|
|
15
|
+
const allocation = await managerMod.allocateWorkerWorktree({ repoRoot: repo, missionId: 'M-naruto-blackbox', workerId: file.replace('.txt', ''), slotId: file.replace('.txt', '') });
|
|
16
|
+
fs.writeFileSync(path.join(allocation.worktree_path, file), `${file}\nworker-change\n`);
|
|
17
|
+
allocations.push(allocation);
|
|
18
|
+
}
|
|
19
|
+
assertGate(run('git', ['status', '--porcelain=v1'], repo).trim() === '', 'main worktree must remain unchanged before integration');
|
|
20
|
+
const diffs = [];
|
|
21
|
+
for (const allocation of allocations) {
|
|
22
|
+
diffs.push(await diffMod.exportGitWorktreeDiff({ mainRepoRoot: repo, worktreePath: allocation.worktree_path, missionId: 'M-naruto-blackbox', workerId: allocation.worker_id }));
|
|
23
|
+
}
|
|
24
|
+
const integration = await managerMod.allocateWorkerWorktree({ repoRoot: repo, missionId: 'M-naruto-blackbox', workerId: 'integration', slotId: 'integration' });
|
|
25
|
+
const report = await mergeMod.applyGitWorktreeMergeQueue({ integrationWorktreePath: integration.worktree_path, diffs });
|
|
26
|
+
assertGate(report.ok === true && report.applied_count === 2, 'integration worktree merge report must apply worker diffs', report);
|
|
27
|
+
assertGate(run('git', ['status', '--porcelain=v1'], repo).trim() === '', 'main worktree must remain unchanged after integration queue');
|
|
28
|
+
emitGate('naruto:worktree-coding:blackbox', { allocations: allocations.length, applied_count: report.applied_count });
|
|
29
|
+
//# sourceMappingURL=naruto-worktree-coding-blackbox.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
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, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
import { makeGitFixture, makeNonGitFixture } from './lib/git-worktree-fixture.js';
|
|
8
|
+
const capabilityMod = await importDist('core/git/git-worktree-capability.js');
|
|
9
|
+
const workGraphMod = await importDist('core/naruto/naruto-work-graph.js');
|
|
10
|
+
const activePoolMod = await importDist('core/naruto/naruto-active-pool.js');
|
|
11
|
+
const governorMod = await importDist('core/naruto/naruto-concurrency-governor.js');
|
|
12
|
+
const repo = makeGitFixture('naruto-worktree-coding');
|
|
13
|
+
process.env.SKS_WORKTREE_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-naruto-wt-'));
|
|
14
|
+
const capability = await capabilityMod.evaluateGitWorktreeCapability({ root: repo, missionId: 'M-naruto-wt', requireGitWorktree: process.argv.includes('--require-real') });
|
|
15
|
+
const policy = {
|
|
16
|
+
mode: capability.mode,
|
|
17
|
+
required: capability.mode === 'git-worktree',
|
|
18
|
+
main_repo_root: capability.detection.root,
|
|
19
|
+
worktree_root: capability.root_resolution?.root || null,
|
|
20
|
+
fallback_reason: capability.mode === 'git-worktree' ? null : capability.blockers.join(';')
|
|
21
|
+
};
|
|
22
|
+
const graph = workGraphMod.buildNarutoWorkGraph({
|
|
23
|
+
requestedClones: 8,
|
|
24
|
+
totalWorkItems: 12,
|
|
25
|
+
writeCapable: true,
|
|
26
|
+
targetPaths: Array.from({ length: 12 }, (_, index) => `src/wt-${index}.ts`),
|
|
27
|
+
maxActiveWorkers: 4,
|
|
28
|
+
worktreePolicy: policy
|
|
29
|
+
});
|
|
30
|
+
const governor = governorMod.decideNarutoConcurrency({ requestedClones: 8, totalWorkItems: 12, pendingWorkQueueSize: 12, backend: 'fake' });
|
|
31
|
+
const pool = await activePoolMod.runNarutoActivePool({ graph, governor: { ...governor, safe_active_workers: 4 } });
|
|
32
|
+
assertGate(capability.ok === true && capability.mode === 'git-worktree', 'Git Naruto coding fixture must use git-worktree mode', capability);
|
|
33
|
+
assertGate(graph.worktree_policy.mode === 'git-worktree', 'Naruto work graph must carry git-worktree policy', graph.worktree_policy);
|
|
34
|
+
assertGate(graph.work_items.filter((item) => item.write_allowed).every((item) => item.worktree?.allocation_required === true), 'write-capable work items must require worktree allocation', graph.work_items);
|
|
35
|
+
assertGate(pool.worktree_allocation_required_count > 0, 'active pool must plan worktree allocations for write work', pool);
|
|
36
|
+
const nonGit = makeNonGitFixture('naruto-worktree-non-git');
|
|
37
|
+
const nonGitCapability = await capabilityMod.evaluateGitWorktreeCapability({ root: nonGit, missionId: 'M-naruto-non-git' });
|
|
38
|
+
assertGate(nonGitCapability.mode === 'patch-envelope-only' && nonGitCapability.worktree_probe_attempted === false, 'non-Git Naruto must degrade without worktree probe', nonGitCapability);
|
|
39
|
+
emitGate('naruto:worktree-coding', {
|
|
40
|
+
worktree_mode: graph.worktree_policy.mode,
|
|
41
|
+
allocation_required_count: pool.worktree_allocation_required_count,
|
|
42
|
+
non_git_mode: nonGitCapability.mode
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=naruto-worktree-coding-check.js.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const workGraphMod = await importDist('core/naruto/naruto-work-graph.js');
|
|
5
|
+
const rolesMod = await importDist('core/naruto/naruto-role-policy.js');
|
|
6
|
+
const packMod = await importDist('core/naruto/naruto-gpt-final-pack.js');
|
|
7
|
+
const policy = {
|
|
8
|
+
mode: 'git-worktree',
|
|
9
|
+
required: true,
|
|
10
|
+
main_repo_root: '/repo',
|
|
11
|
+
worktree_root: '/cache/sks/worktrees/repo/M-final',
|
|
12
|
+
fallback_reason: null
|
|
13
|
+
};
|
|
14
|
+
const graph = workGraphMod.buildNarutoWorkGraph({ requestedClones: 6, totalWorkItems: 8, writeCapable: true, worktreePolicy: policy });
|
|
15
|
+
const roleDistribution = rolesMod.buildNarutoRoleDistribution(graph.work_items);
|
|
16
|
+
const worktreeDiff = {
|
|
17
|
+
schema: 'sks.git-worktree-diff.v1',
|
|
18
|
+
ok: true,
|
|
19
|
+
mission_id: 'M-final',
|
|
20
|
+
worker_id: 'worker-1',
|
|
21
|
+
main_repo_root: '/repo',
|
|
22
|
+
worktree_path: '/cache/wt/worker-1',
|
|
23
|
+
branch: 'sks/M/worker-1',
|
|
24
|
+
changed_files: ['src/a.ts'],
|
|
25
|
+
diff: 'diff --git a/src/a.ts b/src/a.ts\n',
|
|
26
|
+
diff_bytes: 37
|
|
27
|
+
};
|
|
28
|
+
const pack = packMod.buildNarutoGptFinalPack({
|
|
29
|
+
missionId: 'M-final',
|
|
30
|
+
graph,
|
|
31
|
+
roleDistribution,
|
|
32
|
+
changedFiles: ['src/a.ts'],
|
|
33
|
+
worktreePolicy: policy,
|
|
34
|
+
worktreeDiffs: [worktreeDiff],
|
|
35
|
+
localLlmMetrics: { participated: true, final_status: 'draft_until_gpt_final' }
|
|
36
|
+
});
|
|
37
|
+
assertGate(pack.worktree_policy.mode === 'git-worktree', 'GPT final pack must include worktree policy', pack.worktree_policy);
|
|
38
|
+
assertGate(pack.worktree_diffs.length === 1, 'GPT final pack must include bounded worktree diffs', pack);
|
|
39
|
+
assertGate(pack.local_llm_metrics.final_status === 'draft_until_gpt_final', 'local LLM output must remain draft until GPT final', pack.local_llm_metrics);
|
|
40
|
+
assertGate(pack.bounded === true && pack.secrets_redacted === true, 'GPT final pack must stay bounded/redacted', pack);
|
|
41
|
+
emitGate('naruto:worktree-gpt-final', {
|
|
42
|
+
worktree_mode: pack.worktree_policy.mode,
|
|
43
|
+
worktree_diffs: pack.worktree_diffs.length
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=naruto-worktree-gpt-final-check.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
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: 10,
|
|
7
|
+
visiblePaneCap: 6,
|
|
8
|
+
roles: ['implementer', 'verifier'],
|
|
9
|
+
backend: 'codex-sdk',
|
|
10
|
+
worktreePolicy: {
|
|
11
|
+
mode: 'git-worktree',
|
|
12
|
+
required: true,
|
|
13
|
+
main_repo_root: '/repo',
|
|
14
|
+
worktree_root: '/cache/sks/worktrees/repo/M',
|
|
15
|
+
fallback_reason: null
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
assertGate(plan.ok === true, 'Naruto worktree Zellij dashboard must pass', plan);
|
|
19
|
+
assertGate(plan.worktree_mode === 'git-worktree', 'dashboard must carry worktree mode', plan);
|
|
20
|
+
assertGate(plan.worktree_labels.length === plan.visible_worker_panes, 'visible panes must have worktree labels', plan);
|
|
21
|
+
assertGate(plan.pane_titles.every((title) => title.includes('WT:') && title.includes('branch:')), 'pane titles must include worktree id and branch', plan.pane_titles);
|
|
22
|
+
assertGate(plan.headless_workers === 4, 'dashboard must still expose headless worker count', plan);
|
|
23
|
+
emitGate('naruto:worktree-zellij-ui', {
|
|
24
|
+
visible_worker_panes: plan.visible_worker_panes,
|
|
25
|
+
headless_workers: plan.headless_workers,
|
|
26
|
+
sample_title: plan.pane_titles[0]
|
|
27
|
+
});
|
|
28
|
+
//# sourceMappingURL=naruto-worktree-zellij-ui-check.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate, readJson, readText } from './sks-1-18-gate-lib.js';
|
|
4
|
+
const pkg = readJson('package.json');
|
|
5
|
+
const manifest = readJson('release-gates.v2.json');
|
|
6
|
+
const runner = readText('src/core/release/release-gate-dag.ts');
|
|
7
|
+
const scheduler = readText('src/core/release/release-gate-scheduler.ts');
|
|
8
|
+
const cache = readText('src/core/release/release-gate-cache-v2.ts');
|
|
9
|
+
assertGate(pkg.scripts['release:check'].includes('release-gate-dag-runner.js'), 'release:check must execute DAG runner', pkg.scripts['release:check']);
|
|
10
|
+
assertGate(!/&&\s*npm run\s+\w/.test(pkg.scripts['release:check'].replace('npm run build --silent &&', '')), 'release:check must not be a giant npm-run chain', pkg.scripts['release:check']);
|
|
11
|
+
assertGate(pkg.scripts['release:check:legacy'], 'release:check:legacy must exist for explicit debugging');
|
|
12
|
+
assertGate(manifest.schema === 'sks.release-gates.v2' && manifest.gates.length >= 10, 'release-gates.v2 manifest must exist with nodes', manifest);
|
|
13
|
+
assertGate(runner.includes('Promise.race') && scheduler.includes('pickLaunchableReleaseGates'), 'DAG runner must schedule independent gates concurrently');
|
|
14
|
+
assertGate(runner.includes('readReleaseGateCacheHit') && cache.includes('RELEASE_GATE_CACHE_V2_SCHEMA'), 'DAG runner must use release gate cache v2 module');
|
|
15
|
+
assertGate(runner.includes('cpu_time_saved_ms') && runner.includes('peak_running') && runner.includes('budget_snapshot'), 'DAG summary must include CPU time saved, peak running gates, and resource budget proof');
|
|
16
|
+
emitGate('release:dag-runner', { gates: manifest.gates.length, default_script: pkg.scripts['release:check'] });
|
|
17
|
+
//# sourceMappingURL=release-gate-dag-runner-check.js.map
|