sneakoscope 2.0.8 → 2.0.9
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 +1 -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 +20 -8
- package/dist/commands/zellij.js +144 -1
- package/dist/core/agents/agent-orchestrator.js +4 -2
- package/dist/core/agents/native-cli-session-swarm.js +76 -9
- package/dist/core/commands/mad-sks-command.js +17 -26
- package/dist/core/commands/naruto-command.js +99 -36
- package/dist/core/fsx.js +1 -1
- package/dist/core/naruto/naruto-active-pool.js +108 -0
- package/dist/core/naruto/naruto-concurrency-governor.js +16 -1
- package/dist/core/naruto/naruto-work-graph.js +2 -1
- package/dist/core/release/release-gate-cache-v2.js +58 -4
- package/dist/core/release/release-gate-dag.js +36 -25
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-dashboard-renderer.js +22 -6
- package/dist/core/zellij/zellij-launcher.js +3 -3
- package/dist/core/zellij/zellij-layout-builder.js +1 -1
- package/dist/core/zellij/zellij-right-column-layout-proof.js +42 -0
- package/dist/core/zellij/zellij-right-column-manager.js +245 -0
- package/dist/core/zellij/zellij-worker-pane-manager.js +118 -13
- package/dist/scripts/codex-sdk-release-review-pipeline-check.js +5 -5
- package/dist/scripts/doctor-fix-proves-codex-read-check.js +26 -5
- package/dist/scripts/lib/codex-sdk-gate-lib.js +4 -0
- package/dist/scripts/mad-sks-zellij-default-pane-worker-check.js +2 -2
- package/dist/scripts/naruto-concurrency-governor-check.js +2 -1
- package/dist/scripts/naruto-extreme-parallelism-check.js +22 -0
- package/dist/scripts/naruto-real-active-pool-check.js +38 -0
- package/dist/scripts/naruto-work-graph-check.js +1 -1
- package/dist/scripts/naruto-zellij-dynamic-right-column-check.js +21 -0
- package/dist/scripts/product-design-auto-install-check.js +3 -3
- package/dist/scripts/product-design-plugin-routing-check.js +3 -3
- package/dist/scripts/release-cache-glob-hashing-check.js +42 -0
- package/dist/scripts/release-dag-full-coverage-check.js +35 -0
- package/dist/scripts/release-parallel-speed-budget-check.js +67 -13
- package/dist/scripts/release-readiness-report.js +1 -1
- package/dist/scripts/zellij-dashboard-pane-check.js +6 -4
- package/dist/scripts/zellij-developer-controls-check.js +20 -0
- package/dist/scripts/zellij-dynamic-pane-lifecycle-check.js +21 -0
- package/dist/scripts/zellij-initial-main-only-blackbox.js +28 -0
- package/dist/scripts/zellij-right-column-geometry-proof.js +29 -0
- package/dist/scripts/zellij-right-column-manager-check.js +22 -0
- package/dist/scripts/zellij-worker-pane-manager-check.js +2 -1
- package/dist/scripts/zellij-worker-pane-manager-single-owner-check.js +7 -6
- package/package.json +13 -3
- package/schemas/zellij/zellij-right-column-state.schema.json +41 -0
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
|
|
|
16
16
|
|
|
17
17
|
## Current Release
|
|
18
18
|
|
|
19
|
-
SKS **2.0.
|
|
19
|
+
SKS **2.0.9** makes the release path DAG-parallel by default and hardens the Naruto/MAD-SKS worktree proof chain. `release:check` now runs a manifest-backed DAG runner with resource-aware scheduling, hermetic per-gate environments, bounded logs, per-gate reports, cache proof, and parallel speed-budget evidence. Git worktree coding now preserves allocation manifests, detects dirty main worktrees, includes untracked content in exported diffs, emits one `git_apply_patch` envelope operation, applies worktree diffs through an integration queue, and locks retained dirty worktrees.
|
|
20
20
|
|
|
21
21
|
What changed:
|
|
22
22
|
|
|
@@ -4,7 +4,7 @@ use std::io::{self, Read, Seek, SeekFrom};
|
|
|
4
4
|
fn main() {
|
|
5
5
|
let mut args = std::env::args().skip(1);
|
|
6
6
|
match args.next().as_deref() {
|
|
7
|
-
Some("--version") => println!("sks-rs 2.0.
|
|
7
|
+
Some("--version") => println!("sks-rs 2.0.9"),
|
|
8
8
|
Some("compact-info") => {
|
|
9
9
|
let mut input = String::new();
|
|
10
10
|
let _ = io::stdin().read_to_string(&mut input);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "sks.dist-build-stamp.v1",
|
|
3
3
|
"package_name": "sneakoscope",
|
|
4
|
-
"package_version": "2.0.
|
|
5
|
-
"source_digest": "
|
|
6
|
-
"source_file_count":
|
|
7
|
-
"built_at_source_time":
|
|
4
|
+
"package_version": "2.0.9",
|
|
5
|
+
"source_digest": "a2c7c47838f03483ee3a406fe6435876148d688fa16037d1b4eab45da1f930c4",
|
|
6
|
+
"source_file_count": 2017,
|
|
7
|
+
"built_at_source_time": 1780749751025
|
|
8
8
|
}
|
package/dist/bin/sks.js
CHANGED
package/dist/build-manifest.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "sks.dist-build.v2",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"package_version": "2.0.
|
|
3
|
+
"version": "2.0.9",
|
|
4
|
+
"package_version": "2.0.9",
|
|
5
5
|
"typescript": true,
|
|
6
6
|
"mjs_runtime_files": 0,
|
|
7
|
-
"compiled_file_count":
|
|
8
|
-
"compiled_js_count":
|
|
7
|
+
"compiled_file_count": 1079,
|
|
8
|
+
"compiled_js_count": 1079,
|
|
9
9
|
"compiled_dts_count": 0,
|
|
10
|
-
"source_digest": "
|
|
11
|
-
"source_file_count":
|
|
12
|
-
"source_files_hash": "
|
|
13
|
-
"source_list_hash": "
|
|
10
|
+
"source_digest": "a2c7c47838f03483ee3a406fe6435876148d688fa16037d1b4eab45da1f930c4",
|
|
11
|
+
"source_file_count": 2017,
|
|
12
|
+
"source_files_hash": "b69bf6184e62a1136caf9dc353eea79dcae63e3ba260a10fbc8eb6a38de7541a",
|
|
13
|
+
"source_list_hash": "b69bf6184e62a1136caf9dc353eea79dcae63e3ba260a10fbc8eb6a38de7541a",
|
|
14
14
|
"src_mjs_runtime_files": 0,
|
|
15
15
|
"dist_stamp_schema": "sks.dist-build-stamp.v1",
|
|
16
16
|
"files": [
|
|
@@ -631,6 +631,8 @@
|
|
|
631
631
|
"core/zellij/zellij-layout-builder.js",
|
|
632
632
|
"core/zellij/zellij-naruto-dashboard.js",
|
|
633
633
|
"core/zellij/zellij-pane-proof.js",
|
|
634
|
+
"core/zellij/zellij-right-column-layout-proof.js",
|
|
635
|
+
"core/zellij/zellij-right-column-manager.js",
|
|
634
636
|
"core/zellij/zellij-screen-proof.js",
|
|
635
637
|
"core/zellij/zellij-worker-pane-manager.js",
|
|
636
638
|
"scripts/agent-ast-aware-work-graph-check.js",
|
|
@@ -922,9 +924,11 @@
|
|
|
922
924
|
"scripts/mutation-callsite-coverage-check.js",
|
|
923
925
|
"scripts/naruto-active-pool-check.js",
|
|
924
926
|
"scripts/naruto-concurrency-governor-check.js",
|
|
927
|
+
"scripts/naruto-extreme-parallelism-check.js",
|
|
925
928
|
"scripts/naruto-gpt-final-pack-check.js",
|
|
926
929
|
"scripts/naruto-parallel-patch-apply-check.js",
|
|
927
930
|
"scripts/naruto-readonly-routing-check.js",
|
|
931
|
+
"scripts/naruto-real-active-pool-check.js",
|
|
928
932
|
"scripts/naruto-real-local-gpt-final-smoke.js",
|
|
929
933
|
"scripts/naruto-role-distribution-check.js",
|
|
930
934
|
"scripts/naruto-shadow-clone-swarm-check.js",
|
|
@@ -934,6 +938,7 @@
|
|
|
934
938
|
"scripts/naruto-worktree-coding-check.js",
|
|
935
939
|
"scripts/naruto-worktree-gpt-final-check.js",
|
|
936
940
|
"scripts/naruto-worktree-zellij-ui-check.js",
|
|
941
|
+
"scripts/naruto-zellij-dynamic-right-column-check.js",
|
|
937
942
|
"scripts/naruto-zellij-massive-ui-check.js",
|
|
938
943
|
"scripts/non-recursive-pipeline-check.js",
|
|
939
944
|
"scripts/npm-publish-performance-check.js",
|
|
@@ -973,9 +978,11 @@
|
|
|
973
978
|
"scripts/qa-backfill-route-blackbox.js",
|
|
974
979
|
"scripts/qa-patch-swarm-route-blackbox.js",
|
|
975
980
|
"scripts/readme-architecture-imagegen-official-check.js",
|
|
981
|
+
"scripts/release-cache-glob-hashing-check.js",
|
|
976
982
|
"scripts/release-check-dynamic-execute.js",
|
|
977
983
|
"scripts/release-check-dynamic.js",
|
|
978
984
|
"scripts/release-check-stamp.js",
|
|
985
|
+
"scripts/release-dag-full-coverage-check.js",
|
|
979
986
|
"scripts/release-dist-freshness-check.js",
|
|
980
987
|
"scripts/release-dynamic-performance-check.js",
|
|
981
988
|
"scripts/release-gate-budget-check.js",
|
|
@@ -1067,7 +1074,10 @@
|
|
|
1067
1074
|
"scripts/zellij-capability-check.js",
|
|
1068
1075
|
"scripts/zellij-dashboard-pane-check.js",
|
|
1069
1076
|
"scripts/zellij-dashboard-watch.js",
|
|
1077
|
+
"scripts/zellij-developer-controls-check.js",
|
|
1070
1078
|
"scripts/zellij-doctor-readiness-check.js",
|
|
1079
|
+
"scripts/zellij-dynamic-pane-lifecycle-check.js",
|
|
1080
|
+
"scripts/zellij-initial-main-only-blackbox.js",
|
|
1071
1081
|
"scripts/zellij-lane-renderer-check.js",
|
|
1072
1082
|
"scripts/zellij-launch-command-truth-check.js",
|
|
1073
1083
|
"scripts/zellij-layout-valid-check.js",
|
|
@@ -1075,6 +1085,8 @@
|
|
|
1075
1085
|
"scripts/zellij-real-session-cleanup-check.js",
|
|
1076
1086
|
"scripts/zellij-real-session-heartbeat-check.js",
|
|
1077
1087
|
"scripts/zellij-real-session-launch-check.js",
|
|
1088
|
+
"scripts/zellij-right-column-geometry-proof.js",
|
|
1089
|
+
"scripts/zellij-right-column-manager-check.js",
|
|
1078
1090
|
"scripts/zellij-screen-proof-check.js",
|
|
1079
1091
|
"scripts/zellij-spawn-on-demand-layout-check.js",
|
|
1080
1092
|
"scripts/zellij-ui-design-check.js",
|
package/dist/commands/zellij.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs';
|
|
2
3
|
import { projectRoot, readJson } from '../core/fsx.js';
|
|
3
4
|
import { flag } from '../cli/args.js';
|
|
4
5
|
import { printJson } from '../cli/output.js';
|
|
5
6
|
import { checkZellijCapability } from '../core/zellij/zellij-capability.js';
|
|
6
7
|
import { runZellij } from '../core/zellij/zellij-command.js';
|
|
7
8
|
import { appendZellijLaneCommand, normalizeZellijSlot } from '../core/zellij/zellij-lane-runtime.js';
|
|
9
|
+
import { buildZellijDashboardSnapshot, renderZellijDashboardText } from '../core/zellij/zellij-dashboard-renderer.js';
|
|
8
10
|
export const ZELLIJ_COMMAND_SCHEMA = 'sks.zellij-command.v1';
|
|
9
11
|
export const ZELLIJ_REPAIR_SCHEMA = 'sks.zellij-repair.v1';
|
|
10
12
|
function installHint() {
|
|
@@ -24,6 +26,14 @@ export async function run(_command = 'zellij', args = []) {
|
|
|
24
26
|
return zellijRepair(root, args, json);
|
|
25
27
|
if (sub === 'dispatch' || sub === 'send')
|
|
26
28
|
return zellijDispatch(root, args, json);
|
|
29
|
+
if (sub === 'focus-worker')
|
|
30
|
+
return zellijFocusWorker(root, args, json);
|
|
31
|
+
if (sub === 'worker-logs')
|
|
32
|
+
return zellijWorkerLogs(root, args, json);
|
|
33
|
+
if (sub === 'dashboard')
|
|
34
|
+
return zellijDashboard(root, args, json);
|
|
35
|
+
if (sub === 'close-drained')
|
|
36
|
+
return zellijCloseDrained(root, args, json);
|
|
27
37
|
return zellijStatus(root, args, json);
|
|
28
38
|
}
|
|
29
39
|
async function zellijStatus(root, args, json) {
|
|
@@ -63,6 +73,108 @@ async function zellijStatus(root, args, json) {
|
|
|
63
73
|
if (!result.ok)
|
|
64
74
|
process.exitCode = 1;
|
|
65
75
|
}
|
|
76
|
+
async function zellijFocusWorker(root, args, json) {
|
|
77
|
+
const missionId = resolveMissionId(root, readOption(args, '--mission', readOption(args, '--mission-id', 'latest') || 'latest') || 'latest');
|
|
78
|
+
const slotId = normalizeZellijSlot(readOption(args, '--slot', positionalAfter(args, 'focus-worker') || 'slot-001'));
|
|
79
|
+
const state = await readJson(path.join(root, '.sneakoscope', 'missions', missionId, 'zellij-right-column-state.json'), null);
|
|
80
|
+
const worker = state?.visible_worker_panes?.find?.((row) => normalizeZellijSlot(row.slot_id) === slotId && row.pane_id);
|
|
81
|
+
const result = worker?.pane_id
|
|
82
|
+
? await runZellij(['--session', state.session_name, 'action', 'focus-pane-id', String(worker.pane_id)], { cwd: root, timeoutMs: 5000, optional: true })
|
|
83
|
+
: null;
|
|
84
|
+
const out = {
|
|
85
|
+
schema: 'sks.zellij-focus-worker.v1',
|
|
86
|
+
ok: Boolean(worker?.pane_id) && (result?.ok !== false),
|
|
87
|
+
mission_id: missionId,
|
|
88
|
+
slot_id: slotId,
|
|
89
|
+
pane_id: worker?.pane_id || null,
|
|
90
|
+
session_name: state?.session_name || null,
|
|
91
|
+
result,
|
|
92
|
+
blockers: worker?.pane_id ? (result && !result.ok ? result.blockers : []) : ['worker_pane_not_found']
|
|
93
|
+
};
|
|
94
|
+
if (json)
|
|
95
|
+
printJson(out);
|
|
96
|
+
else
|
|
97
|
+
console.log(out.ok ? `Focused ${slotId} (${out.pane_id})` : `Worker pane not found: ${slotId}`);
|
|
98
|
+
if (!out.ok)
|
|
99
|
+
process.exitCode = 1;
|
|
100
|
+
}
|
|
101
|
+
async function zellijWorkerLogs(root, args, json) {
|
|
102
|
+
const missionId = resolveMissionId(root, readOption(args, '--mission', readOption(args, '--mission-id', 'latest') || 'latest') || 'latest');
|
|
103
|
+
const slotArg = positionalAfter(args, 'worker-logs') || readOption(args, '--slot', '');
|
|
104
|
+
const slotId = slotArg ? normalizeZellijSlot(slotArg) : null;
|
|
105
|
+
const swarm = await readJson(path.join(root, '.sneakoscope', 'missions', missionId, 'agents', 'agent-native-cli-session-swarm.json'), null);
|
|
106
|
+
const records = Array.isArray(swarm?.records) ? swarm.records : [];
|
|
107
|
+
const filtered = slotId ? records.filter((row) => normalizeZellijSlot(row.slot_id) === slotId) : records;
|
|
108
|
+
const out = {
|
|
109
|
+
schema: 'sks.zellij-worker-logs.v1',
|
|
110
|
+
ok: filtered.length > 0,
|
|
111
|
+
mission_id: missionId,
|
|
112
|
+
slot_id: slotId,
|
|
113
|
+
logs: filtered.map((row) => ({
|
|
114
|
+
slot_id: row.slot_id,
|
|
115
|
+
generation_index: row.generation_index,
|
|
116
|
+
status: row.status,
|
|
117
|
+
stdout_log: row.stdout_log ? path.join(root, '.sneakoscope', 'missions', missionId, 'agents', row.stdout_log) : null,
|
|
118
|
+
stderr_log: row.stderr_log ? path.join(root, '.sneakoscope', 'missions', missionId, 'agents', row.stderr_log) : null,
|
|
119
|
+
worker_artifact_dir: row.worker_artifact_dir
|
|
120
|
+
})),
|
|
121
|
+
blockers: filtered.length ? [] : ['worker_log_records_missing']
|
|
122
|
+
};
|
|
123
|
+
if (json)
|
|
124
|
+
printJson(out);
|
|
125
|
+
else
|
|
126
|
+
for (const log of out.logs)
|
|
127
|
+
console.log(`${log.slot_id} gen-${log.generation_index} ${log.status}\nstdout: ${log.stdout_log}\nstderr: ${log.stderr_log}`);
|
|
128
|
+
if (!out.ok)
|
|
129
|
+
process.exitCode = 1;
|
|
130
|
+
}
|
|
131
|
+
async function zellijDashboard(root, args, json) {
|
|
132
|
+
const missionId = resolveMissionId(root, readOption(args, '--mission', readOption(args, '--mission-id', 'latest') || 'latest') || 'latest');
|
|
133
|
+
const snapshot = await readJson(path.join(root, '.sneakoscope', 'missions', missionId, 'zellij-dashboard-snapshot.json'), null);
|
|
134
|
+
const state = await readJson(path.join(root, '.sneakoscope', 'missions', missionId, 'zellij-right-column-state.json'), null);
|
|
135
|
+
const watch = flag(args, '--watch');
|
|
136
|
+
const out = {
|
|
137
|
+
schema: 'sks.zellij-dashboard-command.v1',
|
|
138
|
+
ok: Boolean(snapshot || state),
|
|
139
|
+
mission_id: missionId,
|
|
140
|
+
snapshot,
|
|
141
|
+
right_column_state: state,
|
|
142
|
+
watch,
|
|
143
|
+
watch_command: `sks zellij dashboard --mission ${missionId} --watch`
|
|
144
|
+
};
|
|
145
|
+
if (json)
|
|
146
|
+
printJson(out);
|
|
147
|
+
else if (snapshot)
|
|
148
|
+
console.log(renderZellijDashboardText(buildZellijDashboardSnapshot({ ...snapshot, mission_id: snapshot.mission_id || missionId })));
|
|
149
|
+
else
|
|
150
|
+
console.log(JSON.stringify(state || out, null, 2));
|
|
151
|
+
if (!out.ok)
|
|
152
|
+
process.exitCode = 1;
|
|
153
|
+
}
|
|
154
|
+
async function zellijCloseDrained(root, args, json) {
|
|
155
|
+
const missionId = resolveMissionId(root, readOption(args, '--mission', readOption(args, '--mission-id', 'latest') || 'latest') || 'latest');
|
|
156
|
+
const state = await readJson(path.join(root, '.sneakoscope', 'missions', missionId, 'zellij-right-column-state.json'), null);
|
|
157
|
+
const rows = Array.isArray(state?.visible_worker_panes) ? state.visible_worker_panes.filter((row) => row.pane_id && (row.status === 'draining' || row.status === 'closed')) : [];
|
|
158
|
+
const results = [];
|
|
159
|
+
for (const row of rows) {
|
|
160
|
+
results.push(await runZellij(['--session', state.session_name, 'action', 'close-pane', '--pane-id', String(row.pane_id)], { cwd: root, timeoutMs: 5000, optional: true }));
|
|
161
|
+
}
|
|
162
|
+
const out = {
|
|
163
|
+
schema: 'sks.zellij-close-drained.v1',
|
|
164
|
+
ok: results.every((result) => result.ok !== false),
|
|
165
|
+
mission_id: missionId,
|
|
166
|
+
closed_count: results.filter((result) => result.ok).length,
|
|
167
|
+
attempted_count: results.length,
|
|
168
|
+
results,
|
|
169
|
+
blockers: results.flatMap((result) => result.ok ? [] : result.blockers)
|
|
170
|
+
};
|
|
171
|
+
if (json)
|
|
172
|
+
printJson(out);
|
|
173
|
+
else
|
|
174
|
+
console.log(`Closed drained panes: ${out.closed_count}/${out.attempted_count}`);
|
|
175
|
+
if (!out.ok)
|
|
176
|
+
process.exitCode = 1;
|
|
177
|
+
}
|
|
66
178
|
async function zellijDispatch(root, args, json) {
|
|
67
179
|
const missionId = readOption(args, '--mission', readOption(args, '--mission-id', 'latest') || 'latest') || 'latest';
|
|
68
180
|
const slotId = normalizeZellijSlot(readOption(args, '--slot', 'slot-001'));
|
|
@@ -153,12 +265,16 @@ function printHelp(json) {
|
|
|
153
265
|
schema: ZELLIJ_COMMAND_SCHEMA,
|
|
154
266
|
subcommand: 'help',
|
|
155
267
|
ok: true,
|
|
156
|
-
usage: 'sks zellij status|repair|dispatch|send|
|
|
268
|
+
usage: 'sks zellij status|repair|dispatch|send|focus-worker|worker-logs|dashboard|close-drained [--json]',
|
|
157
269
|
subcommands: {
|
|
158
270
|
status: 'Report Zellij runtime capability and interactive-route readiness.',
|
|
159
271
|
repair: 'Explain how to install/repair Zellij (no automatic install).',
|
|
160
272
|
dispatch: 'Append a nonblocking JSONL command for a lane; optionally write to a reconciled pane id with --write-pane.',
|
|
161
273
|
send: 'Alias for dispatch.',
|
|
274
|
+
'focus-worker': 'Focus a visible right-column worker pane by slot.',
|
|
275
|
+
'worker-logs': 'Print stdout/stderr log paths for worker slots.',
|
|
276
|
+
dashboard: 'Render the latest dashboard snapshot; --watch prints watch metadata.',
|
|
277
|
+
'close-drained': 'Close drained right-column panes.',
|
|
162
278
|
capability: 'Alias for status.'
|
|
163
279
|
}
|
|
164
280
|
};
|
|
@@ -169,6 +285,10 @@ function printHelp(json) {
|
|
|
169
285
|
console.log(' sks zellij status [--require-real] [--json]');
|
|
170
286
|
console.log(' sks zellij repair [--explain] [--json]');
|
|
171
287
|
console.log(' sks zellij dispatch --mission M --slot slot-001 --text "..." [--write-pane] [--json]');
|
|
288
|
+
console.log(' sks zellij focus-worker slot-001 [--mission M] [--json]');
|
|
289
|
+
console.log(' sks zellij worker-logs [slot-001] [--mission M] [--json]');
|
|
290
|
+
console.log(' sks zellij dashboard [--mission M] [--watch] [--json]');
|
|
291
|
+
console.log(' sks zellij close-drained [--mission M] [--json]');
|
|
172
292
|
}
|
|
173
293
|
}
|
|
174
294
|
function defaultLedgerRoot(root, missionId) {
|
|
@@ -180,4 +300,27 @@ function readOption(args, name, fallback) {
|
|
|
180
300
|
const index = args.indexOf(name);
|
|
181
301
|
return index >= 0 && args[index + 1] ? String(args[index + 1]) : fallback;
|
|
182
302
|
}
|
|
303
|
+
function positionalAfter(args, subcommand) {
|
|
304
|
+
const index = args.indexOf(subcommand);
|
|
305
|
+
for (const arg of args.slice(index >= 0 ? index + 1 : 1)) {
|
|
306
|
+
if (!String(arg).startsWith('-'))
|
|
307
|
+
return String(arg);
|
|
308
|
+
}
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
function resolveMissionId(root, requested) {
|
|
312
|
+
if (requested && requested !== 'latest')
|
|
313
|
+
return requested;
|
|
314
|
+
const dir = path.join(root, '.sneakoscope', 'missions');
|
|
315
|
+
try {
|
|
316
|
+
const rows = fs.readdirSync(dir)
|
|
317
|
+
.filter((name) => /^M-/.test(name))
|
|
318
|
+
.map((name) => ({ name, mtime: fs.statSync(path.join(dir, name)).mtimeMs }))
|
|
319
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
320
|
+
return rows[0]?.name || 'latest';
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
return 'latest';
|
|
324
|
+
}
|
|
325
|
+
}
|
|
183
326
|
//# sourceMappingURL=zellij.js.map
|
|
@@ -281,7 +281,9 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
281
281
|
noOllama: opts.noOllama === true,
|
|
282
282
|
route,
|
|
283
283
|
fastModePolicy,
|
|
284
|
-
...(opts.workerPlacement === undefined ? {} : { workerPlacement: String(opts.workerPlacement) })
|
|
284
|
+
...(opts.workerPlacement === undefined ? {} : { workerPlacement: String(opts.workerPlacement) }),
|
|
285
|
+
zellijVisiblePaneCap: Number(opts.zellijVisiblePaneCap || visualLaneCount || targetActiveSlots),
|
|
286
|
+
projectRoot: root
|
|
285
287
|
});
|
|
286
288
|
await nativeCliSwarm.initialize();
|
|
287
289
|
await setCurrent(root, { mission_id: missionId, mode: 'AGENT', phase: 'AGENT_NATIVE_KERNEL_RUNNING', route_command: routeCommand, native_agent_backend: backend });
|
|
@@ -334,7 +336,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
334
336
|
generationIndex: agent.generation_index,
|
|
335
337
|
requireGeneration: true
|
|
336
338
|
});
|
|
337
|
-
const backendOpts = { ...opts, missionId, agentRoot: ledgerRoot, cwd: workerWorktree?.context.path || root, route, prompt, fastMode: fastModePolicy.fast_mode, serviceTier: fastModePolicy.service_tier, ...(workerWorktree ? { worktree: workerWorktree.context } : {}) };
|
|
339
|
+
const backendOpts = { ...opts, missionId, agentRoot: ledgerRoot, cwd: workerWorktree?.context.path || root, projectRoot: root, route, prompt, fastMode: fastModePolicy.fast_mode, serviceTier: fastModePolicy.service_tier, ...(workerWorktree ? { worktree: workerWorktree.context } : {}) };
|
|
338
340
|
const result = opts.nativeCliSwarm === false
|
|
339
341
|
? await runAgentByBackend(backend, runtimeAgent, runtimeSlice, backendOpts)
|
|
340
342
|
: await nativeCliSwarm.launchWorker({ agent: runtimeAgent, slice: runtimeSlice, opts: backendOpts });
|
|
@@ -5,6 +5,7 @@ import { appendJsonl, ensureDir, exists, nowIso, packageRoot, readJson, writeJso
|
|
|
5
5
|
import { fastModeEnv } from './fast-mode-policy.js';
|
|
6
6
|
import { validateAgentWorkerResult } from './agent-worker-pipeline.js';
|
|
7
7
|
import { closeWorkerPane, openWorkerPane } from '../zellij/zellij-worker-pane-manager.js';
|
|
8
|
+
import { recordHeadlessWorkerInRightColumn } from '../zellij/zellij-right-column-manager.js';
|
|
8
9
|
import { resolveProviderContext } from '../provider/provider-context.js';
|
|
9
10
|
export const NATIVE_CLI_SESSION_SWARM_SCHEMA = 'sks.agent-native-cli-session-swarm.v1';
|
|
10
11
|
export function createNativeCliSessionSwarmRecorder(root, input) {
|
|
@@ -104,7 +105,8 @@ class NativeCliSessionSwarmRecorder {
|
|
|
104
105
|
const placement = String(ctx.opts.workerPlacement || this.input.workerPlacement || (this.input.backend === 'zellij' ? 'zellij-pane' : 'process'));
|
|
105
106
|
const useZellijPane = placement === 'zellij-pane'
|
|
106
107
|
&& ctx.opts.zellijPaneWorker !== false
|
|
107
|
-
&& (ctx.opts.zellijSessionName || this.input.missionId)
|
|
108
|
+
&& (ctx.opts.zellijSessionName || this.input.missionId)
|
|
109
|
+
&& this.visibleZellijPaneCount() < this.zellijVisiblePaneCap(ctx.opts);
|
|
108
110
|
if (useZellijPane) {
|
|
109
111
|
stdout.end();
|
|
110
112
|
stderr.end();
|
|
@@ -119,6 +121,22 @@ class NativeCliSessionSwarmRecorder {
|
|
|
119
121
|
workerDirRel
|
|
120
122
|
});
|
|
121
123
|
}
|
|
124
|
+
if (placement === 'zellij-pane' && ctx.opts.zellijPaneWorker !== false && !useZellijPane) {
|
|
125
|
+
record.worker_placement = 'headless';
|
|
126
|
+
record.headless_reason = `visible_pane_cap:${this.zellijVisiblePaneCap(ctx.opts)}`;
|
|
127
|
+
await recordHeadlessWorkerInRightColumn({
|
|
128
|
+
root: this.root,
|
|
129
|
+
projectRoot: ctx.opts.projectRoot || this.input.projectRoot || ctx.opts.cwd,
|
|
130
|
+
missionId: this.input.missionId,
|
|
131
|
+
sessionName: String(ctx.opts.zellijSessionName || (this.input.missionId ? `sks-${this.input.missionId}` : 'sks-agent-runtime')),
|
|
132
|
+
slotId: String(ctx.agent.slot_id || ctx.agent.id || 'slot-001'),
|
|
133
|
+
generationIndex: Number(ctx.agent.generation_index || 1),
|
|
134
|
+
reason: record.headless_reason
|
|
135
|
+
}).catch(() => null);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
record.worker_placement = placement === 'zellij-pane' ? 'zellij-pane' : 'process';
|
|
139
|
+
}
|
|
122
140
|
const child = spawn(process.execPath, args, {
|
|
123
141
|
cwd: workerCwd,
|
|
124
142
|
env: {
|
|
@@ -194,11 +212,26 @@ class NativeCliSessionSwarmRecorder {
|
|
|
194
212
|
const activeToken = this.nextPaneToken--;
|
|
195
213
|
this.active.add(activeToken);
|
|
196
214
|
this.maxObserved = Math.max(this.maxObserved, this.active.size);
|
|
215
|
+
const providerContext = await resolveProviderContext({
|
|
216
|
+
root: this.root,
|
|
217
|
+
route: this.input.route,
|
|
218
|
+
serviceTier: this.input.fastModePolicy.service_tier
|
|
219
|
+
});
|
|
197
220
|
const workerCommand = buildPaneWorkerCommand({
|
|
198
221
|
args: input.args,
|
|
199
222
|
stdoutPath: path.join(this.root, input.stdoutRel),
|
|
200
223
|
stderrPath: path.join(this.root, input.stderrRel),
|
|
201
224
|
heartbeatPath: path.join(this.root, input.heartbeatRel),
|
|
225
|
+
header: buildPaneWorkerHeader({
|
|
226
|
+
slotId,
|
|
227
|
+
generationIndex: Number(input.ctx.agent.generation_index || 1),
|
|
228
|
+
role: input.ctx.agent.naruto_role || input.ctx.agent.role || input.ctx.agent.persona_id || 'worker',
|
|
229
|
+
backend: this.input.backend,
|
|
230
|
+
provider: providerContext.provider,
|
|
231
|
+
serviceTier: this.input.fastModePolicy.service_tier,
|
|
232
|
+
worktree,
|
|
233
|
+
task: input.ctx.slice?.description || input.ctx.slice?.title || input.ctx.slice?.id || ''
|
|
234
|
+
}),
|
|
202
235
|
env: {
|
|
203
236
|
...(input.ctx.opts.env || {}),
|
|
204
237
|
...fastModeEnv(this.input.fastModePolicy),
|
|
@@ -215,11 +248,6 @@ class NativeCliSessionSwarmRecorder {
|
|
|
215
248
|
SKS_ZELLIJ_SESSION_NAME: sessionName
|
|
216
249
|
}
|
|
217
250
|
});
|
|
218
|
-
const providerContext = await resolveProviderContext({
|
|
219
|
-
root: this.root,
|
|
220
|
-
route: this.input.route,
|
|
221
|
-
serviceTier: this.input.fastModePolicy.service_tier
|
|
222
|
-
});
|
|
223
251
|
let paneRecord = await openWorkerPane({
|
|
224
252
|
root: this.root,
|
|
225
253
|
missionId: this.input.missionId,
|
|
@@ -238,7 +266,25 @@ class NativeCliSessionSwarmRecorder {
|
|
|
238
266
|
providerContext,
|
|
239
267
|
serviceTier: this.input.fastModePolicy.service_tier,
|
|
240
268
|
worktree: worktree ? { id: worktree.id, path: worktree.path, branch: worktree.branch } : null,
|
|
241
|
-
backend: this.input.backend
|
|
269
|
+
backend: this.input.backend,
|
|
270
|
+
projectRoot: input.ctx.opts.projectRoot || this.input.projectRoot || input.ctx.opts.cwd,
|
|
271
|
+
rightColumnMode: 'spawn-on-first-worker',
|
|
272
|
+
visiblePaneCap: this.zellijVisiblePaneCap(input.ctx.opts),
|
|
273
|
+
dashboardSnapshot: {
|
|
274
|
+
mode: this.input.route || '$Agent',
|
|
275
|
+
backend_counts: { [this.input.backend]: this.input.targetActiveSlots },
|
|
276
|
+
placement_counts: {
|
|
277
|
+
'zellij-pane': this.zellijVisiblePaneCap(input.ctx.opts),
|
|
278
|
+
headless: Math.max(0, this.input.targetActiveSlots - this.zellijVisiblePaneCap(input.ctx.opts))
|
|
279
|
+
},
|
|
280
|
+
active_workers: this.input.targetActiveSlots,
|
|
281
|
+
visible_panes: this.zellijVisiblePaneCap(input.ctx.opts),
|
|
282
|
+
headless_workers: Math.max(0, this.input.targetActiveSlots - this.zellijVisiblePaneCap(input.ctx.opts)),
|
|
283
|
+
queue_depth: Math.max(0, this.input.requestedAgents - this.input.targetActiveSlots),
|
|
284
|
+
local_llm: { tps: 0, queue: 0 },
|
|
285
|
+
gpt_final_status: 'pending',
|
|
286
|
+
gate_progress: 'worker-spawn'
|
|
287
|
+
}
|
|
242
288
|
});
|
|
243
289
|
const launchBlockers = paneRecord.blockers || [];
|
|
244
290
|
input.record.command_line = ['zellij', '--session', sessionName, 'action', 'new-pane', '--direction', paneRecord.direction_applied, '--name', paneRecord.pane_name, '--', 'sh', '-lc', '<native-cli-worker-command>'];
|
|
@@ -339,6 +385,7 @@ class NativeCliSessionSwarmRecorder {
|
|
|
339
385
|
root: this.root,
|
|
340
386
|
paneRecord,
|
|
341
387
|
cwd: workerCwd,
|
|
388
|
+
projectRoot: input.ctx.opts.projectRoot || this.input.projectRoot || input.ctx.opts.cwd,
|
|
342
389
|
status: input.record.status === 'closed' ? 'closed' : 'failed',
|
|
343
390
|
blockers: input.record.blockers,
|
|
344
391
|
sdkThreadId,
|
|
@@ -409,6 +456,8 @@ class NativeCliSessionSwarmRecorder {
|
|
|
409
456
|
closed_worker_process_count: closed.length,
|
|
410
457
|
max_observed_worker_process_count: this.maxObserved,
|
|
411
458
|
active_worker_process_count: this.active.size,
|
|
459
|
+
visible_zellij_pane_cap: this.input.zellijVisiblePaneCap || null,
|
|
460
|
+
headless_overflow_worker_count: this.records.filter((row) => row.worker_placement === 'headless').length,
|
|
412
461
|
unique_worker_session_count: new Set(this.records.map((row) => row.session_id).filter(Boolean)).size,
|
|
413
462
|
unique_slot_count: new Set(this.records.map((row) => row.slot_id).filter(Boolean)).size,
|
|
414
463
|
unique_generation_count: new Set(this.records.map((row) => `${row.slot_id}:${row.generation_index}`).filter(Boolean)).size,
|
|
@@ -423,17 +472,35 @@ class NativeCliSessionSwarmRecorder {
|
|
|
423
472
|
blockers: this.records.flatMap((row) => row.blockers || [])
|
|
424
473
|
};
|
|
425
474
|
}
|
|
475
|
+
zellijVisiblePaneCap(opts = {}) {
|
|
476
|
+
const raw = Number(opts.zellijVisiblePaneCap || this.input.zellijVisiblePaneCap || this.input.targetActiveSlots || 1);
|
|
477
|
+
return Math.max(1, Math.floor(Number.isFinite(raw) ? raw : 1));
|
|
478
|
+
}
|
|
479
|
+
visibleZellijPaneCount() {
|
|
480
|
+
return this.records.filter((row) => row.scaling_primitive === 'native_cli_process_in_zellij_worker_pane' && (row.status === 'launching' || row.status === 'running')).length;
|
|
481
|
+
}
|
|
426
482
|
}
|
|
427
483
|
export function buildPaneWorkerCommand(input) {
|
|
428
484
|
const envPrefix = Object.entries(input.env)
|
|
429
485
|
.filter(([key, value]) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(key) && value != null)
|
|
430
|
-
.map(([key, value]) =>
|
|
486
|
+
.map(([key, value]) => `export ${key}=${shellQuote(String(value))};`)
|
|
431
487
|
.sort();
|
|
432
488
|
const command = [shellQuote(process.execPath), ...input.args.map(shellQuote)].join(' ');
|
|
433
489
|
const heartbeat = `printf '%s\\n' ${shellQuote(JSON.stringify({ schema: 'sks.zellij-worker-pane-event.v1', event: 'worker_command_exited' }))} >> ${shellQuote(input.heartbeatPath)}`;
|
|
434
490
|
const holdMs = Math.max(0, Number(process.env.SKS_ZELLIJ_WORKER_PANE_HOLD_MS || 1500));
|
|
435
491
|
const hold = holdMs > 0 ? `sleep ${shellQuote(String(Math.min(30, holdMs / 1000)))}` : ':';
|
|
436
|
-
|
|
492
|
+
const header = input.header ? `printf '%s\\n' ${shellQuote(input.header)} | tee -a ${shellQuote(input.stdoutPath)};` : '';
|
|
493
|
+
return `${envPrefix.join(' ')} ${header} ${command} >> ${shellQuote(input.stdoutPath)} 2>> ${shellQuote(input.stderrPath)}; code=$?; ${heartbeat}; ${hold}; exit $code`.trim();
|
|
494
|
+
}
|
|
495
|
+
function buildPaneWorkerHeader(input) {
|
|
496
|
+
return [
|
|
497
|
+
'SKS Worker',
|
|
498
|
+
`slot: ${input.slotId} gen: ${input.generationIndex} role: ${input.role}`,
|
|
499
|
+
`backend: ${input.backend} provider: ${input.provider} service: ${input.serviceTier}`,
|
|
500
|
+
`worktree: ${input.worktree ? `${input.worktree.id} branch: ${input.worktree.branch}` : '-'}`,
|
|
501
|
+
`task: ${String(input.task || '').slice(0, 160)}`,
|
|
502
|
+
'status: running'
|
|
503
|
+
].join('\n');
|
|
437
504
|
}
|
|
438
505
|
async function waitForWorkerResult(file, timeoutMs) {
|
|
439
506
|
const deadline = Date.now() + Math.max(1000, timeoutMs);
|
|
@@ -7,7 +7,6 @@ import { createMission, setCurrent } from '../mission.js';
|
|
|
7
7
|
import { buildMadHighLaunchProfileNoWrite, madHighProfileName } from '../auto-review.js';
|
|
8
8
|
import { permissionGateSummary } from '../permission-gates.js';
|
|
9
9
|
import { attachZellijSessionInteractive, launchMadZellijUi, sanitizeZellijSessionName } from '../zellij/zellij-launcher.js';
|
|
10
|
-
import { openZellijDashboardPane } from '../zellij/zellij-dashboard-pane.js';
|
|
11
10
|
import { createMadSksAuthorizationManifest, validateMadSksAuthorizationManifest } from '../mad-sks/authorization-manifest.js';
|
|
12
11
|
import { createMadSksAuditLedger, madSksAuditAction, writeMadSksAuditLedger } from '../mad-sks/audit-ledger.js';
|
|
13
12
|
import { compareProtectedCoreSnapshots, evaluateMadSksWrite, resolveProtectedCore, snapshotProtectedCore } from '../mad-sks/immutable-harness-guard.js';
|
|
@@ -114,36 +113,24 @@ export async function madHighCommand(args = [], deps = {}) {
|
|
|
114
113
|
console.log(`MAD Zellij action: ${formatMadZellijAction(launch)}`);
|
|
115
114
|
return launch;
|
|
116
115
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
visible_panes: 1,
|
|
128
|
-
headless_workers: 0,
|
|
129
|
-
queue_depth: 0,
|
|
130
|
-
worktrees: { active: 0, completed: 0, retained: 0 },
|
|
131
|
-
local_llm: { tps: 0, queue: 0 },
|
|
132
|
-
gpt_final_status: 'pending',
|
|
133
|
-
gate_progress: 'mad-sks:session-open'
|
|
134
|
-
}
|
|
135
|
-
}).catch((err) => ({
|
|
136
|
-
ok: false,
|
|
137
|
-
pane_kind: 'dashboard',
|
|
138
|
-
worker_pane: false,
|
|
139
|
-
blockers: [`zellij_dashboard_exception:${err?.message || String(err)}`]
|
|
140
|
-
}));
|
|
116
|
+
await writeJsonAtomic(path.join(madLaunch.dir, 'zellij-initial-ui.json'), {
|
|
117
|
+
schema: 'sks.zellij-initial-ui.v1',
|
|
118
|
+
ok: true,
|
|
119
|
+
mission_id: madLaunch.mission_id,
|
|
120
|
+
session_name: launch.session_name,
|
|
121
|
+
initial_panes: 'main-only',
|
|
122
|
+
dashboard_created: false,
|
|
123
|
+
worker_panes_created: 0,
|
|
124
|
+
right_column_mode: 'spawn-on-first-worker'
|
|
125
|
+
});
|
|
141
126
|
const madNativeSwarm = await startMadNativeSwarm(madLaunch.root, madLaunch, args, profile, {
|
|
142
127
|
env: {
|
|
143
128
|
...madSksEnv,
|
|
144
129
|
SKS_ZELLIJ_SESSION_NAME: launch.session_name
|
|
145
130
|
},
|
|
146
|
-
zellijSessionName: launch.session_name
|
|
131
|
+
zellijSessionName: launch.session_name,
|
|
132
|
+
workerPlacement: shouldAutoAttachZellij(args) ? 'zellij-pane' : 'process',
|
|
133
|
+
zellijVisiblePaneCap: Number(process.env.SKS_ZELLIJ_VISIBLE_PANE_CAP || 8)
|
|
147
134
|
});
|
|
148
135
|
// The launcher only creates a detached background session. In an interactive
|
|
149
136
|
// terminal, immediately attach so the session actually opens for the user
|
|
@@ -218,6 +205,8 @@ export async function startMadNativeSwarm(root, madLaunch, args = [], profile =
|
|
|
218
205
|
command.push('--real');
|
|
219
206
|
command.push('--zellij-session-name', opts.zellijSessionName || `sks-${madLaunch.mission_id}`);
|
|
220
207
|
command.push('--zellij-pane-worker');
|
|
208
|
+
command.push('--worker-placement', opts.workerPlacement || 'zellij-pane');
|
|
209
|
+
command.push('--zellij-visible-pane-cap', String(opts.zellijVisiblePaneCap || swarm.agents));
|
|
221
210
|
}
|
|
222
211
|
const baseReport = {
|
|
223
212
|
schema: 'sks.mad-sks-native-swarm.v1',
|
|
@@ -234,6 +223,8 @@ export async function startMadNativeSwarm(root, madLaunch, args = [], profile =
|
|
|
234
223
|
work_items: swarm.workItems,
|
|
235
224
|
backend: swarm.backend,
|
|
236
225
|
zellij_session_name: opts.zellijSessionName || null,
|
|
226
|
+
worker_placement: opts.workerPlacement || (swarm.backend === 'zellij' ? 'zellij-pane' : 'process'),
|
|
227
|
+
zellij_visible_pane_cap: opts.zellijVisiblePaneCap || null,
|
|
237
228
|
readonly: true,
|
|
238
229
|
command,
|
|
239
230
|
stdout_log: path.relative(root, stdoutLog),
|