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
|
@@ -3,7 +3,7 @@ import { ensureDir, nowIso, packageRoot, writeTextAtomic } from '../fsx.js';
|
|
|
3
3
|
import { writeZellijLaneRuntimeManifest } from './zellij-lane-runtime.js';
|
|
4
4
|
export const ZELLIJ_LAYOUT_SCHEMA = 'sks.zellij-layout.v1';
|
|
5
5
|
export function buildZellijLayoutKdl(input) {
|
|
6
|
-
const slotCount = Math.max(
|
|
6
|
+
const slotCount = Math.max(0, Number(input.slotCount ?? 1));
|
|
7
7
|
const sessionName = input.sessionName || `sks-${input.missionId}`;
|
|
8
8
|
const cwd = path.resolve(input.cwd || process.cwd());
|
|
9
9
|
const ledgerRoot = path.resolve(input.ledgerRoot);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export function evaluateZellijRightColumnGeometry(input) {
|
|
2
|
+
const tolerance = Math.max(0, Number(input.tolerance ?? 2));
|
|
3
|
+
const main = input.panes.find((pane) => pane.role === 'main') || null;
|
|
4
|
+
const dashboard = input.panes.find((pane) => pane.role === 'dashboard') || null;
|
|
5
|
+
const workers = input.panes.filter((pane) => pane.role === 'worker');
|
|
6
|
+
const workerGeometries = workers.map((pane) => pane.geometry).filter(Boolean);
|
|
7
|
+
const baseX = workerGeometries[0]?.x;
|
|
8
|
+
const sameRightX = baseX == null ? null : workerGeometries.every((geometry) => geometry.x != null && Math.abs(geometry.x - baseX) <= tolerance);
|
|
9
|
+
const rightOfMain = !main?.geometry ? null : workerGeometries.every((geometry) => {
|
|
10
|
+
if (geometry.x == null || main.geometry?.x == null || main.geometry?.width == null)
|
|
11
|
+
return false;
|
|
12
|
+
return geometry.x >= main.geometry.x + main.geometry.width - tolerance;
|
|
13
|
+
});
|
|
14
|
+
const increasingY = workerGeometries.every((geometry, index) => {
|
|
15
|
+
if (index === 0)
|
|
16
|
+
return true;
|
|
17
|
+
const previous = workerGeometries[index - 1];
|
|
18
|
+
return geometry.y != null && previous?.y != null && geometry.y > previous.y;
|
|
19
|
+
});
|
|
20
|
+
const visibleCapOk = workers.length <= Math.max(0, Math.floor(Number(input.visiblePaneCap || 0)));
|
|
21
|
+
const blockers = [
|
|
22
|
+
...(!main ? ['right_column_main_pane_missing'] : []),
|
|
23
|
+
...(!dashboard ? ['right_column_dashboard_missing'] : []),
|
|
24
|
+
...(sameRightX === false ? ['right_column_worker_x_range_mismatch'] : []),
|
|
25
|
+
...(rightOfMain === false ? ['right_column_workers_not_right_of_main'] : []),
|
|
26
|
+
...(increasingY === false ? ['right_column_workers_not_stacked_down'] : []),
|
|
27
|
+
...(visibleCapOk ? [] : ['right_column_visible_cap_exceeded'])
|
|
28
|
+
];
|
|
29
|
+
return {
|
|
30
|
+
schema: 'sks.zellij-right-column-layout-proof.v1',
|
|
31
|
+
ok: blockers.length === 0,
|
|
32
|
+
main_pane_id: main?.pane_id || null,
|
|
33
|
+
dashboard_pane_id: dashboard?.pane_id || null,
|
|
34
|
+
worker_pane_ids: workers.map((pane) => pane.pane_id),
|
|
35
|
+
same_right_x: sameRightX,
|
|
36
|
+
right_of_main: rightOfMain,
|
|
37
|
+
increasing_y: increasingY,
|
|
38
|
+
visible_cap_ok: visibleCapOk,
|
|
39
|
+
blockers
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=zellij-right-column-layout-proof.js.map
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { appendJsonl, ensureDir, nowIso, readJson, writeJsonAtomic } from '../fsx.js';
|
|
3
|
+
import { openZellijDashboardPane } from './zellij-dashboard-pane.js';
|
|
4
|
+
export const ZELLIJ_RIGHT_COLUMN_STATE_SCHEMA = 'sks.zellij-right-column-state.v1';
|
|
5
|
+
export async function ensureRightColumn(input) {
|
|
6
|
+
const paths = resolveRightColumnPaths(input.root, input.missionId, input.projectRoot);
|
|
7
|
+
await ensureDir(paths.missionDir);
|
|
8
|
+
const existing = await readRightColumnState(input.root, input.missionId, input.projectRoot);
|
|
9
|
+
if (existing?.status === 'active' && existing.dashboard_pane_id) {
|
|
10
|
+
return writeRightColumnState(paths.statePath, { ...existing, updated_at: nowIso() });
|
|
11
|
+
}
|
|
12
|
+
const creating = await writeRightColumnState(paths.statePath, {
|
|
13
|
+
schema: ZELLIJ_RIGHT_COLUMN_STATE_SCHEMA,
|
|
14
|
+
generated_at: nowIso(),
|
|
15
|
+
updated_at: nowIso(),
|
|
16
|
+
mission_id: input.missionId,
|
|
17
|
+
session_name: input.sessionName,
|
|
18
|
+
status: 'creating',
|
|
19
|
+
dashboard_pane_id: null,
|
|
20
|
+
right_anchor_pane_id: null,
|
|
21
|
+
visible_worker_panes: [],
|
|
22
|
+
headless_workers: [],
|
|
23
|
+
blockers: []
|
|
24
|
+
});
|
|
25
|
+
await appendRightColumnEvent(paths.eventsPath, 'right_column_creating', creating, {});
|
|
26
|
+
const dashboard = await openZellijDashboardPane({
|
|
27
|
+
root: paths.projectRoot,
|
|
28
|
+
missionId: input.missionId,
|
|
29
|
+
sessionName: input.sessionName,
|
|
30
|
+
cwd: input.cwd || paths.projectRoot,
|
|
31
|
+
snapshot: {
|
|
32
|
+
...input.dashboardSnapshot,
|
|
33
|
+
mission_id: input.missionId,
|
|
34
|
+
gate_progress: input.dashboardSnapshot.gate_progress || 'right-column:first-worker'
|
|
35
|
+
}
|
|
36
|
+
}).catch((err) => ({
|
|
37
|
+
ok: false,
|
|
38
|
+
pane_id: null,
|
|
39
|
+
blockers: [`zellij_dashboard_exception:${err?.message || String(err)}`]
|
|
40
|
+
}));
|
|
41
|
+
const blockers = Array.isArray(dashboard.blockers) ? dashboard.blockers : [];
|
|
42
|
+
const active = await writeRightColumnState(paths.statePath, {
|
|
43
|
+
...creating,
|
|
44
|
+
updated_at: nowIso(),
|
|
45
|
+
status: blockers.length ? 'creating' : 'active',
|
|
46
|
+
dashboard_pane_id: dashboard.pane_id ? String(dashboard.pane_id) : null,
|
|
47
|
+
right_anchor_pane_id: dashboard.pane_id ? String(dashboard.pane_id) : null,
|
|
48
|
+
blockers
|
|
49
|
+
});
|
|
50
|
+
await appendRightColumnEvent(paths.eventsPath, 'right_column_created', active, { ok: active.status === 'active' });
|
|
51
|
+
await appendRightColumnEvent(paths.eventsPath, 'dashboard_pane_created', active, { pane_id: active.dashboard_pane_id, blockers });
|
|
52
|
+
return active;
|
|
53
|
+
}
|
|
54
|
+
export async function prepareWorkerInRightColumn(input) {
|
|
55
|
+
const paths = resolveRightColumnPaths(input.root, input.missionId, input.projectRoot);
|
|
56
|
+
const state = await ensureRightColumn({
|
|
57
|
+
root: input.root,
|
|
58
|
+
...(input.projectRoot ? { projectRoot: input.projectRoot } : {}),
|
|
59
|
+
missionId: input.missionId,
|
|
60
|
+
sessionName: input.sessionName,
|
|
61
|
+
cwd: input.cwd,
|
|
62
|
+
dashboardSnapshot: input.dashboardSnapshot
|
|
63
|
+
});
|
|
64
|
+
const activeVisible = state.visible_worker_panes.filter((pane) => pane.status === 'launching' || pane.status === 'running');
|
|
65
|
+
const cap = Math.max(1, Math.floor(Number(input.visiblePaneCap || 1)));
|
|
66
|
+
if (activeVisible.length >= cap) {
|
|
67
|
+
const next = await recordHeadlessWorkerInRightColumn({
|
|
68
|
+
root: input.root,
|
|
69
|
+
...(input.projectRoot ? { projectRoot: input.projectRoot } : {}),
|
|
70
|
+
missionId: input.missionId,
|
|
71
|
+
sessionName: input.sessionName,
|
|
72
|
+
slotId: input.worker.slotId,
|
|
73
|
+
generationIndex: input.worker.generationIndex,
|
|
74
|
+
reason: `visible_pane_cap:${cap}`
|
|
75
|
+
});
|
|
76
|
+
return { state: next, placement: 'headless', focusPaneId: null, yOrder: null };
|
|
77
|
+
}
|
|
78
|
+
const lastVisible = activeVisible[activeVisible.length - 1];
|
|
79
|
+
const focusPaneId = lastVisible?.pane_id || state.right_anchor_pane_id || state.dashboard_pane_id || null;
|
|
80
|
+
const yOrder = Math.max(1, ...state.visible_worker_panes.map((pane) => Number(pane.y_order || 0) + 1));
|
|
81
|
+
const next = await writeRightColumnState(paths.statePath, {
|
|
82
|
+
...state,
|
|
83
|
+
updated_at: nowIso(),
|
|
84
|
+
right_anchor_pane_id: focusPaneId,
|
|
85
|
+
visible_worker_panes: [
|
|
86
|
+
...state.visible_worker_panes,
|
|
87
|
+
{
|
|
88
|
+
pane_id: null,
|
|
89
|
+
slot_id: input.worker.slotId,
|
|
90
|
+
generation_index: input.worker.generationIndex,
|
|
91
|
+
y_order: yOrder,
|
|
92
|
+
status: 'launching'
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
});
|
|
96
|
+
await appendRightColumnEvent(paths.eventsPath, 'scheduler_slot_reserved', next, {
|
|
97
|
+
slot_id: input.worker.slotId,
|
|
98
|
+
generation_index: input.worker.generationIndex,
|
|
99
|
+
y_order: yOrder
|
|
100
|
+
});
|
|
101
|
+
return { state: next, placement: 'zellij-pane', focusPaneId, yOrder };
|
|
102
|
+
}
|
|
103
|
+
export async function recordWorkerPaneInRightColumn(input) {
|
|
104
|
+
const paths = resolveRightColumnPaths(input.root, input.missionId, input.projectRoot);
|
|
105
|
+
const state = await readRightColumnState(input.root, input.missionId, input.projectRoot);
|
|
106
|
+
if (!state)
|
|
107
|
+
return null;
|
|
108
|
+
const yOrder = Math.max(1, Math.floor(Number(input.yOrder || 0))) || Math.max(1, ...state.visible_worker_panes.map((pane) => pane.y_order + 1));
|
|
109
|
+
const slotId = input.record.slot_id;
|
|
110
|
+
const generationIndex = input.record.generation_index;
|
|
111
|
+
const rows = state.visible_worker_panes.filter((pane) => !(pane.slot_id === slotId && pane.generation_index === generationIndex && pane.pane_id == null));
|
|
112
|
+
rows.push({
|
|
113
|
+
pane_id: input.record.pane_id,
|
|
114
|
+
slot_id: slotId,
|
|
115
|
+
generation_index: generationIndex,
|
|
116
|
+
y_order: yOrder,
|
|
117
|
+
status: input.record.status === 'failed' ? 'failed' : 'running'
|
|
118
|
+
});
|
|
119
|
+
const next = await writeRightColumnState(paths.statePath, {
|
|
120
|
+
...state,
|
|
121
|
+
updated_at: nowIso(),
|
|
122
|
+
right_anchor_pane_id: input.record.pane_id || state.right_anchor_pane_id,
|
|
123
|
+
visible_worker_panes: rows.sort((a, b) => a.y_order - b.y_order),
|
|
124
|
+
blockers: [...new Set([...state.blockers, ...(input.record.blockers || [])])]
|
|
125
|
+
});
|
|
126
|
+
await appendRightColumnEvent(paths.eventsPath, 'worker_pane_created', next, {
|
|
127
|
+
slot_id: slotId,
|
|
128
|
+
generation_index: generationIndex,
|
|
129
|
+
pane_id: input.record.pane_id,
|
|
130
|
+
y_order: yOrder,
|
|
131
|
+
direction_applied: input.record.direction_applied,
|
|
132
|
+
blockers: input.record.blockers
|
|
133
|
+
});
|
|
134
|
+
return next;
|
|
135
|
+
}
|
|
136
|
+
export async function recordHeadlessWorkerInRightColumn(input) {
|
|
137
|
+
const paths = resolveRightColumnPaths(input.root, input.missionId, input.projectRoot);
|
|
138
|
+
const state = await readRightColumnState(input.root, input.missionId, input.projectRoot) || {
|
|
139
|
+
schema: ZELLIJ_RIGHT_COLUMN_STATE_SCHEMA,
|
|
140
|
+
generated_at: nowIso(),
|
|
141
|
+
updated_at: nowIso(),
|
|
142
|
+
mission_id: input.missionId,
|
|
143
|
+
session_name: input.sessionName,
|
|
144
|
+
status: 'absent',
|
|
145
|
+
dashboard_pane_id: null,
|
|
146
|
+
right_anchor_pane_id: null,
|
|
147
|
+
visible_worker_panes: [],
|
|
148
|
+
headless_workers: [],
|
|
149
|
+
blockers: []
|
|
150
|
+
};
|
|
151
|
+
const headless = [
|
|
152
|
+
...state.headless_workers.filter((row) => !(row.slot_id === input.slotId && row.generation_index === input.generationIndex)),
|
|
153
|
+
{ slot_id: input.slotId, generation_index: input.generationIndex, reason: input.reason }
|
|
154
|
+
];
|
|
155
|
+
const next = await writeRightColumnState(paths.statePath, { ...state, updated_at: nowIso(), headless_workers: headless });
|
|
156
|
+
await appendRightColumnEvent(paths.eventsPath, 'worker_headless_overflow', next, {
|
|
157
|
+
slot_id: input.slotId,
|
|
158
|
+
generation_index: input.generationIndex,
|
|
159
|
+
reason: input.reason
|
|
160
|
+
});
|
|
161
|
+
return next;
|
|
162
|
+
}
|
|
163
|
+
export async function closeWorkerInRightColumn(input) {
|
|
164
|
+
const paths = resolveRightColumnPaths(input.root, input.missionId, input.projectRoot);
|
|
165
|
+
const state = await readRightColumnState(input.root, input.missionId, input.projectRoot);
|
|
166
|
+
if (!state)
|
|
167
|
+
return null;
|
|
168
|
+
const panes = state.visible_worker_panes.map((pane) => {
|
|
169
|
+
const same = pane.slot_id === input.slotId && pane.generation_index === input.generationIndex;
|
|
170
|
+
return same ? { ...pane, pane_id: input.paneId || pane.pane_id, status: input.status } : pane;
|
|
171
|
+
});
|
|
172
|
+
const visibleStillActive = panes.filter((pane) => pane.status === 'launching' || pane.status === 'running');
|
|
173
|
+
const next = await writeRightColumnState(paths.statePath, {
|
|
174
|
+
...state,
|
|
175
|
+
updated_at: nowIso(),
|
|
176
|
+
status: visibleStillActive.length || state.headless_workers.length ? 'active' : 'draining',
|
|
177
|
+
right_anchor_pane_id: visibleStillActive[visibleStillActive.length - 1]?.pane_id || state.dashboard_pane_id,
|
|
178
|
+
visible_worker_panes: panes
|
|
179
|
+
});
|
|
180
|
+
await appendRightColumnEvent(paths.eventsPath, 'worker_pane_drained', next, {
|
|
181
|
+
slot_id: input.slotId,
|
|
182
|
+
generation_index: input.generationIndex,
|
|
183
|
+
pane_id: input.paneId,
|
|
184
|
+
status: input.status
|
|
185
|
+
});
|
|
186
|
+
return next;
|
|
187
|
+
}
|
|
188
|
+
export async function openWorkerInRightColumn(input) {
|
|
189
|
+
const prepared = await prepareWorkerInRightColumn({
|
|
190
|
+
root: input.root,
|
|
191
|
+
missionId: input.state.mission_id,
|
|
192
|
+
sessionName: input.state.session_name,
|
|
193
|
+
cwd: input.worker.cwd || input.root,
|
|
194
|
+
worker: { slotId: input.worker.slotId, generationIndex: input.worker.generationIndex },
|
|
195
|
+
visiblePaneCap: input.visiblePaneCap,
|
|
196
|
+
dashboardSnapshot: { mission_id: input.state.mission_id }
|
|
197
|
+
});
|
|
198
|
+
return { state: prepared.state, pane: null, placement: prepared.placement };
|
|
199
|
+
}
|
|
200
|
+
export async function readRightColumnState(root, missionId, projectRoot) {
|
|
201
|
+
const paths = resolveRightColumnPaths(root, missionId, projectRoot);
|
|
202
|
+
return readJson(paths.statePath, null);
|
|
203
|
+
}
|
|
204
|
+
export function resolveRightColumnPaths(root, missionId, projectRoot) {
|
|
205
|
+
const resolvedRoot = path.resolve(root);
|
|
206
|
+
const resolvedProjectRoot = projectRoot ? path.resolve(projectRoot) : inferProjectRoot(resolvedRoot, missionId);
|
|
207
|
+
const missionDir = inferMissionDir(resolvedRoot, missionId) || path.join(resolvedProjectRoot, '.sneakoscope', 'missions', missionId);
|
|
208
|
+
return {
|
|
209
|
+
projectRoot: resolvedProjectRoot,
|
|
210
|
+
missionDir,
|
|
211
|
+
statePath: path.join(missionDir, 'zellij-right-column-state.json'),
|
|
212
|
+
eventsPath: path.join(missionDir, 'zellij-right-column-events.jsonl')
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
async function writeRightColumnState(file, state) {
|
|
216
|
+
await writeJsonAtomic(file, state);
|
|
217
|
+
return state;
|
|
218
|
+
}
|
|
219
|
+
async function appendRightColumnEvent(file, eventType, state, payload) {
|
|
220
|
+
await appendJsonl(file, {
|
|
221
|
+
schema: 'sks.zellij-right-column-event.v1',
|
|
222
|
+
ts: nowIso(),
|
|
223
|
+
event_type: eventType,
|
|
224
|
+
mission_id: state.mission_id,
|
|
225
|
+
session_name: state.session_name,
|
|
226
|
+
...payload
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
function inferMissionDir(root, missionId) {
|
|
230
|
+
if (path.basename(root) === 'agents' && path.basename(path.dirname(root)) === missionId)
|
|
231
|
+
return path.dirname(root);
|
|
232
|
+
if (path.basename(root) === missionId && path.basename(path.dirname(root)) === 'missions')
|
|
233
|
+
return root;
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
function inferProjectRoot(root, missionId) {
|
|
237
|
+
if (path.basename(root) === 'agents' && path.basename(path.dirname(root)) === missionId) {
|
|
238
|
+
return path.dirname(path.dirname(path.dirname(path.dirname(root))));
|
|
239
|
+
}
|
|
240
|
+
if (path.basename(root) === missionId && path.basename(path.dirname(root)) === 'missions') {
|
|
241
|
+
return path.dirname(path.dirname(path.dirname(root)));
|
|
242
|
+
}
|
|
243
|
+
return root;
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=zellij-right-column-manager.js.map
|
|
@@ -4,6 +4,7 @@ import { providerPaneLabel } from '../provider/provider-badge.js';
|
|
|
4
4
|
import { resolveProviderContext } from '../provider/provider-context.js';
|
|
5
5
|
import { runZellij } from './zellij-command.js';
|
|
6
6
|
import { extractZellijPaneIdFromOutput } from './zellij-lane-runtime.js';
|
|
7
|
+
import { closeWorkerInRightColumn, prepareWorkerInRightColumn, recordWorkerPaneInRightColumn } from './zellij-right-column-manager.js';
|
|
7
8
|
export const ZELLIJ_WORKER_PANE_SCHEMA = 'sks.zellij-worker-pane.v1';
|
|
8
9
|
export const ZELLIJ_WORKER_PANE_EVENT_SCHEMA = 'sks.zellij-worker-pane-event.v1';
|
|
9
10
|
export function buildWorkerPaneName(slotId, generationIndex) {
|
|
@@ -59,8 +60,9 @@ export function buildWorkerPaneArtifact(input) {
|
|
|
59
60
|
opened_at: now,
|
|
60
61
|
closed_at: null,
|
|
61
62
|
close: null,
|
|
62
|
-
direction_requested: 'right',
|
|
63
|
+
direction_requested: input.directionRequested || 'right',
|
|
63
64
|
direction_applied: input.directionApplied || 'not_applied',
|
|
65
|
+
right_column: input.rightColumn || null,
|
|
64
66
|
sdk_thread_id: input.sdkThreadId || null,
|
|
65
67
|
sdk_run_id: input.sdkRunId || null,
|
|
66
68
|
stream_event_count: Number(input.streamEventCount || 0),
|
|
@@ -85,24 +87,49 @@ export async function openWorkerPane(input) {
|
|
|
85
87
|
optional: false
|
|
86
88
|
});
|
|
87
89
|
const createSession = normalizeExistingZellijSession(input.sessionName, createSessionRaw);
|
|
90
|
+
const rightColumn = input.rightColumnMode === 'spawn-on-first-worker'
|
|
91
|
+
? await prepareWorkerInRightColumn({
|
|
92
|
+
root,
|
|
93
|
+
...(input.projectRoot ? { projectRoot: input.projectRoot } : {}),
|
|
94
|
+
missionId: input.missionId,
|
|
95
|
+
sessionName: input.sessionName,
|
|
96
|
+
cwd,
|
|
97
|
+
worker: { slotId: input.slotId, generationIndex: input.generationIndex },
|
|
98
|
+
visiblePaneCap: input.visiblePaneCap || 1,
|
|
99
|
+
dashboardSnapshot: {
|
|
100
|
+
...(input.dashboardSnapshot || {}),
|
|
101
|
+
mode: String(input.dashboardSnapshot?.mode || 'naruto'),
|
|
102
|
+
active_workers: Number(input.dashboardSnapshot?.active_workers || input.visiblePaneCap || 1),
|
|
103
|
+
visible_panes: Number(input.dashboardSnapshot?.visible_panes || input.visiblePaneCap || 1)
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
: null;
|
|
88
107
|
const paneName = buildWorkerPaneTitle(input.slotId, input.generationIndex, providerContext, input.serviceTier, input.backend, input.statusLabel || 'running', input.worktree || null);
|
|
108
|
+
const directionRequested = rightColumn ? 'down' : 'right';
|
|
109
|
+
const focus = rightColumn?.focusPaneId
|
|
110
|
+
? await focusZellijPaneById(input.sessionName, rightColumn.focusPaneId, cwd)
|
|
111
|
+
: null;
|
|
112
|
+
const newPaneArgs = ['--session', input.sessionName, 'action', 'new-pane', '--direction', directionRequested, ...(rightColumn ? ['--near-current-pane'] : []), '--name', paneName, '--', 'sh', '-lc', input.workerCommand];
|
|
89
113
|
let launch = createSession.ok
|
|
90
|
-
? await runZellij(
|
|
114
|
+
? await runZellij(newPaneArgs, {
|
|
91
115
|
cwd,
|
|
92
116
|
timeoutMs: 5000,
|
|
93
117
|
optional: false
|
|
94
118
|
})
|
|
95
119
|
: null;
|
|
96
|
-
let directionApplied = launch?.ok ?
|
|
120
|
+
let directionApplied = launch?.ok ? directionRequested : 'not_applied';
|
|
97
121
|
if (createSession.ok && launch && !launch.ok) {
|
|
98
|
-
const
|
|
122
|
+
const fallbackArgs = rightColumn
|
|
123
|
+
? ['--session', input.sessionName, 'action', 'new-pane', '--direction', 'down', '--name', paneName, '--', 'sh', '-lc', input.workerCommand]
|
|
124
|
+
: ['--session', input.sessionName, 'action', 'new-pane', '--name', paneName, '--', 'sh', '-lc', input.workerCommand];
|
|
125
|
+
const fallback = await runZellij(fallbackArgs, {
|
|
99
126
|
cwd,
|
|
100
127
|
timeoutMs: 5000,
|
|
101
128
|
optional: false
|
|
102
129
|
});
|
|
103
130
|
if (fallback.ok) {
|
|
104
131
|
launch = fallback;
|
|
105
|
-
directionApplied = 'unknown';
|
|
132
|
+
directionApplied = rightColumn ? 'down' : 'unknown';
|
|
106
133
|
}
|
|
107
134
|
}
|
|
108
135
|
const stdoutPaneId = launch?.ok ? extractZellijPaneIdFromOutput(launch.stdout_tail) : null;
|
|
@@ -118,6 +145,7 @@ export async function openWorkerPane(input) {
|
|
|
118
145
|
: 'zellij_worker_pane_launch_failed';
|
|
119
146
|
const blockers = [
|
|
120
147
|
...(createSession.ok ? [] : createSession.blockers.map((blocker) => `zellij_worker_session_${blocker}`)),
|
|
148
|
+
...(rightColumn && rightColumn.placement !== 'zellij-pane' ? [`zellij_worker_right_column_${rightColumn.placement}`] : []),
|
|
121
149
|
...(launch && !launch.ok ? launch.blockers.map((blocker) => `zellij_worker_pane_${blocker}`) : []),
|
|
122
150
|
...(launch?.ok && !isRealZellijWorkerPaneIdSource(paneIdSource) ? ['zellij_worker_pane_id_real_source_missing'] : [])
|
|
123
151
|
];
|
|
@@ -127,14 +155,30 @@ export async function openWorkerPane(input) {
|
|
|
127
155
|
paneIdSource,
|
|
128
156
|
createSession,
|
|
129
157
|
launch,
|
|
130
|
-
paneReconciliation: {
|
|
158
|
+
paneReconciliation: {
|
|
159
|
+
...(reconciledPane || {}),
|
|
160
|
+
focus_pane: focus,
|
|
161
|
+
focus_degraded: focus ? focus.ok !== true : false,
|
|
162
|
+
rename_pane: renamePane
|
|
163
|
+
},
|
|
164
|
+
directionRequested,
|
|
131
165
|
directionApplied,
|
|
166
|
+
rightColumn: rightColumn ? { mode: 'spawn-on-first-worker', focus_pane_id: rightColumn.focusPaneId, y_order: rightColumn.yOrder } : null,
|
|
132
167
|
status: blockers.length ? 'failed' : 'running',
|
|
133
168
|
providerContext,
|
|
134
169
|
serviceTier: input.serviceTier || providerContext.service_tier,
|
|
135
170
|
blockers
|
|
136
171
|
});
|
|
137
172
|
await writeWorkerPaneArtifact(root, record);
|
|
173
|
+
if (rightColumn) {
|
|
174
|
+
await recordWorkerPaneInRightColumn({
|
|
175
|
+
root,
|
|
176
|
+
...(input.projectRoot ? { projectRoot: input.projectRoot } : {}),
|
|
177
|
+
missionId: input.missionId,
|
|
178
|
+
record,
|
|
179
|
+
yOrder: rightColumn.yOrder
|
|
180
|
+
});
|
|
181
|
+
}
|
|
138
182
|
await appendWorkerPaneEvent(root, 'zellij_worker_pane_created', input, {
|
|
139
183
|
ok: record.ok,
|
|
140
184
|
pane_id: record.pane_id,
|
|
@@ -174,12 +218,16 @@ export async function openWorkerPane(input) {
|
|
|
174
218
|
}
|
|
175
219
|
export async function closeWorkerPane(input) {
|
|
176
220
|
const root = path.resolve(input.root);
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
221
|
+
const success = (input.status || 'closed') === 'closed' && !(input.blockers || []).length;
|
|
222
|
+
const closeSuccess = process.env.SKS_ZELLIJ_CLOSE_WORKER_PANE !== '0';
|
|
223
|
+
const closeFailed = process.env.SKS_ZELLIJ_CLOSE_FAILED_PANE === '1' || process.env.SKS_ZELLIJ_KEEP_FAILED_PANE === '0';
|
|
224
|
+
const paneId = input.paneRecord.pane_id;
|
|
225
|
+
const shouldClose = Boolean(paneId) && (success ? closeSuccess : closeFailed);
|
|
226
|
+
const close = shouldClose
|
|
227
|
+
? await closeZellijPaneById(input.paneRecord.session_name, paneId || '', input.cwd || packageRoot())
|
|
228
|
+
: null;
|
|
229
|
+
const rename = !shouldClose && paneId
|
|
230
|
+
? await renameZellijPaneById(input.paneRecord.session_name, paneId, `${input.paneRecord.pane_title} · ${success ? 'drained' : 'failed'}`, input.cwd || packageRoot())
|
|
183
231
|
: null;
|
|
184
232
|
const next = {
|
|
185
233
|
...input.paneRecord,
|
|
@@ -193,9 +241,25 @@ export async function closeWorkerPane(input) {
|
|
|
193
241
|
stream_event_count: Number(input.streamEventCount || input.paneRecord.stream_event_count || 0),
|
|
194
242
|
structured_output_valid: input.structuredOutputValid === true || input.paneRecord.structured_output_valid === true,
|
|
195
243
|
worker_result_path: input.workerResultPath || input.paneRecord.worker_result_path,
|
|
196
|
-
blockers: [
|
|
244
|
+
blockers: [
|
|
245
|
+
...input.paneRecord.blockers,
|
|
246
|
+
...(input.blockers || []),
|
|
247
|
+
...(close && !close.ok ? close.blockers.map((blocker) => `zellij_worker_close_${blocker}`) : []),
|
|
248
|
+
...(rename && !rename.ok ? rename.blockers.map((blocker) => `zellij_worker_rename_${blocker}`) : [])
|
|
249
|
+
]
|
|
197
250
|
};
|
|
198
251
|
await writeWorkerPaneArtifact(root, next);
|
|
252
|
+
if (next.right_column?.mode === 'spawn-on-first-worker') {
|
|
253
|
+
await closeWorkerInRightColumn({
|
|
254
|
+
root,
|
|
255
|
+
...(input.projectRoot ? { projectRoot: input.projectRoot } : {}),
|
|
256
|
+
missionId: next.mission_id,
|
|
257
|
+
slotId: next.slot_id,
|
|
258
|
+
generationIndex: next.generation_index,
|
|
259
|
+
paneId: next.pane_id,
|
|
260
|
+
status: next.status === 'failed' ? 'failed' : close?.ok ? 'closed' : 'draining'
|
|
261
|
+
});
|
|
262
|
+
}
|
|
199
263
|
await appendWorkerPaneEvent(root, 'pane_closed', {
|
|
200
264
|
root,
|
|
201
265
|
missionId: next.mission_id,
|
|
@@ -374,6 +438,47 @@ async function renameZellijPaneById(sessionName, paneId, paneName, cwd) {
|
|
|
374
438
|
}
|
|
375
439
|
return last;
|
|
376
440
|
}
|
|
441
|
+
async function focusZellijPaneById(sessionName, paneId, cwd) {
|
|
442
|
+
const candidates = zellijPaneIdCandidates(paneId);
|
|
443
|
+
let last = null;
|
|
444
|
+
for (const candidate of candidates) {
|
|
445
|
+
const focus = await runZellij(['--session', sessionName, 'action', 'focus-pane-id', candidate], {
|
|
446
|
+
cwd,
|
|
447
|
+
timeoutMs: 5000,
|
|
448
|
+
optional: true
|
|
449
|
+
});
|
|
450
|
+
last = focus;
|
|
451
|
+
if (focus.ok)
|
|
452
|
+
return focus;
|
|
453
|
+
}
|
|
454
|
+
return last;
|
|
455
|
+
}
|
|
456
|
+
async function closeZellijPaneById(sessionName, paneId, cwd) {
|
|
457
|
+
const candidates = zellijPaneIdCandidates(paneId);
|
|
458
|
+
let last = null;
|
|
459
|
+
for (const candidate of candidates) {
|
|
460
|
+
const close = await runZellij(['--session', sessionName, 'action', 'close-pane', '--pane-id', candidate], {
|
|
461
|
+
cwd,
|
|
462
|
+
timeoutMs: 5000,
|
|
463
|
+
optional: true
|
|
464
|
+
});
|
|
465
|
+
last = close;
|
|
466
|
+
if (close.ok)
|
|
467
|
+
return close;
|
|
468
|
+
}
|
|
469
|
+
return last;
|
|
470
|
+
}
|
|
471
|
+
function zellijPaneIdCandidates(paneId) {
|
|
472
|
+
const raw = String(paneId || '').trim();
|
|
473
|
+
const numeric = raw.replace(/^terminal_/, '');
|
|
474
|
+
const parsed = Number.parseInt(numeric, 10);
|
|
475
|
+
return [...new Set([
|
|
476
|
+
raw,
|
|
477
|
+
numeric,
|
|
478
|
+
Number.isFinite(parsed) ? String(parsed) : '',
|
|
479
|
+
Number.isFinite(parsed) ? `terminal_${parsed}` : ''
|
|
480
|
+
].filter(Boolean))];
|
|
481
|
+
}
|
|
377
482
|
function sleep(ms) {
|
|
378
483
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
379
484
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @ts-nocheck
|
|
3
|
-
import { assertGate, emitGate, packageScripts, readText } from './lib/codex-sdk-gate-lib.js';
|
|
3
|
+
import { assertGate, emitGate, packageScripts, readText, releaseGateIds } from './lib/codex-sdk-gate-lib.js';
|
|
4
4
|
const scripts = packageScripts();
|
|
5
|
-
const releaseCheck = String(scripts['release:check'] || '');
|
|
6
5
|
const releaseRealCheck = String(scripts['release:real-check'] || '');
|
|
7
|
-
|
|
8
|
-
assertGate(
|
|
6
|
+
const releaseGates = releaseGateIds();
|
|
7
|
+
assertGate(releaseGates.has('codex-sdk:capability'), 'release gate DAG must include Codex SDK capability gate');
|
|
8
|
+
assertGate(releaseGates.has('codex-sdk:all-pipelines'), 'release gate DAG must include Codex SDK all-pipelines gate');
|
|
9
9
|
assertGate(releaseRealCheck.includes('codex-sdk:real-smoke'), 'release:real-check must include Codex SDK real smoke');
|
|
10
10
|
assertGate(readText('src/core/agents/agent-orchestrator.ts').includes('legacy_codex_exec_runtime_removed'), 'orchestrator must block legacy codex-exec requests');
|
|
11
|
-
emitGate('codex-sdk:release-review-pipeline', {
|
|
11
|
+
emitGate('codex-sdk:release-review-pipeline', { release_gate_dag_contains_sdk: true });
|
|
12
12
|
//# sourceMappingURL=codex-sdk-release-review-pipeline-check.js.map
|
|
@@ -25,19 +25,40 @@ const run = spawnSync(process.execPath, [
|
|
|
25
25
|
SKS_DISABLE_UPDATE_CHECK: '1'
|
|
26
26
|
},
|
|
27
27
|
encoding: 'utf8',
|
|
28
|
-
timeout:
|
|
28
|
+
timeout: 180000
|
|
29
29
|
});
|
|
30
30
|
const parsed = parseLastJson(run.stdout || '{}');
|
|
31
31
|
const ok = run.status !== 0
|
|
32
32
|
&& parsed.ready?.ready === false
|
|
33
33
|
&& parsed.ready?.blockers?.includes('codex_cli_config_eperm')
|
|
34
34
|
&& parsed.ready?.next_actions?.length > 0;
|
|
35
|
-
console.log(JSON.stringify({
|
|
35
|
+
console.log(JSON.stringify({
|
|
36
|
+
schema: 'sks.doctor-fix-proves-codex-read-check.v1',
|
|
37
|
+
ok,
|
|
38
|
+
status: run.status,
|
|
39
|
+
signal: run.signal,
|
|
40
|
+
error: run.error ? String(run.error.message || run.error) : null,
|
|
41
|
+
parsed,
|
|
42
|
+
stdout_tail: String(run.stdout || '').slice(-1000),
|
|
43
|
+
stderr_tail: String(run.stderr || '').slice(-1000)
|
|
44
|
+
}, null, 2));
|
|
36
45
|
if (!ok)
|
|
37
46
|
process.exitCode = 1;
|
|
38
47
|
function parseLastJson(text) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
48
|
+
const source = String(text || '').trim();
|
|
49
|
+
if (!source)
|
|
50
|
+
return {};
|
|
51
|
+
const starts = [];
|
|
52
|
+
for (let index = source.indexOf('{'); index >= 0; index = source.indexOf('{', index + 1))
|
|
53
|
+
starts.push(index);
|
|
54
|
+
for (let i = starts.length - 1; i >= 0; i -= 1) {
|
|
55
|
+
try {
|
|
56
|
+
return JSON.parse(source.slice(starts[i]));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Continue searching for the outer JSON object; pretty JSON may contain nested objects.
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return {};
|
|
42
63
|
}
|
|
43
64
|
//# sourceMappingURL=doctor-fix-proves-codex-read-check.js.map
|
|
@@ -59,6 +59,10 @@ export async function runFakeCodexSdkTaskFixture(label = 'fixture', extra = {})
|
|
|
59
59
|
export function packageScripts() {
|
|
60
60
|
return readJson('package.json').scripts || {};
|
|
61
61
|
}
|
|
62
|
+
export function releaseGateIds() {
|
|
63
|
+
const manifest = readJson('release-gates.v2.json');
|
|
64
|
+
return new Set((manifest.gates || []).map((gate) => gate.id));
|
|
65
|
+
}
|
|
62
66
|
export function assertSourceIncludes(file, tokens) {
|
|
63
67
|
const text = readText(file);
|
|
64
68
|
for (const token of tokens)
|
|
@@ -17,10 +17,10 @@ const checks = {
|
|
|
17
17
|
zellij_session_before_swarm: launchIndex >= 0 && swarmIndex >= 0 && launchIndex < swarmIndex,
|
|
18
18
|
main_only_session: mad.includes('slotCount: 0'),
|
|
19
19
|
zellij_default_backend: /return 'zellij'/.test(mad) && mad.includes("list.includes('--json')") && mad.includes("list.includes('--no-attach')"),
|
|
20
|
-
worker_command_real_zellij: mad.includes("command.push('--real')") && mad.includes("command.push('--zellij-session-name'") && mad.includes("command.push('--zellij-pane-worker')"),
|
|
20
|
+
worker_command_real_zellij: mad.includes("command.push('--real')") && mad.includes("command.push('--zellij-session-name'") && mad.includes("command.push('--zellij-pane-worker')") && mad.includes("command.push('--worker-placement'"),
|
|
21
21
|
parser_accepts_worker_flags: parser.includes('--zellij-session-name') && parser.includes('--zellij-pane-worker') && parser.includes('--no-zellij-pane-worker'),
|
|
22
22
|
native_worker_pane_path: swarm.includes("this.input.backend === 'zellij'") && swarm.includes('ctx.opts.zellijPaneWorker !== false') && swarm.includes('openWorkerPane({'),
|
|
23
|
-
right_pane_requested: manager.includes("'--direction', '
|
|
23
|
+
right_pane_requested: manager.includes("'--direction', directionRequested") && manager.includes("'--near-current-pane'")
|
|
24
24
|
};
|
|
25
25
|
const ok = Object.values(checks).every(Boolean);
|
|
26
26
|
emit({
|
|
@@ -10,6 +10,7 @@ const normal = governorMod.decideNarutoConcurrency({
|
|
|
10
10
|
zellijVisiblePaneCap: 12,
|
|
11
11
|
hardware: {
|
|
12
12
|
cores: 32,
|
|
13
|
+
loadAverage: [0, 0, 0],
|
|
13
14
|
freeMemoryBytes: 48 * 1024 * 1024 * 1024,
|
|
14
15
|
totalMemoryBytes: 64 * 1024 * 1024 * 1024,
|
|
15
16
|
fileDescriptorLimit: 4096,
|
|
@@ -37,7 +38,7 @@ const pressure = governorMod.decideNarutoConcurrency({
|
|
|
37
38
|
diskIoPressure: 0.9
|
|
38
39
|
}
|
|
39
40
|
});
|
|
40
|
-
assertGate(normal.safe_active_workers <=
|
|
41
|
+
assertGate(normal.safe_active_workers >= 32 && normal.safe_active_workers <= 100, 'requested_clones=200 fixture must cap active workers safely while allowing aggressive process-pool fanout', { normal });
|
|
41
42
|
assertGate(normal.safe_zellij_visible_panes === 12 && normal.headless_workers === normal.safe_active_workers - 12, 'zellij visible panes must stay within UI cap', { normal });
|
|
42
43
|
assertGate(normal.local_llm_parallel <= 4, 'local LLM active requests must respect max_parallel_requests=4', { normal });
|
|
43
44
|
assertGate(pressure.safe_active_workers < normal.safe_active_workers, 'memory/load pressure fixture must decrease active workers', { normal: normal.safe_active_workers, pressure: pressure.safe_active_workers });
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
|
|
4
|
+
import { buildNarutoWorkGraph } from '../core/naruto/naruto-work-graph.js';
|
|
5
|
+
import { decideNarutoConcurrency } from '../core/naruto/naruto-concurrency-governor.js';
|
|
6
|
+
const graph = buildNarutoWorkGraph({ requestedClones: 100, writeCapable: true, maxActiveWorkers: 32 });
|
|
7
|
+
const governor = decideNarutoConcurrency({
|
|
8
|
+
requestedClones: 100,
|
|
9
|
+
totalWorkItems: graph.total_work_items,
|
|
10
|
+
pendingWorkQueueSize: graph.total_work_items,
|
|
11
|
+
backend: 'codex-sdk',
|
|
12
|
+
hardware: { cores: 16, loadAverage: [1, 1, 1], freeMemoryBytes: 64 * 1024 * 1024 * 1024, totalMemoryBytes: 128 * 1024 * 1024 * 1024, fileDescriptorLimit: 8192, processCount: 100, terminalRows: 48, remoteApiRateLimitBudget: 32, localLlmMaxParallelRequests: 8 }
|
|
13
|
+
});
|
|
14
|
+
const report = {
|
|
15
|
+
schema: 'sks.naruto-extreme-parallelism-check.v1',
|
|
16
|
+
ok: graph.total_work_items >= 200 && governor.safe_active_workers >= 16 && governor.safe_zellij_visible_panes <= governor.safe_active_workers && graph.mixed_work_kinds.length >= 6,
|
|
17
|
+
graph: { total_work_items: graph.total_work_items, mixed_work_kinds: graph.mixed_work_kinds, write_allowed_count: graph.write_allowed_count },
|
|
18
|
+
governor
|
|
19
|
+
};
|
|
20
|
+
assertGate(report.ok, 'Naruto extreme parallelism must fan out >=2x clones and keep a high safe active pool', report);
|
|
21
|
+
emitGate('naruto:extreme-parallelism', report);
|
|
22
|
+
//# sourceMappingURL=naruto-extreme-parallelism-check.js.map
|