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.
Files changed (50) hide show
  1. package/README.md +1 -1
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/crates/sks-core/src/main.rs +1 -1
  5. package/dist/.sks-build-stamp.json +4 -4
  6. package/dist/bin/sks.js +1 -1
  7. package/dist/build-manifest.json +20 -8
  8. package/dist/commands/zellij.js +144 -1
  9. package/dist/core/agents/agent-orchestrator.js +4 -2
  10. package/dist/core/agents/native-cli-session-swarm.js +76 -9
  11. package/dist/core/commands/mad-sks-command.js +17 -26
  12. package/dist/core/commands/naruto-command.js +99 -36
  13. package/dist/core/fsx.js +1 -1
  14. package/dist/core/naruto/naruto-active-pool.js +108 -0
  15. package/dist/core/naruto/naruto-concurrency-governor.js +16 -1
  16. package/dist/core/naruto/naruto-work-graph.js +2 -1
  17. package/dist/core/release/release-gate-cache-v2.js +58 -4
  18. package/dist/core/release/release-gate-dag.js +36 -25
  19. package/dist/core/version.js +1 -1
  20. package/dist/core/zellij/zellij-dashboard-renderer.js +22 -6
  21. package/dist/core/zellij/zellij-launcher.js +3 -3
  22. package/dist/core/zellij/zellij-layout-builder.js +1 -1
  23. package/dist/core/zellij/zellij-right-column-layout-proof.js +42 -0
  24. package/dist/core/zellij/zellij-right-column-manager.js +245 -0
  25. package/dist/core/zellij/zellij-worker-pane-manager.js +118 -13
  26. package/dist/scripts/codex-sdk-release-review-pipeline-check.js +5 -5
  27. package/dist/scripts/doctor-fix-proves-codex-read-check.js +26 -5
  28. package/dist/scripts/lib/codex-sdk-gate-lib.js +4 -0
  29. package/dist/scripts/mad-sks-zellij-default-pane-worker-check.js +2 -2
  30. package/dist/scripts/naruto-concurrency-governor-check.js +2 -1
  31. package/dist/scripts/naruto-extreme-parallelism-check.js +22 -0
  32. package/dist/scripts/naruto-real-active-pool-check.js +38 -0
  33. package/dist/scripts/naruto-work-graph-check.js +1 -1
  34. package/dist/scripts/naruto-zellij-dynamic-right-column-check.js +21 -0
  35. package/dist/scripts/product-design-auto-install-check.js +3 -3
  36. package/dist/scripts/product-design-plugin-routing-check.js +3 -3
  37. package/dist/scripts/release-cache-glob-hashing-check.js +42 -0
  38. package/dist/scripts/release-dag-full-coverage-check.js +35 -0
  39. package/dist/scripts/release-parallel-speed-budget-check.js +67 -13
  40. package/dist/scripts/release-readiness-report.js +1 -1
  41. package/dist/scripts/zellij-dashboard-pane-check.js +6 -4
  42. package/dist/scripts/zellij-developer-controls-check.js +20 -0
  43. package/dist/scripts/zellij-dynamic-pane-lifecycle-check.js +21 -0
  44. package/dist/scripts/zellij-initial-main-only-blackbox.js +28 -0
  45. package/dist/scripts/zellij-right-column-geometry-proof.js +29 -0
  46. package/dist/scripts/zellij-right-column-manager-check.js +22 -0
  47. package/dist/scripts/zellij-worker-pane-manager-check.js +2 -1
  48. package/dist/scripts/zellij-worker-pane-manager-single-owner-check.js +7 -6
  49. package/package.json +13 -3
  50. 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(1, Number(input.slotCount || 1));
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(['--session', input.sessionName, 'action', 'new-pane', '--direction', 'right', '--name', paneName, '--', 'sh', '-lc', input.workerCommand], {
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 ? 'right' : 'not_applied';
120
+ let directionApplied = launch?.ok ? directionRequested : 'not_applied';
97
121
  if (createSession.ok && launch && !launch.ok) {
98
- const fallback = await runZellij(['--session', input.sessionName, 'action', 'new-pane', '--name', paneName, '--', 'sh', '-lc', input.workerCommand], {
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: { ...(reconciledPane || {}), rename_pane: renamePane },
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 close = process.env.SKS_ZELLIJ_CLOSE_WORKER_PANE === '1' && input.paneRecord.pane_id
178
- ? await runZellij(['--session', input.paneRecord.session_name, 'action', 'close-pane', '--pane-id', input.paneRecord.pane_id], {
179
- cwd: input.cwd || packageRoot(),
180
- timeoutMs: 5000,
181
- optional: true
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: [...input.paneRecord.blockers, ...(input.blockers || []), ...(close && !close.ok ? close.blockers.map((blocker) => `zellij_worker_close_${blocker}`) : [])]
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
- assertGate(releaseCheck.includes('codex-sdk:capability'), 'release:check must include Codex SDK capability gate');
8
- assertGate(releaseCheck.includes('codex-sdk:all-pipelines'), 'release:check must include Codex SDK all-pipelines gate');
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', { release_check_contains_sdk: true });
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: 60000
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({ schema: 'sks.doctor-fix-proves-codex-read-check.v1', ok, status: run.status, parsed }, null, 2));
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 index = String(text).lastIndexOf('\n{');
40
- const jsonText = index >= 0 ? String(text).slice(index + 1) : String(text).slice(String(text).indexOf('{'));
41
- return JSON.parse(jsonText || '{}');
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', 'right'")
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 <= 32, 'requested_clones=200 fixture must cap active workers safely', { normal });
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