sneakoscope 6.1.0 → 6.1.2

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 (220) hide show
  1. package/README.md +28 -11
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/dist/bin/fast-inline.js +18 -9
  5. package/dist/bin/sks-dispatch.js +2 -2
  6. package/dist/cli/args.js +2 -0
  7. package/dist/cli/command-manifest-lite.js +2 -3
  8. package/dist/cli/command-registry.js +3 -4
  9. package/dist/cli/help-fast.js +1 -1
  10. package/dist/cli/install-helpers.js +108 -303
  11. package/dist/cli/install-tool-helpers.js +287 -0
  12. package/dist/cli/router.js +40 -4
  13. package/dist/commands/codex-lb.js +51 -20
  14. package/dist/commands/codex.js +39 -1
  15. package/dist/commands/doctor.js +242 -20
  16. package/dist/commands/tmux.js +5 -1
  17. package/dist/commands/zellij-monitor-pane.js +2 -0
  18. package/dist/commands/zellij-viewport-pane.js +3 -1
  19. package/dist/commands/zellij.js +1 -1
  20. package/dist/config/skills-manifest.json +59 -59
  21. package/dist/core/agent-bridge/agent-manifest.js +48 -0
  22. package/dist/core/agents/agent-command-surface.js +2 -1
  23. package/dist/core/agents/agent-effort-policy.js +30 -38
  24. package/dist/core/agents/agent-plan.js +100 -21
  25. package/dist/core/agents/agent-role-config.js +43 -46
  26. package/dist/core/agents/agent-runner-codex-exec.js +16 -3
  27. package/dist/core/agents/agent-schema.js +3 -2
  28. package/dist/core/agents/native-cli-session-swarm.js +1 -1
  29. package/dist/core/agents/zellij-right-lane-cockpit.js +2 -2
  30. package/dist/core/codex/agent-config-file-repair.js +94 -193
  31. package/dist/core/codex/codex-cli-update.js +723 -0
  32. package/dist/core/codex/codex-config-guard.js +7 -2
  33. package/dist/core/codex/codex-project-config-policy.js +3 -6
  34. package/dist/core/codex/codex-startup-config-postcheck.js +52 -42
  35. package/dist/core/codex-adapter.js +35 -22
  36. package/dist/core/codex-app/codex-agent-role-sync.js +13 -54
  37. package/dist/core/codex-app/codex-app-launcher.js +48 -17
  38. package/dist/core/codex-app/codex-app-restart.js +23 -2
  39. package/dist/core/codex-app/sks-menubar.js +128 -2
  40. package/dist/core/codex-control/codex-0139-image-path-real-probe.js +15 -4
  41. package/dist/core/codex-control/codex-0139-web-search-probe.js +17 -6
  42. package/dist/core/codex-control/codex-lb-launch-recovery.js +278 -0
  43. package/dist/core/codex-control/codex-reliability-shield.js +89 -29
  44. package/dist/core/codex-control/codex-sdk-adapter.js +44 -8
  45. package/dist/core/codex-control/codex-task-runner.js +62 -9
  46. package/dist/core/codex-control/python-codex-sdk-adapter.js +30 -3
  47. package/dist/core/codex-exec-output-schema.js +35 -6
  48. package/dist/core/codex-lb/codex-lb-env.js +1 -1
  49. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +291 -0
  50. package/dist/core/codex-native/codex-native-feature-broker.js +9 -16
  51. package/dist/core/codex-native/codex-native-repair-transaction.js +1 -1
  52. package/dist/core/codex-native/core-skill-manifest.js +8 -4
  53. package/dist/core/codex-runtime/codex-desktop-config-policy.js +2 -3
  54. package/dist/core/commands/agent-bridge-command.js +23 -2
  55. package/dist/core/commands/agent-command.js +19 -5
  56. package/dist/core/commands/basic-cli.js +47 -6
  57. package/dist/core/commands/command-utils.js +1 -1
  58. package/dist/core/commands/mad-sks-command.js +33 -8
  59. package/dist/core/commands/naruto-command.js +643 -1156
  60. package/dist/core/commands/research-command.js +293 -231
  61. package/dist/core/commands/run-command.js +100 -23
  62. package/dist/core/commands/team-command.js +2 -3
  63. package/dist/core/commands/team-legacy-observe-command.js +94 -359
  64. package/dist/core/db-safety.js +2 -2
  65. package/dist/core/decision-lattice.js +6 -6
  66. package/dist/core/doctor/codex-startup-config-repair.js +8 -3
  67. package/dist/core/doctor/doctor-codex-startup-repair.js +6 -141
  68. package/dist/core/feature-fixture-executor.js +71 -7
  69. package/dist/core/feature-fixture-runner.js +53 -12
  70. package/dist/core/feature-fixtures.js +47 -14
  71. package/dist/core/feature-registry.js +28 -27
  72. package/dist/core/harness-conflicts.js +18 -9
  73. package/dist/core/hooks-runtime/hook-io.js +8 -4
  74. package/dist/core/hooks-runtime/light-turn.js +70 -0
  75. package/dist/core/hooks-runtime/payload-signals.js +270 -0
  76. package/dist/core/hooks-runtime/team-digest.js +0 -1
  77. package/dist/core/hooks-runtime/tool-output-quarantine.js +93 -0
  78. package/dist/core/hooks-runtime.js +411 -258
  79. package/dist/core/init/skills.js +16 -30
  80. package/dist/core/init.js +144 -36
  81. package/dist/core/managed-assets/managed-assets-manifest.js +417 -10
  82. package/dist/core/mission.js +24 -1
  83. package/dist/core/pipeline-internals/runtime-core.js +570 -177
  84. package/dist/core/pipeline-internals/runtime-gates.js +174 -48
  85. package/dist/core/preflight/parallel-preflight-engine.js +50 -1
  86. package/dist/core/proof/route-proof-gate.js +7 -2
  87. package/dist/core/proof-field.js +1 -1
  88. package/dist/core/provider/model-router.js +33 -31
  89. package/dist/core/recallpulse/policy.js +12 -28
  90. package/dist/core/recallpulse.js +11 -6
  91. package/dist/core/release/npm-pack-proof.js +247 -0
  92. package/dist/core/release/package-dist-snapshot.js +151 -0
  93. package/dist/core/release/package-size-budget.js +5 -0
  94. package/dist/core/release/release-authorization-snapshot.js +115 -0
  95. package/dist/core/release/release-gate-affected-selector.js +14 -2
  96. package/dist/core/release/release-gate-cache-v2.js +30 -0
  97. package/dist/core/release/release-gate-contract.js +161 -0
  98. package/dist/core/release/release-gate-dag.js +1 -0
  99. package/dist/core/release/release-real-contract.js +90 -10
  100. package/dist/core/release-parallel-full-coverage.js +31 -143
  101. package/dist/core/research/claim-evidence-matrix.js +41 -6
  102. package/dist/core/research/experiment-plan.js +14 -10
  103. package/dist/core/research/falsification.js +9 -2
  104. package/dist/core/research/implementation-blueprint-densifier.js +82 -60
  105. package/dist/core/research/implementation-blueprint.js +32 -26
  106. package/dist/core/research/mock-result.js +122 -11
  107. package/dist/core/research/replication-pack.js +15 -8
  108. package/dist/core/research/research-adversarial-review.js +1068 -0
  109. package/dist/core/research/research-claim-builder.js +69 -17
  110. package/dist/core/research/research-claim-synthesizer.js +343 -0
  111. package/dist/core/research/research-cycle-runner.js +53 -3
  112. package/dist/core/research/research-falsification-runner.js +176 -0
  113. package/dist/core/research/research-final-reviewer.js +44 -125
  114. package/dist/core/research/research-realistic-report.js +14 -6
  115. package/dist/core/research/research-review-artifact-digest.js +66 -0
  116. package/dist/core/research/research-source-evidence.js +144 -0
  117. package/dist/core/research/research-source-layer-catalog.js +68 -0
  118. package/dist/core/research/research-source-ledger-merge.js +250 -12
  119. package/dist/core/research/research-source-shards.js +26 -70
  120. package/dist/core/research/research-stage-runner.js +237 -247
  121. package/dist/core/research/research-super-search.js +184 -0
  122. package/dist/core/research/research-synthesis-prompt.js +20 -1
  123. package/dist/core/research/research-synthesis-writer.js +86 -5
  124. package/dist/core/research/research-work-graph.js +25 -18
  125. package/dist/core/research/source-quality-report.js +21 -0
  126. package/dist/core/research.js +429 -280
  127. package/dist/core/routes/constants.js +1 -1
  128. package/dist/core/routes/dollar-manifest-lite.js +11 -11
  129. package/dist/core/routes.js +90 -63
  130. package/dist/core/runtime/task-profile.js +66 -0
  131. package/dist/core/runtime/verification-budget.js +12 -0
  132. package/dist/core/security/high-risk-contracts.js +6 -6
  133. package/dist/core/stop-gate/stop-gate-check.js +49 -12
  134. package/dist/core/subagents/agent-catalog.js +215 -0
  135. package/dist/core/subagents/model-policy.js +118 -0
  136. package/dist/core/subagents/naruto-help-contract.js +40 -0
  137. package/dist/core/subagents/official-subagent-config.js +488 -0
  138. package/dist/core/subagents/official-subagent-preparation.js +251 -0
  139. package/dist/core/subagents/official-subagent-prompt.js +137 -0
  140. package/dist/core/subagents/official-subagent-runner.js +129 -0
  141. package/dist/core/subagents/subagent-evidence.js +663 -0
  142. package/dist/core/subagents/terminology.js +16 -0
  143. package/dist/core/subagents/thread-budget.js +21 -0
  144. package/dist/core/subagents/triwiki-attention.js +65 -0
  145. package/dist/core/super-search/runtime-helpers.js +173 -19
  146. package/dist/core/super-search/runtime.js +140 -15
  147. package/dist/core/super-search/source-records.js +49 -8
  148. package/dist/core/team-review-policy.js +15 -0
  149. package/dist/core/triwiki/triwiki-module-card.js +1 -1
  150. package/dist/core/triwiki-wrongness/wrongness-ledger.js +9 -2
  151. package/dist/core/version-manager.js +51 -1
  152. package/dist/core/version.js +1 -1
  153. package/dist/core/work-order-ledger.js +40 -1
  154. package/dist/core/zellij/zellij-fake-adapter.js +3 -1
  155. package/dist/core/zellij/zellij-launcher.js +37 -8
  156. package/dist/core/zellij/zellij-layout-builder.js +14 -5
  157. package/dist/core/zellij/zellij-official-subagent-activity.js +477 -0
  158. package/dist/core/zellij/zellij-official-subagent-telemetry.js +264 -0
  159. package/dist/core/zellij/zellij-slot-pane-renderer.js +17 -5
  160. package/dist/core/zellij/zellij-slot-telemetry.js +15 -3
  161. package/dist/core/zellij/zellij-ui-mode.js +1 -1
  162. package/dist/core/zellij/zellij-viewport-binder.js +3 -0
  163. package/dist/scripts/agent-role-config-repair-check.js +14 -16
  164. package/dist/scripts/architecture-guard-check.js +8 -1
  165. package/dist/scripts/check-route-modularity.js +0 -1
  166. package/dist/scripts/check-ts-contracts.js +1 -1
  167. package/dist/scripts/codex-control-all-pipelines-check.js +7 -3
  168. package/dist/scripts/codex-control-tool-output-continuity-audit-check.js +27 -0
  169. package/dist/scripts/codex-native-agent-role-content-check.js +15 -7
  170. package/dist/scripts/codex-native-repair-transaction-check.js +3 -1
  171. package/dist/scripts/codex-sdk-all-pipelines-check.js +7 -4
  172. package/dist/scripts/codex-sdk-research-pipeline-check.js +30 -8
  173. package/dist/scripts/db-route-materialization-check.js +33 -0
  174. package/dist/scripts/docs-truthfulness-check.js +3 -1
  175. package/dist/scripts/doctor-codex-startup-repair-check.js +12 -15
  176. package/dist/scripts/doctor-fix-production-blackbox.js +12 -2
  177. package/dist/scripts/doctor-startup-config-repair-blackbox.js +8 -2
  178. package/dist/scripts/doctor-startup-config-repair-check.js +12 -2
  179. package/dist/scripts/install-update-preserves-config-check.js +6 -1
  180. package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +0 -1
  181. package/dist/scripts/managed-role-manifest-parity-check.js +5 -4
  182. package/dist/scripts/naruto-codex-e2e-check.js +14 -7
  183. package/dist/scripts/naruto-shadow-clone-swarm-check.js +4 -201
  184. package/dist/scripts/npm-publish-performance-check.js +20 -12
  185. package/dist/scripts/official-subagent-workflow-check.js +145 -0
  186. package/dist/scripts/package-published-contract-check.js +6 -29
  187. package/dist/scripts/packlist-performance-check.js +17 -3
  188. package/dist/scripts/parallel-verification-engine-check.js +2 -2
  189. package/dist/scripts/prepublish-release-check-or-fast.js +23 -86
  190. package/dist/scripts/release-affected-selector-check.js +74 -1
  191. package/dist/scripts/release-check-stamp.js +153 -248
  192. package/dist/scripts/release-dag-full-coverage-check.js +7 -15
  193. package/dist/scripts/release-dynamic-presets-check.js +2 -1
  194. package/dist/scripts/release-gate-dag-runner-check.js +0 -1
  195. package/dist/scripts/release-gate-dag-runner.js +12 -1
  196. package/dist/scripts/release-gate-existence-audit.js +1 -2
  197. package/dist/scripts/release-parallel-full-coverage-check.js +12 -6
  198. package/dist/scripts/release-parallel-speed-budget-check.js +18 -2
  199. package/dist/scripts/release-real-check.js +26 -4
  200. package/dist/scripts/release-registry-check.js +61 -16
  201. package/dist/scripts/research-blueprint-densifier-check.js +2 -2
  202. package/dist/scripts/research-real-cycle-no-legacy-final-md-check.js +11 -7
  203. package/dist/scripts/sizecheck.js +2 -2
  204. package/dist/scripts/sks-3-1-4-directive-check-lib.js +8 -2
  205. package/dist/scripts/sks-3-1-5-directive-check-lib.js +3 -2
  206. package/dist/scripts/sks-3-1-6-directive-check-lib.js +5 -3
  207. package/dist/scripts/sks-menubar-install-check.js +8 -0
  208. package/dist/scripts/trust-fixture-check.js +32 -10
  209. package/dist/scripts/wrongness-fixture-check.js +1 -1
  210. package/dist/scripts/zellij-layout-valid-check.js +5 -5
  211. package/dist/scripts/zellij-spawn-on-demand-layout-check.js +3 -3
  212. package/docs/demo.tape +1 -1
  213. package/infra-harness-gates.json +1486 -0
  214. package/package.json +13 -10
  215. package/release-gates.v2.json +4060 -0
  216. package/runtime-required-scripts.json +9 -0
  217. package/dist/commands/db.js +0 -6
  218. package/dist/core/commands/db-command.js +0 -146
  219. package/dist/core/research/prompt.js +0 -15
  220. package/dist/scripts/codex-control-tool-call-sequence-repair-check.js +0 -14
@@ -1,6 +1,7 @@
1
1
  import { codexModelEffortCapability } from '../codex-control/codex-model-capabilities.js';
2
2
  import { GLM_52_OPENROUTER_MODEL } from '../providers/glm/glm-52-settings.js';
3
- import { isNarutoGpt56Model, routeNarutoGpt56Model } from '../provider/model-router.js';
3
+ import { isNarutoGpt56Model } from '../provider/model-router.js';
4
+ import { decideSubagentModel } from '../subagents/model-policy.js';
4
5
  const XHIGH_SIGNAL_RE = /(frontier|autoresearch|novelty|hypothesis|falsif|forensic|from-chat-img|image\s*work\s*order|새로운\s*연구|가설|포렌식)/i;
5
6
  const HIGH_SIGNAL_RE = /(database|supabase|sql|migration|security|permission|mad|release|publish|deploy|architecture|policy|schema|hook|rollback|db|보안|배포|마이그레이션|데이터베이스|권한|릴리즈)/i;
6
7
  const MEDIUM_SIGNAL_RE = /(tmux|terminal|cli|tool(?:\s|-)?call|router|routing|orchestrat|pipeline|multi[-\s]?session|multi[-\s]?agent|lease|ledger|proof|검증|파이프라인|오케스트레이션|병렬|에이전트)/i;
@@ -61,21 +62,24 @@ export function decideAgentEffort(input = {}) {
61
62
  ]
62
63
  };
63
64
  }
64
- // $Naruto workers use the codex-lb GPT-5.6 family only. Model and effort are
65
- // selected by the actual work kind; the removed low/medium cap must never be
66
- // reintroduced through tool-count or read-only heuristics.
67
- export function decideNarutoCloneEffort(input = {}) {
65
+ // Official Codex subagents always use max reasoning. Clear bounded work uses
66
+ // Luna; any judgment-bearing slice uses Sol. There is no automatic Terra or
67
+ // lower-effort fallback.
68
+ export function decideOfficialSubagentModel(input = {}) {
68
69
  const persona = input.persona || {};
69
70
  const prompt = String(input.prompt || '');
70
71
  const role = String(persona.role || '');
71
- const agentId = String(input.agentId || persona.id || 'naruto_clone');
72
- const taskText = [role, agentId, persona.naruto_role].join(' ');
73
- const riskText = [prompt, persona.risk_focus, persona.write_policy].join(' ');
74
- const routed = routeNarutoGpt56Model({ taskText, riskText });
75
- const effort = routed.reasoning;
72
+ const agentId = String(input.agentId || persona.id || 'subagent');
73
+ const routed = decideSubagentModel({
74
+ title: [agentId, persona.naruto_role, persona.work_kind].filter(Boolean).join(' '),
75
+ description: [prompt, persona.risk_focus, persona.write_policy].filter(Boolean).join(' '),
76
+ role,
77
+ expectedOutput: (persona.output_expectations || []).join(' ')
78
+ });
79
+ const effort = 'max';
76
80
  const modelCapability = codexModelEffortCapability({
77
81
  model: routed.model,
78
- advertisedEfforts: narutoAdvertisedEfforts(routed.model),
82
+ advertisedEfforts: ['max'],
79
83
  defaultEffort: effort
80
84
  });
81
85
  return {
@@ -87,24 +91,23 @@ export function decideNarutoCloneEffort(input = {}) {
87
91
  reasoning_effort: effort,
88
92
  model_reasoning_effort: effort,
89
93
  model_tier: `${routed.model}-${effort}`,
90
- model_profile: `sks-naruto-${safeProfileSegment(routed.model)}-${effort}-fast`,
91
- model_selection_reason: narutoSelectionReason(routed.model, effort),
94
+ model_profile: `sks-official-subagent-${safeProfileSegment(routed.model)}-${effort}-fast`,
95
+ model_selection_reason: routed.reason,
92
96
  model_effort_capability: modelCapability,
93
97
  reasoning_profile: reasoningProfileName(effort),
94
98
  service_tier: 'fast',
95
- reason: narutoSelectionReason(routed.model, effort),
99
+ reason: routed.reason,
96
100
  dynamic: true,
97
101
  escalation_triggers: [
98
- 'complex or high-risk Terra work escalates from xhigh to max',
99
- 'complex E2E, browser, Computer Use, or forensic Luna verification escalates from xhigh to max',
100
- 'refactoring, architecture, planning, strategy, and integration select Sol at max'
102
+ 'UI, review, debugging, planning, architecture, integration, security, database, release, or ambiguity selects Sol Max',
103
+ 'requiresJudgment or reasoning-sensitive evidence selects Sol Max',
104
+ 'requested model or max effort unavailable blocks instead of silently falling back'
101
105
  ],
102
- downshift_triggers: [
103
- 'ordinary coding stays on Terra xhigh',
104
- 'ordinary E2E, browser, Computer Use, and GUI verification stays on Luna xhigh'
105
- ]
106
+ downshift_triggers: []
106
107
  };
107
108
  }
109
+ /** @deprecated since 6.1.1. Use decideOfficialSubagentModel. */
110
+ export const decideNarutoCloneEffort = decideOfficialSubagentModel;
108
111
  export function buildAgentEffortPolicy(roster = {}) {
109
112
  const decisions = Array.isArray(roster.roster) ? roster.roster.map((agent) => ({
110
113
  agent_id: agent.id,
@@ -126,19 +129,20 @@ export function buildAgentEffortPolicy(roster = {}) {
126
129
  policy_version: 1,
127
130
  dynamic: true,
128
131
  service_tier: 'fast',
129
- model_catalog_policy: narutoFamilyOnly ? 'naruto_gpt_5_6_family_dynamic' : 'codex_catalog_passthrough',
130
- model_constraint: narutoFamilyOnly ? ['gpt-5.6-luna', 'gpt-5.6-terra', 'gpt-5.6-sol'] : null,
132
+ model_catalog_policy: narutoFamilyOnly ? 'official_subagent_luna_sol_max' : 'codex_catalog_passthrough',
133
+ model_constraint: narutoFamilyOnly ? ['gpt-5.6-luna', 'gpt-5.6-sol'] : null,
134
+ explicit_compatibility_models: narutoFamilyOnly ? ['gpt-5.6-terra'] : null,
131
135
  model_tiers: narutoFamilyOnly
132
- ? ['gpt-5.6-luna-xhigh', 'gpt-5.6-luna-max', 'gpt-5.6-terra-xhigh', 'gpt-5.6-terra-max', 'gpt-5.6-sol-max']
136
+ ? ['gpt-5.6-luna-max', 'gpt-5.6-sol-max', 'gpt-5.6-terra-max']
133
137
  : ['codex-selected-low', 'codex-selected-medium', 'codex-selected-high', 'codex-selected-xhigh', 'glm-5.2-minimal', 'glm-5.2-low', 'glm-5.2-high', 'glm-5.2-xhigh'],
134
- allowed_efforts: narutoFamilyOnly ? ['xhigh', 'max'] : codexModelEffortCapability().advertised_efforts,
138
+ allowed_efforts: narutoFamilyOnly ? ['max'] : codexModelEffortCapability().advertised_efforts,
135
139
  model_effort_capability: codexModelEffortCapability(),
136
140
  max_agents: roster.max_agents || 20,
137
141
  agent_count: roster.agent_count || decisions.length,
138
142
  concurrency: roster.concurrency || decisions.length,
139
143
  decisions,
140
144
  rule: narutoFamilyOnly
141
- ? 'Naruto workers use only GPT-5.6 Luna/Terra/Sol: Terra xhigh/max for coding, Sol max for refactoring/planning/strategy/integration, and Luna xhigh/max for E2E/browser/Computer Use/GUI verification.'
145
+ ? 'Official Naruto subagents automatically use GPT-5.6 Luna Max for clear bounded repeatable work and GPT-5.6 Sol Max for every reasoning-sensitive slice; an explicit user-selected Terra model remains compatible but is never selected automatically.'
142
146
  : 'Codex/OpenAI workers inherit the current Codex-selected model, including future catalog entries; SKS changes only advertised reasoning effort. Explicit non-Codex provider modes retain their provider model.'
143
147
  };
144
148
  }
@@ -165,18 +169,6 @@ function effortReason(effort) {
165
169
  return 'simple_bounded_slice';
166
170
  return 'default_orchestration_slice';
167
171
  }
168
- function narutoAdvertisedEfforts(model) {
169
- return model === 'gpt-5.6-luna'
170
- ? ['low', 'medium', 'high', 'xhigh', 'max']
171
- : ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'];
172
- }
173
- function narutoSelectionReason(model, effort) {
174
- if (model === 'gpt-5.6-sol')
175
- return `naruto_refactor_plan_strategy_sol_${effort}`;
176
- if (model === 'gpt-5.6-luna')
177
- return `naruto_e2e_browser_computer_use_luna_${effort}`;
178
- return `naruto_coding_terra_${effort}`;
179
- }
180
172
  export function decideAgentWorkerModel(input = {}) {
181
173
  const mainModel = String(input.mainModel || process.env.SKS_CODEX_MODEL || process.env.CODEX_MODEL || '').trim();
182
174
  const glmMain = isGlmWorkerMode(mainModel);
@@ -1,44 +1,123 @@
1
- import { AGENT_INTAKE_STAGE_ID, DEFAULT_AGENT_COUNT } from './agent-schema.js';
2
- const AGENT_REQUIRED_ROUTE_KEYS = new Set([
3
- 'team', '$team', 'naruto', '$naruto', 'shadowclone', '$shadowclone', 'shadow-clone', '$shadow-clone', 'kagebunshin', '$kagebunshin', 'kage-bunshin', '$kage-bunshin',
4
- 'research', '$research', 'autoresearch', '$autoresearch', 'qa-loop', '$qa-loop', 'review', '$review', 'release-review', '$release-review'
1
+ import { AGENT_INTAKE_STAGE_ID } from './agent-schema.js';
2
+ import { classifyTaskProfile, isTaskProfile } from '../runtime/task-profile.js';
3
+ import { DEFAULT_NARUTO_MAX_THREADS, DEFAULT_NARUTO_REQUESTED_SUBAGENTS, resolveSubagentThreadBudget } from '../subagents/thread-budget.js';
4
+ const OFFICIAL_SUBAGENT_ROUTE_KEYS = new Set([
5
+ 'team', '$team',
6
+ 'naruto', '$naruto',
7
+ 'shadowclone', '$shadowclone',
8
+ 'shadow-clone', '$shadow-clone',
9
+ 'kagebunshin', '$kagebunshin',
10
+ 'kage-bunshin', '$kage-bunshin',
11
+ 'swarm', '$swarm',
12
+ 'work', '$work'
5
13
  ]);
14
+ const EXPLICIT_SUBAGENT_RE = /\$(Team|Naruto|ShadowClone|Shadow-Clone|Kagebunshin|Kage-Bunshin|Swarm|Work)\b/i;
15
+ const PARALLELIZABLE_RE = /\b(parallel|subagents?|fan out|one agent per|independent|disjoint|multiple files|all files)\b|병렬|하위\s*에이전트|서브\s*에이전트|독립|분리된|여러\s*파일|모든\s*파일|분담/i;
6
16
  function routeKey(route) {
7
17
  return String(route?.id || route?.command || route?.name || route || '').trim().toLowerCase();
8
18
  }
9
19
  export function routeRequiresAgentIntake(route, input = {}) {
10
- if (input.noAgents === true || input.agents === false)
20
+ const options = normalizeOptions(input);
21
+ if (options.noAgents === true || options.agents === false)
11
22
  return false;
12
- if (input.force === true || input.forceAgents === true)
23
+ if (options.force === true || options.forceAgents === true)
13
24
  return true;
14
- const key = routeKey(route);
15
- if (AGENT_REQUIRED_ROUTE_KEYS.has(key))
25
+ const task = String(options.task || '');
26
+ const officialRouteWasImplicit = Boolean(route
27
+ && typeof route === 'object'
28
+ && !Array.isArray(route)
29
+ && route.explicit_invocation === false);
30
+ if ((OFFICIAL_SUBAGENT_ROUTE_KEYS.has(routeKey(route)) && !officialRouteWasImplicit) || EXPLICIT_SUBAGENT_RE.test(task))
16
31
  return true;
17
- const task = String(input.task || '');
18
- return /\$(Team|Naruto|ShadowClone|Kagebunshin|Research|AutoResearch|QA-LOOP|Review|Release-Review)\b/i.test(task);
32
+ if (positiveNumber(options.requestedSubagents) || positiveNumber(options.agents))
33
+ return true;
34
+ const profile = taskProfile(options.taskProfile, task);
35
+ if (profile === 'parallel-read' || profile === 'parallel-write')
36
+ return true;
37
+ return profile === 'high-risk' && explicitlyParallelizable(task);
19
38
  }
20
39
  export function normalizeAgentPolicy(route, task = '', input = {}) {
21
- const required = routeRequiresAgentIntake(route, { task, ...(typeof input === 'object' && input ? input : {}) });
40
+ const options = normalizeOptions(input);
41
+ const profile = taskProfile(options.taskProfile, String(task || ''));
42
+ const required = routeRequiresAgentIntake(route, { ...options, task, taskProfile: profile });
43
+ const requested = firstPositiveNumber(options.requestedSubagents, options.agents, options.independentSliceCount);
44
+ const budget = resolveSubagentThreadBudget({
45
+ ...(requested === null ? {} : { requested }),
46
+ ...(positiveNumber(options.maxThreads) ? { configuredMaxThreads: Number(options.maxThreads) } : {}),
47
+ ...(positiveNumber(options.independentSliceCount) ? { independentSliceCount: Number(options.independentSliceCount) } : {})
48
+ });
49
+ const requestedSubagents = required ? budget.requestedSubagents : 0;
22
50
  return {
23
- schema: 'sks.agent-intake-policy.v1',
51
+ schema: 'sks.subagent-intake-policy.v1',
24
52
  required,
53
+ subagents_required: required,
54
+ task_profile: profile,
25
55
  stage_id: AGENT_INTAKE_STAGE_ID,
26
- agent_count: required ? DEFAULT_AGENT_COUNT : 0,
27
- backend: 'native-agent-kernel',
28
- outputs: ['agents/agent-proof-evidence.json', 'agents/agent-sessions.json', 'agents/agent-leases.json', 'agents/agent-consensus.json']
56
+ workflow: 'official_codex_subagent',
57
+ requested_subagents: requestedSubagents,
58
+ max_threads: budget.maxThreads,
59
+ max_depth: budget.maxDepth,
60
+ first_wave: required ? budget.firstWave : 0,
61
+ wave_count: required ? budget.waveCount : 0,
62
+ agent_count: requestedSubagents,
63
+ backend: 'official-codex-subagent',
64
+ reason: policyReason(route, task, profile, required),
65
+ outputs: ['subagent-plan.json', 'subagent-events.jsonl', 'subagent-parent-summary.json', 'subagent-evidence.json'],
66
+ deprecated_fields: ['agent_count']
29
67
  };
30
68
  }
31
69
  export function agentPipelineStage(policy = {}) {
32
70
  const required = policy.required !== false;
71
+ const requestedSubagents = required
72
+ ? Math.max(1, Math.floor(Number(policy.requested_subagents || policy.agent_count || DEFAULT_NARUTO_REQUESTED_SUBAGENTS)))
73
+ : 0;
74
+ const maxThreads = required
75
+ ? Math.max(1, Math.floor(Number(policy.max_threads || DEFAULT_NARUTO_MAX_THREADS)))
76
+ : 0;
33
77
  return {
34
78
  id: AGENT_INTAKE_STAGE_ID,
35
- goal: 'Run native multi-session agent intake with non-overlapping leases and proof evidence.',
36
- agent_count: required ? Number(policy.agent_count || DEFAULT_AGENT_COUNT) : 0,
37
- max_parallel_native_sessions: Number(policy.agent_count || DEFAULT_AGENT_COUNT),
38
- backend: 'native-agent-kernel',
79
+ goal: 'Run a Codex official subagent workflow with disjoint ownership and correlated event evidence.',
80
+ workflow: 'official_codex_subagent',
81
+ requested_subagents: requestedSubagents,
82
+ max_parallel_agent_threads: Math.min(requestedSubagents, maxThreads),
83
+ max_threads: maxThreads,
84
+ max_depth: 1,
85
+ agent_count: requestedSubagents,
86
+ backend: 'official-codex-subagent',
39
87
  read_only: false,
40
- write_policy: 'bounded workspace-write analysis leases; parent-owned integration',
41
- outputs: policy.outputs || ['agents/agent-proof-evidence.json']
88
+ write_policy: 'bounded workspace-write with disjoint path leases; parent-owned integration',
89
+ outputs: policy.outputs || ['subagent-plan.json', 'subagent-events.jsonl', 'subagent-parent-summary.json', 'subagent-evidence.json'],
90
+ deprecated_fields: ['agent_count']
42
91
  };
43
92
  }
93
+ export function explicitlyParallelizable(prompt) {
94
+ return PARALLELIZABLE_RE.test(String(prompt || ''));
95
+ }
96
+ function taskProfile(value, task) {
97
+ return isTaskProfile(value) ? value : classifyTaskProfile(task);
98
+ }
99
+ function normalizeOptions(input) {
100
+ if (typeof input === 'number' && Number.isFinite(input))
101
+ return { agents: input };
102
+ return input && typeof input === 'object' && !Array.isArray(input) ? input : {};
103
+ }
104
+ function firstPositiveNumber(...values) {
105
+ for (const value of values) {
106
+ if (positiveNumber(value))
107
+ return Math.floor(Number(value));
108
+ }
109
+ return null;
110
+ }
111
+ function positiveNumber(value) {
112
+ const parsed = Number(value);
113
+ return Number.isFinite(parsed) && parsed > 0;
114
+ }
115
+ function policyReason(route, task, profile, required) {
116
+ if (!required)
117
+ return `task_profile_${profile}_does_not_require_subagents`;
118
+ if (OFFICIAL_SUBAGENT_ROUTE_KEYS.has(routeKey(route)) || EXPLICIT_SUBAGENT_RE.test(String(task || ''))) {
119
+ return 'explicit_official_subagent_route';
120
+ }
121
+ return `task_profile_${profile}_requires_subagents`;
122
+ }
44
123
  //# sourceMappingURL=agent-plan.js.map
@@ -1,17 +1,30 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { ensureDir, nowIso, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
4
- import { MANAGED_AGENT_ROLES, managedAgentRoleByFile, managedAgentRoleByName, managedAgentRoleContent, managedAgentRoleOwnsText } from '../managed-assets/managed-assets-manifest.js';
3
+ import { nowIso, writeJsonAtomic } from '../fsx.js';
4
+ import { MANAGED_AGENT_ROLES, MANAGED_OFFICIAL_SUBAGENT_ROLES, managedAgentRoleByFile, managedAgentRoleByName, managedAgentRoleContent, managedOfficialSubagentRoleByFile, managedOfficialSubagentRoleByName, managedOfficialSubagentRoleContent } from '../managed-assets/managed-assets-manifest.js';
5
+ import { installOfficialSubagentAgentConfigs } from '../subagents/official-subagent-config.js';
5
6
  export const AGENT_ROLE_CONFIG_REPAIR_SCHEMA = 'sks.agent-role-config-repair.v1';
6
- export const SKS_OWNED_AGENT_CONFIGS = new Map(MANAGED_AGENT_ROLES.map((role) => [
7
- role.filename,
8
- { name: role.codex_name, sandbox: role.sandbox, content: managedAgentRoleContent(role), id: role.id }
9
- ]));
7
+ export const SKS_OWNED_AGENT_CONFIGS = new Map([
8
+ ...MANAGED_OFFICIAL_SUBAGENT_ROLES.map((role) => [
9
+ role.filename,
10
+ { name: role.codex_name, sandbox: role.sandbox ?? null, content: managedOfficialSubagentRoleContent(role), id: role.id }
11
+ ]),
12
+ ...MANAGED_AGENT_ROLES.map((role) => [
13
+ role.filename,
14
+ { name: role.codex_name, sandbox: role.sandbox, content: managedAgentRoleContent(role), id: role.id }
15
+ ])
16
+ ]);
10
17
  export function managedAgentRoleConfigForFile(file) {
18
+ const official = managedOfficialSubagentRoleByFile(file);
19
+ if (official)
20
+ return managedOfficialSubagentRoleContent(official);
11
21
  const role = managedAgentRoleByFile(file);
12
22
  return role ? managedAgentRoleContent(role) : null;
13
23
  }
14
24
  export function managedAgentRoleConfigForRole(role) {
25
+ const official = managedOfficialSubagentRoleByName(role);
26
+ if (official)
27
+ return { file: official.filename, content: managedOfficialSubagentRoleContent(official) };
15
28
  const match = managedAgentRoleByName(role);
16
29
  return match ? { file: match.filename, content: managedAgentRoleContent(match) } : null;
17
30
  }
@@ -19,66 +32,50 @@ export async function repairAgentRoleConfigs(input) {
19
32
  const root = path.resolve(input.root);
20
33
  const codexHome = input.codexHome || process.env.CODEX_HOME || path.join(process.env.HOME || '', '.codex');
21
34
  const candidates = [path.join(root, '.codex', 'agents'), path.join(codexHome, 'agents')];
22
- const missing = [];
23
- const stale = [];
24
- const created = [];
25
- const repaired = [];
26
- const existing = [];
27
- const projectAgentsDir = path.join(root, '.codex', 'agents');
35
+ const officialRepair = await installOfficialSubagentAgentConfigs(root, { apply: input.apply === true });
36
+ const missing = [...officialRepair.missing];
37
+ const stale = [...officialRepair.stale];
38
+ stale.push(...officialRepair.legacy_stale);
39
+ const created = [...officialRepair.created];
40
+ const repaired = [...officialRepair.updated];
41
+ const removed = [...officialRepair.removed_legacy];
42
+ const existing = [...officialRepair.existing];
43
+ const manualBlockers = [...officialRepair.manual_blockers];
44
+ // Exact historical SKS templates are removed by the official installer.
45
+ // Any user-authored or modified legacy TOML remains an extension surface and
46
+ // is only inventoried here; it is never normalized, overwritten, or deleted.
28
47
  for (const role of MANAGED_AGENT_ROLES) {
29
48
  const file = role.filename;
30
- const content = managedAgentRoleContent(role);
31
49
  const foundPaths = candidates.map((dir) => path.join(dir, file)).filter((filePath) => fs.existsSync(filePath));
32
- let managedCopyFound = false;
33
50
  for (const foundPath of foundPaths) {
34
- const text = fs.readFileSync(foundPath, 'utf8');
35
- if (isValidRoleConfig(text, content)) {
36
- managedCopyFound = true;
37
- existing.push(path.relative(root, foundPath) || foundPath);
38
- continue;
39
- }
40
- const projectOwnedByFilename = foundPath.startsWith(`${projectAgentsDir}${path.sep}`);
41
- if (!projectOwnedByFilename && !managedAgentRoleOwnsText(text, role))
42
- continue;
43
- managedCopyFound = true;
44
- stale.push(file);
45
- if (input.apply) {
46
- await ensureDir(path.dirname(foundPath));
47
- await writeTextAtomic(foundPath, content);
48
- repaired.push(path.relative(root, foundPath) || foundPath);
49
- }
50
- }
51
- if (managedCopyFound)
52
- continue;
53
- missing.push(file);
54
- if (input.apply) {
55
- const target = path.join(projectAgentsDir, file);
56
- await ensureDir(path.dirname(target));
57
- await writeTextAtomic(target, content);
58
- created.push(path.relative(root, target));
51
+ existing.push(path.relative(root, foundPath) || foundPath);
59
52
  }
60
53
  }
61
54
  const requiredFixes = missing.length + stale.length;
62
- const appliedFixes = created.length + repaired.length;
55
+ const appliedFixes = created.length + repaired.length + removed.length;
63
56
  const report = {
64
57
  schema: AGENT_ROLE_CONFIG_REPAIR_SCHEMA,
65
58
  generated_at: nowIso(),
66
- ok: input.apply ? requiredFixes === appliedFixes : true,
59
+ ok: input.apply ? requiredFixes === appliedFixes && manualBlockers.length === 0 : manualBlockers.length === 0,
67
60
  apply: input.apply === true,
68
61
  missing,
69
62
  stale,
70
63
  existing,
71
64
  created,
72
65
  repaired,
73
- manifest_role_ids: MANAGED_AGENT_ROLES.map((role) => role.id),
66
+ removed,
67
+ backups: officialRepair.backups,
68
+ manual_blockers: manualBlockers,
69
+ manifest_role_ids: MANAGED_OFFICIAL_SUBAGENT_ROLES.map((role) => role.id),
70
+ legacy_compatibility_role_ids: MANAGED_AGENT_ROLES.map((role) => role.id),
74
71
  warnings_suppressed: true,
75
- blockers: input.apply && requiredFixes !== appliedFixes ? ['agent_role_config_repair_incomplete'] : []
72
+ blockers: [
73
+ ...manualBlockers,
74
+ ...(input.apply && requiredFixes !== appliedFixes ? ['agent_role_config_repair_incomplete'] : [])
75
+ ]
76
76
  };
77
77
  if (input.reportPath)
78
78
  await writeJsonAtomic(input.reportPath, report);
79
79
  return report;
80
80
  }
81
- function isValidRoleConfig(text, expected) {
82
- return text === expected;
83
- }
84
81
  //# sourceMappingURL=agent-role-config.js.map
@@ -4,6 +4,7 @@ import { managedProxyEnvForChild } from '../codex/managed-proxy-env.js';
4
4
  import { agentWorkerEnv, validateAgentWorkerResult } from './agent-worker-pipeline.js';
5
5
  import { fastModeEnv, resolveFastModePolicy } from './fast-mode-policy.js';
6
6
  import { buildCodexExecArgs } from '../codex/codex-cli-syntax-builder.js';
7
+ import { codexLbRecoveryBlockedProcessResult, withCodexLbCliLaunchRecovery } from '../codex-control/codex-lb-launch-recovery.js';
7
8
  export function buildCodexExecAgentArgs(agent, prompt, opts = {}) {
8
9
  const resultFile = opts.resultFile || defaultCodexResultFile(agent, opts);
9
10
  const sandbox = opts.workspaceWrite ? 'workspace-write' : 'read-only';
@@ -72,8 +73,19 @@ export async function runCodexExecAgent(agent, slice, opts = {}) {
72
73
  const stderrFile = path.join(logRoot, 'codex-exec.stderr.log');
73
74
  const allowedCommandsFile = path.join(opts.agentRoot || opts.cwd || process.cwd(), 'agent-allowed-commands.json');
74
75
  const workerEnv = agentWorkerEnv(agent, allowedCommandsFile);
75
- const proxyEnv = managedProxyEnvForChild({ ...process.env, ...(opts.env || {}) });
76
- const result = await runProcess(opts.codexBin || 'codex', command.args, { cwd: opts.cwd || process.cwd(), env: { ...(opts.env || {}), ...proxyEnv, ...fastModeEnv(fastPolicy), ...workerEnv }, timeoutMs: opts.timeoutMs || 30 * 60 * 1000, maxOutputBytes: 256 * 1024, stdoutFile, stderrFile });
76
+ const effectiveEnv = { ...process.env, ...(opts.env || {}) };
77
+ const proxyEnv = managedProxyEnvForChild(effectiveEnv);
78
+ const execute = opts.runProcessImpl || runProcess;
79
+ const guarded = await withCodexLbCliLaunchRecovery({
80
+ root: opts.cwd || process.cwd(),
81
+ env: effectiveEnv,
82
+ cliArgs: command.args.slice(0, -1),
83
+ ...(typeof opts.recoveryFetch === 'function' ? { fetchImpl: opts.recoveryFetch } : {}),
84
+ ...(opts.recoveryTimeoutMs === undefined ? {} : { timeoutMs: opts.recoveryTimeoutMs })
85
+ }, () => execute(opts.codexBin || 'codex', command.args, { cwd: opts.cwd || process.cwd(), env: { ...(opts.env || {}), ...proxyEnv, ...fastModeEnv(fastPolicy), ...workerEnv }, timeoutMs: opts.timeoutMs || 30 * 60 * 1000, maxOutputBytes: 256 * 1024, stdoutFile, stderrFile }));
86
+ const result = guarded.launched
87
+ ? guarded.value
88
+ : codexLbRecoveryBlockedProcessResult(guarded.toolOutputRecovery);
77
89
  const report = await writeCodexProcessReport(opts.agentRoot || opts.cwd || process.cwd(), agent, {
78
90
  project_hash: opts.projectHash || agent.project_hash || agent.root_hash || null,
79
91
  command: [opts.codexBin || 'codex', ...command.args],
@@ -99,6 +111,7 @@ export async function runCodexExecAgent(agent, slice, opts = {}) {
99
111
  stderr_bytes: result.stderrBytes,
100
112
  truncated: result.truncated,
101
113
  timed_out: result.timedOut,
114
+ codex_lb_tool_output_recovery: guarded.toolOutputRecovery,
102
115
  dry_run: false
103
116
  });
104
117
  if (result.code === 0) {
@@ -123,7 +136,7 @@ export async function runCodexExecAgent(agent, slice, opts = {}) {
123
136
  return { ...validated, status: 'blocked', blockers: [...validated.blockers, 'codex_exec_result_schema_invalid'] };
124
137
  }
125
138
  }
126
- return validateAgentWorkerResult({ mission_id: opts.missionId || opts.mission_id || '', agent_id: agent.id, session_id: agent.session_id, persona_id: agent.persona_id || agent.id, task_slice_id: slice?.id || '', status: result.code === 0 ? 'done' : 'failed', backend: 'codex-exec', summary: result.stdout.slice(-1000) || result.stderr.slice(-1000), artifacts: [command.resultFile, report], blockers: result.code === 0 ? ['codex_exec_output_last_message_missing_or_invalid'] : ['codex_exec_exit_' + result.code], confidence: 'verified_partial', unverified: result.code === 0 ? ['codex-exec stdout fallback; resultFile JSON missing or invalid'] : [], writes: [], source_intelligence_refs: agent.source_intelligence_refs || null, goal_mode_ref: agent.goal_mode_ref || null, verification: { status: result.code === 0 ? 'partial' : 'failed', checks: ['codex-exec-exit-code', 'codex-exec-process-report', 'codex-exec-output-last-message'] } });
139
+ return validateAgentWorkerResult({ mission_id: opts.missionId || opts.mission_id || '', agent_id: agent.id, session_id: agent.session_id, persona_id: agent.persona_id || agent.id, task_slice_id: slice?.id || '', status: result.code === 0 ? 'done' : 'failed', backend: 'codex-exec', summary: result.stdout.slice(-1000) || result.stderr.slice(-1000), artifacts: [command.resultFile, report], blockers: result.code === 0 ? ['codex_exec_output_last_message_missing_or_invalid'] : [...(guarded.launched ? [] : guarded.toolOutputRecovery.blockers), 'codex_exec_exit_' + result.code], confidence: 'verified_partial', unverified: result.code === 0 ? ['codex-exec stdout fallback; resultFile JSON missing or invalid'] : [], writes: [], source_intelligence_refs: agent.source_intelligence_refs || null, goal_mode_ref: agent.goal_mode_ref || null, codex_child_report: { tool_output_recovery: guarded.toolOutputRecovery }, verification: { status: result.code === 0 ? 'partial' : 'failed', checks: ['codex-exec-exit-code', 'codex-exec-process-report', 'codex-exec-output-last-message'] } });
127
140
  }
128
141
  function workerNoMcpDefault(agent, opts = {}, sandbox = 'read-only') {
129
142
  if (opts.noMcp !== undefined)
@@ -1,3 +1,4 @@
1
+ export { DEFAULT_NARUTO_MAX_THREADS, DEFAULT_NARUTO_REQUESTED_SUBAGENTS, HARD_NARUTO_MAX_THREADS } from '../subagents/thread-budget.js';
1
2
  export const AGENT_KERNEL_SCHEMA = 'sks.native-agent-kernel.v1';
2
3
  export const AGENT_RESULT_SCHEMA = 'sks.agent-result.v1';
3
4
  export const AGENT_LEDGER_EVENT_SCHEMA = 'sks.agent-ledger-event.v1';
@@ -9,9 +10,9 @@ export const AGENT_COUNT = DEFAULT_AGENT_COUNT;
9
10
  export const AGENT_INTAKE_STAGE_ID = 'native_agent_intake';
10
11
  export const MAX_AGENT_COUNT = 20;
11
12
  export const DEFAULT_AGENT_CONCURRENCY = 4;
12
- // Naruto may queue a large roster, but active workers are governed separately and
13
- // remain bounded by live CPU, memory, load, and I/O pressure.
13
+ /** @deprecated Legacy process-swarm queue ceiling; never an official thread cap. */
14
14
  export const MAX_NARUTO_AGENT_COUNT = 100;
15
+ /** @deprecated Legacy clone default; official workflows use one safe default child unless --agents is explicit. */
15
16
  export const DEFAULT_NARUTO_CLONES = 8;
16
17
  export const AGENT_BACKENDS = ['fake', 'process', 'codex-sdk', 'zellij', 'ollama', 'local-llm'];
17
18
  export function normalizeAgentBackend(input) {
@@ -435,7 +435,7 @@ class NativeCliSessionSwarmRecorder {
435
435
  headless_by_design_viewport_ui: process.env.SKS_ZELLIJ_LEGACY_WORKER_PANES === '1' ? 0 : this.input.targetActiveSlots
436
436
  },
437
437
  active_workers: this.input.targetActiveSlots,
438
- visible_panes: Number(process.env.SKS_ZELLIJ_VIEWPORTS || 4),
438
+ visible_panes: Number(process.env.SKS_ZELLIJ_VIEWPORTS || 1),
439
439
  headless_workers: process.env.SKS_ZELLIJ_LEGACY_WORKER_PANES === '1' ? Math.max(0, this.input.targetActiveSlots - this.zellijVisiblePaneCap(input.ctx.opts)) : this.input.targetActiveSlots,
440
440
  queue_depth: Math.max(0, this.input.requestedAgents - this.input.targetActiveSlots),
441
441
  local_llm: { tps: 0, queue: 0 },
@@ -36,9 +36,9 @@ export function buildZellijRightLaneCockpit(input = {}) {
36
36
  visible_lane_count: Math.min(lanes.length, maxVisible),
37
37
  page_count: pageCount,
38
38
  actual_pane_ids: lanes.map((lane) => lane.pane_id).filter(Boolean),
39
- attach_command: input.sessionName ? `zellij attach ${input.sessionName}` : 'sks team open-zellij latest',
39
+ attach_command: input.sessionName ? `zellij attach ${input.sessionName}` : 'sks zellij status',
40
40
  keyboard_hint: 'Use the Zellij pane controls to move between lanes; detach with the configured Zellij detach binding.',
41
- cleanup_command_hint: 'sks team cleanup-zellij latest',
41
+ cleanup_command_hint: 'Use native Zellij session controls; legacy Team mutation commands are removed.',
42
42
  ok: lanes.length > 0
43
43
  };
44
44
  const laneManifest = {