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
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.8** 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.
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
 
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "sks-core"
79
- version = "2.0.8"
79
+ version = "2.0.9"
80
80
  dependencies = [
81
81
  "serde_json",
82
82
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "2.0.8"
3
+ version = "2.0.9"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -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.8"),
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.8",
5
- "source_digest": "5009938d20628f783aa7ac19da170d2737fef89481b49d9c8dc3f2f97c0dcf9d",
6
- "source_file_count": 2004,
7
- "built_at_source_time": 1780739165211
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
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const FAST_PACKAGE_VERSION = '2.0.8';
2
+ const FAST_PACKAGE_VERSION = '2.0.9';
3
3
  const args = process.argv.slice(2);
4
4
  try {
5
5
  if (args[0] === '--agent' && args[1] === 'worker') {
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "schema": "sks.dist-build.v2",
3
- "version": "2.0.8",
4
- "package_version": "2.0.8",
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": 1067,
8
- "compiled_js_count": 1067,
7
+ "compiled_file_count": 1079,
8
+ "compiled_js_count": 1079,
9
9
  "compiled_dts_count": 0,
10
- "source_digest": "5009938d20628f783aa7ac19da170d2737fef89481b49d9c8dc3f2f97c0dcf9d",
11
- "source_file_count": 2004,
12
- "source_files_hash": "045de0cf4e0b27b18838e5826c77f19ee281908588bbfde4a00a448b5a3c03eb",
13
- "source_list_hash": "045de0cf4e0b27b18838e5826c77f19ee281908588bbfde4a00a448b5a3c03eb",
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",
@@ -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|capability [--require-real] [--json]',
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]) => `${key}=${shellQuote(String(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
- return `${envPrefix.join(' ')} ${command} > ${shellQuote(input.stdoutPath)} 2> ${shellQuote(input.stderrPath)}; code=$?; ${heartbeat}; ${hold}; exit $code`.trim();
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
- launch.dashboard_pane = await openZellijDashboardPane({
118
- root: madLaunch.root,
119
- missionId: madLaunch.mission_id,
120
- sessionName: launch.session_name,
121
- cwd: process.cwd(),
122
- snapshot: {
123
- mode: 'mad-sks',
124
- backend_counts: { zellij: 1 },
125
- placement_counts: { 'zellij-pane': 1, headless: 0 },
126
- active_workers: 1,
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),