@rosthq/cli 0.7.68 → 0.7.69

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/index.js CHANGED
@@ -472,13 +472,13 @@ function __disposeResources(env) {
472
472
  }
473
473
  return next();
474
474
  }
475
- function __rewriteRelativeImportExtension(path7, preserveJsx) {
476
- if (typeof path7 === "string" && /^\.\.?\//.test(path7)) {
477
- return path7.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
475
+ function __rewriteRelativeImportExtension(path8, preserveJsx) {
476
+ if (typeof path8 === "string" && /^\.\.?\//.test(path8)) {
477
+ return path8.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
478
478
  return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
479
479
  });
480
480
  }
481
- return path7;
481
+ return path8;
482
482
  }
483
483
  var extendStatics, __assign, __createBinding, __setModuleDefault, ownKeys, _SuppressedError, tslib_es6_default;
484
484
  var init_tslib_es6 = __esm({
@@ -14027,10 +14027,10 @@ function mergeDefs(...defs) {
14027
14027
  function cloneDef(schema) {
14028
14028
  return mergeDefs(schema._zod.def);
14029
14029
  }
14030
- function getElementAtPath(obj, path7) {
14031
- if (!path7)
14030
+ function getElementAtPath(obj, path8) {
14031
+ if (!path8)
14032
14032
  return obj;
14033
- return path7.reduce((acc, key) => acc?.[key], obj);
14033
+ return path8.reduce((acc, key) => acc?.[key], obj);
14034
14034
  }
14035
14035
  function promiseAllObject(promisesObj) {
14036
14036
  const keys = Object.keys(promisesObj);
@@ -14439,11 +14439,11 @@ function explicitlyAborted(x, startIndex = 0) {
14439
14439
  }
14440
14440
  return false;
14441
14441
  }
14442
- function prefixIssues(path7, issues) {
14442
+ function prefixIssues(path8, issues) {
14443
14443
  return issues.map((iss) => {
14444
14444
  var _a3;
14445
14445
  (_a3 = iss).path ?? (_a3.path = []);
14446
- iss.path.unshift(path7);
14446
+ iss.path.unshift(path8);
14447
14447
  return iss;
14448
14448
  });
14449
14449
  }
@@ -14590,16 +14590,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
14590
14590
  }
14591
14591
  function formatError(error51, mapper = (issue2) => issue2.message) {
14592
14592
  const fieldErrors = { _errors: [] };
14593
- const processError = (error52, path7 = []) => {
14593
+ const processError = (error52, path8 = []) => {
14594
14594
  for (const issue2 of error52.issues) {
14595
14595
  if (issue2.code === "invalid_union" && issue2.errors.length) {
14596
- issue2.errors.map((issues) => processError({ issues }, [...path7, ...issue2.path]));
14596
+ issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
14597
14597
  } else if (issue2.code === "invalid_key") {
14598
- processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
14598
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
14599
14599
  } else if (issue2.code === "invalid_element") {
14600
- processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
14600
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
14601
14601
  } else {
14602
- const fullpath = [...path7, ...issue2.path];
14602
+ const fullpath = [...path8, ...issue2.path];
14603
14603
  if (fullpath.length === 0) {
14604
14604
  fieldErrors._errors.push(mapper(issue2));
14605
14605
  } else {
@@ -14626,17 +14626,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
14626
14626
  }
14627
14627
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
14628
14628
  const result = { errors: [] };
14629
- const processError = (error52, path7 = []) => {
14629
+ const processError = (error52, path8 = []) => {
14630
14630
  var _a3, _b;
14631
14631
  for (const issue2 of error52.issues) {
14632
14632
  if (issue2.code === "invalid_union" && issue2.errors.length) {
14633
- issue2.errors.map((issues) => processError({ issues }, [...path7, ...issue2.path]));
14633
+ issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
14634
14634
  } else if (issue2.code === "invalid_key") {
14635
- processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
14635
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
14636
14636
  } else if (issue2.code === "invalid_element") {
14637
- processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
14637
+ processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
14638
14638
  } else {
14639
- const fullpath = [...path7, ...issue2.path];
14639
+ const fullpath = [...path8, ...issue2.path];
14640
14640
  if (fullpath.length === 0) {
14641
14641
  result.errors.push(mapper(issue2));
14642
14642
  continue;
@@ -14668,8 +14668,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
14668
14668
  }
14669
14669
  function toDotPath(_path) {
14670
14670
  const segs = [];
14671
- const path7 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
14672
- for (const seg of path7) {
14671
+ const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
14672
+ for (const seg of path8) {
14673
14673
  if (typeof seg === "number")
14674
14674
  segs.push(`[${seg}]`);
14675
14675
  else if (typeof seg === "symbol")
@@ -27361,13 +27361,13 @@ function resolveRef(ref, ctx) {
27361
27361
  if (!ref.startsWith("#")) {
27362
27362
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
27363
27363
  }
27364
- const path7 = ref.slice(1).split("/").filter(Boolean);
27365
- if (path7.length === 0) {
27364
+ const path8 = ref.slice(1).split("/").filter(Boolean);
27365
+ if (path8.length === 0) {
27366
27366
  return ctx.rootSchema;
27367
27367
  }
27368
27368
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
27369
- if (path7[0] === defsKey) {
27370
- const key = path7[1];
27369
+ if (path8[0] === defsKey) {
27370
+ const key = path8[1];
27371
27371
  if (!key || !ctx.defs[key]) {
27372
27372
  throw new Error(`Reference not found: ${ref}`);
27373
27373
  }
@@ -27829,7 +27829,7 @@ var CommandClient = class {
27829
27829
  this.fetchImpl = options.fetchImpl ?? fetch;
27830
27830
  }
27831
27831
  async execute(commandId, body = {}, options = {}) {
27832
- const path7 = `/api/commands/${encodeURIComponent(commandId)}`;
27832
+ const path8 = `/api/commands/${encodeURIComponent(commandId)}`;
27833
27833
  const headers = {
27834
27834
  authorization: `Bearer ${this.token}`,
27835
27835
  "content-type": "application/json"
@@ -27837,7 +27837,7 @@ var CommandClient = class {
27837
27837
  if (options.targetSeatId !== void 0 && options.targetSeatId.length > 0) {
27838
27838
  headers["x-rost-seat"] = options.targetSeatId;
27839
27839
  }
27840
- const response = await this.fetchImpl(`${this.appUrl}${path7}`, {
27840
+ const response = await this.fetchImpl(`${this.appUrl}${path8}`, {
27841
27841
  method: "POST",
27842
27842
  headers,
27843
27843
  body: JSON.stringify(body)
@@ -27850,7 +27850,7 @@ var CommandClient = class {
27850
27850
  const snippet = redactSecrets(text.replace(/\s+/g, " ").trim()).slice(0, 200);
27851
27851
  throw new CommandClientError(
27852
27852
  response.status,
27853
- `server returned HTTP ${response.status} (non-JSON) from ${path7}` + (snippet ? ` \u2014 ${snippet}` : "") + " \u2014 the deployment may be unhealthy"
27853
+ `server returned HTTP ${response.status} (non-JSON) from ${path8}` + (snippet ? ` \u2014 ${snippet}` : "") + " \u2014 the deployment may be unhealthy"
27854
27854
  );
27855
27855
  }
27856
27856
  const parsed = commandResponseSchema.parse(raw);
@@ -33181,8 +33181,8 @@ var IcebergError = class extends Error {
33181
33181
  return this.status === 419;
33182
33182
  }
33183
33183
  };
33184
- function buildUrl(baseUrl, path7, query) {
33185
- const url2 = new URL(path7, baseUrl);
33184
+ function buildUrl(baseUrl, path8, query) {
33185
+ const url2 = new URL(path8, baseUrl);
33186
33186
  if (query) {
33187
33187
  for (const [key, value] of Object.entries(query)) {
33188
33188
  if (value !== void 0) {
@@ -33212,12 +33212,12 @@ function createFetchClient(options) {
33212
33212
  return {
33213
33213
  async request({
33214
33214
  method,
33215
- path: path7,
33215
+ path: path8,
33216
33216
  query,
33217
33217
  body,
33218
33218
  headers
33219
33219
  }) {
33220
- const url2 = buildUrl(options.baseUrl, path7, query);
33220
+ const url2 = buildUrl(options.baseUrl, path8, query);
33221
33221
  const authHeaders = await buildAuthHeaders(options.auth);
33222
33222
  const res = await fetchFn(url2, {
33223
33223
  method,
@@ -34079,7 +34079,7 @@ var StorageFileApi = class extends BaseApiClient {
34079
34079
  * @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.
34080
34080
  * @param fileBody The body of the file to be stored in the bucket.
34081
34081
  */
34082
- async uploadOrUpdate(method, path7, fileBody, fileOptions) {
34082
+ async uploadOrUpdate(method, path8, fileBody, fileOptions) {
34083
34083
  var _this = this;
34084
34084
  return _this.handleOperation(async () => {
34085
34085
  let body;
@@ -34103,7 +34103,7 @@ var StorageFileApi = class extends BaseApiClient {
34103
34103
  if ((typeof ReadableStream !== "undefined" && body instanceof ReadableStream || body && typeof body === "object" && "pipe" in body && typeof body.pipe === "function") && !options.duplex) options.duplex = "half";
34104
34104
  }
34105
34105
  if (fileOptions === null || fileOptions === void 0 ? void 0 : fileOptions.headers) for (const [key, value] of Object.entries(fileOptions.headers)) headers = setHeader(headers, key, value);
34106
- const cleanPath = _this._removeEmptyFolders(path7);
34106
+ const cleanPath = _this._removeEmptyFolders(path8);
34107
34107
  const _path = _this._getFinalPath(cleanPath);
34108
34108
  const data = await (method == "PUT" ? put : post)(_this.fetch, `${_this.url}/object/${_path}`, body, _objectSpread22({ headers }, (options === null || options === void 0 ? void 0 : options.duplex) ? { duplex: options.duplex } : {}));
34109
34109
  return {
@@ -34180,8 +34180,8 @@ var StorageFileApi = class extends BaseApiClient {
34180
34180
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
34181
34181
  * - For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Upload file using `ArrayBuffer` from base64 file data instead, see example below.
34182
34182
  */
34183
- async upload(path7, fileBody, fileOptions) {
34184
- return this.uploadOrUpdate("POST", path7, fileBody, fileOptions);
34183
+ async upload(path8, fileBody, fileOptions) {
34184
+ return this.uploadOrUpdate("POST", path8, fileBody, fileOptions);
34185
34185
  }
34186
34186
  /**
34187
34187
  * Upload a file with a token generated from `createSignedUploadUrl`.
@@ -34221,9 +34221,9 @@ var StorageFileApi = class extends BaseApiClient {
34221
34221
  * - `objects` table permissions: none
34222
34222
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
34223
34223
  */
34224
- async uploadToSignedUrl(path7, token, fileBody, fileOptions) {
34224
+ async uploadToSignedUrl(path8, token, fileBody, fileOptions) {
34225
34225
  var _this3 = this;
34226
- const cleanPath = _this3._removeEmptyFolders(path7);
34226
+ const cleanPath = _this3._removeEmptyFolders(path8);
34227
34227
  const _path = _this3._getFinalPath(cleanPath);
34228
34228
  const url2 = new URL(_this3.url + `/object/upload/sign/${_path}`);
34229
34229
  url2.searchParams.set("token", token);
@@ -34292,10 +34292,10 @@ var StorageFileApi = class extends BaseApiClient {
34292
34292
  * - `objects` table permissions: `insert`
34293
34293
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
34294
34294
  */
34295
- async createSignedUploadUrl(path7, options) {
34295
+ async createSignedUploadUrl(path8, options) {
34296
34296
  var _this4 = this;
34297
34297
  return _this4.handleOperation(async () => {
34298
- let _path = _this4._getFinalPath(path7);
34298
+ let _path = _this4._getFinalPath(path8);
34299
34299
  const headers = _objectSpread22({}, _this4.headers);
34300
34300
  if (options === null || options === void 0 ? void 0 : options.upsert) headers["x-upsert"] = "true";
34301
34301
  const data = await post(_this4.fetch, `${_this4.url}/object/upload/sign/${_path}`, {}, { headers });
@@ -34304,7 +34304,7 @@ var StorageFileApi = class extends BaseApiClient {
34304
34304
  if (!token) throw new StorageError("No token returned by API");
34305
34305
  return {
34306
34306
  signedUrl: url2.toString(),
34307
- path: path7,
34307
+ path: path8,
34308
34308
  token
34309
34309
  };
34310
34310
  });
@@ -34364,8 +34364,8 @@ var StorageFileApi = class extends BaseApiClient {
34364
34364
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
34365
34365
  * - For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Update file using `ArrayBuffer` from base64 file data instead, see example below.
34366
34366
  */
34367
- async update(path7, fileBody, fileOptions) {
34368
- return this.uploadOrUpdate("PUT", path7, fileBody, fileOptions);
34367
+ async update(path8, fileBody, fileOptions) {
34368
+ return this.uploadOrUpdate("PUT", path8, fileBody, fileOptions);
34369
34369
  }
34370
34370
  /**
34371
34371
  * Moves an existing file to a new path in the same bucket.
@@ -34516,10 +34516,10 @@ var StorageFileApi = class extends BaseApiClient {
34516
34516
  * - `objects` table permissions: `select`
34517
34517
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
34518
34518
  */
34519
- async createSignedUrl(path7, expiresIn, options) {
34519
+ async createSignedUrl(path8, expiresIn, options) {
34520
34520
  var _this8 = this;
34521
34521
  return _this8.handleOperation(async () => {
34522
- let _path = _this8._getFinalPath(path7);
34522
+ let _path = _this8._getFinalPath(path8);
34523
34523
  const hasTransform = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0;
34524
34524
  let data = await post(_this8.fetch, `${_this8.url}/object/sign/${_path}`, _objectSpread22({ expiresIn }, hasTransform ? { transform: options.transform } : {}), { headers: _this8.headers });
34525
34525
  const query = new URLSearchParams();
@@ -34655,13 +34655,13 @@ var StorageFileApi = class extends BaseApiClient {
34655
34655
  * - `objects` table permissions: `select`
34656
34656
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
34657
34657
  */
34658
- download(path7, options, parameters) {
34658
+ download(path8, options, parameters) {
34659
34659
  const renderPath = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0 ? "render/image/authenticated" : "object";
34660
34660
  const query = new URLSearchParams();
34661
34661
  if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
34662
34662
  if ((options === null || options === void 0 ? void 0 : options.cacheNonce) != null) query.set("cacheNonce", String(options.cacheNonce));
34663
34663
  const queryString = query.toString();
34664
- const _path = this._getFinalPath(path7);
34664
+ const _path = this._getFinalPath(path8);
34665
34665
  const downloadFn = () => get(this.fetch, `${this.url}/${renderPath}/${_path}${queryString ? `?${queryString}` : ""}`, {
34666
34666
  headers: this.headers,
34667
34667
  noResolveJson: true
@@ -34692,9 +34692,9 @@ var StorageFileApi = class extends BaseApiClient {
34692
34692
  * }
34693
34693
  * ```
34694
34694
  */
34695
- async info(path7) {
34695
+ async info(path8) {
34696
34696
  var _this10 = this;
34697
- const _path = _this10._getFinalPath(path7);
34697
+ const _path = _this10._getFinalPath(path8);
34698
34698
  return _this10.handleOperation(async () => {
34699
34699
  return recursiveToCamel(await get(_this10.fetch, `${_this10.url}/object/info/${_path}`, { headers: _this10.headers }));
34700
34700
  });
@@ -34715,9 +34715,9 @@ var StorageFileApi = class extends BaseApiClient {
34715
34715
  * .exists('folder/avatar1.png')
34716
34716
  * ```
34717
34717
  */
34718
- async exists(path7) {
34718
+ async exists(path8) {
34719
34719
  var _this11 = this;
34720
- const _path = _this11._getFinalPath(path7);
34720
+ const _path = _this11._getFinalPath(path8);
34721
34721
  try {
34722
34722
  await head(_this11.fetch, `${_this11.url}/object/${_path}`, { headers: _this11.headers });
34723
34723
  return {
@@ -34796,8 +34796,8 @@ var StorageFileApi = class extends BaseApiClient {
34796
34796
  * - `objects` table permissions: none
34797
34797
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
34798
34798
  */
34799
- getPublicUrl(path7, options) {
34800
- const _path = this._getFinalPath(path7);
34799
+ getPublicUrl(path8, options) {
34800
+ const _path = this._getFinalPath(path8);
34801
34801
  const query = new URLSearchParams();
34802
34802
  if (options === null || options === void 0 ? void 0 : options.download) query.set("download", options.download === true ? "" : options.download);
34803
34803
  if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
@@ -34936,10 +34936,10 @@ var StorageFileApi = class extends BaseApiClient {
34936
34936
  * - `objects` table permissions: `select`
34937
34937
  * - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
34938
34938
  */
34939
- async list(path7, options, parameters) {
34939
+ async list(path8, options, parameters) {
34940
34940
  var _this13 = this;
34941
34941
  return _this13.handleOperation(async () => {
34942
- const body = _objectSpread22(_objectSpread22(_objectSpread22({}, DEFAULT_SEARCH_OPTIONS), options), {}, { prefix: path7 || "" });
34942
+ const body = _objectSpread22(_objectSpread22(_objectSpread22({}, DEFAULT_SEARCH_OPTIONS), options), {}, { prefix: path8 || "" });
34943
34943
  return await post(_this13.fetch, `${_this13.url}/object/list/${_this13.bucketId}`, body, { headers: _this13.headers }, parameters);
34944
34944
  });
34945
34945
  }
@@ -35004,11 +35004,11 @@ var StorageFileApi = class extends BaseApiClient {
35004
35004
  if (typeof Buffer !== "undefined") return Buffer.from(data).toString("base64");
35005
35005
  return btoa(data);
35006
35006
  }
35007
- _getFinalPath(path7) {
35008
- return `${this.bucketId}/${path7.replace(/^\/+/, "")}`;
35007
+ _getFinalPath(path8) {
35008
+ return `${this.bucketId}/${path8.replace(/^\/+/, "")}`;
35009
35009
  }
35010
- _removeEmptyFolders(path7) {
35011
- return path7.replace(/^\/|\/$/g, "").replace(/\/+/g, "/");
35010
+ _removeEmptyFolders(path8) {
35011
+ return path8.replace(/^\/|\/$/g, "").replace(/\/+/g, "/");
35012
35012
  }
35013
35013
  /** Modifies the `query`, appending values the from `transform` */
35014
35014
  applyTransformOptsToQuery(query, transform2) {
@@ -40919,6 +40919,23 @@ var goalListMeasurablesOutputSchema = external_exports.object({
40919
40919
  goal_id: uuidSchema8,
40920
40920
  bindings: external_exports.array(goalMeasurableBindingSchema)
40921
40921
  }).strict();
40922
+ var goalCoreSchema = external_exports.object({
40923
+ id: uuidSchema8,
40924
+ title: external_exports.string(),
40925
+ kind: external_exports.enum(["objective", "cycle_goal", "company_objective", "seat_goal", "milestone"]),
40926
+ status: goalStatusSchema,
40927
+ status_source: goalStatusSourceSchema,
40928
+ progress_pct: external_exports.number().int().min(0).max(100).nullable(),
40929
+ seat_id: uuidSchema8.nullable(),
40930
+ parent_goal_id: uuidSchema8.nullable(),
40931
+ definition_of_done: external_exports.string()
40932
+ }).strict();
40933
+ var goalGetInputSchema = external_exports.object({
40934
+ goal_id: uuidSchema8
40935
+ }).strict();
40936
+ var goalGetOutputSchema = external_exports.object({
40937
+ goal: goalCoreSchema
40938
+ }).strict();
40922
40939
  var issueStatusSchema = external_exports.enum(["open", "diagnosing", "resolved", "dropped"]);
40923
40940
  var frictionListInputSchema = external_exports.object({
40924
40941
  status: external_exports.enum(["open", "diagnosing", "resolved", "dropped", "active", "all"]).optional()
@@ -40941,6 +40958,28 @@ var frictionIssueSummarySchema = external_exports.object({
40941
40958
  var frictionListOutputSchema = external_exports.object({
40942
40959
  issues: external_exports.array(frictionIssueSummarySchema)
40943
40960
  }).strict();
40961
+ var frictionIssueDetailSchema = frictionIssueSummarySchema.extend({
40962
+ raised_by_seat_type: external_exports.enum(["human", "agent", "hybrid"]),
40963
+ raised_by_seat_steward_name: external_exports.string().nullable(),
40964
+ origin_actor_kind: external_exports.enum(["user", "agent", "system"]).nullable(),
40965
+ origin_actor_id: uuidSchema8.nullable(),
40966
+ evidence: external_exports.unknown(),
40967
+ action_task_title: external_exports.string().nullable(),
40968
+ action_task_owner_seat_id: uuidSchema8.nullable(),
40969
+ action_task_owner_seat_name: external_exports.string().nullable(),
40970
+ action_task_due_on: external_exports.string().nullable(),
40971
+ decision_id: uuidSchema8.nullable(),
40972
+ decision_title: external_exports.string().nullable(),
40973
+ decision_summary: external_exports.string().nullable(),
40974
+ decided_by_name: external_exports.string().nullable(),
40975
+ updated_at: external_exports.string()
40976
+ }).strict();
40977
+ var frictionGetInputSchema = external_exports.object({
40978
+ issue_id: uuidSchema8
40979
+ }).strict();
40980
+ var frictionGetOutputSchema = external_exports.object({
40981
+ issue: frictionIssueDetailSchema
40982
+ }).strict();
40944
40983
  var frictionUpdateStatusInputSchema = external_exports.object({
40945
40984
  issue_id: uuidSchema8,
40946
40985
  status: external_exports.enum(["open", "diagnosing"])
@@ -40952,17 +40991,34 @@ var frictionUpdateStatusOutputSchema = external_exports.object({
40952
40991
  }).strict();
40953
40992
  var frictionResolveInputSchema = external_exports.object({
40954
40993
  issue_id: uuidSchema8,
40994
+ resolution_mode: external_exports.enum(["ids", "already_fixed"]).default("ids"),
40955
40995
  root_cause: external_exports.string().trim().min(1),
40956
- owner_seat_id: uuidSchema8,
40957
- task_title: external_exports.string().trim().min(1),
40958
- task_description: external_exports.string().trim().min(1),
40959
- done_by: dateOnlySchema,
40996
+ owner_seat_id: uuidSchema8.optional(),
40997
+ task_title: external_exports.string().trim().min(1).optional(),
40998
+ task_description: external_exports.string().trim().min(1).optional(),
40999
+ done_by: dateOnlySchema.optional(),
40960
41000
  resolving_seat_id: uuidSchema8.optional()
40961
- }).strict();
41001
+ }).strict().superRefine((value, ctx) => {
41002
+ if (value.resolution_mode !== "ids") {
41003
+ return;
41004
+ }
41005
+ if (value.owner_seat_id === void 0) {
41006
+ ctx.addIssue({ code: "custom", path: ["owner_seat_id"], message: 'Required for resolution_mode "ids".' });
41007
+ }
41008
+ if (value.task_title === void 0) {
41009
+ ctx.addIssue({ code: "custom", path: ["task_title"], message: 'Required for resolution_mode "ids".' });
41010
+ }
41011
+ if (value.task_description === void 0) {
41012
+ ctx.addIssue({ code: "custom", path: ["task_description"], message: 'Required for resolution_mode "ids".' });
41013
+ }
41014
+ if (value.done_by === void 0) {
41015
+ ctx.addIssue({ code: "custom", path: ["done_by"], message: 'Required for resolution_mode "ids".' });
41016
+ }
41017
+ });
40962
41018
  var frictionResolveOutputSchema = external_exports.object({
40963
41019
  issue_id: uuidSchema8,
40964
41020
  status: external_exports.literal("resolved"),
40965
- action_task_id: uuidSchema8,
41021
+ action_task_id: uuidSchema8.nullable(),
40966
41022
  decision_id: uuidSchema8
40967
41023
  }).strict();
40968
41024
  var frictionLinkTaskInputSchema = external_exports.object({
@@ -41565,6 +41621,18 @@ var compassShowMarkdownInputSchema = external_exports.object({}).strict();
41565
41621
  var charterShowMarkdownInputSchema = external_exports.object({
41566
41622
  seat_id: uuidSchema9
41567
41623
  }).strict();
41624
+ var charterShowMarkdownOutputSchema = external_exports.object({
41625
+ markdown: external_exports.string().min(1),
41626
+ charter_version_id: uuidSchema9.nullable(),
41627
+ seat_id: uuidSchema9,
41628
+ version: external_exports.number().int().nonnegative().nullable(),
41629
+ status: external_exports.string().nullable(),
41630
+ doc: external_exports.unknown().nullable(),
41631
+ dry_run: external_exports.object({
41632
+ status: external_exports.enum(["passed", "failed"]),
41633
+ summary: external_exports.string()
41634
+ }).strict().nullable()
41635
+ }).strict();
41568
41636
  var agentShowMarkdownInputSchema = external_exports.object({
41569
41637
  seat_id: uuidSchema9
41570
41638
  }).strict();
@@ -41799,6 +41867,27 @@ var confirmationRejectOutputSchema = external_exports.object({
41799
41867
  command_id: external_exports.string().min(1),
41800
41868
  rejected: external_exports.literal(true)
41801
41869
  }).strict();
41870
+ var confirmationListInputSchema = external_exports.object({
41871
+ limit: external_exports.number().int().min(1).max(200).optional()
41872
+ }).strict();
41873
+ var confirmationSummarySchema = external_exports.object({
41874
+ id: uuidSchema10,
41875
+ command_id: external_exports.string(),
41876
+ redacted_args: external_exports.unknown(),
41877
+ actor_kind: external_exports.enum(["user", "agent", "system"]),
41878
+ source: external_exports.string(),
41879
+ scope_kind: external_exports.enum(["tenant_admin", "tenant", "seat"]),
41880
+ seat_id: uuidSchema10.nullable(),
41881
+ seat_name: external_exports.string().nullable(),
41882
+ seat_type: external_exports.enum(["human", "agent", "hybrid"]).nullable(),
41883
+ risk_level: external_exports.enum(["normal", "sensitive", "dangerous"]),
41884
+ summary: external_exports.string(),
41885
+ expires_at: external_exports.string(),
41886
+ created_at: external_exports.string()
41887
+ }).strict();
41888
+ var confirmationListOutputSchema = external_exports.object({
41889
+ confirmations: external_exports.array(confirmationSummarySchema)
41890
+ }).strict();
41802
41891
  var credentialIngressInputSchema = external_exports.object({
41803
41892
  seat_id: uuidSchema10.optional(),
41804
41893
  provider: external_exports.string().trim().min(1),
@@ -46261,7 +46350,7 @@ External connectors are being rolled out provider by provider, conservatively (r
46261
46350
  order: 48,
46262
46351
  title: "CLI and MCP installation guide",
46263
46352
  summary: "Install the public CLI, register remote token-backed MCP clients, and find the full command and tool catalog.",
46264
- version: "2026-07-12.2",
46353
+ version: "2026-07-12.3",
46265
46354
  public: true,
46266
46355
  audiences: ["human", "cli", "mcp", "in_app_agent"],
46267
46356
  stages: ["company_setup", "staffing"],
@@ -46834,6 +46923,7 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
46834
46923
  | \`rost_skip_charter_draft\` | \`charter.skip\` | Mark a Charter draft as skipped. | Seat or tenant-admin | Call only when a human defers the seat. |
46835
46924
  | \`rost_apply_charter_seat_type_recommendation\` | \`charter.apply_seat_type_recommendation\` | Apply a Charter's seat-type recommendation. | Seat or tenant-admin | Call after reviewing the draft. |
46836
46925
  | \`rost_sign_charter_manifest\` | \`charter.sign_manifest\` | Request human confirmation for a permission manifest. | Seat or tenant-admin | Use after tool permissions are reviewed. |
46926
+ | \`rost_list_pending_confirmations\` | \`confirmation.list\` | List in-flight confirmations awaiting a human decision, scoped to the caller's authority (owner sees all; a member sees seats they occupy; an agent sees its own seat). | Seat or tenant-admin | Call with \`{}\`. |
46837
46927
  | \`rost_draft_compass\` | \`compass.draft\` | Create a Compass draft. | Tenant | Call with a concise Compass document. |
46838
46928
  | \`rost_update_compass_draft\` | \`compass.update_draft\` | Replace a Compass draft document. | Tenant | Call with the \`compass_version_id\` from \`compass.draft\` as \`draft_id\` and the updated document. |
46839
46929
  | \`rost_approve_compass_version\` | \`compass.approve_version\` | Activate a Compass version by supersession. | Tenant | Call after human review. |
@@ -46934,6 +47024,7 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
46934
47024
  | \`rost_import_rocks_from_a_ninety_rocks_export\` | \`cascade.import\` | Bulk-import Rocks as Cascade cycle goals under a company objective in the active cycle (from a ninety Rocks export). Owners resolve to seats; idempotent re-import skips a cycle goal already imported for the same objective + seat + title. | Tenant | Call with the parsed \`rocks\` array. |
46935
47025
  | \`rost_import_a_ninety_v_to_into_a_compass_draft\` | \`compass.import\` | AI-draft a Compass from a ninety V/TO (Core Values \u2192 principles, 10/3/1-Year \u2192 horizon goals, Rocks \u2192 cycle objectives), landed as a draft a human confirms by supersession \u2014 never an accepted Compass. Idempotent by document content (a re-upload of the same V/TO short-circuits without re-drafting). | Tenant | Call with the extracted V/TO \`text\` (and optional \`source_name\`). |
46936
47026
  | \`rost_list_cascade_goals\` | \`goal.list\` | List Cascade goals, optionally by cycle or seat. | Seat or tenant-admin | Call with \`{}\` or \`{"cycle_id":"<id>"}\`. |
47027
+ | \`rost_get_cascade_goal\` | \`goal.get\` | Get one goal's core detail and status by id. Seat-scoped callers may only read their own seat's goals. | Seat or tenant-admin | Call with \`{"goal_id":"<id>"}\`. |
46937
47028
  | \`rost_list_a_cascade_goals_signals\` | \`goal.list_measurables\` | List the goal's status-driving Signal binding (role drives_status; 0-or-1 per goal) with its current indicator and latest confirmed reading. Driver-only \u2014 informs bindings (direct indicators) are not returned. Read-only. | Seat or tenant-admin | Call with \`{"goal_id":"<id>"}\`. |
46938
47029
  | \`rost_create_cascade_goal\` | \`goal.create\` | Create a cycle goal under an objective. | Tenant | Call with cycle, seat, parent, title, definition of done. |
46939
47030
  | \`rost_update_cascade_goal\` | \`goal.update\` | Update a goal's title or definition of done. | Tenant | Call with \`goal_id\` and the changed fields. |
@@ -46946,6 +47037,7 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
46946
47037
  | \`rost_reparent_cascade_goal\` | \`goal.reparent\` | Move a goal under a new parent. | Tenant | Authority change; expect confirmation. |
46947
47038
  | \`rost_drop_cascade_goal\` | \`goal.drop\` | Drop (retire) a goal, retained for audit. | Tenant | Expect confirmation. |
46948
47039
  | \`rost_list_friction_issues\` | \`friction.list\` | List Friction issues ranked by impact and severity. | Seat or tenant-admin | Call with \`{}\` or \`{"status":"active"}\`. |
47040
+ | \`rost_get_friction_issue\` | \`friction.get\` | Get full detail for one Friction issue by id. | Seat or tenant-admin | Call with \`{"issue_id":"<id>"}\`. |
46949
47041
  | \`rost_assist_friction_issue\` | \`friction.assist\` | Advisory IDS assist: the most-similar prior resolved issues with their root causes and decisions, a recurring-pattern flag, and recommended options. Read-only \u2014 it never resolves the issue. | Tenant | Call with \`{"issue_id":"<id>"}\`. |
46950
47042
  | \`rost_update_friction_issue_status\` | \`friction.update_status\` | Move a non-terminal issue between open and diagnosing. | Seat or tenant-admin | Call with \`issue_id\` and \`status\`. |
46951
47043
  | \`rost_resolve_friction_issue\` | \`friction.resolve\` | Resolve an issue with a root cause and remediation task. | Tenant | Human decision; expect confirmation. |
@@ -47516,6 +47608,7 @@ Retrieve the narrowest relevant guide before making a setup recommendation. Pref
47516
47608
  "compass.approve_version",
47517
47609
  "onboarding.finish",
47518
47610
  "goal.list",
47611
+ "goal.get",
47519
47612
  "goal.create",
47520
47613
  "goal.update",
47521
47614
  "goal.set_status",
@@ -47735,6 +47828,7 @@ Agents may record readings when the Charter allows it. Agent-reported readings s
47735
47828
  "compass.answer_gap",
47736
47829
  "friction.file_issue",
47737
47830
  "friction.list",
47831
+ "friction.get",
47738
47832
  "friction.assist",
47739
47833
  "friction.update_status",
47740
47834
  "friction.resolve",
@@ -47881,7 +47975,7 @@ Keep agent scope tight at first. Approve more autonomy only after evidence. Use
47881
47975
  public: true,
47882
47976
  audiences: ["human", "cli", "mcp", "in_app_agent"],
47883
47977
  stages: ["graph_design", "charter_design", "staffing", "operating_rhythm"],
47884
- relatedCommandIds: ["confirmation.approve", "confirmation.reject", "charter.approve", "agent.go_live", "credential.ingress", "mcp_token.create", "staffing.assign_user", "goal.reparent", "friction.resolve"],
47978
+ relatedCommandIds: ["confirmation.approve", "confirmation.list", "confirmation.reject", "charter.approve", "agent.go_live", "credential.ingress", "mcp_token.create", "staffing.assign_user", "goal.reparent", "friction.resolve"],
47885
47979
  legal: { publicRisk: "low", notes: ["{{brand}}-native human-gate guidance."] },
47886
47980
  sources: [
47887
47981
  {
@@ -50026,6 +50120,11 @@ function helpText() {
50026
50120
  ].join("\n");
50027
50121
  }
50028
50122
 
50123
+ // src/update-check.ts
50124
+ import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
50125
+ import { homedir as homedir2 } from "node:os";
50126
+ import path2 from "node:path";
50127
+
50029
50128
  // src/cli-version.ts
50030
50129
  import { readFile as readFile2 } from "node:fs/promises";
50031
50130
  import { dirname as dirname2, resolve } from "node:path";
@@ -50047,15 +50146,23 @@ async function readCliVersion() {
50047
50146
  var latestPackageSchema = external_exports.object({
50048
50147
  version: external_exports.string()
50049
50148
  });
50050
- async function maybePrintUpgradeNudge(io) {
50051
- if (process.env.CI || process.env.VITEST || process.env.CLI_SKIP_UPDATE_CHECK === "1") {
50149
+ var updateCheckStateSchema = external_exports.object({ lastNaggedOn: external_exports.string() }).strict();
50150
+ async function maybePrintUpgradeNudge(io, options = {}) {
50151
+ if (!options.skipEnvGuard && (process.env.CI || process.env.VITEST || process.env.CLI_SKIP_UPDATE_CHECK === "1")) {
50152
+ return;
50153
+ }
50154
+ const statePath = options.statePath ?? defaultUpdateCheckStatePath();
50155
+ const today = toUtcDateOnly(options.now ?? /* @__PURE__ */ new Date());
50156
+ const state = await readUpdateCheckState(statePath);
50157
+ if (state?.lastNaggedOn === today) {
50052
50158
  return;
50053
50159
  }
50054
50160
  const currentVersion = await readCliVersion();
50055
50161
  if (!currentVersion || currentVersion === "0.0.0") {
50056
50162
  return;
50057
50163
  }
50058
- const latestVersion = await fetchLatestVersion(cliBrand.packageName);
50164
+ const fetchLatest = options.fetchLatest ?? fetchLatestVersion;
50165
+ const latestVersion = await fetchLatest(cliBrand.packageName);
50059
50166
  if (!latestVersion || !isSemverBehind(currentVersion, latestVersion)) {
50060
50167
  return;
50061
50168
  }
@@ -50063,6 +50170,28 @@ async function maybePrintUpgradeNudge(io) {
50063
50170
  `A newer ${cliBrand.binName} CLI is available: ${currentVersion} -> ${latestVersion}. Upgrade with npm i -g ${cliBrand.packageName}@latest.
50064
50171
  `
50065
50172
  );
50173
+ await writeUpdateCheckStateBestEffort(statePath, { lastNaggedOn: today });
50174
+ }
50175
+ function defaultUpdateCheckStatePath() {
50176
+ return path2.join(homedir2(), ".config", cliBrand.binName, "update-check.json");
50177
+ }
50178
+ function toUtcDateOnly(date5) {
50179
+ return date5.toISOString().slice(0, 10);
50180
+ }
50181
+ async function readUpdateCheckState(statePath) {
50182
+ try {
50183
+ return updateCheckStateSchema.parse(JSON.parse(await readFile3(statePath, "utf8")));
50184
+ } catch {
50185
+ return null;
50186
+ }
50187
+ }
50188
+ async function writeUpdateCheckStateBestEffort(statePath, state) {
50189
+ try {
50190
+ await mkdir2(path2.dirname(statePath), { recursive: true, mode: 448 });
50191
+ await writeFile2(statePath, `${JSON.stringify(state)}
50192
+ `, { mode: 384 });
50193
+ } catch {
50194
+ }
50066
50195
  }
50067
50196
  async function fetchLatestVersion(packageName) {
50068
50197
  const controller = new AbortController();
@@ -50168,6 +50297,7 @@ var COMMAND_MANIFEST = [
50168
50297
  { "id": "compass.show_markdown", "namespace": "compass", "action": "show_markdown", "title": "Show Compass as markdown", "description": "Compose the current Compass and its open gaps into a clean, human-skimmable markdown card for review.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Render the current Compass and its open gaps as a clean markdown card to show your human a quick review." },
50169
50298
  { "id": "compass.update_draft", "namespace": "compass", "action": "update_draft", "title": "Update Compass draft", "description": "Replace a draft Compass document.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "draft_id", "flag": "draft-id", "type": "string", "required": true }], "hasComplexInput": true, "help": "Pass the compass_version_id returned by compass.draft as draft_id; update_draft replaces only an unpublished draft in this tenant." },
50170
50299
  { "id": "confirmation.approve", "namespace": "confirmation", "action": "approve", "title": "Approve pending confirmation", "description": "Approve an in-flight confirmation and execute the original command as the approving human.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "confirmation_id", "flag": "confirmation-id", "type": "string", "required": true }, { "name": "reviewed", "flag": "reviewed", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "Approve pending confirmations only when the requested durable change is clear to the human owner." },
50300
+ { "id": "confirmation.list", "namespace": "confirmation", "action": "list", "title": "List pending confirmations", "description": "List in-flight confirmations awaiting a human decision, scoped to the caller's authority (owner sees all; a member sees seats they occupy; an agent sees its own seat).", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "limit", "flag": "limit", "type": "integer", "required": false }], "hasComplexInput": false, "help": "List pending confirmations awaiting a human decision before approving or rejecting them." },
50171
50301
  { "id": "confirmation.reject", "namespace": "confirmation", "action": "reject", "title": "Reject pending confirmation", "description": "Reject an in-flight confirmation without executing the original command.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "confirmation_id", "flag": "confirmation-id", "type": "string", "required": true }, { "name": "reason", "flag": "reason", "type": "string", "required": false }], "hasComplexInput": false, "help": "Reject pending confirmations when authority, evidence, or human intent is unclear." },
50172
50302
  { "id": "credential.ingress", "namespace": "credential", "action": "ingress", "title": "Store credential", "description": "Store a secret through the vault and persist only the credential vault reference.", "requiredScope": "seat", "confirmation": "credential_flow", "exposeOverMcp": false, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }, { "name": "provider", "flag": "provider", "type": "string", "required": true }, { "name": "scope_description", "flag": "scope-description", "type": "string", "required": true }, { "name": "secret_name", "flag": "secret-name", "type": "string", "required": true }], "hasComplexInput": false, "secretBlocked": true, "help": "Ingress credentials only through vault-backed flows; never place raw secrets in prompts, logs, or docs." },
50173
50303
  { "id": "deliverable.accept", "namespace": "deliverable", "action": "accept", "title": "Accept deliverable value", "description": "Record a human-confirmed accepted value (USD) on a deliverable. Humans decide; agents cannot self-accept. Re-accepting records a correction as a new event; prior events are never mutated.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "deliverable_id", "flag": "deliverable-id", "type": "string", "required": true }, { "name": "impact_value_usd", "flag": "impact-value-usd", "type": "number", "required": true }], "hasComplexInput": false, "help": "Record a human-confirmed accepted value (USD) on a deliverable; owner-only and human-gated. Humans decide \u2014 agents cannot self-accept. Re-accepting records a correction as a new event." },
@@ -50185,14 +50315,16 @@ var COMMAND_MANIFEST = [
50185
50315
  { "id": "escalation.resolve", "namespace": "escalation", "action": "resolve", "title": "Resolve escalation", "description": "Approve an open escalation (or convert it to Friction). Writes a human decision; agents cannot resolve.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": false, "fields": [{ "name": "id", "flag": "id", "type": "string", "required": true }, { "name": "action", "flag": "action", "type": "enum", "required": false, "enumValues": ["approve", "convert_to_issue"] }, { "name": "rationale", "flag": "rationale", "type": "string", "required": false }], "hasComplexInput": false, "help": "Resolve an escalation as a human Steward; the decision records decided_by as the approving human. Agents cannot resolve." },
50186
50316
  { "id": "friction.assist", "namespace": "friction", "action": "assist", "title": "Assist Friction issue", "description": "Advisory IDS assist for an issue: the most-similar prior resolved issues with their root causes and decisions, a recurring-pattern flag, and recommended options. Read-only \u2014 it never resolves the issue.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "limit", "flag": "limit", "type": "integer", "required": false }], "hasComplexInput": false, "help": "Advisory IDS assist: the most-similar prior resolved issues with their root causes and decisions, plus a recurring-pattern flag. Read-only \u2014 it never resolves the issue." },
50187
50317
  { "id": "friction.file_issue", "namespace": "friction", "action": "file_issue", "title": "File Friction issue", "description": "Emit an issue event and open a Friction issue raised by the acting seat.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "summary", "flag": "summary", "type": "string", "required": true }, { "name": "blocking_goal_id", "flag": "blocking-goal-id", "type": "string", "required": false }, { "name": "broken_measurable_id", "flag": "broken-measurable-id", "type": "string", "required": false }, { "name": "severity", "flag": "severity", "type": "enum", "required": true, "enumValues": ["low", "med", "high", "critical"] }], "hasComplexInput": true, "help": "File a Friction issue with evidence when a goal or measurable is blocked or broken." },
50318
+ { "id": "friction.get", "namespace": "friction", "action": "get", "title": "Get Friction issue", "description": "Get full detail for one Friction issue by id.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Get full detail for one Friction issue by id, including its root cause, action task, and resolution decision when present." },
50188
50319
  { "id": "friction.import", "namespace": "friction", "action": "import", "title": "Import Friction issues from a ninety Issues List", "description": "Bulk-import a ninety Issues List export into Friction. Owners are seat names resolved to seats; each issue is raised by the resolved seat and attributed to the importing human. Idempotent \u2014 re-importing the same export is a no-op, and an existing open issue with the same seat + summary is skipped.", "requiredScope": "tenant_admin", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "dry_run", "flag": "dry-run", "type": "boolean", "required": false }], "hasComplexInput": true, "help": "Import a ninety Issues List export into Friction; owners resolve to seats, idempotent by file + seat/summary." },
50189
50320
  { "id": "friction.link_task", "namespace": "friction", "action": "link_task", "title": "Link task to Friction issue", "description": "Attach an existing tenant task as the action task for a non-terminal issue. Both ids must belong to the tenant.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "task_id", "flag": "task-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Attach an existing task as the action task for a non-terminal issue." },
50190
50321
  { "id": "friction.list", "namespace": "friction", "action": "list", "title": "List Friction issues", "description": "List Friction issues ranked by status, impact, and severity. Defaults to active (open + diagnosing).", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["open", "diagnosing", "resolved", "dropped", "active", "all"] }], "hasComplexInput": false, "help": "List Friction issues ranked by impact and severity to find the issue id before updating or resolving it." },
50191
- { "id": "friction.resolve", "namespace": "friction", "action": "resolve", "title": "Resolve Friction issue", "description": "Resolve an issue with a root cause and remediation task. This records a human decision (decided_by) and creates the follow-up task in one transaction.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "root_cause", "flag": "root-cause", "type": "string", "required": true }, { "name": "owner_seat_id", "flag": "owner-seat-id", "type": "string", "required": true }, { "name": "task_title", "flag": "task-title", "type": "string", "required": true }, { "name": "task_description", "flag": "task-description", "type": "string", "required": true }, { "name": "done_by", "flag": "done-by", "type": "string", "required": true }, { "name": "resolving_seat_id", "flag": "resolving-seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Resolve an issue with a root cause and remediation task; resolution is a human decision." },
50322
+ { "id": "friction.resolve", "namespace": "friction", "action": "resolve", "title": "Resolve Friction issue", "description": 'Resolve an issue with a root cause. In the default "ids" resolution_mode this also creates a remediation follow-up task; "already_fixed" records only the root cause (no follow-up task). Always records a human decision (decided_by) in the same transaction.', "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "resolution_mode", "flag": "resolution-mode", "type": "enum", "required": false, "enumValues": ["ids", "already_fixed"] }, { "name": "root_cause", "flag": "root-cause", "type": "string", "required": true }, { "name": "owner_seat_id", "flag": "owner-seat-id", "type": "string", "required": false }, { "name": "task_title", "flag": "task-title", "type": "string", "required": false }, { "name": "task_description", "flag": "task-description", "type": "string", "required": false }, { "name": "done_by", "flag": "done-by", "type": "string", "required": false }, { "name": "resolving_seat_id", "flag": "resolving-seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Resolve an issue with a root cause and remediation task; resolution is a human decision." },
50192
50323
  { "id": "friction.update_status", "namespace": "friction", "action": "update_status", "title": "Update Friction issue status", "description": "Move a non-terminal issue between open and diagnosing. Terminal issues (resolved/dropped) cannot be reopened here.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "status", "flag": "status", "type": "enum", "required": true, "enumValues": ["open", "diagnosing"] }], "hasComplexInput": false, "help": "Move a non-terminal issue between open and diagnosing while it is being worked." },
50193
50324
  { "id": "goal.bind_measurable", "namespace": "goal", "action": "bind_measurable", "title": "Bind a Signal to a Cascade goal", "description": "Bind a measurable to a goal. Role defaults to 'informs' \u2014 a conservative informative indicator allowed at any goal level (many per goal) that never changes goal status. Role 'drives_status' makes it the goal's status driver: allowed only on a childless seat goal or milestone, at most one per goal, and auto-status starts OFF until a steward opts in with goal.set_auto_status. Binding is human-gated.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }, { "name": "measurable_id", "flag": "measurable-id", "type": "string", "required": true }, { "name": "role", "flag": "role", "type": "enum", "required": false, "enumValues": ["drives_status", "informs"] }], "hasComplexInput": false, "help": "Bind a Signal to a goal. Defaults to role informs (a conservative indicator at any level that never changes status); pass role drives_status to make it a childless leaf goal's status driver (auto-status starts OFF until a steward opts in)." },
50194
50325
  { "id": "goal.create", "namespace": "goal", "action": "create", "title": "Create Cascade goal", "description": "Create a cycle goal under an existing objective. The parent chain must terminate at a Compass objective in the same cycle (enforced server-side).", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "cycle_id", "flag": "cycle-id", "type": "string", "required": true }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "parent_goal_id", "flag": "parent-goal-id", "type": "string", "required": true }, { "name": "title", "flag": "title", "type": "string", "required": true }, { "name": "definition_of_done", "flag": "definition-of-done", "type": "string", "required": true }, { "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["on", "off"] }], "hasComplexInput": false, "help": "Create cycle goals under an existing objective; the parent chain must terminate at a Compass objective." },
50195
50326
  { "id": "goal.drop", "namespace": "goal", "action": "drop", "title": "Drop Cascade goal", "description": "Drop (retire) a goal by setting status to dropped. Dropping retires the commitment, so it is human-gated. The row is retained for audit (never deleted).", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Drop a goal to retire a commitment; the goal is retained for audit and dropping is human-gated." },
50327
+ { "id": "goal.get", "namespace": "goal", "action": "get", "title": "Get Cascade goal", "description": "Get one goal's core detail and status by id. Seat-scoped callers may only read their own seat's goals.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Get one goal's core detail and status by id; seat tokens may only read their own goals." },
50196
50328
  { "id": "goal.list", "namespace": "goal", "action": "list", "title": "List Cascade goals", "description": "List goals in the tenant, optionally filtered by cycle or seat. Seat-scoped callers see only their own seat's goals.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "cycle_id", "flag": "cycle-id", "type": "string", "required": false }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "List Cascade goals to find goal ids, parentage, and seat ownership before mutating the tree." },
50197
50329
  { "id": "goal.list_at_risk", "namespace": "goal", "action": "list_at_risk", "title": "List at-risk Cascade goals", "description": "List goals projected to miss their cycle pace (at-risk or projected-miss), with how many days behind pace. Read-only; status-only goals (no progress) are excluded.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "List goals projected off pace (at-risk or projected-miss), with how many days behind pace. Read-only; status-only goals are excluded." },
50198
50330
  { "id": "goal.list_measurables", "namespace": "goal", "action": "list_measurables", "title": "List a Cascade goal's Signals", "description": "List the status-driver Signal bound to a Cascade goal (role drives_status), with its current signal indicator and latest confirmed reading. Read-only. Informative (informs) bindings appear in the goal-detail panel's Direct indicators, not here.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "List the Signals bound to a goal (role drives_status) with each one's current indicator and latest confirmed reading." },
@@ -50497,6 +50629,19 @@ function execute(context, parsed, commandId, body, format) {
50497
50629
  }
50498
50630
 
50499
50631
  // src/generator/flags.ts
50632
+ var SEAT_FLAG_FILLS_REQUIRED_SEAT_ID = /* @__PURE__ */ new Set([
50633
+ "agent.status",
50634
+ "agent.show_markdown",
50635
+ "agent.get_run",
50636
+ "agent.list_runs",
50637
+ "agent.list_tool_calls",
50638
+ "charter.show_markdown",
50639
+ "seat.get",
50640
+ "seat.decommission_preview",
50641
+ "deliverable.get",
50642
+ "deliverable.list",
50643
+ "skill.check_dependencies"
50644
+ ]);
50500
50645
  function booleanFlagsFor(entry, overrides = {}) {
50501
50646
  const booleanFields = new Set(entry.fields.filter((field3) => field3.type === "boolean").map((field3) => field3.name));
50502
50647
  const flags = /* @__PURE__ */ new Set(["yes", "y"]);
@@ -50586,6 +50731,9 @@ function buildBodyFromFlags(entry, parsed, positional, overrides = {}) {
50586
50731
  if (raw === void 0 && positional !== void 0 && overrides.primaryPositional === field3.name) {
50587
50732
  raw = positional;
50588
50733
  }
50734
+ if (raw === void 0 && field3.name === "seat_id" && (!field3.required || SEAT_FLAG_FILLS_REQUIRED_SEAT_ID.has(entry.id))) {
50735
+ raw = parsed.seat;
50736
+ }
50589
50737
  if (raw === void 0 || raw.length === 0) {
50590
50738
  continue;
50591
50739
  }
@@ -50990,6 +51138,15 @@ function renderGoalStatus(output) {
50990
51138
  const record2 = asRecord(output);
50991
51139
  return `Goal ${field(record2, "goal_id")} status set to ${field(record2, "status")}.`;
50992
51140
  }
51141
+ function renderGoalGet(output) {
51142
+ const record2 = asRecord(asRecord(output).goal);
51143
+ return [
51144
+ `${field(record2, "id")} ${field(record2, "status")} ${field(record2, "title")}`,
51145
+ `kind: ${field(record2, "kind")} status source: ${field(record2, "status_source")}`,
51146
+ `progress: ${field(record2, "progress_pct")}`,
51147
+ `definition of done: ${field(record2, "definition_of_done")}`
51148
+ ].join("\n");
51149
+ }
50993
51150
  function renderGoalReparent(output) {
50994
51151
  const record2 = asRecord(output);
50995
51152
  return `Goal ${field(record2, "goal_id")} reparented under ${field(record2, "parent_goal_id")}.`;
@@ -51020,6 +51177,27 @@ function renderFrictionLink(output) {
51020
51177
  const record2 = asRecord(output);
51021
51178
  return `Linked task ${field(record2, "action_task_id")} to issue ${field(record2, "issue_id")}.`;
51022
51179
  }
51180
+ function renderFrictionGet(output) {
51181
+ const record2 = asRecord(asRecord(output).issue);
51182
+ return [
51183
+ `${field(record2, "issue_id")} ${field(record2, "status")} ${field(record2, "severity")}`,
51184
+ `summary: ${field(record2, "summary")}`,
51185
+ `raised by: ${field(record2, "raised_by_seat_name")}`,
51186
+ `impact score: ${field(record2, "impact_score")}`,
51187
+ `root cause: ${field(record2, "root_cause")}`,
51188
+ `action task: ${field(record2, "action_task_id")}`
51189
+ ].join("\n");
51190
+ }
51191
+ function renderConfirmationList(output) {
51192
+ const confirmations = asArray(asRecord(output).confirmations);
51193
+ if (confirmations.length === 0) {
51194
+ return "No pending confirmations.";
51195
+ }
51196
+ return confirmations.map((entry) => {
51197
+ const record2 = asRecord(entry);
51198
+ return `${field(record2, "id")} ${field(record2, "risk_level")} ${field(record2, "command_id")} ${field(record2, "summary")}`;
51199
+ }).join("\n");
51200
+ }
51023
51201
  function renderEscalationList(output) {
51024
51202
  const escalations = asArray(asRecord(output).escalations);
51025
51203
  if (escalations.length === 0) {
@@ -51922,7 +52100,8 @@ var GROUP_SPECS = {
51922
52100
  list: { commandId: "goal.list", render: renderGoalList },
51923
52101
  create: { commandId: "goal.create", render: renderGoalCreate },
51924
52102
  update: { commandId: "goal.update", handler: goalUpdateHandler, render: renderGoalUpdate },
51925
- status: { commandId: "goal.set_status", render: renderGoalStatus },
52103
+ status: { commandId: "goal.get", render: renderGoalGet, primaryPositional: "goal_id" },
52104
+ "set-status": { commandId: "goal.set_status", render: renderGoalStatus },
51926
52105
  reparent: { commandId: "goal.reparent", render: renderGoalReparent },
51927
52106
  drop: { commandId: "goal.drop", render: renderGoalDrop }
51928
52107
  }
@@ -51946,6 +52125,7 @@ var GROUP_SPECS = {
51946
52125
  friction: {
51947
52126
  verbs: {
51948
52127
  list: { commandId: "friction.list", render: renderFrictionList },
52128
+ get: { commandId: "friction.get", render: renderFrictionGet, primaryPositional: "issue_id" },
51949
52129
  file: { commandId: "friction.file_issue", handler: frictionFileHandler, render: renderFrictionFile },
51950
52130
  resolve: { commandId: "friction.resolve", render: renderFrictionResolve },
51951
52131
  link: { commandId: "friction.link_task", render: renderFrictionLink },
@@ -51967,7 +52147,7 @@ var GROUP_SPECS = {
51967
52147
  verbs: {
51968
52148
  list: { commandId: "escalation.list", render: renderEscalationList },
51969
52149
  get: { commandId: "escalation.get", render: renderEscalationGet, primaryPositional: "id" },
51970
- resolve: { commandId: "escalation.resolve", render: renderEscalationResolve },
52150
+ resolve: { commandId: "escalation.resolve", render: renderEscalationResolve, primaryPositional: "id" },
51971
52151
  reject: { commandId: "escalation.reject", render: renderEscalationReject }
51972
52152
  }
51973
52153
  },
@@ -52089,6 +52269,11 @@ var GROUP_SPECS = {
52089
52269
  verbs: {
52090
52270
  health: { commandId: "system.health", handler: systemHealthHandler, render: formatSystemHealth }
52091
52271
  }
52272
+ },
52273
+ confirmation: {
52274
+ verbs: {
52275
+ list: { commandId: "confirmation.list", render: renderConfirmationList }
52276
+ }
52092
52277
  }
52093
52278
  };
52094
52279
 
@@ -52378,7 +52563,7 @@ function ensureTrailingSlash2(value) {
52378
52563
  // src/skills.ts
52379
52564
  import { existsSync, mkdirSync, readFileSync as readFileSync3, rmSync, writeFileSync } from "node:fs";
52380
52565
  import os from "node:os";
52381
- import path2 from "node:path";
52566
+ import path3 from "node:path";
52382
52567
  var UsageError2 = class extends Error {
52383
52568
  };
52384
52569
  var CLIENTS = /* @__PURE__ */ new Set(["claude-code", "codex", "cursor"]);
@@ -52573,8 +52758,8 @@ function writeInstalls(output, root) {
52573
52758
  const slug2 = safeLocalSlug(String(install.slug ?? ""));
52574
52759
  const metadata = asRecord2(install.metadata);
52575
52760
  const files = asArray2(install.files).map(asRecord2);
52576
- const dir = path2.join(root, slug2);
52577
- const metadataPath = path2.join(dir, ".rost-skill.json");
52761
+ const dir = path3.join(root, slug2);
52762
+ const metadataPath = path3.join(dir, ".rost-skill.json");
52578
52763
  const expectedHash = String(metadata.content_sha256 ?? "");
52579
52764
  if (existingHash(metadataPath) === expectedHash) {
52580
52765
  return { slug: slug2, dir, status: "unchanged", files: files.length };
@@ -52584,8 +52769,8 @@ function writeInstalls(output, root) {
52584
52769
  for (const file2 of files) {
52585
52770
  const relativePath = safeRelativePath(String(file2.path ?? ""));
52586
52771
  const content = String(file2.content ?? "");
52587
- const target = path2.join(dir, relativePath);
52588
- mkdirSync(path2.dirname(target), { recursive: true });
52772
+ const target = path3.join(dir, relativePath);
52773
+ mkdirSync(path3.dirname(target), { recursive: true });
52589
52774
  writeFileSync(target, content, "utf8");
52590
52775
  }
52591
52776
  writeFileSync(metadataPath, `${JSON.stringify(metadata, null, 2)}
@@ -52605,7 +52790,7 @@ function removeRevokedInstalls(output, root) {
52605
52790
  if (installs.has(slug2)) {
52606
52791
  continue;
52607
52792
  }
52608
- const dir = path2.join(root, slug2);
52793
+ const dir = path3.join(root, slug2);
52609
52794
  if (!existsSync(dir)) {
52610
52795
  continue;
52611
52796
  }
@@ -52617,15 +52802,15 @@ function removeRevokedInstalls(output, root) {
52617
52802
  function installRoot(client, env) {
52618
52803
  const override = env.ROST_SKILL_INSTALL_ROOT;
52619
52804
  if (override && override.length > 0) {
52620
- return path2.resolve(override, client);
52805
+ return path3.resolve(override, client);
52621
52806
  }
52622
52807
  if (client === "codex") {
52623
- return path2.join(env.CODEX_HOME ?? path2.join(os.homedir(), ".codex"), "skills", "rost");
52808
+ return path3.join(env.CODEX_HOME ?? path3.join(os.homedir(), ".codex"), "skills", "rost");
52624
52809
  }
52625
52810
  if (client === "claude-code") {
52626
- return path2.join(env.CLAUDE_HOME ?? path2.join(os.homedir(), ".claude"), "skills", "rost");
52811
+ return path3.join(env.CLAUDE_HOME ?? path3.join(os.homedir(), ".claude"), "skills", "rost");
52627
52812
  }
52628
- return path2.join(os.homedir(), ".cursor", "skills", "rost");
52813
+ return path3.join(os.homedir(), ".cursor", "skills", "rost");
52629
52814
  }
52630
52815
  function safeRelativePath(value) {
52631
52816
  const normalized = value.trim().replaceAll("\\", "/").replace(/^\.\/+/, "");
@@ -52834,9 +53019,9 @@ import { promisify as promisify3 } from "node:util";
52834
53019
  import { existsSync as existsSync2, realpathSync } from "node:fs";
52835
53020
  import { readdir, rm as rm2, stat as stat2 } from "node:fs/promises";
52836
53021
  import { tmpdir } from "node:os";
52837
- import path3 from "node:path";
53022
+ import path4 from "node:path";
52838
53023
  var SANDBOX_EXEC_PATH = "/usr/bin/sandbox-exec";
52839
- var RUNNER_ASKPASS_DIR = path3.join(tmpdir(), "rost-runner-askpass");
53024
+ var RUNNER_ASKPASS_DIR = path4.join(tmpdir(), "rost-runner-askpass");
52840
53025
  var RUNNER_TEMP_PREFIXES = [
52841
53026
  "rost-runner-mcp-",
52842
53027
  "rost-runner-sandbox-",
@@ -53006,7 +53191,7 @@ function canonical(p) {
53006
53191
  }
53007
53192
  }
53008
53193
  function canonicalFile(p) {
53009
- return path3.join(canonical(path3.dirname(p)), path3.basename(p));
53194
+ return path4.join(canonical(path4.dirname(p)), path4.basename(p));
53010
53195
  }
53011
53196
  function isSandboxExecAvailable() {
53012
53197
  try {
@@ -53089,7 +53274,7 @@ async function sweepStaleRunnerTempFiles(dir, options = {}) {
53089
53274
  if (!RUNNER_TEMP_PREFIXES.some((prefix) => name.startsWith(prefix))) {
53090
53275
  return;
53091
53276
  }
53092
- const full = path3.join(dir, name);
53277
+ const full = path4.join(dir, name);
53093
53278
  try {
53094
53279
  const info = await stat2(full);
53095
53280
  if (now - info.mtimeMs < maxAgeMs) {
@@ -53107,9 +53292,9 @@ async function sweepStaleRunnerTempFiles(dir, options = {}) {
53107
53292
  // src/runner-service.ts
53108
53293
  import { execFile as execFileCallback2 } from "node:child_process";
53109
53294
  import { realpathSync as realpathSync2 } from "node:fs";
53110
- import { access, mkdir as mkdir2, readFile as readFile3, readdir as readdir2, rm as rm3, writeFile as writeFile2 } from "node:fs/promises";
53111
- import { homedir as homedir2 } from "node:os";
53112
- import path4 from "node:path";
53295
+ import { access, mkdir as mkdir3, readFile as readFile4, readdir as readdir2, rm as rm3, writeFile as writeFile3 } from "node:fs/promises";
53296
+ import { homedir as homedir3 } from "node:os";
53297
+ import path5 from "node:path";
53113
53298
  import { promisify as promisify2 } from "node:util";
53114
53299
  var execFile2 = promisify2(execFileCallback2);
53115
53300
  var SERVICE_VERBS = ["install-service", "start", "stop", "restart", "status", "logs", "uninstall"];
@@ -53126,9 +53311,9 @@ function isRunnerServiceInvocation(args) {
53126
53311
  function runnerServicePaths(homeDir, runnerName) {
53127
53312
  const safeName = safeRunnerName(runnerName);
53128
53313
  return {
53129
- launchAgentPath: path4.join(homeDir, "Library", "LaunchAgents", `${serviceLabel(safeName)}.plist`),
53130
- stateFile: path4.join(homeDir, "Library", "Application Support", cliBrand.name, `runner-${safeName}.json`),
53131
- logDir: path4.join(homeDir, "Library", "Logs", cliBrand.name, "runner", safeName)
53314
+ launchAgentPath: path5.join(homeDir, "Library", "LaunchAgents", `${serviceLabel(safeName)}.plist`),
53315
+ stateFile: path5.join(homeDir, "Library", "Application Support", cliBrand.name, `runner-${safeName}.json`),
53316
+ logDir: path5.join(homeDir, "Library", "Logs", cliBrand.name, "runner", safeName)
53132
53317
  };
53133
53318
  }
53134
53319
  function renderLaunchdPlist(config2) {
@@ -53170,9 +53355,9 @@ ${config2.allowDevelopmentAppUrl === true ? ` <key>${allowInsecureAppUrlEnv}<
53170
53355
  <key>RunAtLoad</key>
53171
53356
  <true/>
53172
53357
  <key>StandardOutPath</key>
53173
- <string>${escapePlist(path4.join(config2.logDir, "stdout.log"))}</string>
53358
+ <string>${escapePlist(path5.join(config2.logDir, "stdout.log"))}</string>
53174
53359
  <key>StandardErrorPath</key>
53175
- <string>${escapePlist(path4.join(config2.logDir, "stderr.log"))}</string>
53360
+ <string>${escapePlist(path5.join(config2.logDir, "stderr.log"))}</string>
53176
53361
  </dict>
53177
53362
  </plist>
53178
53363
  `;
@@ -53208,7 +53393,7 @@ ${serviceUsage()}
53208
53393
  userCode: parsed.userCode,
53209
53394
  nodePath: options.nodePath ?? resolveNodePath(),
53210
53395
  binPath: options.binPath ?? resolveBinPath(),
53211
- homeDir: options.homeDir ?? homedir2(),
53396
+ homeDir: options.homeDir ?? homedir3(),
53212
53397
  platform: options.platform ?? process.platform,
53213
53398
  exec: options.exec ?? defaultExec,
53214
53399
  uid: options.uid ?? (process.getuid ? process.getuid() : 0)
@@ -53239,9 +53424,9 @@ async function installService(options) {
53239
53424
  const safeName = safeRunnerName(options.runnerName);
53240
53425
  const paths = runnerServicePaths(options.homeDir, safeName);
53241
53426
  const label = serviceLabel(safeName);
53242
- await mkdir2(paths.logDir, { recursive: true });
53243
- await mkdir2(path4.dirname(paths.stateFile), { recursive: true });
53244
- await mkdir2(path4.dirname(paths.launchAgentPath), { recursive: true });
53427
+ await mkdir3(paths.logDir, { recursive: true });
53428
+ await mkdir3(path5.dirname(paths.stateFile), { recursive: true });
53429
+ await mkdir3(path5.dirname(paths.launchAgentPath), { recursive: true });
53245
53430
  if (options.userCode !== void 0) {
53246
53431
  const paired = await pairRunnerOnce(options, safeName, paths.stateFile, options.userCode);
53247
53432
  if (!paired) {
@@ -53259,7 +53444,7 @@ async function installService(options) {
53259
53444
  servicePath: buildServicePath(options.nodePath, options.homeDir),
53260
53445
  execute: options.execute
53261
53446
  });
53262
- await writeFile2(paths.launchAgentPath, plist, { mode: 420 });
53447
+ await writeFile3(paths.launchAgentPath, plist, { mode: 420 });
53263
53448
  await bootoutQuietly(options.exec, options.uid, paths.launchAgentPath);
53264
53449
  try {
53265
53450
  const bootstrapped = await bootstrapService(options.exec, options.uid, paths.launchAgentPath);
@@ -53396,8 +53581,8 @@ async function logsService(options) {
53396
53581
  const safeName = safeRunnerName(options.runnerName);
53397
53582
  const paths = runnerServicePaths(options.homeDir, safeName);
53398
53583
  const label = serviceLabel(safeName);
53399
- const stdoutLog = path4.join(paths.logDir, "stdout.log");
53400
- const stderrLog = path4.join(paths.logDir, "stderr.log");
53584
+ const stdoutLog = path5.join(paths.logDir, "stdout.log");
53585
+ const stderrLog = path5.join(paths.logDir, "stderr.log");
53401
53586
  options.io.stdout.write(
53402
53587
  `${[
53403
53588
  `runner service logs for ${label}:`,
@@ -53500,8 +53685,8 @@ function serviceTargets(uid, label) {
53500
53685
  return launchdDomains(uid).map((domain2) => `${domain2}/${label}`);
53501
53686
  }
53502
53687
  async function inspectRunnerServiceInstallations(options = {}) {
53503
- const homeDir = options.homeDir ?? homedir2();
53504
- const launchAgentsDir = path4.join(homeDir, "Library", "LaunchAgents");
53688
+ const homeDir = options.homeDir ?? homedir3();
53689
+ const launchAgentsDir = path5.join(homeDir, "Library", "LaunchAgents");
53505
53690
  let names = [];
53506
53691
  try {
53507
53692
  const entries = await readdir2(launchAgentsDir);
@@ -53521,7 +53706,7 @@ async function inspectRunnerService(options) {
53521
53706
  const paths = runnerServicePaths(options.homeDir, safeName);
53522
53707
  const label = serviceLabel(safeName);
53523
53708
  const installed = await fileExists(paths.launchAgentPath);
53524
- const plist = installed ? await readFile3(paths.launchAgentPath, "utf8").catch(() => null) : null;
53709
+ const plist = installed ? await readFile4(paths.launchAgentPath, "utf8").catch(() => null) : null;
53525
53710
  const programArgs = plist ? extractProgramArguments(plist) : [];
53526
53711
  const appUrl2 = plist ? extractPlistEnvironmentValue(plist, `${cliBrand.envPrefix}_APP_URL`) : null;
53527
53712
  const urlPolicyEnv = extractPlistEnvironmentValue(plist ?? "", allowInsecureAppUrlEnv) === "1" ? "set" : "unset";
@@ -53630,11 +53815,11 @@ function resolveNodePath() {
53630
53815
  }
53631
53816
  function buildServicePath(nodePath, homeDir) {
53632
53817
  const entries = [
53633
- path4.dirname(nodePath),
53818
+ path5.dirname(nodePath),
53634
53819
  "/opt/homebrew/bin",
53635
53820
  "/usr/local/bin",
53636
- path4.join(homeDir, ".local", "bin"),
53637
- path4.join(homeDir, "bin"),
53821
+ path5.join(homeDir, ".local", "bin"),
53822
+ path5.join(homeDir, "bin"),
53638
53823
  "/usr/bin",
53639
53824
  "/bin",
53640
53825
  "/usr/sbin",
@@ -53789,7 +53974,7 @@ async function fileExists(file2) {
53789
53974
  }
53790
53975
  async function readTail(file2, maxBytes) {
53791
53976
  try {
53792
- const content = await readFile3(file2, "utf8");
53977
+ const content = await readFile4(file2, "utf8");
53793
53978
  return content.length > maxBytes ? content.slice(content.length - maxBytes) : content;
53794
53979
  } catch {
53795
53980
  return null;
@@ -53936,17 +54121,17 @@ function parseSemver2(value) {
53936
54121
  // src/runner-serve.ts
53937
54122
  import { execFile as execFileCallback5, spawn } from "node:child_process";
53938
54123
  import { createHash as createHash2 } from "node:crypto";
53939
- import { chmod as chmod2, mkdir as mkdir4, readFile as readFile4, rename, rm as rm5, statfs, writeFile as writeFile4 } from "node:fs/promises";
53940
- import { cpus, homedir as homedir3, hostname as hostname3, platform, totalmem, tmpdir as tmpdir2 } from "node:os";
53941
- import path6 from "node:path";
54124
+ import { chmod as chmod2, mkdir as mkdir5, readFile as readFile5, rename, rm as rm5, statfs, writeFile as writeFile5 } from "node:fs/promises";
54125
+ import { cpus, homedir as homedir4, hostname as hostname3, platform, totalmem, tmpdir as tmpdir2 } from "node:os";
54126
+ import path7 from "node:path";
53942
54127
  import { setTimeout as sleep3 } from "node:timers/promises";
53943
54128
  import { promisify as promisify5 } from "node:util";
53944
54129
 
53945
54130
  // src/forge-workspace.ts
53946
54131
  import { execFile as execFileCallback4 } from "node:child_process";
53947
54132
  import { createHash } from "node:crypto";
53948
- import { chmod, lstat, mkdir as mkdir3, mkdtemp, realpath, rm as rm4, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
53949
- import path5 from "node:path";
54133
+ import { chmod, lstat, mkdir as mkdir4, mkdtemp, realpath, rm as rm4, stat as stat3, writeFile as writeFile4 } from "node:fs/promises";
54134
+ import path6 from "node:path";
53950
54135
  import { setTimeout as sleep2 } from "node:timers/promises";
53951
54136
  import { promisify as promisify4 } from "node:util";
53952
54137
 
@@ -54083,20 +54268,20 @@ function shortRequestId(buildRequestId) {
54083
54268
  return slice.length > 0 ? slice : createHash("sha1").update(buildRequestId).digest("hex").slice(0, 8);
54084
54269
  }
54085
54270
  function requestRoot(baseDir, buildRequestId) {
54086
- return path5.join(baseDir, "work", shortRequestId(buildRequestId));
54271
+ return path6.join(baseDir, "work", shortRequestId(buildRequestId));
54087
54272
  }
54088
54273
  function baseRepoDir(baseDir, buildRequestId) {
54089
- return path5.join(requestRoot(baseDir, buildRequestId), "base");
54274
+ return path6.join(requestRoot(baseDir, buildRequestId), "base");
54090
54275
  }
54091
54276
  function branchName(buildRequestId, changeset) {
54092
54277
  const short = shortRequestId(buildRequestId);
54093
54278
  return changeset.total > 1 ? `forge/${short}-cs${changeset.ordinal}` : `forge/${short}`;
54094
54279
  }
54095
54280
  function buildWorktreeDir(baseDir, buildRequestId, ordinal) {
54096
- return path5.join(requestRoot(baseDir, buildRequestId), `cs${ordinal}`);
54281
+ return path6.join(requestRoot(baseDir, buildRequestId), `cs${ordinal}`);
54097
54282
  }
54098
54283
  function reviewWorktreeDir(baseDir, buildRequestId, ordinal) {
54099
- return path5.join(requestRoot(baseDir, buildRequestId), `review-cs${ordinal}`);
54284
+ return path6.join(requestRoot(baseDir, buildRequestId), `review-cs${ordinal}`);
54100
54285
  }
54101
54286
  function remoteUrlFor(options) {
54102
54287
  if (options.remoteUrl) {
@@ -54113,7 +54298,7 @@ async function pathExists(target) {
54113
54298
  }
54114
54299
  }
54115
54300
  async function isGitRepo(dir) {
54116
- return await pathExists(path5.join(dir, ".git")) || await pathExists(path5.join(dir, "HEAD"));
54301
+ return await pathExists(path6.join(dir, ".git")) || await pathExists(path6.join(dir, "HEAD"));
54117
54302
  }
54118
54303
  async function runGit(args, cwd, timeoutMs = LOCAL_GIT_TIMEOUT_MS) {
54119
54304
  try {
@@ -54166,10 +54351,10 @@ async function withNetworkRetries(op, fn, retryCounter) {
54166
54351
  throw new Error(`${op} exhausted retries: ${lastError instanceof Error ? redactSecrets(lastError.message) : redactSecrets(String(lastError))}`);
54167
54352
  }
54168
54353
  async function canonicalAskpassBase(baseDir) {
54169
- return path5.join(await realpath(path5.dirname(baseDir)), path5.basename(baseDir));
54354
+ return path6.join(await realpath(path6.dirname(baseDir)), path6.basename(baseDir));
54170
54355
  }
54171
54356
  async function prepareAskpassTurnDir(baseDir) {
54172
- await mkdir3(baseDir, { recursive: true, mode: 448 });
54357
+ await mkdir4(baseDir, { recursive: true, mode: 448 });
54173
54358
  const baseInfo = await lstat(baseDir);
54174
54359
  if (baseInfo.isSymbolicLink() || !baseInfo.isDirectory()) {
54175
54360
  throw new Error(`refusing to use askpass dir ${baseDir}: not a real directory (possible symlink attack)`);
@@ -54178,10 +54363,10 @@ async function prepareAskpassTurnDir(baseDir) {
54178
54363
  throw new Error(`refusing to use askpass dir ${baseDir}: not owned by this user (possible pre-planted dir)`);
54179
54364
  }
54180
54365
  await chmod(baseDir, 448);
54181
- const turnDir = await mkdtemp(path5.join(baseDir, "rost-runner-askpass-"));
54366
+ const turnDir = await mkdtemp(path6.join(baseDir, "rost-runner-askpass-"));
54182
54367
  const canonicalBase = await canonicalAskpassBase(baseDir);
54183
54368
  const realTurn = await realpath(turnDir);
54184
- if (path5.dirname(realTurn) !== canonicalBase) {
54369
+ if (path6.dirname(realTurn) !== canonicalBase) {
54185
54370
  await rm4(turnDir, { recursive: true, force: true });
54186
54371
  throw new Error(`refusing to use askpass dir ${turnDir}: resolved outside ${canonicalBase} (possible symlink attack)`);
54187
54372
  }
@@ -54189,7 +54374,7 @@ async function prepareAskpassTurnDir(baseDir) {
54189
54374
  }
54190
54375
  async function openAskpassSession(credential, baseDir = RUNNER_ASKPASS_DIR) {
54191
54376
  const turnDir = await prepareAskpassTurnDir(baseDir);
54192
- const helperPath = path5.join(turnDir, "askpass.sh");
54377
+ const helperPath = path6.join(turnDir, "askpass.sh");
54193
54378
  const helper = [
54194
54379
  "#!/bin/sh",
54195
54380
  "# One-shot Forge GIT_ASKPASS helper. Contains no secret; reads the token from env.",
@@ -54199,7 +54384,7 @@ async function openAskpassSession(credential, baseDir = RUNNER_ASKPASS_DIR) {
54199
54384
  "esac",
54200
54385
  ""
54201
54386
  ].join("\n");
54202
- await writeFile3(helperPath, helper, { mode: 448 });
54387
+ await writeFile4(helperPath, helper, { mode: 448 });
54203
54388
  await chmod(helperPath, 448);
54204
54389
  const env = {
54205
54390
  ...process.env,
@@ -54250,8 +54435,8 @@ async function localBranchExists(baseRepo, branch) {
54250
54435
  async function worktreeRegistered(baseRepo, worktreeDir) {
54251
54436
  try {
54252
54437
  const listing = await runGit(["worktree", "list", "--porcelain"], baseRepo);
54253
- const target = path5.resolve(worktreeDir);
54254
- return listing.split("\n").some((line) => line.startsWith("worktree ") && path5.resolve(line.slice("worktree ".length).trim()) === target);
54438
+ const target = path6.resolve(worktreeDir);
54439
+ return listing.split("\n").some((line) => line.startsWith("worktree ") && path6.resolve(line.slice("worktree ".length).trim()) === target);
54255
54440
  } catch {
54256
54441
  return false;
54257
54442
  }
@@ -54262,7 +54447,7 @@ async function configureForgeIdentity(baseRepo) {
54262
54447
  }
54263
54448
  async function ensureBaseClone(input) {
54264
54449
  const baseRepo = baseRepoDir(input.baseDir, input.buildRequestId);
54265
- await mkdir3(path5.dirname(baseRepo), { recursive: true, mode: 448 });
54450
+ await mkdir4(path6.dirname(baseRepo), { recursive: true, mode: 448 });
54266
54451
  await withLedgerStep(input.ledger, "clone", (retryCounter) => withAskpass(input.credential, async (netEnv) => {
54267
54452
  if (await isGitRepo(baseRepo)) {
54268
54453
  await runGitNetwork("git fetch", ["fetch", "--prune", "--quiet", input.url, "+refs/heads/*:refs/remotes/origin/*"], netEnv, baseRepo, FETCH_TIMEOUT_MS, retryCounter);
@@ -54311,7 +54496,7 @@ async function prepareMergeWorkspace(options) {
54311
54496
  ledger: options.ledger
54312
54497
  });
54313
54498
  const branch = options.headBranch;
54314
- const worktreeDir = path5.join(requestRoot(options.baseDir, options.buildRequestId), "merge");
54499
+ const worktreeDir = path6.join(requestRoot(options.baseDir, options.buildRequestId), "merge");
54315
54500
  const originDefault = `origin/${options.repo.default_branch}`;
54316
54501
  const originHead = `origin/${branch}`;
54317
54502
  await withLedgerStep(options.ledger, "branch", async () => {
@@ -54789,7 +54974,7 @@ async function runRunnerServe(options) {
54789
54974
  const env = options.env ?? process.env;
54790
54975
  const fetchImpl = options.fetchImpl ?? fetch;
54791
54976
  const cliVersion = await readCliVersion();
54792
- const homeDir = options.homeDir ?? homedir3();
54977
+ const homeDir = options.homeDir ?? homedir4();
54793
54978
  let config2;
54794
54979
  try {
54795
54980
  config2 = parseServeArgs(options.args, options.appUrl, env, homeDir);
@@ -54975,7 +55160,7 @@ function detectTelemetry(capabilities, env, activeSessions, cliVersion) {
54975
55160
  }
54976
55161
  function parseServeArgs(args, appUrl2, env, homeDir) {
54977
55162
  let name = env.RUNNER_NAME ?? `headless-${hostname3()}`;
54978
- let stateFile = env.RUNNER_STATE_FILE ?? path6.join(tmpdir2(), `rost-runner-${createHash2("sha1").update(appUrl2).digest("hex").slice(0, 8)}.json`);
55163
+ let stateFile = env.RUNNER_STATE_FILE ?? path7.join(tmpdir2(), `rost-runner-${createHash2("sha1").update(appUrl2).digest("hex").slice(0, 8)}.json`);
54979
55164
  let heartbeatMs = Number(env.RUNNER_HEARTBEAT_MS ?? 3e4);
54980
55165
  let interactiveClaimMs = Number(env.RUNNER_INTERACTIVE_CLAIM_MS ?? 1e3);
54981
55166
  let execute2 = env.RUNNER_EXECUTE === "1";
@@ -55026,7 +55211,7 @@ function parseServeArgs(args, appUrl2, env, homeDir) {
55026
55211
  tmpDir: tmpdir2(),
55027
55212
  homeDir,
55028
55213
  stateFile,
55029
- runnerBaseDir: path6.join(homeDir, ".rost"),
55214
+ runnerBaseDir: path7.join(homeDir, ".rost"),
55030
55215
  allowNetwork: network.allowNetwork
55031
55216
  });
55032
55217
  return {
@@ -55132,7 +55317,7 @@ async function pairIfNeeded(client, fetchImpl, appUrl2, config2, io) {
55132
55317
  }
55133
55318
  async function loadState(filePath, expectedTenantId) {
55134
55319
  try {
55135
- const parsed = JSON.parse(await readFile4(filePath, "utf8"));
55320
+ const parsed = JSON.parse(await readFile5(filePath, "utf8"));
55136
55321
  if (typeof parsed.runner_id === "string" && typeof parsed.runner_secret === "string") {
55137
55322
  if (expectedTenantId && parsed.tenant_id !== expectedTenantId) {
55138
55323
  return null;
@@ -55163,10 +55348,10 @@ function isRuntimeSessionMap(value) {
55163
55348
  });
55164
55349
  }
55165
55350
  async function saveState(filePath, state) {
55166
- await mkdir4(path6.dirname(filePath), { recursive: true, mode: 448 });
55351
+ await mkdir5(path7.dirname(filePath), { recursive: true, mode: 448 });
55167
55352
  const tempPath = `${filePath}.${process.pid}.${createHash2("sha1").update(`${Date.now()}:${Math.random()}`).digest("hex").slice(0, 8)}.tmp`;
55168
55353
  try {
55169
- await writeFile4(tempPath, `${JSON.stringify(state)}
55354
+ await writeFile5(tempPath, `${JSON.stringify(state)}
55170
55355
  `, { mode: 384 });
55171
55356
  await chmod2(tempPath, 384);
55172
55357
  await rename(tempPath, filePath);
@@ -55216,8 +55401,8 @@ function resolveSandboxKind(env, homeDir) {
55216
55401
  workspaceDir: tmpdir2(),
55217
55402
  tmpDir: tmpdir2(),
55218
55403
  homeDir,
55219
- stateFile: path6.join(tmpdir2(), "runner-sandbox-probe.json"),
55220
- runnerBaseDir: path6.join(homeDir, ".rost"),
55404
+ stateFile: path7.join(tmpdir2(), "runner-sandbox-probe.json"),
55405
+ runnerBaseDir: path7.join(homeDir, ".rost"),
55221
55406
  allowNetwork: resolveSandboxNetworkFlag(env) === "allow"
55222
55407
  }).kind;
55223
55408
  }
@@ -55316,9 +55501,9 @@ async function probeGhAuth() {
55316
55501
  }
55317
55502
  }
55318
55503
  async function probeForgeDiskFreeMb(homeDir) {
55319
- const dir = path6.join(homeDir, ".rost", "forge");
55504
+ const dir = path7.join(homeDir, ".rost", "forge");
55320
55505
  try {
55321
- await mkdir4(dir, { recursive: true, mode: 448 });
55506
+ await mkdir5(dir, { recursive: true, mode: 448 });
55322
55507
  const stats = await statfs(dir);
55323
55508
  return Math.floor(stats.bavail * stats.bsize / (1024 * 1024));
55324
55509
  } catch {
@@ -55650,7 +55835,7 @@ async function prepareForgeTurn(ctx, workOrder, execution) {
55650
55835
  let workspace;
55651
55836
  try {
55652
55837
  workspace = await prepareForgeWorkspace({
55653
- baseDir: path6.join(ctx.config.homeDir, ".rost", "forge", ctx.state.runner_id),
55838
+ baseDir: path7.join(ctx.config.homeDir, ".rost", "forge", ctx.state.runner_id),
55654
55839
  tenantId,
55655
55840
  buildRequestId,
55656
55841
  changeset: { id: buildRequestId, ordinal: 1, total: 1 },
@@ -55670,7 +55855,7 @@ async function prepareForgeTurn(ctx, workOrder, execution) {
55670
55855
  tmpDir: tmpdir2(),
55671
55856
  homeDir: ctx.config.homeDir,
55672
55857
  stateFile: ctx.config.stateFile,
55673
- runnerBaseDir: path6.join(ctx.config.homeDir, ".rost"),
55858
+ runnerBaseDir: path7.join(ctx.config.homeDir, ".rost"),
55674
55859
  allowWritePaths: [workspace.baseRepo],
55675
55860
  // Re-allow the shared object store for local commits, but DENY the model writing the
55676
55861
  // repo's hook + config (and the worktree's gitdir pointer). The harness runs git
@@ -55678,9 +55863,9 @@ async function prepareForgeTurn(ctx, workOrder, execution) {
55678
55863
  // hook or `ext::`/`insteadOf` config would otherwise exfiltrate it (DER-1327 review).
55679
55864
  // `.git/{objects,refs,worktrees,logs,index,HEAD}` stay writable so the model can commit.
55680
55865
  denyWritePaths: [
55681
- `${path6.join(workspace.baseRepo, ".git", "hooks")}/`,
55682
- path6.join(workspace.baseRepo, ".git", "config"),
55683
- path6.join(workspace.worktreeDir, ".git")
55866
+ `${path7.join(workspace.baseRepo, ".git", "hooks")}/`,
55867
+ path7.join(workspace.baseRepo, ".git", "config"),
55868
+ path7.join(workspace.worktreeDir, ".git")
55684
55869
  ],
55685
55870
  allowNetwork: ctx.config.sandboxAllowNetwork
55686
55871
  });
@@ -55699,7 +55884,7 @@ async function prepareForgeTurn(ctx, workOrder, execution) {
55699
55884
  var FORGE_MAX_CHANGED_PATHS = 2e3;
55700
55885
  var FORGE_MAX_CHANGED_PATH_LENGTH = 500;
55701
55886
  function forgeChangedPathsField(changedPaths) {
55702
- const withinCaps = changedPaths.length > 0 && changedPaths.length <= FORGE_MAX_CHANGED_PATHS && changedPaths.every((path7) => path7.length >= 1 && path7.length <= FORGE_MAX_CHANGED_PATH_LENGTH);
55887
+ const withinCaps = changedPaths.length > 0 && changedPaths.length <= FORGE_MAX_CHANGED_PATHS && changedPaths.every((path8) => path8.length >= 1 && path8.length <= FORGE_MAX_CHANGED_PATH_LENGTH);
55703
55888
  return withinCaps ? { changedPaths: [...changedPaths] } : {};
55704
55889
  }
55705
55890
  async function finalizeForgeBuildPush(ctx, prep, result) {
@@ -55840,9 +56025,9 @@ async function spawnRunnerTurn(ctx, workOrder, runtime, kind) {
55840
56025
  const token = typeof mcp.token === "string" ? mcp.token : "";
55841
56026
  const url2 = typeof mcp.url === "string" ? `${ctx.appUrl.replace(/\/+$/, "")}${mcp.url}` : `${ctx.appUrl.replace(/\/+$/, "")}/mcp`;
55842
56027
  const mcpConfig = JSON.stringify({ mcpServers: { rost: { type: "http", url: url2, headers: { Authorization: `Bearer ${token}` } } } });
55843
- const configPath = path6.join(tmpdir2(), `rost-runner-mcp-${createHash2("sha256").update(`${url2}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 16)}.json`);
56028
+ const configPath = path7.join(tmpdir2(), `rost-runner-mcp-${createHash2("sha256").update(`${url2}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 16)}.json`);
55844
56029
  const prompt = buildTurnPrompt({ kind, workOrder, execution, hasWorkspace: forgePrep !== null });
55845
- await writeFile4(configPath, `${mcpConfig}
56030
+ await writeFile5(configPath, `${mcpConfig}
55846
56031
  `, { mode: 384 });
55847
56032
  await chmod2(configPath, 384);
55848
56033
  const resumeSessionId = runtime === "claude" ? getClaudeResumeSessionId(ctx.state, workOrder) : void 0;
@@ -55857,11 +56042,11 @@ async function spawnRunnerTurn(ctx, workOrder, runtime, kind) {
55857
56042
  });
55858
56043
  let sandboxProfilePath = null;
55859
56044
  if (sandbox.kind === "seatbelt") {
55860
- sandboxProfilePath = path6.join(
56045
+ sandboxProfilePath = path7.join(
55861
56046
  tmpdir2(),
55862
56047
  `rost-runner-sandbox-${createHash2("sha256").update(`${configPath}:${Math.random()}`).digest("hex").slice(0, 16)}.sb`
55863
56048
  );
55864
- await writeFile4(sandboxProfilePath, sandbox.profile, { mode: 384 });
56049
+ await writeFile5(sandboxProfilePath, sandbox.profile, { mode: 384 });
55865
56050
  await chmod2(sandboxProfilePath, 384);
55866
56051
  }
55867
56052
  const { command, args } = wrapCommandWithSandbox(sandbox, built.command, built.args, sandboxProfilePath);
@@ -55992,7 +56177,7 @@ async function resolveMergeConflictTurn(ctx, input) {
55992
56177
  let workspace;
55993
56178
  try {
55994
56179
  workspace = await prepareMergeWorkspace({
55995
- baseDir: path6.join(ctx.config.homeDir, ".rost", "forge", ctx.state.runner_id),
56180
+ baseDir: path7.join(ctx.config.homeDir, ".rost", "forge", ctx.state.runner_id),
55996
56181
  tenantId,
55997
56182
  buildRequestId: input.buildRequestId,
55998
56183
  repo: input.repo,
@@ -56010,12 +56195,12 @@ async function resolveMergeConflictTurn(ctx, input) {
56010
56195
  tmpDir: tmpdir2(),
56011
56196
  homeDir: ctx.config.homeDir,
56012
56197
  stateFile: ctx.config.stateFile,
56013
- runnerBaseDir: path6.join(ctx.config.homeDir, ".rost"),
56198
+ runnerBaseDir: path7.join(ctx.config.homeDir, ".rost"),
56014
56199
  allowWritePaths: [workspace.baseRepo],
56015
56200
  denyWritePaths: [
56016
- `${path6.join(workspace.baseRepo, ".git", "hooks")}/`,
56017
- path6.join(workspace.baseRepo, ".git", "config"),
56018
- path6.join(workspace.worktreeDir, ".git")
56201
+ `${path7.join(workspace.baseRepo, ".git", "hooks")}/`,
56202
+ path7.join(workspace.baseRepo, ".git", "config"),
56203
+ path7.join(workspace.worktreeDir, ".git")
56019
56204
  ],
56020
56205
  allowNetwork: ctx.config.sandboxAllowNetwork
56021
56206
  });
@@ -56045,8 +56230,8 @@ async function spawnMergeConflictModel(ctx, input) {
56045
56230
  const token = typeof mcp.token === "string" ? mcp.token : "";
56046
56231
  const url2 = typeof mcp.url === "string" ? `${ctx.appUrl.replace(/\/+$/, "")}${mcp.url}` : `${ctx.appUrl.replace(/\/+$/, "")}/mcp`;
56047
56232
  const mcpConfig = JSON.stringify({ mcpServers: { rost: { type: "http", url: url2, headers: { Authorization: `Bearer ${token}` } } } });
56048
- const configPath = path6.join(tmpdir2(), `rost-runner-mcp-${createHash2("sha256").update(`${url2}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 16)}.json`);
56049
- await writeFile4(configPath, `${mcpConfig}
56233
+ const configPath = path7.join(tmpdir2(), `rost-runner-mcp-${createHash2("sha256").update(`${url2}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 16)}.json`);
56234
+ await writeFile5(configPath, `${mcpConfig}
56050
56235
  `, { mode: 384 });
56051
56236
  await chmod2(configPath, 384);
56052
56237
  const plan = resolveTurnPlan({ kind: "work_order", execution: input.execution, repoDir: input.workspace.worktreeDir });
@@ -56058,8 +56243,8 @@ async function spawnMergeConflictModel(ctx, input) {
56058
56243
  ].join("\n");
56059
56244
  let sandboxProfilePath = null;
56060
56245
  if (input.sandbox.kind === "seatbelt") {
56061
- sandboxProfilePath = path6.join(tmpdir2(), `rost-runner-sandbox-${createHash2("sha256").update(`${configPath}:${Math.random()}`).digest("hex").slice(0, 16)}.sb`);
56062
- await writeFile4(sandboxProfilePath, input.sandbox.profile, { mode: 384 });
56246
+ sandboxProfilePath = path7.join(tmpdir2(), `rost-runner-sandbox-${createHash2("sha256").update(`${configPath}:${Math.random()}`).digest("hex").slice(0, 16)}.sb`);
56247
+ await writeFile5(sandboxProfilePath, input.sandbox.profile, { mode: 384 });
56063
56248
  await chmod2(sandboxProfilePath, 384);
56064
56249
  }
56065
56250
  const built = buildTurnCommand({