webmux 0.19.0 → 0.20.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.
@@ -2,7 +2,7 @@
2
2
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
3
3
  var __require = import.meta.require;
4
4
 
5
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/identity.js
5
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/identity.js
6
6
  var require_identity = __commonJS((exports) => {
7
7
  var ALIAS = Symbol.for("yaml.alias");
8
8
  var DOC = Symbol.for("yaml.document");
@@ -56,7 +56,7 @@ var require_identity = __commonJS((exports) => {
56
56
  exports.isSeq = isSeq;
57
57
  });
58
58
 
59
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/visit.js
59
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/visit.js
60
60
  var require_visit = __commonJS((exports) => {
61
61
  var identity = require_identity();
62
62
  var BREAK = Symbol("break visit");
@@ -211,7 +211,7 @@ var require_visit = __commonJS((exports) => {
211
211
  exports.visitAsync = visitAsync;
212
212
  });
213
213
 
214
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/doc/directives.js
214
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/doc/directives.js
215
215
  var require_directives = __commonJS((exports) => {
216
216
  var identity = require_identity();
217
217
  var visit = require_visit();
@@ -363,7 +363,7 @@ var require_directives = __commonJS((exports) => {
363
363
  exports.Directives = Directives;
364
364
  });
365
365
 
366
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/doc/anchors.js
366
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/doc/anchors.js
367
367
  var require_anchors = __commonJS((exports) => {
368
368
  var identity = require_identity();
369
369
  var visit = require_visit();
@@ -425,7 +425,7 @@ var require_anchors = __commonJS((exports) => {
425
425
  exports.findNewAnchor = findNewAnchor;
426
426
  });
427
427
 
428
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/doc/applyReviver.js
428
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/doc/applyReviver.js
429
429
  var require_applyReviver = __commonJS((exports) => {
430
430
  function applyReviver(reviver, obj, key, val) {
431
431
  if (val && typeof val === "object") {
@@ -472,7 +472,7 @@ var require_applyReviver = __commonJS((exports) => {
472
472
  exports.applyReviver = applyReviver;
473
473
  });
474
474
 
475
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/toJS.js
475
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/toJS.js
476
476
  var require_toJS = __commonJS((exports) => {
477
477
  var identity = require_identity();
478
478
  function toJS(value, arg, ctx) {
@@ -499,7 +499,7 @@ var require_toJS = __commonJS((exports) => {
499
499
  exports.toJS = toJS;
500
500
  });
501
501
 
502
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/Node.js
502
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/Node.js
503
503
  var require_Node = __commonJS((exports) => {
504
504
  var applyReviver = require_applyReviver();
505
505
  var identity = require_identity();
@@ -536,7 +536,7 @@ var require_Node = __commonJS((exports) => {
536
536
  exports.NodeBase = NodeBase;
537
537
  });
538
538
 
539
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/Alias.js
539
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/Alias.js
540
540
  var require_Alias = __commonJS((exports) => {
541
541
  var anchors = require_anchors();
542
542
  var visit = require_visit();
@@ -644,7 +644,7 @@ var require_Alias = __commonJS((exports) => {
644
644
  exports.Alias = Alias;
645
645
  });
646
646
 
647
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/Scalar.js
647
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/Scalar.js
648
648
  var require_Scalar = __commonJS((exports) => {
649
649
  var identity = require_identity();
650
650
  var Node = require_Node();
@@ -672,7 +672,7 @@ var require_Scalar = __commonJS((exports) => {
672
672
  exports.isScalarValue = isScalarValue;
673
673
  });
674
674
 
675
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/doc/createNode.js
675
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/doc/createNode.js
676
676
  var require_createNode = __commonJS((exports) => {
677
677
  var Alias = require_Alias();
678
678
  var identity = require_identity();
@@ -744,7 +744,7 @@ var require_createNode = __commonJS((exports) => {
744
744
  exports.createNode = createNode;
745
745
  });
746
746
 
747
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/Collection.js
747
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/Collection.js
748
748
  var require_Collection = __commonJS((exports) => {
749
749
  var createNode = require_createNode();
750
750
  var identity = require_identity();
@@ -859,7 +859,7 @@ var require_Collection = __commonJS((exports) => {
859
859
  exports.isEmptyPath = isEmptyPath;
860
860
  });
861
861
 
862
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/stringify/stringifyComment.js
862
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringifyComment.js
863
863
  var require_stringifyComment = __commonJS((exports) => {
864
864
  var stringifyComment = (str) => str.replace(/^(?!$)(?: $)?/gm, "#");
865
865
  function indentComment(comment, indent) {
@@ -876,7 +876,7 @@ var require_stringifyComment = __commonJS((exports) => {
876
876
  exports.stringifyComment = stringifyComment;
877
877
  });
878
878
 
879
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/stringify/foldFlowLines.js
879
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/foldFlowLines.js
880
880
  var require_foldFlowLines = __commonJS((exports) => {
881
881
  var FOLD_FLOW = "flow";
882
882
  var FOLD_BLOCK = "block";
@@ -1013,7 +1013,7 @@ ${indent}${text.slice(fold + 1, end2)}`;
1013
1013
  exports.foldFlowLines = foldFlowLines;
1014
1014
  });
1015
1015
 
1016
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/stringify/stringifyString.js
1016
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringifyString.js
1017
1017
  var require_stringifyString = __commonJS((exports) => {
1018
1018
  var Scalar = require_Scalar();
1019
1019
  var foldFlowLines = require_foldFlowLines();
@@ -1311,7 +1311,7 @@ ${indent}`);
1311
1311
  exports.stringifyString = stringifyString;
1312
1312
  });
1313
1313
 
1314
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/stringify/stringify.js
1314
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringify.js
1315
1315
  var require_stringify = __commonJS((exports) => {
1316
1316
  var anchors = require_anchors();
1317
1317
  var identity = require_identity();
@@ -1334,6 +1334,7 @@ var require_stringify = __commonJS((exports) => {
1334
1334
  nullStr: "null",
1335
1335
  simpleKeys: false,
1336
1336
  singleQuote: null,
1337
+ trailingComma: false,
1337
1338
  trueStr: "true",
1338
1339
  verifyAliasOrder: true
1339
1340
  }, doc.schema.toStringOptions, options);
@@ -1431,7 +1432,7 @@ ${ctx.indent}${str}`;
1431
1432
  exports.stringify = stringify;
1432
1433
  });
1433
1434
 
1434
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/stringify/stringifyPair.js
1435
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringifyPair.js
1435
1436
  var require_stringifyPair = __commonJS((exports) => {
1436
1437
  var identity = require_identity();
1437
1438
  var Scalar = require_Scalar();
@@ -1567,7 +1568,7 @@ ${ctx.indent}`;
1567
1568
  exports.stringifyPair = stringifyPair;
1568
1569
  });
1569
1570
 
1570
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/log.js
1571
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/log.js
1571
1572
  var require_log = __commonJS((exports) => {
1572
1573
  var node_process = __require("process");
1573
1574
  function debug(logLevel, ...messages) {
@@ -1586,7 +1587,7 @@ var require_log = __commonJS((exports) => {
1586
1587
  exports.warn = warn;
1587
1588
  });
1588
1589
 
1589
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/yaml-1.1/merge.js
1590
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/merge.js
1590
1591
  var require_merge = __commonJS((exports) => {
1591
1592
  var identity = require_identity();
1592
1593
  var Scalar = require_Scalar();
@@ -1640,7 +1641,7 @@ var require_merge = __commonJS((exports) => {
1640
1641
  exports.merge = merge;
1641
1642
  });
1642
1643
 
1643
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/addPairToJSMap.js
1644
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/addPairToJSMap.js
1644
1645
  var require_addPairToJSMap = __commonJS((exports) => {
1645
1646
  var log2 = require_log();
1646
1647
  var merge = require_merge();
@@ -1701,7 +1702,7 @@ var require_addPairToJSMap = __commonJS((exports) => {
1701
1702
  exports.addPairToJSMap = addPairToJSMap;
1702
1703
  });
1703
1704
 
1704
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/Pair.js
1705
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/Pair.js
1705
1706
  var require_Pair = __commonJS((exports) => {
1706
1707
  var createNode = require_createNode();
1707
1708
  var stringifyPair = require_stringifyPair();
@@ -1739,7 +1740,7 @@ var require_Pair = __commonJS((exports) => {
1739
1740
  exports.createPair = createPair;
1740
1741
  });
1741
1742
 
1742
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/stringify/stringifyCollection.js
1743
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringifyCollection.js
1743
1744
  var require_stringifyCollection = __commonJS((exports) => {
1744
1745
  var identity = require_identity();
1745
1746
  var stringify = require_stringify();
@@ -1842,13 +1843,20 @@ ${indent}${line}` : `
1842
1843
  if (comment)
1843
1844
  reqNewline = true;
1844
1845
  let str = stringify.stringify(item, itemCtx, () => comment = null);
1845
- if (i < items.length - 1)
1846
+ reqNewline || (reqNewline = lines.length > linesAtValue || str.includes(`
1847
+ `));
1848
+ if (i < items.length - 1) {
1846
1849
  str += ",";
1850
+ } else if (ctx.options.trailingComma) {
1851
+ if (ctx.options.lineWidth > 0) {
1852
+ reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > ctx.options.lineWidth);
1853
+ }
1854
+ if (reqNewline) {
1855
+ str += ",";
1856
+ }
1857
+ }
1847
1858
  if (comment)
1848
1859
  str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
1849
- if (!reqNewline && (lines.length > linesAtValue || str.includes(`
1850
- `)))
1851
- reqNewline = true;
1852
1860
  lines.push(str);
1853
1861
  linesAtValue = lines.length;
1854
1862
  }
@@ -1884,7 +1892,7 @@ ${indent}${end}`;
1884
1892
  exports.stringifyCollection = stringifyCollection;
1885
1893
  });
1886
1894
 
1887
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/YAMLMap.js
1895
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/YAMLMap.js
1888
1896
  var require_YAMLMap = __commonJS((exports) => {
1889
1897
  var stringifyCollection = require_stringifyCollection();
1890
1898
  var addPairToJSMap = require_addPairToJSMap();
@@ -2011,7 +2019,7 @@ var require_YAMLMap = __commonJS((exports) => {
2011
2019
  exports.findPair = findPair;
2012
2020
  });
2013
2021
 
2014
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/common/map.js
2022
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/common/map.js
2015
2023
  var require_map = __commonJS((exports) => {
2016
2024
  var identity = require_identity();
2017
2025
  var YAMLMap = require_YAMLMap();
@@ -2030,7 +2038,7 @@ var require_map = __commonJS((exports) => {
2030
2038
  exports.map = map;
2031
2039
  });
2032
2040
 
2033
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/YAMLSeq.js
2041
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/YAMLSeq.js
2034
2042
  var require_YAMLSeq = __commonJS((exports) => {
2035
2043
  var createNode = require_createNode();
2036
2044
  var stringifyCollection = require_stringifyCollection();
@@ -2123,7 +2131,7 @@ var require_YAMLSeq = __commonJS((exports) => {
2123
2131
  exports.YAMLSeq = YAMLSeq;
2124
2132
  });
2125
2133
 
2126
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/common/seq.js
2134
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/common/seq.js
2127
2135
  var require_seq = __commonJS((exports) => {
2128
2136
  var identity = require_identity();
2129
2137
  var YAMLSeq = require_YAMLSeq();
@@ -2142,7 +2150,7 @@ var require_seq = __commonJS((exports) => {
2142
2150
  exports.seq = seq;
2143
2151
  });
2144
2152
 
2145
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/common/string.js
2153
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/common/string.js
2146
2154
  var require_string = __commonJS((exports) => {
2147
2155
  var stringifyString = require_stringifyString();
2148
2156
  var string = {
@@ -2158,7 +2166,7 @@ var require_string = __commonJS((exports) => {
2158
2166
  exports.string = string;
2159
2167
  });
2160
2168
 
2161
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/common/null.js
2169
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/common/null.js
2162
2170
  var require_null = __commonJS((exports) => {
2163
2171
  var Scalar = require_Scalar();
2164
2172
  var nullTag = {
@@ -2173,7 +2181,7 @@ var require_null = __commonJS((exports) => {
2173
2181
  exports.nullTag = nullTag;
2174
2182
  });
2175
2183
 
2176
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/core/bool.js
2184
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/core/bool.js
2177
2185
  var require_bool = __commonJS((exports) => {
2178
2186
  var Scalar = require_Scalar();
2179
2187
  var boolTag = {
@@ -2194,7 +2202,7 @@ var require_bool = __commonJS((exports) => {
2194
2202
  exports.boolTag = boolTag;
2195
2203
  });
2196
2204
 
2197
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/stringify/stringifyNumber.js
2205
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringifyNumber.js
2198
2206
  var require_stringifyNumber = __commonJS((exports) => {
2199
2207
  function stringifyNumber({ format, minFractionDigits, tag, value }) {
2200
2208
  if (typeof value === "bigint")
@@ -2218,7 +2226,7 @@ var require_stringifyNumber = __commonJS((exports) => {
2218
2226
  exports.stringifyNumber = stringifyNumber;
2219
2227
  });
2220
2228
 
2221
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/core/float.js
2229
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/core/float.js
2222
2230
  var require_float = __commonJS((exports) => {
2223
2231
  var Scalar = require_Scalar();
2224
2232
  var stringifyNumber = require_stringifyNumber();
@@ -2261,7 +2269,7 @@ var require_float = __commonJS((exports) => {
2261
2269
  exports.floatNaN = floatNaN;
2262
2270
  });
2263
2271
 
2264
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/core/int.js
2272
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/core/int.js
2265
2273
  var require_int = __commonJS((exports) => {
2266
2274
  var stringifyNumber = require_stringifyNumber();
2267
2275
  var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
@@ -2303,7 +2311,7 @@ var require_int = __commonJS((exports) => {
2303
2311
  exports.intOct = intOct;
2304
2312
  });
2305
2313
 
2306
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/core/schema.js
2314
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/core/schema.js
2307
2315
  var require_schema = __commonJS((exports) => {
2308
2316
  var map = require_map();
2309
2317
  var _null = require_null();
@@ -2328,7 +2336,7 @@ var require_schema = __commonJS((exports) => {
2328
2336
  exports.schema = schema;
2329
2337
  });
2330
2338
 
2331
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/json/schema.js
2339
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/json/schema.js
2332
2340
  var require_schema2 = __commonJS((exports) => {
2333
2341
  var Scalar = require_Scalar();
2334
2342
  var map = require_map();
@@ -2392,7 +2400,7 @@ var require_schema2 = __commonJS((exports) => {
2392
2400
  exports.schema = schema;
2393
2401
  });
2394
2402
 
2395
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/yaml-1.1/binary.js
2403
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/binary.js
2396
2404
  var require_binary = __commonJS((exports) => {
2397
2405
  var node_buffer = __require("buffer");
2398
2406
  var Scalar = require_Scalar();
@@ -2447,7 +2455,7 @@ var require_binary = __commonJS((exports) => {
2447
2455
  exports.binary = binary;
2448
2456
  });
2449
2457
 
2450
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/yaml-1.1/pairs.js
2458
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/pairs.js
2451
2459
  var require_pairs = __commonJS((exports) => {
2452
2460
  var identity = require_identity();
2453
2461
  var Pair = require_Pair();
@@ -2522,7 +2530,7 @@ ${cn.comment}` : item.comment;
2522
2530
  exports.resolvePairs = resolvePairs;
2523
2531
  });
2524
2532
 
2525
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/yaml-1.1/omap.js
2533
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/omap.js
2526
2534
  var require_omap = __commonJS((exports) => {
2527
2535
  var identity = require_identity();
2528
2536
  var toJS = require_toJS();
@@ -2594,7 +2602,7 @@ var require_omap = __commonJS((exports) => {
2594
2602
  exports.omap = omap;
2595
2603
  });
2596
2604
 
2597
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/yaml-1.1/bool.js
2605
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/bool.js
2598
2606
  var require_bool2 = __commonJS((exports) => {
2599
2607
  var Scalar = require_Scalar();
2600
2608
  function boolStringify({ value, source }, ctx) {
@@ -2623,7 +2631,7 @@ var require_bool2 = __commonJS((exports) => {
2623
2631
  exports.trueTag = trueTag;
2624
2632
  });
2625
2633
 
2626
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/yaml-1.1/float.js
2634
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/float.js
2627
2635
  var require_float2 = __commonJS((exports) => {
2628
2636
  var Scalar = require_Scalar();
2629
2637
  var stringifyNumber = require_stringifyNumber();
@@ -2669,7 +2677,7 @@ var require_float2 = __commonJS((exports) => {
2669
2677
  exports.floatNaN = floatNaN;
2670
2678
  });
2671
2679
 
2672
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/yaml-1.1/int.js
2680
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/int.js
2673
2681
  var require_int2 = __commonJS((exports) => {
2674
2682
  var stringifyNumber = require_stringifyNumber();
2675
2683
  var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
@@ -2745,7 +2753,7 @@ var require_int2 = __commonJS((exports) => {
2745
2753
  exports.intOct = intOct;
2746
2754
  });
2747
2755
 
2748
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/yaml-1.1/set.js
2756
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/set.js
2749
2757
  var require_set = __commonJS((exports) => {
2750
2758
  var identity = require_identity();
2751
2759
  var Pair = require_Pair();
@@ -2828,7 +2836,7 @@ var require_set = __commonJS((exports) => {
2828
2836
  exports.set = set;
2829
2837
  });
2830
2838
 
2831
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js
2839
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js
2832
2840
  var require_timestamp = __commonJS((exports) => {
2833
2841
  var stringifyNumber = require_stringifyNumber();
2834
2842
  function parseSexagesimal(str, asBigInt) {
@@ -2910,7 +2918,7 @@ var require_timestamp = __commonJS((exports) => {
2910
2918
  exports.timestamp = timestamp;
2911
2919
  });
2912
2920
 
2913
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/yaml-1.1/schema.js
2921
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/schema.js
2914
2922
  var require_schema3 = __commonJS((exports) => {
2915
2923
  var map = require_map();
2916
2924
  var _null = require_null();
@@ -2951,7 +2959,7 @@ var require_schema3 = __commonJS((exports) => {
2951
2959
  exports.schema = schema;
2952
2960
  });
2953
2961
 
2954
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/tags.js
2962
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/tags.js
2955
2963
  var require_tags = __commonJS((exports) => {
2956
2964
  var map = require_map();
2957
2965
  var _null = require_null();
@@ -3042,7 +3050,7 @@ var require_tags = __commonJS((exports) => {
3042
3050
  exports.getTags = getTags;
3043
3051
  });
3044
3052
 
3045
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/schema/Schema.js
3053
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/Schema.js
3046
3054
  var require_Schema = __commonJS((exports) => {
3047
3055
  var identity = require_identity();
3048
3056
  var map = require_map();
@@ -3072,7 +3080,7 @@ var require_Schema = __commonJS((exports) => {
3072
3080
  exports.Schema = Schema;
3073
3081
  });
3074
3082
 
3075
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/stringify/stringifyDocument.js
3083
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringifyDocument.js
3076
3084
  var require_stringifyDocument = __commonJS((exports) => {
3077
3085
  var identity = require_identity();
3078
3086
  var stringify = require_stringify();
@@ -3152,7 +3160,7 @@ var require_stringifyDocument = __commonJS((exports) => {
3152
3160
  exports.stringifyDocument = stringifyDocument;
3153
3161
  });
3154
3162
 
3155
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/doc/Document.js
3163
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/doc/Document.js
3156
3164
  var require_Document = __commonJS((exports) => {
3157
3165
  var Alias = require_Alias();
3158
3166
  var Collection = require_Collection();
@@ -3387,7 +3395,7 @@ var require_Document = __commonJS((exports) => {
3387
3395
  exports.Document = Document;
3388
3396
  });
3389
3397
 
3390
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/errors.js
3398
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/errors.js
3391
3399
  var require_errors = __commonJS((exports) => {
3392
3400
  class YAMLError extends Error {
3393
3401
  constructor(name, pos, code, message) {
@@ -3452,7 +3460,7 @@ ${pointer}
3452
3460
  exports.prettifyError = prettifyError;
3453
3461
  });
3454
3462
 
3455
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/resolve-props.js
3463
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-props.js
3456
3464
  var require_resolve_props = __commonJS((exports) => {
3457
3465
  function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIndent, startOnNewline }) {
3458
3466
  let spaceBefore = false;
@@ -3582,7 +3590,7 @@ var require_resolve_props = __commonJS((exports) => {
3582
3590
  exports.resolveProps = resolveProps;
3583
3591
  });
3584
3592
 
3585
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/util-contains-newline.js
3593
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/util-contains-newline.js
3586
3594
  var require_util_contains_newline = __commonJS((exports) => {
3587
3595
  function containsNewline(key) {
3588
3596
  if (!key)
@@ -3622,7 +3630,7 @@ var require_util_contains_newline = __commonJS((exports) => {
3622
3630
  exports.containsNewline = containsNewline;
3623
3631
  });
3624
3632
 
3625
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/util-flow-indent-check.js
3633
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/util-flow-indent-check.js
3626
3634
  var require_util_flow_indent_check = __commonJS((exports) => {
3627
3635
  var utilContainsNewline = require_util_contains_newline();
3628
3636
  function flowIndentCheck(indent, fc, onError) {
@@ -3637,7 +3645,7 @@ var require_util_flow_indent_check = __commonJS((exports) => {
3637
3645
  exports.flowIndentCheck = flowIndentCheck;
3638
3646
  });
3639
3647
 
3640
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/util-map-includes.js
3648
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/util-map-includes.js
3641
3649
  var require_util_map_includes = __commonJS((exports) => {
3642
3650
  var identity = require_identity();
3643
3651
  function mapIncludes(ctx, items, search) {
@@ -3650,7 +3658,7 @@ var require_util_map_includes = __commonJS((exports) => {
3650
3658
  exports.mapIncludes = mapIncludes;
3651
3659
  });
3652
3660
 
3653
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/resolve-block-map.js
3661
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-block-map.js
3654
3662
  var require_resolve_block_map = __commonJS((exports) => {
3655
3663
  var Pair = require_Pair();
3656
3664
  var YAMLMap = require_YAMLMap();
@@ -3757,7 +3765,7 @@ var require_resolve_block_map = __commonJS((exports) => {
3757
3765
  exports.resolveBlockMap = resolveBlockMap;
3758
3766
  });
3759
3767
 
3760
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/resolve-block-seq.js
3768
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-block-seq.js
3761
3769
  var require_resolve_block_seq = __commonJS((exports) => {
3762
3770
  var YAMLSeq = require_YAMLSeq();
3763
3771
  var resolveProps = require_resolve_props();
@@ -3805,7 +3813,7 @@ var require_resolve_block_seq = __commonJS((exports) => {
3805
3813
  exports.resolveBlockSeq = resolveBlockSeq;
3806
3814
  });
3807
3815
 
3808
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/resolve-end.js
3816
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-end.js
3809
3817
  var require_resolve_end = __commonJS((exports) => {
3810
3818
  function resolveEnd(end, offset, reqSpace, onError) {
3811
3819
  let comment = "";
@@ -3845,7 +3853,7 @@ var require_resolve_end = __commonJS((exports) => {
3845
3853
  exports.resolveEnd = resolveEnd;
3846
3854
  });
3847
3855
 
3848
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/resolve-flow-collection.js
3856
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-flow-collection.js
3849
3857
  var require_resolve_flow_collection = __commonJS((exports) => {
3850
3858
  var identity = require_identity();
3851
3859
  var Pair = require_Pair();
@@ -4036,7 +4044,7 @@ var require_resolve_flow_collection = __commonJS((exports) => {
4036
4044
  exports.resolveFlowCollection = resolveFlowCollection;
4037
4045
  });
4038
4046
 
4039
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/compose-collection.js
4047
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/compose-collection.js
4040
4048
  var require_compose_collection = __commonJS((exports) => {
4041
4049
  var identity = require_identity();
4042
4050
  var Scalar = require_Scalar();
@@ -4098,7 +4106,7 @@ var require_compose_collection = __commonJS((exports) => {
4098
4106
  exports.composeCollection = composeCollection;
4099
4107
  });
4100
4108
 
4101
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/resolve-block-scalar.js
4109
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-block-scalar.js
4102
4110
  var require_resolve_block_scalar = __commonJS((exports) => {
4103
4111
  var Scalar = require_Scalar();
4104
4112
  function resolveBlockScalar(ctx, scalar, onError) {
@@ -4291,7 +4299,7 @@ var require_resolve_block_scalar = __commonJS((exports) => {
4291
4299
  exports.resolveBlockScalar = resolveBlockScalar;
4292
4300
  });
4293
4301
 
4294
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/resolve-flow-scalar.js
4302
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-flow-scalar.js
4295
4303
  var require_resolve_flow_scalar = __commonJS((exports) => {
4296
4304
  var Scalar = require_Scalar();
4297
4305
  var resolveEnd = require_resolve_end();
@@ -4507,7 +4515,7 @@ var require_resolve_flow_scalar = __commonJS((exports) => {
4507
4515
  exports.resolveFlowScalar = resolveFlowScalar;
4508
4516
  });
4509
4517
 
4510
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/compose-scalar.js
4518
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/compose-scalar.js
4511
4519
  var require_compose_scalar = __commonJS((exports) => {
4512
4520
  var identity = require_identity();
4513
4521
  var Scalar = require_Scalar();
@@ -4585,7 +4593,7 @@ var require_compose_scalar = __commonJS((exports) => {
4585
4593
  exports.composeScalar = composeScalar;
4586
4594
  });
4587
4595
 
4588
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/util-empty-scalar-position.js
4596
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/util-empty-scalar-position.js
4589
4597
  var require_util_empty_scalar_position = __commonJS((exports) => {
4590
4598
  function emptyScalarPosition(offset, before, pos) {
4591
4599
  if (before) {
@@ -4612,7 +4620,7 @@ var require_util_empty_scalar_position = __commonJS((exports) => {
4612
4620
  exports.emptyScalarPosition = emptyScalarPosition;
4613
4621
  });
4614
4622
 
4615
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/compose-node.js
4623
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/compose-node.js
4616
4624
  var require_compose_node = __commonJS((exports) => {
4617
4625
  var Alias = require_Alias();
4618
4626
  var identity = require_identity();
@@ -4643,17 +4651,22 @@ var require_compose_node = __commonJS((exports) => {
4643
4651
  case "block-map":
4644
4652
  case "block-seq":
4645
4653
  case "flow-collection":
4646
- node = composeCollection.composeCollection(CN, ctx, token, props, onError);
4647
- if (anchor)
4648
- node.anchor = anchor.source.substring(1);
4654
+ try {
4655
+ node = composeCollection.composeCollection(CN, ctx, token, props, onError);
4656
+ if (anchor)
4657
+ node.anchor = anchor.source.substring(1);
4658
+ } catch (error) {
4659
+ const message = error instanceof Error ? error.message : String(error);
4660
+ onError(token, "RESOURCE_EXHAUSTION", message);
4661
+ }
4649
4662
  break;
4650
4663
  default: {
4651
4664
  const message = token.type === "error" ? token.message : `Unsupported token (type: ${token.type})`;
4652
4665
  onError(token, "UNEXPECTED_TOKEN", message);
4653
- node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError);
4654
4666
  isSrcToken = false;
4655
4667
  }
4656
4668
  }
4669
+ node ?? (node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError));
4657
4670
  if (anchor && node.anchor === "")
4658
4671
  onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string");
4659
4672
  if (atKey && ctx.options.stringKeys && (!identity.isScalar(node) || typeof node.value !== "string" || node.tag && node.tag !== "tag:yaml.org,2002:str")) {
@@ -4710,7 +4723,7 @@ var require_compose_node = __commonJS((exports) => {
4710
4723
  exports.composeNode = composeNode;
4711
4724
  });
4712
4725
 
4713
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/compose-doc.js
4726
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/compose-doc.js
4714
4727
  var require_compose_doc = __commonJS((exports) => {
4715
4728
  var Document = require_Document();
4716
4729
  var composeNode = require_compose_node();
@@ -4750,7 +4763,7 @@ var require_compose_doc = __commonJS((exports) => {
4750
4763
  exports.composeDoc = composeDoc;
4751
4764
  });
4752
4765
 
4753
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/compose/composer.js
4766
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/composer.js
4754
4767
  var require_composer = __commonJS((exports) => {
4755
4768
  var node_process = __require("process");
4756
4769
  var directives = require_directives();
@@ -4939,7 +4952,7 @@ ${end.comment}` : end.comment;
4939
4952
  exports.Composer = Composer;
4940
4953
  });
4941
4954
 
4942
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/parse/cst-scalar.js
4955
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/cst-scalar.js
4943
4956
  var require_cst_scalar = __commonJS((exports) => {
4944
4957
  var resolveBlockScalar = require_resolve_block_scalar();
4945
4958
  var resolveFlowScalar = require_resolve_flow_scalar();
@@ -5129,7 +5142,7 @@ var require_cst_scalar = __commonJS((exports) => {
5129
5142
  exports.setScalarValue = setScalarValue;
5130
5143
  });
5131
5144
 
5132
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/parse/cst-stringify.js
5145
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/cst-stringify.js
5133
5146
  var require_cst_stringify = __commonJS((exports) => {
5134
5147
  var stringify = (cst) => ("type" in cst) ? stringifyToken(cst) : stringifyItem(cst);
5135
5148
  function stringifyToken(token) {
@@ -5187,7 +5200,7 @@ var require_cst_stringify = __commonJS((exports) => {
5187
5200
  exports.stringify = stringify;
5188
5201
  });
5189
5202
 
5190
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/parse/cst-visit.js
5203
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/cst-visit.js
5191
5204
  var require_cst_visit = __commonJS((exports) => {
5192
5205
  var BREAK = Symbol("break visit");
5193
5206
  var SKIP = Symbol("skip children");
@@ -5246,7 +5259,7 @@ var require_cst_visit = __commonJS((exports) => {
5246
5259
  exports.visit = visit;
5247
5260
  });
5248
5261
 
5249
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/parse/cst.js
5262
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/cst.js
5250
5263
  var require_cst = __commonJS((exports) => {
5251
5264
  var cstScalar = require_cst_scalar();
5252
5265
  var cstStringify = require_cst_stringify();
@@ -5347,7 +5360,7 @@ var require_cst = __commonJS((exports) => {
5347
5360
  exports.tokenType = tokenType;
5348
5361
  });
5349
5362
 
5350
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/parse/lexer.js
5363
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/lexer.js
5351
5364
  var require_lexer = __commonJS((exports) => {
5352
5365
  var cst = require_cst();
5353
5366
  function isEmpty(ch) {
@@ -5933,7 +5946,7 @@ var require_lexer = __commonJS((exports) => {
5933
5946
  exports.Lexer = Lexer;
5934
5947
  });
5935
5948
 
5936
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/parse/line-counter.js
5949
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/line-counter.js
5937
5950
  var require_line_counter = __commonJS((exports) => {
5938
5951
  class LineCounter {
5939
5952
  constructor() {
@@ -5961,7 +5974,7 @@ var require_line_counter = __commonJS((exports) => {
5961
5974
  exports.LineCounter = LineCounter;
5962
5975
  });
5963
5976
 
5964
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/parse/parser.js
5977
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/parser.js
5965
5978
  var require_parser = __commonJS((exports) => {
5966
5979
  var node_process = __require("process");
5967
5980
  var cst = require_cst();
@@ -6810,7 +6823,7 @@ var require_parser = __commonJS((exports) => {
6810
6823
  exports.Parser = Parser;
6811
6824
  });
6812
6825
 
6813
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/public-api.js
6826
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/public-api.js
6814
6827
  var require_public_api = __commonJS((exports) => {
6815
6828
  var composer = require_composer();
6816
6829
  var Document = require_Document();
@@ -6906,7 +6919,7 @@ var require_public_api = __commonJS((exports) => {
6906
6919
 
6907
6920
  // backend/src/server.ts
6908
6921
  import { randomUUID as randomUUID3 } from "crypto";
6909
- import { join as join6, resolve as resolve6 } from "path";
6922
+ import { join as join6, resolve as resolve7 } from "path";
6910
6923
  import { mkdirSync } from "fs";
6911
6924
  import { networkInterfaces } from "os";
6912
6925
 
@@ -6934,6 +6947,27 @@ var log = {
6934
6947
  // backend/src/adapters/terminal.ts
6935
6948
  var textDecoder = new TextDecoder;
6936
6949
  var textEncoder = new TextEncoder;
6950
+ function detectPtyWrapper() {
6951
+ if (process.platform === "darwin")
6952
+ return "python3";
6953
+ const scriptResult = Bun.spawnSync(["which", "script"], { stdout: "ignore", stderr: "ignore" });
6954
+ if (scriptResult.exitCode === 0)
6955
+ return "script";
6956
+ const py3Result = Bun.spawnSync(["which", "python3"], { stdout: "ignore", stderr: "ignore" });
6957
+ if (py3Result.exitCode === 0)
6958
+ return "python3";
6959
+ return null;
6960
+ }
6961
+ var ptyWrapper = detectPtyWrapper();
6962
+ function buildPtyArgs(cmd) {
6963
+ if (ptyWrapper === "python3") {
6964
+ return ["python3", "-c", "import pty,sys;pty.spawn(sys.argv[1:])", "bash", "-c", cmd];
6965
+ }
6966
+ if (ptyWrapper === "script") {
6967
+ return ["script", "-q", "-c", cmd, "/dev/null"];
6968
+ }
6969
+ throw new Error("No PTY wrapper found. Install util-linux (provides 'script') or python3, then restart the server.");
6970
+ }
6937
6971
  var DASH_PORT = Bun.env.PORT || "5111";
6938
6972
  var SESSION_PREFIX = `wm-dash-${DASH_PORT}-`;
6939
6973
  var MAX_SCROLLBACK_BYTES = 1 * 1024 * 1024;
@@ -7014,8 +7048,7 @@ async function attach(attachId, target, cols, rows, initialPane) {
7014
7048
  rows,
7015
7049
  initialPane
7016
7050
  });
7017
- const scriptArgs = process.platform === "darwin" ? ["python3", "-c", "import pty,sys;pty.spawn(sys.argv[1:])", "bash", "-c", cmd] : ["script", "-q", "-c", cmd, "/dev/null"];
7018
- const proc = Bun.spawn(scriptArgs, {
7051
+ const proc = Bun.spawn(buildPtyArgs(cmd), {
7019
7052
  stdin: "pipe",
7020
7053
  stdout: "pipe",
7021
7054
  stderr: "pipe",
@@ -7172,6 +7205,10 @@ async function sendPrompt(worktreeId, target, text, paneIndex = 0, preamble) {
7172
7205
  if (paste.exitCode !== 0) {
7173
7206
  return { ok: false, error: `paste-buffer failed${paste.stderr ? `: ${paste.stderr}` : ""}` };
7174
7207
  }
7208
+ const enter = await tmuxExec(["tmux", "send-keys", "-t", paneTarget, "Enter"]);
7209
+ if (enter.exitCode !== 0) {
7210
+ return { ok: false, error: `send-keys Enter failed${enter.stderr ? `: ${enter.stderr}` : ""}` };
7211
+ }
7175
7212
  return { ok: true };
7176
7213
  }
7177
7214
 
@@ -7200,7 +7237,7 @@ async function loadControlToken() {
7200
7237
  import { readFileSync } from "fs";
7201
7238
  import { dirname as dirname2, join, resolve } from "path";
7202
7239
 
7203
- // node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/index.js
7240
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/index.js
7204
7241
  var composer = require_composer();
7205
7242
  var Document = require_Document();
7206
7243
  var Schema = require_Schema();
@@ -7256,7 +7293,8 @@ var DEFAULT_CONFIG = {
7256
7293
  workspace: {
7257
7294
  mainBranch: "main",
7258
7295
  worktreeRoot: "../worktrees",
7259
- defaultAgent: "claude"
7296
+ defaultAgent: "claude",
7297
+ autoPull: { enabled: false, intervalSeconds: 300 }
7260
7298
  },
7261
7299
  profiles: {
7262
7300
  default: {
@@ -7268,7 +7306,7 @@ var DEFAULT_CONFIG = {
7268
7306
  services: [],
7269
7307
  startupEnvs: {},
7270
7308
  integrations: {
7271
- github: { linkedRepos: [] },
7309
+ github: { linkedRepos: [], autoRemoveOnMerge: false },
7272
7310
  linear: { enabled: true, autoCreateWorktrees: false, createTicketOption: false }
7273
7311
  },
7274
7312
  lifecycleHooks: {},
@@ -7330,6 +7368,9 @@ function parsePane(raw, index) {
7330
7368
  if (typeof raw.command !== "string" || !raw.command.trim())
7331
7369
  return null;
7332
7370
  pane.command = raw.command.trim();
7371
+ if (typeof raw.workingDir === "string" && raw.workingDir.trim()) {
7372
+ pane.workingDir = raw.workingDir.trim();
7373
+ }
7333
7374
  }
7334
7375
  return pane;
7335
7376
  }
@@ -7427,6 +7468,13 @@ function parseAutoName(raw) {
7427
7468
  ...typeof raw.system_prompt === "string" && raw.system_prompt.trim() ? { systemPrompt: raw.system_prompt.trim() } : {}
7428
7469
  };
7429
7470
  }
7471
+ function parseAutoPull(raw) {
7472
+ if (!isRecord(raw))
7473
+ return DEFAULT_CONFIG.workspace.autoPull;
7474
+ const enabled = typeof raw.enabled === "boolean" ? raw.enabled : false;
7475
+ const interval = typeof raw.intervalSeconds === "number" && Number.isFinite(raw.intervalSeconds) && raw.intervalSeconds >= 30 ? raw.intervalSeconds : 300;
7476
+ return { enabled, intervalSeconds: interval };
7477
+ }
7430
7478
  function parseLinkedRepos(raw) {
7431
7479
  if (!Array.isArray(raw))
7432
7480
  return [];
@@ -7460,14 +7508,16 @@ function parseProjectConfig(parsed) {
7460
7508
  workspace: {
7461
7509
  mainBranch: isRecord(parsed.workspace) && typeof parsed.workspace.mainBranch === "string" ? parsed.workspace.mainBranch : DEFAULT_CONFIG.workspace.mainBranch,
7462
7510
  worktreeRoot: isRecord(parsed.workspace) && typeof parsed.workspace.worktreeRoot === "string" ? parsed.workspace.worktreeRoot : DEFAULT_CONFIG.workspace.worktreeRoot,
7463
- defaultAgent: isRecord(parsed.workspace) ? parseAgentKind(parsed.workspace.defaultAgent) : DEFAULT_CONFIG.workspace.defaultAgent
7511
+ defaultAgent: isRecord(parsed.workspace) ? parseAgentKind(parsed.workspace.defaultAgent) : DEFAULT_CONFIG.workspace.defaultAgent,
7512
+ autoPull: isRecord(parsed.workspace) ? parseAutoPull(parsed.workspace.autoPull) : DEFAULT_CONFIG.workspace.autoPull
7464
7513
  },
7465
7514
  profiles: parseProfiles(parsed.profiles, true),
7466
7515
  services: parseServices(parsed.services),
7467
7516
  startupEnvs: parseStartupEnvs(parsed.startupEnvs),
7468
7517
  integrations: {
7469
7518
  github: {
7470
- linkedRepos: isRecord(parsed.integrations) && isRecord(parsed.integrations.github) ? parseLinkedRepos(parsed.integrations.github.linkedRepos) : isRecord(parsed.integrations) && Array.isArray(parsed.integrations.github) ? parseLinkedRepos(parsed.integrations.github) : []
7519
+ linkedRepos: isRecord(parsed.integrations) && isRecord(parsed.integrations.github) ? parseLinkedRepos(parsed.integrations.github.linkedRepos) : isRecord(parsed.integrations) && Array.isArray(parsed.integrations.github) ? parseLinkedRepos(parsed.integrations.github) : [],
7520
+ autoRemoveOnMerge: isRecord(parsed.integrations) && isRecord(parsed.integrations.github) && typeof parsed.integrations.github.autoRemoveOnMerge === "boolean" ? parsed.integrations.github.autoRemoveOnMerge : DEFAULT_CONFIG.integrations.github.autoRemoveOnMerge
7471
7521
  },
7472
7522
  linear: {
7473
7523
  enabled: isRecord(parsed.integrations) && isRecord(parsed.integrations.linear) && typeof parsed.integrations.linear.enabled === "boolean" ? parsed.integrations.linear.enabled : DEFAULT_CONFIG.integrations.linear.enabled,
@@ -7500,11 +7550,36 @@ function parseLocalLinearOverlay(parsed) {
7500
7550
  overlay.teamId = linear.teamId.trim();
7501
7551
  return Object.keys(overlay).length > 0 ? overlay : null;
7502
7552
  }
7553
+ function parseLocalGitHubOverlay(parsed) {
7554
+ if (!isRecord(parsed.integrations))
7555
+ return null;
7556
+ const github = parsed.integrations.github;
7557
+ if (!isRecord(github))
7558
+ return null;
7559
+ const overlay = {};
7560
+ if (typeof github.autoRemoveOnMerge === "boolean")
7561
+ overlay.autoRemoveOnMerge = github.autoRemoveOnMerge;
7562
+ return Object.keys(overlay).length > 0 ? overlay : null;
7563
+ }
7564
+ function parseLocalAutoPullOverlay(parsed) {
7565
+ if (!isRecord(parsed.workspace))
7566
+ return null;
7567
+ const autoPull = parsed.workspace.autoPull;
7568
+ if (!isRecord(autoPull))
7569
+ return null;
7570
+ const overlay = {};
7571
+ if (typeof autoPull.enabled === "boolean")
7572
+ overlay.enabled = autoPull.enabled;
7573
+ if (typeof autoPull.intervalSeconds === "number" && Number.isFinite(autoPull.intervalSeconds) && autoPull.intervalSeconds >= 30) {
7574
+ overlay.intervalSeconds = autoPull.intervalSeconds;
7575
+ }
7576
+ return Object.keys(overlay).length > 0 ? overlay : null;
7577
+ }
7503
7578
  function loadLocalProjectConfigOverlay(root) {
7504
7579
  try {
7505
7580
  const text = readLocalConfigFile(root).trim();
7506
7581
  if (!text) {
7507
- return { worktreeRoot: null, profiles: {}, lifecycleHooks: {}, linear: null };
7582
+ return { worktreeRoot: null, profiles: {}, lifecycleHooks: {}, linear: null, github: null, autoPull: null };
7508
7583
  }
7509
7584
  const parsed = parseConfigDocument(text);
7510
7585
  const ws = isRecord(parsed.workspace) ? parsed.workspace : null;
@@ -7512,10 +7587,12 @@ function loadLocalProjectConfigOverlay(root) {
7512
7587
  worktreeRoot: ws && typeof ws.worktreeRoot === "string" ? ws.worktreeRoot : null,
7513
7588
  profiles: parseProfiles(parsed.profiles, false),
7514
7589
  lifecycleHooks: parseLifecycleHooks(parsed.lifecycleHooks),
7515
- linear: parseLocalLinearOverlay(parsed)
7590
+ linear: parseLocalLinearOverlay(parsed),
7591
+ github: parseLocalGitHubOverlay(parsed),
7592
+ autoPull: parseLocalAutoPullOverlay(parsed)
7516
7593
  };
7517
7594
  } catch {
7518
- return { worktreeRoot: null, profiles: {}, lifecycleHooks: {}, linear: null };
7595
+ return { worktreeRoot: null, profiles: {}, lifecycleHooks: {}, linear: null, github: null, autoPull: null };
7519
7596
  }
7520
7597
  }
7521
7598
  function mergeHookCommand(projectCommand, localCommand) {
@@ -7557,22 +7634,26 @@ function loadConfig(dir, options = {}) {
7557
7634
  projectConfig = defaultConfig();
7558
7635
  }
7559
7636
  const localOverlay = loadLocalProjectConfigOverlay(root);
7637
+ const workspace = localOverlay.worktreeRoot !== null || localOverlay.autoPull ? {
7638
+ ...projectConfig.workspace,
7639
+ ...localOverlay.worktreeRoot !== null ? { worktreeRoot: localOverlay.worktreeRoot } : {},
7640
+ ...localOverlay.autoPull ? { autoPull: { ...projectConfig.workspace.autoPull, ...localOverlay.autoPull } } : {}
7641
+ } : projectConfig.workspace;
7642
+ const hasIntegrationOverlay = localOverlay.linear || localOverlay.github;
7643
+ const integrations = hasIntegrationOverlay ? {
7644
+ ...projectConfig.integrations,
7645
+ ...localOverlay.linear ? { linear: { ...projectConfig.integrations.linear, ...localOverlay.linear } } : {},
7646
+ ...localOverlay.github ? { github: { ...projectConfig.integrations.github, ...localOverlay.github } } : {}
7647
+ } : projectConfig.integrations;
7560
7648
  return {
7561
7649
  ...projectConfig,
7562
- ...localOverlay.worktreeRoot !== null ? {
7563
- workspace: { ...projectConfig.workspace, worktreeRoot: localOverlay.worktreeRoot }
7564
- } : {},
7650
+ workspace,
7565
7651
  profiles: {
7566
7652
  ...cloneProfiles(projectConfig.profiles),
7567
7653
  ...cloneProfiles(localOverlay.profiles)
7568
7654
  },
7569
7655
  lifecycleHooks: mergeLifecycleHooks(projectConfig.lifecycleHooks, localOverlay.lifecycleHooks),
7570
- ...localOverlay.linear ? {
7571
- integrations: {
7572
- ...projectConfig.integrations,
7573
- linear: { ...projectConfig.integrations.linear, ...localOverlay.linear }
7574
- }
7575
- } : {}
7656
+ integrations
7576
7657
  };
7577
7658
  }
7578
7659
  async function persistLocalLinearConfig(dir, changes) {
@@ -7591,6 +7672,22 @@ async function persistLocalLinearConfig(dir, changes) {
7591
7672
  existing.integrations = integrations;
7592
7673
  await Bun.write(localPath, $stringify(existing));
7593
7674
  }
7675
+ async function persistLocalGitHubConfig(dir, changes) {
7676
+ const root = projectRoot(dir);
7677
+ const localPath = join(root, ".webmux.local.yaml");
7678
+ let existing = {};
7679
+ try {
7680
+ const text = readFileSync(localPath, "utf8").trim();
7681
+ if (text)
7682
+ existing = parseConfigDocument(text);
7683
+ } catch {}
7684
+ const integrations = isRecord(existing.integrations) ? { ...existing.integrations } : {};
7685
+ const github = isRecord(integrations.github) ? { ...integrations.github } : {};
7686
+ Object.assign(github, changes);
7687
+ integrations.github = github;
7688
+ existing.integrations = integrations;
7689
+ await Bun.write(localPath, $stringify(existing));
7690
+ }
7594
7691
  function expandTemplate(template, env) {
7595
7692
  return template.replace(/\$\{(\w+)\}/g, (_, key) => env[key] ?? "");
7596
7693
  }
@@ -7946,7 +8043,7 @@ async function createLinearIssue(input) {
7946
8043
  // backend/src/services/lifecycle-service.ts
7947
8044
  import { randomUUID as randomUUID2 } from "crypto";
7948
8045
  import { mkdir as mkdir4 } from "fs/promises";
7949
- import { dirname as dirname4, resolve as resolve4 } from "path";
8046
+ import { dirname as dirname4, resolve as resolve5 } from "path";
7950
8047
 
7951
8048
  // backend/src/adapters/agent-runtime.ts
7952
8049
  import { chmod as chmod2, mkdir as mkdir3 } from "fs/promises";
@@ -8069,7 +8166,7 @@ function isPrComment(raw) {
8069
8166
  function isCiCheck(raw) {
8070
8167
  if (!isRecord2(raw))
8071
8168
  return false;
8072
- return typeof raw.name === "string" && (raw.status === "pending" || raw.status === "success" || raw.status === "failed" || raw.status === "skipped") && typeof raw.url === "string" && (raw.runId === null || typeof raw.runId === "number");
8169
+ return typeof raw.name === "string" && (raw.status === "pending" || raw.status === "success" || raw.status === "failed" || raw.status === "skipped") && (raw.url === null || typeof raw.url === "string") && (raw.runId === null || typeof raw.runId === "number");
8073
8170
  }
8074
8171
  function isPrEntry(raw) {
8075
8172
  if (!isRecord2(raw))
@@ -8569,20 +8666,31 @@ function buildDockerAgentPaneCommand(input) {
8569
8666
  }
8570
8667
 
8571
8668
  // backend/src/services/session-service.ts
8669
+ import { resolve as resolve3 } from "path";
8670
+ function quoteShell2(value) {
8671
+ return `'${value.replaceAll("'", "'\\''")}'`;
8672
+ }
8572
8673
  function resolvePaneCwd(template, ctx) {
8573
8674
  return template.cwd === "repo" ? ctx.repoRoot : ctx.worktreePath;
8574
8675
  }
8575
- function resolvePaneStartupCommand(template, commands) {
8676
+ function buildCommandPaneStartupCommand(template, ctx) {
8677
+ if (!template.command) {
8678
+ throw new Error(`Pane "${template.id}" is kind=command but has no command`);
8679
+ }
8680
+ if (!template.workingDir) {
8681
+ return template.command;
8682
+ }
8683
+ const workingDir = resolve3(resolvePaneCwd(template, ctx), template.workingDir);
8684
+ return `cd -- ${quoteShell2(workingDir)} && ${template.command}`;
8685
+ }
8686
+ function resolvePaneStartupCommand(template, ctx) {
8576
8687
  switch (template.kind) {
8577
8688
  case "agent":
8578
- return commands.agent;
8689
+ return ctx.paneCommands.agent;
8579
8690
  case "shell":
8580
8691
  return;
8581
8692
  case "command":
8582
- if (!template.command) {
8583
- throw new Error(`Pane "${template.id}" is kind=command but has no command`);
8584
- }
8585
- return template.command;
8693
+ return buildCommandPaneStartupCommand(template, ctx);
8586
8694
  }
8587
8695
  }
8588
8696
  function planSessionLayout(projectRoot2, branch, templates, ctx) {
@@ -8590,7 +8698,7 @@ function planSessionLayout(projectRoot2, branch, templates, ctx) {
8590
8698
  throw new Error("At least one pane template is required");
8591
8699
  }
8592
8700
  const panes = templates.map((template, index) => {
8593
- const startupCommand = resolvePaneStartupCommand(template, ctx.paneCommands);
8701
+ const startupCommand = resolvePaneStartupCommand(template, ctx);
8594
8702
  return {
8595
8703
  id: template.id,
8596
8704
  index,
@@ -8652,7 +8760,7 @@ import { randomUUID } from "crypto";
8652
8760
 
8653
8761
  // backend/src/adapters/git.ts
8654
8762
  import { rmSync } from "fs";
8655
- import { resolve as resolve3 } from "path";
8763
+ import { resolve as resolve4 } from "path";
8656
8764
  function runGit(args, cwd) {
8657
8765
  const result = Bun.spawnSync(["git", ...args], {
8658
8766
  cwd,
@@ -8686,8 +8794,8 @@ function errorMessage(error) {
8686
8794
  return error instanceof Error ? error.message : String(error);
8687
8795
  }
8688
8796
  function isRegisteredWorktree(entries, worktreePath) {
8689
- const resolvedPath = resolve3(worktreePath);
8690
- return entries.some((entry) => resolve3(entry.path) === resolvedPath);
8797
+ const resolvedPath = resolve4(worktreePath);
8798
+ return entries.some((entry) => resolve4(entry.path) === resolvedPath);
8691
8799
  }
8692
8800
  function removeDirectory(path) {
8693
8801
  rmSync(path, {
@@ -8710,11 +8818,11 @@ function currentCheckoutRef(cwd) {
8710
8818
  }
8711
8819
  function resolveWorktreeRoot(cwd) {
8712
8820
  const output = runGit(["rev-parse", "--show-toplevel"], cwd);
8713
- return resolve3(cwd, output);
8821
+ return resolve4(cwd, output);
8714
8822
  }
8715
8823
  function resolveWorktreeGitDir(cwd) {
8716
8824
  const output = runGit(["rev-parse", "--git-dir"], cwd);
8717
- return resolve3(cwd, output);
8825
+ return resolve4(cwd, output);
8718
8826
  }
8719
8827
  function parseGitWorktreePorcelain(output) {
8720
8828
  const entries = [];
@@ -8772,6 +8880,14 @@ function listLocalGitBranches(cwd) {
8772
8880
  return output.split(`
8773
8881
  `).map((line) => line.trim()).filter((line) => line.length > 0);
8774
8882
  }
8883
+ function listRemoteGitBranches(cwd) {
8884
+ try {
8885
+ runGit(["fetch", "--prune", "origin"], cwd);
8886
+ } catch {}
8887
+ const output = runGit(["for-each-ref", "--format=%(refname:short)", "refs/remotes/origin"], cwd);
8888
+ return output.split(`
8889
+ `).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => line.replace(/^origin\//, "")).filter((name) => name !== "HEAD");
8890
+ }
8775
8891
  function readGitWorktreeStatus(cwd) {
8776
8892
  const dirtyOutput = runGit(["status", "--porcelain"], cwd);
8777
8893
  const commit = tryRunGit(["rev-parse", "HEAD"], cwd);
@@ -8819,6 +8935,9 @@ class BunGitGateway {
8819
8935
  listLocalBranches(cwd) {
8820
8936
  return listLocalGitBranches(cwd);
8821
8937
  }
8938
+ listRemoteBranches(cwd) {
8939
+ return listRemoteGitBranches(cwd);
8940
+ }
8822
8941
  readWorktreeStatus(cwd) {
8823
8942
  return readGitWorktreeStatus(cwd);
8824
8943
  }
@@ -8893,6 +9012,15 @@ class BunGitGateway {
8893
9012
  };
8894
9013
  });
8895
9014
  }
9015
+ fetchBranch(repoRoot, remote, branch) {
9016
+ return tryRunGit(["fetch", remote, branch], repoRoot);
9017
+ }
9018
+ fastForwardMerge(repoRoot, ref) {
9019
+ return tryRunGit(["merge", "--ff-only", ref], repoRoot);
9020
+ }
9021
+ hardReset(repoRoot, ref) {
9022
+ return tryRunGit(["reset", "--hard", ref], repoRoot);
9023
+ }
8896
9024
  }
8897
9025
 
8898
9026
  // backend/src/domain/model.ts
@@ -8947,6 +9075,7 @@ async function initializeManagedWorktree(opts) {
8947
9075
  schemaVersion: WORKTREE_META_SCHEMA_VERSION,
8948
9076
  worktreeId: opts.worktreeId ?? randomUUID(),
8949
9077
  branch: opts.branch,
9078
+ ...opts.baseBranch ? { baseBranch: opts.baseBranch } : {},
8950
9079
  createdAt,
8951
9080
  profile: opts.profile,
8952
9081
  agent: opts.agent,
@@ -8993,6 +9122,7 @@ async function createManagedWorktree(opts, deps = {}) {
8993
9122
  const initialized = await initializeManagedWorktree({
8994
9123
  gitDir,
8995
9124
  branch: opts.branch,
9125
+ baseBranch: opts.baseBranch,
8996
9126
  profile: opts.profile,
8997
9127
  agent: opts.agent,
8998
9128
  runtime: opts.runtime,
@@ -9065,19 +9195,34 @@ class LifecycleService {
9065
9195
  }
9066
9196
  async createWorktree(input) {
9067
9197
  const mode = input.mode ?? "new";
9198
+ const requestedBaseBranch = input.baseBranch?.trim();
9199
+ if (requestedBaseBranch && !isValidBranchName(requestedBaseBranch)) {
9200
+ throw new LifecycleError("Invalid base branch name", 400);
9201
+ }
9202
+ if (requestedBaseBranch && mode === "existing") {
9203
+ throw new LifecycleError("Base branch is only supported for new worktrees", 400);
9204
+ }
9068
9205
  const branch = await this.resolveBranch(input.branch, input.prompt, mode);
9206
+ if (requestedBaseBranch && requestedBaseBranch === branch) {
9207
+ throw new LifecycleError("Base branch must differ from branch name", 400);
9208
+ }
9209
+ const baseBranch = mode === "new" ? requestedBaseBranch || this.deps.config.workspace.mainBranch : undefined;
9069
9210
  this.ensureBranchAvailable(branch, mode);
9070
9211
  const { profileName, profile } = this.resolveProfile(input.profile);
9071
9212
  const agent = this.resolveAgent(input.agent);
9072
9213
  const worktreePath = this.resolveWorktreePath(branch);
9214
+ const createProgressBase = {
9215
+ branch,
9216
+ ...baseBranch ? { baseBranch } : {},
9217
+ path: worktreePath,
9218
+ profile: profileName,
9219
+ agent
9220
+ };
9073
9221
  const deleteBranchOnRollback = mode === "new";
9074
9222
  let initialized = null;
9075
9223
  try {
9076
9224
  await this.reportCreateProgress({
9077
- branch,
9078
- path: worktreePath,
9079
- profile: profileName,
9080
- agent,
9225
+ ...createProgressBase,
9081
9226
  phase: "creating_worktree"
9082
9227
  });
9083
9228
  await mkdir4(dirname4(worktreePath), { recursive: true });
@@ -9086,7 +9231,7 @@ class LifecycleService {
9086
9231
  worktreePath,
9087
9232
  branch,
9088
9233
  mode,
9089
- ...mode === "new" ? { baseBranch: this.deps.config.workspace.mainBranch } : {},
9234
+ ...baseBranch ? { baseBranch } : {},
9090
9235
  profile: profileName,
9091
9236
  agent,
9092
9237
  runtime: profile.runtime,
@@ -9100,10 +9245,7 @@ class LifecycleService {
9100
9245
  git: this.deps.git
9101
9246
  });
9102
9247
  await this.reportCreateProgress({
9103
- branch,
9104
- path: worktreePath,
9105
- profile: profileName,
9106
- agent,
9248
+ ...createProgressBase,
9107
9249
  phase: "running_post_create_hook"
9108
9250
  });
9109
9251
  await this.runLifecycleHook({
@@ -9118,10 +9260,7 @@ class LifecycleService {
9118
9260
  worktreePath
9119
9261
  });
9120
9262
  await this.reportCreateProgress({
9121
- branch,
9122
- path: worktreePath,
9123
- profile: profileName,
9124
- agent,
9263
+ ...createProgressBase,
9125
9264
  phase: "preparing_runtime"
9126
9265
  });
9127
9266
  await ensureAgentRuntimeArtifacts({
@@ -9129,10 +9268,7 @@ class LifecycleService {
9129
9268
  worktreePath
9130
9269
  });
9131
9270
  await this.reportCreateProgress({
9132
- branch,
9133
- path: worktreePath,
9134
- profile: profileName,
9135
- agent,
9271
+ ...createProgressBase,
9136
9272
  phase: "starting_session"
9137
9273
  });
9138
9274
  await this.materializeRuntimeSession({
@@ -9145,10 +9281,7 @@ class LifecycleService {
9145
9281
  launchMode: "fresh"
9146
9282
  });
9147
9283
  await this.reportCreateProgress({
9148
- branch,
9149
- path: worktreePath,
9150
- profile: profileName,
9151
- agent,
9284
+ ...createProgressBase,
9152
9285
  phase: "reconciling"
9153
9286
  });
9154
9287
  await this.deps.reconciliation.reconcile(this.deps.projectRoot, { force: true });
@@ -9246,8 +9379,13 @@ class LifecycleService {
9246
9379
  }
9247
9380
  listAvailableBranches() {
9248
9381
  const localBranches = this.listLocalBranches().filter((branch) => isValidBranchName(branch));
9382
+ const remoteBranches = this.listRemoteBranches().filter((branch) => isValidBranchName(branch));
9249
9383
  const checkedOutBranches = this.listCheckedOutBranches();
9250
- return localBranches.filter((branch) => !checkedOutBranches.has(branch)).sort((left, right) => left.localeCompare(right)).map((name) => ({ name }));
9384
+ const allBranches = [...new Set([...localBranches, ...remoteBranches])];
9385
+ return allBranches.filter((branch) => !checkedOutBranches.has(branch)).sort((left, right) => left.localeCompare(right)).map((name) => ({ name }));
9386
+ }
9387
+ listBaseBranches() {
9388
+ return this.listLocalBranches().filter((branch) => isValidBranchName(branch)).sort((left, right) => left.localeCompare(right)).map((name) => ({ name }));
9251
9389
  }
9252
9390
  async resolveBranch(rawBranch, prompt, mode) {
9253
9391
  const explicitBranch = rawBranch?.trim();
@@ -9315,17 +9453,20 @@ class LifecycleService {
9315
9453
  return allocateServicePorts(metas, this.deps.config.services);
9316
9454
  }
9317
9455
  resolveWorktreePath(branch) {
9318
- return resolve4(this.deps.projectRoot, this.deps.config.workspace.worktreeRoot, branch);
9456
+ return resolve5(this.deps.projectRoot, this.deps.config.workspace.worktreeRoot, branch);
9319
9457
  }
9320
9458
  listLocalBranches() {
9321
- return this.deps.git.listLocalBranches(resolve4(this.deps.projectRoot));
9459
+ return this.deps.git.listLocalBranches(resolve5(this.deps.projectRoot));
9460
+ }
9461
+ listRemoteBranches() {
9462
+ return this.deps.git.listRemoteBranches(resolve5(this.deps.projectRoot));
9322
9463
  }
9323
9464
  listCheckedOutBranches() {
9324
- return new Set(this.deps.git.listWorktrees(resolve4(this.deps.projectRoot)).filter((entry) => !entry.bare && entry.branch !== null).map((entry) => entry.branch));
9465
+ return new Set(this.deps.git.listWorktrees(resolve5(this.deps.projectRoot)).filter((entry) => !entry.bare && entry.branch !== null).map((entry) => entry.branch));
9325
9466
  }
9326
9467
  listProjectWorktrees() {
9327
- const projectRoot2 = resolve4(this.deps.projectRoot);
9328
- return this.deps.git.listWorktrees(projectRoot2).filter((entry) => !entry.bare && resolve4(entry.path) !== projectRoot2);
9468
+ const projectRoot2 = resolve5(this.deps.projectRoot);
9469
+ return this.deps.git.listWorktrees(projectRoot2).filter((entry) => !entry.bare && resolve5(entry.path) !== projectRoot2);
9329
9470
  }
9330
9471
  async readManagedMetas() {
9331
9472
  const metas = await Promise.all(this.listProjectWorktrees().map(async (entry) => {
@@ -9560,7 +9701,7 @@ class LifecycleService {
9560
9701
  }
9561
9702
 
9562
9703
  // backend/src/services/native-terminal-service.ts
9563
- function quoteShell2(value) {
9704
+ function quoteShell3(value) {
9564
9705
  return `'${value.replaceAll("'", "'\\''")}'`;
9565
9706
  }
9566
9707
  function sanitizeSessionSuffix(value) {
@@ -9572,10 +9713,10 @@ function buildNativeTerminalTmuxCommand(env) {
9572
9713
  const socket = env.WEBMUX_ISOLATED_TMUX_SOCKET;
9573
9714
  const config = env.WEBMUX_ISOLATED_TMUX_CONFIG;
9574
9715
  if (socket && config) {
9575
- return `tmux -L ${quoteShell2(socket)} -f ${quoteShell2(config)}`;
9716
+ return `tmux -L ${quoteShell3(socket)} -f ${quoteShell3(config)}`;
9576
9717
  }
9577
9718
  if (socket) {
9578
- return `tmux -L ${quoteShell2(socket)}`;
9719
+ return `tmux -L ${quoteShell3(socket)}`;
9579
9720
  }
9580
9721
  return "tmux";
9581
9722
  }
@@ -9599,8 +9740,8 @@ function buildNativeTerminalLaunch(input) {
9599
9740
  const groupedSessionPrefix = `${sessionPrefix}${sanitizeSessionSuffix(state.worktreeId)}`;
9600
9741
  const attachScript = [
9601
9742
  `g_name="${groupedSessionPrefix}-${"$"}$-$(date +%s)"`,
9602
- `owner_session_name=${quoteShell2(state.session.sessionName)}`,
9603
- `window_name=${quoteShell2(state.session.windowName)}`,
9743
+ `owner_session_name=${quoteShell3(state.session.sessionName)}`,
9744
+ `window_name=${quoteShell3(state.session.windowName)}`,
9604
9745
  `grouped_window_target="${"$"}g_name:${"$"}window_name"`,
9605
9746
  `grouped_pane_target="${"$"}grouped_window_target.0"`,
9606
9747
  `cleanup() { ${tmuxCommand} kill-session -t "${"$"}g_name" >/dev/null 2>&1 || true; }`,
@@ -9621,7 +9762,7 @@ function buildNativeTerminalLaunch(input) {
9621
9762
  worktreeId: state.worktreeId,
9622
9763
  branch: state.branch,
9623
9764
  path: state.path,
9624
- shellCommand: `/bin/sh -lc ${quoteShell2(attachScript)}`
9765
+ shellCommand: `/bin/sh -lc ${quoteShell3(attachScript)}`
9625
9766
  }
9626
9767
  };
9627
9768
  }
@@ -9679,17 +9820,31 @@ var etagCache = new Map;
9679
9820
  function summarizeChecks(checks) {
9680
9821
  if (!checks || checks.length === 0)
9681
9822
  return "none";
9682
- const allDone = checks.every((c) => c.status === "COMPLETED");
9823
+ const allDone = checks.every((c) => c.__typename === "StatusContext" ? c.state !== "PENDING" && c.state !== "EXPECTED" : c.status === "COMPLETED");
9683
9824
  if (!allDone)
9684
9825
  return "pending";
9685
- const allPass = checks.every((c) => c.conclusion === "SUCCESS" || c.conclusion === "NEUTRAL" || c.conclusion === "SKIPPED");
9826
+ const allPass = checks.every((c) => {
9827
+ if (c.__typename === "StatusContext")
9828
+ return c.state === "SUCCESS";
9829
+ return c.conclusion === "SUCCESS" || c.conclusion === "NEUTRAL" || c.conclusion === "SKIPPED";
9830
+ });
9686
9831
  return allPass ? "success" : "failed";
9687
9832
  }
9688
9833
  function parseRunId(detailsUrl) {
9834
+ if (!detailsUrl)
9835
+ return null;
9689
9836
  const match = detailsUrl.match(/\/actions\/runs\/(\d+)/);
9690
9837
  return match ? parseInt(match[1], 10) : null;
9691
9838
  }
9692
9839
  function deriveCheckStatus(check) {
9840
+ if (check.__typename === "StatusContext") {
9841
+ const s = check.state;
9842
+ if (s === "SUCCESS")
9843
+ return "success";
9844
+ if (s === "PENDING" || s === "EXPECTED")
9845
+ return "pending";
9846
+ return "failed";
9847
+ }
9693
9848
  if (check.status !== "COMPLETED")
9694
9849
  return "pending";
9695
9850
  const c = check.conclusion;
@@ -9702,12 +9857,16 @@ function deriveCheckStatus(check) {
9702
9857
  function mapChecks(checks) {
9703
9858
  if (!checks || checks.length === 0)
9704
9859
  return [];
9705
- return checks.map((c) => ({
9706
- name: c.name,
9707
- status: deriveCheckStatus(c),
9708
- url: c.detailsUrl,
9709
- runId: parseRunId(c.detailsUrl)
9710
- }));
9860
+ return checks.map((c) => {
9861
+ const name = c.__typename === "StatusContext" ? c.context : c.name;
9862
+ const url = c.__typename === "StatusContext" ? c.targetUrl : c.detailsUrl;
9863
+ return {
9864
+ name,
9865
+ status: deriveCheckStatus(c),
9866
+ url,
9867
+ runId: parseRunId(url)
9868
+ };
9869
+ });
9711
9870
  }
9712
9871
  function parseReviewComments(json) {
9713
9872
  const raw = JSON.parse(json);
@@ -9974,7 +10133,7 @@ async function syncPrStatus(getWorktreeGitDirs, linkedRepos, projectDir) {
9974
10133
  etagCache.delete(key);
9975
10134
  }
9976
10135
  }
9977
- function startPrMonitor(getWorktreeGitDirs, linkedRepos, projectDir, intervalMs = 1e4, isActive) {
10136
+ function startPrMonitor(getWorktreeGitDirs, linkedRepos, projectDir, intervalMs = 1e4, isActive, onAfterSync) {
9978
10137
  const run = async () => {
9979
10138
  if (isActive && !isActive()) {
9980
10139
  log.debug("[pr] skipping PR sync: no active clients");
@@ -9983,6 +10142,11 @@ function startPrMonitor(getWorktreeGitDirs, linkedRepos, projectDir, intervalMs
9983
10142
  await syncPrStatus(getWorktreeGitDirs, linkedRepos, projectDir).catch((err) => {
9984
10143
  log.error(`[pr] sync error: ${err}`);
9985
10144
  });
10145
+ if (onAfterSync) {
10146
+ await onAfterSync().catch((err) => {
10147
+ log.error(`[pr] after-sync hook error: ${err}`);
10148
+ });
10149
+ }
9986
10150
  };
9987
10151
  return startSerializedInterval(run, intervalMs);
9988
10152
  }
@@ -10046,6 +10210,99 @@ function resetProcessedIssues() {
10046
10210
  processedIssueIds.clear();
10047
10211
  }
10048
10212
 
10213
+ // backend/src/services/auto-remove-service.ts
10214
+ async function runAutoRemove(deps) {
10215
+ const worktrees = deps.git.listWorktrees(deps.projectRoot).filter((e) => !e.bare && e.branch !== null && e.path !== deps.projectRoot);
10216
+ for (const entry of worktrees) {
10217
+ const branch = entry.branch;
10218
+ if (deps.isRemoving(branch))
10219
+ continue;
10220
+ const prs = await readWorktreePrs(deps.git.resolveWorktreeGitDir(entry.path));
10221
+ if (prs.length === 0)
10222
+ continue;
10223
+ if (!prs.every((pr) => pr.state === "merged"))
10224
+ continue;
10225
+ if (deps.git.readWorktreeStatus(entry.path).dirty) {
10226
+ log.info(`[auto-remove] skipping dirty worktree: ${branch}`);
10227
+ continue;
10228
+ }
10229
+ deps.markRemoving(branch);
10230
+ try {
10231
+ log.info(`[auto-remove] removing merged worktree: ${branch}`);
10232
+ await deps.lifecycleService.removeWorktree(branch);
10233
+ deps.notifications.notify({
10234
+ branch,
10235
+ type: "worktree_auto_removed",
10236
+ message: `Worktree auto-removed after merge: ${branch}`
10237
+ });
10238
+ log.info(`[auto-remove] removed worktree: ${branch}`);
10239
+ } catch (err) {
10240
+ const msg = err instanceof Error ? err.message : String(err);
10241
+ log.error(`[auto-remove] failed to remove worktree ${branch}: ${msg}`);
10242
+ } finally {
10243
+ deps.unmarkRemoving(branch);
10244
+ }
10245
+ }
10246
+ }
10247
+
10248
+ // backend/src/services/auto-pull-service.ts
10249
+ function pullMainBranch(deps) {
10250
+ const { git, projectRoot: projectRoot2, mainBranch } = deps;
10251
+ const beforeCommit = git.readWorktreeStatus(projectRoot2).currentCommit;
10252
+ const fetchResult = git.fetchBranch(projectRoot2, "origin", mainBranch);
10253
+ if (!fetchResult.ok) {
10254
+ return { status: "fetch_failed", error: fetchResult.stderr };
10255
+ }
10256
+ const mergeResult = git.fastForwardMerge(projectRoot2, `origin/${mainBranch}`);
10257
+ if (!mergeResult.ok) {
10258
+ return { status: "merge_failed", error: mergeResult.stderr };
10259
+ }
10260
+ const afterStatus = git.readWorktreeStatus(projectRoot2);
10261
+ const afterCommit = afterStatus.currentCommit;
10262
+ if (beforeCommit === afterCommit) {
10263
+ return { status: "already_up_to_date" };
10264
+ }
10265
+ return { status: "updated", from: beforeCommit ?? "unknown", to: afterCommit ?? "unknown" };
10266
+ }
10267
+ function forcePullMainBranch(deps) {
10268
+ const { git, projectRoot: projectRoot2, mainBranch } = deps;
10269
+ const beforeCommit = git.readWorktreeStatus(projectRoot2).currentCommit;
10270
+ const fetchResult = git.fetchBranch(projectRoot2, "origin", mainBranch);
10271
+ if (!fetchResult.ok) {
10272
+ return { status: "fetch_failed", error: fetchResult.stderr };
10273
+ }
10274
+ const resetResult = git.hardReset(projectRoot2, `origin/${mainBranch}`);
10275
+ if (!resetResult.ok) {
10276
+ return { status: "merge_failed", error: resetResult.stderr };
10277
+ }
10278
+ const afterCommit = git.readWorktreeStatus(projectRoot2).currentCommit;
10279
+ if (beforeCommit === afterCommit) {
10280
+ return { status: "already_up_to_date" };
10281
+ }
10282
+ return { status: "updated", from: beforeCommit ?? "unknown", to: afterCommit ?? "unknown" };
10283
+ }
10284
+ function startAutoPullMonitor(deps, intervalMs) {
10285
+ log.info(`[auto-pull] monitor started (interval: ${intervalMs}ms)`);
10286
+ const run = async () => {
10287
+ const result = pullMainBranch(deps);
10288
+ switch (result.status) {
10289
+ case "updated":
10290
+ log.info(`[auto-pull] updated ${deps.mainBranch}: ${result.from.slice(0, 8)} \u2192 ${result.to.slice(0, 8)}`);
10291
+ break;
10292
+ case "already_up_to_date":
10293
+ log.debug("[auto-pull] already up to date");
10294
+ break;
10295
+ case "fetch_failed":
10296
+ log.warn(`[auto-pull] fetch failed: ${result.error}`);
10297
+ break;
10298
+ case "merge_failed":
10299
+ log.warn(`[auto-pull] merge failed (ff-only): ${result.error}`);
10300
+ break;
10301
+ }
10302
+ };
10303
+ return startSerializedInterval(run, intervalMs);
10304
+ }
10305
+
10049
10306
  // backend/src/services/snapshot-service.ts
10050
10307
  function formatElapsedSince(startedAt, now) {
10051
10308
  if (!startedAt)
@@ -10080,6 +10337,7 @@ function mapCreationSnapshot(creating) {
10080
10337
  function mapWorktreeSnapshot(state, now, creating, findLinearIssue) {
10081
10338
  return {
10082
10339
  branch: state.branch,
10340
+ ...state.baseBranch ? { baseBranch: state.baseBranch } : {},
10083
10341
  path: state.path,
10084
10342
  dir: state.path,
10085
10343
  profile: state.profile,
@@ -10099,6 +10357,7 @@ function mapWorktreeSnapshot(state, now, creating, findLinearIssue) {
10099
10357
  function mapCreatingWorktreeSnapshot(creating, findLinearIssue) {
10100
10358
  return {
10101
10359
  branch: creating.branch,
10360
+ ...creating.baseBranch ? { baseBranch: creating.baseBranch } : {},
10102
10361
  path: creating.path,
10103
10362
  dir: creating.path,
10104
10363
  profile: creating.profile,
@@ -10502,7 +10761,7 @@ class BunPortProbe {
10502
10761
  this.hostnames = hostnames;
10503
10762
  }
10504
10763
  isListening(port) {
10505
- return new Promise((resolve5) => {
10764
+ return new Promise((resolve6) => {
10506
10765
  let settled = false;
10507
10766
  let pending = this.hostnames.length;
10508
10767
  const settle = (result) => {
@@ -10511,20 +10770,20 @@ class BunPortProbe {
10511
10770
  if (result) {
10512
10771
  settled = true;
10513
10772
  clearTimeout(timer);
10514
- resolve5(true);
10773
+ resolve6(true);
10515
10774
  return;
10516
10775
  }
10517
10776
  pending--;
10518
10777
  if (pending === 0) {
10519
10778
  settled = true;
10520
10779
  clearTimeout(timer);
10521
- resolve5(false);
10780
+ resolve6(false);
10522
10781
  }
10523
10782
  };
10524
10783
  const timer = setTimeout(() => {
10525
10784
  if (!settled) {
10526
10785
  settled = true;
10527
- resolve5(false);
10786
+ resolve6(false);
10528
10787
  }
10529
10788
  }, this.timeoutMs);
10530
10789
  for (const hostname of this.hostnames) {
@@ -10661,33 +10920,14 @@ class AutoNameService {
10661
10920
  }
10662
10921
 
10663
10922
  // backend/src/services/notification-service.ts
10664
- function buildNotification(event, id, timestamp) {
10923
+ function eventToNotificationInput(event) {
10665
10924
  switch (event.type) {
10666
10925
  case "agent_stopped":
10667
- return {
10668
- id,
10669
- branch: event.branch,
10670
- type: "agent_stopped",
10671
- message: `Agent stopped on ${event.branch}`,
10672
- timestamp
10673
- };
10926
+ return { branch: event.branch, type: "agent_stopped", message: `Agent stopped on ${event.branch}` };
10674
10927
  case "pr_opened":
10675
- return {
10676
- id,
10677
- branch: event.branch,
10678
- type: "pr_opened",
10679
- message: `PR opened on ${event.branch}`,
10680
- url: event.url,
10681
- timestamp
10682
- };
10928
+ return { branch: event.branch, type: "pr_opened", message: `PR opened on ${event.branch}`, url: event.url };
10683
10929
  case "runtime_error":
10684
- return {
10685
- id,
10686
- branch: event.branch,
10687
- type: "runtime_error",
10688
- message: `Runtime error on ${event.branch}: ${event.message}`,
10689
- timestamp
10690
- };
10930
+ return { branch: event.branch, type: "runtime_error", message: `Runtime error on ${event.branch}: ${event.message}` };
10691
10931
  default:
10692
10932
  return null;
10693
10933
  }
@@ -10712,10 +10952,15 @@ class NotificationService {
10712
10952
  this.broadcast("dismiss", { id });
10713
10953
  return true;
10714
10954
  }
10715
- recordEvent(event, now = () => new Date) {
10716
- const notification = buildNotification(event, this.nextId, now().getTime());
10717
- if (!notification)
10718
- return null;
10955
+ notify(input) {
10956
+ const notification = {
10957
+ id: this.nextId,
10958
+ branch: input.branch,
10959
+ type: input.type,
10960
+ message: input.message,
10961
+ ...input.url ? { url: input.url } : {},
10962
+ timestamp: Date.now()
10963
+ };
10719
10964
  this.nextId += 1;
10720
10965
  this.notifications.push(notification);
10721
10966
  while (this.notifications.length > this.maxItems) {
@@ -10724,6 +10969,12 @@ class NotificationService {
10724
10969
  this.broadcast("notification", notification);
10725
10970
  return notification;
10726
10971
  }
10972
+ recordEvent(event) {
10973
+ const input = eventToNotificationInput(event);
10974
+ if (!input)
10975
+ return null;
10976
+ return this.notify(input);
10977
+ }
10727
10978
  stream() {
10728
10979
  let controllerRef = null;
10729
10980
  const stream = new ReadableStream({
@@ -10773,6 +11024,7 @@ function makeDefaultState(input) {
10773
11024
  return {
10774
11025
  worktreeId: input.worktreeId,
10775
11026
  branch: input.branch,
11027
+ baseBranch: input.baseBranch ?? null,
10776
11028
  path: input.path,
10777
11029
  profile: input.profile ?? null,
10778
11030
  agentName: input.agentName ?? null,
@@ -10817,6 +11069,8 @@ class ProjectRuntime {
10817
11069
  this.reindexBranch(existing.branch, input.branch, input.worktreeId);
10818
11070
  existing.path = input.path;
10819
11071
  existing.branch = input.branch;
11072
+ if (input.baseBranch !== undefined)
11073
+ existing.baseBranch = input.baseBranch;
10820
11074
  existing.profile = input.profile ?? existing.profile;
10821
11075
  existing.agentName = input.agentName ?? existing.agentName;
10822
11076
  if (input.runtime)
@@ -10929,9 +11183,9 @@ class ProjectRuntime {
10929
11183
  }
10930
11184
 
10931
11185
  // backend/src/services/reconciliation-service.ts
10932
- import { basename as basename2, resolve as resolve5 } from "path";
11186
+ import { basename as basename2, resolve as resolve6 } from "path";
10933
11187
  function makeUnmanagedWorktreeId(path) {
10934
- return `unmanaged:${resolve5(path)}`;
11188
+ return `unmanaged:${resolve6(path)}`;
10935
11189
  }
10936
11190
  function isValidPort2(port) {
10937
11191
  return port !== null && Number.isInteger(port) && port >= 1 && port <= 65535;
@@ -10988,7 +11242,7 @@ class ReconciliationService {
10988
11242
  if (!options.force && this.now() - this.lastReconciledAt < this.freshnessMs) {
10989
11243
  return;
10990
11244
  }
10991
- const normalizedRepoRoot = resolve5(repoRoot);
11245
+ const normalizedRepoRoot = resolve6(repoRoot);
10992
11246
  const reconcilePromise = this.runReconcile(normalizedRepoRoot).then(() => {
10993
11247
  this.lastReconciledAt = this.now();
10994
11248
  });
@@ -11007,7 +11261,7 @@ class ReconciliationService {
11007
11261
  windows = [];
11008
11262
  }
11009
11263
  const seenWorktreeIds = new Set;
11010
- const candidateEntries = worktrees.filter((entry) => !entry.bare && resolve5(entry.path) !== normalizedRepoRoot);
11264
+ const candidateEntries = worktrees.filter((entry) => !entry.bare && resolve6(entry.path) !== normalizedRepoRoot);
11011
11265
  const reconciledStates = await mapWithConcurrency(candidateEntries, this.concurrency, async (entry) => {
11012
11266
  const gitDir = this.deps.git.resolveWorktreeGitDir(entry.path);
11013
11267
  const meta = await readWorktreeMeta(gitDir);
@@ -11018,6 +11272,7 @@ class ReconciliationService {
11018
11272
  return {
11019
11273
  worktreeId,
11020
11274
  branch,
11275
+ baseBranch: meta?.baseBranch ?? null,
11021
11276
  path: entry.path,
11022
11277
  profile: meta?.profile ?? null,
11023
11278
  agentName: meta?.agent ?? null,
@@ -11049,6 +11304,7 @@ class ReconciliationService {
11049
11304
  this.deps.runtime.upsertWorktree({
11050
11305
  worktreeId: state.worktreeId,
11051
11306
  branch: state.branch,
11307
+ baseBranch: state.baseBranch,
11052
11308
  path: state.path,
11053
11309
  profile: state.profile,
11054
11310
  agentName: state.agentName,
@@ -11083,6 +11339,7 @@ class WorktreeCreationTracker {
11083
11339
  set(progress) {
11084
11340
  const next = {
11085
11341
  branch: progress.branch,
11342
+ ...progress.baseBranch ? { baseBranch: progress.baseBranch } : {},
11086
11343
  path: progress.path,
11087
11344
  profile: progress.profile,
11088
11345
  agentName: progress.agent,
@@ -11177,6 +11434,7 @@ var removingBranches = new Set;
11177
11434
  var lifecycleService = runtime.lifecycleService;
11178
11435
  var linearAutoCreateEnabled = config.integrations.linear.autoCreateWorktrees;
11179
11436
  var stopLinearAutoCreate = null;
11437
+ var autoRemoveOnMergeEnabled = config.integrations.github.autoRemoveOnMerge;
11180
11438
  function startLinearAutoCreate() {
11181
11439
  if (stopLinearAutoCreate)
11182
11440
  return;
@@ -11193,6 +11451,15 @@ function stopLinearAutoCreateMonitor() {
11193
11451
  stopLinearAutoCreate = null;
11194
11452
  }
11195
11453
  }
11454
+ var autoRemoveDeps = {
11455
+ lifecycleService,
11456
+ git,
11457
+ projectRoot: PROJECT_DIR,
11458
+ notifications: runtimeNotifications,
11459
+ isRemoving: (branch) => removingBranches.has(branch),
11460
+ markRemoving: (branch) => removingBranches.add(branch),
11461
+ unmarkRemoving: (branch) => removingBranches.delete(branch)
11462
+ };
11196
11463
  function getFrontendConfig() {
11197
11464
  const defaultProfileName = getDefaultProfileName(config);
11198
11465
  const orderedProfileEntries = Object.entries(config.profiles).sort(([left], [right]) => {
@@ -11215,9 +11482,12 @@ function getFrontendConfig() {
11215
11482
  startupEnvs: config.startupEnvs,
11216
11483
  linkedRepos: config.integrations.github.linkedRepos.map((lr) => ({
11217
11484
  alias: lr.alias,
11218
- ...lr.dir ? { dir: resolve6(PROJECT_DIR, lr.dir) } : {}
11485
+ ...lr.dir ? { dir: resolve7(PROJECT_DIR, lr.dir) } : {}
11219
11486
  })),
11220
- linearAutoCreateWorktrees: linearAutoCreateEnabled
11487
+ linearAutoCreateWorktrees: linearAutoCreateEnabled,
11488
+ autoRemoveOnMerge: autoRemoveOnMergeEnabled,
11489
+ projectDir: PROJECT_DIR,
11490
+ mainBranch: config.workspace.mainBranch
11221
11491
  };
11222
11492
  }
11223
11493
  function parseWsMessage(raw) {
@@ -11343,9 +11613,9 @@ async function hasValidControlToken(req) {
11343
11613
  }
11344
11614
  async function getWorktreeGitDirs() {
11345
11615
  const gitDirs = new Map;
11346
- const projectRoot2 = resolve6(PROJECT_DIR);
11616
+ const projectRoot2 = resolve7(PROJECT_DIR);
11347
11617
  for (const entry of git.listWorktrees(projectRoot2)) {
11348
- if (entry.bare || resolve6(entry.path) === projectRoot2 || !entry.branch)
11618
+ if (entry.bare || resolve7(entry.path) === projectRoot2 || !entry.branch)
11349
11619
  continue;
11350
11620
  gitDirs.set(entry.branch, git.resolveWorktreeGitDir(entry.path));
11351
11621
  }
@@ -11431,6 +11701,11 @@ async function apiListBranches() {
11431
11701
  branches: lifecycleService.listAvailableBranches()
11432
11702
  });
11433
11703
  }
11704
+ async function apiListBaseBranches() {
11705
+ return jsonResponse({
11706
+ branches: lifecycleService.listBaseBranches()
11707
+ });
11708
+ }
11434
11709
  async function apiCreateWorktree(req) {
11435
11710
  const raw = await req.json();
11436
11711
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
@@ -11449,6 +11724,7 @@ async function apiCreateWorktree(req) {
11449
11724
  envOverrides = parsed;
11450
11725
  }
11451
11726
  const branch = typeof body.branch === "string" && body.branch.trim() ? body.branch.trim() : undefined;
11727
+ const baseBranch = typeof body.baseBranch === "string" && body.baseBranch.trim() ? body.baseBranch.trim() : undefined;
11452
11728
  const prompt = typeof body.prompt === "string" && body.prompt.trim() ? body.prompt.trim() : undefined;
11453
11729
  const profile = typeof body.profile === "string" ? body.profile : undefined;
11454
11730
  const agent = body.agent === "claude" || body.agent === "codex" ? body.agent : undefined;
@@ -11458,9 +11734,15 @@ async function apiCreateWorktree(req) {
11458
11734
  if (body.mode !== undefined && body.mode !== "new" && body.mode !== "existing") {
11459
11735
  return errorResponse("Invalid worktree create mode", 400);
11460
11736
  }
11737
+ if (baseBranch && !isValidBranchName(baseBranch)) {
11738
+ return errorResponse("Invalid base branch name", 400);
11739
+ }
11461
11740
  if (createLinearTicket && mode === "existing") {
11462
11741
  return errorResponse("Linear ticket creation is only supported for new branches", 400);
11463
11742
  }
11743
+ if (baseBranch && mode === "existing") {
11744
+ return errorResponse("Base branch is only supported for new branches", 400);
11745
+ }
11464
11746
  if (createLinearTicket && !config.integrations.linear.enabled) {
11465
11747
  return errorResponse("Linear integration is disabled", 400);
11466
11748
  }
@@ -11494,10 +11776,14 @@ async function apiCreateWorktree(req) {
11494
11776
  } else if (resolvedBranch) {
11495
11777
  ensureBranchNotCreating(resolvedBranch);
11496
11778
  }
11497
- log.info(`[worktree:add] mode=${mode ?? "new"}${resolvedBranch ? ` branch=${resolvedBranch}` : ""}${profile ? ` profile=${profile}` : ""}${agent ? ` agent=${agent}` : ""}${createLinearTicket ? " linearTicket=true" : ""}${prompt ? ` prompt="${prompt.slice(0, 80)}"` : ""}`);
11779
+ if (resolvedBranch && baseBranch && resolvedBranch === baseBranch) {
11780
+ return errorResponse("Base branch must differ from branch name", 400);
11781
+ }
11782
+ log.info(`[worktree:add] mode=${mode ?? "new"}${resolvedBranch ? ` branch=${resolvedBranch}` : ""}${baseBranch ? ` base=${baseBranch}` : ""}${profile ? ` profile=${profile}` : ""}${agent ? ` agent=${agent}` : ""}${createLinearTicket ? " linearTicket=true" : ""}${prompt ? ` prompt="${prompt.slice(0, 80)}"` : ""}`);
11498
11783
  const result = await lifecycleService.createWorktree({
11499
11784
  mode,
11500
11785
  branch: resolvedBranch,
11786
+ baseBranch,
11501
11787
  prompt,
11502
11788
  profile,
11503
11789
  agent,
@@ -11574,6 +11860,29 @@ async function apiSetLinearAutoCreate(req) {
11574
11860
  await persistLocalLinearConfig(PROJECT_DIR, { autoCreateWorktrees: linearAutoCreateEnabled });
11575
11861
  return jsonResponse({ ok: true, enabled: linearAutoCreateEnabled });
11576
11862
  }
11863
+ async function apiSetAutoRemoveOnMerge(req) {
11864
+ const raw = await req.json();
11865
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
11866
+ return errorResponse("Invalid request body", 400);
11867
+ }
11868
+ const body = raw;
11869
+ if (typeof body.enabled !== "boolean") {
11870
+ return errorResponse("Missing boolean 'enabled' field", 400);
11871
+ }
11872
+ autoRemoveOnMergeEnabled = body.enabled;
11873
+ log.info(`[config] Auto-remove on merge ${autoRemoveOnMergeEnabled ? "enabled" : "disabled"}`);
11874
+ await persistLocalGitHubConfig(PROJECT_DIR, { autoRemoveOnMerge: autoRemoveOnMergeEnabled });
11875
+ return jsonResponse({ ok: true, enabled: autoRemoveOnMergeEnabled });
11876
+ }
11877
+ async function apiPullMain(req) {
11878
+ const raw = await req.json().catch(() => ({}));
11879
+ const body = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
11880
+ const force = body.force === true;
11881
+ const deps = { git, projectRoot: PROJECT_DIR, mainBranch: config.workspace.mainBranch };
11882
+ const result = force ? forcePullMainBranch(deps) : pullMainBranch(deps);
11883
+ log.info(`[pull-main] ${force ? "force " : ""}pull: ${result.status}`);
11884
+ return jsonResponse(result);
11885
+ }
11577
11886
  async function apiGetLinearIssues() {
11578
11887
  const apiKey = Bun.env.LINEAR_API_KEY;
11579
11888
  const fetchResult = config.integrations.linear.enabled && apiKey?.trim() ? await fetchAssignedIssues() : undefined;
@@ -11654,7 +11963,7 @@ async function apiUploadFiles(name, req) {
11654
11963
  }
11655
11964
  const safeName = `${Date.now()}_${sanitizeFilename(entry.name)}`;
11656
11965
  const destPath = join6(uploadDir, safeName);
11657
- if (!resolve6(destPath).startsWith(uploadDir + "/")) {
11966
+ if (!resolve7(destPath).startsWith(uploadDir + "/")) {
11658
11967
  return errorResponse("Invalid filename", 400);
11659
11968
  }
11660
11969
  await Bun.write(destPath, entry);
@@ -11677,6 +11986,9 @@ Bun.serve({
11677
11986
  "/api/branches": {
11678
11987
  GET: () => catching("GET /api/branches", () => apiListBranches())
11679
11988
  },
11989
+ "/api/base-branches": {
11990
+ GET: () => catching("GET /api/base-branches", () => apiListBaseBranches())
11991
+ },
11680
11992
  "/api/project": {
11681
11993
  GET: () => catching("GET /api/project", () => apiGetProject())
11682
11994
  },
@@ -11756,6 +12068,12 @@ Bun.serve({
11756
12068
  "/api/linear/auto-create": {
11757
12069
  PUT: (req) => catching("PUT /api/linear/auto-create", () => apiSetLinearAutoCreate(req))
11758
12070
  },
12071
+ "/api/github/auto-remove-on-merge": {
12072
+ PUT: (req) => catching("PUT /api/github/auto-remove-on-merge", () => apiSetAutoRemoveOnMerge(req))
12073
+ },
12074
+ "/api/pull-main": {
12075
+ POST: (req) => catching("POST /api/pull-main", () => apiPullMain(req))
12076
+ },
11759
12077
  "/api/ci-logs/:runId": {
11760
12078
  GET: (req) => catching(`GET /api/ci-logs/${req.params.runId}`, () => apiCiLogs(req.params.runId))
11761
12079
  },
@@ -11778,8 +12096,8 @@ Bun.serve({
11778
12096
  const url = new URL(req.url);
11779
12097
  const rawPath = url.pathname === "/" ? "index.html" : url.pathname;
11780
12098
  const filePath = join6(STATIC_DIR, rawPath);
11781
- const staticRoot = resolve6(STATIC_DIR);
11782
- if (!resolve6(filePath).startsWith(staticRoot + "/")) {
12099
+ const staticRoot = resolve7(STATIC_DIR);
12100
+ if (!resolve7(filePath).startsWith(staticRoot + "/")) {
11783
12101
  return new Response("Forbidden", { status: 403 });
11784
12102
  }
11785
12103
  const file = Bun.file(filePath);
@@ -11884,10 +12202,17 @@ if (tmuxCheck.exitCode !== 0) {
11884
12202
  log.info("Started tmux session");
11885
12203
  }
11886
12204
  cleanupStaleSessions();
11887
- startPrMonitor(getWorktreeGitDirs, config.integrations.github.linkedRepos, PROJECT_DIR, undefined, hasRecentDashboardActivity);
12205
+ startPrMonitor(getWorktreeGitDirs, config.integrations.github.linkedRepos, PROJECT_DIR, undefined, hasRecentDashboardActivity, async () => {
12206
+ if (autoRemoveOnMergeEnabled) {
12207
+ await runAutoRemove(autoRemoveDeps);
12208
+ }
12209
+ });
11888
12210
  if (linearAutoCreateEnabled) {
11889
12211
  startLinearAutoCreate();
11890
12212
  }
12213
+ if (config.workspace.autoPull.enabled) {
12214
+ startAutoPullMonitor({ git, projectRoot: PROJECT_DIR, mainBranch: config.workspace.mainBranch }, config.workspace.autoPull.intervalSeconds * 1000);
12215
+ }
11891
12216
  log.info(`Dev Dashboard API running at http://localhost:${PORT}`);
11892
12217
  var nets = networkInterfaces();
11893
12218
  for (const addrs of Object.values(nets)) {