xtrm-cli 0.5.0 → 0.5.27

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 (50) hide show
  1. package/.pi/structured-returns/0e4a7405-1ac3-4ae1-8dbc-d31507b2e2e4.combined.log +17 -0
  2. package/.pi/structured-returns/0e4a7405-1ac3-4ae1-8dbc-d31507b2e2e4.stderr.log +0 -0
  3. package/.pi/structured-returns/0e4a7405-1ac3-4ae1-8dbc-d31507b2e2e4.stdout.log +17 -0
  4. package/dist/index.cjs +969 -1059
  5. package/dist/index.cjs.map +1 -1
  6. package/package.json +1 -1
  7. package/src/commands/clean.ts +7 -6
  8. package/src/commands/debug.ts +255 -0
  9. package/src/commands/docs.ts +180 -0
  10. package/src/commands/help.ts +92 -171
  11. package/src/commands/init.ts +9 -32
  12. package/src/commands/install-pi.ts +9 -16
  13. package/src/commands/install.ts +150 -2
  14. package/src/commands/pi-install.ts +10 -44
  15. package/src/core/context.ts +4 -52
  16. package/src/core/diff.ts +3 -16
  17. package/src/core/preflight.ts +0 -1
  18. package/src/index.ts +7 -4
  19. package/src/types/config.ts +0 -2
  20. package/src/utils/config-injector.ts +3 -3
  21. package/src/utils/pi-extensions.ts +41 -0
  22. package/src/utils/worktree-session.ts +86 -50
  23. package/test/extensions/beads-claim-lifecycle.test.ts +93 -0
  24. package/test/extensions/beads-parity.test.ts +94 -0
  25. package/test/extensions/extension-harness.ts +5 -5
  26. package/test/extensions/quality-gates-parity.test.ts +89 -0
  27. package/test/extensions/session-flow.test.ts +91 -0
  28. package/test/extensions/xtrm-loader.test.ts +38 -20
  29. package/test/install-pi.test.ts +22 -11
  30. package/test/pi-extensions.test.ts +50 -0
  31. package/test/session-launcher.test.ts +28 -38
  32. package/extensions/beads.ts +0 -109
  33. package/extensions/core/adapter.ts +0 -45
  34. package/extensions/core/lib.ts +0 -3
  35. package/extensions/core/logger.ts +0 -45
  36. package/extensions/core/runner.ts +0 -71
  37. package/extensions/custom-footer.ts +0 -160
  38. package/extensions/main-guard-post-push.ts +0 -44
  39. package/extensions/main-guard.ts +0 -126
  40. package/extensions/minimal-mode.ts +0 -201
  41. package/extensions/quality-gates.ts +0 -67
  42. package/extensions/service-skills.ts +0 -150
  43. package/extensions/xtrm-loader.ts +0 -89
  44. package/hooks/gitnexus-impact-reminder.py +0 -13
  45. package/src/commands/finish.ts +0 -25
  46. package/src/core/session-state.ts +0 -139
  47. package/src/core/xtrm-finish.ts +0 -267
  48. package/src/tests/session-flow-parity.test.ts +0 -118
  49. package/src/tests/session-state.test.ts +0 -124
  50. package/src/tests/xtrm-finish.test.ts +0 -148
package/dist/index.cjs CHANGED
@@ -3503,7 +3503,7 @@ var require_kleur = __commonJS({
3503
3503
  bgCyan: init2(46, 49),
3504
3504
  bgWhite: init2(47, 49)
3505
3505
  };
3506
- function run3(arr, str) {
3506
+ function run2(arr, str) {
3507
3507
  let i = 0, tmp, beg = "", end = "";
3508
3508
  for (; i < arr.length; i++) {
3509
3509
  tmp = arr[i];
@@ -3554,9 +3554,9 @@ var require_kleur = __commonJS({
3554
3554
  return function(txt) {
3555
3555
  if (this !== void 0 && this.has !== void 0) {
3556
3556
  this.has.includes(open) || (this.has.push(open), this.keys.push(blk));
3557
- return txt === void 0 ? this : $2.enabled ? run3(this.keys, txt + "") : txt + "";
3557
+ return txt === void 0 ? this : $2.enabled ? run2(this.keys, txt + "") : txt + "";
3558
3558
  }
3559
- return txt === void 0 ? chain2([open], [blk]) : $2.enabled ? run3([blk], txt + "") : txt + "";
3559
+ return txt === void 0 ? chain2([open], [blk]) : $2.enabled ? run2([blk], txt + "") : txt + "";
3560
3560
  };
3561
3561
  }
3562
3562
  module2.exports = $2;
@@ -6053,7 +6053,7 @@ var require_dist = __commonJS({
6053
6053
  });
6054
6054
  };
6055
6055
  }
6056
- var prompts7 = require_prompts();
6056
+ var prompts6 = require_prompts();
6057
6057
  var passOn = ["suggest", "format", "onState", "validate", "onRender", "type"];
6058
6058
  var noop = () => {
6059
6059
  };
@@ -6104,7 +6104,7 @@ var require_dist = __commonJS({
6104
6104
  var _question2 = question;
6105
6105
  name = _question2.name;
6106
6106
  type = _question2.type;
6107
- if (prompts7[type] === void 0) {
6107
+ if (prompts6[type] === void 0) {
6108
6108
  throw new Error(`prompt type (${type}) is not defined`);
6109
6109
  }
6110
6110
  if (override2[question.name] !== void 0) {
@@ -6115,7 +6115,7 @@ var require_dist = __commonJS({
6115
6115
  }
6116
6116
  }
6117
6117
  try {
6118
- answer = prompt._injected ? getInjectedAnswer(prompt._injected, question.initial) : yield prompts7[type](question);
6118
+ answer = prompt._injected ? getInjectedAnswer(prompt._injected, question.initial) : yield prompts6[type](question);
6119
6119
  answers[name] = answer = yield getFormattedAnswer(question, answer, true);
6120
6120
  quit = yield onSubmit(question, answer, answers);
6121
6121
  } catch (err) {
@@ -6147,7 +6147,7 @@ var require_dist = __commonJS({
6147
6147
  }
6148
6148
  module2.exports = Object.assign(prompt, {
6149
6149
  prompt,
6150
- prompts: prompts7,
6150
+ prompts: prompts6,
6151
6151
  inject,
6152
6152
  override
6153
6153
  });
@@ -8234,7 +8234,7 @@ var require_prompts2 = __commonJS({
8234
8234
  var require_lib = __commonJS({
8235
8235
  "../node_modules/prompts/lib/index.js"(exports2, module2) {
8236
8236
  "use strict";
8237
- var prompts7 = require_prompts2();
8237
+ var prompts6 = require_prompts2();
8238
8238
  var passOn = ["suggest", "format", "onState", "validate", "onRender", "type"];
8239
8239
  var noop = () => {
8240
8240
  };
@@ -8266,7 +8266,7 @@ var require_lib = __commonJS({
8266
8266
  throw new Error("prompt message is required");
8267
8267
  }
8268
8268
  ({ name, type } = question);
8269
- if (prompts7[type] === void 0) {
8269
+ if (prompts6[type] === void 0) {
8270
8270
  throw new Error(`prompt type (${type}) is not defined`);
8271
8271
  }
8272
8272
  if (override2[question.name] !== void 0) {
@@ -8277,7 +8277,7 @@ var require_lib = __commonJS({
8277
8277
  }
8278
8278
  }
8279
8279
  try {
8280
- answer = prompt._injected ? getInjectedAnswer(prompt._injected, question.initial) : await prompts7[type](question);
8280
+ answer = prompt._injected ? getInjectedAnswer(prompt._injected, question.initial) : await prompts6[type](question);
8281
8281
  answers[name] = answer = await getFormattedAnswer(question, answer, true);
8282
8282
  quit = await onSubmit(question, answer, answers);
8283
8283
  } catch (err) {
@@ -8300,7 +8300,7 @@ var require_lib = __commonJS({
8300
8300
  function override(answers) {
8301
8301
  prompt._override = Object.assign({}, answers);
8302
8302
  }
8303
- module2.exports = Object.assign(prompt, { prompt, prompts: prompts7, inject, override });
8303
+ module2.exports = Object.assign(prompt, { prompt, prompts: prompts6, inject, override });
8304
8304
  }
8305
8305
  });
8306
8306
 
@@ -15255,7 +15255,7 @@ var require_dataType = __commonJS({
15255
15255
  exports2.coerceAndCheckDataType = coerceAndCheckDataType;
15256
15256
  var COERCIBLE = /* @__PURE__ */ new Set(["string", "number", "integer", "boolean", "null"]);
15257
15257
  function coerceToTypes(types, coerceTypes) {
15258
- return coerceTypes ? types.filter((t2) => COERCIBLE.has(t2) || coerceTypes === "array" && t2 === "array") : [];
15258
+ return coerceTypes ? types.filter((t3) => COERCIBLE.has(t3) || coerceTypes === "array" && t3 === "array") : [];
15259
15259
  }
15260
15260
  function coerceData(it, types, coerceTo) {
15261
15261
  const { gen, data, opts } = it;
@@ -15265,9 +15265,9 @@ var require_dataType = __commonJS({
15265
15265
  gen.if((0, codegen_1._)`${dataType} == 'object' && Array.isArray(${data}) && ${data}.length == 1`, () => gen.assign(data, (0, codegen_1._)`${data}[0]`).assign(dataType, (0, codegen_1._)`typeof ${data}`).if(checkDataTypes(types, data, opts.strictNumbers), () => gen.assign(coerced, data)));
15266
15266
  }
15267
15267
  gen.if((0, codegen_1._)`${coerced} !== undefined`);
15268
- for (const t2 of coerceTo) {
15269
- if (COERCIBLE.has(t2) || t2 === "array" && opts.coerceTypes === "array") {
15270
- coerceSpecificType(t2);
15268
+ for (const t3 of coerceTo) {
15269
+ if (COERCIBLE.has(t3) || t3 === "array" && opts.coerceTypes === "array") {
15270
+ coerceSpecificType(t3);
15271
15271
  }
15272
15272
  }
15273
15273
  gen.else();
@@ -15277,8 +15277,8 @@ var require_dataType = __commonJS({
15277
15277
  gen.assign(data, coerced);
15278
15278
  assignParentData(it, coerced);
15279
15279
  });
15280
- function coerceSpecificType(t2) {
15281
- switch (t2) {
15280
+ function coerceSpecificType(t3) {
15281
+ switch (t3) {
15282
15282
  case "string":
15283
15283
  gen.elseIf((0, codegen_1._)`${dataType} == "number" || ${dataType} == "boolean"`).assign(coerced, (0, codegen_1._)`"" + ${data}`).elseIf((0, codegen_1._)`${data} === null`).assign(coerced, (0, codegen_1._)`""`);
15284
15284
  return;
@@ -15350,8 +15350,8 @@ var require_dataType = __commonJS({
15350
15350
  }
15351
15351
  if (types.number)
15352
15352
  delete types.integer;
15353
- for (const t2 in types)
15354
- cond = (0, codegen_1.and)(cond, checkDataType(t2, data, strictNums, correct));
15353
+ for (const t3 in types)
15354
+ cond = (0, codegen_1.and)(cond, checkDataType(t3, data, strictNums, correct));
15355
15355
  return cond;
15356
15356
  }
15357
15357
  exports2.checkDataTypes = checkDataTypes;
@@ -16266,9 +16266,9 @@ var require_validate = __commonJS({
16266
16266
  it.dataTypes = types;
16267
16267
  return;
16268
16268
  }
16269
- types.forEach((t2) => {
16270
- if (!includesType(it.dataTypes, t2)) {
16271
- strictTypesError(it, `type "${t2}" not allowed by context "${it.dataTypes.join(",")}"`);
16269
+ types.forEach((t3) => {
16270
+ if (!includesType(it.dataTypes, t3)) {
16271
+ strictTypesError(it, `type "${t3}" not allowed by context "${it.dataTypes.join(",")}"`);
16272
16272
  }
16273
16273
  });
16274
16274
  narrowSchemaTypes(it, types);
@@ -16284,7 +16284,7 @@ var require_validate = __commonJS({
16284
16284
  const rule = rules[keyword];
16285
16285
  if (typeof rule == "object" && (0, applicability_1.shouldUseRule)(it.schema, rule)) {
16286
16286
  const { type } = rule.definition;
16287
- if (type.length && !type.some((t2) => hasApplicableType(ts, t2))) {
16287
+ if (type.length && !type.some((t3) => hasApplicableType(ts, t3))) {
16288
16288
  strictTypesError(it, `missing type "${type.join(",")}" for keyword "${keyword}"`);
16289
16289
  }
16290
16290
  }
@@ -16293,15 +16293,15 @@ var require_validate = __commonJS({
16293
16293
  function hasApplicableType(schTs, kwdT) {
16294
16294
  return schTs.includes(kwdT) || kwdT === "number" && schTs.includes("integer");
16295
16295
  }
16296
- function includesType(ts, t2) {
16297
- return ts.includes(t2) || t2 === "integer" && ts.includes("number");
16296
+ function includesType(ts, t3) {
16297
+ return ts.includes(t3) || t3 === "integer" && ts.includes("number");
16298
16298
  }
16299
16299
  function narrowSchemaTypes(it, withTypes) {
16300
16300
  const ts = [];
16301
- for (const t2 of it.dataTypes) {
16302
- if (includesType(withTypes, t2))
16303
- ts.push(t2);
16304
- else if (withTypes.includes("integer") && t2 === "number")
16301
+ for (const t3 of it.dataTypes) {
16302
+ if (includesType(withTypes, t3))
16303
+ ts.push(t3);
16304
+ else if (withTypes.includes("integer") && t3 === "number")
16305
16305
  ts.push("integer");
16306
16306
  }
16307
16307
  it.dataTypes = ts;
@@ -17912,7 +17912,7 @@ var require_core = __commonJS({
17912
17912
  type: (0, dataType_1.getJSONTypes)(def.type),
17913
17913
  schemaType: (0, dataType_1.getJSONTypes)(def.schemaType)
17914
17914
  };
17915
- (0, util_1.eachItem)(keyword, definition.type.length === 0 ? (k) => addRule.call(this, k, definition) : (k) => definition.type.forEach((t2) => addRule.call(this, k, definition, t2)));
17915
+ (0, util_1.eachItem)(keyword, definition.type.length === 0 ? (k) => addRule.call(this, k, definition) : (k) => definition.type.forEach((t3) => addRule.call(this, k, definition, t3)));
17916
17916
  return this;
17917
17917
  }
17918
17918
  getKeyword(keyword) {
@@ -18111,7 +18111,7 @@ var require_core = __commonJS({
18111
18111
  if (dataType && post)
18112
18112
  throw new Error('keyword with "post" flag cannot have "type"');
18113
18113
  const { RULES } = this;
18114
- let ruleGroup = post ? RULES.post : RULES.rules.find(({ type: t2 }) => t2 === dataType);
18114
+ let ruleGroup = post ? RULES.post : RULES.rules.find(({ type: t3 }) => t3 === dataType);
18115
18115
  if (!ruleGroup) {
18116
18116
  ruleGroup = { type: dataType, rules: [] };
18117
18117
  RULES.rules.push(ruleGroup);
@@ -18659,7 +18659,7 @@ var require_uniqueItems = __commonJS({
18659
18659
  gen.if((0, codegen_1._)`${i} > 1`, () => (canOptimize() ? loopN : loopN2)(i, j));
18660
18660
  }
18661
18661
  function canOptimize() {
18662
- return itemTypes.length > 0 && !itemTypes.some((t2) => t2 === "object" || t2 === "array");
18662
+ return itemTypes.length > 0 && !itemTypes.some((t3) => t3 === "object" || t3 === "array");
18663
18663
  }
18664
18664
  function loopN(i, j) {
18665
18665
  const item = gen.name("item");
@@ -20300,18 +20300,18 @@ var require_formats = __commonJS({
20300
20300
  const timeZone = matches[5];
20301
20301
  return (hour <= 23 && minute <= 59 && second <= 59 || hour === 23 && minute === 59 && second === 60) && (!withTimeZone || timeZone !== "");
20302
20302
  }
20303
- function compareTime(t1, t2) {
20304
- if (!(t1 && t2))
20303
+ function compareTime(t1, t22) {
20304
+ if (!(t1 && t22))
20305
20305
  return void 0;
20306
20306
  const a1 = TIME.exec(t1);
20307
- const a2 = TIME.exec(t2);
20307
+ const a2 = TIME.exec(t22);
20308
20308
  if (!(a1 && a2))
20309
20309
  return void 0;
20310
20310
  t1 = a1[1] + a1[2] + a1[3] + (a1[4] || "");
20311
- t2 = a2[1] + a2[2] + a2[3] + (a2[4] || "");
20312
- if (t1 > t2)
20311
+ t22 = a2[1] + a2[2] + a2[3] + (a2[4] || "");
20312
+ if (t1 > t22)
20313
20313
  return 1;
20314
- if (t1 < t2)
20314
+ if (t1 < t22)
20315
20315
  return -1;
20316
20316
  return 0;
20317
20317
  }
@@ -20324,11 +20324,11 @@ var require_formats = __commonJS({
20324
20324
  if (!(dt1 && dt2))
20325
20325
  return void 0;
20326
20326
  const [d1, t1] = dt1.split(DATE_TIME_SEPARATOR);
20327
- const [d2, t2] = dt2.split(DATE_TIME_SEPARATOR);
20327
+ const [d2, t22] = dt2.split(DATE_TIME_SEPARATOR);
20328
20328
  const res = compareDate(d1, d2);
20329
20329
  if (res === void 0)
20330
20330
  return void 0;
20331
- return res || compareTime(t1, t2);
20331
+ return res || compareTime(t1, t22);
20332
20332
  }
20333
20333
  var NOT_URI_FRAGMENT = /\/|:/;
20334
20334
  var URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
@@ -20536,7 +20536,7 @@ var require_re = __commonJS({
20536
20536
  var safeRe = exports2.safeRe = [];
20537
20537
  var src = exports2.src = [];
20538
20538
  var safeSrc = exports2.safeSrc = [];
20539
- var t2 = exports2.t = {};
20539
+ var t3 = exports2.t = {};
20540
20540
  var R = 0;
20541
20541
  var LETTERDASHNUMBER = "[a-zA-Z0-9-]";
20542
20542
  var safeRegexReplacements = [
@@ -20554,7 +20554,7 @@ var require_re = __commonJS({
20554
20554
  const safe = makeSafeRegex(value);
20555
20555
  const index = R++;
20556
20556
  debug(name, index, value);
20557
- t2[name] = index;
20557
+ t3[name] = index;
20558
20558
  src[index] = value;
20559
20559
  safeSrc[index] = safe;
20560
20560
  re[index] = new RegExp(value, isGlobal ? "g" : void 0);
@@ -20563,46 +20563,46 @@ var require_re = __commonJS({
20563
20563
  createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*");
20564
20564
  createToken("NUMERICIDENTIFIERLOOSE", "\\d+");
20565
20565
  createToken("NONNUMERICIDENTIFIER", `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`);
20566
- createToken("MAINVERSION", `(${src[t2.NUMERICIDENTIFIER]})\\.(${src[t2.NUMERICIDENTIFIER]})\\.(${src[t2.NUMERICIDENTIFIER]})`);
20567
- createToken("MAINVERSIONLOOSE", `(${src[t2.NUMERICIDENTIFIERLOOSE]})\\.(${src[t2.NUMERICIDENTIFIERLOOSE]})\\.(${src[t2.NUMERICIDENTIFIERLOOSE]})`);
20568
- createToken("PRERELEASEIDENTIFIER", `(?:${src[t2.NONNUMERICIDENTIFIER]}|${src[t2.NUMERICIDENTIFIER]})`);
20569
- createToken("PRERELEASEIDENTIFIERLOOSE", `(?:${src[t2.NONNUMERICIDENTIFIER]}|${src[t2.NUMERICIDENTIFIERLOOSE]})`);
20570
- createToken("PRERELEASE", `(?:-(${src[t2.PRERELEASEIDENTIFIER]}(?:\\.${src[t2.PRERELEASEIDENTIFIER]})*))`);
20571
- createToken("PRERELEASELOOSE", `(?:-?(${src[t2.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${src[t2.PRERELEASEIDENTIFIERLOOSE]})*))`);
20566
+ createToken("MAINVERSION", `(${src[t3.NUMERICIDENTIFIER]})\\.(${src[t3.NUMERICIDENTIFIER]})\\.(${src[t3.NUMERICIDENTIFIER]})`);
20567
+ createToken("MAINVERSIONLOOSE", `(${src[t3.NUMERICIDENTIFIERLOOSE]})\\.(${src[t3.NUMERICIDENTIFIERLOOSE]})\\.(${src[t3.NUMERICIDENTIFIERLOOSE]})`);
20568
+ createToken("PRERELEASEIDENTIFIER", `(?:${src[t3.NONNUMERICIDENTIFIER]}|${src[t3.NUMERICIDENTIFIER]})`);
20569
+ createToken("PRERELEASEIDENTIFIERLOOSE", `(?:${src[t3.NONNUMERICIDENTIFIER]}|${src[t3.NUMERICIDENTIFIERLOOSE]})`);
20570
+ createToken("PRERELEASE", `(?:-(${src[t3.PRERELEASEIDENTIFIER]}(?:\\.${src[t3.PRERELEASEIDENTIFIER]})*))`);
20571
+ createToken("PRERELEASELOOSE", `(?:-?(${src[t3.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${src[t3.PRERELEASEIDENTIFIERLOOSE]})*))`);
20572
20572
  createToken("BUILDIDENTIFIER", `${LETTERDASHNUMBER}+`);
20573
- createToken("BUILD", `(?:\\+(${src[t2.BUILDIDENTIFIER]}(?:\\.${src[t2.BUILDIDENTIFIER]})*))`);
20574
- createToken("FULLPLAIN", `v?${src[t2.MAINVERSION]}${src[t2.PRERELEASE]}?${src[t2.BUILD]}?`);
20575
- createToken("FULL", `^${src[t2.FULLPLAIN]}$`);
20576
- createToken("LOOSEPLAIN", `[v=\\s]*${src[t2.MAINVERSIONLOOSE]}${src[t2.PRERELEASELOOSE]}?${src[t2.BUILD]}?`);
20577
- createToken("LOOSE", `^${src[t2.LOOSEPLAIN]}$`);
20573
+ createToken("BUILD", `(?:\\+(${src[t3.BUILDIDENTIFIER]}(?:\\.${src[t3.BUILDIDENTIFIER]})*))`);
20574
+ createToken("FULLPLAIN", `v?${src[t3.MAINVERSION]}${src[t3.PRERELEASE]}?${src[t3.BUILD]}?`);
20575
+ createToken("FULL", `^${src[t3.FULLPLAIN]}$`);
20576
+ createToken("LOOSEPLAIN", `[v=\\s]*${src[t3.MAINVERSIONLOOSE]}${src[t3.PRERELEASELOOSE]}?${src[t3.BUILD]}?`);
20577
+ createToken("LOOSE", `^${src[t3.LOOSEPLAIN]}$`);
20578
20578
  createToken("GTLT", "((?:<|>)?=?)");
20579
- createToken("XRANGEIDENTIFIERLOOSE", `${src[t2.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);
20580
- createToken("XRANGEIDENTIFIER", `${src[t2.NUMERICIDENTIFIER]}|x|X|\\*`);
20581
- createToken("XRANGEPLAIN", `[v=\\s]*(${src[t2.XRANGEIDENTIFIER]})(?:\\.(${src[t2.XRANGEIDENTIFIER]})(?:\\.(${src[t2.XRANGEIDENTIFIER]})(?:${src[t2.PRERELEASE]})?${src[t2.BUILD]}?)?)?`);
20582
- createToken("XRANGEPLAINLOOSE", `[v=\\s]*(${src[t2.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t2.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t2.XRANGEIDENTIFIERLOOSE]})(?:${src[t2.PRERELEASELOOSE]})?${src[t2.BUILD]}?)?)?`);
20583
- createToken("XRANGE", `^${src[t2.GTLT]}\\s*${src[t2.XRANGEPLAIN]}$`);
20584
- createToken("XRANGELOOSE", `^${src[t2.GTLT]}\\s*${src[t2.XRANGEPLAINLOOSE]}$`);
20579
+ createToken("XRANGEIDENTIFIERLOOSE", `${src[t3.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);
20580
+ createToken("XRANGEIDENTIFIER", `${src[t3.NUMERICIDENTIFIER]}|x|X|\\*`);
20581
+ createToken("XRANGEPLAIN", `[v=\\s]*(${src[t3.XRANGEIDENTIFIER]})(?:\\.(${src[t3.XRANGEIDENTIFIER]})(?:\\.(${src[t3.XRANGEIDENTIFIER]})(?:${src[t3.PRERELEASE]})?${src[t3.BUILD]}?)?)?`);
20582
+ createToken("XRANGEPLAINLOOSE", `[v=\\s]*(${src[t3.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t3.XRANGEIDENTIFIERLOOSE]})(?:\\.(${src[t3.XRANGEIDENTIFIERLOOSE]})(?:${src[t3.PRERELEASELOOSE]})?${src[t3.BUILD]}?)?)?`);
20583
+ createToken("XRANGE", `^${src[t3.GTLT]}\\s*${src[t3.XRANGEPLAIN]}$`);
20584
+ createToken("XRANGELOOSE", `^${src[t3.GTLT]}\\s*${src[t3.XRANGEPLAINLOOSE]}$`);
20585
20585
  createToken("COERCEPLAIN", `${"(^|[^\\d])(\\d{1,"}${MAX_SAFE_COMPONENT_LENGTH}})(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`);
20586
- createToken("COERCE", `${src[t2.COERCEPLAIN]}(?:$|[^\\d])`);
20587
- createToken("COERCEFULL", src[t2.COERCEPLAIN] + `(?:${src[t2.PRERELEASE]})?(?:${src[t2.BUILD]})?(?:$|[^\\d])`);
20588
- createToken("COERCERTL", src[t2.COERCE], true);
20589
- createToken("COERCERTLFULL", src[t2.COERCEFULL], true);
20586
+ createToken("COERCE", `${src[t3.COERCEPLAIN]}(?:$|[^\\d])`);
20587
+ createToken("COERCEFULL", src[t3.COERCEPLAIN] + `(?:${src[t3.PRERELEASE]})?(?:${src[t3.BUILD]})?(?:$|[^\\d])`);
20588
+ createToken("COERCERTL", src[t3.COERCE], true);
20589
+ createToken("COERCERTLFULL", src[t3.COERCEFULL], true);
20590
20590
  createToken("LONETILDE", "(?:~>?)");
20591
- createToken("TILDETRIM", `(\\s*)${src[t2.LONETILDE]}\\s+`, true);
20591
+ createToken("TILDETRIM", `(\\s*)${src[t3.LONETILDE]}\\s+`, true);
20592
20592
  exports2.tildeTrimReplace = "$1~";
20593
- createToken("TILDE", `^${src[t2.LONETILDE]}${src[t2.XRANGEPLAIN]}$`);
20594
- createToken("TILDELOOSE", `^${src[t2.LONETILDE]}${src[t2.XRANGEPLAINLOOSE]}$`);
20593
+ createToken("TILDE", `^${src[t3.LONETILDE]}${src[t3.XRANGEPLAIN]}$`);
20594
+ createToken("TILDELOOSE", `^${src[t3.LONETILDE]}${src[t3.XRANGEPLAINLOOSE]}$`);
20595
20595
  createToken("LONECARET", "(?:\\^)");
20596
- createToken("CARETTRIM", `(\\s*)${src[t2.LONECARET]}\\s+`, true);
20596
+ createToken("CARETTRIM", `(\\s*)${src[t3.LONECARET]}\\s+`, true);
20597
20597
  exports2.caretTrimReplace = "$1^";
20598
- createToken("CARET", `^${src[t2.LONECARET]}${src[t2.XRANGEPLAIN]}$`);
20599
- createToken("CARETLOOSE", `^${src[t2.LONECARET]}${src[t2.XRANGEPLAINLOOSE]}$`);
20600
- createToken("COMPARATORLOOSE", `^${src[t2.GTLT]}\\s*(${src[t2.LOOSEPLAIN]})$|^$`);
20601
- createToken("COMPARATOR", `^${src[t2.GTLT]}\\s*(${src[t2.FULLPLAIN]})$|^$`);
20602
- createToken("COMPARATORTRIM", `(\\s*)${src[t2.GTLT]}\\s*(${src[t2.LOOSEPLAIN]}|${src[t2.XRANGEPLAIN]})`, true);
20598
+ createToken("CARET", `^${src[t3.LONECARET]}${src[t3.XRANGEPLAIN]}$`);
20599
+ createToken("CARETLOOSE", `^${src[t3.LONECARET]}${src[t3.XRANGEPLAINLOOSE]}$`);
20600
+ createToken("COMPARATORLOOSE", `^${src[t3.GTLT]}\\s*(${src[t3.LOOSEPLAIN]})$|^$`);
20601
+ createToken("COMPARATOR", `^${src[t3.GTLT]}\\s*(${src[t3.FULLPLAIN]})$|^$`);
20602
+ createToken("COMPARATORTRIM", `(\\s*)${src[t3.GTLT]}\\s*(${src[t3.LOOSEPLAIN]}|${src[t3.XRANGEPLAIN]})`, true);
20603
20603
  exports2.comparatorTrimReplace = "$1$2$3";
20604
- createToken("HYPHENRANGE", `^\\s*(${src[t2.XRANGEPLAIN]})\\s+-\\s+(${src[t2.XRANGEPLAIN]})\\s*$`);
20605
- createToken("HYPHENRANGELOOSE", `^\\s*(${src[t2.XRANGEPLAINLOOSE]})\\s+-\\s+(${src[t2.XRANGEPLAINLOOSE]})\\s*$`);
20604
+ createToken("HYPHENRANGE", `^\\s*(${src[t3.XRANGEPLAIN]})\\s+-\\s+(${src[t3.XRANGEPLAIN]})\\s*$`);
20605
+ createToken("HYPHENRANGELOOSE", `^\\s*(${src[t3.XRANGEPLAINLOOSE]})\\s+-\\s+(${src[t3.XRANGEPLAINLOOSE]})\\s*$`);
20606
20606
  createToken("STAR", "(<|>)?=?\\s*\\*");
20607
20607
  createToken("GTE0", "^\\s*>=\\s*0\\.0\\.0\\s*$");
20608
20608
  createToken("GTE0PRE", "^\\s*>=\\s*0\\.0\\.0-0\\s*$");
@@ -20659,7 +20659,7 @@ var require_semver = __commonJS({
20659
20659
  "use strict";
20660
20660
  var debug = require_debug();
20661
20661
  var { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants();
20662
- var { safeRe: re, t: t2 } = require_re();
20662
+ var { safeRe: re, t: t3 } = require_re();
20663
20663
  var parseOptions = require_parse_options();
20664
20664
  var { compareIdentifiers } = require_identifiers();
20665
20665
  var SemVer = class _SemVer {
@@ -20683,7 +20683,7 @@ var require_semver = __commonJS({
20683
20683
  this.options = options;
20684
20684
  this.loose = !!options.loose;
20685
20685
  this.includePrerelease = !!options.includePrerelease;
20686
- const m = version3.trim().match(options.loose ? re[t2.LOOSE] : re[t2.FULL]);
20686
+ const m = version3.trim().match(options.loose ? re[t3.LOOSE] : re[t3.FULL]);
20687
20687
  if (!m) {
20688
20688
  throw new TypeError(`Invalid Version: ${version3}`);
20689
20689
  }
@@ -20822,7 +20822,7 @@ var require_semver = __commonJS({
20822
20822
  throw new Error("invalid increment argument: identifier is empty");
20823
20823
  }
20824
20824
  if (identifier) {
20825
- const match = `-${identifier}`.match(this.options.loose ? re[t2.PRERELEASELOOSE] : re[t2.PRERELEASE]);
20825
+ const match = `-${identifier}`.match(this.options.loose ? re[t3.PRERELEASELOOSE] : re[t3.PRERELEASE]);
20826
20826
  if (!match || match[1] !== identifier) {
20827
20827
  throw new Error(`invalid identifier: ${identifier}`);
20828
20828
  }
@@ -21271,7 +21271,7 @@ var require_coerce = __commonJS({
21271
21271
  "use strict";
21272
21272
  var SemVer = require_semver();
21273
21273
  var parse4 = require_parse();
21274
- var { safeRe: re, t: t2 } = require_re();
21274
+ var { safeRe: re, t: t3 } = require_re();
21275
21275
  var coerce = (version3, options) => {
21276
21276
  if (version3 instanceof SemVer) {
21277
21277
  return version3;
@@ -21285,9 +21285,9 @@ var require_coerce = __commonJS({
21285
21285
  options = options || {};
21286
21286
  let match = null;
21287
21287
  if (!options.rtl) {
21288
- match = version3.match(options.includePrerelease ? re[t2.COERCEFULL] : re[t2.COERCE]);
21288
+ match = version3.match(options.includePrerelease ? re[t3.COERCEFULL] : re[t3.COERCE]);
21289
21289
  } else {
21290
- const coerceRtlRegex = options.includePrerelease ? re[t2.COERCERTLFULL] : re[t2.COERCERTL];
21290
+ const coerceRtlRegex = options.includePrerelease ? re[t3.COERCERTLFULL] : re[t3.COERCERTL];
21291
21291
  let next;
21292
21292
  while ((next = coerceRtlRegex.exec(version3)) && (!match || match.index + match[0].length !== version3.length)) {
21293
21293
  if (!match || next.index + next[0].length !== match.index + match[0].length) {
@@ -21426,20 +21426,20 @@ var require_range = __commonJS({
21426
21426
  return cached2;
21427
21427
  }
21428
21428
  const loose = this.options.loose;
21429
- const hr = loose ? re[t2.HYPHENRANGELOOSE] : re[t2.HYPHENRANGE];
21429
+ const hr = loose ? re[t3.HYPHENRANGELOOSE] : re[t3.HYPHENRANGE];
21430
21430
  range = range.replace(hr, hyphenReplace(this.options.includePrerelease));
21431
21431
  debug("hyphen replace", range);
21432
- range = range.replace(re[t2.COMPARATORTRIM], comparatorTrimReplace);
21432
+ range = range.replace(re[t3.COMPARATORTRIM], comparatorTrimReplace);
21433
21433
  debug("comparator trim", range);
21434
- range = range.replace(re[t2.TILDETRIM], tildeTrimReplace);
21434
+ range = range.replace(re[t3.TILDETRIM], tildeTrimReplace);
21435
21435
  debug("tilde trim", range);
21436
- range = range.replace(re[t2.CARETTRIM], caretTrimReplace);
21436
+ range = range.replace(re[t3.CARETTRIM], caretTrimReplace);
21437
21437
  debug("caret trim", range);
21438
21438
  let rangeList = range.split(" ").map((comp) => parseComparator(comp, this.options)).join(" ").split(/\s+/).map((comp) => replaceGTE0(comp, this.options));
21439
21439
  if (loose) {
21440
21440
  rangeList = rangeList.filter((comp) => {
21441
21441
  debug("loose invalid filter", comp, this.options);
21442
- return !!comp.match(re[t2.COMPARATORLOOSE]);
21442
+ return !!comp.match(re[t3.COMPARATORLOOSE]);
21443
21443
  });
21444
21444
  }
21445
21445
  debug("range list", rangeList);
@@ -21501,7 +21501,7 @@ var require_range = __commonJS({
21501
21501
  var SemVer = require_semver();
21502
21502
  var {
21503
21503
  safeRe: re,
21504
- t: t2,
21504
+ t: t3,
21505
21505
  comparatorTrimReplace,
21506
21506
  tildeTrimReplace,
21507
21507
  caretTrimReplace
@@ -21522,7 +21522,7 @@ var require_range = __commonJS({
21522
21522
  return result;
21523
21523
  };
21524
21524
  var parseComparator = (comp, options) => {
21525
- comp = comp.replace(re[t2.BUILD], "");
21525
+ comp = comp.replace(re[t3.BUILD], "");
21526
21526
  debug("comp", comp, options);
21527
21527
  comp = replaceCarets(comp, options);
21528
21528
  debug("caret", comp);
@@ -21539,7 +21539,7 @@ var require_range = __commonJS({
21539
21539
  return comp.trim().split(/\s+/).map((c) => replaceTilde(c, options)).join(" ");
21540
21540
  };
21541
21541
  var replaceTilde = (comp, options) => {
21542
- const r = options.loose ? re[t2.TILDELOOSE] : re[t2.TILDE];
21542
+ const r = options.loose ? re[t3.TILDELOOSE] : re[t3.TILDE];
21543
21543
  return comp.replace(r, (_, M, m, p, pr) => {
21544
21544
  debug("tilde", comp, _, M, m, p, pr);
21545
21545
  let ret;
@@ -21564,7 +21564,7 @@ var require_range = __commonJS({
21564
21564
  };
21565
21565
  var replaceCaret = (comp, options) => {
21566
21566
  debug("caret", comp, options);
21567
- const r = options.loose ? re[t2.CARETLOOSE] : re[t2.CARET];
21567
+ const r = options.loose ? re[t3.CARETLOOSE] : re[t3.CARET];
21568
21568
  const z2 = options.includePrerelease ? "-0" : "";
21569
21569
  return comp.replace(r, (_, M, m, p, pr) => {
21570
21570
  debug("caret", comp, _, M, m, p, pr);
@@ -21612,7 +21612,7 @@ var require_range = __commonJS({
21612
21612
  };
21613
21613
  var replaceXRange = (comp, options) => {
21614
21614
  comp = comp.trim();
21615
- const r = options.loose ? re[t2.XRANGELOOSE] : re[t2.XRANGE];
21615
+ const r = options.loose ? re[t3.XRANGELOOSE] : re[t3.XRANGE];
21616
21616
  return comp.replace(r, (ret, gtlt, M, m, p, pr) => {
21617
21617
  debug("xRange", comp, ret, gtlt, M, m, p, pr);
21618
21618
  const xM = isX(M);
@@ -21667,11 +21667,11 @@ var require_range = __commonJS({
21667
21667
  };
21668
21668
  var replaceStars = (comp, options) => {
21669
21669
  debug("replaceStars", comp, options);
21670
- return comp.trim().replace(re[t2.STAR], "");
21670
+ return comp.trim().replace(re[t3.STAR], "");
21671
21671
  };
21672
21672
  var replaceGTE0 = (comp, options) => {
21673
21673
  debug("replaceGTE0", comp, options);
21674
- return comp.trim().replace(re[options.includePrerelease ? t2.GTE0PRE : t2.GTE0], "");
21674
+ return comp.trim().replace(re[options.includePrerelease ? t3.GTE0PRE : t3.GTE0], "");
21675
21675
  };
21676
21676
  var hyphenReplace = (incPr) => ($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr) => {
21677
21677
  if (isX(fM)) {
@@ -21757,7 +21757,7 @@ var require_comparator = __commonJS({
21757
21757
  debug("comp", this);
21758
21758
  }
21759
21759
  parse(comp) {
21760
- const r = this.options.loose ? re[t2.COMPARATORLOOSE] : re[t2.COMPARATOR];
21760
+ const r = this.options.loose ? re[t3.COMPARATORLOOSE] : re[t3.COMPARATOR];
21761
21761
  const m = comp.match(r);
21762
21762
  if (!m) {
21763
21763
  throw new TypeError(`Invalid comparator: ${comp}`);
@@ -21831,7 +21831,7 @@ var require_comparator = __commonJS({
21831
21831
  };
21832
21832
  module2.exports = Comparator;
21833
21833
  var parseOptions = require_parse_options();
21834
- var { safeRe: re, t: t2 } = require_re();
21834
+ var { safeRe: re, t: t3 } = require_re();
21835
21835
  var cmp = require_cmp();
21836
21836
  var debug = require_debug();
21837
21837
  var SemVer = require_semver();
@@ -24334,15 +24334,15 @@ var require_esprima = __commonJS({
24334
24334
  return this.scanner.source.slice(token.start, token.end);
24335
24335
  };
24336
24336
  Parser2.prototype.convertToken = function(token) {
24337
- var t2 = {
24337
+ var t3 = {
24338
24338
  type: token_1.TokenName[token.type],
24339
24339
  value: this.getTokenRaw(token)
24340
24340
  };
24341
24341
  if (this.config.range) {
24342
- t2.range = [token.start, token.end];
24342
+ t3.range = [token.start, token.end];
24343
24343
  }
24344
24344
  if (this.config.loc) {
24345
- t2.loc = {
24345
+ t3.loc = {
24346
24346
  start: {
24347
24347
  line: this.startMarker.line,
24348
24348
  column: this.startMarker.column
@@ -24356,9 +24356,9 @@ var require_esprima = __commonJS({
24356
24356
  if (token.type === 9) {
24357
24357
  var pattern = token.pattern;
24358
24358
  var flags = token.flags;
24359
- t2.regex = { pattern, flags };
24359
+ t3.regex = { pattern, flags };
24360
24360
  }
24361
- return t2;
24361
+ return t3;
24362
24362
  };
24363
24363
  Parser2.prototype.nextToken = function() {
24364
24364
  var token = this.lookahead;
@@ -27021,19 +27021,19 @@ var require_esprima = __commonJS({
27021
27021
  }
27022
27022
  return error49;
27023
27023
  };
27024
- ErrorHandler2.prototype.createError = function(index, line, col2, description) {
27024
+ ErrorHandler2.prototype.createError = function(index, line, col, description) {
27025
27025
  var msg = "Line " + line + ": " + description;
27026
- var error49 = this.constructError(msg, col2);
27026
+ var error49 = this.constructError(msg, col);
27027
27027
  error49.index = index;
27028
27028
  error49.lineNumber = line;
27029
27029
  error49.description = description;
27030
27030
  return error49;
27031
27031
  };
27032
- ErrorHandler2.prototype.throwError = function(index, line, col2, description) {
27033
- throw this.createError(index, line, col2, description);
27032
+ ErrorHandler2.prototype.throwError = function(index, line, col, description) {
27033
+ throw this.createError(index, line, col, description);
27034
27034
  };
27035
- ErrorHandler2.prototype.tolerateError = function(index, line, col2, description) {
27036
- var error49 = this.createError(index, line, col2, description);
27035
+ ErrorHandler2.prototype.tolerateError = function(index, line, col, description) {
27036
+ var error49 = this.createError(index, line, col, description);
27037
27037
  if (this.tolerant) {
27038
27038
  this.recordError(error49);
27039
27039
  } else {
@@ -28461,7 +28461,7 @@ var require_esprima = __commonJS({
28461
28461
  this.values = [];
28462
28462
  this.curly = this.paren = -1;
28463
28463
  }
28464
- Reader2.prototype.beforeFunctionExpression = function(t2) {
28464
+ Reader2.prototype.beforeFunctionExpression = function(t3) {
28465
28465
  return [
28466
28466
  "(",
28467
28467
  "{",
@@ -28519,7 +28519,7 @@ var require_esprima = __commonJS({
28519
28519
  ">",
28520
28520
  "!=",
28521
28521
  "!=="
28522
- ].indexOf(t2) >= 0;
28522
+ ].indexOf(t3) >= 0;
28523
28523
  };
28524
28524
  Reader2.prototype.isRegexStart = function() {
28525
28525
  var previous = this.values[this.values.length - 1];
@@ -28746,18 +28746,18 @@ var require_src2 = __commonJS({
28746
28746
  }
28747
28747
  const al = log10(a);
28748
28748
  const bl = log10(b);
28749
- let t2 = 0;
28749
+ let t3 = 0;
28750
28750
  if (al < bl) {
28751
28751
  a *= POWERS_OF_TEN[bl - al - 1];
28752
28752
  b /= 10;
28753
- t2 = -1;
28753
+ t3 = -1;
28754
28754
  } else if (al > bl) {
28755
28755
  b *= POWERS_OF_TEN[al - bl - 1];
28756
28756
  a /= 10;
28757
- t2 = 1;
28757
+ t3 = 1;
28758
28758
  }
28759
28759
  if (a === b) {
28760
- return t2;
28760
+ return t3;
28761
28761
  }
28762
28762
  return a < b ? -1 : 1;
28763
28763
  }
@@ -28797,9 +28797,9 @@ var require_src2 = __commonJS({
28797
28797
  function reverseRun(array2, lo, hi) {
28798
28798
  hi--;
28799
28799
  while (lo < hi) {
28800
- const t2 = array2[lo];
28800
+ const t3 = array2[lo];
28801
28801
  array2[lo++] = array2[hi];
28802
- array2[hi--] = t2;
28802
+ array2[hi--] = t3;
28803
28803
  }
28804
28804
  }
28805
28805
  function binaryInsertionSort(array2, lo, hi, start, compare) {
@@ -30006,7 +30006,7 @@ var require_parse2 = __commonJS({
30006
30006
  }
30007
30007
  return current.type === "Punctuator" ? current.value : current.type;
30008
30008
  };
30009
- var is = (t2) => type() === t2;
30009
+ var is = (t3) => type() === t3;
30010
30010
  var expect = (a) => {
30011
30011
  if (!is(a)) {
30012
30012
  unexpected();
@@ -30319,10 +30319,10 @@ var require_stringify = __commonJS({
30319
30319
  replacer = null;
30320
30320
  indent2 = EMPTY;
30321
30321
  };
30322
- var join5 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + LF + gap : two ? two.trimRight() + LF + gap : EMPTY;
30322
+ var join6 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + LF + gap : two ? two.trimRight() + LF + gap : EMPTY;
30323
30323
  var join_content = (inside, value, gap) => {
30324
30324
  const comment = process_comments(value, PREFIX_BEFORE, gap + indent2, true);
30325
- return join5(comment, inside, gap);
30325
+ return join6(comment, inside, gap);
30326
30326
  };
30327
30327
  var array_stringify = (value, gap) => {
30328
30328
  const deeper_gap = gap + indent2;
@@ -30333,7 +30333,7 @@ var require_stringify = __commonJS({
30333
30333
  if (i !== 0) {
30334
30334
  inside += COMMA;
30335
30335
  }
30336
- const before = join5(
30336
+ const before = join6(
30337
30337
  after_comma,
30338
30338
  process_comments(value, BEFORE(i), deeper_gap),
30339
30339
  deeper_gap
@@ -30343,7 +30343,7 @@ var require_stringify = __commonJS({
30343
30343
  inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
30344
30344
  after_comma = process_comments(value, AFTER(i), deeper_gap);
30345
30345
  }
30346
- inside += join5(
30346
+ inside += join6(
30347
30347
  after_comma,
30348
30348
  process_comments(value, PREFIX_AFTER, deeper_gap),
30349
30349
  deeper_gap
@@ -30368,7 +30368,7 @@ var require_stringify = __commonJS({
30368
30368
  inside += COMMA;
30369
30369
  }
30370
30370
  first = false;
30371
- const before = join5(
30371
+ const before = join6(
30372
30372
  after_comma,
30373
30373
  process_comments(value, BEFORE(key), deeper_gap),
30374
30374
  deeper_gap
@@ -30378,7 +30378,7 @@ var require_stringify = __commonJS({
30378
30378
  after_comma = process_comments(value, AFTER(key), deeper_gap);
30379
30379
  };
30380
30380
  keys.forEach(iteratee);
30381
- inside += join5(
30381
+ inside += join6(
30382
30382
  after_comma,
30383
30383
  process_comments(value, PREFIX_AFTER, deeper_gap),
30384
30384
  deeper_gap
@@ -31075,7 +31075,7 @@ var require_main = __commonJS({
31075
31075
  "use strict";
31076
31076
  var fs22 = require("fs");
31077
31077
  var path22 = require("path");
31078
- var os7 = require("os");
31078
+ var os8 = require("os");
31079
31079
  var crypto2 = require("crypto");
31080
31080
  var packageJson = require_package();
31081
31081
  var version3 = packageJson.version;
@@ -31198,7 +31198,7 @@ var require_main = __commonJS({
31198
31198
  return null;
31199
31199
  }
31200
31200
  function _resolveHome(envPath) {
31201
- return envPath[0] === "~" ? path22.join(os7.homedir(), envPath.slice(1)) : envPath;
31201
+ return envPath[0] === "~" ? path22.join(os8.homedir(), envPath.slice(1)) : envPath;
31202
31202
  }
31203
31203
  function _configVault(options) {
31204
31204
  const debug = Boolean(options && options.debug);
@@ -31880,7 +31880,7 @@ var require_has_flag = __commonJS({
31880
31880
  var require_supports_colors = __commonJS({
31881
31881
  "../node_modules/@colors/colors/lib/system/supports-colors.js"(exports2, module2) {
31882
31882
  "use strict";
31883
- var os7 = require("os");
31883
+ var os8 = require("os");
31884
31884
  var hasFlag2 = require_has_flag();
31885
31885
  var env3 = process.env;
31886
31886
  var forceColor = void 0;
@@ -31918,7 +31918,7 @@ var require_supports_colors = __commonJS({
31918
31918
  }
31919
31919
  var min = forceColor ? 1 : 0;
31920
31920
  if (process.platform === "win32") {
31921
- var osRelease = os7.release().split(".");
31921
+ var osRelease = os8.release().split(".");
31922
31922
  if (Number(process.versions.node.split(".")[0]) >= 8 && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
31923
31923
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
31924
31924
  }
@@ -32847,19 +32847,19 @@ var require_layout_manager = __commonJS({
32847
32847
  var Cell = require_cell();
32848
32848
  var { ColSpanCell, RowSpanCell } = Cell;
32849
32849
  (function() {
32850
- function next(alloc, col2) {
32851
- if (alloc[col2] > 0) {
32852
- return next(alloc, col2 + 1);
32850
+ function next(alloc, col) {
32851
+ if (alloc[col] > 0) {
32852
+ return next(alloc, col + 1);
32853
32853
  }
32854
- return col2;
32854
+ return col;
32855
32855
  }
32856
32856
  function layoutTable(table) {
32857
32857
  let alloc = {};
32858
32858
  table.forEach(function(row, rowIndex) {
32859
- let col2 = 0;
32859
+ let col = 0;
32860
32860
  row.forEach(function(cell) {
32861
32861
  cell.y = rowIndex;
32862
- cell.x = rowIndex ? next(alloc, col2) : col2;
32862
+ cell.x = rowIndex ? next(alloc, col) : col;
32863
32863
  const rowSpan = cell.rowSpan || 1;
32864
32864
  const colSpan = cell.colSpan || 1;
32865
32865
  if (rowSpan > 1) {
@@ -32867,7 +32867,7 @@ var require_layout_manager = __commonJS({
32867
32867
  alloc[cell.x + cs] = rowSpan;
32868
32868
  }
32869
32869
  }
32870
- col2 = cell.x + colSpan;
32870
+ col = cell.x + colSpan;
32871
32871
  });
32872
32872
  Object.keys(alloc).forEach((idx) => {
32873
32873
  alloc[idx]--;
@@ -33039,29 +33039,29 @@ var require_layout_manager = __commonJS({
33039
33039
  for (let k = spanners.length - 1; k >= 0; k--) {
33040
33040
  let cell = spanners[k];
33041
33041
  let span = cell[colSpan];
33042
- let col2 = cell[x];
33043
- let existingWidth = result[col2];
33044
- let editableCols = typeof vals[col2] === "number" ? 0 : 1;
33042
+ let col = cell[x];
33043
+ let existingWidth = result[col];
33044
+ let editableCols = typeof vals[col] === "number" ? 0 : 1;
33045
33045
  if (typeof existingWidth === "number") {
33046
33046
  for (let i = 1; i < span; i++) {
33047
- existingWidth += 1 + result[col2 + i];
33048
- if (typeof vals[col2 + i] !== "number") {
33047
+ existingWidth += 1 + result[col + i];
33048
+ if (typeof vals[col + i] !== "number") {
33049
33049
  editableCols++;
33050
33050
  }
33051
33051
  }
33052
33052
  } else {
33053
33053
  existingWidth = desiredWidth === "desiredWidth" ? cell.desiredWidth - 1 : 1;
33054
- if (!auto[col2] || auto[col2] < existingWidth) {
33055
- auto[col2] = existingWidth;
33054
+ if (!auto[col] || auto[col] < existingWidth) {
33055
+ auto[col] = existingWidth;
33056
33056
  }
33057
33057
  }
33058
33058
  if (cell[desiredWidth] > existingWidth) {
33059
33059
  let i = 0;
33060
33060
  while (editableCols > 0 && cell[desiredWidth] > existingWidth) {
33061
- if (typeof vals[col2 + i] !== "number") {
33061
+ if (typeof vals[col + i] !== "number") {
33062
33062
  let dif = Math.round((cell[desiredWidth] - existingWidth) / editableCols);
33063
33063
  existingWidth += dif;
33064
- result[col2 + i] += dif;
33064
+ result[col + i] += dif;
33065
33065
  editableCols--;
33066
33066
  }
33067
33067
  i++;
@@ -33948,7 +33948,7 @@ function init(open, close) {
33948
33948
  var kleur_default = $;
33949
33949
 
33950
33950
  // src/commands/install.ts
33951
- var import_prompts2 = __toESM(require_prompts3(), 1);
33951
+ var import_prompts = __toESM(require_prompts3(), 1);
33952
33952
 
33953
33953
  // ../node_modules/eventemitter3/index.mjs
33954
33954
  var import_index2 = __toESM(require_eventemitter3(), 1);
@@ -34911,12 +34911,12 @@ var TestRendererSerializer = class {
34911
34911
  data
34912
34912
  };
34913
34913
  if (typeof this.options?.task !== "boolean") {
34914
- const t2 = Object.fromEntries(this.options.task.map((entity) => {
34914
+ const t3 = Object.fromEntries(this.options.task.map((entity) => {
34915
34915
  const property = task[entity];
34916
34916
  if (typeof property === "function") return [entity, property.call(task)];
34917
34917
  return [entity, property];
34918
34918
  }));
34919
- if (Object.keys(task).length > 0) output.task = t2;
34919
+ if (Object.keys(task).length > 0) output.task = t3;
34920
34920
  }
34921
34921
  return output;
34922
34922
  }
@@ -35746,14 +35746,15 @@ var Listr = class {
35746
35746
  };
35747
35747
 
35748
35748
  // src/commands/install.ts
35749
- var import_fs_extra11 = __toESM(require_lib2(), 1);
35749
+ var import_fs_extra12 = __toESM(require_lib2(), 1);
35750
+ var import_os5 = __toESM(require("os"), 1);
35750
35751
 
35751
35752
  // src/core/context.ts
35752
35753
  var import_os2 = __toESM(require("os"), 1);
35753
35754
  var import_path = __toESM(require("path"), 1);
35754
35755
  var import_fs_extra = __toESM(require_lib2(), 1);
35755
35756
 
35756
- // ../node_modules/conf/dist/source/index.js
35757
+ // node_modules/conf/dist/source/index.js
35757
35758
  var import_node_util3 = require("util");
35758
35759
  var import_node_process10 = __toESM(require("process"), 1);
35759
35760
  var import_node_fs3 = __toESM(require("fs"), 1);
@@ -36080,9 +36081,9 @@ var retryifyAsync = (fn, options) => {
36080
36081
  throw error49;
36081
36082
  if (Date.now() >= timestamp)
36082
36083
  throw error49;
36083
- const delay4 = Math.round(interval * Math.random());
36084
- if (delay4 > 0) {
36085
- const delayPromise = new Promise((resolve2) => setTimeout(resolve2, delay4));
36084
+ const delay3 = Math.round(interval * Math.random());
36085
+ if (delay3 > 0) {
36086
+ const delayPromise = new Promise((resolve2) => setTimeout(resolve2, delay3));
36086
36087
  return delayPromise.then(() => attempt.apply(void 0, args));
36087
36088
  } else {
36088
36089
  return attempt.apply(void 0, args);
@@ -36341,14 +36342,14 @@ var Temp = {
36341
36342
  }
36342
36343
  },
36343
36344
  truncate: (filePath) => {
36344
- const basename = import_node_path2.default.basename(filePath);
36345
- if (basename.length <= LIMIT_BASENAME_LENGTH)
36345
+ const basename2 = import_node_path2.default.basename(filePath);
36346
+ if (basename2.length <= LIMIT_BASENAME_LENGTH)
36346
36347
  return filePath;
36347
- const truncable = /^(\.?)(.*?)((?:\.[^.]+)?(?:\.tmp-\d{10}[a-f0-9]{6})?)$/.exec(basename);
36348
+ const truncable = /^(\.?)(.*?)((?:\.[^.]+)?(?:\.tmp-\d{10}[a-f0-9]{6})?)$/.exec(basename2);
36348
36349
  if (!truncable)
36349
36350
  return filePath;
36350
- const truncationLength = basename.length - LIMIT_BASENAME_LENGTH;
36351
- return `${filePath.slice(0, -basename.length)}${truncable[1]}${truncable[2].slice(0, -truncationLength)}${truncable[3]}`;
36351
+ const truncationLength = basename2.length - LIMIT_BASENAME_LENGTH;
36352
+ return `${filePath.slice(0, -basename2.length)}${truncable[1]}${truncable[2].slice(0, -truncationLength)}${truncable[3]}`;
36352
36353
  }
36353
36354
  };
36354
36355
  node_default(Temp.purgeSyncAll);
@@ -36432,7 +36433,7 @@ function writeFileSync(filePath, data, options = DEFAULT_WRITE_OPTIONS) {
36432
36433
  }
36433
36434
  }
36434
36435
 
36435
- // ../node_modules/conf/dist/source/index.js
36436
+ // node_modules/conf/dist/source/index.js
36436
36437
  var import_ajv = __toESM(require_ajv(), 1);
36437
36438
  var import_ajv_formats = __toESM(require_dist2(), 1);
36438
36439
 
@@ -36546,7 +36547,7 @@ var debounceFn = (inputFunction, options = {}) => {
36546
36547
  };
36547
36548
  var debounce_fn_default = debounceFn;
36548
36549
 
36549
- // ../node_modules/conf/dist/source/index.js
36550
+ // node_modules/conf/dist/source/index.js
36550
36551
  var import_semver = __toESM(require_semver2(), 1);
36551
36552
 
36552
36553
  // ../node_modules/uint8array-extras/index.js
@@ -36588,7 +36589,7 @@ function stringToUint8Array(string4) {
36588
36589
  }
36589
36590
  var byteToHexLookupTable = Array.from({ length: 256 }, (_, index) => index.toString(16).padStart(2, "0"));
36590
36591
 
36591
- // ../node_modules/conf/dist/source/index.js
36592
+ // node_modules/conf/dist/source/index.js
36592
36593
  var Ajv = import_ajv.default.default;
36593
36594
  var ajvFormats = import_ajv_formats.default.default;
36594
36595
  var encryptionAlgorithm = "aes-256-cbc";
@@ -36985,7 +36986,6 @@ var Conf = class {
36985
36986
  };
36986
36987
 
36987
36988
  // src/core/context.ts
36988
- var import_prompts = __toESM(require_prompts3(), 1);
36989
36989
  var config = null;
36990
36990
  function getConfig() {
36991
36991
  if (!config) {
@@ -37021,58 +37021,17 @@ function resolveTargets(selector, candidates) {
37021
37021
  }
37022
37022
  async function getContext(options = {}) {
37023
37023
  const { selector, createMissingDirs = true } = options;
37024
- const choices = [];
37025
37024
  const candidates = getCandidatePaths();
37026
37025
  const directTargets = resolveTargets(selector, candidates);
37027
- if (directTargets) {
37028
- const activeConfig2 = getConfig();
37029
- if (createMissingDirs) {
37030
- for (const target of directTargets) {
37031
- await import_fs_extra.default.ensureDir(target);
37032
- }
37033
- }
37034
- return {
37035
- targets: directTargets,
37036
- syncMode: activeConfig2.get("syncMode"),
37037
- config: activeConfig2
37038
- };
37039
- }
37040
37026
  const activeConfig = getConfig();
37041
- for (const c of candidates) {
37042
- const exists = await import_fs_extra.default.pathExists(c.path);
37043
- const icon = exists ? kleur_default.green("\u25CF") : kleur_default.gray("\u25CB");
37044
- const desc = exists ? "Found" : "Not found (will create)";
37045
- choices.push({
37046
- title: `${icon} ${c.label} (${c.path})`,
37047
- description: desc,
37048
- value: c.path,
37049
- selected: exists
37050
- // Pre-select existing environments
37051
- });
37052
- }
37053
- const response = await (0, import_prompts.default)({
37054
- type: "multiselect",
37055
- name: "targets",
37056
- message: "Select target environment(s):",
37057
- choices,
37058
- hint: "- Space to select. Return to submit",
37059
- instructions: false
37060
- });
37061
- if (response.targets === void 0) {
37062
- console.log(kleur_default.gray("\nCancelled."));
37063
- process.exit(130);
37064
- }
37065
- if (response.targets.length === 0) {
37066
- console.log(kleur_default.gray("No targets selected."));
37067
- process.exit(0);
37068
- }
37027
+ const selectedPaths = directTargets ?? candidates.map((c) => c.path);
37069
37028
  if (createMissingDirs) {
37070
- for (const target of response.targets) {
37029
+ for (const target of selectedPaths) {
37071
37030
  await import_fs_extra.default.ensureDir(target);
37072
37031
  }
37073
37032
  }
37074
37033
  return {
37075
- targets: response.targets,
37034
+ targets: selectedPaths,
37076
37035
  syncMode: activeConfig.get("syncMode"),
37077
37036
  config: activeConfig
37078
37037
  };
@@ -37182,16 +37141,13 @@ var PruneModeReadError = class extends Error {
37182
37141
  async function calculateDiff(repoRoot, systemRoot, pruneMode = false) {
37183
37142
  const adapter = detectAdapter(systemRoot);
37184
37143
  const isClaude = adapter?.toolName === "claude-code";
37185
- const isQwen = adapter?.toolName === "qwen";
37186
37144
  const normalizedRoot = (0, import_path4.normalize)(systemRoot).replace(/\\/g, "/");
37187
37145
  const isAgentsSkills = normalizedRoot.includes(".agents/skills");
37188
37146
  const changeSet = {
37189
37147
  skills: { missing: [], outdated: [], drifted: [], total: 0 },
37190
37148
  hooks: { missing: [], outdated: [], drifted: [], total: 0 },
37191
37149
  config: { missing: [], outdated: [], drifted: [], total: 0 },
37192
- commands: { missing: [], outdated: [], drifted: [], total: 0 },
37193
- "qwen-commands": { missing: [], outdated: [], drifted: [], total: 0 },
37194
- "antigravity-workflows": { missing: [], outdated: [], drifted: [], total: 0 }
37150
+ commands: { missing: [], outdated: [], drifted: [], total: 0 }
37195
37151
  };
37196
37152
  const manifestPath = (0, import_path4.join)(systemRoot, ".jaggers-sync-manifest.json");
37197
37153
  let installedHashes = null;
@@ -37215,18 +37171,10 @@ async function calculateDiff(repoRoot, systemRoot, pruneMode = false) {
37215
37171
  return changeSet;
37216
37172
  }
37217
37173
  const folders = ["skills", "hooks"];
37218
- if (isQwen) folders.push("qwen-commands");
37219
- else if (!isClaude) folders.push("commands");
37174
+ if (!isClaude) folders.push("commands");
37220
37175
  for (const category of folders) {
37221
- let repoPath;
37222
- let systemPath;
37223
- if (category === "qwen-commands") {
37224
- repoPath = (0, import_path4.join)(repoRoot, ".qwen", "commands");
37225
- systemPath = (0, import_path4.join)(systemRoot, "commands");
37226
- } else {
37227
- repoPath = (0, import_path4.join)(repoRoot, category);
37228
- systemPath = (0, import_path4.join)(systemRoot, category);
37229
- }
37176
+ const repoPath = (0, import_path4.join)(repoRoot, category);
37177
+ const systemPath = (0, import_path4.join)(systemRoot, category);
37230
37178
  if (!await import_fs_extra3.default.pathExists(repoPath)) continue;
37231
37179
  const items = (await import_fs_extra3.default.readdir(repoPath)).filter((i) => !IGNORED_ITEMS.has(i));
37232
37180
  changeSet[category].total = items.length;
@@ -37417,7 +37365,7 @@ function mergeHookWrappers(existing, incoming) {
37417
37365
  if (!existingCommands.some((c) => incomingKeys.has(commandKey(c)))) return false;
37418
37366
  if (typeof existingWrapper2.matcher === "string" && typeof incomingWrapper.matcher === "string" && incomingTokens.size > 0) {
37419
37367
  const existingTokens = existingWrapper2.matcher.split("|").map((s) => s.trim()).filter(Boolean);
37420
- const hasOverlap = existingTokens.some((t2) => incomingTokens.has(t2));
37368
+ const hasOverlap = existingTokens.some((t3) => incomingTokens.has(t3));
37421
37369
  if (!hasOverlap) return false;
37422
37370
  }
37423
37371
  return true;
@@ -40170,7 +40118,7 @@ async function handleMissingEnvVars(missing) {
40170
40118
  if (missing.length === 0) {
40171
40119
  return true;
40172
40120
  }
40173
- const prompts7 = (await Promise.resolve().then(() => __toESM(require_prompts3(), 1))).default;
40121
+ const prompts6 = (await Promise.resolve().then(() => __toESM(require_prompts3(), 1))).default;
40174
40122
  const answers = {};
40175
40123
  for (const key of missing) {
40176
40124
  const config3 = REQUIRED_ENV_VARS[key];
@@ -40182,7 +40130,7 @@ async function handleMissingEnvVars(missing) {
40182
40130
  console.log(kleur_default.yellow(`
40183
40131
  \u26A0\uFE0F ${key} is required by a selected MCP server`));
40184
40132
  }
40185
- const { value } = await prompts7({
40133
+ const { value } = await prompts6({
40186
40134
  type: "text",
40187
40135
  name: "value",
40188
40136
  message: `Enter ${key}:`,
@@ -40395,8 +40343,8 @@ async function syncMcpServersWithCli(agent, mcpConfig, dryRun = false, prune = f
40395
40343
  }
40396
40344
  let selectedNames = toAdd.map(([name]) => name);
40397
40345
  if (!dryRun) {
40398
- const prompts7 = await Promise.resolve().then(() => __toESM(require_prompts3(), 1));
40399
- const { selected } = await prompts7.default({
40346
+ const prompts6 = await Promise.resolve().then(() => __toESM(require_prompts3(), 1));
40347
+ const { selected } = await prompts6.default({
40400
40348
  type: "multiselect",
40401
40349
  name: "selected",
40402
40350
  message: `Select MCP servers to install via ${agent} CLI:`,
@@ -40853,36 +40801,49 @@ var sym = {
40853
40801
  };
40854
40802
 
40855
40803
  // src/commands/install.ts
40856
- var import_path11 = __toESM(require("path"), 1);
40804
+ var import_path12 = __toESM(require("path"), 1);
40857
40805
 
40858
40806
  // src/commands/pi-install.ts
40859
- var import_fs_extra10 = __toESM(require_lib2(), 1);
40860
- var import_path10 = __toESM(require("path"), 1);
40807
+ var import_fs_extra11 = __toESM(require_lib2(), 1);
40808
+ var import_path11 = __toESM(require("path"), 1);
40861
40809
  var import_node_child_process = require("child_process");
40862
40810
  var import_node_os4 = require("os");
40863
- var PI_AGENT_DIR = process.env.PI_AGENT_DIR || import_path10.default.join((0, import_node_os4.homedir)(), ".pi", "agent");
40811
+
40812
+ // src/utils/pi-extensions.ts
40813
+ var import_fs_extra10 = __toESM(require_lib2(), 1);
40814
+ var import_path10 = __toESM(require("path"), 1);
40815
+ async function syncManagedPiExtensions({
40816
+ sourceDir,
40817
+ targetDir,
40818
+ dryRun = false,
40819
+ log
40820
+ }) {
40821
+ if (!await import_fs_extra10.default.pathExists(sourceDir)) return 0;
40822
+ if (!dryRun) {
40823
+ await import_fs_extra10.default.ensureDir(import_path10.default.dirname(targetDir));
40824
+ await import_fs_extra10.default.copy(sourceDir, targetDir, { overwrite: true });
40825
+ }
40826
+ const entries = await import_fs_extra10.default.readdir(sourceDir, { withFileTypes: true });
40827
+ const managedPackages = entries.filter((entry) => entry.isDirectory()).length;
40828
+ if (log) {
40829
+ if (dryRun) {
40830
+ log(` [DRY RUN] sync extensions ${sourceDir} -> ${targetDir}`);
40831
+ }
40832
+ log(` Pi will auto-discover ${managedPackages} extension package(s) from ${targetDir}`);
40833
+ }
40834
+ return managedPackages;
40835
+ }
40836
+
40837
+ // src/commands/pi-install.ts
40838
+ var PI_AGENT_DIR = process.env.PI_AGENT_DIR || import_path11.default.join((0, import_node_os4.homedir)(), ".pi", "agent");
40864
40839
  function isPiInstalled() {
40865
40840
  const r = (0, import_node_child_process.spawnSync)("pi", ["--version"], { encoding: "utf8", stdio: "pipe" });
40866
40841
  return r.status === 0;
40867
40842
  }
40868
- async function listExtensionDirs(baseDir) {
40869
- if (!await import_fs_extra10.default.pathExists(baseDir)) return [];
40870
- const entries = await import_fs_extra10.default.readdir(baseDir, { withFileTypes: true });
40871
- const extDirs = [];
40872
- for (const entry of entries) {
40873
- if (!entry.isDirectory()) continue;
40874
- const extPath = import_path10.default.join(baseDir, entry.name);
40875
- const pkgPath = import_path10.default.join(extPath, "package.json");
40876
- if (await import_fs_extra10.default.pathExists(pkgPath)) {
40877
- extDirs.push(extPath);
40878
- }
40879
- }
40880
- return extDirs;
40881
- }
40882
40843
  async function runPiInstall(dryRun = false) {
40883
40844
  const repoRoot = await findRepoRoot();
40884
- const piConfigDir = import_path10.default.join(repoRoot, "config", "pi");
40885
- const schemaPath = import_path10.default.join(piConfigDir, "install-schema.json");
40845
+ const piConfigDir = import_path11.default.join(repoRoot, "config", "pi");
40846
+ const schemaPath = import_path11.default.join(piConfigDir, "install-schema.json");
40886
40847
  console.log(t.bold("\n \u2699 Pi extensions + packages"));
40887
40848
  if (!isPiInstalled()) {
40888
40849
  console.log(kleur_default.yellow(" pi not found \u2014 installing oh-pi globally..."));
@@ -40900,37 +40861,22 @@ async function runPiInstall(dryRun = false) {
40900
40861
  const v = (0, import_node_child_process.spawnSync)("pi", ["--version"], { encoding: "utf8" });
40901
40862
  console.log(t.success(` \u2713 pi ${v.stdout.trim()} already installed`));
40902
40863
  }
40903
- const extensionsSrc = import_path10.default.join(piConfigDir, "extensions");
40904
- const extensionsDst = import_path10.default.join(PI_AGENT_DIR, "extensions");
40905
- if (await import_fs_extra10.default.pathExists(extensionsSrc)) {
40906
- if (!dryRun) {
40907
- await import_fs_extra10.default.ensureDir(PI_AGENT_DIR);
40908
- await import_fs_extra10.default.copy(extensionsSrc, extensionsDst, { overwrite: true });
40909
- }
40910
- console.log(t.success(` ${sym.ok} extensions synced`));
40911
- const extDirs = await listExtensionDirs(extensionsDst);
40912
- if (extDirs.length > 0) {
40913
- console.log(kleur_default.dim(` Registering ${extDirs.length} extensions...`));
40914
- for (const extPath of extDirs) {
40915
- const extName = import_path10.default.basename(extPath);
40916
- if (dryRun) {
40917
- console.log(kleur_default.cyan(` [DRY RUN] pi install -l ~/.pi/agent/extensions/${extName}`));
40918
- continue;
40919
- }
40920
- const r = (0, import_node_child_process.spawnSync)("pi", ["install", "-l", extPath], { stdio: "pipe", encoding: "utf8" });
40921
- if (r.status === 0) {
40922
- console.log(t.success(` ${sym.ok} ${extName} registered`));
40923
- } else {
40924
- console.log(kleur_default.yellow(` \u26A0 ${extName} \u2014 registration failed`));
40925
- }
40926
- }
40927
- }
40864
+ const extensionsSrc = import_path11.default.join(piConfigDir, "extensions");
40865
+ const extensionsDst = import_path11.default.join(PI_AGENT_DIR, "extensions");
40866
+ const managedPackages = await syncManagedPiExtensions({
40867
+ sourceDir: extensionsSrc,
40868
+ targetDir: extensionsDst,
40869
+ dryRun,
40870
+ log: (message) => console.log(kleur_default.dim(message))
40871
+ });
40872
+ if (managedPackages > 0) {
40873
+ console.log(t.success(` ${sym.ok} extensions synced (${managedPackages} packages)`));
40928
40874
  }
40929
- if (!await import_fs_extra10.default.pathExists(schemaPath)) {
40875
+ if (!await import_fs_extra11.default.pathExists(schemaPath)) {
40930
40876
  console.log(kleur_default.dim(" No install-schema.json found, skipping packages"));
40931
40877
  return;
40932
40878
  }
40933
- const schema = await import_fs_extra10.default.readJson(schemaPath);
40879
+ const schema = await import_fs_extra11.default.readJson(schemaPath);
40934
40880
  for (const pkg of schema.packages) {
40935
40881
  if (dryRun) {
40936
40882
  console.log(kleur_default.cyan(` [DRY RUN] pi install ${pkg}`));
@@ -40996,7 +40942,7 @@ function formatTargetLabel(target) {
40996
40942
  const normalized = target.replace(/\\/g, "/").toLowerCase();
40997
40943
  if (normalized.endsWith("/.agents/skills") || normalized.includes("/.agents/skills/")) return "~/.agents/skills";
40998
40944
  if (normalized.endsWith("/.claude") || normalized.includes("/.claude/")) return "~/.claude";
40999
- return import_path11.default.basename(target);
40945
+ return import_path12.default.basename(target);
41000
40946
  }
41001
40947
  function isBeadsInstalled() {
41002
40948
  try {
@@ -41014,19 +40960,27 @@ function isDoltInstalled() {
41014
40960
  return false;
41015
40961
  }
41016
40962
  }
40963
+ function isDeepwikiInstalled() {
40964
+ try {
40965
+ (0, import_child_process2.execSync)("deepwiki --version", { stdio: "ignore" });
40966
+ return true;
40967
+ } catch {
40968
+ return false;
40969
+ }
40970
+ }
41017
40971
  async function needsSettingsSync(repoRoot, target) {
41018
40972
  const normalizedTarget = target.replace(/\\/g, "/").toLowerCase();
41019
40973
  if (normalizedTarget.includes(".agents/skills")) return false;
41020
40974
  if (detectAgent(target) === "claude") return false;
41021
- const hooksTemplatePath = import_path11.default.join(repoRoot, "config", "hooks.json");
41022
- if (!await import_fs_extra11.default.pathExists(hooksTemplatePath)) return false;
41023
- const requiredEvents = Object.keys((await import_fs_extra11.default.readJson(hooksTemplatePath)).hooks ?? {});
40975
+ const hooksTemplatePath = import_path12.default.join(repoRoot, "config", "hooks.json");
40976
+ if (!await import_fs_extra12.default.pathExists(hooksTemplatePath)) return false;
40977
+ const requiredEvents = Object.keys((await import_fs_extra12.default.readJson(hooksTemplatePath)).hooks ?? {});
41024
40978
  if (requiredEvents.length === 0) return false;
41025
- const targetSettingsPath = import_path11.default.join(target, "settings.json");
41026
- if (!await import_fs_extra11.default.pathExists(targetSettingsPath)) return true;
40979
+ const targetSettingsPath = import_path12.default.join(target, "settings.json");
40980
+ if (!await import_fs_extra12.default.pathExists(targetSettingsPath)) return true;
41027
40981
  let settings = {};
41028
40982
  try {
41029
- settings = await import_fs_extra11.default.readJson(targetSettingsPath);
40983
+ settings = await import_fs_extra12.default.readJson(targetSettingsPath);
41030
40984
  } catch {
41031
40985
  return true;
41032
40986
  }
@@ -41069,20 +41023,114 @@ async function installOfficialClaudePlugins(dryRun) {
41069
41023
  console.log(t.success(` \u2713 Official plugins ready (${installedCount} installed, ${alreadyInstalledCount} already present)
41070
41024
  `));
41071
41025
  }
41026
+ async function cleanStalePrePluginFiles(repoRoot, dryRun) {
41027
+ const home = import_os5.default.homedir();
41028
+ const staleHooksDir = import_path12.default.join(home, ".claude", "hooks");
41029
+ const staleSkillsDir = import_path12.default.join(home, ".claude", "skills");
41030
+ const settingsPath = import_path12.default.join(home, ".claude", "settings.json");
41031
+ const removed = [];
41032
+ const repoHooksDir = import_path12.default.join(repoRoot, "hooks");
41033
+ if (await import_fs_extra12.default.pathExists(repoHooksDir) && await import_fs_extra12.default.pathExists(staleHooksDir)) {
41034
+ const repoHookNames = (await import_fs_extra12.default.readdir(repoHooksDir)).filter((n) => n !== "README.md" && n !== "hooks.json");
41035
+ for (const name of repoHookNames) {
41036
+ const staleFile = import_path12.default.join(staleHooksDir, name);
41037
+ if (await import_fs_extra12.default.pathExists(staleFile)) {
41038
+ if (dryRun) {
41039
+ console.log(t.accent(` [DRY RUN] Would remove stale hook: ~/.claude/hooks/${name}`));
41040
+ } else {
41041
+ await import_fs_extra12.default.remove(staleFile);
41042
+ console.log(t.muted(` \u2717 Removed stale hook: ~/.claude/hooks/${name}`));
41043
+ }
41044
+ removed.push(`hooks/${name}`);
41045
+ }
41046
+ }
41047
+ }
41048
+ const repoSkillsDir = import_path12.default.join(repoRoot, "skills");
41049
+ if (await import_fs_extra12.default.pathExists(repoSkillsDir) && await import_fs_extra12.default.pathExists(staleSkillsDir)) {
41050
+ const repoSkillNames = (await import_fs_extra12.default.readdir(repoSkillsDir)).filter((n) => !n.startsWith("."));
41051
+ for (const name of repoSkillNames) {
41052
+ const staleDir = import_path12.default.join(staleSkillsDir, name);
41053
+ if (await import_fs_extra12.default.pathExists(staleDir)) {
41054
+ if (dryRun) {
41055
+ console.log(t.accent(` [DRY RUN] Would remove stale skill: ~/.claude/skills/${name}`));
41056
+ } else {
41057
+ await import_fs_extra12.default.remove(staleDir);
41058
+ console.log(t.muted(` \u2717 Removed stale skill: ~/.claude/skills/${name}`));
41059
+ }
41060
+ removed.push(`skills/${name}`);
41061
+ }
41062
+ }
41063
+ }
41064
+ if (await import_fs_extra12.default.pathExists(settingsPath)) {
41065
+ let settings;
41066
+ try {
41067
+ settings = await import_fs_extra12.default.readJson(settingsPath);
41068
+ } catch {
41069
+ settings = null;
41070
+ }
41071
+ if (settings && settings.hooks && typeof settings.hooks === "object") {
41072
+ let settingsModified = false;
41073
+ for (const [event, matchers] of Object.entries(settings.hooks)) {
41074
+ if (!Array.isArray(matchers)) continue;
41075
+ const cleanedMatchers = matchers.filter((matcher) => {
41076
+ const hooks = Array.isArray(matcher?.hooks) ? matcher.hooks : [];
41077
+ const staleHooks = hooks.filter((h) => {
41078
+ const cmd = typeof h?.command === "string" ? h.command : "";
41079
+ return cmd.includes("/.claude/hooks/") && !cmd.includes("${CLAUDE_PLUGIN_ROOT}");
41080
+ });
41081
+ if (staleHooks.length > 0) {
41082
+ for (const h of staleHooks) {
41083
+ const msg = `settings.json [${event}] hook: ${h.command}`;
41084
+ if (dryRun) {
41085
+ console.log(t.accent(` [DRY RUN] Would remove stale ${msg}`));
41086
+ } else {
41087
+ console.log(t.muted(` \u2717 Removed stale ${msg}`));
41088
+ }
41089
+ removed.push(msg);
41090
+ }
41091
+ const remainingHooks = hooks.filter((h) => {
41092
+ const cmd = typeof h?.command === "string" ? h.command : "";
41093
+ return !(cmd.includes("/.claude/hooks/") && !cmd.includes("${CLAUDE_PLUGIN_ROOT}"));
41094
+ });
41095
+ if (remainingHooks.length === 0) return false;
41096
+ matcher.hooks = remainingHooks;
41097
+ settingsModified = true;
41098
+ return true;
41099
+ }
41100
+ return true;
41101
+ });
41102
+ if (cleanedMatchers.length !== matchers.length) {
41103
+ settings.hooks[event] = cleanedMatchers;
41104
+ settingsModified = true;
41105
+ }
41106
+ }
41107
+ if (settingsModified && !dryRun) {
41108
+ await import_fs_extra12.default.writeJson(settingsPath, settings, { spaces: 2 });
41109
+ }
41110
+ }
41111
+ }
41112
+ if (removed.length === 0) {
41113
+ console.log(t.success(" \u2713 No stale pre-plugin files found"));
41114
+ }
41115
+ }
41072
41116
  async function installPlugin(repoRoot, dryRun) {
41073
41117
  console.log(t.bold("\n \u2699 xtrm-tools (Claude Code plugin)"));
41074
41118
  if (dryRun) {
41075
41119
  console.log(t.accent(" [DRY RUN] Would register xtrm-tools marketplace and install plugin\n"));
41120
+ await cleanStalePrePluginFiles(repoRoot, true);
41076
41121
  await installOfficialClaudePlugins(true);
41077
41122
  return;
41078
41123
  }
41079
- (0, import_child_process3.spawnSync)("claude", ["plugin", "marketplace", "add", repoRoot, "--scope", "user"], { stdio: "pipe" });
41124
+ const xtrmPkgRoot = import_path12.default.resolve(__dirname, "..", "..");
41125
+ (0, import_child_process3.spawnSync)("claude", ["plugin", "marketplace", "add", xtrmPkgRoot, "--scope", "user"], { stdio: "pipe" });
41080
41126
  const listResult = (0, import_child_process3.spawnSync)("claude", ["plugin", "list"], { encoding: "utf8", stdio: "pipe" });
41081
41127
  if (listResult.stdout?.includes("xtrm-tools@xtrm-tools")) {
41082
41128
  (0, import_child_process3.spawnSync)("claude", ["plugin", "uninstall", "xtrm-tools@xtrm-tools"], { stdio: "inherit" });
41083
41129
  }
41084
41130
  (0, import_child_process3.spawnSync)("claude", ["plugin", "install", "xtrm-tools@xtrm-tools", "--scope", "user"], { stdio: "inherit" });
41085
41131
  console.log(t.success(" \u2713 xtrm-tools plugin installed"));
41132
+ console.log(t.warning(" \u21BB Restart Claude Code for the new plugin hooks to take effect"));
41133
+ await cleanStalePrePluginFiles(repoRoot, dryRun);
41086
41134
  await installOfficialClaudePlugins(false);
41087
41135
  }
41088
41136
  function createInstallAllCommand() {
@@ -41107,8 +41155,8 @@ function createInstallCommand() {
41107
41155
  createMissingDirs: !dryRun
41108
41156
  });
41109
41157
  const { targets, syncMode } = ctx;
41110
- const claudeTargets = targets.filter((t2) => detectAgent(t2) === "claude");
41111
- const otherTargets = targets.filter((t2) => detectAgent(t2) !== "claude");
41158
+ const claudeTargets = targets.filter((t3) => detectAgent(t3) === "claude");
41159
+ const otherTargets = targets.filter((t3) => detectAgent(t3) !== "claude");
41112
41160
  if (!backport) {
41113
41161
  console.log(t.bold("\n \u2699 beads + dolt (workflow enforcement backend)"));
41114
41162
  console.log(t.muted(" beads is a git-backed issue tracker; dolt is its SQL+git storage backend."));
@@ -41121,7 +41169,7 @@ function createInstallCommand() {
41121
41169
  const missing = [!beadsOk && "bd", !doltOk && "dolt"].filter(Boolean).join(", ");
41122
41170
  let doInstall = effectiveYes;
41123
41171
  if (!effectiveYes) {
41124
- const { install } = await (0, import_prompts2.default)({
41172
+ const { install } = await (0, import_prompts.default)({
41125
41173
  type: "confirm",
41126
41174
  name: "install",
41127
41175
  message: `Install beads + dolt? (${missing} not found) \u2014 required for workflow enforcement hooks`,
@@ -41154,6 +41202,31 @@ function createInstallCommand() {
41154
41202
  }
41155
41203
  }
41156
41204
  }
41205
+ if (!backport) {
41206
+ console.log(t.bold("\n \u2699 deepwiki (AI-powered repo documentation)"));
41207
+ const deepwikiOk = isDeepwikiInstalled();
41208
+ if (deepwikiOk) {
41209
+ console.log(t.success(" \u2713 deepwiki already installed\n"));
41210
+ } else {
41211
+ let doInstall = effectiveYes;
41212
+ if (!effectiveYes) {
41213
+ const { install } = await (0, import_prompts.default)({
41214
+ type: "confirm",
41215
+ name: "install",
41216
+ message: "Install @seflless/deepwiki?",
41217
+ initial: true
41218
+ });
41219
+ doInstall = install;
41220
+ }
41221
+ if (doInstall) {
41222
+ console.log(t.muted("\n Installing @seflless/deepwiki..."));
41223
+ (0, import_child_process3.spawnSync)("npm", ["install", "-g", "@seflless/deepwiki"], { stdio: "inherit" });
41224
+ console.log(t.success(" \u2713 deepwiki installed\n"));
41225
+ } else {
41226
+ console.log(t.muted(" \u2139 Skipped.\n"));
41227
+ }
41228
+ }
41229
+ }
41157
41230
  if (!backport) {
41158
41231
  for (const _claudeTarget of claudeTargets) {
41159
41232
  await installPlugin(repoRoot, dryRun);
@@ -41207,7 +41280,7 @@ function createInstallCommand() {
41207
41280
  }
41208
41281
  if (!effectiveYes) {
41209
41282
  const totalChangesCount = allChanges.reduce((s, c) => s + c.totalChanges, 0);
41210
- const { confirm } = await (0, import_prompts2.default)({
41283
+ const { confirm } = await (0, import_prompts.default)({
41211
41284
  type: "confirm",
41212
41285
  name: "confirm",
41213
41286
  message: `Proceed with ${actionLabel} (${totalChangesCount} total changes)?`,
@@ -41245,61 +41318,93 @@ var import_node_child_process3 = require("child_process");
41245
41318
 
41246
41319
  // src/utils/worktree-session.ts
41247
41320
  var import_node_path5 = __toESM(require("path"), 1);
41248
- var import_fs_extra12 = __toESM(require_lib2(), 1);
41249
41321
  var import_node_child_process2 = require("child_process");
41322
+ var import_node_fs4 = require("fs");
41323
+ var import_node_os5 = require("os");
41250
41324
  function randomSlug(len = 4) {
41251
41325
  return Math.random().toString(36).slice(2, 2 + len);
41252
41326
  }
41253
- function shortDate() {
41254
- const d = /* @__PURE__ */ new Date();
41255
- return `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, "0")}${String(d.getDate()).padStart(2, "0")}`;
41327
+ function gitRepoRoot(cwd) {
41328
+ const r = (0, import_node_child_process2.spawnSync)("git", ["rev-parse", "--show-toplevel"], {
41329
+ cwd,
41330
+ stdio: "pipe",
41331
+ encoding: "utf8"
41332
+ });
41333
+ return r.status === 0 ? (r.stdout ?? "").trim() : null;
41334
+ }
41335
+ function resolveStatuslineScript() {
41336
+ const pluginsFile = import_node_path5.default.join((0, import_node_os5.homedir)(), ".claude", "plugins", "installed_plugins.json");
41337
+ try {
41338
+ const plugins = JSON.parse((0, import_node_fs4.readFileSync)(pluginsFile, "utf8"));
41339
+ for (const [key, entries] of Object.entries(plugins?.plugins ?? {})) {
41340
+ if (!key.startsWith("xtrm-tools@") || !entries?.length) continue;
41341
+ const p = import_node_path5.default.join(entries[0].installPath, "hooks", "statusline.mjs");
41342
+ if ((0, import_node_fs4.existsSync)(p)) return p;
41343
+ }
41344
+ } catch {
41345
+ }
41346
+ const fallback = import_node_path5.default.join((0, import_node_os5.homedir)(), ".claude", "hooks", "statusline.mjs");
41347
+ return (0, import_node_fs4.existsSync)(fallback) ? fallback : null;
41256
41348
  }
41257
41349
  async function launchWorktreeSession(opts) {
41258
41350
  const { runtime, name } = opts;
41259
41351
  const cwd = process.cwd();
41260
- const repoRoot = await findRepoRoot();
41261
- const cwdBasename = import_node_path5.default.basename(cwd);
41262
- const date5 = shortDate();
41263
- const worktreeName = `${cwdBasename}-xt-${runtime}-${date5}`;
41264
- const worktreePath = import_node_path5.default.join(import_node_path5.default.dirname(cwd), worktreeName);
41265
- const branchName = `xt/${name ?? randomSlug(4)}`;
41352
+ const repoRoot = gitRepoRoot(cwd);
41353
+ if (!repoRoot) {
41354
+ console.error(kleur_default.red("\n \u2717 Not inside a git repository\n"));
41355
+ process.exit(1);
41356
+ }
41357
+ const cwdBasename = import_node_path5.default.basename(repoRoot);
41358
+ const slug = name ?? randomSlug(4);
41359
+ const worktreeName = `${cwdBasename}-xt-${runtime}-${slug}`;
41360
+ const worktreePath = import_node_path5.default.join(repoRoot, ".xtrm", "worktrees", worktreeName);
41361
+ const branchName = `xt/${slug}`;
41266
41362
  console.log(kleur_default.bold(`
41267
41363
  Launching ${runtime} session`));
41268
41364
  console.log(kleur_default.dim(` worktree: ${worktreePath}`));
41269
41365
  console.log(kleur_default.dim(` branch: ${branchName}
41270
41366
  `));
41271
- const branchExists = (0, import_node_child_process2.spawnSync)("git", ["rev-parse", "--verify", branchName], {
41367
+ const bdResult = (0, import_node_child_process2.spawnSync)("bd", ["worktree", "create", worktreePath, "--branch", branchName], {
41272
41368
  cwd: repoRoot,
41273
- stdio: "pipe"
41274
- }).status === 0;
41275
- const worktreeArgs = branchExists ? ["worktree", "add", worktreePath, branchName] : ["worktree", "add", "-b", branchName, worktreePath];
41276
- const worktreeResult = (0, import_node_child_process2.spawnSync)("git", worktreeArgs, { cwd: repoRoot, stdio: "inherit" });
41277
- if (worktreeResult.status !== 0) {
41278
- console.error(kleur_default.red(`
41369
+ stdio: "inherit"
41370
+ });
41371
+ if (bdResult.error || bdResult.status !== 0) {
41372
+ if (bdResult.status !== 0 && !bdResult.error) {
41373
+ console.log(kleur_default.dim(" beads: no database found, creating worktree without redirect"));
41374
+ }
41375
+ const branchExists = (0, import_node_child_process2.spawnSync)("git", ["rev-parse", "--verify", branchName], {
41376
+ cwd: repoRoot,
41377
+ stdio: "pipe"
41378
+ }).status === 0;
41379
+ const gitArgs = branchExists ? ["worktree", "add", worktreePath, branchName] : ["worktree", "add", "-b", branchName, worktreePath];
41380
+ const gitResult = (0, import_node_child_process2.spawnSync)("git", gitArgs, { cwd: repoRoot, stdio: "inherit" });
41381
+ if (gitResult.status !== 0) {
41382
+ console.error(kleur_default.red(`
41279
41383
  \u2717 Failed to create worktree at ${worktreePath}
41280
41384
  `));
41281
- process.exit(1);
41282
- }
41283
- const mainBeadsDir = import_node_path5.default.join(repoRoot, ".beads");
41284
- const worktreeBeadsDir = import_node_path5.default.join(worktreePath, ".beads");
41285
- const mainPortFile = import_node_path5.default.join(mainBeadsDir, "dolt-server.port");
41286
- if (await import_fs_extra12.default.pathExists(mainBeadsDir)) {
41287
- const worktreePortFile = import_node_path5.default.join(worktreeBeadsDir, "dolt-server.port");
41288
- (0, import_node_child_process2.spawnSync)("bd", ["dolt", "stop"], { cwd: worktreePath, stdio: "pipe" });
41289
- if (await import_fs_extra12.default.pathExists(mainPortFile)) {
41290
- const mainPort = (await import_fs_extra12.default.readFile(mainPortFile, "utf8")).trim();
41291
- await import_fs_extra12.default.ensureDir(worktreeBeadsDir);
41292
- await import_fs_extra12.default.writeFile(worktreePortFile, mainPort, "utf8");
41293
- console.log(kleur_default.dim(` beads: redirected to main server (port ${mainPort})`));
41294
- } else {
41295
- console.log(kleur_default.dim(" beads: no port file found in main checkout, skipping redirect"));
41385
+ process.exit(1);
41296
41386
  }
41297
41387
  }
41298
41388
  console.log(kleur_default.green(`
41299
41389
  \u2713 Worktree ready \u2014 launching ${runtime}...
41300
41390
  `));
41391
+ if (runtime === "claude") {
41392
+ const statuslinePath = resolveStatuslineScript();
41393
+ if (statuslinePath) {
41394
+ const claudeDir = import_node_path5.default.join(worktreePath, ".claude");
41395
+ const localSettingsPath = import_node_path5.default.join(claudeDir, "settings.local.json");
41396
+ try {
41397
+ (0, import_node_fs4.mkdirSync)(claudeDir, { recursive: true });
41398
+ (0, import_node_fs4.writeFileSync)(localSettingsPath, JSON.stringify({
41399
+ statusLine: { type: "command", command: `node ${statuslinePath}`, padding: 1 }
41400
+ }, null, 2));
41401
+ } catch {
41402
+ }
41403
+ }
41404
+ }
41301
41405
  const runtimeCmd = runtime === "claude" ? "claude" : "pi";
41302
- const launchResult = (0, import_node_child_process2.spawnSync)(runtimeCmd, [], {
41406
+ const runtimeArgs = runtime === "claude" ? ["--dangerously-skip-permissions"] : [];
41407
+ const launchResult = (0, import_node_child_process2.spawnSync)(runtimeCmd, runtimeArgs, {
41303
41408
  cwd: worktreePath,
41304
41409
  stdio: "inherit"
41305
41410
  });
@@ -41392,31 +41497,31 @@ function createClaudeCommand() {
41392
41497
  }
41393
41498
 
41394
41499
  // src/commands/pi.ts
41395
- var import_path13 = __toESM(require("path"), 1);
41500
+ var import_path14 = __toESM(require("path"), 1);
41396
41501
  var import_node_child_process5 = require("child_process");
41397
- var import_node_os6 = require("os");
41502
+ var import_node_os7 = require("os");
41398
41503
  var import_fs_extra14 = __toESM(require_lib2(), 1);
41399
41504
 
41400
41505
  // src/commands/install-pi.ts
41401
- var import_prompts3 = __toESM(require_prompts3(), 1);
41506
+ var import_prompts2 = __toESM(require_prompts3(), 1);
41402
41507
  var import_fs_extra13 = __toESM(require_lib2(), 1);
41403
- var import_path12 = __toESM(require("path"), 1);
41508
+ var import_path13 = __toESM(require("path"), 1);
41404
41509
  var import_node_child_process4 = require("child_process");
41405
- var import_node_os5 = require("os");
41406
- var PI_AGENT_DIR2 = process.env.PI_AGENT_DIR || import_path12.default.join((0, import_node_os5.homedir)(), ".pi", "agent");
41510
+ var import_node_os6 = require("os");
41511
+ var PI_AGENT_DIR2 = process.env.PI_AGENT_DIR || import_path13.default.join((0, import_node_os6.homedir)(), ".pi", "agent");
41407
41512
  function fillTemplate(template, values) {
41408
41513
  return template.replace(/\{\{(\w+)\}\}/g, (_, key) => values[key] ?? "");
41409
41514
  }
41410
41515
  function readExistingPiValues(piAgentDir) {
41411
41516
  const values = {};
41412
41517
  try {
41413
- const auth = JSON.parse(require("fs").readFileSync(import_path12.default.join(piAgentDir, "auth.json"), "utf8"));
41518
+ const auth = JSON.parse(require("fs").readFileSync(import_path13.default.join(piAgentDir, "auth.json"), "utf8"));
41414
41519
  if (auth?.dashscope?.key) values["DASHSCOPE_API_KEY"] = auth.dashscope.key;
41415
41520
  if (auth?.zai?.key) values["ZAI_API_KEY"] = auth.zai.key;
41416
41521
  } catch {
41417
41522
  }
41418
41523
  try {
41419
- const models = JSON.parse(require("fs").readFileSync(import_path12.default.join(piAgentDir, "models.json"), "utf8"));
41524
+ const models = JSON.parse(require("fs").readFileSync(import_path13.default.join(piAgentDir, "models.json"), "utf8"));
41420
41525
  if (!values["DASHSCOPE_API_KEY"] && models?.providers?.dashscope?.apiKey) {
41421
41526
  values["DASHSCOPE_API_KEY"] = models.providers.dashscope.apiKey;
41422
41527
  }
@@ -41427,14 +41532,14 @@ function readExistingPiValues(piAgentDir) {
41427
41532
  function isPiInstalled2() {
41428
41533
  return (0, import_node_child_process4.spawnSync)("pi", ["--version"], { encoding: "utf8" }).status === 0;
41429
41534
  }
41430
- async function listExtensionDirs2(baseDir) {
41535
+ async function listExtensionDirs(baseDir) {
41431
41536
  if (!await import_fs_extra13.default.pathExists(baseDir)) return [];
41432
41537
  const entries = await import_fs_extra13.default.readdir(baseDir, { withFileTypes: true });
41433
41538
  const extDirs = [];
41434
41539
  for (const entry of entries) {
41435
41540
  if (!entry.isDirectory()) continue;
41436
- const extPath = import_path12.default.join(baseDir, entry.name);
41437
- const pkgPath = import_path12.default.join(extPath, "package.json");
41541
+ const extPath = import_path13.default.join(baseDir, entry.name);
41542
+ const pkgPath = import_path13.default.join(extPath, "package.json");
41438
41543
  if (await import_fs_extra13.default.pathExists(pkgPath)) {
41439
41544
  extDirs.push(entry.name);
41440
41545
  }
@@ -41447,8 +41552,8 @@ async function fileSha256(filePath) {
41447
41552
  return crypto2.createHash("sha256").update(content).digest("hex");
41448
41553
  }
41449
41554
  async function extensionHash(extDir) {
41450
- const pkgPath = import_path12.default.join(extDir, "package.json");
41451
- const indexPath = import_path12.default.join(extDir, "index.ts");
41555
+ const pkgPath = import_path13.default.join(extDir, "package.json");
41556
+ const indexPath = import_path13.default.join(extDir, "index.ts");
41452
41557
  const hashes = [];
41453
41558
  if (await import_fs_extra13.default.pathExists(pkgPath)) {
41454
41559
  hashes.push(await fileSha256(pkgPath));
@@ -41459,20 +41564,20 @@ async function extensionHash(extDir) {
41459
41564
  return hashes.join(":");
41460
41565
  }
41461
41566
  async function diffPiExtensions(sourceDir, targetDir) {
41462
- const sourceAbs = import_path12.default.resolve(sourceDir);
41463
- const targetAbs = import_path12.default.resolve(targetDir);
41464
- const sourceExts = await listExtensionDirs2(sourceAbs);
41567
+ const sourceAbs = import_path13.default.resolve(sourceDir);
41568
+ const targetAbs = import_path13.default.resolve(targetDir);
41569
+ const sourceExts = await listExtensionDirs(sourceAbs);
41465
41570
  const missing = [];
41466
41571
  const stale = [];
41467
41572
  const upToDate = [];
41468
41573
  for (const extName of sourceExts) {
41469
- const srcExtPath = import_path12.default.join(sourceAbs, extName);
41470
- const dstExtPath = import_path12.default.join(targetAbs, extName);
41574
+ const srcExtPath = import_path13.default.join(sourceAbs, extName);
41575
+ const dstExtPath = import_path13.default.join(targetAbs, extName);
41471
41576
  if (!await import_fs_extra13.default.pathExists(dstExtPath)) {
41472
41577
  missing.push(extName);
41473
41578
  continue;
41474
41579
  }
41475
- const dstPkgPath = import_path12.default.join(dstExtPath, "package.json");
41580
+ const dstPkgPath = import_path13.default.join(dstExtPath, "package.json");
41476
41581
  if (!await import_fs_extra13.default.pathExists(dstPkgPath)) {
41477
41582
  missing.push(extName);
41478
41583
  continue;
@@ -41512,10 +41617,10 @@ function createInstallPiCommand() {
41512
41617
  cmd.description("Install Pi coding agent with providers, extensions, and npm packages").option("-y, --yes", "Skip confirmation prompts", false).option("--check", "Check Pi extension deployment drift without writing changes", false).action(async (opts) => {
41513
41618
  const { yes, check: check2 } = opts;
41514
41619
  const repoRoot = await findRepoRoot();
41515
- const piConfigDir = import_path12.default.join(repoRoot, "config", "pi");
41620
+ const piConfigDir = import_path13.default.join(repoRoot, "config", "pi");
41516
41621
  if (check2) {
41517
- const sourceDir = import_path12.default.join(piConfigDir, "extensions");
41518
- const targetDir = import_path12.default.join(PI_AGENT_DIR2, "extensions");
41622
+ const sourceDir = import_path13.default.join(piConfigDir, "extensions");
41623
+ const targetDir = import_path13.default.join(PI_AGENT_DIR2, "extensions");
41519
41624
  const diff = await diffPiExtensions(sourceDir, targetDir);
41520
41625
  printPiCheckSummary(diff);
41521
41626
  if (diff.missing.length > 0 || diff.stale.length > 0) {
@@ -41538,7 +41643,7 @@ function createInstallPiCommand() {
41538
41643
  console.log(t.success(` pi ${v.stdout.trim()} already installed
41539
41644
  `));
41540
41645
  }
41541
- const schema = await import_fs_extra13.default.readJson(import_path12.default.join(piConfigDir, "install-schema.json"));
41646
+ const schema = await import_fs_extra13.default.readJson(import_path13.default.join(piConfigDir, "install-schema.json"));
41542
41647
  const existing = readExistingPiValues(PI_AGENT_DIR2);
41543
41648
  const values = { ...existing };
41544
41649
  console.log(t.bold(" API Keys\n"));
@@ -41548,43 +41653,36 @@ function createInstallPiCommand() {
41548
41653
  continue;
41549
41654
  }
41550
41655
  if (!field.required && !yes) {
41551
- const { include } = await (0, import_prompts3.default)({ type: "confirm", name: "include", message: ` Configure ${field.label}? (optional)`, initial: false });
41656
+ const { include } = await (0, import_prompts2.default)({ type: "confirm", name: "include", message: ` Configure ${field.label}? (optional)`, initial: false });
41552
41657
  if (!include) continue;
41553
41658
  }
41554
- const { value } = await (0, import_prompts3.default)({ type: field.secret ? "password" : "text", name: "value", message: ` ${field.label}`, hint: field.hint, validate: (v) => field.required && !v ? "Required" : true });
41659
+ const { value } = await (0, import_prompts2.default)({ type: field.secret ? "password" : "text", name: "value", message: ` ${field.label}`, hint: field.hint, validate: (v) => field.required && !v ? "Required" : true });
41555
41660
  if (value) values[field.key] = value;
41556
41661
  }
41557
41662
  await import_fs_extra13.default.ensureDir(PI_AGENT_DIR2);
41558
41663
  console.log(t.muted(`
41559
41664
  Writing config to ${PI_AGENT_DIR2}`));
41560
41665
  for (const name of ["models.json", "auth.json", "settings.json"]) {
41561
- const destPath = import_path12.default.join(PI_AGENT_DIR2, name);
41666
+ const destPath = import_path13.default.join(PI_AGENT_DIR2, name);
41562
41667
  if (name === "auth.json" && await import_fs_extra13.default.pathExists(destPath) && !yes) {
41563
- const { overwrite } = await (0, import_prompts3.default)({ type: "confirm", name: "overwrite", message: ` ${name} already exists \u2014 overwrite? (OAuth tokens will be lost)`, initial: false });
41668
+ const { overwrite } = await (0, import_prompts2.default)({ type: "confirm", name: "overwrite", message: ` ${name} already exists \u2014 overwrite? (OAuth tokens will be lost)`, initial: false });
41564
41669
  if (!overwrite) {
41565
41670
  console.log(t.muted(` skipped ${name}`));
41566
41671
  continue;
41567
41672
  }
41568
41673
  }
41569
- const raw = await import_fs_extra13.default.readFile(import_path12.default.join(piConfigDir, `${name}.template`), "utf8");
41674
+ const raw = await import_fs_extra13.default.readFile(import_path13.default.join(piConfigDir, `${name}.template`), "utf8");
41570
41675
  await import_fs_extra13.default.writeFile(destPath, fillTemplate(raw, values), "utf8");
41571
41676
  console.log(t.success(` ${sym.ok} ${name}`));
41572
41677
  }
41573
- await import_fs_extra13.default.copy(import_path12.default.join(piConfigDir, "extensions"), import_path12.default.join(PI_AGENT_DIR2, "extensions"), { overwrite: true });
41574
- console.log(t.success(` ${sym.ok} extensions/`));
41575
- const extDirs = await listExtensionDirs2(import_path12.default.join(PI_AGENT_DIR2, "extensions"));
41576
- if (extDirs.length > 0) {
41577
- console.log(kleur_default.dim(`
41578
- Registering ${extDirs.length} extensions...`));
41579
- for (const extName of extDirs) {
41580
- const extPath = import_path12.default.join(PI_AGENT_DIR2, "extensions", extName);
41581
- const r = (0, import_node_child_process4.spawnSync)("pi", ["install", "-l", extPath], { stdio: "pipe", encoding: "utf8" });
41582
- if (r.status === 0) {
41583
- console.log(t.success(` ${sym.ok} ${extName} registered`));
41584
- } else {
41585
- console.log(kleur_default.yellow(` \u26A0 ${extName} \u2014 registration failed`));
41586
- }
41587
- }
41678
+ const managedPackages = await syncManagedPiExtensions({
41679
+ sourceDir: import_path13.default.join(piConfigDir, "extensions"),
41680
+ targetDir: import_path13.default.join(PI_AGENT_DIR2, "extensions"),
41681
+ dryRun: false,
41682
+ log: (message) => console.log(kleur_default.dim(` ${message}`))
41683
+ });
41684
+ if (managedPackages > 0) {
41685
+ console.log(t.success(` ${sym.ok} extensions/ (${managedPackages} packages)`));
41588
41686
  }
41589
41687
  console.log(t.bold("\n npm Packages\n"));
41590
41688
  for (const pkg of schema.packages) {
@@ -41602,7 +41700,7 @@ function createInstallPiCommand() {
41602
41700
  }
41603
41701
 
41604
41702
  // src/commands/pi.ts
41605
- var PI_AGENT_DIR3 = process.env.PI_AGENT_DIR || import_path13.default.join((0, import_node_os6.homedir)(), ".pi", "agent");
41703
+ var PI_AGENT_DIR3 = process.env.PI_AGENT_DIR || import_path14.default.join((0, import_node_os7.homedir)(), ".pi", "agent");
41606
41704
  function createPiCommand() {
41607
41705
  const cmd = new Command("pi").description("Launch a Pi session in a sandboxed worktree, or manage the Pi runtime").argument("[name]", "Optional session name \u2014 used as xt/<name> branch (random if omitted)").action(async (name) => {
41608
41706
  await launchWorktreeSession({ runtime: "pi", name });
@@ -41625,8 +41723,8 @@ function createPiCommand() {
41625
41723
  return;
41626
41724
  }
41627
41725
  const repoRoot = await findRepoRoot();
41628
- const sourceDir = import_path13.default.join(repoRoot, "config", "pi", "extensions");
41629
- const targetDir = import_path13.default.join(PI_AGENT_DIR3, "extensions");
41726
+ const sourceDir = import_path14.default.join(repoRoot, "config", "pi", "extensions");
41727
+ const targetDir = import_path14.default.join(PI_AGENT_DIR3, "extensions");
41630
41728
  const diff = await diffPiExtensions(sourceDir, targetDir);
41631
41729
  if (diff.missing.length === 0 && diff.stale.length === 0) {
41632
41730
  console.log(t.success(` \u2713 extensions up-to-date (${diff.upToDate.length} deployed)`));
@@ -41648,9 +41746,9 @@ function createPiCommand() {
41648
41746
  allOk = false;
41649
41747
  }
41650
41748
  const repoRoot = await findRepoRoot();
41651
- const piConfigDir = import_path13.default.join(repoRoot, "config", "pi");
41652
- const sourceDir = import_path13.default.join(piConfigDir, "extensions");
41653
- const targetDir = import_path13.default.join(PI_AGENT_DIR3, "extensions");
41749
+ const piConfigDir = import_path14.default.join(repoRoot, "config", "pi");
41750
+ const sourceDir = import_path14.default.join(piConfigDir, "extensions");
41751
+ const targetDir = import_path14.default.join(PI_AGENT_DIR3, "extensions");
41654
41752
  const diff = await diffPiExtensions(sourceDir, targetDir);
41655
41753
  if (diff.missing.length === 0 && diff.stale.length === 0) {
41656
41754
  console.log(t.success(` \u2713 extensions deployed (${diff.upToDate.length})`));
@@ -41658,7 +41756,7 @@ function createPiCommand() {
41658
41756
  console.log(kleur_default.yellow(` \u26A0 extension drift (${diff.missing.length} missing, ${diff.stale.length} stale)`));
41659
41757
  allOk = false;
41660
41758
  }
41661
- const schemaPath = import_path13.default.join(piConfigDir, "install-schema.json");
41759
+ const schemaPath = import_path14.default.join(piConfigDir, "install-schema.json");
41662
41760
  if (await import_fs_extra14.default.pathExists(schemaPath)) {
41663
41761
  try {
41664
41762
  (0, import_node_child_process5.execSync)("pi --version", { stdio: "ignore" });
@@ -41690,49 +41788,45 @@ function createPiCommand() {
41690
41788
  }
41691
41789
 
41692
41790
  // src/commands/init.ts
41693
- var import_path15 = __toESM(require("path"), 1);
41791
+ var import_path16 = __toESM(require("path"), 1);
41694
41792
  var import_fs_extra16 = __toESM(require_lib2(), 1);
41695
41793
  var import_child_process4 = require("child_process");
41696
41794
 
41697
41795
  // src/commands/install-service-skills.ts
41698
- var import_path14 = __toESM(require("path"), 1);
41796
+ var import_path15 = __toESM(require("path"), 1);
41699
41797
  var import_fs_extra15 = __toESM(require_lib2(), 1);
41700
41798
  function resolvePkgRoot() {
41701
41799
  const candidates = [
41702
- import_path14.default.resolve(__dirname, "../.."),
41703
- import_path14.default.resolve(__dirname, "../../..")
41800
+ import_path15.default.resolve(__dirname, "../.."),
41801
+ import_path15.default.resolve(__dirname, "../../..")
41704
41802
  ];
41705
- const match = candidates.find((candidate) => import_fs_extra15.default.existsSync(import_path14.default.join(candidate, "project-skills")));
41803
+ const match = candidates.find((candidate) => import_fs_extra15.default.existsSync(import_path15.default.join(candidate, "project-skills")));
41706
41804
  if (!match) {
41707
41805
  throw new Error("Unable to locate project-skills directory from CLI runtime.");
41708
41806
  }
41709
41807
  return match;
41710
41808
  }
41711
41809
  var PKG_ROOT = resolvePkgRoot();
41712
- var SKILLS_SRC = import_path14.default.join(PKG_ROOT, "project-skills", "service-skills-set", ".claude");
41810
+ var SKILLS_SRC = import_path15.default.join(PKG_ROOT, "project-skills", "service-skills-set", ".claude");
41713
41811
 
41714
41812
  // src/commands/init.ts
41715
41813
  function resolvePkgRoot2() {
41716
41814
  const candidates = [
41717
- import_path15.default.resolve(__dirname, "../.."),
41718
- import_path15.default.resolve(__dirname, "../../..")
41815
+ import_path16.default.resolve(__dirname, "../.."),
41816
+ import_path16.default.resolve(__dirname, "../../..")
41719
41817
  ];
41720
- const match = candidates.find((candidate) => import_fs_extra16.default.existsSync(import_path15.default.join(candidate, "project-skills")));
41818
+ const match = candidates.find((candidate) => import_fs_extra16.default.existsSync(import_path16.default.join(candidate, "project-skills")));
41721
41819
  if (!match) {
41722
41820
  throw new Error("Unable to locate project-skills directory from CLI runtime.");
41723
41821
  }
41724
41822
  return match;
41725
41823
  }
41726
41824
  var PKG_ROOT2 = resolvePkgRoot2();
41727
- var PROJECT_SKILLS_DIR = import_path15.default.join(PKG_ROOT2, "project-skills");
41728
- var MCP_CORE_CONFIG_PATH = import_path15.default.join(PKG_ROOT2, "config", "mcp_servers.json");
41729
- var INSTRUCTIONS_DIR = import_path15.default.join(PKG_ROOT2, "config", "instructions");
41825
+ var PROJECT_SKILLS_DIR = import_path16.default.join(PKG_ROOT2, "project-skills");
41826
+ var MCP_CORE_CONFIG_PATH = import_path16.default.join(PKG_ROOT2, "config", "mcp_servers.json");
41827
+ var INSTRUCTIONS_DIR = import_path16.default.join(PKG_ROOT2, "config", "instructions");
41730
41828
  var XTRM_BLOCK_START = "<!-- xtrm:start -->";
41731
41829
  var XTRM_BLOCK_END = "<!-- xtrm:end -->";
41732
- var syncedProjectMcpRoots = /* @__PURE__ */ new Set();
41733
- function toServiceId(name) {
41734
- return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "service";
41735
- }
41736
41830
  function parseComposeServices(content) {
41737
41831
  const lines = content.split("\n");
41738
41832
  const services = /* @__PURE__ */ new Set();
@@ -41756,8 +41850,8 @@ function parseComposeServices(content) {
41756
41850
  return [...services];
41757
41851
  }
41758
41852
  async function detectProjectFeatures(projectRoot) {
41759
- const hasTypeScript = await import_fs_extra16.default.pathExists(import_path15.default.join(projectRoot, "tsconfig.json"));
41760
- const hasPython = await import_fs_extra16.default.pathExists(import_path15.default.join(projectRoot, "pyproject.toml")) || await import_fs_extra16.default.pathExists(import_path15.default.join(projectRoot, "setup.py")) || await import_fs_extra16.default.pathExists(import_path15.default.join(projectRoot, "requirements.txt"));
41853
+ const hasTypeScript = await import_fs_extra16.default.pathExists(import_path16.default.join(projectRoot, "tsconfig.json"));
41854
+ const hasPython = await import_fs_extra16.default.pathExists(import_path16.default.join(projectRoot, "pyproject.toml")) || await import_fs_extra16.default.pathExists(import_path16.default.join(projectRoot, "setup.py")) || await import_fs_extra16.default.pathExists(import_path16.default.join(projectRoot, "requirements.txt"));
41761
41855
  const composeCandidates = [
41762
41856
  "docker-compose.yml",
41763
41857
  "docker-compose.yaml",
@@ -41766,7 +41860,7 @@ async function detectProjectFeatures(projectRoot) {
41766
41860
  ];
41767
41861
  const dockerServices = /* @__PURE__ */ new Set();
41768
41862
  for (const composeFile of composeCandidates) {
41769
- const composePath = import_path15.default.join(projectRoot, composeFile);
41863
+ const composePath = import_path16.default.join(projectRoot, composeFile);
41770
41864
  if (!await import_fs_extra16.default.pathExists(composePath)) continue;
41771
41865
  try {
41772
41866
  const content = await import_fs_extra16.default.readFile(composePath, "utf8");
@@ -41776,9 +41870,9 @@ async function detectProjectFeatures(projectRoot) {
41776
41870
  } catch {
41777
41871
  }
41778
41872
  }
41779
- const hasDockerfile = await import_fs_extra16.default.pathExists(import_path15.default.join(projectRoot, "Dockerfile"));
41873
+ const hasDockerfile = await import_fs_extra16.default.pathExists(import_path16.default.join(projectRoot, "Dockerfile"));
41780
41874
  if (hasDockerfile && dockerServices.size === 0) {
41781
- dockerServices.add(import_path15.default.basename(projectRoot));
41875
+ dockerServices.add(import_path16.default.basename(projectRoot));
41782
41876
  }
41783
41877
  return {
41784
41878
  hasTypeScript,
@@ -41787,116 +41881,6 @@ async function detectProjectFeatures(projectRoot) {
41787
41881
  generatedRegistry: false
41788
41882
  };
41789
41883
  }
41790
- async function ensureServiceRegistry(projectRoot, services) {
41791
- const registryPath = import_path15.default.join(projectRoot, "service-registry.json");
41792
- if (services.length === 0) {
41793
- return { generated: false, registryPath };
41794
- }
41795
- const existedBefore = await import_fs_extra16.default.pathExists(registryPath);
41796
- const now = (/* @__PURE__ */ new Date()).toISOString();
41797
- let registry2 = { version: "1.0.0", services: {} };
41798
- if (existedBefore) {
41799
- try {
41800
- registry2 = await import_fs_extra16.default.readJson(registryPath);
41801
- if (!registry2.services || typeof registry2.services !== "object") {
41802
- registry2.services = {};
41803
- }
41804
- } catch {
41805
- registry2 = { version: "1.0.0", services: {} };
41806
- }
41807
- }
41808
- let changed = false;
41809
- for (const serviceName of services) {
41810
- const serviceId = toServiceId(serviceName);
41811
- if (registry2.services[serviceId]) continue;
41812
- registry2.services[serviceId] = {
41813
- name: serviceName,
41814
- description: `Detected from Docker configuration (${serviceName}).`,
41815
- territory: [],
41816
- skill_path: `.claude/skills/${serviceId}/SKILL.md`,
41817
- last_sync: now
41818
- };
41819
- changed = true;
41820
- }
41821
- if (changed || !existedBefore) {
41822
- await import_fs_extra16.default.writeJson(registryPath, registry2, { spaces: 2 });
41823
- }
41824
- return { generated: changed || !existedBefore, registryPath };
41825
- }
41826
- function resolveEnvVars(value) {
41827
- if (typeof value !== "string") return value;
41828
- return value.replace(/\$\{([A-Z0-9_]+)\}/g, (_m, name) => process.env[name] || "");
41829
- }
41830
- function hasClaudeCli() {
41831
- const r = (0, import_child_process4.spawnSync)("claude", ["--version"], { stdio: "pipe" });
41832
- return r.status === 0;
41833
- }
41834
- function buildProjectMcpArgs(name, server) {
41835
- const transport = server.type || (server.url?.includes("/sse") ? "sse" : "http");
41836
- if (server.command) {
41837
- const args = ["mcp", "add", "-s", "project"];
41838
- if (server.env && typeof server.env === "object") {
41839
- for (const [k, v] of Object.entries(server.env)) {
41840
- args.push("-e", `${k}=${resolveEnvVars(String(v))}`);
41841
- }
41842
- }
41843
- args.push(name, "--", server.command, ...server.args || []);
41844
- return args;
41845
- }
41846
- if (server.url || server.serverUrl) {
41847
- const url2 = server.url || server.serverUrl;
41848
- const args = ["mcp", "add", "-s", "project", "--transport", transport, name, url2];
41849
- if (server.headers && typeof server.headers === "object") {
41850
- for (const [k, v] of Object.entries(server.headers)) {
41851
- args.push("--header", `${k}: ${resolveEnvVars(String(v))}`);
41852
- }
41853
- }
41854
- return args;
41855
- }
41856
- return null;
41857
- }
41858
- async function syncProjectMcpServers(projectRoot) {
41859
- if (syncedProjectMcpRoots.has(projectRoot)) return;
41860
- syncedProjectMcpRoots.add(projectRoot);
41861
- if (!await import_fs_extra16.default.pathExists(MCP_CORE_CONFIG_PATH)) return;
41862
- console.log(kleur_default.bold("\n\u2500\u2500 Installing MCP (project scope) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
41863
- if (!hasClaudeCli()) {
41864
- console.log(kleur_default.yellow(" \u26A0 Claude CLI not found; skipping project-scope MCP registration."));
41865
- return;
41866
- }
41867
- const mcpConfig = await import_fs_extra16.default.readJson(MCP_CORE_CONFIG_PATH);
41868
- const servers = Object.entries(mcpConfig?.mcpServers ?? {});
41869
- if (servers.length === 0) {
41870
- console.log(kleur_default.dim(" \u2139 No core MCP servers configured."));
41871
- return;
41872
- }
41873
- let added = 0;
41874
- let existing = 0;
41875
- let failed = 0;
41876
- for (const [name, server] of servers) {
41877
- const args = buildProjectMcpArgs(name, server);
41878
- if (!args) continue;
41879
- const r = (0, import_child_process4.spawnSync)("claude", args, {
41880
- cwd: projectRoot,
41881
- encoding: "utf8",
41882
- stdio: ["pipe", "pipe", "pipe"]
41883
- });
41884
- if (r.status === 0) {
41885
- added++;
41886
- console.log(`${kleur_default.green(" \u2713")} ${name}`);
41887
- continue;
41888
- }
41889
- const stderr = `${r.stderr || ""}`.toLowerCase();
41890
- if (stderr.includes("already exists") || stderr.includes("already configured")) {
41891
- existing++;
41892
- console.log(kleur_default.dim(` \u2713 ${name} (already configured)`));
41893
- continue;
41894
- }
41895
- failed++;
41896
- console.log(kleur_default.red(` \u2717 ${name} (${(r.stderr || r.stdout || "failed").toString().trim()})`));
41897
- }
41898
- console.log(kleur_default.dim(` \u21B3 MCP project-scope result: ${added} added, ${existing} existing, ${failed} failed`));
41899
- }
41900
41884
  function upsertManagedBlock(fileContent, blockBody, startMarker = XTRM_BLOCK_START, endMarker = XTRM_BLOCK_END) {
41901
41885
  const normalizedBody = blockBody.trim();
41902
41886
  const managedBlock = `${startMarker}
@@ -41922,13 +41906,13 @@ async function injectProjectInstructionHeaders(projectRoot) {
41922
41906
  ];
41923
41907
  console.log(kleur_default.bold("Injecting xtrm agent instruction headers..."));
41924
41908
  for (const target of targets) {
41925
- const templatePath = import_path15.default.join(INSTRUCTIONS_DIR, target.template);
41909
+ const templatePath = import_path16.default.join(INSTRUCTIONS_DIR, target.template);
41926
41910
  if (!await import_fs_extra16.default.pathExists(templatePath)) {
41927
41911
  console.log(kleur_default.yellow(` \u26A0 Missing template: ${target.template}`));
41928
41912
  continue;
41929
41913
  }
41930
41914
  const template = await import_fs_extra16.default.readFile(templatePath, "utf8");
41931
- const outputPath = import_path15.default.join(projectRoot, target.output);
41915
+ const outputPath = import_path16.default.join(projectRoot, target.output);
41932
41916
  const existing = await import_fs_extra16.default.pathExists(outputPath) ? await import_fs_extra16.default.readFile(outputPath, "utf8") : "";
41933
41917
  const next = upsertManagedBlock(existing, template);
41934
41918
  if (next === existing) {
@@ -41948,15 +41932,14 @@ function buildProjectInitGuide() {
41948
41932
  kleur_default.dim(" xtrm init (alias: xtrm project init)"),
41949
41933
  kleur_default.dim(" - Initializes beads workspace (bd init)"),
41950
41934
  kleur_default.dim(" - Refreshes GitNexus index if missing/stale"),
41951
- kleur_default.dim(" - Syncs project-scoped MCP entries"),
41952
- kleur_default.dim(" - Detects TS/Python/Docker project signals"),
41953
- kleur_default.dim(" - Scaffolds service-registry.json when Docker services are detected"),
41935
+ kleur_default.dim(" - Injects XTRM workflow headers into AGENTS.md + CLAUDE.md"),
41936
+ kleur_default.dim(" - Detects TypeScript/Python project signals"),
41954
41937
  "",
41955
41938
  `${kleur_default.cyan("2) What is already global (no per-project install needed):")}`,
41956
- kleur_default.dim(" - quality gates hooks (formerly installed via quality-gates)"),
41957
- kleur_default.dim(" - service-skills routing and drift checks (formerly service-skills-set)"),
41958
- kleur_default.dim(" - main-guard + beads workflow gates"),
41959
- kleur_default.dim(" - optional TDD strategy guidance (legacy name: tdd-guard)"),
41939
+ kleur_default.dim(" - quality gates hooks (ESLint/tsc/ruff/mypy on every edit)"),
41940
+ kleur_default.dim(" - beads workflow gates (edit/commit/stop/memory enforcement)"),
41941
+ kleur_default.dim(" - session-flow gates (claim sync, stop gate, xt end reminder)"),
41942
+ kleur_default.dim(" - service-skills routing and drift checks"),
41960
41943
  "",
41961
41944
  `${kleur_default.cyan("3) Configure repo quality tools (hooks enforce what exists):")}`,
41962
41945
  kleur_default.dim(" - TS: eslint + prettier + tsc"),
@@ -41968,12 +41951,9 @@ function buildProjectInitGuide() {
41968
41951
  kleur_default.dim(" - During work: keep issue status current; create discovered follow-ups"),
41969
41952
  kleur_default.dim(' - Finish work: bd close <id> --reason "Done" --json'),
41970
41953
  "",
41971
- `${kleur_default.cyan("5) Git workflow (main-guard expected path):")}`,
41972
- kleur_default.dim(" - git checkout -b feature/<name>"),
41973
- kleur_default.dim(" - commit on feature branch only"),
41974
- kleur_default.dim(" - git push -u origin feature/<name>"),
41975
- kleur_default.dim(" - gh pr create --fill && gh pr merge --squash"),
41976
- kleur_default.dim(" - git checkout main && git pull --ff-only"),
41954
+ `${kleur_default.cyan("5) Git workflow:")}`,
41955
+ kleur_default.dim(' - bd close <id> --reason "..." \u2190 closes issue + auto-commits'),
41956
+ kleur_default.dim(" - xt end \u2190 push, PR, merge, worktree cleanup"),
41977
41957
  ""
41978
41958
  ];
41979
41959
  return lines.join("\n");
@@ -41996,28 +41976,12 @@ async function bootstrapProjectInit() {
41996
41976
  await runBdInitForProject(projectRoot);
41997
41977
  await injectProjectInstructionHeaders(projectRoot);
41998
41978
  await runGitNexusInitForProject(projectRoot);
41999
- await syncProjectMcpServers(projectRoot);
42000
- if (detected.dockerServices.length > 0) {
42001
- const { generated, registryPath } = await ensureServiceRegistry(projectRoot, detected.dockerServices);
42002
- detected.generatedRegistry = generated;
42003
- detected.registryPath = registryPath;
42004
- if (generated) {
42005
- console.log(`${kleur_default.green(" \u2713")} service registry scaffolded at ${import_path15.default.relative(projectRoot, registryPath)}`);
42006
- } else {
42007
- console.log(kleur_default.dim(" \u2713 service-registry.json already includes detected services"));
42008
- }
42009
- }
42010
41979
  const projectTypes = [];
42011
41980
  if (detected.hasTypeScript) projectTypes.push("TypeScript");
42012
41981
  if (detected.hasPython) projectTypes.push("Python");
42013
- if (detected.dockerServices.length > 0) projectTypes.push("Docker");
42014
41982
  console.log(kleur_default.bold("\nProject initialized."));
42015
41983
  console.log(kleur_default.white(` Quality gates active globally.`));
42016
41984
  console.log(kleur_default.white(` Project types: ${projectTypes.length > 0 ? projectTypes.join(", ") : "none detected"}.`));
42017
- console.log(kleur_default.white(` Services detected: ${detected.dockerServices.length > 0 ? detected.dockerServices.join(", ") : "none"}.`));
42018
- if (detected.registryPath) {
42019
- console.log(kleur_default.dim(` Service registry: ${detected.registryPath}`));
42020
- }
42021
41985
  console.log("");
42022
41986
  }
42023
41987
  async function runBdInitForProject(projectRoot) {
@@ -42092,14 +42056,14 @@ function getProjectRoot() {
42092
42056
  if (result.status !== 0) {
42093
42057
  throw new Error("Not inside a git repository. Run this command from your target project directory.");
42094
42058
  }
42095
- return import_path15.default.resolve(result.stdout.trim());
42059
+ return import_path16.default.resolve(result.stdout.trim());
42096
42060
  }
42097
42061
 
42098
42062
  // src/commands/status.ts
42099
- var import_prompts4 = __toESM(require_prompts3(), 1);
42063
+ var import_prompts3 = __toESM(require_prompts3(), 1);
42100
42064
 
42101
42065
  // src/core/manifest.ts
42102
- var import_path16 = require("path");
42066
+ var import_path17 = require("path");
42103
42067
 
42104
42068
  // ../node_modules/zod/v4/classic/external.js
42105
42069
  var external_exports = {};
@@ -42948,8 +42912,8 @@ function numKeys(data) {
42948
42912
  return keyCount;
42949
42913
  }
42950
42914
  var getParsedType = (data) => {
42951
- const t2 = typeof data;
42952
- switch (t2) {
42915
+ const t3 = typeof data;
42916
+ switch (t3) {
42953
42917
  case "undefined":
42954
42918
  return "undefined";
42955
42919
  case "string":
@@ -42988,7 +42952,7 @@ var getParsedType = (data) => {
42988
42952
  }
42989
42953
  return "object";
42990
42954
  default:
42991
- throw new Error(`Unknown data type: ${t2}`);
42955
+ throw new Error(`Unknown data type: ${t3}`);
42992
42956
  }
42993
42957
  };
42994
42958
  var propertyKeyTypes = /* @__PURE__ */ new Set(["string", "number", "symbol"]);
@@ -43295,8 +43259,8 @@ function getLengthableOrigin(input) {
43295
43259
  return "unknown";
43296
43260
  }
43297
43261
  function parsedType(data) {
43298
- const t2 = typeof data;
43299
- switch (t2) {
43262
+ const t3 = typeof data;
43263
+ switch (t3) {
43300
43264
  case "number": {
43301
43265
  return Number.isNaN(data) ? "nan" : "number";
43302
43266
  }
@@ -43313,7 +43277,7 @@ function parsedType(data) {
43313
43277
  }
43314
43278
  }
43315
43279
  }
43316
- return t2;
43280
+ return t3;
43317
43281
  }
43318
43282
  function issue(...args) {
43319
43283
  const [iss, input, inst] = args;
@@ -45023,12 +44987,12 @@ function handleCatchall(proms, input, payload, ctx, def, inst) {
45023
44987
  const unrecognized = [];
45024
44988
  const keySet = def.keySet;
45025
44989
  const _catchall = def.catchall._zod;
45026
- const t2 = _catchall.def.type;
44990
+ const t3 = _catchall.def.type;
45027
44991
  const isOptionalOut = _catchall.optout === "optional";
45028
44992
  for (const key in input) {
45029
44993
  if (keySet.has(key))
45030
44994
  continue;
45031
- if (t2 === "never") {
44995
+ if (t3 === "never") {
45032
44996
  unrecognized.push(key);
45033
44997
  continue;
45034
44998
  }
@@ -48135,16 +48099,16 @@ var error17 = () => {
48135
48099
  number: { unit: "", shortLabel: "\u05E7\u05D8\u05DF", longLabel: "\u05D2\u05D3\u05D5\u05DC" }
48136
48100
  // no unit
48137
48101
  };
48138
- const typeEntry = (t2) => t2 ? TypeNames[t2] : void 0;
48139
- const typeLabel = (t2) => {
48140
- const e = typeEntry(t2);
48102
+ const typeEntry = (t3) => t3 ? TypeNames[t3] : void 0;
48103
+ const typeLabel = (t3) => {
48104
+ const e = typeEntry(t3);
48141
48105
  if (e)
48142
48106
  return e.label;
48143
- return t2 ?? TypeNames.unknown.label;
48107
+ return t3 ?? TypeNames.unknown.label;
48144
48108
  };
48145
- const withDefinite = (t2) => `\u05D4${typeLabel(t2)}`;
48146
- const verbFor = (t2) => {
48147
- const e = typeEntry(t2);
48109
+ const withDefinite = (t3) => `\u05D4${typeLabel(t3)}`;
48110
+ const verbFor = (t3) => {
48111
+ const e = typeEntry(t3);
48148
48112
  const gender = e?.gender ?? "m";
48149
48113
  return gender === "f" ? "\u05E6\u05E8\u05D9\u05DB\u05D4 \u05DC\u05D4\u05D9\u05D5\u05EA" : "\u05E6\u05E8\u05D9\u05DA \u05DC\u05D4\u05D9\u05D5\u05EA";
48150
48114
  };
@@ -55539,8 +55503,8 @@ function convertBaseSchema(schema, ctx) {
55539
55503
  }
55540
55504
  const type = schema.type;
55541
55505
  if (Array.isArray(type)) {
55542
- const typeSchemas = type.map((t2) => {
55543
- const typeSchema = { ...schema, type: t2 };
55506
+ const typeSchemas = type.map((t3) => {
55507
+ const typeSchema = { ...schema, type: t3 };
55544
55508
  return convertBaseSchema(typeSchema, ctx);
55545
55509
  });
55546
55510
  if (typeSchemas.length === 0) {
@@ -55886,9 +55850,7 @@ var ChangeSetSchema = external_exports.object({
55886
55850
  skills: ChangeSetCategorySchema,
55887
55851
  hooks: ChangeSetCategorySchema,
55888
55852
  config: ChangeSetCategorySchema,
55889
- commands: ChangeSetCategorySchema,
55890
- "qwen-commands": ChangeSetCategorySchema,
55891
- "antigravity-workflows": ChangeSetCategorySchema
55853
+ commands: ChangeSetCategorySchema
55892
55854
  });
55893
55855
  var SyncPlanSchema = external_exports.object({
55894
55856
  mode: SyncModeSchema,
@@ -55910,17 +55872,17 @@ var ManifestSchema = external_exports.object({
55910
55872
  // src/core/manifest.ts
55911
55873
  var MANIFEST_FILE = ".jaggers-sync-manifest.json";
55912
55874
  function getManifestPath(projectDir) {
55913
- return (0, import_path16.join)(projectDir, MANIFEST_FILE);
55875
+ return (0, import_path17.join)(projectDir, MANIFEST_FILE);
55914
55876
  }
55915
55877
 
55916
55878
  // src/commands/status.ts
55917
55879
  var import_fs_extra17 = __toESM(require_lib2(), 1);
55918
- var import_path17 = __toESM(require("path"), 1);
55880
+ var import_path18 = __toESM(require("path"), 1);
55919
55881
  function formatTargetLabel2(target) {
55920
55882
  const normalized = target.replace(/\\/g, "/").toLowerCase();
55921
55883
  if (normalized.endsWith("/.agents/skills") || normalized.includes("/.agents/skills/")) return "~/.agents/skills";
55922
55884
  if (normalized.endsWith("/.claude") || normalized.includes("/.claude/")) return "~/.claude";
55923
- return import_path17.default.basename(target);
55885
+ return import_path18.default.basename(target);
55924
55886
  }
55925
55887
  function formatRelativeTime(timestamp) {
55926
55888
  const now = Date.now();
@@ -56002,7 +55964,7 @@ function createStatusCommand() {
56002
55964
  console.log(kleur_default.yellow(`
56003
55965
  \u26A0 ${totalPending} pending change${totalPending !== 1 ? "s" : ""} across ${pending.length} environment${pending.length !== 1 ? "s" : ""}
56004
55966
  `));
56005
- const { selected } = await (0, import_prompts4.default)({
55967
+ const { selected } = await (0, import_prompts3.default)({
56006
55968
  type: "multiselect",
56007
55969
  name: "selected",
56008
55970
  message: "Select environments to sync:",
@@ -56044,176 +56006,100 @@ function createResetCommand() {
56044
56006
  }
56045
56007
 
56046
56008
  // src/commands/help.ts
56047
- var import_path18 = __toESM(require("path"), 1);
56048
- var import_fs_extra18 = __toESM(require_lib2(), 1);
56049
- var HOOK_CATALOG = [
56050
- { file: "main-guard.mjs", event: "PreToolUse", desc: "Blocks direct edits / unsafe Bash on protected branches" },
56051
- { file: "main-guard-post-push.mjs", event: "PostToolUse", desc: "After feature-branch push, reminds PR/merge/sync steps" },
56052
- { file: "serena-workflow-reminder.py", event: "SessionStart", desc: "Injects Serena semantic editing workflow reminder" },
56053
- { file: "gitnexus/gitnexus-hook.cjs", event: "PostToolUse", desc: "Adds GitNexus context for search and Serena tooling" },
56054
- { file: "agent_context.py", event: "Support module", desc: "Shared hook I/O helper used by Python hook scripts" },
56055
- { file: "beads-edit-gate.mjs", event: "PreToolUse", desc: "Blocks file edits if no beads issue is claimed", beads: true },
56056
- { file: "beads-commit-gate.mjs", event: "PreToolUse", desc: "Blocks commits when no beads issue is in progress", beads: true },
56057
- { file: "beads-memory-gate.mjs", event: "Stop", desc: "Prompts memory save when claim was closed", beads: true },
56058
- { file: "beads-compact-save.mjs", event: "PreCompact", desc: "Saves in_progress issue + session-state bundle", beads: true },
56059
- { file: "beads-compact-restore.mjs", event: "SessionStart", desc: "Restores compacted issue + session-state bundle", beads: true },
56060
- { file: "beads-claim-sync.mjs", event: "PostToolUse", desc: "Auto-claim sync + worktree/session-state bootstrap", sessionFlow: true },
56061
- { file: "beads-stop-gate.mjs", event: "Stop", desc: "Blocks stop for waiting-merge/conflicting/pending-cleanup", sessionFlow: true },
56062
- { file: "branch-state.mjs", event: "UserPromptSubmit", desc: "Injects current git branch into prompt context" },
56063
- { file: "quality-check.cjs", event: "PostToolUse", desc: "Runs JS/TS quality checks on mutating edits" },
56064
- { file: "quality-check.py", event: "PostToolUse", desc: "Runs Python quality checks on mutating edits" }
56065
- ];
56066
- async function readSkillsFromDir(dir) {
56067
- if (!await import_fs_extra18.default.pathExists(dir)) return [];
56068
- const entries = await import_fs_extra18.default.readdir(dir);
56069
- const skills = [];
56070
- for (const name of entries.sort()) {
56071
- const skillMd = import_path18.default.join(dir, name, "SKILL.md");
56072
- if (!await import_fs_extra18.default.pathExists(skillMd)) continue;
56073
- const content = await import_fs_extra18.default.readFile(skillMd, "utf8");
56074
- const m = content.match(/^description:\s*(.+)$/m);
56075
- skills.push({ name, desc: m ? m[1].replace(/^["']|["']$/g, "").trim() : "" });
56076
- }
56077
- return skills;
56078
- }
56079
- async function readProjectSkillsFromDir(dir) {
56080
- if (!await import_fs_extra18.default.pathExists(dir)) return [];
56081
- const entries = await import_fs_extra18.default.readdir(dir);
56082
- const skills = [];
56083
- for (const name of entries.sort()) {
56084
- const readme = import_path18.default.join(dir, name, "README.md");
56085
- if (!await import_fs_extra18.default.pathExists(readme)) continue;
56086
- const content = await import_fs_extra18.default.readFile(readme, "utf8");
56087
- const descLine = content.split("\n").find((line) => {
56088
- const trimmed = line.trim();
56089
- return Boolean(trimmed) && !trimmed.startsWith("#") && !trimmed.startsWith("[") && !trimmed.startsWith("<");
56090
- }) || "";
56091
- skills.push({ name, desc: descLine.replace(/[*_`]/g, "").trim() });
56092
- }
56093
- return skills;
56094
- }
56095
- function resolvePkgRootFallback() {
56096
- const candidates = [
56097
- import_path18.default.resolve(__dirname, "../.."),
56098
- import_path18.default.resolve(__dirname, "../../..")
56099
- ];
56100
- const match = candidates.find(
56101
- (candidate) => import_fs_extra18.default.existsSync(import_path18.default.join(candidate, "skills")) || import_fs_extra18.default.existsSync(import_path18.default.join(candidate, "project-skills"))
56102
- );
56103
- return match || null;
56104
- }
56105
- function col(s, width) {
56106
- return s.length >= width ? s.slice(0, width - 1) + "\u2026" : s.padEnd(width);
56009
+ function section(title, lines) {
56010
+ return [title, ...lines, ""].join("\n");
56107
56011
  }
56108
56012
  function createHelpCommand() {
56109
- return new Command("help").description("Show help information and component catalogue").action(async () => {
56110
- let repoRoot;
56111
- try {
56112
- repoRoot = await findRepoRoot();
56113
- } catch {
56114
- repoRoot = "";
56115
- }
56116
- const pkgRoot = resolvePkgRootFallback();
56117
- const skillsRoot = repoRoot || pkgRoot || "";
56118
- const projectSkillsRoot = repoRoot || pkgRoot || "";
56119
- const skills = skillsRoot ? await readSkillsFromDir(import_path18.default.join(skillsRoot, "skills")) : [];
56120
- const projectSkills = projectSkillsRoot ? await readProjectSkillsFromDir(import_path18.default.join(projectSkillsRoot, "project-skills")) : [];
56121
- const W = 80;
56122
- const hr = kleur_default.dim("-".repeat(W));
56123
- const section = (title) => `
56124
- ${kleur_default.bold().cyan(title)}
56125
- ${hr}`;
56126
- const installSection = [
56127
- section("INSTALL COMMANDS"),
56128
- "",
56129
- ` ${kleur_default.bold("xtrm install all")}`,
56130
- ` ${kleur_default.dim("Global install: skills + all hooks (including beads gates) + MCP servers.")}`,
56131
- ` ${kleur_default.dim("Checks for beads+dolt and prompts to install if missing.")}`,
56013
+ return new Command("help").description("Show rich CLI help in a plain text format").action(async () => {
56014
+ const blocks = [];
56015
+ blocks.push(section("XTRM CLI", [
56016
+ " xtrm and xt are equivalent commands.",
56017
+ " Use xt for short workflow commands (xt claude, xt pi, xt end)."
56018
+ ]));
56019
+ blocks.push(section("USAGE", [
56020
+ " xtrm <command> [subcommand] [options]",
56021
+ " xt <command> [subcommand] [options]"
56022
+ ]));
56023
+ blocks.push(section("CORE WORKFLOW", [
56024
+ " 1) Start a runtime session in a worktree:",
56025
+ " xt claude [name] or xt pi [name]",
56026
+ " 2) Do your work in that worktree/branch.",
56027
+ " 3) Finish with:",
56028
+ " xt end",
56029
+ " 4) Manage old worktrees when needed:",
56030
+ " xt worktree list | xt worktree clean"
56031
+ ]));
56032
+ blocks.push(section("PRIMARY COMMANDS", [
56033
+ " xtrm install [target-selector] [options]",
56034
+ " Install/sync tools, hooks, skills, and MCP wiring.",
56035
+ " Options: --dry-run, --yes/-y, --prune, --backport",
56132
56036
  "",
56133
- ` ${kleur_default.bold("xtrm install basic")}`,
56134
- ` ${kleur_default.dim("Global install: skills + general hooks + MCP servers.")}`,
56135
- ` ${kleur_default.dim("No beads dependency -- safe to run with zero external deps.")}`,
56037
+ " xtrm status [--json]",
56038
+ " Show pending changes for detected environments.",
56136
56039
  "",
56137
- ` ${kleur_default.bold("xtrm install project")} ${kleur_default.dim("<tool-name | all>")}`,
56138
- ` ${kleur_default.dim("Project-scoped install into .claude/ of current git root.")}`,
56139
- ` ${kleur_default.dim("Run xtrm install project list to see available project skills.")}`,
56040
+ " xtrm clean [options]",
56041
+ " Remove orphaned hooks/skills and stale hook wiring entries.",
56042
+ " Options: --dry-run, --hooks-only, --skills-only, --yes/-y",
56140
56043
  "",
56141
- ` ${kleur_default.dim("Default target directories:")}`,
56142
- ` ${kleur_default.dim("~/.claude/hooks (global hook scripts)")}`,
56143
- ` ${kleur_default.dim("~/.claude/skills (global Claude skills)")}`,
56144
- ` ${kleur_default.dim("~/.agents/skills (agents skills cache mirror)")}`,
56044
+ " xtrm init",
56045
+ " Initialize project-level workflow setup.",
56145
56046
  "",
56146
- ` ${kleur_default.dim("Flags (all profiles): --dry-run --yes / -y --no-mcp --force --prune --backport")}`
56147
- ].join("\n");
56148
- const general = HOOK_CATALOG.filter((h) => !h.beads && !h.sessionFlow);
56149
- const beads = HOOK_CATALOG.filter((h) => h.beads);
56150
- const sessionFlow = HOOK_CATALOG.filter((h) => h.sessionFlow);
56151
- const hookRows = (hooks) => hooks.map(
56152
- (h) => ` ${kleur_default.white(col(h.file, 34))}${kleur_default.yellow(col(h.event, 20))}${kleur_default.dim(h.desc)}`
56153
- ).join("\n");
56154
- const hooksSection = [
56155
- section("GLOBAL HOOKS"),
56047
+ " xtrm docs show [filter] [--raw] [--json]",
56048
+ " Show frontmatter for README/CHANGELOG/docs/*.md.",
56156
56049
  "",
56157
- kleur_default.dim(" " + col("File", 34) + col("Event", 20) + "Description"),
56050
+ " xtrm debug [options]",
56051
+ " Stream xtrm event log (tool calls, gates, session/bd lifecycle).",
56052
+ " Options: --follow, --all, --session <id>, --type <domain>, --json",
56158
56053
  "",
56159
- hookRows(general),
56054
+ " xtrm reset",
56055
+ " Clear saved CLI preferences.",
56160
56056
  "",
56161
- ` ${kleur_default.dim("beads gate hooks (xtrm install all -- require beads+dolt):")}`,
56162
- hookRows(beads),
56057
+ " xtrm help",
56058
+ " Show this help page."
56059
+ ]));
56060
+ blocks.push(section("RUNTIME COMMANDS", [
56061
+ " xt claude [name]",
56062
+ " Launch Claude in a sandboxed xt/<name> worktree.",
56063
+ " xt claude install [--dry-run]",
56064
+ " Install/refresh xtrm Claude plugin + official plugins.",
56065
+ " xt claude status | xt claude doctor | xt claude reload",
56163
56066
  "",
56164
- ` ${kleur_default.dim("session-flow hooks (xtrm finish lifecycle):")}`,
56165
- hookRows(sessionFlow)
56166
- ].join("\n");
56167
- const skillRows = skills.map((s) => {
56168
- const desc = s.desc.length > 46 ? s.desc.slice(0, 45) + "\u2026" : s.desc;
56169
- return ` ${kleur_default.white(col(s.name, 30))}${kleur_default.dim(desc)}`;
56170
- }).join("\n");
56171
- const skillsSection = [
56172
- section(`SKILLS ${kleur_default.dim("(" + skills.length + " available)")}`),
56173
- "",
56174
- skills.length ? skillRows : kleur_default.dim(" (none found -- run from repo root to see skills)")
56175
- ].join("\n");
56176
- const psRows = projectSkills.map(
56177
- (s) => ` ${kleur_default.white(col(s.name, 30))}${kleur_default.dim(s.desc)}`
56178
- ).join("\n");
56179
- const psSection = [
56180
- section("PROJECT SKILLS + HOOKS"),
56181
- "",
56182
- projectSkills.length ? psRows : kleur_default.dim(" (none found in package)"),
56183
- "",
56184
- ` ${kleur_default.dim("Install: xtrm install project <name> | xtrm install project list")}`,
56185
- ` ${kleur_default.dim("Each project skill can install .claude/skills plus project hooks/settings.")}`
56186
- ].join("\n");
56187
- const otherSection = [
56188
- section("OTHER COMMANDS"),
56189
- "",
56190
- ` ${kleur_default.bold("xtrm status")} ${kleur_default.dim("Show pending changes without applying them")}`,
56191
- ` ${kleur_default.bold("xtrm finish")} ${kleur_default.dim("Run blocking session closure lifecycle (PR + cleanup)")}`,
56192
- ` ${kleur_default.bold("xtrm reset")} ${kleur_default.dim("Clear saved preferences and start fresh")}`,
56193
- ` ${kleur_default.bold("xtrm help")} ${kleur_default.dim("Show this overview")}`
56194
- ].join("\n");
56195
- const resourcesSection = [
56196
- section("RESOURCES"),
56197
- "",
56198
- ` Repository https://github.com/Jaggerxtrm/xtrm-tools`,
56199
- ` Issues https://github.com/Jaggerxtrm/xtrm-tools/issues`,
56200
- "",
56201
- ` ${kleur_default.dim("Run 'xtrm <command> --help' for command-specific options.")}`,
56202
- ""
56203
- ].join("\n");
56204
- console.log([installSection, hooksSection, skillsSection, psSection, otherSection, resourcesSection].join("\n"));
56067
+ " xt pi [name]",
56068
+ " Launch Pi in a sandboxed xt/<name> worktree.",
56069
+ " xt pi install [--dry-run]",
56070
+ " Non-interactive extension sync + package install.",
56071
+ " xt pi setup",
56072
+ " Interactive first-time setup.",
56073
+ " xt pi status | xt pi doctor | xt pi reload"
56074
+ ]));
56075
+ blocks.push(section("WORKTREE COMMANDS", [
56076
+ " xt worktree list",
56077
+ " List active xt/* worktrees and merge status.",
56078
+ " xt worktree clean [--yes/-y]",
56079
+ " Remove worktrees already merged into main.",
56080
+ " xt worktree remove <name> [--yes/-y]",
56081
+ " Remove a specific xt worktree by name or path."
56082
+ ]));
56083
+ blocks.push(section("SESSION CLOSE", [
56084
+ " xt end [options]",
56085
+ " Rebase to origin/main, push, open PR, link issues, and optionally clean worktree.",
56086
+ " Options: --draft, --keep, --yes/-y"
56087
+ ]));
56088
+ blocks.push(section("NOTES", [
56089
+ " - Banner is shown only for xtrm install.",
56090
+ " - For command-level details, run: xtrm <command> --help",
56091
+ " - For subcommand details, run: xtrm <command> <subcommand> --help"
56092
+ ]));
56093
+ process.stdout.write(blocks.join("\n"));
56205
56094
  });
56206
56095
  }
56207
56096
 
56208
56097
  // src/commands/clean.ts
56209
- var import_fs_extra19 = __toESM(require_lib2(), 1);
56098
+ var import_fs_extra18 = __toESM(require_lib2(), 1);
56210
56099
  var import_path19 = __toESM(require("path"), 1);
56211
- var import_os5 = require("os");
56100
+ var import_os6 = require("os");
56212
56101
  var CANONICAL_HOOKS = /* @__PURE__ */ new Set([
56213
- "agent_context.py",
56214
- "serena-workflow-reminder.py",
56215
- "main-guard.mjs",
56216
- "main-guard-post-push.mjs",
56102
+ "using-xtrm-reminder.mjs",
56217
56103
  "beads-gate-core.mjs",
56218
56104
  "beads-gate-utils.mjs",
56219
56105
  "beads-gate-messages.mjs",
@@ -56224,12 +56110,16 @@ var CANONICAL_HOOKS = /* @__PURE__ */ new Set([
56224
56110
  "beads-claim-sync.mjs",
56225
56111
  "beads-compact-save.mjs",
56226
56112
  "beads-compact-restore.mjs",
56227
- "branch-state.mjs",
56113
+ "worktree-boundary.mjs",
56114
+ "statusline.mjs",
56228
56115
  "quality-check.cjs",
56116
+ "quality-check-env.mjs",
56229
56117
  "quality-check.py",
56118
+ "xtrm-logger.mjs",
56119
+ "xtrm-tool-logger.mjs",
56120
+ "xtrm-session-logger.mjs",
56230
56121
  "gitnexus",
56231
56122
  // directory
56232
- "statusline-starship.sh",
56233
56123
  "README.md"
56234
56124
  ]);
56235
56125
  var CANONICAL_SKILLS = /* @__PURE__ */ new Set([
@@ -56269,18 +56159,18 @@ var IGNORED_ITEMS2 = /* @__PURE__ */ new Set([
56269
56159
  "node_modules"
56270
56160
  ]);
56271
56161
  async function cleanHooks(dryRun) {
56272
- const hooksDir = import_path19.default.join((0, import_os5.homedir)(), ".claude", "hooks");
56162
+ const hooksDir = import_path19.default.join((0, import_os6.homedir)(), ".claude", "hooks");
56273
56163
  const removed = [];
56274
56164
  const cache = [];
56275
- if (!await import_fs_extra19.default.pathExists(hooksDir)) {
56165
+ if (!await import_fs_extra18.default.pathExists(hooksDir)) {
56276
56166
  return { removed, cache };
56277
56167
  }
56278
- const entries = await import_fs_extra19.default.readdir(hooksDir);
56168
+ const entries = await import_fs_extra18.default.readdir(hooksDir);
56279
56169
  for (const entry of entries) {
56280
56170
  if (IGNORED_ITEMS2.has(entry)) {
56281
56171
  if (!dryRun) {
56282
56172
  const fullPath2 = import_path19.default.join(hooksDir, entry);
56283
- await import_fs_extra19.default.remove(fullPath2);
56173
+ await import_fs_extra18.default.remove(fullPath2);
56284
56174
  }
56285
56175
  cache.push(entry);
56286
56176
  continue;
@@ -56289,10 +56179,10 @@ async function cleanHooks(dryRun) {
56289
56179
  continue;
56290
56180
  }
56291
56181
  const fullPath = import_path19.default.join(hooksDir, entry);
56292
- const stat = await import_fs_extra19.default.stat(fullPath);
56182
+ const stat = await import_fs_extra18.default.stat(fullPath);
56293
56183
  if (stat.isFile() || stat.isDirectory() && IGNORED_ITEMS2.has(entry)) {
56294
56184
  if (!dryRun) {
56295
- await import_fs_extra19.default.remove(fullPath);
56185
+ await import_fs_extra18.default.remove(fullPath);
56296
56186
  }
56297
56187
  removed.push(entry);
56298
56188
  }
@@ -56300,12 +56190,12 @@ async function cleanHooks(dryRun) {
56300
56190
  return { removed, cache };
56301
56191
  }
56302
56192
  async function cleanSkills(dryRun) {
56303
- const skillsDir = import_path19.default.join((0, import_os5.homedir)(), ".agents", "skills");
56193
+ const skillsDir = import_path19.default.join((0, import_os6.homedir)(), ".agents", "skills");
56304
56194
  const removed = [];
56305
- if (!await import_fs_extra19.default.pathExists(skillsDir)) {
56195
+ if (!await import_fs_extra18.default.pathExists(skillsDir)) {
56306
56196
  return removed;
56307
56197
  }
56308
- const entries = await import_fs_extra19.default.readdir(skillsDir);
56198
+ const entries = await import_fs_extra18.default.readdir(skillsDir);
56309
56199
  for (const entry of entries) {
56310
56200
  if (IGNORED_ITEMS2.has(entry)) {
56311
56201
  continue;
@@ -56317,10 +56207,10 @@ async function cleanSkills(dryRun) {
56317
56207
  continue;
56318
56208
  }
56319
56209
  const fullPath = import_path19.default.join(skillsDir, entry);
56320
- const stat = await import_fs_extra19.default.stat(fullPath);
56210
+ const stat = await import_fs_extra18.default.stat(fullPath);
56321
56211
  if (stat.isDirectory()) {
56322
56212
  if (!dryRun) {
56323
- await import_fs_extra19.default.remove(fullPath);
56213
+ await import_fs_extra18.default.remove(fullPath);
56324
56214
  }
56325
56215
  removed.push(entry);
56326
56216
  }
@@ -56328,14 +56218,14 @@ async function cleanSkills(dryRun) {
56328
56218
  return removed;
56329
56219
  }
56330
56220
  async function cleanOrphanedHookEntries(dryRun, repoRoot) {
56331
- const settingsPath = import_path19.default.join((0, import_os5.homedir)(), ".claude", "settings.json");
56221
+ const settingsPath = import_path19.default.join((0, import_os6.homedir)(), ".claude", "settings.json");
56332
56222
  const removed = [];
56333
- if (!await import_fs_extra19.default.pathExists(settingsPath)) {
56223
+ if (!await import_fs_extra18.default.pathExists(settingsPath)) {
56334
56224
  return removed;
56335
56225
  }
56336
56226
  let settings = {};
56337
56227
  try {
56338
- settings = await import_fs_extra19.default.readJson(settingsPath);
56228
+ settings = await import_fs_extra18.default.readJson(settingsPath);
56339
56229
  } catch {
56340
56230
  return removed;
56341
56231
  }
@@ -56353,8 +56243,8 @@ async function cleanOrphanedHookEntries(dryRun, repoRoot) {
56353
56243
  if (repoRoot) {
56354
56244
  const hooksJsonPath = import_path19.default.join(repoRoot, "config", "hooks.json");
56355
56245
  try {
56356
- if (await import_fs_extra19.default.pathExists(hooksJsonPath)) {
56357
- const hooksJson = await import_fs_extra19.default.readJson(hooksJsonPath);
56246
+ if (await import_fs_extra18.default.pathExists(hooksJsonPath)) {
56247
+ const hooksJson = await import_fs_extra18.default.readJson(hooksJsonPath);
56358
56248
  for (const [event, entries] of Object.entries(hooksJson.hooks ?? {})) {
56359
56249
  for (const entry of entries) {
56360
56250
  const script = entry.script;
@@ -56416,7 +56306,7 @@ async function cleanOrphanedHookEntries(dryRun, repoRoot) {
56416
56306
  }
56417
56307
  }
56418
56308
  if (modified && !dryRun) {
56419
- await import_fs_extra19.default.writeJson(settingsPath, settings, { spaces: 2 });
56309
+ await import_fs_extra18.default.writeJson(settingsPath, settings, { spaces: 2 });
56420
56310
  }
56421
56311
  return removed;
56422
56312
  }
@@ -56497,327 +56387,15 @@ function createCleanCommand() {
56497
56387
  });
56498
56388
  }
56499
56389
 
56500
- // src/core/xtrm-finish.ts
56501
- var import_node_child_process7 = require("child_process");
56502
- var import_node_fs5 = require("fs");
56503
-
56504
- // src/core/session-state.ts
56505
- var import_node_child_process6 = require("child_process");
56506
- var import_node_fs4 = require("fs");
56507
- var import_node_path6 = __toESM(require("path"), 1);
56508
- var SESSION_STATE_FILE = ".xtrm-session-state.json";
56509
- var SESSION_PHASES = [
56510
- "claimed",
56511
- "phase1-done",
56512
- "waiting-merge",
56513
- "conflicting",
56514
- "pending-cleanup",
56515
- "merged",
56516
- "cleanup-done"
56517
- ];
56518
- var ALLOWED_TRANSITIONS = {
56519
- claimed: ["phase1-done", "waiting-merge", "conflicting", "pending-cleanup", "cleanup-done"],
56520
- "phase1-done": ["waiting-merge", "conflicting", "pending-cleanup", "cleanup-done"],
56521
- "waiting-merge": ["conflicting", "pending-cleanup", "merged", "cleanup-done"],
56522
- conflicting: ["waiting-merge", "pending-cleanup", "merged", "cleanup-done"],
56523
- "pending-cleanup": ["waiting-merge", "conflicting", "merged", "cleanup-done"],
56524
- merged: ["cleanup-done"],
56525
- "cleanup-done": []
56526
- };
56527
- var nowIso = () => (/* @__PURE__ */ new Date()).toISOString();
56528
- function isPhase(value) {
56529
- return typeof value === "string" && SESSION_PHASES.includes(value);
56530
- }
56531
- function normalizeState(value) {
56532
- if (!value || typeof value !== "object") {
56533
- throw new Error("Invalid session state payload");
56534
- }
56535
- const state = value;
56536
- if (!state.issueId || !state.branch || !state.worktreePath || !state.phase) {
56537
- throw new Error("Session state requires issueId, branch, worktreePath, and phase");
56538
- }
56539
- if (!isPhase(state.phase)) throw new Error(`Invalid session phase: ${String(state.phase)}`);
56540
- return {
56541
- issueId: String(state.issueId),
56542
- branch: String(state.branch),
56543
- worktreePath: String(state.worktreePath),
56544
- prNumber: state.prNumber ?? null,
56545
- prUrl: state.prUrl ?? null,
56546
- phase: state.phase,
56547
- conflictFiles: Array.isArray(state.conflictFiles) ? state.conflictFiles.map(String) : [],
56548
- startedAt: state.startedAt || nowIso(),
56549
- lastChecked: nowIso()
56550
- };
56551
- }
56552
- function findSessionStateFile(startCwd = process.cwd()) {
56553
- let current = import_node_path6.default.resolve(startCwd);
56554
- for (; ; ) {
56555
- const candidate = import_node_path6.default.join(current, SESSION_STATE_FILE);
56556
- if ((0, import_node_fs4.existsSync)(candidate)) return candidate;
56557
- const parent = import_node_path6.default.dirname(current);
56558
- if (parent === current) return null;
56559
- current = parent;
56560
- }
56561
- }
56562
- function readSessionState(startCwd = process.cwd()) {
56563
- const filePath = findSessionStateFile(startCwd);
56564
- if (!filePath) return null;
56565
- try {
56566
- const parsed = JSON.parse((0, import_node_fs4.readFileSync)(filePath, "utf8"));
56567
- return normalizeState(parsed);
56568
- } catch {
56569
- return null;
56570
- }
56571
- }
56572
- function updateSessionPhase(nextPhase, startCwd = process.cwd(), patch = {}) {
56573
- const filePath = findSessionStateFile(startCwd);
56574
- if (!filePath) throw new Error("Session state file not found");
56575
- const current = readSessionState(startCwd);
56576
- if (!current) throw new Error("Session state file invalid");
56577
- if (!isPhase(nextPhase)) {
56578
- throw new Error(`Invalid session phase: ${String(nextPhase)}`);
56579
- }
56580
- if (current.phase !== nextPhase && !ALLOWED_TRANSITIONS[current.phase].includes(nextPhase)) {
56581
- throw new Error(`Invalid phase transition: ${current.phase} -> ${nextPhase}`);
56582
- }
56583
- const nextState = normalizeState({
56584
- ...current,
56585
- ...patch,
56586
- phase: nextPhase
56587
- });
56588
- (0, import_node_fs4.writeFileSync)(filePath, JSON.stringify(nextState, null, 2) + "\n", "utf8");
56589
- return nextState;
56590
- }
56591
-
56592
- // src/core/xtrm-finish.ts
56593
- var DEFAULT_POLL_INTERVAL_MS = 5e3;
56594
- var DEFAULT_TIMEOUT_MS = 10 * 60 * 1e3;
56595
- function run2(cmd, args, cwd) {
56596
- const r = (0, import_node_child_process7.spawnSync)(cmd, args, {
56597
- cwd,
56598
- encoding: "utf8",
56599
- stdio: ["pipe", "pipe", "pipe"]
56600
- });
56601
- return {
56602
- code: r.status ?? 1,
56603
- stdout: (r.stdout ?? "").trim(),
56604
- stderr: (r.stderr ?? "").trim()
56605
- };
56606
- }
56607
- function getControlRepoRoot(cwd) {
56608
- const commonDir = run2("git", ["rev-parse", "--path-format=absolute", "--git-common-dir"], cwd);
56609
- if (commonDir.code === 0 && commonDir.stdout) {
56610
- return commonDir.stdout.replace(/\/.git$/, "");
56611
- }
56612
- return cwd;
56613
- }
56614
- function resolveExecutionCwd(controlCwd, state) {
56615
- if (state.worktreePath && (0, import_node_fs5.existsSync)(state.worktreePath)) {
56616
- return state.worktreePath;
56617
- }
56618
- return controlCwd;
56619
- }
56620
- function parsePrCreate(stdout) {
56621
- const urlMatch = stdout.match(/https?:\/\/\S+\/pull\/(\d+)/);
56622
- if (urlMatch) {
56623
- return { prNumber: Number(urlMatch[1]), prUrl: urlMatch[0] };
56624
- }
56625
- const numberMatch = stdout.match(/#(\d+)/);
56626
- if (numberMatch) {
56627
- return { prNumber: Number(numberMatch[1]), prUrl: null };
56628
- }
56629
- return { prNumber: null, prUrl: null };
56630
- }
56631
- function getConflictFiles(cwd) {
56632
- const out = run2("git", ["diff", "--name-only", "--diff-filter=U"], cwd);
56633
- if (out.code !== 0 || !out.stdout) return [];
56634
- return out.stdout.split("\n").map((s) => s.trim()).filter(Boolean);
56635
- }
56636
- async function delay2(ms) {
56637
- if (ms <= 0) return;
56638
- await new Promise((resolve2) => setTimeout(resolve2, ms));
56639
- }
56640
- function ensureCleanPhaseTransition(cwd, phase, patch = {}) {
56641
- try {
56642
- updateSessionPhase(phase, cwd, patch);
56643
- } catch {
56644
- }
56645
- }
56646
- function handleRebaseAndPush(cwd) {
56647
- const fetch = run2("git", ["fetch", "origin"], cwd);
56648
- if (fetch.code !== 0) return { ok: false, error: fetch.stderr || fetch.stdout };
56649
- const rebase = run2("git", ["rebase", "origin/main"], cwd);
56650
- if (rebase.code !== 0) {
56651
- const conflicts = getConflictFiles(cwd);
56652
- return { ok: false, conflicts, error: rebase.stderr || rebase.stdout };
56653
- }
56654
- const push = run2("git", ["push", "--force-with-lease"], cwd);
56655
- if (push.code !== 0) {
56656
- return { ok: false, error: push.stderr || push.stdout };
56657
- }
56658
- return { ok: true };
56659
- }
56660
- function cleanupPhase(controlCwd, state) {
56661
- if ((0, import_node_fs5.existsSync)(state.worktreePath)) {
56662
- const rm = run2("git", ["worktree", "remove", state.worktreePath, "--force"], controlCwd);
56663
- if (rm.code !== 0) {
56664
- return { ok: false, message: rm.stderr || rm.stdout || `Failed to remove worktree ${state.worktreePath}` };
56665
- }
56666
- }
56667
- run2("git", ["fetch", "--prune"], controlCwd);
56668
- ensureCleanPhaseTransition(controlCwd, "cleanup-done");
56669
- const prLabel = state.prNumber != null ? `#${state.prNumber}` : "(unknown PR)";
56670
- return { ok: true, message: `Done. PR ${prLabel} merged. Worktree removed.` };
56671
- }
56672
- async function pollUntilMerged(controlCwd, executionCwd, state, opts) {
56673
- if (state.prNumber == null) {
56674
- return { ok: false, message: "Session state missing prNumber. Re-run phase 1 before polling." };
56675
- }
56676
- const started = Date.now();
56677
- while (Date.now() - started < opts.timeoutMs) {
56678
- const view = run2("gh", ["pr", "view", String(state.prNumber), "--json", "state,mergeStateStatus,mergeable"], executionCwd);
56679
- if (view.code !== 0) {
56680
- return { ok: false, message: view.stderr || view.stdout || `Failed to inspect PR #${state.prNumber}` };
56681
- }
56682
- let payload = null;
56683
- try {
56684
- payload = JSON.parse(view.stdout);
56685
- } catch {
56686
- return { ok: false, message: `Unable to parse gh pr view output for #${state.prNumber}` };
56687
- }
56688
- ensureCleanPhaseTransition(controlCwd, "waiting-merge");
56689
- if (payload.state === "MERGED") {
56690
- ensureCleanPhaseTransition(controlCwd, "merged");
56691
- const latest = readSessionState(controlCwd) ?? state;
56692
- return cleanupPhase(controlCwd, latest);
56693
- }
56694
- if (payload.mergeStateStatus === "BEHIND") {
56695
- run2("git", ["fetch", "origin"], executionCwd);
56696
- run2("git", ["push"], executionCwd);
56697
- await delay2(opts.pollIntervalMs);
56698
- continue;
56699
- }
56700
- if (payload.mergeable === "CONFLICTING") {
56701
- const rebased = handleRebaseAndPush(executionCwd);
56702
- if (!rebased.ok) {
56703
- const conflictFiles = rebased.conflicts ?? getConflictFiles(executionCwd);
56704
- ensureCleanPhaseTransition(controlCwd, "conflicting", { conflictFiles });
56705
- return {
56706
- ok: false,
56707
- message: `Conflicts in: ${conflictFiles.join(", ") || "unknown files"}. Resolve, push, then re-run xtrm finish.`
56708
- };
56709
- }
56710
- ensureCleanPhaseTransition(controlCwd, "waiting-merge", { conflictFiles: [] });
56711
- await delay2(opts.pollIntervalMs);
56712
- continue;
56713
- }
56714
- await delay2(opts.pollIntervalMs);
56715
- }
56716
- ensureCleanPhaseTransition(controlCwd, "pending-cleanup");
56717
- return {
56718
- ok: false,
56719
- message: `PR #${state.prNumber} not yet merged. Run xtrm finish when ready.`
56720
- };
56721
- }
56722
- function isWorkingTreeDirty(cwd) {
56723
- const st = run2("git", ["status", "--porcelain"], cwd);
56724
- return st.code === 0 && st.stdout.length > 0;
56725
- }
56726
- function runPhase1(controlCwd, executionCwd, state) {
56727
- if (isWorkingTreeDirty(executionCwd)) {
56728
- const add = run2("git", ["add", "-A"], executionCwd);
56729
- if (add.code !== 0) return { ok: false, message: add.stderr || add.stdout };
56730
- const msg = `feat(${state.issueId}): ${state.branch}`;
56731
- const commit = run2("git", ["commit", "-m", msg], executionCwd);
56732
- if (commit.code !== 0) {
56733
- return { ok: false, message: commit.stderr || commit.stdout || "git commit failed" };
56734
- }
56735
- }
56736
- const push = run2("git", ["push", "-u", "origin", state.branch], executionCwd);
56737
- if (push.code !== 0) return { ok: false, message: push.stderr || push.stdout || "git push failed" };
56738
- const create = run2("gh", ["pr", "create", "--fill"], executionCwd);
56739
- if (create.code !== 0) return { ok: false, message: create.stderr || create.stdout || "gh pr create failed" };
56740
- const parsed = parsePrCreate(create.stdout);
56741
- const merge2 = run2("gh", ["pr", "merge", "--squash", "--auto"], executionCwd);
56742
- if (merge2.code !== 0) return { ok: false, message: merge2.stderr || merge2.stdout || "gh pr merge failed" };
56743
- ensureCleanPhaseTransition(controlCwd, "phase1-done", {
56744
- prNumber: parsed.prNumber,
56745
- prUrl: parsed.prUrl
56746
- });
56747
- ensureCleanPhaseTransition(controlCwd, "waiting-merge", {
56748
- prNumber: parsed.prNumber,
56749
- prUrl: parsed.prUrl
56750
- });
56751
- return { ok: true, message: "phase1 complete" };
56752
- }
56753
- async function runXtrmFinish(options = {}) {
56754
- const cwd = options.cwd ?? process.cwd();
56755
- const controlCwd = getControlRepoRoot(cwd);
56756
- const state = readSessionState(controlCwd);
56757
- if (!state) {
56758
- return { ok: false, message: "No .xtrm-session-state.json found. Claim an issue first (bd update <id> --claim)." };
56759
- }
56760
- const executionCwd = resolveExecutionCwd(controlCwd, state);
56761
- const opts = {
56762
- cwd: controlCwd,
56763
- pollIntervalMs: options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS,
56764
- timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS
56765
- };
56766
- if (state.phase === "cleanup-done") {
56767
- return { ok: true, message: "Session is already cleanup-done." };
56768
- }
56769
- if (state.phase === "conflicting") {
56770
- const resolved = handleRebaseAndPush(executionCwd);
56771
- if (!resolved.ok) {
56772
- const files = resolved.conflicts ?? getConflictFiles(executionCwd);
56773
- ensureCleanPhaseTransition(controlCwd, "conflicting", { conflictFiles: files });
56774
- return { ok: false, message: `Conflicts in: ${files.join(", ") || "unknown files"}. Resolve, push, then re-run xtrm finish.` };
56775
- }
56776
- ensureCleanPhaseTransition(controlCwd, "waiting-merge", { conflictFiles: [] });
56777
- const refreshed2 = readSessionState(controlCwd) ?? state;
56778
- return pollUntilMerged(controlCwd, executionCwd, refreshed2, opts);
56779
- }
56780
- if (state.phase === "waiting-merge" || state.phase === "pending-cleanup" || state.phase === "merged") {
56781
- const refreshed2 = readSessionState(controlCwd) ?? state;
56782
- if (refreshed2.phase === "merged") return cleanupPhase(controlCwd, refreshed2);
56783
- return pollUntilMerged(controlCwd, executionCwd, refreshed2, opts);
56784
- }
56785
- const phase1 = runPhase1(controlCwd, executionCwd, state);
56786
- if (!phase1.ok) return phase1;
56787
- const refreshed = readSessionState(controlCwd) ?? state;
56788
- return pollUntilMerged(controlCwd, executionCwd, refreshed, opts);
56789
- }
56790
-
56791
- // src/commands/finish.ts
56792
- function createFinishCommand() {
56793
- return new Command("finish").description("Complete session closure lifecycle (phase1 + merge polling + cleanup)").option("--poll-interval-ms <ms>", "Polling interval for PR state checks", (v) => Number(v), 5e3).option("--timeout-ms <ms>", "Maximum wait time before pending-cleanup", (v) => Number(v), 10 * 60 * 1e3).action(async (opts) => {
56794
- const result = await runXtrmFinish({
56795
- cwd: process.cwd(),
56796
- pollIntervalMs: opts.pollIntervalMs,
56797
- timeoutMs: opts.timeoutMs
56798
- });
56799
- if (result.ok) {
56800
- console.log(kleur_default.green(`
56801
- \u2713 ${result.message}
56802
- `));
56803
- return;
56804
- }
56805
- console.error(kleur_default.red(`
56806
- \u2717 ${result.message}
56807
- `));
56808
- process.exitCode = 1;
56809
- });
56810
- }
56811
-
56812
56390
  // src/commands/end.ts
56813
- var import_prompts5 = __toESM(require_prompts3(), 1);
56814
- var import_node_child_process8 = require("child_process");
56391
+ var import_prompts4 = __toESM(require_prompts3(), 1);
56392
+ var import_node_child_process6 = require("child_process");
56815
56393
  function git(args, cwd) {
56816
- const r = (0, import_node_child_process8.spawnSync)("git", args, { cwd, encoding: "utf8", stdio: "pipe" });
56394
+ const r = (0, import_node_child_process6.spawnSync)("git", args, { cwd, encoding: "utf8", stdio: "pipe" });
56817
56395
  return { ok: r.status === 0, out: (r.stdout ?? "").trim(), err: (r.stderr ?? "").trim() };
56818
56396
  }
56819
56397
  function bd(args, cwd) {
56820
- const r = (0, import_node_child_process8.spawnSync)("bd", args, { cwd, encoding: "utf8", stdio: "pipe" });
56398
+ const r = (0, import_node_child_process6.spawnSync)("bd", args, { cwd, encoding: "utf8", stdio: "pipe" });
56821
56399
  return { ok: r.status === 0, out: (r.stdout ?? "").trim() };
56822
56400
  }
56823
56401
  function extractIssueIds(commitLog) {
@@ -56945,7 +56523,7 @@ function createEndCommand() {
56945
56523
  console.log(kleur_default.dim(" Creating PR..."));
56946
56524
  const prArgs = ["pr", "create", "--title", prTitle, "--body", prBody];
56947
56525
  if (opts.draft) prArgs.push("--draft");
56948
- const prResult = (0, import_node_child_process8.spawnSync)("gh", prArgs, { cwd, encoding: "utf8", stdio: "pipe" });
56526
+ const prResult = (0, import_node_child_process6.spawnSync)("gh", prArgs, { cwd, encoding: "utf8", stdio: "pipe" });
56949
56527
  if (prResult.status !== 0) {
56950
56528
  console.error(kleur_default.red(`
56951
56529
  \u2717 PR creation failed:
@@ -56964,7 +56542,7 @@ function createEndCommand() {
56964
56542
  if (!opts.keep) {
56965
56543
  let doRemove = opts.yes;
56966
56544
  if (!opts.yes) {
56967
- const { remove } = await (0, import_prompts5.default)({
56545
+ const { remove } = await (0, import_prompts4.default)({
56968
56546
  type: "confirm",
56969
56547
  name: "remove",
56970
56548
  message: `Remove local worktree at ${cwd}?`,
@@ -56975,7 +56553,7 @@ function createEndCommand() {
56975
56553
  if (doRemove) {
56976
56554
  try {
56977
56555
  const repoRoot = git(["rev-parse", "--show-toplevel"], cwd).out;
56978
- const removeResult = (0, import_node_child_process8.spawnSync)(
56556
+ const removeResult = (0, import_node_child_process6.spawnSync)(
56979
56557
  "git",
56980
56558
  ["worktree", "remove", cwd, "--force"],
56981
56559
  { cwd: repoRoot, encoding: "utf8", stdio: "pipe" }
@@ -56998,10 +56576,10 @@ function createEndCommand() {
56998
56576
  }
56999
56577
 
57000
56578
  // src/commands/worktree.ts
57001
- var import_prompts6 = __toESM(require_prompts3(), 1);
57002
- var import_node_child_process9 = require("child_process");
56579
+ var import_prompts5 = __toESM(require_prompts3(), 1);
56580
+ var import_node_child_process7 = require("child_process");
57003
56581
  function listXtWorktrees(repoRoot) {
57004
- const r = (0, import_node_child_process9.spawnSync)("git", ["worktree", "list", "--porcelain"], {
56582
+ const r = (0, import_node_child_process7.spawnSync)("git", ["worktree", "list", "--porcelain"], {
57005
56583
  cwd: repoRoot,
57006
56584
  encoding: "utf8",
57007
56585
  stdio: "pipe"
@@ -57030,7 +56608,7 @@ function listXtWorktrees(repoRoot) {
57030
56608
  }
57031
56609
  function isMergedIntoMain(branch, repoRoot) {
57032
56610
  const branchShort = branch.replace("refs/heads/", "");
57033
- const r = (0, import_node_child_process9.spawnSync)("git", ["branch", "--merged", "origin/main", "--list", branchShort], {
56611
+ const r = (0, import_node_child_process7.spawnSync)("git", ["branch", "--merged", "origin/main", "--list", branchShort], {
57034
56612
  cwd: repoRoot,
57035
56613
  encoding: "utf8",
57036
56614
  stdio: "pipe"
@@ -57038,7 +56616,7 @@ function isMergedIntoMain(branch, repoRoot) {
57038
56616
  return (r.stdout ?? "").includes(branchShort);
57039
56617
  }
57040
56618
  function getRepoRoot(cwd) {
57041
- const r = (0, import_node_child_process9.spawnSync)("git", ["rev-parse", "--show-toplevel"], { cwd, encoding: "utf8", stdio: "pipe" });
56619
+ const r = (0, import_node_child_process7.spawnSync)("git", ["rev-parse", "--show-toplevel"], { cwd, encoding: "utf8", stdio: "pipe" });
57042
56620
  return r.ok ? r.stdout.trim() : cwd;
57043
56621
  }
57044
56622
  function createWorktreeCommand() {
@@ -57079,7 +56657,7 @@ function createWorktreeCommand() {
57079
56657
  }
57080
56658
  let doRemove = opts.yes;
57081
56659
  if (!opts.yes) {
57082
- const { confirm } = await (0, import_prompts6.default)({
56660
+ const { confirm } = await (0, import_prompts5.default)({
57083
56661
  type: "confirm",
57084
56662
  name: "confirm",
57085
56663
  message: `Remove ${merged.length} worktree(s)?`,
@@ -57092,7 +56670,7 @@ function createWorktreeCommand() {
57092
56670
  return;
57093
56671
  }
57094
56672
  for (const wt of merged) {
57095
- const r = (0, import_node_child_process9.spawnSync)("git", ["worktree", "remove", wt.path, "--force"], {
56673
+ const r = (0, import_node_child_process7.spawnSync)("git", ["worktree", "remove", wt.path, "--force"], {
57096
56674
  cwd: repoRoot,
57097
56675
  encoding: "utf8",
57098
56676
  stdio: "pipe"
@@ -57120,7 +56698,7 @@ function createWorktreeCommand() {
57120
56698
  }
57121
56699
  let doRemove = opts.yes;
57122
56700
  if (!opts.yes) {
57123
- const { confirm } = await (0, import_prompts6.default)({
56701
+ const { confirm } = await (0, import_prompts5.default)({
57124
56702
  type: "confirm",
57125
56703
  name: "confirm",
57126
56704
  message: `Remove ${target.path}?`,
@@ -57132,7 +56710,7 @@ function createWorktreeCommand() {
57132
56710
  console.log(kleur_default.dim(" Cancelled\n"));
57133
56711
  return;
57134
56712
  }
57135
- const r = (0, import_node_child_process9.spawnSync)("git", ["worktree", "remove", target.path, "--force"], {
56713
+ const r = (0, import_node_child_process7.spawnSync)("git", ["worktree", "remove", target.path, "--force"], {
57136
56714
  cwd: repoRoot,
57137
56715
  encoding: "utf8",
57138
56716
  stdio: "pipe"
@@ -57151,6 +56729,336 @@ function createWorktreeCommand() {
57151
56729
  return cmd;
57152
56730
  }
57153
56731
 
56732
+ // src/commands/docs.ts
56733
+ var import_fs_extra19 = __toESM(require_lib2(), 1);
56734
+ var import_path20 = __toESM(require("path"), 1);
56735
+ var REQUIRED_FIELDS = /* @__PURE__ */ new Set(["title", "type", "status", "updated_at", "version"]);
56736
+ function parseFrontmatter(content) {
56737
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
56738
+ if (!match) return null;
56739
+ const fm = {};
56740
+ for (const line of match[1].split("\n")) {
56741
+ const colon = line.indexOf(":");
56742
+ if (colon === -1) continue;
56743
+ const key = line.slice(0, colon).trim();
56744
+ const value = line.slice(colon + 1).trim().replace(/^["']|["']$/g, "");
56745
+ if (key) fm[key] = value;
56746
+ }
56747
+ return fm;
56748
+ }
56749
+ async function collectDocFiles(repoRoot, filterPattern) {
56750
+ const candidates = [];
56751
+ for (const name of ["README.md", "CHANGELOG.md"]) {
56752
+ const p = import_path20.default.join(repoRoot, name);
56753
+ if (await import_fs_extra19.default.pathExists(p)) candidates.push(p);
56754
+ }
56755
+ const docsDir = import_path20.default.join(repoRoot, "docs");
56756
+ if (await import_fs_extra19.default.pathExists(docsDir)) {
56757
+ const entries = await import_fs_extra19.default.readdir(docsDir);
56758
+ for (const entry of entries) {
56759
+ if (entry.endsWith(".md")) candidates.push(import_path20.default.join(docsDir, entry));
56760
+ }
56761
+ }
56762
+ const results = [];
56763
+ for (const filePath of candidates) {
56764
+ const rel = import_path20.default.relative(repoRoot, filePath);
56765
+ if (filterPattern && !rel.includes(filterPattern) && !import_path20.default.basename(filePath).includes(filterPattern)) {
56766
+ continue;
56767
+ }
56768
+ let entry;
56769
+ try {
56770
+ const stat = await import_fs_extra19.default.stat(filePath);
56771
+ const content = await import_fs_extra19.default.readFile(filePath, "utf8");
56772
+ const frontmatter = parseFrontmatter(content);
56773
+ entry = {
56774
+ filePath,
56775
+ relativePath: rel,
56776
+ frontmatter,
56777
+ sizeBytes: stat.size,
56778
+ lastModified: stat.mtime
56779
+ };
56780
+ } catch (err) {
56781
+ entry = {
56782
+ filePath,
56783
+ relativePath: rel,
56784
+ frontmatter: null,
56785
+ sizeBytes: 0,
56786
+ lastModified: /* @__PURE__ */ new Date(0),
56787
+ parseError: err.message
56788
+ };
56789
+ }
56790
+ results.push(entry);
56791
+ }
56792
+ return results;
56793
+ }
56794
+ function formatSize(bytes) {
56795
+ if (bytes < 1024) return `${bytes}B`;
56796
+ return `${(bytes / 1024).toFixed(1)}KB`;
56797
+ }
56798
+ function formatDate(d) {
56799
+ return d.toISOString().slice(0, 10);
56800
+ }
56801
+ function printEntry(entry, raw) {
56802
+ const header = kleur_default.bold().white(entry.relativePath);
56803
+ const meta3 = kleur_default.gray(` ${formatSize(entry.sizeBytes)} modified ${formatDate(entry.lastModified)}`);
56804
+ console.log(`
56805
+ ${header}${meta3}`);
56806
+ if (entry.parseError) {
56807
+ console.log(kleur_default.red(` \u2717 Error reading file: ${entry.parseError}`));
56808
+ return;
56809
+ }
56810
+ if (!entry.frontmatter || Object.keys(entry.frontmatter).length === 0) {
56811
+ console.log(kleur_default.gray(" (no frontmatter)"));
56812
+ return;
56813
+ }
56814
+ if (raw) {
56815
+ console.log(kleur_default.gray(" ---"));
56816
+ for (const [k, v] of Object.entries(entry.frontmatter)) {
56817
+ console.log(` ${k}: ${v}`);
56818
+ }
56819
+ console.log(kleur_default.gray(" ---"));
56820
+ return;
56821
+ }
56822
+ for (const [k, v] of Object.entries(entry.frontmatter)) {
56823
+ const keyStr = REQUIRED_FIELDS.has(k) ? kleur_default.cyan(k.padEnd(14)) : kleur_default.gray(k.padEnd(14));
56824
+ const valStr = v ?? "";
56825
+ console.log(` ${keyStr} ${valStr}`);
56826
+ }
56827
+ }
56828
+ function createDocsCommand() {
56829
+ const docs = new Command("docs").description("Documentation management commands");
56830
+ docs.command("show [filter]").description("Display frontmatters for README, CHANGELOG, and docs/ files").option("--raw", "Output raw YAML frontmatter", false).option("--json", "Output JSON", false).action(async (filter, opts) => {
56831
+ const repoRoot = await findRepoRoot();
56832
+ const entries = await collectDocFiles(repoRoot, filter);
56833
+ if (entries.length === 0) {
56834
+ console.log(kleur_default.yellow("\n No documentation files found.\n"));
56835
+ return;
56836
+ }
56837
+ if (opts.json) {
56838
+ const output = entries.map((e) => ({
56839
+ path: e.relativePath,
56840
+ sizeBytes: e.sizeBytes,
56841
+ lastModified: e.lastModified.toISOString(),
56842
+ frontmatter: e.frontmatter,
56843
+ parseError: e.parseError ?? null
56844
+ }));
56845
+ console.log(JSON.stringify(output, null, 2));
56846
+ return;
56847
+ }
56848
+ for (const entry of entries) {
56849
+ printEntry(entry, opts.raw);
56850
+ }
56851
+ const without = entries.filter((e) => !e.frontmatter || Object.keys(e.frontmatter).length === 0).length;
56852
+ console.log(
56853
+ `
56854
+ ${sym.ok} ${entries.length} file${entries.length !== 1 ? "s" : ""}` + (without > 0 ? kleur_default.gray(` (${without} without frontmatter)`) : "") + "\n"
56855
+ );
56856
+ });
56857
+ return docs;
56858
+ }
56859
+
56860
+ // src/commands/debug.ts
56861
+ var import_node_child_process8 = require("child_process");
56862
+ var import_node_fs5 = require("fs");
56863
+ var import_node_path6 = require("path");
56864
+ var KIND_LABELS = {
56865
+ "session.start": { label: "SESS+", color: kleur_default.green },
56866
+ "session.end": { label: "SESS-", color: kleur_default.white },
56867
+ "gate.edit.allow": { label: "EDIT+", color: kleur_default.green },
56868
+ "gate.edit.block": { label: "EDIT-", color: kleur_default.red },
56869
+ "gate.commit.allow": { label: "CMIT+", color: kleur_default.green },
56870
+ "gate.commit.block": { label: "CMIT-", color: kleur_default.red },
56871
+ "gate.stop.block": { label: "STOP-", color: kleur_default.red },
56872
+ "gate.memory.triggered": { label: "MEMO-", color: kleur_default.yellow },
56873
+ "gate.memory.acked": { label: "MEMO+", color: kleur_default.green },
56874
+ "gate.worktree.block": { label: "WTRE-", color: kleur_default.red },
56875
+ "bd.claimed": { label: "CLMD ", color: kleur_default.cyan },
56876
+ "bd.closed": { label: "CLSD ", color: kleur_default.green },
56877
+ "bd.committed": {
56878
+ label: (outcome) => outcome === "error" ? "ACMT-" : "ACMT+",
56879
+ color: (outcome) => outcome === "error" ? kleur_default.red : kleur_default.cyan
56880
+ }
56881
+ };
56882
+ var TOOL_ABBREVS = {
56883
+ Bash: "BASH",
56884
+ bash: "BASH",
56885
+ execute_shell_command: "BASH",
56886
+ Read: "READ",
56887
+ Write: "WRIT",
56888
+ Edit: "EDIT",
56889
+ MultiEdit: "EDIT",
56890
+ NotebookEdit: "NTED",
56891
+ Glob: "GLOB",
56892
+ Grep: "GREP",
56893
+ WebFetch: "WBFT",
56894
+ WebSearch: "WSRC",
56895
+ Agent: "AGNT",
56896
+ Task: "TASK",
56897
+ LSP: "LSP "
56898
+ };
56899
+ function toolAbbrev(toolName) {
56900
+ if (TOOL_ABBREVS[toolName]) return TOOL_ABBREVS[toolName];
56901
+ if (toolName.startsWith("mcp__serena__")) return "SRNA";
56902
+ if (toolName.startsWith("mcp__gitnexus__")) return "GTNX";
56903
+ if (toolName.startsWith("mcp__deepwiki__")) return "WIKI";
56904
+ if (toolName.startsWith("mcp__")) return "MCP ";
56905
+ return toolName.slice(0, 4).toUpperCase();
56906
+ }
56907
+ function getLabel(event) {
56908
+ if (event.kind === "tool.call") {
56909
+ const abbrev = toolAbbrev(event.tool_name ?? "").padEnd(5);
56910
+ return event.outcome === "error" ? kleur_default.red(abbrev) : kleur_default.dim(abbrev);
56911
+ }
56912
+ const def = KIND_LABELS[event.kind];
56913
+ if (!def) {
56914
+ const seg = (event.kind.split(".").pop() ?? "UNKN").slice(0, 4).toUpperCase();
56915
+ const label = `${seg}${event.outcome === "block" ? "-" : "+"}`.padEnd(5);
56916
+ return event.outcome === "block" ? kleur_default.red(label) : kleur_default.dim(label);
56917
+ }
56918
+ if (event.kind === "bd.committed") {
56919
+ const label = event.outcome === "error" ? "ACMT-" : "ACMT+";
56920
+ return event.outcome === "error" ? kleur_default.red(label) : kleur_default.cyan(label);
56921
+ }
56922
+ return def.color(
56923
+ def.label
56924
+ );
56925
+ }
56926
+ var SESSION_COLORS = [
56927
+ kleur_default.blue,
56928
+ kleur_default.green,
56929
+ kleur_default.yellow,
56930
+ kleur_default.cyan,
56931
+ kleur_default.magenta
56932
+ ];
56933
+ function buildColorMap(events) {
56934
+ const map2 = /* @__PURE__ */ new Map();
56935
+ for (const ev of events) {
56936
+ if (!map2.has(ev.session_id)) {
56937
+ map2.set(ev.session_id, SESSION_COLORS[map2.size % SESSION_COLORS.length]);
56938
+ }
56939
+ }
56940
+ return map2;
56941
+ }
56942
+ function extendColorMap(map2, events) {
56943
+ for (const ev of events) {
56944
+ if (!map2.has(ev.session_id)) {
56945
+ map2.set(ev.session_id, SESSION_COLORS[map2.size % SESSION_COLORS.length]);
56946
+ }
56947
+ }
56948
+ }
56949
+ function fmtTime(ts) {
56950
+ return new Date(ts).toLocaleTimeString("en-GB", { hour12: false });
56951
+ }
56952
+ function buildDetail(event) {
56953
+ const parts = [];
56954
+ let d = null;
56955
+ if (event.data) {
56956
+ try {
56957
+ d = JSON.parse(event.data);
56958
+ } catch {
56959
+ }
56960
+ }
56961
+ if (event.kind === "tool.call") {
56962
+ if (d?.cmd) parts.push(kleur_default.dim(d.cmd.slice(0, 72)));
56963
+ if (d?.file) parts.push(kleur_default.dim((0, import_node_path6.basename)(d.file)));
56964
+ if (d?.pattern) parts.push(kleur_default.dim(`/${d.pattern}/`));
56965
+ if (d?.url) parts.push(kleur_default.dim(d.url.slice(0, 72)));
56966
+ if (d?.query) parts.push(kleur_default.dim(d.query.slice(0, 72)));
56967
+ if (d?.prompt) parts.push(kleur_default.dim(d.prompt.slice(0, 72)));
56968
+ } else {
56969
+ if (event.issue_id) parts.push(kleur_default.yellow(event.issue_id));
56970
+ if (d?.file) parts.push(kleur_default.dim((0, import_node_path6.basename)(d.file)));
56971
+ if (d?.reason_code) parts.push(kleur_default.dim(`[${d.reason_code}]`));
56972
+ if (event.worktree) parts.push(kleur_default.dim(`wt:${event.worktree}`));
56973
+ }
56974
+ return parts.join(" ") || kleur_default.dim("\u2014");
56975
+ }
56976
+ function formatLine(event, colorMap) {
56977
+ const time3 = kleur_default.dim(fmtTime(event.ts));
56978
+ const colorFn = colorMap.get(event.session_id) ?? kleur_default.white;
56979
+ const session = colorFn(event.session_id.slice(0, 8));
56980
+ const label = getLabel(event);
56981
+ const detail = buildDetail(event);
56982
+ return `${time3} ${label} ${session} ${detail}`;
56983
+ }
56984
+ function findDbPath(cwd) {
56985
+ let dir = cwd;
56986
+ for (let i = 0; i < 10; i++) {
56987
+ if ((0, import_node_fs5.existsSync)((0, import_node_path6.join)(dir, ".beads"))) return (0, import_node_path6.join)(dir, ".xtrm", "debug.db");
56988
+ const parent = (0, import_node_path6.join)(dir, "..");
56989
+ if (parent === dir) break;
56990
+ dir = parent;
56991
+ }
56992
+ return null;
56993
+ }
56994
+ function buildWhere(opts, base) {
56995
+ const clauses = [];
56996
+ if (base) clauses.push(base);
56997
+ if (opts.session) {
56998
+ const s = opts.session.replace(/'/g, "''");
56999
+ clauses.push(`session_id LIKE '${s}%'`);
57000
+ }
57001
+ if (opts.type) {
57002
+ const t3 = opts.type.replace(/'/g, "''");
57003
+ clauses.push(`kind LIKE '${t3}.%' OR kind = '${t3}'`);
57004
+ }
57005
+ return clauses.length ? clauses.join(" AND ") : "";
57006
+ }
57007
+ function queryEvents(dbPath, where, limit) {
57008
+ const sql = `SELECT id,ts,session_id,runtime,worktree,kind,tool_name,outcome,issue_id,duration_ms,data FROM events${where ? ` WHERE ${where}` : ""} ORDER BY id ASC LIMIT ${limit}`;
57009
+ const result = (0, import_node_child_process8.spawnSync)("sqlite3", [dbPath, "-json", sql], {
57010
+ stdio: ["pipe", "pipe", "pipe"],
57011
+ encoding: "utf8",
57012
+ timeout: 5e3
57013
+ });
57014
+ if (result.status !== 0 || !result.stdout.trim()) return [];
57015
+ try {
57016
+ return JSON.parse(result.stdout);
57017
+ } catch {
57018
+ return [];
57019
+ }
57020
+ }
57021
+ function follow(dbPath, opts) {
57022
+ const sinceTs = Date.now() - 5 * 60 * 1e3;
57023
+ const initial = queryEvents(dbPath, buildWhere(opts, `ts >= ${sinceTs}`), 200);
57024
+ const colorMap = buildColorMap(initial);
57025
+ let lastId = 0;
57026
+ for (const ev of initial) {
57027
+ if (ev.id > lastId) lastId = ev.id;
57028
+ opts.json ? console.log(JSON.stringify(ev)) : console.log(formatLine(ev, colorMap));
57029
+ }
57030
+ const interval = setInterval(() => {
57031
+ const events = queryEvents(dbPath, buildWhere(opts, `id > ${lastId}`), 50);
57032
+ if (events.length > 0) {
57033
+ extendColorMap(colorMap, events);
57034
+ for (const ev of events) {
57035
+ if (ev.id > lastId) lastId = ev.id;
57036
+ opts.json ? console.log(JSON.stringify(ev)) : console.log(formatLine(ev, colorMap));
57037
+ }
57038
+ }
57039
+ }, 2e3);
57040
+ process.on("SIGINT", () => {
57041
+ clearInterval(interval);
57042
+ process.exit(0);
57043
+ });
57044
+ }
57045
+ function createDebugCommand() {
57046
+ return new Command("debug").description("Watch xtrm events: tool calls, gate decisions, bd lifecycle").option("-f, --follow", "Follow new events (default)", false).option("--all", "Show full history and exit", false).option("--session <id>", "Filter by session ID (prefix match)").option("--type <domain>", "Filter by domain: tool | gate | bd | session").option("--json", "Output raw JSON lines", false).action((opts) => {
57047
+ const cwd = process.cwd();
57048
+ const dbPath = findDbPath(cwd);
57049
+ if (!dbPath || !(0, import_node_fs5.existsSync)(dbPath)) return;
57050
+ if (opts.all) {
57051
+ const events = queryEvents(dbPath, buildWhere(opts, ""), 1e3);
57052
+ const colorMap = buildColorMap(events);
57053
+ for (const ev of events) {
57054
+ opts.json ? console.log(JSON.stringify(ev)) : console.log(formatLine(ev, colorMap));
57055
+ }
57056
+ return;
57057
+ }
57058
+ follow(dbPath, opts);
57059
+ });
57060
+ }
57061
+
57154
57062
  // src/utils/banner.ts
57155
57063
  var ART = [
57156
57064
  " \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
@@ -57218,7 +57126,7 @@ function pressAnyKey() {
57218
57126
  setTimeout(finish, 4e3);
57219
57127
  });
57220
57128
  }
57221
- function delay3(ms) {
57129
+ function delay2(ms) {
57222
57130
  return new Promise((r) => setTimeout(r, ms));
57223
57131
  }
57224
57132
  async function typewriterTagline(text) {
@@ -57228,7 +57136,7 @@ async function typewriterTagline(text) {
57228
57136
  process.stdout.write(prefix);
57229
57137
  for (const ch of text) {
57230
57138
  process.stdout.write(ch);
57231
- await delay3(CHAR_DELAY);
57139
+ await delay2(CHAR_DELAY);
57232
57140
  }
57233
57141
  process.stdout.write(suffix + "\n");
57234
57142
  }
@@ -57249,8 +57157,8 @@ function gradientLine(line) {
57249
57157
  let out = "";
57250
57158
  const len = line.length;
57251
57159
  for (let i = 0; i < len; i++) {
57252
- const t2 = len > 1 ? i / (len - 1) : 0;
57253
- const hue = HUE_START + t2 * (HUE_END - HUE_START);
57160
+ const t3 = len > 1 ? i / (len - 1) : 0;
57161
+ const hue = HUE_START + t3 * (HUE_END - HUE_START);
57254
57162
  const [r, g, b] = hslToRgb(hue, SAT, LIG);
57255
57163
  out += `\x1B[38;2;${r};${g};${b}m` + line[i];
57256
57164
  }
@@ -57346,9 +57254,10 @@ program2.command("init").description("Alias for xtrm project init").action(async
57346
57254
  program2.addCommand(createStatusCommand());
57347
57255
  program2.addCommand(createResetCommand());
57348
57256
  program2.addCommand(createCleanCommand());
57349
- program2.addCommand(createFinishCommand());
57350
57257
  program2.addCommand(createEndCommand());
57351
57258
  program2.addCommand(createWorktreeCommand());
57259
+ program2.addCommand(createDocsCommand());
57260
+ program2.addCommand(createDebugCommand());
57352
57261
  program2.addCommand(createHelpCommand());
57353
57262
  program2.action(async () => {
57354
57263
  program2.help();
@@ -57369,8 +57278,9 @@ process.on("unhandledRejection", (reason) => {
57369
57278
  process.exit(1);
57370
57279
  });
57371
57280
  var isHelpOrVersion = process.argv.some((a) => a === "--help" || a === "-h" || a === "--version" || a === "-V");
57281
+ var isInstallCommand = (process.argv[2] ?? "") === "install";
57372
57282
  (async () => {
57373
- if (!isHelpOrVersion) {
57283
+ if (!isHelpOrVersion && isInstallCommand) {
57374
57284
  await printBanner(version2);
57375
57285
  }
57376
57286
  program2.parseAsync(process.argv);