sneakoscope 3.1.1 → 3.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 (49) 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/cli/install-helpers.js +6 -7
  8. package/dist/core/agents/agent-orchestrator.js +7 -2
  9. package/dist/core/agents/agent-proof-evidence.js +20 -0
  10. package/dist/core/agents/fast-mode-policy.js +7 -5
  11. package/dist/core/agents/intelligent-work-graph.js +93 -14
  12. package/dist/core/agents/native-cli-session-swarm.js +46 -0
  13. package/dist/core/agents/no-subagent-scaling-policy.js +10 -1
  14. package/dist/core/agents/official-subagent-helper-policy.js +62 -0
  15. package/dist/core/codex-app.js +0 -2
  16. package/dist/core/commands/fast-mode-command.js +1 -1
  17. package/dist/core/commands/loop-command.js +35 -3
  18. package/dist/core/commands/naruto-command.js +10 -6
  19. package/dist/core/commands/wiki-command.js +35 -1
  20. package/dist/core/fsx.js +1 -1
  21. package/dist/core/init.js +1 -2
  22. package/dist/core/loops/loop-artifacts.js +21 -0
  23. package/dist/core/loops/loop-concurrency-budget.js +55 -0
  24. package/dist/core/loops/loop-final-arbiter-contract.js +28 -0
  25. package/dist/core/loops/loop-finalizer.js +25 -3
  26. package/dist/core/loops/loop-fixture-policy.js +58 -0
  27. package/dist/core/loops/loop-gate-runner.js +48 -7
  28. package/dist/core/loops/loop-gpt-final-arbiter.js +26 -6
  29. package/dist/core/loops/loop-integration-merge.js +20 -15
  30. package/dist/core/loops/loop-interrupt-registry.js +118 -0
  31. package/dist/core/loops/loop-merge-strategy.js +105 -0
  32. package/dist/core/loops/loop-mutation-ledger.js +103 -0
  33. package/dist/core/loops/loop-runtime-control.js +2 -0
  34. package/dist/core/loops/loop-runtime.js +6 -3
  35. package/dist/core/loops/loop-scheduler.js +2 -2
  36. package/dist/core/loops/loop-side-effect-scanner.js +91 -0
  37. package/dist/core/loops/loop-worker-runtime.js +35 -29
  38. package/dist/core/naruto/naruto-loop-mesh.js +3 -0
  39. package/dist/core/proof/auto-finalize.js +3 -2
  40. package/dist/core/proof/route-finalizer.js +71 -6
  41. package/dist/core/release/release-gate-dag.js +56 -1
  42. package/dist/core/version.js +1 -1
  43. package/dist/scripts/lib/native-cli-session-swarm-check-lib.js +14 -2
  44. package/dist/scripts/loop-directive-check-lib.js +1 -1
  45. package/dist/scripts/loop-hardening-check-lib.js +289 -0
  46. package/dist/scripts/prepublish-release-check-or-fast.js +38 -10
  47. package/dist/scripts/release-check-stamp.js +29 -4
  48. package/dist/scripts/release-gate-existence-audit.js +1 -0
  49. package/package.json +28 -1
package/README.md CHANGED
@@ -35,7 +35,7 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
35
35
 
36
36
  ## 🚀 Current Release
37
37
 
38
- SKS **3.1.1** is Codex 0.139-aware while it bundles @openai/codex-sdk 0.138.0 at this release boundary. It detects and uses 0.139 features from the external Codex CLI when that CLI supports them, with release gates that include hermetic fixtures and actual real probes for code-mode web search, preserved `oneOf`/`allOf` tool schemas, doctor env redaction, plugin marketplace `source` and cache behavior, the `-P` profile alias, the multi-agent v2 `interrupt_agent` rename, image referenced-path routing, sandbox/proxy preservation, Zellij stacked/fallback pane proof, pane-lock openWorkerPane integration, release cache safety fixtures, runtime proof summaries, and release proof source-truth artifacts. See [docs/codex-0.139-compat.md](docs/codex-0.139-compat.md) and [docs/codex-0.139-real-probes.md](docs/codex-0.139-real-probes.md).
38
+ SKS **3.1.2** hardens Loop Mesh for production use: fixture workers/gates/final arbiters are test-only, `gpt:final-arbiter` is explicitly finalizer-owned, integration merge uses a strategy ladder, side-effect reports come from loop diffs and mutation ledgers, loop kill interrupts active worker sessions, and global loop concurrency budgets prevent worker/model-call oversubscription. It remains Codex 0.139-aware while bundling @openai/codex-sdk 0.138.0 at this release boundary; see [docs/codex-0.139-compat.md](docs/codex-0.139-compat.md), [docs/codex-0.139-real-probes.md](docs/codex-0.139-real-probes.md), [docs/loop-fixture-policy.md](docs/loop-fixture-policy.md), and [docs/loop-merge-strategy.md](docs/loop-merge-strategy.md).
39
39
 
40
40
  SKS 3.0.0 was the parallel-runtime stabilization release. The whole live-swarm experience — what you actually *see* while 5, 20, or 100 workers run — was rebuilt and proven end-to-end.
41
41
 
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "sks-core"
79
- version = "3.1.1"
79
+ version = "3.1.2"
80
80
  dependencies = [
81
81
  "serde_json",
82
82
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "3.1.1"
3
+ version = "3.1.2"
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 3.1.1"),
7
+ Some("--version") => println!("sks-rs 3.1.2"),
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": "3.1.1",
5
- "source_digest": "ea95ac89533e71474a3f68a4dbf879d966eb64159ca24da208d6bb066fb7c573",
6
- "source_file_count": 2410,
7
- "built_at_source_time": 1781345242524
4
+ "package_version": "3.1.2",
5
+ "source_digest": "0312e2e27bae702aee9d6c07009b9492e43274c3d26e3b63a5140196997fea39",
6
+ "source_file_count": 2448,
7
+ "built_at_source_time": 1781367909038
8
8
  }
package/dist/bin/sks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const FAST_PACKAGE_VERSION = '3.1.1';
2
+ const FAST_PACKAGE_VERSION = '3.1.2';
3
3
  const args = process.argv.slice(2);
4
4
  try {
5
5
  if (args[0] === '--agent' && args[1] === 'worker') {
@@ -1515,7 +1515,7 @@ function normalizeCodexFastModeUiConfigOnce(text = '', opts = {}) {
1515
1515
  next = upsertTopLevelTomlStringIfAbsent(next, 'model', 'gpt-5.5');
1516
1516
  next = opts.forceFastMode === true
1517
1517
  ? upsertTopLevelTomlString(next, 'service_tier', 'fast')
1518
- : upsertTopLevelTomlStringIfAbsent(next, 'service_tier', 'fast');
1518
+ : next;
1519
1519
  // Codex App feature flags / fast-mode UI / suppress-warning are SET-IF-ABSENT: a fresh
1520
1520
  // config still gets SKS's defaults, but SKS NEVER overrides (re-enables) a feature the
1521
1521
  // user disabled in the App, and never rejects-then-hides UI by forcing an unrecognized
@@ -1536,11 +1536,10 @@ function normalizeCodexFastModeUiConfigOnce(text = '', opts = {}) {
1536
1536
  else {
1537
1537
  next = upsertTomlTableKeyIfAbsent(next, 'user.fast_mode', 'visible = true');
1538
1538
  next = upsertTomlTableKeyIfAbsent(next, 'user.fast_mode', 'enabled = true');
1539
- next = upsertTomlTableKeyIfAbsent(next, 'user.fast_mode', 'default_profile = "sks-fast-high"');
1539
+ next = removeTomlTableKey(next, 'user.fast_mode', 'default_profile');
1540
1540
  }
1541
- // Keep ONLY the sks-fast-high config-profile table: the Codex App fast-mode
1542
- // (`[user.fast_mode] default_profile = "sks-fast-high"`) and the
1543
- // codex-app:ui-preservation gate still expect it. The other SKS config profiles are
1541
+ // Keep ONLY the sks-fast-high config-profile table for explicit fast-mode opt-in
1542
+ // and CLI `--profile` use. The other SKS config profiles are
1544
1543
  // no longer written as `[profiles.sks-*]` tables here (Codex 0.134+ deprecates them);
1545
1544
  // they are managed as per-file `<name>.config.toml` overlays by
1546
1545
  // migrateSksProfilesToPerFile (src/core/auto-review.ts), which also writes the
@@ -2953,8 +2952,8 @@ export async function selftestCodexLb(tmp) {
2953
2952
  });
2954
2953
  if (brokenChain.ok || brokenChain.status !== 'previous_response_not_found' || brokenChain.chain_unhealthy !== true)
2955
2954
  throw new Error('selftest: codex-lb response chain health check did not detect previous_response_not_found');
2956
- if (!/^model = "gpt-5\.5"/m.test(codexLbConfig) || !codexLbConfig.includes('service_tier = "fast"') || !codexLbConfig.includes('hooks = true') || hasDeprecatedCodexHooksFeatureFlag(codexLbConfig) || !codexLbConfig.includes('remote_control = true') || !codexLbConfig.includes('multi_agent = true') || !codexLbConfig.includes('fast_mode = true') || !codexLbConfig.includes('fast_mode_ui = true') || !codexLbConfig.includes('codex_git_commit = true') || !codexLbConfig.includes('computer_use = true') || !codexLbConfig.includes('browser_use = true') || !codexLbConfig.includes('browser_use_external = true') || !codexLbConfig.includes('guardian_approval = true') || !codexLbConfig.includes('tool_suggest = true') || !codexLbConfig.includes('apps = true') || !codexLbConfig.includes('plugins = true') || !codexLbConfig.includes('[plugins."latex@openai-bundled"]') || !codexLbConfig.includes('[plugins."documents@openai-primary-runtime"]') || !codexLbConfig.includes('[user.fast_mode]') || !codexLbConfig.includes('visible = true') || !codexLbConfig.includes('enabled = true') || !codexLbConfig.includes('default_profile = "sks-fast-high"') || !/\[profiles\.custom\][\s\S]*?model_reasoning_effort = "low"/.test(codexLbConfig) || !/\[profiles\.sks-fast-high\][\s\S]*?service_tier = "fast"/.test(codexLbConfig) || codexLbConfig.includes('fast_default_opt_out = true') || hasTopLevelCodexModeLock(codexLbConfig))
2957
- throw new Error('selftest: codex-lb setup did not preserve Codex App feature flags, default plugins, profile-scoped reasoning effort, Fast mode defaults, Codex Git commit generation, force GPT-5.5, or migrate the hooks feature flag');
2955
+ if (!/^model = "gpt-5\.5"/m.test(codexLbConfig) || !codexLbConfig.includes('hooks = true') || hasDeprecatedCodexHooksFeatureFlag(codexLbConfig) || !codexLbConfig.includes('remote_control = true') || !codexLbConfig.includes('multi_agent = true') || !codexLbConfig.includes('fast_mode = true') || !codexLbConfig.includes('fast_mode_ui = true') || !codexLbConfig.includes('codex_git_commit = true') || !codexLbConfig.includes('computer_use = true') || !codexLbConfig.includes('browser_use = true') || !codexLbConfig.includes('browser_use_external = true') || !codexLbConfig.includes('guardian_approval = true') || !codexLbConfig.includes('tool_suggest = true') || !codexLbConfig.includes('apps = true') || !codexLbConfig.includes('plugins = true') || !codexLbConfig.includes('[plugins."latex@openai-bundled"]') || !codexLbConfig.includes('[plugins."documents@openai-primary-runtime"]') || !codexLbConfig.includes('[user.fast_mode]') || !codexLbConfig.includes('visible = true') || !codexLbConfig.includes('enabled = true') || !/\[profiles\.custom\][\s\S]*?model_reasoning_effort = "low"/.test(codexLbConfig) || !/\[profiles\.sks-fast-high\][\s\S]*?service_tier = "fast"/.test(codexLbConfig) || codexLbConfig.includes('fast_default_opt_out = true') || hasTopLevelCodexModeLock(codexLbConfig))
2956
+ throw new Error('selftest: codex-lb setup did not preserve Codex App feature flags, default plugins, profile-scoped reasoning effort, explicit Fast profile, Codex Git commit generation, force GPT-5.5, or migrate the hooks feature flag');
2958
2957
  if (!hasCodexUnstableFeatureWarningSuppression(codexLbConfig))
2959
2958
  throw new Error('selftest: codex-lb setup did not suppress Codex unstable feature warning');
2960
2959
  const codexLbLaunch = `source ${path.join(tmp, '.codex', 'sks-codex-lb.env')} && codex '--model' 'gpt-5.5'`;
@@ -49,6 +49,7 @@ import { applyFastModeToRoster, resolveFastModePolicy, writeFastModePropagationP
49
49
  import { createNativeCliSessionSwarmRecorder } from './native-cli-session-swarm.js';
50
50
  import { writeNativeCliSessionProof } from './native-cli-session-proof.js';
51
51
  import { writeNoSubagentScalingPolicy } from './no-subagent-scaling-policy.js';
52
+ import { writeOfficialSubagentHelperPolicy } from './official-subagent-helper-policy.js';
52
53
  import { runCodexTask } from '../codex-control/codex-control-plane.js';
53
54
  import { CODEX_AGENT_WORKER_RESULT_SCHEMA_ID, codexAgentWorkerResultSchema } from '../codex-control/schemas/agent-worker-result.schema.js';
54
55
  import { resolveLocalCollaborationPolicy, localCollaborationParticipated } from '../local-llm/local-collaboration-policy.js';
@@ -255,7 +256,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
255
256
  total_work_items: partition.task_graph?.total_work_items || partition.slices.length,
256
257
  service_tier: fastModePolicy.service_tier,
257
258
  fast_mode: fastModePolicy.fast_mode,
258
- fast_mode_default: true,
259
+ fast_mode_default: fastModePolicy.default_fast_mode,
259
260
  backpressure: 'dynamic scheduler maintains target active slots until the work queue drains',
260
261
  rate_limit_delay_ms: backend === 'codex-sdk' ? 250 : 0,
261
262
  resource_pressure_warnings: roster.agent_count > roster.concurrency ? ['agents_exceed_concurrency_batches'] : []
@@ -487,7 +488,8 @@ export async function runNativeAgentOrchestrator(opts = {}) {
487
488
  targetActiveSlots,
488
489
  totalWorkItems: partition.task_graph?.total_work_items || partition.slices.length
489
490
  });
490
- const noSubagentScalingPolicy = await writeNoSubagentScalingPolicy(ledgerRoot, { nativeProof: nativeCliSessionProof });
491
+ const officialSubagentHelperPolicy = await writeOfficialSubagentHelperPolicy(ledgerRoot, { nativeProof: nativeCliSessionProof });
492
+ const noSubagentScalingPolicy = await writeNoSubagentScalingPolicy(ledgerRoot, { nativeProof: nativeCliSessionProof, officialSubagentHelperPolicy });
491
493
  const fastModePropagation = await writeFastModePropagationProof(ledgerRoot, { policy: fastModePolicy, backend, results });
492
494
  const localCollaborationPolicy = resolveLocalCollaborationPolicy();
493
495
  await writeJsonAtomic(path.join(ledgerRoot, 'local-collaboration-policy.json'), localCollaborationPolicy);
@@ -560,6 +562,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
560
562
  ...(timeoutKill.killed_sessions || []).map((id) => 'timeout_killed:' + id),
561
563
  ...(recursion.ok ? [] : recursion.violations.map((id) => 'recursion:' + id)),
562
564
  ...(nativeCliSessionProof.ok ? [] : nativeCliSessionProof.blockers),
565
+ ...(officialSubagentHelperPolicy.ok ? [] : officialSubagentHelperPolicy.blockers),
563
566
  ...(noSubagentScalingPolicy.ok ? [] : noSubagentScalingPolicy.blockers),
564
567
  ...(fastModePropagation.ok ? [] : fastModePropagation.blockers),
565
568
  ...(gitWorktreeRuntime.required === true && gitWorktreeRuntime.ok === false ? gitWorktreeRuntime.blockers || ['git_worktree_runtime_not_ok'] : []),
@@ -597,6 +600,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
597
600
  strategyGate,
598
601
  nativeCliSessionProof,
599
602
  noSubagentScalingPolicy,
603
+ officialSubagentHelperPolicy,
600
604
  fastModePolicy,
601
605
  fastModePropagation,
602
606
  gitWorktreeRuntime,
@@ -642,6 +646,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
642
646
  parallel_write_policy: parallelWritePolicy,
643
647
  native_cli_session_proof: nativeCliSessionProof,
644
648
  no_subagent_scaling_policy: noSubagentScalingPolicy,
649
+ official_subagent_helper_policy: officialSubagentHelperPolicy,
645
650
  fast_mode_policy: fastModePolicy,
646
651
  fast_mode_propagation: fastModePropagation,
647
652
  git_worktree_runtime: gitWorktreeRuntime,
@@ -51,6 +51,7 @@ export async function writeAgentProofEvidence(root, input) {
51
51
  });
52
52
  const nativeCliSessionProof = input.nativeCliSessionProof || await readJson(path.join(root, 'native-cli-session-proof.json'), null);
53
53
  const noSubagentScalingPolicy = input.noSubagentScalingPolicy || await readJson(path.join(root, 'no-subagent-scaling-policy.json'), null);
54
+ const officialSubagentHelperPolicy = input.officialSubagentHelperPolicy || await readJson(path.join(root, 'official-subagent-helper-policy.json'), null);
54
55
  const fastModePropagation = input.fastModePropagation || await readJson(path.join(root, 'fast-mode-propagation-proof.json'), null);
55
56
  const zellijPaneProof = await readJson(path.join(root, 'zellij-pane-proof.json'), null);
56
57
  const cleanupProof = await readJson(path.join(root, 'agent-cleanup-proof.json'), null);
@@ -179,6 +180,7 @@ export async function writeAgentProofEvidence(root, input) {
179
180
  ...(input.results || []).flatMap((result) => result.blockers || []),
180
181
  ...(nativeCliSessionProof?.ok === false ? nativeCliSessionProof.blockers || ['native_cli_session_proof_not_ok'] : []),
181
182
  ...(noSubagentScalingPolicy?.ok === false ? noSubagentScalingPolicy.blockers || ['no_subagent_scaling_policy_not_ok'] : []),
183
+ ...(officialSubagentHelperPolicy?.ok === false ? officialSubagentHelperPolicy.blockers || ['official_subagent_helper_policy_not_ok'] : []),
182
184
  ...(fastModePropagation?.ok === false ? fastModePropagation.blockers || ['fast_mode_propagation_not_ok'] : []),
183
185
  ...(patchSwarm?.ok === false ? patchSwarm.blockers || ['patch_swarm_not_ok'] : []),
184
186
  ...(gitWorktreeRuntime?.required === true && gitWorktreeRuntime?.ok === false ? gitWorktreeRuntime.blockers || ['git_worktree_runtime_not_ok'] : []),
@@ -225,6 +227,23 @@ export async function writeAgentProofEvidence(root, input) {
225
227
  native_cli_session_proof: nativeCliSessionProof ? 'native-cli-session-proof.json' : null,
226
228
  native_cli_session_swarm: nativeCliSessionProof ? 'agent-native-cli-session-swarm.json' : null,
227
229
  no_subagent_scaling_policy: noSubagentScalingPolicy ? 'no-subagent-scaling-policy.json' : null,
230
+ official_subagent_helper_policy: officialSubagentHelperPolicy ? 'official-subagent-helper-policy.json' : null,
231
+ official_subagent_helper_lane_enabled: officialSubagentHelperPolicy?.official_codex_subagent_helper_lane_enabled === true,
232
+ official_subagent_helper_lane_ok: officialSubagentHelperPolicy?.ok === true,
233
+ official_subagent_helper_worker_capacity_credit: Number(officialSubagentHelperPolicy?.worker_capacity_credit || 0),
234
+ official_subagent_helper_observed_subagent_event_count: Number(officialSubagentHelperPolicy?.observed_subagent_event_count || 0),
235
+ official_subagent_helper_events_counted_as_worker_sessions: officialSubagentHelperPolicy?.subagent_events_counted_as_worker_sessions === true,
236
+ official_subagent_helper_capacity_source: officialSubagentHelperPolicy?.worker_capacity_source || null,
237
+ official_subagent_helper_parallel_allowed: officialSubagentHelperPolicy?.helper_lane_may_run_in_parallel_with_native_workers === true,
238
+ official_subagent_helper_capabilities: officialSubagentHelperPolicy?.codex_app_capabilities_allowed || [],
239
+ official_subagent_helper_builtin_agents: officialSubagentHelperPolicy?.built_in_agents_allowed || [],
240
+ official_subagent_helper_required_output_proof_for_generated_images: officialSubagentHelperPolicy?.required_output_proof_for_generated_images || [],
241
+ codex_builtin_imagegen_helper_allowed: officialSubagentHelperPolicy?.codex_builtin_imagegen_helper_allowed === true,
242
+ codex_builtin_imagegen_required_surface: officialSubagentHelperPolicy?.preferred_image_generation_surface || null,
243
+ codex_builtin_imagegen_evidence_class: officialSubagentHelperPolicy?.codex_app_builtin_evidence_class || null,
244
+ imagegen_api_fallback_evidence_class: officialSubagentHelperPolicy?.api_fallback_evidence_class || null,
245
+ imagegen_provider_surface_evidence_required: officialSubagentHelperPolicy?.provider_surface_evidence_required === true,
246
+ imagegen_api_fallback_counts_as_codex_app_evidence: officialSubagentHelperPolicy?.imagegen_api_fallback_counts_as_codex_app_evidence === true,
228
247
  fast_mode_policy: input.fastModePolicy || null,
229
248
  fast_mode_propagation: fastModePropagation ? 'fast-mode-propagation-proof.json' : null,
230
249
  native_cli_worker_process_count: Number(nativeCliSessionProof?.spawned_worker_process_count || 0),
@@ -403,6 +422,7 @@ export async function writeAgentProofEvidence(root, input) {
403
422
  'gpt-final-arbiter/gpt-final-arbiter.json': gptFinalArbiter,
404
423
  'native-cli-session-proof.json': nativeCliSessionProof,
405
424
  'no-subagent-scaling-policy.json': noSubagentScalingPolicy,
425
+ 'official-subagent-helper-policy.json': officialSubagentHelperPolicy,
406
426
  'fast-mode-propagation-proof.json': fastModePropagation
407
427
  }
408
428
  });
@@ -18,15 +18,17 @@ export function resolveFastModePolicy(input = {}) {
18
18
  ? 'standard'
19
19
  : preference?.mode === 'standard'
20
20
  ? 'standard'
21
- : 'fast';
21
+ : explicitFast || explicitTier === 'fast' || preference?.mode === 'fast'
22
+ ? 'fast'
23
+ : 'standard';
22
24
  return {
23
25
  schema: FAST_MODE_POLICY_SCHEMA,
24
26
  generated_at: nowIso(),
25
27
  fast_mode: serviceTier === 'fast',
26
28
  service_tier: serviceTier,
27
29
  codex_desktop_service_tier: codexDesktopServiceTier(serviceTier),
28
- default_fast_mode: true,
29
- disabled_by: explicitNoFast ? 'no-fast' : explicitTier === 'standard' ? 'service-tier-standard' : preference?.mode === 'standard' ? 'preference-standard' : 'none',
30
+ default_fast_mode: false,
31
+ disabled_by: explicitNoFast ? 'no-fast' : explicitTier === 'standard' ? 'service-tier-standard' : preference?.mode === 'standard' ? 'preference-standard' : serviceTier === 'standard' ? 'default-standard' : 'none',
30
32
  explicit_fast: explicitFast,
31
33
  explicit_no_fast: explicitNoFast,
32
34
  explicit_service_tier: explicitTier,
@@ -125,7 +127,7 @@ export async function writeFastModePropagationProof(root, input = { policy: reso
125
127
  const agentProcessReports = await collectNamedJson(root, 'agent-process-report.json');
126
128
  const zellijReports = await collectNamedJson(root, 'agent-zellij-report.json');
127
129
  const madReports = await collectNamedJson(root, 'mad-sks-worker-report.json');
128
- const defaultFastExpected = input.policy.disabled_by === 'none';
130
+ const defaultFastExpected = input.policy.fast_mode === true;
129
131
  const childReports = [...workerFastReports, ...workerProcessReports, ...agentProcessReports, ...zellijReports, ...madReports];
130
132
  const missingFast = defaultFastExpected
131
133
  ? childReports.filter((row) => row.json?.fast_mode !== true && row.json?.fast_mode !== 'true')
@@ -144,7 +146,7 @@ export async function writeFastModePropagationProof(root, input = { policy: reso
144
146
  ok: missingFast.length === 0 && missingTier.length === 0 && workerMissing.length === 0 && missingCliOverride.length === 0,
145
147
  policy: input.policy,
146
148
  backend: input.backend || null,
147
- default_fast_mode: true,
149
+ default_fast_mode: input.policy.default_fast_mode,
148
150
  service_tier: input.policy.service_tier,
149
151
  fast_mode: input.policy.fast_mode,
150
152
  worker_fast_report_count: workerFastReports.length,
@@ -112,6 +112,12 @@ export function enhanceTaskGraphWithIntelligence(taskGraph, graph) {
112
112
  }
113
113
  export async function writeIntelligentWorkGraphArtifacts(root, graph) {
114
114
  const compact = compactIntelligentWorkGraph(graph);
115
+ const symbolOwnership = compactSymbolOwnershipMap(graph);
116
+ const routeOwnership = limitRecordOfArrays(graph.route_to_module_ownership, graphRecordLimit(), graphArrayLimit());
117
+ const commandOwnership = limitRecordOfArrays(graph.command_to_module_ownership, graphRecordLimit(), graphArrayLimit());
118
+ const testOwnership = compactTestOwnershipMap(graph.test_ownership_map);
119
+ const criticalPath = compactCriticalPath(graph.critical_path);
120
+ const integrationBottlenecks = compactIntegrationBottlenecks(graph.integration_bottlenecks);
115
121
  await writeJsonAtomic(path.join(root, 'agent-intelligent-work-graph.json'), compact);
116
122
  await writeJsonAtomic(path.join(root, 'agent-intelligent-work-graph-v2.json'), compact);
117
123
  await writeJsonAtomic(path.join(root, 'agent-symbol-ownership-map.json'), {
@@ -119,23 +125,19 @@ export async function writeIntelligentWorkGraphArtifacts(root, graph) {
119
125
  generated_at: graph.generated_at,
120
126
  ok: Object.keys(graph.symbol_to_files).length > 0,
121
127
  ast_coverage: graph.ast_coverage,
122
- file_to_symbols: graph.file_to_symbols,
123
- symbol_to_files: graph.symbol_to_files,
124
- exported_symbols: graph.exported_symbols,
125
- imported_symbols: graph.imported_symbols,
126
- exported_api_ownership: graph.exported_api_ownership
128
+ ...symbolOwnership
127
129
  });
128
130
  await writeJsonAtomic(path.join(root, 'agent-route-ownership-map.json'), {
129
131
  schema: 'sks.agent-route-ownership-map.v1',
130
132
  generated_at: graph.generated_at,
131
133
  ok: Object.keys(graph.route_to_module_ownership).length > 0,
132
- route_to_module_ownership: graph.route_to_module_ownership
134
+ route_to_module_ownership: routeOwnership
133
135
  });
134
136
  await writeJsonAtomic(path.join(root, 'agent-command-ownership-map.json'), {
135
137
  schema: 'sks.agent-command-ownership-map.v1',
136
138
  generated_at: graph.generated_at,
137
139
  ok: Object.keys(graph.command_to_module_ownership).length > 0,
138
- command_to_module_ownership: graph.command_to_module_ownership
140
+ command_to_module_ownership: commandOwnership
139
141
  });
140
142
  await writeJsonAtomic(path.join(root, 'agent-test-ownership-map.json'), {
141
143
  schema: 'sks.agent-test-ownership-map.v1',
@@ -143,7 +145,7 @@ export async function writeIntelligentWorkGraphArtifacts(root, graph) {
143
145
  ok: graph.test_ownership_map.unmapped_sources.length < Math.max(10, graph.source_inventory_count),
144
146
  ast_coverage: graph.ast_coverage,
145
147
  test_ownership_confidence: graph.test_ownership_confidence,
146
- ...graph.test_ownership_map
148
+ ...testOwnership
147
149
  });
148
150
  await writeJsonAtomic(path.join(root, 'agent-source-test-ownership-v2.json'), {
149
151
  schema: 'sks.agent-source-test-ownership.v2',
@@ -151,14 +153,14 @@ export async function writeIntelligentWorkGraphArtifacts(root, graph) {
151
153
  ok: graph.test_ownership_confidence > 0,
152
154
  ast_coverage: graph.ast_coverage,
153
155
  test_ownership_confidence: graph.test_ownership_confidence,
154
- source_to_test_relations: graph.source_to_test_relations,
155
- ...graph.test_ownership_map
156
+ source_to_test_relations: testOwnership.relations,
157
+ ...testOwnership
156
158
  });
157
159
  await writeJsonAtomic(path.join(root, 'agent-critical-path.json'), {
158
160
  schema: 'sks.agent-critical-path.v1',
159
161
  generated_at: graph.generated_at,
160
162
  ok: graph.critical_path.path.length > 0,
161
- ...graph.critical_path
163
+ ...criticalPath
162
164
  });
163
165
  await writeJsonAtomic(path.join(root, 'agent-critical-path-v2.json'), {
164
166
  schema: 'sks.agent-critical-path.v2',
@@ -166,21 +168,21 @@ export async function writeIntelligentWorkGraphArtifacts(root, graph) {
166
168
  ok: graph.critical_path.path.length > 0,
167
169
  ast_coverage: graph.ast_coverage,
168
170
  critical_path_confidence: graph.critical_path.confidence || graph.test_ownership_confidence,
169
- ...graph.critical_path
171
+ ...criticalPath
170
172
  });
171
173
  await writeJsonAtomic(path.join(root, 'agent-integration-bottlenecks.json'), {
172
174
  schema: 'sks.agent-integration-bottlenecks.v1',
173
175
  generated_at: graph.generated_at,
174
176
  ok: true,
175
177
  critical_path_confidence: graph.critical_path.confidence || null,
176
- ...graph.integration_bottlenecks
178
+ ...integrationBottlenecks
177
179
  });
178
180
  await writeJsonAtomic(path.join(root, 'agent-integration-bottlenecks-v2.json'), {
179
181
  schema: 'sks.agent-integration-bottlenecks.v2',
180
182
  generated_at: graph.generated_at,
181
183
  ok: true,
182
184
  critical_path_confidence: graph.critical_path.confidence || null,
183
- ...graph.integration_bottlenecks
185
+ ...integrationBottlenecks
184
186
  });
185
187
  }
186
188
  export function compactIntelligentWorkGraph(graph) {
@@ -222,6 +224,83 @@ export function compactIntelligentWorkGraph(graph) {
222
224
  function limitArray(items, limit) {
223
225
  return Array.isArray(items) ? items.slice(0, limit) : [];
224
226
  }
227
+ function graphRecordLimit() {
228
+ return Math.max(50, Math.floor(Number(process.env.SKS_WORK_GRAPH_RECORD_LIMIT || 500) || 500));
229
+ }
230
+ function graphArrayLimit() {
231
+ return Math.max(10, Math.floor(Number(process.env.SKS_WORK_GRAPH_ARRAY_LIMIT || 50) || 50));
232
+ }
233
+ function graphRelationLimit() {
234
+ return Math.max(100, Math.floor(Number(process.env.SKS_WORK_GRAPH_RELATION_LIMIT || 1000) || 1000));
235
+ }
236
+ function limitRecordOfArrays(record, entryLimit, arrayLimit) {
237
+ const out = {};
238
+ for (const [key, value] of Object.entries(record || {}).slice(0, entryLimit)) {
239
+ out[key] = Array.isArray(value) ? value.slice(0, arrayLimit) : value;
240
+ }
241
+ return out;
242
+ }
243
+ function compactSymbolOwnershipMap(graph) {
244
+ const entryLimit = graphRecordLimit();
245
+ const arrayLimit = graphArrayLimit();
246
+ const exportedApiOwnership = {};
247
+ for (const [symbol, file] of Object.entries(graph.exported_api_ownership || {}).slice(0, entryLimit))
248
+ exportedApiOwnership[symbol] = String(file);
249
+ return {
250
+ compact: true,
251
+ limits: { record_entries: entryLimit, array_items: arrayLimit },
252
+ original_counts: {
253
+ file_to_symbols: Object.keys(graph.file_to_symbols || {}).length,
254
+ symbol_to_files: Object.keys(graph.symbol_to_files || {}).length,
255
+ exported_symbols: Object.keys(graph.exported_symbols || {}).length,
256
+ imported_symbols: Object.keys(graph.imported_symbols || {}).length,
257
+ exported_api_ownership: Object.keys(graph.exported_api_ownership || {}).length
258
+ },
259
+ file_to_symbols: limitRecordOfArrays(graph.file_to_symbols, entryLimit, arrayLimit),
260
+ symbol_to_files: limitRecordOfArrays(graph.symbol_to_files, entryLimit, arrayLimit),
261
+ exported_symbols: limitRecordOfArrays(graph.exported_symbols, entryLimit, arrayLimit),
262
+ imported_symbols: limitRecordOfArrays(graph.imported_symbols, entryLimit, arrayLimit),
263
+ exported_api_ownership: exportedApiOwnership
264
+ };
265
+ }
266
+ function compactTestOwnershipMap(map = {}) {
267
+ const entryLimit = graphRecordLimit();
268
+ const arrayLimit = graphArrayLimit();
269
+ const relationLimit = graphRelationLimit();
270
+ const relations = limitArray((Array.isArray(map.relations) ? map.relations : []).map((row) => ({
271
+ ...row,
272
+ symbol_overlap: limitArray(row?.symbol_overlap, arrayLimit)
273
+ })), relationLimit);
274
+ return {
275
+ compact: true,
276
+ limits: { owner_entries: entryLimit, owner_items: arrayLimit, relations: relationLimit },
277
+ original_counts: {
278
+ owner_by_source: Object.keys(map.owner_by_source || {}).length,
279
+ unmapped_sources: Array.isArray(map.unmapped_sources) ? map.unmapped_sources.length : 0,
280
+ relations: Array.isArray(map.relations) ? map.relations.length : 0
281
+ },
282
+ owner_by_source: limitRecordOfArrays(map.owner_by_source, entryLimit, arrayLimit),
283
+ mapped_source_count: Number(map.mapped_source_count || 0),
284
+ unmapped_sources: limitArray(map.unmapped_sources, entryLimit),
285
+ relations
286
+ };
287
+ }
288
+ function compactCriticalPath(criticalPath = {}) {
289
+ return {
290
+ ...criticalPath,
291
+ path: limitArray(criticalPath.path, 500),
292
+ compact: true,
293
+ original_path_length: Array.isArray(criticalPath.path) ? criticalPath.path.length : 0
294
+ };
295
+ }
296
+ function compactIntegrationBottlenecks(bottlenecks = {}) {
297
+ return {
298
+ ...bottlenecks,
299
+ bottlenecks: limitArray(bottlenecks.bottlenecks, 200),
300
+ changed_bottlenecks: limitArray(bottlenecks.changed_bottlenecks, 200),
301
+ compact: true
302
+ };
303
+ }
225
304
  function buildTestOwnershipMap(sourceFiles, testFiles, ast, dependencyGraph = {}) {
226
305
  const ownerBySource = {};
227
306
  const relations = [];
@@ -12,6 +12,7 @@ import { resolveZellijWorkerPaneUiMode } from '../zellij/zellij-ui-mode.js';
12
12
  import { appendZellijSlotTelemetry } from '../zellij/zellij-slot-telemetry.js';
13
13
  import { appendParallelRuntimeEvent } from './parallel-runtime-proof.js';
14
14
  import { appendAgentMessage } from './agent-message-bus.js';
15
+ import { markLoopWorkerInterrupted, registerLoopActiveWorker } from '../loops/loop-interrupt-registry.js';
15
16
  export const NATIVE_CLI_SESSION_SWARM_SCHEMA = 'sks.agent-native-cli-session-swarm.v1';
16
17
  export function createNativeCliSessionSwarmRecorder(root, input) {
17
18
  return new NativeCliSessionSwarmRecorder(root, input);
@@ -176,6 +177,13 @@ class NativeCliSessionSwarmRecorder {
176
177
  });
177
178
  record.pid = child.pid || null;
178
179
  record.process_id = child.pid || null;
180
+ const loopHandle = await registerLoopWorkerHandle({
181
+ root: ctx.opts.projectRoot || this.input.projectRoot || ctx.opts.cwd || packageRoot(),
182
+ env: ctx.opts.env || {},
183
+ agentId: String(ctx.agent.id || ctx.agent.session_id || 'agent'),
184
+ sessionId: ctx.agent.session_id || null,
185
+ pid: child.pid || null
186
+ });
179
187
  record.status = 'running';
180
188
  await appendParallelRuntimeEvent(this.root, this.input.missionId, {
181
189
  event_type: 'worker_process_spawned',
@@ -211,6 +219,9 @@ class NativeCliSessionSwarmRecorder {
211
219
  record.exit_code = exit.code;
212
220
  record.signal = exit.signal;
213
221
  record.status = exit.code === 0 ? 'closed' : 'failed';
222
+ if (loopHandle) {
223
+ await markLoopWorkerInterrupted(ctx.opts.projectRoot || this.input.projectRoot || ctx.opts.cwd || packageRoot(), loopHandle.mission_id, loopHandle.worker_id, record.status === 'closed' ? 'completed' : 'failed').catch(() => undefined);
224
+ }
214
225
  if (record.worker_placement === 'headless') {
215
226
  await closeWorkerInRightColumn({
216
227
  root: this.root,
@@ -343,6 +354,13 @@ class NativeCliSessionSwarmRecorder {
343
354
  stdoutRel: input.stdoutRel,
344
355
  stderrRel: input.stderrRel
345
356
  });
357
+ let loopHandle = await registerLoopWorkerHandle({
358
+ root: input.ctx.opts.projectRoot || this.input.projectRoot || input.ctx.opts.cwd || packageRoot(),
359
+ env: input.ctx.opts.env || {},
360
+ agentId: String(input.ctx.agent.id || input.ctx.agent.session_id || 'agent'),
361
+ sessionId: input.ctx.agent.session_id || null,
362
+ pid: processRun?.pid || null
363
+ });
346
364
  if (processRun?.pid) {
347
365
  input.record.pid = processRun.pid;
348
366
  input.record.process_id = processRun.pid;
@@ -542,6 +560,15 @@ class NativeCliSessionSwarmRecorder {
542
560
  }
543
561
  input.record.pid = Number(workerProcessReport?.pid || processRun?.pid) || null;
544
562
  input.record.process_id = input.record.pid;
563
+ if (!loopHandle && input.record.pid) {
564
+ loopHandle = await registerLoopWorkerHandle({
565
+ root: input.ctx.opts.projectRoot || this.input.projectRoot || input.ctx.opts.cwd || packageRoot(),
566
+ env: input.ctx.opts.env || {},
567
+ agentId: String(input.ctx.agent.id || input.ctx.agent.session_id || 'agent'),
568
+ sessionId: input.ctx.agent.session_id || null,
569
+ pid: input.record.pid
570
+ });
571
+ }
545
572
  input.record.compact_worker_exit_code = compactExit?.code ?? null;
546
573
  input.record.compact_worker_signal = compactExit?.signal ?? null;
547
574
  input.record.sdk_thread_id = sdkThreadId;
@@ -550,6 +577,9 @@ class NativeCliSessionSwarmRecorder {
550
577
  input.record.structured_output_valid = workerProcessReport?.structured_output_valid === true || workerProcessReport?.backend_router_report?.structured_output_valid === true;
551
578
  input.record.exit_code = parsed ? (parsed.status === 'done' ? 0 : 1) : 1;
552
579
  input.record.status = parsed?.status === 'done' ? 'closed' : 'failed';
580
+ if (loopHandle) {
581
+ await markLoopWorkerInterrupted(input.ctx.opts.projectRoot || this.input.projectRoot || input.ctx.opts.cwd || packageRoot(), loopHandle.mission_id, loopHandle.worker_id, input.record.status === 'closed' ? 'completed' : 'failed').catch(() => undefined);
582
+ }
553
583
  const heartbeatOk = await hasHeartbeat(path.join(this.root, input.heartbeatRel));
554
584
  input.record.blockers = [
555
585
  ...(parsed ? parsed.blockers || [] : ['zellij_worker_result_timeout']),
@@ -915,6 +945,22 @@ function normalizeParallelPlacement(value) {
915
945
  return text;
916
946
  return 'unknown';
917
947
  }
948
+ async function registerLoopWorkerHandle(input) {
949
+ const missionId = String(input.env.SKS_MISSION_ID || input.env.SKS_PARENT_MISSION_ID || '').trim();
950
+ const loopId = String(input.env.SKS_LOOP_ID || '').trim();
951
+ const phase = String(input.env.SKS_LOOP_PHASE || '').trim();
952
+ if (!missionId || !loopId || (phase !== 'maker' && phase !== 'checker'))
953
+ return null;
954
+ return registerLoopActiveWorker(input.root, {
955
+ mission_id: missionId,
956
+ loop_id: loopId,
957
+ phase,
958
+ worker_id: input.agentId,
959
+ session_id: input.sessionId,
960
+ pid: input.pid,
961
+ interrupt_supported: Boolean(input.pid || input.sessionId)
962
+ }).catch(() => null);
963
+ }
918
964
  async function tailFile(file, max) {
919
965
  try {
920
966
  const text = await fs.promises.readFile(file, 'utf8');
@@ -3,6 +3,7 @@ import { nowIso, readJson, readText, writeJsonAtomic } from '../fsx.js';
3
3
  export const NO_SUBAGENT_SCALING_POLICY_SCHEMA = 'sks.no-subagent-scaling-policy.v1';
4
4
  export async function writeNoSubagentScalingPolicy(root, input = {}) {
5
5
  const nativeProof = input.nativeProof || await readJson(path.join(root, 'native-cli-session-proof.json'), null);
6
+ const officialSubagentHelperPolicy = input.officialSubagentHelperPolicy || await readJson(path.join(root, 'official-subagent-helper-policy.json'), null);
6
7
  const swarm = await readJson(path.join(root, 'agent-native-cli-session-swarm.json'), null);
7
8
  const events = await readText(path.join(root, 'agent-events.jsonl'), '');
8
9
  const subagentEventCount = String(events).split(/\n/).filter((line) => /Subagent(Start|Stop)|subagent/i.test(line)).length;
@@ -11,7 +12,8 @@ export async function writeNoSubagentScalingPolicy(root, input = {}) {
11
12
  const blockers = [
12
13
  ...(allowedScalingPrimitives.has(String(swarm?.scaling_primitive || '')) ? [] : ['main_scaling_primitive_not_native_cli_process']),
13
14
  ...(nativeProcessCount > 0 ? [] : ['native_cli_worker_process_proof_missing']),
14
- ...(nativeProof?.worker_proof_is_only_subagent_events === true ? ['worker_proof_only_subagent_events'] : [])
15
+ ...(nativeProof?.worker_proof_is_only_subagent_events === true ? ['worker_proof_only_subagent_events'] : []),
16
+ ...(officialSubagentHelperPolicy?.ok === false ? officialSubagentHelperPolicy.blockers || ['official_subagent_helper_policy_not_ok'] : [])
15
17
  ];
16
18
  const report = {
17
19
  schema: NO_SUBAGENT_SCALING_POLICY_SCHEMA,
@@ -21,6 +23,13 @@ export async function writeNoSubagentScalingPolicy(root, input = {}) {
21
23
  subagent_events_counted_as_worker_sessions: false,
22
24
  scout_events_counted_as_worker_sessions: false,
23
25
  worker_internal_scout_usage_allowed_as_helper_only: true,
26
+ official_codex_subagent_helper_lane_allowed: officialSubagentHelperPolicy?.ok !== false,
27
+ official_codex_subagent_helper_policy: officialSubagentHelperPolicy ? 'official-subagent-helper-policy.json' : null,
28
+ official_helper_lane_worker_capacity_credit: 0,
29
+ official_helper_lane_observed_subagent_event_count: Number(officialSubagentHelperPolicy?.observed_subagent_event_count || 0),
30
+ official_helper_lane_events_counted_as_worker_sessions: false,
31
+ codex_builtin_capability_lane_allowed: officialSubagentHelperPolicy?.official_codex_subagent_helper_lane_enabled === true,
32
+ codex_builtin_imagegen_helper_allowed: officialSubagentHelperPolicy?.codex_builtin_imagegen_helper_allowed === true,
24
33
  native_worker_process_count: nativeProcessCount,
25
34
  subagent_event_count: subagentEventCount,
26
35
  worker_process_proof: 'native-cli-session-proof.json',
@@ -0,0 +1,62 @@
1
+ import path from 'node:path';
2
+ import { nowIso, readJson, readText, writeJsonAtomic } from '../fsx.js';
3
+ export const OFFICIAL_SUBAGENT_HELPER_POLICY_SCHEMA = 'sks.official-subagent-helper-policy.v1';
4
+ export async function writeOfficialSubagentHelperPolicy(root, input = {}) {
5
+ const nativeProof = input.nativeProof || await readJson(path.join(root, 'native-cli-session-proof.json'), null);
6
+ const events = await readText(path.join(root, 'agent-events.jsonl'), '');
7
+ const subagentEventCount = String(events).split(/\n/).filter((line) => /Subagent(Start|Stop)|subagent/i.test(line)).length;
8
+ const nativeProcessCount = Number(nativeProof?.spawned_worker_process_count || 0);
9
+ const workerCapacityCredit = 0;
10
+ const subagentEventsCountedAsWorkerSessions = false;
11
+ const builtInAgentsAllowed = ['default', 'worker', 'explorer'];
12
+ const codexAppCapabilitiesAllowed = [
13
+ 'image_generation',
14
+ 'computer_use_for_native_app_targets',
15
+ 'in_app_browser_for_allowed_web_targets',
16
+ 'web_search',
17
+ 'mcp_tools',
18
+ 'product_design_plugin'
19
+ ];
20
+ const requiredOutputProofForGeneratedImages = ['path', 'sha256', 'bytes', 'dimensions', 'model_or_surface'];
21
+ const blockers = [
22
+ ...(workerCapacityCredit === 0 ? [] : ['official_helper_worker_capacity_credit_not_zero']),
23
+ ...(subagentEventsCountedAsWorkerSessions === false ? [] : ['official_helper_subagent_events_counted_as_worker_sessions']),
24
+ ...(codexAppCapabilitiesAllowed.includes('image_generation') ? [] : ['official_helper_image_generation_capability_missing']),
25
+ ...(requiredOutputProofForGeneratedImages.includes('sha256') && requiredOutputProofForGeneratedImages.includes('dimensions')
26
+ ? []
27
+ : ['official_helper_image_output_proof_incomplete'])
28
+ ];
29
+ const report = {
30
+ schema: OFFICIAL_SUBAGENT_HELPER_POLICY_SCHEMA,
31
+ generated_at: nowIso(),
32
+ ok: blockers.length === 0,
33
+ official_codex_subagent_helper_lane_enabled: true,
34
+ official_codex_subagents_allowed: true,
35
+ helper_lane_role: 'capability_helper_only',
36
+ helper_lane_may_run_in_parallel_with_native_workers: true,
37
+ worker_capacity_source: 'native-cli-session-proof.json',
38
+ worker_capacity_credit: workerCapacityCredit,
39
+ subagent_events_counted_as_worker_sessions: subagentEventsCountedAsWorkerSessions,
40
+ native_worker_process_count: nativeProcessCount,
41
+ observed_subagent_event_count: subagentEventCount,
42
+ built_in_agents_allowed: builtInAgentsAllowed,
43
+ codex_app_capabilities_allowed: codexAppCapabilitiesAllowed,
44
+ codex_builtin_imagegen_helper_allowed: true,
45
+ preferred_image_generation_surface: 'Codex App $imagegen/gpt-image-2',
46
+ codex_app_builtin_evidence_class: 'codex_app_builtin',
47
+ api_fallback_evidence_class: 'api_fallback',
48
+ provider_surface_evidence_required: true,
49
+ imagegen_api_fallback_counts_as_codex_app_evidence: false,
50
+ required_output_proof_for_generated_images: requiredOutputProofForGeneratedImages,
51
+ proof_rule: 'Official Codex subagents and app tools may assist native workers, but never increase requested_agents, target_active_slots, spawned_worker_process_count, or max_observed_worker_process_count.',
52
+ limitations: [
53
+ 'helper_subagent_events_do_not_prove_worker_capacity',
54
+ 'codex_app_capability_detection_is_not_generated_output_proof',
55
+ 'image_generation_claims_require_real_raster_output_evidence'
56
+ ],
57
+ blockers
58
+ };
59
+ await writeJsonAtomic(path.join(root, 'official-subagent-helper-policy.json'), report);
60
+ return report;
61
+ }
62
+ //# sourceMappingURL=official-subagent-helper-policy.js.map
@@ -809,8 +809,6 @@ async function codexFastModeConfigStatus(opts = {}) {
809
809
  blockers.push('user.fast_mode.visible_missing');
810
810
  if (!/(^|\n)\s*enabled\s*=\s*true\s*(?:#.*)?(?=\n|$)/.test(fastMode))
811
811
  blockers.push('user.fast_mode.enabled_missing');
812
- if (!/(^|\n)\s*default_profile\s*=\s*"sks-fast-high"\s*(?:#.*)?(?=\n|$)/.test(fastMode))
813
- blockers.push('user.fast_mode.default_profile_missing');
814
812
  return {
815
813
  ok: blockers.length === 0,
816
814
  checked: true,
@@ -62,7 +62,7 @@ export async function fastModeCommand(args = []) {
62
62
  else if (action === 'clear')
63
63
  console.log(`Cleared: ${removed ? 'yes' : 'already default'}`);
64
64
  else if (!preference)
65
- console.log('Preference: implicit fast');
65
+ console.log('Preference: implicit standard');
66
66
  console.log('Dollar: $Fast-On | $Fast-Off | $Fast-Mode');
67
67
  return result;
68
68
  }