sneakoscope 2.0.10 → 2.0.12

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 (65) hide show
  1. package/README.md +5 -3
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/crates/sks-core/src/main.rs +1 -1
  5. package/dist/.sks-build-stamp.json +4 -4
  6. package/dist/bin/sks.js +1 -1
  7. package/dist/build-manifest.json +27 -8
  8. package/dist/cli/command-registry.js +1 -0
  9. package/dist/cli/install-helpers.js +8 -20
  10. package/dist/commands/doctor.js +5 -9
  11. package/dist/commands/zellij-slot-column-anchor.js +23 -0
  12. package/dist/core/agents/agent-orchestrator.js +338 -12
  13. package/dist/core/agents/agent-patch-schema.js +8 -1
  14. package/dist/core/agents/agent-scheduler.js +12 -1
  15. package/dist/core/agents/agent-slot-pane-binding-proof.js +3 -3
  16. package/dist/core/agents/agent-work-queue.js +26 -2
  17. package/dist/core/agents/agent-worker-pipeline.js +2 -0
  18. package/dist/core/agents/native-cli-session-swarm.js +2 -2
  19. package/dist/core/commands/naruto-command.js +191 -39
  20. package/dist/core/fsx.js +1 -1
  21. package/dist/core/git/git-worktree-checkpoint.js +52 -0
  22. package/dist/core/git/git-worktree-cross-rebase.js +54 -0
  23. package/dist/core/git/git-worktree-merge-queue.js +92 -3
  24. package/dist/core/git/git-worktree-patch-envelope.js +8 -1
  25. package/dist/core/init.js +2 -2
  26. package/dist/core/naruto/naruto-allocation-policy.js +99 -0
  27. package/dist/core/naruto/naruto-real-worker-child.js +110 -11
  28. package/dist/core/naruto/naruto-rebalance-policy.js +48 -0
  29. package/dist/core/naruto/naruto-task-hints.js +71 -0
  30. package/dist/core/naruto/naruto-work-graph.js +13 -0
  31. package/dist/core/pipeline/finalize-pipeline-result.js +3 -1
  32. package/dist/core/pipeline/gpt-final-required.js +22 -2
  33. package/dist/core/version.js +1 -1
  34. package/dist/core/zellij/zellij-right-column-manager.js +45 -2
  35. package/dist/core/zellij/zellij-slot-column-anchor.js +218 -0
  36. package/dist/core/zellij/zellij-worker-pane-manager.js +81 -14
  37. package/dist/scripts/agent-real-codex-in-zellij-worker-pane-check.js +8 -2
  38. package/dist/scripts/agent-slot-pane-binding-proof-check.js +4 -4
  39. package/dist/scripts/codex-sdk-release-review-pipeline-check.js +2 -1
  40. package/dist/scripts/codex-sdk-zellij-pane-binding-check.js +2 -2
  41. package/dist/scripts/git-worktree-checkpoint-check.js +20 -0
  42. package/dist/scripts/git-worktree-cross-rebase-check.js +39 -0
  43. package/dist/scripts/git-worktree-merge-queue-check.js +1 -0
  44. package/dist/scripts/local-collab-worktree-gpt-final-apply-policy-check.js +63 -0
  45. package/dist/scripts/naruto-actual-worker-control-plane-check.js +56 -0
  46. package/dist/scripts/naruto-allocation-policy-check.js +33 -0
  47. package/dist/scripts/naruto-allocation-runtime-wiring-check.js +92 -0
  48. package/dist/scripts/naruto-extreme-parallelism-real-check.js +5 -4
  49. package/dist/scripts/naruto-orchestrator-runtime-source-check.js +70 -0
  50. package/dist/scripts/naruto-real-active-pool-runtime-check.js +4 -2
  51. package/dist/scripts/naruto-rebalance-policy-check.js +41 -0
  52. package/dist/scripts/naruto-shadow-clone-swarm-check.js +8 -4
  53. package/dist/scripts/release-dag-full-coverage-check.js +19 -1
  54. package/dist/scripts/release-readiness-report.js +1 -1
  55. package/dist/scripts/release-real-check.js +258 -77
  56. package/dist/scripts/zellij-first-slot-down-stack-check.js +20 -0
  57. package/dist/scripts/zellij-first-slot-down-stack-real-check.js +356 -0
  58. package/dist/scripts/zellij-right-column-manager-check.js +7 -2
  59. package/dist/scripts/zellij-slot-column-anchor-check.js +45 -0
  60. package/dist/scripts/zellij-slot-only-ui-check.js +6 -2
  61. package/dist/scripts/zellij-slot-renderer-proof-semantics-check.js +59 -0
  62. package/dist/scripts/zellij-worker-pane-manager-check.js +23 -1
  63. package/dist/scripts/zellij-worker-pane-manager-single-owner-check.js +11 -4
  64. package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +21 -4
  65. package/package.json +15 -3
@@ -3,6 +3,8 @@ import { createMission, missionDir, setCurrent } from '../mission.js';
3
3
  import { exists, nowIso, readJson, readText, sha256, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
4
4
  import { buildAgentRoster, normalizeAgentConcurrency } from './agent-roster.js';
5
5
  import { buildAgentWorkPartition } from './agent-work-partition.js';
6
+ import { detectAgentLeaseConflicts } from './work-partition/conflict-detector.js';
7
+ import { buildNoOverlapProof } from './work-partition/no-overlap-proof.js';
6
8
  import { initializeAgentCentralLedger, appendAgentLedgerEvent, compactAgentLedger } from './agent-central-ledger.js';
7
9
  import { detectStaleAgentSessions, killTimedOutAgentSessions, openAgentSession, heartbeatAgentSession, collectAgentSession, completeAgentSession, closeAgentSession, writeAgentLifecycleAggregate, writeAgentLifecyclePolicy } from './agent-lifecycle.js';
8
10
  import { writeAgentConsensus } from './agent-consensus.js';
@@ -55,9 +57,12 @@ import { selectFinalGptPatchSource } from '../pipeline/final-gpt-patch-stage.js'
55
57
  import { allocateWorkerWorktree } from '../git/git-worktree-manager.js';
56
58
  import { exportGitWorktreeDiff } from '../git/git-worktree-diff.js';
57
59
  import { buildGitWorktreePatchEnvelope } from '../git/git-worktree-patch-envelope.js';
60
+ import { checkpointWorkerWorktree } from '../git/git-worktree-checkpoint.js';
58
61
  import { cleanupGitWorktree } from '../git/git-worktree-cleanup.js';
59
62
  import { createGitIntegrationWorktree } from '../git/git-integration-worktree.js';
60
63
  import { applyGitWorktreeMergeQueue } from '../git/git-worktree-merge-queue.js';
64
+ import { crossRebaseIdleWorktrees } from '../git/git-worktree-cross-rebase.js';
65
+ import { gitOutputLine, runGitCommand } from '../git/git-worktree-runner.js';
61
66
  export async function runNativeAgentOrchestrator(opts = {}) {
62
67
  const root = path.resolve(opts.root || process.cwd());
63
68
  const prompt = String(opts.prompt || 'Native agent run');
@@ -192,7 +197,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
192
197
  }
193
198
  };
194
199
  }
195
- const partition = await buildAgentWorkPartition(root, roster, prompt, {
200
+ let partition = await buildAgentWorkPartition(root, roster, prompt, {
196
201
  route,
197
202
  targetActiveSlots,
198
203
  desiredWorkItemCount,
@@ -203,12 +208,24 @@ export async function runNativeAgentOrchestrator(opts = {}) {
203
208
  strategyOwnershipPlan: strategyCompiled.file_ownership_plan,
204
209
  microWins: strategyCompiled.gate.micro_wins
205
210
  });
211
+ if (opts.narutoWorkGraph?.work_items?.length) {
212
+ partition = applyNarutoWorkGraphToPartition(partition, opts.narutoWorkGraph, roster, targetActiveSlots);
213
+ augmentVerificationRollbackDagForNaruto(strategyCompiled.verification_rollback_dag, partition.slices);
214
+ }
206
215
  await runAgentJanitor({ missionDir: dir, missionId, projectHash: namespace.root_hash });
207
216
  const ledgerRoot = await initializeAgentCentralLedger(dir, { missionId, roster, partition, route, prompt, dynamicScheduler: true });
208
217
  // Consult the TriWiki context pack (read-only) before dispatching workers, and
209
218
  // persist it as a proof artifact so the kernel proof references the wiki it acted on.
210
219
  const triwikiContext = await loadTriWikiRuntimeContext(root);
211
220
  await writeTriWikiContextArtifact(ledgerRoot, triwikiContext);
221
+ if (opts.narutoWorkGraph?.work_items?.length) {
222
+ await writeJsonAtomic(path.join(ledgerRoot, 'naruto-work-graph.json'), opts.narutoWorkGraph);
223
+ await writeJsonAtomic(path.join(ledgerRoot, 'naruto-runtime-wiring.json'), buildNarutoRuntimeWiringProof(partition, opts.narutoWorkGraph, roster, targetActiveSlots));
224
+ }
225
+ if (opts.narutoAllocationPolicy)
226
+ await writeJsonAtomic(path.join(ledgerRoot, 'naruto-allocation-policy.json'), opts.narutoAllocationPolicy);
227
+ if (opts.narutoRebalancePolicy)
228
+ await writeJsonAtomic(path.join(ledgerRoot, 'naruto-rebalance-policy.json'), opts.narutoRebalancePolicy);
212
229
  await writeAgentTaskGraph(ledgerRoot, partition.task_graph);
213
230
  await writeAdhdOrchestrationArtifacts(ledgerRoot, strategyCompiled.gate);
214
231
  await writeStrategyCompilerArtifacts(ledgerRoot, strategyCompiled);
@@ -270,6 +287,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
270
287
  worktree_root: gitWorktreePolicy?.worktree_root || null,
271
288
  allocations: [],
272
289
  diffs: [],
290
+ checkpoints: [],
273
291
  cleanup: [],
274
292
  blockers: []
275
293
  };
@@ -342,6 +360,8 @@ export async function runNativeAgentOrchestrator(opts = {}) {
342
360
  const result = opts.nativeCliSwarm === false
343
361
  ? await runAgentByBackend(backend, runtimeAgent, runtimeSlice, backendOpts)
344
362
  : await nativeCliSwarm.launchWorker({ agent: runtimeAgent, slice: runtimeSlice, opts: backendOpts });
363
+ if (route === '$Naruto')
364
+ attachNarutoRuntimeProof(result, runtimeAgent, runtimeSlice);
345
365
  if (workerWorktree)
346
366
  await finalizeWorkerGitWorktree({
347
367
  root,
@@ -424,7 +444,10 @@ export async function runNativeAgentOrchestrator(opts = {}) {
424
444
  await writeJsonAtomic(path.join(ledgerRoot, 'local-collaboration-policy.json'), localCollaborationPolicy);
425
445
  const localParticipated = localCollaborationParticipated(results);
426
446
  const candidatePatchEnvelopes = results.flatMap((result) => Array.isArray(result.patch_envelopes) ? result.patch_envelopes : []);
427
- const gptFinalArbiter = localParticipated
447
+ const worktreeParticipated = candidatePatchEnvelopes.some((envelope) => envelope?.source === 'git-worktree-diff' || envelope?.git_worktree?.worktree_path)
448
+ || results.some((result) => result?.git_worktree_diff || result?.git_worktree_checkpoint);
449
+ const gptFinalRequired = localParticipated || worktreeParticipated;
450
+ const gptFinalArbiter = gptFinalRequired
428
451
  ? await runFinalGptReviewStage({
429
452
  schema: 'sks.gpt-final-arbiter-input.v1',
430
453
  route,
@@ -448,10 +471,10 @@ export async function runNativeAgentOrchestrator(opts = {}) {
448
471
  rollback_plan: { verification_rollback_dag: strategyCompiled.verification_rollback_dag || null }
449
472
  }, { cwd: root, mutationLedgerRoot: path.join(ledgerRoot, 'gpt-final-arbiter') })
450
473
  : null;
451
- const finalGptPatchStage = localParticipated
474
+ const finalGptPatchStage = gptFinalRequired
452
475
  ? selectFinalGptPatchSource(gptFinalArbiter, candidatePatchEnvelopes)
453
476
  : null;
454
- const resultsForPatchSwarm = localParticipated && finalGptPatchStage?.ok === true && gptFinalArbiter?.result?.status === 'modified'
477
+ const resultsForPatchSwarm = gptFinalRequired && finalGptPatchStage?.ok === true && gptFinalArbiter?.result?.status === 'modified'
455
478
  ? withFinalGptPatchEnvelopes(results, finalGptPatchStage.patch_envelopes)
456
479
  : results;
457
480
  const patchSwarm = await runAgentPatchSwarmRuntime(root, ledgerRoot, {
@@ -462,7 +485,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
462
485
  results: resultsForPatchSwarm,
463
486
  parallelWritePolicy,
464
487
  verificationRollbackDag: strategyCompiled.verification_rollback_dag,
465
- dryRun: opts.dryRunPatches === true || opts.applyPatches !== true || (localParticipated && gptFinalArbiter?.ok !== true),
488
+ dryRun: opts.dryRunPatches === true || opts.applyPatches !== true || (gptFinalRequired && gptFinalArbiter?.ok !== true),
466
489
  gptFinalArbiter,
467
490
  finalGptPatchStage
468
491
  });
@@ -491,8 +514,8 @@ export async function runNativeAgentOrchestrator(opts = {}) {
491
514
  ...(noSubagentScalingPolicy.ok ? [] : noSubagentScalingPolicy.blockers),
492
515
  ...(fastModePropagation.ok ? [] : fastModePropagation.blockers),
493
516
  ...(gitWorktreeRuntime.required === true && gitWorktreeRuntime.ok === false ? gitWorktreeRuntime.blockers || ['git_worktree_runtime_not_ok'] : []),
494
- ...(localParticipated && gptFinalArbiter?.ok !== true ? gptFinalArbiter?.blockers || ['gpt_final_arbiter_not_ok'] : []),
495
- ...(localParticipated && finalGptPatchStage?.ok === false ? finalGptPatchStage.blockers || ['final_gpt_patch_stage_not_ok'] : []),
517
+ ...(gptFinalRequired && gptFinalArbiter?.ok !== true ? gptFinalArbiter?.blockers || ['gpt_final_arbiter_not_ok'] : []),
518
+ ...(gptFinalRequired && finalGptPatchStage?.ok === false ? finalGptPatchStage.blockers || ['final_gpt_patch_stage_not_ok'] : []),
496
519
  ...(patchSwarm.ok ? [] : patchSwarm.blockers),
497
520
  ...(janitor.ok ? [] : janitor.blockers)
498
521
  ];
@@ -597,6 +620,247 @@ function withFinalGptPatchEnvelopes(results, patchEnvelopes = []) {
597
620
  next[0] = { ...next[0], patch_envelopes: patchEnvelopes };
598
621
  return next;
599
622
  }
623
+ function applyNarutoWorkGraphToPartition(partition, graph, roster, targetActiveSlots) {
624
+ const activeRoster = (Array.isArray(roster?.roster) ? roster.roster : []).slice(0, Math.max(1, targetActiveSlots));
625
+ const activeAgentIds = new Set(activeRoster.map((row) => String(row.id || '')).filter(Boolean));
626
+ const fallbackOwners = activeRoster.length ? activeRoster : [{ id: 'naruto_clone_001', role: 'verifier' }];
627
+ const referenceWorkItem = Array.isArray(partition?.task_graph?.work_items) ? partition.task_graph.work_items.find(Boolean) : null;
628
+ const sourceIntelligenceRefs = referenceWorkItem?.source_intelligence_refs || partition?.source_intelligence_refs || null;
629
+ const goalModeRef = referenceWorkItem?.goal_mode_ref || partition?.goal_mode_ref || null;
630
+ const strategyRefs = referenceWorkItem?.strategy_refs || partition?.strategy_refs || null;
631
+ const slices = (graph.work_items || []).map((item, index) => {
632
+ const requestedOwner = item.owner ? String(item.owner) : '';
633
+ const owner = requestedOwner && activeAgentIds.has(requestedOwner)
634
+ ? requestedOwner
635
+ : String(fallbackOwners[index % fallbackOwners.length]?.id || requestedOwner || `naruto_clone_${String(index + 1).padStart(3, '0')}`);
636
+ const sliceId = String(item.id || `NW-${String(index + 1).padStart(6, '0')}`);
637
+ const writePaths = normalizePathList(item.write_paths);
638
+ const readonlyPaths = normalizePathList(item.readonly_paths);
639
+ const targetPaths = normalizePathList(item.target_paths);
640
+ const verificationNodeId = writePaths.length ? `verify:${sliceId}` : null;
641
+ const rollbackNodeId = writePaths.length ? `rollback:${sliceId}` : null;
642
+ return {
643
+ id: sliceId,
644
+ owner_agent_id: owner,
645
+ owner,
646
+ lane: owner,
647
+ role: String(item.required_role || 'verifier'),
648
+ domain: String(item.allocation_hints?.domains?.[0] || item.kind || 'naruto'),
649
+ title: String(item.title || item.id || `Naruto work ${index + 1}`),
650
+ dependencies: Array.isArray(item.dependencies) ? item.dependencies.map(String) : [],
651
+ priority: index + 1,
652
+ required_persona_category: String(item.required_role || 'verifier'),
653
+ lease_requirements: Array.isArray(item.lease_requirements) ? item.lease_requirements : [],
654
+ generated_by: 'sks.naruto-work-graph.v1',
655
+ route_domain: String(item.kind || 'naruto'),
656
+ work_item_kind: String(item.kind || 'verification'),
657
+ target_paths: targetPaths,
658
+ readonly_paths: readonlyPaths,
659
+ write_paths: writePaths,
660
+ allocation_reason: item.allocation_reason || null,
661
+ allocation_score: item.allocation_score ?? null,
662
+ allocation_hints: item.allocation_hints || null,
663
+ allocation_original_owner: requestedOwner || null,
664
+ allocation_owner_rebalanced: Boolean(requestedOwner && owner !== requestedOwner),
665
+ micro_win_id: sliceId,
666
+ verification_node_id: verificationNodeId,
667
+ rollback_node_id: rollbackNodeId,
668
+ verification_required: item.verification_required === true,
669
+ source_intelligence_refs: sourceIntelligenceRefs,
670
+ goal_mode_ref: goalModeRef,
671
+ strategy_refs: strategyRefs,
672
+ max_attempts: 1,
673
+ description: [
674
+ String(item.title || item.id || 'Naruto work item'),
675
+ `Naruto owner: ${owner}`,
676
+ item.allocation_reason ? `Allocation: ${item.allocation_reason}` : null,
677
+ writePaths.length ? `Write paths: ${writePaths.join(', ')}` : 'Read-only or no-write work item.'
678
+ ].filter(Boolean).join('\n')
679
+ };
680
+ });
681
+ const workItems = (graph.work_items || []).map((item) => ({
682
+ ...item,
683
+ source_intelligence_refs: item.source_intelligence_refs || sourceIntelligenceRefs,
684
+ goal_mode_ref: item.goal_mode_ref || goalModeRef,
685
+ strategy_refs: item.strategy_refs || strategyRefs
686
+ }));
687
+ const leases = slices.flatMap((slice) => [
688
+ ...slice.write_paths.map((file, index) => ({
689
+ id: `${slice.id}:write:${index + 1}`,
690
+ agent_id: slice.owner_agent_id,
691
+ kind: 'write',
692
+ path: file,
693
+ domain: slice.domain,
694
+ status: 'active',
695
+ owner_agent: slice.owner_agent_id,
696
+ write_paths: slice.write_paths,
697
+ strategy_task_id: slice.id,
698
+ micro_win_id: slice.micro_win_id || slice.id,
699
+ verification_node_id: slice.verification_node_id || null,
700
+ rollback_node_id: slice.rollback_node_id || null,
701
+ protected_path_check: { ok: true, blockers: [] }
702
+ })),
703
+ ...slice.readonly_paths.map((file, index) => ({
704
+ id: `${slice.id}:read:${index + 1}`,
705
+ agent_id: slice.owner_agent_id,
706
+ kind: 'read',
707
+ path: file,
708
+ domain: slice.domain,
709
+ status: 'active',
710
+ owner_agent: slice.owner_agent_id,
711
+ write_paths: slice.write_paths,
712
+ strategy_task_id: slice.id,
713
+ micro_win_id: slice.micro_win_id || slice.id,
714
+ verification_node_id: slice.verification_node_id || null,
715
+ rollback_node_id: slice.rollback_node_id || null,
716
+ protected_path_check: { ok: true, blockers: [] }
717
+ }))
718
+ ]);
719
+ const conflict_report = detectAgentLeaseConflicts(leases);
720
+ const no_overlap_proof = buildNoOverlapProof(leases);
721
+ const taskGraph = partition.task_graph
722
+ ? {
723
+ ...partition.task_graph,
724
+ total_work_items: slices.length,
725
+ work_items: workItems,
726
+ route_work_count_summary: {
727
+ ...(partition.task_graph.route_work_count_summary || {}),
728
+ naruto_work_graph_items: slices.length,
729
+ allocation_owner_rebalanced_count: slices.filter((slice) => slice.allocation_owner_rebalanced).length
730
+ }
731
+ }
732
+ : null;
733
+ return {
734
+ ...partition,
735
+ ok: conflict_report.ok && no_overlap_proof.ok,
736
+ task_graph: taskGraph,
737
+ slices,
738
+ leases,
739
+ conflict_report,
740
+ no_overlap_proof,
741
+ source_intelligence_refs: sourceIntelligenceRefs,
742
+ goal_mode_ref: goalModeRef,
743
+ strategy_refs: strategyRefs,
744
+ blockers: [...(conflict_report.blockers || []), ...(no_overlap_proof.blockers || [])]
745
+ };
746
+ }
747
+ function augmentVerificationRollbackDagForNaruto(dag, slices) {
748
+ if (!dag || !Array.isArray(dag.nodes) || !Array.isArray(slices))
749
+ return dag;
750
+ const byId = new Set(dag.nodes.map((node) => String(node.id || '')).filter(Boolean));
751
+ for (const slice of slices) {
752
+ const sliceId = String(slice?.id || '');
753
+ if (!sliceId)
754
+ continue;
755
+ const writePaths = normalizePathList(slice.write_paths);
756
+ if (!byId.has(sliceId)) {
757
+ dag.nodes.push({
758
+ id: sliceId,
759
+ kind: writePaths.length ? 'write' : 'verification',
760
+ depends_on: [],
761
+ proof_artifact: writePaths.length ? 'agent-patch-queue.json' : 'agent-worker-result.json'
762
+ });
763
+ byId.add(sliceId);
764
+ }
765
+ if (!writePaths.length)
766
+ continue;
767
+ const verificationNodeId = String(slice.verification_node_id || `verify:${sliceId}`);
768
+ const rollbackNodeId = String(slice.rollback_node_id || `rollback:${sliceId}`);
769
+ if (!byId.has(verificationNodeId)) {
770
+ dag.nodes.push({
771
+ id: verificationNodeId,
772
+ kind: 'verification',
773
+ depends_on: [sliceId],
774
+ proof_artifact: 'agent-patch-verification-results.json'
775
+ });
776
+ byId.add(verificationNodeId);
777
+ }
778
+ if (!byId.has(rollbackNodeId)) {
779
+ dag.nodes.push({
780
+ id: rollbackNodeId,
781
+ kind: 'rollback',
782
+ depends_on: [sliceId, verificationNodeId],
783
+ proof_artifact: 'agent-patch-rollback-proof.json'
784
+ });
785
+ byId.add(rollbackNodeId);
786
+ }
787
+ }
788
+ dag.rollback_ready = true;
789
+ dag.verification_ready = true;
790
+ if (dag.validation?.blockers?.length)
791
+ dag.validation = { ok: true, blockers: [] };
792
+ return dag;
793
+ }
794
+ function buildNarutoRuntimeWiringProof(partition, graph, roster, targetActiveSlots) {
795
+ const activeAgentIds = new Set((Array.isArray(roster?.roster) ? roster.roster : []).slice(0, Math.max(1, targetActiveSlots)).map((row) => String(row.id || '')).filter(Boolean));
796
+ const slices = Array.isArray(partition?.slices) ? partition.slices : [];
797
+ const activeWriteConflicts = slices.flatMap((slice) => normalizePathList(slice.write_paths));
798
+ const duplicateActiveWrites = activeWriteConflicts.filter((file, index, all) => all.indexOf(file) !== index);
799
+ const ownerPreserved = slices.every((slice) => !slice.allocation_original_owner || slice.allocation_owner_rebalanced || slice.owner_agent_id === slice.allocation_original_owner);
800
+ const inactiveOwnersRebalanced = slices.every((slice) => !slice.allocation_original_owner || activeAgentIds.has(slice.allocation_original_owner) || slice.allocation_owner_rebalanced);
801
+ const blockers = [
802
+ ...(slices.length === Number(graph?.work_items?.length || 0) ? [] : ['naruto_runtime_slice_count_mismatch']),
803
+ ...(ownerPreserved ? [] : ['naruto_runtime_owner_not_preserved']),
804
+ ...(inactiveOwnersRebalanced ? [] : ['naruto_runtime_inactive_owner_not_rebalanced']),
805
+ ...(duplicateActiveWrites.length ? ['naruto_runtime_duplicate_write_paths_in_partition'] : [])
806
+ ];
807
+ return {
808
+ schema: 'sks.naruto-runtime-wiring.v1',
809
+ generated_at: nowIso(),
810
+ ok: blockers.length === 0,
811
+ source_of_truth: 'naruto-work-graph',
812
+ scheduler_slice_count: slices.length,
813
+ work_graph_item_count: Number(graph?.work_items?.length || 0),
814
+ owner_preserved: ownerPreserved,
815
+ inactive_owners_rebalanced: inactiveOwnersRebalanced,
816
+ write_conflict_free_partition: duplicateActiveWrites.length === 0,
817
+ slice_owners: slices.map((slice) => ({
818
+ id: slice.id,
819
+ owner_agent_id: slice.owner_agent_id,
820
+ original_owner: slice.allocation_original_owner || null,
821
+ rebalanced: slice.allocation_owner_rebalanced === true,
822
+ write_paths: slice.write_paths || [],
823
+ dependencies: slice.dependencies || []
824
+ })),
825
+ blockers
826
+ };
827
+ }
828
+ function attachNarutoRuntimeProof(result, agent, slice) {
829
+ const controlPlane = result?.codex_child_report || result?.codex_sdk_thread || result?.backend_router_report || null;
830
+ const selectedBackend = String(result?.backend_router_report?.selected_backend || result?.backend || '');
831
+ const actualWorkerControlPlane = selectedBackend === 'codex-sdk' || selectedBackend === 'local-llm'
832
+ ? Boolean(controlPlane?.sdk_thread_id || controlPlane?.worker_result_path || result?.codex_child_report?.worker_result_path)
833
+ : false;
834
+ result.naruto_runtime = {
835
+ schema: 'sks.naruto-worker-runtime-proof.v1',
836
+ source_of_truth: 'agent-orchestrator-scheduler',
837
+ actual_worker_control_plane: actualWorkerControlPlane,
838
+ work_item_id: String(slice?.id || result?.task_slice_id || ''),
839
+ owner: String(slice?.owner_agent_id || slice?.owner || agent?.id || ''),
840
+ allocation_reason: slice?.allocation_reason || null,
841
+ rebalance_generation: Number(slice?.allocation_owner_rebalanced === true ? 1 : 0),
842
+ selected_backend: selectedBackend || null,
843
+ explicit_fake_backend: selectedBackend === 'fake',
844
+ control_plane_result: controlPlane
845
+ ? {
846
+ worker_result_path: controlPlane.worker_result_path || null,
847
+ sdk_thread_id: controlPlane.sdk_thread_id || null,
848
+ sdk_run_id: controlPlane.sdk_run_id || null,
849
+ structured_output_valid: controlPlane.structured_output_valid === true,
850
+ stream_event_count: Number(controlPlane.stream_event_count || 0)
851
+ }
852
+ : null
853
+ };
854
+ if (result.naruto_runtime.control_plane_result)
855
+ result.control_plane_result = result.naruto_runtime.control_plane_result;
856
+ result.verification = {
857
+ status: result.verification?.status || 'not_run',
858
+ checks: [...(result.verification?.checks || []), 'naruto-agent-orchestrator-scheduler-source-of-truth']
859
+ };
860
+ }
861
+ function normalizePathList(values) {
862
+ return (Array.isArray(values) ? values : []).map((file) => String(file || '').replace(/\\/g, '/').replace(/^\.\/+/, '').replace(/\/+$/, '')).filter(Boolean);
863
+ }
600
864
  async function prepareWorkerGitWorktree(input) {
601
865
  if (input.policy?.mode !== 'git-worktree')
602
866
  return null;
@@ -647,6 +911,14 @@ async function finalizeWorkerGitWorktree(input) {
647
911
  workerId: String(input.agent.id || input.slice.id || 'worker')
648
912
  });
649
913
  await writeJsonAtomic(path.join(input.workerWorktree.artifactDir, 'git-worktree-diff.json'), diff);
914
+ const checkpoint = await checkpointWorkerWorktree({
915
+ worktreePath: allocation.worktree_path,
916
+ repoRoot: allocation.main_repo_root || input.root,
917
+ workerId: String(input.agent.id || input.slice.id || 'worker'),
918
+ taskId: String(input.slice.id || input.agent.id || 'task'),
919
+ mode: 'auto'
920
+ });
921
+ await writeJsonAtomic(path.join(input.workerWorktree.artifactDir, 'git-worktree-checkpoint.json'), checkpoint);
650
922
  input.runtime.diffs.push({
651
923
  agent_id: input.agent.id,
652
924
  slice_id: input.slice.id,
@@ -656,18 +928,29 @@ async function finalizeWorkerGitWorktree(input) {
656
928
  diff_bytes: diff.diff_bytes,
657
929
  blockers: diff.blockers
658
930
  });
931
+ input.runtime.checkpoints.push({
932
+ agent_id: input.agent.id,
933
+ slice_id: input.slice.id,
934
+ ok: checkpoint.ok,
935
+ mode_applied: checkpoint.mode_applied,
936
+ commit_hash: checkpoint.commit_hash,
937
+ changed_files: checkpoint.changed_files,
938
+ blockers: checkpoint.blockers
939
+ });
659
940
  if (!diff.clean && diff.ok) {
660
941
  const envelope = buildGitWorktreePatchEnvelope({
661
942
  diff,
662
943
  agentId: String(input.agent.id || 'agent'),
663
944
  sessionId: String(input.agent.session_id || ''),
664
945
  slotId: String(input.agent.slot_id || ''),
665
- generationIndex: Math.max(1, Math.floor(Number(input.agent.generation_index || 1)))
946
+ generationIndex: Math.max(1, Math.floor(Number(input.agent.generation_index || 1))),
947
+ checkpoint
666
948
  });
667
949
  input.result.patch_envelopes = [...(Array.isArray(input.result.patch_envelopes) ? input.result.patch_envelopes : []), envelope];
668
950
  input.result.changed_files = [...new Set([...(input.result.changed_files || []), ...diff.changed_files])];
669
- input.result.artifacts = [...new Set([...(input.result.artifacts || []), path.relative(input.ledgerRoot, path.join(input.workerWorktree.artifactDir, 'git-worktree-diff.json'))])];
951
+ input.result.artifacts = [...new Set([...(input.result.artifacts || []), path.relative(input.ledgerRoot, path.join(input.workerWorktree.artifactDir, 'git-worktree-diff.json')), path.relative(input.ledgerRoot, path.join(input.workerWorktree.artifactDir, 'git-worktree-checkpoint.json'))])];
670
952
  input.result.git_worktree_diff = diff;
953
+ input.result.git_worktree_checkpoint = checkpoint;
671
954
  }
672
955
  const cleanup = await cleanupGitWorktree({
673
956
  repoRoot: allocation.main_repo_root || input.root,
@@ -684,7 +967,7 @@ async function finalizeWorkerGitWorktree(input) {
684
967
  retention_lock_path: cleanup.retention_lock_path,
685
968
  blockers: cleanup.blockers
686
969
  });
687
- input.runtime.blockers.push(...diff.blockers, ...cleanup.blockers);
970
+ input.runtime.blockers.push(...diff.blockers, ...checkpoint.blockers, ...cleanup.blockers);
688
971
  input.runtime.ok = input.runtime.blockers.length === 0;
689
972
  await writeJsonAtomic(path.join(input.ledgerRoot, 'agent-git-worktree-runtime.json'), input.runtime);
690
973
  }
@@ -1003,6 +1286,7 @@ async function runAgentPatchSwarmRuntime(root, ledgerRoot, input) {
1003
1286
  }
1004
1287
  async function runGitWorktreeIntegrationPrimary(root, ledgerRoot, missionId, entries, queueStore) {
1005
1288
  const diffs = entries.map((entry) => gitWorktreeDiffFromQueueEntry(entry)).filter(Boolean);
1289
+ const checkpoints = entries.map((entry) => gitWorktreeCheckpointFromQueueEntry(entry)).filter(Boolean);
1006
1290
  const repoRoot = diffs[0]?.main_repo_root || root;
1007
1291
  const baseRef = diffs.find((diff) => diff.base_head)?.base_head || undefined;
1008
1292
  const integration = await createGitIntegrationWorktree({ repoRoot, missionId, ...(baseRef ? { baseRef } : {}) });
@@ -1039,15 +1323,35 @@ async function runGitWorktreeIntegrationPrimary(root, ledgerRoot, missionId, ent
1039
1323
  await queueStore.markApplying(entry.id);
1040
1324
  const queueReport = await applyGitWorktreeMergeQueue({
1041
1325
  integrationWorktreePath: integration.worktree_path,
1042
- diffs
1326
+ diffs,
1327
+ checkpoints
1043
1328
  });
1044
1329
  const rollbackPlan = queueReport.ok ? await captureGitWorktreeRollbackPlan(repoRoot, queueReport.changed_files || []) : { ok: false, rollback: [], blockers: ['git_worktree_integration_prevalidation_failed'] };
1045
1330
  const mainApplyReport = queueReport.ok && rollbackPlan.ok
1046
1331
  ? await applyGitWorktreeMergeQueue({
1047
1332
  integrationWorktreePath: repoRoot,
1048
- diffs
1333
+ diffs,
1334
+ checkpoints
1049
1335
  })
1050
1336
  : null;
1337
+ const integrationHead = mainApplyReport?.ok
1338
+ ? gitOutputLine(await runGitCommand(repoRoot, ['rev-parse', 'HEAD']).catch(() => ({ ok: false, stdout: '' })))
1339
+ : null;
1340
+ const crossRebase = integrationHead
1341
+ ? await crossRebaseIdleWorktrees({
1342
+ integrationHead,
1343
+ workers: diffs
1344
+ .filter((diff) => diff.worktree_path)
1345
+ .map((diff) => ({
1346
+ worker_id: diff.worker_id,
1347
+ worktree_path: diff.worktree_path,
1348
+ branch: diff.branch,
1349
+ state: 'done'
1350
+ }))
1351
+ })
1352
+ : null;
1353
+ if (crossRebase)
1354
+ await writeJsonAtomic(path.join(ledgerRoot, 'git-worktree-cross-rebase-report.json'), crossRebase);
1051
1355
  const rollbackEvidence = mainApplyReport?.ok
1052
1356
  ? await completeGitWorktreeRollbackPlan(repoRoot, rollbackPlan.rollback)
1053
1357
  : rollbackPlan;
@@ -1093,6 +1397,7 @@ async function runGitWorktreeIntegrationPrimary(root, ledgerRoot, missionId, ent
1093
1397
  conflicted_entry_ids: conflictedEntryIds,
1094
1398
  merge_queue: queueReport,
1095
1399
  main_repo_apply: mainApplyReport,
1400
+ cross_rebase: crossRebase,
1096
1401
  rollback_evidence: rollbackEvidence,
1097
1402
  apply_results: applyResults,
1098
1403
  blockers: reportBlockers
@@ -1176,6 +1481,27 @@ function gitWorktreeDiffFromQueueEntry(entry) {
1176
1481
  blockers: []
1177
1482
  };
1178
1483
  }
1484
+ function gitWorktreeCheckpointFromQueueEntry(entry) {
1485
+ const envelope = entry?.envelope || {};
1486
+ const meta = envelope.git_worktree || {};
1487
+ const checkpoint = meta.checkpoint || null;
1488
+ if (!checkpoint || checkpoint.mode_applied !== 'checkpoint-commit' || !checkpoint.commit_hash)
1489
+ return null;
1490
+ return {
1491
+ schema: 'sks.git-worktree-checkpoint.v1',
1492
+ ok: Array.isArray(checkpoint.blockers) ? checkpoint.blockers.length === 0 : true,
1493
+ generated_at: nowIso(),
1494
+ worktree_path: String(meta.worktree_path || ''),
1495
+ repo_root: String(meta.main_repo_root || ''),
1496
+ worker_id: String(envelope.agent_id || entry.agent_id || entry.id),
1497
+ task_id: String(envelope.task_slice_id || entry.id || ''),
1498
+ mode_requested: 'auto',
1499
+ mode_applied: 'checkpoint-commit',
1500
+ commit_hash: String(checkpoint.commit_hash),
1501
+ changed_files: Array.isArray(checkpoint.changed_files) ? checkpoint.changed_files.map(String) : Array.isArray(meta.changed_files) ? meta.changed_files.map(String) : [],
1502
+ blockers: Array.isArray(checkpoint.blockers) ? checkpoint.blockers.map(String) : []
1503
+ };
1504
+ }
1179
1505
  function normalizeDesiredWorkItemCount(value, minimumValue, targetActiveSlots) {
1180
1506
  const parsed = Number(value);
1181
1507
  const minimum = Number(minimumValue);
@@ -117,7 +117,14 @@ function normalizeGitWorktreeMetadata(input) {
117
117
  base_head: input?.base_head == null ? null : String(input.base_head),
118
118
  worktree_head: input?.worktree_head == null ? null : String(input.worktree_head),
119
119
  changed_files: Array.isArray(input?.changed_files) ? input.changed_files.map(String) : [],
120
- diff_bytes: Number(input?.diff_bytes || 0)
120
+ diff_bytes: Number(input?.diff_bytes || 0),
121
+ checkpoint: input?.checkpoint ? {
122
+ ...(input.checkpoint.schema === undefined ? {} : { schema: String(input.checkpoint.schema) }),
123
+ ...(input.checkpoint.mode_applied === undefined ? {} : { mode_applied: String(input.checkpoint.mode_applied) }),
124
+ commit_hash: input.checkpoint.commit_hash == null ? null : String(input.checkpoint.commit_hash),
125
+ changed_files: Array.isArray(input.checkpoint.changed_files) ? input.checkpoint.changed_files.map(String) : [],
126
+ blockers: Array.isArray(input.checkpoint.blockers) ? input.checkpoint.blockers.map(String) : []
127
+ } : null
121
128
  };
122
129
  }
123
130
  function normalizeHint(input) {
@@ -115,7 +115,11 @@ export async function runAgentScheduler(input) {
115
115
  break;
116
116
  const generationIndex = slot.generation_count + 1;
117
117
  const provisionalSessionId = `${slot.slot_id}-gen-${generationIndex}`;
118
- const workItem = leaseNextWorkItem(queue, provisionalSessionId);
118
+ const workItem = leaseNextWorkItem(queue, provisionalSessionId, {
119
+ slotId: slot.slot_id,
120
+ agentId: String(slot.persona_assignment?.agent_id || ''),
121
+ activeWritePaths: activeWritePaths(queue)
122
+ });
119
123
  if (!workItem)
120
124
  break;
121
125
  const generation = createAgentSessionGeneration({
@@ -314,6 +318,13 @@ function buildAgentForGeneration(slot, generation, workItem) {
314
318
  goal_mode_ref: generation.goal_mode_ref
315
319
  };
316
320
  }
321
+ function activeWritePaths(queue) {
322
+ return queue.items
323
+ .filter((item) => item.status === 'running')
324
+ .flatMap((item) => Array.isArray(item.slice?.write_paths) ? item.slice.write_paths : [])
325
+ .map((file) => String(file || '').replace(/\\/g, '/').replace(/^\.\/+/, '').replace(/\/+$/, ''))
326
+ .filter(Boolean);
327
+ }
317
328
  function delay(ms) {
318
329
  return new Promise((resolve) => setTimeout(resolve, ms));
319
330
  }
@@ -14,9 +14,9 @@ export async function evaluateAgentSlotPaneBindingProof(root, input = {}) {
14
14
  const summary = await readJson(path.join(root, 'agent-native-cli-session-swarm.json'), null);
15
15
  const ledger = await readJsonl(path.join(root, 'agent-zellij-pane-launch-ledger.jsonl'));
16
16
  const zellijRecords = Array.isArray(summary?.records)
17
- ? summary.records.filter((record) => record.scaling_primitive === 'native_cli_process_in_zellij_worker_pane')
17
+ ? summary.records.filter((record) => record.scaling_primitive === 'native_cli_process_in_zellij_worker_pane' || record.scaling_primitive === 'native_cli_process_with_zellij_slot_renderer')
18
18
  : [];
19
- const paneLedgers = ledger.filter((row) => row.scaling_primitive === 'native_cli_process_in_zellij_worker_pane' || row.pane_kind === 'worker_codex_sdk');
19
+ const paneLedgers = ledger.filter((row) => row.scaling_primitive === 'native_cli_process_in_zellij_worker_pane' || row.scaling_primitive === 'native_cli_process_with_zellij_slot_renderer' || row.pane_kind === 'worker_codex_sdk' || row.pane_kind === 'slot_status_renderer');
20
20
  const uniqueKeys = new Set();
21
21
  const duplicates = [];
22
22
  for (const row of zellijRecords) {
@@ -29,7 +29,7 @@ export async function evaluateAgentSlotPaneBindingProof(root, input = {}) {
29
29
  const zellijPaneWorkerSessions = Number(summary?.zellij_pane_worker_sessions || 0);
30
30
  const blockers = [
31
31
  ...(input.requireZellij && !zellijRecords.length ? ['slot_pane_binding_zellij_records_missing'] : []),
32
- ...(zellijRecords.some((record) => record.pane_kind !== 'worker_codex_sdk') ? ['slot_pane_binding_wrong_pane_kind'] : []),
32
+ ...(zellijRecords.some((record) => record.pane_kind !== 'worker_codex_sdk' && record.pane_kind !== 'slot_status_renderer') ? ['slot_pane_binding_wrong_pane_kind'] : []),
33
33
  ...(zellijRecords.some((record) => !isRealZellijWorkerPaneIdSource(record.zellij_pane_id_source)) ? ['slot_pane_binding_synthetic_or_missing_pane_id_source'] : []),
34
34
  ...(zellijRecords.some((record) => !record.zellij_pane_id) ? ['slot_pane_binding_pane_id_missing'] : []),
35
35
  ...(zellijRecords.some((record) => !record.sdk_thread_id) ? ['slot_pane_binding_sdk_thread_id_missing'] : []),
@@ -44,8 +44,15 @@ export function pendingWorkItems(queue) {
44
44
  .filter((item) => item.status === 'pending' && item.dependencies.every((dep) => completed.has(dep)))
45
45
  .sort((a, b) => a.priority - b.priority || a.id.localeCompare(b.id));
46
46
  }
47
- export function leaseNextWorkItem(queue, sessionId) {
48
- const item = pendingWorkItems(queue)[0];
47
+ export function leaseNextWorkItem(queue, sessionId, opts = {}) {
48
+ const activeWritePaths = new Set((opts.activeWritePaths || []).map(normalizePath).filter(Boolean));
49
+ const ready = pendingWorkItems(queue).filter((candidate) => {
50
+ const writePaths = sliceWritePaths(candidate);
51
+ return writePaths.every((file) => !activeWritePaths.has(file));
52
+ });
53
+ const item = ready.find((candidate) => ownerMatches(candidate, opts))
54
+ || ready.find((candidate) => !candidateOwner(candidate))
55
+ || ready[0];
49
56
  if (!item)
50
57
  return null;
51
58
  item.status = 'running';
@@ -54,6 +61,23 @@ export function leaseNextWorkItem(queue, sessionId) {
54
61
  queue.updated_at = nowIso();
55
62
  return item;
56
63
  }
64
+ function ownerMatches(item, opts) {
65
+ const owner = candidateOwner(item);
66
+ if (!owner)
67
+ return false;
68
+ return owner === opts.slotId || owner === opts.agentId;
69
+ }
70
+ function candidateOwner(item) {
71
+ const slice = item.slice || {};
72
+ return String(slice.owner_agent_id || slice.owner || slice.lane || '').trim();
73
+ }
74
+ function sliceWritePaths(item) {
75
+ const paths = Array.isArray(item.slice?.write_paths) ? item.slice.write_paths : [];
76
+ return paths.map((file) => normalizePath(String(file))).filter(Boolean);
77
+ }
78
+ function normalizePath(file) {
79
+ return String(file || '').replace(/\\/g, '/').replace(/^\.\/+/, '').replace(/\/+$/, '');
80
+ }
57
81
  export function completeWorkItem(queue, itemId, sessionId, status, reason = null) {
58
82
  const item = queue.items.find((row) => row.id === itemId);
59
83
  if (!item)
@@ -55,6 +55,8 @@ export function validateAgentWorkerResult(result) {
55
55
  ...(result?.source_intelligence_refs === undefined ? {} : { source_intelligence_refs: result.source_intelligence_refs }),
56
56
  ...(result?.goal_mode_ref === undefined ? {} : { goal_mode_ref: result.goal_mode_ref }),
57
57
  ...(result?.follow_up_work_items === undefined ? {} : { follow_up_work_items: followUps.accepted }),
58
+ ...(result?.naruto_runtime === undefined ? {} : { naruto_runtime: result.naruto_runtime }),
59
+ ...(result?.control_plane_result === undefined ? {} : { control_plane_result: result.control_plane_result }),
58
60
  recursion_guard: { ok: guard.ok, violations: guard.violations },
59
61
  verification: normalizeVerification(result?.verification)
60
62
  };
@@ -336,8 +336,8 @@ class NativeCliSessionSwarmRecorder {
336
336
  input.record.zellij_create_session = paneRecord.create_session;
337
337
  input.record.zellij_launch = paneRecord.launch;
338
338
  input.record.zellij_worker_pane = path.join(input.workerDirRel, 'zellij-worker-pane.json');
339
- input.record.pane_kind = 'worker_codex_sdk';
340
- input.record.scaling_primitive = 'native_cli_process_in_zellij_worker_pane';
339
+ input.record.pane_kind = paneRecord.pane_kind;
340
+ input.record.scaling_primitive = paneRecord.scaling_primitive;
341
341
  input.record.provider = paneRecord.provider;
342
342
  input.record.service_tier = paneRecord.service_tier;
343
343
  input.record.provider_context = paneRecord.provider_context;