sneakoscope 2.0.11 → 2.0.13

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 (75) hide show
  1. package/README.md +9 -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/core/agents/agent-orchestrator.js +279 -1
  9. package/dist/core/agents/agent-scheduler.js +12 -1
  10. package/dist/core/agents/agent-slot-pane-binding-proof.js +3 -3
  11. package/dist/core/agents/agent-work-queue.js +26 -2
  12. package/dist/core/agents/agent-worker-pipeline.js +2 -0
  13. package/dist/core/agents/native-cli-session-swarm.js +2 -2
  14. package/dist/core/codex-control/codex-sdk-adapter.js +10 -0
  15. package/dist/core/codex-control/codex-task-runner.js +4 -2
  16. package/dist/core/commands/naruto-command.js +104 -51
  17. package/dist/core/commands/research-command.js +43 -4
  18. package/dist/core/fsx.js +1 -1
  19. package/dist/core/git/git-worktree-merge-queue.js +34 -14
  20. package/dist/core/naruto/naruto-rebalance-policy.js +15 -3
  21. package/dist/core/naruto/naruto-work-graph.js +13 -0
  22. package/dist/core/research/claim-evidence-matrix.js +160 -0
  23. package/dist/core/research/experiment-plan.js +53 -0
  24. package/dist/core/research/falsification.js +18 -0
  25. package/dist/core/research/implementation-blueprint-markdown.js +31 -0
  26. package/dist/core/research/implementation-blueprint.js +66 -0
  27. package/dist/core/research/replication-pack.js +50 -0
  28. package/dist/core/research/research-cycle-runner.js +25 -0
  29. package/dist/core/research/research-final-reviewer.js +58 -0
  30. package/dist/core/research/research-handoff.js +51 -0
  31. package/dist/core/research/research-prompt-contract.js +24 -0
  32. package/dist/core/research/research-quality-contract.js +61 -0
  33. package/dist/core/research/research-report-quality.js +67 -0
  34. package/dist/core/research/research-stage-runner.js +16 -0
  35. package/dist/core/research/research-work-graph.js +75 -0
  36. package/dist/core/research/source-quality-report.js +94 -0
  37. package/dist/core/research.js +344 -44
  38. package/dist/core/version.js +1 -1
  39. package/dist/core/zellij/zellij-slot-column-anchor.js +165 -4
  40. package/dist/core/zellij/zellij-slot-pane-renderer.js +259 -16
  41. package/dist/core/zellij/zellij-worker-pane-manager.js +13 -7
  42. package/dist/scripts/agent-real-codex-in-zellij-worker-pane-check.js +8 -2
  43. package/dist/scripts/agent-slot-pane-binding-proof-check.js +4 -4
  44. package/dist/scripts/codex-sdk-release-review-pipeline-check.js +2 -1
  45. package/dist/scripts/codex-sdk-research-pipeline-check.js +7 -0
  46. package/dist/scripts/codex-sdk-zellij-pane-binding-check.js +2 -2
  47. package/dist/scripts/git-worktree-cross-rebase-check.js +13 -1
  48. package/dist/scripts/git-worktree-merge-queue-check.js +1 -0
  49. package/dist/scripts/local-collab-worktree-gpt-final-apply-policy-check.js +63 -0
  50. package/dist/scripts/naruto-actual-worker-control-plane-check.js +30 -3
  51. package/dist/scripts/naruto-allocation-runtime-wiring-check.js +92 -0
  52. package/dist/scripts/naruto-orchestrator-runtime-source-check.js +65 -6
  53. package/dist/scripts/naruto-rebalance-policy-check.js +15 -2
  54. package/dist/scripts/naruto-shadow-clone-swarm-check.js +1 -1
  55. package/dist/scripts/packlist-performance-check.js +1 -1
  56. package/dist/scripts/release-dag-full-coverage-check.js +4 -0
  57. package/dist/scripts/release-real-check.js +258 -77
  58. package/dist/scripts/research-quality-gate-check.js +86 -0
  59. package/dist/scripts/zellij-first-slot-down-stack-check.js +1 -1
  60. package/dist/scripts/zellij-first-slot-down-stack-real-check.js +344 -4
  61. package/dist/scripts/zellij-right-column-manager-check.js +1 -1
  62. package/dist/scripts/zellij-slot-column-anchor-check.js +45 -3
  63. package/dist/scripts/zellij-slot-only-ui-check.js +3 -1
  64. package/dist/scripts/zellij-slot-pane-renderer-check.js +73 -5
  65. package/dist/scripts/zellij-slot-renderer-proof-semantics-check.js +59 -0
  66. package/dist/scripts/zellij-worker-pane-manager-check.js +23 -1
  67. package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +21 -4
  68. package/package.json +17 -2
  69. package/schemas/research/claim-evidence-matrix.schema.json +37 -0
  70. package/schemas/research/experiment-plan.schema.json +17 -0
  71. package/schemas/research/implementation-blueprint.schema.json +30 -0
  72. package/schemas/research/replication-pack.schema.json +17 -0
  73. package/schemas/research/research-final-review.schema.json +16 -0
  74. package/schemas/research/research-quality-contract.schema.json +37 -0
  75. package/schemas/research/source-quality-report.schema.json +18 -0
package/README.md CHANGED
@@ -16,12 +16,14 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
16
16
 
17
17
  ## Current Release
18
18
 
19
- SKS **2.0.11** is the slot-only Zellij and Naruto runtime stabilization release. Compact slot panes are now the default visual worker surface, the initial Zellij session stays main-only until the first visible worker is reserved, overflow workers continue headlessly with runtime evidence instead of opening excess panes, and dashboard panes stay opt-in. The release path remains manifest-backed through the v2 DAG runner, with real Zellij/Naruto/worktree proof gates split into `real-check`.
19
+ SKS **2.0.13** is the public-ready research pipeline stabilization release. It closes the Research quality contract, claim-evidence matrix, source-quality report, implementation handoff, experiment/replication pack, final-reviewer, and read-only stage-aware work graph path while preserving the 2.0.12 parallel runtime stabilization work.
20
20
 
21
21
  What changed:
22
22
 
23
- - Zellij slot panes render compact worker slots without nested dashboard chrome, and right-column state records visible panes plus headless overflow lifecycle.
24
- - Naruto active-pool checks now exercise real child-worker spawn/result collection paths, including high-fanout overflow and completed-worker collection order.
23
+ - Zellij slot panes distinguish `slot_status_renderer` panes from Codex worker panes, and the first visible worker now stacks downward below the `SLOTS` anchor with real geometry proof available under `real-check`.
24
+ - Naruto allocation owners now flow into work graph items, scheduler slices, queue ownership, and worker runtime proof; inactive owners are rebalanced and active write conflicts stay out of concurrent execution.
25
+ - Naruto active-pool checks now exercise actual child-worker spawn/result collection paths while production source-of-truth stays with the agent orchestrator scheduler.
26
+ - Worktree candidate output requires GPT Final approval before apply; GPT `modified` output replaces candidate patches and GPT `rejected` blocks apply.
25
27
  - Visible Zellij reservations are capped before pane launch so concurrent worker starts cannot over-open the right column.
26
28
  - Git worktree integration now proves the primary repo receives validated worktree diffs, with rollback hash evidence recorded around the apply step.
27
29
  - Agent role config repair detects stale generated role files and rewrites structured GPT-5.5-compatible configs atomically.
@@ -464,6 +466,8 @@ sks code-structure scan --json
464
466
 
465
467
  `sks research` prepares a named genius-lens agent council, requires every agent to run at `xhigh`, records one literal `Eureka!` idea per agent, runs an evidence-bound debate, and creates `research-source-skill.md` as a route-local source collection skill before synthesis. Research is not a code-change route: real runs may write only their own mission artifacts under `.sneakoscope/missions/<id>/`, and source/package/docs/config mutations block the run with `research-code-mutation-blocker.json`. The required Research persona lenses are Einstein Agent, Feynman Agent, Turing Agent, von Neumann Agent, and Skeptic Agent; they are cognitive roles, not impersonations, and `agent-ledger.json` must include `display_name`, `persona`, `persona_boundary`, `reasoning_effort`, falsifiers, cheap probes, and `challenge_or_response`. Normal Research is not a fixed three-cycle flow: it repeats source gathering, Eureka ideas, debate, falsification, and synthesis pressure until every agent records final agreement, or pauses at the explicit max-cycle safety cap with an unpassed gate. `debate-ledger.json` must include `consensus_iterations`, `unanimous_consensus`, and per-agent agreements; `research-gate.json` cannot pass until unanimous consensus is true for all agents. Normal Research is intentionally allowed to take one or two hours when the problem needs it; `--mock` is only for selftests or dry harness checks, and a real run blocks with `research-blocker.json` instead of silently substituting mock output when the Codex execution path is unavailable. The source layer contract separates latest papers, official/government or leading-institution sources, standards/primary docs, current news such as BBC/CNN/GDELT-style sources, public discourse such as X/Reddit, developer/practitioner knowledge such as Stack Overflow/GitHub, traditional background sources, and counterevidence/fact-checking; `source-ledger.json` must record layer coverage, source quality, blockers, citations, and cross-layer triangulation. Context7 is optional for `$Research` and only becomes relevant when the research topic specifically depends on package, API, framework, or SDK documentation. Research runs require `research-report.md`, `research-paper.md`, `genius-opinion-summary.md`, `research-source-skill.md`, `source-ledger.json`, `agent-ledger.json`, `debate-ledger.json`, `novelty-ledger.json`, `falsification-ledger.json`, and `research-gate.json` so they stay source-backed, adversarially checked, falsifiable, paper-ready, and clear about every agent lens opinion. `research status` reports source entries, source-layer coverage, triangulation checks, counterevidence, xhigh agent count, Eureka moments, debate exchanges, consensus iterations, unanimous consensus, paper presence/sections, genius-opinion summary coverage, agent findings, and falsification cases alongside the gate.
466
468
 
469
+ In 2.0.13, Research also writes a quality contract and handoff package: `research-quality-contract.json`, `claim-evidence-matrix.json`, `source-quality-report.json`, `implementation-blueprint.json`/`.md`, `experiment-plan.json`/`.md`, `replication-pack.json`, `research-work-graph.json`, and `research-final-review.json`. The default gate requires 12 total sources, 5 source layers, 2 counterevidence sources, 8 key claims, 6 triangulated claims, 8 blueprint sections, 4 falsification cases, 5 experiment steps, and a 2200-word report before `research-gate.json` can pass. See `docs/research-pipeline.md`, `docs/research-artifacts.md`, and `docs/research-implementation-handoff.md`.
470
+
467
471
  `sks recallpulse` is the 0.8.0 report-only RecallPulse utility. It writes `recallpulse-decision.json`, `mission-status-ledger.json`, `route-proof-capsule.json`, `evidence-envelope.json`, `recallpulse-governance-report.json`, `recallpulse-task-goal-ledger.json`, and `recallpulse-eval-report.json` for the current mission. RecallPulse does not replace route gates, Honest Mode, DB safety, imagegen evidence, or TriWiki validation; it records cache hits, hydration needs, duplicate suppression, route-governance risks, and final-summary-ready durable status so later releases can promote only measured improvements. Checklist updates are sequential: every `Txxx` row is treated as a child `$Goal` checkpoint, and `sks recallpulse checklist ... --task T001 --apply` refuses out-of-order checks unless explicitly overridden.
468
472
 
469
473
  `sks pipeline plan` shows the active route lane, kept/skipped stages, verification commands, and no-unrequested-fallback invariant. The 0.9.0 Decision Lattice augments this planning surface with report-only A*/proof-debt evidence: frontier paths considered, the selected path, and rejected paths with rejection reasons. `sks proof-field scan` remains the lightweight rubric for small changes; risky or broad signals return to the full Team/Honest path, and no speedup claim is valid without replay or eval evidence.
@@ -529,6 +533,8 @@ $DB inspect this migration for destructive risk
529
533
 
530
534
  Local model workers are off by default, so SKS stays GPT-only unless you explicitly enable them. Use the Codex App prompt commands:
531
535
 
536
+ ![SKS Local LLM mode workflow](docs/sks-local-llm-mode/assets/sks-local-llm-flow.png)
537
+
532
538
  ```text
533
539
  $with-local-llm-on
534
540
  $with-local-llm-off
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "sks-core"
79
- version = "2.0.11"
79
+ version = "2.0.13"
80
80
  dependencies = [
81
81
  "serde_json",
82
82
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "2.0.11"
3
+ version = "2.0.13"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -4,7 +4,7 @@ use std::io::{self, Read, Seek, SeekFrom};
4
4
  fn main() {
5
5
  let mut args = std::env::args().skip(1);
6
6
  match args.next().as_deref() {
7
- Some("--version") => println!("sks-rs 2.0.11"),
7
+ Some("--version") => println!("sks-rs 2.0.13"),
8
8
  Some("compact-info") => {
9
9
  let mut input = String::new();
10
10
  let _ = io::stdin().read_to_string(&mut input);
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schema": "sks.dist-build-stamp.v1",
3
3
  "package_name": "sneakoscope",
4
- "package_version": "2.0.11",
5
- "source_digest": "7f7339938c95fb98e1fb072192115eb0ca8cbc8136800d007b85d51fe413de19",
6
- "source_file_count": 2046,
7
- "built_at_source_time": 1780821479881
4
+ "package_version": "2.0.13",
5
+ "source_digest": "4e6d812c7572cee4b51a8e1d0374fff3b908c58e2173b6255122b87ce9e8b83e",
6
+ "source_file_count": 2090,
7
+ "built_at_source_time": 1780843454792
8
8
  }
package/dist/bin/sks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const FAST_PACKAGE_VERSION = '2.0.11';
2
+ const FAST_PACKAGE_VERSION = '2.0.13';
3
3
  const args = process.argv.slice(2);
4
4
  try {
5
5
  if (args[0] === '--agent' && args[1] === 'worker') {
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "schema": "sks.dist-build.v2",
3
- "version": "2.0.11",
4
- "package_version": "2.0.11",
3
+ "version": "2.0.13",
4
+ "package_version": "2.0.13",
5
5
  "typescript": true,
6
6
  "mjs_runtime_files": 0,
7
- "compiled_file_count": 1108,
8
- "compiled_js_count": 1108,
7
+ "compiled_file_count": 1127,
8
+ "compiled_js_count": 1127,
9
9
  "compiled_dts_count": 0,
10
- "source_digest": "7f7339938c95fb98e1fb072192115eb0ca8cbc8136800d007b85d51fe413de19",
11
- "source_file_count": 2046,
12
- "source_files_hash": "b94b6d01c22138f134b831e0e793a981744316d3e78bf457e00d81cadd9d5c07",
13
- "source_list_hash": "b94b6d01c22138f134b831e0e793a981744316d3e78bf457e00d81cadd9d5c07",
10
+ "source_digest": "4e6d812c7572cee4b51a8e1d0374fff3b908c58e2173b6255122b87ce9e8b83e",
11
+ "source_file_count": 2090,
12
+ "source_files_hash": "07ac9249be0189c641861e02515d575578156357d6a92cd33869ae8cc4a38691",
13
+ "source_list_hash": "07ac9249be0189c641861e02515d575578156357d6a92cd33869ae8cc4a38691",
14
14
  "src_mjs_runtime_files": 0,
15
15
  "dist_stamp_schema": "sks.dist-build-stamp.v1",
16
16
  "files": [
@@ -538,6 +538,21 @@
538
538
  "core/release/release-gate-scheduler.js",
539
539
  "core/reporting/markdown-table.js",
540
540
  "core/research.js",
541
+ "core/research/claim-evidence-matrix.js",
542
+ "core/research/experiment-plan.js",
543
+ "core/research/falsification.js",
544
+ "core/research/implementation-blueprint-markdown.js",
545
+ "core/research/implementation-blueprint.js",
546
+ "core/research/replication-pack.js",
547
+ "core/research/research-cycle-runner.js",
548
+ "core/research/research-final-reviewer.js",
549
+ "core/research/research-handoff.js",
550
+ "core/research/research-prompt-contract.js",
551
+ "core/research/research-quality-contract.js",
552
+ "core/research/research-report-quality.js",
553
+ "core/research/research-stage-runner.js",
554
+ "core/research/research-work-graph.js",
555
+ "core/research/source-quality-report.js",
541
556
  "core/responses-retry-policy.js",
542
557
  "core/retention.js",
543
558
  "core/router/capability-card.js",
@@ -905,6 +920,7 @@
905
920
  "scripts/local-collab-gpt-final-availability-check.js",
906
921
  "scripts/local-collab-no-local-only-final-check.js",
907
922
  "scripts/local-collab-policy-check.js",
923
+ "scripts/local-collab-worktree-gpt-final-apply-policy-check.js",
908
924
  "scripts/local-llm-all-pipelines-check.js",
909
925
  "scripts/local-llm-cache-performance-check.js",
910
926
  "scripts/local-llm-capability-check.js",
@@ -942,6 +958,7 @@
942
958
  "scripts/naruto-active-pool-check.js",
943
959
  "scripts/naruto-actual-worker-control-plane-check.js",
944
960
  "scripts/naruto-allocation-policy-check.js",
961
+ "scripts/naruto-allocation-runtime-wiring-check.js",
945
962
  "scripts/naruto-concurrency-governor-check.js",
946
963
  "scripts/naruto-extreme-parallelism-check.js",
947
964
  "scripts/naruto-extreme-parallelism-real-check.js",
@@ -1036,6 +1053,7 @@
1036
1053
  "scripts/repo-audit.js",
1037
1054
  "scripts/research-actual-route-backfill-check.js",
1038
1055
  "scripts/research-backfill-route-blackbox.js",
1056
+ "scripts/research-quality-gate-check.js",
1039
1057
  "scripts/responses-retry-policy-centralized-check.js",
1040
1058
  "scripts/retention-cleanup-safety-check.js",
1041
1059
  "scripts/route-blackbox-realism-check.js",
@@ -1117,6 +1135,7 @@
1117
1135
  "scripts/zellij-slot-column-anchor-check.js",
1118
1136
  "scripts/zellij-slot-only-ui-check.js",
1119
1137
  "scripts/zellij-slot-pane-renderer-check.js",
1138
+ "scripts/zellij-slot-renderer-proof-semantics-check.js",
1120
1139
  "scripts/zellij-spawn-on-demand-layout-check.js",
1121
1140
  "scripts/zellij-ui-design-check.js",
1122
1141
  "scripts/zellij-worker-pane-manager-check.js",
@@ -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';
@@ -59,6 +61,8 @@ import { checkpointWorkerWorktree } from '../git/git-worktree-checkpoint.js';
59
61
  import { cleanupGitWorktree } from '../git/git-worktree-cleanup.js';
60
62
  import { createGitIntegrationWorktree } from '../git/git-integration-worktree.js';
61
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';
62
66
  export async function runNativeAgentOrchestrator(opts = {}) {
63
67
  const root = path.resolve(opts.root || process.cwd());
64
68
  const prompt = String(opts.prompt || 'Native agent run');
@@ -193,7 +197,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
193
197
  }
194
198
  };
195
199
  }
196
- const partition = await buildAgentWorkPartition(root, roster, prompt, {
200
+ let partition = await buildAgentWorkPartition(root, roster, prompt, {
197
201
  route,
198
202
  targetActiveSlots,
199
203
  desiredWorkItemCount,
@@ -204,12 +208,24 @@ export async function runNativeAgentOrchestrator(opts = {}) {
204
208
  strategyOwnershipPlan: strategyCompiled.file_ownership_plan,
205
209
  microWins: strategyCompiled.gate.micro_wins
206
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
+ }
207
215
  await runAgentJanitor({ missionDir: dir, missionId, projectHash: namespace.root_hash });
208
216
  const ledgerRoot = await initializeAgentCentralLedger(dir, { missionId, roster, partition, route, prompt, dynamicScheduler: true });
209
217
  // Consult the TriWiki context pack (read-only) before dispatching workers, and
210
218
  // persist it as a proof artifact so the kernel proof references the wiki it acted on.
211
219
  const triwikiContext = await loadTriWikiRuntimeContext(root);
212
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);
213
229
  await writeAgentTaskGraph(ledgerRoot, partition.task_graph);
214
230
  await writeAdhdOrchestrationArtifacts(ledgerRoot, strategyCompiled.gate);
215
231
  await writeStrategyCompilerArtifacts(ledgerRoot, strategyCompiled);
@@ -344,6 +360,8 @@ export async function runNativeAgentOrchestrator(opts = {}) {
344
360
  const result = opts.nativeCliSwarm === false
345
361
  ? await runAgentByBackend(backend, runtimeAgent, runtimeSlice, backendOpts)
346
362
  : await nativeCliSwarm.launchWorker({ agent: runtimeAgent, slice: runtimeSlice, opts: backendOpts });
363
+ if (route === '$Naruto')
364
+ attachNarutoRuntimeProof(result, runtimeAgent, runtimeSlice);
347
365
  if (workerWorktree)
348
366
  await finalizeWorkerGitWorktree({
349
367
  root,
@@ -602,6 +620,247 @@ function withFinalGptPatchEnvelopes(results, patchEnvelopes = []) {
602
620
  next[0] = { ...next[0], patch_envelopes: patchEnvelopes };
603
621
  return next;
604
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
+ }
605
864
  async function prepareWorkerGitWorktree(input) {
606
865
  if (input.policy?.mode !== 'git-worktree')
607
866
  return null;
@@ -1075,6 +1334,24 @@ async function runGitWorktreeIntegrationPrimary(root, ledgerRoot, missionId, ent
1075
1334
  checkpoints
1076
1335
  })
1077
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);
1078
1355
  const rollbackEvidence = mainApplyReport?.ok
1079
1356
  ? await completeGitWorktreeRollbackPlan(repoRoot, rollbackPlan.rollback)
1080
1357
  : rollbackPlan;
@@ -1120,6 +1397,7 @@ async function runGitWorktreeIntegrationPrimary(root, ledgerRoot, missionId, ent
1120
1397
  conflicted_entry_ids: conflictedEntryIds,
1121
1398
  merge_queue: queueReport,
1122
1399
  main_repo_apply: mainApplyReport,
1400
+ cross_rebase: crossRebase,
1123
1401
  rollback_evidence: rollbackEvidence,
1124
1402
  apply_results: applyResults,
1125
1403
  blockers: reportBlockers
@@ -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;