@rosthq/cli 0.7.68 → 0.7.70
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/generated/command-manifest.d.ts.map +1 -1
- package/dist/generator/flags.d.ts.map +1 -1
- package/dist/generator/groups.d.ts.map +1 -1
- package/dist/index.js +435 -169
- package/dist/index.js.map +4 -4
- package/dist/update-check.d.ts +11 -1
- package/dist/update-check.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -472,13 +472,13 @@ function __disposeResources(env) {
|
|
|
472
472
|
}
|
|
473
473
|
return next();
|
|
474
474
|
}
|
|
475
|
-
function __rewriteRelativeImportExtension(
|
|
476
|
-
if (typeof
|
|
477
|
-
return
|
|
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
|
|
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,
|
|
14031
|
-
if (!
|
|
14030
|
+
function getElementAtPath(obj, path8) {
|
|
14031
|
+
if (!path8)
|
|
14032
14032
|
return obj;
|
|
14033
|
-
return
|
|
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(
|
|
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(
|
|
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,
|
|
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 }, [...
|
|
14596
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
14597
14597
|
} else if (issue2.code === "invalid_key") {
|
|
14598
|
-
processError({ issues: issue2.issues }, [...
|
|
14598
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
14599
14599
|
} else if (issue2.code === "invalid_element") {
|
|
14600
|
-
processError({ issues: issue2.issues }, [...
|
|
14600
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
14601
14601
|
} else {
|
|
14602
|
-
const fullpath = [...
|
|
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,
|
|
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 }, [...
|
|
14633
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
14634
14634
|
} else if (issue2.code === "invalid_key") {
|
|
14635
|
-
processError({ issues: issue2.issues }, [...
|
|
14635
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
14636
14636
|
} else if (issue2.code === "invalid_element") {
|
|
14637
|
-
processError({ issues: issue2.issues }, [...
|
|
14637
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
14638
14638
|
} else {
|
|
14639
|
-
const fullpath = [...
|
|
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
|
|
14672
|
-
for (const seg of
|
|
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
|
|
27365
|
-
if (
|
|
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 (
|
|
27370
|
-
const key =
|
|
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
|
|
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}${
|
|
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 ${
|
|
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,
|
|
33185
|
-
const url2 = new URL(
|
|
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:
|
|
33215
|
+
path: path8,
|
|
33216
33216
|
query,
|
|
33217
33217
|
body,
|
|
33218
33218
|
headers
|
|
33219
33219
|
}) {
|
|
33220
|
-
const url2 = buildUrl(options.baseUrl,
|
|
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,
|
|
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(
|
|
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(
|
|
34184
|
-
return this.uploadOrUpdate("POST",
|
|
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(
|
|
34224
|
+
async uploadToSignedUrl(path8, token, fileBody, fileOptions) {
|
|
34225
34225
|
var _this3 = this;
|
|
34226
|
-
const cleanPath = _this3._removeEmptyFolders(
|
|
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(
|
|
34295
|
+
async createSignedUploadUrl(path8, options) {
|
|
34296
34296
|
var _this4 = this;
|
|
34297
34297
|
return _this4.handleOperation(async () => {
|
|
34298
|
-
let _path = _this4._getFinalPath(
|
|
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:
|
|
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(
|
|
34368
|
-
return this.uploadOrUpdate("PUT",
|
|
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(
|
|
34519
|
+
async createSignedUrl(path8, expiresIn, options) {
|
|
34520
34520
|
var _this8 = this;
|
|
34521
34521
|
return _this8.handleOperation(async () => {
|
|
34522
|
-
let _path = _this8._getFinalPath(
|
|
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(
|
|
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(
|
|
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(
|
|
34695
|
+
async info(path8) {
|
|
34696
34696
|
var _this10 = this;
|
|
34697
|
-
const _path = _this10._getFinalPath(
|
|
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(
|
|
34718
|
+
async exists(path8) {
|
|
34719
34719
|
var _this11 = this;
|
|
34720
|
-
const _path = _this11._getFinalPath(
|
|
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(
|
|
34800
|
-
const _path = this._getFinalPath(
|
|
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(
|
|
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:
|
|
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(
|
|
35008
|
-
return `${this.bucketId}/${
|
|
35007
|
+
_getFinalPath(path8) {
|
|
35008
|
+
return `${this.bucketId}/${path8.replace(/^\/+/, "")}`;
|
|
35009
35009
|
}
|
|
35010
|
-
_removeEmptyFolders(
|
|
35011
|
-
return
|
|
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) {
|
|
@@ -40845,13 +40845,24 @@ var goalListAtRiskOutputSchema = external_exports.object({
|
|
|
40845
40845
|
var goalSignalStateSchema = external_exports.enum(["ok", "risk", "crit", "pending"]);
|
|
40846
40846
|
var goalStatusSourceSchema = external_exports.enum(["human", "agent", "rollup", "signal"]);
|
|
40847
40847
|
var goalMeasurableRoleSchema = external_exports.enum(["drives_status", "informs"]);
|
|
40848
|
+
var goalDriverAnchorSchema = external_exports.object({
|
|
40849
|
+
// The closed period being anchored on (an ISO date / period label — free-form so a
|
|
40850
|
+
// caller can pass '2026-Q1' or '2026-06-30' as the books define the period).
|
|
40851
|
+
period_start: external_exports.string().min(1),
|
|
40852
|
+
// The value the goal's Signal should show for that closed period per the books.
|
|
40853
|
+
expected_value: external_exports.number()
|
|
40854
|
+
}).strict();
|
|
40848
40855
|
var goalBindMeasurableInputSchema = external_exports.object({
|
|
40849
40856
|
goal_id: uuidSchema8,
|
|
40850
40857
|
measurable_id: uuidSchema8,
|
|
40851
40858
|
// DER-1643: new operator bindings default to the conservative 'informs' role.
|
|
40852
40859
|
// 'drives_status' is the deliberate leaf-only status driver (childless goal only,
|
|
40853
40860
|
// one per goal) and stays human-confirmed.
|
|
40854
|
-
role: goalMeasurableRoleSchema.default("informs")
|
|
40861
|
+
role: goalMeasurableRoleSchema.default("informs"),
|
|
40862
|
+
// DER-1126 (ADR-0009 R5): required when role is 'drives_status' — a binding may not
|
|
40863
|
+
// drive status without a second anchor. Optional here (only drives_status needs it);
|
|
40864
|
+
// the command rejects a driver bind that omits it, exactly like signal.bind_confirm.
|
|
40865
|
+
second_anchor: goalDriverAnchorSchema.optional()
|
|
40855
40866
|
}).strict();
|
|
40856
40867
|
var goalBindMeasurableOutputSchema = external_exports.object({
|
|
40857
40868
|
goal_id: uuidSchema8,
|
|
@@ -40869,7 +40880,11 @@ var goalBindMeasurableOutputSchema = external_exports.object({
|
|
|
40869
40880
|
// DER-1633: false for a fresh binding; true when this exact (goal, Signal) pair was
|
|
40870
40881
|
// already bound — the command is an idempotent no-op (no new event, no duplicate
|
|
40871
40882
|
// confirmation). Lets a caller distinguish "just bound" from "already bound".
|
|
40872
|
-
already_bound: external_exports.boolean()
|
|
40883
|
+
already_bound: external_exports.boolean(),
|
|
40884
|
+
// DER-1126: the second anchor recorded when this binding was promoted to (or created
|
|
40885
|
+
// as) the status driver. Null for an 'informs' binding (no anchor) and for a legacy
|
|
40886
|
+
// driver bound before the anchor gate existed.
|
|
40887
|
+
driver_anchor: goalDriverAnchorSchema.nullable()
|
|
40873
40888
|
}).strict();
|
|
40874
40889
|
var goalUnbindMeasurableInputSchema = external_exports.object({
|
|
40875
40890
|
goal_id: uuidSchema8,
|
|
@@ -40910,7 +40925,11 @@ var goalMeasurableBindingSchema = external_exports.object({
|
|
|
40910
40925
|
computed_status: goalStatusSchema.nullable(),
|
|
40911
40926
|
// The latest confirmed reading's value (null while awaiting one) — enough to render
|
|
40912
40927
|
// "measured by <Signal>: <value> <unit>" instead of a bare "Not measured".
|
|
40913
|
-
last_reading_value: external_exports.number().nullable()
|
|
40928
|
+
last_reading_value: external_exports.number().nullable(),
|
|
40929
|
+
// DER-1126: the second anchor recorded when this driver was confirmed (null for a
|
|
40930
|
+
// legacy driver bound before the anchor gate). Lets the driver view show "Anchored on
|
|
40931
|
+
// <period>: expected <value>".
|
|
40932
|
+
driver_anchor: goalDriverAnchorSchema.nullable()
|
|
40914
40933
|
}).strict();
|
|
40915
40934
|
var goalListMeasurablesInputSchema = external_exports.object({
|
|
40916
40935
|
goal_id: uuidSchema8
|
|
@@ -40919,6 +40938,23 @@ var goalListMeasurablesOutputSchema = external_exports.object({
|
|
|
40919
40938
|
goal_id: uuidSchema8,
|
|
40920
40939
|
bindings: external_exports.array(goalMeasurableBindingSchema)
|
|
40921
40940
|
}).strict();
|
|
40941
|
+
var goalCoreSchema = external_exports.object({
|
|
40942
|
+
id: uuidSchema8,
|
|
40943
|
+
title: external_exports.string(),
|
|
40944
|
+
kind: external_exports.enum(["objective", "cycle_goal", "company_objective", "seat_goal", "milestone"]),
|
|
40945
|
+
status: goalStatusSchema,
|
|
40946
|
+
status_source: goalStatusSourceSchema,
|
|
40947
|
+
progress_pct: external_exports.number().int().min(0).max(100).nullable(),
|
|
40948
|
+
seat_id: uuidSchema8.nullable(),
|
|
40949
|
+
parent_goal_id: uuidSchema8.nullable(),
|
|
40950
|
+
definition_of_done: external_exports.string()
|
|
40951
|
+
}).strict();
|
|
40952
|
+
var goalGetInputSchema = external_exports.object({
|
|
40953
|
+
goal_id: uuidSchema8
|
|
40954
|
+
}).strict();
|
|
40955
|
+
var goalGetOutputSchema = external_exports.object({
|
|
40956
|
+
goal: goalCoreSchema
|
|
40957
|
+
}).strict();
|
|
40922
40958
|
var issueStatusSchema = external_exports.enum(["open", "diagnosing", "resolved", "dropped"]);
|
|
40923
40959
|
var frictionListInputSchema = external_exports.object({
|
|
40924
40960
|
status: external_exports.enum(["open", "diagnosing", "resolved", "dropped", "active", "all"]).optional()
|
|
@@ -40941,6 +40977,28 @@ var frictionIssueSummarySchema = external_exports.object({
|
|
|
40941
40977
|
var frictionListOutputSchema = external_exports.object({
|
|
40942
40978
|
issues: external_exports.array(frictionIssueSummarySchema)
|
|
40943
40979
|
}).strict();
|
|
40980
|
+
var frictionIssueDetailSchema = frictionIssueSummarySchema.extend({
|
|
40981
|
+
raised_by_seat_type: external_exports.enum(["human", "agent", "hybrid"]),
|
|
40982
|
+
raised_by_seat_steward_name: external_exports.string().nullable(),
|
|
40983
|
+
origin_actor_kind: external_exports.enum(["user", "agent", "system"]).nullable(),
|
|
40984
|
+
origin_actor_id: uuidSchema8.nullable(),
|
|
40985
|
+
evidence: external_exports.unknown(),
|
|
40986
|
+
action_task_title: external_exports.string().nullable(),
|
|
40987
|
+
action_task_owner_seat_id: uuidSchema8.nullable(),
|
|
40988
|
+
action_task_owner_seat_name: external_exports.string().nullable(),
|
|
40989
|
+
action_task_due_on: external_exports.string().nullable(),
|
|
40990
|
+
decision_id: uuidSchema8.nullable(),
|
|
40991
|
+
decision_title: external_exports.string().nullable(),
|
|
40992
|
+
decision_summary: external_exports.string().nullable(),
|
|
40993
|
+
decided_by_name: external_exports.string().nullable(),
|
|
40994
|
+
updated_at: external_exports.string()
|
|
40995
|
+
}).strict();
|
|
40996
|
+
var frictionGetInputSchema = external_exports.object({
|
|
40997
|
+
issue_id: uuidSchema8
|
|
40998
|
+
}).strict();
|
|
40999
|
+
var frictionGetOutputSchema = external_exports.object({
|
|
41000
|
+
issue: frictionIssueDetailSchema
|
|
41001
|
+
}).strict();
|
|
40944
41002
|
var frictionUpdateStatusInputSchema = external_exports.object({
|
|
40945
41003
|
issue_id: uuidSchema8,
|
|
40946
41004
|
status: external_exports.enum(["open", "diagnosing"])
|
|
@@ -40952,17 +41010,34 @@ var frictionUpdateStatusOutputSchema = external_exports.object({
|
|
|
40952
41010
|
}).strict();
|
|
40953
41011
|
var frictionResolveInputSchema = external_exports.object({
|
|
40954
41012
|
issue_id: uuidSchema8,
|
|
41013
|
+
resolution_mode: external_exports.enum(["ids", "already_fixed"]).default("ids"),
|
|
40955
41014
|
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,
|
|
41015
|
+
owner_seat_id: uuidSchema8.optional(),
|
|
41016
|
+
task_title: external_exports.string().trim().min(1).optional(),
|
|
41017
|
+
task_description: external_exports.string().trim().min(1).optional(),
|
|
41018
|
+
done_by: dateOnlySchema.optional(),
|
|
40960
41019
|
resolving_seat_id: uuidSchema8.optional()
|
|
40961
|
-
}).strict()
|
|
41020
|
+
}).strict().superRefine((value, ctx) => {
|
|
41021
|
+
if (value.resolution_mode !== "ids") {
|
|
41022
|
+
return;
|
|
41023
|
+
}
|
|
41024
|
+
if (value.owner_seat_id === void 0) {
|
|
41025
|
+
ctx.addIssue({ code: "custom", path: ["owner_seat_id"], message: 'Required for resolution_mode "ids".' });
|
|
41026
|
+
}
|
|
41027
|
+
if (value.task_title === void 0) {
|
|
41028
|
+
ctx.addIssue({ code: "custom", path: ["task_title"], message: 'Required for resolution_mode "ids".' });
|
|
41029
|
+
}
|
|
41030
|
+
if (value.task_description === void 0) {
|
|
41031
|
+
ctx.addIssue({ code: "custom", path: ["task_description"], message: 'Required for resolution_mode "ids".' });
|
|
41032
|
+
}
|
|
41033
|
+
if (value.done_by === void 0) {
|
|
41034
|
+
ctx.addIssue({ code: "custom", path: ["done_by"], message: 'Required for resolution_mode "ids".' });
|
|
41035
|
+
}
|
|
41036
|
+
});
|
|
40962
41037
|
var frictionResolveOutputSchema = external_exports.object({
|
|
40963
41038
|
issue_id: uuidSchema8,
|
|
40964
41039
|
status: external_exports.literal("resolved"),
|
|
40965
|
-
action_task_id: uuidSchema8,
|
|
41040
|
+
action_task_id: uuidSchema8.nullable(),
|
|
40966
41041
|
decision_id: uuidSchema8
|
|
40967
41042
|
}).strict();
|
|
40968
41043
|
var frictionLinkTaskInputSchema = external_exports.object({
|
|
@@ -41565,6 +41640,18 @@ var compassShowMarkdownInputSchema = external_exports.object({}).strict();
|
|
|
41565
41640
|
var charterShowMarkdownInputSchema = external_exports.object({
|
|
41566
41641
|
seat_id: uuidSchema9
|
|
41567
41642
|
}).strict();
|
|
41643
|
+
var charterShowMarkdownOutputSchema = external_exports.object({
|
|
41644
|
+
markdown: external_exports.string().min(1),
|
|
41645
|
+
charter_version_id: uuidSchema9.nullable(),
|
|
41646
|
+
seat_id: uuidSchema9,
|
|
41647
|
+
version: external_exports.number().int().nonnegative().nullable(),
|
|
41648
|
+
status: external_exports.string().nullable(),
|
|
41649
|
+
doc: external_exports.unknown().nullable(),
|
|
41650
|
+
dry_run: external_exports.object({
|
|
41651
|
+
status: external_exports.enum(["passed", "failed"]),
|
|
41652
|
+
summary: external_exports.string()
|
|
41653
|
+
}).strict().nullable()
|
|
41654
|
+
}).strict();
|
|
41568
41655
|
var agentShowMarkdownInputSchema = external_exports.object({
|
|
41569
41656
|
seat_id: uuidSchema9
|
|
41570
41657
|
}).strict();
|
|
@@ -41799,6 +41886,27 @@ var confirmationRejectOutputSchema = external_exports.object({
|
|
|
41799
41886
|
command_id: external_exports.string().min(1),
|
|
41800
41887
|
rejected: external_exports.literal(true)
|
|
41801
41888
|
}).strict();
|
|
41889
|
+
var confirmationListInputSchema = external_exports.object({
|
|
41890
|
+
limit: external_exports.number().int().min(1).max(200).optional()
|
|
41891
|
+
}).strict();
|
|
41892
|
+
var confirmationSummarySchema = external_exports.object({
|
|
41893
|
+
id: uuidSchema10,
|
|
41894
|
+
command_id: external_exports.string(),
|
|
41895
|
+
redacted_args: external_exports.unknown(),
|
|
41896
|
+
actor_kind: external_exports.enum(["user", "agent", "system"]),
|
|
41897
|
+
source: external_exports.string(),
|
|
41898
|
+
scope_kind: external_exports.enum(["tenant_admin", "tenant", "seat"]),
|
|
41899
|
+
seat_id: uuidSchema10.nullable(),
|
|
41900
|
+
seat_name: external_exports.string().nullable(),
|
|
41901
|
+
seat_type: external_exports.enum(["human", "agent", "hybrid"]).nullable(),
|
|
41902
|
+
risk_level: external_exports.enum(["normal", "sensitive", "dangerous"]),
|
|
41903
|
+
summary: external_exports.string(),
|
|
41904
|
+
expires_at: external_exports.string(),
|
|
41905
|
+
created_at: external_exports.string()
|
|
41906
|
+
}).strict();
|
|
41907
|
+
var confirmationListOutputSchema = external_exports.object({
|
|
41908
|
+
confirmations: external_exports.array(confirmationSummarySchema)
|
|
41909
|
+
}).strict();
|
|
41802
41910
|
var credentialIngressInputSchema = external_exports.object({
|
|
41803
41911
|
seat_id: uuidSchema10.optional(),
|
|
41804
41912
|
provider: external_exports.string().trim().min(1),
|
|
@@ -43020,6 +43128,37 @@ var systemHealthOutputSchema = external_exports.object({
|
|
|
43020
43128
|
findings: external_exports.array(systemHealthFindingSchema)
|
|
43021
43129
|
}).strict();
|
|
43022
43130
|
|
|
43131
|
+
// ../../packages/protocol/src/baserow-filter-operators.ts
|
|
43132
|
+
var baserowFilterOperatorSchema = external_exports.enum([
|
|
43133
|
+
"equal",
|
|
43134
|
+
"not_equal",
|
|
43135
|
+
"higher_than",
|
|
43136
|
+
"higher_than_or_equal",
|
|
43137
|
+
"lower_than",
|
|
43138
|
+
"lower_than_or_equal",
|
|
43139
|
+
"contains",
|
|
43140
|
+
"contains_not",
|
|
43141
|
+
"empty",
|
|
43142
|
+
"not_empty"
|
|
43143
|
+
]);
|
|
43144
|
+
var BASEROW_FILTER_OPERATORS = {
|
|
43145
|
+
equal: { requiresValue: true, label: "equals" },
|
|
43146
|
+
not_equal: { requiresValue: true, label: "does not equal" },
|
|
43147
|
+
higher_than: { requiresValue: true, label: "is greater than" },
|
|
43148
|
+
higher_than_or_equal: { requiresValue: true, label: "is greater than or equal to" },
|
|
43149
|
+
lower_than: { requiresValue: true, label: "is less than" },
|
|
43150
|
+
lower_than_or_equal: { requiresValue: true, label: "is less than or equal to" },
|
|
43151
|
+
contains: { requiresValue: true, label: "contains" },
|
|
43152
|
+
contains_not: { requiresValue: true, label: "does not contain" },
|
|
43153
|
+
empty: { requiresValue: false, label: "is empty" },
|
|
43154
|
+
not_empty: { requiresValue: false, label: "is not empty" }
|
|
43155
|
+
};
|
|
43156
|
+
var baserowFilterOperatorOptions = Object.keys(BASEROW_FILTER_OPERATORS).map((value) => ({
|
|
43157
|
+
value,
|
|
43158
|
+
label: BASEROW_FILTER_OPERATORS[value].label,
|
|
43159
|
+
requiresValue: BASEROW_FILTER_OPERATORS[value].requiresValue
|
|
43160
|
+
}));
|
|
43161
|
+
|
|
43023
43162
|
// ../../packages/protocol/src/signal-source.ts
|
|
43024
43163
|
var uuid9 = external_exports.string().uuid();
|
|
43025
43164
|
var signalCadenceSchema = external_exports.enum(["daily", "weekly", "monthly", "quarterly", "annual"]);
|
|
@@ -43150,6 +43289,18 @@ var signalBindConfirmOutputSchema = external_exports.object({
|
|
|
43150
43289
|
binding_status: external_exports.literal("active")
|
|
43151
43290
|
}).strict();
|
|
43152
43291
|
|
|
43292
|
+
// ../../packages/protocol/src/baserow-filtered-count.ts
|
|
43293
|
+
var FIELD_KEY_PATTERN = /^field_\d+$/;
|
|
43294
|
+
var baserowFilteredCountInputSchema = external_exports.object({
|
|
43295
|
+
endpointHost: external_exports.string().min(1).max(255),
|
|
43296
|
+
// Accept string or number from callers (CLI/MCP/assistant), coerce to a bounded
|
|
43297
|
+
// positive integer before it is ever used as a URL path segment.
|
|
43298
|
+
tableId: external_exports.coerce.number().int().positive().max(2147483647),
|
|
43299
|
+
fieldKey: external_exports.string().regex(FIELD_KEY_PATTERN, "fieldKey must look like field_123"),
|
|
43300
|
+
operator: baserowFilterOperatorSchema,
|
|
43301
|
+
value: external_exports.string().max(200).optional()
|
|
43302
|
+
}).strict();
|
|
43303
|
+
|
|
43153
43304
|
// ../../packages/protocol/src/signal-report.ts
|
|
43154
43305
|
var uuidSchema14 = external_exports.string().uuid();
|
|
43155
43306
|
var dateOnlySchema2 = external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/, "expected YYYY-MM-DD");
|
|
@@ -44658,7 +44809,24 @@ var statusEventPayloadSchema = external_exports.object({
|
|
|
44658
44809
|
// so every existing status writer (status.record, corrections, imports) is
|
|
44659
44810
|
// unaffected.
|
|
44660
44811
|
note: external_exports.string().min(1).max(2e3).optional(),
|
|
44661
|
-
confidence: external_exports.enum(["low", "medium", "high"]).optional()
|
|
44812
|
+
confidence: external_exports.enum(["low", "medium", "high"]).optional(),
|
|
44813
|
+
// DER-1123: when this reading supersedes a materially-different same-period
|
|
44814
|
+
// reading (e.g. an integration pull replacing an agent-reported value), the
|
|
44815
|
+
// prior reading's provenance is captured here — append-only, so the audit
|
|
44816
|
+
// story survives even though the canonical row keeps a single value
|
|
44817
|
+
// (invariant #8, supersession not silent rewrite). Non-secret fields ONLY
|
|
44818
|
+
// (source kind, the numeric value, actor kind, a timestamp); never a vault
|
|
44819
|
+
// ref, token, or raw integration response.
|
|
44820
|
+
supersededFrom: external_exports.object({
|
|
44821
|
+
// The value's origin (agent report / human entry / integration pull).
|
|
44822
|
+
source: external_exports.enum(["agent", "human", "integration"]),
|
|
44823
|
+
value: external_exports.number().finite(),
|
|
44824
|
+
// The actor that last ESTABLISHED the superseded value — its reporter, or the
|
|
44825
|
+
// human who confirmed/corrected it. Optional (a reading may lack a backing
|
|
44826
|
+
// event). Never an actor id — only the coarse kind, so no PII.
|
|
44827
|
+
actorKind: external_exports.enum(["user", "agent", "system"]).optional(),
|
|
44828
|
+
at: external_exports.string().min(1)
|
|
44829
|
+
}).strict().optional()
|
|
44662
44830
|
}).strict()).optional(),
|
|
44663
44831
|
goals: external_exports.array(external_exports.object({
|
|
44664
44832
|
id: uuidSchema16,
|
|
@@ -45445,7 +45613,7 @@ Treat AICOS as a coordinator over the operating system. It can become more usefu
|
|
|
45445
45613
|
order: 20,
|
|
45446
45614
|
title: "Responsibility Graph playbook",
|
|
45447
45615
|
summary: "How to build a functions-first graph with seats, owners, Stewards, vacancies, and clean authority.",
|
|
45448
|
-
version: "2026-07-10.
|
|
45616
|
+
version: "2026-07-10.3",
|
|
45449
45617
|
public: true,
|
|
45450
45618
|
audiences: ["human", "cli", "mcp", "in_app_agent"],
|
|
45451
45619
|
stages: ["graph_design", "staffing"],
|
|
@@ -45518,6 +45686,8 @@ The graph is also where you land after onboarding \u2014 it is the mission contr
|
|
|
45518
45686
|
- **Signal** \u2014 the worst measurable state per seat.
|
|
45519
45687
|
- **Scoreboard** \u2014 direct work and direct cost on each seat, plus a separate team/subtree rollup for manager seats. The tenant summary counts direct agent work once, so a parent seat's team cost does not double-count the same run again. A seat whose direct cost is a clear outlier above the rest of the fleet is flagged as cost drift (labelled, not colour-only). Human seats and seats with no direct or team runs read calmly rather than showing a bare zero. For a small fleet the Scoreboard also leads with a two-tile summary \u2014 total work and total cost \u2014 framed as the single question that matters: is it earning its keep.
|
|
45520
45688
|
|
|
45689
|
+
Switching into Cascade never re-runs the chart layout \u2014 seat positions scale in place to fit taller goal-summary cards, and the connector layer scales to match, so nothing rearranges under you. A company-objectives card anchors above the root seat with the active cycle's objectives; selecting one traces and emphasizes its branch down through the connectors while the rest of the chart recedes. Selecting a seat's goal opens the same goal detail panel \`/cascade\` uses, as a right-hand drawer \u2014 breadcrumb ancestry and child-goal rows let you walk the branch without leaving the graph, and an **Open in Cascade** link round-trips the same cycle, branch, and goal selection to the \`/cascade\` page. Lens, objective, goal, seat, and cycle are all URL state, so a reload or a shared link reopens the same view.
|
|
45690
|
+
|
|
45521
45691
|
The graph also carries a mission-control panel. It pulls the same operational state visible on the agent and setup-health surfaces: held actions that need steward decisions, failed runs, open Friction, pending Signal readings, stale agents, and setup recommendations. Each item can focus the affected seat on the canvas and links to the route where the operator can act.
|
|
45522
45692
|
|
|
45523
45693
|
## An agent seat's profile
|
|
@@ -46261,7 +46431,7 @@ External connectors are being rolled out provider by provider, conservatively (r
|
|
|
46261
46431
|
order: 48,
|
|
46262
46432
|
title: "CLI and MCP installation guide",
|
|
46263
46433
|
summary: "Install the public CLI, register remote token-backed MCP clients, and find the full command and tool catalog.",
|
|
46264
|
-
version: "2026-07-12.
|
|
46434
|
+
version: "2026-07-12.4",
|
|
46265
46435
|
public: true,
|
|
46266
46436
|
audiences: ["human", "cli", "mcp", "in_app_agent"],
|
|
46267
46437
|
stages: ["company_setup", "staffing"],
|
|
@@ -46834,6 +47004,7 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
|
|
|
46834
47004
|
| \`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
47005
|
| \`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
47006
|
| \`rost_sign_charter_manifest\` | \`charter.sign_manifest\` | Request human confirmation for a permission manifest. | Seat or tenant-admin | Use after tool permissions are reviewed. |
|
|
47007
|
+
| \`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
47008
|
| \`rost_draft_compass\` | \`compass.draft\` | Create a Compass draft. | Tenant | Call with a concise Compass document. |
|
|
46838
47009
|
| \`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
47010
|
| \`rost_approve_compass_version\` | \`compass.approve_version\` | Activate a Compass version by supersession. | Tenant | Call after human review. |
|
|
@@ -46934,18 +47105,20 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
|
|
|
46934
47105
|
| \`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
47106
|
| \`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
47107
|
| \`rost_list_cascade_goals\` | \`goal.list\` | List Cascade goals, optionally by cycle or seat. | Seat or tenant-admin | Call with \`{}\` or \`{"cycle_id":"<id>"}\`. |
|
|
47108
|
+
| \`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
47109
|
| \`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
47110
|
| \`rost_create_cascade_goal\` | \`goal.create\` | Create a cycle goal under an objective. | Tenant | Call with cycle, seat, parent, title, definition of done. |
|
|
46939
47111
|
| \`rost_update_cascade_goal\` | \`goal.update\` | Update a goal's title or definition of done. | Tenant | Call with \`goal_id\` and the changed fields. |
|
|
46940
47112
|
| \`rost_set_cascade_goal_status\` | \`goal.set_status\` | Set a goal's status (on/off/done). | Seat or tenant-admin | Seats may set only their own goals. |
|
|
46941
47113
|
| \`rost_set_cascade_goal_progress\` | \`goal.set_progress\` | Report a goal's quantified progress (0-100). An agent's progress is a proposal a human approves before the goal moves. | Seat or tenant-admin | Seats set only their own goals; expect confirmation. |
|
|
46942
|
-
| \`rost_bind_a_signal_to_a_cascade_goal\` | \`goal.bind_measurable\` | Bind a measurable to a goal. Defaults to role \`informs\` \u2014 a conservative indicator allowed at any goal level (many per goal) that never changes status. Pass role \`drives_status\` to make it the goal's status driver (childless leaf only, one per goal). Human-gated. | Seat or tenant-admin | Call with \`{"goal_id":"<id>","measurable_id":"<id>"}\` (add \`"role":"drives_status"\` for the driver); expect confirmation. |
|
|
47114
|
+
| \`rost_bind_a_signal_to_a_cascade_goal\` | \`goal.bind_measurable\` | Bind a measurable to a goal. Defaults to role \`informs\` \u2014 a conservative indicator allowed at any goal level (many per goal) that never changes status. Pass role \`drives_status\` to make it the goal's status driver (childless leaf only, one per goal); a driver requires a \`second_anchor\` (a prior closed period + expected value confirming the Signal matched the books) and promotes an existing \`informs\` binding of the same Signal. Human-gated. | Seat or tenant-admin | Call with \`{"goal_id":"<id>","measurable_id":"<id>"}\` (add \`"role":"drives_status","second_anchor":{"period_start":"2026-Q1","expected_value":0}\` for the driver); expect confirmation. |
|
|
46943
47115
|
| \`rost_unbind_a_signal_from_a_cascade_goal\` | \`goal.unbind_measurable\` | Remove a goal\u2194measurable binding (role defaults to \`drives_status\`; pass \`"role":"informs"\` to remove an indicator). | Seat or tenant-admin | Call with \`{"goal_id":"<id>","measurable_id":"<id>"}\`. |
|
|
46944
47116
|
| \`rost_toggle_signal_driven_auto_status\` | \`goal.set_auto_status\` | Per-goal steward opt-in (default OFF) that lets the bound measurable's latest confirmed reading compute the goal's status. Enabling applies the current signal immediately. Human-gated. | Seat or tenant-admin | Call with \`{"goal_id":"<id>","enabled":true}\`; expect confirmation. |
|
|
46945
47117
|
| \`rost_list_at_risk_cascade_goals\` | \`goal.list_at_risk\` | List goals projected off pace (at-risk or projected-miss) with days behind pace. Read-only; status-only goals excluded. | Tenant | Call with \`{}\`. |
|
|
46946
47118
|
| \`rost_reparent_cascade_goal\` | \`goal.reparent\` | Move a goal under a new parent. | Tenant | Authority change; expect confirmation. |
|
|
46947
47119
|
| \`rost_drop_cascade_goal\` | \`goal.drop\` | Drop (retire) a goal, retained for audit. | Tenant | Expect confirmation. |
|
|
46948
47120
|
| \`rost_list_friction_issues\` | \`friction.list\` | List Friction issues ranked by impact and severity. | Seat or tenant-admin | Call with \`{}\` or \`{"status":"active"}\`. |
|
|
47121
|
+
| \`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
47122
|
| \`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
47123
|
| \`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
47124
|
| \`rost_resolve_friction_issue\` | \`friction.resolve\` | Resolve an issue with a root cause and remediation task. | Tenant | Human decision; expect confirmation. |
|
|
@@ -47507,7 +47680,7 @@ Retrieve the narrowest relevant guide before making a setup recommendation. Pref
|
|
|
47507
47680
|
order: 60,
|
|
47508
47681
|
title: "Cascade guide",
|
|
47509
47682
|
summary: "How to connect company goals to seat-level work without turning {{brand}} into a project-management tool.",
|
|
47510
|
-
version: "2026-07-12.
|
|
47683
|
+
version: "2026-07-12.2",
|
|
47511
47684
|
public: true,
|
|
47512
47685
|
audiences: ["human", "cli", "mcp", "in_app_agent"],
|
|
47513
47686
|
stages: ["operating_rhythm"],
|
|
@@ -47516,6 +47689,7 @@ Retrieve the narrowest relevant guide before making a setup recommendation. Pref
|
|
|
47516
47689
|
"compass.approve_version",
|
|
47517
47690
|
"onboarding.finish",
|
|
47518
47691
|
"goal.list",
|
|
47692
|
+
"goal.get",
|
|
47519
47693
|
"goal.create",
|
|
47520
47694
|
"goal.update",
|
|
47521
47695
|
"goal.set_status",
|
|
@@ -47585,7 +47759,7 @@ On human and function seat pages, goal visibility includes both direct goals and
|
|
|
47585
47759
|
|
|
47586
47760
|
## Drive a goal's status from a Signal
|
|
47587
47761
|
|
|
47588
|
-
A Signal can be linked to a goal for visibility, or set to compute its status. Bind a Signal with \`goal.bind_measurable\`. By default the binding is **informative** (role \`informs\`): it appears as a direct indicator on the goal, is allowed at any level (company objective, parent, or leaf), can be one of many on the same goal, and never changes the goal's status. To let a Signal **drive** a leaf goal's status instead, bind it with \`--role drives_status\` (the goal must be a childless seat goal or milestone \u2014 a company objective or a goal with children rolls up from its children, so a driver there is rejected). A goal can have at most one driving Signal, and choosing a driver is a deliberate, human-gated act.
|
|
47762
|
+
A Signal can be linked to a goal for visibility, or set to compute its status. Bind a Signal with \`goal.bind_measurable\`. By default the binding is **informative** (role \`informs\`): it appears as a direct indicator on the goal, is allowed at any level (company objective, parent, or leaf), can be one of many on the same goal, and never changes the goal's status. To let a Signal **drive** a leaf goal's status instead, bind it with \`--role drives_status\` (the goal must be a childless seat goal or milestone \u2014 a company objective or a goal with children rolls up from its children, so a driver there is rejected). A goal can have at most one driving Signal, and choosing a driver is a deliberate, human-gated act. Promoting a Signal to the status driver requires a **second anchor**: a prior closed period plus the value that period's books show (\`second_anchor: { period_start, expected_value }\`). The instantaneous reading is not enough \u2014 the anchor proves the Signal matched reality at least once before it may automatically flip a goal, and it is recorded durably with the confirmation. Confirming a driver over an existing informative binding of the same Signal promotes that binding in place.
|
|
47589
47763
|
|
|
47590
47764
|
A \`drives_status\` binding starts as an indicator only: nothing changes until a steward opts in with \`goal.set_auto_status --enabled true\`. Once opted in, the goal's status is computed from the measurable's latest confirmed reading against its target and direction \u2014 on target reads on-track, below target reads off-track. Only confirmed readings drive status; an agent's draft reading never auto-flips a goal. A human who sets the status by hand pins it, and that pin wins over the computed value until they change it or re-run \`goal.set_auto_status\`. Remove a binding with \`goal.unbind_measurable\`; the goal keeps its last status. Until a binding is opted in, an off-track Signal never raises an at-risk alert on its own.
|
|
47591
47765
|
|
|
@@ -47613,7 +47787,7 @@ Agents can suggest commitments and report progress. They should not create a new
|
|
|
47613
47787
|
order: 61,
|
|
47614
47788
|
title: "Signal guide",
|
|
47615
47789
|
summary: "How to define and read measurables so the company runs on evidence instead of status theater.",
|
|
47616
|
-
version: "2026-07-
|
|
47790
|
+
version: "2026-07-12.1",
|
|
47617
47791
|
public: true,
|
|
47618
47792
|
audiences: ["human", "cli", "mcp", "in_app_agent"],
|
|
47619
47793
|
stages: ["operating_rhythm"],
|
|
@@ -47701,7 +47875,7 @@ Once a measurable's number lives in a connected system, you can teach {{brand}}
|
|
|
47701
47875
|
- \`signal.bind\` persists the validated recipe as an inert \`draft\` binding. It requires the \`preview_token\` from a preview of the same recipe, so nothing is bound that was not first seen working.
|
|
47702
47876
|
- \`signal.bind_confirm\` is human-only. It activates the binding (\`draft -> active\`); an agent that calls it produces a pending confirmation instead. Only after a human confirms does the scheduled pull begin writing confirmed readings.
|
|
47703
47877
|
|
|
47704
|
-
Discovery always returns a \`recipe_presets\` array; it is empty when {{brand}} does not recognize a safe source type. Today the proven self-filling path is Baserow REST through \`integration.connect_rest\`: a tenant admin creates or rotates the Baserow connection through the command/vault path, then Signal runs \`integration.discover -> signal.preview -> signal.bind -> signal.bind_confirm\` against that connected source. Baserow row-field
|
|
47878
|
+
Discovery always returns a \`recipe_presets\` array; it is empty when {{brand}} does not recognize a safe source type. Today the proven self-filling path is Baserow REST through \`integration.connect_rest\`: a tenant admin creates or rotates the Baserow connection through the command/vault path, then Signal runs \`integration.discover -> signal.preview -> signal.bind -> signal.bind_confirm\` against that connected source. Baserow discovery now offers two first-class presets: \`baserow.row-field\` (read one scalar field from a row) and \`baserow.filtered-count\` (count rows matching a condition). The filtered-count builder takes a table id, field key, comparison operator, and comparison value and assembles a validated \`rest_for_signals\` recipe whose \`value_path\` is the response \`count\`; the field key and operator are allowlisted (they form the query-parameter name) and the comparison value is percent-encoded, so nothing the operator types can inject into the URL. The human still supplies the real table, field, operator, value, and host \u2014 presets and the builder are starter recipes, not secret stores. Google Sheets Signal pulls are not live yet: Google uses OAuth JSON credentials and remains withheld from REST presets until the pull executor extracts and refreshes the Google access token instead of treating the stored credential blob as a bearer token. A preset includes a label, cadence, required metadata, a draft \`rest_for_signals\` recipe, and the host allowlist to preview with. The human still fills in the real Baserow table/row/field or exact REST URL and value path before running \`signal.preview\`; presets are starter recipes, not secret stores.
|
|
47705
47879
|
|
|
47706
47880
|
Recipes are validated data, never code: a read-only GET, a closed set of non-secret headers, and a restricted scalar path to the value. Every fetch passes one SSRF guard (HTTPS only, a steward-confirmed host allowlist set at bind, and a runtime check that the host does not resolve to a private address). The preset output never contains \`nango://\` handles, vault refs, tokens, or static credential headers. Deterministic pulls write \`integration\`-sourced readings on the measurable's cadence.
|
|
47707
47881
|
|
|
@@ -47735,6 +47909,7 @@ Agents may record readings when the Charter allows it. Agent-reported readings s
|
|
|
47735
47909
|
"compass.answer_gap",
|
|
47736
47910
|
"friction.file_issue",
|
|
47737
47911
|
"friction.list",
|
|
47912
|
+
"friction.get",
|
|
47738
47913
|
"friction.assist",
|
|
47739
47914
|
"friction.update_status",
|
|
47740
47915
|
"friction.resolve",
|
|
@@ -47881,7 +48056,7 @@ Keep agent scope tight at first. Approve more autonomy only after evidence. Use
|
|
|
47881
48056
|
public: true,
|
|
47882
48057
|
audiences: ["human", "cli", "mcp", "in_app_agent"],
|
|
47883
48058
|
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"],
|
|
48059
|
+
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
48060
|
legal: { publicRisk: "low", notes: ["{{brand}}-native human-gate guidance."] },
|
|
47886
48061
|
sources: [
|
|
47887
48062
|
{
|
|
@@ -50026,6 +50201,11 @@ function helpText() {
|
|
|
50026
50201
|
].join("\n");
|
|
50027
50202
|
}
|
|
50028
50203
|
|
|
50204
|
+
// src/update-check.ts
|
|
50205
|
+
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
|
|
50206
|
+
import { homedir as homedir2 } from "node:os";
|
|
50207
|
+
import path2 from "node:path";
|
|
50208
|
+
|
|
50029
50209
|
// src/cli-version.ts
|
|
50030
50210
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
50031
50211
|
import { dirname as dirname2, resolve } from "node:path";
|
|
@@ -50047,15 +50227,23 @@ async function readCliVersion() {
|
|
|
50047
50227
|
var latestPackageSchema = external_exports.object({
|
|
50048
50228
|
version: external_exports.string()
|
|
50049
50229
|
});
|
|
50050
|
-
|
|
50051
|
-
|
|
50230
|
+
var updateCheckStateSchema = external_exports.object({ lastNaggedOn: external_exports.string() }).strict();
|
|
50231
|
+
async function maybePrintUpgradeNudge(io, options = {}) {
|
|
50232
|
+
if (!options.skipEnvGuard && (process.env.CI || process.env.VITEST || process.env.CLI_SKIP_UPDATE_CHECK === "1")) {
|
|
50233
|
+
return;
|
|
50234
|
+
}
|
|
50235
|
+
const statePath = options.statePath ?? defaultUpdateCheckStatePath();
|
|
50236
|
+
const today = toUtcDateOnly(options.now ?? /* @__PURE__ */ new Date());
|
|
50237
|
+
const state = await readUpdateCheckState(statePath);
|
|
50238
|
+
if (state?.lastNaggedOn === today) {
|
|
50052
50239
|
return;
|
|
50053
50240
|
}
|
|
50054
50241
|
const currentVersion = await readCliVersion();
|
|
50055
50242
|
if (!currentVersion || currentVersion === "0.0.0") {
|
|
50056
50243
|
return;
|
|
50057
50244
|
}
|
|
50058
|
-
const
|
|
50245
|
+
const fetchLatest = options.fetchLatest ?? fetchLatestVersion;
|
|
50246
|
+
const latestVersion = await fetchLatest(cliBrand.packageName);
|
|
50059
50247
|
if (!latestVersion || !isSemverBehind(currentVersion, latestVersion)) {
|
|
50060
50248
|
return;
|
|
50061
50249
|
}
|
|
@@ -50063,6 +50251,28 @@ async function maybePrintUpgradeNudge(io) {
|
|
|
50063
50251
|
`A newer ${cliBrand.binName} CLI is available: ${currentVersion} -> ${latestVersion}. Upgrade with npm i -g ${cliBrand.packageName}@latest.
|
|
50064
50252
|
`
|
|
50065
50253
|
);
|
|
50254
|
+
await writeUpdateCheckStateBestEffort(statePath, { lastNaggedOn: today });
|
|
50255
|
+
}
|
|
50256
|
+
function defaultUpdateCheckStatePath() {
|
|
50257
|
+
return path2.join(homedir2(), ".config", cliBrand.binName, "update-check.json");
|
|
50258
|
+
}
|
|
50259
|
+
function toUtcDateOnly(date5) {
|
|
50260
|
+
return date5.toISOString().slice(0, 10);
|
|
50261
|
+
}
|
|
50262
|
+
async function readUpdateCheckState(statePath) {
|
|
50263
|
+
try {
|
|
50264
|
+
return updateCheckStateSchema.parse(JSON.parse(await readFile3(statePath, "utf8")));
|
|
50265
|
+
} catch {
|
|
50266
|
+
return null;
|
|
50267
|
+
}
|
|
50268
|
+
}
|
|
50269
|
+
async function writeUpdateCheckStateBestEffort(statePath, state) {
|
|
50270
|
+
try {
|
|
50271
|
+
await mkdir2(path2.dirname(statePath), { recursive: true, mode: 448 });
|
|
50272
|
+
await writeFile2(statePath, `${JSON.stringify(state)}
|
|
50273
|
+
`, { mode: 384 });
|
|
50274
|
+
} catch {
|
|
50275
|
+
}
|
|
50066
50276
|
}
|
|
50067
50277
|
async function fetchLatestVersion(packageName) {
|
|
50068
50278
|
const controller = new AbortController();
|
|
@@ -50168,6 +50378,7 @@ var COMMAND_MANIFEST = [
|
|
|
50168
50378
|
{ "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
50379
|
{ "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
50380
|
{ "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." },
|
|
50381
|
+
{ "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
50382
|
{ "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
50383
|
{ "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
50384
|
{ "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 +50396,16 @@ var COMMAND_MANIFEST = [
|
|
|
50185
50396
|
{ "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
50397
|
{ "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
50398
|
{ "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." },
|
|
50399
|
+
{ "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
50400
|
{ "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
50401
|
{ "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
50402
|
{ "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":
|
|
50403
|
+
{ "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
50404
|
{ "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
|
-
{ "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":
|
|
50405
|
+
{ "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, requires a second_anchor (a prior closed period + expected value confirming the Signal matched the books), and auto-status starts OFF until a steward opts in with goal.set_auto_status. Binding a driver over an existing informs binding of the same Signal promotes it. 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": true, "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 with a second_anchor (a prior closed period + expected value confirming the Signal matched the books) to make it a childless leaf goal's status driver \u2014 this promotes an existing informs binding (auto-status starts OFF until a steward opts in)." },
|
|
50194
50406
|
{ "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
50407
|
{ "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." },
|
|
50408
|
+
{ "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
50409
|
{ "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
50410
|
{ "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
50411
|
{ "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 +50710,19 @@ function execute(context, parsed, commandId, body, format) {
|
|
|
50497
50710
|
}
|
|
50498
50711
|
|
|
50499
50712
|
// src/generator/flags.ts
|
|
50713
|
+
var SEAT_FLAG_FILLS_REQUIRED_SEAT_ID = /* @__PURE__ */ new Set([
|
|
50714
|
+
"agent.status",
|
|
50715
|
+
"agent.show_markdown",
|
|
50716
|
+
"agent.get_run",
|
|
50717
|
+
"agent.list_runs",
|
|
50718
|
+
"agent.list_tool_calls",
|
|
50719
|
+
"charter.show_markdown",
|
|
50720
|
+
"seat.get",
|
|
50721
|
+
"seat.decommission_preview",
|
|
50722
|
+
"deliverable.get",
|
|
50723
|
+
"deliverable.list",
|
|
50724
|
+
"skill.check_dependencies"
|
|
50725
|
+
]);
|
|
50500
50726
|
function booleanFlagsFor(entry, overrides = {}) {
|
|
50501
50727
|
const booleanFields = new Set(entry.fields.filter((field3) => field3.type === "boolean").map((field3) => field3.name));
|
|
50502
50728
|
const flags = /* @__PURE__ */ new Set(["yes", "y"]);
|
|
@@ -50586,6 +50812,9 @@ function buildBodyFromFlags(entry, parsed, positional, overrides = {}) {
|
|
|
50586
50812
|
if (raw === void 0 && positional !== void 0 && overrides.primaryPositional === field3.name) {
|
|
50587
50813
|
raw = positional;
|
|
50588
50814
|
}
|
|
50815
|
+
if (raw === void 0 && field3.name === "seat_id" && (!field3.required || SEAT_FLAG_FILLS_REQUIRED_SEAT_ID.has(entry.id))) {
|
|
50816
|
+
raw = parsed.seat;
|
|
50817
|
+
}
|
|
50589
50818
|
if (raw === void 0 || raw.length === 0) {
|
|
50590
50819
|
continue;
|
|
50591
50820
|
}
|
|
@@ -50990,6 +51219,15 @@ function renderGoalStatus(output) {
|
|
|
50990
51219
|
const record2 = asRecord(output);
|
|
50991
51220
|
return `Goal ${field(record2, "goal_id")} status set to ${field(record2, "status")}.`;
|
|
50992
51221
|
}
|
|
51222
|
+
function renderGoalGet(output) {
|
|
51223
|
+
const record2 = asRecord(asRecord(output).goal);
|
|
51224
|
+
return [
|
|
51225
|
+
`${field(record2, "id")} ${field(record2, "status")} ${field(record2, "title")}`,
|
|
51226
|
+
`kind: ${field(record2, "kind")} status source: ${field(record2, "status_source")}`,
|
|
51227
|
+
`progress: ${field(record2, "progress_pct")}`,
|
|
51228
|
+
`definition of done: ${field(record2, "definition_of_done")}`
|
|
51229
|
+
].join("\n");
|
|
51230
|
+
}
|
|
50993
51231
|
function renderGoalReparent(output) {
|
|
50994
51232
|
const record2 = asRecord(output);
|
|
50995
51233
|
return `Goal ${field(record2, "goal_id")} reparented under ${field(record2, "parent_goal_id")}.`;
|
|
@@ -51020,6 +51258,27 @@ function renderFrictionLink(output) {
|
|
|
51020
51258
|
const record2 = asRecord(output);
|
|
51021
51259
|
return `Linked task ${field(record2, "action_task_id")} to issue ${field(record2, "issue_id")}.`;
|
|
51022
51260
|
}
|
|
51261
|
+
function renderFrictionGet(output) {
|
|
51262
|
+
const record2 = asRecord(asRecord(output).issue);
|
|
51263
|
+
return [
|
|
51264
|
+
`${field(record2, "issue_id")} ${field(record2, "status")} ${field(record2, "severity")}`,
|
|
51265
|
+
`summary: ${field(record2, "summary")}`,
|
|
51266
|
+
`raised by: ${field(record2, "raised_by_seat_name")}`,
|
|
51267
|
+
`impact score: ${field(record2, "impact_score")}`,
|
|
51268
|
+
`root cause: ${field(record2, "root_cause")}`,
|
|
51269
|
+
`action task: ${field(record2, "action_task_id")}`
|
|
51270
|
+
].join("\n");
|
|
51271
|
+
}
|
|
51272
|
+
function renderConfirmationList(output) {
|
|
51273
|
+
const confirmations = asArray(asRecord(output).confirmations);
|
|
51274
|
+
if (confirmations.length === 0) {
|
|
51275
|
+
return "No pending confirmations.";
|
|
51276
|
+
}
|
|
51277
|
+
return confirmations.map((entry) => {
|
|
51278
|
+
const record2 = asRecord(entry);
|
|
51279
|
+
return `${field(record2, "id")} ${field(record2, "risk_level")} ${field(record2, "command_id")} ${field(record2, "summary")}`;
|
|
51280
|
+
}).join("\n");
|
|
51281
|
+
}
|
|
51023
51282
|
function renderEscalationList(output) {
|
|
51024
51283
|
const escalations = asArray(asRecord(output).escalations);
|
|
51025
51284
|
if (escalations.length === 0) {
|
|
@@ -51922,7 +52181,8 @@ var GROUP_SPECS = {
|
|
|
51922
52181
|
list: { commandId: "goal.list", render: renderGoalList },
|
|
51923
52182
|
create: { commandId: "goal.create", render: renderGoalCreate },
|
|
51924
52183
|
update: { commandId: "goal.update", handler: goalUpdateHandler, render: renderGoalUpdate },
|
|
51925
|
-
status: { commandId: "goal.
|
|
52184
|
+
status: { commandId: "goal.get", render: renderGoalGet, primaryPositional: "goal_id" },
|
|
52185
|
+
"set-status": { commandId: "goal.set_status", render: renderGoalStatus },
|
|
51926
52186
|
reparent: { commandId: "goal.reparent", render: renderGoalReparent },
|
|
51927
52187
|
drop: { commandId: "goal.drop", render: renderGoalDrop }
|
|
51928
52188
|
}
|
|
@@ -51946,6 +52206,7 @@ var GROUP_SPECS = {
|
|
|
51946
52206
|
friction: {
|
|
51947
52207
|
verbs: {
|
|
51948
52208
|
list: { commandId: "friction.list", render: renderFrictionList },
|
|
52209
|
+
get: { commandId: "friction.get", render: renderFrictionGet, primaryPositional: "issue_id" },
|
|
51949
52210
|
file: { commandId: "friction.file_issue", handler: frictionFileHandler, render: renderFrictionFile },
|
|
51950
52211
|
resolve: { commandId: "friction.resolve", render: renderFrictionResolve },
|
|
51951
52212
|
link: { commandId: "friction.link_task", render: renderFrictionLink },
|
|
@@ -51967,7 +52228,7 @@ var GROUP_SPECS = {
|
|
|
51967
52228
|
verbs: {
|
|
51968
52229
|
list: { commandId: "escalation.list", render: renderEscalationList },
|
|
51969
52230
|
get: { commandId: "escalation.get", render: renderEscalationGet, primaryPositional: "id" },
|
|
51970
|
-
resolve: { commandId: "escalation.resolve", render: renderEscalationResolve },
|
|
52231
|
+
resolve: { commandId: "escalation.resolve", render: renderEscalationResolve, primaryPositional: "id" },
|
|
51971
52232
|
reject: { commandId: "escalation.reject", render: renderEscalationReject }
|
|
51972
52233
|
}
|
|
51973
52234
|
},
|
|
@@ -52089,6 +52350,11 @@ var GROUP_SPECS = {
|
|
|
52089
52350
|
verbs: {
|
|
52090
52351
|
health: { commandId: "system.health", handler: systemHealthHandler, render: formatSystemHealth }
|
|
52091
52352
|
}
|
|
52353
|
+
},
|
|
52354
|
+
confirmation: {
|
|
52355
|
+
verbs: {
|
|
52356
|
+
list: { commandId: "confirmation.list", render: renderConfirmationList }
|
|
52357
|
+
}
|
|
52092
52358
|
}
|
|
52093
52359
|
};
|
|
52094
52360
|
|
|
@@ -52378,7 +52644,7 @@ function ensureTrailingSlash2(value) {
|
|
|
52378
52644
|
// src/skills.ts
|
|
52379
52645
|
import { existsSync, mkdirSync, readFileSync as readFileSync3, rmSync, writeFileSync } from "node:fs";
|
|
52380
52646
|
import os from "node:os";
|
|
52381
|
-
import
|
|
52647
|
+
import path3 from "node:path";
|
|
52382
52648
|
var UsageError2 = class extends Error {
|
|
52383
52649
|
};
|
|
52384
52650
|
var CLIENTS = /* @__PURE__ */ new Set(["claude-code", "codex", "cursor"]);
|
|
@@ -52573,8 +52839,8 @@ function writeInstalls(output, root) {
|
|
|
52573
52839
|
const slug2 = safeLocalSlug(String(install.slug ?? ""));
|
|
52574
52840
|
const metadata = asRecord2(install.metadata);
|
|
52575
52841
|
const files = asArray2(install.files).map(asRecord2);
|
|
52576
|
-
const dir =
|
|
52577
|
-
const metadataPath =
|
|
52842
|
+
const dir = path3.join(root, slug2);
|
|
52843
|
+
const metadataPath = path3.join(dir, ".rost-skill.json");
|
|
52578
52844
|
const expectedHash = String(metadata.content_sha256 ?? "");
|
|
52579
52845
|
if (existingHash(metadataPath) === expectedHash) {
|
|
52580
52846
|
return { slug: slug2, dir, status: "unchanged", files: files.length };
|
|
@@ -52584,8 +52850,8 @@ function writeInstalls(output, root) {
|
|
|
52584
52850
|
for (const file2 of files) {
|
|
52585
52851
|
const relativePath = safeRelativePath(String(file2.path ?? ""));
|
|
52586
52852
|
const content = String(file2.content ?? "");
|
|
52587
|
-
const target =
|
|
52588
|
-
mkdirSync(
|
|
52853
|
+
const target = path3.join(dir, relativePath);
|
|
52854
|
+
mkdirSync(path3.dirname(target), { recursive: true });
|
|
52589
52855
|
writeFileSync(target, content, "utf8");
|
|
52590
52856
|
}
|
|
52591
52857
|
writeFileSync(metadataPath, `${JSON.stringify(metadata, null, 2)}
|
|
@@ -52605,7 +52871,7 @@ function removeRevokedInstalls(output, root) {
|
|
|
52605
52871
|
if (installs.has(slug2)) {
|
|
52606
52872
|
continue;
|
|
52607
52873
|
}
|
|
52608
|
-
const dir =
|
|
52874
|
+
const dir = path3.join(root, slug2);
|
|
52609
52875
|
if (!existsSync(dir)) {
|
|
52610
52876
|
continue;
|
|
52611
52877
|
}
|
|
@@ -52617,15 +52883,15 @@ function removeRevokedInstalls(output, root) {
|
|
|
52617
52883
|
function installRoot(client, env) {
|
|
52618
52884
|
const override = env.ROST_SKILL_INSTALL_ROOT;
|
|
52619
52885
|
if (override && override.length > 0) {
|
|
52620
|
-
return
|
|
52886
|
+
return path3.resolve(override, client);
|
|
52621
52887
|
}
|
|
52622
52888
|
if (client === "codex") {
|
|
52623
|
-
return
|
|
52889
|
+
return path3.join(env.CODEX_HOME ?? path3.join(os.homedir(), ".codex"), "skills", "rost");
|
|
52624
52890
|
}
|
|
52625
52891
|
if (client === "claude-code") {
|
|
52626
|
-
return
|
|
52892
|
+
return path3.join(env.CLAUDE_HOME ?? path3.join(os.homedir(), ".claude"), "skills", "rost");
|
|
52627
52893
|
}
|
|
52628
|
-
return
|
|
52894
|
+
return path3.join(os.homedir(), ".cursor", "skills", "rost");
|
|
52629
52895
|
}
|
|
52630
52896
|
function safeRelativePath(value) {
|
|
52631
52897
|
const normalized = value.trim().replaceAll("\\", "/").replace(/^\.\/+/, "");
|
|
@@ -52834,9 +53100,9 @@ import { promisify as promisify3 } from "node:util";
|
|
|
52834
53100
|
import { existsSync as existsSync2, realpathSync } from "node:fs";
|
|
52835
53101
|
import { readdir, rm as rm2, stat as stat2 } from "node:fs/promises";
|
|
52836
53102
|
import { tmpdir } from "node:os";
|
|
52837
|
-
import
|
|
53103
|
+
import path4 from "node:path";
|
|
52838
53104
|
var SANDBOX_EXEC_PATH = "/usr/bin/sandbox-exec";
|
|
52839
|
-
var RUNNER_ASKPASS_DIR =
|
|
53105
|
+
var RUNNER_ASKPASS_DIR = path4.join(tmpdir(), "rost-runner-askpass");
|
|
52840
53106
|
var RUNNER_TEMP_PREFIXES = [
|
|
52841
53107
|
"rost-runner-mcp-",
|
|
52842
53108
|
"rost-runner-sandbox-",
|
|
@@ -53006,7 +53272,7 @@ function canonical(p) {
|
|
|
53006
53272
|
}
|
|
53007
53273
|
}
|
|
53008
53274
|
function canonicalFile(p) {
|
|
53009
|
-
return
|
|
53275
|
+
return path4.join(canonical(path4.dirname(p)), path4.basename(p));
|
|
53010
53276
|
}
|
|
53011
53277
|
function isSandboxExecAvailable() {
|
|
53012
53278
|
try {
|
|
@@ -53089,7 +53355,7 @@ async function sweepStaleRunnerTempFiles(dir, options = {}) {
|
|
|
53089
53355
|
if (!RUNNER_TEMP_PREFIXES.some((prefix) => name.startsWith(prefix))) {
|
|
53090
53356
|
return;
|
|
53091
53357
|
}
|
|
53092
|
-
const full =
|
|
53358
|
+
const full = path4.join(dir, name);
|
|
53093
53359
|
try {
|
|
53094
53360
|
const info = await stat2(full);
|
|
53095
53361
|
if (now - info.mtimeMs < maxAgeMs) {
|
|
@@ -53107,9 +53373,9 @@ async function sweepStaleRunnerTempFiles(dir, options = {}) {
|
|
|
53107
53373
|
// src/runner-service.ts
|
|
53108
53374
|
import { execFile as execFileCallback2 } from "node:child_process";
|
|
53109
53375
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
53110
|
-
import { access, mkdir as
|
|
53111
|
-
import { homedir as
|
|
53112
|
-
import
|
|
53376
|
+
import { access, mkdir as mkdir3, readFile as readFile4, readdir as readdir2, rm as rm3, writeFile as writeFile3 } from "node:fs/promises";
|
|
53377
|
+
import { homedir as homedir3 } from "node:os";
|
|
53378
|
+
import path5 from "node:path";
|
|
53113
53379
|
import { promisify as promisify2 } from "node:util";
|
|
53114
53380
|
var execFile2 = promisify2(execFileCallback2);
|
|
53115
53381
|
var SERVICE_VERBS = ["install-service", "start", "stop", "restart", "status", "logs", "uninstall"];
|
|
@@ -53126,9 +53392,9 @@ function isRunnerServiceInvocation(args) {
|
|
|
53126
53392
|
function runnerServicePaths(homeDir, runnerName) {
|
|
53127
53393
|
const safeName = safeRunnerName(runnerName);
|
|
53128
53394
|
return {
|
|
53129
|
-
launchAgentPath:
|
|
53130
|
-
stateFile:
|
|
53131
|
-
logDir:
|
|
53395
|
+
launchAgentPath: path5.join(homeDir, "Library", "LaunchAgents", `${serviceLabel(safeName)}.plist`),
|
|
53396
|
+
stateFile: path5.join(homeDir, "Library", "Application Support", cliBrand.name, `runner-${safeName}.json`),
|
|
53397
|
+
logDir: path5.join(homeDir, "Library", "Logs", cliBrand.name, "runner", safeName)
|
|
53132
53398
|
};
|
|
53133
53399
|
}
|
|
53134
53400
|
function renderLaunchdPlist(config2) {
|
|
@@ -53170,9 +53436,9 @@ ${config2.allowDevelopmentAppUrl === true ? ` <key>${allowInsecureAppUrlEnv}<
|
|
|
53170
53436
|
<key>RunAtLoad</key>
|
|
53171
53437
|
<true/>
|
|
53172
53438
|
<key>StandardOutPath</key>
|
|
53173
|
-
<string>${escapePlist(
|
|
53439
|
+
<string>${escapePlist(path5.join(config2.logDir, "stdout.log"))}</string>
|
|
53174
53440
|
<key>StandardErrorPath</key>
|
|
53175
|
-
<string>${escapePlist(
|
|
53441
|
+
<string>${escapePlist(path5.join(config2.logDir, "stderr.log"))}</string>
|
|
53176
53442
|
</dict>
|
|
53177
53443
|
</plist>
|
|
53178
53444
|
`;
|
|
@@ -53208,7 +53474,7 @@ ${serviceUsage()}
|
|
|
53208
53474
|
userCode: parsed.userCode,
|
|
53209
53475
|
nodePath: options.nodePath ?? resolveNodePath(),
|
|
53210
53476
|
binPath: options.binPath ?? resolveBinPath(),
|
|
53211
|
-
homeDir: options.homeDir ??
|
|
53477
|
+
homeDir: options.homeDir ?? homedir3(),
|
|
53212
53478
|
platform: options.platform ?? process.platform,
|
|
53213
53479
|
exec: options.exec ?? defaultExec,
|
|
53214
53480
|
uid: options.uid ?? (process.getuid ? process.getuid() : 0)
|
|
@@ -53239,9 +53505,9 @@ async function installService(options) {
|
|
|
53239
53505
|
const safeName = safeRunnerName(options.runnerName);
|
|
53240
53506
|
const paths = runnerServicePaths(options.homeDir, safeName);
|
|
53241
53507
|
const label = serviceLabel(safeName);
|
|
53242
|
-
await
|
|
53243
|
-
await
|
|
53244
|
-
await
|
|
53508
|
+
await mkdir3(paths.logDir, { recursive: true });
|
|
53509
|
+
await mkdir3(path5.dirname(paths.stateFile), { recursive: true });
|
|
53510
|
+
await mkdir3(path5.dirname(paths.launchAgentPath), { recursive: true });
|
|
53245
53511
|
if (options.userCode !== void 0) {
|
|
53246
53512
|
const paired = await pairRunnerOnce(options, safeName, paths.stateFile, options.userCode);
|
|
53247
53513
|
if (!paired) {
|
|
@@ -53259,7 +53525,7 @@ async function installService(options) {
|
|
|
53259
53525
|
servicePath: buildServicePath(options.nodePath, options.homeDir),
|
|
53260
53526
|
execute: options.execute
|
|
53261
53527
|
});
|
|
53262
|
-
await
|
|
53528
|
+
await writeFile3(paths.launchAgentPath, plist, { mode: 420 });
|
|
53263
53529
|
await bootoutQuietly(options.exec, options.uid, paths.launchAgentPath);
|
|
53264
53530
|
try {
|
|
53265
53531
|
const bootstrapped = await bootstrapService(options.exec, options.uid, paths.launchAgentPath);
|
|
@@ -53396,8 +53662,8 @@ async function logsService(options) {
|
|
|
53396
53662
|
const safeName = safeRunnerName(options.runnerName);
|
|
53397
53663
|
const paths = runnerServicePaths(options.homeDir, safeName);
|
|
53398
53664
|
const label = serviceLabel(safeName);
|
|
53399
|
-
const stdoutLog =
|
|
53400
|
-
const stderrLog =
|
|
53665
|
+
const stdoutLog = path5.join(paths.logDir, "stdout.log");
|
|
53666
|
+
const stderrLog = path5.join(paths.logDir, "stderr.log");
|
|
53401
53667
|
options.io.stdout.write(
|
|
53402
53668
|
`${[
|
|
53403
53669
|
`runner service logs for ${label}:`,
|
|
@@ -53500,8 +53766,8 @@ function serviceTargets(uid, label) {
|
|
|
53500
53766
|
return launchdDomains(uid).map((domain2) => `${domain2}/${label}`);
|
|
53501
53767
|
}
|
|
53502
53768
|
async function inspectRunnerServiceInstallations(options = {}) {
|
|
53503
|
-
const homeDir = options.homeDir ??
|
|
53504
|
-
const launchAgentsDir =
|
|
53769
|
+
const homeDir = options.homeDir ?? homedir3();
|
|
53770
|
+
const launchAgentsDir = path5.join(homeDir, "Library", "LaunchAgents");
|
|
53505
53771
|
let names = [];
|
|
53506
53772
|
try {
|
|
53507
53773
|
const entries = await readdir2(launchAgentsDir);
|
|
@@ -53521,7 +53787,7 @@ async function inspectRunnerService(options) {
|
|
|
53521
53787
|
const paths = runnerServicePaths(options.homeDir, safeName);
|
|
53522
53788
|
const label = serviceLabel(safeName);
|
|
53523
53789
|
const installed = await fileExists(paths.launchAgentPath);
|
|
53524
|
-
const plist = installed ? await
|
|
53790
|
+
const plist = installed ? await readFile4(paths.launchAgentPath, "utf8").catch(() => null) : null;
|
|
53525
53791
|
const programArgs = plist ? extractProgramArguments(plist) : [];
|
|
53526
53792
|
const appUrl2 = plist ? extractPlistEnvironmentValue(plist, `${cliBrand.envPrefix}_APP_URL`) : null;
|
|
53527
53793
|
const urlPolicyEnv = extractPlistEnvironmentValue(plist ?? "", allowInsecureAppUrlEnv) === "1" ? "set" : "unset";
|
|
@@ -53630,11 +53896,11 @@ function resolveNodePath() {
|
|
|
53630
53896
|
}
|
|
53631
53897
|
function buildServicePath(nodePath, homeDir) {
|
|
53632
53898
|
const entries = [
|
|
53633
|
-
|
|
53899
|
+
path5.dirname(nodePath),
|
|
53634
53900
|
"/opt/homebrew/bin",
|
|
53635
53901
|
"/usr/local/bin",
|
|
53636
|
-
|
|
53637
|
-
|
|
53902
|
+
path5.join(homeDir, ".local", "bin"),
|
|
53903
|
+
path5.join(homeDir, "bin"),
|
|
53638
53904
|
"/usr/bin",
|
|
53639
53905
|
"/bin",
|
|
53640
53906
|
"/usr/sbin",
|
|
@@ -53789,7 +54055,7 @@ async function fileExists(file2) {
|
|
|
53789
54055
|
}
|
|
53790
54056
|
async function readTail(file2, maxBytes) {
|
|
53791
54057
|
try {
|
|
53792
|
-
const content = await
|
|
54058
|
+
const content = await readFile4(file2, "utf8");
|
|
53793
54059
|
return content.length > maxBytes ? content.slice(content.length - maxBytes) : content;
|
|
53794
54060
|
} catch {
|
|
53795
54061
|
return null;
|
|
@@ -53936,17 +54202,17 @@ function parseSemver2(value) {
|
|
|
53936
54202
|
// src/runner-serve.ts
|
|
53937
54203
|
import { execFile as execFileCallback5, spawn } from "node:child_process";
|
|
53938
54204
|
import { createHash as createHash2 } from "node:crypto";
|
|
53939
|
-
import { chmod as chmod2, mkdir as
|
|
53940
|
-
import { cpus, homedir as
|
|
53941
|
-
import
|
|
54205
|
+
import { chmod as chmod2, mkdir as mkdir5, readFile as readFile5, rename, rm as rm5, statfs, writeFile as writeFile5 } from "node:fs/promises";
|
|
54206
|
+
import { cpus, homedir as homedir4, hostname as hostname3, platform, totalmem, tmpdir as tmpdir2 } from "node:os";
|
|
54207
|
+
import path7 from "node:path";
|
|
53942
54208
|
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
53943
54209
|
import { promisify as promisify5 } from "node:util";
|
|
53944
54210
|
|
|
53945
54211
|
// src/forge-workspace.ts
|
|
53946
54212
|
import { execFile as execFileCallback4 } from "node:child_process";
|
|
53947
54213
|
import { createHash } from "node:crypto";
|
|
53948
|
-
import { chmod, lstat, mkdir as
|
|
53949
|
-
import
|
|
54214
|
+
import { chmod, lstat, mkdir as mkdir4, mkdtemp, realpath, rm as rm4, stat as stat3, writeFile as writeFile4 } from "node:fs/promises";
|
|
54215
|
+
import path6 from "node:path";
|
|
53950
54216
|
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
53951
54217
|
import { promisify as promisify4 } from "node:util";
|
|
53952
54218
|
|
|
@@ -54083,20 +54349,20 @@ function shortRequestId(buildRequestId) {
|
|
|
54083
54349
|
return slice.length > 0 ? slice : createHash("sha1").update(buildRequestId).digest("hex").slice(0, 8);
|
|
54084
54350
|
}
|
|
54085
54351
|
function requestRoot(baseDir, buildRequestId) {
|
|
54086
|
-
return
|
|
54352
|
+
return path6.join(baseDir, "work", shortRequestId(buildRequestId));
|
|
54087
54353
|
}
|
|
54088
54354
|
function baseRepoDir(baseDir, buildRequestId) {
|
|
54089
|
-
return
|
|
54355
|
+
return path6.join(requestRoot(baseDir, buildRequestId), "base");
|
|
54090
54356
|
}
|
|
54091
54357
|
function branchName(buildRequestId, changeset) {
|
|
54092
54358
|
const short = shortRequestId(buildRequestId);
|
|
54093
54359
|
return changeset.total > 1 ? `forge/${short}-cs${changeset.ordinal}` : `forge/${short}`;
|
|
54094
54360
|
}
|
|
54095
54361
|
function buildWorktreeDir(baseDir, buildRequestId, ordinal) {
|
|
54096
|
-
return
|
|
54362
|
+
return path6.join(requestRoot(baseDir, buildRequestId), `cs${ordinal}`);
|
|
54097
54363
|
}
|
|
54098
54364
|
function reviewWorktreeDir(baseDir, buildRequestId, ordinal) {
|
|
54099
|
-
return
|
|
54365
|
+
return path6.join(requestRoot(baseDir, buildRequestId), `review-cs${ordinal}`);
|
|
54100
54366
|
}
|
|
54101
54367
|
function remoteUrlFor(options) {
|
|
54102
54368
|
if (options.remoteUrl) {
|
|
@@ -54113,7 +54379,7 @@ async function pathExists(target) {
|
|
|
54113
54379
|
}
|
|
54114
54380
|
}
|
|
54115
54381
|
async function isGitRepo(dir) {
|
|
54116
|
-
return await pathExists(
|
|
54382
|
+
return await pathExists(path6.join(dir, ".git")) || await pathExists(path6.join(dir, "HEAD"));
|
|
54117
54383
|
}
|
|
54118
54384
|
async function runGit(args, cwd, timeoutMs = LOCAL_GIT_TIMEOUT_MS) {
|
|
54119
54385
|
try {
|
|
@@ -54166,10 +54432,10 @@ async function withNetworkRetries(op, fn, retryCounter) {
|
|
|
54166
54432
|
throw new Error(`${op} exhausted retries: ${lastError instanceof Error ? redactSecrets(lastError.message) : redactSecrets(String(lastError))}`);
|
|
54167
54433
|
}
|
|
54168
54434
|
async function canonicalAskpassBase(baseDir) {
|
|
54169
|
-
return
|
|
54435
|
+
return path6.join(await realpath(path6.dirname(baseDir)), path6.basename(baseDir));
|
|
54170
54436
|
}
|
|
54171
54437
|
async function prepareAskpassTurnDir(baseDir) {
|
|
54172
|
-
await
|
|
54438
|
+
await mkdir4(baseDir, { recursive: true, mode: 448 });
|
|
54173
54439
|
const baseInfo = await lstat(baseDir);
|
|
54174
54440
|
if (baseInfo.isSymbolicLink() || !baseInfo.isDirectory()) {
|
|
54175
54441
|
throw new Error(`refusing to use askpass dir ${baseDir}: not a real directory (possible symlink attack)`);
|
|
@@ -54178,10 +54444,10 @@ async function prepareAskpassTurnDir(baseDir) {
|
|
|
54178
54444
|
throw new Error(`refusing to use askpass dir ${baseDir}: not owned by this user (possible pre-planted dir)`);
|
|
54179
54445
|
}
|
|
54180
54446
|
await chmod(baseDir, 448);
|
|
54181
|
-
const turnDir = await mkdtemp(
|
|
54447
|
+
const turnDir = await mkdtemp(path6.join(baseDir, "rost-runner-askpass-"));
|
|
54182
54448
|
const canonicalBase = await canonicalAskpassBase(baseDir);
|
|
54183
54449
|
const realTurn = await realpath(turnDir);
|
|
54184
|
-
if (
|
|
54450
|
+
if (path6.dirname(realTurn) !== canonicalBase) {
|
|
54185
54451
|
await rm4(turnDir, { recursive: true, force: true });
|
|
54186
54452
|
throw new Error(`refusing to use askpass dir ${turnDir}: resolved outside ${canonicalBase} (possible symlink attack)`);
|
|
54187
54453
|
}
|
|
@@ -54189,7 +54455,7 @@ async function prepareAskpassTurnDir(baseDir) {
|
|
|
54189
54455
|
}
|
|
54190
54456
|
async function openAskpassSession(credential, baseDir = RUNNER_ASKPASS_DIR) {
|
|
54191
54457
|
const turnDir = await prepareAskpassTurnDir(baseDir);
|
|
54192
|
-
const helperPath =
|
|
54458
|
+
const helperPath = path6.join(turnDir, "askpass.sh");
|
|
54193
54459
|
const helper = [
|
|
54194
54460
|
"#!/bin/sh",
|
|
54195
54461
|
"# One-shot Forge GIT_ASKPASS helper. Contains no secret; reads the token from env.",
|
|
@@ -54199,7 +54465,7 @@ async function openAskpassSession(credential, baseDir = RUNNER_ASKPASS_DIR) {
|
|
|
54199
54465
|
"esac",
|
|
54200
54466
|
""
|
|
54201
54467
|
].join("\n");
|
|
54202
|
-
await
|
|
54468
|
+
await writeFile4(helperPath, helper, { mode: 448 });
|
|
54203
54469
|
await chmod(helperPath, 448);
|
|
54204
54470
|
const env = {
|
|
54205
54471
|
...process.env,
|
|
@@ -54250,8 +54516,8 @@ async function localBranchExists(baseRepo, branch) {
|
|
|
54250
54516
|
async function worktreeRegistered(baseRepo, worktreeDir) {
|
|
54251
54517
|
try {
|
|
54252
54518
|
const listing = await runGit(["worktree", "list", "--porcelain"], baseRepo);
|
|
54253
|
-
const target =
|
|
54254
|
-
return listing.split("\n").some((line) => line.startsWith("worktree ") &&
|
|
54519
|
+
const target = path6.resolve(worktreeDir);
|
|
54520
|
+
return listing.split("\n").some((line) => line.startsWith("worktree ") && path6.resolve(line.slice("worktree ".length).trim()) === target);
|
|
54255
54521
|
} catch {
|
|
54256
54522
|
return false;
|
|
54257
54523
|
}
|
|
@@ -54262,7 +54528,7 @@ async function configureForgeIdentity(baseRepo) {
|
|
|
54262
54528
|
}
|
|
54263
54529
|
async function ensureBaseClone(input) {
|
|
54264
54530
|
const baseRepo = baseRepoDir(input.baseDir, input.buildRequestId);
|
|
54265
|
-
await
|
|
54531
|
+
await mkdir4(path6.dirname(baseRepo), { recursive: true, mode: 448 });
|
|
54266
54532
|
await withLedgerStep(input.ledger, "clone", (retryCounter) => withAskpass(input.credential, async (netEnv) => {
|
|
54267
54533
|
if (await isGitRepo(baseRepo)) {
|
|
54268
54534
|
await runGitNetwork("git fetch", ["fetch", "--prune", "--quiet", input.url, "+refs/heads/*:refs/remotes/origin/*"], netEnv, baseRepo, FETCH_TIMEOUT_MS, retryCounter);
|
|
@@ -54311,7 +54577,7 @@ async function prepareMergeWorkspace(options) {
|
|
|
54311
54577
|
ledger: options.ledger
|
|
54312
54578
|
});
|
|
54313
54579
|
const branch = options.headBranch;
|
|
54314
|
-
const worktreeDir =
|
|
54580
|
+
const worktreeDir = path6.join(requestRoot(options.baseDir, options.buildRequestId), "merge");
|
|
54315
54581
|
const originDefault = `origin/${options.repo.default_branch}`;
|
|
54316
54582
|
const originHead = `origin/${branch}`;
|
|
54317
54583
|
await withLedgerStep(options.ledger, "branch", async () => {
|
|
@@ -54789,7 +55055,7 @@ async function runRunnerServe(options) {
|
|
|
54789
55055
|
const env = options.env ?? process.env;
|
|
54790
55056
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
54791
55057
|
const cliVersion = await readCliVersion();
|
|
54792
|
-
const homeDir = options.homeDir ??
|
|
55058
|
+
const homeDir = options.homeDir ?? homedir4();
|
|
54793
55059
|
let config2;
|
|
54794
55060
|
try {
|
|
54795
55061
|
config2 = parseServeArgs(options.args, options.appUrl, env, homeDir);
|
|
@@ -54975,7 +55241,7 @@ function detectTelemetry(capabilities, env, activeSessions, cliVersion) {
|
|
|
54975
55241
|
}
|
|
54976
55242
|
function parseServeArgs(args, appUrl2, env, homeDir) {
|
|
54977
55243
|
let name = env.RUNNER_NAME ?? `headless-${hostname3()}`;
|
|
54978
|
-
let stateFile = env.RUNNER_STATE_FILE ??
|
|
55244
|
+
let stateFile = env.RUNNER_STATE_FILE ?? path7.join(tmpdir2(), `rost-runner-${createHash2("sha1").update(appUrl2).digest("hex").slice(0, 8)}.json`);
|
|
54979
55245
|
let heartbeatMs = Number(env.RUNNER_HEARTBEAT_MS ?? 3e4);
|
|
54980
55246
|
let interactiveClaimMs = Number(env.RUNNER_INTERACTIVE_CLAIM_MS ?? 1e3);
|
|
54981
55247
|
let execute2 = env.RUNNER_EXECUTE === "1";
|
|
@@ -55026,7 +55292,7 @@ function parseServeArgs(args, appUrl2, env, homeDir) {
|
|
|
55026
55292
|
tmpDir: tmpdir2(),
|
|
55027
55293
|
homeDir,
|
|
55028
55294
|
stateFile,
|
|
55029
|
-
runnerBaseDir:
|
|
55295
|
+
runnerBaseDir: path7.join(homeDir, ".rost"),
|
|
55030
55296
|
allowNetwork: network.allowNetwork
|
|
55031
55297
|
});
|
|
55032
55298
|
return {
|
|
@@ -55132,7 +55398,7 @@ async function pairIfNeeded(client, fetchImpl, appUrl2, config2, io) {
|
|
|
55132
55398
|
}
|
|
55133
55399
|
async function loadState(filePath, expectedTenantId) {
|
|
55134
55400
|
try {
|
|
55135
|
-
const parsed = JSON.parse(await
|
|
55401
|
+
const parsed = JSON.parse(await readFile5(filePath, "utf8"));
|
|
55136
55402
|
if (typeof parsed.runner_id === "string" && typeof parsed.runner_secret === "string") {
|
|
55137
55403
|
if (expectedTenantId && parsed.tenant_id !== expectedTenantId) {
|
|
55138
55404
|
return null;
|
|
@@ -55163,10 +55429,10 @@ function isRuntimeSessionMap(value) {
|
|
|
55163
55429
|
});
|
|
55164
55430
|
}
|
|
55165
55431
|
async function saveState(filePath, state) {
|
|
55166
|
-
await
|
|
55432
|
+
await mkdir5(path7.dirname(filePath), { recursive: true, mode: 448 });
|
|
55167
55433
|
const tempPath = `${filePath}.${process.pid}.${createHash2("sha1").update(`${Date.now()}:${Math.random()}`).digest("hex").slice(0, 8)}.tmp`;
|
|
55168
55434
|
try {
|
|
55169
|
-
await
|
|
55435
|
+
await writeFile5(tempPath, `${JSON.stringify(state)}
|
|
55170
55436
|
`, { mode: 384 });
|
|
55171
55437
|
await chmod2(tempPath, 384);
|
|
55172
55438
|
await rename(tempPath, filePath);
|
|
@@ -55216,8 +55482,8 @@ function resolveSandboxKind(env, homeDir) {
|
|
|
55216
55482
|
workspaceDir: tmpdir2(),
|
|
55217
55483
|
tmpDir: tmpdir2(),
|
|
55218
55484
|
homeDir,
|
|
55219
|
-
stateFile:
|
|
55220
|
-
runnerBaseDir:
|
|
55485
|
+
stateFile: path7.join(tmpdir2(), "runner-sandbox-probe.json"),
|
|
55486
|
+
runnerBaseDir: path7.join(homeDir, ".rost"),
|
|
55221
55487
|
allowNetwork: resolveSandboxNetworkFlag(env) === "allow"
|
|
55222
55488
|
}).kind;
|
|
55223
55489
|
}
|
|
@@ -55316,9 +55582,9 @@ async function probeGhAuth() {
|
|
|
55316
55582
|
}
|
|
55317
55583
|
}
|
|
55318
55584
|
async function probeForgeDiskFreeMb(homeDir) {
|
|
55319
|
-
const dir =
|
|
55585
|
+
const dir = path7.join(homeDir, ".rost", "forge");
|
|
55320
55586
|
try {
|
|
55321
|
-
await
|
|
55587
|
+
await mkdir5(dir, { recursive: true, mode: 448 });
|
|
55322
55588
|
const stats = await statfs(dir);
|
|
55323
55589
|
return Math.floor(stats.bavail * stats.bsize / (1024 * 1024));
|
|
55324
55590
|
} catch {
|
|
@@ -55650,7 +55916,7 @@ async function prepareForgeTurn(ctx, workOrder, execution) {
|
|
|
55650
55916
|
let workspace;
|
|
55651
55917
|
try {
|
|
55652
55918
|
workspace = await prepareForgeWorkspace({
|
|
55653
|
-
baseDir:
|
|
55919
|
+
baseDir: path7.join(ctx.config.homeDir, ".rost", "forge", ctx.state.runner_id),
|
|
55654
55920
|
tenantId,
|
|
55655
55921
|
buildRequestId,
|
|
55656
55922
|
changeset: { id: buildRequestId, ordinal: 1, total: 1 },
|
|
@@ -55670,7 +55936,7 @@ async function prepareForgeTurn(ctx, workOrder, execution) {
|
|
|
55670
55936
|
tmpDir: tmpdir2(),
|
|
55671
55937
|
homeDir: ctx.config.homeDir,
|
|
55672
55938
|
stateFile: ctx.config.stateFile,
|
|
55673
|
-
runnerBaseDir:
|
|
55939
|
+
runnerBaseDir: path7.join(ctx.config.homeDir, ".rost"),
|
|
55674
55940
|
allowWritePaths: [workspace.baseRepo],
|
|
55675
55941
|
// Re-allow the shared object store for local commits, but DENY the model writing the
|
|
55676
55942
|
// repo's hook + config (and the worktree's gitdir pointer). The harness runs git
|
|
@@ -55678,9 +55944,9 @@ async function prepareForgeTurn(ctx, workOrder, execution) {
|
|
|
55678
55944
|
// hook or `ext::`/`insteadOf` config would otherwise exfiltrate it (DER-1327 review).
|
|
55679
55945
|
// `.git/{objects,refs,worktrees,logs,index,HEAD}` stay writable so the model can commit.
|
|
55680
55946
|
denyWritePaths: [
|
|
55681
|
-
`${
|
|
55682
|
-
|
|
55683
|
-
|
|
55947
|
+
`${path7.join(workspace.baseRepo, ".git", "hooks")}/`,
|
|
55948
|
+
path7.join(workspace.baseRepo, ".git", "config"),
|
|
55949
|
+
path7.join(workspace.worktreeDir, ".git")
|
|
55684
55950
|
],
|
|
55685
55951
|
allowNetwork: ctx.config.sandboxAllowNetwork
|
|
55686
55952
|
});
|
|
@@ -55699,7 +55965,7 @@ async function prepareForgeTurn(ctx, workOrder, execution) {
|
|
|
55699
55965
|
var FORGE_MAX_CHANGED_PATHS = 2e3;
|
|
55700
55966
|
var FORGE_MAX_CHANGED_PATH_LENGTH = 500;
|
|
55701
55967
|
function forgeChangedPathsField(changedPaths) {
|
|
55702
|
-
const withinCaps = changedPaths.length > 0 && changedPaths.length <= FORGE_MAX_CHANGED_PATHS && changedPaths.every((
|
|
55968
|
+
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
55969
|
return withinCaps ? { changedPaths: [...changedPaths] } : {};
|
|
55704
55970
|
}
|
|
55705
55971
|
async function finalizeForgeBuildPush(ctx, prep, result) {
|
|
@@ -55840,9 +56106,9 @@ async function spawnRunnerTurn(ctx, workOrder, runtime, kind) {
|
|
|
55840
56106
|
const token = typeof mcp.token === "string" ? mcp.token : "";
|
|
55841
56107
|
const url2 = typeof mcp.url === "string" ? `${ctx.appUrl.replace(/\/+$/, "")}${mcp.url}` : `${ctx.appUrl.replace(/\/+$/, "")}/mcp`;
|
|
55842
56108
|
const mcpConfig = JSON.stringify({ mcpServers: { rost: { type: "http", url: url2, headers: { Authorization: `Bearer ${token}` } } } });
|
|
55843
|
-
const configPath =
|
|
56109
|
+
const configPath = path7.join(tmpdir2(), `rost-runner-mcp-${createHash2("sha256").update(`${url2}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 16)}.json`);
|
|
55844
56110
|
const prompt = buildTurnPrompt({ kind, workOrder, execution, hasWorkspace: forgePrep !== null });
|
|
55845
|
-
await
|
|
56111
|
+
await writeFile5(configPath, `${mcpConfig}
|
|
55846
56112
|
`, { mode: 384 });
|
|
55847
56113
|
await chmod2(configPath, 384);
|
|
55848
56114
|
const resumeSessionId = runtime === "claude" ? getClaudeResumeSessionId(ctx.state, workOrder) : void 0;
|
|
@@ -55857,11 +56123,11 @@ async function spawnRunnerTurn(ctx, workOrder, runtime, kind) {
|
|
|
55857
56123
|
});
|
|
55858
56124
|
let sandboxProfilePath = null;
|
|
55859
56125
|
if (sandbox.kind === "seatbelt") {
|
|
55860
|
-
sandboxProfilePath =
|
|
56126
|
+
sandboxProfilePath = path7.join(
|
|
55861
56127
|
tmpdir2(),
|
|
55862
56128
|
`rost-runner-sandbox-${createHash2("sha256").update(`${configPath}:${Math.random()}`).digest("hex").slice(0, 16)}.sb`
|
|
55863
56129
|
);
|
|
55864
|
-
await
|
|
56130
|
+
await writeFile5(sandboxProfilePath, sandbox.profile, { mode: 384 });
|
|
55865
56131
|
await chmod2(sandboxProfilePath, 384);
|
|
55866
56132
|
}
|
|
55867
56133
|
const { command, args } = wrapCommandWithSandbox(sandbox, built.command, built.args, sandboxProfilePath);
|
|
@@ -55992,7 +56258,7 @@ async function resolveMergeConflictTurn(ctx, input) {
|
|
|
55992
56258
|
let workspace;
|
|
55993
56259
|
try {
|
|
55994
56260
|
workspace = await prepareMergeWorkspace({
|
|
55995
|
-
baseDir:
|
|
56261
|
+
baseDir: path7.join(ctx.config.homeDir, ".rost", "forge", ctx.state.runner_id),
|
|
55996
56262
|
tenantId,
|
|
55997
56263
|
buildRequestId: input.buildRequestId,
|
|
55998
56264
|
repo: input.repo,
|
|
@@ -56010,12 +56276,12 @@ async function resolveMergeConflictTurn(ctx, input) {
|
|
|
56010
56276
|
tmpDir: tmpdir2(),
|
|
56011
56277
|
homeDir: ctx.config.homeDir,
|
|
56012
56278
|
stateFile: ctx.config.stateFile,
|
|
56013
|
-
runnerBaseDir:
|
|
56279
|
+
runnerBaseDir: path7.join(ctx.config.homeDir, ".rost"),
|
|
56014
56280
|
allowWritePaths: [workspace.baseRepo],
|
|
56015
56281
|
denyWritePaths: [
|
|
56016
|
-
`${
|
|
56017
|
-
|
|
56018
|
-
|
|
56282
|
+
`${path7.join(workspace.baseRepo, ".git", "hooks")}/`,
|
|
56283
|
+
path7.join(workspace.baseRepo, ".git", "config"),
|
|
56284
|
+
path7.join(workspace.worktreeDir, ".git")
|
|
56019
56285
|
],
|
|
56020
56286
|
allowNetwork: ctx.config.sandboxAllowNetwork
|
|
56021
56287
|
});
|
|
@@ -56045,8 +56311,8 @@ async function spawnMergeConflictModel(ctx, input) {
|
|
|
56045
56311
|
const token = typeof mcp.token === "string" ? mcp.token : "";
|
|
56046
56312
|
const url2 = typeof mcp.url === "string" ? `${ctx.appUrl.replace(/\/+$/, "")}${mcp.url}` : `${ctx.appUrl.replace(/\/+$/, "")}/mcp`;
|
|
56047
56313
|
const mcpConfig = JSON.stringify({ mcpServers: { rost: { type: "http", url: url2, headers: { Authorization: `Bearer ${token}` } } } });
|
|
56048
|
-
const configPath =
|
|
56049
|
-
await
|
|
56314
|
+
const configPath = path7.join(tmpdir2(), `rost-runner-mcp-${createHash2("sha256").update(`${url2}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 16)}.json`);
|
|
56315
|
+
await writeFile5(configPath, `${mcpConfig}
|
|
56050
56316
|
`, { mode: 384 });
|
|
56051
56317
|
await chmod2(configPath, 384);
|
|
56052
56318
|
const plan = resolveTurnPlan({ kind: "work_order", execution: input.execution, repoDir: input.workspace.worktreeDir });
|
|
@@ -56058,8 +56324,8 @@ async function spawnMergeConflictModel(ctx, input) {
|
|
|
56058
56324
|
].join("\n");
|
|
56059
56325
|
let sandboxProfilePath = null;
|
|
56060
56326
|
if (input.sandbox.kind === "seatbelt") {
|
|
56061
|
-
sandboxProfilePath =
|
|
56062
|
-
await
|
|
56327
|
+
sandboxProfilePath = path7.join(tmpdir2(), `rost-runner-sandbox-${createHash2("sha256").update(`${configPath}:${Math.random()}`).digest("hex").slice(0, 16)}.sb`);
|
|
56328
|
+
await writeFile5(sandboxProfilePath, input.sandbox.profile, { mode: 384 });
|
|
56063
56329
|
await chmod2(sandboxProfilePath, 384);
|
|
56064
56330
|
}
|
|
56065
56331
|
const built = buildTurnCommand({
|