sneakoscope 1.21.2 → 1.21.4
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 +3 -3
- 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 +6 -6
- package/dist/cli/install-helpers.d.ts +1 -1
- package/dist/cli/install-helpers.js +17 -8
- package/dist/commands/image-ux-review.d.ts +3 -0
- package/dist/commands/mad-sks.d.ts +1 -0
- package/dist/commands/ppt.d.ts +3 -0
- package/dist/core/agents/agent-gate.d.ts +1 -0
- package/dist/core/agents/agent-gate.js +14 -2
- package/dist/core/agents/agent-orchestrator.d.ts +3 -0
- package/dist/core/agents/agent-orchestrator.js +15 -1
- package/dist/core/agents/agent-proof-evidence.d.ts +2 -0
- package/dist/core/agents/agent-proof-evidence.js +3 -0
- package/dist/core/agents/agent-roster.d.ts +5 -0
- package/dist/core/agents/agent-roster.js +33 -7
- package/dist/core/agents/agent-schema.d.ts +1 -0
- package/dist/core/agents/route-collaboration-ledger.d.ts +3 -0
- package/dist/core/agents/zellij-lane-supervisor.js +7 -3
- package/dist/core/agents/zellij-right-lane-cockpit.js +1 -1
- package/dist/core/commands/fast-mode-command.d.ts +51 -0
- package/dist/core/commands/fast-mode-command.js +5 -0
- package/dist/core/commands/image-ux-review-command.d.ts +3 -0
- package/dist/core/commands/mad-sks-command.d.ts +1 -0
- package/dist/core/commands/naruto-command.js +44 -22
- package/dist/core/commands/ppt-command.d.ts +3 -0
- package/dist/core/commands/team-command.js +10 -7
- package/dist/core/fsx.d.ts +1 -1
- package/dist/core/fsx.js +1 -1
- package/dist/core/proof/auto-finalize.js +24 -20
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-clipboard-config.d.ts +2 -0
- package/dist/core/zellij/zellij-clipboard-config.js +9 -7
- package/dist/core/zellij/zellij-lane-renderer.js +33 -3
- package/dist/core/zellij/zellij-launcher.d.ts +3 -0
- package/dist/core/zellij/zellij-launcher.js +1 -0
- package/dist/core/zellij/zellij-layout-builder.js +10 -2
- package/dist/scripts/release-parallel-check.js +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -16,11 +16,11 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
|
|
|
16
16
|
|
|
17
17
|
## Current Release
|
|
18
18
|
|
|
19
|
-
SKS **1.21.
|
|
19
|
+
SKS **1.21.4** makes Fast mode state and Naruto clone activity directly visible in SKS Zellij lanes. The lane renderer now resolves the project-local `sks fast-mode on|off` preference even before worker scheduler artifacts arrive, and Naruto launches the right-side Zellij lane stack before clone scheduling starts so each clone slot can show live activity. Naruto's host-capacity model also no longer collapses `codex-exec` concurrency to one slot on capable Macs just because `freemem` is low; use `--concurrency` / `--target-active-slots` or `SKS_NARUTO_MAX_CONCURRENCY` for explicit operator control. SKS-launched interactive Codex panes also use `--no-alt-screen` by default so Mac trackpad/wheel gestures scroll the terminal conversation history instead of the prompt textarea/history; set `SKS_ZELLIJ_CODEX_ALT_SCREEN=1` before launch to opt back into alternate-screen mode. It carries forward the 1.21.3 Zellij clipboard, visual lane count, direct-publish stamp repair, and Codex Fast mode repair fixes.
|
|
20
20
|
|
|
21
21
|
SKS **1.20.4** is a targeted `sks --mad` / codex-lb Zellij usability patch: when a background MAD Zellij session launches successfully, SKS now prints the exact `Attach with: ZELLIJ_SOCKET_DIR=... zellij attach ...` command so operators can enter the fresh session without manually reconstructing the socket namespace.
|
|
22
22
|
|
|
23
|
-
SKS **1.20.3** added the macOS Zellij launch fallback and project-local Fast mode control. SKS supplies a short per-user `ZELLIJ_SOCKET_DIR` by default, caps generated session names safely, records `*_command_with_env` attach commands, and classifies `IPC socket path is too long` as `zellij_socket_path_too_long` instead of a generic launch failure. It also adds `sks fast-mode on|off|status|clear`, `$Fast-On`, `$Fast-Off`, and `$Fast-Mode`; saved project preferences are used only when no explicit `--fast`, `--no-fast`, or `--service-tier` flag is present.
|
|
23
|
+
SKS **1.20.3** added the macOS Zellij launch fallback and project-local Fast mode control. SKS supplies a short per-user `ZELLIJ_SOCKET_DIR` by default, caps generated session names safely, records `*_command_with_env` attach commands, and classifies `IPC socket path is too long` as `zellij_socket_path_too_long` instead of a generic launch failure. It also adds `sks fast-mode on|off|status|clear`, `$Fast-On`, `$Fast-Off`, and `$Fast-Mode`; saved project preferences are used only when no explicit `--fast`, `--no-fast`, or `--service-tier` flag is present. In 1.21.3 and newer, the explicit `on` action also restores Codex App/CLI Fast mode defaults in `~/.codex/config.toml` when they were disabled.
|
|
24
24
|
|
|
25
25
|
It carries forward the **1.20.2** stabilization layer: **Mutation Guard** routes genuinely-risky global/config/permission/package mutations through the Requested-Scope Contract + Mutation Ledger (`safety:mutation-callsite-coverage` fails any unguarded, unallowlisted risky call site); `release:check:dynamic:execute` is the real **caching gate runner** (schema v2, real/heavy gates deferred to `release:real-check`, dynamic-only cannot authorize publish); the **Core Skill** deployed snapshot is read by the route runtime and recorded in `agent-proof-evidence.json` (`selected_core_skill`), with promotions written to the mutation ledger; and `sks doctor` exposes an explicit **`zellij_readiness`** block (`zellij:doctor-readiness`). See `docs/dynamic-release-pipeline.md`.
|
|
26
26
|
|
|
@@ -341,7 +341,7 @@ sks team open-zellij latest
|
|
|
341
341
|
sks team attach-zellij latest
|
|
342
342
|
```
|
|
343
343
|
|
|
344
|
-
Interactive SKS sessions use Zellij layouts. By default SKS launches Codex in Fast service tier with `--model gpt-5.5`, `-c service_tier="fast"`,
|
|
344
|
+
Interactive SKS sessions use Zellij layouts. By default SKS launches Codex in Fast service tier with `--model gpt-5.5`, `-c service_tier="fast"`, the selected `model_reasoning_effort`, and `--no-alt-screen` for Zellij-backed interactive panes so terminal scrollback captures the conversation transcript. SKS always forces the model to `gpt-5.5`; `SKS_CODEX_MODEL` and `SKS_CODEX_FAST_HIGH=0` cannot downgrade or remove that model pin. You can still set `SKS_CODEX_REASONING` to change reasoning effort, and `SKS_ZELLIJ_CODEX_ALT_SCREEN=1` restores Codex's alternate-screen UI for the next launch. Use `sks --mad --workspace <name>` for an explicit MAD session and `sks help` for CLI help.
|
|
345
345
|
|
|
346
346
|
Before opening the interactive runtime, SKS checks the installed Codex CLI against npm `@openai/codex@latest`. If a newer version exists, it asks `Y/n`; answering `y` updates automatically with `npm i -g @openai/codex@latest` and then opens the runtime with the updated Codex CLI.
|
|
347
347
|
|
|
@@ -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 1.21.
|
|
7
|
+
Some("--version") => println!("sks-rs 1.21.4"),
|
|
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": "1.21.
|
|
5
|
-
"source_digest": "
|
|
6
|
-
"source_file_count":
|
|
7
|
-
"built_at_source_time":
|
|
4
|
+
"package_version": "1.21.4",
|
|
5
|
+
"source_digest": "70780332db02a19044731adecdb06abcf7d9efdc8b128627be712ca33b3c6881",
|
|
6
|
+
"source_file_count": 1755,
|
|
7
|
+
"built_at_source_time": 1780318491834
|
|
8
8
|
}
|
package/dist/bin/sks.js
CHANGED
package/dist/build-manifest.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "sks.dist-build.v2",
|
|
3
|
-
"version": "1.21.
|
|
4
|
-
"package_version": "1.21.
|
|
3
|
+
"version": "1.21.4",
|
|
4
|
+
"package_version": "1.21.4",
|
|
5
5
|
"typescript": true,
|
|
6
6
|
"mjs_runtime_files": 0,
|
|
7
7
|
"compiled_file_count": 1022,
|
|
8
8
|
"compiled_js_count": 511,
|
|
9
9
|
"compiled_dts_count": 511,
|
|
10
|
-
"source_digest": "
|
|
11
|
-
"source_file_count":
|
|
12
|
-
"source_files_hash": "
|
|
13
|
-
"source_list_hash": "
|
|
10
|
+
"source_digest": "70780332db02a19044731adecdb06abcf7d9efdc8b128627be712ca33b3c6881",
|
|
11
|
+
"source_file_count": 1755,
|
|
12
|
+
"source_files_hash": "e6487058a1a0894c6b8a629b64319d45be1ad9a0658ab422a39969c1e39ad7e3",
|
|
13
|
+
"source_list_hash": "e6487058a1a0894c6b8a629b64319d45be1ad9a0658ab422a39969c1e39ad7e3",
|
|
14
14
|
"src_mjs_runtime_files": 0,
|
|
15
15
|
"dist_stamp_schema": "sks.dist-build-stamp.v1",
|
|
16
16
|
"files": [
|
|
@@ -336,7 +336,7 @@ export declare function ensureGlobalCodexFastModeDuringInstall(opts?: any): Prom
|
|
|
336
336
|
backup_path?: never;
|
|
337
337
|
parse_smoke?: never;
|
|
338
338
|
}>;
|
|
339
|
-
export declare function normalizeCodexFastModeUiConfig(text?: any): string;
|
|
339
|
+
export declare function normalizeCodexFastModeUiConfig(text?: any, opts?: any): string;
|
|
340
340
|
export declare function safeWriteCodexConfigToml(configPath: string, current: string, next: string, tag?: string): Promise<{
|
|
341
341
|
ok: boolean;
|
|
342
342
|
status: string;
|
|
@@ -1479,7 +1479,7 @@ export async function ensureGlobalCodexFastModeDuringInstall(opts = {}) {
|
|
|
1479
1479
|
return { status: 'unparseable_config_preserved', config_path: configPath, backup_path: backupPath, parse_smoke: currentSmoke };
|
|
1480
1480
|
}
|
|
1481
1481
|
}
|
|
1482
|
-
const next = normalizeCodexFastModeUiConfig(current);
|
|
1482
|
+
const next = normalizeCodexFastModeUiConfig(current, { forceFastMode: opts.forceFastMode === true });
|
|
1483
1483
|
if (next === ensureTrailingNewline(current))
|
|
1484
1484
|
return { status: 'present', config_path: configPath };
|
|
1485
1485
|
// Safety gate 2: never WRITE a config that would not parse.
|
|
@@ -1495,12 +1495,12 @@ export async function ensureGlobalCodexFastModeDuringInstall(opts = {}) {
|
|
|
1495
1495
|
return { status: 'failed', config_path: configPath, error: err.message };
|
|
1496
1496
|
}
|
|
1497
1497
|
}
|
|
1498
|
-
export function normalizeCodexFastModeUiConfig(text = '') {
|
|
1498
|
+
export function normalizeCodexFastModeUiConfig(text = '', opts = {}) {
|
|
1499
1499
|
// Run to a fixed point so a second install is a true no-op (idempotent). The per-pass
|
|
1500
1500
|
// table/whitespace normalization converges within one extra pass.
|
|
1501
|
-
return normalizeCodexFastModeUiConfigOnce(normalizeCodexFastModeUiConfigOnce(text));
|
|
1501
|
+
return normalizeCodexFastModeUiConfigOnce(normalizeCodexFastModeUiConfigOnce(text, opts), opts);
|
|
1502
1502
|
}
|
|
1503
|
-
function normalizeCodexFastModeUiConfigOnce(text = '') {
|
|
1503
|
+
function normalizeCodexFastModeUiConfigOnce(text = '', opts = {}) {
|
|
1504
1504
|
// Preserve user-owned top-level scalars (model / service_tier / model_reasoning_effort):
|
|
1505
1505
|
// SKS only supplies a default when the user has not chosen one, and never strips the
|
|
1506
1506
|
// user's own reasoning effort. SKS continues to manage its own namespaced tables below
|
|
@@ -1509,7 +1509,9 @@ function normalizeCodexFastModeUiConfigOnce(text = '') {
|
|
|
1509
1509
|
next = removeTomlTableKey(next, 'notice', 'fast_default_opt_out');
|
|
1510
1510
|
next = removeTomlTableKey(next, 'features', 'codex_hooks');
|
|
1511
1511
|
next = upsertTopLevelTomlStringIfAbsent(next, 'model', 'gpt-5.5');
|
|
1512
|
-
next =
|
|
1512
|
+
next = opts.forceFastMode === true
|
|
1513
|
+
? upsertTopLevelTomlString(next, 'service_tier', 'fast')
|
|
1514
|
+
: upsertTopLevelTomlStringIfAbsent(next, 'service_tier', 'fast');
|
|
1513
1515
|
// Codex App feature flags / fast-mode UI / suppress-warning are SET-IF-ABSENT: a fresh
|
|
1514
1516
|
// config still gets SKS's defaults, but SKS NEVER overrides (re-enables) a feature the
|
|
1515
1517
|
// user disabled in the App, and never rejects-then-hides UI by forcing an unrecognized
|
|
@@ -1522,9 +1524,16 @@ function normalizeCodexFastModeUiConfigOnce(text = '') {
|
|
|
1522
1524
|
'guardian_approval = true', 'tool_suggest = true', 'apps = true', 'plugins = true'
|
|
1523
1525
|
])
|
|
1524
1526
|
next = upsertTomlTableKeyIfAbsent(next, 'features', featureLine);
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1527
|
+
if (opts.forceFastMode === true) {
|
|
1528
|
+
next = upsertTomlTableKey(next, 'user.fast_mode', 'visible = true');
|
|
1529
|
+
next = upsertTomlTableKey(next, 'user.fast_mode', 'enabled = true');
|
|
1530
|
+
next = upsertTomlTableKey(next, 'user.fast_mode', 'default_profile = "sks-fast-high"');
|
|
1531
|
+
}
|
|
1532
|
+
else {
|
|
1533
|
+
next = upsertTomlTableKeyIfAbsent(next, 'user.fast_mode', 'visible = true');
|
|
1534
|
+
next = upsertTomlTableKeyIfAbsent(next, 'user.fast_mode', 'enabled = true');
|
|
1535
|
+
next = upsertTomlTableKeyIfAbsent(next, 'user.fast_mode', 'default_profile = "sks-fast-high"');
|
|
1536
|
+
}
|
|
1528
1537
|
// Keep ONLY the sks-fast-high config-profile table: the Codex App fast-mode
|
|
1529
1538
|
// (`[user.fast_mode] default_profile = "sks-fast-high"`) and the
|
|
1530
1539
|
// codex-app:ui-preservation gate still expect it. The other SKS config profiles are
|
|
@@ -511,6 +511,7 @@ export declare function run(command: any, args?: any): Promise<void | {
|
|
|
511
511
|
status: string;
|
|
512
512
|
blockers: string[];
|
|
513
513
|
};
|
|
514
|
+
visual_lane_count?: never;
|
|
514
515
|
native_cli_session_proof?: never;
|
|
515
516
|
no_subagent_scaling_policy?: never;
|
|
516
517
|
fast_mode_policy?: never;
|
|
@@ -578,6 +579,7 @@ export declare function run(command: any, args?: any): Promise<void | {
|
|
|
578
579
|
requested_work_items: number;
|
|
579
580
|
actual_total_work_items: any;
|
|
580
581
|
target_active_slots: number;
|
|
582
|
+
visual_lane_count: number;
|
|
581
583
|
minimum_work_items: number;
|
|
582
584
|
scheduler: {
|
|
583
585
|
schema: string;
|
|
@@ -974,6 +976,7 @@ export declare function run(command: any, args?: any): Promise<void | {
|
|
|
974
976
|
all_generations_closed: boolean;
|
|
975
977
|
scheduler_state: string;
|
|
976
978
|
target_active_slots: number;
|
|
979
|
+
visual_lane_count: number;
|
|
977
980
|
requested_work_items: number;
|
|
978
981
|
actual_total_work_items: number;
|
|
979
982
|
minimum_work_items: number;
|
|
@@ -29,6 +29,7 @@ export declare function run(_command: any, args?: any): Promise<void | {
|
|
|
29
29
|
zellij_socket_dir_source: import("../core/zellij/zellij-command.js").ZellijSocketDirSource;
|
|
30
30
|
clipboard_config_path: string;
|
|
31
31
|
clipboard_copy_command: string;
|
|
32
|
+
clipboard_mouse_mode: boolean;
|
|
32
33
|
pane_proof_path: string;
|
|
33
34
|
pane_proof: {
|
|
34
35
|
schema: string;
|
package/dist/commands/ppt.d.ts
CHANGED
|
@@ -360,6 +360,7 @@ export declare function run(command: any, args?: any): Promise<void | {
|
|
|
360
360
|
status: string;
|
|
361
361
|
blockers: string[];
|
|
362
362
|
};
|
|
363
|
+
visual_lane_count?: never;
|
|
363
364
|
native_cli_session_proof?: never;
|
|
364
365
|
no_subagent_scaling_policy?: never;
|
|
365
366
|
fast_mode_policy?: never;
|
|
@@ -427,6 +428,7 @@ export declare function run(command: any, args?: any): Promise<void | {
|
|
|
427
428
|
requested_work_items: number;
|
|
428
429
|
actual_total_work_items: any;
|
|
429
430
|
target_active_slots: number;
|
|
431
|
+
visual_lane_count: number;
|
|
430
432
|
minimum_work_items: number;
|
|
431
433
|
scheduler: {
|
|
432
434
|
schema: string;
|
|
@@ -823,6 +825,7 @@ export declare function run(command: any, args?: any): Promise<void | {
|
|
|
823
825
|
all_generations_closed: boolean;
|
|
824
826
|
scheduler_state: string;
|
|
825
827
|
target_active_slots: number;
|
|
828
|
+
visual_lane_count: number;
|
|
826
829
|
requested_work_items: number;
|
|
827
830
|
actual_total_work_items: number;
|
|
828
831
|
minimum_work_items: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { AGENT_INTAKE_STAGE_ID } from './agent-schema.js';
|
|
3
|
+
import { AGENT_INTAKE_STAGE_ID, DEFAULT_AGENT_COUNT } from './agent-schema.js';
|
|
4
4
|
async function exists(file) {
|
|
5
5
|
try {
|
|
6
6
|
await fs.access(file);
|
|
@@ -22,8 +22,16 @@ export async function readAgentGateStatus(root, missionId) {
|
|
|
22
22
|
const dir = path.join(root, '.sneakoscope', 'missions', missionId);
|
|
23
23
|
const proofPath = path.join(dir, 'agents', 'agent-proof-evidence.json');
|
|
24
24
|
const gatePath = path.join(dir, 'agent-gate.json');
|
|
25
|
+
const policyPath = path.join(dir, 'agents', 'agent-concurrency-policy.json');
|
|
26
|
+
const teamPlanPath = path.join(dir, 'team-plan.json');
|
|
25
27
|
const proof = await readJson(proofPath, null);
|
|
26
28
|
const gate = await readJson(gatePath, null);
|
|
29
|
+
const policy = await readJson(policyPath, null);
|
|
30
|
+
const teamPlan = await readJson(teamPlanPath, null);
|
|
31
|
+
const expectedAgentCount = Math.max(DEFAULT_AGENT_COUNT, Number(gate?.expected_agent_count ||
|
|
32
|
+
teamPlan?.bundle_size ||
|
|
33
|
+
policy?.agents ||
|
|
34
|
+
DEFAULT_AGENT_COUNT) || DEFAULT_AGENT_COUNT);
|
|
27
35
|
const missing = [];
|
|
28
36
|
if (!(await exists(proofPath)))
|
|
29
37
|
missing.push('agents/agent-proof-evidence.json');
|
|
@@ -32,8 +40,11 @@ export async function readAgentGateStatus(root, missionId) {
|
|
|
32
40
|
blockers.push('agent_proof_not_ok');
|
|
33
41
|
if (proof?.status !== 'passed')
|
|
34
42
|
blockers.push('agent_proof_status_not_passed');
|
|
35
|
-
|
|
43
|
+
const agentCount = Number(proof?.agent_count || 0);
|
|
44
|
+
if (agentCount < DEFAULT_AGENT_COUNT)
|
|
36
45
|
blockers.push('agent_count_below_5');
|
|
46
|
+
if (agentCount < expectedAgentCount)
|
|
47
|
+
blockers.push('agent_count_below_expected');
|
|
37
48
|
if (proof?.no_overlap_ok !== true)
|
|
38
49
|
blockers.push('agent_no_overlap_not_ok');
|
|
39
50
|
if (proof?.ledger_hash_chain_ok !== true)
|
|
@@ -52,6 +63,7 @@ export async function readAgentGateStatus(root, missionId) {
|
|
|
52
63
|
source: proofPath,
|
|
53
64
|
proof,
|
|
54
65
|
gate,
|
|
66
|
+
expected_agent_count: expectedAgentCount,
|
|
55
67
|
all_sessions_closed: sessionsClosed
|
|
56
68
|
};
|
|
57
69
|
}
|
|
@@ -127,6 +127,7 @@ export declare function runNativeAgentOrchestrator(opts?: AgentRunOptions): Prom
|
|
|
127
127
|
status: string;
|
|
128
128
|
blockers: string[];
|
|
129
129
|
};
|
|
130
|
+
visual_lane_count?: never;
|
|
130
131
|
native_cli_session_proof?: never;
|
|
131
132
|
no_subagent_scaling_policy?: never;
|
|
132
133
|
fast_mode_policy?: never;
|
|
@@ -194,6 +195,7 @@ export declare function runNativeAgentOrchestrator(opts?: AgentRunOptions): Prom
|
|
|
194
195
|
requested_work_items: number;
|
|
195
196
|
actual_total_work_items: any;
|
|
196
197
|
target_active_slots: number;
|
|
198
|
+
visual_lane_count: number;
|
|
197
199
|
minimum_work_items: number;
|
|
198
200
|
scheduler: {
|
|
199
201
|
schema: string;
|
|
@@ -590,6 +592,7 @@ export declare function runNativeAgentOrchestrator(opts?: AgentRunOptions): Prom
|
|
|
590
592
|
all_generations_closed: boolean;
|
|
591
593
|
scheduler_state: string;
|
|
592
594
|
target_active_slots: number;
|
|
595
|
+
visual_lane_count: number;
|
|
593
596
|
requested_work_items: number;
|
|
594
597
|
actual_total_work_items: number;
|
|
595
598
|
minimum_work_items: number;
|
|
@@ -79,6 +79,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
79
79
|
})
|
|
80
80
|
}));
|
|
81
81
|
const targetActiveSlots = normalizeTargetActiveSlots(opts.targetActiveSlots ?? opts.agents ?? roster.agent_count, maxAgentCount);
|
|
82
|
+
const visualLaneCount = normalizeVisualLaneCount(opts.visualLaneCount ?? opts.clones ?? opts.agents ?? roster.agent_count, roster.agent_count, maxAgentCount);
|
|
82
83
|
const desiredWorkItemCount = normalizeDesiredWorkItemCount(opts.desiredWorkItemCount, opts.minimumWorkItems, targetActiveSlots);
|
|
83
84
|
const minimumWorkItems = normalizeMinimumWorkItems(opts.minimumWorkItems, targetActiveSlots);
|
|
84
85
|
const sourceIntelligence = await runSourceIntelligence({ root, missionDir: dir, route, query: prompt, offline: true, context7Available: true });
|
|
@@ -195,7 +196,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
195
196
|
await writeIntelligentWorkGraphArtifacts(ledgerRoot, partition.intelligent_work_graph);
|
|
196
197
|
await writeScoutPolicyArtifact(ledgerRoot);
|
|
197
198
|
await writeZellijRightLaneCockpit(ledgerRoot, { missionId, sessionName: `sks-${missionId}`, agents: roster.roster });
|
|
198
|
-
await initializeZellijLaneSupervisor(ledgerRoot, { missionId, sessionName: `sks-${missionId}`, targetActiveSlots, launchRealZellij: realZellij });
|
|
199
|
+
await initializeZellijLaneSupervisor(ledgerRoot, { missionId, sessionName: `sks-${missionId}`, targetActiveSlots: visualLaneCount, launchRealZellij: realZellij });
|
|
199
200
|
await writeZellijPaneProof(root, { missionId, require: realZellijProofRequired, phase: 'initial', ledgerRoot });
|
|
200
201
|
await writeAgentCodexCockpitArtifacts(dir, { missionId, projectHash: namespace.root_hash });
|
|
201
202
|
await writeJsonAtomic(path.join(ledgerRoot, 'agent-no-overlap-proof.json'), partition.no_overlap_proof || { schema: 'sks.agent-no-overlap-proof.v1', ok: false, blockers: ['missing_no_overlap_proof'] });
|
|
@@ -209,6 +210,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
209
210
|
concurrency: roster.concurrency,
|
|
210
211
|
batch_count: 0,
|
|
211
212
|
target_active_slots: targetActiveSlots,
|
|
213
|
+
visual_lane_count: visualLaneCount,
|
|
212
214
|
desired_work_items: desiredWorkItemCount,
|
|
213
215
|
minimum_work_items: minimumWorkItems,
|
|
214
216
|
requested_work_items: desiredWorkItemCount,
|
|
@@ -404,6 +406,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
404
406
|
minimumWorkItems,
|
|
405
407
|
targetActiveSlots,
|
|
406
408
|
realParallel: backend === 'codex-exec' && opts.mock !== true,
|
|
409
|
+
visualLaneCount,
|
|
407
410
|
roster,
|
|
408
411
|
partition,
|
|
409
412
|
consensus,
|
|
@@ -442,6 +445,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
|
|
|
442
445
|
requested_work_items: desiredWorkItemCount,
|
|
443
446
|
actual_total_work_items: partition.task_graph?.total_work_items || partition.slices.length,
|
|
444
447
|
target_active_slots: targetActiveSlots,
|
|
448
|
+
visual_lane_count: visualLaneCount,
|
|
445
449
|
minimum_work_items: minimumWorkItems,
|
|
446
450
|
scheduler,
|
|
447
451
|
source_intelligence: sourceIntelligenceRef,
|
|
@@ -724,6 +728,16 @@ function normalizeMinimumWorkItems(value, targetActiveSlots) {
|
|
|
724
728
|
return Math.max(1, Math.floor(targetActiveSlots));
|
|
725
729
|
return Math.max(1, Math.floor(parsed));
|
|
726
730
|
}
|
|
731
|
+
function normalizeVisualLaneCount(value, fallback, maxAgentCount) {
|
|
732
|
+
const parsed = Number(value);
|
|
733
|
+
const fallbackCount = Number(fallback);
|
|
734
|
+
const raw = Number.isFinite(parsed) && parsed > 0
|
|
735
|
+
? parsed
|
|
736
|
+
: Number.isFinite(fallbackCount) && fallbackCount > 0
|
|
737
|
+
? fallbackCount
|
|
738
|
+
: 1;
|
|
739
|
+
return Math.max(1, Math.min(maxAgentCount, Math.floor(raw)));
|
|
740
|
+
}
|
|
727
741
|
function isWriteCapableRun(opts) {
|
|
728
742
|
return opts.applyPatches === true || opts.dryRunPatches === true || (opts.writeMode !== undefined && opts.writeMode !== 'off');
|
|
729
743
|
}
|
|
@@ -7,6 +7,7 @@ export declare function writeAgentProofEvidence(root: string, input: {
|
|
|
7
7
|
requestedWorkItems?: number;
|
|
8
8
|
minimumWorkItems?: number;
|
|
9
9
|
targetActiveSlots?: number;
|
|
10
|
+
visualLaneCount?: number;
|
|
10
11
|
realParallel?: boolean;
|
|
11
12
|
roster?: any;
|
|
12
13
|
partition?: any;
|
|
@@ -97,6 +98,7 @@ export declare function writeAgentProofEvidence(root: string, input: {
|
|
|
97
98
|
all_generations_closed: boolean;
|
|
98
99
|
scheduler_state: string;
|
|
99
100
|
target_active_slots: number;
|
|
101
|
+
visual_lane_count: number;
|
|
100
102
|
requested_work_items: number;
|
|
101
103
|
actual_total_work_items: number;
|
|
102
104
|
minimum_work_items: number;
|
|
@@ -47,6 +47,7 @@ export async function writeAgentProofEvidence(root, input) {
|
|
|
47
47
|
const workQueueTotalWorkItems = Number(workQueue?.total_work_items || 0);
|
|
48
48
|
const schedulerTotalWorkItems = Number(scheduler?.total_work_items || 0);
|
|
49
49
|
const targetActiveSlots = Number(input.targetActiveSlots || scheduler?.target_active_slots || taskGraph?.target_active_slots || input.roster?.agent_count || 0);
|
|
50
|
+
const visualLaneCount = Number(input.visualLaneCount || zellijLanes?.lane_count || laneSupervisor?.lane_count || targetActiveSlots || 0);
|
|
50
51
|
const minimumWorkItems = Number(input.minimumWorkItems || taskGraph?.minimum_work_items || targetActiveSlots || 0);
|
|
51
52
|
const taskGraphMatchesCliOptions = Boolean(taskGraph) && requestedWorkItems === taskGraphTotalWorkItems && targetActiveSlots === Number(taskGraph.target_active_slots || 0);
|
|
52
53
|
const workQueueMatchesTaskGraph = Boolean(workQueue && taskGraph) && workQueueTotalWorkItems === taskGraphTotalWorkItems;
|
|
@@ -111,6 +112,7 @@ export async function writeAgentProofEvidence(root, input) {
|
|
|
111
112
|
...(terminalCloseReportCount < generationCount ? ['terminal_close_report_count_below_generation_count'] : []),
|
|
112
113
|
...(slots && slots.all_slots_closed_after_drain !== true ? ['agent_worker_slots_not_closed_after_drain'] : []),
|
|
113
114
|
...(!laneSupervisor ? ['zellij_lane_supervisor_missing'] : []),
|
|
115
|
+
...(laneSupervisor && visualLaneCount > 0 && Number(laneSupervisor.lane_count || 0) < visualLaneCount ? ['zellij_lane_count_below_visual_lane_count'] : []),
|
|
114
116
|
...(laneSupervisor && laneSupervisor.no_flicker_verified !== true ? ['zellij_lane_no_flicker_not_verified'] : []),
|
|
115
117
|
...(laneSupervisor && laneSupervisor.pane_survival_checked !== true ? ['zellij_lane_survival_not_checked'] : []),
|
|
116
118
|
...(laneSupervisor && Number(laneSupervisor.unexpected_close_count || 0) > 0 ? ['zellij_lane_unexpected_close_before_drain'] : []),
|
|
@@ -206,6 +208,7 @@ export async function writeAgentProofEvidence(root, input) {
|
|
|
206
208
|
all_generations_closed: generations.ok,
|
|
207
209
|
scheduler_state: 'agent-scheduler-state.json',
|
|
208
210
|
target_active_slots: targetActiveSlots,
|
|
211
|
+
visual_lane_count: visualLaneCount,
|
|
209
212
|
requested_work_items: requestedWorkItems,
|
|
210
213
|
actual_total_work_items: taskGraphTotalWorkItems || schedulerTotalWorkItems,
|
|
211
214
|
minimum_work_items: minimumWorkItems,
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import type { AgentPersona, AgentRosterEntry } from './agent-schema.js';
|
|
2
2
|
export declare function systemSafeNarutoConcurrency(opts?: {
|
|
3
3
|
backend?: string;
|
|
4
|
+
cores?: number;
|
|
5
|
+
freeBytes?: number;
|
|
6
|
+
totalBytes?: number;
|
|
4
7
|
}): {
|
|
5
8
|
cap: number;
|
|
6
9
|
cores: number;
|
|
7
10
|
free_gb: number;
|
|
11
|
+
total_gb: number;
|
|
8
12
|
backend: string;
|
|
9
13
|
heavy: boolean;
|
|
10
14
|
override_applied: boolean;
|
|
15
|
+
memory_model: string;
|
|
11
16
|
};
|
|
12
17
|
export declare function normalizeAgentCount(value: unknown, fallback?: number, maxAgentCount?: number): number;
|
|
13
18
|
export declare function normalizeAgentConcurrency(value: unknown, agents: number, maxAgentCount?: number): number;
|
|
@@ -7,22 +7,35 @@ import { buildAgentEffortPolicy, decideAgentEffort, decideNarutoCloneEffort } fr
|
|
|
7
7
|
// host can safely sustain — derived from CPU cores and free memory, heavier-bounded for
|
|
8
8
|
// real child-process backends (codex-exec/zellij/process) than for in-process (fake).
|
|
9
9
|
export function systemSafeNarutoConcurrency(opts = {}) {
|
|
10
|
-
const cores = Math.max(1, Number(os.cpus()?.length) || 4);
|
|
10
|
+
const cores = Math.max(1, Number(opts.cores ?? os.cpus()?.length) || 4);
|
|
11
11
|
let freeBytes = 2 * 1024 * 1024 * 1024;
|
|
12
|
+
let totalBytes = 8 * 1024 * 1024 * 1024;
|
|
12
13
|
try {
|
|
13
|
-
freeBytes = os.freemem() || freeBytes;
|
|
14
|
+
freeBytes = Number(opts.freeBytes ?? os.freemem()) || freeBytes;
|
|
15
|
+
}
|
|
16
|
+
catch { /* keep fallback */ }
|
|
17
|
+
try {
|
|
18
|
+
totalBytes = Number(opts.totalBytes ?? os.totalmem()) || totalBytes;
|
|
14
19
|
}
|
|
15
20
|
catch { /* keep fallback */ }
|
|
16
21
|
const freeGb = freeBytes / (1024 * 1024 * 1024);
|
|
22
|
+
const totalGb = totalBytes / (1024 * 1024 * 1024);
|
|
17
23
|
const backend = String(opts.backend || 'codex-exec');
|
|
18
24
|
const heavy = backend === 'codex-exec' || backend === 'zellij' || backend === 'process';
|
|
19
25
|
let cap;
|
|
20
26
|
if (heavy) {
|
|
21
|
-
// Real codex children are
|
|
22
|
-
//
|
|
27
|
+
// Real codex children are heavier than fake workers, but macOS can report
|
|
28
|
+
// very low freemem while reclaimable memory is still available. Use a
|
|
29
|
+
// conservative total-memory floor so Naruto keeps meaningful parallelism
|
|
30
|
+
// instead of collapsing to one slot on otherwise capable machines.
|
|
23
31
|
const byCpu = Math.max(1, cores - 1);
|
|
24
|
-
const
|
|
25
|
-
|
|
32
|
+
const gbPerWorker = positiveEnvNumber('SKS_NARUTO_GB_PER_WORKER', 0.6);
|
|
33
|
+
const reclaimableFloorGb = totalGb >= 16 ? 6 : totalGb >= 8 ? 3 : totalGb >= 4 ? 1.5 : freeGb;
|
|
34
|
+
const budgetGb = Math.max(freeGb, reclaimableFloorGb);
|
|
35
|
+
const byMem = Math.max(1, Math.floor(budgetGb / gbPerWorker));
|
|
36
|
+
const minParallelDefault = totalGb >= 16 ? 8 : totalGb >= 8 ? 4 : totalGb >= 4 ? 2 : 1;
|
|
37
|
+
const minParallel = Math.min(byCpu, Math.floor(positiveEnvNumber('SKS_NARUTO_MIN_CONCURRENCY', minParallelDefault)));
|
|
38
|
+
cap = Math.min(byCpu, Math.max(byMem, minParallel), 16);
|
|
26
39
|
}
|
|
27
40
|
else {
|
|
28
41
|
// In-process / light workers can pack tighter.
|
|
@@ -32,7 +45,20 @@ export function systemSafeNarutoConcurrency(opts = {}) {
|
|
|
32
45
|
if (Number.isFinite(override) && override >= 1)
|
|
33
46
|
cap = Math.min(Math.floor(override), MAX_NARUTO_AGENT_COUNT);
|
|
34
47
|
cap = Math.max(1, Math.min(cap, MAX_NARUTO_AGENT_COUNT));
|
|
35
|
-
return {
|
|
48
|
+
return {
|
|
49
|
+
cap,
|
|
50
|
+
cores,
|
|
51
|
+
free_gb: Math.round(freeGb * 10) / 10,
|
|
52
|
+
total_gb: Math.round(totalGb * 10) / 10,
|
|
53
|
+
backend,
|
|
54
|
+
heavy,
|
|
55
|
+
override_applied: Number.isFinite(override) && override >= 1,
|
|
56
|
+
memory_model: heavy ? 'free_or_reclaimable_floor' : 'light_worker_cpu_bound'
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function positiveEnvNumber(name, fallback) {
|
|
60
|
+
const parsed = Number(process.env[name]);
|
|
61
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
36
62
|
}
|
|
37
63
|
function resolveMaxAgentCount(value) {
|
|
38
64
|
const parsed = Number(value);
|
|
@@ -186,6 +186,7 @@ export declare function writeRouteCollaborationArtifacts(root: string, opts: {
|
|
|
186
186
|
status: string;
|
|
187
187
|
blockers: string[];
|
|
188
188
|
};
|
|
189
|
+
visual_lane_count?: never;
|
|
189
190
|
native_cli_session_proof?: never;
|
|
190
191
|
no_subagent_scaling_policy?: never;
|
|
191
192
|
fast_mode_policy?: never;
|
|
@@ -253,6 +254,7 @@ export declare function writeRouteCollaborationArtifacts(root: string, opts: {
|
|
|
253
254
|
requested_work_items: number;
|
|
254
255
|
actual_total_work_items: any;
|
|
255
256
|
target_active_slots: number;
|
|
257
|
+
visual_lane_count: number;
|
|
256
258
|
minimum_work_items: number;
|
|
257
259
|
scheduler: {
|
|
258
260
|
schema: string;
|
|
@@ -649,6 +651,7 @@ export declare function writeRouteCollaborationArtifacts(root: string, opts: {
|
|
|
649
651
|
all_generations_closed: boolean;
|
|
650
652
|
scheduler_state: string;
|
|
651
653
|
target_active_slots: number;
|
|
654
|
+
visual_lane_count: number;
|
|
652
655
|
requested_work_items: number;
|
|
653
656
|
actual_total_work_items: number;
|
|
654
657
|
minimum_work_items: number;
|
|
@@ -34,9 +34,13 @@ export async function updateZellijLaneSupervisorFromSlots(root, input) {
|
|
|
34
34
|
targetActiveSlots: Math.max(1, input.slots.length || input.state?.target_active_slots || 1)
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
37
|
+
const slotById = new Map(input.slots.map((slot) => [slot.slot_id, slot]));
|
|
38
|
+
const laneCount = Math.max(supervisor.lanes.length, input.slots.length);
|
|
39
|
+
const lanes = Array.from({ length: laneCount }, (_, index) => {
|
|
40
|
+
const previous = supervisor.lanes[index] || createLane(input.missionId, supervisor.session_name, index + 1, nowIso());
|
|
41
|
+
const slot = slotById.get(previous.slot_id);
|
|
42
|
+
if (!slot)
|
|
43
|
+
return previous;
|
|
40
44
|
return {
|
|
41
45
|
...previous,
|
|
42
46
|
current_session_id: slot.current_session_id,
|
|
@@ -4,7 +4,7 @@ export const ZELLIJ_RIGHT_LANE_LAYOUT_SCHEMA = 'sks.agent-zellij-right-lane-layo
|
|
|
4
4
|
export const ZELLIJ_RIGHT_LANES_SCHEMA = 'sks.agent-zellij-right-lanes.v1';
|
|
5
5
|
export function buildZellijRightLaneCockpit(input = {}) {
|
|
6
6
|
const agents = input.slots || input.agents || [];
|
|
7
|
-
const maxVisible = input.maxVisibleLanes ||
|
|
7
|
+
const maxVisible = input.maxVisibleLanes || Math.max(agents.length, 1);
|
|
8
8
|
const lanes = agents.map((agent, index) => ({
|
|
9
9
|
lane_index: index + 1,
|
|
10
10
|
slot_id: String(agent.slot_id || agent.id || agent.agent_id || `slot-${String(index + 1).padStart(3, '0')}`),
|
|
@@ -12,6 +12,57 @@ export declare function fastModeCommand(args?: string[]): Promise<void | {
|
|
|
12
12
|
fast_mode: boolean;
|
|
13
13
|
service_tier: import("../agents/fast-mode-policy.js").AgentServiceTier;
|
|
14
14
|
disabled_by: "none" | "no-fast" | "service-tier-standard" | "preference-standard";
|
|
15
|
+
codex_fast_mode_repair: {
|
|
16
|
+
status: string;
|
|
17
|
+
reason: string;
|
|
18
|
+
config_path?: never;
|
|
19
|
+
backup_path?: never;
|
|
20
|
+
parse_smoke?: never;
|
|
21
|
+
error?: never;
|
|
22
|
+
} | {
|
|
23
|
+
status: string;
|
|
24
|
+
config_path: any;
|
|
25
|
+
backup_path: string | null;
|
|
26
|
+
parse_smoke: {
|
|
27
|
+
ok: boolean;
|
|
28
|
+
unterminated_multiline_string: boolean;
|
|
29
|
+
invalid_table_header: string | null;
|
|
30
|
+
};
|
|
31
|
+
reason?: never;
|
|
32
|
+
error?: never;
|
|
33
|
+
} | {
|
|
34
|
+
status: string;
|
|
35
|
+
config_path: any;
|
|
36
|
+
reason?: never;
|
|
37
|
+
backup_path?: never;
|
|
38
|
+
parse_smoke?: never;
|
|
39
|
+
error?: never;
|
|
40
|
+
} | {
|
|
41
|
+
status: string;
|
|
42
|
+
config_path: any;
|
|
43
|
+
parse_smoke: {
|
|
44
|
+
ok: boolean;
|
|
45
|
+
unterminated_multiline_string: boolean;
|
|
46
|
+
invalid_table_header: string | null;
|
|
47
|
+
};
|
|
48
|
+
reason?: never;
|
|
49
|
+
backup_path?: never;
|
|
50
|
+
error?: never;
|
|
51
|
+
} | {
|
|
52
|
+
status: string;
|
|
53
|
+
config_path: any;
|
|
54
|
+
backup_path: string | null;
|
|
55
|
+
reason?: never;
|
|
56
|
+
parse_smoke?: never;
|
|
57
|
+
error?: never;
|
|
58
|
+
} | {
|
|
59
|
+
status: string;
|
|
60
|
+
config_path: any;
|
|
61
|
+
error: any;
|
|
62
|
+
reason?: never;
|
|
63
|
+
backup_path?: never;
|
|
64
|
+
parse_smoke?: never;
|
|
65
|
+
} | null;
|
|
15
66
|
policy: import("../agents/fast-mode-policy.js").FastModePolicy;
|
|
16
67
|
dollar_commands: {
|
|
17
68
|
on: string;
|