@usepowerplant/cli 0.4.14 → 0.4.15

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.
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="81d65aee-a279-58bd-9476-cc1269e40adf")}catch(e){}}();
3
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="bdd42bb0-e20a-5100-a257-b6dbb21d0f74")}catch(e){}}();
4
4
  const __cliNodeMajor = Number(process.versions.node.split('.')[0]);
5
5
  if (__cliNodeMajor < 20) {
6
6
  console.error(`powerplant needs Node 20 or newer — this is Node ${process.versions.node}.`);
@@ -6879,19 +6879,19 @@ var require_module_details_from_path = __commonJS({
6879
6879
  basedir += segments[i] + sep2;
6880
6880
  }
6881
6881
  }
6882
- var path33 = "";
6882
+ var path34 = "";
6883
6883
  var lastSegmentIndex = segments.length - 1;
6884
6884
  for (var i2 = index + offset; i2 <= lastSegmentIndex; i2++) {
6885
6885
  if (i2 === lastSegmentIndex) {
6886
- path33 += segments[i2];
6886
+ path34 += segments[i2];
6887
6887
  } else {
6888
- path33 += segments[i2] + sep2;
6888
+ path34 += segments[i2] + sep2;
6889
6889
  }
6890
6890
  }
6891
6891
  return {
6892
6892
  name,
6893
6893
  basedir,
6894
- path: path33
6894
+ path: path34
6895
6895
  };
6896
6896
  };
6897
6897
  }
@@ -6901,7 +6901,7 @@ var require_module_details_from_path = __commonJS({
6901
6901
  var require_require_in_the_middle = __commonJS({
6902
6902
  "../../node_modules/.pnpm/require-in-the-middle@8.0.1/node_modules/require-in-the-middle/index.js"(exports, module2) {
6903
6903
  "use strict";
6904
- var path33 = __require("path");
6904
+ var path34 = __require("path");
6905
6905
  var Module = __require("module");
6906
6906
  var debug2 = require_src3()("require-in-the-middle");
6907
6907
  var moduleDetailsFromPath = require_module_details_from_path();
@@ -7046,7 +7046,7 @@ var require_require_in_the_middle = __commonJS({
7046
7046
  }
7047
7047
  moduleName = filename;
7048
7048
  } else if (hasWhitelist === true && modules.includes(filename)) {
7049
- const parsedPath = path33.parse(filename);
7049
+ const parsedPath = path34.parse(filename);
7050
7050
  moduleName = parsedPath.name;
7051
7051
  basedir = parsedPath.dir;
7052
7052
  } else {
@@ -7084,7 +7084,7 @@ var require_require_in_the_middle = __commonJS({
7084
7084
  }
7085
7085
  if (res !== filename) {
7086
7086
  if (internals === true) {
7087
- moduleName = moduleName + path33.sep + path33.relative(basedir, filename);
7087
+ moduleName = moduleName + path34.sep + path34.relative(basedir, filename);
7088
7088
  debug2("preparing to process require of internal file: %s", moduleName);
7089
7089
  } else {
7090
7090
  debug2("ignoring require of non-main module file: %s", res);
@@ -7120,8 +7120,8 @@ var require_require_in_the_middle = __commonJS({
7120
7120
  }
7121
7121
  };
7122
7122
  function resolveModuleName(stat) {
7123
- const normalizedPath = path33.sep !== "/" ? stat.path.split(path33.sep).join("/") : stat.path;
7124
- return path33.posix.join(stat.name, normalizedPath).replace(normalize3, "");
7123
+ const normalizedPath = path34.sep !== "/" ? stat.path.split(path34.sep).join("/") : stat.path;
7124
+ return path34.posix.join(stat.name, normalizedPath).replace(normalize3, "");
7125
7125
  }
7126
7126
  }
7127
7127
  });
@@ -7206,7 +7206,7 @@ var require_RequireInTheMiddleSingleton = __commonJS({
7206
7206
  Object.defineProperty(exports, "__esModule", { value: true });
7207
7207
  exports.RequireInTheMiddleSingleton = void 0;
7208
7208
  var require_in_the_middle_1 = require_require_in_the_middle();
7209
- var path33 = __require("path");
7209
+ var path34 = __require("path");
7210
7210
  var ModuleNameTrie_1 = require_ModuleNameTrie();
7211
7211
  var isMocha = [
7212
7212
  "afterEach",
@@ -7270,7 +7270,7 @@ var require_RequireInTheMiddleSingleton = __commonJS({
7270
7270
  };
7271
7271
  exports.RequireInTheMiddleSingleton = RequireInTheMiddleSingleton;
7272
7272
  function normalizePathSeparators(moduleNameOrPath) {
7273
- return path33.sep !== ModuleNameTrie_1.ModuleNameSeparator ? moduleNameOrPath.split(path33.sep).join(ModuleNameTrie_1.ModuleNameSeparator) : moduleNameOrPath;
7273
+ return path34.sep !== ModuleNameTrie_1.ModuleNameSeparator ? moduleNameOrPath.split(path34.sep).join(ModuleNameTrie_1.ModuleNameSeparator) : moduleNameOrPath;
7274
7274
  }
7275
7275
  }
7276
7276
  });
@@ -7480,7 +7480,7 @@ var require_register = __commonJS({
7480
7480
  // ../../node_modules/.pnpm/import-in-the-middle@3.5.1/node_modules/import-in-the-middle/index.js
7481
7481
  var require_import_in_the_middle = __commonJS({
7482
7482
  "../../node_modules/.pnpm/import-in-the-middle@3.5.1/node_modules/import-in-the-middle/index.js"(exports, module2) {
7483
- var path33 = __require("path");
7483
+ var path34 = __require("path");
7484
7484
  var moduleDetailsFromPath = require_module_details_from_path();
7485
7485
  var { fileURLToPath: fileURLToPath3 } = __require("url");
7486
7486
  var { MessageChannel } = __require("worker_threads");
@@ -7599,7 +7599,7 @@ var require_import_in_the_middle = __commonJS({
7599
7599
  } else if (baseDir.endsWith(specifiers.get(loadUrl)) || isTurbopackSpecifier(specifiers.get(loadUrl), baseDir)) {
7600
7600
  callHookFn(hookFn, namespace, name, baseDir);
7601
7601
  } else if (internals) {
7602
- const internalPath = name + path33.sep + path33.relative(baseDir, filePath);
7602
+ const internalPath = name + path34.sep + path34.relative(baseDir, filePath);
7603
7603
  callHookFn(hookFn, namespace, internalPath, baseDir);
7604
7604
  }
7605
7605
  } else if (matchArg === specifier) {
@@ -7674,7 +7674,7 @@ var require_instrumentation2 = __commonJS({
7674
7674
  "use strict";
7675
7675
  Object.defineProperty(exports, "__esModule", { value: true });
7676
7676
  exports.InstrumentationBase = void 0;
7677
- var path33 = __require("path");
7677
+ var path34 = __require("path");
7678
7678
  var util_1 = __require("util");
7679
7679
  var semver_1 = require_semver();
7680
7680
  var shimmer_1 = require_shimmer();
@@ -7775,7 +7775,7 @@ var require_instrumentation2 = __commonJS({
7775
7775
  }
7776
7776
  _extractPackageVersion(baseDir) {
7777
7777
  try {
7778
- const json2 = (0, fs_1.readFileSync)(path33.join(baseDir, "package.json"), {
7778
+ const json2 = (0, fs_1.readFileSync)(path34.join(baseDir, "package.json"), {
7779
7779
  encoding: "utf8"
7780
7780
  });
7781
7781
  const version2 = JSON.parse(json2).version;
@@ -7817,7 +7817,7 @@ var require_instrumentation2 = __commonJS({
7817
7817
  return exports2;
7818
7818
  }
7819
7819
  const files = module3.files ?? [];
7820
- const normalizedName = path33.normalize(name);
7820
+ const normalizedName = path34.normalize(name);
7821
7821
  const supportedFileInstrumentations = files.filter((f) => f.name === normalizedName && isSupported(f.supportedVersions, version2, module3.includePrerelease));
7822
7822
  return supportedFileInstrumentations.reduce((patchedExports, file2) => {
7823
7823
  file2.moduleExports = patchedExports;
@@ -7863,8 +7863,8 @@ var require_instrumentation2 = __commonJS({
7863
7863
  this._warnOnPreloadedModules();
7864
7864
  for (const module3 of this._modules) {
7865
7865
  const hookFn = (exports2, name, baseDir) => {
7866
- if (!baseDir && path33.isAbsolute(name)) {
7867
- const parsedPath = path33.parse(name);
7866
+ if (!baseDir && path34.isAbsolute(name)) {
7867
+ const parsedPath = path34.parse(name);
7868
7868
  name = parsedPath.name;
7869
7869
  baseDir = parsedPath.dir;
7870
7870
  }
@@ -7873,7 +7873,7 @@ var require_instrumentation2 = __commonJS({
7873
7873
  const onRequire = (exports2, name, baseDir) => {
7874
7874
  return this._onRequire(module3, exports2, name, baseDir);
7875
7875
  };
7876
- const hook = path33.isAbsolute(module3.name) ? new require_in_the_middle_1.Hook([module3.name], { internals: true }, onRequire) : this._requireInTheMiddleSingleton.register(module3.name, onRequire);
7876
+ const hook = path34.isAbsolute(module3.name) ? new require_in_the_middle_1.Hook([module3.name], { internals: true }, onRequire) : this._requireInTheMiddleSingleton.register(module3.name, onRequire);
7877
7877
  this._hooks.push(hook);
7878
7878
  const esmHook = new import_in_the_middle_1.Hook([module3.name], { internals: true }, hookFn);
7879
7879
  this._hooks.push(esmHook);
@@ -8481,9 +8481,9 @@ var require_getMachineId_linux = __commonJS({
8481
8481
  var api_1 = (init_esm(), __toCommonJS(esm_exports));
8482
8482
  async function getMachineId() {
8483
8483
  const paths = ["/etc/machine-id", "/var/lib/dbus/machine-id"];
8484
- for (const path33 of paths) {
8484
+ for (const path34 of paths) {
8485
8485
  try {
8486
- const result = await fs_1.promises.readFile(path33, { encoding: "utf8" });
8486
+ const result = await fs_1.promises.readFile(path34, { encoding: "utf8" });
8487
8487
  return result.trim();
8488
8488
  } catch (e) {
8489
8489
  api_1.diag.debug(`error reading machine id: ${e}`);
@@ -11843,14 +11843,14 @@ var require_util = __commonJS({
11843
11843
  }
11844
11844
  const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80;
11845
11845
  let origin = url2.origin != null ? url2.origin : `${url2.protocol || ""}//${url2.hostname || ""}:${port}`;
11846
- let path33 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
11846
+ let path34 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
11847
11847
  if (origin[origin.length - 1] === "/") {
11848
11848
  origin = origin.slice(0, origin.length - 1);
11849
11849
  }
11850
- if (path33 && path33[0] !== "/") {
11851
- path33 = `/${path33}`;
11850
+ if (path34 && path34[0] !== "/") {
11851
+ path34 = `/${path34}`;
11852
11852
  }
11853
- return new URL(`${origin}${path33}`);
11853
+ return new URL(`${origin}${path34}`);
11854
11854
  }
11855
11855
  if (!isHttpOrHttpsPrefixed(url2.origin || url2.protocol)) {
11856
11856
  throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
@@ -12671,9 +12671,9 @@ var require_diagnostics = __commonJS({
12671
12671
  "undici:client:sendHeaders",
12672
12672
  (evt) => {
12673
12673
  const {
12674
- request: { method, path: path33, origin }
12674
+ request: { method, path: path34, origin }
12675
12675
  } = evt;
12676
- debugLog3("sending request to %s %s%s", method, origin, path33);
12676
+ debugLog3("sending request to %s %s%s", method, origin, path34);
12677
12677
  }
12678
12678
  );
12679
12679
  }
@@ -12691,14 +12691,14 @@ var require_diagnostics = __commonJS({
12691
12691
  "undici:request:headers",
12692
12692
  (evt) => {
12693
12693
  const {
12694
- request: { method, path: path33, origin },
12694
+ request: { method, path: path34, origin },
12695
12695
  response: { statusCode }
12696
12696
  } = evt;
12697
12697
  debugLog3(
12698
12698
  "received response to %s %s%s - HTTP %d",
12699
12699
  method,
12700
12700
  origin,
12701
- path33,
12701
+ path34,
12702
12702
  statusCode
12703
12703
  );
12704
12704
  }
@@ -12707,23 +12707,23 @@ var require_diagnostics = __commonJS({
12707
12707
  "undici:request:trailers",
12708
12708
  (evt) => {
12709
12709
  const {
12710
- request: { method, path: path33, origin }
12710
+ request: { method, path: path34, origin }
12711
12711
  } = evt;
12712
- debugLog3("trailers received from %s %s%s", method, origin, path33);
12712
+ debugLog3("trailers received from %s %s%s", method, origin, path34);
12713
12713
  }
12714
12714
  );
12715
12715
  diagnosticsChannel9.subscribe(
12716
12716
  "undici:request:error",
12717
12717
  (evt) => {
12718
12718
  const {
12719
- request: { method, path: path33, origin },
12719
+ request: { method, path: path34, origin },
12720
12720
  error: error63
12721
12721
  } = evt;
12722
12722
  debugLog3(
12723
12723
  "request to %s %s%s errored - %s",
12724
12724
  method,
12725
12725
  origin,
12726
- path33,
12726
+ path34,
12727
12727
  error63.message
12728
12728
  );
12729
12729
  }
@@ -12838,7 +12838,7 @@ var require_request = __commonJS({
12838
12838
  var kHandler = /* @__PURE__ */ Symbol("handler");
12839
12839
  var Request2 = class {
12840
12840
  constructor(origin, {
12841
- path: path33,
12841
+ path: path34,
12842
12842
  method,
12843
12843
  body,
12844
12844
  headers,
@@ -12855,11 +12855,11 @@ var require_request = __commonJS({
12855
12855
  maxRedirections,
12856
12856
  typeOfService
12857
12857
  }, handler) {
12858
- if (typeof path33 !== "string") {
12858
+ if (typeof path34 !== "string") {
12859
12859
  throw new InvalidArgumentError("path must be a string");
12860
- } else if (path33[0] !== "/" && !(path33.startsWith("http://") || path33.startsWith("https://")) && method !== "CONNECT") {
12860
+ } else if (path34[0] !== "/" && !(path34.startsWith("http://") || path34.startsWith("https://")) && method !== "CONNECT") {
12861
12861
  throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
12862
- } else if (invalidPathRegex.test(path33)) {
12862
+ } else if (invalidPathRegex.test(path34)) {
12863
12863
  throw new InvalidArgumentError("invalid request path");
12864
12864
  }
12865
12865
  if (typeof method !== "string") {
@@ -12934,7 +12934,7 @@ var require_request = __commonJS({
12934
12934
  this.completed = false;
12935
12935
  this.aborted = false;
12936
12936
  this.upgrade = upgrade || null;
12937
- this.path = query ? serializePathWithQuery(path33, query) : path33;
12937
+ this.path = query ? serializePathWithQuery(path34, query) : path34;
12938
12938
  this.origin = origin;
12939
12939
  this.protocol = getProtocolFromUrlString(origin);
12940
12940
  this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
@@ -18116,7 +18116,7 @@ var require_client_h1 = __commonJS({
18116
18116
  return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
18117
18117
  }
18118
18118
  function writeH1(client, request2) {
18119
- const { method, path: path33, host, upgrade, blocking, reset } = request2;
18119
+ const { method, path: path34, host, upgrade, blocking, reset } = request2;
18120
18120
  let { body, headers, contentLength } = request2;
18121
18121
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
18122
18122
  if (util2.isFormDataLike(body)) {
@@ -18194,7 +18194,7 @@ var require_client_h1 = __commonJS({
18194
18194
  if (socket.setTypeOfService) {
18195
18195
  socket.setTypeOfService(request2.typeOfService);
18196
18196
  }
18197
- let header = `${method} ${path33} HTTP/1.1\r
18197
+ let header = `${method} ${path34} HTTP/1.1\r
18198
18198
  `;
18199
18199
  if (typeof host === "string") {
18200
18200
  header += `host: ${host}\r
@@ -18873,7 +18873,7 @@ var require_client_h2 = __commonJS({
18873
18873
  const headersTimeout = request2.headersTimeout ?? client[kHeadersTimeout];
18874
18874
  const bodyTimeout = request2.bodyTimeout ?? client[kBodyTimeout];
18875
18875
  const session = client[kHTTP2Session];
18876
- const { method, path: path33, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
18876
+ const { method, path: path34, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request2;
18877
18877
  let { body } = request2;
18878
18878
  if (upgrade != null && upgrade !== "websocket") {
18879
18879
  util2.errorRequest(client, request2, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
@@ -18942,7 +18942,7 @@ var require_client_h2 = __commonJS({
18942
18942
  }
18943
18943
  headers[HTTP2_HEADER_METHOD] = "CONNECT";
18944
18944
  headers[HTTP2_HEADER_PROTOCOL] = "websocket";
18945
- headers[HTTP2_HEADER_PATH] = path33;
18945
+ headers[HTTP2_HEADER_PATH] = path34;
18946
18946
  if (protocol === "ws:" || protocol === "wss:") {
18947
18947
  headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
18948
18948
  } else {
@@ -18984,7 +18984,7 @@ var require_client_h2 = __commonJS({
18984
18984
  stream.setTimeout(headersTimeout);
18985
18985
  return true;
18986
18986
  }
18987
- headers[HTTP2_HEADER_PATH] = path33;
18987
+ headers[HTTP2_HEADER_PATH] = path34;
18988
18988
  headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
18989
18989
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
18990
18990
  if (body && typeof body.read === "function") {
@@ -21336,10 +21336,10 @@ var require_proxy_agent = __commonJS({
21336
21336
  };
21337
21337
  const {
21338
21338
  origin,
21339
- path: path33 = "/",
21339
+ path: path34 = "/",
21340
21340
  headers = {}
21341
21341
  } = opts;
21342
- opts.path = origin + path33;
21342
+ opts.path = origin + path34;
21343
21343
  if (!("host" in headers) && !("Host" in headers)) {
21344
21344
  const { host } = new URL(origin);
21345
21345
  headers.host = host;
@@ -23448,20 +23448,20 @@ var require_mock_utils = __commonJS({
23448
23448
  }
23449
23449
  return normalizedQp;
23450
23450
  }
23451
- function safeUrl(path33) {
23452
- if (typeof path33 !== "string") {
23453
- return path33;
23451
+ function safeUrl(path34) {
23452
+ if (typeof path34 !== "string") {
23453
+ return path34;
23454
23454
  }
23455
- const pathSegments = path33.split("?", 3);
23455
+ const pathSegments = path34.split("?", 3);
23456
23456
  if (pathSegments.length !== 2) {
23457
- return path33;
23457
+ return path34;
23458
23458
  }
23459
23459
  const qp = new URLSearchParams(pathSegments.pop());
23460
23460
  qp.sort();
23461
23461
  return [...pathSegments, qp.toString()].join("?");
23462
23462
  }
23463
- function matchKey(mockDispatch2, { path: path33, method, body, headers }) {
23464
- const pathMatch = matchValue(mockDispatch2.path, path33);
23463
+ function matchKey(mockDispatch2, { path: path34, method, body, headers }) {
23464
+ const pathMatch = matchValue(mockDispatch2.path, path34);
23465
23465
  const methodMatch = matchValue(mockDispatch2.method, method);
23466
23466
  const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
23467
23467
  const headersMatch = matchHeaders(mockDispatch2, headers);
@@ -23486,8 +23486,8 @@ var require_mock_utils = __commonJS({
23486
23486
  const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
23487
23487
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
23488
23488
  const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
23489
- let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path33, ignoreTrailingSlash }) => {
23490
- return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path33)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path33), resolvedPath);
23489
+ let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path34, ignoreTrailingSlash }) => {
23490
+ return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path34)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path34), resolvedPath);
23491
23491
  });
23492
23492
  if (matchedMockDispatches.length === 0) {
23493
23493
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
@@ -23526,19 +23526,19 @@ var require_mock_utils = __commonJS({
23526
23526
  mockDispatches.splice(index, 1);
23527
23527
  }
23528
23528
  }
23529
- function removeTrailingSlash(path33) {
23530
- while (path33.endsWith("/")) {
23531
- path33 = path33.slice(0, -1);
23529
+ function removeTrailingSlash(path34) {
23530
+ while (path34.endsWith("/")) {
23531
+ path34 = path34.slice(0, -1);
23532
23532
  }
23533
- if (path33.length === 0) {
23534
- path33 = "/";
23533
+ if (path34.length === 0) {
23534
+ path34 = "/";
23535
23535
  }
23536
- return path33;
23536
+ return path34;
23537
23537
  }
23538
23538
  function buildKey(opts) {
23539
- const { path: path33, method, body, headers, query } = opts;
23539
+ const { path: path34, method, body, headers, query } = opts;
23540
23540
  return {
23541
- path: path33,
23541
+ path: path34,
23542
23542
  method,
23543
23543
  body,
23544
23544
  headers,
@@ -24228,10 +24228,10 @@ var require_pending_interceptors_formatter = __commonJS({
24228
24228
  }
24229
24229
  format(pendingInterceptors) {
24230
24230
  const withPrettyHeaders = pendingInterceptors.map(
24231
- ({ method, path: path33, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
24231
+ ({ method, path: path34, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
24232
24232
  Method: method,
24233
24233
  Origin: origin,
24234
- Path: path33,
24234
+ Path: path34,
24235
24235
  "Status code": statusCode,
24236
24236
  Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
24237
24237
  Invocations: timesInvoked,
@@ -24313,9 +24313,9 @@ var require_mock_agent = __commonJS({
24313
24313
  const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
24314
24314
  const dispatchOpts = { ...opts };
24315
24315
  if (acceptNonStandardSearchParameters && dispatchOpts.path) {
24316
- const [path33, searchParams] = dispatchOpts.path.split("?");
24316
+ const [path34, searchParams] = dispatchOpts.path.split("?");
24317
24317
  const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
24318
- dispatchOpts.path = `${path33}?${normalizedSearchParams}`;
24318
+ dispatchOpts.path = `${path34}?${normalizedSearchParams}`;
24319
24319
  }
24320
24320
  return this[kAgent].dispatch(dispatchOpts, handler);
24321
24321
  }
@@ -24716,12 +24716,12 @@ var require_snapshot_recorder = __commonJS({
24716
24716
  * @return {Promise<void>} - Resolves when snapshots are loaded
24717
24717
  */
24718
24718
  async loadSnapshots(filePath) {
24719
- const path33 = filePath || this.#snapshotPath;
24720
- if (!path33) {
24719
+ const path34 = filePath || this.#snapshotPath;
24720
+ if (!path34) {
24721
24721
  throw new InvalidArgumentError("Snapshot path is required");
24722
24722
  }
24723
24723
  try {
24724
- const data = await readFile3(resolve2(path33), "utf8");
24724
+ const data = await readFile3(resolve2(path34), "utf8");
24725
24725
  const parsed = JSON.parse(data);
24726
24726
  if (Array.isArray(parsed)) {
24727
24727
  this.#snapshots.clear();
@@ -24735,7 +24735,7 @@ var require_snapshot_recorder = __commonJS({
24735
24735
  if (error63.code === "ENOENT") {
24736
24736
  this.#snapshots.clear();
24737
24737
  } else {
24738
- throw new UndiciError(`Failed to load snapshots from ${path33}`, { cause: error63 });
24738
+ throw new UndiciError(`Failed to load snapshots from ${path34}`, { cause: error63 });
24739
24739
  }
24740
24740
  }
24741
24741
  }
@@ -24746,11 +24746,11 @@ var require_snapshot_recorder = __commonJS({
24746
24746
  * @returns {Promise<void>} - Resolves when snapshots are saved
24747
24747
  */
24748
24748
  async saveSnapshots(filePath) {
24749
- const path33 = filePath || this.#snapshotPath;
24750
- if (!path33) {
24749
+ const path34 = filePath || this.#snapshotPath;
24750
+ if (!path34) {
24751
24751
  throw new InvalidArgumentError("Snapshot path is required");
24752
24752
  }
24753
- const resolvedPath = resolve2(path33);
24753
+ const resolvedPath = resolve2(path34);
24754
24754
  await mkdir(dirname2(resolvedPath), { recursive: true });
24755
24755
  const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
24756
24756
  hash: hash2,
@@ -25382,15 +25382,15 @@ var require_redirect_handler = __commonJS({
25382
25382
  return;
25383
25383
  }
25384
25384
  const { origin, pathname, search } = util2.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
25385
- const path33 = search ? `${pathname}${search}` : pathname;
25386
- const redirectUrlString = `${origin}${path33}`;
25385
+ const path34 = search ? `${pathname}${search}` : pathname;
25386
+ const redirectUrlString = `${origin}${path34}`;
25387
25387
  for (const historyUrl of this.history) {
25388
25388
  if (historyUrl.toString() === redirectUrlString) {
25389
25389
  throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
25390
25390
  }
25391
25391
  }
25392
25392
  this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
25393
- this.opts.path = path33;
25393
+ this.opts.path = path34;
25394
25394
  this.opts.origin = origin;
25395
25395
  this.opts.query = null;
25396
25396
  }
@@ -27150,10 +27150,10 @@ var require_cache_handler = __commonJS({
27150
27150
  }
27151
27151
  return locationUrl.pathname + locationUrl.search;
27152
27152
  }
27153
- function deleteCachedUri(store, cacheKey, path33) {
27153
+ function deleteCachedUri(store, cacheKey, path34) {
27154
27154
  deleteCachedValue(store, {
27155
27155
  ...cacheKey,
27156
- path: path33
27156
+ path: path34
27157
27157
  });
27158
27158
  for (let i = 0; i < util2.safeHTTPMethods.length; i++) {
27159
27159
  const method = util2.safeHTTPMethods[i];
@@ -27161,7 +27161,7 @@ var require_cache_handler = __commonJS({
27161
27161
  deleteCachedValue(store, {
27162
27162
  ...cacheKey,
27163
27163
  method,
27164
- path: path33
27164
+ path: path34
27165
27165
  });
27166
27166
  }
27167
27167
  }
@@ -27172,9 +27172,9 @@ var require_cache_handler = __commonJS({
27172
27172
  }
27173
27173
  const values = Array.isArray(headerValue) ? headerValue : [headerValue];
27174
27174
  for (let i = 0; i < values.length; i++) {
27175
- const path33 = getSameOriginPath(cacheKey, values[i]);
27176
- if (path33 !== void 0) {
27177
- deleteCachedUri(store, cacheKey, path33);
27175
+ const path34 = getSameOriginPath(cacheKey, values[i]);
27176
+ if (path34 !== void 0) {
27177
+ deleteCachedUri(store, cacheKey, path34);
27178
27178
  }
27179
27179
  }
27180
27180
  }
@@ -32174,11 +32174,11 @@ var require_fetch = __commonJS({
32174
32174
  function dispatch({ body }) {
32175
32175
  const url2 = requestCurrentURL(request2);
32176
32176
  const agent = fetchParams.controller.dispatcher;
32177
- const path33 = url2.pathname + url2.search;
32177
+ const path34 = url2.pathname + url2.search;
32178
32178
  const hasTrailingQuestionMark = url2.search.length === 0 && url2.href[url2.href.length - url2.hash.length - 1] === "?";
32179
32179
  return new Promise((resolve2, reject) => agent.dispatch(
32180
32180
  {
32181
- path: hasTrailingQuestionMark ? `${path33}?` : path33,
32181
+ path: hasTrailingQuestionMark ? `${path34}?` : path34,
32182
32182
  origin: url2.origin,
32183
32183
  method: request2.method,
32184
32184
  body: agent.isMockActive ? request2.body && (request2.body.source || request2.body.stream) : body,
@@ -33125,9 +33125,9 @@ var require_util4 = __commonJS({
33125
33125
  }
33126
33126
  }
33127
33127
  }
33128
- function validateCookiePath(path33) {
33129
- for (let i = 0; i < path33.length; ++i) {
33130
- const code = path33.charCodeAt(i);
33128
+ function validateCookiePath(path34) {
33129
+ for (let i = 0; i < path34.length; ++i) {
33130
+ const code = path34.charCodeAt(i);
33131
33131
  if (code < 32 || // exclude CTLs (0-31)
33132
33132
  code > 126 || // exclude DEL and non-ascii
33133
33133
  code === 59) {
@@ -36475,11 +36475,11 @@ var require_undici = __commonJS({
36475
36475
  if (typeof opts.path !== "string") {
36476
36476
  throw new InvalidArgumentError("invalid opts.path");
36477
36477
  }
36478
- let path33 = opts.path;
36478
+ let path34 = opts.path;
36479
36479
  if (!opts.path.startsWith("/")) {
36480
- path33 = `/${path33}`;
36480
+ path34 = `/${path34}`;
36481
36481
  }
36482
- url2 = new URL(util2.parseOrigin(url2).origin + path33);
36482
+ url2 = new URL(util2.parseOrigin(url2).origin + path34);
36483
36483
  } else {
36484
36484
  if (!opts) {
36485
36485
  opts = typeof url2 === "object" ? url2 : {};
@@ -36588,6 +36588,15 @@ ${captureLines}` : capture.stack;
36588
36588
  }
36589
36589
  });
36590
36590
 
36591
+ // src/hookPreferences.ts
36592
+ import { mkdirSync as mkdirSync10, readFileSync as readFileSync11, renameSync as renameSync5, writeFileSync as writeFileSync9 } from "node:fs";
36593
+ import path21 from "node:path";
36594
+
36595
+ // ../../apps/syncservice/src/credentials.ts
36596
+ import { chmodSync as chmodSync4, existsSync as existsSync7, mkdirSync as mkdirSync9, readFileSync as readFileSync8, unlinkSync as unlinkSync3, writeFileSync as writeFileSync8 } from "node:fs";
36597
+ import os12 from "node:os";
36598
+ import path14 from "node:path";
36599
+
36591
36600
  // ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/external.js
36592
36601
  var external_exports = {};
36593
36602
  __export(external_exports, {
@@ -37404,10 +37413,10 @@ function mergeDefs(...defs) {
37404
37413
  function cloneDef(schema) {
37405
37414
  return mergeDefs(schema._zod.def);
37406
37415
  }
37407
- function getElementAtPath(obj, path33) {
37408
- if (!path33)
37416
+ function getElementAtPath(obj, path34) {
37417
+ if (!path34)
37409
37418
  return obj;
37410
- return path33.reduce((acc, key) => acc?.[key], obj);
37419
+ return path34.reduce((acc, key) => acc?.[key], obj);
37411
37420
  }
37412
37421
  function promiseAllObject(promisesObj) {
37413
37422
  const keys = Object.keys(promisesObj);
@@ -37747,11 +37756,11 @@ function explicitlyAborted(x, startIndex = 0) {
37747
37756
  }
37748
37757
  return false;
37749
37758
  }
37750
- function prefixIssues(path33, issues) {
37759
+ function prefixIssues(path34, issues) {
37751
37760
  return issues.map((iss) => {
37752
37761
  var _a4;
37753
37762
  (_a4 = iss).path ?? (_a4.path = []);
37754
- iss.path.unshift(path33);
37763
+ iss.path.unshift(path34);
37755
37764
  return iss;
37756
37765
  });
37757
37766
  }
@@ -38201,16 +38210,16 @@ function flattenError(error63, mapper = (issue2) => issue2.message) {
38201
38210
  }
38202
38211
  function formatError(error63, mapper = (issue2) => issue2.message) {
38203
38212
  const fieldErrors = { _errors: [] };
38204
- const processError = (error64, path33 = []) => {
38213
+ const processError = (error64, path34 = []) => {
38205
38214
  for (const issue2 of error64.issues) {
38206
38215
  if (issue2.code === "invalid_union" && issue2.errors.length) {
38207
- issue2.errors.map((issues) => processError({ issues }, [...path33, ...issue2.path]));
38216
+ issue2.errors.map((issues) => processError({ issues }, [...path34, ...issue2.path]));
38208
38217
  } else if (issue2.code === "invalid_key") {
38209
- processError({ issues: issue2.issues }, [...path33, ...issue2.path]);
38218
+ processError({ issues: issue2.issues }, [...path34, ...issue2.path]);
38210
38219
  } else if (issue2.code === "invalid_element") {
38211
- processError({ issues: issue2.issues }, [...path33, ...issue2.path]);
38220
+ processError({ issues: issue2.issues }, [...path34, ...issue2.path]);
38212
38221
  } else {
38213
- const fullpath = [...path33, ...issue2.path];
38222
+ const fullpath = [...path34, ...issue2.path];
38214
38223
  if (fullpath.length === 0) {
38215
38224
  fieldErrors._errors.push(mapper(issue2));
38216
38225
  } else {
@@ -38249,17 +38258,17 @@ function formatError(error63, mapper = (issue2) => issue2.message) {
38249
38258
  }
38250
38259
  function treeifyError(error63, mapper = (issue2) => issue2.message) {
38251
38260
  const result = { errors: [] };
38252
- const processError = (error64, path33 = []) => {
38261
+ const processError = (error64, path34 = []) => {
38253
38262
  var _a4;
38254
38263
  for (const issue2 of error64.issues) {
38255
38264
  if (issue2.code === "invalid_union" && issue2.errors.length) {
38256
- issue2.errors.map((issues) => processError({ issues }, [...path33, ...issue2.path]));
38265
+ issue2.errors.map((issues) => processError({ issues }, [...path34, ...issue2.path]));
38257
38266
  } else if (issue2.code === "invalid_key") {
38258
- processError({ issues: issue2.issues }, [...path33, ...issue2.path]);
38267
+ processError({ issues: issue2.issues }, [...path34, ...issue2.path]);
38259
38268
  } else if (issue2.code === "invalid_element") {
38260
- processError({ issues: issue2.issues }, [...path33, ...issue2.path]);
38269
+ processError({ issues: issue2.issues }, [...path34, ...issue2.path]);
38261
38270
  } else {
38262
- const fullpath = [...path33, ...issue2.path];
38271
+ const fullpath = [...path34, ...issue2.path];
38263
38272
  if (fullpath.length === 0) {
38264
38273
  result.errors.push(mapper(issue2));
38265
38274
  continue;
@@ -38298,8 +38307,8 @@ function treeifyError(error63, mapper = (issue2) => issue2.message) {
38298
38307
  }
38299
38308
  function toDotPath(_path) {
38300
38309
  const segs = [];
38301
- const path33 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
38302
- for (const seg of path33) {
38310
+ const path34 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
38311
+ for (const seg of path34) {
38303
38312
  if (typeof seg === "number")
38304
38313
  segs.push(`[${seg}]`);
38305
38314
  else if (typeof seg === "symbol")
@@ -55401,13 +55410,13 @@ function resolveRef(ref, ctx) {
55401
55410
  if (!ref.startsWith("#")) {
55402
55411
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
55403
55412
  }
55404
- const path33 = ref.slice(1).split("/").filter(Boolean);
55405
- if (path33.length === 0) {
55413
+ const path34 = ref.slice(1).split("/").filter(Boolean);
55414
+ if (path34.length === 0) {
55406
55415
  return ctx.rootSchema;
55407
55416
  }
55408
55417
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
55409
- if (path33[0] === defsKey) {
55410
- const key = path33[1] === void 0 ? void 0 : decodeJSONPointerSegment(path33[1]);
55418
+ if (path34[0] === defsKey) {
55419
+ const key = path34[1] === void 0 ? void 0 : decodeJSONPointerSegment(path34[1]);
55411
55420
  if (!key || !ctx.defs[key]) {
55412
55421
  throw new Error(`Reference not found: ${ref}`);
55413
55422
  }
@@ -56264,8 +56273,42 @@ var mcpWarningDismissalSchema = external_exports.object({
56264
56273
  warning: mcpWarningSchema
56265
56274
  }).strict();
56266
56275
 
56276
+ // ../core/src/harnesses.ts
56277
+ var HARNESSES = [
56278
+ "claude-local",
56279
+ "claude-cloud",
56280
+ "codex-local",
56281
+ "codex-cloud",
56282
+ "cursor-local",
56283
+ "cursor-cloud"
56284
+ ];
56285
+ var harnessSchema = external_exports.enum(HARNESSES);
56286
+ var SESSION_SOURCE_HARNESSES = {
56287
+ "claude-code": "claude-local",
56288
+ "claude-cloud": "claude-cloud",
56289
+ codex: "codex-local",
56290
+ cursor: "cursor-local",
56291
+ "cursor-cloud": "cursor-cloud"
56292
+ };
56293
+ function harnessFromLegacySessionSource(source) {
56294
+ if (source === "github-pr") return { kind: "not-harness", source };
56295
+ return { kind: "harness", harness: SESSION_SOURCE_HARNESSES[source] };
56296
+ }
56297
+ var LEGACY_SESSION_SOURCE_BY_HARNESS = {
56298
+ "claude-local": "claude-code",
56299
+ "claude-cloud": "claude-cloud",
56300
+ "codex-local": "codex",
56301
+ "codex-cloud": null,
56302
+ "cursor-local": "cursor",
56303
+ "cursor-cloud": "cursor-cloud"
56304
+ };
56305
+ function legacySessionSourceFromHarness(harness) {
56306
+ const source = LEGACY_SESSION_SOURCE_BY_HARNESS[harness];
56307
+ return source === null ? { kind: "unsupported", harness } : { kind: "supported", source };
56308
+ }
56309
+
56267
56310
  // ../core/src/sessionIngest.ts
56268
- var SESSION_SOURCES = [
56311
+ var LEGACY_SESSION_SOURCES = [
56269
56312
  "claude-code",
56270
56313
  "claude-cloud",
56271
56314
  "codex",
@@ -56275,13 +56318,22 @@ var SESSION_SOURCES = [
56275
56318
  ];
56276
56319
  var SESSION_SPEED_MODES = ["standard", "fast"];
56277
56320
  var SESSION_SPEED_OBSERVATIONS = [...SESSION_SPEED_MODES, "unknown"];
56278
- function isSessionSource(source) {
56279
- return typeof source === "string" && SESSION_SOURCES.includes(source);
56321
+ function isLegacySessionSource(source) {
56322
+ return typeof source === "string" && LEGACY_SESSION_SOURCES.includes(source);
56280
56323
  }
56281
56324
  var SESSION_ACTIVE_WINDOW_MS = 30 * 60 * 1e3;
56282
- var COLLECTOR_SESSION_SOURCES = ["claude-code", "codex", "cursor"];
56283
- var PREVIEW_REGISTRABLE_SOURCES = [
56284
- ...COLLECTOR_SESSION_SOURCES,
56325
+ var LEGACY_COLLECTOR_SESSION_SOURCES = ["claude-code", "codex", "cursor"];
56326
+ var LEGACY_PREVIEW_REGISTRABLE_SOURCES = [
56327
+ ...LEGACY_COLLECTOR_SESSION_SOURCES,
56328
+ "cursor-cloud"
56329
+ ];
56330
+ var COLLECTOR_SESSION_HARNESSES = [
56331
+ "claude-local",
56332
+ "codex-local",
56333
+ "cursor-local"
56334
+ ];
56335
+ var PREVIEW_REGISTRABLE_HARNESSES = [
56336
+ ...COLLECTOR_SESSION_HARNESSES,
56285
56337
  "cursor-cloud"
56286
56338
  ];
56287
56339
  var MAX_INGEST_BATCH = 500;
@@ -56295,7 +56347,7 @@ var MAX_BRANCH_FACTS = 50;
56295
56347
  var MENUBAR_AGENT_CLICK = "menubar:agent_click";
56296
56348
  var MENUBAR_MCP_WARNING_REMOVE = "menubar:mcp_warning_remove";
56297
56349
  var menubarAgentClickSchema = external_exports.object({
56298
- source: external_exports.enum([...SESSION_SOURCES, "unknown"]),
56350
+ source: external_exports.enum([...LEGACY_SESSION_SOURCES, "unknown"]),
56299
56351
  destination: external_exports.enum(["focus", "resume", "desktop", "web"])
56300
56352
  }).strict();
56301
56353
  var menubarEventSchema = external_exports.discriminatedUnion("event", [
@@ -56312,7 +56364,7 @@ function claudeCodeMessageOrigin(facts, text) {
56312
56364
  if (facts.nativeOrigin !== null && CLAUDE_CODE_NATIVE_ORIGINS.has(facts.nativeOrigin)) {
56313
56365
  origin = facts.nativeOrigin;
56314
56366
  }
56315
- if (facts.nativeOrigin === CLAUDE_CODE_TASK_NOTIFICATION_ORIGIN || facts.isMeta === true || facts.isCompactSummary === true || facts.model === "<synthetic>") {
56367
+ if (facts.nativeOrigin === CLAUDE_CODE_TASK_NOTIFICATION_ORIGIN || facts.commandMode === CLAUDE_CODE_TASK_NOTIFICATION_ORIGIN || facts.isMeta === true || facts.isCompactSummary === true || facts.model === "<synthetic>") {
56316
56368
  origin = "harness";
56317
56369
  }
56318
56370
  return origin === "human" && SYSTEM_REMINDER.test(text) ? "mixed" : origin;
@@ -56764,16 +56816,16 @@ function githubRepositoryOfRemote(url2) {
56764
56816
  const afterUser = url2.replace(REMOTE_SCHEME, "").replace(REMOTE_USER, "");
56765
56817
  const host = afterUser.startsWith("ssh.") ? afterUser.slice("ssh.".length) : afterUser;
56766
56818
  if (!host.startsWith("github.com")) return null;
56767
- let path33 = host.slice("github.com".length);
56768
- const port = hasScheme ? REMOTE_PORT.exec(path33) : null;
56769
- if (port !== null) path33 = path33.slice(port[0].length);
56770
- else if (path33.startsWith("/") || path33.startsWith(":")) path33 = path33.slice(1);
56819
+ let path34 = host.slice("github.com".length);
56820
+ const port = hasScheme ? REMOTE_PORT.exec(path34) : null;
56821
+ if (port !== null) path34 = path34.slice(port[0].length);
56822
+ else if (path34.startsWith("/") || path34.startsWith(":")) path34 = path34.slice(1);
56771
56823
  else return null;
56772
- if (path33.endsWith("/")) path33 = path33.slice(0, -1);
56773
- if (path33.endsWith(".git")) path33 = path33.slice(0, -".git".length);
56774
- const segments = path33.split("/");
56824
+ if (path34.endsWith("/")) path34 = path34.slice(0, -1);
56825
+ if (path34.endsWith(".git")) path34 = path34.slice(0, -".git".length);
56826
+ const segments = path34.split("/");
56775
56827
  if (segments.length !== 2 || !segments.every((segment) => REMOTE_PATH_SEGMENT.test(segment))) return null;
56776
- return path33;
56828
+ return path34;
56777
56829
  }
56778
56830
  var PUSH_DESTINATION = /\bTo\s+([^\s\\"]+)/g;
56779
56831
  function pushDestinationsInText(text) {
@@ -57433,7 +57485,8 @@ function originFacts(record2) {
57433
57485
  nativeOrigin: typeof origin?.kind === "string" ? origin.kind : null,
57434
57486
  isMeta: typeof record2.isMeta === "boolean" ? record2.isMeta : null,
57435
57487
  isCompactSummary: typeof record2.isCompactSummary === "boolean" ? record2.isCompactSummary : null,
57436
- model: typeof message2?.model === "string" ? message2.model : null
57488
+ model: typeof message2?.model === "string" ? message2.model : null,
57489
+ commandMode: null
57437
57490
  };
57438
57491
  }
57439
57492
  function recordTime(record2) {
@@ -57708,10 +57761,10 @@ function boundUnfamiliarPayload(record2) {
57708
57761
  }
57709
57762
  function excludeImageCarriers(record2) {
57710
57763
  const excludedKeys = [];
57711
- const withoutImages = (value, path33) => {
57764
+ const withoutImages = (value, path34) => {
57712
57765
  if (Array.isArray(value)) {
57713
57766
  return value.map((item, index) => {
57714
- const itemPath = `${path33}[${index}]`;
57767
+ const itemPath = `${path34}[${index}]`;
57715
57768
  if (typeof item === "string" && isImageCarrier(item)) {
57716
57769
  excludedKeys.push(itemPath);
57717
57770
  return null;
@@ -57722,7 +57775,7 @@ function excludeImageCarriers(record2) {
57722
57775
  if (!isRecord2(value)) return value;
57723
57776
  const kept = [];
57724
57777
  for (const [key, item] of Object.entries(value)) {
57725
- const keyPath = path33 === "" ? key : `${path33}.${key}`;
57778
+ const keyPath = path34 === "" ? key : `${path34}.${key}`;
57726
57779
  if (isImageBase64Payload(value, key) || typeof item === "string" && isImageCarrier(item)) {
57727
57780
  excludedKeys.push(keyPath);
57728
57781
  continue;
@@ -58443,8 +58496,8 @@ function primaryArg(args) {
58443
58496
  function readFilePath(name, primary) {
58444
58497
  if (!primary || !READ_TOOLS.has(name)) return null;
58445
58498
  if (ARTIFACT_PATH_RE.test(primary)) return null;
58446
- const path33 = primary.startsWith("/workspace/") ? primary.slice("/workspace/".length) : primary;
58447
- return path33.length > 0 ? path33 : null;
58499
+ const path34 = primary.startsWith("/workspace/") ? primary.slice("/workspace/".length) : primary;
58500
+ return path34.length > 0 ? path34 : null;
58448
58501
  }
58449
58502
  function asRecord3(value) {
58450
58503
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -58849,14 +58902,18 @@ var recentSessionCursorSchema = external_exports.object({
58849
58902
  id: external_exports.uuid()
58850
58903
  });
58851
58904
 
58852
- // src/mcpPreferences.ts
58853
- import { mkdirSync as mkdirSync10, readFileSync as readFileSync11, renameSync as renameSync5, writeFileSync as writeFileSync9 } from "node:fs";
58854
- import path21 from "node:path";
58855
-
58856
- // ../../apps/collector/src/credentials.ts
58857
- import { chmodSync as chmodSync4, existsSync as existsSync7, mkdirSync as mkdirSync9, readFileSync as readFileSync8, unlinkSync as unlinkSync3, writeFileSync as writeFileSync8 } from "node:fs";
58858
- import os12 from "node:os";
58859
- import path14 from "node:path";
58905
+ // ../core/src/codexClient.ts
58906
+ var codexClientSchema = external_exports.enum(["desktop", "tui", "unknown"]);
58907
+ var metadataSchema = external_exports.object({ originator: external_exports.unknown().optional(), source: external_exports.unknown().optional() });
58908
+ function classifyCodexClient(metadata) {
58909
+ const parsed = metadataSchema.safeParse(metadata);
58910
+ if (!parsed.success) return "unknown";
58911
+ const { originator, source } = parsed.data;
58912
+ if (source === "exec" || typeof source === "object" && source !== null) return "unknown";
58913
+ if (originator === "Codex Desktop") return "desktop";
58914
+ if (source === "cli") return "tui";
58915
+ return "unknown";
58916
+ }
58860
58917
 
58861
58918
  // ../../node_modules/.pnpm/@sentry+core@10.74.0/node_modules/@sentry/core/build/esm/debug-build.js
58862
58919
  var DEBUG_BUILD = typeof __SENTRY_DEBUG__ === "undefined" || __SENTRY_DEBUG__;
@@ -59038,8 +59095,8 @@ function getFunctionName(fn) {
59038
59095
  return defaultFunctionName;
59039
59096
  }
59040
59097
  }
59041
- function normalizeStackTracePath(path33) {
59042
- let filename = path33?.startsWith("file://") ? path33.slice(7) : path33;
59098
+ function normalizeStackTracePath(path34) {
59099
+ let filename = path34?.startsWith("file://") ? path34.slice(7) : path34;
59043
59100
  if (filename?.match(/\/[A-Z]:/)) {
59044
59101
  filename = filename.slice(1);
59045
59102
  }
@@ -60849,8 +60906,8 @@ function isValidProtocol(protocol) {
60849
60906
  return protocol === "http" || protocol === "https";
60850
60907
  }
60851
60908
  function dsnToString(dsn, withPassword = false) {
60852
- const { host, path: path33, pass, port, projectId, protocol, publicKey } = dsn;
60853
- return `${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ""}@${host}${port ? `:${port}` : ""}/${path33 ? `${path33}/` : path33}${projectId}`;
60909
+ const { host, path: path34, pass, port, projectId, protocol, publicKey } = dsn;
60910
+ return `${protocol}://${publicKey}${withPassword && pass ? `:${pass}` : ""}@${host}${port ? `:${port}` : ""}/${path34 ? `${path34}/` : path34}${projectId}`;
60854
60911
  }
60855
60912
  function dsnFromString(str) {
60856
60913
  const match = DSN_REGEX.exec(str);
@@ -60861,11 +60918,11 @@ function dsnFromString(str) {
60861
60918
  return void 0;
60862
60919
  }
60863
60920
  const [protocol, publicKey, pass = "", host = "", port = "", lastPath = ""] = match.slice(1);
60864
- let path33 = "";
60921
+ let path34 = "";
60865
60922
  let projectId = lastPath;
60866
60923
  const split = projectId.split("/");
60867
60924
  if (split.length > 1) {
60868
- path33 = split.slice(0, -1).join("/");
60925
+ path34 = split.slice(0, -1).join("/");
60869
60926
  projectId = split.pop();
60870
60927
  }
60871
60928
  if (projectId) {
@@ -60874,7 +60931,7 @@ function dsnFromString(str) {
60874
60931
  projectId = projectMatch[0];
60875
60932
  }
60876
60933
  }
60877
- return dsnFromComponents({ host, pass, path: path33, projectId, port, protocol, publicKey });
60934
+ return dsnFromComponents({ host, pass, path: path34, projectId, port, protocol, publicKey });
60878
60935
  }
60879
60936
  function dsnFromComponents(components) {
60880
60937
  return {
@@ -65403,9 +65460,9 @@ function stripUrlQueryAndFragment(urlPath) {
65403
65460
  return urlPath.split(/[?#]/, 1)[0];
65404
65461
  }
65405
65462
  function getSanitizedUrlString(url2) {
65406
- const { protocol, host, path: path33 } = url2;
65463
+ const { protocol, host, path: path34 } = url2;
65407
65464
  const filteredHost = host?.replace(/^.*@/, "[filtered]:[filtered]@").replace(/(:80)$/, "").replace(/(:443)$/, "") || "";
65408
- return `${protocol ? `${protocol}://` : ""}${filteredHost}${path33}`;
65465
+ return `${protocol ? `${protocol}://` : ""}${filteredHost}${path34}`;
65409
65466
  }
65410
65467
  function stripDataUrlContent(url2, includeDataPrefix = true) {
65411
65468
  if (url2.startsWith("data:")) {
@@ -66350,8 +66407,8 @@ function splitPath(filename) {
66350
66407
  const parts = splitPathRe.exec(truncated);
66351
66408
  return parts ? parts.slice(1) : [];
66352
66409
  }
66353
- function dirname(path33) {
66354
- const result = splitPath(path33);
66410
+ function dirname(path34) {
66411
+ const result = splitPath(path34);
66355
66412
  const root = result[0] || "";
66356
66413
  let dir = result[1];
66357
66414
  if (!root && !dir) {
@@ -70194,15 +70251,15 @@ var getLayerMetadata = (route, layer, layerPath) => {
70194
70251
  };
70195
70252
  }
70196
70253
  };
70197
- var getRouterPath = (path33, layer) => {
70254
+ var getRouterPath = (path34, layer) => {
70198
70255
  const stackLayer = Array.isArray(layer.handle?.stack) ? layer.handle?.stack?.[0] : void 0;
70199
70256
  if (stackLayer?.route?.path) {
70200
- return `${path33}${stackLayer.route.path}`;
70257
+ return `${path34}${stackLayer.route.path}`;
70201
70258
  }
70202
70259
  if (stackLayer && Array.isArray(stackLayer?.handle?.stack)) {
70203
- return getRouterPath(path33, stackLayer);
70260
+ return getRouterPath(path34, stackLayer);
70204
70261
  }
70205
- return path33;
70262
+ return path34;
70206
70263
  };
70207
70264
  var isLayerIgnored = (name, type, config2) => {
70208
70265
  if (Array.isArray(config2?.ignoreLayersType) && config2?.ignoreLayersType?.includes(type)) {
@@ -70222,7 +70279,7 @@ function getActualMatchedRoute(req, constructedRoute) {
70222
70279
  if (layersStore.length === 0) {
70223
70280
  return void 0;
70224
70281
  }
70225
- if (layersStore.every((path33) => path33 === "/")) {
70282
+ if (layersStore.every((path34) => path34 === "/")) {
70226
70283
  return req.originalUrl === "/" ? "/" : void 0;
70227
70284
  }
70228
70285
  if (constructedRoute === "*") {
@@ -70238,11 +70295,11 @@ function getActualMatchedRoute(req, constructedRoute) {
70238
70295
  function getConstructedRoute(req) {
70239
70296
  const layersStore = getStoredLayers(req);
70240
70297
  let constructedRoute = "";
70241
- for (const path33 of layersStore) {
70242
- if (path33 === "/" || path33 === "/*") {
70298
+ for (const path34 of layersStore) {
70299
+ if (path34 === "/" || path34 === "/*") {
70243
70300
  continue;
70244
70301
  }
70245
- constructedRoute += !constructedRoute || constructedRoute.endsWith("/") ? path33 : `/${path33}`;
70302
+ constructedRoute += !constructedRoute || constructedRoute.endsWith("/") ? path34 : `/${path34}`;
70246
70303
  }
70247
70304
  return constructedRoute.replace(/\/{2,}/g, "/");
70248
70305
  }
@@ -70747,9 +70804,9 @@ function getRequestUrlObject(requestOptions) {
70747
70804
  const hostHeader = requestOptions.headers?.host && String(requestOptions.headers?.host);
70748
70805
  const hostname4 = hostHeader || requestOptions.hostname || requestOptions.host || "";
70749
70806
  const port = !requestOptions.port || requestOptions.port === 80 || requestOptions.port === 443 || /^(.*):(\d+)$/.test(hostname4) ? "" : `:${requestOptions.port}`;
70750
- const path33 = requestOptions.path ? requestOptions.path : "/";
70807
+ const path34 = requestOptions.path ? requestOptions.path : "/";
70751
70808
  const base = `${protocol}//${hostname4}${port}`;
70752
- return new URL(path33.startsWith("//") ? `${base}${path33}` : path33, base);
70809
+ return new URL(path34.startsWith("//") ? `${base}${path34}` : path34, base);
70753
70810
  }
70754
70811
  function getRequestUrlFromClientRequest(request2) {
70755
70812
  return String(getRequestUrl(getRequestOptions(request2)));
@@ -71422,11 +71479,11 @@ function shouldIgnoreSpansForIncomingRequest(request2, {
71422
71479
  return false;
71423
71480
  }
71424
71481
  function isStaticAssetRequest(urlPath) {
71425
- const path33 = stripUrlQueryAndFragment(urlPath);
71426
- if (path33.match(/\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {
71482
+ const path34 = stripUrlQueryAndFragment(urlPath);
71483
+ if (path34.match(/\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {
71427
71484
  return true;
71428
71485
  }
71429
- if (path33.match(/^\/(robots\.txt|sitemap\.xml|manifest\.json|browserconfig\.xml)$/)) {
71486
+ if (path34.match(/^\/(robots\.txt|sitemap\.xml|manifest\.json|browserconfig\.xml)$/)) {
71430
71487
  return true;
71431
71488
  }
71432
71489
  return false;
@@ -71667,11 +71724,11 @@ function isKnownPrefetchRequest2(req) {
71667
71724
  return req.headers["next-router-prefetch"] === "1";
71668
71725
  }
71669
71726
  function isStaticAssetRequest2(urlPath) {
71670
- const path33 = stripUrlQueryAndFragment(urlPath);
71671
- if (path33.match(/\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {
71727
+ const path34 = stripUrlQueryAndFragment(urlPath);
71728
+ if (path34.match(/\.(ico|png|jpg|jpeg|gif|svg|css|js|woff|woff2|ttf|eot|webp|avif)$/)) {
71672
71729
  return true;
71673
71730
  }
71674
- if (path33.match(/^\/(robots\.txt|sitemap\.xml|manifest\.json|browserconfig\.xml)$/)) {
71731
+ if (path34.match(/^\/(robots\.txt|sitemap\.xml|manifest\.json|browserconfig\.xml)$/)) {
71675
71732
  return true;
71676
71733
  }
71677
71734
  return false;
@@ -72031,19 +72088,19 @@ function getBreadcrumbData(request2) {
72031
72088
  return {};
72032
72089
  }
72033
72090
  }
72034
- function getAbsoluteUrl2(origin, path33 = "/") {
72091
+ function getAbsoluteUrl2(origin, path34 = "/") {
72035
72092
  try {
72036
- const url2 = new URL(path33, origin);
72093
+ const url2 = new URL(path34, origin);
72037
72094
  return url2.toString();
72038
72095
  } catch {
72039
72096
  const url2 = `${origin}`;
72040
- if (url2.endsWith("/") && path33.startsWith("/")) {
72041
- return `${url2}${path33.slice(1)}`;
72097
+ if (url2.endsWith("/") && path34.startsWith("/")) {
72098
+ return `${url2}${path34.slice(1)}`;
72042
72099
  }
72043
- if (!url2.endsWith("/") && !path33.startsWith("/")) {
72044
- return `${url2}/${path33}`;
72100
+ if (!url2.endsWith("/") && !path34.startsWith("/")) {
72101
+ return `${url2}/${path34}`;
72045
72102
  }
72046
- return `${url2}${path33}`;
72103
+ return `${url2}${path34}`;
72047
72104
  }
72048
72105
  }
72049
72106
 
@@ -72288,15 +72345,15 @@ function getRequestMethod(original) {
72288
72345
  }
72289
72346
  return "_OTHER";
72290
72347
  }
72291
- function getAbsoluteUrl3(origin, path33 = "/") {
72348
+ function getAbsoluteUrl3(origin, path34 = "/") {
72292
72349
  const url2 = `${origin}`;
72293
- if (url2.endsWith("/") && path33.startsWith("/")) {
72294
- return `${url2}${path33.slice(1)}`;
72350
+ if (url2.endsWith("/") && path34.startsWith("/")) {
72351
+ return `${url2}${path34.slice(1)}`;
72295
72352
  }
72296
- if (!url2.endsWith("/") && !path33.startsWith("/")) {
72297
- return `${url2}/${path33}`;
72353
+ if (!url2.endsWith("/") && !path34.startsWith("/")) {
72354
+ return `${url2}/${path34}`;
72298
72355
  }
72299
- return `${url2}${path33}`;
72356
+ return `${url2}${path34}`;
72300
72357
  }
72301
72358
 
72302
72359
  // ../../node_modules/.pnpm/@sentry+node-core@10.74.0_@opentelemetry+api@1.9.1_@opentelemetry+core@2.11.0_@opentele_b542b1cf9336850aabd631474d797bed/node_modules/@sentry/node-core/build/esm/integrations/node-fetch/index.js
@@ -74789,12 +74846,12 @@ function emplace(map2, key, contents) {
74789
74846
  }
74790
74847
  return value;
74791
74848
  }
74792
- function shouldSkipContextLinesForFile(path33) {
74793
- if (path33.startsWith("node:")) return true;
74794
- if (path33.endsWith(".min.js")) return true;
74795
- if (path33.endsWith(".min.cjs")) return true;
74796
- if (path33.endsWith(".min.mjs")) return true;
74797
- if (path33.startsWith("data:")) return true;
74849
+ function shouldSkipContextLinesForFile(path34) {
74850
+ if (path34.startsWith("node:")) return true;
74851
+ if (path34.endsWith(".min.js")) return true;
74852
+ if (path34.endsWith(".min.cjs")) return true;
74853
+ if (path34.endsWith(".min.mjs")) return true;
74854
+ if (path34.startsWith("data:")) return true;
74798
74855
  return false;
74799
74856
  }
74800
74857
  function shouldSkipContextLinesForFrame(frame) {
@@ -74842,9 +74899,9 @@ function makeLineReaderRanges(lines, linecontext) {
74842
74899
  }
74843
74900
  return out;
74844
74901
  }
74845
- function getContextLinesFromFile(path33, ranges, output2) {
74902
+ function getContextLinesFromFile(path34, ranges, output2) {
74846
74903
  return new Promise((resolve2, _reject) => {
74847
- const stream = createReadStream(path33);
74904
+ const stream = createReadStream(path34);
74848
74905
  const lineReaded = createInterface({
74849
74906
  input: stream
74850
74907
  });
@@ -74862,8 +74919,8 @@ function getContextLinesFromFile(path33, ranges, output2) {
74862
74919
  let rangeStart = range[0];
74863
74920
  let rangeEnd = range[1];
74864
74921
  function onStreamError(e) {
74865
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path33, 1);
74866
- DEBUG_BUILD2 && debug.error(`Failed to read file: ${path33}. Error: ${e}`);
74922
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path34, 1);
74923
+ DEBUG_BUILD2 && debug.error(`Failed to read file: ${path34}. Error: ${e}`);
74867
74924
  lineReaded.close();
74868
74925
  lineReaded.removeAllListeners();
74869
74926
  destroyStreamAndResolve();
@@ -76302,8 +76359,8 @@ function getSpotlightConfig(optionsSpotlight) {
76302
76359
 
76303
76360
  // ../../node_modules/.pnpm/@sentry+node-core@10.74.0_@opentelemetry+api@1.9.1_@opentelemetry+core@2.11.0_@opentele_b542b1cf9336850aabd631474d797bed/node_modules/@sentry/node-core/build/esm/utils/module.js
76304
76361
  import { posix, sep } from "node:path";
76305
- function normalizeWindowsPath(path33) {
76306
- return path33.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
76362
+ function normalizeWindowsPath(path34) {
76363
+ return path34.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
76307
76364
  }
76308
76365
  function createGetModuleFromFilename(basePath = process.argv[1] ? dirname(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
76309
76366
  const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
@@ -79188,22 +79245,22 @@ function addSpanSource(span, loc, start, end) {
79188
79245
  span.setAttribute(AttributeNames2.SOURCE, source);
79189
79246
  }
79190
79247
  }
79191
- function createFieldIfNotExists(contextValue, info, path33) {
79192
- let field = getField(contextValue, path33);
79248
+ function createFieldIfNotExists(contextValue, info, path34) {
79249
+ let field = getField(contextValue, path34);
79193
79250
  if (field) {
79194
79251
  return { field, spanAdded: false };
79195
79252
  }
79196
- const parentSpan = getParentFieldSpan(contextValue, path33);
79253
+ const parentSpan = getParentFieldSpan(contextValue, path34);
79197
79254
  field = {
79198
- span: createResolverSpan(contextValue, info, path33, parentSpan)
79255
+ span: createResolverSpan(contextValue, info, path34, parentSpan)
79199
79256
  };
79200
- addField(contextValue, path33, field);
79257
+ addField(contextValue, path34, field);
79201
79258
  return { field, spanAdded: true };
79202
79259
  }
79203
- function createResolverSpan(contextValue, info, path33, parentSpan) {
79260
+ function createResolverSpan(contextValue, info, path34, parentSpan) {
79204
79261
  const attributes = {
79205
79262
  [AttributeNames2.FIELD_NAME]: info.fieldName,
79206
- [AttributeNames2.FIELD_PATH]: path33.join("."),
79263
+ [AttributeNames2.FIELD_PATH]: path34.join("."),
79207
79264
  [AttributeNames2.FIELD_TYPE]: info.returnType.toString(),
79208
79265
  [AttributeNames2.PARENT_NAME]: info.parentType.name
79209
79266
  };
@@ -79235,15 +79292,15 @@ function getOperation(document2, operationName) {
79235
79292
  return document2.definitions.find((definition) => OPERATION_VALUES.indexOf(definition?.operation) !== -1);
79236
79293
  }
79237
79294
  }
79238
- function addField(contextValue, path33, field) {
79239
- return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].fields[path33.join(".")] = field;
79295
+ function addField(contextValue, path34, field) {
79296
+ return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].fields[path34.join(".")] = field;
79240
79297
  }
79241
- function getField(contextValue, path33) {
79242
- return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].fields[path33.join(".")];
79298
+ function getField(contextValue, path34) {
79299
+ return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].fields[path34.join(".")];
79243
79300
  }
79244
- function getParentFieldSpan(contextValue, path33) {
79245
- for (let i = path33.length - 1; i > 0; i--) {
79246
- const field = getField(contextValue, path33.slice(0, i));
79301
+ function getParentFieldSpan(contextValue, path34) {
79302
+ for (let i = path34.length - 1; i > 0; i--) {
79303
+ const field = getField(contextValue, path34.slice(0, i));
79247
79304
  if (field) {
79248
79305
  return field.span;
79249
79306
  }
@@ -79253,9 +79310,9 @@ function getParentFieldSpan(contextValue, path33) {
79253
79310
  function getRootSpan2(contextValue) {
79254
79311
  return contextValue[OTEL_GRAPHQL_DATA_SYMBOL].span;
79255
79312
  }
79256
- function pathToArray(path33) {
79313
+ function pathToArray(path34) {
79257
79314
  const flattened = [];
79258
- let curr = path33;
79315
+ let curr = path34;
79259
79316
  while (curr) {
79260
79317
  flattened.push(String(curr.key));
79261
79318
  curr = curr.prev;
@@ -79396,8 +79453,8 @@ function wrapFieldResolver(getConfig3, fieldResolver, isDefaultResolver = false)
79396
79453
  if (!contextValue[OTEL_GRAPHQL_DATA_SYMBOL]) {
79397
79454
  return fieldResolver.call(this, source, args, contextValue, info);
79398
79455
  }
79399
- const path33 = pathToArray(info?.path);
79400
- const { field, spanAdded } = createFieldIfNotExists(contextValue, info, path33);
79456
+ const path34 = pathToArray(info?.path);
79457
+ const { field, spanAdded } = createFieldIfNotExists(contextValue, info, path34);
79401
79458
  const span = field.span;
79402
79459
  const shouldEndSpan = spanAdded;
79403
79460
  return withActiveSpan(span, () => {
@@ -82380,10 +82437,10 @@ var PostgresJsInstrumentation = class extends import_instrumentation24.Instrumen
82380
82437
  },
82381
82438
  (exports) => exports
82382
82439
  );
82383
- ["src", "cf/src", "cjs/src"].forEach((path33) => {
82440
+ ["src", "cf/src", "cjs/src"].forEach((path34) => {
82384
82441
  module2.files.push(
82385
82442
  new InstrumentationNodeModuleFile(
82386
- `postgres/${path33}/query.js`,
82443
+ `postgres/${path34}/query.js`,
82387
82444
  SUPPORTED_VERSIONS4,
82388
82445
  this._patchQueryPrototype.bind(this),
82389
82446
  this._unpatchQueryPrototype.bind(this)
@@ -83014,13 +83071,13 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
83014
83071
  return function(original) {
83015
83072
  return function wrappedHandler(...args) {
83016
83073
  if (typeof args[0] === "string") {
83017
- const path33 = args[0];
83074
+ const path34 = args[0];
83018
83075
  if (args.length === 1) {
83019
- return original.apply(this, [path33]);
83076
+ return original.apply(this, [path34]);
83020
83077
  }
83021
83078
  const handlers2 = args.slice(1);
83022
83079
  return original.apply(this, [
83023
- path33,
83080
+ path34,
83024
83081
  ...handlers2.map((handler) => instrumentation._wrapHandler(handler))
83025
83082
  ]);
83026
83083
  }
@@ -83054,13 +83111,13 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
83054
83111
  return function(original) {
83055
83112
  return function wrappedHandler(...args) {
83056
83113
  if (typeof args[0] === "string") {
83057
- const path33 = args[0];
83114
+ const path34 = args[0];
83058
83115
  if (args.length === 1) {
83059
- return original.apply(this, [path33]);
83116
+ return original.apply(this, [path34]);
83060
83117
  }
83061
83118
  const handlers2 = args.slice(1);
83062
83119
  return original.apply(this, [
83063
- path33,
83120
+ path34,
83064
83121
  ...handlers2.map((handler) => instrumentation._wrapHandler(handler))
83065
83122
  ]);
83066
83123
  }
@@ -83080,8 +83137,8 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
83080
83137
  if (!instrumentation.isEnabled()) {
83081
83138
  return handler.apply(this, [c, next]);
83082
83139
  }
83083
- const path33 = c.req.path;
83084
- const span = instrumentation.tracer.startSpan(path33);
83140
+ const path34 = c.req.path;
83141
+ const span = instrumentation.tracer.startSpan(path34);
83085
83142
  return context.with(trace.setSpan(context.active(), span), () => {
83086
83143
  return instrumentation._safeExecute(
83087
83144
  () => {
@@ -83091,7 +83148,7 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
83091
83148
  const type = instrumentation._determineHandlerType(result2);
83092
83149
  span.setAttributes({
83093
83150
  [AttributeNames5.HONO_TYPE]: type,
83094
- [AttributeNames5.HONO_NAME]: type === HonoTypes.REQUEST_HANDLER ? path33 : handler.name || "anonymous"
83151
+ [AttributeNames5.HONO_NAME]: type === HonoTypes.REQUEST_HANDLER ? path34 : handler.name || "anonymous"
83095
83152
  });
83096
83153
  instrumentation.getConfig().responseHook?.(span);
83097
83154
  return result2;
@@ -83100,7 +83157,7 @@ var HonoInstrumentation = class extends import_instrumentation27.Instrumentation
83100
83157
  const type = instrumentation._determineHandlerType(result);
83101
83158
  span.setAttributes({
83102
83159
  [AttributeNames5.HONO_TYPE]: type,
83103
- [AttributeNames5.HONO_NAME]: type === HonoTypes.REQUEST_HANDLER ? path33 : handler.name || "anonymous"
83160
+ [AttributeNames5.HONO_NAME]: type === HonoTypes.REQUEST_HANDLER ? path34 : handler.name || "anonymous"
83104
83161
  });
83105
83162
  instrumentation.getConfig().responseHook?.(span);
83106
83163
  return result;
@@ -83304,11 +83361,11 @@ var KoaInstrumentation = class extends import_instrumentation29.InstrumentationB
83304
83361
  const router = dispatchLayer.router;
83305
83362
  const routesStack = router?.stack ?? [];
83306
83363
  for (const pathLayer of routesStack) {
83307
- const path33 = pathLayer.path;
83364
+ const path34 = pathLayer.path;
83308
83365
  const pathStack = pathLayer.stack;
83309
83366
  for (let j = 0; j < pathStack.length; j++) {
83310
83367
  const routedMiddleware = pathStack[j];
83311
- pathStack[j] = this._patchLayer(routedMiddleware, true, path33);
83368
+ pathStack[j] = this._patchLayer(routedMiddleware, true, path34);
83312
83369
  }
83313
83370
  }
83314
83371
  return dispatchLayer;
@@ -85555,7 +85612,7 @@ function _init2(options = {}, getDefaultIntegrationsImpl) {
85555
85612
  return client;
85556
85613
  }
85557
85614
 
85558
- // ../../apps/collector/src/reporting.ts
85615
+ // ../../apps/syncservice/src/reporting.ts
85559
85616
  function initCollectorReporting(appEnv, release2) {
85560
85617
  const dsn = process.env.SENTRY_DSN;
85561
85618
  if (!dsn) return;
@@ -85625,7 +85682,7 @@ async function flushReporting() {
85625
85682
  await flush(2e3).catch(() => void 0);
85626
85683
  }
85627
85684
 
85628
- // ../../apps/collector/src/macosCredentialStore.ts
85685
+ // ../../apps/syncservice/src/macosCredentialStore.ts
85629
85686
  import { execFileSync as execFileSync3 } from "node:child_process";
85630
85687
  import { createCipheriv, createDecipheriv, randomBytes, randomUUID as randomUUID2 } from "node:crypto";
85631
85688
  import {
@@ -85640,7 +85697,7 @@ import {
85640
85697
  import os11 from "node:os";
85641
85698
  import path13 from "node:path";
85642
85699
 
85643
- // ../../apps/collector/src/readIfExists.ts
85700
+ // ../../apps/syncservice/src/readIfExists.ts
85644
85701
  import { readFileSync as readFileSync2 } from "node:fs";
85645
85702
  function readIfExists(file2) {
85646
85703
  try {
@@ -85651,7 +85708,7 @@ function readIfExists(file2) {
85651
85708
  }
85652
85709
  }
85653
85710
 
85654
- // ../../apps/collector/src/childExitCodes.ts
85711
+ // ../../apps/syncservice/src/childExitCodes.ts
85655
85712
  var SECURITY_EXITS = {
85656
85713
  36: "user interaction is not allowed, Keychain needs a desktop session",
85657
85714
  44: "item not found",
@@ -85678,7 +85735,7 @@ function describeLaunchctlExit(status) {
85678
85735
  return `launchctl exited ${status}${meaning ? ` (${meaning})` : ""}`;
85679
85736
  }
85680
85737
 
85681
- // ../../apps/collector/src/service.ts
85738
+ // ../../apps/syncservice/src/service.ts
85682
85739
  import { execFileSync } from "node:child_process";
85683
85740
  import { chmodSync, existsSync, mkdirSync, readFileSync as readFileSync3, rmSync, unlinkSync, writeFileSync } from "node:fs";
85684
85741
  import os3 from "node:os";
@@ -85895,16 +85952,38 @@ function xmlEscape(value) {
85895
85952
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
85896
85953
  }
85897
85954
 
85898
- // ../../apps/collector/src/status.ts
85955
+ // ../../apps/syncservice/src/status.ts
85899
85956
  import { mkdirSync as mkdirSync7, readFileSync as readFileSync7, renameSync as renameSync3, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "node:fs";
85900
85957
  import os10 from "node:os";
85901
85958
  import path12 from "node:path";
85902
85959
 
85903
- // ../../apps/collector/src/hookHealth.ts
85960
+ // ../../apps/syncservice/src/hookHealth.ts
85904
85961
  import { existsSync as existsSync6, lstatSync as lstatSync4 } from "node:fs";
85905
85962
  import path11 from "node:path";
85906
85963
 
85907
- // ../../apps/collector/src/codexTranscriptDiscovery.ts
85964
+ // ../../apps/syncservice/src/codexHookGuidance.ts
85965
+ var CODEX_ACTIVITY_WINDOW_MS = 7 * 24 * 60 * 6e4;
85966
+ function codexHookInstructions(client) {
85967
+ switch (client) {
85968
+ case "desktop":
85969
+ return "Open Settings \u2192 Hooks in Codex to trust Powerplant. This makes sync more efficient.";
85970
+ case "tui":
85971
+ return "Run /hooks in Codex to trust Powerplant. This makes sync more efficient.";
85972
+ case "unknown":
85973
+ return "Open Settings \u2192 Hooks in the Codex app, or run /hooks in the Codex TUI, to trust Powerplant.";
85974
+ }
85975
+ }
85976
+ function hookWarning(health, nowMs) {
85977
+ const silence = health.silence;
85978
+ if (health.harness !== "codex" || silence?.kind !== "not-firing") return silence;
85979
+ const activity = health.codexActivity;
85980
+ if (activity === void 0) return void 0;
85981
+ const age = nowMs - Date.parse(activity.at);
85982
+ if (!Number.isFinite(age) || age < 0 || age > CODEX_ACTIVITY_WINDOW_MS) return void 0;
85983
+ return { ...silence, fix: codexHookInstructions(activity.client) };
85984
+ }
85985
+
85986
+ // ../../apps/syncservice/src/codexTranscriptDiscovery.ts
85908
85987
  import { createHash } from "node:crypto";
85909
85988
  import { closeSync, lstatSync, openSync, readSync, readdirSync, realpathSync } from "node:fs";
85910
85989
  import path2 from "node:path";
@@ -85965,13 +86044,13 @@ function readCodexTranscriptDiscoveryRecords(home, roots) {
85965
86044
  return result;
85966
86045
  }
85967
86046
 
85968
- // ../../apps/collector/src/diagnostics.ts
86047
+ // ../../apps/syncservice/src/diagnostics.ts
85969
86048
  import { createHmac } from "node:crypto";
85970
86049
 
85971
- // ../../apps/collector/src/http.ts
86050
+ // ../../apps/syncservice/src/http.ts
85972
86051
  var import_undici = __toESM(require_undici(), 1);
85973
86052
  var CLI_VERSION_HEADER = "x-powerplant-cli-version";
85974
- var cliVersion = true ? "0.4.14" : "0.0.0-checkout";
86053
+ var cliVersion = true ? "0.4.15" : "0.0.0-checkout";
85975
86054
  function cliVersionHeaders() {
85976
86055
  return { [CLI_VERSION_HEADER]: cliVersion, "user-agent": `powerplant-cli/${cliVersion}` };
85977
86056
  }
@@ -86043,7 +86122,7 @@ function isPoisonedHttp2Session(error63) {
86043
86122
  return false;
86044
86123
  }
86045
86124
 
86046
- // ../../apps/collector/src/diagnostics.ts
86125
+ // ../../apps/syncservice/src/diagnostics.ts
86047
86126
  function observeFileDiagnostic(observer, file2) {
86048
86127
  try {
86049
86128
  observer?.(file2);
@@ -86095,8 +86174,8 @@ function createStructureDiagnostics() {
86095
86174
  observe: (source) => (observation) => {
86096
86175
  try {
86097
86176
  const formatVersion = admitted("formatVersion", observation.formatVersion ?? null);
86098
- const path33 = observation.path.replace(/[^A-Za-z0-9_.$:/=[\]-]/g, "_").slice(0, 160) || "other";
86099
- const key = [source, path33, observation.reason, observation.valueType, formatVersion].join("\0");
86177
+ const path34 = observation.path.replace(/[^A-Za-z0-9_.$:/=[\]-]/g, "_").slice(0, 160) || "other";
86178
+ const key = [source, path34, observation.reason, observation.valueType, formatVersion].join("\0");
86100
86179
  const count3 = observation.count ?? 1;
86101
86180
  const existing = groups.get(key);
86102
86181
  if (existing) {
@@ -86106,7 +86185,7 @@ function createStructureDiagnostics() {
86106
86185
  if (samples.length >= MAX_STRUCTURE_DIAGNOSTICS) return;
86107
86186
  const sample = {
86108
86187
  source,
86109
- path: path33,
86188
+ path: path34,
86110
86189
  reason: observation.reason,
86111
86190
  valueType: observation.valueType,
86112
86191
  formatVersion,
@@ -86278,13 +86357,13 @@ function bindDiagnosticEnrollment(diagnostic, token) {
86278
86357
  passEnrollments.set(diagnostic, token);
86279
86358
  }
86280
86359
 
86281
- // ../../apps/collector/src/codexSessions.ts
86360
+ // ../../apps/syncservice/src/codexSessions.ts
86282
86361
  import { closeSync as closeSync3, mkdirSync as mkdirSync2, openSync as openSync3, renameSync, rmSync as rmSync2, utimesSync, writeSync } from "node:fs";
86283
86362
  import os6 from "node:os";
86284
86363
  import path5 from "node:path";
86285
86364
  import { setImmediate as yieldToEventLoop } from "node:timers/promises";
86286
86365
 
86287
- // ../../apps/collector/src/gitOwner.ts
86366
+ // ../../apps/syncservice/src/gitOwner.ts
86288
86367
  import { execFileSync as execFileSync2 } from "node:child_process";
86289
86368
  import { readFileSync as readFileSync4, statSync } from "node:fs";
86290
86369
  import os4 from "node:os";
@@ -86484,7 +86563,7 @@ function isPermissionError(cause) {
86484
86563
  return typeof cause === "object" && cause !== null && "code" in cause && (cause.code === "EPERM" || cause.code === "EACCES");
86485
86564
  }
86486
86565
 
86487
- // ../../apps/collector/src/scan.ts
86566
+ // ../../apps/syncservice/src/scan.ts
86488
86567
  import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync2, readSync as readSync2, statSync as statSync2 } from "node:fs";
86489
86568
  import { StringDecoder } from "node:string_decoder";
86490
86569
  var SESSION_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -86569,7 +86648,7 @@ function describeReadError(error63) {
86569
86648
  return error63 instanceof Error ? error63.message : String(error63);
86570
86649
  }
86571
86650
 
86572
- // ../../apps/collector/src/scope.ts
86651
+ // ../../apps/syncservice/src/scope.ts
86573
86652
  import os5 from "node:os";
86574
86653
  import path4 from "node:path";
86575
86654
  var captureEverythingUnresolved = {
@@ -86658,15 +86737,6 @@ function withWorkspaceRouting(policy, repoPart) {
86658
86737
  const severalWorkspaces = (policy.workspaceClaims?.length ?? 0) > 1;
86659
86738
  return severalWorkspaces && claiming.length > 0 ? `${repoPart}, routing each repo to the workspace that syncs it (${listSome(claiming.map((workspace) => workspace.name))})` : repoPart;
86660
86739
  }
86661
- function describeEnrollmentCapture(policy) {
86662
- if (policy.mode === "org-repos") {
86663
- const boundary = orgRepoBoundary(policy);
86664
- if (boundary.kind === "repo-list") {
86665
- return `Set allowlist from this org: ${withWorkspaceRouting(policy, listSome(boundary.repos))}`;
86666
- }
86667
- }
86668
- return `Syncing: ${describeCapturePolicy(policy)}`;
86669
- }
86670
86740
  function describeStoredCapture(credentials) {
86671
86741
  if (credentials.captureMode === "scope") {
86672
86742
  return describeCapturePolicy({
@@ -86718,12 +86788,14 @@ function isPathWithinScopes(resolved, scopePaths) {
86718
86788
  );
86719
86789
  }
86720
86790
 
86721
- // ../../apps/collector/src/codexSessions.ts
86791
+ // ../../apps/syncservice/src/codexSessions.ts
86722
86792
  function parseCodexRollout(text, sharedUsage) {
86723
86793
  let meta3 = null;
86724
86794
  let initialEvent;
86725
86795
  let records = 0;
86726
86796
  let model;
86797
+ let codexClient = "unknown";
86798
+ let noninteractive;
86727
86799
  const timestamps = [];
86728
86800
  const usage = sharedUsage ?? createCodexUsageReader();
86729
86801
  for (const line of parseJsonl(text)) {
@@ -86736,6 +86808,8 @@ function parseCodexRollout(text, sharedUsage) {
86736
86808
  const record2 = payload;
86737
86809
  if (line.type === "session_meta") {
86738
86810
  meta3 ??= record2;
86811
+ codexClient = classifyCodexClient(record2);
86812
+ noninteractive = record2.source === "exec" ? true : void 0;
86739
86813
  } else if (line.type === "turn_context" && typeof record2.model === "string") {
86740
86814
  model = record2.model;
86741
86815
  }
@@ -86746,6 +86820,8 @@ function parseCodexRollout(text, sharedUsage) {
86746
86820
  const sessionId = meta3?.id ?? meta3?.session_id;
86747
86821
  const facts = meta3 === null ? {} : harnessSessionFacts("codex", { ...meta3, initialEvent });
86748
86822
  return {
86823
+ codexClient,
86824
+ ...noninteractive && { noninteractive },
86749
86825
  kind: facts.subagent ? "subagent" : "session",
86750
86826
  ...facts.standaloneReview && { standaloneReview: true },
86751
86827
  ...typeof sessionId === "string" && sessionId !== "" && { sessionId },
@@ -86783,6 +86859,8 @@ function foldRolloutPages(pages, usage) {
86783
86859
  const repoFullName = first("repoFullName");
86784
86860
  return {
86785
86861
  kind: pages[0].kind,
86862
+ codexClient: pages.at(-1).codexClient,
86863
+ ...pages.at(-1).noninteractive && { noninteractive: true },
86786
86864
  ...pages[0].standaloneReview && { standaloneReview: true },
86787
86865
  ...sessionId !== void 0 && { sessionId },
86788
86866
  ...startedAt !== void 0 && { startedAt },
@@ -86849,11 +86927,12 @@ var MergedTranscriptWriter = class {
86849
86927
  function rolloutLocation(rolloutPath) {
86850
86928
  const record2 = readFirstRecord(rolloutPath, (candidate) => candidate.type === "session_meta");
86851
86929
  const meta3 = record2?.payload;
86852
- if (!meta3 || typeof meta3 !== "object" || Array.isArray(meta3)) return { kind: "session", totals: null, fastTotals: null };
86930
+ if (!meta3 || typeof meta3 !== "object" || Array.isArray(meta3)) return { kind: "session", codexClient: "unknown", totals: null, fastTotals: null };
86853
86931
  const { cwd, id, session_id: fallbackId } = meta3;
86854
86932
  const sessionId = id ?? fallbackId;
86855
86933
  const startedAt = record2?.timestamp;
86856
86934
  return {
86935
+ codexClient: classifyCodexClient(meta3),
86857
86936
  kind: isSidecarThread(meta3) ? "subagent" : "session",
86858
86937
  ...typeof sessionId === "string" && { sessionId },
86859
86938
  ...typeof startedAt === "string" && { startedAt },
@@ -86912,7 +86991,7 @@ async function collectCodexSessions(options = {}) {
86912
86991
  let skippedTooLarge = 0;
86913
86992
  let mergedThreads = 0;
86914
86993
  let largestMergedBytes = 0;
86915
- const externalIdOf = (rolloutPath) => path5.basename(rolloutPath, ".jsonl");
86994
+ const harnessSessionIdOf = (rolloutPath) => path5.basename(rolloutPath, ".jsonl");
86916
86995
  const files = /* @__PURE__ */ new Map();
86917
86996
  const observe = async (paths, archived, discoverySessionId) => {
86918
86997
  for (const rolloutPath of paths) {
@@ -86953,7 +87032,7 @@ async function collectCodexSessions(options = {}) {
86953
87032
  }
86954
87033
  for (const [threadId2, observed] of byThread) {
86955
87034
  const stored = dedupeStoreCopies(observed);
86956
- let externalId = externalIdOf((stored.find((file2) => !file2.identity.page) ?? stored[0]).rolloutPath);
87035
+ let harnessSessionId = harnessSessionIdOf((stored.find((file2) => !file2.identity.page) ?? stored[0]).rolloutPath);
86957
87036
  try {
86958
87037
  const mergedTranscriptPath = stored.length > 1 ? path5.join(mergedTranscriptsDir, `${threadId2}.jsonl`) : void 0;
86959
87038
  const changedMs = Math.max(...stored.map((file2) => file2.changedMs));
@@ -86970,7 +87049,7 @@ async function collectCodexSessions(options = {}) {
86970
87049
  if (named.length === 0) continue;
86971
87050
  const threadFiles = named.length > 1 ? orderPages(named) : named;
86972
87051
  const base = threadFiles[0];
86973
- externalId = externalIdOf(base.rolloutPath);
87052
+ harnessSessionId = harnessSessionIdOf(base.rolloutPath);
86974
87053
  const mtimeMs = Math.max(...threadFiles.map((file2) => file2.mtimeMs));
86975
87054
  const sizeBytes = threadFiles.reduce((sum2, file2) => sum2 + file2.sizeBytes, 0);
86976
87055
  if (sizeBytes > maxBytes) {
@@ -86993,7 +87072,7 @@ async function collectCodexSessions(options = {}) {
86993
87072
  continue;
86994
87073
  }
86995
87074
  const thread = {
86996
- externalId,
87075
+ harnessSessionId,
86997
87076
  files: threadFiles,
86998
87077
  ...threadFiles.length > 1 && mergedTranscriptPath !== void 0 && { mergedTranscriptPath },
86999
87078
  mtimeMs,
@@ -87005,8 +87084,8 @@ async function collectCodexSessions(options = {}) {
87005
87084
  transcriptPath: base.rolloutPath,
87006
87085
  ...location.cwd && { cwd: location.cwd },
87007
87086
  item: {
87008
- source: "codex",
87009
- externalId,
87087
+ harness: "codex-local",
87088
+ harnessSessionId,
87010
87089
  status: now - mtimeMs < ACTIVE_GRACE_MS ? "active" : "inactive",
87011
87090
  archived: thread.archived,
87012
87091
  capturedVia: decision.via
@@ -87016,7 +87095,7 @@ async function collectCodexSessions(options = {}) {
87016
87095
  }
87017
87096
  candidates.push({ thread, ...location.cwd && { cwd: location.cwd }, decision });
87018
87097
  } catch (error63) {
87019
- unreadable.push(`${externalId}: ${describeReadError(error63)}`);
87098
+ unreadable.push(`${harnessSessionId}: ${describeReadError(error63)}`);
87020
87099
  observeFileDiagnostic(options.onFileDiagnostic, {
87021
87100
  path: stored[0].rolloutPath,
87022
87101
  reason: "unreadable",
@@ -87080,11 +87159,13 @@ async function collectCodexSessions(options = {}) {
87080
87159
  const title = summary.sessionId ? threadNames.get(summary.sessionId) : void 0;
87081
87160
  items.push({
87082
87161
  mtimeMs: thread.mtimeMs,
87162
+ codexClient: summary.codexClient,
87163
+ ...summary.noninteractive && { codexNoninteractive: true },
87083
87164
  transcriptPath: transcriptUploadSourcePath,
87084
87165
  ...cwd && { cwd },
87085
87166
  item: {
87086
- source: "codex",
87087
- externalId: thread.externalId,
87167
+ harness: "codex-local",
87168
+ harnessSessionId: thread.harnessSessionId,
87088
87169
  status: now - thread.mtimeMs < ACTIVE_GRACE_MS ? "active" : "inactive",
87089
87170
  archived: thread.archived,
87090
87171
  ...summary.standaloneReview && { automation: true },
@@ -87113,7 +87194,7 @@ async function collectCodexSessions(options = {}) {
87113
87194
  });
87114
87195
  } catch (error63) {
87115
87196
  writer?.abandon();
87116
- unreadable.push(`${thread.externalId}: ${describeReadError(error63)}`);
87197
+ unreadable.push(`${thread.harnessSessionId}: ${describeReadError(error63)}`);
87117
87198
  observeFileDiagnostic(options.onFileDiagnostic, {
87118
87199
  path: thread.files[0].rolloutPath,
87119
87200
  reason: "unreadable",
@@ -87161,7 +87242,7 @@ function codexThreadCwd(threadId2, sessionsDir = path5.join(os6.homedir(), ".cod
87161
87242
  return void 0;
87162
87243
  }
87163
87244
 
87164
- // ../../apps/collector/src/cursorTranscriptFile.ts
87245
+ // ../../apps/syncservice/src/cursorTranscriptFile.ts
87165
87246
  import { createHash as createHash3 } from "node:crypto";
87166
87247
  import {
87167
87248
  chmodSync as chmodSync3,
@@ -87179,7 +87260,7 @@ import {
87179
87260
  import os8 from "node:os";
87180
87261
  import path7 from "node:path";
87181
87262
 
87182
- // ../../apps/collector/src/captureOmissions.ts
87263
+ // ../../apps/syncservice/src/captureOmissions.ts
87183
87264
  var REPORTED_REASONS = /* @__PURE__ */ new Set([
87184
87265
  "unsupported",
87185
87266
  "malformed",
@@ -87191,21 +87272,21 @@ function createOmissionRecorder() {
87191
87272
  const count3 = (reason, by = 1) => {
87192
87273
  if (by > 0) counts[reason] = (counts[reason] ?? 0) + by;
87193
87274
  };
87194
- const shape = (reason, path33, valueType, formatVersion, by = 1) => {
87275
+ const shape = (reason, path34, valueType, formatVersion, by = 1) => {
87195
87276
  if (!REPORTED_REASONS.has(reason)) return;
87196
- const key = `${path33}\0${reason}\0${valueType}\0${formatVersion ?? ""}`;
87277
+ const key = `${path34}\0${reason}\0${valueType}\0${formatVersion ?? ""}`;
87197
87278
  const group = groups.get(key);
87198
87279
  if (group) group.count += by;
87199
87280
  else if (groups.size < MAX_STRUCTURE_DIAGNOSTICS) {
87200
- groups.set(key, { path: path33, reason, valueType, count: by, ...formatVersion !== void 0 && { formatVersion } });
87281
+ groups.set(key, { path: path34, reason, valueType, count: by, ...formatVersion !== void 0 && { formatVersion } });
87201
87282
  }
87202
87283
  };
87203
87284
  return {
87204
87285
  count: count3,
87205
87286
  shape,
87206
- note(reason, path33, valueType, formatVersion) {
87287
+ note(reason, path34, valueType, formatVersion) {
87207
87288
  count3(reason);
87208
- shape(reason, path33, valueType, formatVersion);
87289
+ shape(reason, path34, valueType, formatVersion);
87209
87290
  },
87210
87291
  absorb(other) {
87211
87292
  for (const [reason, by] of Object.entries(other.omissions())) {
@@ -87230,7 +87311,7 @@ function unhandledObservations(shapes, externalId) {
87230
87311
  return shapes.map(({ formatVersion, ...shape }) => ({ ...shape, formatVersion: formatVersion ?? null, externalId }));
87231
87312
  }
87232
87313
 
87233
- // ../../apps/collector/src/cursorLocal.ts
87314
+ // ../../apps/syncservice/src/cursorLocal.ts
87234
87315
  import { createHash as createHash2 } from "node:crypto";
87235
87316
  import { chmodSync as chmodSync2, existsSync as existsSync2, mkdirSync as mkdirSync3, utimesSync as utimesSync2, writeFileSync as writeFileSync2 } from "node:fs";
87236
87317
  import os7 from "node:os";
@@ -87445,8 +87526,8 @@ var MODEL_INFO_FIELDS_INTERPRETED = /* @__PURE__ */ new Set(["modelName"]);
87445
87526
  function collectUnfamiliar(record2, interpreted, excluded, prefix, into, recorder, formatVersion) {
87446
87527
  for (const [key, value] of Object.entries(record2)) {
87447
87528
  if (interpreted.has(key) || excluded.has(key)) continue;
87448
- const path33 = prefix === "" ? key : `${prefix}.${key}`;
87449
- into.set(path33, value);
87529
+ const path34 = prefix === "" ? key : `${prefix}.${key}`;
87530
+ into.set(path34, value);
87450
87531
  recorder.shape("unsupported", `bubble.${prefix === "" ? "" : `${prefix}.`}${nativeTypeLabel(key) ?? "other"}`, jsonValueType(value), formatVersion);
87451
87532
  }
87452
87533
  }
@@ -87532,8 +87613,8 @@ function bubbleLines(bubble, at, recorder) {
87532
87613
  const formatVersion = typeof bubble._v === "number" || typeof bubble._v === "string" ? String(bubble._v) : void 0;
87533
87614
  if (bubble.type !== 1 && bubble.type !== 2) {
87534
87615
  const nativeType = nativeTypeLabel(String(bubble.type));
87535
- const path33 = `bubble.type=${nativeType ?? "other"}`;
87536
- recorder.note("unsupported", path33, jsonValueType(bubble.type), formatVersion);
87616
+ const path34 = `bubble.type=${nativeType ?? "other"}`;
87617
+ recorder.note("unsupported", path34, jsonValueType(bubble.type), formatVersion);
87537
87618
  const retained = Object.fromEntries(Object.entries(bubble).filter(([key]) => !BUBBLE_FIELDS_EXCLUDED.has(key)));
87538
87619
  const bounded = boundUnfamiliarPayload(retained);
87539
87620
  if (bounded.payload === void 0) recorder.count("truncated");
@@ -87750,8 +87831,8 @@ function collectFromStore(db, userDir, options, result, knownIds) {
87750
87831
  transcriptPath: path6.join(userDir, "globalStorage", "state.vscdb"),
87751
87832
  ...cwd && { cwd },
87752
87833
  item: {
87753
- source: "cursor",
87754
- externalId: raw.composerId,
87834
+ harness: "cursor-local",
87835
+ harnessSessionId: raw.composerId,
87755
87836
  status: now - lastUpdatedAt < ACTIVE_GRACE_MS ? "active" : "inactive",
87756
87837
  capturedVia: decision.via
87757
87838
  }
@@ -87829,8 +87910,8 @@ function collectFromStore(db, userDir, options, result, knownIds) {
87829
87910
  transcriptPath: transcriptUploadSourcePath,
87830
87911
  ...cwd && { cwd },
87831
87912
  item: {
87832
- source: "cursor",
87833
- externalId: raw.composerId,
87913
+ harness: "cursor-local",
87914
+ harnessSessionId: raw.composerId,
87834
87915
  status: now - lastUpdatedAt < ACTIVE_GRACE_MS ? "active" : "inactive",
87835
87916
  // The header's own archive evidence, both ways; omitted (nothing
87836
87917
  // claimed) when the column establishes neither.
@@ -87857,7 +87938,7 @@ function collectFromStore(db, userDir, options, result, knownIds) {
87857
87938
  }
87858
87939
  }
87859
87940
 
87860
- // ../../apps/collector/src/cursorTranscriptFile.ts
87941
+ // ../../apps/syncservice/src/cursorTranscriptFile.ts
87861
87942
  var textBlock = external_exports.object({ type: external_exports.literal("text"), text: external_exports.string() });
87862
87943
  var toolUseBlock = external_exports.object({
87863
87944
  type: external_exports.literal("tool_use"),
@@ -87884,12 +87965,12 @@ var CONTENT_LINE_TYPES2 = /* @__PURE__ */ new Set([
87884
87965
  function parseCursorTranscriptFile(text) {
87885
87966
  const lines = [];
87886
87967
  const recorder = createOmissionRecorder();
87887
- const retainUnsupported = (record2, at, path33, discriminator) => {
87968
+ const retainUnsupported = (record2, at, path34, discriminator) => {
87888
87969
  const nativeType = nativeTypeLabel(discriminator);
87889
87970
  const bounded = boundUnfamiliarPayload(record2);
87890
87971
  lines.push({ type: "unsupported", ...nativeType !== void 0 && { nativeType }, ...at, ...bounded });
87891
- recorder.note("unsupported", `${path33}=${nativeType ?? "other"}`, jsonValueType(discriminator));
87892
- if (bounded.payload === void 0) recorder.note("truncated", `${path33}=${nativeType ?? "other"}`, "object");
87972
+ recorder.note("unsupported", `${path34}=${nativeType ?? "other"}`, jsonValueType(discriminator));
87973
+ if (bounded.payload === void 0) recorder.note("truncated", `${path34}=${nativeType ?? "other"}`, "object");
87893
87974
  };
87894
87975
  text.split("\n").forEach((row, recordIndex) => {
87895
87976
  if (!row.trim()) return;
@@ -87911,8 +87992,8 @@ function parseCursorTranscriptFile(text) {
87911
87992
  }
87912
87993
  const record2 = message.safeParse(value);
87913
87994
  if (!record2.success) {
87914
- const [path33, discriminator] = typeof value.type === "string" ? ["record.type", value.type] : typeof value.role === "string" ? ["message.role", value.role] : ["record", void 0];
87915
- retainUnsupported(value, { recordIndex }, path33, discriminator);
87995
+ const [path34, discriminator] = typeof value.type === "string" ? ["record.type", value.type] : typeof value.role === "string" ? ["message.role", value.role] : ["record", void 0];
87996
+ retainUnsupported(value, { recordIndex }, path34, discriminator);
87916
87997
  return;
87917
87998
  }
87918
87999
  const role = record2.data.role;
@@ -88074,8 +88155,8 @@ function collectCursorTranscriptFiles(options, isDatabaseSession, result, databa
88074
88155
  continue;
88075
88156
  }
88076
88157
  const common = {
88077
- source: "cursor",
88078
- externalId: record2.sessionId,
88158
+ harness: "cursor-local",
88159
+ harnessSessionId: record2.sessionId,
88079
88160
  status: (options.now ?? Date.now()) - stat.mtimeMs < ACTIVE_GRACE_MS ? "active" : "inactive",
88080
88161
  ...decision.repoFullName && { repoFullName: decision.repoFullName },
88081
88162
  capturedVia: decision.via
@@ -88165,7 +88246,7 @@ function collectCursorTranscriptFiles(options, isDatabaseSession, result, databa
88165
88246
  }
88166
88247
  }
88167
88248
 
88168
- // ../../apps/collector/src/hookInstall.ts
88249
+ // ../../apps/syncservice/src/hookInstall.ts
88169
88250
  import { existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync5, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "node:fs";
88170
88251
  import os9 from "node:os";
88171
88252
  import path8 from "node:path";
@@ -88287,7 +88368,7 @@ function installCollectorHooks(homeDir = os9.homedir()) {
88287
88368
  };
88288
88369
  }
88289
88370
 
88290
- // ../../apps/collector/src/lifecycleJournal.ts
88371
+ // ../../apps/syncservice/src/lifecycleJournal.ts
88291
88372
  import path9 from "node:path";
88292
88373
  var LIFECYCLE_JOURNAL_FILENAME = "session-lifecycle.jsonl";
88293
88374
  function lifecycleJournalPath(home) {
@@ -88319,7 +88400,7 @@ function observedSessionEnd(entry, mtimeMs) {
88319
88400
  return entry.at;
88320
88401
  }
88321
88402
 
88322
- // ../../apps/collector/src/harnessHooks.ts
88403
+ // ../../apps/syncservice/src/harnessHooks.ts
88323
88404
  import {
88324
88405
  existsSync as existsSync5,
88325
88406
  lstatSync as lstatSync3,
@@ -88484,10 +88565,12 @@ function installHarnessHooks(home) {
88484
88565
  });
88485
88566
  }
88486
88567
 
88487
- // ../../apps/collector/src/hookHealth.ts
88568
+ // ../../apps/syncservice/src/hookHealth.ts
88488
88569
  var HOOK_OBSERVATION_GRACE_MS = 2 * 6e4;
88489
88570
  var hookHealthSchema = external_exports.object({
88490
88571
  harness: hookHarnessSchema,
88572
+ /** Latest recorded interactive Codex activity, not file discovery time. */
88573
+ codexActivity: external_exports.object({ client: codexClientSchema, at: external_exports.string() }).optional(),
88491
88574
  /** What this daemon's boot-time install did (installCollectorHooks / installHarnessHooks). */
88492
88575
  install: hookInstallOutcomeSchema,
88493
88576
  /** unverified: no in-scope session started since the install has been
@@ -88567,7 +88650,7 @@ function inspectHookConfig(harness, home) {
88567
88650
  var NOT_FIRING = {
88568
88651
  codex: () => ({
88569
88652
  problem: "Codex hooks are installed but not running",
88570
- fix: "In Codex, run /hooks and trust the Powerplant hooks."
88653
+ fix: codexHookInstructions("unknown")
88571
88654
  }),
88572
88655
  claude: () => ({
88573
88656
  problem: "Claude Code hooks are installed but didn't run for a new session",
@@ -88609,10 +88692,10 @@ function describeHookSilence(harness, state, home) {
88609
88692
  return { kind: "not-firing", ...NOT_FIRING[harness](home) };
88610
88693
  }
88611
88694
  }
88612
- var HARNESS_OF_SOURCE = {
88613
- "claude-code": "claude",
88614
- codex: "codex",
88615
- cursor: "cursor"
88695
+ var NATIVE_HOOK_NAME_BY_HARNESS = {
88696
+ "claude-local": "claude",
88697
+ "codex-local": "codex",
88698
+ "cursor-local": "cursor"
88616
88699
  };
88617
88700
  function hookSessionId(harness, externalId) {
88618
88701
  if (harness !== "codex") return externalId;
@@ -88657,11 +88740,10 @@ function createHookHealthTracker(deps) {
88657
88740
  }
88658
88741
  };
88659
88742
  const admit = (session, nowMs) => {
88660
- const harness = HARNESS_OF_SOURCE[session.item.source];
88661
- if (harness === void 0) return;
88743
+ const harness = NATIVE_HOOK_NAME_BY_HARNESS[session.item.harness];
88662
88744
  if (session.item.automation === true || session.item.startedAt === void 0) return;
88663
88745
  if (!(Date.parse(session.item.startedAt) > installedAtMs)) return;
88664
- const sessionId = hookSessionId(harness, session.item.externalId);
88746
+ const sessionId = hookSessionId(harness, session.item.harnessSessionId);
88665
88747
  if (sessionId === null) return;
88666
88748
  const key = `${harness}:${sessionId}`;
88667
88749
  if (judged.has(key) || candidates.has(key)) return;
@@ -88673,7 +88755,7 @@ function createHookHealthTracker(deps) {
88673
88755
  const name = HARNESS_NAMES[harness];
88674
88756
  if (fired) {
88675
88757
  if (current.state === "firing") return false;
88676
- health[harness] = { harness, install: current.install, state: "firing" };
88758
+ health[harness] = { ...current, state: "firing", silence: void 0 };
88677
88759
  log3(
88678
88760
  current.state === "silent" ? `${name} hooks are firing again (session ${candidate.sessionId} has a hook record)` : `${name} hooks verified firing (session ${candidate.sessionId} has a hook record)`
88679
88761
  );
@@ -88682,8 +88764,7 @@ function createHookHealthTracker(deps) {
88682
88764
  const silence = describeHookSilence(harness, inspect(harness), home);
88683
88765
  if (current.silence?.problem === silence.problem) return false;
88684
88766
  health[harness] = {
88685
- harness,
88686
- install: current.install,
88767
+ ...current,
88687
88768
  state: "silent",
88688
88769
  silence: { ...silence, since: new Date(nowMs).toISOString() }
88689
88770
  };
@@ -88710,9 +88791,24 @@ function createHookHealthTracker(deps) {
88710
88791
  };
88711
88792
  return {
88712
88793
  observe(sessions, nowMs) {
88713
- for (const session of sessions) admit(session, nowMs);
88794
+ let activityChanged = false;
88795
+ for (const session of sessions) {
88796
+ if (session.item.harness === "codex-local" && session.item.automation !== true && session.codexNoninteractive !== true) {
88797
+ const at = session.item.endedAt ?? session.item.startedAt;
88798
+ const timestamp = at === void 0 ? NaN : Date.parse(at);
88799
+ const previous = health.codex.codexActivity;
88800
+ if (Number.isFinite(timestamp) && timestamp <= nowMs && (previous === void 0 || timestamp > Date.parse(previous.at))) {
88801
+ health.codex = { ...health.codex, codexActivity: {
88802
+ client: session.codexClient ?? "unknown",
88803
+ at: new Date(timestamp).toISOString()
88804
+ } };
88805
+ activityChanged = true;
88806
+ }
88807
+ }
88808
+ admit(session, nowMs);
88809
+ }
88714
88810
  let observed;
88715
- let changed = false;
88811
+ let changed = activityChanged;
88716
88812
  let failure2;
88717
88813
  for (const [key, candidate] of candidates) {
88718
88814
  if (nowMs - candidate.firstSeenMs < HOOK_OBSERVATION_GRACE_MS) continue;
@@ -88742,7 +88838,7 @@ function createHookHealthTracker(deps) {
88742
88838
  };
88743
88839
  }
88744
88840
 
88745
- // ../../apps/collector/src/status.ts
88841
+ // ../../apps/syncservice/src/status.ts
88746
88842
  var HEARTBEAT_INTERVAL_MS = 6e4;
88747
88843
  var STALLED_AFTER_MS = 5 * 6e4;
88748
88844
  var CONTROL_POLL_MS = 15e3;
@@ -88888,7 +88984,7 @@ function isPidAlive(pid) {
88888
88984
  }
88889
88985
  }
88890
88986
 
88891
- // ../../apps/collector/src/credentialMigration.ts
88987
+ // ../../apps/syncservice/src/credentialMigration.ts
88892
88988
  function assertCredentialMigrationReady(appEnv) {
88893
88989
  const reason = credentialMigrationBlocker(appEnv);
88894
88990
  if (reason === null) return;
@@ -88919,7 +89015,7 @@ function credentialMigrationBlocker(appEnv) {
88919
89015
  return null;
88920
89016
  }
88921
89017
 
88922
- // ../../apps/collector/src/macosCredentialStore.ts
89018
+ // ../../apps/syncservice/src/macosCredentialStore.ts
88923
89019
  var LEGACY_SERVICE = "powerplant-collector";
88924
89020
  var KEY_SERVICE = "powerplant-collector-encryption";
88925
89021
  var keySchema = external_exports.string().regex(/^[0-9a-f]{64}$/);
@@ -89119,7 +89215,7 @@ var MacosCredentialStore = class {
89119
89215
  }
89120
89216
  };
89121
89217
 
89122
- // ../../apps/collector/src/credentials.ts
89218
+ // ../../apps/syncservice/src/credentials.ts
89123
89219
  var storedCredentialsSchema = external_exports.object({
89124
89220
  machineId: external_exports.string().min(1),
89125
89221
  machineName: external_exports.string().min(1),
@@ -89275,13 +89371,13 @@ function fallbackFile(appEnv) {
89275
89371
  return path14.join(os12.homedir(), ".config", "powerplant", `collector-${appEnv}.json`);
89276
89372
  }
89277
89373
 
89278
- // ../../apps/collector/src/enroll.ts
89374
+ // ../../apps/syncservice/src/enroll.ts
89279
89375
  import { spawn } from "node:child_process";
89280
89376
  import { createHash as createHash4, randomBytes as randomBytes2 } from "node:crypto";
89281
89377
  import http5 from "node:http";
89282
89378
  import os13 from "node:os";
89283
89379
 
89284
- // ../../apps/collector/src/upload.ts
89380
+ // ../../apps/syncservice/src/upload.ts
89285
89381
  import { readFileSync as readFileSync9 } from "node:fs";
89286
89382
  import { gzipSync } from "node:zlib";
89287
89383
  function parseApiResponse(schema, body, route) {
@@ -89400,7 +89496,7 @@ async function uploadSessions(apiUrl, machineToken, items) {
89400
89496
  unchanged: external_exports.number(),
89401
89497
  outOfPolicy: external_exports.number(),
89402
89498
  deferred: external_exports.number().optional(),
89403
- foreignOwned: external_exports.array(external_exports.object({ source: external_exports.string(), externalId: external_exports.string() })).optional()
89499
+ foreignOwned: external_exports.array(external_exports.object({ source: external_exports.enum(LEGACY_COLLECTOR_SESSION_SOURCES), externalId: external_exports.string() })).optional()
89404
89500
  })
89405
89501
  }),
89406
89502
  await response.json().catch(() => null),
@@ -89410,7 +89506,16 @@ async function uploadSessions(apiUrl, machineToken, items) {
89410
89506
  unchanged += result.data.unchanged;
89411
89507
  outOfPolicy += result.data.outOfPolicy;
89412
89508
  deferred += result.data.deferred ?? 0;
89413
- foreignOwned.push(...result.data.foreignOwned ?? []);
89509
+ for (const identity of result.data.foreignOwned ?? []) {
89510
+ const harness = harnessFromLegacySessionSource(identity.source);
89511
+ if (harness.kind !== "harness") {
89512
+ throw new Error("sessions ingest returned an unsupported ownership identity");
89513
+ }
89514
+ foreignOwned.push({
89515
+ harness: external_exports.enum(COLLECTOR_SESSION_HARNESSES).parse(harness.harness),
89516
+ harnessSessionId: identity.externalId
89517
+ });
89518
+ }
89414
89519
  }
89415
89520
  return { upserted, unchanged, outOfPolicy, deferred, ...foreignOwned.length > 0 ? { foreignOwned } : {} };
89416
89521
  }
@@ -89483,7 +89588,7 @@ async function uploadRawSessions(apiUrl, machineToken, transcriptUploadSources,
89483
89588
  shipped?.set(transcriptUploadSourcePath, session.mtimeMs);
89484
89589
  continue;
89485
89590
  }
89486
- const query = `source=${session.item.source}&externalId=${encodeURIComponent(session.item.externalId)}`;
89591
+ const query = `harness=${session.item.harness}&harnessSessionId=${encodeURIComponent(session.item.harnessSessionId)}`;
89487
89592
  const response = await fetchWithRetry(
89488
89593
  "uploading a raw transcript",
89489
89594
  `${apiUrl}/api/ingest/sessions/raw?${query}`,
@@ -89517,7 +89622,7 @@ async function uploadRawSessions(apiUrl, machineToken, transcriptUploadSources,
89517
89622
  } catch (error63) {
89518
89623
  if (error63 instanceof RateLimitedError) rateLimited ??= error63;
89519
89624
  summary.failed.push(
89520
- `${session.item.externalId}: ${error63 instanceof Error ? error63.message : String(error63)}`
89625
+ `${session.item.harnessSessionId}: ${error63 instanceof Error ? error63.message : String(error63)}`
89521
89626
  );
89522
89627
  }
89523
89628
  }
@@ -89525,7 +89630,7 @@ async function uploadRawSessions(apiUrl, machineToken, transcriptUploadSources,
89525
89630
  return summary;
89526
89631
  }
89527
89632
 
89528
- // ../../apps/collector/src/enroll.ts
89633
+ // ../../apps/syncservice/src/enroll.ts
89529
89634
  var APPROVAL_TIMEOUT_MS = 5 * 60 * 1e3;
89530
89635
  var gotrueTokenSchema = external_exports.object({ access_token: external_exports.string().min(1) });
89531
89636
  var gotrueErrorSchema = external_exports.object({
@@ -89583,7 +89688,7 @@ async function runEnrollment(config2, options) {
89583
89688
  let scopePaths = (options.scope ?? []).map(normalizeScopePath);
89584
89689
  let captureMode = scopePaths.length > 0 ? "scope" : "org-repos";
89585
89690
  if (captureMode === "scope") {
89586
- log3(`- Folders that will upload once approved: ${scopePaths.join(", ")}`);
89691
+ log3(`Folders that will upload once approved: ${scopePaths.join(", ")}`);
89587
89692
  }
89588
89693
  const result = await enroll(config2, {
89589
89694
  name,
@@ -89598,7 +89703,7 @@ async function runEnrollment(config2, options) {
89598
89703
  if (config2.appEnv === "development") {
89599
89704
  const home = normalizeScopePath(os13.homedir());
89600
89705
  log3(
89601
- `- No GitHub integration on org "${result.org.name}", syncing sessions under ${home} (your home folder, local DB only). Re-enroll with --scope <path> to narrow.`
89706
+ `No GitHub integration on org "${result.org.name}", syncing sessions under ${home} (your home folder, local DB only). Re-enroll with --scope <path> to narrow.`
89602
89707
  );
89603
89708
  captureMode = "scope";
89604
89709
  scopePaths = [home];
@@ -89635,14 +89740,6 @@ async function runEnrollment(config2, options) {
89635
89740
  // claims are unknown, and the first sweep must not stamp over them.
89636
89741
  ...workspace.integration === "linked" && workspace.owners.length === 0 && workspace.repos === null && { unresolved: true }
89637
89742
  }));
89638
- const policy = captureMode === "org-repos" ? {
89639
- mode: "org-repos",
89640
- allowedOwners: orgPolicy?.owners ?? [],
89641
- allowedRepos: orgPolicy?.repos ?? null,
89642
- ...workspacePolicies !== void 0 && { workspaceClaims: workspacePolicies },
89643
- memberFolders: [],
89644
- repoOf: () => null
89645
- } : { mode: "scope", scopePaths, repoOf: () => null };
89646
89743
  const credentials = {
89647
89744
  machineId: result.machine.id,
89648
89745
  machineName: result.machine.name,
@@ -89658,9 +89755,7 @@ async function runEnrollment(config2, options) {
89658
89755
  scopePaths
89659
89756
  };
89660
89757
  const location = saveCredentials(config2.appEnv, credentials);
89661
- log3(`- Enrolled "${result.machine.name}" (${result.machine.id}) into org "${result.org.name}".`);
89662
- log3(`- Machine token stored in ${location}.`);
89663
- log3(`- ${describeEnrollmentCapture(policy)}.`);
89758
+ log3(`Machine token stored in ${location}`);
89664
89759
  return credentials;
89665
89760
  }
89666
89761
  async function enroll(config2, options, createAuthClient = gotrueAuthClient, listener = {}) {
@@ -89843,7 +89938,7 @@ function waitForApproval(approvalUrl, state, options) {
89843
89938
  server.listen(port, "127.0.0.1", () => {
89844
89939
  const address = server.address();
89845
89940
  if (onListening && address !== null && typeof address === "object") onListening(address.port);
89846
- log3(`- Opening approval page\u2026 ${approvalUrl}`);
89941
+ log3(`Opening approval page\u2026 ${approvalUrl}`);
89847
89942
  open3(approvalUrl);
89848
89943
  });
89849
89944
  });
@@ -89858,7 +89953,7 @@ function openBrowser(url2) {
89858
89953
  spawn(command, [url2], { stdio: "ignore", detached: true }).unref();
89859
89954
  }
89860
89955
 
89861
- // ../../apps/collector/src/folders.ts
89956
+ // ../../apps/syncservice/src/folders.ts
89862
89957
  var defaultDeps = { load: loadCredentials, persist: saveCredentials };
89863
89958
  function requireEnrolled(config2, enrollCommand, deps) {
89864
89959
  const credentials = deps.load(config2.appEnv);
@@ -89919,7 +90014,7 @@ function removeFolder(config2, rawPath, enrollCommand, log3, deps = defaultDeps)
89919
90014
  log3(`Removed ${folder}, sessions there stay local from the next sync pass.`);
89920
90015
  }
89921
90016
 
89922
- // ../../apps/collector/src/claudeCode.ts
90017
+ // ../../apps/syncservice/src/claudeCode.ts
89923
90018
  import os14 from "node:os";
89924
90019
  import path15 from "node:path";
89925
90020
  import { setImmediate as yieldToEventLoop2 } from "node:timers/promises";
@@ -90045,7 +90140,7 @@ async function collectClaudeCodeSessions(options = {}) {
90045
90140
  mtimeMs: stat.mtimeMs,
90046
90141
  transcriptPath,
90047
90142
  ...cwd && { cwd },
90048
- item: { source: "claude-code", externalId: sessionId, status, capturedVia: decision.via }
90143
+ item: { harness: "claude-local", harnessSessionId: sessionId, status, capturedVia: decision.via }
90049
90144
  });
90050
90145
  continue;
90051
90146
  }
@@ -90103,8 +90198,8 @@ async function collectClaudeCodeSessions(options = {}) {
90103
90198
  transcriptPath,
90104
90199
  ...cwd && { cwd },
90105
90200
  item: {
90106
- source: "claude-code",
90107
- externalId: sessionId,
90201
+ harness: "claude-local",
90202
+ harnessSessionId: sessionId,
90108
90203
  status,
90109
90204
  ...summary.startedAt && { startedAt: summary.startedAt },
90110
90205
  ...endedAt && { endedAt },
@@ -90228,11 +90323,11 @@ function claudeCodeSessionCwd(sessionId, claudeDir = path15.join(os14.homedir(),
90228
90323
  return void 0;
90229
90324
  }
90230
90325
 
90231
- // ../../apps/collector/src/protectedRepoDiscovery.ts
90326
+ // ../../apps/syncservice/src/protectedRepoDiscovery.ts
90232
90327
  import os15 from "node:os";
90233
90328
  import path16 from "node:path";
90234
90329
 
90235
- // ../../apps/collector/src/syncWindow.ts
90330
+ // ../../apps/syncservice/src/syncWindow.ts
90236
90331
  var STEADY_SYNC_WINDOW_DAYS = 3;
90237
90332
  var DEEP_FIRST_SYNC_DAYS = 90;
90238
90333
  var DEEP_FIRST_SYNC_MAX_SESSIONS = 100;
@@ -90263,7 +90358,7 @@ function describeScanReach(window2, narrowSinceMs) {
90263
90358
  return `changed since ${new Date(narrowSinceMs).toISOString()}`;
90264
90359
  }
90265
90360
 
90266
- // ../../apps/collector/src/protectedRepoDiscovery.ts
90361
+ // ../../apps/syncservice/src/protectedRepoDiscovery.ts
90267
90362
  var defaultDiscoveryDeps = {
90268
90363
  collectClaude: collectClaudeCodeSessions,
90269
90364
  collectCodex: collectCodexSessions,
@@ -90459,7 +90554,7 @@ function sameList(a, b2) {
90459
90554
  return a.length === b2.length && a.every((root, index) => root === b2[index]);
90460
90555
  }
90461
90556
 
90462
- // ../../apps/collector/src/recentCatchup.ts
90557
+ // ../../apps/syncservice/src/recentCatchup.ts
90463
90558
  function createRecentCatchup(run, now = Date.now) {
90464
90559
  let coveredSince = now();
90465
90560
  let nextCheck = coveredSince + 15e3;
@@ -90499,7 +90594,7 @@ function recentSyncOptions(shared, narrowSinceMs, selection) {
90499
90594
  };
90500
90595
  }
90501
90596
 
90502
- // ../../apps/collector/src/branchFacts.ts
90597
+ // ../../apps/syncservice/src/branchFacts.ts
90503
90598
  import { readFileSync as readFileSync10 } from "node:fs";
90504
90599
  import path17 from "node:path";
90505
90600
  var SHA_SHAPE = /^[0-9a-f]{40}$/;
@@ -90533,13 +90628,13 @@ function branchFactsOf(sessions, observe) {
90533
90628
  if (!session.cwd) return [];
90534
90629
  const observed = observe(session.cwd);
90535
90630
  if (!observed) return [];
90536
- const key = `${session.item.source}
90537
- ${session.item.externalId}
90631
+ const key = `${session.item.harness}
90632
+ ${session.item.harnessSessionId}
90538
90633
  ${observed.repoFullName}
90539
90634
  ${observed.branch}`;
90540
90635
  if (seen.has(key)) return [];
90541
90636
  seen.add(key);
90542
- return [{ source: session.item.source, externalId: session.item.externalId, ...observed }];
90637
+ return [{ harness: session.item.harness, harnessSessionId: session.item.harnessSessionId, ...observed }];
90543
90638
  });
90544
90639
  }
90545
90640
  function branchObserver(environment = {}) {
@@ -90577,7 +90672,7 @@ function readIfExists2(p) {
90577
90672
  }
90578
90673
  }
90579
90674
 
90580
- // ../../apps/collector/src/previewRegistration.ts
90675
+ // ../../apps/syncservice/src/previewRegistration.ts
90581
90676
  async function registerAnnouncedPreviews(apiUrl, machineToken, collected, memo2, deps = {}) {
90582
90677
  const readTranscript = deps.readTranscript ?? readIfExists;
90583
90678
  const upload = deps.upload ?? uploadPreviewRegistration;
@@ -90595,7 +90690,11 @@ async function registerAnnouncedPreviews(apiUrl, machineToken, collected, memo2,
90595
90690
  try {
90596
90691
  const text = readTranscript(session.transcriptPath);
90597
90692
  if (text === null) continue;
90598
- const previews = announcedPreviewsFromTurns(parseSessionTurns(session.item.source, text)).filter(
90693
+ const legacyIdentity = legacySessionSourceFromHarness(session.item.harness);
90694
+ if (legacyIdentity.kind === "unsupported") {
90695
+ throw new Error(`Transcript parsing does not support ${session.item.harness}`);
90696
+ }
90697
+ const previews = announcedPreviewsFromTurns(parseSessionTurns(legacyIdentity.source, text)).filter(
90599
90698
  (preview) => preview.url.length <= MAX_PREVIEW_URL_LENGTH && redactText(preview.url) === preview.url
90600
90699
  ).slice(-MAX_REGISTERED_PREVIEWS).map((preview) => ({
90601
90700
  ...preview,
@@ -90607,32 +90706,32 @@ async function registerAnnouncedPreviews(apiUrl, machineToken, collected, memo2,
90607
90706
  continue;
90608
90707
  }
90609
90708
  const outcome = await upload(apiUrl, machineToken, {
90610
- source: session.item.source,
90611
- externalId: session.item.externalId,
90709
+ harness: session.item.harness,
90710
+ harnessSessionId: session.item.harnessSessionId,
90612
90711
  previews
90613
90712
  });
90614
90713
  if (outcome === "foreign-owner") {
90615
90714
  memo2.set(session.transcriptPath, { examinedMtimeMs: session.mtimeMs, foreignOwner: true });
90616
- summary.foreignOwned.push(session.item.externalId);
90715
+ summary.foreignOwned.push(session.item.harnessSessionId);
90617
90716
  continue;
90618
90717
  }
90619
90718
  if (outcome === "previews-off") {
90620
90719
  memo2.set(session.transcriptPath, { examinedMtimeMs: session.mtimeMs, previewsOff: true });
90621
- summary.previewsOff.push(session.item.externalId);
90720
+ summary.previewsOff.push(session.item.harnessSessionId);
90622
90721
  continue;
90623
90722
  }
90624
90723
  memo2.set(session.transcriptPath, { examinedMtimeMs: session.mtimeMs, registeredJson });
90625
90724
  summary.registered += 1;
90626
90725
  } catch (error63) {
90627
90726
  summary.failed.push(
90628
- `${session.item.externalId}: ${error63 instanceof Error ? error63.message : String(error63)}`
90727
+ `${session.item.harnessSessionId}: ${error63 instanceof Error ? error63.message : String(error63)}`
90629
90728
  );
90630
90729
  }
90631
90730
  }
90632
90731
  return summary;
90633
90732
  }
90634
90733
 
90635
- // ../../apps/collector/src/sync.ts
90734
+ // ../../apps/syncservice/src/sync.ts
90636
90735
  var defaultPolicyDeps = {
90637
90736
  fetchPolicy: fetchCapturePolicy,
90638
90737
  load: loadCredentials,
@@ -90828,7 +90927,7 @@ async function runSyncPassInternal(config2, options, diagnostic) {
90828
90927
  for (const failure2 of codex.unreadable) log3(` codex rollout skipped, ${failure2}`);
90829
90928
  if (options.dryRun) {
90830
90929
  for (const s of items.slice(0, 10)) {
90831
- log3(` ${s.externalId} ${s.model ?? "model unmeasured"} ${s.title ?? "(untitled)"}`);
90930
+ log3(` ${s.harnessSessionId} ${s.model ?? "model unmeasured"} ${s.title ?? "(untitled)"}`);
90832
90931
  }
90833
90932
  if (items.length > 10) log3(` ... and ${items.length - 10} more`);
90834
90933
  log3("Dry run, nothing uploaded.");
@@ -90868,13 +90967,13 @@ async function runSyncPassInternal(config2, options, diagnostic) {
90868
90967
  items
90869
90968
  );
90870
90969
  const foreignKeys = new Set(
90871
- foreignOwned.map(({ source, externalId }) => JSON.stringify([source, externalId]))
90970
+ foreignOwned.map(({ harness, harnessSessionId }) => JSON.stringify([harness, harnessSessionId]))
90872
90971
  );
90873
90972
  const writable = collected.filter(
90874
- ({ item }) => !foreignKeys.has(JSON.stringify([item.source, item.externalId]))
90973
+ ({ item }) => !foreignKeys.has(JSON.stringify([item.harness, item.harnessSessionId]))
90875
90974
  );
90876
- for (const { source, externalId } of foreignOwned) {
90877
- log3(`Skipped ${source} session ${externalId}: already synced from another machine.`);
90975
+ for (const { harness, harnessSessionId } of foreignOwned) {
90976
+ log3(`Skipped ${harness} session ${harnessSessionId}: already synced from another machine.`);
90878
90977
  }
90879
90978
  Object.assign(diagnostic, { upserted, unchanged, outOfPolicy, deferred });
90880
90979
  log3(
@@ -91017,7 +91116,7 @@ function failedPassDiagnostic(error63) {
91017
91116
  return error63 instanceof Error ? failedPasses.get(error63) : void 0;
91018
91117
  }
91019
91118
 
91020
- // ../../apps/collector/src/versionSupport.ts
91119
+ // ../../apps/syncservice/src/versionSupport.ts
91021
91120
  var FETCH_TIMEOUT_MS = 3e3;
91022
91121
  var policyEnvelope = external_exports.object({
91023
91122
  data: external_exports.object({
@@ -91057,15 +91156,15 @@ function isUpdateAvailable(cliVersion2, latestVersion) {
91057
91156
  }
91058
91157
  function unsupportedVersionNotice(cliVersion2, oldestSupportedVersion) {
91059
91158
  if (!isUnsupportedVersion(cliVersion2, oldestSupportedVersion)) return null;
91060
- return `\u26A0 Powerplant CLI ${cliVersion2} is no longer supported (oldest supported: ${oldestSupportedVersion}). Update now: powerplant update (or npm install -g @usepowerplant/cli). Unsupported versions can stop working without further notice.`;
91159
+ return `! Powerplant CLI ${cliVersion2} is no longer supported (oldest supported: ${oldestSupportedVersion}). Update now: powerplant update (or npm install -g @usepowerplant/cli). Unsupported versions can stop working without further notice.`;
91061
91160
  }
91062
91161
 
91063
- // ../../apps/collector/src/watch.ts
91162
+ // ../../apps/syncservice/src/watch.ts
91064
91163
  import { existsSync as existsSync8, watch as fsWatch } from "node:fs";
91065
91164
  import os16 from "node:os";
91066
91165
  import path18 from "node:path";
91067
91166
 
91068
- // ../../apps/collector/src/selfRestart.ts
91167
+ // ../../apps/syncservice/src/selfRestart.ts
91069
91168
  import { statSync as statSync3 } from "node:fs";
91070
91169
  var ENTRY_CHECK_INTERVAL_MS = 5 * 6e4;
91071
91170
  function watchEntryForUpdate(entryPath2, onChanged, options = {}) {
@@ -91094,7 +91193,7 @@ function defaultStat(file2) {
91094
91193
  }
91095
91194
  }
91096
91195
 
91097
- // ../../apps/collector/src/watch.ts
91196
+ // ../../apps/syncservice/src/watch.ts
91098
91197
  var WATCH_DEBOUNCE_MS = 5e3;
91099
91198
  var WATCH_MAX_WAIT_MS = 3e4;
91100
91199
  var SAFETY_NET_INTERVAL_MS = 60 * 60 * 1e3;
@@ -91634,12 +91733,12 @@ function describeDelay(ms) {
91634
91733
  return seconds < 120 ? `${seconds}s` : `${Math.round(seconds / 60)} minutes`;
91635
91734
  }
91636
91735
 
91637
- // ../../apps/collector/src/localSessionFacts.ts
91736
+ // ../../apps/syncservice/src/localSessionFacts.ts
91638
91737
  import { existsSync as existsSync9, readdirSync as readdirSync4, statSync as statSync4 } from "node:fs";
91639
91738
  import os17 from "node:os";
91640
91739
  import path20 from "node:path";
91641
91740
 
91642
- // ../../apps/collector/src/codexReviewFacts.ts
91741
+ // ../../apps/syncservice/src/codexReviewFacts.ts
91643
91742
  import { closeSync as closeSync6, lstatSync as lstatSync5, openSync as openSync6, readSync as readSync4, realpathSync as realpathSync3 } from "node:fs";
91644
91743
  import path19 from "node:path";
91645
91744
  var pointerSchema = external_exports.object({
@@ -91709,7 +91808,7 @@ function readPrefix(file2) {
91709
91808
  }
91710
91809
  }
91711
91810
 
91712
- // ../../apps/collector/src/localSessionFacts.ts
91811
+ // ../../apps/syncservice/src/localSessionFacts.ts
91713
91812
  var WORKING_FRESH_MS = 9e4;
91714
91813
  var STORES = [
91715
91814
  {
@@ -91839,12 +91938,51 @@ function localSessionKey(session) {
91839
91938
  return JSON.stringify([session.source, session.externalId]);
91840
91939
  }
91841
91940
 
91941
+ // src/hookPreferences.ts
91942
+ var preferencesSchema = external_exports.object({
91943
+ version: external_exports.literal(1),
91944
+ codexNotFiringDismissed: external_exports.boolean()
91945
+ });
91946
+ function hookPreferencesPath(appEnv, home) {
91947
+ return path21.join(collectorStateDir(home), `hook-preferences-${appEnv}.json`);
91948
+ }
91949
+ function readHookPreferences(appEnv, home) {
91950
+ const file2 = hookPreferencesPath(appEnv, home);
91951
+ try {
91952
+ return preferencesSchema.parse(JSON.parse(readFileSync11(file2, "utf8")));
91953
+ } catch (error63) {
91954
+ if (error63 instanceof Error && "code" in error63 && error63.code === "ENOENT") {
91955
+ return { version: 1, codexNotFiringDismissed: false };
91956
+ }
91957
+ throw new ExpectedCliError(`Cannot read hook preferences at ${file2}. Restore or remove that file, then retry.`, { cause: error63 });
91958
+ }
91959
+ }
91960
+ function readHookPreferencesForMenu(appEnv, home) {
91961
+ try {
91962
+ return { codexHookWarningDismissed: readHookPreferences(appEnv, home).codexNotFiringDismissed };
91963
+ } catch (error63) {
91964
+ if (!(error63 instanceof ExpectedCliError)) throw error63;
91965
+ return { hookPreferencesError: error63.message };
91966
+ }
91967
+ }
91968
+ function dismissCodexHookWarning(appEnv, home) {
91969
+ const preferences = readHookPreferences(appEnv, home);
91970
+ if (preferences.codexNotFiringDismissed) return;
91971
+ const file2 = hookPreferencesPath(appEnv, home);
91972
+ mkdirSync10(path21.dirname(file2), { recursive: true });
91973
+ const temporary = `${file2}.${process.pid}.tmp`;
91974
+ writeFileSync9(temporary, JSON.stringify({ ...preferences, codexNotFiringDismissed: true }, null, 2), { mode: 384 });
91975
+ renameSync5(temporary, file2);
91976
+ }
91977
+
91842
91978
  // src/mcpPreferences.ts
91979
+ import { mkdirSync as mkdirSync11, readFileSync as readFileSync12, renameSync as renameSync6, writeFileSync as writeFileSync10 } from "node:fs";
91980
+ import path22 from "node:path";
91843
91981
  var preferenceSchema = external_exports.object({
91844
91982
  optedIn: external_exports.boolean().optional(),
91845
91983
  dismissedWarning: mcpWarningSchema.optional()
91846
91984
  });
91847
- var preferencesSchema = external_exports.object({
91985
+ var preferencesSchema2 = external_exports.object({
91848
91986
  version: external_exports.literal(1),
91849
91987
  clients: external_exports.object({
91850
91988
  claude: preferenceSchema.optional(),
@@ -91854,12 +91992,12 @@ var preferencesSchema = external_exports.object({
91854
91992
  });
91855
91993
  var emptyMcpPreferences = () => ({ version: 1, clients: {} });
91856
91994
  function mcpPreferencesPath(appEnv, home) {
91857
- return path21.join(collectorStateDir(home), `mcp-preferences-${appEnv}.json`);
91995
+ return path22.join(collectorStateDir(home), `mcp-preferences-${appEnv}.json`);
91858
91996
  }
91859
91997
  function readMcpPreferences(appEnv, home) {
91860
91998
  const file2 = mcpPreferencesPath(appEnv, home);
91861
91999
  try {
91862
- return preferencesSchema.parse(JSON.parse(readFileSync11(file2, "utf8")));
92000
+ return preferencesSchema2.parse(JSON.parse(readFileSync12(file2, "utf8")));
91863
92001
  } catch (error63) {
91864
92002
  if (error63 instanceof Error && "code" in error63 && error63.code === "ENOENT") return emptyMcpPreferences();
91865
92003
  throw new ExpectedCliError(`Cannot read MCP preferences at ${file2}. Restore or remove that file, then retry.`, { cause: error63 });
@@ -91867,10 +92005,10 @@ function readMcpPreferences(appEnv, home) {
91867
92005
  }
91868
92006
  function writeMcpPreferences(appEnv, preferences, home) {
91869
92007
  const file2 = mcpPreferencesPath(appEnv, home);
91870
- mkdirSync10(path21.dirname(file2), { recursive: true });
92008
+ mkdirSync11(path22.dirname(file2), { recursive: true });
91871
92009
  const temporary = `${file2}.${process.pid}.tmp`;
91872
- writeFileSync9(temporary, JSON.stringify(preferencesSchema.parse(preferences), null, 2), { mode: 384 });
91873
- renameSync5(temporary, file2);
92010
+ writeFileSync10(temporary, JSON.stringify(preferencesSchema2.parse(preferences), null, 2), { mode: 384 });
92011
+ renameSync6(temporary, file2);
91874
92012
  }
91875
92013
  function recordMcpChoices(appEnv, offered, selected, home) {
91876
92014
  const preferences = readMcpPreferences(appEnv, home);
@@ -91940,14 +92078,14 @@ function nativeFailureRecord(error63) {
91940
92078
 
91941
92079
  // src/desktopDiagnostics.ts
91942
92080
  import os19 from "node:os";
91943
- import path23 from "node:path";
92081
+ import path24 from "node:path";
91944
92082
 
91945
92083
  // src/memberSessions.ts
91946
92084
  import { execFileSync as execFileSync4 } from "node:child_process";
91947
92085
  import { existsSync as existsSync10 } from "node:fs";
91948
92086
  import { open as open2, readdir as readdir2 } from "node:fs/promises";
91949
92087
  import os18 from "node:os";
91950
- import path22 from "node:path";
92088
+ import path23 from "node:path";
91951
92089
  var memberSessionSchema = external_exports.object({
91952
92090
  id: external_exports.string().min(1),
91953
92091
  source: external_exports.string().min(1),
@@ -92064,10 +92202,10 @@ function detectClaudeDesktop(probe) {
92064
92202
  return detectDesktopScheme(["Claude.app"], "claude", probe);
92065
92203
  }
92066
92204
  function detectDesktopScheme(bundles, scheme, probe = { exists: existsSync10, readUrlSchemes: realReadUrlSchemes }) {
92067
- const roots = ["/Applications", path22.join(os18.homedir(), "Applications")];
92205
+ const roots = ["/Applications", path23.join(os18.homedir(), "Applications")];
92068
92206
  return roots.some(
92069
92207
  (root) => bundles.some((bundle) => {
92070
- const bundlePath = path22.join(root, bundle);
92208
+ const bundlePath = path23.join(root, bundle);
92071
92209
  return probe.exists(bundlePath) && probe.readUrlSchemes(bundlePath).includes(scheme);
92072
92210
  })
92073
92211
  );
@@ -92077,7 +92215,7 @@ function realReadUrlSchemes(bundlePath) {
92077
92215
  try {
92078
92216
  const json2 = execFileSync4(
92079
92217
  "plutil",
92080
- ["-extract", "CFBundleURLTypes", "json", "-o", "-", path22.join(bundlePath, "Contents", "Info.plist")],
92218
+ ["-extract", "CFBundleURLTypes", "json", "-o", "-", path23.join(bundlePath, "Contents", "Info.plist")],
92081
92219
  { stdio: ["ignore", "pipe", "ignore"] }
92082
92220
  ).toString();
92083
92221
  const parsed = urlSchemesSchema.safeParse(JSON.parse(json2));
@@ -92096,7 +92234,7 @@ var claudeDesktopSessionSchema = external_exports.object({
92096
92234
  * and still links: the flag must never cost the row its desktop link. */
92097
92235
  isArchived: external_exports.unknown().optional()
92098
92236
  });
92099
- async function readClaudeDesktopSessions(wanted, root = path22.join(os18.homedir(), "Library/Application Support/Claude/claude-code-sessions")) {
92237
+ async function readClaudeDesktopSessions(wanted, root = path23.join(os18.homedir(), "Library/Application Support/Claude/claude-code-sessions")) {
92100
92238
  const sessions = /* @__PURE__ */ new Map();
92101
92239
  const ambiguous = /* @__PURE__ */ new Set();
92102
92240
  if (wanted.size === 0) return sessions;
@@ -92107,7 +92245,7 @@ async function readClaudeDesktopSessions(wanted, root = path22.join(os18.homedir
92107
92245
  throw error63;
92108
92246
  });
92109
92247
  for (const entry of entries) {
92110
- const file2 = path22.join(directory, entry.name);
92248
+ const file2 = path23.join(directory, entry.name);
92111
92249
  if (entry.isDirectory() && depth < 2) {
92112
92250
  await visit3(file2, depth + 1);
92113
92251
  } else if (depth === 2 && entry.isFile() && /^local_.*\.json$/.test(entry.name)) {
@@ -92147,7 +92285,7 @@ function isMissingFile(error63) {
92147
92285
  }
92148
92286
 
92149
92287
  // src/desktopDiagnostics.ts
92150
- async function probeClaudeDesktopSessions(wanted, installed, reportFault, root = path23.join(os19.homedir(), "Library/Application Support/Claude/claude-code-sessions"), read = readClaudeDesktopSessions) {
92288
+ async function probeClaudeDesktopSessions(wanted, installed, reportFault, root = path24.join(os19.homedir(), "Library/Application Support/Claude/claude-code-sessions"), read = readClaudeDesktopSessions) {
92151
92289
  if (!installed || wanted.size === 0) {
92152
92290
  return { sessions: /* @__PURE__ */ new Map(), diagnostic: { outcome: "not-needed" } };
92153
92291
  }
@@ -92165,24 +92303,24 @@ async function probeClaudeDesktopSessions(wanted, installed, reportFault, root =
92165
92303
  // src/cli.ts
92166
92304
  import { spawn as spawn3 } from "node:child_process";
92167
92305
  import { randomUUID as randomUUID4 } from "node:crypto";
92168
- import { existsSync as existsSync14, mkdirSync as mkdirSync15, openSync as openSync9, realpathSync as realpathSync5, rmSync as rmSync7 } from "node:fs";
92169
- import path32 from "node:path";
92306
+ import { existsSync as existsSync14, mkdirSync as mkdirSync16, openSync as openSync9, realpathSync as realpathSync5, rmSync as rmSync7 } from "node:fs";
92307
+ import path33 from "node:path";
92170
92308
  import { parseArgs } from "node:util";
92171
92309
 
92172
92310
  // src/connect.ts
92173
92311
  import { execFileSync as execFileSync5, spawnSync } from "node:child_process";
92174
92312
  import {
92175
92313
  existsSync as existsSync11,
92176
- mkdirSync as mkdirSync11,
92314
+ mkdirSync as mkdirSync12,
92177
92315
  mkdtempSync,
92178
92316
  readdirSync as readdirSync5,
92179
- readFileSync as readFileSync12,
92317
+ readFileSync as readFileSync13,
92180
92318
  realpathSync as realpathSync4,
92181
92319
  statSync as statSync5,
92182
- writeFileSync as writeFileSync10
92320
+ writeFileSync as writeFileSync11
92183
92321
  } from "node:fs";
92184
92322
  import os20 from "node:os";
92185
- import path24 from "node:path";
92323
+ import path25 from "node:path";
92186
92324
  import { emitKeypressEvents } from "node:readline";
92187
92325
 
92188
92326
  // src/agentVersions.ts
@@ -92256,7 +92394,7 @@ function startTimeBudget(totalMs, now = Date.now) {
92256
92394
  return { remainingMs: () => Math.max(0, deadline - now()) };
92257
92395
  }
92258
92396
  function defaultApplicationsDirs(homeDir) {
92259
- return process.platform === "darwin" ? ["/Applications", path24.join(homeDir, "Applications")] : [];
92397
+ return process.platform === "darwin" ? ["/Applications", path25.join(homeDir, "Applications")] : [];
92260
92398
  }
92261
92399
  function detectClients(options = {}) {
92262
92400
  const homeDir = options.homeDir ?? os20.homedir();
@@ -92284,7 +92422,7 @@ function detectClients(options = {}) {
92284
92422
  clients.push({ client, bin, ...configDir !== void 0 && { configDir } });
92285
92423
  };
92286
92424
  for (const bin of whichAll("claude")) add("claude", bin);
92287
- const localClaude = path24.join(homeDir, ".local", "bin", "claude");
92425
+ const localClaude = path25.join(homeDir, ".local", "bin", "claude");
92288
92426
  if (existsSync11(localClaude)) add("claude", localClaude);
92289
92427
  for (const bin of desktopClaudeBinaries(homeDir)) add("claude", bin);
92290
92428
  const claudeBins = clients.filter((client) => client.client === "claude" && client.configDir === void 0).map((client) => client.bin);
@@ -92292,12 +92430,12 @@ function detectClients(options = {}) {
92292
92430
  for (const bin of claudeBins) add("claude", bin, configDir);
92293
92431
  }
92294
92432
  for (const bin of whichAll("codex")) add("codex", bin);
92295
- const localCodex = path24.join(homeDir, ".local", "bin", "codex");
92433
+ const localCodex = path25.join(homeDir, ".local", "bin", "codex");
92296
92434
  if (existsSync11(localCodex)) add("codex", localCodex);
92297
92435
  for (const bin of codexBundleBinaries(applicationsDirs, bundleSeams)) add("codex", bin);
92298
- const cursorDir = path24.join(homeDir, ".cursor");
92436
+ const cursorDir = path25.join(homeDir, ".cursor");
92299
92437
  if (!options.requireCursorApp && existsSync11(cursorDir) || cursorAppInstalled(applicationsDirs, bundleSeams)) {
92300
- clients.push({ client: "cursor", bin: path24.join(cursorDir, "mcp.json") });
92438
+ clients.push({ client: "cursor", bin: path25.join(cursorDir, "mcp.json") });
92301
92439
  }
92302
92440
  return clients;
92303
92441
  }
@@ -92305,7 +92443,7 @@ function claudeConfigHomes(homeDir, env) {
92305
92443
  const homes = [];
92306
92444
  const seen = /* @__PURE__ */ new Set();
92307
92445
  try {
92308
- seen.add(realpathSync4(path24.join(homeDir, ".claude")));
92446
+ seen.add(realpathSync4(path25.join(homeDir, ".claude")));
92309
92447
  } catch {
92310
92448
  }
92311
92449
  const add = (configDir) => {
@@ -92317,7 +92455,7 @@ function claudeConfigHomes(homeDir, env) {
92317
92455
  }
92318
92456
  if (seen.has(real)) return;
92319
92457
  seen.add(real);
92320
- homes.push(path24.resolve(configDir));
92458
+ homes.push(path25.resolve(configDir));
92321
92459
  };
92322
92460
  let entries = [];
92323
92461
  try {
@@ -92325,8 +92463,8 @@ function claudeConfigHomes(homeDir, env) {
92325
92463
  } catch {
92326
92464
  }
92327
92465
  for (const entry of entries.sort()) {
92328
- if (entry.startsWith(".claude-") && existsSync11(path24.join(homeDir, entry, ".claude.json"))) {
92329
- add(path24.join(homeDir, entry));
92466
+ if (entry.startsWith(".claude-") && existsSync11(path25.join(homeDir, entry, ".claude.json"))) {
92467
+ add(path25.join(homeDir, entry));
92330
92468
  }
92331
92469
  }
92332
92470
  if (env.CLAUDE_CONFIG_DIR) add(env.CLAUDE_CONFIG_DIR);
@@ -92354,7 +92492,7 @@ function appBundles(applicationsDirs, namePrefixes) {
92354
92492
  for (const entry of entries) {
92355
92493
  if (!entry.endsWith(".app")) continue;
92356
92494
  if (!namePrefixes.some((prefix) => entry.startsWith(prefix))) continue;
92357
- bundles.push(path24.join(dir, entry));
92495
+ bundles.push(path25.join(dir, entry));
92358
92496
  }
92359
92497
  }
92360
92498
  return bundles;
@@ -92374,7 +92512,7 @@ function codexBundleBinaries(applicationsDirs, seams) {
92374
92512
  const infoTimeoutMs = budgetedTimeout(BUNDLE_INFO_TIMEOUT_MS, appDir, seams);
92375
92513
  if (infoTimeoutMs === null) continue;
92376
92514
  if (seams.readBundleInfo(appDir, infoTimeoutMs)?.bundleId !== CODEX_BUNDLE_ID) continue;
92377
- const bin = path24.join(appDir, "Contents", "Resources", "codex");
92515
+ const bin = path25.join(appDir, "Contents", "Resources", "codex");
92378
92516
  if (!isExecutableFile(bin)) continue;
92379
92517
  if (!signedByTeam(bin, OPENAI_TEAM_ID, "OpenAI", appDir, seams)) continue;
92380
92518
  found.push(bin);
@@ -92386,7 +92524,7 @@ function trustedCursorBundle(appDir, seams) {
92386
92524
  if (infoTimeoutMs === null) return null;
92387
92525
  const info = seams.readBundleInfo(appDir, infoTimeoutMs);
92388
92526
  if (info?.executable === void 0) return null;
92389
- const bin = path24.join(appDir, "Contents", "MacOS", info.executable);
92527
+ const bin = path25.join(appDir, "Contents", "MacOS", info.executable);
92390
92528
  if (!isExecutableFile(bin)) return null;
92391
92529
  if (!signedByTeam(bin, CURSOR_TEAM_ID, "Cursor", appDir, seams)) return null;
92392
92530
  return info;
@@ -92423,7 +92561,7 @@ var bundleInfoSchema = external_exports.object({
92423
92561
  function realReadBundleInfo(appDir, timeoutMs) {
92424
92562
  const result = spawnSync(
92425
92563
  "plutil",
92426
- ["-convert", "json", "-o", "-", path24.join(appDir, "Contents", "Info.plist")],
92564
+ ["-convert", "json", "-o", "-", path25.join(appDir, "Contents", "Info.plist")],
92427
92565
  { encoding: "utf8", timeout: timeoutMs }
92428
92566
  );
92429
92567
  if (result.status !== 0) return null;
@@ -92445,14 +92583,14 @@ function realVerifySignature(binPath, teamId, timeoutMs) {
92445
92583
  }).status === 0;
92446
92584
  }
92447
92585
  function desktopClaudeBinaries(homeDir) {
92448
- const root = path24.join(homeDir, "Library", "Application Support", "Claude", "claude-code");
92586
+ const root = path25.join(homeDir, "Library", "Application Support", "Claude", "claude-code");
92449
92587
  let versions;
92450
92588
  try {
92451
92589
  versions = readdirSync5(root);
92452
92590
  } catch {
92453
92591
  return [];
92454
92592
  }
92455
- return versions.map((version2) => path24.join(root, version2, "claude.app", "Contents", "MacOS", "claude")).filter((bin) => existsSync11(bin));
92593
+ return versions.map((version2) => path25.join(root, version2, "claude.app", "Contents", "MacOS", "claude")).filter((bin) => existsSync11(bin));
92456
92594
  }
92457
92595
  function defaultWhichAll(name) {
92458
92596
  try {
@@ -92473,7 +92611,7 @@ function runConnect(clients, deps) {
92473
92611
  failed: 0
92474
92612
  };
92475
92613
  if (clients.length === 0) {
92476
- deps.log("No coding agents found (looked for `claude`, `codex`, and Cursor), nothing to connect.");
92614
+ deps.log("No coding agents found (looked for claude, codex, and Cursor)");
92477
92615
  return outcome;
92478
92616
  }
92479
92617
  for (const [agent, candidates] of agents) {
@@ -92523,8 +92661,8 @@ function connectTarget(agent, candidates, all, deps) {
92523
92661
  }
92524
92662
  if (last.state !== "failed") return last;
92525
92663
  if (index < candidates.length - 1) {
92526
- deps.log(`${name} could not be used, ${last.detail}`);
92527
- deps.log(`\u2192 trying another ${AGENT_DISPLAY_NAMES[agent]} installation\u2026`);
92664
+ deps.log(`! ${name}: could not be used, ${last.detail}`);
92665
+ deps.log(`\u2192 ${AGENT_DISPLAY_NAMES[agent]}: trying another installation\u2026`);
92528
92666
  } else {
92529
92667
  deps.log(`\u2717 ${name}: ${last.detail}`);
92530
92668
  }
@@ -92581,17 +92719,18 @@ async function pickAgents(clients, deps) {
92581
92719
  function realCheckboxPrompt(question, choices, seams = {}) {
92582
92720
  const input2 = seams.input ?? process.stdin;
92583
92721
  const output2 = seams.output ?? process.stdout;
92722
+ const indent = seams.indent ?? "";
92584
92723
  const raiseInterrupt = seams.raiseInterrupt ?? (() => process.kill(process.pid, "SIGINT"));
92585
92724
  const selected = new Set(choices.map((choice) => choice.value));
92586
92725
  let active = 0;
92587
92726
  let settled = false;
92588
92727
  const wasRaw = input2.isRaw === true;
92589
92728
  const render = () => [
92590
- `? ${question}`,
92729
+ `${indent}? ${question}`,
92591
92730
  ...choices.map(
92592
- (choice, index) => `${index === active ? "\u276F" : " "} [${selected.has(choice.value) ? "x" : " "}] ${choice.label}`
92731
+ (choice, index) => `${indent}${index === active ? "\u276F" : " "} [${selected.has(choice.value) ? "x" : " "}] ${choice.label}`
92593
92732
  ),
92594
- " \u2191/\u2193 move \xB7 space toggle \xB7 enter confirm"
92733
+ `${indent} \u2191/\u2193 move \xB7 space toggle \xB7 enter confirm`
92595
92734
  ].join("\n");
92596
92735
  const redraw = () => {
92597
92736
  output2.write(`\r\x1B[${choices.length + 1}A\x1B[J${render()}`);
@@ -92685,26 +92824,22 @@ function connectClaude(client, name, deps) {
92685
92824
  const { missing, registeredUrl } = probe;
92686
92825
  if (missing || registeredUrl !== void 0 && registeredUrl !== deps.mcpUrl) {
92687
92826
  if (!missing) {
92688
- deps.log(`${name}: registered against ${registeredUrl}, re-registering for ${deps.mcpUrl}.`);
92827
+ deps.log(`${name} was registered against ${registeredUrl}, re-registering for ${deps.mcpUrl}.`);
92689
92828
  deps.run(bin, ["mcp", "remove", "--scope", "user", deps.serverName], env);
92690
92829
  }
92691
92830
  const add = deps.run(bin, claudeAddArgs(deps), env);
92692
92831
  if (add.status !== 0) {
92693
92832
  return failed(`registering the Powerplant MCP failed, ${describeFailure(add)}`);
92694
92833
  }
92695
- deps.log(`${name}: Powerplant MCP registered (user scope).`);
92696
92834
  } else if (probe.authenticated) {
92697
- deps.log(`\u2713 ${name} MCP already connected`);
92835
+ deps.log(`\u2713 ${name}: MCP already connected`);
92698
92836
  return { state: "connected", unchanged: true };
92699
92837
  } else if (deps.officialClients?.["claude-code"]) {
92700
- deps.log(`${name}: re-registering with the pre-registered client before sign-in.`);
92701
92838
  deps.run(bin, ["mcp", "remove", "--scope", "user", deps.serverName], env);
92702
92839
  const add = deps.run(bin, claudeAddArgs(deps), env);
92703
92840
  if (add.status !== 0) {
92704
92841
  return failed(`registering the Powerplant MCP failed, ${describeFailure(add)}`);
92705
92842
  }
92706
- } else {
92707
- deps.log(`${name}: Powerplant MCP already registered.`);
92708
92843
  }
92709
92844
  return login(bin, name, ["mcp", "login", deps.serverName], deps, env);
92710
92845
  }
@@ -92923,9 +93058,7 @@ function healOrphanCodexOauthTable(name, deps) {
92923
93058
  const { content, changed } = unpatchCodexConfigToml(existing, deps.serverName);
92924
93059
  if (!changed) return;
92925
93060
  deps.writeTextFile(deps.codexConfigPath, content);
92926
- deps.log(
92927
- `${name}: removed leftover sign-in settings from an interrupted setup, codex can read its configuration again.`
92928
- );
93061
+ deps.log(`Removed leftover ${name} sign-in settings from an interrupted setup.`);
92929
93062
  }
92930
93063
  function connectCodex(bin, name, deps) {
92931
93064
  healOrphanCodexOauthTable(name, deps);
@@ -92937,7 +93070,7 @@ function connectCodex(bin, name, deps) {
92937
93070
  const wrongUrl = registeredUrl !== void 0 && registeredUrl !== deps.mcpUrl;
92938
93071
  const alreadyConnected = !missing && !wrongUrl && probe.authenticated;
92939
93072
  if (missing || wrongUrl) {
92940
- if (wrongUrl) deps.log(`${name}: registered against ${registeredUrl}, re-registering for ${deps.mcpUrl}.`);
93073
+ if (wrongUrl) deps.log(`${name} was registered against ${registeredUrl}, re-registering for ${deps.mcpUrl}.`);
92941
93074
  if (codexAddLogsIn(bin, deps)) {
92942
93075
  ensureCodexCallbackPort(name, deps);
92943
93076
  const outcome = login(bin, name, codexAddArgs(deps, { withOfficialClientId: true }), deps);
@@ -92948,27 +93081,21 @@ function connectCodex(bin, name, deps) {
92948
93081
  if (add.status !== 0) {
92949
93082
  return failed(`registering the Powerplant MCP failed, ${describeFailure(add)}`);
92950
93083
  }
92951
- deps.log(`${name}: Powerplant MCP registered.`);
92952
93084
  } else if (alreadyConnected) {
92953
- deps.log(`\u2713 ${name} MCP already connected`);
92954
- } else {
92955
- deps.log(`${name}: Powerplant MCP already registered.`);
93085
+ deps.log(`\u2713 ${name}: MCP already connected`);
92956
93086
  }
92957
93087
  ensureCodexOfficialClient(name, deps);
92958
93088
  if (alreadyConnected) return { state: "connected", unchanged: true };
92959
93089
  return login(bin, name, ["mcp", "login", deps.serverName], deps);
92960
93090
  }
92961
- function applyCodexConfigPatch(name, deps, patch, successLine) {
93091
+ function applyCodexConfigPatch(name, deps, patch) {
92962
93092
  if (patch.conflict !== void 0) {
92963
93093
  deps.log(
92964
- `${name}: ${patch.conflict}, sign-in may fail until the port conflict is resolved; then re-run ${deps.connectCommand}.`
93094
+ `! ${name}: ${patch.conflict}, sign-in may fail until the port conflict is resolved, then re-run ${deps.connectCommand}`
92965
93095
  );
92966
93096
  return;
92967
93097
  }
92968
- if (patch.changed) {
92969
- deps.writeTextFile(deps.codexConfigPath, patch.content);
92970
- deps.log(`${name}: ${successLine}`);
92971
- }
93098
+ if (patch.changed) deps.writeTextFile(deps.codexConfigPath, patch.content);
92972
93099
  }
92973
93100
  function ensureCodexCallbackPort(name, deps) {
92974
93101
  const official = deps.officialClients?.codex;
@@ -92976,8 +93103,7 @@ function ensureCodexCallbackPort(name, deps) {
92976
93103
  applyCodexConfigPatch(
92977
93104
  name,
92978
93105
  deps,
92979
- patchCodexCallbackPort(deps.readTextFile(deps.codexConfigPath), official.callbackPort),
92980
- "OAuth callback port pinned in config.toml."
93106
+ patchCodexCallbackPort(deps.readTextFile(deps.codexConfigPath), official.callbackPort)
92981
93107
  );
92982
93108
  }
92983
93109
  function ensureCodexOfficialClient(name, deps) {
@@ -92991,8 +93117,7 @@ function ensureCodexOfficialClient(name, deps) {
92991
93117
  deps.serverName,
92992
93118
  official.clientId,
92993
93119
  official.callbackPort
92994
- ),
92995
- "pre-registered Powerplant client configured in config.toml."
93120
+ )
92996
93121
  );
92997
93122
  }
92998
93123
  function connectCursor(mcpJsonPath, name, deps) {
@@ -93009,24 +93134,23 @@ function connectCursor(mcpJsonPath, name, deps) {
93009
93134
  );
93010
93135
  }
93011
93136
  if (patch.changed) deps.writeTextFile(mcpJsonPath, patch.content);
93012
- const configured = patch.changed ? "configured" : "already configured";
93013
93137
  if (deps.openUrl(cursorInstallDeeplink(deps.serverName, patch.entry))) {
93014
- deps.log(`\u2192 ${name} ${configured}, approve inside Cursor when it asks.`);
93138
+ deps.log(`\u2192 ${name}: approve inside Cursor when it asks`);
93015
93139
  return { state: "configured", unchanged: !patch.changed };
93016
93140
  }
93017
93141
  deps.log(
93018
- `\u2192 ${name} ${configured}, could not open Cursor; in Cursor's MCP settings, enable the ${deps.serverName} server and sign in.`
93142
+ `! ${name}: could not open Cursor, enable the ${deps.serverName} server in Cursor's MCP settings and sign in`
93019
93143
  );
93020
93144
  return { state: "pending", unchanged: false };
93021
93145
  }
93022
93146
  function login(bin, name, args, deps, env) {
93023
- deps.log(`\u2192 ${name} approve in your browser\u2026`);
93147
+ deps.log(`\u2192 ${name}: approve in your browser\u2026`);
93024
93148
  const status = deps.runInteractive(bin, args, env);
93025
93149
  if (status === 0) {
93026
- deps.log(`\u2713 ${name} MCP connected`);
93150
+ deps.log(`\u2713 ${name}: MCP connected`);
93027
93151
  return { state: "connected", unchanged: false };
93028
93152
  }
93029
- deps.log(`\u2192 ${name} MCP sign-in not completed, finish later with: ${deps.connectCommand}`);
93153
+ deps.log(`! ${name}: sign-in not completed`);
93030
93154
  return { state: "pending", unchanged: false };
93031
93155
  }
93032
93156
  function runDisconnect(clients, deps) {
@@ -93069,7 +93193,7 @@ function disconnectTarget(agent, candidates, deps) {
93069
93193
  }
93070
93194
  if (last !== "failed") return last;
93071
93195
  if (index < candidates.length - 1) {
93072
- deps.log(`\u2192 trying another ${AGENT_DISPLAY_NAMES[agent]} installation\u2026`);
93196
+ deps.log(`\u2192 ${AGENT_DISPLAY_NAMES[agent]}: trying another installation\u2026`);
93073
93197
  }
93074
93198
  }
93075
93199
  return last;
@@ -93155,11 +93279,11 @@ function anyClientStillConnected(clients, deps) {
93155
93279
  });
93156
93280
  }
93157
93281
  function describeBinary(bin) {
93158
- return `${path24.basename(bin)} (${bin.replace(os20.homedir(), "~")})`;
93282
+ return `${path25.basename(bin)} (${bin.replace(os20.homedir(), "~")})`;
93159
93283
  }
93160
93284
  function describeClaudeTarget(client) {
93161
93285
  if (client.configDir === void 0) return describeBinary(client.bin);
93162
- return `${path24.basename(client.bin)} (${client.configDir.replace(os20.homedir(), "~")})`;
93286
+ return `${path25.basename(client.bin)} (${client.configDir.replace(os20.homedir(), "~")})`;
93163
93287
  }
93164
93288
  var FAILURE_DETAIL_MAX_CHARS = 200;
93165
93289
  function describeFailure(result) {
@@ -93172,7 +93296,7 @@ function describeFailure(result) {
93172
93296
  }
93173
93297
  var neutralDirMemo;
93174
93298
  function neutralWorkdir() {
93175
- neutralDirMemo ??= mkdtempSync(path24.join(os20.tmpdir(), "powerplant-connect-"));
93299
+ neutralDirMemo ??= mkdtempSync(path25.join(os20.tmpdir(), "powerplant-connect-"));
93176
93300
  return neutralDirMemo;
93177
93301
  }
93178
93302
  async function fetchOfficialClients(apiUrl, log3) {
@@ -93202,25 +93326,25 @@ async function fetchOfficialClients(apiUrl, log3) {
93202
93326
  }
93203
93327
  function realReadTextFile(filePath) {
93204
93328
  try {
93205
- return readFileSync12(filePath, "utf8");
93329
+ return readFileSync13(filePath, "utf8");
93206
93330
  } catch {
93207
93331
  return null;
93208
93332
  }
93209
93333
  }
93210
93334
  function realReadTextFileStrict(filePath) {
93211
93335
  try {
93212
- return readFileSync12(filePath, "utf8");
93336
+ return readFileSync13(filePath, "utf8");
93213
93337
  } catch (error63) {
93214
93338
  if (error63 instanceof Error && error63.code === "ENOENT") return null;
93215
93339
  throw error63;
93216
93340
  }
93217
93341
  }
93218
93342
  function realWriteTextFile(filePath, content) {
93219
- mkdirSync11(path24.dirname(filePath), { recursive: true });
93220
- writeFileSync10(filePath, content);
93343
+ mkdirSync12(path25.dirname(filePath), { recursive: true });
93344
+ writeFileSync11(filePath, content);
93221
93345
  }
93222
93346
  function codexConfigPath(homeDir = os20.homedir()) {
93223
- return path24.join(process.env.CODEX_HOME ?? path24.join(homeDir, ".codex"), "config.toml");
93347
+ return path25.join(process.env.CODEX_HOME ?? path25.join(homeDir, ".codex"), "config.toml");
93224
93348
  }
93225
93349
  function realOpenUrl(url2) {
93226
93350
  const bin = process.platform === "darwin" ? "open" : process.platform === "linux" ? "xdg-open" : null;
@@ -93281,8 +93405,8 @@ function realRunInteractive(bin, args, env) {
93281
93405
 
93282
93406
  // src/connections.ts
93283
93407
  import { execFileSync as execFileSync6, spawnSync as spawnSync2 } from "node:child_process";
93284
- import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync11 } from "node:fs";
93285
- import path25 from "node:path";
93408
+ import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync12 } from "node:fs";
93409
+ import path26 from "node:path";
93286
93410
  function probeConnections(clients, deps) {
93287
93411
  const reports = [];
93288
93412
  for (const kind of ["claude", "codex", "cursor"]) {
@@ -93326,7 +93450,7 @@ function aggregateClaudeTargets(targets) {
93326
93450
  if (targets.length === 1 || worst.report.state === "signed-in") return worst.report;
93327
93451
  return {
93328
93452
  ...worst.report,
93329
- target: worst.configDir === void 0 ? "default profile" : path25.basename(worst.configDir)
93453
+ target: worst.configDir === void 0 ? "default profile" : path26.basename(worst.configDir)
93330
93454
  };
93331
93455
  }
93332
93456
  function probeClient(client, deps) {
@@ -93405,12 +93529,12 @@ var detectedClientsSchema = external_exports.object({
93405
93529
  )
93406
93530
  });
93407
93531
  function detectedClientsPath(homeDir) {
93408
- return path25.join(collectorStateDir(homeDir), "detected-clients.json");
93532
+ return path26.join(collectorStateDir(homeDir), "detected-clients.json");
93409
93533
  }
93410
93534
  function saveDetectedClients(clients, pathValue, homeDir) {
93411
93535
  try {
93412
93536
  const file2 = detectedClientsPath(homeDir);
93413
- mkdirSync12(path25.dirname(file2), { recursive: true });
93537
+ mkdirSync13(path26.dirname(file2), { recursive: true });
93414
93538
  const record2 = {
93415
93539
  detectedAt: (/* @__PURE__ */ new Date()).toISOString(),
93416
93540
  path: pathValue,
@@ -93420,7 +93544,7 @@ function saveDetectedClients(clients, pathValue, homeDir) {
93420
93544
  ...configDir !== void 0 && { configDir }
93421
93545
  }))
93422
93546
  };
93423
- writeFileSync11(file2, JSON.stringify(record2, null, 2));
93547
+ writeFileSync12(file2, JSON.stringify(record2, null, 2));
93424
93548
  } catch {
93425
93549
  }
93426
93550
  }
@@ -93497,7 +93621,7 @@ function whichAllWith(pathValue) {
93497
93621
  import { closeSync as closeSync7, fstatSync, openSync as openSync7, readSync as readSync5 } from "node:fs";
93498
93622
 
93499
93623
  // src/update.ts
93500
- import path27 from "node:path";
93624
+ import path28 from "node:path";
93501
93625
 
93502
93626
  // src/duration.ts
93503
93627
  function duration3(ms) {
@@ -93515,11 +93639,11 @@ function ago(ms) {
93515
93639
  }
93516
93640
 
93517
93641
  // src/installOwner.ts
93518
- import { accessSync, constants as constants2, readFileSync as readFileSync13 } from "node:fs";
93519
- import path26 from "node:path";
93642
+ import { accessSync, constants as constants2, readFileSync as readFileSync14 } from "node:fs";
93643
+ import path27 from "node:path";
93520
93644
 
93521
93645
  // src/version.ts
93522
- var CLI_VERSION = true ? "0.4.14" : "0.0.0-checkout";
93646
+ var CLI_VERSION = true ? "0.4.15" : "0.0.0-checkout";
93523
93647
  var CLI_RELEASE_BUILD = true ? true : false;
93524
93648
  var CLI_PACKAGE_NAME = "@usepowerplant/cli";
93525
93649
 
@@ -93543,13 +93667,13 @@ function inspectInstall(entryPath2, env) {
93543
93667
  inPlace: { ok: false, reason: `the install at ${packageDir} isn't a layout this CLI recognises` }
93544
93668
  };
93545
93669
  }
93546
- const modulesDir = path26.dirname(path26.dirname(packageDir));
93547
- const prefix = manager === "npm" ? path26.dirname(path26.dirname(modulesDir)) : null;
93670
+ const modulesDir = path27.dirname(path27.dirname(packageDir));
93671
+ const prefix = manager === "npm" ? path27.dirname(path27.dirname(modulesDir)) : null;
93548
93672
  const group = /^(.*\/global\/v11\/[^/]+)\/node_modules\//.exec(packageDir)?.[1];
93549
93673
  if (manager === "pnpm" && group !== void 0) {
93550
93674
  let dependencies = [];
93551
93675
  try {
93552
- const raw = env.readTextFile?.(path26.join(group, "package.json"));
93676
+ const raw = env.readTextFile?.(path27.join(group, "package.json"));
93553
93677
  const manifest = external_exports.object({ dependencies: external_exports.record(external_exports.string(), external_exports.string()) }).parse(JSON.parse(raw ?? "null"));
93554
93678
  dependencies = Object.keys(manifest.dependencies);
93555
93679
  } catch {
@@ -93576,7 +93700,7 @@ function detectManager(packageDir, pnpmHome) {
93576
93700
  return null;
93577
93701
  }
93578
93702
  function linkedEntryPath(realEntryPath, invokedEntryPath) {
93579
- if (invokedEntryPath !== void 0 && /\/global\/v11\/[^/]+\/node_modules\//.test(invokedEntryPath) && invokedEntryPath.endsWith(`${PACKAGE_SEGMENT}dist/cli.js`)) return path26.normalize(invokedEntryPath);
93703
+ if (invokedEntryPath !== void 0 && /\/global\/v11\/[^/]+\/node_modules\//.test(invokedEntryPath) && invokedEntryPath.endsWith(`${PACKAGE_SEGMENT}dist/cli.js`)) return path27.normalize(invokedEntryPath);
93580
93704
  const store = realEntryPath.lastIndexOf("/.pnpm/");
93581
93705
  if (store === -1) return realEntryPath;
93582
93706
  const at = realEntryPath.indexOf(PACKAGE_SEGMENT, store);
@@ -93603,7 +93727,7 @@ function manualUpdateCommand(manager, version2, prefix = null, channel3 = "lates
93603
93727
  return [bin, ...args].join(" ");
93604
93728
  }
93605
93729
  function installedVersion(packageDir, readTextFile) {
93606
- const raw = readTextFile(path26.join(packageDir, "package.json"));
93730
+ const raw = readTextFile(path27.join(packageDir, "package.json"));
93607
93731
  if (raw === null) return null;
93608
93732
  try {
93609
93733
  const parsed = JSON.parse(raw);
@@ -93620,7 +93744,7 @@ function realInspectEnvironment() {
93620
93744
  pnpmHome: process.env.PNPM_HOME,
93621
93745
  readTextFile: (file2) => {
93622
93746
  try {
93623
- return readFileSync13(file2, "utf8");
93747
+ return readFileSync14(file2, "utf8");
93624
93748
  } catch (error63) {
93625
93749
  if (error63 instanceof Error && "code" in error63 && error63.code === "ENOENT") return null;
93626
93750
  throw error63;
@@ -93669,10 +93793,10 @@ function releaseNotServed(managerOutput) {
93669
93793
  return /\bETARGET\b|\bnotarget\b|ERR_PNPM_NO_MATCHING_VERSION/.test(managerOutput);
93670
93794
  }
93671
93795
  function updateProgressPath(homeDir) {
93672
- return path27.join(collectorStateDir(homeDir), "cli-update.json");
93796
+ return path28.join(collectorStateDir(homeDir), "cli-update.json");
93673
93797
  }
93674
93798
  function updateLogPath(homeDir) {
93675
- return path27.join(collectorStateDir(homeDir), "cli-update.log");
93799
+ return path28.join(collectorStateDir(homeDir), "cli-update.log");
93676
93800
  }
93677
93801
  function readUpdateProgress(readTextFile, file2 = updateProgressPath()) {
93678
93802
  const raw = readTextFile(file2);
@@ -93835,34 +93959,33 @@ function automaticUpdatesChoice(control) {
93835
93959
  return control.autoUpdate ? "on" : "off";
93836
93960
  }
93837
93961
  async function offerAutomaticUpdates(deps, options) {
93838
- const { log: log3, indent } = options;
93962
+ const { output: output2 } = options;
93839
93963
  if (deps.readControl().autoUpdate !== void 0) return "already-chosen";
93840
- const offCommand = "powerplant update --automatic off";
93841
93964
  if (!options.promptAllowed) {
93842
93965
  deps.set(true);
93843
- log3(`${indent}\u2713 Automatic updates on (the default), turn off any time with \`${offCommand}\``);
93966
+ output2.log("\u2713 Automatic updates on");
93844
93967
  return "on";
93845
93968
  }
93846
93969
  for (; ; ) {
93847
93970
  const answer = await deps.promptLine(
93848
- `${indent}Keep the Powerplant CLI up to date automatically? (recommended) [Y/n] `
93971
+ `${output2.indent}Keep the Powerplant CLI up to date automatically? (recommended) [Y/n] `
93849
93972
  );
93850
93973
  if (answer === null) {
93851
- log3(`${indent}Automatic updates left off, turn on with \`powerplant update --automatic on\``);
93974
+ output2.log(`Automatic updates left off, turn on with \`powerplant update --automatic on\``);
93852
93975
  return "left-unchosen";
93853
93976
  }
93854
93977
  const normalized = answer.trim().toLowerCase();
93855
93978
  if (normalized === "" || normalized === "y" || normalized === "yes") {
93856
93979
  deps.set(true);
93857
- log3(`${indent}\u2713 Automatic updates on, turn off any time with \`${offCommand}\``);
93980
+ output2.log("\u2713 Automatic updates on");
93858
93981
  return "on";
93859
93982
  }
93860
93983
  if (normalized === "n" || normalized === "no") {
93861
93984
  deps.set(false);
93862
- log3(`${indent}Automatic updates off, turn on with \`powerplant update --automatic on\``);
93985
+ output2.log(`Automatic updates off, turn on with \`powerplant update --automatic on\``);
93863
93986
  return "off";
93864
93987
  }
93865
- log3(`${indent}Please answer y or n.`);
93988
+ output2.log("Please answer y or n.");
93866
93989
  }
93867
93990
  }
93868
93991
  function parseAutomaticFlag(value) {
@@ -93902,13 +94025,13 @@ function redactedLogTail(raw) {
93902
94025
  while (lines.length > 0 && lines[lines.length - 1]?.trim() === "") lines.pop();
93903
94026
  return lines.slice(-DOCTOR_LOG_TAIL_LINES);
93904
94027
  }
93905
- function readDoctorLogTail(path33) {
94028
+ function readDoctorLogTail(path34) {
93906
94029
  let fd;
93907
94030
  try {
93908
- fd = openSync7(path33, "r");
94031
+ fd = openSync7(path34, "r");
93909
94032
  } catch (error63) {
93910
- if (error63.code === "ENOENT") return { path: path33, lines: null };
93911
- return { path: path33, lines: null, readError: error63 instanceof Error ? error63.message : String(error63) };
94033
+ if (error63.code === "ENOENT") return { path: path34, lines: null };
94034
+ return { path: path34, lines: null, readError: error63 instanceof Error ? error63.message : String(error63) };
93912
94035
  }
93913
94036
  try {
93914
94037
  const size = fstatSync(fd).size;
@@ -93917,9 +94040,9 @@ function readDoctorLogTail(path33) {
93917
94040
  readSync5(fd, buffer, 0, buffer.length, offset);
93918
94041
  let text = buffer.toString("utf8");
93919
94042
  if (offset > 0) text = text.slice(text.indexOf("\n") + 1);
93920
- return { path: path33, lines: redactedLogTail(text) };
94043
+ return { path: path34, lines: redactedLogTail(text) };
93921
94044
  } catch (error63) {
93922
- return { path: path33, lines: null, readError: error63 instanceof Error ? error63.message : String(error63) };
94045
+ return { path: path34, lines: null, readError: error63 instanceof Error ? error63.message : String(error63) };
93923
94046
  } finally {
93924
94047
  closeSync7(fd);
93925
94048
  }
@@ -94020,8 +94143,9 @@ function serviceLines(i) {
94020
94143
  }
94021
94144
  }
94022
94145
  for (const hook of status.hooks ?? []) {
94146
+ const silence = hookWarning(hook, i.now);
94023
94147
  out.push(
94024
- hook.silence ? `Hooks (${hook.harness}): ${hook.silence.problem}. ${hook.silence.fix}` : `Hooks (${hook.harness}): ${hook.state}, install ${hook.install}`
94148
+ silence ? `Hooks (${hook.harness}): ${silence.problem}. ${silence.fix}` : `Hooks (${hook.harness}): ${hook.state}, install ${hook.install}`
94025
94149
  );
94026
94150
  }
94027
94151
  return out;
@@ -94078,6 +94202,7 @@ function isCliEnv(value) {
94078
94202
  return value in CLI_ENVIRONMENTS;
94079
94203
  }
94080
94204
  function describeEnvironment(config2, env, explicitEnv) {
94205
+ if (config2.appEnv === "production") return null;
94081
94206
  const steeredByEnvVar = explicitEnv === void 0 && env.POWERPLANT_ENV !== void 0;
94082
94207
  return `Environment: ${config2.appEnv} (API ${config2.apiUrl})${steeredByEnvVar ? ", set by POWERPLANT_ENV" : ""}`;
94083
94208
  }
@@ -94174,36 +94299,36 @@ function pausedSince(control, now) {
94174
94299
  }
94175
94300
  function pausedNotice(control, resumeCommand2, now) {
94176
94301
  if (!control.paused) return null;
94177
- return `\u23F8 ${pausedSince(control, now)}. Nothing uploads until you run \`${resumeCommand2}\`.`;
94302
+ return `! ${pausedSince(control, now)}. Nothing uploads until you run \`${resumeCommand2}\`.`;
94178
94303
  }
94179
94304
  function pausedSyncNotice(control, resumeCommand2, now, dryRun) {
94180
94305
  if (!control.paused || dryRun) return pausedNotice(control, resumeCommand2, now);
94181
- return `\u23F8 ${pausedSince(control, now)}. This pass uploads because you asked for it. Background syncing stays paused until you run \`${resumeCommand2}\`.`;
94306
+ return `! ${pausedSince(control, now)}. This pass uploads because you asked for it. Background syncing stays paused until you run \`${resumeCommand2}\`.`;
94182
94307
  }
94183
94308
  async function offerResume(deps, options) {
94184
- const { log: log3, indent } = options;
94309
+ const { output: output2 } = options;
94185
94310
  const control = deps.readControl();
94186
94311
  if (!control.paused) return "not-paused";
94187
94312
  const now = deps.now();
94188
94313
  const age = pausedFor(control, now);
94189
- log3(`${indent}! ${pausedSince(control, now)}, the background sync is running but uploads nothing`);
94190
- if (options.promptAllowed && await confirmResume(deps, log3, indent)) {
94314
+ output2.log(`! ${pausedSince(control, now)}, the background sync is running but uploads nothing`);
94315
+ if (options.promptAllowed && await confirmResume(deps, output2)) {
94191
94316
  deps.resume();
94192
- log3(
94193
- `${indent}\u2713 Syncing resumed, the background sync is catching up on ${age === null ? "the pause" : `the paused ${age}`}`
94317
+ output2.log(
94318
+ `\u2713 Syncing resumed, the background sync is catching up on ${age === null ? "the pause" : `the paused ${age}`}`
94194
94319
  );
94195
94320
  return "resumed";
94196
94321
  }
94197
- log3(`${indent}Nothing uploads until you run \`${deps.resumeCommand}\``);
94322
+ output2.log(`Nothing uploads until you run \`${deps.resumeCommand}\``);
94198
94323
  return "still-paused";
94199
94324
  }
94200
- async function confirmResume(deps, log3, indent) {
94325
+ async function confirmResume(deps, output2) {
94201
94326
  for (; ; ) {
94202
- const answer = await deps.promptLine(`${indent}Resume syncing now? [Y/n] `);
94327
+ const answer = await deps.promptLine(`${output2.indent}Resume syncing now? [Y/n] `);
94203
94328
  const normalized = answer?.trim().toLowerCase() ?? "";
94204
94329
  if (answer === null || normalized === "n" || normalized === "no") return false;
94205
94330
  if (normalized === "" || normalized === "y" || normalized === "yes") return true;
94206
- log3(`${indent}Please answer "y" or "n".`);
94331
+ output2.log('Please answer "y" or "n".');
94207
94332
  }
94208
94333
  }
94209
94334
 
@@ -94231,39 +94356,43 @@ function syncNote(credentials) {
94231
94356
  return `Uploads nothing yet, ${org} has no GitHub integration.`;
94232
94357
  }
94233
94358
  }
94359
+ function initExitCode(summary) {
94360
+ return summary === "ready" || summary === "already-set-up" ? 0 : 1;
94361
+ }
94362
+ function enrolledLine(credentials) {
94363
+ return `\u2713 ${credentials.machineName} enrolled${credentials.orgName ? ` in ${credentials.orgName}` : ""}`;
94364
+ }
94234
94365
  async function runInit(deps) {
94235
- const { log: log3 } = deps;
94366
+ const { command, stage } = deps.terminal;
94236
94367
  const existing = deps.loadCredentials();
94237
- log3("\u26A1 Powerplant");
94238
- log3(` ${existing ? "Checking" : "Setting up"} this machine \xB7 ${deps.environmentName}`);
94239
- log3("");
94368
+ command.log("\u26A1 Powerplant");
94369
+ command.detail(`${existing ? "Checking" : "Setting up"} this machine \xB7 ${deps.environmentName}`);
94370
+ command.log("");
94371
+ command.log("1/3 Enroll this machine");
94240
94372
  let enrolled = false;
94241
94373
  let credentials;
94242
94374
  if (existing) {
94243
- log3(
94244
- `\u2713 Machine enrolled as ${existing.machineName}${existing.orgName ? ` in ${existing.orgName}` : ""}`
94375
+ stage.log(
94376
+ `\u2713 Already enrolled as ${existing.machineName}${existing.orgName ? ` in ${existing.orgName}` : ""}`
94245
94377
  );
94246
94378
  credentials = existing;
94247
94379
  } else {
94248
- log3("1/3 Enroll this machine");
94249
- credentials = await deps.activity("Waiting for approval in your browser\u2026", deps.enroll);
94250
- log3(
94251
- ` \u2713 ${credentials.machineName} enrolled${credentials.orgName ? ` in ${credentials.orgName}` : ""}`
94252
- );
94380
+ credentials = await stage.activity("Waiting for approval in your browser\u2026", deps.enroll);
94381
+ stage.log(enrolledLine(credentials));
94253
94382
  enrolled = true;
94254
94383
  }
94255
- log3("");
94384
+ command.log("");
94256
94385
  const orgName = credentials.orgName;
94257
94386
  let repoDiscoveryDidWork = false;
94258
94387
  let protectedFoldersNeedAttention = false;
94259
94388
  let installed = false;
94260
94389
  let menubarDidWork = false;
94261
94390
  let pauseOffer = "not-paused";
94262
- log3("2/3 Start background sync");
94263
- log3(" When syncing is enabled, session transcripts upload to Powerplant for the team whose capture settings match the repository.");
94264
- log3(` ${syncNote(credentials)}`);
94391
+ command.log("2/3 Start background sync");
94392
+ stage.log("When syncing is enabled, session transcripts upload to Powerplant for the team whose capture settings match the repository.");
94393
+ stage.log(syncNote(credentials));
94265
94394
  if (deps.platform === "darwin") {
94266
- const protectedSessions = await deps.activity(
94395
+ const protectedSessions = await stage.activity(
94267
94396
  "Checking recent session locations\u2026",
94268
94397
  deps.findProtectedSessions
94269
94398
  );
@@ -94276,54 +94405,54 @@ async function runInit(deps) {
94276
94405
  const toProbe = [];
94277
94406
  let needsAttention = false;
94278
94407
  if (fresh.length > 0) {
94279
- log3(" Coding agents recorded recent sessions in folders macOS is currently hiding from Powerplant:");
94280
- logProtectedFolders(log3, fresh);
94408
+ stage.log("Coding agents recorded recent sessions in folders macOS is currently hiding from Powerplant:");
94409
+ logProtectedFolders(stage, fresh);
94281
94410
  if (!deps.promptAllowed) {
94282
94411
  needsAttention = true;
94283
- logProtectedSessionsStayLocal(log3, fresh);
94284
- log3(` Run \`powerplant init\` in a terminal to ${consented ? "scan" : "review"} them.`);
94412
+ logProtectedSessionsStayLocal(stage, fresh);
94413
+ stage.detail(`Run \`powerplant init\` in a terminal to ${consented ? "scan" : "review"} them.`);
94285
94414
  } else {
94286
- log3(
94287
- consented ? ` You already allowed Git metadata scans. Checking those folders for ${org}'s work repositories.` : ` If you allow it, Powerplant reads only Git metadata there, to find ${org}'s work repositories.`
94415
+ stage.log(
94416
+ consented ? `You already allowed Git metadata scans. Checking those folders for ${org}'s work repositories.` : `If you allow it, Powerplant reads only Git metadata there, to find ${org}'s work repositories.`
94288
94417
  );
94289
- if (consented || await confirmProtectedRepoDiscovery(deps)) toProbe.push(...fresh);
94418
+ if (consented || await confirmProtectedRepoDiscovery(deps, stage)) toProbe.push(...fresh);
94290
94419
  else {
94291
94420
  needsAttention = true;
94292
- logProtectedSessionsStayLocal(log3, fresh);
94421
+ logProtectedSessionsStayLocal(stage, fresh);
94293
94422
  }
94294
94423
  }
94295
94424
  }
94296
94425
  if (blocked.length > 0) {
94297
94426
  if (deps.promptAllowed) {
94298
- log3(` Checking whether macOS still blocks ${displayRoots(blocked)}.`);
94427
+ stage.log(`Checking whether macOS still blocks ${displayRoots(blocked)}.`);
94299
94428
  toProbe.push(...blocked);
94300
94429
  } else {
94301
94430
  needsAttention = true;
94302
- logBlockedByMacOS(log3, blocked);
94431
+ logBlockedByMacOS(stage, blocked);
94303
94432
  }
94304
94433
  }
94305
94434
  if (toProbe.length > 0) {
94306
- log3(' macOS may label Powerplant as "node" because Powerplant runs on Node.js.');
94435
+ stage.log('macOS may label Powerplant as "node" because Powerplant runs on Node.js.');
94307
94436
  const probe = async (roots) => {
94308
- const result2 = await deps.activity(
94437
+ const result2 = await stage.activity(
94309
94438
  "Scanning recorded session folders for Git repositories\u2026",
94310
94439
  () => deps.allowProtectedRepoDiscovery(roots)
94311
94440
  );
94312
- needsAttention = reportProtectedRepoDiscovery(log3, result2) || needsAttention;
94441
+ needsAttention = reportProtectedRepoDiscovery(stage, result2) || needsAttention;
94313
94442
  const unblocked = result2.unmatched.filter((entry) => reviewOf(entry) === "blocked");
94314
94443
  if (unblocked.length > 0) {
94315
- log3(` \u2713 macOS now lets Powerplant read ${displayRoots(unblocked)}. No work repositories were found there.`);
94444
+ stage.log(`\u2713 macOS now lets Powerplant read ${displayRoots(unblocked)}. No work repositories were found there.`);
94316
94445
  }
94317
94446
  if (result2.enabled.length > 0 || unblocked.length > 0) repoDiscoveryDidWork = true;
94318
94447
  return result2;
94319
94448
  };
94320
94449
  const result = await probe(toProbe);
94321
94450
  if (result.needsReview.length > 0) {
94322
- log3(" Some of those sessions use Git checkouts in other folders macOS is hiding from Powerplant:");
94323
- logProtectedFolders(log3, result.needsReview);
94451
+ stage.log("Some of those sessions use Git checkouts in other folders macOS is hiding from Powerplant:");
94452
+ logProtectedFolders(stage, result.needsReview);
94324
94453
  const second = await probe([...result.unreviewed, ...result.needsReview]);
94325
94454
  if (second.unreviewed.length > 0) {
94326
- logProtectedSessionsStayLocal(log3, second.unreviewed);
94455
+ logProtectedSessionsStayLocal(stage, second.unreviewed);
94327
94456
  needsAttention = true;
94328
94457
  }
94329
94458
  }
@@ -94332,137 +94461,125 @@ async function runInit(deps) {
94332
94461
  }
94333
94462
  }
94334
94463
  if (deps.platform !== "darwin") {
94335
- log3(
94336
- " Background sync is macOS-only for now. Run `powerplant sync` on a schedule of your choosing instead."
94464
+ stage.log(
94465
+ "Background sync is macOS-only for now. Run `powerplant sync` on a schedule of your choosing instead."
94337
94466
  );
94338
94467
  } else {
94339
94468
  const fresh = !deps.serviceUpToDate();
94340
94469
  if (fresh) {
94341
- await deps.activity("Installing background sync\u2026", deps.installService);
94342
- await deps.activity("Checking background sync version\u2026", () => deps.ensureServiceVersion(true));
94470
+ await stage.activity("Installing background sync\u2026", deps.installService);
94471
+ await stage.activity("Checking background sync version\u2026", () => deps.ensureServiceVersion(true));
94343
94472
  installed = true;
94344
94473
  } else {
94345
- installed = await deps.activity("Checking background sync version\u2026", () => deps.ensureServiceVersion(false));
94474
+ installed = await stage.activity("Checking background sync version\u2026", () => deps.ensureServiceVersion(false));
94346
94475
  }
94347
- pauseOffer = await offerResume(deps.pause, { log: log3, indent: " ", promptAllowed: deps.promptAllowed });
94348
- if (pauseOffer === "not-paused") log3(fresh ? " \u2713 Background sync is running" : "\u2713 Background sync is running");
94349
- await offerAutomaticUpdates(deps.autoUpdate, { log: log3, indent: " ", promptAllowed: deps.promptAllowed });
94476
+ pauseOffer = await offerResume(deps.pause, { output: stage, promptAllowed: deps.promptAllowed });
94477
+ if (pauseOffer === "not-paused") stage.log("\u2713 Background sync is running");
94478
+ await offerAutomaticUpdates(deps.autoUpdate, { output: stage, promptAllowed: deps.promptAllowed });
94350
94479
  if (deps.menubarApp !== null) {
94351
- const app = await deps.activity("Setting up the menu bar app\u2026", deps.menubarApp);
94352
- menubarDidWork = narrateMenubarApp(log3, app);
94480
+ const app = await stage.activity("Setting up the menu bar app\u2026", deps.menubarApp);
94481
+ menubarDidWork = narrateMenubarApp(stage, app);
94353
94482
  }
94354
94483
  }
94355
- log3("");
94356
- log3("3/3 Give your agents Powerplant MCP access");
94484
+ command.log("");
94485
+ command.log("3/3 Give your agents Powerplant MCP access");
94357
94486
  let outcome = null;
94358
94487
  try {
94359
94488
  outcome = await deps.connect();
94360
94489
  } catch (error63) {
94361
- log3(` \u2717 Could not give your agents Powerplant MCP access, ${error63 instanceof Error ? error63.message : String(error63)}`);
94490
+ stage.log(`\u2717 Could not give your agents Powerplant MCP access, ${error63 instanceof Error ? error63.message : String(error63)}`);
94362
94491
  }
94363
94492
  if (outcome?.found === 0) {
94364
- log3(
94365
- deps.platform === "darwin" ? ` This machine still syncs once one is installed, then run: ${deps.connectCommand}` : ` Once one is installed, run: ${deps.connectCommand}`
94366
- );
94493
+ stage.log(`Once one is installed, run \`${deps.connectCommand}\``);
94367
94494
  }
94368
- log3("");
94495
+ command.log("");
94369
94496
  const connectDidWork = outcome !== null && outcome.connected + outcome.configured > outcome.unchanged;
94370
94497
  const connectSettled = outcome !== null && outcome.found > 0 && outcome.pending === 0 && outcome.failed === 0 && outcome.skipped === 0 && outcome.unchanged === outcome.found && !connectDidWork;
94371
94498
  if (!enrolled && !installed && !menubarDidWork && !repoDiscoveryDidWork && !protectedFoldersNeedAttention && pauseOffer === "not-paused" && connectSettled) {
94372
- log3("Everything is already set up.");
94373
- return;
94499
+ command.log("\u2713 Everything is already set up");
94500
+ return "already-set-up";
94374
94501
  }
94375
94502
  const connectedAny = outcome !== null && outcome.connected + outcome.configured > 0;
94376
94503
  const connectIncomplete = outcome === null || outcome.pending > 0 || outcome.failed > 0 || outcome.skipped > 0 && !connectedAny;
94377
94504
  if (pauseOffer === "still-paused") {
94378
- log3("! Syncing is paused");
94379
- log3("");
94380
- log3(`Nothing uploads until you run \`${deps.pause.resumeCommand}\``);
94381
- if (connectIncomplete) log3(`Finish MCP setup: ${deps.connectCommand}`);
94382
- return;
94505
+ command.log("! Syncing is paused");
94506
+ command.log("");
94507
+ command.detail(`Nothing uploads until you run \`${deps.pause.resumeCommand}\``);
94508
+ if (connectIncomplete) command.detail(`Finish MCP setup: \`${deps.connectCommand}\``);
94509
+ return "paused";
94383
94510
  }
94384
94511
  if (connectIncomplete) {
94385
94512
  const onlySkipped = outcome !== null && outcome.skipped > 0 && outcome.pending === 0 && outcome.failed === 0;
94386
- log3(onlySkipped ? "! MCP setup was skipped" : "! Setup needs one more step");
94387
- log3("");
94388
- log3(
94389
- deps.platform === "darwin" ? "Your synced sessions will still appear in Powerplant." : "Your synced sessions will appear after `powerplant sync` runs."
94390
- );
94391
- log3("");
94392
- log3(`${onlySkipped ? "Add MCP later" : "Finish MCP setup"}: ${deps.connectCommand}`);
94393
- return;
94394
- }
94395
- log3("\u2713 Syncing is ready");
94396
- log3("");
94397
- log3(` Success! See your team's activity: ${deps.webUrl}`);
94398
- log3("");
94399
- log3(
94400
- deps.platform === "darwin" ? " As you code, try asking the Powerplant MCP about your sessions." : " As you code, run `powerplant sync`, then try asking the Powerplant MCP about your sessions."
94401
- );
94402
- log3("");
94403
- log3(
94404
- " Consider adding to your AGENTS file that the Powerplant MCP can be used to check for other team members' WIP, or for analyzing agent sessions that weren't following your docs and instructions."
94513
+ command.log(onlySkipped ? "! MCP setup was skipped" : "! Setup needs one more step");
94514
+ command.log("");
94515
+ command.detail(`${onlySkipped ? "Add MCP later" : "Finish MCP setup"}: \`${deps.connectCommand}\``);
94516
+ return onlySkipped ? "mcp-skipped" : "needs-step";
94517
+ }
94518
+ command.log("\u2713 Syncing is ready");
94519
+ command.log("");
94520
+ command.detail(
94521
+ deps.platform === "darwin" ? `See your team's activity: ${deps.webUrl}` : `Run \`powerplant sync\` after coding, then see your team's activity: ${deps.webUrl}`
94405
94522
  );
94406
94523
  if (outcome !== null && outcome.skipped > 0) {
94407
- log3("");
94408
- log3(` Add MCP to the agents you skipped any time: ${deps.connectCommand}`);
94524
+ command.detail(`Add MCP to the agents you skipped any time: \`${deps.connectCommand}\``);
94409
94525
  }
94526
+ return "ready";
94410
94527
  }
94411
- function narrateMenubarApp(log3, outcome) {
94528
+ function narrateMenubarApp(stage, outcome) {
94412
94529
  switch (outcome.kind) {
94413
94530
  case "installed":
94414
- log3(" \u2713 Menu bar app installed, look for the bolt in your menu bar");
94531
+ stage.log("\u2713 Menu bar app installed, look for the bolt in your menu bar");
94415
94532
  return true;
94416
94533
  case "updated":
94417
- log3(" \u2713 Menu bar app updated to match this CLI");
94534
+ stage.log("\u2713 Menu bar app updated to match this CLI");
94418
94535
  return true;
94419
94536
  case "already-current":
94420
- log3(" \u2713 Menu bar app is installed");
94537
+ stage.log("\u2713 Menu bar app is installed");
94421
94538
  return outcome.launched;
94422
94539
  case "skipped":
94423
94540
  return false;
94424
94541
  case "failed":
94425
- log3(` ! Could not set up the menu bar app: ${outcome.detail}`);
94426
- log3(" Rerun `powerplant init` to try again.");
94542
+ stage.log(`! Could not set up the menu bar app: ${outcome.detail}`);
94543
+ stage.detail("Rerun `powerplant init` to try again.");
94427
94544
  return true;
94428
94545
  }
94429
94546
  }
94430
- async function confirmProtectedRepoDiscovery(deps) {
94547
+ async function confirmProtectedRepoDiscovery(deps, stage) {
94431
94548
  for (; ; ) {
94432
94549
  const answer = await deps.promptLine(
94433
- "Scan Git metadata for your org's work repositories? [y/N] "
94550
+ `${stage.indent}Scan Git metadata for your org's work repositories? [y/N] `
94434
94551
  );
94435
94552
  const normalized = answer?.trim().toLowerCase() ?? "";
94436
94553
  if (normalized === "" || normalized === "n" || normalized === "no") return false;
94437
94554
  if (normalized === "y" || normalized === "yes") return true;
94438
- deps.log(' Please answer "y" or "n".');
94555
+ stage.log('Please answer "y" or "n".');
94439
94556
  }
94440
94557
  }
94441
- function logProtectedFolders(log3, roots) {
94558
+ function logProtectedFolders(stage, roots) {
94442
94559
  for (const folder of roots.flatMap((entry) => entry.folders)) {
94443
- log3(` ${folder.displayPath} (${folder.sessionCount} session${folder.sessionCount === 1 ? "" : "s"})`);
94560
+ stage.detail(`${folder.displayPath} (${folder.sessionCount} session${folder.sessionCount === 1 ? "" : "s"})`);
94444
94561
  }
94445
94562
  }
94446
- function reportProtectedRepoDiscovery(log3, result) {
94563
+ function reportProtectedRepoDiscovery(stage, result) {
94447
94564
  if (result.enabled.length > 0) {
94448
- log3(` \u2713 Repository scanning enabled for ${displayRoots(result.enabled)}`);
94565
+ stage.log(`\u2713 Repository scanning enabled for ${displayRoots(result.enabled)}`);
94449
94566
  }
94450
- if (result.blocked.length > 0) logBlockedByMacOS(log3, result.blocked);
94567
+ if (result.blocked.length > 0) logBlockedByMacOS(stage, result.blocked);
94451
94568
  return result.blocked.length > 0;
94452
94569
  }
94453
- function logBlockedByMacOS(log3, roots) {
94454
- log3(` ! macOS blocked Powerplant from reading ${displayRoots(roots)}.`);
94455
- log3(` Sessions there will stay local. ${MACOS_BLOCKED_FOLDER_REMEDY}`);
94570
+ function logBlockedByMacOS(stage, roots) {
94571
+ stage.log(`! macOS blocked Powerplant from reading ${displayRoots(roots)}.`);
94572
+ stage.detail(`Sessions there will stay local. ${MACOS_BLOCKED_FOLDER_REMEDY}`);
94456
94573
  }
94457
94574
  function displayRoots(roots) {
94458
94575
  return roots.map((entry) => entry.displayRoot).join(", ");
94459
94576
  }
94460
- function logProtectedSessionsStayLocal(log3, found) {
94577
+ function logProtectedSessionsStayLocal(stage, found) {
94461
94578
  const total = found.reduce((sum2, entry) => sum2 + entry.sessionCount, 0);
94462
- log3(
94463
- ` ! Repository matching for ${total} recent session${total === 1 ? "" : "s"} under ${displayRoots(found)} was not enabled.`
94579
+ stage.log(
94580
+ `! Repository matching for ${total} recent session${total === 1 ? "" : "s"} under ${displayRoots(found)} was not enabled.`
94464
94581
  );
94465
- log3(" Sessions outside folders you explicitly added will stay local.");
94582
+ stage.detail("Sessions outside folders you explicitly added will stay local.");
94466
94583
  }
94467
94584
  async function realPromptLine(question) {
94468
94585
  const prompt = createInterface2({ input: process.stdin, output: process.stdout });
@@ -94476,7 +94593,7 @@ async function realPromptLine(question) {
94476
94593
  }
94477
94594
 
94478
94595
  // src/menu.ts
94479
- import path28 from "node:path";
94596
+ import path29 from "node:path";
94480
94597
  var MENU_CONTRACT = 1;
94481
94598
  var CLIENT_NAMES = { claude: "Claude Code", codex: "Codex", cursor: "Cursor" };
94482
94599
  function renderMenu(i) {
@@ -94538,6 +94655,11 @@ function renderMenu(i) {
94538
94655
  items.push({ type: "action", title: "Copy MCP repair details", copy: i.mcpPreferencesError });
94539
94656
  items.push({ type: "separator" });
94540
94657
  }
94658
+ if (i.hookPreferencesError !== void 0) {
94659
+ items.push(problem("Hook warning preference can't be read", "Restore or remove the preferences file."));
94660
+ items.push({ type: "action", title: "Copy hook preference repair details", copy: i.hookPreferencesError });
94661
+ items.push({ type: "separator" });
94662
+ }
94541
94663
  if (i.credentialsError !== void 0) {
94542
94664
  items.push(problem("Stored enrollment can't be read", i.credentialsError));
94543
94665
  items.push({ type: "action", title: "Enroll Again\u2026", terminal: ["init", ...envArgs] });
@@ -94552,7 +94674,10 @@ function renderMenu(i) {
94552
94674
  trailing: "Enrolled"
94553
94675
  });
94554
94676
  items.push({ type: "separator" });
94555
- items.push(...collectorBlock(i, envArgs, problem));
94677
+ items.push(...collectorBlock(i, envArgs, problem, (title, subtitle, dismiss) => {
94678
+ attention = true;
94679
+ return { type: "status", mark: "warn", title, subtitle, ...dismiss && { dismiss } };
94680
+ }, more));
94556
94681
  }
94557
94682
  const agents = recentAgentItems(i);
94558
94683
  if (agents !== null) {
@@ -94633,7 +94758,7 @@ function failedUpdateDetail(i, progress) {
94633
94758
  }
94634
94759
  return progress.detail;
94635
94760
  }
94636
- function collectorBlock(i, envArgs, problem) {
94761
+ function collectorBlock(i, envArgs, problem, warning2, more) {
94637
94762
  const restart = {
94638
94763
  type: "action",
94639
94764
  title: "Restart background sync",
@@ -94702,9 +94827,26 @@ function collectorBlock(i, envArgs, problem) {
94702
94827
  break;
94703
94828
  }
94704
94829
  const status = i.daemon.status;
94705
- const silentHooks = (status.hooks ?? []).flatMap(
94706
- (hook) => hook.silence ? [problem(hook.silence.problem, hook.silence.fix)] : []
94707
- );
94830
+ const silentHooks = (status.hooks ?? []).flatMap((hook) => {
94831
+ const silence = hookWarning(hook, i.now);
94832
+ if (!silence) return [];
94833
+ if (hook.harness !== "codex" || silence.kind !== "not-firing") {
94834
+ return [problem(silence.problem, silence.fix)];
94835
+ }
94836
+ const title = "Codex hook install incomplete";
94837
+ const subtitle = silence.fix;
94838
+ if (i.codexHookWarningDismissed) {
94839
+ more.push({ type: "status", mark: "muted", title, subtitle });
94840
+ return [];
94841
+ }
94842
+ const dismiss = i.hookPreferencesError === void 0 ? {
94843
+ type: "action",
94844
+ title: "Dismiss Codex hooks warning",
94845
+ run: ["dismiss-codex-hook-warning", ...envArgs]
94846
+ } : void 0;
94847
+ if (dismiss) more.push(dismiss);
94848
+ return [warning2(title, subtitle, dismiss)];
94849
+ });
94708
94850
  if (i.control.paused) {
94709
94851
  return [
94710
94852
  {
@@ -94756,7 +94898,7 @@ function agentRow(session, i) {
94756
94898
  const when = ago(i.now - Date.parse(session.lastActivityAt));
94757
94899
  const localMachine = i.credentials !== null && session.machineId === i.credentials.machineId;
94758
94900
  const desktopSessionId = localMachine && session.source === "claude-code" ? i.claudeDesktopSessions?.get(session.externalId)?.sessionId : void 0;
94759
- const app = desktopSessionId !== void 0 ? "Claude desktop" : isSessionSource(session.source) ? describeSessionSource(session.source) : session.source;
94901
+ const app = desktopSessionId !== void 0 ? "Claude desktop" : isLegacySessionSource(session.source) ? describeSessionSource(session.source) : session.source;
94760
94902
  const links = sessionLinks(session, i.config.webUrl, {
94761
94903
  codexDesktop: i.codexDesktop,
94762
94904
  localMachine,
@@ -94774,7 +94916,7 @@ function agentRow(session, i) {
94774
94916
  title: links.extra.label,
94775
94917
  reportClick: [
94776
94918
  "report-agent-click",
94777
- isSessionSource(session.source) ? session.source : "unknown",
94919
+ isLegacySessionSource(session.source) ? session.source : "unknown",
94778
94920
  "focus" in links.extra ? "focus" : "terminal" in links.extra ? "resume" : /^(codex|claude):/.test(links.extra.url) ? "desktop" : "web",
94779
94921
  ...envArgs
94780
94922
  ],
@@ -94894,7 +95036,7 @@ function daemonVersionNote(i) {
94894
95036
  }
94895
95037
  var VERSION_CACHE_TTL_MS = 60 * 6e4;
94896
95038
  function versionCachePath(homeDir, source = "npm") {
94897
- return path28.join(collectorStateDir(homeDir), source === "npm" ? "version-check.json" : "version-check-promoted.json");
95039
+ return path29.join(collectorStateDir(homeDir), source === "npm" ? "version-check.json" : "version-check-promoted.json");
94898
95040
  }
94899
95041
  async function cachedLatestVersion(options) {
94900
95042
  const raw = options.readTextFile(options.cacheFile);
@@ -94926,7 +95068,7 @@ function writeVersionCache(options) {
94926
95068
  import { execFileSync as execFileSync7 } from "node:child_process";
94927
95069
  import { readdir as readdir3, readFile as readFile2 } from "node:fs/promises";
94928
95070
  import os21 from "node:os";
94929
- import path29 from "node:path";
95071
+ import path30 from "node:path";
94930
95072
  var sessionFileAsObserved = external_exports.looseObject({
94931
95073
  pid: external_exports.number().int().positive(),
94932
95074
  sessionId: external_exports.string().min(1),
@@ -94935,7 +95077,7 @@ var sessionFileAsObserved = external_exports.looseObject({
94935
95077
  var START_TIME_TOLERANCE_MS = 3e4;
94936
95078
  var SESSION_FILE = /^(\d+)\.json$/;
94937
95079
  function claudeSessionsDir(homeDir = os21.homedir()) {
94938
- return path29.join(homeDir, ".claude", "sessions");
95080
+ return path30.join(homeDir, ".claude", "sessions");
94939
95081
  }
94940
95082
  async function readLiveTerminalSessions(wanted, deps = {}) {
94941
95083
  const found = /* @__PURE__ */ new Map();
@@ -94960,7 +95102,7 @@ async function readLiveTerminalSessions(wanted, deps = {}) {
94960
95102
  }
94961
95103
  continue;
94962
95104
  }
94963
- const session = await readSessionFile(path29.join(sessionsDir, entry), report2);
95105
+ const session = await readSessionFile(path30.join(sessionsDir, entry), report2);
94964
95106
  if (session === null) continue;
94965
95107
  if (session.pid !== Number(match[1])) {
94966
95108
  report2({
@@ -94998,7 +95140,7 @@ async function readSessionFile(file2, report2) {
94998
95140
  report2({
94999
95141
  operation: "claude-session-registry-shape",
95000
95142
  message: "A Claude Code session file has a shape this CLI can't read",
95001
- context: { file: path29.basename(file2), shape: describeShape(raw) }
95143
+ context: { file: path30.basename(file2), shape: describeShape(raw) }
95002
95144
  });
95003
95145
  return null;
95004
95146
  }
@@ -95139,14 +95281,9 @@ function automaticUpdatesLine(control) {
95139
95281
  }
95140
95282
  function renderStatus(i) {
95141
95283
  const lines = [];
95142
- lines.push(`Environment: ${i.config.appEnv} (API ${i.config.apiUrl})`);
95143
- lines.push(
95144
- `CLI: powerplant ${i.cliVersion}` + (isUpdateAvailable(i.cliVersion, i.latestVersion) ? `, ${i.latestVersion} is available: powerplant update` : "")
95145
- );
95146
- const unsupported = unsupportedVersionNotice(i.cliVersion, i.oldestSupportedVersion);
95147
- if (unsupported !== null) lines.push(unsupported);
95284
+ if (i.config.appEnv !== "production") lines.push(`Environment: ${i.config.appEnv} (API ${i.config.apiUrl})`);
95148
95285
  if (i.credentialsError !== void 0) {
95149
- lines.push(`\u26A0 ${i.credentialsError}`);
95286
+ lines.push(`\u2717 ${i.credentialsError}`);
95150
95287
  } else if (!i.credentials) {
95151
95288
  lines.push("Not enrolled, run: powerplant init");
95152
95289
  } else {
@@ -95158,7 +95295,7 @@ function renderStatus(i) {
95158
95295
  for (const entry of i.protectedSessions ?? []) {
95159
95296
  const sessions = `${entry.sessionCount} recent agent session${entry.sessionCount === 1 ? "" : "s"}`;
95160
95297
  lines.push(
95161
- protectedRootReview(i.credentials, entry.root) === "blocked" ? `\u26A0 macOS is blocking Powerplant from reading ${entry.displayRoot} (${sessions}). Those sessions are staying local. ${MACOS_BLOCKED_FOLDER_REMEDY}` : `\u26A0 Repository matching is not enabled for ${sessions} under ${entry.displayRoot}. Sessions outside folders you explicitly added are staying local, run \`powerplant init\` to review Git repository scanning.`
95298
+ protectedRootReview(i.credentials, entry.root) === "blocked" ? `! macOS is blocking Powerplant from reading ${entry.displayRoot} (${sessions}). Those sessions are staying local. ${MACOS_BLOCKED_FOLDER_REMEDY}` : `! Repository matching is not enabled for ${sessions} under ${entry.displayRoot}. Sessions outside folders you explicitly added are staying local, run \`powerplant init\` to review Git repository scanning.`
95162
95299
  );
95163
95300
  }
95164
95301
  }
@@ -95184,6 +95321,11 @@ function renderStatus(i) {
95184
95321
  lines.push(...renderDaemon(i));
95185
95322
  break;
95186
95323
  }
95324
+ lines.push(
95325
+ `CLI: powerplant ${i.cliVersion}` + (isUpdateAvailable(i.cliVersion, i.latestVersion) ? `, ${i.latestVersion} is available: powerplant update` : "")
95326
+ );
95327
+ const unsupported = unsupportedVersionNotice(i.cliVersion, i.oldestSupportedVersion);
95328
+ if (unsupported !== null) lines.push(unsupported);
95187
95329
  return lines;
95188
95330
  }
95189
95331
  function renderDaemon(i) {
@@ -95201,7 +95343,7 @@ function renderDaemon(i) {
95201
95343
  const lines = [];
95202
95344
  if (i.daemon.state === "stalled") {
95203
95345
  lines.push(
95204
- `\u26A0 Background sync stalled, no heartbeat for ${duration3(i.daemon.staleMs)} (pid ${status.pid}). Run: powerplant restart`
95346
+ `\u2717 Background sync stalled, no heartbeat for ${duration3(i.daemon.staleMs)} (pid ${status.pid}). Run: powerplant restart`
95205
95347
  );
95206
95348
  } else {
95207
95349
  lines.push(
@@ -95226,11 +95368,12 @@ function renderDaemon(i) {
95226
95368
  lines.push(signals === null ? " No pass has run yet in this run." : ` ${signals}`);
95227
95369
  if (status.lastPass && !status.lastPass.ok) {
95228
95370
  lines.push(
95229
- ` \u26A0 Last pass failed: ${status.lastPass.error ?? "unknown error"} (${status.consecutiveFailures} consecutive failure${status.consecutiveFailures === 1 ? "" : "s"}).`
95371
+ ` \u2717 Last pass failed: ${status.lastPass.error ?? "unknown error"} (${status.consecutiveFailures} consecutive failure${status.consecutiveFailures === 1 ? "" : "s"}).`
95230
95372
  );
95231
95373
  }
95232
95374
  for (const hook of status.hooks ?? []) {
95233
- if (hook.silence) lines.push(` \u26A0 ${hook.silence.problem}. ${hook.silence.fix}`);
95375
+ const silence = hookWarning(hook, i.now);
95376
+ if (silence) lines.push(` ! ${silence.problem}. ${silence.fix}`);
95234
95377
  }
95235
95378
  return lines;
95236
95379
  }
@@ -95321,11 +95464,15 @@ var ANSI = {
95321
95464
  resetUnderline: "\x1B[24m"
95322
95465
  };
95323
95466
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
95467
+ var COLUMNS = {
95468
+ command: { line: 0, detail: 2 },
95469
+ stage: { line: 5, detail: 7 }
95470
+ };
95324
95471
  function terminalUsesEffects(interactive, env) {
95325
95472
  return interactive && !("NO_COLOR" in env);
95326
95473
  }
95327
95474
  function colorPrefix(line) {
95328
- const status = /^(\s*)([✓!✗→⏸⚠])/.exec(line);
95475
+ const status = /^(\s*)([✓!✗→])/.exec(line);
95329
95476
  if (status) {
95330
95477
  const color = status[2] === "\u2713" ? ANSI.green : status[2] === "\u2717" ? ANSI.red : ANSI.yellow;
95331
95478
  return `${status[1]}${color}${status[2]}${ANSI.resetColor}${line.slice(status[0].length)}`;
@@ -95341,11 +95488,8 @@ function styleUrls(line) {
95341
95488
  (url2) => `${ANSI.cyan}${ANSI.underline}${url2}${ANSI.resetUnderline}${ANSI.resetColor}`
95342
95489
  );
95343
95490
  }
95344
- function styleCommands(line, dimmed) {
95345
- return line.replace(
95346
- /`([^`]+)`/g,
95347
- (_, command) => `${ANSI.bold}${command}${ANSI.resetDim}${dimmed ? ANSI.dim : ""}`
95348
- );
95491
+ function styleCommands(line) {
95492
+ return line.replace(/`([^`]+)`/g, (_, command) => `${ANSI.bold}${command}${ANSI.resetDim}`);
95349
95493
  }
95350
95494
  function dim(line) {
95351
95495
  return `${ANSI.dim}${line}${ANSI.resetDim}`;
@@ -95358,22 +95502,20 @@ function withDimTerminal(write, work) {
95358
95502
  write(ANSI.resetDim);
95359
95503
  }
95360
95504
  }
95361
- function styleLine(line) {
95362
- if (/^\s*- Opening approval page… https:\/\//.test(line)) return dim(line);
95363
- if (/^\s*[✓!✗→⏸⚠]/.test(line)) return styleCommands(styleUrls(colorPrefix(line)), false);
95364
- if (line.startsWith(" ")) {
95365
- const urlStart = line.search(/https:\/\//);
95366
- if (urlStart >= 0) {
95367
- return `${ANSI.dim}${styleCommands(line.slice(0, urlStart), true)}${ANSI.resetDim}${styleUrls(line.slice(urlStart))}`;
95368
- }
95369
- return `${ANSI.dim}${styleCommands(line, true)}${ANSI.resetDim}`;
95370
- }
95371
- return styleCommands(styleUrls(colorPrefix(line)), false);
95505
+ function skippable(line, place) {
95506
+ if (/^\s*[✓!✗→]/.test(line)) return false;
95507
+ if (/`[^`]+`|https:\/\//.test(line)) return false;
95508
+ return place.level === "stage" ? !place.detail : place.detail;
95509
+ }
95510
+ function styleLine(line, place) {
95511
+ if (skippable(line, place)) return dim(line);
95512
+ return styleCommands(styleUrls(colorPrefix(line)));
95372
95513
  }
95373
95514
  function createTerminalOutput(options) {
95374
95515
  const interactive = options.interactive;
95375
95516
  const color = interactive && options.color;
95376
95517
  let activityLabel = null;
95518
+ let activityIndent = "";
95377
95519
  let frameIndex = 0;
95378
95520
  let timer = null;
95379
95521
  const renderActivity = () => {
@@ -95381,24 +95523,26 @@ function createTerminalOutput(options) {
95381
95523
  const frame = SPINNER_FRAMES[frameIndex % SPINNER_FRAMES.length];
95382
95524
  frameIndex += 1;
95383
95525
  const glyph = color ? `${ANSI.amber}${frame}${ANSI.resetColor}` : frame;
95384
- options.write(`${ANSI.clearLine} ${glyph} ${activityLabel}`);
95526
+ options.write(`${ANSI.clearLine}${activityIndent}${glyph} ${activityLabel}`);
95385
95527
  };
95386
95528
  const clearActivity = () => {
95387
95529
  if (activityLabel !== null) options.write(ANSI.clearLine);
95388
95530
  };
95389
- const log3 = (line) => {
95531
+ const log3 = (line, place) => {
95390
95532
  const rerender = activityLabel !== null;
95391
95533
  if (rerender) clearActivity();
95392
- options.write(`${color ? styleLine(line) : line}
95534
+ options.write(`${color ? styleLine(line, place) : line}
95393
95535
  `);
95394
95536
  if (rerender) renderActivity();
95395
95537
  };
95396
- const activity = async (label2, work) => {
95538
+ const activity = async (place, label2, work) => {
95539
+ const indent = " ".repeat(COLUMNS[place.level].line);
95397
95540
  if (!interactive) {
95398
- log3(` \u2026 ${label2}`);
95541
+ log3(`${indent}\u2026 ${label2}`, place);
95399
95542
  return await work();
95400
95543
  }
95401
95544
  activityLabel = label2;
95545
+ activityIndent = indent;
95402
95546
  frameIndex = 0;
95403
95547
  renderActivity();
95404
95548
  timer = setInterval(renderActivity, 80);
@@ -95412,13 +95556,27 @@ function createTerminalOutput(options) {
95412
95556
  activityLabel = null;
95413
95557
  }
95414
95558
  };
95415
- return { log: log3, activity };
95559
+ const writer = (level) => {
95560
+ const columns = COLUMNS[level];
95561
+ const indent = " ".repeat(columns.line);
95562
+ const detailIndent = " ".repeat(columns.detail);
95563
+ const line = { level, detail: false };
95564
+ const detail = { level, detail: true };
95565
+ return {
95566
+ indent,
95567
+ // A blank line separates stages; it carries no indentation.
95568
+ log: (text) => log3(text === "" ? "" : `${indent}${text}`, line),
95569
+ detail: (text) => log3(`${detailIndent}${text}`, detail),
95570
+ activity: (label2, work) => activity(line, label2, work)
95571
+ };
95572
+ };
95573
+ return { command: writer("command"), stage: writer("stage") };
95416
95574
  }
95417
95575
 
95418
95576
  // src/credentialUpgrade.ts
95419
95577
  import { spawn as spawn2 } from "node:child_process";
95420
- import { closeSync as closeSync8, mkdirSync as mkdirSync13, openSync as openSync8 } from "node:fs";
95421
- import path30 from "node:path";
95578
+ import { closeSync as closeSync8, mkdirSync as mkdirSync14, openSync as openSync8 } from "node:fs";
95579
+ import path31 from "node:path";
95422
95580
  async function prepareCredentialUpgrade(deps) {
95423
95581
  if (!deps.needsMigration() || !deps.serviceExists() || deps.ready()) return "ready";
95424
95582
  if (deps.installing()) return "busy";
@@ -95451,7 +95609,7 @@ async function prepareCredentialUpgrade(deps) {
95451
95609
  }
95452
95610
  }
95453
95611
  async function tryCredentialUpgradeLock(file2) {
95454
- mkdirSync13(path30.dirname(file2), { recursive: true, mode: 448 });
95612
+ mkdirSync14(path31.dirname(file2), { recursive: true, mode: 448 });
95455
95613
  closeSync8(openSync8(file2, "a", 384));
95456
95614
  const child = spawn2("/usr/bin/lockf", ["-k", "-s", "-t", "0", file2, "/bin/sh", "-c", "printf 'ready\\n'; exec /bin/cat >/dev/null"], {
95457
95615
  detached: true,
@@ -95569,9 +95727,9 @@ async function tryCredentialUpgradeLock(file2) {
95569
95727
  }
95570
95728
 
95571
95729
  // src/menubarApp.ts
95572
- import { existsSync as existsSync13, mkdirSync as mkdirSync14, renameSync as renameSync6, rmSync as rmSync6 } from "node:fs";
95730
+ import { existsSync as existsSync13, mkdirSync as mkdirSync15, renameSync as renameSync7, rmSync as rmSync6 } from "node:fs";
95573
95731
  import os22 from "node:os";
95574
- import path31 from "node:path";
95732
+ import path32 from "node:path";
95575
95733
  import { spawnSync as spawnSync4 } from "node:child_process";
95576
95734
  var MENUBAR_APP_ZIP = "dist/menubar/Powerplant.app.zip";
95577
95735
  var MENUBAR_APP_NAME = "Powerplant.app";
@@ -95610,13 +95768,13 @@ async function syncMenubarApp(ops, context2) {
95610
95768
  }
95611
95769
  function realMenubarAppOps(input2) {
95612
95770
  const home = input2.homeDir ?? os22.homedir();
95613
- const userAppPath = path31.join(home, "Applications", MENUBAR_APP_NAME);
95614
- const candidates = [userAppPath, path31.join("/Applications", MENUBAR_APP_NAME)];
95771
+ const userAppPath = path32.join(home, "Applications", MENUBAR_APP_NAME);
95772
+ const candidates = [userAppPath, path32.join("/Applications", MENUBAR_APP_NAME)];
95615
95773
  return {
95616
95774
  cliVersion: input2.cliVersion,
95617
95775
  packagedZip: () => {
95618
95776
  if (input2.packageDir === null) return null;
95619
- const zip = path31.join(input2.packageDir, MENUBAR_APP_ZIP);
95777
+ const zip = path32.join(input2.packageDir, MENUBAR_APP_ZIP);
95620
95778
  return existsSync13(zip) ? zip : null;
95621
95779
  },
95622
95780
  installedApp: () => {
@@ -95636,10 +95794,10 @@ function realMenubarAppOps(input2) {
95636
95794
  throw new Error(`the running app at ${appPath} did not quit`);
95637
95795
  },
95638
95796
  replace: (zip, appPath) => {
95639
- const parent = path31.dirname(appPath);
95640
- mkdirSync14(parent, { recursive: true });
95641
- const staging = path31.join(parent, `.${MENUBAR_APP_NAME}.swap-${process.pid}`);
95642
- const retired = path31.join(parent, `.${MENUBAR_APP_NAME}.old-${process.pid}`);
95797
+ const parent = path32.dirname(appPath);
95798
+ mkdirSync15(parent, { recursive: true });
95799
+ const staging = path32.join(parent, `.${MENUBAR_APP_NAME}.swap-${process.pid}`);
95800
+ const retired = path32.join(parent, `.${MENUBAR_APP_NAME}.old-${process.pid}`);
95643
95801
  rmSync6(staging, { recursive: true, force: true });
95644
95802
  rmSync6(retired, { recursive: true, force: true });
95645
95803
  try {
@@ -95649,16 +95807,16 @@ function realMenubarAppOps(input2) {
95649
95807
  `ditto could not extract ${zip} (${extract.stderr?.toString().trim() || `exit ${extract.status}`})`
95650
95808
  );
95651
95809
  }
95652
- const extracted = path31.join(staging, MENUBAR_APP_NAME);
95653
- if (!existsSync13(path31.join(extracted, "Contents", "Info.plist"))) {
95810
+ const extracted = path32.join(staging, MENUBAR_APP_NAME);
95811
+ if (!existsSync13(path32.join(extracted, "Contents", "Info.plist"))) {
95654
95812
  throw new Error(`${zip} does not contain ${MENUBAR_APP_NAME}`);
95655
95813
  }
95656
95814
  const hadOld = existsSync13(appPath);
95657
- if (hadOld) renameSync6(appPath, retired);
95815
+ if (hadOld) renameSync7(appPath, retired);
95658
95816
  try {
95659
- renameSync6(extracted, appPath);
95817
+ renameSync7(extracted, appPath);
95660
95818
  } catch (error63) {
95661
- if (hadOld) renameSync6(retired, appPath);
95819
+ if (hadOld) renameSync7(retired, appPath);
95662
95820
  throw error63;
95663
95821
  }
95664
95822
  } finally {
@@ -95678,7 +95836,7 @@ function realMenubarAppOps(input2) {
95678
95836
  };
95679
95837
  }
95680
95838
  function appProcessIds(appPath) {
95681
- const executable = path31.join(appPath, "Contents", "MacOS", "PowerplantMenubar");
95839
+ const executable = path32.join(appPath, "Contents", "MacOS", "PowerplantMenubar");
95682
95840
  const result = spawnSync4("ps", ["-axo", "pid=,comm="], { encoding: "utf8" });
95683
95841
  if (result.status !== 0) {
95684
95842
  throw new Error(`ps could not list processes (${result.error?.message ?? `exit ${result.status}`})`);
@@ -95707,10 +95865,10 @@ var workspaceSchema = external_exports.object({
95707
95865
  active: external_exports.boolean()
95708
95866
  });
95709
95867
  var FETCH_TIMEOUT_MS2 = 1e4;
95710
- async function callApi(credentials, path33, init3, fetchImpl) {
95868
+ async function callApi(credentials, path34, init3, fetchImpl) {
95711
95869
  let response;
95712
95870
  try {
95713
- response = await fetchImpl(`${credentials.apiUrl}${path33}`, {
95871
+ response = await fetchImpl(`${credentials.apiUrl}${path34}`, {
95714
95872
  ...init3,
95715
95873
  headers: {
95716
95874
  authorization: `Bearer ${credentials.token}`,
@@ -95729,7 +95887,7 @@ async function callApi(credentials, path33, init3, fetchImpl) {
95729
95887
  );
95730
95888
  }
95731
95889
  if (!response.ok) {
95732
- throw new ExpectedCliError(`Powerplant answered ${response.status} for ${path33}.`);
95890
+ throw new ExpectedCliError(`Powerplant answered ${response.status} for ${path34}.`);
95733
95891
  }
95734
95892
  return response.json();
95735
95893
  }
@@ -95814,7 +95972,8 @@ Commands:
95814
95972
  update Update this CLI to the latest published version, using the
95815
95973
  package manager that installed it, and restart background sync.
95816
95974
  --automatic on|off sets whether the background sync installs
95817
- new releases itself (on from the first install).
95975
+ new releases itself. \`powerplant init\` asks once; a machine
95976
+ that was never asked stays off.
95818
95977
  restart Restart the background sync.
95819
95978
  pause Pause background syncing: the service keeps running but
95820
95979
  uploads nothing. An explicit \`powerplant sync\` still runs.
@@ -95912,9 +96071,11 @@ ${USAGE}`);
95912
96071
  const chosenEnv = values.env;
95913
96072
  const config2 = resolveCliConfig(process.env, chosenEnv);
95914
96073
  const banner = describeEnvironment(config2, process.env, chosenEnv);
95915
- console.error(
95916
- terminalUsesEffects(process.stderr.isTTY === true, process.env) ? dim(banner) : banner
95917
- );
96074
+ if (banner !== null) {
96075
+ console.error(
96076
+ terminalUsesEffects(process.stderr.isTTY === true, process.env) ? dim(banner) : banner
96077
+ );
96078
+ }
95918
96079
  const dsn = reportingDsn(process.env, config2, CLI_RELEASE_BUILD);
95919
96080
  if (dsn !== void 0) process.env.SENTRY_DSN = dsn;
95920
96081
  initCollectorReporting(config2.appEnv, CLI_VERSION);
@@ -95946,7 +96107,7 @@ ${USAGE}`);
95946
96107
  install: () => {
95947
96108
  installService(config2, watchCommand(config2));
95948
96109
  },
95949
- tryLock: () => tryCredentialUpgradeLock(path32.join(collectorStateDir(), `credential-upgrade-${config2.appEnv}.lock`)),
96110
+ tryLock: () => tryCredentialUpgradeLock(path33.join(collectorStateDir(), `credential-upgrade-${config2.appEnv}.lock`)),
95950
96111
  now: Date.now,
95951
96112
  sleep: () => new Promise((resolve2) => setTimeout(resolve2, 250)),
95952
96113
  restartCommand: `powerplant restart${config2.appEnv === "production" ? "" : ` --env ${config2.appEnv}`}`,
@@ -95984,12 +96145,19 @@ ${USAGE}`);
95984
96145
  stdoutIsTty: process.stdout.isTTY === true
95985
96146
  });
95986
96147
  const pause = realPauseDeps(config2.appEnv, withEnv("powerplant resume"), realPromptLine);
96148
+ const terminalEffects = terminalUsesEffects(process.stdout.isTTY === true, process.env);
96149
+ const terminal = createTerminalOutput({
96150
+ interactive: terminalEffects && !values.verbose,
96151
+ color: terminalEffects,
96152
+ write: (chunk) => process.stdout.write(chunk)
96153
+ });
95987
96154
  if (!PAUSE_NOTICE_SKIPPED.has(command)) {
95988
96155
  const notice = pausedNotice(pause.readControl(), pause.resumeCommand, Date.now());
95989
96156
  if (notice !== null) console.error(styledFor(process.stderr)(notice));
95990
96157
  }
95991
96158
  const agentCount = (clients) => new Set(clients.map((client) => client.client)).size;
95992
- const connect3 = async (log3) => {
96159
+ const connect3 = async (output2) => {
96160
+ const log3 = output2.log;
95993
96161
  const detected = detectClients({ warn: log3 });
95994
96162
  saveDetectedClients(detected, process.env.PATH ?? "");
95995
96163
  let clients = clientFilter === void 0 ? detected : detected.filter((client) => clientFilter.has(client.client));
@@ -96014,7 +96182,7 @@ ${USAGE}`);
96014
96182
  if (pickerOn && clientFilter === void 0 && clients.length > 0) {
96015
96183
  clients = await pickAgents(clients, {
96016
96184
  log: log3,
96017
- promptCheckboxes: realCheckboxPrompt,
96185
+ promptCheckboxes: (question, choices) => realCheckboxPrompt(question, choices, { indent: output2.indent }),
96018
96186
  onChoice: (selected) => recordMcpChoices(config2.appEnv, detected.map((client) => client.client), selected.map((client) => client.client))
96019
96187
  });
96020
96188
  skipped = agentCount(detected) - agentCount(clients);
@@ -96051,19 +96219,13 @@ ${USAGE}`);
96051
96219
  };
96052
96220
  switch (command) {
96053
96221
  case "init": {
96054
- const terminalEffects = terminalUsesEffects(process.stdout.isTTY === true, process.env);
96055
- const terminal = createTerminalOutput({
96056
- interactive: terminalEffects && !values.verbose,
96057
- color: terminalEffects,
96058
- write: (chunk) => process.stdout.write(chunk)
96059
- });
96060
- await runInit({
96061
- log: terminal.log,
96062
- activity: terminal.activity,
96222
+ const summary = await runInit({
96223
+ terminal,
96063
96224
  loadCredentials: () => loadCredentials(config2.appEnv),
96064
- // Enrollment's own narration (org, token location, capture boundary)
96065
- // indents under stage 1.
96066
- enroll: () => enroll2((line) => terminal.log(` ${line}`)),
96225
+ // Enrollment's own lines (approval URL, token location) are detail
96226
+ // lines under stage 1's spinner; init prints the result line, and
96227
+ // stage 2 states the capture boundary.
96228
+ enroll: () => enroll2(terminal.stage.detail),
96067
96229
  // Discovery may read a worktree pointer under a root the store
96068
96230
  // already allows, so a revoked checkout root still surfaces.
96069
96231
  findProtectedSessions: () => findRecentProtectedSessions({
@@ -96096,16 +96258,17 @@ ${USAGE}`);
96096
96258
  set: (enabled) => setAutomaticUpdates(config2.appEnv, enabled),
96097
96259
  promptLine: realPromptLine
96098
96260
  },
96099
- connect: () => connect3((line) => terminal.log(` ${line}`)),
96261
+ connect: () => connect3(terminal.stage),
96100
96262
  menubarApp: managesMenubarApp(config2) ? () => syncMenubarApp(thisInstallMenubarAppOps(), "init") : null,
96101
96263
  connectCommand,
96102
96264
  environmentName: config2.appEnv,
96103
96265
  webUrl: config2.webUrl
96104
96266
  });
96267
+ process.exitCode = initExitCode(summary);
96105
96268
  return;
96106
96269
  }
96107
96270
  case "connect": {
96108
- const outcome = await connect3(console.log);
96271
+ const outcome = await connect3(terminal.command);
96109
96272
  if (outcome.pending > 0) {
96110
96273
  console.log(`Some logins are unfinished, re-run \`${connectCommand}\` any time.`);
96111
96274
  }
@@ -96139,8 +96302,14 @@ The access you granted these agents stays on your Powerplant account until you r
96139
96302
  return;
96140
96303
  }
96141
96304
  case "enroll": {
96142
- await enroll2();
96143
- await offerResume(pause, { log: console.log, indent: "", promptAllowed: pickerOn });
96305
+ const credentials = await terminal.command.activity(
96306
+ "Waiting for approval in your browser\u2026",
96307
+ () => enroll2(terminal.command.detail)
96308
+ );
96309
+ terminal.command.log(enrolledLine(credentials));
96310
+ terminal.command.detail(`Syncing: ${describeStoredCapture(credentials)}`);
96311
+ const offer = await offerResume(pause, { output: terminal.command, promptAllowed: pickerOn });
96312
+ if (offer === "still-paused") process.exitCode = 1;
96144
96313
  return;
96145
96314
  }
96146
96315
  case "status": {
@@ -96256,6 +96425,7 @@ The access you granted these agents stays on your Powerplant account until you r
96256
96425
  latestVersion,
96257
96426
  oldestSupportedVersion,
96258
96427
  ...readMcpPreferencesForMenu(config2.appEnv),
96428
+ ...readHookPreferencesForMenu(config2.appEnv),
96259
96429
  connections: probeConnections(clients, {
96260
96430
  mcpUrl: `${config2.apiUrl}/mcp`,
96261
96431
  serverName: mcpServerNameFor(config2.appEnv),
@@ -96282,6 +96452,10 @@ The access you granted these agents stays on your Powerplant account until you r
96282
96452
  if (!await reportMenubarEvent({ event: MENUBAR_AGENT_CLICK, ...parsed2.data }, stored.credentials, console.error)) process.exitCode = 1;
96283
96453
  return;
96284
96454
  }
96455
+ case "dismiss-codex-hook-warning": {
96456
+ dismissCodexHookWarning(config2.appEnv);
96457
+ return;
96458
+ }
96285
96459
  case "dismiss-mcp-warning": {
96286
96460
  const parsed2 = mcpWarningDismissalSchema.safeParse({ client: positionals[1], warning: positionals[2] });
96287
96461
  if (!parsed2.success) throw new ExpectedCliError("Expected a client and MCP warning type to dismiss.");
@@ -96448,7 +96622,8 @@ ${USAGE}`);
96448
96622
  }
96449
96623
  }
96450
96624
  function styledFor(stream) {
96451
- return terminalUsesEffects(stream.isTTY === true, process.env) ? styleLine : (line) => line;
96625
+ if (!terminalUsesEffects(stream.isTTY === true, process.env)) return (line) => line;
96626
+ return (line) => styleLine(line, { level: "command", detail: line.startsWith(" ") });
96452
96627
  }
96453
96628
  function oldestSupportedFor(credentials) {
96454
96629
  return credentials === null ? Promise.resolve(null) : fetchOldestSupportedVersion(credentials.apiUrl, credentials.token);
@@ -96510,7 +96685,7 @@ function startBackgroundUpdate(config2, target) {
96510
96685
  readProgress: updateProgress.read,
96511
96686
  writeProgress: updateProgress.write,
96512
96687
  spawnChild: () => {
96513
- mkdirSync15(path32.dirname(updateLogPath()), { recursive: true });
96688
+ mkdirSync16(path33.dirname(updateLogPath()), { recursive: true });
96514
96689
  const log3 = openSync9(updateLogPath(), "a");
96515
96690
  const child = spawn3(process.execPath, [entryPath(), "update", ...envArgsFor(config2)], {
96516
96691
  detached: true,
@@ -96535,7 +96710,7 @@ function automaticUpdateCheck(config2) {
96535
96710
  "daemon"
96536
96711
  );
96537
96712
  if (app.kind === "updated") log3(`menu bar app updated to ${CLI_VERSION}`);
96538
- if (app.kind === "failed") log3(`\u26A0 menu bar app could not be updated: ${app.detail}`);
96713
+ if (app.kind === "failed") log3(`! menu bar app could not be updated: ${app.detail}`);
96539
96714
  }
96540
96715
  const decision = autoUpdateDecision({
96541
96716
  control: readCollectorControl(config2.appEnv),
@@ -96600,7 +96775,7 @@ var cliCommand = "none";
96600
96775
  main().catch(async (error63) => {
96601
96776
  if (error63 instanceof ExpectedCliError) {
96602
96777
  console.error(
96603
- terminalUsesEffects(process.stderr.isTTY === true, process.env) ? styleLine(error63.message) : error63.message
96778
+ terminalUsesEffects(process.stderr.isTTY === true, process.env) ? styleLine(error63.message, { level: "command", detail: false }) : error63.message
96604
96779
  );
96605
96780
  } else {
96606
96781
  console.error(error63);
@@ -96619,4 +96794,4 @@ undici/lib/web/websocket/frame.js:
96619
96794
  (*! ws. MIT License. Einar Otto Stangvik <einaros@gmail.com> *)
96620
96795
  */
96621
96796
 
96622
- //# debugId=81d65aee-a279-58bd-9476-cc1269e40adf
96797
+ //# debugId=bdd42bb0-e20a-5100-a257-b6dbb21d0f74