opencode-swarm 7.107.6 → 7.108.0

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 (76) hide show
  1. package/dist/cli/{capability-probe-wsjzcp48.js → capability-probe-sh9bwh39.js} +2 -1
  2. package/dist/cli/{config-doctor-kdq3vae4.js → config-doctor-q354tb2w.js} +2 -2
  3. package/dist/cli/core-vev13ej2.js +34 -0
  4. package/dist/cli/{curator-drift-ed7p5mfy.js → curator-drift-fdfgj9qf.js} +3 -3
  5. package/dist/cli/{curator-jpwvkpdv.js → curator-js92gc8a.js} +24 -20
  6. package/dist/cli/curator-llm-factory-n70bxf40.js +40 -0
  7. package/dist/cli/{dispatch-anmxxhen.js → dispatch-zr1xja4t.js} +2 -2
  8. package/dist/cli/{evidence-summary-service-6zsgw7x7.js → evidence-summary-service-bjhr75v0.js} +9 -7
  9. package/dist/cli/{gate-evidence-pgr7d942.js → gate-evidence-v6ds8rcp.js} +5 -4
  10. package/dist/cli/guardrail-explain-sn2a4pb7.js +41 -0
  11. package/dist/cli/{guardrail-log-fjypsmek.js → guardrail-log-8mqqsssq.js} +4 -4
  12. package/dist/cli/hive-promoter-3hh8ph4a.js +48 -0
  13. package/dist/cli/{index-9b7qp18e.js → index-1cn967sa.js} +2 -2
  14. package/dist/cli/{index-572t1qff.js → index-1emhz3zb.js} +1378 -2013
  15. package/dist/cli/{index-n1sptn1w.js → index-2nt4mq9n.js} +1 -1
  16. package/dist/cli/{index-6h82c2h0.js → index-48mc4d48.js} +1056 -192
  17. package/dist/cli/{index-bq8kd9r9.js → index-5gnp8fyw.js} +3 -3
  18. package/dist/cli/index-5mkc2f9z.js +154 -0
  19. package/dist/cli/{index-0kxc7t16.js → index-6jng9c8t.js} +1 -1
  20. package/dist/cli/{index-57rthc1z.js → index-7jyndvsy.js} +2 -2
  21. package/dist/cli/{index-b9v501fr.js → index-7xgqky26.js} +33 -5
  22. package/dist/cli/{index-4r5z8sgw.js → index-85bacexr.js} +2 -2
  23. package/dist/cli/{index-bpgqbwmf.js → index-9qxntjtx.js} +6 -6
  24. package/dist/cli/index-f1qyj61w.js +418 -0
  25. package/dist/cli/{index-wvxhynxq.js → index-fm7xz1ne.js} +1 -1
  26. package/dist/cli/{index-dfdg4ws5.js → index-fz1jgbvw.js} +6 -6
  27. package/dist/cli/{index-pchpahdf.js → index-h4c4rrwx.js} +20 -3
  28. package/dist/cli/{index-kxm3bdjh.js → index-mmny81g1.js} +6 -6
  29. package/dist/cli/{index-v4fcn4tr.js → index-q1exe2b3.js} +2 -198
  30. package/dist/cli/{index-57ymmh7h.js → index-r3j3458j.js} +4 -4
  31. package/dist/cli/{index-3naa2ajc.js → index-vvk2g744.js} +10 -156
  32. package/dist/cli/{index-zej8cy0j.js → index-vx76tcxe.js} +1 -1
  33. package/dist/cli/{index-xmarctsf.js → index-wg0665ft.js} +7 -7
  34. package/dist/cli/{index-4vsgp5a8.js → index-wj4jeavn.js} +1 -1
  35. package/dist/cli/index-wvrj16f0.js +206 -0
  36. package/dist/cli/{index-h28wfp7n.js → index-x06d2qqm.js} +28 -24
  37. package/dist/cli/index-x2q0gnt8.js +254 -0
  38. package/dist/cli/{index-xg18az81.js → index-yw8qpf51.js} +1 -1
  39. package/dist/cli/index.js +24 -20
  40. package/dist/cli/{knowledge-escalator-3sgwrgy9.js → knowledge-escalator-6v7sjprx.js} +8 -7
  41. package/dist/cli/{knowledge-events-kfc6xmkw.js → knowledge-events-6n3x3he2.js} +6 -5
  42. package/dist/cli/{knowledge-store-kyacem71.js → knowledge-store-exkw6yb1.js} +6 -5
  43. package/dist/cli/{knowledge-validator-ez3ws8ef.js → knowledge-validator-exymfcb9.js} +7 -6
  44. package/dist/cli/{pending-delegations-vfnpm8zt.js → pending-delegations-yyz3fcfn.js} +5 -4
  45. package/dist/cli/{pr-subscriptions-bpvazmsw.js → pr-subscriptions-vv8byxe6.js} +6 -5
  46. package/dist/cli/{schema-x0ekqzvs.js → schema-x17zmd03.js} +1 -1
  47. package/dist/cli/scope-persistence-6m5nsp1r.js +20 -0
  48. package/dist/cli/{skill-generator-x83re96d.js → skill-generator-mx9br4ty.js} +9 -8
  49. package/dist/commands/_shared/url-security.d.ts +13 -3
  50. package/dist/commands/close.d.ts +11 -0
  51. package/dist/commands/lanes.d.ts +35 -0
  52. package/dist/commands/registry.d.ts +7 -0
  53. package/dist/config/schema.d.ts +102 -0
  54. package/dist/git/branch.d.ts +53 -7
  55. package/dist/git/index.d.ts +5 -1
  56. package/dist/git/pr.d.ts +35 -2
  57. package/dist/hooks/delegation-gate/worktree-isolation.d.ts +118 -2
  58. package/dist/hooks/delegation-gate/worktree-merge-status.d.ts +17 -0
  59. package/dist/hooks/init-orphan-recovery-advisory.d.ts +58 -0
  60. package/dist/hooks/init-orphan-recovery.d.ts +65 -0
  61. package/dist/index.js +427 -416
  62. package/dist/sandbox/executor.d.ts +11 -1
  63. package/dist/sandbox/linux/bubblewrap-executor.d.ts +3 -1
  64. package/dist/sandbox/macos/sandbox-exec-executor.d.ts +3 -1
  65. package/dist/sandbox/win32/native-sandbox-executor.d.ts +1 -1
  66. package/dist/sandbox/win32/restricted-environment-executor.d.ts +4 -1
  67. package/dist/turbo/lean/runner.d.ts +11 -20
  68. package/dist/turbo/lean/worktree.d.ts +9 -3
  69. package/dist/utils/bun-compat.d.ts +30 -0
  70. package/dist/worktree/core.d.ts +55 -0
  71. package/dist/worktree/merge.d.ts +5 -1
  72. package/dist/worktree/types.d.ts +38 -0
  73. package/package.json +1 -1
  74. package/dist/cli/curator-llm-factory-9y15npd5.js +0 -36
  75. package/dist/cli/guardrail-explain-jk0amzae.js +0 -37
  76. package/dist/cli/hive-promoter-j2krbdn9.js +0 -44
@@ -0,0 +1,35 @@
1
+ /**
2
+ * /swarm lanes command — lists active, awaiting-merge, and conflicted worktree lanes.
3
+ *
4
+ * FR-105: SC-114, SC-115, SC-116, SC-117
5
+ */
6
+ import { type WorktreeMergeFailure } from '../hooks/delegation-gate/worktree-merge-status';
7
+ /**
8
+ * Lane record shape for machine-parseable output (--json).
9
+ */
10
+ export interface LaneRecord {
11
+ state: 'active' | 'awaiting-merge' | 'conflicted';
12
+ laneId: string;
13
+ branch: string;
14
+ worktreePath: string;
15
+ taskId: string;
16
+ planTaskId?: string;
17
+ parentSessionID: string;
18
+ mergeStrategy: 'merge' | 'rebase' | 'cherry-pick';
19
+ mergeOutcome?: WorktreeMergeFailure;
20
+ recoveryHint: string;
21
+ }
22
+ /**
23
+ * Handle the `/swarm lanes` command.
24
+ *
25
+ * Reads authoritative in-flight state from `standardWorktreeByCallID` and
26
+ * merge failure records from `worktree-merge-status.ts`. Produces two
27
+ * output formats controlled by the `--json` flag:
28
+ *
29
+ * - Human-readable (default): grouped by state with one-line summaries.
30
+ * - Machine-parseable (--json): stable-order array of `LaneRecord` objects.
31
+ *
32
+ * @param directory - Project root directory (used to init the durable status path)
33
+ * @param args - Command arguments; `--json` selects machine-parseable output
34
+ */
35
+ export declare function handleLanesCommand(directory: string, args: string[]): string;
@@ -190,6 +190,13 @@ export declare const COMMAND_REGISTRY: {
190
190
  readonly toolPolicy: "agent";
191
191
  readonly toolNoArgs: true;
192
192
  };
193
+ readonly lanes: {
194
+ readonly handler: (ctx: CommandContext) => Promise<string>;
195
+ readonly description: "List active, awaiting-merge, and conflicted worktree lanes";
196
+ readonly category: "diagnostics";
197
+ readonly toolPolicy: "agent";
198
+ readonly toolNoArgs: true;
199
+ };
193
200
  readonly 'sync-plan': {
194
201
  readonly handler: (ctx: CommandContext) => Promise<string>;
195
202
  readonly description: "Ensure plan.json and plan.md are synced";
@@ -1067,6 +1067,15 @@ export declare const WorktreeIsolationConfigSchema: z.ZodObject<{
1067
1067
  skip: "skip";
1068
1068
  copy: "copy";
1069
1069
  }>>;
1070
+ serialization_release_after_dispatches: z.ZodDefault<z.ZodNumber>;
1071
+ serialization_release_after_ms: z.ZodDefault<z.ZodNumber>;
1072
+ runtime_isolation: z.ZodOptional<z.ZodObject<{
1073
+ enabled: z.ZodDefault<z.ZodBoolean>;
1074
+ port_base: z.ZodOptional<z.ZodNumber>;
1075
+ port_stride: z.ZodDefault<z.ZodNumber>;
1076
+ env_overrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1077
+ cache_redirects: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1078
+ }, z.core.$strip>>;
1070
1079
  }, z.core.$strip>;
1071
1080
  export type WorktreeIsolationConfig = z.infer<typeof WorktreeIsolationConfigSchema>;
1072
1081
  export declare const LeanTurboConfigSchema: z.ZodObject<{
@@ -1088,6 +1097,18 @@ export declare const LeanTurboConfigSchema: z.ZodObject<{
1088
1097
  "cherry-pick": "cherry-pick";
1089
1098
  }>>>;
1090
1099
  worktree_dir: z.ZodOptional<z.ZodString>;
1100
+ deps_strategy: z.ZodOptional<z.ZodEnum<{
1101
+ link: "link";
1102
+ skip: "skip";
1103
+ copy: "copy";
1104
+ }>>;
1105
+ runtime_isolation: z.ZodOptional<z.ZodObject<{
1106
+ enabled: z.ZodDefault<z.ZodBoolean>;
1107
+ port_base: z.ZodOptional<z.ZodNumber>;
1108
+ port_stride: z.ZodDefault<z.ZodNumber>;
1109
+ env_overrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1110
+ cache_redirects: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1111
+ }, z.core.$strip>>;
1091
1112
  }, z.core.$strip>;
1092
1113
  export type LeanTurboConfig = z.infer<typeof LeanTurboConfigSchema>;
1093
1114
  /**
@@ -1142,6 +1163,18 @@ export declare const StandardTurboConfigSchema: z.ZodObject<{
1142
1163
  "cherry-pick": "cherry-pick";
1143
1164
  }>>>;
1144
1165
  worktree_dir: z.ZodOptional<z.ZodString>;
1166
+ deps_strategy: z.ZodOptional<z.ZodEnum<{
1167
+ link: "link";
1168
+ skip: "skip";
1169
+ copy: "copy";
1170
+ }>>;
1171
+ runtime_isolation: z.ZodOptional<z.ZodObject<{
1172
+ enabled: z.ZodDefault<z.ZodBoolean>;
1173
+ port_base: z.ZodOptional<z.ZodNumber>;
1174
+ port_stride: z.ZodDefault<z.ZodNumber>;
1175
+ env_overrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1176
+ cache_redirects: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1177
+ }, z.core.$strip>>;
1145
1178
  }, z.core.$strip>>;
1146
1179
  epic: z.ZodOptional<z.ZodObject<{
1147
1180
  cochange: z.ZodOptional<z.ZodObject<{
@@ -1184,6 +1217,18 @@ export declare const LeanTurboStrategyConfigSchema: z.ZodObject<{
1184
1217
  "cherry-pick": "cherry-pick";
1185
1218
  }>>>;
1186
1219
  worktree_dir: z.ZodOptional<z.ZodString>;
1220
+ deps_strategy: z.ZodOptional<z.ZodEnum<{
1221
+ link: "link";
1222
+ skip: "skip";
1223
+ copy: "copy";
1224
+ }>>;
1225
+ runtime_isolation: z.ZodOptional<z.ZodObject<{
1226
+ enabled: z.ZodDefault<z.ZodBoolean>;
1227
+ port_base: z.ZodOptional<z.ZodNumber>;
1228
+ port_stride: z.ZodDefault<z.ZodNumber>;
1229
+ env_overrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1230
+ cache_redirects: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1231
+ }, z.core.$strip>>;
1187
1232
  }, z.core.$strip>;
1188
1233
  epic: z.ZodOptional<z.ZodObject<{
1189
1234
  cochange: z.ZodOptional<z.ZodObject<{
@@ -1226,6 +1271,18 @@ export declare const TurboConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1226
1271
  "cherry-pick": "cherry-pick";
1227
1272
  }>>>;
1228
1273
  worktree_dir: z.ZodOptional<z.ZodString>;
1274
+ deps_strategy: z.ZodOptional<z.ZodEnum<{
1275
+ link: "link";
1276
+ skip: "skip";
1277
+ copy: "copy";
1278
+ }>>;
1279
+ runtime_isolation: z.ZodOptional<z.ZodObject<{
1280
+ enabled: z.ZodDefault<z.ZodBoolean>;
1281
+ port_base: z.ZodOptional<z.ZodNumber>;
1282
+ port_stride: z.ZodDefault<z.ZodNumber>;
1283
+ env_overrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1284
+ cache_redirects: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1285
+ }, z.core.$strip>>;
1229
1286
  }, z.core.$strip>>;
1230
1287
  epic: z.ZodOptional<z.ZodObject<{
1231
1288
  cochange: z.ZodOptional<z.ZodObject<{
@@ -1267,6 +1324,18 @@ export declare const TurboConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1267
1324
  "cherry-pick": "cherry-pick";
1268
1325
  }>>>;
1269
1326
  worktree_dir: z.ZodOptional<z.ZodString>;
1327
+ deps_strategy: z.ZodOptional<z.ZodEnum<{
1328
+ link: "link";
1329
+ skip: "skip";
1330
+ copy: "copy";
1331
+ }>>;
1332
+ runtime_isolation: z.ZodOptional<z.ZodObject<{
1333
+ enabled: z.ZodDefault<z.ZodBoolean>;
1334
+ port_base: z.ZodOptional<z.ZodNumber>;
1335
+ port_stride: z.ZodDefault<z.ZodNumber>;
1336
+ env_overrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1337
+ cache_redirects: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1338
+ }, z.core.$strip>>;
1270
1339
  }, z.core.$strip>;
1271
1340
  epic: z.ZodOptional<z.ZodObject<{
1272
1341
  cochange: z.ZodOptional<z.ZodObject<{
@@ -2179,6 +2248,15 @@ export declare const PluginConfigSchema: z.ZodObject<{
2179
2248
  skip: "skip";
2180
2249
  copy: "copy";
2181
2250
  }>>;
2251
+ serialization_release_after_dispatches: z.ZodDefault<z.ZodNumber>;
2252
+ serialization_release_after_ms: z.ZodDefault<z.ZodNumber>;
2253
+ runtime_isolation: z.ZodOptional<z.ZodObject<{
2254
+ enabled: z.ZodDefault<z.ZodBoolean>;
2255
+ port_base: z.ZodOptional<z.ZodNumber>;
2256
+ port_stride: z.ZodDefault<z.ZodNumber>;
2257
+ env_overrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2258
+ cache_redirects: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2259
+ }, z.core.$strip>>;
2182
2260
  }, z.core.$strip>>;
2183
2261
  turbo: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
2184
2262
  strategy: z.ZodLiteral<"standard">;
@@ -2201,6 +2279,18 @@ export declare const PluginConfigSchema: z.ZodObject<{
2201
2279
  "cherry-pick": "cherry-pick";
2202
2280
  }>>>;
2203
2281
  worktree_dir: z.ZodOptional<z.ZodString>;
2282
+ deps_strategy: z.ZodOptional<z.ZodEnum<{
2283
+ link: "link";
2284
+ skip: "skip";
2285
+ copy: "copy";
2286
+ }>>;
2287
+ runtime_isolation: z.ZodOptional<z.ZodObject<{
2288
+ enabled: z.ZodDefault<z.ZodBoolean>;
2289
+ port_base: z.ZodOptional<z.ZodNumber>;
2290
+ port_stride: z.ZodDefault<z.ZodNumber>;
2291
+ env_overrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2292
+ cache_redirects: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2293
+ }, z.core.$strip>>;
2204
2294
  }, z.core.$strip>>;
2205
2295
  epic: z.ZodOptional<z.ZodObject<{
2206
2296
  cochange: z.ZodOptional<z.ZodObject<{
@@ -2242,6 +2332,18 @@ export declare const PluginConfigSchema: z.ZodObject<{
2242
2332
  "cherry-pick": "cherry-pick";
2243
2333
  }>>>;
2244
2334
  worktree_dir: z.ZodOptional<z.ZodString>;
2335
+ deps_strategy: z.ZodOptional<z.ZodEnum<{
2336
+ link: "link";
2337
+ skip: "skip";
2338
+ copy: "copy";
2339
+ }>>;
2340
+ runtime_isolation: z.ZodOptional<z.ZodObject<{
2341
+ enabled: z.ZodDefault<z.ZodBoolean>;
2342
+ port_base: z.ZodOptional<z.ZodNumber>;
2343
+ port_stride: z.ZodDefault<z.ZodNumber>;
2344
+ env_overrides: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2345
+ cache_redirects: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
2346
+ }, z.core.$strip>>;
2245
2347
  }, z.core.$strip>;
2246
2348
  epic: z.ZodOptional<z.ZodObject<{
2247
2349
  cochange: z.ZodOptional<z.ZodObject<{
@@ -1,3 +1,4 @@
1
+ import * as child_process from 'node:child_process';
1
2
  export type GitRepositoryStatus = {
2
3
  isRepo: true;
3
4
  } | {
@@ -5,6 +6,23 @@ export type GitRepositoryStatus = {
5
6
  reason: 'not_git_repo' | 'git_unavailable' | 'git_error';
6
7
  message: string;
7
8
  };
9
+ /**
10
+ * Seam that calls child_process.spawnSync dynamically.
11
+ * Uses getChildProcessSpawnSync() to resolve at call time, allowing
12
+ * tests to mock child_process.spawnSync before gitExec runs.
13
+ */
14
+ declare const __spawnSyncSeam: {
15
+ spawnSync: (cmd: string, args: string[], options?: {
16
+ cwd?: string;
17
+ encoding?: BufferEncoding;
18
+ timeout?: number;
19
+ maxBuffer?: number;
20
+ windowsHide?: boolean;
21
+ stdio?: "pipe" | "ignore" | "inherit" | Array<"pipe" | "ignore" | "inherit">;
22
+ env?: Record<string, string | undefined>;
23
+ envOverrides?: Record<string, string | null>;
24
+ }) => child_process.SpawnSyncReturns<string | Buffer>;
25
+ };
8
26
  /**
9
27
  * Execute git command safely.
10
28
  *
@@ -33,8 +51,17 @@ export type GitRepositoryStatus = {
33
51
  * with exponential backoff up to MAX_TRANSIENT_RETRIES before throwing.
34
52
  * Permanent errors — non-zero exit, missing git binary, non-transient
35
53
  * spawn errors — throw immediately with no retry.
54
+ *
55
+ * Lane env fallback (FR-201): when `laneEnv` is not provided but `laneIndex`
56
+ * is, reads the lane env file from disk synchronously.
57
+ */
58
+ /**
59
+ * Synchronously read and parse a lane runtime profile from disk.
60
+ * Mirrors the logic of `readLaneEnvFileFromDisk` but uses sync fs.
61
+ * Returns an empty record when the file does not exist or cannot be read.
36
62
  */
37
- declare function gitExec(args: string[], cwd: string): string;
63
+ export declare function readLaneEnvFileFromDiskSync(worktreePath: string, laneIndex: number): Record<string, string>;
64
+ declare function gitExec(args: string[], cwd: string, laneEnv?: Record<string, string>, laneIndex?: number): string;
38
65
  export declare function getGitRepositoryStatus(cwd: string): GitRepositoryStatus;
39
66
  /**
40
67
  * Check if we're in a git repository
@@ -42,15 +69,20 @@ export declare function getGitRepositoryStatus(cwd: string): GitRepositoryStatus
42
69
  export declare function isGitRepo(cwd: string): boolean;
43
70
  /**
44
71
  * Get current branch name
72
+ * @param cwd - Working directory
73
+ * @param laneEnv - Optional lane env overrides for git spawn
74
+ * @param laneIndex - Optional lane index; if laneEnv not provided, reads env file from disk
45
75
  */
46
- export declare function getCurrentBranch(cwd: string): string;
76
+ export declare function getCurrentBranch(cwd: string, laneEnv?: Record<string, string>, laneIndex?: number): string;
47
77
  /**
48
78
  * Create a new branch
49
79
  * @param cwd - Working directory
50
80
  * @param branchName - Name of the branch to create
51
81
  * @param remote - Remote name (default: 'origin')
82
+ * @param laneEnv - Optional lane env overrides for git spawn
83
+ * @param laneIndex - Optional lane index; if laneEnv not provided, reads env file from disk
52
84
  */
53
- export declare function createBranch(cwd: string, branchName: string, remote?: string): void;
85
+ export declare function createBranch(cwd: string, branchName: string, remote?: string, laneEnv?: Record<string, string>, laneIndex?: number): void;
54
86
  /**
55
87
  * Get list of changed files compared to main/master
56
88
  * @param cwd - Working directory
@@ -72,20 +104,32 @@ export declare function stageFiles(cwd: string, files: string[]): void;
72
104
  /**
73
105
  * Stage all files in the working directory
74
106
  * @param cwd - Working directory
107
+ * @param laneEnv - Optional lane env overrides for git spawn
108
+ * @param laneIndex - Optional lane index; if laneEnv not provided, reads env file from disk
75
109
  */
76
- export declare function stageAll(cwd: string): void;
110
+ export declare function stageAll(cwd: string, laneEnv?: Record<string, string>, laneIndex?: number): void;
77
111
  /**
78
112
  * Commit changes
113
+ * @param cwd - Working directory
114
+ * @param message - Commit message
115
+ * @param laneEnv - Optional lane env overrides for git spawn
116
+ * @param laneIndex - Optional lane index; if laneEnv not provided, reads env file from disk
79
117
  */
80
- export declare function commitChanges(cwd: string, message: string): void;
118
+ export declare function commitChanges(cwd: string, message: string, laneEnv?: Record<string, string>, laneIndex?: number): void;
81
119
  /**
82
120
  * Get current commit SHA
121
+ * @param cwd - Working directory
122
+ * @param laneEnv - Optional lane env overrides for git spawn
123
+ * @param laneIndex - Optional lane index; if laneEnv not provided, reads env file from disk
83
124
  */
84
- export declare function getCurrentSha(cwd: string): string;
125
+ export declare function getCurrentSha(cwd: string, laneEnv?: Record<string, string>, laneIndex?: number): string;
85
126
  /**
86
127
  * Check if there are uncommitted changes
128
+ * @param cwd - Working directory
129
+ * @param laneEnv - Optional lane env overrides for git spawn
130
+ * @param laneIndex - Optional lane index; if laneEnv not provided, reads env file from disk
87
131
  */
88
- export declare function hasUncommittedChanges(cwd: string): boolean;
132
+ export declare function hasUncommittedChanges(cwd: string, laneEnv?: Record<string, string>, laneIndex?: number): boolean;
89
133
  export interface ResetToRemoteBranchResult {
90
134
  success: boolean;
91
135
  targetBranch: string;
@@ -155,5 +199,7 @@ export declare const _internals: {
155
199
  getGitRepositoryStatus: typeof getGitRepositoryStatus;
156
200
  resetToRemoteBranch: typeof resetToRemoteBranch;
157
201
  resetToMainAfterMerge: typeof resetToMainAfterMerge;
202
+ spawnSync: typeof __spawnSyncSeam.spawnSync;
203
+ readLaneEnvFileFromDiskSync: typeof readLaneEnvFileFromDiskSync;
158
204
  };
159
205
  export {};
@@ -4,6 +4,10 @@ export interface PRWorkflowOptions {
4
4
  title: string;
5
5
  body?: string;
6
6
  branch?: string;
7
+ /** Optional lane env overrides for git spawns. */
8
+ laneEnv?: Record<string, string>;
9
+ /** Optional lane index; used to read env file from disk if laneEnv not provided. */
10
+ laneIndex?: number;
7
11
  }
8
12
  export interface PRWorkflowResult {
9
13
  success: boolean;
@@ -18,5 +22,5 @@ export declare function runPRWorkflow(cwd: string, options: PRWorkflowOptions):
18
22
  /**
19
23
  * Generate evidence summary without creating PR
20
24
  */
21
- export declare function prepareEvidence(cwd: string): string;
25
+ export declare function prepareEvidence(cwd: string): Promise<string>;
22
26
  export { isGhAvailable, isAuthenticated, isGitRepo, createBranch };
package/dist/git/pr.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as child_process from 'node:child_process';
2
+ import { readLaneEnvFileFromDiskSync } from './branch.js';
2
3
  export declare const GIT_TIMEOUT_MS = 30000;
3
4
  /**
4
5
  * Sanitize input string to prevent command injection
@@ -15,15 +16,41 @@ export declare function sanitizeInput(input: string): string;
15
16
  * - Bounded transient retry for ETIMEDOUT per AGENTS.md invariant 9
16
17
  */
17
18
  export declare function ghExec(args: string[], cwd: string): string;
19
+ /**
20
+ * File-scoped indirection seam for spawnSync.
21
+ * Supports envOverrides so lane runtime profiles can inject env.
22
+ */
23
+ declare const __spawnSyncSeam: {
24
+ spawnSync: (cmd: string, args: string[], options?: {
25
+ cwd?: string;
26
+ encoding?: BufferEncoding;
27
+ timeout?: number;
28
+ maxBuffer?: number;
29
+ windowsHide?: boolean;
30
+ stdio?: "pipe" | "ignore" | "inherit" | Array<"pipe" | "ignore" | "inherit">;
31
+ env?: Record<string, string | undefined>;
32
+ envOverrides?: Record<string, string | null>;
33
+ }) => child_process.SpawnSyncReturns<string | NonSharedBuffer>;
34
+ };
18
35
  /**
19
36
  * Shared spawnSync wrapper with bounded ETIMEDOUT-only transient retry.
37
+ * Applies envOverrides to options.env before calling spawnSync.
20
38
  *
21
39
  * Mirrors the retry shape from ghExec (invariant 9):
22
40
  * - Up to MAX_TRANSIENT_RETRIES attempts with exponential backoff on ETIMEDOUT
23
41
  * - ENOENT and non-zero exit are thrown immediately (not retried)
24
42
  * - On success, returns the raw spawnSync result transparently
25
43
  */
26
- declare function spawnSyncWithTransientRetry(command: string, args: string[], options: child_process.SpawnSyncOptions): child_process.SpawnSyncReturns<string>;
44
+ declare function spawnSyncWithTransientRetry(command: string, args: string[], options?: {
45
+ cwd?: string;
46
+ encoding?: BufferEncoding;
47
+ timeout?: number;
48
+ maxBuffer?: number;
49
+ windowsHide?: boolean;
50
+ stdio?: 'pipe' | 'ignore' | 'inherit' | Array<'pipe' | 'ignore' | 'inherit'>;
51
+ env?: Record<string, string | undefined>;
52
+ envOverrides?: Record<string, string | null>;
53
+ }): child_process.SpawnSyncReturns<string>;
27
54
  /**
28
55
  * Execute gh CLI command asynchronously (non-blocking).
29
56
  * Used by background workers that must not block the event loop.
@@ -40,6 +67,8 @@ export declare const _internals: {
40
67
  ghExec: typeof ghExec;
41
68
  ghExecAsync: typeof ghExecAsync;
42
69
  spawnSyncWithTransientRetry: typeof spawnSyncWithTransientRetry;
70
+ spawnSync: typeof __spawnSyncSeam.spawnSync;
71
+ readLaneEnvFileFromDiskSync: typeof readLaneEnvFileFromDiskSync;
43
72
  };
44
73
  /**
45
74
  * Check if gh CLI is available
@@ -62,8 +91,12 @@ export declare function createPullRequest(cwd: string, title: string, body?: str
62
91
  }>;
63
92
  /**
64
93
  * Commit and push current changes
94
+ * @param cwd - Working directory
95
+ * @param message - Commit message
96
+ * @param laneEnv - Optional lane env overrides for git spawns
97
+ * @param laneIndex - Optional lane index; if laneEnv not provided, reads env file from disk
65
98
  */
66
- export declare function commitAndPush(cwd: string, message: string): void;
99
+ export declare function commitAndPush(cwd: string, message: string, laneEnv?: Record<string, string>, laneIndex?: number): Promise<void>;
67
100
  export interface PRStatusResult {
68
101
  number: number;
69
102
  state: 'OPEN' | 'CLOSED' | 'MERGED';
@@ -8,9 +8,46 @@
8
8
  * Extracted from delegation-gate.ts (FR-003) for modularity.
9
9
  * The _internals seam allows test injection of worktree operations.
10
10
  */
11
- import type { PluginConfig } from '../../config';
11
+ import type { PluginConfig, WorktreeIsolationConfig } from '../../config';
12
12
  import type { WorktreeHandle } from '../../worktree';
13
13
  import { attemptMergeBackFromDirty, cleanupOrphanedBranches, postMergeCleanup, provisionWorktree, removeWorktree, startupOrphanRecovery } from '../../worktree';
14
+ /**
15
+ * FR-201: Per-lane runtime profile injected into spawned child processes.
16
+ *
17
+ * Produced at lane provisioning time and written as `.swarm/lanes/{laneIndex}.env`
18
+ * (KEY=VAL format, one per line) so any child process spawned inside the lane
19
+ * can source it to get lane-specific PORT, TMPDIR, cache redirects, etc.
20
+ *
21
+ * The profile is computed from the resolved WorktreeIsolationConfig.runtime_isolation:
22
+ * - PORT = (port_base ?? 0) + laneIndex * port_stride
23
+ * - env_overrides merged verbatim
24
+ * - cache_redirects mapped to env vars
25
+ */
26
+ export interface LaneRuntimeProfile {
27
+ /** 0-based lane index used for port and env derivation. */
28
+ laneIndex: number;
29
+ /** Absolute path to the provisioned worktree. */
30
+ worktreePath: string;
31
+ /** Env var overrides for this lane (includes PORT after derivation). */
32
+ envOverrides: Record<string, string>;
33
+ }
34
+ /**
35
+ * Parses a Lean Turbo laneId (e.g. "lane-3") and returns its 0-based index.
36
+ * Returns 0 for unparseable ids.
37
+ */
38
+ export declare function parseLeanLaneIndex(laneId: string): number;
39
+ /**
40
+ * FR-201 SC-122: Computes the per-lane runtime profile from the resolved runtime_isolation config.
41
+ *
42
+ * Derives:
43
+ * - PORT = (port_base ?? 0) + laneIndex * port_stride
44
+ * - Derives PORT from port_base + lane_index * port_stride (when port_base is set)
45
+ * - Merges env_overrides — explicit caller values win over derived PORT
46
+ * - Merges cache_redirects (base → lane-suffixed-path mapped to env vars; wins over env_overrides)
47
+ *
48
+ * Returns undefined when runtime_isolation is disabled (zero behavior change).
49
+ */
50
+ export declare function computeLaneRuntimeProfile(runtime: WorktreeIsolationConfig['runtime_isolation'], laneIndex: number, worktreePath: string): LaneRuntimeProfile | undefined;
14
51
  export declare const MAX_TRACKED_STANDARD_WORKTREE_CALLS = 256;
15
52
  export interface StandardWorktreeDispatch {
16
53
  callID: string;
@@ -19,11 +56,54 @@ export interface StandardWorktreeDispatch {
19
56
  planTaskId?: string;
20
57
  handle: WorktreeHandle;
21
58
  mergeStrategy: 'merge' | 'rebase' | 'cherry-pick';
59
+ /** FR-201: 0-based lane index for runtime profile derivation. */
60
+ laneIndex: number;
61
+ }
62
+ export interface AwaitingMergeRecord {
63
+ callID: string;
64
+ parentSessionID: string;
65
+ taskId: string;
66
+ planTaskId?: string;
67
+ branch: string;
68
+ worktreePath: string;
69
+ mergeStrategy: 'merge' | 'rebase' | 'cherry-pick';
70
+ queuedAt: number;
22
71
  }
72
+ /** Map keyed by callID. Lanes waiting for or in the middle of merge-back. */
73
+ export declare const awaitingMergeByCallID: Map<string, AwaitingMergeRecord>;
23
74
  export declare const standardWorktreeByCallID: Map<string, StandardWorktreeDispatch>;
24
75
  export declare const standardWorktreeSerializationSessions: Set<string>;
76
+ /**
77
+ * FR-104 SC-111/SC-112: Per-session state tracking for serialization release.
78
+ * Maps sessionID → serialization state for that session.
79
+ */
80
+ interface SessionSerializationState {
81
+ sessionID: string;
82
+ /** Date.now() when the session was first added to standardWorktreeSerializationSessions */
83
+ serializedAt: number;
84
+ /**
85
+ * Count of successful dispatches (merge-back completed with 'merged') from this
86
+ * session since it entered serialized mode.
87
+ */
88
+ successfulDispatchesSince: number;
89
+ }
25
90
  export declare function resetStandardWorktreeIsolationState(): void;
91
+ /**
92
+ * FR-104 SC-111/SC-112: Check whether a serialized session has met its release conditions
93
+ * (either enough successful dispatches have completed, or the TTL has expired).
94
+ * If so, release it from serialized mode.
95
+ */
96
+ export declare function checkStandardWorktreeSerializationRelease(sessionID: string, config: WorktreeIsolationConfig): void;
97
+ /**
98
+ * FR-104 SC-113: Add a session to the serialization set.
99
+ * When the set is at capacity, evicts the oldest entry whose session has NO
100
+ * in-flight dispatch — never evict an actively-dispatching session.
101
+ * If ALL 256 entries are in-flight, refuses the new entry and logs a warning
102
+ * rather than silently breaking isolation.
103
+ */
104
+ declare function rememberStandardWorktreeSerializationSession(sessionID: string): boolean;
26
105
  export declare function sanitizeWorktreeTaskId(raw: string): string;
106
+ export declare function resolveWorktreeIsolationConfig(config: PluginConfig): WorktreeIsolationConfig;
27
107
  export declare function precreateStandardWorktreeSession(args: {
28
108
  config: PluginConfig;
29
109
  directory: string;
@@ -33,8 +113,31 @@ export declare function precreateStandardWorktreeSession(args: {
33
113
  planTaskId?: string;
34
114
  description?: string;
35
115
  outputArgs: Record<string, unknown>;
116
+ /** Scope to materialize into the lane for durability across restart (FR-102). */
117
+ scope?: {
118
+ taskId: string;
119
+ files: string[];
120
+ };
36
121
  }): Promise<void>;
37
- export declare function finishStandardWorktreeDispatch(directory: string, dispatch: StandardWorktreeDispatch): Promise<void>;
122
+ export declare function finishStandardWorktreeDispatch(directory: string, dispatch: StandardWorktreeDispatch, config?: PluginConfig,
123
+ /**
124
+ * Optional callID for cleanup of awaitingMergeByCallID. When omitted,
125
+ * derived from dispatch.callID (for backward compatibility with test callers
126
+ * that pass StandardWorktreeDispatch objects directly).
127
+ */
128
+ callID?: string): Promise<void>;
129
+ /**
130
+ * FR-201: Read and parse a lane runtime profile from disk.
131
+ *
132
+ * Reads `<worktree>/.swarm/lanes/{laneIndex}.env` (KEY=VALUE format, one per line).
133
+ * - Skips blank lines and lines starting with `#` (comments).
134
+ * - Skips malformed lines (no `=` separator).
135
+ * - Validates each key with `isValidEnvKey`; rejects and skips invalid keys.
136
+ * - Returns an empty record when the file does not exist.
137
+ *
138
+ * Exposed via _internals for testability (no mock.module leakage).
139
+ */
140
+ export declare function readLaneEnvFileFromDisk(worktreePath: string, laneIndex: number): Promise<Record<string, string>>;
38
141
  /**
39
142
  * _internals seam for test injection of worktree operations.
40
143
  * Tests set these entries on delegation-gate's _internals (which proxies
@@ -45,6 +148,19 @@ export declare const _internals: {
45
148
  removeWorktree: typeof removeWorktree;
46
149
  attemptMergeBackFromDirty: typeof attemptMergeBackFromDirty;
47
150
  postMergeCleanup: typeof postMergeCleanup;
151
+ /** FR-201: read lane runtime profile from disk for spawn injection. */
152
+ readLaneEnvFileFromDisk: typeof readLaneEnvFileFromDisk;
153
+ /** FR-104: exposes serializationStateBySessionID for test setup (SC-111/SC-112/SC-113). */
154
+ serializationStateBySessionID: Map<string, SessionSerializationState>;
155
+ /**
156
+ * FR-104 SC-113: exposes the FIFO eviction function for direct test invocation.
157
+ * Tests use this to exercise the cap-check logic without going through the
158
+ * full precreateStandardWorktreeSession path.
159
+ */
160
+ rememberStandardWorktreeSerializationSession: typeof rememberStandardWorktreeSerializationSession;
161
+ /** FR-105 SC-115: exposes awaitingMergeByCallID for test setup. */
162
+ awaitingMergeByCallID: Map<string, AwaitingMergeRecord>;
48
163
  startupOrphanRecovery: typeof startupOrphanRecovery;
49
164
  cleanupOrphanedBranches: typeof cleanupOrphanedBranches;
50
165
  };
166
+ export {};
@@ -34,6 +34,14 @@ export interface WorktreeMergeFailure {
34
34
  stage: string;
35
35
  /** Human-readable detail surfaced in the Rule 2 skip warning. */
36
36
  message: string;
37
+ /** Worktree path where the lane is preserved after a failed/partial merge. */
38
+ worktreePath?: string;
39
+ /** Branch name of the lane. */
40
+ branch?: string;
41
+ /** Timestamp (Date.now()) when the lane entered merge-back. */
42
+ queuedAt?: number;
43
+ /** Timestamp (Date.now()) when merge-back completed (success or failure). */
44
+ completedAt?: number;
37
45
  }
38
46
  declare function getDurableStatusPath(projectDir?: string): string;
39
47
  /**
@@ -70,6 +78,15 @@ export declare function clearWorktreeMergeStatus(taskId: string | undefined): vo
70
78
  * On first read after plugin restart, loads from durable storage.
71
79
  */
72
80
  export declare function getWorktreeMergeFailure(taskId: string): WorktreeMergeFailure | undefined;
81
+ /**
82
+ * Iterate all worktree merge failures. Used by /swarm lanes to surface
83
+ * conflicted lanes that are NOT in awaitingMergeByCallID (i.e., merge
84
+ * has completed with partial/failed outcome).
85
+ */
86
+ export declare function getAllWorktreeMergeFailures(): IterableIterator<[
87
+ string,
88
+ WorktreeMergeFailure
89
+ ]>;
73
90
  /**
74
91
  * @internal test seam. Use `resetForTest()` in afterEach to isolate tests
75
92
  * that set durableStatusPath via `initDurableStatusPath`.
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Init Orphan Recovery Advisory Hook (FR-103 SC-108)
3
+ *
4
+ * At plugin init, `cleanupOrphanedBranches` is called to reclaim orphaned worktrees
5
+ * and branches. Any warnings or errors (state-unreadable conditions) are written
6
+ * to `<directory>/.swarm/advisories/init-orphan-recovery.json`.
7
+ *
8
+ * This hook runs in the `messagesTransform` chain (before `guardrailsHooks.messagesTransform`)
9
+ * and surfaces those advisories to the architect on their NEXT TURN.
10
+ *
11
+ * Advisory file format:
12
+ * ```json
13
+ * {
14
+ * "initTimestamp": "<ISO timestamp>",
15
+ * "warnings": ["warning message 1", "warning message 2"],
16
+ * "errors": [{ "branch": "swarm-lane/sess/lane", "error": "detail" }],
17
+ * "reclaimed": { "removedBranches": [], "prunedWorktrees": true }
18
+ * }
19
+ * ```
20
+ *
21
+ * The file is deleted after consumption (best-effort) so repeated turns don't re-surface.
22
+ */
23
+ export interface InitOrphanAdvisory {
24
+ initTimestamp: string;
25
+ warnings: string[];
26
+ errors: Array<{
27
+ branch: string;
28
+ error: string;
29
+ }>;
30
+ reclaimed: {
31
+ removedBranches: string[];
32
+ removedWorktrees: string[];
33
+ prunedWorktrees: boolean;
34
+ };
35
+ }
36
+ /**
37
+ * Creates a messagesTransform hook that surfaces init orphan recovery advisories
38
+ * on the architect's first turn after plugin init.
39
+ *
40
+ * @param directory - Project root directory (for .swarm/advisories path)
41
+ * @returns A hook object with a messagesTransform handler
42
+ */
43
+ export declare function createInitOrphanRecoveryAdvisoryHook(directory: string): {
44
+ messagesTransform: (input: Record<string, never>, output: {
45
+ messages?: Array<{
46
+ info: {
47
+ role: string;
48
+ agent?: string;
49
+ sessionID?: string;
50
+ };
51
+ parts: Array<{
52
+ type?: string;
53
+ text?: string;
54
+ [key: string]: unknown;
55
+ }>;
56
+ }>;
57
+ }) => Promise<void>;
58
+ };