sneakoscope 2.0.6 → 2.0.8

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 (79) hide show
  1. package/README.md +6 -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/build-manifest.json +56 -8
  8. package/dist/core/agents/agent-command-surface.js +4 -2
  9. package/dist/core/agents/agent-orchestrator.js +140 -4
  10. package/dist/core/agents/agent-patch-schema.js +20 -4
  11. package/dist/core/agents/agent-proof-evidence.js +3 -0
  12. package/dist/core/agents/native-cli-session-swarm.js +31 -5
  13. package/dist/core/agents/native-cli-worker.js +28 -1
  14. package/dist/core/codex-control/python-codex-sdk-adapter.js +28 -4
  15. package/dist/core/commands/mad-sks-command.js +25 -0
  16. package/dist/core/commands/naruto-command.js +68 -10
  17. package/dist/core/feature-registry.js +2 -0
  18. package/dist/core/fsx.js +1 -1
  19. package/dist/core/git/git-integration-worktree.js +15 -0
  20. package/dist/core/git/git-repo-detection.js +79 -0
  21. package/dist/core/git/git-worktree-cache-policy.js +36 -0
  22. package/dist/core/git/git-worktree-capability.js +54 -0
  23. package/dist/core/git/git-worktree-cleanup.js +62 -0
  24. package/dist/core/git/git-worktree-conflict-resolver.js +13 -0
  25. package/dist/core/git/git-worktree-diff.js +55 -0
  26. package/dist/core/git/git-worktree-manager.js +93 -0
  27. package/dist/core/git/git-worktree-merge-queue.js +55 -0
  28. package/dist/core/git/git-worktree-patch-envelope.js +35 -0
  29. package/dist/core/git/git-worktree-pool.js +23 -0
  30. package/dist/core/git/git-worktree-root.js +52 -0
  31. package/dist/core/git/git-worktree-runner.js +40 -0
  32. package/dist/core/naruto/naruto-active-pool.js +35 -0
  33. package/dist/core/naruto/naruto-gpt-final-pack.js +2 -0
  34. package/dist/core/naruto/naruto-work-graph.js +16 -1
  35. package/dist/core/release/release-gate-cache-v2.js +63 -0
  36. package/dist/core/release/release-gate-dag.js +179 -0
  37. package/dist/core/release/release-gate-hermetic-env.js +32 -0
  38. package/dist/core/release/release-gate-node.js +62 -0
  39. package/dist/core/release/release-gate-report.js +11 -0
  40. package/dist/core/release/release-gate-resource-governor.js +54 -0
  41. package/dist/core/release/release-gate-scheduler.js +15 -0
  42. package/dist/core/version.js +1 -1
  43. package/dist/core/zellij/zellij-dashboard-pane.js +71 -0
  44. package/dist/core/zellij/zellij-dashboard-renderer.js +42 -0
  45. package/dist/core/zellij/zellij-naruto-dashboard.js +10 -1
  46. package/dist/core/zellij/zellij-worker-pane-manager.js +68 -6
  47. package/dist/scripts/git-worktree-cache-performance-check.js +25 -0
  48. package/dist/scripts/git-worktree-capability-check.js +27 -0
  49. package/dist/scripts/git-worktree-cleanup-check.js +27 -0
  50. package/dist/scripts/git-worktree-diff-envelope-check.js +17 -0
  51. package/dist/scripts/git-worktree-diff-export-check.js +43 -0
  52. package/dist/scripts/git-worktree-dirty-lock-check.js +17 -0
  53. package/dist/scripts/git-worktree-dirty-main-detection-check.js +14 -0
  54. package/dist/scripts/git-worktree-integration-primary-check.js +22 -0
  55. package/dist/scripts/git-worktree-manager-check.js +37 -0
  56. package/dist/scripts/git-worktree-manifest-append-check.js +18 -0
  57. package/dist/scripts/git-worktree-merge-queue-check.js +30 -0
  58. package/dist/scripts/git-worktree-pool-performance-check.js +20 -0
  59. package/dist/scripts/git-worktree-untracked-diff-check.js +18 -0
  60. package/dist/scripts/lib/git-worktree-fixture.js +33 -0
  61. package/dist/scripts/naruto-shadow-clone-swarm-check.js +9 -5
  62. package/dist/scripts/naruto-worktree-coding-blackbox.js +29 -0
  63. package/dist/scripts/naruto-worktree-coding-check.js +44 -0
  64. package/dist/scripts/naruto-worktree-gpt-final-check.js +45 -0
  65. package/dist/scripts/naruto-worktree-zellij-ui-check.js +28 -0
  66. package/dist/scripts/release-gate-dag-runner-check.js +17 -0
  67. package/dist/scripts/release-gate-dag-runner.js +32 -0
  68. package/dist/scripts/release-gate-worker.js +10 -0
  69. package/dist/scripts/release-metadata-1-19-check.js +8 -2
  70. package/dist/scripts/release-parallel-check.js +1 -1
  71. package/dist/scripts/release-parallel-speed-budget-check.js +25 -0
  72. package/dist/scripts/release-stability-report-check.js +99 -0
  73. package/dist/scripts/zellij-dashboard-pane-check.js +68 -0
  74. package/dist/scripts/zellij-dashboard-watch.js +41 -0
  75. package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +185 -0
  76. package/package.json +33 -5
  77. package/schemas/git/git-worktree-capability.schema.json +19 -0
  78. package/schemas/git/git-worktree-manifest.schema.json +36 -0
  79. package/schemas/release/release-gate-node.schema.json +52 -0
package/README.md CHANGED
@@ -16,10 +16,15 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
16
16
 
17
17
  ## Current Release
18
18
 
19
- SKS **2.0.6** wires Codex App Product Design into the design pipeline and hardens Naruto read-only routing on top of the 2.0 execution layer. Design routes can now discover, install, verify, and prefer the remote `product-design@openai-curated-remote` plugin, while read-only native worker runs keep write mode off and avoid treating pre-existing dirty files as generated patches.
19
+ SKS **2.0.8** makes the release path DAG-parallel by default and hardens the Naruto/MAD-SKS worktree proof chain. `release:check` now runs a manifest-backed DAG runner with resource-aware scheduling, hermetic per-gate environments, bounded logs, per-gate reports, cache proof, and parallel speed-budget evidence. Git worktree coding now preserves allocation manifests, detects dirty main worktrees, includes untracked content in exported diffs, emits one `git_apply_patch` envelope operation, applies worktree diffs through an integration queue, and locks retained dirty worktrees.
20
20
 
21
21
  What changed:
22
22
 
23
+ - Git capability checks detect repo roots, Git dirs, worktree support, and safe cache roots while blocking in-repo worktree roots unless `SKS_ALLOW_IN_REPO_WORKTREES=1` is explicit.
24
+ - Worker worktree allocation creates isolated branches/paths under `$SKS_WORKTREE_ROOT`, `$XDG_CACHE_HOME/sks/worktrees`, or `~/.cache/sks/worktrees`; main checkouts stay untouched until integration.
25
+ - Worktree diff export records status, changed files, full-index binary diffs, and `git-worktree-diff` patch envelopes for parent-owned integration.
26
+ - Integration worktrees apply worker diffs with `git apply --3way`, while cleanup removes only clean worktrees and retains dirty ones with a lock artifact.
27
+ - Naruto work graphs, active-pool artifacts, Zellij dashboard titles, native worker intake, and GPT Final packs now carry worktree policy and WT/branch context.
23
28
  - Product Design plugin readiness now checks both local and remote Codex App catalogs, auto-installs the remote plugin when needed, and records the installed/enabled skill surface.
24
29
  - UI/design/PPT runtime routes prefer Product Design for research, ideation, audit, design QA, prototype, URL-to-code, image-to-code, share, and user-context steps.
25
30
  - Naruto read-only runs force write mode off, propagate no-patch reasons through worker proof, and skip changed-file lease checks when no write-capable patch envelope exists.
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "sks-core"
79
- version = "2.0.6"
79
+ version = "2.0.8"
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.6"
3
+ version = "2.0.8"
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.6"),
7
+ Some("--version") => println!("sks-rs 2.0.8"),
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.6",
5
- "source_digest": "3947e39c47a565506e9ffd37568ae889bc7943f6dc342b5c357976b840770f94",
6
- "source_file_count": 1953,
7
- "built_at_source_time": 1780662014263
4
+ "package_version": "2.0.8",
5
+ "source_digest": "5009938d20628f783aa7ac19da170d2737fef89481b49d9c8dc3f2f97c0dcf9d",
6
+ "source_file_count": 2004,
7
+ "built_at_source_time": 1780739165211
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.6';
2
+ const FAST_PACKAGE_VERSION = '2.0.8';
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.6",
4
- "package_version": "2.0.6",
3
+ "version": "2.0.8",
4
+ "package_version": "2.0.8",
5
5
  "typescript": true,
6
6
  "mjs_runtime_files": 0,
7
- "compiled_file_count": 1019,
8
- "compiled_js_count": 1019,
7
+ "compiled_file_count": 1067,
8
+ "compiled_js_count": 1067,
9
9
  "compiled_dts_count": 0,
10
- "source_digest": "3947e39c47a565506e9ffd37568ae889bc7943f6dc342b5c357976b840770f94",
11
- "source_file_count": 1953,
12
- "source_files_hash": "5d6f0e4186fc37279e1cf6de0c6b3c7230123c4a588966f8fda2a9324eb75192",
13
- "source_list_hash": "5d6f0e4186fc37279e1cf6de0c6b3c7230123c4a588966f8fda2a9324eb75192",
10
+ "source_digest": "5009938d20628f783aa7ac19da170d2737fef89481b49d9c8dc3f2f97c0dcf9d",
11
+ "source_file_count": 2004,
12
+ "source_files_hash": "045de0cf4e0b27b18838e5826c77f19ee281908588bbfde4a00a448b5a3c03eb",
13
+ "source_list_hash": "045de0cf4e0b27b18838e5826c77f19ee281908588bbfde4a00a448b5a3c03eb",
14
14
  "src_mjs_runtime_files": 0,
15
15
  "dist_stamp_schema": "sks.dist-build-stamp.v1",
16
16
  "files": [
@@ -342,6 +342,19 @@
342
342
  "core/git-hygiene/shared-memory-security.js",
343
343
  "core/git-hygiene/validators.js",
344
344
  "core/git-simple.js",
345
+ "core/git/git-integration-worktree.js",
346
+ "core/git/git-repo-detection.js",
347
+ "core/git/git-worktree-cache-policy.js",
348
+ "core/git/git-worktree-capability.js",
349
+ "core/git/git-worktree-cleanup.js",
350
+ "core/git/git-worktree-conflict-resolver.js",
351
+ "core/git/git-worktree-diff.js",
352
+ "core/git/git-worktree-manager.js",
353
+ "core/git/git-worktree-merge-queue.js",
354
+ "core/git/git-worktree-patch-envelope.js",
355
+ "core/git/git-worktree-pool.js",
356
+ "core/git/git-worktree-root.js",
357
+ "core/git/git-worktree-runner.js",
345
358
  "core/goal-workflow.js",
346
359
  "core/gx-renderer.js",
347
360
  "core/harness-conflicts.js",
@@ -506,6 +519,13 @@
506
519
  "core/release-parallel-full-coverage.js",
507
520
  "core/release/gate-cache.js",
508
521
  "core/release/gate-manifest.js",
522
+ "core/release/release-gate-cache-v2.js",
523
+ "core/release/release-gate-dag.js",
524
+ "core/release/release-gate-hermetic-env.js",
525
+ "core/release/release-gate-node.js",
526
+ "core/release/release-gate-report.js",
527
+ "core/release/release-gate-resource-governor.js",
528
+ "core/release/release-gate-scheduler.js",
509
529
  "core/reporting/markdown-table.js",
510
530
  "core/research.js",
511
531
  "core/responses-retry-policy.js",
@@ -603,6 +623,8 @@
603
623
  "core/zellij/zellij-capability.js",
604
624
  "core/zellij/zellij-clipboard-config.js",
605
625
  "core/zellij/zellij-command.js",
626
+ "core/zellij/zellij-dashboard-pane.js",
627
+ "core/zellij/zellij-dashboard-renderer.js",
606
628
  "core/zellij/zellij-lane-renderer.js",
607
629
  "core/zellij/zellij-lane-runtime.js",
608
630
  "core/zellij/zellij-launcher.js",
@@ -814,6 +836,19 @@
814
836
  "scripts/flagship-proof-graph-v3-check.js",
815
837
  "scripts/flagship-proof-graph-v4-check.js",
816
838
  "scripts/git-precommit-fixture-check.js",
839
+ "scripts/git-worktree-cache-performance-check.js",
840
+ "scripts/git-worktree-capability-check.js",
841
+ "scripts/git-worktree-cleanup-check.js",
842
+ "scripts/git-worktree-diff-envelope-check.js",
843
+ "scripts/git-worktree-diff-export-check.js",
844
+ "scripts/git-worktree-dirty-lock-check.js",
845
+ "scripts/git-worktree-dirty-main-detection-check.js",
846
+ "scripts/git-worktree-integration-primary-check.js",
847
+ "scripts/git-worktree-manager-check.js",
848
+ "scripts/git-worktree-manifest-append-check.js",
849
+ "scripts/git-worktree-merge-queue-check.js",
850
+ "scripts/git-worktree-pool-performance-check.js",
851
+ "scripts/git-worktree-untracked-diff-check.js",
817
852
  "scripts/goal-mode-official-default-check.js",
818
853
  "scripts/gpt-final-arbiter-check.js",
819
854
  "scripts/gpt-final-arbiter-performance-check.js",
@@ -841,6 +876,7 @@
841
876
  "scripts/legacy-upgrade-matrix-check.js",
842
877
  "scripts/lib/codex-sdk-gate-lib.js",
843
878
  "scripts/lib/ensure-dist-fresh.js",
879
+ "scripts/lib/git-worktree-fixture.js",
844
880
  "scripts/lib/mad-sks-actual-executor-check-lib.js",
845
881
  "scripts/lib/native-cli-session-swarm-check-lib.js",
846
882
  "scripts/lib/real-codex-parallel-gate.js",
@@ -894,6 +930,10 @@
894
930
  "scripts/naruto-shadow-clone-swarm-check.js",
895
931
  "scripts/naruto-verification-pool-check.js",
896
932
  "scripts/naruto-work-graph-check.js",
933
+ "scripts/naruto-worktree-coding-blackbox.js",
934
+ "scripts/naruto-worktree-coding-check.js",
935
+ "scripts/naruto-worktree-gpt-final-check.js",
936
+ "scripts/naruto-worktree-zellij-ui-check.js",
897
937
  "scripts/naruto-zellij-massive-ui-check.js",
898
938
  "scripts/non-recursive-pipeline-check.js",
899
939
  "scripts/npm-publish-performance-check.js",
@@ -939,8 +979,11 @@
939
979
  "scripts/release-dist-freshness-check.js",
940
980
  "scripts/release-dynamic-performance-check.js",
941
981
  "scripts/release-gate-budget-check.js",
982
+ "scripts/release-gate-dag-runner-check.js",
983
+ "scripts/release-gate-dag-runner.js",
942
984
  "scripts/release-gate-existence-audit.js",
943
985
  "scripts/release-gate-planner.js",
986
+ "scripts/release-gate-worker.js",
944
987
  "scripts/release-metadata-1-11-check.js",
945
988
  "scripts/release-metadata-1-12-check.js",
946
989
  "scripts/release-metadata-1-13-check.js",
@@ -952,11 +995,13 @@
952
995
  "scripts/release-native-agent-fixture-check.js",
953
996
  "scripts/release-parallel-check.js",
954
997
  "scripts/release-parallel-full-coverage-check.js",
998
+ "scripts/release-parallel-speed-budget-check.js",
955
999
  "scripts/release-provenance-check.js",
956
1000
  "scripts/release-readiness-report.js",
957
1001
  "scripts/release-real-check.js",
958
1002
  "scripts/release-registry-check.js",
959
1003
  "scripts/release-runtime-truth-matrix-check.js",
1004
+ "scripts/release-stability-report-check.js",
960
1005
  "scripts/release-version-truth-check.js",
961
1006
  "scripts/repo-audit.js",
962
1007
  "scripts/research-actual-route-backfill-check.js",
@@ -1020,6 +1065,8 @@
1020
1065
  "scripts/wrongness-fixture-check.js",
1021
1066
  "scripts/xai-mcp-capability-check.js",
1022
1067
  "scripts/zellij-capability-check.js",
1068
+ "scripts/zellij-dashboard-pane-check.js",
1069
+ "scripts/zellij-dashboard-watch.js",
1023
1070
  "scripts/zellij-doctor-readiness-check.js",
1024
1071
  "scripts/zellij-lane-renderer-check.js",
1025
1072
  "scripts/zellij-launch-command-truth-check.js",
@@ -1033,6 +1080,7 @@
1033
1080
  "scripts/zellij-ui-design-check.js",
1034
1081
  "scripts/zellij-worker-pane-manager-check.js",
1035
1082
  "scripts/zellij-worker-pane-manager-single-owner-check.js",
1083
+ "scripts/zellij-worker-pane-real-ui-blackbox.js",
1036
1084
  "scripts/zellij-worker-pane-spawn-order-check.js",
1037
1085
  "vendor/openai-codex/latest/hooks/permission-request.command.input.schema.json",
1038
1086
  "vendor/openai-codex/latest/hooks/permission-request.command.output.schema.json",
@@ -33,6 +33,8 @@ export function parseAgentCommandArgs(command, args = []) {
33
33
  const ollamaBaseUrl = String(readOption(args, '--ollama-base-url', readOption(args, '--local-model-base-url', '')) || '') || null;
34
34
  const zellijSessionName = String(readOption(args, '--zellij-session-name', '') || '') || null;
35
35
  const zellijPaneWorker = hasFlag(args, '--no-zellij-pane-worker') ? false : hasFlag(args, '--zellij-pane-worker') ? true : undefined;
36
+ const workerPlacement = String(readOption(args, '--worker-placement', zellijPaneWorker === true ? 'zellij-pane' : '') || '') || undefined;
37
+ const zellijVisiblePaneCap = Number(readOption(args, '--zellij-visible-pane-cap', process.env.SKS_ZELLIJ_VISIBLE_PANE_CAP || 12));
36
38
  const apply = hasFlag(args, '--apply');
37
39
  const dryRun = hasFlag(args, '--dry-run') || hasFlag(args, '--dryrun');
38
40
  const drain = hasFlag(args, '--drain');
@@ -40,7 +42,7 @@ export function parseAgentCommandArgs(command, args = []) {
40
42
  const graceMs = Number(readOption(args, '--grace-ms', 750));
41
43
  const killEscalation = hasFlag(args, '--kill-escalation') || !hasFlag(args, '--no-kill-escalation');
42
44
  const codexApp = hasFlag(args, '--codex-app');
43
- const positionals = positionalArgs(rest, new Set(['--agents', '--target-active-slots', '--work-items', '--minimum-work-items', '--max-queue-expansion', '--concurrency', '--backend', '--route', '--mission', '--mission-id', '--agent', '--lane', '--stale-ms', '--grace-ms', '--profile', '--write-mode', '--max-write-agents', '--patch-entry-id', '--patch-entry', '--service-tier', '--zellij-session-name', '--intake', '--agent-root', '--artifact-dir', '--result-path', '--heartbeat-path', '--patch-envelope-path', '--ollama-model', '--local-model-model', '--ollama-base-url', '--local-model-base-url']));
45
+ const positionals = positionalArgs(rest, new Set(['--agents', '--target-active-slots', '--work-items', '--minimum-work-items', '--max-queue-expansion', '--concurrency', '--backend', '--route', '--mission', '--mission-id', '--agent', '--lane', '--stale-ms', '--grace-ms', '--profile', '--write-mode', '--max-write-agents', '--patch-entry-id', '--patch-entry', '--service-tier', '--zellij-session-name', '--worker-placement', '--zellij-visible-pane-cap', '--intake', '--agent-root', '--artifact-dir', '--result-path', '--heartbeat-path', '--patch-envelope-path', '--ollama-model', '--local-model-model', '--ollama-base-url', '--local-model-base-url']));
44
46
  const missionDefault = action === 'run' || action === 'spawn' || action === 'plan' ? '' : 'latest';
45
47
  const positionalMission = action === 'run' || action === 'spawn' || action === 'plan' ? '' : (positionals[0] || '');
46
48
  const missionId = String(readOption(args, '--mission', readOption(args, '--mission-id', positionalMission || missionDefault)));
@@ -48,7 +50,7 @@ export function parseAgentCommandArgs(command, args = []) {
48
50
  const patchEntryId = String(readOption(args, '--patch-entry-id', readOption(args, '--patch-entry', '')));
49
51
  const promptPositionals = positionalMission ? positionals.slice(1) : positionals;
50
52
  const prompt = promptPositionals.join(' ').trim() || 'Native agent run';
51
- return { command, action, prompt, route, agents, targetActiveSlots, desiredWorkItemCount, minimumWorkItems, maxQueueExpansion, concurrency, backend, backendExplicit, mock, real, readonly, profile, writeMode, applyPatches, dryRunPatches, maxWriteAgents, fastMode, serviceTier, noFast, ollamaEnabled: useOllama && !noOllama, noOllama, ollamaModel, ollamaBaseUrl, zellijSessionName, zellijPaneWorker, apply, dryRun, drain, staleMs, graceMs, killEscalation, json, missionId, lane, codexApp, patchEntryId };
53
+ return { command, action, prompt, route, agents, targetActiveSlots, desiredWorkItemCount, minimumWorkItems, maxQueueExpansion, concurrency, backend, backendExplicit, mock, real, readonly, profile, writeMode, applyPatches, dryRunPatches, maxWriteAgents, fastMode, serviceTier, noFast, ollamaEnabled: useOllama && !noOllama, noOllama, ollamaModel, ollamaBaseUrl, zellijSessionName, zellijPaneWorker, workerPlacement, zellijVisiblePaneCap, apply, dryRun, drain, staleMs, graceMs, killEscalation, json, missionId, lane, codexApp, patchEntryId };
52
54
  }
53
55
  function hasFlag(args, flag) {
54
56
  return args.includes(flag);
@@ -52,6 +52,10 @@ import { CODEX_AGENT_WORKER_RESULT_SCHEMA_ID, codexAgentWorkerResultSchema } fro
52
52
  import { resolveLocalCollaborationPolicy, localCollaborationParticipated } from '../local-llm/local-collaboration-policy.js';
53
53
  import { runFinalGptReviewStage } from '../pipeline/final-gpt-review-stage.js';
54
54
  import { selectFinalGptPatchSource } from '../pipeline/final-gpt-patch-stage.js';
55
+ import { allocateWorkerWorktree } from '../git/git-worktree-manager.js';
56
+ import { exportGitWorktreeDiff } from '../git/git-worktree-diff.js';
57
+ import { buildGitWorktreePatchEnvelope } from '../git/git-worktree-patch-envelope.js';
58
+ import { cleanupGitWorktree } from '../git/git-worktree-cleanup.js';
55
59
  export async function runNativeAgentOrchestrator(opts = {}) {
56
60
  const root = path.resolve(opts.root || process.cwd());
57
61
  const prompt = String(opts.prompt || 'Native agent run');
@@ -253,6 +257,21 @@ export async function runNativeAgentOrchestrator(opts = {}) {
253
257
  strategy_gate: strategyRef
254
258
  };
255
259
  await writeJsonAtomic(path.join(ledgerRoot, 'agent-parallel-write-policy.json'), parallelWritePolicy);
260
+ const gitWorktreePolicy = opts.gitWorktreePolicy || null;
261
+ const gitWorktreeRuntime = {
262
+ schema: 'sks.agent-git-worktree-runtime.v1',
263
+ generated_at: nowIso(),
264
+ ok: true,
265
+ mode: gitWorktreePolicy?.mode || 'patch-envelope-only',
266
+ required: gitWorktreePolicy?.required === true,
267
+ main_repo_root: gitWorktreePolicy?.main_repo_root || root,
268
+ worktree_root: gitWorktreePolicy?.worktree_root || null,
269
+ allocations: [],
270
+ diffs: [],
271
+ cleanup: [],
272
+ blockers: []
273
+ };
274
+ await writeJsonAtomic(path.join(ledgerRoot, 'agent-git-worktree-runtime.json'), gitWorktreeRuntime);
256
275
  const nativeCliSwarm = createNativeCliSessionSwarmRecorder(ledgerRoot, {
257
276
  missionId,
258
277
  requestedAgents: Number(opts.agents || roster.agent_count || targetActiveSlots),
@@ -261,7 +280,8 @@ export async function runNativeAgentOrchestrator(opts = {}) {
261
280
  backendExplicit: opts.backendExplicit === true,
262
281
  noOllama: opts.noOllama === true,
263
282
  route,
264
- fastModePolicy
283
+ fastModePolicy,
284
+ ...(opts.workerPlacement === undefined ? {} : { workerPlacement: String(opts.workerPlacement) })
265
285
  });
266
286
  await nativeCliSwarm.initialize();
267
287
  await setCurrent(root, { mission_id: missionId, mode: 'AGENT', phase: 'AGENT_NATIVE_KERNEL_RUNNING', route_command: routeCommand, native_agent_backend: backend });
@@ -280,6 +300,17 @@ export async function runNativeAgentOrchestrator(opts = {}) {
280
300
  goalModeRef,
281
301
  launchSession: async ({ agent, workItem }) => {
282
302
  const slice = workItem.slice || { id: workItem.id, description: workItem.description || prompt };
303
+ const workerWorktree = await prepareWorkerGitWorktree({
304
+ root,
305
+ ledgerRoot,
306
+ missionId,
307
+ agent,
308
+ slice,
309
+ policy: gitWorktreePolicy,
310
+ runtime: gitWorktreeRuntime
311
+ });
312
+ const runtimeAgent = workerWorktree ? { ...agent, worktree: workerWorktree.context } : agent;
313
+ const runtimeSlice = workerWorktree ? { ...slice, worktree: workerWorktree.context } : slice;
283
314
  await openAgentSession(ledgerRoot, agent);
284
315
  await heartbeatAgentSession(ledgerRoot, agent);
285
316
  await appendAgentCodexCockpitHookEvent(dir, {
@@ -303,10 +334,21 @@ export async function runNativeAgentOrchestrator(opts = {}) {
303
334
  generationIndex: agent.generation_index,
304
335
  requireGeneration: true
305
336
  });
306
- const backendOpts = { ...opts, missionId, agentRoot: ledgerRoot, cwd: root, route, prompt, fastMode: fastModePolicy.fast_mode, serviceTier: fastModePolicy.service_tier };
337
+ const backendOpts = { ...opts, missionId, agentRoot: ledgerRoot, cwd: workerWorktree?.context.path || root, route, prompt, fastMode: fastModePolicy.fast_mode, serviceTier: fastModePolicy.service_tier, ...(workerWorktree ? { worktree: workerWorktree.context } : {}) };
307
338
  const result = opts.nativeCliSwarm === false
308
- ? await runAgentByBackend(backend, agent, slice, backendOpts)
309
- : await nativeCliSwarm.launchWorker({ agent, slice, opts: backendOpts });
339
+ ? await runAgentByBackend(backend, runtimeAgent, runtimeSlice, backendOpts)
340
+ : await nativeCliSwarm.launchWorker({ agent: runtimeAgent, slice: runtimeSlice, opts: backendOpts });
341
+ if (workerWorktree)
342
+ await finalizeWorkerGitWorktree({
343
+ root,
344
+ ledgerRoot,
345
+ missionId,
346
+ agent: runtimeAgent,
347
+ slice: runtimeSlice,
348
+ result,
349
+ workerWorktree,
350
+ runtime: gitWorktreeRuntime
351
+ });
310
352
  const terminalClose = await closeAgentTerminalSession(ledgerRoot, agent, {
311
353
  exitCode: result.status === 'done' ? 0 : 1,
312
354
  status: result.status,
@@ -444,6 +486,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
444
486
  ...(nativeCliSessionProof.ok ? [] : nativeCliSessionProof.blockers),
445
487
  ...(noSubagentScalingPolicy.ok ? [] : noSubagentScalingPolicy.blockers),
446
488
  ...(fastModePropagation.ok ? [] : fastModePropagation.blockers),
489
+ ...(gitWorktreeRuntime.required === true && gitWorktreeRuntime.ok === false ? gitWorktreeRuntime.blockers || ['git_worktree_runtime_not_ok'] : []),
447
490
  ...(localParticipated && gptFinalArbiter?.ok !== true ? gptFinalArbiter?.blockers || ['gpt_final_arbiter_not_ok'] : []),
448
491
  ...(localParticipated && finalGptPatchStage?.ok === false ? finalGptPatchStage.blockers || ['final_gpt_patch_stage_not_ok'] : []),
449
492
  ...(patchSwarm.ok ? [] : patchSwarm.blockers),
@@ -480,6 +523,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
480
523
  noSubagentScalingPolicy,
481
524
  fastModePolicy,
482
525
  fastModePropagation,
526
+ gitWorktreeRuntime,
483
527
  triwikiContext,
484
528
  selectedCoreSkill,
485
529
  localCollaborationPolicy,
@@ -524,6 +568,7 @@ export async function runNativeAgentOrchestrator(opts = {}) {
524
568
  no_subagent_scaling_policy: noSubagentScalingPolicy,
525
569
  fast_mode_policy: fastModePolicy,
526
570
  fast_mode_propagation: fastModePropagation,
571
+ git_worktree_runtime: gitWorktreeRuntime,
527
572
  local_collaboration_policy: localCollaborationPolicy,
528
573
  gpt_final_arbiter: gptFinalArbiter,
529
574
  final_gpt_patch_stage: finalGptPatchStage,
@@ -548,6 +593,97 @@ function withFinalGptPatchEnvelopes(results, patchEnvelopes = []) {
548
593
  next[0] = { ...next[0], patch_envelopes: patchEnvelopes };
549
594
  return next;
550
595
  }
596
+ async function prepareWorkerGitWorktree(input) {
597
+ if (input.policy?.mode !== 'git-worktree')
598
+ return null;
599
+ const sliceHasWritePaths = Array.isArray(input.slice.write_paths) && input.slice.write_paths.length > 0;
600
+ const agentWriteCapable = input.agent.write_allowed === true || /write|lease|required/i.test(String(input.agent.write_policy || ''));
601
+ if (!sliceHasWritePaths && !agentWriteCapable)
602
+ return null;
603
+ const generationIndex = Math.max(1, Math.floor(Number(input.agent.generation_index || 1)));
604
+ const allocation = await allocateWorkerWorktree({
605
+ repoRoot: input.policy.main_repo_root || input.root,
606
+ missionId: input.missionId,
607
+ workerId: String(input.agent.id || input.slice.id || 'worker'),
608
+ slotId: String(input.agent.slot_id || input.agent.id || 'slot-001'),
609
+ generationIndex
610
+ });
611
+ const artifactDir = path.join(input.ledgerRoot, input.agent.session_artifact_dir || path.join('sessions', input.agent.id || input.slice.id || 'worker'), 'worker');
612
+ await writeJsonAtomic(path.join(artifactDir, 'git-worktree-allocation.json'), allocation);
613
+ input.runtime.allocations.push({
614
+ agent_id: input.agent.id,
615
+ slice_id: input.slice.id,
616
+ ok: allocation.ok,
617
+ worktree_path: allocation.worktree_path,
618
+ branch: allocation.branch,
619
+ blockers: allocation.blockers
620
+ });
621
+ input.runtime.blockers.push(...allocation.blockers);
622
+ input.runtime.ok = input.runtime.blockers.length === 0;
623
+ await writeJsonAtomic(path.join(input.ledgerRoot, 'agent-git-worktree-runtime.json'), input.runtime);
624
+ if (!allocation.ok)
625
+ return null;
626
+ return {
627
+ allocation,
628
+ artifactDir,
629
+ context: {
630
+ id: `${allocation.slot_id}-gen-${allocation.generation_index}`,
631
+ path: allocation.worktree_path,
632
+ branch: allocation.branch,
633
+ main_repo_root: allocation.main_repo_root
634
+ }
635
+ };
636
+ }
637
+ async function finalizeWorkerGitWorktree(input) {
638
+ const allocation = input.workerWorktree.allocation;
639
+ const diff = await exportGitWorktreeDiff({
640
+ mainRepoRoot: allocation.main_repo_root || input.root,
641
+ worktreePath: allocation.worktree_path,
642
+ missionId: input.missionId,
643
+ workerId: String(input.agent.id || input.slice.id || 'worker')
644
+ });
645
+ await writeJsonAtomic(path.join(input.workerWorktree.artifactDir, 'git-worktree-diff.json'), diff);
646
+ input.runtime.diffs.push({
647
+ agent_id: input.agent.id,
648
+ slice_id: input.slice.id,
649
+ ok: diff.ok,
650
+ clean: diff.clean,
651
+ changed_files: diff.changed_files,
652
+ diff_bytes: diff.diff_bytes,
653
+ blockers: diff.blockers
654
+ });
655
+ if (!diff.clean && diff.ok) {
656
+ const envelope = buildGitWorktreePatchEnvelope({
657
+ diff,
658
+ agentId: String(input.agent.id || 'agent'),
659
+ sessionId: String(input.agent.session_id || ''),
660
+ slotId: String(input.agent.slot_id || ''),
661
+ generationIndex: Math.max(1, Math.floor(Number(input.agent.generation_index || 1)))
662
+ });
663
+ input.result.patch_envelopes = [...(Array.isArray(input.result.patch_envelopes) ? input.result.patch_envelopes : []), envelope];
664
+ input.result.changed_files = [...new Set([...(input.result.changed_files || []), ...diff.changed_files])];
665
+ input.result.artifacts = [...new Set([...(input.result.artifacts || []), path.relative(input.ledgerRoot, path.join(input.workerWorktree.artifactDir, 'git-worktree-diff.json'))])];
666
+ input.result.git_worktree_diff = diff;
667
+ }
668
+ const cleanup = await cleanupGitWorktree({
669
+ repoRoot: allocation.main_repo_root || input.root,
670
+ worktreePath: allocation.worktree_path,
671
+ branch: allocation.branch,
672
+ deleteBranch: diff.clean
673
+ });
674
+ await writeJsonAtomic(path.join(input.workerWorktree.artifactDir, 'git-worktree-cleanup.json'), cleanup);
675
+ input.runtime.cleanup.push({
676
+ agent_id: input.agent.id,
677
+ slice_id: input.slice.id,
678
+ action: cleanup.action,
679
+ clean: cleanup.clean,
680
+ retention_lock_path: cleanup.retention_lock_path,
681
+ blockers: cleanup.blockers
682
+ });
683
+ input.runtime.blockers.push(...diff.blockers, ...cleanup.blockers);
684
+ input.runtime.ok = input.runtime.blockers.length === 0;
685
+ await writeJsonAtomic(path.join(input.ledgerRoot, 'agent-git-worktree-runtime.json'), input.runtime);
686
+ }
551
687
  async function legacyCodexExecBlockedRun(input) {
552
688
  const blockers = ['legacy_codex_exec_runtime_removed'];
553
689
  const ledgerRoot = path.join(input.dir, 'agents');
@@ -27,6 +27,7 @@ export function normalizeAgentPatchEnvelope(input) {
27
27
  ...(input?.verification_node_id === undefined ? {} : { verification_node_id: String(input.verification_node_id) }),
28
28
  ...(input?.rollback_node_id === undefined ? {} : { rollback_node_id: String(input.rollback_node_id) }),
29
29
  ...(input?.lease_proof ? { lease_proof: normalizeLeaseProof(input.lease_proof) } : {}),
30
+ ...(input?.git_worktree ? { git_worktree: normalizeGitWorktreeMetadata(input.git_worktree) } : {}),
30
31
  ...(input?.rationale ? { rationale: String(input.rationale) } : {}),
31
32
  ...(input?.verification_hint ? { verification_hint: normalizeHint(input.verification_hint) } : {}),
32
33
  ...(input?.rollback_hint ? { rollback_hint: normalizeHint(input.rollback_hint) } : {}),
@@ -49,12 +50,14 @@ export function validateAgentPatchEnvelope(envelope) {
49
50
  violations.push('lease_id_missing');
50
51
  if (!envelope.operations.length)
51
52
  violations.push('operations_missing');
52
- if (envelope.source && !['fixture', 'model_authored', 'process_generated', 'zellij_generated'].includes(envelope.source))
53
+ if (envelope.source && !['fixture', 'model_authored', 'process_generated', 'zellij_generated', 'git-worktree-diff'].includes(envelope.source))
53
54
  violations.push('source_invalid');
54
55
  if (envelope.source === 'model_authored' && !hasFiniteNumber(envelope.backend_child_process_id) && !envelope.backend_sdk_thread_id && !envelope.backend_ollama_request_id)
55
56
  violations.push('model_authored_backend_proof_missing');
56
57
  if (envelope.source === 'fixture' && envelope.backend_child_process_id !== undefined)
57
58
  violations.push('fixture_backend_child_process_id_present');
59
+ if (envelope.source === 'git-worktree-diff' && !envelope.git_worktree?.worktree_path)
60
+ violations.push('git_worktree_metadata_missing');
58
61
  for (const operation of envelope.operations) {
59
62
  if (!operation.path || operation.path.includes('\0') || operation.path.startsWith('/') || operation.path.split(/[\\/]/).includes('..')) {
60
63
  violations.push(`invalid_path:${operation.path || 'missing'}`);
@@ -65,8 +68,10 @@ export function validateAgentPatchEnvelope(envelope) {
65
68
  violations.push(`write_content_missing:${operation.path}`);
66
69
  if (operation.op === 'unified_diff' && typeof operation.diff !== 'string')
67
70
  violations.push(`unified_diff_missing:${operation.path}`);
71
+ if (operation.op === 'git_apply_patch' && typeof operation.diff !== 'string')
72
+ violations.push(`git_apply_patch_missing:${operation.path}`);
68
73
  const allowedPaths = envelope.allowed_paths?.length ? envelope.allowed_paths : envelope.lease_proof?.allowed_paths;
69
- if (allowedPaths?.length && !pathAllowedByLease(operation.path, allowedPaths)) {
74
+ if (operation.op !== 'git_apply_patch' && allowedPaths?.length && !pathAllowedByLease(operation.path, allowedPaths)) {
70
75
  violations.push(`lease_path_not_allowed:${operation.path}`);
71
76
  }
72
77
  }
@@ -74,13 +79,13 @@ export function validateAgentPatchEnvelope(envelope) {
74
79
  }
75
80
  function normalizeEnvelopeSource(value) {
76
81
  const text = String(value || '');
77
- return text === 'fixture' || text === 'model_authored' || text === 'process_generated' || text === 'zellij_generated' ? text : null;
82
+ return text === 'fixture' || text === 'model_authored' || text === 'process_generated' || text === 'zellij_generated' || text === 'git-worktree-diff' ? text : null;
78
83
  }
79
84
  function hasFiniteNumber(value) {
80
85
  return value !== null && value !== undefined && value !== '' && Number.isFinite(Number(value));
81
86
  }
82
87
  function normalizeOperation(input) {
83
- const op = input?.op === 'write' ? 'write' : input?.op === 'unified_diff' || input?.op === 'patch' ? 'unified_diff' : 'replace';
88
+ const op = input?.op === 'write' ? 'write' : input?.op === 'git_apply_patch' ? 'git_apply_patch' : input?.op === 'unified_diff' || input?.op === 'patch' ? 'unified_diff' : 'replace';
84
89
  return {
85
90
  op,
86
91
  path: String(input?.path || ''),
@@ -104,6 +109,17 @@ function normalizeLeaseProof(input) {
104
109
  ...(input?.rollback_node_id === undefined ? {} : { rollback_node_id: String(input.rollback_node_id) })
105
110
  };
106
111
  }
112
+ function normalizeGitWorktreeMetadata(input) {
113
+ return {
114
+ main_repo_root: String(input?.main_repo_root || ''),
115
+ worktree_path: String(input?.worktree_path || ''),
116
+ branch: input?.branch == null ? null : String(input.branch),
117
+ base_head: input?.base_head == null ? null : String(input.base_head),
118
+ worktree_head: input?.worktree_head == null ? null : String(input.worktree_head),
119
+ changed_files: Array.isArray(input?.changed_files) ? input.changed_files.map(String) : [],
120
+ diff_bytes: Number(input?.diff_bytes || 0)
121
+ };
122
+ }
107
123
  function normalizeHint(input) {
108
124
  return {
109
125
  ...(input?.command === undefined ? {} : { command: String(input.command) }),
@@ -21,6 +21,7 @@ export async function writeAgentProofEvidence(root, input) {
21
21
  const scheduler = input.scheduler || await readJson(path.join(root, 'agent-scheduler-state.json'), null);
22
22
  const taskGraph = input.partition?.task_graph || await readJson(path.join(root, 'agent-task-graph.json'), null);
23
23
  const parallelWritePolicy = input.parallelWritePolicy || await readJson(path.join(root, 'agent-parallel-write-policy.json'), null);
24
+ const gitWorktreeRuntime = input.gitWorktreeRuntime || await readJson(path.join(root, 'agent-git-worktree-runtime.json'), null);
24
25
  const patchQueue = await readJson(path.join(root, 'agent-patch-queue.json'), null);
25
26
  const patchQueueEvents = await readTextSafe(path.join(root, 'agent-patch-queue-events.jsonl'));
26
27
  const patchMerge = await readJson(path.join(root, 'agent-merge-coordinator-report.json'), null);
@@ -180,6 +181,7 @@ export async function writeAgentProofEvidence(root, input) {
180
181
  ...(noSubagentScalingPolicy?.ok === false ? noSubagentScalingPolicy.blockers || ['no_subagent_scaling_policy_not_ok'] : []),
181
182
  ...(fastModePropagation?.ok === false ? fastModePropagation.blockers || ['fast_mode_propagation_not_ok'] : []),
182
183
  ...(patchSwarm?.ok === false ? patchSwarm.blockers || ['patch_swarm_not_ok'] : []),
184
+ ...(gitWorktreeRuntime?.required === true && gitWorktreeRuntime?.ok === false ? gitWorktreeRuntime.blockers || ['git_worktree_runtime_not_ok'] : []),
183
185
  ...(patchSwarm && !patchQueue ? ['patch_queue_missing'] : []),
184
186
  ...(patchSwarm && !patchMerge ? ['patch_merge_report_missing'] : []),
185
187
  ...(patchSwarm && !patchApplyResults ? ['patch_apply_results_missing'] : []),
@@ -217,6 +219,7 @@ export async function writeAgentProofEvidence(root, input) {
217
219
  // Deployed Core Skill snapshot consulted at route start (read-only; never
218
220
  // confers mutation rights). Null when no snapshot is deployed for this route.
219
221
  selected_core_skill: input.selectedCoreSkill || null,
222
+ git_worktree_runtime: gitWorktreeRuntime,
220
223
  route_blackbox_kind: input.routeBlackboxKind || (realRouteCommandUsed ? 'actual_route_command' : 'generic_agent_route_standin'),
221
224
  real_route_command_used: realRouteCommandUsed,
222
225
  native_cli_session_proof: nativeCliSessionProof ? 'native-cli-session-proof.json' : null,