sneakoscope 2.0.9 → 2.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +8 -4
  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 +21 -8
  8. package/dist/cli/command-registry.js +1 -0
  9. package/dist/commands/doctor.js +18 -1
  10. package/dist/commands/zellij-slot-pane.js +26 -0
  11. package/dist/core/agents/agent-orchestrator.js +198 -7
  12. package/dist/core/agents/agent-role-config.js +92 -0
  13. package/dist/core/agents/native-cli-session-swarm.js +186 -71
  14. package/dist/core/commands/naruto-command.js +59 -4
  15. package/dist/core/doctor/doctor-readiness-matrix.js +6 -0
  16. package/dist/core/fsx.js +1 -1
  17. package/dist/core/hooks-runtime.js +4 -0
  18. package/dist/core/init.js +1 -0
  19. package/dist/core/naruto/naruto-active-pool.js +35 -2
  20. package/dist/core/naruto/naruto-concurrency-governor.js +1 -1
  21. package/dist/core/naruto/naruto-real-worker-child.js +35 -0
  22. package/dist/core/naruto/naruto-real-worker-runtime.js +121 -0
  23. package/dist/core/version.js +1 -1
  24. package/dist/core/zellij/zellij-right-column-manager.js +66 -7
  25. package/dist/core/zellij/zellij-slot-pane-renderer.js +82 -0
  26. package/dist/core/zellij/zellij-ui-mode.js +16 -0
  27. package/dist/core/zellij/zellij-worker-pane-manager.js +38 -8
  28. package/dist/scripts/agent-role-config-repair-check.js +33 -0
  29. package/dist/scripts/git-worktree-integration-primary-check.js +4 -2
  30. package/dist/scripts/git-worktree-integration-primary-runtime-check.js +20 -0
  31. package/dist/scripts/mutation-callsite-coverage-check.js +2 -1
  32. package/dist/scripts/naruto-extreme-parallelism-check.js +1 -1
  33. package/dist/scripts/naruto-extreme-parallelism-real-check.js +42 -0
  34. package/dist/scripts/naruto-real-active-pool-check.js +3 -2
  35. package/dist/scripts/naruto-real-active-pool-runtime-check.js +53 -0
  36. package/dist/scripts/naruto-zellij-dynamic-right-column-check.js +29 -2
  37. package/dist/scripts/readme-architecture-imagegen-official-check.js +4 -3
  38. package/dist/scripts/release-check-dynamic-execute.js +27 -1
  39. package/dist/scripts/release-check-dynamic.js +38 -11
  40. package/dist/scripts/release-check-stamp.js +7 -2
  41. package/dist/scripts/release-dynamic-performance-check.js +31 -1
  42. package/dist/scripts/release-gate-existence-audit.js +29 -33
  43. package/dist/scripts/release-readiness-report.js +13 -2
  44. package/dist/scripts/zellij-right-column-geometry-proof.js +155 -22
  45. package/dist/scripts/zellij-right-column-headless-overflow-check.js +22 -0
  46. package/dist/scripts/zellij-right-column-manager-check.js +4 -4
  47. package/dist/scripts/zellij-slot-only-ui-check.js +22 -0
  48. package/dist/scripts/zellij-slot-pane-renderer-check.js +38 -0
  49. package/package.json +12 -4
package/README.md CHANGED
@@ -16,15 +16,19 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
16
16
 
17
17
  ## Current Release
18
18
 
19
- SKS **2.0.9** 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.
19
+ SKS **2.0.10** 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`.
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.
25
+ - Visible Zellij reservations are capped before pane launch so concurrent worker starts cannot over-open the right column.
26
+ - Git worktree integration now proves the primary repo receives validated worktree diffs, with rollback hash evidence recorded around the apply step.
27
+ - Agent role config repair detects stale generated role files and rewrites structured GPT-5.5-compatible configs atomically.
28
+ - Release gates now include slot-only UI, compact slot renderer, headless overflow, role-config repair, worktree primary-runtime, real active-pool, extreme real parallelism, and real right-column geometry checks.
29
+ - Release audit, dynamic selection, and stamp hashing use `release-gates.v2.json` as the manifest source of truth.
23
30
  - 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
31
  - 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.
28
32
  - 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.
29
33
  - 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.
30
34
  - 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.9"
79
+ version = "2.0.10"
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.9"
3
+ version = "2.0.10"
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.9"),
7
+ Some("--version") => println!("sks-rs 2.0.10"),
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.9",
5
- "source_digest": "a2c7c47838f03483ee3a406fe6435876148d688fa16037d1b4eab45da1f930c4",
6
- "source_file_count": 2017,
7
- "built_at_source_time": 1780749751025
4
+ "package_version": "2.0.10",
5
+ "source_digest": "ee8d0f4a75b8f5aeb6bfa26042f194cba01728768422448bf9b1e54748007137",
6
+ "source_file_count": 2030,
7
+ "built_at_source_time": 1780813031543
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.9';
2
+ const FAST_PACKAGE_VERSION = '2.0.10';
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.9",
4
- "package_version": "2.0.9",
3
+ "version": "2.0.10",
4
+ "package_version": "2.0.10",
5
5
  "typescript": true,
6
6
  "mjs_runtime_files": 0,
7
- "compiled_file_count": 1079,
8
- "compiled_js_count": 1079,
7
+ "compiled_file_count": 1092,
8
+ "compiled_js_count": 1092,
9
9
  "compiled_dts_count": 0,
10
- "source_digest": "a2c7c47838f03483ee3a406fe6435876148d688fa16037d1b4eab45da1f930c4",
11
- "source_file_count": 2017,
12
- "source_files_hash": "b69bf6184e62a1136caf9dc353eea79dcae63e3ba260a10fbc8eb6a38de7541a",
13
- "source_list_hash": "b69bf6184e62a1136caf9dc353eea79dcae63e3ba260a10fbc8eb6a38de7541a",
10
+ "source_digest": "ee8d0f4a75b8f5aeb6bfa26042f194cba01728768422448bf9b1e54748007137",
11
+ "source_file_count": 2030,
12
+ "source_files_hash": "26a7831ee3d5b0909718d62eefcb828bfc074c18f454d5f46f5ebdf2ded482f6",
13
+ "source_list_hash": "26a7831ee3d5b0909718d62eefcb828bfc074c18f454d5f46f5ebdf2ded482f6",
14
14
  "src_mjs_runtime_files": 0,
15
15
  "dist_stamp_schema": "sks.dist-build-stamp.v1",
16
16
  "files": [
@@ -101,6 +101,7 @@
101
101
  "commands/versioning.js",
102
102
  "commands/wiki.js",
103
103
  "commands/zellij-lane.js",
104
+ "commands/zellij-slot-pane.js",
104
105
  "commands/zellij.js",
105
106
  "core/agents/agent-central-ledger.js",
106
107
  "core/agents/agent-cleanup-executor.js",
@@ -132,6 +133,7 @@
132
133
  "core/agents/agent-plan.js",
133
134
  "core/agents/agent-proof-evidence.js",
134
135
  "core/agents/agent-recursion-guard.js",
136
+ "core/agents/agent-role-config.js",
135
137
  "core/agents/agent-roster.js",
136
138
  "core/agents/agent-runner-codex-exec.js",
137
139
  "core/agents/agent-runner-fake.js",
@@ -433,6 +435,8 @@
433
435
  "core/naruto/naruto-gpt-final-pack.js",
434
436
  "core/naruto/naruto-parallel-patch-apply.js",
435
437
  "core/naruto/naruto-patch-transaction-batch.js",
438
+ "core/naruto/naruto-real-worker-child.js",
439
+ "core/naruto/naruto-real-worker-runtime.js",
436
440
  "core/naruto/naruto-role-policy.js",
437
441
  "core/naruto/naruto-verification-dag.js",
438
442
  "core/naruto/naruto-verification-pool.js",
@@ -634,6 +638,8 @@
634
638
  "core/zellij/zellij-right-column-layout-proof.js",
635
639
  "core/zellij/zellij-right-column-manager.js",
636
640
  "core/zellij/zellij-screen-proof.js",
641
+ "core/zellij/zellij-slot-pane-renderer.js",
642
+ "core/zellij/zellij-ui-mode.js",
637
643
  "core/zellij/zellij-worker-pane-manager.js",
638
644
  "scripts/agent-ast-aware-work-graph-check.js",
639
645
  "scripts/agent-backfill-replenishment-check.js",
@@ -688,6 +694,7 @@
688
694
  "scripts/agent-real-codex-parallel-workers-5-check.js",
689
695
  "scripts/agent-real-codex-parallel-workers-check.js",
690
696
  "scripts/agent-real-codex-patch-envelope-smoke.js",
697
+ "scripts/agent-role-config-repair-check.js",
691
698
  "scripts/agent-rollback-command-check.js",
692
699
  "scripts/agent-route-blackbox-lib.js",
693
700
  "scripts/agent-route-truth-backfill-check.js",
@@ -846,6 +853,7 @@
846
853
  "scripts/git-worktree-dirty-lock-check.js",
847
854
  "scripts/git-worktree-dirty-main-detection-check.js",
848
855
  "scripts/git-worktree-integration-primary-check.js",
856
+ "scripts/git-worktree-integration-primary-runtime-check.js",
849
857
  "scripts/git-worktree-manager-check.js",
850
858
  "scripts/git-worktree-manifest-append-check.js",
851
859
  "scripts/git-worktree-merge-queue-check.js",
@@ -925,10 +933,12 @@
925
933
  "scripts/naruto-active-pool-check.js",
926
934
  "scripts/naruto-concurrency-governor-check.js",
927
935
  "scripts/naruto-extreme-parallelism-check.js",
936
+ "scripts/naruto-extreme-parallelism-real-check.js",
928
937
  "scripts/naruto-gpt-final-pack-check.js",
929
938
  "scripts/naruto-parallel-patch-apply-check.js",
930
939
  "scripts/naruto-readonly-routing-check.js",
931
940
  "scripts/naruto-real-active-pool-check.js",
941
+ "scripts/naruto-real-active-pool-runtime-check.js",
932
942
  "scripts/naruto-real-local-gpt-final-smoke.js",
933
943
  "scripts/naruto-role-distribution-check.js",
934
944
  "scripts/naruto-shadow-clone-swarm-check.js",
@@ -1086,8 +1096,11 @@
1086
1096
  "scripts/zellij-real-session-heartbeat-check.js",
1087
1097
  "scripts/zellij-real-session-launch-check.js",
1088
1098
  "scripts/zellij-right-column-geometry-proof.js",
1099
+ "scripts/zellij-right-column-headless-overflow-check.js",
1089
1100
  "scripts/zellij-right-column-manager-check.js",
1090
1101
  "scripts/zellij-screen-proof-check.js",
1102
+ "scripts/zellij-slot-only-ui-check.js",
1103
+ "scripts/zellij-slot-pane-renderer-check.js",
1091
1104
  "scripts/zellij-spawn-on-demand-layout-check.js",
1092
1105
  "scripts/zellij-ui-design-check.js",
1093
1106
  "scripts/zellij-worker-pane-manager-check.js",
@@ -104,6 +104,7 @@ export const COMMANDS = {
104
104
  hermes: entry('labs', 'Create Hermes Agent skill package', 'dist/commands/hermes.js', directCommand(() => import('../commands/hermes.js'), 'dist/commands/hermes.js')),
105
105
  tmux: entry('beta', 'Show removed-runtime migration notice', 'dist/commands/tmux.js', directCommand(() => import('../commands/tmux.js'), 'dist/commands/tmux.js')),
106
106
  'zellij-lane': entry('beta', 'Render a Zellij lane frame for SKS sessions', 'dist/commands/zellij-lane.js', directCommand(() => import('../commands/zellij-lane.js'), 'dist/commands/zellij-lane.js')),
107
+ 'zellij-slot-pane': entry('beta', 'Render a compact Zellij worker slot pane', 'dist/commands/zellij-slot-pane.js', directCommand(() => import('../commands/zellij-slot-pane.js'), 'dist/commands/zellij-slot-pane.js')),
107
108
  zellij: entry('beta', 'Inspect Zellij runtime status and explain repair (no auto-install)', 'dist/commands/zellij.js', directCommand(() => import('../commands/zellij.js'), 'dist/commands/zellij.js')),
108
109
  mad: entry('beta', 'MAD-SKS Zellij permission launcher', 'dist/commands/mad-sks.js', directCommand(() => import('../commands/mad-sks.js'), 'dist/commands/mad-sks.js')),
109
110
  'mad-sks': entry('beta', 'MAD-SKS scoped permission modifier', 'dist/commands/mad-sks.js', directCommand(() => import('../commands/mad-sks.js'), 'dist/commands/mad-sks.js')),
@@ -19,6 +19,7 @@ import { repairCodexAppFastUi } from '../core/codex-app/codex-app-fast-ui-repair
19
19
  import { resolveProviderContext } from '../core/provider/provider-context.js';
20
20
  import { readLocalModelConfig } from '../core/agents/ollama-worker-config.js';
21
21
  import { runSksUpdateNow } from '../core/update-check.js';
22
+ import { repairAgentRoleConfigs } from '../core/agents/agent-role-config.js';
22
23
  export async function run(_command, args = []) {
23
24
  const doctorFix = flag(args, '--fix');
24
25
  let setupRepair = null;
@@ -151,6 +152,20 @@ export async function run(_command, args = []) {
151
152
  const zellij = await checkZellijCapability({ root, require: process.env.SKS_REQUIRE_ZELLIJ === '1' });
152
153
  const localModel = await readLocalModelConfig().catch(() => null);
153
154
  const permissionProfiles = await inventoryCodexPermissionProfiles(root, { writeReport: true });
155
+ const agentRoleConfigRepair = await repairAgentRoleConfigs({
156
+ root,
157
+ apply: doctorFix,
158
+ reportPath: `${root}/.sneakoscope/reports/agent-role-config-repair.json`
159
+ }).catch((err) => ({
160
+ schema: 'sks.agent-role-config-repair.v1',
161
+ ok: false,
162
+ apply: doctorFix,
163
+ missing: [],
164
+ existing: [],
165
+ created: [],
166
+ warnings_suppressed: false,
167
+ blockers: [err?.message || String(err)]
168
+ }));
154
169
  const globalSksInstallCleanup = flag(args, '--fix') && !flag(args, '--local-only')
155
170
  ? await cleanDuplicateGlobalSksInstalls({ root, fix: true }).catch((err) => ({ schema: 'sks.global-sks-install-cleanup.v1', ok: false, fix: true, error: err?.message || String(err), blockers: ['global_sks_install_cleanup_exception'] }))
156
171
  : null;
@@ -166,6 +181,7 @@ export async function run(_command, args = []) {
166
181
  require_codex_doctor: flag(args, '--fix') || flag(args, '--require-actual-codex'),
167
182
  zellij,
168
183
  local_model: localModel,
184
+ agent_role_config: agentRoleConfigRepair,
169
185
  repair: configRepair,
170
186
  codex_app_ui: codexAppUi,
171
187
  require_codex_cli_config_load: flag(args, '--fix') || flag(args, '--require-actual-codex'),
@@ -191,6 +207,7 @@ export async function run(_command, args = []) {
191
207
  codex_doctor_diff: codexDoctorDiff,
192
208
  zellij,
193
209
  local_model: localModel,
210
+ agent_role_config: agentRoleConfigRepair,
194
211
  zellij_readiness: zellijReadiness,
195
212
  codex_permission_profiles: permissionProfiles,
196
213
  imagegen: {
@@ -201,7 +218,7 @@ export async function run(_command, args = []) {
201
218
  ready,
202
219
  sneakoscope: { ok: await exists(`${root}/.sneakoscope`) },
203
220
  package: { bytes: pkgBytes, human: formatBytes(pkgBytes) },
204
- repair: { sks_update: sksUpdate, setup: setupRepair, codex_config: configRepair, migration_journal: migrationJournal, global_sks_installs: globalSksInstallCleanup }
221
+ repair: { sks_update: sksUpdate, setup: setupRepair, codex_config: configRepair, migration_journal: migrationJournal, global_sks_installs: globalSksInstallCleanup, agent_role_config: agentRoleConfigRepair }
205
222
  };
206
223
  if (flag(args, '--json')) {
207
224
  printJson(result);
@@ -0,0 +1,26 @@
1
+ import { renderZellijSlotPaneFromArtifacts } from '../core/zellij/zellij-slot-pane-renderer.js';
2
+ export async function run(_command = 'zellij-slot-pane', args = []) {
3
+ const artifactDir = readOption(args, '--artifact-dir', process.cwd()) || process.cwd();
4
+ const slotId = readOption(args, '--slot', 'slot-001') || 'slot-001';
5
+ const generationIndex = Number(readOption(args, '--generation', '1') || 1);
6
+ const backend = readOption(args, '--backend', null);
7
+ const role = readOption(args, '--role', null);
8
+ const mode = readOption(args, '--mode', 'compact-slots');
9
+ const watch = hasFlag(args, '--watch');
10
+ const intervalMs = Math.max(250, Number(readOption(args, '--interval-ms', '1000') || 1000));
11
+ for (;;) {
12
+ const text = await renderZellijSlotPaneFromArtifacts({ artifactDir, slotId, generationIndex, backend, role, mode });
13
+ process.stdout.write('\x1Bc' + text + '\n');
14
+ if (!watch)
15
+ break;
16
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
17
+ }
18
+ }
19
+ function readOption(args, name, fallback) {
20
+ const index = args.indexOf(name);
21
+ return index >= 0 && args[index + 1] ? String(args[index + 1]) : fallback;
22
+ }
23
+ function hasFlag(args, flag) {
24
+ return args.includes(flag);
25
+ }
26
+ //# sourceMappingURL=zellij-slot-pane.js.map
@@ -1,6 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import { createMission, missionDir, setCurrent } from '../mission.js';
3
- import { nowIso, readJson, readText, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
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
6
  import { initializeAgentCentralLedger, appendAgentLedgerEvent, compactAgentLedger } from './agent-central-ledger.js';
@@ -56,6 +56,8 @@ import { allocateWorkerWorktree } from '../git/git-worktree-manager.js';
56
56
  import { exportGitWorktreeDiff } from '../git/git-worktree-diff.js';
57
57
  import { buildGitWorktreePatchEnvelope } from '../git/git-worktree-patch-envelope.js';
58
58
  import { cleanupGitWorktree } from '../git/git-worktree-cleanup.js';
59
+ import { createGitIntegrationWorktree } from '../git/git-integration-worktree.js';
60
+ import { applyGitWorktreeMergeQueue } from '../git/git-worktree-merge-queue.js';
59
61
  export async function runNativeAgentOrchestrator(opts = {}) {
60
62
  const root = path.resolve(opts.root || process.cwd());
61
63
  const prompt = String(opts.prompt || 'Native agent run');
@@ -753,9 +755,18 @@ async function runAgentPatchSwarmRuntime(root, ledgerRoot, input) {
753
755
  }
754
756
  }
755
757
  const pendingEntries = queueStore.queue.queued();
756
- const merge = coordinateAgentPatchMerge(pendingEntries);
758
+ const worktreeEntries = pendingEntries.filter((entry) => entry.envelope?.source === 'git-worktree-diff');
759
+ const normalEntries = pendingEntries.filter((entry) => entry.envelope?.source !== 'git-worktree-diff');
760
+ let worktreeMergeReport = null;
761
+ const worktreeApplyResults = [];
762
+ if (worktreeEntries.length) {
763
+ worktreeMergeReport = await runGitWorktreeIntegrationPrimary(root, ledgerRoot, input.missionId, worktreeEntries, queueStore);
764
+ for (const row of worktreeMergeReport.apply_results || [])
765
+ worktreeApplyResults.push(row);
766
+ }
767
+ const merge = coordinateAgentPatchMerge(normalEntries);
757
768
  await writeAgentMergeCoordinatorArtifacts(ledgerRoot, merge);
758
- const conflictRebase = await executeAgentPatchConflictRebase(root, pendingEntries, merge, { dryRun: input.dryRun, artifactsDir: ledgerRoot });
769
+ const conflictRebase = await executeAgentPatchConflictRebase(root, normalEntries, merge, { dryRun: input.dryRun, artifactsDir: ledgerRoot });
759
770
  merge.conflict_rebase_results = 'agent-patch-conflict-rebase-results.json';
760
771
  merge.rebase_success_count = conflictRebase.succeeded_entry_ids.length;
761
772
  merge.rebase_blocker_count = conflictRebase.blockers.length;
@@ -765,11 +776,11 @@ async function runAgentPatchSwarmRuntime(root, ledgerRoot, input) {
765
776
  merge.unresolved_conflict_entry_ids = [...conflictedEntryIds];
766
777
  merge.ok = conflictedEntryIds.size === 0 && (conflictRebase.failed_entry_ids || []).length === 0 && (conflictRebase.blocked_entry_ids || []).length === 0;
767
778
  merge.blockers = merge.ok ? [] : merge.blockers || [];
768
- for (const entry of pendingEntries) {
779
+ for (const entry of normalEntries) {
769
780
  if (conflictedEntryIds.has(entry.id))
770
781
  await queueStore.markConflicted(entry.id, merge.blockers || ['patch_conflict']);
771
782
  }
772
- const disjointEntries = pendingEntries.filter((entry) => !conflictedEntryIds.has(entry.id));
783
+ const disjointEntries = normalEntries.filter((entry) => !conflictedEntryIds.has(entry.id));
773
784
  const startedAt = nowIso();
774
785
  for (const entryId of rebaseSucceededEntryIds) {
775
786
  await queueStore.markApplying(entryId);
@@ -797,6 +808,7 @@ async function runAgentPatchSwarmRuntime(root, ledgerRoot, input) {
797
808
  return { entry_id: entry.id, started_at, finished_at, ...applyResult };
798
809
  }));
799
810
  const applyResults = [
811
+ ...worktreeApplyResults,
800
812
  ...parallelApplyResults,
801
813
  ...(conflictRebase.apply_results || []).map((row) => ({ entry_id: row.entry_id, started_at: row.apply_started_at || nowIso(), finished_at: row.apply_ended_at || nowIso(), ...row }))
802
814
  ];
@@ -912,7 +924,8 @@ async function runAgentPatchSwarmRuntime(root, ledgerRoot, input) {
912
924
  conflictRebase,
913
925
  verificationRollbackDag: input.verificationRollbackDag,
914
926
  gptFinalArbiter: input.gptFinalArbiter,
915
- finalGptPatchStage: input.finalGptPatchStage
927
+ finalGptPatchStage: input.finalGptPatchStage,
928
+ worktreeMergeReport
916
929
  };
917
930
  const initialProof = buildAgentPatchProof(proofInput);
918
931
  await writeJsonAtomic(path.join(ledgerRoot, 'agent-patch-proof.json'), initialProof);
@@ -942,6 +955,8 @@ async function runAgentPatchSwarmRuntime(root, ledgerRoot, input) {
942
955
  apply_finished_at: finishedAt,
943
956
  apply_latency_ms: Math.max(0, Date.parse(finishedAt) - Date.parse(startedAt)),
944
957
  parallel_apply_count: parallelEntries.length,
958
+ worktree_integration_primary_count: worktreeEntries.length,
959
+ worktree_merge_queue: worktreeMergeReport,
945
960
  parallel_apply_groups: merge.parallel_apply_groups || [],
946
961
  serial_merge_groups: merge.serial_merge_groups || [],
947
962
  conflict_rebase: {
@@ -971,7 +986,8 @@ async function runAgentPatchSwarmRuntime(root, ledgerRoot, input) {
971
986
  proof: 'agent-patch-proof.json',
972
987
  transaction_journal: 'agent-patch-transaction-journal.jsonl',
973
988
  transaction_journal_summary: 'agent-patch-transaction-journal-summary.json',
974
- conflict_rebase: 'agent-patch-conflict-rebase-results.json'
989
+ conflict_rebase: 'agent-patch-conflict-rebase-results.json',
990
+ git_worktree_merge_queue: worktreeMergeReport ? 'git-worktree-merge-queue-report.json' : null
975
991
  },
976
992
  blockers
977
993
  };
@@ -985,6 +1001,181 @@ async function runAgentPatchSwarmRuntime(root, ledgerRoot, input) {
985
1001
  await writeJsonAtomic(path.join(ledgerRoot, 'agent-patch-swarm-runtime.json'), report);
986
1002
  return report;
987
1003
  }
1004
+ async function runGitWorktreeIntegrationPrimary(root, ledgerRoot, missionId, entries, queueStore) {
1005
+ const diffs = entries.map((entry) => gitWorktreeDiffFromQueueEntry(entry)).filter(Boolean);
1006
+ const repoRoot = diffs[0]?.main_repo_root || root;
1007
+ const baseRef = diffs.find((diff) => diff.base_head)?.base_head || undefined;
1008
+ const integration = await createGitIntegrationWorktree({ repoRoot, missionId, ...(baseRef ? { baseRef } : {}) });
1009
+ const applyResults = [];
1010
+ if (!integration.ok) {
1011
+ for (const entry of entries) {
1012
+ await queueStore.markConflicted(entry.id, integration.blockers || ['git_worktree_integration_allocation_failed']);
1013
+ applyResults.push({
1014
+ entry_id: entry.id,
1015
+ started_at: nowIso(),
1016
+ finished_at: nowIso(),
1017
+ ok: false,
1018
+ changed_files: entry.write_paths || entry.envelope?.git_worktree?.changed_files || [],
1019
+ verification: { checks: ['git-worktree-integration-primary'] },
1020
+ violations: integration.blockers || ['git_worktree_integration_allocation_failed']
1021
+ });
1022
+ }
1023
+ const blockedReport = {
1024
+ schema: 'sks.git-worktree-integration-primary-runtime.v1',
1025
+ ok: false,
1026
+ generated_at: nowIso(),
1027
+ integration,
1028
+ integration_worktree_path: integration.worktree_path || null,
1029
+ applied_entry_ids: [],
1030
+ conflicted_entry_ids: entries.map((entry) => entry.id),
1031
+ apply_results: applyResults,
1032
+ blockers: integration.blockers || ['git_worktree_integration_allocation_failed']
1033
+ };
1034
+ await writeJsonAtomic(path.join(ledgerRoot, 'git-worktree-merge-queue-report.json'), blockedReport);
1035
+ return blockedReport;
1036
+ }
1037
+ const startedAt = nowIso();
1038
+ for (const entry of entries)
1039
+ await queueStore.markApplying(entry.id);
1040
+ const queueReport = await applyGitWorktreeMergeQueue({
1041
+ integrationWorktreePath: integration.worktree_path,
1042
+ diffs
1043
+ });
1044
+ const rollbackPlan = queueReport.ok ? await captureGitWorktreeRollbackPlan(repoRoot, queueReport.changed_files || []) : { ok: false, rollback: [], blockers: ['git_worktree_integration_prevalidation_failed'] };
1045
+ const mainApplyReport = queueReport.ok && rollbackPlan.ok
1046
+ ? await applyGitWorktreeMergeQueue({
1047
+ integrationWorktreePath: repoRoot,
1048
+ diffs
1049
+ })
1050
+ : null;
1051
+ const rollbackEvidence = mainApplyReport?.ok
1052
+ ? await completeGitWorktreeRollbackPlan(repoRoot, rollbackPlan.rollback)
1053
+ : rollbackPlan;
1054
+ const finishedAt = nowIso();
1055
+ const conflictsByWorker = new Set([
1056
+ ...(queueReport.conflicts || []).map((row) => String(row.worker_id || row.workerId || '')),
1057
+ ...(mainApplyReport?.conflicts || []).map((row) => String(row.worker_id || row.workerId || ''))
1058
+ ]);
1059
+ const appliedEntryIds = [];
1060
+ const conflictedEntryIds = [];
1061
+ for (const entry of entries) {
1062
+ const workerId = String(entry.envelope?.git_worktree?.worker_id || entry.envelope?.agent_id || entry.agent_id || '');
1063
+ const changedFiles = entry.write_paths || entry.envelope?.git_worktree?.changed_files || [];
1064
+ const ok = queueReport.ok && mainApplyReport?.ok === true && rollbackEvidence.ok === true && !conflictsByWorker.has(workerId);
1065
+ if (ok) {
1066
+ await queueStore.markApplied(entry.id);
1067
+ appliedEntryIds.push(entry.id);
1068
+ }
1069
+ else {
1070
+ await queueStore.markConflicted(entry.id, queueReport.blockers || ['git_worktree_merge_failed']);
1071
+ conflictedEntryIds.push(entry.id);
1072
+ }
1073
+ applyResults.push({
1074
+ entry_id: entry.id,
1075
+ started_at: startedAt,
1076
+ finished_at: finishedAt,
1077
+ ok,
1078
+ changed_files: changedFiles,
1079
+ rollback: ok ? rollbackEvidence.rollback.filter((row) => changedFiles.includes(row.path)) : [],
1080
+ rollback_digest: ok ? `git-worktree-integration:${entry.id}:${sha256(JSON.stringify(rollbackEvidence.rollback.filter((row) => changedFiles.includes(row.path))))}` : null,
1081
+ verification: { checks: ['git-worktree-integration-primary', 'git-apply-3way', 'main-repo-apply', 'rollback-hashes'] },
1082
+ violations: ok ? [] : [...(queueReport.blockers || []), ...(mainApplyReport?.blockers || []), ...(rollbackEvidence.blockers || []), 'git_worktree_main_repo_apply_failed'].filter(Boolean)
1083
+ });
1084
+ }
1085
+ const reportBlockers = [...(queueReport.blockers || []), ...(mainApplyReport?.blockers || []), ...(rollbackEvidence.blockers || [])];
1086
+ const report = {
1087
+ schema: 'sks.git-worktree-integration-primary-runtime.v1',
1088
+ ok: reportBlockers.length === 0 && appliedEntryIds.length === entries.length,
1089
+ generated_at: nowIso(),
1090
+ integration,
1091
+ integration_worktree_path: integration.worktree_path,
1092
+ applied_entry_ids: appliedEntryIds,
1093
+ conflicted_entry_ids: conflictedEntryIds,
1094
+ merge_queue: queueReport,
1095
+ main_repo_apply: mainApplyReport,
1096
+ rollback_evidence: rollbackEvidence,
1097
+ apply_results: applyResults,
1098
+ blockers: reportBlockers
1099
+ };
1100
+ await writeJsonAtomic(path.join(ledgerRoot, 'git-worktree-merge-queue-report.json'), report);
1101
+ return report;
1102
+ }
1103
+ async function captureGitWorktreeRollbackPlan(root, changedFiles) {
1104
+ const rootResolved = path.resolve(root);
1105
+ const rollback = [];
1106
+ const blockers = [];
1107
+ for (const file of [...new Set(changedFiles.map((row) => String(row || '').trim()).filter(Boolean))]) {
1108
+ const rel = normalizeWorktreeRelPath(file);
1109
+ const absolute = path.resolve(rootResolved, rel);
1110
+ if (!absolute.startsWith(rootResolved + path.sep)) {
1111
+ blockers.push(`git_worktree_rollback_path_outside_root:${rel}`);
1112
+ continue;
1113
+ }
1114
+ const beforeExists = await exists(absolute);
1115
+ const before = beforeExists ? await readText(absolute, '') : '';
1116
+ rollback.push({
1117
+ path: rel,
1118
+ existed: beforeExists,
1119
+ sha256_before: beforeExists ? sha256(String(before)) : null,
1120
+ content_before: beforeExists ? String(before) : null
1121
+ });
1122
+ }
1123
+ return { ok: blockers.length === 0, rollback, blockers };
1124
+ }
1125
+ async function completeGitWorktreeRollbackPlan(root, rollback) {
1126
+ const rootResolved = path.resolve(root);
1127
+ const blockers = [];
1128
+ const completed = [];
1129
+ for (const row of rollback) {
1130
+ const rel = normalizeWorktreeRelPath(row.path);
1131
+ const absolute = path.resolve(rootResolved, rel);
1132
+ if (!absolute.startsWith(rootResolved + path.sep)) {
1133
+ blockers.push(`git_worktree_rollback_path_outside_root:${rel}`);
1134
+ continue;
1135
+ }
1136
+ const afterExists = await exists(absolute);
1137
+ if (!afterExists) {
1138
+ blockers.push(`git_worktree_rollback_after_missing:${rel}`);
1139
+ completed.push({ ...row, path: rel, sha256_after: null });
1140
+ continue;
1141
+ }
1142
+ const after = await readText(absolute, '');
1143
+ completed.push({
1144
+ ...row,
1145
+ path: rel,
1146
+ sha256_after: sha256(String(after))
1147
+ });
1148
+ }
1149
+ return { ok: blockers.length === 0, rollback: completed, blockers };
1150
+ }
1151
+ function normalizeWorktreeRelPath(file) {
1152
+ return String(file || '').replace(/\\/g, '/').replace(/^\/+/, '');
1153
+ }
1154
+ function gitWorktreeDiffFromQueueEntry(entry) {
1155
+ const envelope = entry?.envelope || {};
1156
+ const meta = envelope.git_worktree || {};
1157
+ const operation = Array.isArray(envelope.operations) ? envelope.operations.find((row) => row?.op === 'git_apply_patch') : null;
1158
+ const diff = String(operation?.diff || '');
1159
+ return {
1160
+ schema: 'sks.git-worktree-diff.v1',
1161
+ ok: true,
1162
+ generated_at: nowIso(),
1163
+ mission_id: String(envelope.mission_id || ''),
1164
+ worker_id: String(envelope.agent_id || entry.agent_id || entry.id),
1165
+ main_repo_root: String(meta.main_repo_root || ''),
1166
+ worktree_path: String(meta.worktree_path || ''),
1167
+ branch: meta.branch == null ? null : String(meta.branch),
1168
+ base_head: meta.base_head == null ? null : String(meta.base_head),
1169
+ worktree_head: meta.worktree_head == null ? null : String(meta.worktree_head),
1170
+ status_porcelain: '',
1171
+ changed_files: Array.isArray(meta.changed_files) ? meta.changed_files.map(String) : entry.write_paths || [],
1172
+ untracked_files: [],
1173
+ diff,
1174
+ diff_bytes: Buffer.byteLength(diff),
1175
+ clean: diff.trim().length === 0,
1176
+ blockers: []
1177
+ };
1178
+ }
988
1179
  function normalizeDesiredWorkItemCount(value, minimumValue, targetActiveSlots) {
989
1180
  const parsed = Number(value);
990
1181
  const minimum = Number(minimumValue);
@@ -0,0 +1,92 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { ensureDir, nowIso, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
4
+ import { REQUIRED_CODEX_MODEL } from '../codex-model-guard.js';
5
+ export const AGENT_ROLE_CONFIG_REPAIR_SCHEMA = 'sks.agent-role-config-repair.v1';
6
+ const SKS_OWNED_AGENT_CONFIGS = new Map([
7
+ ['analysis-scout.toml', roleConfig('analysis_scout', 'Read-only SKS analysis scout retained for stale Codex agent-role config repair.', 'read-only')],
8
+ ['native-agent-intake.toml', roleConfig('native_agent', 'Read-only Team native agent for repository/docs/tests/API/risk slices.', 'read-only')],
9
+ ['team-consensus.toml', roleConfig('team_consensus', 'Planning and debate specialist for SKS Team mode.', 'read-only')],
10
+ ['implementation-worker.toml', roleConfig('implementation_worker', 'Implementation specialist for bounded SKS Team write sets.', 'workspace-write')],
11
+ ['db-safety-reviewer.toml', roleConfig('db_safety_reviewer', 'Read-only database safety reviewer for SQL, migrations, Supabase, and rollback safety.', 'read-only')],
12
+ ['qa-reviewer.toml', roleConfig('qa_reviewer', 'Strict read-only verification reviewer for correctness, regressions, and final evidence.', 'read-only')]
13
+ ]);
14
+ export async function repairAgentRoleConfigs(input) {
15
+ const root = path.resolve(input.root);
16
+ const codexHome = input.codexHome || process.env.CODEX_HOME || path.join(process.env.HOME || '', '.codex');
17
+ const candidates = [path.join(root, '.codex', 'agents'), path.join(codexHome, 'agents')];
18
+ const missing = [];
19
+ const stale = [];
20
+ const created = [];
21
+ const repaired = [];
22
+ const existing = [];
23
+ for (const [file, config] of SKS_OWNED_AGENT_CONFIGS) {
24
+ const found = candidates.find((dir) => fs.existsSync(path.join(dir, file)));
25
+ if (found) {
26
+ const foundPath = path.join(found, file);
27
+ const text = fs.readFileSync(foundPath, 'utf8');
28
+ if (isValidRoleConfig(text, config)) {
29
+ existing.push(path.relative(root, foundPath) || foundPath);
30
+ continue;
31
+ }
32
+ stale.push(file);
33
+ if (input.apply) {
34
+ const target = foundPath.startsWith(path.join(root, '.codex', 'agents')) ? foundPath : path.join(root, '.codex', 'agents', file);
35
+ await ensureDir(path.dirname(target));
36
+ await writeTextAtomic(target, config.content);
37
+ repaired.push(path.relative(root, target));
38
+ }
39
+ continue;
40
+ }
41
+ missing.push(file);
42
+ if (input.apply) {
43
+ const target = path.join(root, '.codex', 'agents', file);
44
+ await ensureDir(path.dirname(target));
45
+ await writeTextAtomic(target, config.content);
46
+ created.push(path.relative(root, target));
47
+ }
48
+ }
49
+ const requiredFixes = missing.length + stale.length;
50
+ const appliedFixes = created.length + repaired.length;
51
+ const report = {
52
+ schema: AGENT_ROLE_CONFIG_REPAIR_SCHEMA,
53
+ generated_at: nowIso(),
54
+ ok: input.apply ? requiredFixes === appliedFixes : true,
55
+ apply: input.apply === true,
56
+ missing,
57
+ stale,
58
+ existing,
59
+ created,
60
+ repaired,
61
+ warnings_suppressed: true,
62
+ blockers: input.apply && requiredFixes !== appliedFixes ? ['agent_role_config_repair_incomplete'] : []
63
+ };
64
+ if (input.reportPath)
65
+ await writeJsonAtomic(input.reportPath, report);
66
+ return report;
67
+ }
68
+ function roleConfig(name, description, sandbox) {
69
+ const content = [
70
+ `name = "${name}"`,
71
+ `description = "${description}"`,
72
+ `model = "${REQUIRED_CODEX_MODEL}"`,
73
+ 'model_reasoning_effort = "medium"',
74
+ `sandbox_mode = "${sandbox}"`,
75
+ 'approval_policy = "never"',
76
+ 'developer_instructions = """',
77
+ `You are the SKS ${name} role.`,
78
+ sandbox === 'read-only' ? 'Do not edit files.' : 'Only edit the bounded files assigned by the parent orchestrator.',
79
+ 'Return concise source-backed findings and LIVE_EVENT lines when applicable.',
80
+ '"""',
81
+ ''
82
+ ].join('\n');
83
+ return { name, sandbox, content };
84
+ }
85
+ function isValidRoleConfig(text, config) {
86
+ return text.includes(`name = "${config.name}"`)
87
+ && text.includes('description = "')
88
+ && text.includes(`model = "${REQUIRED_CODEX_MODEL}"`)
89
+ && text.includes(`sandbox_mode = "${config.sandbox}"`)
90
+ && text.includes('developer_instructions = """');
91
+ }
92
+ //# sourceMappingURL=agent-role-config.js.map