@alessandroraffa/tangyr 4.0.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1034 -641
- package/mappings/platform-paths.yaml +24 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1372,8 +1372,8 @@ var require_command = __commonJS({
|
|
|
1372
1372
|
"use strict";
|
|
1373
1373
|
var EventEmitter = __require("events").EventEmitter;
|
|
1374
1374
|
var childProcess = __require("child_process");
|
|
1375
|
-
var
|
|
1376
|
-
var
|
|
1375
|
+
var path53 = __require("path");
|
|
1376
|
+
var fs52 = __require("fs");
|
|
1377
1377
|
var process5 = __require("process");
|
|
1378
1378
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
1379
1379
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -2367,7 +2367,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2367
2367
|
* @param {string} subcommandName
|
|
2368
2368
|
*/
|
|
2369
2369
|
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
2370
|
-
if (
|
|
2370
|
+
if (fs52.existsSync(executableFile)) return;
|
|
2371
2371
|
const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
|
|
2372
2372
|
const executableMissing = `'${executableFile}' does not exist
|
|
2373
2373
|
- if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
@@ -2385,11 +2385,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2385
2385
|
let launchWithNode = false;
|
|
2386
2386
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
2387
2387
|
function findFile(baseDir, baseName) {
|
|
2388
|
-
const localBin =
|
|
2389
|
-
if (
|
|
2390
|
-
if (sourceExt.includes(
|
|
2388
|
+
const localBin = path53.resolve(baseDir, baseName);
|
|
2389
|
+
if (fs52.existsSync(localBin)) return localBin;
|
|
2390
|
+
if (sourceExt.includes(path53.extname(baseName))) return void 0;
|
|
2391
2391
|
const foundExt = sourceExt.find(
|
|
2392
|
-
(ext) =>
|
|
2392
|
+
(ext) => fs52.existsSync(`${localBin}${ext}`)
|
|
2393
2393
|
);
|
|
2394
2394
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
2395
2395
|
return void 0;
|
|
@@ -2401,21 +2401,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2401
2401
|
if (this._scriptPath) {
|
|
2402
2402
|
let resolvedScriptPath;
|
|
2403
2403
|
try {
|
|
2404
|
-
resolvedScriptPath =
|
|
2404
|
+
resolvedScriptPath = fs52.realpathSync(this._scriptPath);
|
|
2405
2405
|
} catch {
|
|
2406
2406
|
resolvedScriptPath = this._scriptPath;
|
|
2407
2407
|
}
|
|
2408
|
-
executableDir =
|
|
2409
|
-
|
|
2408
|
+
executableDir = path53.resolve(
|
|
2409
|
+
path53.dirname(resolvedScriptPath),
|
|
2410
2410
|
executableDir
|
|
2411
2411
|
);
|
|
2412
2412
|
}
|
|
2413
2413
|
if (executableDir) {
|
|
2414
2414
|
let localFile = findFile(executableDir, executableFile);
|
|
2415
2415
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
2416
|
-
const legacyName =
|
|
2416
|
+
const legacyName = path53.basename(
|
|
2417
2417
|
this._scriptPath,
|
|
2418
|
-
|
|
2418
|
+
path53.extname(this._scriptPath)
|
|
2419
2419
|
);
|
|
2420
2420
|
if (legacyName !== this._name) {
|
|
2421
2421
|
localFile = findFile(
|
|
@@ -2426,7 +2426,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2426
2426
|
}
|
|
2427
2427
|
executableFile = localFile || executableFile;
|
|
2428
2428
|
}
|
|
2429
|
-
launchWithNode = sourceExt.includes(
|
|
2429
|
+
launchWithNode = sourceExt.includes(path53.extname(executableFile));
|
|
2430
2430
|
let proc;
|
|
2431
2431
|
if (process5.platform !== "win32") {
|
|
2432
2432
|
if (launchWithNode) {
|
|
@@ -3341,7 +3341,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3341
3341
|
* @return {Command}
|
|
3342
3342
|
*/
|
|
3343
3343
|
nameFromFilename(filename) {
|
|
3344
|
-
this._name =
|
|
3344
|
+
this._name = path53.basename(filename, path53.extname(filename));
|
|
3345
3345
|
return this;
|
|
3346
3346
|
}
|
|
3347
3347
|
/**
|
|
@@ -3355,9 +3355,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3355
3355
|
* @param {string} [path]
|
|
3356
3356
|
* @return {(string|null|Command)}
|
|
3357
3357
|
*/
|
|
3358
|
-
executableDir(
|
|
3359
|
-
if (
|
|
3360
|
-
this._executableDir =
|
|
3358
|
+
executableDir(path54) {
|
|
3359
|
+
if (path54 === void 0) return this._executableDir;
|
|
3360
|
+
this._executableDir = path54;
|
|
3361
3361
|
return this;
|
|
3362
3362
|
}
|
|
3363
3363
|
/**
|
|
@@ -3713,17 +3713,17 @@ var require_visit = __commonJS({
|
|
|
3713
3713
|
visit.BREAK = BREAK;
|
|
3714
3714
|
visit.SKIP = SKIP;
|
|
3715
3715
|
visit.REMOVE = REMOVE;
|
|
3716
|
-
function visit_(key, node, visitor,
|
|
3717
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
3716
|
+
function visit_(key, node, visitor, path53) {
|
|
3717
|
+
const ctrl = callVisitor(key, node, visitor, path53);
|
|
3718
3718
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
3719
|
-
replaceNode(key,
|
|
3720
|
-
return visit_(key, ctrl, visitor,
|
|
3719
|
+
replaceNode(key, path53, ctrl);
|
|
3720
|
+
return visit_(key, ctrl, visitor, path53);
|
|
3721
3721
|
}
|
|
3722
3722
|
if (typeof ctrl !== "symbol") {
|
|
3723
3723
|
if (identity.isCollection(node)) {
|
|
3724
|
-
|
|
3724
|
+
path53 = Object.freeze(path53.concat(node));
|
|
3725
3725
|
for (let i = 0; i < node.items.length; ++i) {
|
|
3726
|
-
const ci2 = visit_(i, node.items[i], visitor,
|
|
3726
|
+
const ci2 = visit_(i, node.items[i], visitor, path53);
|
|
3727
3727
|
if (typeof ci2 === "number")
|
|
3728
3728
|
i = ci2 - 1;
|
|
3729
3729
|
else if (ci2 === BREAK)
|
|
@@ -3734,13 +3734,13 @@ var require_visit = __commonJS({
|
|
|
3734
3734
|
}
|
|
3735
3735
|
}
|
|
3736
3736
|
} else if (identity.isPair(node)) {
|
|
3737
|
-
|
|
3738
|
-
const ck = visit_("key", node.key, visitor,
|
|
3737
|
+
path53 = Object.freeze(path53.concat(node));
|
|
3738
|
+
const ck = visit_("key", node.key, visitor, path53);
|
|
3739
3739
|
if (ck === BREAK)
|
|
3740
3740
|
return BREAK;
|
|
3741
3741
|
else if (ck === REMOVE)
|
|
3742
3742
|
node.key = null;
|
|
3743
|
-
const cv = visit_("value", node.value, visitor,
|
|
3743
|
+
const cv = visit_("value", node.value, visitor, path53);
|
|
3744
3744
|
if (cv === BREAK)
|
|
3745
3745
|
return BREAK;
|
|
3746
3746
|
else if (cv === REMOVE)
|
|
@@ -3761,17 +3761,17 @@ var require_visit = __commonJS({
|
|
|
3761
3761
|
visitAsync.BREAK = BREAK;
|
|
3762
3762
|
visitAsync.SKIP = SKIP;
|
|
3763
3763
|
visitAsync.REMOVE = REMOVE;
|
|
3764
|
-
async function visitAsync_(key, node, visitor,
|
|
3765
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
3764
|
+
async function visitAsync_(key, node, visitor, path53) {
|
|
3765
|
+
const ctrl = await callVisitor(key, node, visitor, path53);
|
|
3766
3766
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
3767
|
-
replaceNode(key,
|
|
3768
|
-
return visitAsync_(key, ctrl, visitor,
|
|
3767
|
+
replaceNode(key, path53, ctrl);
|
|
3768
|
+
return visitAsync_(key, ctrl, visitor, path53);
|
|
3769
3769
|
}
|
|
3770
3770
|
if (typeof ctrl !== "symbol") {
|
|
3771
3771
|
if (identity.isCollection(node)) {
|
|
3772
|
-
|
|
3772
|
+
path53 = Object.freeze(path53.concat(node));
|
|
3773
3773
|
for (let i = 0; i < node.items.length; ++i) {
|
|
3774
|
-
const ci2 = await visitAsync_(i, node.items[i], visitor,
|
|
3774
|
+
const ci2 = await visitAsync_(i, node.items[i], visitor, path53);
|
|
3775
3775
|
if (typeof ci2 === "number")
|
|
3776
3776
|
i = ci2 - 1;
|
|
3777
3777
|
else if (ci2 === BREAK)
|
|
@@ -3782,13 +3782,13 @@ var require_visit = __commonJS({
|
|
|
3782
3782
|
}
|
|
3783
3783
|
}
|
|
3784
3784
|
} else if (identity.isPair(node)) {
|
|
3785
|
-
|
|
3786
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
3785
|
+
path53 = Object.freeze(path53.concat(node));
|
|
3786
|
+
const ck = await visitAsync_("key", node.key, visitor, path53);
|
|
3787
3787
|
if (ck === BREAK)
|
|
3788
3788
|
return BREAK;
|
|
3789
3789
|
else if (ck === REMOVE)
|
|
3790
3790
|
node.key = null;
|
|
3791
|
-
const cv = await visitAsync_("value", node.value, visitor,
|
|
3791
|
+
const cv = await visitAsync_("value", node.value, visitor, path53);
|
|
3792
3792
|
if (cv === BREAK)
|
|
3793
3793
|
return BREAK;
|
|
3794
3794
|
else if (cv === REMOVE)
|
|
@@ -3815,23 +3815,23 @@ var require_visit = __commonJS({
|
|
|
3815
3815
|
}
|
|
3816
3816
|
return visitor;
|
|
3817
3817
|
}
|
|
3818
|
-
function callVisitor(key, node, visitor,
|
|
3818
|
+
function callVisitor(key, node, visitor, path53) {
|
|
3819
3819
|
if (typeof visitor === "function")
|
|
3820
|
-
return visitor(key, node,
|
|
3820
|
+
return visitor(key, node, path53);
|
|
3821
3821
|
if (identity.isMap(node))
|
|
3822
|
-
return visitor.Map?.(key, node,
|
|
3822
|
+
return visitor.Map?.(key, node, path53);
|
|
3823
3823
|
if (identity.isSeq(node))
|
|
3824
|
-
return visitor.Seq?.(key, node,
|
|
3824
|
+
return visitor.Seq?.(key, node, path53);
|
|
3825
3825
|
if (identity.isPair(node))
|
|
3826
|
-
return visitor.Pair?.(key, node,
|
|
3826
|
+
return visitor.Pair?.(key, node, path53);
|
|
3827
3827
|
if (identity.isScalar(node))
|
|
3828
|
-
return visitor.Scalar?.(key, node,
|
|
3828
|
+
return visitor.Scalar?.(key, node, path53);
|
|
3829
3829
|
if (identity.isAlias(node))
|
|
3830
|
-
return visitor.Alias?.(key, node,
|
|
3830
|
+
return visitor.Alias?.(key, node, path53);
|
|
3831
3831
|
return void 0;
|
|
3832
3832
|
}
|
|
3833
|
-
function replaceNode(key,
|
|
3834
|
-
const parent =
|
|
3833
|
+
function replaceNode(key, path53, node) {
|
|
3834
|
+
const parent = path53[path53.length - 1];
|
|
3835
3835
|
if (identity.isCollection(parent)) {
|
|
3836
3836
|
parent.items[key] = node;
|
|
3837
3837
|
} else if (identity.isPair(parent)) {
|
|
@@ -4439,10 +4439,10 @@ var require_Collection = __commonJS({
|
|
|
4439
4439
|
var createNode = require_createNode();
|
|
4440
4440
|
var identity = require_identity();
|
|
4441
4441
|
var Node = require_Node();
|
|
4442
|
-
function collectionFromPath(schema,
|
|
4442
|
+
function collectionFromPath(schema, path53, value) {
|
|
4443
4443
|
let v2 = value;
|
|
4444
|
-
for (let i =
|
|
4445
|
-
const k2 =
|
|
4444
|
+
for (let i = path53.length - 1; i >= 0; --i) {
|
|
4445
|
+
const k2 = path53[i];
|
|
4446
4446
|
if (typeof k2 === "number" && Number.isInteger(k2) && k2 >= 0) {
|
|
4447
4447
|
const a = [];
|
|
4448
4448
|
a[k2] = v2;
|
|
@@ -4461,7 +4461,7 @@ var require_Collection = __commonJS({
|
|
|
4461
4461
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
4462
4462
|
});
|
|
4463
4463
|
}
|
|
4464
|
-
var isEmptyPath = (
|
|
4464
|
+
var isEmptyPath = (path53) => path53 == null || typeof path53 === "object" && !!path53[Symbol.iterator]().next().done;
|
|
4465
4465
|
var Collection = class extends Node.NodeBase {
|
|
4466
4466
|
constructor(type, schema) {
|
|
4467
4467
|
super(type);
|
|
@@ -4491,11 +4491,11 @@ var require_Collection = __commonJS({
|
|
|
4491
4491
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
4492
4492
|
* that already exists in the map.
|
|
4493
4493
|
*/
|
|
4494
|
-
addIn(
|
|
4495
|
-
if (isEmptyPath(
|
|
4494
|
+
addIn(path53, value) {
|
|
4495
|
+
if (isEmptyPath(path53))
|
|
4496
4496
|
this.add(value);
|
|
4497
4497
|
else {
|
|
4498
|
-
const [key, ...rest] =
|
|
4498
|
+
const [key, ...rest] = path53;
|
|
4499
4499
|
const node = this.get(key, true);
|
|
4500
4500
|
if (identity.isCollection(node))
|
|
4501
4501
|
node.addIn(rest, value);
|
|
@@ -4509,8 +4509,8 @@ var require_Collection = __commonJS({
|
|
|
4509
4509
|
* Removes a value from the collection.
|
|
4510
4510
|
* @returns `true` if the item was found and removed.
|
|
4511
4511
|
*/
|
|
4512
|
-
deleteIn(
|
|
4513
|
-
const [key, ...rest] =
|
|
4512
|
+
deleteIn(path53) {
|
|
4513
|
+
const [key, ...rest] = path53;
|
|
4514
4514
|
if (rest.length === 0)
|
|
4515
4515
|
return this.delete(key);
|
|
4516
4516
|
const node = this.get(key, true);
|
|
@@ -4524,8 +4524,8 @@ var require_Collection = __commonJS({
|
|
|
4524
4524
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
4525
4525
|
* `true` (collections are always returned intact).
|
|
4526
4526
|
*/
|
|
4527
|
-
getIn(
|
|
4528
|
-
const [key, ...rest] =
|
|
4527
|
+
getIn(path53, keepScalar) {
|
|
4528
|
+
const [key, ...rest] = path53;
|
|
4529
4529
|
const node = this.get(key, true);
|
|
4530
4530
|
if (rest.length === 0)
|
|
4531
4531
|
return !keepScalar && identity.isScalar(node) ? node.value : node;
|
|
@@ -4543,8 +4543,8 @@ var require_Collection = __commonJS({
|
|
|
4543
4543
|
/**
|
|
4544
4544
|
* Checks if the collection includes a value with the key `key`.
|
|
4545
4545
|
*/
|
|
4546
|
-
hasIn(
|
|
4547
|
-
const [key, ...rest] =
|
|
4546
|
+
hasIn(path53) {
|
|
4547
|
+
const [key, ...rest] = path53;
|
|
4548
4548
|
if (rest.length === 0)
|
|
4549
4549
|
return this.has(key);
|
|
4550
4550
|
const node = this.get(key, true);
|
|
@@ -4554,8 +4554,8 @@ var require_Collection = __commonJS({
|
|
|
4554
4554
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
4555
4555
|
* boolean to add/remove the item from the set.
|
|
4556
4556
|
*/
|
|
4557
|
-
setIn(
|
|
4558
|
-
const [key, ...rest] =
|
|
4557
|
+
setIn(path53, value) {
|
|
4558
|
+
const [key, ...rest] = path53;
|
|
4559
4559
|
if (rest.length === 0) {
|
|
4560
4560
|
this.set(key, value);
|
|
4561
4561
|
} else {
|
|
@@ -7067,9 +7067,9 @@ var require_Document = __commonJS({
|
|
|
7067
7067
|
this.contents.add(value);
|
|
7068
7068
|
}
|
|
7069
7069
|
/** Adds a value to the document. */
|
|
7070
|
-
addIn(
|
|
7070
|
+
addIn(path53, value) {
|
|
7071
7071
|
if (assertCollection(this.contents))
|
|
7072
|
-
this.contents.addIn(
|
|
7072
|
+
this.contents.addIn(path53, value);
|
|
7073
7073
|
}
|
|
7074
7074
|
/**
|
|
7075
7075
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -7144,14 +7144,14 @@ var require_Document = __commonJS({
|
|
|
7144
7144
|
* Removes a value from the document.
|
|
7145
7145
|
* @returns `true` if the item was found and removed.
|
|
7146
7146
|
*/
|
|
7147
|
-
deleteIn(
|
|
7148
|
-
if (Collection.isEmptyPath(
|
|
7147
|
+
deleteIn(path53) {
|
|
7148
|
+
if (Collection.isEmptyPath(path53)) {
|
|
7149
7149
|
if (this.contents == null)
|
|
7150
7150
|
return false;
|
|
7151
7151
|
this.contents = null;
|
|
7152
7152
|
return true;
|
|
7153
7153
|
}
|
|
7154
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
7154
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path53) : false;
|
|
7155
7155
|
}
|
|
7156
7156
|
/**
|
|
7157
7157
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -7166,10 +7166,10 @@ var require_Document = __commonJS({
|
|
|
7166
7166
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
7167
7167
|
* `true` (collections are always returned intact).
|
|
7168
7168
|
*/
|
|
7169
|
-
getIn(
|
|
7170
|
-
if (Collection.isEmptyPath(
|
|
7169
|
+
getIn(path53, keepScalar) {
|
|
7170
|
+
if (Collection.isEmptyPath(path53))
|
|
7171
7171
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
7172
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
7172
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path53, keepScalar) : void 0;
|
|
7173
7173
|
}
|
|
7174
7174
|
/**
|
|
7175
7175
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -7180,10 +7180,10 @@ var require_Document = __commonJS({
|
|
|
7180
7180
|
/**
|
|
7181
7181
|
* Checks if the document includes a value at `path`.
|
|
7182
7182
|
*/
|
|
7183
|
-
hasIn(
|
|
7184
|
-
if (Collection.isEmptyPath(
|
|
7183
|
+
hasIn(path53) {
|
|
7184
|
+
if (Collection.isEmptyPath(path53))
|
|
7185
7185
|
return this.contents !== void 0;
|
|
7186
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
7186
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path53) : false;
|
|
7187
7187
|
}
|
|
7188
7188
|
/**
|
|
7189
7189
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -7200,13 +7200,13 @@ var require_Document = __commonJS({
|
|
|
7200
7200
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
7201
7201
|
* boolean to add/remove the item from the set.
|
|
7202
7202
|
*/
|
|
7203
|
-
setIn(
|
|
7204
|
-
if (Collection.isEmptyPath(
|
|
7203
|
+
setIn(path53, value) {
|
|
7204
|
+
if (Collection.isEmptyPath(path53)) {
|
|
7205
7205
|
this.contents = value;
|
|
7206
7206
|
} else if (this.contents == null) {
|
|
7207
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
7207
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path53), value);
|
|
7208
7208
|
} else if (assertCollection(this.contents)) {
|
|
7209
|
-
this.contents.setIn(
|
|
7209
|
+
this.contents.setIn(path53, value);
|
|
7210
7210
|
}
|
|
7211
7211
|
}
|
|
7212
7212
|
/**
|
|
@@ -9163,9 +9163,9 @@ var require_cst_visit = __commonJS({
|
|
|
9163
9163
|
visit.BREAK = BREAK;
|
|
9164
9164
|
visit.SKIP = SKIP;
|
|
9165
9165
|
visit.REMOVE = REMOVE;
|
|
9166
|
-
visit.itemAtPath = (cst,
|
|
9166
|
+
visit.itemAtPath = (cst, path53) => {
|
|
9167
9167
|
let item = cst;
|
|
9168
|
-
for (const [field, index] of
|
|
9168
|
+
for (const [field, index] of path53) {
|
|
9169
9169
|
const tok = item?.[field];
|
|
9170
9170
|
if (tok && "items" in tok) {
|
|
9171
9171
|
item = tok.items[index];
|
|
@@ -9174,23 +9174,23 @@ var require_cst_visit = __commonJS({
|
|
|
9174
9174
|
}
|
|
9175
9175
|
return item;
|
|
9176
9176
|
};
|
|
9177
|
-
visit.parentCollection = (cst,
|
|
9178
|
-
const parent = visit.itemAtPath(cst,
|
|
9179
|
-
const field =
|
|
9177
|
+
visit.parentCollection = (cst, path53) => {
|
|
9178
|
+
const parent = visit.itemAtPath(cst, path53.slice(0, -1));
|
|
9179
|
+
const field = path53[path53.length - 1][0];
|
|
9180
9180
|
const coll = parent?.[field];
|
|
9181
9181
|
if (coll && "items" in coll)
|
|
9182
9182
|
return coll;
|
|
9183
9183
|
throw new Error("Parent collection not found");
|
|
9184
9184
|
};
|
|
9185
|
-
function _visit(
|
|
9186
|
-
let ctrl = visitor(item,
|
|
9185
|
+
function _visit(path53, item, visitor) {
|
|
9186
|
+
let ctrl = visitor(item, path53);
|
|
9187
9187
|
if (typeof ctrl === "symbol")
|
|
9188
9188
|
return ctrl;
|
|
9189
9189
|
for (const field of ["key", "value"]) {
|
|
9190
9190
|
const token = item[field];
|
|
9191
9191
|
if (token && "items" in token) {
|
|
9192
9192
|
for (let i = 0; i < token.items.length; ++i) {
|
|
9193
|
-
const ci2 = _visit(Object.freeze(
|
|
9193
|
+
const ci2 = _visit(Object.freeze(path53.concat([[field, i]])), token.items[i], visitor);
|
|
9194
9194
|
if (typeof ci2 === "number")
|
|
9195
9195
|
i = ci2 - 1;
|
|
9196
9196
|
else if (ci2 === BREAK)
|
|
@@ -9201,10 +9201,10 @@ var require_cst_visit = __commonJS({
|
|
|
9201
9201
|
}
|
|
9202
9202
|
}
|
|
9203
9203
|
if (typeof ctrl === "function" && field === "key")
|
|
9204
|
-
ctrl = ctrl(item,
|
|
9204
|
+
ctrl = ctrl(item, path53);
|
|
9205
9205
|
}
|
|
9206
9206
|
}
|
|
9207
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
9207
|
+
return typeof ctrl === "function" ? ctrl(item, path53) : ctrl;
|
|
9208
9208
|
}
|
|
9209
9209
|
exports2.visit = visit;
|
|
9210
9210
|
}
|
|
@@ -10489,14 +10489,14 @@ var require_parser = __commonJS({
|
|
|
10489
10489
|
case "scalar":
|
|
10490
10490
|
case "single-quoted-scalar":
|
|
10491
10491
|
case "double-quoted-scalar": {
|
|
10492
|
-
const
|
|
10492
|
+
const fs52 = this.flowScalar(this.type);
|
|
10493
10493
|
if (atNextItem || it2.value) {
|
|
10494
|
-
map.items.push({ start, key:
|
|
10494
|
+
map.items.push({ start, key: fs52, sep: [] });
|
|
10495
10495
|
this.onKeyLine = true;
|
|
10496
10496
|
} else if (it2.sep) {
|
|
10497
|
-
this.stack.push(
|
|
10497
|
+
this.stack.push(fs52);
|
|
10498
10498
|
} else {
|
|
10499
|
-
Object.assign(it2, { key:
|
|
10499
|
+
Object.assign(it2, { key: fs52, sep: [] });
|
|
10500
10500
|
this.onKeyLine = true;
|
|
10501
10501
|
}
|
|
10502
10502
|
return;
|
|
@@ -10624,13 +10624,13 @@ var require_parser = __commonJS({
|
|
|
10624
10624
|
case "scalar":
|
|
10625
10625
|
case "single-quoted-scalar":
|
|
10626
10626
|
case "double-quoted-scalar": {
|
|
10627
|
-
const
|
|
10627
|
+
const fs52 = this.flowScalar(this.type);
|
|
10628
10628
|
if (!it2 || it2.value)
|
|
10629
|
-
fc.items.push({ start: [], key:
|
|
10629
|
+
fc.items.push({ start: [], key: fs52, sep: [] });
|
|
10630
10630
|
else if (it2.sep)
|
|
10631
|
-
this.stack.push(
|
|
10631
|
+
this.stack.push(fs52);
|
|
10632
10632
|
else
|
|
10633
|
-
Object.assign(it2, { key:
|
|
10633
|
+
Object.assign(it2, { key: fs52, sep: [] });
|
|
10634
10634
|
return;
|
|
10635
10635
|
}
|
|
10636
10636
|
case "flow-map-end":
|
|
@@ -16497,7 +16497,10 @@ function resolveCopilotProfile(scope, projectRoot, mappings) {
|
|
|
16497
16497
|
hooks: r(slotMap, "hooks"),
|
|
16498
16498
|
hook_scripts: r(slotMap, "hook_scripts"),
|
|
16499
16499
|
mcp_shared_file: r(slotMap, "mcp_shared_file"),
|
|
16500
|
-
instructions
|
|
16500
|
+
instructions,
|
|
16501
|
+
// Project-only, like instructions: `.github/instructions` is a repository
|
|
16502
|
+
// surface and has no user-level equivalent Copilot documents.
|
|
16503
|
+
rules: r(slotMap, "rules")
|
|
16501
16504
|
};
|
|
16502
16505
|
}
|
|
16503
16506
|
function resolveCodexProfile(scope, projectRoot, mappings) {
|
|
@@ -21988,7 +21991,7 @@ function reportHooksSourceConflict(report, targets, hooksDir, hookNames) {
|
|
|
21988
21991
|
|
|
21989
21992
|
// src/adapters/hook-scripts-bridge.ts
|
|
21990
21993
|
import fs25 from "fs";
|
|
21991
|
-
import
|
|
21994
|
+
import path23 from "path";
|
|
21992
21995
|
|
|
21993
21996
|
// src/utils/fs.ts
|
|
21994
21997
|
import fs23 from "fs";
|
|
@@ -22118,8 +22121,62 @@ function compareArtifactState(recorded, artifactPath) {
|
|
|
22118
22121
|
return current === recorded ? "current" : "modified";
|
|
22119
22122
|
}
|
|
22120
22123
|
|
|
22124
|
+
// src/core/shared-artifacts.ts
|
|
22125
|
+
import path22 from "path";
|
|
22126
|
+
var SHARED_NAMESPACE = "shared";
|
|
22127
|
+
var SHARED_INSTRUCTIONS_KEY = `${SHARED_NAMESPACE}/AGENTS.md`;
|
|
22128
|
+
var SHARED_INSTRUCTIONS_FILE = "AGENTS.md";
|
|
22129
|
+
var SHARED_HOOK_SCRIPTS_KEY = `${SHARED_NAMESPACE}/hook_scripts`;
|
|
22130
|
+
function sharedArtifactKey(destination, scope, projectRoot) {
|
|
22131
|
+
if (scope !== "project") {
|
|
22132
|
+
return null;
|
|
22133
|
+
}
|
|
22134
|
+
const root = projectRoot ?? process.cwd();
|
|
22135
|
+
const shared = path22.resolve(root, SHARED_INSTRUCTIONS_FILE);
|
|
22136
|
+
return path22.resolve(destination) === shared ? SHARED_INSTRUCTIONS_KEY : null;
|
|
22137
|
+
}
|
|
22138
|
+
function resolveSharedArtifactKey(key, scope, projectRoot) {
|
|
22139
|
+
if (key !== SHARED_INSTRUCTIONS_KEY || scope !== "project") {
|
|
22140
|
+
return null;
|
|
22141
|
+
}
|
|
22142
|
+
return path22.join(projectRoot ?? process.cwd(), SHARED_INSTRUCTIONS_FILE);
|
|
22143
|
+
}
|
|
22144
|
+
var SHARED_SKILLS_PREFIX = `${SHARED_NAMESPACE}/skills`;
|
|
22145
|
+
function sharedKeyForDestination(destination, scope, projectRoot, platformPaths) {
|
|
22146
|
+
const instructions = sharedArtifactKey(destination, scope, projectRoot);
|
|
22147
|
+
if (instructions) {
|
|
22148
|
+
return instructions;
|
|
22149
|
+
}
|
|
22150
|
+
const resolved = path22.resolve(destination);
|
|
22151
|
+
let profiles;
|
|
22152
|
+
try {
|
|
22153
|
+
profiles = resolveTargetPaths({
|
|
22154
|
+
scope,
|
|
22155
|
+
projectRoot,
|
|
22156
|
+
mappings: platformPaths
|
|
22157
|
+
});
|
|
22158
|
+
} catch {
|
|
22159
|
+
return null;
|
|
22160
|
+
}
|
|
22161
|
+
if (resolved === path22.resolve(profiles.codex.hook_scripts)) {
|
|
22162
|
+
return SHARED_HOOK_SCRIPTS_KEY;
|
|
22163
|
+
}
|
|
22164
|
+
const skillsRoot = path22.resolve(profiles.opencode.skills_shared);
|
|
22165
|
+
if (resolved.startsWith(`${skillsRoot}${path22.sep}`)) {
|
|
22166
|
+
const inside = path22.relative(skillsRoot, resolved).split(path22.sep).join("/");
|
|
22167
|
+
return `${SHARED_SKILLS_PREFIX}/${inside}`;
|
|
22168
|
+
}
|
|
22169
|
+
return null;
|
|
22170
|
+
}
|
|
22171
|
+
function resolveSharedSkillsKey(key, sharedSkillsRoot) {
|
|
22172
|
+
if (!key.startsWith(`${SHARED_SKILLS_PREFIX}/`) || !sharedSkillsRoot) {
|
|
22173
|
+
return null;
|
|
22174
|
+
}
|
|
22175
|
+
const inside = key.slice(SHARED_SKILLS_PREFIX.length + 1);
|
|
22176
|
+
return path22.join(sharedSkillsRoot, ...inside.split("/"));
|
|
22177
|
+
}
|
|
22178
|
+
|
|
22121
22179
|
// src/adapters/hook-scripts-bridge.ts
|
|
22122
|
-
var SHARED_HOOK_SCRIPTS_KEY = "shared/hook_scripts";
|
|
22123
22180
|
function syncHookScriptsBridge(args) {
|
|
22124
22181
|
const { source, destination, config, sourceRoot, options, logger } = args;
|
|
22125
22182
|
if (!fs25.existsSync(source)) {
|
|
@@ -22144,7 +22201,7 @@ function syncHookScriptsBridge(args) {
|
|
|
22144
22201
|
} else if (artifactClass === "managed-symlink") {
|
|
22145
22202
|
fs25.unlinkSync(destination);
|
|
22146
22203
|
}
|
|
22147
|
-
ensureDir(
|
|
22204
|
+
ensureDir(path23.dirname(destination));
|
|
22148
22205
|
createRelativeSymlink(source, destination, "dir");
|
|
22149
22206
|
if (args.manifest) {
|
|
22150
22207
|
const state = describeArtifactState(destination);
|
|
@@ -22173,26 +22230,6 @@ function isSymlinkTo(linkPath, source) {
|
|
|
22173
22230
|
}
|
|
22174
22231
|
}
|
|
22175
22232
|
|
|
22176
|
-
// src/core/shared-artifacts.ts
|
|
22177
|
-
import path23 from "path";
|
|
22178
|
-
var SHARED_NAMESPACE = "shared";
|
|
22179
|
-
var SHARED_INSTRUCTIONS_KEY = `${SHARED_NAMESPACE}/AGENTS.md`;
|
|
22180
|
-
var SHARED_INSTRUCTIONS_FILE = "AGENTS.md";
|
|
22181
|
-
function sharedArtifactKey(destination, scope, projectRoot) {
|
|
22182
|
-
if (scope !== "project") {
|
|
22183
|
-
return null;
|
|
22184
|
-
}
|
|
22185
|
-
const root = projectRoot ?? process.cwd();
|
|
22186
|
-
const shared = path23.resolve(root, SHARED_INSTRUCTIONS_FILE);
|
|
22187
|
-
return path23.resolve(destination) === shared ? SHARED_INSTRUCTIONS_KEY : null;
|
|
22188
|
-
}
|
|
22189
|
-
function resolveSharedArtifactKey(key, scope, projectRoot) {
|
|
22190
|
-
if (key !== SHARED_INSTRUCTIONS_KEY || scope !== "project") {
|
|
22191
|
-
return null;
|
|
22192
|
-
}
|
|
22193
|
-
return path23.join(projectRoot ?? process.cwd(), SHARED_INSTRUCTIONS_FILE);
|
|
22194
|
-
}
|
|
22195
|
-
|
|
22196
22233
|
// src/core/remove.ts
|
|
22197
22234
|
import fs26 from "fs";
|
|
22198
22235
|
function removeManagedPath(managedPath) {
|
|
@@ -22313,6 +22350,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
22313
22350
|
const claudeRoots = scope === "global" && selectedTools.has("claude-code") ? resolveClaudeRootsForUninstall(manifest, runtime) : [];
|
|
22314
22351
|
let removedCount = 0;
|
|
22315
22352
|
const removedParentDirs = /* @__PURE__ */ new Set();
|
|
22353
|
+
const keptSurfaces = [];
|
|
22316
22354
|
for (const file of useManifestPathRemoval ? manifestArtifacts : []) {
|
|
22317
22355
|
if (isMergeSurfaceKey(file.relativePath)) {
|
|
22318
22356
|
const surfacePath = file.path ?? resolveManifestKeyToPath(
|
|
@@ -22324,6 +22362,9 @@ async function runUninstallCommand(options, logger) {
|
|
|
22324
22362
|
if (surfacePath && stripTangyrFromMergeSurface(surfacePath, logger)) {
|
|
22325
22363
|
removedParentDirs.add(path24.dirname(surfacePath));
|
|
22326
22364
|
removedCount++;
|
|
22365
|
+
if (fs27.existsSync(surfacePath)) {
|
|
22366
|
+
keptSurfaces.push(surfacePath);
|
|
22367
|
+
}
|
|
22327
22368
|
} else {
|
|
22328
22369
|
logger.verbose(
|
|
22329
22370
|
` left in place (merge surface, nothing of ours in it): ${surfacePath ?? file.relativePath}`
|
|
@@ -22426,10 +22467,6 @@ ${String(kept.length)} later backup(s) were NOT restored: the earliest copy of e
|
|
|
22426
22467
|
logger.verbose(` removed manifest: ${manifestPath}`);
|
|
22427
22468
|
}
|
|
22428
22469
|
pruneEmptyDirs(path24.join(scopePath, "backups"), logger);
|
|
22429
|
-
const pruneBoundary = path24.dirname(scopePath);
|
|
22430
|
-
for (const dir of removedParentDirs) {
|
|
22431
|
-
pruneEmptyAncestors(dir, pruneBoundary, logger);
|
|
22432
|
-
}
|
|
22433
22470
|
try {
|
|
22434
22471
|
const remaining = fs27.readdirSync(scopePath);
|
|
22435
22472
|
if (remaining.length === 0) {
|
|
@@ -22452,6 +22489,22 @@ ${String(kept.length)} later backup(s) were NOT restored: the earliest copy of e
|
|
|
22452
22489
|
} else {
|
|
22453
22490
|
logger.verbose(" no manifest to update after partial residue cleanup");
|
|
22454
22491
|
}
|
|
22492
|
+
const pruneBoundary = path24.dirname(scopePath);
|
|
22493
|
+
for (const dir of removedParentDirs) {
|
|
22494
|
+
pruneEmptyAncestors(dir, pruneBoundary, logger);
|
|
22495
|
+
}
|
|
22496
|
+
if (keptSurfaces.length > 0) {
|
|
22497
|
+
logger.warn(
|
|
22498
|
+
`
|
|
22499
|
+
${String(keptSurfaces.length)} shared file(s) kept, with Tangyr's own block removed from each:`
|
|
22500
|
+
);
|
|
22501
|
+
for (const surface of keptSurfaces) {
|
|
22502
|
+
logger.warn(` ${surface}`);
|
|
22503
|
+
}
|
|
22504
|
+
logger.warn(
|
|
22505
|
+
" What remains in them was not written with a marker of ours, so it is left rather than guessed at. Delete what you no longer want."
|
|
22506
|
+
);
|
|
22507
|
+
}
|
|
22455
22508
|
logger.info(`
|
|
22456
22509
|
Uninstallation complete: ${removedCount} file(s) removed.`);
|
|
22457
22510
|
}
|
|
@@ -22467,6 +22520,13 @@ function resolveManifestKeyToPath(key, scope, runtime, projectRootOverride) {
|
|
|
22467
22520
|
if (component === "hook_scripts") {
|
|
22468
22521
|
return resolveSharedHookScriptsPath(runtime, scope, projectRoot);
|
|
22469
22522
|
}
|
|
22523
|
+
const sharedSkill = resolveSharedSkillsKey(
|
|
22524
|
+
key,
|
|
22525
|
+
resolveSharedSkillsPath(runtime, scope, projectRoot)
|
|
22526
|
+
);
|
|
22527
|
+
if (sharedSkill) {
|
|
22528
|
+
return sharedSkill;
|
|
22529
|
+
}
|
|
22470
22530
|
return resolveSharedArtifactKey(key, scope, projectRoot);
|
|
22471
22531
|
}
|
|
22472
22532
|
if (tool === "claude-code") {
|
|
@@ -23864,6 +23924,27 @@ function resolveSharedHookScriptsPath(runtime, scope, projectRoot) {
|
|
|
23864
23924
|
}
|
|
23865
23925
|
return resolveTargetPath("~/.agents/hooks");
|
|
23866
23926
|
}
|
|
23927
|
+
function resolveSharedSkillsPath(runtime, scope, projectRoot) {
|
|
23928
|
+
if (runtime) {
|
|
23929
|
+
try {
|
|
23930
|
+
const mappings = loadMappings(
|
|
23931
|
+
runtime.sourceRoot,
|
|
23932
|
+
runtime.config,
|
|
23933
|
+
runtime.configDir
|
|
23934
|
+
);
|
|
23935
|
+
return resolveTargetPaths({
|
|
23936
|
+
scope,
|
|
23937
|
+
projectRoot,
|
|
23938
|
+
mappings: mappings.platformPaths
|
|
23939
|
+
}).opencode.skills_shared;
|
|
23940
|
+
} catch {
|
|
23941
|
+
}
|
|
23942
|
+
}
|
|
23943
|
+
if (scope === "project") {
|
|
23944
|
+
return path24.join(projectRoot ?? process.cwd(), ".agents", "skills");
|
|
23945
|
+
}
|
|
23946
|
+
return resolveTargetPath("~/.agents/skills");
|
|
23947
|
+
}
|
|
23867
23948
|
function resolveOpenCodePaths(runtime, scope = "global", projectRoot) {
|
|
23868
23949
|
if (runtime) {
|
|
23869
23950
|
try {
|
|
@@ -25220,8 +25301,8 @@ function toConflictPolicy2(value) {
|
|
|
25220
25301
|
}
|
|
25221
25302
|
|
|
25222
25303
|
// src/commands/install.ts
|
|
25223
|
-
import
|
|
25224
|
-
import
|
|
25304
|
+
import fs46 from "fs";
|
|
25305
|
+
import path46 from "path";
|
|
25225
25306
|
|
|
25226
25307
|
// src/core/channel-state.ts
|
|
25227
25308
|
import fs32 from "fs";
|
|
@@ -26168,12 +26249,15 @@ function findContestedInstructions(instructionsByTarget) {
|
|
|
26168
26249
|
}
|
|
26169
26250
|
return contested;
|
|
26170
26251
|
}
|
|
26171
|
-
function reportContestedInstructions(instructionsByTarget, kitDeclaresRules, logger) {
|
|
26252
|
+
function reportContestedInstructions(instructionsByTarget, kitDeclaresRules, logger, missingByTarget) {
|
|
26172
26253
|
if (!kitDeclaresRules) {
|
|
26173
26254
|
return;
|
|
26174
26255
|
}
|
|
26175
26256
|
for (const contested of findContestedInstructions(instructionsByTarget)) {
|
|
26176
|
-
|
|
26257
|
+
const losers = missingByTarget ? contested.losers.filter(
|
|
26258
|
+
(target) => (missingByTarget.get(target)?.length ?? 0) > 0
|
|
26259
|
+
) : contested.losers;
|
|
26260
|
+
if (losers.length === 0) {
|
|
26177
26261
|
continue;
|
|
26178
26262
|
}
|
|
26179
26263
|
logger.warn(
|
|
@@ -26183,7 +26267,7 @@ ${contested.destination} is the instructions file for ${contested.claimants.join
|
|
|
26183
26267
|
if (contested.survivor) {
|
|
26184
26268
|
logger.warn(` The content on disk is ${contested.survivor}'s.`);
|
|
26185
26269
|
}
|
|
26186
|
-
for (const target of
|
|
26270
|
+
for (const target of losers) {
|
|
26187
26271
|
logger.warn(
|
|
26188
26272
|
` ${target} does NOT get its rules: ${FOLDS_RULES_INTO_INSTRUCTIONS[target]}, and that content is overwritten here.`
|
|
26189
26273
|
);
|
|
@@ -26206,12 +26290,141 @@ function instructionsByActiveTarget(tools, scope, projectRoot, mappings) {
|
|
|
26206
26290
|
byTarget.set(tool, instructions);
|
|
26207
26291
|
}
|
|
26208
26292
|
}
|
|
26293
|
+
if (scope === "project" && projectRoot && tools.includes("copilot")) {
|
|
26294
|
+
byTarget.set("copilot", path31.join(projectRoot, "AGENTS.md"));
|
|
26295
|
+
}
|
|
26209
26296
|
return byTarget;
|
|
26210
26297
|
}
|
|
26211
26298
|
|
|
26299
|
+
// src/core/rules-coverage.ts
|
|
26300
|
+
import fs35 from "fs";
|
|
26301
|
+
import path32 from "path";
|
|
26302
|
+
function readingSurfaces(profile) {
|
|
26303
|
+
const record = profile;
|
|
26304
|
+
return {
|
|
26305
|
+
slot: typeof record?.rules === "string" ? record.rules : null,
|
|
26306
|
+
instructions: typeof record?.instructions === "string" ? record.instructions : null
|
|
26307
|
+
};
|
|
26308
|
+
}
|
|
26309
|
+
function inRulesSlot(slot, rule) {
|
|
26310
|
+
let entries;
|
|
26311
|
+
try {
|
|
26312
|
+
entries = fs35.readdirSync(slot);
|
|
26313
|
+
} catch {
|
|
26314
|
+
return false;
|
|
26315
|
+
}
|
|
26316
|
+
return entries.some(
|
|
26317
|
+
(entry) => entry === rule || entry.startsWith(`${rule}.`)
|
|
26318
|
+
);
|
|
26319
|
+
}
|
|
26320
|
+
function inInstructions(instructions, rule) {
|
|
26321
|
+
let content;
|
|
26322
|
+
try {
|
|
26323
|
+
content = fs35.readFileSync(instructions, "utf8");
|
|
26324
|
+
} catch {
|
|
26325
|
+
return false;
|
|
26326
|
+
}
|
|
26327
|
+
return content.split("\n").some((line) => line.trim() === `## ${rule}`);
|
|
26328
|
+
}
|
|
26329
|
+
function recordedRulesLoss(lossReport, target) {
|
|
26330
|
+
const entries = lossReport.targets[target]?.rules ?? [];
|
|
26331
|
+
for (const artifact of entries) {
|
|
26332
|
+
for (const field of artifact.fields) {
|
|
26333
|
+
if (field.detail.length > 0) {
|
|
26334
|
+
return field.detail;
|
|
26335
|
+
}
|
|
26336
|
+
}
|
|
26337
|
+
}
|
|
26338
|
+
return null;
|
|
26339
|
+
}
|
|
26340
|
+
function measureRulesCoverage(tools, declaredRules, scope, projectRoot, mappings, lossReport, instructionsByTarget) {
|
|
26341
|
+
const resolved = resolveTargetPaths({
|
|
26342
|
+
scope,
|
|
26343
|
+
projectRoot,
|
|
26344
|
+
mappings: mappings.platformPaths
|
|
26345
|
+
});
|
|
26346
|
+
const contestedByPath = new Map(
|
|
26347
|
+
findContestedInstructions(instructionsByTarget).map((contested) => [
|
|
26348
|
+
contested.destination,
|
|
26349
|
+
contested
|
|
26350
|
+
])
|
|
26351
|
+
);
|
|
26352
|
+
return tools.map((target) => {
|
|
26353
|
+
const surfaces = readingSurfaces(resolved[target]);
|
|
26354
|
+
const missing = declaredRules.filter((rule) => {
|
|
26355
|
+
if (surfaces.slot && inRulesSlot(surfaces.slot, rule)) {
|
|
26356
|
+
return false;
|
|
26357
|
+
}
|
|
26358
|
+
return !(surfaces.instructions && inInstructions(surfaces.instructions, rule));
|
|
26359
|
+
});
|
|
26360
|
+
return {
|
|
26361
|
+
target,
|
|
26362
|
+
missing,
|
|
26363
|
+
declared: declaredRules.length,
|
|
26364
|
+
reason: missing.length === 0 ? null : explain(target, surfaces, contestedByPath, lossReport, projectRoot)
|
|
26365
|
+
};
|
|
26366
|
+
});
|
|
26367
|
+
}
|
|
26368
|
+
function explain(target, surfaces, contestedByPath, lossReport, projectRoot) {
|
|
26369
|
+
if (surfaces.instructions) {
|
|
26370
|
+
const contested = contestedByPath.get(path32.resolve(surfaces.instructions));
|
|
26371
|
+
if (contested && contested.survivor !== null && contested.survivor !== target) {
|
|
26372
|
+
return `its rules are folded into ${display(surfaces.instructions, projectRoot)}, which ${contested.survivor} wrote last`;
|
|
26373
|
+
}
|
|
26374
|
+
}
|
|
26375
|
+
const recorded = recordedRulesLoss(lossReport, target);
|
|
26376
|
+
if (recorded) {
|
|
26377
|
+
return recorded;
|
|
26378
|
+
}
|
|
26379
|
+
if (!surfaces.slot) {
|
|
26380
|
+
return "it has no rules surface in this scope";
|
|
26381
|
+
}
|
|
26382
|
+
return `not in ${display(surfaces.slot, projectRoot)}, nor folded into the instructions file`;
|
|
26383
|
+
}
|
|
26384
|
+
function display(target, projectRoot) {
|
|
26385
|
+
if (!projectRoot) {
|
|
26386
|
+
return target;
|
|
26387
|
+
}
|
|
26388
|
+
const relative = path32.relative(projectRoot, target);
|
|
26389
|
+
return relative.startsWith("..") ? target : relative;
|
|
26390
|
+
}
|
|
26391
|
+
function reportRulesCoverage(coverage, logger) {
|
|
26392
|
+
if (coverage.length === 0 || coverage[0].declared === 0) {
|
|
26393
|
+
return;
|
|
26394
|
+
}
|
|
26395
|
+
const complete = coverage.every((entry) => entry.missing.length === 0);
|
|
26396
|
+
const say = complete ? (line) => {
|
|
26397
|
+
logger.verbose(line);
|
|
26398
|
+
} : (line) => {
|
|
26399
|
+
logger.warn(line);
|
|
26400
|
+
};
|
|
26401
|
+
const declared = coverage[0].declared;
|
|
26402
|
+
const width = Math.max(...coverage.map((entry) => entry.target.length));
|
|
26403
|
+
say(
|
|
26404
|
+
`
|
|
26405
|
+
Rules reaching each target (${String(declared)} declared, measured on disk):`
|
|
26406
|
+
);
|
|
26407
|
+
for (const entry of coverage) {
|
|
26408
|
+
const delivered = declared - entry.missing.length;
|
|
26409
|
+
const counts = `${String(delivered)}/${String(declared)}`;
|
|
26410
|
+
const head = ` ${entry.target.padEnd(width)} ${counts}`;
|
|
26411
|
+
if (entry.missing.length === 0) {
|
|
26412
|
+
say(head);
|
|
26413
|
+
continue;
|
|
26414
|
+
}
|
|
26415
|
+
say(`${head} missing: ${entry.missing.join(", ")}`);
|
|
26416
|
+
if (entry.reason) {
|
|
26417
|
+
say(` ${" ".repeat(width)} ${entry.reason}`);
|
|
26418
|
+
}
|
|
26419
|
+
}
|
|
26420
|
+
}
|
|
26421
|
+
function missingRulesByTarget(coverage) {
|
|
26422
|
+
return new Map(coverage.map((entry) => [entry.target, entry.missing]));
|
|
26423
|
+
}
|
|
26424
|
+
|
|
26212
26425
|
// src/adapters/claude-code.ts
|
|
26213
|
-
import
|
|
26214
|
-
import
|
|
26426
|
+
import fs38 from "fs";
|
|
26427
|
+
import path36 from "path";
|
|
26215
26428
|
|
|
26216
26429
|
// src/core/shim.ts
|
|
26217
26430
|
import crypto4 from "crypto";
|
|
@@ -26233,8 +26446,8 @@ ${SHIM_BODY}`;
|
|
|
26233
26446
|
}
|
|
26234
26447
|
|
|
26235
26448
|
// src/core/skills-slot.ts
|
|
26236
|
-
import
|
|
26237
|
-
import
|
|
26449
|
+
import fs36 from "fs";
|
|
26450
|
+
import path33 from "path";
|
|
26238
26451
|
function isForeignSkillsSlotSymlink(destination, config, sourceRoot, source) {
|
|
26239
26452
|
if (!isSymlinkPath(destination)) {
|
|
26240
26453
|
return false;
|
|
@@ -26247,7 +26460,7 @@ function isForeignSkillsSlotSymlink(destination, config, sourceRoot, source) {
|
|
|
26247
26460
|
}
|
|
26248
26461
|
function syncSkillsSlot(sync) {
|
|
26249
26462
|
const { source, destination, logger } = sync;
|
|
26250
|
-
if (!
|
|
26463
|
+
if (!fs36.existsSync(source)) {
|
|
26251
26464
|
return [
|
|
26252
26465
|
{
|
|
26253
26466
|
component: "skills",
|
|
@@ -26275,7 +26488,7 @@ function syncSkillsSlot(sync) {
|
|
|
26275
26488
|
if (isLegacyWholesaleSymlink) {
|
|
26276
26489
|
for (const name of foreignSkillNames(source, declaredNames)) {
|
|
26277
26490
|
logger.info(
|
|
26278
|
-
`[dry-run] skills: migrate foreign skill ${
|
|
26491
|
+
`[dry-run] skills: migrate foreign skill ${path33.join(source, name)} -> ${path33.join(destination, name)}`
|
|
26279
26492
|
);
|
|
26280
26493
|
}
|
|
26281
26494
|
logger.info(
|
|
@@ -26283,9 +26496,9 @@ function syncSkillsSlot(sync) {
|
|
|
26283
26496
|
);
|
|
26284
26497
|
}
|
|
26285
26498
|
for (const name of declaredNames ?? listSkillDirNames(source)) {
|
|
26286
|
-
const skillDestination =
|
|
26499
|
+
const skillDestination = path33.join(destination, name);
|
|
26287
26500
|
logger.info(
|
|
26288
|
-
`[dry-run] skills: symlink ${
|
|
26501
|
+
`[dry-run] skills: symlink ${path33.join(source, name)} -> ${skillDestination}`
|
|
26289
26502
|
);
|
|
26290
26503
|
outcomes2.push({
|
|
26291
26504
|
component: "skills",
|
|
@@ -26312,9 +26525,9 @@ function syncSkillsSlot(sync) {
|
|
|
26312
26525
|
}
|
|
26313
26526
|
function syncSingleSkill(sync, name) {
|
|
26314
26527
|
const { config, sourceRoot, source, destination } = sync;
|
|
26315
|
-
const skillSource =
|
|
26316
|
-
const skillDestination =
|
|
26317
|
-
if (!
|
|
26528
|
+
const skillSource = path33.join(source, name);
|
|
26529
|
+
const skillDestination = path33.join(destination, name);
|
|
26530
|
+
if (!fs36.existsSync(skillSource)) {
|
|
26318
26531
|
return {
|
|
26319
26532
|
component: "skills",
|
|
26320
26533
|
status: "skipped",
|
|
@@ -26330,29 +26543,29 @@ function syncSingleSkill(sync, name) {
|
|
|
26330
26543
|
};
|
|
26331
26544
|
}
|
|
26332
26545
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(skillDestination, /* @__PURE__ */ new Set([skillDestination]), config)) {
|
|
26333
|
-
|
|
26546
|
+
fs36.unlinkSync(skillDestination);
|
|
26334
26547
|
} else if (artifactClass === "unmanaged-conflict" && !sync.onUnmanagedConflict(skillDestination)) {
|
|
26335
26548
|
return { component: "skills", status: "conflict", path: skillDestination };
|
|
26336
26549
|
} else if (artifactClass === "managed-symlink") {
|
|
26337
|
-
|
|
26550
|
+
fs36.unlinkSync(skillDestination);
|
|
26338
26551
|
}
|
|
26339
26552
|
createRelativeSymlink(skillSource, skillDestination, "dir");
|
|
26340
26553
|
return { component: "skills", status: "success", path: skillDestination };
|
|
26341
26554
|
}
|
|
26342
26555
|
function migrateWholesaleSkillsSymlink(source, destination, declaredNames, logger) {
|
|
26343
26556
|
const foreignNames = foreignSkillNames(source, declaredNames);
|
|
26344
|
-
|
|
26557
|
+
fs36.unlinkSync(destination);
|
|
26345
26558
|
ensureDir(destination);
|
|
26346
26559
|
for (const name of foreignNames) {
|
|
26347
|
-
const from =
|
|
26348
|
-
const to =
|
|
26349
|
-
if (
|
|
26560
|
+
const from = path33.join(source, name);
|
|
26561
|
+
const to = path33.join(destination, name);
|
|
26562
|
+
if (fs36.existsSync(to)) {
|
|
26350
26563
|
logger.warn(
|
|
26351
26564
|
`skills migration: ${to} already exists \u2014 skipping ${from} to avoid overwrite. Nothing in the kit was changed.`
|
|
26352
26565
|
);
|
|
26353
26566
|
continue;
|
|
26354
26567
|
}
|
|
26355
|
-
|
|
26568
|
+
fs36.cpSync(from, to, { recursive: true, verbatimSymlinks: true });
|
|
26356
26569
|
logger.warn(
|
|
26357
26570
|
`skills migration: '${name}' is present under the kit's skills/ but is not declared in its manifest. Copied ${from} -> ${to} so the harness can read it. The original is left in the kit deliberately: this command does not modify a kit. Remove ${from} yourself if it does not belong there, or declare it in tangyr-kit.yaml if it does.`
|
|
26358
26571
|
);
|
|
@@ -26366,44 +26579,44 @@ function foreignSkillNames(source, declaredNames) {
|
|
|
26366
26579
|
return listSkillDirNames(source).filter((name) => !declaredSet.has(name));
|
|
26367
26580
|
}
|
|
26368
26581
|
function listSkillDirNames(dir) {
|
|
26369
|
-
if (!
|
|
26582
|
+
if (!fs36.existsSync(dir)) {
|
|
26370
26583
|
return [];
|
|
26371
26584
|
}
|
|
26372
|
-
return
|
|
26585
|
+
return fs36.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
|
|
26373
26586
|
}
|
|
26374
26587
|
function isSymlinkPath(filePath) {
|
|
26375
26588
|
try {
|
|
26376
|
-
return
|
|
26589
|
+
return fs36.lstatSync(filePath).isSymbolicLink();
|
|
26377
26590
|
} catch {
|
|
26378
26591
|
return false;
|
|
26379
26592
|
}
|
|
26380
26593
|
}
|
|
26381
26594
|
function isSymlinkTo2(linkPath, source) {
|
|
26382
26595
|
try {
|
|
26383
|
-
return
|
|
26596
|
+
return fs36.realpathSync(linkPath) === fs36.realpathSync(source);
|
|
26384
26597
|
} catch {
|
|
26385
26598
|
return false;
|
|
26386
26599
|
}
|
|
26387
26600
|
}
|
|
26388
26601
|
|
|
26389
26602
|
// src/core/hook-scripts.ts
|
|
26390
|
-
import
|
|
26603
|
+
import path34 from "path";
|
|
26391
26604
|
function hookScriptsDir(bridge, target, projectRoot) {
|
|
26392
26605
|
const globalBridge = resolveTargetPath("~/.agents/hooks");
|
|
26393
|
-
if (
|
|
26606
|
+
if (path34.resolve(bridge) === path34.resolve(globalBridge)) {
|
|
26394
26607
|
return { prefix: GLOBAL_HOOK_SCRIPTS_DIR, machineLocal: false };
|
|
26395
26608
|
}
|
|
26396
|
-
const relative =
|
|
26397
|
-
const insideProject = !relative.startsWith("..") && !
|
|
26609
|
+
const relative = path34.relative(projectRoot ?? process.cwd(), bridge);
|
|
26610
|
+
const insideProject = !relative.startsWith("..") && !path34.isAbsolute(relative) && relative !== "";
|
|
26398
26611
|
const variable = PROJECT_DIR_VARIABLE[target];
|
|
26399
26612
|
if (insideProject && variable) {
|
|
26400
|
-
const posix =
|
|
26401
|
-
relative.split(
|
|
26613
|
+
const posix = path34.posix.join(
|
|
26614
|
+
relative.split(path34.sep).join("/"),
|
|
26402
26615
|
"scripts"
|
|
26403
26616
|
);
|
|
26404
26617
|
return { prefix: `$${variable.slice(1)}/${posix}`, machineLocal: false };
|
|
26405
26618
|
}
|
|
26406
|
-
return { prefix:
|
|
26619
|
+
return { prefix: path34.join(bridge, "scripts"), machineLocal: true };
|
|
26407
26620
|
}
|
|
26408
26621
|
var PROJECT_DIR_VARIABLE = {
|
|
26409
26622
|
"claude-code": "$CLAUDE_PROJECT_DIR"
|
|
@@ -26413,19 +26626,19 @@ function machineLocalScriptPathNotice(target, prefix) {
|
|
|
26413
26626
|
}
|
|
26414
26627
|
|
|
26415
26628
|
// src/core/instructions-source.ts
|
|
26416
|
-
import
|
|
26417
|
-
import
|
|
26629
|
+
import fs37 from "fs";
|
|
26630
|
+
import path35 from "path";
|
|
26418
26631
|
var PORTABLE_INSTRUCTIONS_NAME = "AGENTS.md";
|
|
26419
26632
|
var InstructionsSourceMissingError = class extends Error {
|
|
26420
26633
|
constructor(kitRoot, expected, declaredBy) {
|
|
26421
26634
|
super(
|
|
26422
|
-
`${
|
|
26635
|
+
`${path35.join(kitRoot, expected)}: instructions source not found (declared by ${declaredBy}). To fix: create that file, or point '${declaredBy}' at the file this kit actually carries. With neither declaration, the kit's ${DEFAULT_ENTRYPOINT} or ${PORTABLE_INSTRUCTIONS_NAME} is used.`
|
|
26423
26636
|
);
|
|
26424
26637
|
this.name = "InstructionsSourceMissingError";
|
|
26425
26638
|
}
|
|
26426
26639
|
};
|
|
26427
26640
|
function normalizeLabel(kitRoot, file) {
|
|
26428
|
-
return
|
|
26641
|
+
return path35.relative(kitRoot, file).split(path35.sep).join("/");
|
|
26429
26642
|
}
|
|
26430
26643
|
function isExplicitOverride(configured) {
|
|
26431
26644
|
const normalize = (value) => value.replace(/\\/gu, "/").replace(/^\.\//u, "");
|
|
@@ -26434,8 +26647,8 @@ function isExplicitOverride(configured) {
|
|
|
26434
26647
|
function resolveInstructionsSource(kitRoot, config) {
|
|
26435
26648
|
const configured = config.source.instructions;
|
|
26436
26649
|
if (isExplicitOverride(configured)) {
|
|
26437
|
-
const file =
|
|
26438
|
-
if (!
|
|
26650
|
+
const file = path35.resolve(kitRoot, configured);
|
|
26651
|
+
if (!fs37.existsSync(file)) {
|
|
26439
26652
|
throw new InstructionsSourceMissingError(
|
|
26440
26653
|
kitRoot,
|
|
26441
26654
|
configured,
|
|
@@ -26450,8 +26663,8 @@ function resolveInstructionsSource(kitRoot, config) {
|
|
|
26450
26663
|
}
|
|
26451
26664
|
const declared = resolveKitEntrypointName(kitRoot);
|
|
26452
26665
|
if (declared !== void 0) {
|
|
26453
|
-
const file =
|
|
26454
|
-
if (!
|
|
26666
|
+
const file = path35.resolve(kitRoot, declared);
|
|
26667
|
+
if (!fs37.existsSync(file)) {
|
|
26455
26668
|
throw new InstructionsSourceMissingError(
|
|
26456
26669
|
kitRoot,
|
|
26457
26670
|
declared,
|
|
@@ -26465,13 +26678,13 @@ function resolveInstructionsSource(kitRoot, config) {
|
|
|
26465
26678
|
};
|
|
26466
26679
|
}
|
|
26467
26680
|
for (const name of [DEFAULT_ENTRYPOINT, PORTABLE_INSTRUCTIONS_NAME]) {
|
|
26468
|
-
const file =
|
|
26469
|
-
if (
|
|
26681
|
+
const file = path35.resolve(kitRoot, name);
|
|
26682
|
+
if (fs37.existsSync(file)) {
|
|
26470
26683
|
return { file, label: name, origin: "convention" };
|
|
26471
26684
|
}
|
|
26472
26685
|
}
|
|
26473
|
-
const legacy =
|
|
26474
|
-
if (
|
|
26686
|
+
const legacy = path35.resolve(kitRoot, LEGACY_ENTRYPOINT);
|
|
26687
|
+
if (fs37.existsSync(legacy)) {
|
|
26475
26688
|
return {
|
|
26476
26689
|
file: legacy,
|
|
26477
26690
|
label: LEGACY_ENTRYPOINT,
|
|
@@ -26483,7 +26696,7 @@ function resolveInstructionsSource(kitRoot, config) {
|
|
|
26483
26696
|
}
|
|
26484
26697
|
function instructionsSourcePath(kitRoot, config) {
|
|
26485
26698
|
const resolved = resolveInstructionsSource(kitRoot, config);
|
|
26486
|
-
return resolved ? resolved.file :
|
|
26699
|
+
return resolved ? resolved.file : path35.resolve(kitRoot, config.source.instructions);
|
|
26487
26700
|
}
|
|
26488
26701
|
function instructionsSourceLabel(kitRoot, config) {
|
|
26489
26702
|
const resolved = resolveInstructionsSource(kitRoot, config);
|
|
@@ -26604,7 +26817,7 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
|
|
|
26604
26817
|
if (!shouldSkipComponent(options, "hooks")) {
|
|
26605
26818
|
outcomes.push(
|
|
26606
26819
|
syncHookScriptsBridge({
|
|
26607
|
-
source:
|
|
26820
|
+
source: path36.resolve(sourceRoot, config.source.hooks),
|
|
26608
26821
|
destination: profile.hook_scripts,
|
|
26609
26822
|
config,
|
|
26610
26823
|
sourceRoot,
|
|
@@ -26656,13 +26869,13 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
|
|
|
26656
26869
|
}
|
|
26657
26870
|
function syncProviderLoss(config, sourceRoot, mappings, lossReport) {
|
|
26658
26871
|
if (!mappings.modelTiers.custom_provider) return;
|
|
26659
|
-
const agentsDir =
|
|
26660
|
-
if (!
|
|
26661
|
-
for (const agentFile of ts(
|
|
26872
|
+
const agentsDir = path36.join(sourceRoot, config.source.agents);
|
|
26873
|
+
if (!fs38.existsSync(agentsDir)) return;
|
|
26874
|
+
for (const agentFile of ts(path36.join(agentsDir, "*.md")).sort()) {
|
|
26662
26875
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
26663
26876
|
const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
26664
26877
|
if (hasProvider) {
|
|
26665
|
-
const basename =
|
|
26878
|
+
const basename = path36.basename(agentFile);
|
|
26666
26879
|
addLoss(lossReport, "claude-code", "agents", {
|
|
26667
26880
|
source: `agents/${basename}`,
|
|
26668
26881
|
fields: [
|
|
@@ -26687,7 +26900,7 @@ function shouldSkipComponent(options, component) {
|
|
|
26687
26900
|
var SHIM_MANIFEST_KEY = "claude-code/instructions_shim";
|
|
26688
26901
|
function lstatOrNull(p) {
|
|
26689
26902
|
try {
|
|
26690
|
-
return
|
|
26903
|
+
return fs38.lstatSync(p);
|
|
26691
26904
|
} catch {
|
|
26692
26905
|
return null;
|
|
26693
26906
|
}
|
|
@@ -26699,12 +26912,12 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
26699
26912
|
if (shimLink?.isSymbolicLink()) {
|
|
26700
26913
|
backupFile(shimPath, manifest, scopePath);
|
|
26701
26914
|
writeManifest(scopePath, manifest);
|
|
26702
|
-
|
|
26915
|
+
fs38.unlinkSync(shimPath);
|
|
26703
26916
|
logger?.verbose(
|
|
26704
26917
|
`instructions-shim: replaced an unmanaged symlink at ${shimPath}`
|
|
26705
26918
|
);
|
|
26706
26919
|
}
|
|
26707
|
-
if (!
|
|
26920
|
+
if (!fs38.existsSync(shimPath)) {
|
|
26708
26921
|
addArtifactToManifest(manifest, {
|
|
26709
26922
|
relativePath: SHIM_MANIFEST_KEY,
|
|
26710
26923
|
path: shimPath,
|
|
@@ -26712,12 +26925,12 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
26712
26925
|
origin: "tangyr-managed"
|
|
26713
26926
|
});
|
|
26714
26927
|
writeManifest(scopePath, manifest);
|
|
26715
|
-
|
|
26716
|
-
|
|
26928
|
+
fs38.mkdirSync(path36.dirname(shimPath), { recursive: true });
|
|
26929
|
+
fs38.writeFileSync(shimPath, shimContent);
|
|
26717
26930
|
logger?.verbose(`instructions-shim: wrote @AGENTS.md shim -> ${shimPath}`);
|
|
26718
26931
|
return;
|
|
26719
26932
|
}
|
|
26720
|
-
const existing =
|
|
26933
|
+
const existing = fs38.readFileSync(shimPath, "utf8");
|
|
26721
26934
|
const firstNonEmptyLine = existing.split("\n").find((l) => l.trim().length > 0) ?? "";
|
|
26722
26935
|
const marker = extractProvenanceMarker(firstNonEmptyLine);
|
|
26723
26936
|
if (marker !== null && marker.hash === expectedBodyHash) {
|
|
@@ -26734,7 +26947,7 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
26734
26947
|
}
|
|
26735
26948
|
backupFile(shimPath, manifest, scopePath);
|
|
26736
26949
|
writeManifest(scopePath, manifest);
|
|
26737
|
-
|
|
26950
|
+
fs38.writeFileSync(shimPath, shimContent);
|
|
26738
26951
|
addArtifactToManifest(manifest, {
|
|
26739
26952
|
relativePath: SHIM_MANIFEST_KEY,
|
|
26740
26953
|
path: shimPath,
|
|
@@ -26744,10 +26957,10 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
26744
26957
|
logger?.verbose(`instructions-shim: backed up and replaced -> ${shimPath}`);
|
|
26745
26958
|
}
|
|
26746
26959
|
function syncDirectComponent(config, sourceRoot, options, logger, directComponent, manifest, scopePath) {
|
|
26747
|
-
const source = directComponent.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) :
|
|
26960
|
+
const source = directComponent.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : path36.resolve(sourceRoot, config.source[directComponent.sourceKey]);
|
|
26748
26961
|
const sourceLabel = directComponent.sourceKey === "instructions" ? instructionsSourceLabel(sourceRoot, config) : config.source[directComponent.sourceKey];
|
|
26749
26962
|
const destination = directComponent.destination;
|
|
26750
|
-
if (!
|
|
26963
|
+
if (!fs38.existsSync(source)) {
|
|
26751
26964
|
return skippedMissingSource(directComponent.component, source);
|
|
26752
26965
|
}
|
|
26753
26966
|
if (options.dryRun) {
|
|
@@ -26769,7 +26982,7 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
26769
26982
|
};
|
|
26770
26983
|
}
|
|
26771
26984
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
26772
|
-
|
|
26985
|
+
fs38.unlinkSync(destination);
|
|
26773
26986
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict(destination, config, options, logger, manifest, scopePath)) {
|
|
26774
26987
|
return {
|
|
26775
26988
|
component: directComponent.component,
|
|
@@ -26777,11 +26990,11 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
26777
26990
|
path: destination
|
|
26778
26991
|
};
|
|
26779
26992
|
} else if (artifactClass === "managed-symlink") {
|
|
26780
|
-
|
|
26993
|
+
fs38.unlinkSync(destination);
|
|
26781
26994
|
} else if (artifactClass === "managed-compiled") {
|
|
26782
|
-
|
|
26995
|
+
fs38.unlinkSync(destination);
|
|
26783
26996
|
}
|
|
26784
|
-
ensureDir(
|
|
26997
|
+
ensureDir(path36.dirname(destination));
|
|
26785
26998
|
createRelativeSymlink(source, destination, directComponent.type, {
|
|
26786
26999
|
logger,
|
|
26787
27000
|
provenanceMarker: directComponent.type === "file" ? formatProvenanceMarker(
|
|
@@ -26801,7 +27014,7 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
26801
27014
|
return syncSkillsSlot({
|
|
26802
27015
|
config,
|
|
26803
27016
|
sourceRoot,
|
|
26804
|
-
source:
|
|
27017
|
+
source: path36.resolve(sourceRoot, config.source.skills),
|
|
26805
27018
|
destination,
|
|
26806
27019
|
dryRun: options.dryRun,
|
|
26807
27020
|
logger,
|
|
@@ -26835,7 +27048,7 @@ function syncHooks(config, sourceRoot, options, logger, destination, scriptsBrid
|
|
|
26835
27048
|
destination,
|
|
26836
27049
|
settings,
|
|
26837
27050
|
stringifyJson2,
|
|
26838
|
-
!
|
|
27051
|
+
!fs38.existsSync(destination),
|
|
26839
27052
|
logger
|
|
26840
27053
|
);
|
|
26841
27054
|
return {
|
|
@@ -26845,8 +27058,8 @@ function syncHooks(config, sourceRoot, options, logger, destination, scriptsBrid
|
|
|
26845
27058
|
};
|
|
26846
27059
|
}
|
|
26847
27060
|
function syncMcp(config, sourceRoot, options, logger, destination) {
|
|
26848
|
-
const source =
|
|
26849
|
-
if (!
|
|
27061
|
+
const source = path36.resolve(sourceRoot, config.source.mcp);
|
|
27062
|
+
if (!fs38.existsSync(source)) {
|
|
26850
27063
|
return skippedMissingSource("mcp", source);
|
|
26851
27064
|
}
|
|
26852
27065
|
if (options.dryRun) {
|
|
@@ -26871,7 +27084,7 @@ function syncMcp(config, sourceRoot, options, logger, destination) {
|
|
|
26871
27084
|
destination,
|
|
26872
27085
|
hostConfig,
|
|
26873
27086
|
stringifyJson2,
|
|
26874
|
-
!
|
|
27087
|
+
!fs38.existsSync(destination),
|
|
26875
27088
|
logger
|
|
26876
27089
|
);
|
|
26877
27090
|
return {
|
|
@@ -26881,8 +27094,8 @@ function syncMcp(config, sourceRoot, options, logger, destination) {
|
|
|
26881
27094
|
};
|
|
26882
27095
|
}
|
|
26883
27096
|
function syncSettings(config, sourceRoot, options, logger, destination) {
|
|
26884
|
-
const source =
|
|
26885
|
-
if (!
|
|
27097
|
+
const source = path36.resolve(sourceRoot, config.source.settings);
|
|
27098
|
+
if (!fs38.existsSync(source)) {
|
|
26886
27099
|
return skippedMissingSource("settings", source);
|
|
26887
27100
|
}
|
|
26888
27101
|
if (options.dryRun) {
|
|
@@ -26900,7 +27113,7 @@ function syncSettings(config, sourceRoot, options, logger, destination) {
|
|
|
26900
27113
|
destination,
|
|
26901
27114
|
settings,
|
|
26902
27115
|
stringifyJson2,
|
|
26903
|
-
!
|
|
27116
|
+
!fs38.existsSync(destination),
|
|
26904
27117
|
logger
|
|
26905
27118
|
);
|
|
26906
27119
|
return {
|
|
@@ -26924,7 +27137,7 @@ function handleConflict(destination, config, options, logger, manifest, scopePat
|
|
|
26924
27137
|
if (manifest && scopePath) {
|
|
26925
27138
|
backupFile(destination, manifest, scopePath);
|
|
26926
27139
|
writeManifest(scopePath, manifest);
|
|
26927
|
-
|
|
27140
|
+
fs38.rmSync(destination, { recursive: true, force: true });
|
|
26928
27141
|
} else {
|
|
26929
27142
|
const parked = parkConflictingPath(
|
|
26930
27143
|
destination,
|
|
@@ -26939,7 +27152,7 @@ function handleConflict(destination, config, options, logger, manifest, scopePat
|
|
|
26939
27152
|
}
|
|
26940
27153
|
return true;
|
|
26941
27154
|
}
|
|
26942
|
-
|
|
27155
|
+
fs38.rmSync(destination, { recursive: true, force: true });
|
|
26943
27156
|
return true;
|
|
26944
27157
|
}
|
|
26945
27158
|
function skippedMissingSource(component, source) {
|
|
@@ -26951,16 +27164,16 @@ function skippedMissingSource(component, source) {
|
|
|
26951
27164
|
}
|
|
26952
27165
|
function isSymlinkTo3(linkPath, source) {
|
|
26953
27166
|
try {
|
|
26954
|
-
return
|
|
27167
|
+
return fs38.realpathSync(linkPath) === fs38.realpathSync(source);
|
|
26955
27168
|
} catch {
|
|
26956
27169
|
return false;
|
|
26957
27170
|
}
|
|
26958
27171
|
}
|
|
26959
27172
|
function readJsonObject3(filePath) {
|
|
26960
|
-
if (!
|
|
27173
|
+
if (!fs38.existsSync(filePath)) {
|
|
26961
27174
|
return {};
|
|
26962
27175
|
}
|
|
26963
|
-
const parsed = JSON.parse(
|
|
27176
|
+
const parsed = JSON.parse(fs38.readFileSync(filePath, "utf8"));
|
|
26964
27177
|
return isRecord3(parsed) ? parsed : {};
|
|
26965
27178
|
}
|
|
26966
27179
|
function markManaged(value) {
|
|
@@ -26987,13 +27200,13 @@ function isRecord3(value) {
|
|
|
26987
27200
|
// src/adapters/codex.ts
|
|
26988
27201
|
var TOML3 = __toESM(require_toml(), 1);
|
|
26989
27202
|
import crypto6 from "crypto";
|
|
26990
|
-
import
|
|
26991
|
-
import
|
|
27203
|
+
import fs41 from "fs";
|
|
27204
|
+
import path40 from "path";
|
|
26992
27205
|
|
|
26993
27206
|
// src/compiler/agents.ts
|
|
26994
27207
|
var TOML = __toESM(require_toml(), 1);
|
|
26995
27208
|
var import_yaml8 = __toESM(require_dist(), 1);
|
|
26996
|
-
import
|
|
27209
|
+
import path37 from "path";
|
|
26997
27210
|
var writeCapabilityClasses = /* @__PURE__ */ new Set(["filesystem-write", "shell-execution"]);
|
|
26998
27211
|
var copilotToolAliasesByClass = {
|
|
26999
27212
|
delegation: "agent",
|
|
@@ -27005,7 +27218,7 @@ var copilotToolAliasesByClass = {
|
|
|
27005
27218
|
};
|
|
27006
27219
|
function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
27007
27220
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
27008
|
-
const relativeSource = `agents/${
|
|
27221
|
+
const relativeSource = `agents/${path37.basename(sourceFile)}`;
|
|
27009
27222
|
if (target === "opencode") {
|
|
27010
27223
|
return compileOpenCodeAgent(
|
|
27011
27224
|
sourceFile,
|
|
@@ -27046,7 +27259,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
|
27046
27259
|
mappings,
|
|
27047
27260
|
lossReport
|
|
27048
27261
|
);
|
|
27049
|
-
const overlayKey = `agents/${
|
|
27262
|
+
const overlayKey = `agents/${path37.basename(sourceFile, ".md")}.${target}.yaml`;
|
|
27050
27263
|
const targetFields = {
|
|
27051
27264
|
...translated.fields,
|
|
27052
27265
|
...extensions[overlayKey] ?? {}
|
|
@@ -27080,7 +27293,7 @@ ${TOML.stringify({
|
|
|
27080
27293
|
function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
27081
27294
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
27082
27295
|
throw new Error(
|
|
27083
|
-
`${
|
|
27296
|
+
`${path37.basename(sourceFile)}: OpenCode agent requires a non-empty description field`
|
|
27084
27297
|
);
|
|
27085
27298
|
}
|
|
27086
27299
|
const frontmatter = {
|
|
@@ -27134,7 +27347,7 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
|
|
|
27134
27347
|
"permission",
|
|
27135
27348
|
"permission-coarsening"
|
|
27136
27349
|
),
|
|
27137
|
-
detail: `${
|
|
27350
|
+
detail: `${path37.basename(sourceFile)}: per-tool permission '${tool}' mapped to coarse allow|deny action`
|
|
27138
27351
|
}
|
|
27139
27352
|
]
|
|
27140
27353
|
});
|
|
@@ -27159,7 +27372,7 @@ ${(0, import_yaml8.stringify)(frontmatter).trim()}
|
|
|
27159
27372
|
function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
27160
27373
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
27161
27374
|
throw new Error(
|
|
27162
|
-
`${
|
|
27375
|
+
`${path37.basename(sourceFile)}: Cursor agent requires a non-empty description field`
|
|
27163
27376
|
);
|
|
27164
27377
|
}
|
|
27165
27378
|
const frontmatter = {
|
|
@@ -27196,7 +27409,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
27196
27409
|
"permission",
|
|
27197
27410
|
"permission-coarsening"
|
|
27198
27411
|
),
|
|
27199
|
-
detail: `${
|
|
27412
|
+
detail: `${path37.basename(sourceFile)}: per-agent tool allow set coarsened to readonly=${readonly} boolean (Cursor only exposes readonly control)`
|
|
27200
27413
|
}
|
|
27201
27414
|
]
|
|
27202
27415
|
});
|
|
@@ -27215,7 +27428,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
27215
27428
|
"provider",
|
|
27216
27429
|
"provider-not-representable"
|
|
27217
27430
|
),
|
|
27218
|
-
detail: `${
|
|
27431
|
+
detail: `${path37.basename(sourceFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
27219
27432
|
}
|
|
27220
27433
|
]
|
|
27221
27434
|
});
|
|
@@ -27247,7 +27460,7 @@ function compileClineAgent(sourceFile, _data, _body, relativeSource, lossReport)
|
|
|
27247
27460
|
"persona",
|
|
27248
27461
|
"persona-not-representable"
|
|
27249
27462
|
),
|
|
27250
|
-
detail: `${
|
|
27463
|
+
detail: `${path37.basename(sourceFile)}: Cline has no committable per-agent persona file for the VSCode extension target; configure the agent through Cline Settings \u2192 Agent.`
|
|
27251
27464
|
}
|
|
27252
27465
|
]
|
|
27253
27466
|
});
|
|
@@ -27295,7 +27508,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
27295
27508
|
field,
|
|
27296
27509
|
"model-not-representable"
|
|
27297
27510
|
),
|
|
27298
|
-
detail: `${
|
|
27511
|
+
detail: `${path37.basename(sourceFile)}: model tier '${String(value)}' has no stable Copilot model literal; omitted so VS Code uses the selected model.`
|
|
27299
27512
|
});
|
|
27300
27513
|
return;
|
|
27301
27514
|
}
|
|
@@ -27313,9 +27526,9 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
27313
27526
|
lossReport,
|
|
27314
27527
|
target,
|
|
27315
27528
|
"agents",
|
|
27316
|
-
`agents/${
|
|
27529
|
+
`agents/${path37.basename(sourceFile)}`,
|
|
27317
27530
|
"info",
|
|
27318
|
-
`${
|
|
27531
|
+
`${path37.basename(sourceFile)}: ${field} is delivered through another managed surface.`
|
|
27319
27532
|
);
|
|
27320
27533
|
return;
|
|
27321
27534
|
}
|
|
@@ -27324,7 +27537,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
27324
27537
|
field,
|
|
27325
27538
|
action: entryType,
|
|
27326
27539
|
severity: resolveLossSeverity("agent-field", field, entryType),
|
|
27327
|
-
detail: `${
|
|
27540
|
+
detail: `${path37.basename(sourceFile)}: ${field} has no emitted field for this target.`
|
|
27328
27541
|
});
|
|
27329
27542
|
}
|
|
27330
27543
|
function mapToolsToCapabilities(value, mappings) {
|
|
@@ -27788,13 +28001,13 @@ function addHookLoss(lossReport, target, eventName, sourceLabel, severity, reaso
|
|
|
27788
28001
|
|
|
27789
28002
|
// src/compiler/command-as-skill.ts
|
|
27790
28003
|
var import_yaml9 = __toESM(require_dist(), 1);
|
|
27791
|
-
import
|
|
27792
|
-
import
|
|
28004
|
+
import fs39 from "fs";
|
|
28005
|
+
import path38 from "path";
|
|
27793
28006
|
var CARRIED_OVER = ["argument-hint", "agent", "launch"];
|
|
27794
28007
|
function compileCommandAsSkill(commandFile, target) {
|
|
27795
|
-
const name =
|
|
28008
|
+
const name = path38.basename(commandFile, ".md");
|
|
27796
28009
|
const { data, body } = parseMarkdownFrontmatter(commandFile);
|
|
27797
|
-
const relativeSource = `commands/${
|
|
28010
|
+
const relativeSource = `commands/${path38.basename(commandFile)}`;
|
|
27798
28011
|
const description = typeof data.description === "string" && data.description.trim().length > 0 ? data.description.trim() : `The ${name} command.`;
|
|
27799
28012
|
const frontmatter = { name, description };
|
|
27800
28013
|
for (const key of CARRIED_OVER) {
|
|
@@ -27817,11 +28030,11 @@ ${body.trim()}
|
|
|
27817
28030
|
return { name, content, relativeSource };
|
|
27818
28031
|
}
|
|
27819
28032
|
function compileCommandsAsSkills(commandsRoot, target) {
|
|
27820
|
-
if (!
|
|
28033
|
+
if (!fs39.existsSync(commandsRoot)) {
|
|
27821
28034
|
return [];
|
|
27822
28035
|
}
|
|
27823
|
-
return
|
|
27824
|
-
(entry) => compileCommandAsSkill(
|
|
28036
|
+
return fs39.readdirSync(commandsRoot).filter((entry) => entry.endsWith(".md")).sort().map(
|
|
28037
|
+
(entry) => compileCommandAsSkill(path38.join(commandsRoot, entry), target)
|
|
27825
28038
|
);
|
|
27826
28039
|
}
|
|
27827
28040
|
|
|
@@ -28104,9 +28317,9 @@ function compileOpenCodeMcp(sourceMcpJson, lossReport, sourceLabel) {
|
|
|
28104
28317
|
}
|
|
28105
28318
|
|
|
28106
28319
|
// src/compiler/rules.ts
|
|
28107
|
-
import
|
|
28320
|
+
import path39 from "path";
|
|
28108
28321
|
var import_yaml10 = __toESM(require_dist(), 1);
|
|
28109
|
-
import
|
|
28322
|
+
import fs40 from "fs";
|
|
28110
28323
|
function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
28111
28324
|
if (target === "copilot") {
|
|
28112
28325
|
addLoss(lossReport, "copilot", "rules", {
|
|
@@ -28143,13 +28356,13 @@ function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
|
28143
28356
|
}
|
|
28144
28357
|
const appendixParts = [];
|
|
28145
28358
|
const dotRulesFiles = [];
|
|
28146
|
-
for (const ruleFile of ts(
|
|
28359
|
+
for (const ruleFile of ts(path39.join(sourceRulesDir, "*.md")).sort()) {
|
|
28147
28360
|
const parsed = parseRule(ruleFile);
|
|
28148
|
-
const name =
|
|
28361
|
+
const name = path39.basename(ruleFile, ".md");
|
|
28149
28362
|
if (parsed.mode === "exec-policy") {
|
|
28150
28363
|
dotRulesFiles.push({
|
|
28151
28364
|
name: `${name}.rules`,
|
|
28152
|
-
content: `${formatProvenanceMarker("toml", `rules/${
|
|
28365
|
+
content: `${formatProvenanceMarker("toml", `rules/${path39.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
|
|
28153
28366
|
${parsed.body}`
|
|
28154
28367
|
});
|
|
28155
28368
|
continue;
|
|
@@ -28158,7 +28371,7 @@ ${parsed.body}`
|
|
|
28158
28371
|
|
|
28159
28372
|
${parsed.body.trim()}`);
|
|
28160
28373
|
addLoss(lossReport, "codex", "rules", {
|
|
28161
|
-
source: `rules/${
|
|
28374
|
+
source: `rules/${path39.basename(ruleFile)}`,
|
|
28162
28375
|
fields: [
|
|
28163
28376
|
{
|
|
28164
28377
|
field: "mode",
|
|
@@ -28168,7 +28381,7 @@ ${parsed.body.trim()}`);
|
|
|
28168
28381
|
"mode",
|
|
28169
28382
|
"rule-as-instruction"
|
|
28170
28383
|
),
|
|
28171
|
-
detail: `${
|
|
28384
|
+
detail: `${path39.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
|
|
28172
28385
|
}
|
|
28173
28386
|
]
|
|
28174
28387
|
});
|
|
@@ -28176,7 +28389,7 @@ ${parsed.body.trim()}`);
|
|
|
28176
28389
|
return { agentsAppendix: appendixParts.join("\n\n"), dotRulesFiles };
|
|
28177
28390
|
}
|
|
28178
28391
|
function parseRule(ruleFile) {
|
|
28179
|
-
const content =
|
|
28392
|
+
const content = fs40.readFileSync(ruleFile, "utf8");
|
|
28180
28393
|
if (!content.startsWith("---\n")) {
|
|
28181
28394
|
return { mode: "guidance", body: content };
|
|
28182
28395
|
}
|
|
@@ -28200,14 +28413,14 @@ function isRuleMode(value) {
|
|
|
28200
28413
|
}
|
|
28201
28414
|
function compileOpenCodeRules(sourceRulesDir, lossReport) {
|
|
28202
28415
|
const appendixParts = [];
|
|
28203
|
-
for (const ruleFile of ts(
|
|
28416
|
+
for (const ruleFile of ts(path39.join(sourceRulesDir, "*.md")).sort()) {
|
|
28204
28417
|
const parsed = parseRule(ruleFile);
|
|
28205
|
-
const name =
|
|
28418
|
+
const name = path39.basename(ruleFile, ".md");
|
|
28206
28419
|
appendixParts.push(`## ${name}
|
|
28207
28420
|
|
|
28208
28421
|
${parsed.body.trim()}`);
|
|
28209
28422
|
addLoss(lossReport, "opencode", "rules", {
|
|
28210
|
-
source: `rules/${
|
|
28423
|
+
source: `rules/${path39.basename(ruleFile)}`,
|
|
28211
28424
|
fields: [
|
|
28212
28425
|
{
|
|
28213
28426
|
field: "rule",
|
|
@@ -28217,7 +28430,7 @@ ${parsed.body.trim()}`);
|
|
|
28217
28430
|
"rule",
|
|
28218
28431
|
"rule-path-scoping"
|
|
28219
28432
|
),
|
|
28220
|
-
detail: `${
|
|
28433
|
+
detail: `${path39.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to AGENTS.md instructions`
|
|
28221
28434
|
}
|
|
28222
28435
|
]
|
|
28223
28436
|
});
|
|
@@ -28226,9 +28439,9 @@ ${parsed.body.trim()}`);
|
|
|
28226
28439
|
}
|
|
28227
28440
|
function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
28228
28441
|
const dotRulesFiles = [];
|
|
28229
|
-
for (const ruleFile of ts(
|
|
28230
|
-
const content =
|
|
28231
|
-
const name =
|
|
28442
|
+
for (const ruleFile of ts(path39.join(sourceRulesDir, "*.md")).sort()) {
|
|
28443
|
+
const content = fs40.readFileSync(ruleFile, "utf8");
|
|
28444
|
+
const name = path39.basename(ruleFile, ".md");
|
|
28232
28445
|
let frontmatterData = {};
|
|
28233
28446
|
let body = content;
|
|
28234
28447
|
if (content.startsWith("---\n")) {
|
|
@@ -28257,7 +28470,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
|
28257
28470
|
}
|
|
28258
28471
|
const marker = formatProvenanceMarker(
|
|
28259
28472
|
"markdown",
|
|
28260
|
-
`rules/${
|
|
28473
|
+
`rules/${path39.basename(ruleFile)}`,
|
|
28261
28474
|
computeSourceHash(ruleFile),
|
|
28262
28475
|
"cursor"
|
|
28263
28476
|
);
|
|
@@ -28273,9 +28486,9 @@ ${body}`;
|
|
|
28273
28486
|
}
|
|
28274
28487
|
function compileClineRules(sourceRulesDir, lossReport) {
|
|
28275
28488
|
const dotRulesFiles = [];
|
|
28276
|
-
for (const ruleFile of ts(
|
|
28277
|
-
const content =
|
|
28278
|
-
const name =
|
|
28489
|
+
for (const ruleFile of ts(path39.join(sourceRulesDir, "*.md")).sort()) {
|
|
28490
|
+
const content = fs40.readFileSync(ruleFile, "utf8");
|
|
28491
|
+
const name = path39.basename(ruleFile, ".md");
|
|
28279
28492
|
let frontmatterData = {};
|
|
28280
28493
|
let body = content;
|
|
28281
28494
|
if (content.startsWith("---\n")) {
|
|
@@ -28292,13 +28505,13 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
28292
28505
|
}
|
|
28293
28506
|
const marker = formatProvenanceMarker(
|
|
28294
28507
|
"markdown",
|
|
28295
|
-
`rules/${
|
|
28508
|
+
`rules/${path39.basename(ruleFile)}`,
|
|
28296
28509
|
computeSourceHash(ruleFile),
|
|
28297
28510
|
"cline"
|
|
28298
28511
|
);
|
|
28299
28512
|
if (frontmatterData.mode === "exec-policy") {
|
|
28300
28513
|
addLoss(lossReport, "cline", "rules", {
|
|
28301
|
-
source: `rules/${
|
|
28514
|
+
source: `rules/${path39.basename(ruleFile)}`,
|
|
28302
28515
|
fields: [
|
|
28303
28516
|
{
|
|
28304
28517
|
field: "mode",
|
|
@@ -28308,7 +28521,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
28308
28521
|
"mode",
|
|
28309
28522
|
"rule-mode-downgrade"
|
|
28310
28523
|
),
|
|
28311
|
-
detail: `${
|
|
28524
|
+
detail: `${path39.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
|
|
28312
28525
|
}
|
|
28313
28526
|
]
|
|
28314
28527
|
});
|
|
@@ -28327,6 +28540,36 @@ ${frontmatterYaml}${body}`;
|
|
|
28327
28540
|
}
|
|
28328
28541
|
return { agentsAppendix: "", dotRulesFiles };
|
|
28329
28542
|
}
|
|
28543
|
+
function compileCopilotRules(sourceRulesDir) {
|
|
28544
|
+
if (!fs40.existsSync(sourceRulesDir)) {
|
|
28545
|
+
return [];
|
|
28546
|
+
}
|
|
28547
|
+
const files = [];
|
|
28548
|
+
for (const ruleFile of ts(path39.join(sourceRulesDir, "*.md")).sort()) {
|
|
28549
|
+
const name = path39.basename(ruleFile, ".md");
|
|
28550
|
+
const { data } = parseMarkdownFrontmatter(ruleFile);
|
|
28551
|
+
const { body } = parseRule(ruleFile);
|
|
28552
|
+
const declared = data.paths;
|
|
28553
|
+
const applyTo = Array.isArray(declared) ? declared.filter((p) => typeof p === "string").join(", ") : typeof declared === "string" && declared.trim() !== "" ? declared.trim() : "**";
|
|
28554
|
+
const frontmatter = [
|
|
28555
|
+
"---",
|
|
28556
|
+
`applyTo: ${JSON.stringify(applyTo)}`,
|
|
28557
|
+
"x-tangyr:",
|
|
28558
|
+
` source: rules/${path39.basename(ruleFile)}`,
|
|
28559
|
+
` hash: ${computeSourceHash(ruleFile)}`,
|
|
28560
|
+
" target: copilot",
|
|
28561
|
+
"---"
|
|
28562
|
+
].join("\n");
|
|
28563
|
+
files.push({
|
|
28564
|
+
name: `${name}.instructions.md`,
|
|
28565
|
+
content: `${frontmatter}
|
|
28566
|
+
|
|
28567
|
+
${body.trim()}
|
|
28568
|
+
`
|
|
28569
|
+
});
|
|
28570
|
+
}
|
|
28571
|
+
return files;
|
|
28572
|
+
}
|
|
28330
28573
|
|
|
28331
28574
|
// src/adapters/codex.ts
|
|
28332
28575
|
var skippedComponents = ["settings", "lsp", "output-styles"];
|
|
@@ -28349,7 +28592,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
28349
28592
|
rules: profile.rules
|
|
28350
28593
|
};
|
|
28351
28594
|
const rules = compileRules(
|
|
28352
|
-
|
|
28595
|
+
path40.join(sourceRoot, config.source.rules),
|
|
28353
28596
|
"codex",
|
|
28354
28597
|
mappings,
|
|
28355
28598
|
lossReport
|
|
@@ -28429,7 +28672,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
28429
28672
|
if (!shouldSkipComponent2(options, "hooks")) {
|
|
28430
28673
|
outcomes.push(
|
|
28431
28674
|
syncHookScriptsBridge({
|
|
28432
|
-
source:
|
|
28675
|
+
source: path40.resolve(sourceRoot, config.source.hooks),
|
|
28433
28676
|
destination: resolveTargetPath(paths.hook_scripts),
|
|
28434
28677
|
config,
|
|
28435
28678
|
sourceRoot,
|
|
@@ -28528,9 +28771,9 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
28528
28771
|
function buildProviderTomlSection(config, sourceRoot, mappings, scope, lossReport) {
|
|
28529
28772
|
const cp = mappings.modelTiers.custom_provider;
|
|
28530
28773
|
if (!cp) return "";
|
|
28531
|
-
const agentsDir =
|
|
28532
|
-
if (!
|
|
28533
|
-
const agentFiles = ts(
|
|
28774
|
+
const agentsDir = path40.join(sourceRoot, config.source.agents);
|
|
28775
|
+
if (!fs41.existsSync(agentsDir)) return "";
|
|
28776
|
+
const agentFiles = ts(path40.join(agentsDir, "*.md")).sort();
|
|
28534
28777
|
const hasProviderAgent = agentFiles.some((agentFile) => {
|
|
28535
28778
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
28536
28779
|
return typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
@@ -28595,7 +28838,7 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
|
|
|
28595
28838
|
}
|
|
28596
28839
|
];
|
|
28597
28840
|
for (const ruleFile of rules.dotRulesFiles) {
|
|
28598
|
-
const destination =
|
|
28841
|
+
const destination = path40.join(rulesRoot, ruleFile.name);
|
|
28599
28842
|
if (options.dryRun) {
|
|
28600
28843
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
28601
28844
|
outcomes.push({
|
|
@@ -28625,16 +28868,16 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
|
|
|
28625
28868
|
function syncInstructions(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
|
|
28626
28869
|
const source = instructionsSourcePath(sourceRoot, config);
|
|
28627
28870
|
const destination = resolveTargetPath(paths.instructions);
|
|
28628
|
-
if (!
|
|
28871
|
+
if (!fs41.existsSync(source)) {
|
|
28629
28872
|
return skippedMissingSource2("instructions", source);
|
|
28630
28873
|
}
|
|
28631
|
-
const composed = `${
|
|
28874
|
+
const composed = `${fs41.readFileSync(source, "utf8").trim()}
|
|
28632
28875
|
|
|
28633
28876
|
--- tangyr managed rules ---
|
|
28634
28877
|
${agentsAppendix}`.trim();
|
|
28635
28878
|
const marker = formatProvenanceMarker(
|
|
28636
28879
|
"markdown",
|
|
28637
|
-
|
|
28880
|
+
path40.basename(instructionsSourceLabel(sourceRoot, config)),
|
|
28638
28881
|
hashString(composed),
|
|
28639
28882
|
"codex"
|
|
28640
28883
|
);
|
|
@@ -28664,7 +28907,7 @@ function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopeP
|
|
|
28664
28907
|
return syncSkillsSlot({
|
|
28665
28908
|
config,
|
|
28666
28909
|
sourceRoot,
|
|
28667
|
-
source:
|
|
28910
|
+
source: path40.resolve(sourceRoot, config.source.skills),
|
|
28668
28911
|
destination: resolveTargetPath(paths.skills),
|
|
28669
28912
|
dryRun: options.dryRun,
|
|
28670
28913
|
logger,
|
|
@@ -28679,13 +28922,13 @@ function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopeP
|
|
|
28679
28922
|
});
|
|
28680
28923
|
}
|
|
28681
28924
|
function syncCommandsAsSkills(config, sourceRoot, paths, options, _lossReport, logger, manifest, scopePath) {
|
|
28682
|
-
const commandsRoot =
|
|
28683
|
-
if (!
|
|
28925
|
+
const commandsRoot = path40.resolve(sourceRoot, config.source.commands);
|
|
28926
|
+
if (!fs41.existsSync(commandsRoot)) {
|
|
28684
28927
|
return [skippedMissingSource2("commands", commandsRoot)];
|
|
28685
28928
|
}
|
|
28686
28929
|
const skillsRoot = resolveTargetPath(paths.skills);
|
|
28687
28930
|
return compileCommandsAsSkills(commandsRoot, "codex").map((skill) => {
|
|
28688
|
-
const destination =
|
|
28931
|
+
const destination = path40.join(skillsRoot, skill.name, "SKILL.md");
|
|
28689
28932
|
if (options.dryRun) {
|
|
28690
28933
|
logger.info(
|
|
28691
28934
|
`[dry-run] commands: compile ${skill.relativeSource} -> ${destination}`
|
|
@@ -28711,16 +28954,16 @@ function syncCommandsAsSkills(config, sourceRoot, paths, options, _lossReport, l
|
|
|
28711
28954
|
});
|
|
28712
28955
|
}
|
|
28713
28956
|
function syncAgents(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
28714
|
-
const sourceAgentsRoot =
|
|
28715
|
-
if (!
|
|
28957
|
+
const sourceAgentsRoot = path40.join(sourceRoot, config.source.agents);
|
|
28958
|
+
if (!fs41.existsSync(sourceAgentsRoot)) {
|
|
28716
28959
|
return [skippedMissingSource2("agents", sourceAgentsRoot)];
|
|
28717
28960
|
}
|
|
28718
|
-
const sourceAgents = ts(
|
|
28961
|
+
const sourceAgents = ts(path40.join(sourceAgentsRoot, "*.md")).sort();
|
|
28719
28962
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
28720
28963
|
return sourceAgents.map((agentFile) => {
|
|
28721
|
-
const destination =
|
|
28964
|
+
const destination = path40.join(
|
|
28722
28965
|
agentsRoot,
|
|
28723
|
-
`${
|
|
28966
|
+
`${path40.basename(agentFile, ".md")}.toml`
|
|
28724
28967
|
);
|
|
28725
28968
|
const compiled = compileAgent(
|
|
28726
28969
|
agentFile,
|
|
@@ -28798,7 +29041,7 @@ function syncHooks2(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
28798
29041
|
destination,
|
|
28799
29042
|
hostHooks,
|
|
28800
29043
|
stringifyJson3,
|
|
28801
|
-
!
|
|
29044
|
+
!fs41.existsSync(destination),
|
|
28802
29045
|
logger
|
|
28803
29046
|
);
|
|
28804
29047
|
return {
|
|
@@ -28811,7 +29054,7 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger, provid
|
|
|
28811
29054
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
28812
29055
|
const sourceLabel = mcpSourceLabel(config);
|
|
28813
29056
|
const destination = resolveTargetPath(paths.mcp_shared_file);
|
|
28814
|
-
if (!
|
|
29057
|
+
if (!fs41.existsSync(source)) {
|
|
28815
29058
|
if (providerToml && !options.dryRun) {
|
|
28816
29059
|
const changed2 = writeTomlManagedSection(
|
|
28817
29060
|
destination,
|
|
@@ -28826,7 +29069,7 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger, provid
|
|
|
28826
29069
|
}
|
|
28827
29070
|
return skippedMissingSource2("mcp", source);
|
|
28828
29071
|
}
|
|
28829
|
-
const sourceMcpJson = JSON.parse(
|
|
29072
|
+
const sourceMcpJson = JSON.parse(fs41.readFileSync(source, "utf8"));
|
|
28830
29073
|
const compiled = compileMcp(sourceMcpJson, "codex", lossReport, sourceLabel);
|
|
28831
29074
|
const managedContent = providerToml ? `${compiled.trimEnd()}${providerToml}` : compiled;
|
|
28832
29075
|
if (options.dryRun) {
|
|
@@ -28851,18 +29094,18 @@ function writeCompiledArtifact(component, destination, content, expectedHash, co
|
|
|
28851
29094
|
if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
28852
29095
|
return { component, status: "conflict", path: destination };
|
|
28853
29096
|
}
|
|
28854
|
-
ensureDir(
|
|
29097
|
+
ensureDir(path40.dirname(destination));
|
|
28855
29098
|
const clearedLink = clearSymlinkAtDestination(destination);
|
|
28856
29099
|
if (clearedLink !== null) {
|
|
28857
29100
|
logger.verbose(
|
|
28858
29101
|
` ${destination}: replaced a symlink to ${clearedLink} with generated content`
|
|
28859
29102
|
);
|
|
28860
29103
|
}
|
|
28861
|
-
|
|
29104
|
+
fs41.writeFileSync(destination, content);
|
|
28862
29105
|
return { component, status: "success", path: destination };
|
|
28863
29106
|
}
|
|
28864
29107
|
function writeTomlManagedSection(destination, managedContent, logger) {
|
|
28865
|
-
const current =
|
|
29108
|
+
const current = fs41.existsSync(destination) ? fs41.readFileSync(destination, "utf8") : "";
|
|
28866
29109
|
const isFirstWrite = current.length > 0 && !current.includes(managedMcpStart);
|
|
28867
29110
|
if (isFirstWrite) {
|
|
28868
29111
|
logger.warn(
|
|
@@ -28878,8 +29121,8 @@ ${managedMcpEnd}
|
|
|
28878
29121
|
if (current === next.trimStart()) {
|
|
28879
29122
|
return false;
|
|
28880
29123
|
}
|
|
28881
|
-
ensureDir(
|
|
28882
|
-
|
|
29124
|
+
ensureDir(path40.dirname(destination));
|
|
29125
|
+
fs41.writeFileSync(destination, next.trimStart());
|
|
28883
29126
|
return true;
|
|
28884
29127
|
}
|
|
28885
29128
|
function removeManagedTomlSection(content) {
|
|
@@ -28905,7 +29148,7 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
|
|
|
28905
29148
|
if (manifest && scopePath) {
|
|
28906
29149
|
backupFile(destination, manifest, scopePath);
|
|
28907
29150
|
writeManifest(scopePath, manifest);
|
|
28908
|
-
|
|
29151
|
+
fs41.rmSync(destination, { recursive: true, force: true });
|
|
28909
29152
|
} else {
|
|
28910
29153
|
const parked = parkConflictingPath(
|
|
28911
29154
|
destination,
|
|
@@ -28920,12 +29163,12 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
|
|
|
28920
29163
|
}
|
|
28921
29164
|
return true;
|
|
28922
29165
|
}
|
|
28923
|
-
|
|
29166
|
+
fs41.rmSync(destination, { recursive: true, force: true });
|
|
28924
29167
|
return true;
|
|
28925
29168
|
}
|
|
28926
29169
|
function isCompiledCurrent(destination, expectedContent, _expectedHash) {
|
|
28927
29170
|
try {
|
|
28928
|
-
return
|
|
29171
|
+
return fs41.readFileSync(destination, "utf8") === expectedContent;
|
|
28929
29172
|
} catch {
|
|
28930
29173
|
return false;
|
|
28931
29174
|
}
|
|
@@ -28941,10 +29184,10 @@ function shouldSkipComponent2(options, component) {
|
|
|
28941
29184
|
return Boolean(options.component && options.component !== component);
|
|
28942
29185
|
}
|
|
28943
29186
|
function readJsonObject4(filePath) {
|
|
28944
|
-
if (!
|
|
29187
|
+
if (!fs41.existsSync(filePath)) {
|
|
28945
29188
|
return {};
|
|
28946
29189
|
}
|
|
28947
|
-
const parsed = JSON.parse(
|
|
29190
|
+
const parsed = JSON.parse(fs41.readFileSync(filePath, "utf8"));
|
|
28948
29191
|
return isRecord5(parsed) ? parsed : {};
|
|
28949
29192
|
}
|
|
28950
29193
|
function stringifyJson3(value) {
|
|
@@ -28960,16 +29203,16 @@ function hashString(value) {
|
|
|
28960
29203
|
|
|
28961
29204
|
// src/adapters/copilot.ts
|
|
28962
29205
|
import crypto7 from "crypto";
|
|
28963
|
-
import
|
|
28964
|
-
import
|
|
29206
|
+
import fs42 from "fs";
|
|
29207
|
+
import path42 from "path";
|
|
28965
29208
|
|
|
28966
29209
|
// src/compiler/commands.ts
|
|
28967
29210
|
var import_yaml11 = __toESM(require_dist(), 1);
|
|
28968
|
-
import
|
|
29211
|
+
import path41 from "path";
|
|
28969
29212
|
function compileCommandPrompt(sourceFile) {
|
|
28970
29213
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
28971
|
-
const relativeSource = `commands/${
|
|
28972
|
-
const fields = promptFrontmatter(data,
|
|
29214
|
+
const relativeSource = `commands/${path41.basename(sourceFile)}`;
|
|
29215
|
+
const fields = promptFrontmatter(data, path41.basename(sourceFile, ".md"));
|
|
28973
29216
|
const marker = formatProvenanceMarker(
|
|
28974
29217
|
"markdown",
|
|
28975
29218
|
relativeSource,
|
|
@@ -29002,12 +29245,7 @@ function promptFrontmatter(data, defaultName) {
|
|
|
29002
29245
|
}
|
|
29003
29246
|
|
|
29004
29247
|
// src/adapters/copilot.ts
|
|
29005
|
-
var skippedComponents2 = [
|
|
29006
|
-
"rules",
|
|
29007
|
-
"settings",
|
|
29008
|
-
"lsp",
|
|
29009
|
-
"output-styles"
|
|
29010
|
-
];
|
|
29248
|
+
var skippedComponents2 = ["settings", "lsp", "output-styles"];
|
|
29011
29249
|
var legacyCopilotAgentsPath = "~/.copilot/agents";
|
|
29012
29250
|
function syncCopilot(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
29013
29251
|
const scope = options.scope ?? "global";
|
|
@@ -29018,6 +29256,7 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
29018
29256
|
}).copilot;
|
|
29019
29257
|
const paths = {
|
|
29020
29258
|
agents: profile.agents,
|
|
29259
|
+
rules: profile.rules,
|
|
29021
29260
|
skills: profile.skills,
|
|
29022
29261
|
prompts: profile.prompts,
|
|
29023
29262
|
hooks: profile.hooks,
|
|
@@ -29051,6 +29290,36 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
29051
29290
|
)
|
|
29052
29291
|
);
|
|
29053
29292
|
}
|
|
29293
|
+
if (!shouldSkipComponent3(options, "rules") && !paths.rules) {
|
|
29294
|
+
addLoss(lossReport, "copilot", "rules", {
|
|
29295
|
+
source: "rules",
|
|
29296
|
+
fields: [
|
|
29297
|
+
{
|
|
29298
|
+
field: "rules",
|
|
29299
|
+
action: "rule-path-scoping",
|
|
29300
|
+
severity: resolveLossSeverity(
|
|
29301
|
+
"agent-field",
|
|
29302
|
+
"rules",
|
|
29303
|
+
"rule-path-scoping"
|
|
29304
|
+
),
|
|
29305
|
+
detail: "Rules: no user-level rules surface for Copilot; `.github/instructions` is a repository path and has no global equivalent"
|
|
29306
|
+
}
|
|
29307
|
+
]
|
|
29308
|
+
});
|
|
29309
|
+
}
|
|
29310
|
+
if (!shouldSkipComponent3(options, "rules") && paths.rules) {
|
|
29311
|
+
outcomes.push(
|
|
29312
|
+
...syncRules2(
|
|
29313
|
+
config,
|
|
29314
|
+
sourceRoot,
|
|
29315
|
+
paths.rules,
|
|
29316
|
+
options,
|
|
29317
|
+
logger,
|
|
29318
|
+
manifest,
|
|
29319
|
+
scopePath
|
|
29320
|
+
)
|
|
29321
|
+
);
|
|
29322
|
+
}
|
|
29054
29323
|
if (!shouldSkipComponent3(options, "agents")) {
|
|
29055
29324
|
outcomes.push(...cleanupLegacyAgents(paths, options, logger));
|
|
29056
29325
|
outcomes.push(
|
|
@@ -29084,7 +29353,7 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
29084
29353
|
if (!shouldSkipComponent3(options, "hooks")) {
|
|
29085
29354
|
outcomes.push(
|
|
29086
29355
|
syncHookScriptsBridge({
|
|
29087
|
-
source:
|
|
29356
|
+
source: path42.resolve(sourceRoot, config.source.hooks),
|
|
29088
29357
|
destination: resolveTargetPath(paths.hook_scripts),
|
|
29089
29358
|
config,
|
|
29090
29359
|
sourceRoot,
|
|
@@ -29165,13 +29434,13 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
29165
29434
|
}
|
|
29166
29435
|
function syncProviderLoss2(config, sourceRoot, mappings, lossReport) {
|
|
29167
29436
|
if (!mappings.modelTiers.custom_provider) return;
|
|
29168
|
-
const agentsDir =
|
|
29169
|
-
if (!
|
|
29170
|
-
for (const agentFile of ts(
|
|
29437
|
+
const agentsDir = path42.join(sourceRoot, config.source.agents);
|
|
29438
|
+
if (!fs42.existsSync(agentsDir)) return;
|
|
29439
|
+
for (const agentFile of ts(path42.join(agentsDir, "*.md")).sort()) {
|
|
29171
29440
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
29172
29441
|
const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
29173
29442
|
if (hasProvider) {
|
|
29174
|
-
const basename =
|
|
29443
|
+
const basename = path42.basename(agentFile);
|
|
29175
29444
|
addLoss(lossReport, "copilot", "agents", {
|
|
29176
29445
|
source: `agents/${basename}`,
|
|
29177
29446
|
fields: [
|
|
@@ -29197,22 +29466,22 @@ function syncCopilotInstructions(config, sourceRoot, options, lossReport, logger
|
|
|
29197
29466
|
return [{ component: "instructions", status: "skipped", path: message }];
|
|
29198
29467
|
}
|
|
29199
29468
|
const source = instructionsSourcePath(sourceRoot, config);
|
|
29200
|
-
if (!
|
|
29469
|
+
if (!fs42.existsSync(source)) {
|
|
29201
29470
|
return [skippedMissingSource3("instructions", source)];
|
|
29202
29471
|
}
|
|
29203
|
-
const rawContent =
|
|
29472
|
+
const rawContent = fs42.readFileSync(source, "utf8");
|
|
29204
29473
|
const contentHash = hashString2(rawContent);
|
|
29205
29474
|
const marker = formatProvenanceMarker(
|
|
29206
29475
|
"markdown",
|
|
29207
|
-
|
|
29476
|
+
path42.basename(instructionsSourceLabel(sourceRoot, config)),
|
|
29208
29477
|
contentHash,
|
|
29209
29478
|
"copilot"
|
|
29210
29479
|
);
|
|
29211
29480
|
const composedContent = `${marker}
|
|
29212
29481
|
${rawContent}`;
|
|
29213
29482
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
29214
|
-
const agentsMdDest =
|
|
29215
|
-
const mirrorDest =
|
|
29483
|
+
const agentsMdDest = path42.resolve(projectRoot, "AGENTS.md");
|
|
29484
|
+
const mirrorDest = path42.resolve(
|
|
29216
29485
|
projectRoot,
|
|
29217
29486
|
".github",
|
|
29218
29487
|
"copilot-instructions.md"
|
|
@@ -29266,14 +29535,14 @@ function writeInstructionsFile(component, destination, content, contentHash, con
|
|
|
29266
29535
|
if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
|
|
29267
29536
|
return { component, status: "conflict", path: destination };
|
|
29268
29537
|
}
|
|
29269
|
-
ensureDir(
|
|
29538
|
+
ensureDir(path42.dirname(destination));
|
|
29270
29539
|
const clearedLink = clearSymlinkAtDestination(destination);
|
|
29271
29540
|
if (clearedLink !== null) {
|
|
29272
29541
|
logger.verbose(
|
|
29273
29542
|
` ${destination}: replaced a symlink to ${clearedLink} with generated content`
|
|
29274
29543
|
);
|
|
29275
29544
|
}
|
|
29276
|
-
|
|
29545
|
+
fs42.writeFileSync(destination, content);
|
|
29277
29546
|
return { component, status: "success", path: destination };
|
|
29278
29547
|
}
|
|
29279
29548
|
function hashString2(value) {
|
|
@@ -29283,7 +29552,7 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
29283
29552
|
return syncSkillsSlot({
|
|
29284
29553
|
config,
|
|
29285
29554
|
sourceRoot,
|
|
29286
|
-
source:
|
|
29555
|
+
source: path42.resolve(sourceRoot, config.source.skills),
|
|
29287
29556
|
destination: resolveTargetPath(paths.skills),
|
|
29288
29557
|
dryRun: options.dryRun,
|
|
29289
29558
|
logger,
|
|
@@ -29298,16 +29567,16 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
29298
29567
|
});
|
|
29299
29568
|
}
|
|
29300
29569
|
function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
29301
|
-
const sourceAgentsRoot =
|
|
29302
|
-
if (!
|
|
29570
|
+
const sourceAgentsRoot = path42.join(sourceRoot, config.source.agents);
|
|
29571
|
+
if (!fs42.existsSync(sourceAgentsRoot)) {
|
|
29303
29572
|
return [skippedMissingSource3("agents", sourceAgentsRoot)];
|
|
29304
29573
|
}
|
|
29305
|
-
const sourceAgents = ts(
|
|
29574
|
+
const sourceAgents = ts(path42.join(sourceAgentsRoot, "*.md")).sort();
|
|
29306
29575
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
29307
29576
|
return sourceAgents.map((agentFile) => {
|
|
29308
|
-
const destination =
|
|
29577
|
+
const destination = path42.join(
|
|
29309
29578
|
agentsRoot,
|
|
29310
|
-
`${
|
|
29579
|
+
`${path42.basename(agentFile, ".md")}.agent.md`
|
|
29311
29580
|
);
|
|
29312
29581
|
const compiled = compileAgent(
|
|
29313
29582
|
agentFile,
|
|
@@ -29335,16 +29604,16 @@ function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, l
|
|
|
29335
29604
|
});
|
|
29336
29605
|
}
|
|
29337
29606
|
function syncCommands(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
29338
|
-
const sourceCommandsRoot =
|
|
29339
|
-
if (!
|
|
29607
|
+
const sourceCommandsRoot = path42.join(sourceRoot, config.source.commands);
|
|
29608
|
+
if (!fs42.existsSync(sourceCommandsRoot)) {
|
|
29340
29609
|
return [skippedMissingSource3("commands", sourceCommandsRoot)];
|
|
29341
29610
|
}
|
|
29342
|
-
const sourceCommands = ts(
|
|
29611
|
+
const sourceCommands = ts(path42.join(sourceCommandsRoot, "*.md")).sort();
|
|
29343
29612
|
const promptsRoot = resolveTargetPath(paths.prompts);
|
|
29344
29613
|
return sourceCommands.map((commandFile) => {
|
|
29345
|
-
const destination =
|
|
29614
|
+
const destination = path42.join(
|
|
29346
29615
|
promptsRoot,
|
|
29347
|
-
`${
|
|
29616
|
+
`${path42.basename(commandFile, ".md")}.prompt.md`
|
|
29348
29617
|
);
|
|
29349
29618
|
const compiled = compileCommandPrompt(commandFile);
|
|
29350
29619
|
if (options.dryRun) {
|
|
@@ -29368,7 +29637,7 @@ function syncCommands(config, sourceRoot, paths, options, logger, manifest, scop
|
|
|
29368
29637
|
});
|
|
29369
29638
|
}
|
|
29370
29639
|
function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, logger) {
|
|
29371
|
-
const destination =
|
|
29640
|
+
const destination = path42.join(
|
|
29372
29641
|
resolveTargetPath(paths.hooks),
|
|
29373
29642
|
"tangyr-managed.json"
|
|
29374
29643
|
);
|
|
@@ -29431,10 +29700,10 @@ function syncMcp3(config, sourceRoot, paths, options, lossReport, logger) {
|
|
|
29431
29700
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
29432
29701
|
const sourceLabel = mcpSourceLabel(config);
|
|
29433
29702
|
const destination = resolveTargetPath(paths.mcp_shared_file);
|
|
29434
|
-
if (!
|
|
29703
|
+
if (!fs42.existsSync(source)) {
|
|
29435
29704
|
return skippedMissingSource3("mcp", source);
|
|
29436
29705
|
}
|
|
29437
|
-
const sourceMcpJson = JSON.parse(
|
|
29706
|
+
const sourceMcpJson = JSON.parse(fs42.readFileSync(source, "utf8"));
|
|
29438
29707
|
const compiled = compileMcp(
|
|
29439
29708
|
sourceMcpJson,
|
|
29440
29709
|
"copilot",
|
|
@@ -29456,6 +29725,36 @@ function syncMcp3(config, sourceRoot, paths, options, lossReport, logger) {
|
|
|
29456
29725
|
logger
|
|
29457
29726
|
);
|
|
29458
29727
|
}
|
|
29728
|
+
function syncRules2(config, sourceRoot, rulesSlot, options, logger, manifest, scopePath) {
|
|
29729
|
+
const sourceRulesDir = path42.resolve(sourceRoot, config.source.rules);
|
|
29730
|
+
if (!fs42.existsSync(sourceRulesDir)) {
|
|
29731
|
+
return [skippedMissingSource3("rules", sourceRulesDir)];
|
|
29732
|
+
}
|
|
29733
|
+
const destinationRoot = resolveTargetPath(rulesSlot);
|
|
29734
|
+
return compileCopilotRules(sourceRulesDir).map((file) => {
|
|
29735
|
+
const destination = path42.join(destinationRoot, file.name);
|
|
29736
|
+
if (options.dryRun) {
|
|
29737
|
+
logger.info(`[dry-run] rules: compile -> ${destination}`);
|
|
29738
|
+
return {
|
|
29739
|
+
component: "rules",
|
|
29740
|
+
status: "dry-run",
|
|
29741
|
+
path: destination
|
|
29742
|
+
};
|
|
29743
|
+
}
|
|
29744
|
+
return writeCompiledArtifact2(
|
|
29745
|
+
"rules",
|
|
29746
|
+
destination,
|
|
29747
|
+
file.content,
|
|
29748
|
+
void 0,
|
|
29749
|
+
config,
|
|
29750
|
+
sourceRoot,
|
|
29751
|
+
options,
|
|
29752
|
+
logger,
|
|
29753
|
+
manifest,
|
|
29754
|
+
scopePath
|
|
29755
|
+
);
|
|
29756
|
+
});
|
|
29757
|
+
}
|
|
29459
29758
|
function writeCompiledArtifact2(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
|
|
29460
29759
|
if (!options.force && isCompiledCurrent2(destination, content, expectedHash)) {
|
|
29461
29760
|
return { component, status: "skipped-current", path: destination };
|
|
@@ -29467,19 +29766,19 @@ function writeCompiledArtifact2(component, destination, content, expectedHash, c
|
|
|
29467
29766
|
if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
|
|
29468
29767
|
return { component, status: "conflict", path: destination };
|
|
29469
29768
|
}
|
|
29470
|
-
ensureDir(
|
|
29769
|
+
ensureDir(path42.dirname(destination));
|
|
29471
29770
|
const clearedLink = clearSymlinkAtDestination(destination);
|
|
29472
29771
|
if (clearedLink !== null) {
|
|
29473
29772
|
logger.verbose(
|
|
29474
29773
|
` ${destination}: replaced a symlink to ${clearedLink} with generated content`
|
|
29475
29774
|
);
|
|
29476
29775
|
}
|
|
29477
|
-
|
|
29776
|
+
fs42.writeFileSync(destination, content);
|
|
29478
29777
|
return { component, status: "success", path: destination };
|
|
29479
29778
|
}
|
|
29480
29779
|
function isCompiledCurrent2(destination, expectedContent, _expectedHash) {
|
|
29481
29780
|
try {
|
|
29482
|
-
return
|
|
29781
|
+
return fs42.readFileSync(destination, "utf8") === expectedContent;
|
|
29483
29782
|
} catch {
|
|
29484
29783
|
return false;
|
|
29485
29784
|
}
|
|
@@ -29499,7 +29798,7 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
|
|
|
29499
29798
|
if (manifest && scopePath) {
|
|
29500
29799
|
backupFile(destination, manifest, scopePath);
|
|
29501
29800
|
writeManifest(scopePath, manifest);
|
|
29502
|
-
|
|
29801
|
+
fs42.rmSync(destination, { recursive: true, force: true });
|
|
29503
29802
|
} else {
|
|
29504
29803
|
const parked = parkConflictingPath(
|
|
29505
29804
|
destination,
|
|
@@ -29514,7 +29813,7 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
|
|
|
29514
29813
|
}
|
|
29515
29814
|
return true;
|
|
29516
29815
|
}
|
|
29517
|
-
|
|
29816
|
+
fs42.rmSync(destination, { recursive: true, force: true });
|
|
29518
29817
|
return true;
|
|
29519
29818
|
}
|
|
29520
29819
|
function shouldSkipComponent3(options, component) {
|
|
@@ -29523,12 +29822,12 @@ function shouldSkipComponent3(options, component) {
|
|
|
29523
29822
|
function cleanupLegacyAgents(paths, options, logger) {
|
|
29524
29823
|
const currentAgentsRoot = resolveTargetPath(paths.agents);
|
|
29525
29824
|
const legacyAgentsRoot = resolveTargetPath(legacyCopilotAgentsPath);
|
|
29526
|
-
if (
|
|
29825
|
+
if (path42.resolve(currentAgentsRoot) === path42.resolve(legacyAgentsRoot)) {
|
|
29527
29826
|
return [];
|
|
29528
29827
|
}
|
|
29529
29828
|
const outcomes = [];
|
|
29530
29829
|
for (const filePath of ts(
|
|
29531
|
-
|
|
29830
|
+
path42.join(legacyAgentsRoot, "*.agent.md")
|
|
29532
29831
|
).sort()) {
|
|
29533
29832
|
if (!isCopilotManagedCompiledFile(filePath)) {
|
|
29534
29833
|
continue;
|
|
@@ -29538,14 +29837,14 @@ function cleanupLegacyAgents(paths, options, logger) {
|
|
|
29538
29837
|
outcomes.push({ component: "agents", status: "dry-run", path: filePath });
|
|
29539
29838
|
continue;
|
|
29540
29839
|
}
|
|
29541
|
-
|
|
29840
|
+
fs42.rmSync(filePath, { force: true });
|
|
29542
29841
|
outcomes.push({ component: "agents", status: "success", path: filePath });
|
|
29543
29842
|
}
|
|
29544
29843
|
return outcomes;
|
|
29545
29844
|
}
|
|
29546
29845
|
function isCopilotManagedCompiledFile(filePath) {
|
|
29547
29846
|
try {
|
|
29548
|
-
return extractProvenanceMarker(
|
|
29847
|
+
return extractProvenanceMarker(fs42.readFileSync(filePath, "utf8"))?.target === "copilot";
|
|
29549
29848
|
} catch {
|
|
29550
29849
|
return false;
|
|
29551
29850
|
}
|
|
@@ -29560,8 +29859,8 @@ function skippedMissingSource3(component, source) {
|
|
|
29560
29859
|
|
|
29561
29860
|
// src/adapters/cursor.ts
|
|
29562
29861
|
import crypto8 from "crypto";
|
|
29563
|
-
import
|
|
29564
|
-
import
|
|
29862
|
+
import fs43 from "fs";
|
|
29863
|
+
import path43 from "path";
|
|
29565
29864
|
function syncCursor(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
29566
29865
|
const scope = options.scope ?? "global";
|
|
29567
29866
|
const profile = resolveTargetPaths({
|
|
@@ -29614,7 +29913,7 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
|
|
|
29614
29913
|
}
|
|
29615
29914
|
if (!shouldSkipComponent4(options, "rules")) {
|
|
29616
29915
|
outcomes.push(
|
|
29617
|
-
...
|
|
29916
|
+
...syncRules3(
|
|
29618
29917
|
config,
|
|
29619
29918
|
sourceRoot,
|
|
29620
29919
|
paths,
|
|
@@ -29673,7 +29972,7 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
|
|
|
29673
29972
|
if (!shouldSkipComponent4(options, "hooks")) {
|
|
29674
29973
|
outcomes.push(
|
|
29675
29974
|
syncHookScriptsBridge({
|
|
29676
|
-
source:
|
|
29975
|
+
source: path43.resolve(sourceRoot, config.source.hooks),
|
|
29677
29976
|
destination: resolveTargetPath(paths.hook_scripts),
|
|
29678
29977
|
config,
|
|
29679
29978
|
sourceRoot,
|
|
@@ -29738,7 +30037,7 @@ function syncInstructions2(config, sourceRoot, paths, options, lossReport, logge
|
|
|
29738
30037
|
const composed = composeCursorInstructions(config, sourceRoot, lossReport);
|
|
29739
30038
|
const marker = formatProvenanceMarker(
|
|
29740
30039
|
"markdown",
|
|
29741
|
-
|
|
30040
|
+
path43.basename(instructionsSourceLabel(sourceRoot, config)),
|
|
29742
30041
|
hashString3(composed),
|
|
29743
30042
|
"cursor"
|
|
29744
30043
|
);
|
|
@@ -29764,7 +30063,7 @@ ${composed}
|
|
|
29764
30063
|
}
|
|
29765
30064
|
function composeCursorInstructions(config, sourceRoot, lossReport) {
|
|
29766
30065
|
const source = instructionsSourcePath(sourceRoot, config);
|
|
29767
|
-
const baseContent =
|
|
30066
|
+
const baseContent = fs43.existsSync(source) ? fs43.readFileSync(source, "utf8").trim() : "";
|
|
29768
30067
|
const personaContent = extractPrimaryPersonaContent(
|
|
29769
30068
|
config,
|
|
29770
30069
|
sourceRoot,
|
|
@@ -29777,11 +30076,11 @@ function composeCursorInstructions(config, sourceRoot, lossReport) {
|
|
|
29777
30076
|
${personaContent}`.trim() : baseContent;
|
|
29778
30077
|
}
|
|
29779
30078
|
function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
29780
|
-
const agentsDir =
|
|
29781
|
-
if (!
|
|
30079
|
+
const agentsDir = path43.join(sourceRoot, config.source.agents);
|
|
30080
|
+
if (!fs43.existsSync(agentsDir)) {
|
|
29782
30081
|
return null;
|
|
29783
30082
|
}
|
|
29784
|
-
const agentFiles = ts(
|
|
30083
|
+
const agentFiles = ts(path43.join(agentsDir, "*.md")).sort();
|
|
29785
30084
|
if (agentFiles.length === 0) {
|
|
29786
30085
|
return null;
|
|
29787
30086
|
}
|
|
@@ -29804,7 +30103,7 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
|
29804
30103
|
return null;
|
|
29805
30104
|
}
|
|
29806
30105
|
addLoss(lossReport, "cursor", "instructions", {
|
|
29807
|
-
source: `agents/${
|
|
30106
|
+
source: `agents/${path43.basename(primaryFile)}`,
|
|
29808
30107
|
fields: [
|
|
29809
30108
|
{
|
|
29810
30109
|
field: "persona",
|
|
@@ -29814,23 +30113,23 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
|
29814
30113
|
"persona",
|
|
29815
30114
|
"instructions-shim"
|
|
29816
30115
|
),
|
|
29817
|
-
detail: `Primary persona from ${
|
|
30116
|
+
detail: `Primary persona from ${path43.basename(primaryFile)} folded into AGENTS.md (Cursor has no custom modes surface)`
|
|
29818
30117
|
}
|
|
29819
30118
|
]
|
|
29820
30119
|
});
|
|
29821
30120
|
return body.trim();
|
|
29822
30121
|
}
|
|
29823
30122
|
function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
29824
|
-
const sourceAgentsRoot =
|
|
29825
|
-
if (!
|
|
30123
|
+
const sourceAgentsRoot = path43.join(sourceRoot, config.source.agents);
|
|
30124
|
+
if (!fs43.existsSync(sourceAgentsRoot)) {
|
|
29826
30125
|
return [skippedMissingSource4("agents", sourceAgentsRoot)];
|
|
29827
30126
|
}
|
|
29828
|
-
const sourceAgents = ts(
|
|
30127
|
+
const sourceAgents = ts(path43.join(sourceAgentsRoot, "*.md")).sort();
|
|
29829
30128
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
29830
30129
|
return sourceAgents.map((agentFile) => {
|
|
29831
|
-
const destination =
|
|
30130
|
+
const destination = path43.join(
|
|
29832
30131
|
agentsRoot,
|
|
29833
|
-
`${
|
|
30132
|
+
`${path43.basename(agentFile, ".md")}.md`
|
|
29834
30133
|
);
|
|
29835
30134
|
let compiled;
|
|
29836
30135
|
try {
|
|
@@ -29870,15 +30169,15 @@ function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, l
|
|
|
29870
30169
|
);
|
|
29871
30170
|
});
|
|
29872
30171
|
}
|
|
29873
|
-
function
|
|
29874
|
-
const sourceRulesDir =
|
|
29875
|
-
if (!
|
|
30172
|
+
function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
|
|
30173
|
+
const sourceRulesDir = path43.join(sourceRoot, config.source.rules);
|
|
30174
|
+
if (!fs43.existsSync(sourceRulesDir)) {
|
|
29876
30175
|
return [skippedMissingSource4("rules", sourceRulesDir)];
|
|
29877
30176
|
}
|
|
29878
30177
|
const compiled = compileRules(sourceRulesDir, "cursor", mappings, lossReport);
|
|
29879
30178
|
const rulesDir = resolveTargetPath(paths.rules);
|
|
29880
30179
|
return compiled.dotRulesFiles.map(({ name, content }) => {
|
|
29881
|
-
const destination =
|
|
30180
|
+
const destination = path43.join(rulesDir, name);
|
|
29882
30181
|
if (options.dryRun) {
|
|
29883
30182
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
29884
30183
|
return {
|
|
@@ -29902,15 +30201,15 @@ function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
29902
30201
|
});
|
|
29903
30202
|
}
|
|
29904
30203
|
function syncCommands2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
29905
|
-
const sourceCommandsRoot =
|
|
29906
|
-
if (!
|
|
30204
|
+
const sourceCommandsRoot = path43.join(sourceRoot, config.source.commands);
|
|
30205
|
+
if (!fs43.existsSync(sourceCommandsRoot)) {
|
|
29907
30206
|
return [skippedMissingSource4("commands", sourceCommandsRoot)];
|
|
29908
30207
|
}
|
|
29909
|
-
const sourceCommands = ts(
|
|
30208
|
+
const sourceCommands = ts(path43.join(sourceCommandsRoot, "*.md")).sort();
|
|
29910
30209
|
const skillsRoot = resolveTargetPath(paths.skills);
|
|
29911
30210
|
return sourceCommands.map((commandFile) => {
|
|
29912
|
-
const baseName =
|
|
29913
|
-
const destination =
|
|
30211
|
+
const baseName = path43.basename(commandFile, ".md");
|
|
30212
|
+
const destination = path43.join(skillsRoot, baseName, "SKILL.md");
|
|
29914
30213
|
const { content } = compileCommandAsSkill(commandFile, "cursor");
|
|
29915
30214
|
if (options.dryRun) {
|
|
29916
30215
|
logger.info(
|
|
@@ -29940,7 +30239,7 @@ function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, _
|
|
|
29940
30239
|
return syncSkillsSlot({
|
|
29941
30240
|
config,
|
|
29942
30241
|
sourceRoot,
|
|
29943
|
-
source:
|
|
30242
|
+
source: path43.resolve(sourceRoot, config.source.skills),
|
|
29944
30243
|
destination,
|
|
29945
30244
|
dryRun: options.dryRun,
|
|
29946
30245
|
logger,
|
|
@@ -29988,18 +30287,18 @@ function syncHooks4(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
29988
30287
|
}
|
|
29989
30288
|
const hooksFileContent = `${JSON.stringify({ version: 1, hooks: compiled.payload }, null, 2)}
|
|
29990
30289
|
`;
|
|
29991
|
-
ensureDir(
|
|
29992
|
-
|
|
30290
|
+
ensureDir(path43.dirname(destination));
|
|
30291
|
+
fs43.writeFileSync(destination, hooksFileContent);
|
|
29993
30292
|
return { component: "hooks", status: "success", path: destination };
|
|
29994
30293
|
}
|
|
29995
30294
|
function syncMcp4(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
|
|
29996
30295
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
29997
30296
|
const sourceLabel = mcpSourceLabel(config);
|
|
29998
30297
|
const destination = resolveTargetPath(paths.mcp_file);
|
|
29999
|
-
if (!
|
|
30298
|
+
if (!fs43.existsSync(source)) {
|
|
30000
30299
|
return skippedMissingSource4("mcp", source);
|
|
30001
30300
|
}
|
|
30002
|
-
const sourceMcpJson = JSON.parse(
|
|
30301
|
+
const sourceMcpJson = JSON.parse(fs43.readFileSync(source, "utf8"));
|
|
30003
30302
|
const mcpJson = compileMcp(sourceMcpJson, "cursor", lossReport, sourceLabel);
|
|
30004
30303
|
if (options.dryRun) {
|
|
30005
30304
|
logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
|
|
@@ -30052,13 +30351,13 @@ function syncPermissions(config, paths, options, _lossReport, logger, manifest,
|
|
|
30052
30351
|
);
|
|
30053
30352
|
}
|
|
30054
30353
|
function syncProviderPin(config, sourceRoot, lossReport) {
|
|
30055
|
-
const agentsDir =
|
|
30056
|
-
if (!
|
|
30057
|
-
for (const agentFile of ts(
|
|
30354
|
+
const agentsDir = path43.join(sourceRoot, config.source.agents);
|
|
30355
|
+
if (!fs43.existsSync(agentsDir)) return;
|
|
30356
|
+
for (const agentFile of ts(path43.join(agentsDir, "*.md")).sort()) {
|
|
30058
30357
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
30059
30358
|
const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
30060
30359
|
if (hasCustomProvider) {
|
|
30061
|
-
const relativeSource = `agents/${
|
|
30360
|
+
const relativeSource = `agents/${path43.basename(agentFile)}`;
|
|
30062
30361
|
addLoss(lossReport, "cursor", "agents", {
|
|
30063
30362
|
source: relativeSource,
|
|
30064
30363
|
fields: [
|
|
@@ -30070,7 +30369,7 @@ function syncProviderPin(config, sourceRoot, lossReport) {
|
|
|
30070
30369
|
"provider",
|
|
30071
30370
|
"provider-not-representable"
|
|
30072
30371
|
),
|
|
30073
|
-
detail: `${
|
|
30372
|
+
detail: `${path43.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
30074
30373
|
}
|
|
30075
30374
|
]
|
|
30076
30375
|
});
|
|
@@ -30088,14 +30387,14 @@ function writeCompiledArtifact3(component, destination, content, expectedHash, c
|
|
|
30088
30387
|
if (artifactClass === "unmanaged-conflict" && !handleConflict4(destination, config, options, logger, manifest, scopePath)) {
|
|
30089
30388
|
return { component, status: "conflict", path: destination };
|
|
30090
30389
|
}
|
|
30091
|
-
ensureDir(
|
|
30390
|
+
ensureDir(path43.dirname(destination));
|
|
30092
30391
|
const clearedLink = clearSymlinkAtDestination(destination);
|
|
30093
30392
|
if (clearedLink !== null) {
|
|
30094
30393
|
logger.verbose(
|
|
30095
30394
|
` ${destination}: replaced a symlink to ${clearedLink} with generated content`
|
|
30096
30395
|
);
|
|
30097
30396
|
}
|
|
30098
|
-
|
|
30397
|
+
fs43.writeFileSync(destination, content);
|
|
30099
30398
|
return { component, status: "success", path: destination };
|
|
30100
30399
|
}
|
|
30101
30400
|
function handleConflict4(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -30113,7 +30412,7 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
|
|
|
30113
30412
|
if (manifest && scopePath) {
|
|
30114
30413
|
backupFile(destination, manifest, scopePath);
|
|
30115
30414
|
writeManifest(scopePath, manifest);
|
|
30116
|
-
|
|
30415
|
+
fs43.rmSync(destination, { recursive: true, force: true });
|
|
30117
30416
|
} else {
|
|
30118
30417
|
const parked = parkConflictingPath(
|
|
30119
30418
|
destination,
|
|
@@ -30128,12 +30427,12 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
|
|
|
30128
30427
|
}
|
|
30129
30428
|
return true;
|
|
30130
30429
|
}
|
|
30131
|
-
|
|
30430
|
+
fs43.rmSync(destination, { recursive: true, force: true });
|
|
30132
30431
|
return true;
|
|
30133
30432
|
}
|
|
30134
30433
|
function isCompiledCurrent3(destination, expectedContent, _expectedHash) {
|
|
30135
30434
|
try {
|
|
30136
|
-
return
|
|
30435
|
+
return fs43.readFileSync(destination, "utf8") === expectedContent;
|
|
30137
30436
|
} catch {
|
|
30138
30437
|
return false;
|
|
30139
30438
|
}
|
|
@@ -30154,8 +30453,8 @@ function hashString3(value) {
|
|
|
30154
30453
|
|
|
30155
30454
|
// src/adapters/cline.ts
|
|
30156
30455
|
import crypto9 from "crypto";
|
|
30157
|
-
import
|
|
30158
|
-
import
|
|
30456
|
+
import fs44 from "fs";
|
|
30457
|
+
import path44 from "path";
|
|
30159
30458
|
function syncCline(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
30160
30459
|
const scope = options.scope ?? "global";
|
|
30161
30460
|
const profile = resolveTargetPaths({
|
|
@@ -30202,7 +30501,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
30202
30501
|
}
|
|
30203
30502
|
if (!shouldSkipComponent5(options, "rules")) {
|
|
30204
30503
|
outcomes.push(
|
|
30205
|
-
...
|
|
30504
|
+
...syncRules4(
|
|
30206
30505
|
config,
|
|
30207
30506
|
sourceRoot,
|
|
30208
30507
|
paths,
|
|
@@ -30268,7 +30567,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
30268
30567
|
function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport, logger, manifest, scopePath) {
|
|
30269
30568
|
if (scope === "global" || paths.instructions === null) {
|
|
30270
30569
|
addLoss(lossReport, "cline", "instructions", {
|
|
30271
|
-
source:
|
|
30570
|
+
source: path44.basename(instructionsSourceLabel(sourceRoot, config)),
|
|
30272
30571
|
fields: [
|
|
30273
30572
|
{
|
|
30274
30573
|
field: "instructions",
|
|
@@ -30290,10 +30589,10 @@ function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport
|
|
|
30290
30589
|
}
|
|
30291
30590
|
const source = instructionsSourcePath(sourceRoot, config);
|
|
30292
30591
|
const destination = resolveTargetPath(paths.instructions);
|
|
30293
|
-
const baseContent =
|
|
30592
|
+
const baseContent = fs44.existsSync(source) ? fs44.readFileSync(source, "utf8").trim() : "";
|
|
30294
30593
|
const marker = formatProvenanceMarker(
|
|
30295
30594
|
"markdown",
|
|
30296
|
-
|
|
30595
|
+
path44.basename(instructionsSourceLabel(sourceRoot, config)),
|
|
30297
30596
|
hashString4(baseContent),
|
|
30298
30597
|
"cline"
|
|
30299
30598
|
);
|
|
@@ -30318,11 +30617,11 @@ ${baseContent}
|
|
|
30318
30617
|
);
|
|
30319
30618
|
}
|
|
30320
30619
|
function syncAgents4(config, sourceRoot, mappings, extensions, options, lossReport, logger) {
|
|
30321
|
-
const sourceAgentsRoot =
|
|
30322
|
-
if (!
|
|
30620
|
+
const sourceAgentsRoot = path44.join(sourceRoot, config.source.agents);
|
|
30621
|
+
if (!fs44.existsSync(sourceAgentsRoot)) {
|
|
30323
30622
|
return [skippedMissingSource5("agents", sourceAgentsRoot)];
|
|
30324
30623
|
}
|
|
30325
|
-
const sourceAgents = ts(
|
|
30624
|
+
const sourceAgents = ts(path44.join(sourceAgentsRoot, "*.md")).sort();
|
|
30326
30625
|
return sourceAgents.map((agentFile) => {
|
|
30327
30626
|
compileAgent(agentFile, "cline", mappings, extensions, lossReport);
|
|
30328
30627
|
if (options.dryRun) {
|
|
@@ -30337,15 +30636,15 @@ function syncAgents4(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
30337
30636
|
};
|
|
30338
30637
|
});
|
|
30339
30638
|
}
|
|
30340
|
-
function
|
|
30341
|
-
const sourceRulesDir =
|
|
30342
|
-
if (!
|
|
30639
|
+
function syncRules4(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
|
|
30640
|
+
const sourceRulesDir = path44.join(sourceRoot, config.source.rules);
|
|
30641
|
+
if (!fs44.existsSync(sourceRulesDir)) {
|
|
30343
30642
|
return [skippedMissingSource5("rules", sourceRulesDir)];
|
|
30344
30643
|
}
|
|
30345
30644
|
const compiled = compileRules(sourceRulesDir, "cline", mappings, lossReport);
|
|
30346
30645
|
const rulesDir = resolveTargetPath(paths.rules);
|
|
30347
30646
|
return compiled.dotRulesFiles.map(({ name, content }) => {
|
|
30348
|
-
const destination =
|
|
30647
|
+
const destination = path44.join(rulesDir, name);
|
|
30349
30648
|
if (options.dryRun) {
|
|
30350
30649
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
30351
30650
|
return {
|
|
@@ -30369,17 +30668,17 @@ function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
30369
30668
|
});
|
|
30370
30669
|
}
|
|
30371
30670
|
function syncCommands3(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
30372
|
-
const sourceCommandsRoot =
|
|
30373
|
-
if (!
|
|
30671
|
+
const sourceCommandsRoot = path44.join(sourceRoot, config.source.commands);
|
|
30672
|
+
if (!fs44.existsSync(sourceCommandsRoot)) {
|
|
30374
30673
|
return [skippedMissingSource5("commands", sourceCommandsRoot)];
|
|
30375
30674
|
}
|
|
30376
|
-
const sourceCommands = ts(
|
|
30675
|
+
const sourceCommands = ts(path44.join(sourceCommandsRoot, "*.md")).sort();
|
|
30377
30676
|
const workflowsRoot = resolveTargetPath(paths.workflows);
|
|
30378
30677
|
return sourceCommands.map((commandFile) => {
|
|
30379
|
-
const baseName =
|
|
30380
|
-
const destination =
|
|
30381
|
-
const commandContent =
|
|
30382
|
-
const relativeSource = `commands/${
|
|
30678
|
+
const baseName = path44.basename(commandFile);
|
|
30679
|
+
const destination = path44.join(workflowsRoot, baseName);
|
|
30680
|
+
const commandContent = fs44.readFileSync(commandFile, "utf8");
|
|
30681
|
+
const relativeSource = `commands/${path44.basename(commandFile)}`;
|
|
30383
30682
|
const marker = formatProvenanceMarker(
|
|
30384
30683
|
"markdown",
|
|
30385
30684
|
relativeSource,
|
|
@@ -30417,7 +30716,7 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
30417
30716
|
return syncSkillsSlot({
|
|
30418
30717
|
config,
|
|
30419
30718
|
sourceRoot,
|
|
30420
|
-
source:
|
|
30719
|
+
source: path44.resolve(sourceRoot, config.source.skills),
|
|
30421
30720
|
destination: resolveTargetPath(paths.skills),
|
|
30422
30721
|
dryRun: options.dryRun,
|
|
30423
30722
|
logger,
|
|
@@ -30450,10 +30749,10 @@ function syncMcp5(config, sourceRoot, paths, options, lossReport, logger, manife
|
|
|
30450
30749
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
30451
30750
|
const sourceLabel = mcpSourceLabel(config);
|
|
30452
30751
|
const destination = resolveTargetPath(paths.mcp_file);
|
|
30453
|
-
if (!
|
|
30752
|
+
if (!fs44.existsSync(source)) {
|
|
30454
30753
|
return skippedMissingSource5("mcp", source);
|
|
30455
30754
|
}
|
|
30456
|
-
const sourceMcpJson = JSON.parse(
|
|
30755
|
+
const sourceMcpJson = JSON.parse(fs44.readFileSync(source, "utf8"));
|
|
30457
30756
|
const mcpJson = compileMcp(sourceMcpJson, "cline", lossReport, sourceLabel);
|
|
30458
30757
|
if (options.dryRun) {
|
|
30459
30758
|
logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
|
|
@@ -30496,11 +30795,11 @@ function syncSettings2(lossReport) {
|
|
|
30496
30795
|
};
|
|
30497
30796
|
}
|
|
30498
30797
|
function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
30499
|
-
const agentsDir =
|
|
30500
|
-
if (!
|
|
30501
|
-
for (const agentFile of ts(
|
|
30798
|
+
const agentsDir = path44.join(sourceRoot, config.source.agents);
|
|
30799
|
+
if (!fs44.existsSync(agentsDir)) return;
|
|
30800
|
+
for (const agentFile of ts(path44.join(agentsDir, "*.md")).sort()) {
|
|
30502
30801
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
30503
|
-
const relativeSource = `agents/${
|
|
30802
|
+
const relativeSource = `agents/${path44.basename(agentFile)}`;
|
|
30504
30803
|
const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
30505
30804
|
if (hasCustomProvider) {
|
|
30506
30805
|
addLoss(lossReport, "cline", "agents", {
|
|
@@ -30514,7 +30813,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
|
30514
30813
|
"provider",
|
|
30515
30814
|
"provider-not-representable"
|
|
30516
30815
|
),
|
|
30517
|
-
detail: `${
|
|
30816
|
+
detail: `${path44.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
|
|
30518
30817
|
}
|
|
30519
30818
|
]
|
|
30520
30819
|
});
|
|
@@ -30532,7 +30831,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
|
30532
30831
|
"model",
|
|
30533
30832
|
"model-not-representable"
|
|
30534
30833
|
),
|
|
30535
|
-
detail: `${
|
|
30834
|
+
detail: `${path44.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
|
|
30536
30835
|
}
|
|
30537
30836
|
]
|
|
30538
30837
|
});
|
|
@@ -30550,14 +30849,14 @@ function writeCompiledArtifact4(component, destination, content, expectedHash, c
|
|
|
30550
30849
|
if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
|
|
30551
30850
|
return { component, status: "conflict", path: destination };
|
|
30552
30851
|
}
|
|
30553
|
-
ensureDir(
|
|
30852
|
+
ensureDir(path44.dirname(destination));
|
|
30554
30853
|
const clearedLink = clearSymlinkAtDestination(destination);
|
|
30555
30854
|
if (clearedLink !== null) {
|
|
30556
30855
|
logger.verbose(
|
|
30557
30856
|
` ${destination}: replaced a symlink to ${clearedLink} with generated content`
|
|
30558
30857
|
);
|
|
30559
30858
|
}
|
|
30560
|
-
|
|
30859
|
+
fs44.writeFileSync(destination, content);
|
|
30561
30860
|
return { component, status: "success", path: destination };
|
|
30562
30861
|
}
|
|
30563
30862
|
function handleConflict5(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -30575,7 +30874,7 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
|
|
|
30575
30874
|
if (manifest && scopePath) {
|
|
30576
30875
|
backupFile(destination, manifest, scopePath);
|
|
30577
30876
|
writeManifest(scopePath, manifest);
|
|
30578
|
-
|
|
30877
|
+
fs44.rmSync(destination, { recursive: true, force: true });
|
|
30579
30878
|
} else {
|
|
30580
30879
|
const parked = parkConflictingPath(
|
|
30581
30880
|
destination,
|
|
@@ -30590,12 +30889,12 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
|
|
|
30590
30889
|
}
|
|
30591
30890
|
return true;
|
|
30592
30891
|
}
|
|
30593
|
-
|
|
30892
|
+
fs44.rmSync(destination, { recursive: true, force: true });
|
|
30594
30893
|
return true;
|
|
30595
30894
|
}
|
|
30596
30895
|
function isCompiledCurrent4(destination, expectedContent, _expectedHash) {
|
|
30597
30896
|
try {
|
|
30598
|
-
return
|
|
30897
|
+
return fs44.readFileSync(destination, "utf8") === expectedContent;
|
|
30599
30898
|
} catch {
|
|
30600
30899
|
return false;
|
|
30601
30900
|
}
|
|
@@ -30616,9 +30915,9 @@ function hashString4(value) {
|
|
|
30616
30915
|
|
|
30617
30916
|
// src/adapters/opencode.ts
|
|
30618
30917
|
import crypto10 from "crypto";
|
|
30619
|
-
import
|
|
30918
|
+
import fs45 from "fs";
|
|
30620
30919
|
import os6 from "os";
|
|
30621
|
-
import
|
|
30920
|
+
import path45 from "path";
|
|
30622
30921
|
var import_yaml12 = __toESM(require_dist(), 1);
|
|
30623
30922
|
function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
30624
30923
|
const scope = options.scope ?? "global";
|
|
@@ -30636,7 +30935,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
30636
30935
|
config_doc: profile.config_doc
|
|
30637
30936
|
};
|
|
30638
30937
|
const rules = compileRules(
|
|
30639
|
-
|
|
30938
|
+
path45.join(sourceRoot, config.source.rules),
|
|
30640
30939
|
"opencode",
|
|
30641
30940
|
mappings,
|
|
30642
30941
|
lossReport
|
|
@@ -30644,7 +30943,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
30644
30943
|
const outcomes = [];
|
|
30645
30944
|
if (!shouldSkipComponent6(options, "instructions")) {
|
|
30646
30945
|
outcomes.push(
|
|
30647
|
-
syncInstructions4(
|
|
30946
|
+
...syncInstructions4(
|
|
30648
30947
|
config,
|
|
30649
30948
|
sourceRoot,
|
|
30650
30949
|
paths,
|
|
@@ -30740,14 +31039,14 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
30740
31039
|
function syncInstructions4(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
|
|
30741
31040
|
const source = instructionsSourcePath(sourceRoot, config);
|
|
30742
31041
|
const destination = resolveTargetPath(paths.instructions);
|
|
30743
|
-
const baseContent =
|
|
31042
|
+
const baseContent = fs45.existsSync(source) ? fs45.readFileSync(source, "utf8").trim() : "";
|
|
30744
31043
|
const composed = agentsAppendix ? `${baseContent}
|
|
30745
31044
|
|
|
30746
31045
|
--- tangyr managed rules ---
|
|
30747
31046
|
${agentsAppendix}`.trim() : baseContent;
|
|
30748
31047
|
const marker = formatProvenanceMarker(
|
|
30749
31048
|
"markdown",
|
|
30750
|
-
|
|
31049
|
+
path45.basename(instructionsSourceLabel(sourceRoot, config)),
|
|
30751
31050
|
hashString5(composed),
|
|
30752
31051
|
"opencode"
|
|
30753
31052
|
);
|
|
@@ -30758,9 +31057,11 @@ ${composed}
|
|
|
30758
31057
|
logger.info(
|
|
30759
31058
|
`[dry-run] instructions: generate ${source} + rules appendix -> ${destination}`
|
|
30760
31059
|
);
|
|
30761
|
-
return
|
|
31060
|
+
return [
|
|
31061
|
+
{ component: "instructions", status: "dry-run", path: destination }
|
|
31062
|
+
];
|
|
30762
31063
|
}
|
|
30763
|
-
|
|
31064
|
+
const written = writeCompiledArtifact5(
|
|
30764
31065
|
"instructions",
|
|
30765
31066
|
destination,
|
|
30766
31067
|
content,
|
|
@@ -30772,18 +31073,60 @@ ${composed}
|
|
|
30772
31073
|
manifest,
|
|
30773
31074
|
scopePath
|
|
30774
31075
|
);
|
|
31076
|
+
const declared = declareInstructions(paths);
|
|
31077
|
+
return declared === null ? [written] : [
|
|
31078
|
+
written,
|
|
31079
|
+
{ component: "instructions", status: "success", path: declared }
|
|
31080
|
+
];
|
|
31081
|
+
}
|
|
31082
|
+
function declaredInstructionsPath(paths) {
|
|
31083
|
+
const configDir = path45.dirname(resolveTargetPath(paths.config_doc));
|
|
31084
|
+
const instructions = resolveTargetPath(paths.instructions);
|
|
31085
|
+
const relative = path45.relative(configDir, instructions);
|
|
31086
|
+
if (relative === "AGENTS.md" || relative.startsWith("..")) {
|
|
31087
|
+
return null;
|
|
31088
|
+
}
|
|
31089
|
+
return relative.split(path45.sep).join("/");
|
|
31090
|
+
}
|
|
31091
|
+
function withDeclaredInstructions(existing, reference) {
|
|
31092
|
+
const listed = Array.isArray(existing) ? existing.filter((entry) => typeof entry === "string") : [];
|
|
31093
|
+
return listed.includes(reference) ? listed : [...listed, reference];
|
|
31094
|
+
}
|
|
31095
|
+
function declareInstructions(paths) {
|
|
31096
|
+
const reference = declaredInstructionsPath(paths);
|
|
31097
|
+
if (reference === null) {
|
|
31098
|
+
return null;
|
|
31099
|
+
}
|
|
31100
|
+
const destination = resolveTargetPath(paths.config_doc);
|
|
31101
|
+
let existing = {};
|
|
31102
|
+
if (fs45.existsSync(destination)) {
|
|
31103
|
+
try {
|
|
31104
|
+
existing = JSON.parse(fs45.readFileSync(destination, "utf8"));
|
|
31105
|
+
} catch {
|
|
31106
|
+
existing = {};
|
|
31107
|
+
}
|
|
31108
|
+
}
|
|
31109
|
+
const config = {
|
|
31110
|
+
$schema: "https://opencode.ai/config.json",
|
|
31111
|
+
...existing,
|
|
31112
|
+
instructions: withDeclaredInstructions(existing.instructions, reference)
|
|
31113
|
+
};
|
|
31114
|
+
ensureDir(path45.dirname(destination));
|
|
31115
|
+
fs45.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
|
|
31116
|
+
`);
|
|
31117
|
+
return destination;
|
|
30775
31118
|
}
|
|
30776
31119
|
function syncAgents5(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
30777
|
-
const sourceAgentsRoot =
|
|
30778
|
-
if (!
|
|
31120
|
+
const sourceAgentsRoot = path45.join(sourceRoot, config.source.agents);
|
|
31121
|
+
if (!fs45.existsSync(sourceAgentsRoot)) {
|
|
30779
31122
|
return [skippedMissingSource6("agents", sourceAgentsRoot)];
|
|
30780
31123
|
}
|
|
30781
|
-
const sourceAgents = ts(
|
|
31124
|
+
const sourceAgents = ts(path45.join(sourceAgentsRoot, "*.md")).sort();
|
|
30782
31125
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
30783
31126
|
return sourceAgents.map((agentFile) => {
|
|
30784
|
-
const destination =
|
|
31127
|
+
const destination = path45.join(
|
|
30785
31128
|
agentsRoot,
|
|
30786
|
-
`${
|
|
31129
|
+
`${path45.basename(agentFile, ".md")}.md`
|
|
30787
31130
|
);
|
|
30788
31131
|
let compiled;
|
|
30789
31132
|
try {
|
|
@@ -30847,11 +31190,11 @@ function applyProviderModelBinding(compiled, mappings) {
|
|
|
30847
31190
|
return `${before}${(0, import_yaml12.stringify)(fields).trim()}${after}`;
|
|
30848
31191
|
}
|
|
30849
31192
|
function syncCommands4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
30850
|
-
const sourceCommandsRoot =
|
|
30851
|
-
if (!
|
|
31193
|
+
const sourceCommandsRoot = path45.join(sourceRoot, config.source.commands);
|
|
31194
|
+
if (!fs45.existsSync(sourceCommandsRoot)) {
|
|
30852
31195
|
return [skippedMissingSource6("commands", sourceCommandsRoot)];
|
|
30853
31196
|
}
|
|
30854
|
-
const sourceCommands = ts(
|
|
31197
|
+
const sourceCommands = ts(path45.join(sourceCommandsRoot, "*.md")).sort();
|
|
30855
31198
|
const commandsRoot = resolveTargetPath(paths.commands);
|
|
30856
31199
|
return sourceCommands.map((commandFile) => {
|
|
30857
31200
|
const { data, body } = parseCommandFile(commandFile);
|
|
@@ -30865,7 +31208,7 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
|
|
|
30865
31208
|
if (typeof data.model === "string") {
|
|
30866
31209
|
frontmatter.model = data.model;
|
|
30867
31210
|
}
|
|
30868
|
-
const relativeSource = `commands/${
|
|
31211
|
+
const relativeSource = `commands/${path45.basename(commandFile)}`;
|
|
30869
31212
|
const marker = formatProvenanceMarker(
|
|
30870
31213
|
"markdown",
|
|
30871
31214
|
relativeSource,
|
|
@@ -30881,9 +31224,9 @@ ${body.trimEnd()}
|
|
|
30881
31224
|
` : `${marker}
|
|
30882
31225
|
${body.trimEnd()}
|
|
30883
31226
|
`;
|
|
30884
|
-
const destination =
|
|
31227
|
+
const destination = path45.join(
|
|
30885
31228
|
commandsRoot,
|
|
30886
|
-
`${
|
|
31229
|
+
`${path45.basename(commandFile, ".md")}.md`
|
|
30887
31230
|
);
|
|
30888
31231
|
if (options.dryRun) {
|
|
30889
31232
|
logger.info(
|
|
@@ -30913,7 +31256,7 @@ function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scop
|
|
|
30913
31256
|
return syncSkillsSlot({
|
|
30914
31257
|
config,
|
|
30915
31258
|
sourceRoot,
|
|
30916
|
-
source:
|
|
31259
|
+
source: path45.resolve(sourceRoot, config.source.skills),
|
|
30917
31260
|
destination,
|
|
30918
31261
|
dryRun: options.dryRun,
|
|
30919
31262
|
logger,
|
|
@@ -30931,13 +31274,13 @@ function syncMcp6(config, sourceRoot, paths, mappings, options, lossReport, logg
|
|
|
30931
31274
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
30932
31275
|
const sourceLabel = mcpSourceLabel(config);
|
|
30933
31276
|
const destination = resolveTargetPath(paths.config_doc);
|
|
30934
|
-
if (!
|
|
31277
|
+
if (!fs45.existsSync(source)) {
|
|
30935
31278
|
if (!options.dryRun) {
|
|
30936
31279
|
syncConfigDoc(paths, {}, lossReport, {}, mappings);
|
|
30937
31280
|
}
|
|
30938
31281
|
return skippedMissingSource6("mcp", source);
|
|
30939
31282
|
}
|
|
30940
|
-
const sourceMcpJson = JSON.parse(
|
|
31283
|
+
const sourceMcpJson = JSON.parse(fs45.readFileSync(source, "utf8"));
|
|
30941
31284
|
const mcpJson = compileMcp(
|
|
30942
31285
|
sourceMcpJson,
|
|
30943
31286
|
"opencode",
|
|
@@ -31003,9 +31346,9 @@ function syncProviderBlock(mappings) {
|
|
|
31003
31346
|
function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings) {
|
|
31004
31347
|
const destination = resolveTargetPath(paths.config_doc);
|
|
31005
31348
|
let existing = {};
|
|
31006
|
-
if (
|
|
31349
|
+
if (fs45.existsSync(destination)) {
|
|
31007
31350
|
try {
|
|
31008
|
-
existing = JSON.parse(
|
|
31351
|
+
existing = JSON.parse(fs45.readFileSync(destination, "utf8"));
|
|
31009
31352
|
} catch {
|
|
31010
31353
|
existing = {};
|
|
31011
31354
|
}
|
|
@@ -31018,6 +31361,13 @@ function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings)
|
|
|
31018
31361
|
...mcpEntries
|
|
31019
31362
|
}
|
|
31020
31363
|
};
|
|
31364
|
+
const instructionsRef = declaredInstructionsPath(paths);
|
|
31365
|
+
if (instructionsRef !== null) {
|
|
31366
|
+
config.instructions = withDeclaredInstructions(
|
|
31367
|
+
existing.instructions,
|
|
31368
|
+
instructionsRef
|
|
31369
|
+
);
|
|
31370
|
+
}
|
|
31021
31371
|
if (Object.keys(permissionMap).length > 0) {
|
|
31022
31372
|
config.permission = permissionMap;
|
|
31023
31373
|
}
|
|
@@ -31030,8 +31380,8 @@ function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings)
|
|
|
31030
31380
|
};
|
|
31031
31381
|
}
|
|
31032
31382
|
}
|
|
31033
|
-
ensureDir(
|
|
31034
|
-
|
|
31383
|
+
ensureDir(path45.dirname(destination));
|
|
31384
|
+
fs45.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
|
|
31035
31385
|
`);
|
|
31036
31386
|
}
|
|
31037
31387
|
function writeCompiledArtifact5(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
|
|
@@ -31045,14 +31395,14 @@ function writeCompiledArtifact5(component, destination, content, expectedHash, c
|
|
|
31045
31395
|
if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
|
|
31046
31396
|
return { component, status: "conflict", path: destination };
|
|
31047
31397
|
}
|
|
31048
|
-
ensureDir(
|
|
31398
|
+
ensureDir(path45.dirname(destination));
|
|
31049
31399
|
const clearedLink = clearSymlinkAtDestination(destination);
|
|
31050
31400
|
if (clearedLink !== null) {
|
|
31051
31401
|
logger.verbose(
|
|
31052
31402
|
` ${destination}: replaced a symlink to ${clearedLink} with generated content`
|
|
31053
31403
|
);
|
|
31054
31404
|
}
|
|
31055
|
-
|
|
31405
|
+
fs45.writeFileSync(destination, content);
|
|
31056
31406
|
return { component, status: "success", path: destination };
|
|
31057
31407
|
}
|
|
31058
31408
|
function handleConflict6(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -31070,7 +31420,7 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
|
|
|
31070
31420
|
if (manifest && scopePath) {
|
|
31071
31421
|
backupFile(destination, manifest, scopePath);
|
|
31072
31422
|
writeManifest(scopePath, manifest);
|
|
31073
|
-
|
|
31423
|
+
fs45.rmSync(destination, { recursive: true, force: true });
|
|
31074
31424
|
} else {
|
|
31075
31425
|
const parked = parkConflictingPath(
|
|
31076
31426
|
destination,
|
|
@@ -31085,12 +31435,12 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
|
|
|
31085
31435
|
}
|
|
31086
31436
|
return true;
|
|
31087
31437
|
}
|
|
31088
|
-
|
|
31438
|
+
fs45.rmSync(destination, { recursive: true, force: true });
|
|
31089
31439
|
return true;
|
|
31090
31440
|
}
|
|
31091
31441
|
function isCompiledCurrent5(destination, expectedContent, _expectedHash) {
|
|
31092
31442
|
try {
|
|
31093
|
-
return
|
|
31443
|
+
return fs45.readFileSync(destination, "utf8") === expectedContent;
|
|
31094
31444
|
} catch {
|
|
31095
31445
|
return false;
|
|
31096
31446
|
}
|
|
@@ -31109,7 +31459,7 @@ function hashString5(value) {
|
|
|
31109
31459
|
return `sha256:${crypto10.createHash("sha256").update(value).digest("hex")}`;
|
|
31110
31460
|
}
|
|
31111
31461
|
function parseCommandFile(commandFile) {
|
|
31112
|
-
const content =
|
|
31462
|
+
const content = fs45.readFileSync(commandFile, "utf8");
|
|
31113
31463
|
if (!content.startsWith("---\n")) {
|
|
31114
31464
|
return { data: {}, body: content };
|
|
31115
31465
|
}
|
|
@@ -31129,7 +31479,7 @@ function parseCommandFile(commandFile) {
|
|
|
31129
31479
|
// src/commands/install.ts
|
|
31130
31480
|
function isBackupablePath(targetPath) {
|
|
31131
31481
|
try {
|
|
31132
|
-
const lstat =
|
|
31482
|
+
const lstat = fs46.lstatSync(targetPath);
|
|
31133
31483
|
return lstat.isSymbolicLink() || lstat.isFile() || lstat.isDirectory();
|
|
31134
31484
|
} catch {
|
|
31135
31485
|
return false;
|
|
@@ -31166,7 +31516,7 @@ async function runInstallCommand(options, logger) {
|
|
|
31166
31516
|
);
|
|
31167
31517
|
}
|
|
31168
31518
|
const kitName = resolvedKitName ?? config.kit;
|
|
31169
|
-
const kitPath = kitPathOverride ?? (options.kitPath ?
|
|
31519
|
+
const kitPath = kitPathOverride ?? (options.kitPath ? path46.resolve(options.kitPath) : config.kitPath);
|
|
31170
31520
|
if (!kitName && !kitPath) {
|
|
31171
31521
|
logger.error(
|
|
31172
31522
|
"No kit specified. Use --kit <name>, --kit-path <path>, or set 'kit'/'kitPath' in tangyr.config.yaml."
|
|
@@ -31271,8 +31621,8 @@ async function runInstallCommand(options, logger) {
|
|
|
31271
31621
|
config: options.config,
|
|
31272
31622
|
scope
|
|
31273
31623
|
});
|
|
31274
|
-
const skillsSource =
|
|
31275
|
-
const isPerSkillSkillsSlot = (f) => (f.tool === "claude-code" || f.tool === "copilot") &&
|
|
31624
|
+
const skillsSource = path46.resolve(kitInfo.path, config.source.skills);
|
|
31625
|
+
const isPerSkillSkillsSlot = (f) => (f.tool === "claude-code" || f.tool === "copilot") && path46.basename(f.path) === "skills";
|
|
31276
31626
|
const foreignSkillsSlots = new Set(
|
|
31277
31627
|
assessResult.findings.filter(
|
|
31278
31628
|
(f) => isPerSkillSkillsSlot(f) && isForeignSkillsSlotSymlink(
|
|
@@ -31310,7 +31660,7 @@ async function runInstallCommand(options, logger) {
|
|
|
31310
31660
|
let instructionsLabel;
|
|
31311
31661
|
try {
|
|
31312
31662
|
const resolved = resolveInstructionsSource(kitInfo.path, config);
|
|
31313
|
-
instructionsLabel = resolved ?
|
|
31663
|
+
instructionsLabel = resolved ? path46.relative(kitInfo.path, resolved.file) : "(none \u2014 no instructions file resolves in this kit)";
|
|
31314
31664
|
} catch (err) {
|
|
31315
31665
|
logger.error(
|
|
31316
31666
|
`[dry-run] ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -31338,7 +31688,7 @@ async function runInstallCommand(options, logger) {
|
|
|
31338
31688
|
}
|
|
31339
31689
|
}
|
|
31340
31690
|
logger.info(
|
|
31341
|
-
`[dry-run] Total: ${plannedTotal} destination(s); manifest at ${
|
|
31691
|
+
`[dry-run] Total: ${plannedTotal} destination(s); manifest at ${path46.join(scopePath, "manifest.json")}`
|
|
31342
31692
|
);
|
|
31343
31693
|
return;
|
|
31344
31694
|
}
|
|
@@ -31397,7 +31747,7 @@ ACCEPTED CONFLICTS (posture: ${posture}; ${replaceable.length} target(s)):`
|
|
|
31397
31747
|
logger.info(` - ${finding.path}`);
|
|
31398
31748
|
logger.info(` source: ${sources}`);
|
|
31399
31749
|
logger.info(
|
|
31400
|
-
` action: backup-and-replace${
|
|
31750
|
+
` action: backup-and-replace${fs46.lstatSync(finding.path).isDirectory() ? " (directory)" : ""}`
|
|
31401
31751
|
);
|
|
31402
31752
|
logger.info(` backup: ${backupLocation}`);
|
|
31403
31753
|
continue;
|
|
@@ -31505,11 +31855,28 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
|
|
|
31505
31855
|
installLossReport
|
|
31506
31856
|
);
|
|
31507
31857
|
}
|
|
31858
|
+
const instructionsByTarget = instructionsByActiveTarget(
|
|
31859
|
+
tools,
|
|
31860
|
+
scope,
|
|
31861
|
+
projectRoot,
|
|
31862
|
+
mappings
|
|
31863
|
+
);
|
|
31864
|
+
const rulesCoverage = measureRulesCoverage(
|
|
31865
|
+
tools,
|
|
31866
|
+
kitInfo.components.rules?.declared ?? [],
|
|
31867
|
+
scope,
|
|
31868
|
+
projectRoot,
|
|
31869
|
+
mappings,
|
|
31870
|
+
installLossReport,
|
|
31871
|
+
instructionsByTarget
|
|
31872
|
+
);
|
|
31508
31873
|
reportContestedInstructions(
|
|
31509
|
-
|
|
31874
|
+
instructionsByTarget,
|
|
31510
31875
|
(kitInfo.components.rules?.declared.length ?? 0) > 0,
|
|
31511
|
-
logger
|
|
31876
|
+
logger,
|
|
31877
|
+
missingRulesByTarget(rulesCoverage)
|
|
31512
31878
|
);
|
|
31879
|
+
reportRulesCoverage(rulesCoverage, logger);
|
|
31513
31880
|
for (const [relativePath, sourcePath] of collectAllFiles(kitInfo, config)) {
|
|
31514
31881
|
addFileToManifest(manifest, {
|
|
31515
31882
|
relativePath,
|
|
@@ -31521,20 +31888,20 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
|
|
|
31521
31888
|
writeManifest(scopePath, manifest);
|
|
31522
31889
|
logger.info(`
|
|
31523
31890
|
Installation complete: ${installedCount} files installed.`);
|
|
31524
|
-
logger.info(`Manifest written to ${
|
|
31891
|
+
logger.info(`Manifest written to ${path46.join(scopePath, "manifest.json")}`);
|
|
31525
31892
|
logger.info(`Kit: ${kitInfo.name} (archetype: ${kitInfo.archetype})`);
|
|
31526
31893
|
logger.info(`Scope: ${scope}`);
|
|
31527
31894
|
logger.info(`Tools: ${tools.join(", ")}`);
|
|
31528
31895
|
reportHookRejections(
|
|
31529
31896
|
installLossReport,
|
|
31530
31897
|
tools,
|
|
31531
|
-
|
|
31898
|
+
path46.resolve(kitInfo.path, "hooks"),
|
|
31532
31899
|
kitInfo.components.hooks.declared
|
|
31533
31900
|
);
|
|
31534
31901
|
const hooksConflict = reportHooksSourceConflict(
|
|
31535
31902
|
installLossReport,
|
|
31536
31903
|
tools,
|
|
31537
|
-
|
|
31904
|
+
path46.resolve(kitInfo.path, "hooks"),
|
|
31538
31905
|
kitInfo.components.hooks.declared
|
|
31539
31906
|
);
|
|
31540
31907
|
if (hooksConflict) {
|
|
@@ -31840,7 +32207,8 @@ function installClaudeCodeAdapterSlots(args) {
|
|
|
31840
32207
|
profile,
|
|
31841
32208
|
outcome,
|
|
31842
32209
|
scope,
|
|
31843
|
-
projectRoot
|
|
32210
|
+
projectRoot,
|
|
32211
|
+
mappings
|
|
31844
32212
|
);
|
|
31845
32213
|
if (!key) {
|
|
31846
32214
|
continue;
|
|
@@ -31865,8 +32233,13 @@ function installClaudeCodeAdapterSlots(args) {
|
|
|
31865
32233
|
}
|
|
31866
32234
|
return count;
|
|
31867
32235
|
}
|
|
31868
|
-
function claudeCodeOutcomeToManifestKey(profile, outcome, scope, projectRoot) {
|
|
31869
|
-
const shared =
|
|
32236
|
+
function claudeCodeOutcomeToManifestKey(profile, outcome, scope, projectRoot, mappings) {
|
|
32237
|
+
const shared = sharedKeyForDestination(
|
|
32238
|
+
outcome.path,
|
|
32239
|
+
scope,
|
|
32240
|
+
projectRoot,
|
|
32241
|
+
mappings.platformPaths
|
|
32242
|
+
);
|
|
31870
32243
|
if (shared) {
|
|
31871
32244
|
return shared;
|
|
31872
32245
|
}
|
|
@@ -31893,7 +32266,7 @@ function installClaudeCodeSkills(config, kitInfo, manifest, options, logger, sco
|
|
|
31893
32266
|
return 0;
|
|
31894
32267
|
}
|
|
31895
32268
|
try {
|
|
31896
|
-
const stat =
|
|
32269
|
+
const stat = fs46.lstatSync(destination);
|
|
31897
32270
|
if (stat.isFile() && !stat.isSymbolicLink()) {
|
|
31898
32271
|
logger.warn(
|
|
31899
32272
|
`${destination}: a regular file occupies the skills slot \u2014 skipping skills. Move or remove it, then re-run install.`
|
|
@@ -31921,17 +32294,17 @@ function installClaudeCodeSkills(config, kitInfo, manifest, options, logger, sco
|
|
|
31921
32294
|
manifest,
|
|
31922
32295
|
scopePath
|
|
31923
32296
|
);
|
|
31924
|
-
const skillsSource =
|
|
32297
|
+
const skillsSource = path46.resolve(kitInfo.path, config.source.skills);
|
|
31925
32298
|
let count = 0;
|
|
31926
32299
|
for (const outcome of outcomes) {
|
|
31927
32300
|
if (outcome.status !== "success" && outcome.status !== "skipped-current") {
|
|
31928
32301
|
continue;
|
|
31929
32302
|
}
|
|
31930
|
-
const skillName =
|
|
32303
|
+
const skillName = path46.basename(outcome.path);
|
|
31931
32304
|
addArtifactToManifest(manifest, {
|
|
31932
32305
|
relativePath: `claude-code/skills/${skillName}`,
|
|
31933
32306
|
path: outcome.path,
|
|
31934
|
-
hash: describeArtifactState(outcome.path) ?? `dir:${
|
|
32307
|
+
hash: describeArtifactState(outcome.path) ?? `dir:${path46.join(skillsSource, skillName)}`,
|
|
31935
32308
|
origin: "tangyr-managed"
|
|
31936
32309
|
});
|
|
31937
32310
|
count++;
|
|
@@ -31945,10 +32318,10 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
|
|
|
31945
32318
|
logger.verbose(` skipped (operator choice): ${placement.destination}`);
|
|
31946
32319
|
continue;
|
|
31947
32320
|
}
|
|
31948
|
-
const destDir =
|
|
31949
|
-
|
|
32321
|
+
const destDir = path46.dirname(placement.destination);
|
|
32322
|
+
fs46.mkdirSync(destDir, { recursive: true });
|
|
31950
32323
|
if (placement.type === "symlink") {
|
|
31951
|
-
if (
|
|
32324
|
+
if (fs46.existsSync(placement.destination) || isSymlink2(placement.destination)) {
|
|
31952
32325
|
removeManagedPath(placement.destination);
|
|
31953
32326
|
}
|
|
31954
32327
|
createRelativeSymlink(
|
|
@@ -31965,7 +32338,7 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
|
|
|
31965
32338
|
` symlink: ${placement.source} \u2192 ${placement.destination}`
|
|
31966
32339
|
);
|
|
31967
32340
|
} else {
|
|
31968
|
-
|
|
32341
|
+
fs46.copyFileSync(placement.source, placement.destination);
|
|
31969
32342
|
logger.verbose(` copy: ${placement.source} \u2192 ${placement.destination}`);
|
|
31970
32343
|
}
|
|
31971
32344
|
addArtifactToManifest(manifest, {
|
|
@@ -32215,7 +32588,12 @@ function countInstalledArtifacts(outcomes) {
|
|
|
32215
32588
|
).length;
|
|
32216
32589
|
}
|
|
32217
32590
|
function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", projectRoot) {
|
|
32218
|
-
const shared =
|
|
32591
|
+
const shared = sharedKeyForDestination(
|
|
32592
|
+
outcome.path,
|
|
32593
|
+
scope,
|
|
32594
|
+
projectRoot,
|
|
32595
|
+
mappings.platformPaths
|
|
32596
|
+
);
|
|
32219
32597
|
if (shared) {
|
|
32220
32598
|
return shared;
|
|
32221
32599
|
}
|
|
@@ -32257,11 +32635,11 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
32257
32635
|
if (outcome.path === mcpFile2) {
|
|
32258
32636
|
return "cline/mcp.json";
|
|
32259
32637
|
}
|
|
32260
|
-
if (outcome.path.startsWith(`${workflowsRoot}${
|
|
32261
|
-
return `cline/workflows/${
|
|
32638
|
+
if (outcome.path.startsWith(`${workflowsRoot}${path46.sep}`)) {
|
|
32639
|
+
return `cline/workflows/${path46.basename(outcome.path)}`;
|
|
32262
32640
|
}
|
|
32263
|
-
if (outcome.path.startsWith(`${rulesRoot2}${
|
|
32264
|
-
return `cline/rules/${
|
|
32641
|
+
if (outcome.path.startsWith(`${rulesRoot2}${path46.sep}`)) {
|
|
32642
|
+
return `cline/rules/${path46.basename(outcome.path)}`;
|
|
32265
32643
|
}
|
|
32266
32644
|
return null;
|
|
32267
32645
|
}
|
|
@@ -32297,14 +32675,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
32297
32675
|
if (outcome.path === permissionsFile) {
|
|
32298
32676
|
return "cursor/permissions.json";
|
|
32299
32677
|
}
|
|
32300
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
32301
|
-
return `cursor/agents/${
|
|
32678
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path46.sep}`)) {
|
|
32679
|
+
return `cursor/agents/${path46.basename(outcome.path)}`;
|
|
32302
32680
|
}
|
|
32303
|
-
if (outcome.path.startsWith(`${rulesRoot2}${
|
|
32304
|
-
return `cursor/rules/${
|
|
32681
|
+
if (outcome.path.startsWith(`${rulesRoot2}${path46.sep}`)) {
|
|
32682
|
+
return `cursor/rules/${path46.basename(outcome.path)}`;
|
|
32305
32683
|
}
|
|
32306
|
-
if (outcome.path.startsWith(`${skillsRoot2}${
|
|
32307
|
-
const rel =
|
|
32684
|
+
if (outcome.path.startsWith(`${skillsRoot2}${path46.sep}`)) {
|
|
32685
|
+
const rel = path46.relative(skillsRoot2, outcome.path);
|
|
32308
32686
|
return `cursor/skills/${rel}`;
|
|
32309
32687
|
}
|
|
32310
32688
|
return null;
|
|
@@ -32330,14 +32708,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
32330
32708
|
if (outcome.path === skillsSharedRoot) {
|
|
32331
32709
|
return "opencode/skills_shared";
|
|
32332
32710
|
}
|
|
32333
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
32334
|
-
return `opencode/agents/${
|
|
32711
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path46.sep}`)) {
|
|
32712
|
+
return `opencode/agents/${path46.basename(outcome.path)}`;
|
|
32335
32713
|
}
|
|
32336
|
-
if (outcome.path.startsWith(`${commandsRoot}${
|
|
32337
|
-
return `opencode/commands/${
|
|
32714
|
+
if (outcome.path.startsWith(`${commandsRoot}${path46.sep}`)) {
|
|
32715
|
+
return `opencode/commands/${path46.basename(outcome.path)}`;
|
|
32338
32716
|
}
|
|
32339
32717
|
if (outcome.path === configDocFile) {
|
|
32340
|
-
return `opencode/${
|
|
32718
|
+
return `opencode/${path46.basename(outcome.path)}`;
|
|
32341
32719
|
}
|
|
32342
32720
|
return null;
|
|
32343
32721
|
}
|
|
@@ -32354,26 +32732,29 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
32354
32732
|
const hooksRoot = resolveTargetPath(copilot.hooks);
|
|
32355
32733
|
const mcpFile2 = resolveTargetPath(copilot.mcp_shared_file);
|
|
32356
32734
|
const instructionsMirror = copilot.instructions !== null ? resolveTargetPath(copilot.instructions) : null;
|
|
32357
|
-
if (outcome.path.startsWith(`${
|
|
32358
|
-
return `copilot/
|
|
32735
|
+
if (copilot.rules !== null && outcome.path.startsWith(`${resolveTargetPath(copilot.rules)}${path46.sep}`)) {
|
|
32736
|
+
return `copilot/rules/${path46.relative(resolveTargetPath(copilot.rules), outcome.path)}`;
|
|
32737
|
+
}
|
|
32738
|
+
if (outcome.path.startsWith(`${skillsRoot2}${path46.sep}`)) {
|
|
32739
|
+
return `copilot/skills/${path46.relative(skillsRoot2, outcome.path)}`;
|
|
32359
32740
|
}
|
|
32360
32741
|
if (outcome.path === skillsRoot2) {
|
|
32361
32742
|
return "copilot/skills";
|
|
32362
32743
|
}
|
|
32363
32744
|
if (instructionsMirror !== null && outcome.path === instructionsMirror) {
|
|
32364
|
-
return `copilot/${
|
|
32745
|
+
return `copilot/${path46.basename(outcome.path)}`;
|
|
32365
32746
|
}
|
|
32366
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
32367
|
-
return `copilot/agents/${
|
|
32747
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path46.sep}`)) {
|
|
32748
|
+
return `copilot/agents/${path46.basename(outcome.path)}`;
|
|
32368
32749
|
}
|
|
32369
|
-
if (outcome.path.startsWith(`${promptsRoot}${
|
|
32370
|
-
return `copilot/prompts/${
|
|
32750
|
+
if (outcome.path.startsWith(`${promptsRoot}${path46.sep}`)) {
|
|
32751
|
+
return `copilot/prompts/${path46.basename(outcome.path)}`;
|
|
32371
32752
|
}
|
|
32372
|
-
if (outcome.path.startsWith(`${hooksRoot}${
|
|
32373
|
-
return `copilot/hooks/${
|
|
32753
|
+
if (outcome.path.startsWith(`${hooksRoot}${path46.sep}`)) {
|
|
32754
|
+
return `copilot/hooks/${path46.basename(outcome.path)}`;
|
|
32374
32755
|
}
|
|
32375
32756
|
if (outcome.path === mcpFile2) {
|
|
32376
|
-
return `copilot/${
|
|
32757
|
+
return `copilot/${path46.basename(outcome.path)}`;
|
|
32377
32758
|
}
|
|
32378
32759
|
return null;
|
|
32379
32760
|
}
|
|
@@ -32390,17 +32771,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
32390
32771
|
if (outcome.path === skillsRoot) {
|
|
32391
32772
|
return "codex/skills";
|
|
32392
32773
|
}
|
|
32393
|
-
if (outcome.path.startsWith(`${agentsRoot}${
|
|
32394
|
-
return `codex/agents/${
|
|
32774
|
+
if (outcome.path.startsWith(`${agentsRoot}${path46.sep}`)) {
|
|
32775
|
+
return `codex/agents/${path46.basename(outcome.path)}`;
|
|
32395
32776
|
}
|
|
32396
|
-
if (outcome.path.startsWith(`${rulesRoot}${
|
|
32397
|
-
return `codex/rules/${
|
|
32777
|
+
if (outcome.path.startsWith(`${rulesRoot}${path46.sep}`)) {
|
|
32778
|
+
return `codex/rules/${path46.basename(outcome.path)}`;
|
|
32398
32779
|
}
|
|
32399
32780
|
if (outcome.path === hooksFile) {
|
|
32400
|
-
return `codex/${
|
|
32781
|
+
return `codex/${path46.basename(outcome.path)}`;
|
|
32401
32782
|
}
|
|
32402
32783
|
if (outcome.path === mcpFile) {
|
|
32403
|
-
return `codex/${
|
|
32784
|
+
return `codex/${path46.basename(outcome.path)}`;
|
|
32404
32785
|
}
|
|
32405
32786
|
return null;
|
|
32406
32787
|
}
|
|
@@ -32469,8 +32850,8 @@ function getClaudeCodePlacements(kitInfo, config, scope = "global", projectRoot,
|
|
|
32469
32850
|
rules: resolvedPaths.rules
|
|
32470
32851
|
};
|
|
32471
32852
|
for (const [component, targetPath] of Object.entries(componentDirMap)) {
|
|
32472
|
-
const componentDir =
|
|
32473
|
-
if (
|
|
32853
|
+
const componentDir = path46.join(kitInfo.path, component);
|
|
32854
|
+
if (fs46.existsSync(componentDir) && fs46.statSync(componentDir).isDirectory()) {
|
|
32474
32855
|
placements.push({
|
|
32475
32856
|
source: componentDir,
|
|
32476
32857
|
destination: targetPath,
|
|
@@ -32500,8 +32881,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile, config) {
|
|
|
32500
32881
|
rules: profile.rules
|
|
32501
32882
|
};
|
|
32502
32883
|
for (const [component, targetPath] of Object.entries(componentDirMap)) {
|
|
32503
|
-
const componentDir =
|
|
32504
|
-
if (
|
|
32884
|
+
const componentDir = path46.join(kitInfo.path, component);
|
|
32885
|
+
if (fs46.existsSync(componentDir) && fs46.statSync(componentDir).isDirectory()) {
|
|
32505
32886
|
placements.push({
|
|
32506
32887
|
source: componentDir,
|
|
32507
32888
|
destination: targetPath,
|
|
@@ -32517,7 +32898,7 @@ function collectAllFiles(kitInfo, config) {
|
|
|
32517
32898
|
const files = /* @__PURE__ */ new Map();
|
|
32518
32899
|
const entrypoint = resolveInstructionsSource(kitInfo.path, config);
|
|
32519
32900
|
if (entrypoint) {
|
|
32520
|
-
files.set(
|
|
32901
|
+
files.set(path46.basename(entrypoint.file), entrypoint.file);
|
|
32521
32902
|
}
|
|
32522
32903
|
for (const [component, reconciliation] of Object.entries(
|
|
32523
32904
|
kitInfo.components
|
|
@@ -32526,22 +32907,22 @@ function collectAllFiles(kitInfo, config) {
|
|
|
32526
32907
|
const missingSet = new Set(reconciliation.missing);
|
|
32527
32908
|
for (const entry of reconciliation.declared) {
|
|
32528
32909
|
if (missingSet.has(entry)) continue;
|
|
32529
|
-
const relPath = isSkills ?
|
|
32530
|
-
files.set(relPath,
|
|
32910
|
+
const relPath = isSkills ? path46.join(component, entry) : path46.join(component, `${entry}.md`);
|
|
32911
|
+
files.set(relPath, path46.join(kitInfo.path, relPath));
|
|
32531
32912
|
}
|
|
32532
32913
|
}
|
|
32533
32914
|
return files;
|
|
32534
32915
|
}
|
|
32535
32916
|
function readLinkTarget(p) {
|
|
32536
32917
|
try {
|
|
32537
|
-
return
|
|
32918
|
+
return fs46.readlinkSync(p);
|
|
32538
32919
|
} catch {
|
|
32539
32920
|
return null;
|
|
32540
32921
|
}
|
|
32541
32922
|
}
|
|
32542
32923
|
function isSymlink2(p) {
|
|
32543
32924
|
try {
|
|
32544
|
-
return
|
|
32925
|
+
return fs46.lstatSync(p).isSymbolicLink();
|
|
32545
32926
|
} catch {
|
|
32546
32927
|
return false;
|
|
32547
32928
|
}
|
|
@@ -32560,10 +32941,10 @@ function skillsSubPathKey(tool, outcomePath, mappings, scope, projectRoot) {
|
|
|
32560
32941
|
continue;
|
|
32561
32942
|
}
|
|
32562
32943
|
const root = resolveTargetPath(slot);
|
|
32563
|
-
if (!outcomePath.startsWith(`${root}${
|
|
32944
|
+
if (!outcomePath.startsWith(`${root}${path46.sep}`)) {
|
|
32564
32945
|
continue;
|
|
32565
32946
|
}
|
|
32566
|
-
const inside =
|
|
32947
|
+
const inside = path46.relative(root, outcomePath).split(path46.sep).join("/");
|
|
32567
32948
|
return `${tool}/skills/${inside}`;
|
|
32568
32949
|
}
|
|
32569
32950
|
return null;
|
|
@@ -32608,14 +32989,14 @@ async function runKitUpdateCommand(options, logger) {
|
|
|
32608
32989
|
}
|
|
32609
32990
|
|
|
32610
32991
|
// src/commands/list.ts
|
|
32611
|
-
import
|
|
32992
|
+
import path47 from "path";
|
|
32612
32993
|
function runListCommand(options, logger) {
|
|
32613
32994
|
let searchPaths = [];
|
|
32614
|
-
let directKitPath = options.kitPath ?
|
|
32995
|
+
let directKitPath = options.kitPath ? path47.resolve(options.kitPath) : void 0;
|
|
32615
32996
|
try {
|
|
32616
32997
|
const { config, configDir } = resolveConfig(options.config);
|
|
32617
32998
|
searchPaths = config.kitSearchPaths ?? [
|
|
32618
|
-
|
|
32999
|
+
path47.join(configDir, "operating-kits")
|
|
32619
33000
|
];
|
|
32620
33001
|
directKitPath = directKitPath ?? config.kitPath;
|
|
32621
33002
|
} catch (err) {
|
|
@@ -32690,7 +33071,7 @@ function withDirectKit(kits, directKitPath) {
|
|
|
32690
33071
|
return kits;
|
|
32691
33072
|
}
|
|
32692
33073
|
const directKit = loadKit(directKitPath);
|
|
32693
|
-
if (kits.some((kit) =>
|
|
33074
|
+
if (kits.some((kit) => path47.resolve(kit.path) === directKit.path)) {
|
|
32694
33075
|
return kits;
|
|
32695
33076
|
}
|
|
32696
33077
|
return [...kits, directKit];
|
|
@@ -32698,8 +33079,8 @@ function withDirectKit(kits, directKitPath) {
|
|
|
32698
33079
|
|
|
32699
33080
|
// src/commands/probe.ts
|
|
32700
33081
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
32701
|
-
import
|
|
32702
|
-
import
|
|
33082
|
+
import fs47 from "fs";
|
|
33083
|
+
import path48 from "path";
|
|
32703
33084
|
function runProbeCommand(options, logger) {
|
|
32704
33085
|
const { config, configDir, configSource, sourceRoot } = resolveRuntime(
|
|
32705
33086
|
options,
|
|
@@ -32727,7 +33108,7 @@ function runProbeCommand(options, logger) {
|
|
|
32727
33108
|
toProbeRow(
|
|
32728
33109
|
target,
|
|
32729
33110
|
key,
|
|
32730
|
-
scope === "project" ?
|
|
33111
|
+
scope === "project" ? path48.resolve(projectRoot ?? process.cwd(), rawPath) : rawPath
|
|
32731
33112
|
)
|
|
32732
33113
|
);
|
|
32733
33114
|
}
|
|
@@ -32749,7 +33130,7 @@ function toProbeRow(target, key, rawPath) {
|
|
|
32749
33130
|
const resolved = resolveTargetPath(rawPath);
|
|
32750
33131
|
let accessible = false;
|
|
32751
33132
|
try {
|
|
32752
|
-
|
|
33133
|
+
fs47.accessSync(resolved);
|
|
32753
33134
|
accessible = true;
|
|
32754
33135
|
} catch {
|
|
32755
33136
|
accessible = false;
|
|
@@ -32758,7 +33139,7 @@ function toProbeRow(target, key, rawPath) {
|
|
|
32758
33139
|
target,
|
|
32759
33140
|
key,
|
|
32760
33141
|
path: resolved,
|
|
32761
|
-
exists:
|
|
33142
|
+
exists: fs47.existsSync(resolved),
|
|
32762
33143
|
accessible
|
|
32763
33144
|
};
|
|
32764
33145
|
}
|
|
@@ -32776,7 +33157,7 @@ function codexRuntimeProbeRows() {
|
|
|
32776
33157
|
["binary_snap", "/snap/bin/codex"],
|
|
32777
33158
|
["binary_flatpak", "/var/lib/flatpak/exports/bin/codex"]
|
|
32778
33159
|
]) {
|
|
32779
|
-
if (
|
|
33160
|
+
if (fs47.existsSync(candidatePath)) {
|
|
32780
33161
|
rows.push(toProbeRow("codex", key, candidatePath));
|
|
32781
33162
|
}
|
|
32782
33163
|
}
|
|
@@ -32792,8 +33173,8 @@ function commandProbeRows(target, key, command, args) {
|
|
|
32792
33173
|
|
|
32793
33174
|
// src/commands/status.ts
|
|
32794
33175
|
import crypto11 from "crypto";
|
|
32795
|
-
import
|
|
32796
|
-
import
|
|
33176
|
+
import fs48 from "fs";
|
|
33177
|
+
import path49 from "path";
|
|
32797
33178
|
function runStatusCommand(options, logger) {
|
|
32798
33179
|
const { config, configDir, configSource, sourceRoot } = resolveRuntime(
|
|
32799
33180
|
options,
|
|
@@ -32899,11 +33280,11 @@ function classifyTargetRows(target, config, sourceRoot, configDir, scope, projec
|
|
|
32899
33280
|
}
|
|
32900
33281
|
}
|
|
32901
33282
|
function sourceMarkdownFiles(sourceRoot, componentPath) {
|
|
32902
|
-
const root =
|
|
32903
|
-
if (!
|
|
33283
|
+
const root = path49.join(sourceRoot, componentPath);
|
|
33284
|
+
if (!fs48.existsSync(root)) {
|
|
32904
33285
|
return [];
|
|
32905
33286
|
}
|
|
32906
|
-
return ts(
|
|
33287
|
+
return ts(path49.join(root, "*.md")).sort();
|
|
32907
33288
|
}
|
|
32908
33289
|
function notRepresentableRow(component, detail) {
|
|
32909
33290
|
return {
|
|
@@ -32914,11 +33295,11 @@ function notRepresentableRow(component, detail) {
|
|
|
32914
33295
|
};
|
|
32915
33296
|
}
|
|
32916
33297
|
function readTargetJson(filePath) {
|
|
32917
|
-
if (!
|
|
33298
|
+
if (!fs48.existsSync(filePath)) {
|
|
32918
33299
|
return { kind: "missing" };
|
|
32919
33300
|
}
|
|
32920
33301
|
try {
|
|
32921
|
-
const parsed = JSON.parse(
|
|
33302
|
+
const parsed = JSON.parse(fs48.readFileSync(filePath, "utf8"));
|
|
32922
33303
|
return { kind: "object", value: isRecord(parsed) ? parsed : {} };
|
|
32923
33304
|
} catch (err) {
|
|
32924
33305
|
return {
|
|
@@ -33007,7 +33388,7 @@ function classifyInstructions(filePath, target, expectedHash, config, sourceRoot
|
|
|
33007
33388
|
}
|
|
33008
33389
|
function compiledMcpDocument(config, sourceRoot, target) {
|
|
33009
33390
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
33010
|
-
if (!
|
|
33391
|
+
if (!fs48.existsSync(source)) {
|
|
33011
33392
|
return {};
|
|
33012
33393
|
}
|
|
33013
33394
|
const compiled = compileMcp(
|
|
@@ -33020,7 +33401,7 @@ function compiledMcpDocument(config, sourceRoot, target) {
|
|
|
33020
33401
|
return isRecord(parsed) ? parsed : {};
|
|
33021
33402
|
}
|
|
33022
33403
|
function classifyMcpDocument(config, sourceRoot, target, filePath) {
|
|
33023
|
-
if (!
|
|
33404
|
+
if (!fs48.existsSync(resolveMcpSourceFile(sourceRoot, config))) {
|
|
33024
33405
|
return notConfiguredRow("mcp", filePath);
|
|
33025
33406
|
}
|
|
33026
33407
|
return classifyJsonDocument(
|
|
@@ -33050,12 +33431,12 @@ function classifyOpenCodeFiles(config, sourceRoot, configDir, scope, projectRoot
|
|
|
33050
33431
|
const rows = [];
|
|
33051
33432
|
const instructionsSource = instructionsSourcePath(sourceRoot, config);
|
|
33052
33433
|
const rules = compileRules(
|
|
33053
|
-
|
|
33434
|
+
path49.join(sourceRoot, config.source.rules),
|
|
33054
33435
|
"opencode",
|
|
33055
33436
|
mappings,
|
|
33056
33437
|
createLossReport()
|
|
33057
33438
|
);
|
|
33058
|
-
const baseInstructions =
|
|
33439
|
+
const baseInstructions = fs48.existsSync(instructionsSource) ? fs48.readFileSync(instructionsSource, "utf8").trim() : "";
|
|
33059
33440
|
const composedInstructions = rules.agentsAppendix ? `${baseInstructions}
|
|
33060
33441
|
|
|
33061
33442
|
--- tangyr managed rules ---
|
|
@@ -33077,10 +33458,10 @@ ${rules.agentsAppendix}`.trim() : baseInstructions;
|
|
|
33077
33458
|
)) {
|
|
33078
33459
|
rows.push(
|
|
33079
33460
|
classifyCompiledFile(
|
|
33080
|
-
`agents/${
|
|
33081
|
-
|
|
33461
|
+
`agents/${path49.basename(agentFile, ".md")}`,
|
|
33462
|
+
path49.join(
|
|
33082
33463
|
resolveTargetPath(paths.agents),
|
|
33083
|
-
`${
|
|
33464
|
+
`${path49.basename(agentFile, ".md")}.md`
|
|
33084
33465
|
),
|
|
33085
33466
|
"opencode",
|
|
33086
33467
|
computeSourceHash(agentFile),
|
|
@@ -33095,10 +33476,10 @@ ${rules.agentsAppendix}`.trim() : baseInstructions;
|
|
|
33095
33476
|
)) {
|
|
33096
33477
|
rows.push(
|
|
33097
33478
|
classifyCompiledFile(
|
|
33098
|
-
`commands/${
|
|
33099
|
-
|
|
33479
|
+
`commands/${path49.basename(commandFile, ".md")}`,
|
|
33480
|
+
path49.join(
|
|
33100
33481
|
resolveTargetPath(paths.commands),
|
|
33101
|
-
`${
|
|
33482
|
+
`${path49.basename(commandFile, ".md")}.md`
|
|
33102
33483
|
),
|
|
33103
33484
|
"opencode",
|
|
33104
33485
|
computeSourceHash(commandFile),
|
|
@@ -33180,10 +33561,10 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
|
|
|
33180
33561
|
)) {
|
|
33181
33562
|
rows.push(
|
|
33182
33563
|
classifyCompiledFile(
|
|
33183
|
-
`agents/${
|
|
33184
|
-
|
|
33564
|
+
`agents/${path49.basename(agentFile, ".md")}`,
|
|
33565
|
+
path49.join(
|
|
33185
33566
|
resolveTargetPath(paths.agents),
|
|
33186
|
-
`${
|
|
33567
|
+
`${path49.basename(agentFile, ".md")}.md`
|
|
33187
33568
|
),
|
|
33188
33569
|
"cursor",
|
|
33189
33570
|
computeSourceHash(agentFile),
|
|
@@ -33200,7 +33581,7 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
|
|
|
33200
33581
|
rows.push(
|
|
33201
33582
|
classifyCompiledFile(
|
|
33202
33583
|
`rules/${ruleFile.name}`,
|
|
33203
|
-
|
|
33584
|
+
path49.join(resolveTargetPath(paths.rules), ruleFile.name),
|
|
33204
33585
|
"cursor",
|
|
33205
33586
|
void 0,
|
|
33206
33587
|
config,
|
|
@@ -33214,11 +33595,11 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
|
|
|
33214
33595
|
sourceRoot,
|
|
33215
33596
|
config.source.commands
|
|
33216
33597
|
)) {
|
|
33217
|
-
const baseName =
|
|
33598
|
+
const baseName = path49.basename(commandFile, ".md");
|
|
33218
33599
|
rows.push(
|
|
33219
33600
|
classifyCompiledFile(
|
|
33220
33601
|
`commands/${baseName}`,
|
|
33221
|
-
|
|
33602
|
+
path49.join(resolveTargetPath(paths.skills), baseName, "SKILL.md"),
|
|
33222
33603
|
"cursor",
|
|
33223
33604
|
computeSourceHash(commandFile),
|
|
33224
33605
|
config,
|
|
@@ -33301,7 +33682,7 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
|
|
|
33301
33682
|
rows.push(
|
|
33302
33683
|
classifyCompiledFile(
|
|
33303
33684
|
`rules/${ruleFile.name}`,
|
|
33304
|
-
|
|
33685
|
+
path49.join(resolveTargetPath(paths.rules), ruleFile.name),
|
|
33305
33686
|
"cline",
|
|
33306
33687
|
void 0,
|
|
33307
33688
|
config,
|
|
@@ -33317,10 +33698,10 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
|
|
|
33317
33698
|
)) {
|
|
33318
33699
|
rows.push(
|
|
33319
33700
|
classifyCompiledFile(
|
|
33320
|
-
`commands/${
|
|
33321
|
-
|
|
33701
|
+
`commands/${path49.basename(commandFile, ".md")}`,
|
|
33702
|
+
path49.join(
|
|
33322
33703
|
resolveTargetPath(paths.workflows),
|
|
33323
|
-
|
|
33704
|
+
path49.basename(commandFile)
|
|
33324
33705
|
),
|
|
33325
33706
|
"cline",
|
|
33326
33707
|
computeSourceHash(commandFile),
|
|
@@ -33361,14 +33742,14 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
|
|
|
33361
33742
|
return rows;
|
|
33362
33743
|
}
|
|
33363
33744
|
function compileRulesFiles(config, sourceRoot, target, mappings) {
|
|
33364
|
-
const rulesSource =
|
|
33365
|
-
if (!
|
|
33745
|
+
const rulesSource = path49.join(sourceRoot, config.source.rules);
|
|
33746
|
+
if (!fs48.existsSync(rulesSource)) {
|
|
33366
33747
|
return [];
|
|
33367
33748
|
}
|
|
33368
33749
|
return compileRules(rulesSource, target, mappings, createLossReport()).dotRulesFiles;
|
|
33369
33750
|
}
|
|
33370
33751
|
function classifyDirectoryPresence(component, dirPath) {
|
|
33371
|
-
const present =
|
|
33752
|
+
const present = fs48.existsSync(dirPath) && fs48.statSync(dirPath).isDirectory();
|
|
33372
33753
|
return {
|
|
33373
33754
|
component,
|
|
33374
33755
|
className: present ? "current" : "missing",
|
|
@@ -33387,7 +33768,7 @@ function slotsForScope2(scopeMap, scope, projectRoot) {
|
|
|
33387
33768
|
const root = projectRoot ?? process.cwd();
|
|
33388
33769
|
const resolved = {};
|
|
33389
33770
|
for (const [slot, value] of Object.entries(projectSlots)) {
|
|
33390
|
-
resolved[slot] = typeof value === "string" ?
|
|
33771
|
+
resolved[slot] = typeof value === "string" ? path49.resolve(root, value) : value;
|
|
33391
33772
|
}
|
|
33392
33773
|
return resolved;
|
|
33393
33774
|
}
|
|
@@ -33407,21 +33788,21 @@ function classifyCodexFiles(config, sourceRoot, configDir, scope, projectRoot) {
|
|
|
33407
33788
|
rules: paths.rules
|
|
33408
33789
|
};
|
|
33409
33790
|
const rules = compileRules(
|
|
33410
|
-
|
|
33791
|
+
path49.join(sourceRoot, config.source.rules),
|
|
33411
33792
|
"codex",
|
|
33412
33793
|
mappings,
|
|
33413
33794
|
createLossReport()
|
|
33414
33795
|
);
|
|
33415
|
-
const instructionsSource =
|
|
33796
|
+
const instructionsSource = fs48.readFileSync(instructionsSourcePath(sourceRoot, config), "utf8").trim();
|
|
33416
33797
|
const composedInstructions = `${instructionsSource}
|
|
33417
33798
|
|
|
33418
33799
|
--- tangyr managed rules ---
|
|
33419
33800
|
${rules.agentsAppendix}`.trim();
|
|
33420
33801
|
const agentFiles = ts(
|
|
33421
|
-
|
|
33802
|
+
path49.join(sourceRoot, config.source.agents, "*.md")
|
|
33422
33803
|
).sort();
|
|
33423
33804
|
const hooksPresent = hooksSourceExists(sourceRoot, config);
|
|
33424
|
-
const mcpSource =
|
|
33805
|
+
const mcpSource = path49.join(sourceRoot, config.source.mcp);
|
|
33425
33806
|
const ruleRows = rules.dotRulesFiles.length === 0 ? [
|
|
33426
33807
|
{
|
|
33427
33808
|
component: "rules",
|
|
@@ -33432,7 +33813,7 @@ ${rules.agentsAppendix}`.trim();
|
|
|
33432
33813
|
] : rules.dotRulesFiles.map(
|
|
33433
33814
|
(ruleFile) => classifyCompiledFile(
|
|
33434
33815
|
`rules/${ruleFile.name}`,
|
|
33435
|
-
|
|
33816
|
+
path49.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
|
|
33436
33817
|
"codex",
|
|
33437
33818
|
void 0,
|
|
33438
33819
|
config,
|
|
@@ -33450,10 +33831,10 @@ ${rules.agentsAppendix}`.trim();
|
|
|
33450
33831
|
),
|
|
33451
33832
|
...agentFiles.map(
|
|
33452
33833
|
(agentFile) => classifyCompiledFile(
|
|
33453
|
-
`agents/${
|
|
33454
|
-
|
|
33834
|
+
`agents/${path49.basename(agentFile, ".md")}`,
|
|
33835
|
+
path49.join(
|
|
33455
33836
|
resolveTargetPath(codexPaths.agents),
|
|
33456
|
-
`${
|
|
33837
|
+
`${path49.basename(agentFile, ".md")}.toml`
|
|
33457
33838
|
),
|
|
33458
33839
|
"codex",
|
|
33459
33840
|
computeSourceHash(agentFile),
|
|
@@ -33481,7 +33862,7 @@ ${rules.agentsAppendix}`.trim();
|
|
|
33481
33862
|
"hooks",
|
|
33482
33863
|
resolveTargetPath(codexPaths.hooksSharedFile)
|
|
33483
33864
|
),
|
|
33484
|
-
|
|
33865
|
+
fs48.existsSync(mcpSource) ? classifyCompiledFile(
|
|
33485
33866
|
"mcp",
|
|
33486
33867
|
resolveTargetPath(codexPaths.mcpSharedFile),
|
|
33487
33868
|
"codex",
|
|
@@ -33547,20 +33928,20 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
|
|
|
33547
33928
|
mcpSharedFile: paths.mcp_shared_file
|
|
33548
33929
|
};
|
|
33549
33930
|
const agentFiles = ts(
|
|
33550
|
-
|
|
33931
|
+
path49.join(sourceRoot, config.source.agents, "*.md")
|
|
33551
33932
|
).sort();
|
|
33552
33933
|
const commandFiles = ts(
|
|
33553
|
-
|
|
33934
|
+
path49.join(sourceRoot, config.source.commands, "*.md")
|
|
33554
33935
|
).sort();
|
|
33555
33936
|
const hooksPresent = hooksSourceExists(sourceRoot, config);
|
|
33556
|
-
const mcpSource =
|
|
33937
|
+
const mcpSource = path49.join(sourceRoot, config.source.mcp);
|
|
33557
33938
|
return [
|
|
33558
33939
|
...agentFiles.map(
|
|
33559
33940
|
(agentFile) => classifyCompiledFile(
|
|
33560
|
-
`agents/${
|
|
33561
|
-
|
|
33941
|
+
`agents/${path49.basename(agentFile, ".md")}`,
|
|
33942
|
+
path49.join(
|
|
33562
33943
|
resolveTargetPath(copilotPaths.agents),
|
|
33563
|
-
`${
|
|
33944
|
+
`${path49.basename(agentFile, ".md")}.agent.md`
|
|
33564
33945
|
),
|
|
33565
33946
|
"copilot",
|
|
33566
33947
|
computeSourceHash(agentFile),
|
|
@@ -33577,10 +33958,10 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
|
|
|
33577
33958
|
),
|
|
33578
33959
|
...commandFiles.map(
|
|
33579
33960
|
(commandFile) => classifyCompiledFile(
|
|
33580
|
-
`commands/${
|
|
33581
|
-
|
|
33961
|
+
`commands/${path49.basename(commandFile, ".md")}`,
|
|
33962
|
+
path49.join(
|
|
33582
33963
|
resolveTargetPath(copilotPaths.prompts),
|
|
33583
|
-
`${
|
|
33964
|
+
`${path49.basename(commandFile, ".md")}.prompt.md`
|
|
33584
33965
|
),
|
|
33585
33966
|
"copilot",
|
|
33586
33967
|
computeSourceHash(commandFile),
|
|
@@ -33599,19 +33980,19 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
|
|
|
33599
33980
|
sourceRoot
|
|
33600
33981
|
),
|
|
33601
33982
|
hooksPresent ? classifyCompiledHooksByProvenance(
|
|
33602
|
-
|
|
33983
|
+
path49.join(
|
|
33603
33984
|
resolveTargetPath(copilotPaths.hooks),
|
|
33604
33985
|
"tangyr-managed.json"
|
|
33605
33986
|
),
|
|
33606
33987
|
"copilot"
|
|
33607
33988
|
) : notConfiguredRow(
|
|
33608
33989
|
"hooks",
|
|
33609
|
-
|
|
33990
|
+
path49.join(
|
|
33610
33991
|
resolveTargetPath(copilotPaths.hooks),
|
|
33611
33992
|
"tangyr-managed.json"
|
|
33612
33993
|
)
|
|
33613
33994
|
),
|
|
33614
|
-
|
|
33995
|
+
fs48.existsSync(mcpSource) ? classifyCompiledFile(
|
|
33615
33996
|
"mcp",
|
|
33616
33997
|
resolveTargetPath(copilotPaths.mcpSharedFile),
|
|
33617
33998
|
"copilot",
|
|
@@ -33631,7 +34012,7 @@ function notConfiguredRow(component, filePath) {
|
|
|
33631
34012
|
}
|
|
33632
34013
|
function classifyDirectArtifact(artifact, config, sourceRoot) {
|
|
33633
34014
|
const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
|
|
33634
|
-
const sourcePath = artifact.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : artifact.sourceKey ?
|
|
34015
|
+
const sourcePath = artifact.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : artifact.sourceKey ? path49.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
|
|
33635
34016
|
if (artifact.sourceKey === "skills" && artifactClass === "unmanaged-conflict") {
|
|
33636
34017
|
const perSkill = classifyPerSkillSlot(artifact.path, sourceRoot);
|
|
33637
34018
|
if (perSkill) {
|
|
@@ -33727,11 +34108,11 @@ function classifyClaudeCodeRows(sourceRoot, config, configDir, scope, projectRoo
|
|
|
33727
34108
|
function classifyPerSkillSlot(slotPath, sourceRoot) {
|
|
33728
34109
|
let entries;
|
|
33729
34110
|
try {
|
|
33730
|
-
const stat =
|
|
34111
|
+
const stat = fs48.lstatSync(slotPath);
|
|
33731
34112
|
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
33732
34113
|
return null;
|
|
33733
34114
|
}
|
|
33734
|
-
entries =
|
|
34115
|
+
entries = fs48.readdirSync(slotPath, { withFileTypes: true });
|
|
33735
34116
|
} catch {
|
|
33736
34117
|
return null;
|
|
33737
34118
|
}
|
|
@@ -33743,7 +34124,7 @@ function classifyPerSkillSlot(slotPath, sourceRoot) {
|
|
|
33743
34124
|
return null;
|
|
33744
34125
|
}
|
|
33745
34126
|
const ours = links.filter(
|
|
33746
|
-
(entry) => isOurSymlink(
|
|
34127
|
+
(entry) => isOurSymlink(path49.join(slotPath, entry.name), sourceRoot)
|
|
33747
34128
|
);
|
|
33748
34129
|
if (ours.length === 0) {
|
|
33749
34130
|
return null;
|
|
@@ -33755,9 +34136,9 @@ function classifyClaudeSharedFiles(config, sourceRoot, settingsPath, claudeJsonP
|
|
|
33755
34136
|
classifyHooks(settingsPath),
|
|
33756
34137
|
classifySettings(
|
|
33757
34138
|
settingsPath,
|
|
33758
|
-
|
|
34139
|
+
path49.resolve(sourceRoot, config.source.settings)
|
|
33759
34140
|
),
|
|
33760
|
-
classifyMcp(claudeJsonPath,
|
|
34141
|
+
classifyMcp(claudeJsonPath, path49.resolve(sourceRoot, config.source.mcp))
|
|
33761
34142
|
];
|
|
33762
34143
|
}
|
|
33763
34144
|
function claudeSharedFileRows(config, sourceRoot, configDir, scope, projectRoot) {
|
|
@@ -33854,14 +34235,14 @@ function classifyMcp(filePath, sourcePath) {
|
|
|
33854
34235
|
}
|
|
33855
34236
|
function isSymlinkCurrent(linkPath, sourcePath) {
|
|
33856
34237
|
try {
|
|
33857
|
-
return
|
|
34238
|
+
return fs48.realpathSync(linkPath) === fs48.realpathSync(sourcePath);
|
|
33858
34239
|
} catch {
|
|
33859
34240
|
return false;
|
|
33860
34241
|
}
|
|
33861
34242
|
}
|
|
33862
34243
|
function isCompiledCurrent6(filePath, sourcePath) {
|
|
33863
34244
|
try {
|
|
33864
|
-
const marker = extractProvenanceMarker(
|
|
34245
|
+
const marker = extractProvenanceMarker(fs48.readFileSync(filePath, "utf8"));
|
|
33865
34246
|
return marker?.hash === computeSourceHash(sourcePath) && marker.target === "claude-code";
|
|
33866
34247
|
} catch {
|
|
33867
34248
|
return false;
|
|
@@ -33891,7 +34272,7 @@ function classifyCompiledFile(component, filePath, target, expectedHash, config,
|
|
|
33891
34272
|
}
|
|
33892
34273
|
function readCompiledContent(filePath) {
|
|
33893
34274
|
try {
|
|
33894
|
-
return
|
|
34275
|
+
return fs48.readFileSync(filePath, "utf8");
|
|
33895
34276
|
} catch {
|
|
33896
34277
|
return null;
|
|
33897
34278
|
}
|
|
@@ -33922,8 +34303,8 @@ function hashString6(value) {
|
|
|
33922
34303
|
}
|
|
33923
34304
|
|
|
33924
34305
|
// src/commands/sync.ts
|
|
33925
|
-
import
|
|
33926
|
-
import
|
|
34306
|
+
import fs49 from "fs";
|
|
34307
|
+
import path50 from "path";
|
|
33927
34308
|
|
|
33928
34309
|
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
33929
34310
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -34593,29 +34974,41 @@ async function runSyncCommand(options, logger) {
|
|
|
34593
34974
|
reportHookRejections(
|
|
34594
34975
|
lossReport,
|
|
34595
34976
|
targets,
|
|
34596
|
-
|
|
34977
|
+
path50.resolve(kitInfo.path, "hooks"),
|
|
34597
34978
|
kitInfo.components.hooks.declared
|
|
34598
34979
|
);
|
|
34599
34980
|
const hooksConflict = reportHooksSourceConflict(
|
|
34600
34981
|
lossReport,
|
|
34601
34982
|
targets,
|
|
34602
|
-
|
|
34983
|
+
path50.resolve(kitInfo.path, "hooks"),
|
|
34603
34984
|
kitInfo.components.hooks.declared
|
|
34604
34985
|
);
|
|
34605
34986
|
if (hooksConflict) {
|
|
34606
34987
|
logger.warn(hooksConflict);
|
|
34607
34988
|
}
|
|
34608
34989
|
if (allMappings) {
|
|
34990
|
+
const instructionsByTarget = instructionsByActiveTarget(
|
|
34991
|
+
targets,
|
|
34992
|
+
syncOptions.scope,
|
|
34993
|
+
syncOptions.projectRoot,
|
|
34994
|
+
allMappings
|
|
34995
|
+
);
|
|
34996
|
+
const rulesCoverage = measureRulesCoverage(
|
|
34997
|
+
targets,
|
|
34998
|
+
kitInfo.components.rules.declared,
|
|
34999
|
+
syncOptions.scope,
|
|
35000
|
+
syncOptions.projectRoot,
|
|
35001
|
+
allMappings,
|
|
35002
|
+
lossReport,
|
|
35003
|
+
instructionsByTarget
|
|
35004
|
+
);
|
|
34609
35005
|
reportContestedInstructions(
|
|
34610
|
-
|
|
34611
|
-
targets,
|
|
34612
|
-
syncOptions.scope,
|
|
34613
|
-
syncOptions.projectRoot,
|
|
34614
|
-
allMappings
|
|
34615
|
-
),
|
|
35006
|
+
instructionsByTarget,
|
|
34616
35007
|
kitInfo.components.rules.declared.length > 0,
|
|
34617
|
-
logger
|
|
35008
|
+
logger,
|
|
35009
|
+
missingRulesByTarget(rulesCoverage)
|
|
34618
35010
|
);
|
|
35011
|
+
reportRulesCoverage(rulesCoverage, logger);
|
|
34619
35012
|
}
|
|
34620
35013
|
}
|
|
34621
35014
|
writeLossReport(options.lossReport, lossReport);
|
|
@@ -34802,8 +35195,8 @@ function reconcileSyncedArtifacts(manifest, results, mappings, scope, projectRoo
|
|
|
34802
35195
|
}
|
|
34803
35196
|
}
|
|
34804
35197
|
function resolveKitFilePath(kitPath, relativePath) {
|
|
34805
|
-
const fullPath =
|
|
34806
|
-
return
|
|
35198
|
+
const fullPath = path50.join(kitPath, relativePath);
|
|
35199
|
+
return fs49.existsSync(fullPath) ? fullPath : null;
|
|
34807
35200
|
}
|
|
34808
35201
|
function cleanupRemovedManagedArtifacts(config, mappings, targets, options, removedSourcePaths, logger) {
|
|
34809
35202
|
if (removedSourcePaths.length === 0 || !mappings) {
|
|
@@ -34866,9 +35259,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
34866
35259
|
}
|
|
34867
35260
|
if (relativePath.startsWith("agents/")) {
|
|
34868
35261
|
removeManagedCompiledArtifact2(
|
|
34869
|
-
|
|
35262
|
+
path50.join(
|
|
34870
35263
|
resolveTargetPath(paths.agents ?? ""),
|
|
34871
|
-
`${
|
|
35264
|
+
`${path50.parse(relativePath).name}.agent.md`
|
|
34872
35265
|
),
|
|
34873
35266
|
"copilot",
|
|
34874
35267
|
relativePath,
|
|
@@ -34878,9 +35271,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
34878
35271
|
}
|
|
34879
35272
|
if (relativePath.startsWith("commands/")) {
|
|
34880
35273
|
removeManagedCompiledArtifact2(
|
|
34881
|
-
|
|
35274
|
+
path50.join(
|
|
34882
35275
|
resolveTargetPath(paths.prompts ?? ""),
|
|
34883
|
-
`${
|
|
35276
|
+
`${path50.parse(relativePath).name}.prompt.md`
|
|
34884
35277
|
),
|
|
34885
35278
|
"copilot",
|
|
34886
35279
|
relativePath,
|
|
@@ -34890,7 +35283,7 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
34890
35283
|
}
|
|
34891
35284
|
if (relativePath.endsWith("hooks.json")) {
|
|
34892
35285
|
removeManagedCompiledArtifact2(
|
|
34893
|
-
|
|
35286
|
+
path50.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
|
|
34894
35287
|
"copilot",
|
|
34895
35288
|
relativePath,
|
|
34896
35289
|
logger
|
|
@@ -34920,9 +35313,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
|
|
|
34920
35313
|
}
|
|
34921
35314
|
if (relativePath.startsWith("agents/")) {
|
|
34922
35315
|
removeManagedCompiledArtifact2(
|
|
34923
|
-
|
|
35316
|
+
path50.join(
|
|
34924
35317
|
resolveTargetPath(paths.agents ?? ""),
|
|
34925
|
-
`${
|
|
35318
|
+
`${path50.parse(relativePath).name}.toml`
|
|
34926
35319
|
),
|
|
34927
35320
|
"codex",
|
|
34928
35321
|
relativePath,
|
|
@@ -34932,9 +35325,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
|
|
|
34932
35325
|
}
|
|
34933
35326
|
if (relativePath.startsWith("rules/")) {
|
|
34934
35327
|
removeManagedCompiledArtifact2(
|
|
34935
|
-
|
|
35328
|
+
path50.join(
|
|
34936
35329
|
resolveTargetPath(paths.rules ?? ""),
|
|
34937
|
-
`${
|
|
35330
|
+
`${path50.parse(relativePath).name}.rules`
|
|
34938
35331
|
),
|
|
34939
35332
|
"codex",
|
|
34940
35333
|
relativePath,
|
|
@@ -34973,9 +35366,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
|
|
|
34973
35366
|
}
|
|
34974
35367
|
if (relativePath.startsWith("agents/")) {
|
|
34975
35368
|
removeManagedCompiledArtifact2(
|
|
34976
|
-
|
|
35369
|
+
path50.join(
|
|
34977
35370
|
resolveTargetPath(paths.agents ?? ""),
|
|
34978
|
-
`${
|
|
35371
|
+
`${path50.parse(relativePath).name}.md`
|
|
34979
35372
|
),
|
|
34980
35373
|
"opencode",
|
|
34981
35374
|
relativePath,
|
|
@@ -34985,9 +35378,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
|
|
|
34985
35378
|
}
|
|
34986
35379
|
if (relativePath.startsWith("commands/")) {
|
|
34987
35380
|
removeManagedCompiledArtifact2(
|
|
34988
|
-
|
|
35381
|
+
path50.join(
|
|
34989
35382
|
resolveTargetPath(paths.commands ?? ""),
|
|
34990
|
-
`${
|
|
35383
|
+
`${path50.parse(relativePath).name}.md`
|
|
34991
35384
|
),
|
|
34992
35385
|
"opencode",
|
|
34993
35386
|
relativePath,
|
|
@@ -35019,9 +35412,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
35019
35412
|
}
|
|
35020
35413
|
if (relativePath.startsWith("agents/")) {
|
|
35021
35414
|
removeManagedCompiledArtifact2(
|
|
35022
|
-
|
|
35415
|
+
path50.join(
|
|
35023
35416
|
resolveTargetPath(paths.agents ?? ""),
|
|
35024
|
-
`${
|
|
35417
|
+
`${path50.parse(relativePath).name}.md`
|
|
35025
35418
|
),
|
|
35026
35419
|
"cursor",
|
|
35027
35420
|
relativePath,
|
|
@@ -35031,9 +35424,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
35031
35424
|
}
|
|
35032
35425
|
if (relativePath.startsWith("rules/")) {
|
|
35033
35426
|
removeManagedCompiledArtifact2(
|
|
35034
|
-
|
|
35427
|
+
path50.join(
|
|
35035
35428
|
resolveTargetPath(paths.rules ?? ""),
|
|
35036
|
-
`${
|
|
35429
|
+
`${path50.parse(relativePath).name}.mdc`
|
|
35037
35430
|
),
|
|
35038
35431
|
"cursor",
|
|
35039
35432
|
relativePath,
|
|
@@ -35043,9 +35436,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
35043
35436
|
}
|
|
35044
35437
|
if (relativePath.startsWith("commands/")) {
|
|
35045
35438
|
removeManagedCompiledArtifact2(
|
|
35046
|
-
|
|
35439
|
+
path50.join(
|
|
35047
35440
|
resolveTargetPath(paths.skills ?? ""),
|
|
35048
|
-
|
|
35441
|
+
path50.parse(relativePath).name,
|
|
35049
35442
|
"SKILL.md"
|
|
35050
35443
|
),
|
|
35051
35444
|
"cursor",
|
|
@@ -35089,9 +35482,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
35089
35482
|
}
|
|
35090
35483
|
if (relativePath.startsWith("rules/")) {
|
|
35091
35484
|
removeManagedCompiledArtifact2(
|
|
35092
|
-
|
|
35485
|
+
path50.join(
|
|
35093
35486
|
resolveTargetPath(paths.rules ?? ""),
|
|
35094
|
-
`${
|
|
35487
|
+
`${path50.parse(relativePath).name}.md`
|
|
35095
35488
|
),
|
|
35096
35489
|
"cline",
|
|
35097
35490
|
relativePath,
|
|
@@ -35101,9 +35494,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
35101
35494
|
}
|
|
35102
35495
|
if (relativePath.startsWith("commands/")) {
|
|
35103
35496
|
removeManagedCompiledArtifact2(
|
|
35104
|
-
|
|
35497
|
+
path50.join(
|
|
35105
35498
|
resolveTargetPath(paths.workflows ?? ""),
|
|
35106
|
-
|
|
35499
|
+
path50.basename(relativePath)
|
|
35107
35500
|
),
|
|
35108
35501
|
"cline",
|
|
35109
35502
|
relativePath,
|
|
@@ -35121,17 +35514,17 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
35121
35514
|
}
|
|
35122
35515
|
}
|
|
35123
35516
|
function removeManagedCompiledArtifact2(artifactPath, expectedTarget, expectedSource, logger) {
|
|
35124
|
-
if (!
|
|
35517
|
+
if (!fs49.existsSync(artifactPath)) {
|
|
35125
35518
|
return;
|
|
35126
35519
|
}
|
|
35127
|
-
if (!
|
|
35520
|
+
if (!fs49.statSync(artifactPath).isFile()) {
|
|
35128
35521
|
return;
|
|
35129
35522
|
}
|
|
35130
|
-
const marker = extractProvenanceMarker(
|
|
35523
|
+
const marker = extractProvenanceMarker(fs49.readFileSync(artifactPath, "utf8"));
|
|
35131
35524
|
if (marker?.source !== expectedSource || marker.target !== expectedTarget) {
|
|
35132
35525
|
return;
|
|
35133
35526
|
}
|
|
35134
|
-
|
|
35527
|
+
fs49.rmSync(artifactPath, { force: true });
|
|
35135
35528
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
35136
35529
|
}
|
|
35137
35530
|
function removeManagedCopilotMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
@@ -35162,10 +35555,10 @@ function removeManagedCodexHooksArtifact2(artifactPath, expectedSource, logger)
|
|
|
35162
35555
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
35163
35556
|
}
|
|
35164
35557
|
function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
35165
|
-
if (!
|
|
35558
|
+
if (!fs49.existsSync(artifactPath)) {
|
|
35166
35559
|
return;
|
|
35167
35560
|
}
|
|
35168
|
-
const content =
|
|
35561
|
+
const content = fs49.readFileSync(artifactPath, "utf8");
|
|
35169
35562
|
const startMarker = "# tangyr: managed mcp start";
|
|
35170
35563
|
const endMarker = "# tangyr: managed mcp end";
|
|
35171
35564
|
const startIndex = content.indexOf(startMarker);
|
|
@@ -35182,19 +35575,19 @@ function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
|
35182
35575
|
const after = content.slice(endIndex + endMarker.length).trimStart();
|
|
35183
35576
|
const cleaned = [before, after].filter((entry) => entry.length > 0).join("\n\n");
|
|
35184
35577
|
if (cleaned.length === 0) {
|
|
35185
|
-
|
|
35578
|
+
fs49.rmSync(artifactPath, { force: true });
|
|
35186
35579
|
} else {
|
|
35187
|
-
|
|
35580
|
+
fs49.writeFileSync(artifactPath, `${cleaned}
|
|
35188
35581
|
`);
|
|
35189
35582
|
}
|
|
35190
35583
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
35191
35584
|
}
|
|
35192
35585
|
function readJsonObject5(filePath) {
|
|
35193
|
-
if (!
|
|
35586
|
+
if (!fs49.existsSync(filePath)) {
|
|
35194
35587
|
return null;
|
|
35195
35588
|
}
|
|
35196
35589
|
try {
|
|
35197
|
-
const parsed = JSON.parse(
|
|
35590
|
+
const parsed = JSON.parse(fs49.readFileSync(filePath, "utf8"));
|
|
35198
35591
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
35199
35592
|
} catch {
|
|
35200
35593
|
return null;
|
|
@@ -35208,10 +35601,10 @@ function readJsonMetadata(value) {
|
|
|
35208
35601
|
}
|
|
35209
35602
|
function writeJsonOrRemove2(filePath, parsed) {
|
|
35210
35603
|
if (isEmptyJsonValue2(parsed)) {
|
|
35211
|
-
|
|
35604
|
+
fs49.rmSync(filePath, { force: true });
|
|
35212
35605
|
return;
|
|
35213
35606
|
}
|
|
35214
|
-
|
|
35607
|
+
fs49.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
|
|
35215
35608
|
`);
|
|
35216
35609
|
}
|
|
35217
35610
|
function isEmptyJsonValue2(value) {
|
|
@@ -35271,8 +35664,8 @@ function removeManagedHookEntries(value, expectedSource) {
|
|
|
35271
35664
|
}
|
|
35272
35665
|
|
|
35273
35666
|
// src/commands/validate.ts
|
|
35274
|
-
import
|
|
35275
|
-
import
|
|
35667
|
+
import fs50 from "fs";
|
|
35668
|
+
import path51 from "path";
|
|
35276
35669
|
var SUPPORTED_KIT_FORMATS2 = [1];
|
|
35277
35670
|
var SUPPORTED_DISCIPLINE_VERSIONS = [
|
|
35278
35671
|
"0.14.0",
|
|
@@ -35387,12 +35780,12 @@ function checkArchetype(kit) {
|
|
|
35387
35780
|
}
|
|
35388
35781
|
function checkHookScriptsExist(kit) {
|
|
35389
35782
|
const violations = [];
|
|
35390
|
-
const hooksDir =
|
|
35783
|
+
const hooksDir = path51.join(kit.path, "hooks");
|
|
35391
35784
|
const missingSet = new Set(kit.components.hooks.missing);
|
|
35392
35785
|
for (const name of kit.components.hooks.declared) {
|
|
35393
35786
|
if (missingSet.has(name)) continue;
|
|
35394
|
-
const declarationPath =
|
|
35395
|
-
if (!
|
|
35787
|
+
const declarationPath = path51.join(hooksDir, `${name}.md`);
|
|
35788
|
+
if (!fs50.existsSync(declarationPath)) continue;
|
|
35396
35789
|
let data;
|
|
35397
35790
|
try {
|
|
35398
35791
|
({ data } = parseMarkdownFrontmatter(declarationPath));
|
|
@@ -35402,8 +35795,8 @@ function checkHookScriptsExist(kit) {
|
|
|
35402
35795
|
if (typeof data.command === "string" && data.command.trim().length > 0) {
|
|
35403
35796
|
continue;
|
|
35404
35797
|
}
|
|
35405
|
-
const scriptPath =
|
|
35406
|
-
if (!
|
|
35798
|
+
const scriptPath = path51.join(hooksDir, "scripts", `${name}.ts`);
|
|
35799
|
+
if (!fs50.existsSync(scriptPath)) {
|
|
35407
35800
|
violations.push({
|
|
35408
35801
|
code: "hook-script-missing",
|
|
35409
35802
|
location: `hooks/scripts/${name}.ts`,
|
|
@@ -35416,10 +35809,10 @@ function checkHookScriptsExist(kit) {
|
|
|
35416
35809
|
function checkOptionalSourceDocuments(kit) {
|
|
35417
35810
|
const violations = [];
|
|
35418
35811
|
for (const name of [".mcp.json", "settings.json", ".lsp.json"]) {
|
|
35419
|
-
const filePath =
|
|
35420
|
-
if (!
|
|
35812
|
+
const filePath = path51.join(kit.path, name);
|
|
35813
|
+
if (!fs50.existsSync(filePath)) continue;
|
|
35421
35814
|
try {
|
|
35422
|
-
const parsed = JSON.parse(
|
|
35815
|
+
const parsed = JSON.parse(fs50.readFileSync(filePath, "utf8"));
|
|
35423
35816
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
35424
35817
|
violations.push({
|
|
35425
35818
|
code: "optional-source-malformed",
|
|
@@ -35441,10 +35834,10 @@ function checkSkillSubfolderNames(kit) {
|
|
|
35441
35834
|
const notices = [];
|
|
35442
35835
|
const canonical = new Set(CANONICAL_SKILL_SUBFOLDERS);
|
|
35443
35836
|
for (const name of kit.components.skills.declared) {
|
|
35444
|
-
const skillDir =
|
|
35837
|
+
const skillDir = path51.join(kit.path, "skills", name);
|
|
35445
35838
|
let entries;
|
|
35446
35839
|
try {
|
|
35447
|
-
entries =
|
|
35840
|
+
entries = fs50.readdirSync(skillDir, { withFileTypes: true });
|
|
35448
35841
|
} catch {
|
|
35449
35842
|
continue;
|
|
35450
35843
|
}
|
|
@@ -35462,7 +35855,7 @@ function checkSkillSubfolderNames(kit) {
|
|
|
35462
35855
|
return notices;
|
|
35463
35856
|
}
|
|
35464
35857
|
function checkHooksSourceForm(kit) {
|
|
35465
|
-
const hooksDir =
|
|
35858
|
+
const hooksDir = path51.join(kit.path, "hooks");
|
|
35466
35859
|
const message = describeHooksSourceConflict(
|
|
35467
35860
|
hooksDir,
|
|
35468
35861
|
kit.components.hooks.declared
|
|
@@ -35474,12 +35867,12 @@ function checkHooksSourceForm(kit) {
|
|
|
35474
35867
|
} : null;
|
|
35475
35868
|
}
|
|
35476
35869
|
function checkHookDeclarations(kit) {
|
|
35477
|
-
const hooksDir =
|
|
35870
|
+
const hooksDir = path51.join(kit.path, "hooks");
|
|
35478
35871
|
return collectHookRejections(hooksDir, kit.components.hooks.declared).map(
|
|
35479
35872
|
(r) => ({
|
|
35480
35873
|
code: "hook-declaration-invalid",
|
|
35481
|
-
location: `hooks/${
|
|
35482
|
-
message: `hooks: '${
|
|
35874
|
+
location: `hooks/${path51.basename(r.file)}`,
|
|
35875
|
+
message: `hooks: '${path51.basename(r.file, ".md")}' was rejected at '${r.field}' \u2014 ${r.reason}. Until this is fixed the hook is not installed on any target; install and sync report it as an error-severity loss and exit 3. To fix: correct the field named above in this file.`
|
|
35483
35876
|
})
|
|
35484
35877
|
);
|
|
35485
35878
|
}
|
|
@@ -35499,11 +35892,11 @@ function checkKitFormatSupported(kit) {
|
|
|
35499
35892
|
function checkEntrypointExists(kit) {
|
|
35500
35893
|
const declared = kit.entrypoint;
|
|
35501
35894
|
const entrypoint = declared ?? DEFAULT_ENTRYPOINT;
|
|
35502
|
-
const entrypointPath =
|
|
35503
|
-
if (
|
|
35895
|
+
const entrypointPath = path51.join(kit.path, entrypoint);
|
|
35896
|
+
if (fs50.existsSync(entrypointPath)) {
|
|
35504
35897
|
return null;
|
|
35505
35898
|
}
|
|
35506
|
-
const legacyPresent = declared === void 0 &&
|
|
35899
|
+
const legacyPresent = declared === void 0 && fs50.existsSync(path51.join(kit.path, LEGACY_ENTRYPOINT));
|
|
35507
35900
|
const remedy = legacyPresent ? `This kit has '${LEGACY_ENTRYPOINT}' but not '${DEFAULT_ENTRYPOINT}'. Until now validate looked for '${LEGACY_ENTRYPOINT}' unconditionally; it now reads the manifest's 'entrypoint', defaulting to '${DEFAULT_ENTRYPOINT}' \u2014 the contract's canonical orientation document, of which '${LEGACY_ENTRYPOINT}' is a target translation. To fix: either add "entrypoint: ${LEGACY_ENTRYPOINT}" to tangyr-kit.yaml to keep the current filename, or rename '${LEGACY_ENTRYPOINT}' to '${DEFAULT_ENTRYPOINT}'.` : declared === void 0 ? `No 'entrypoint' is declared in tangyr-kit.yaml, so '${DEFAULT_ENTRYPOINT}' is expected at the kit root. To fix: create it, or declare the file you use with "entrypoint: <filename>".` : `tangyr-kit.yaml declares "entrypoint: ${declared}", and no such file exists at the kit root. To fix: create it, or correct the declaration.`;
|
|
35508
35901
|
return {
|
|
35509
35902
|
code: "entrypoint-missing",
|
|
@@ -35562,9 +35955,9 @@ function checkComponentFrontmatter(kit) {
|
|
|
35562
35955
|
const missingSet = new Set(kit.components[cat].missing);
|
|
35563
35956
|
for (const name of kit.components[cat].declared) {
|
|
35564
35957
|
if (missingSet.has(name)) continue;
|
|
35565
|
-
const filePath = cat === "skills" ?
|
|
35566
|
-
if (!
|
|
35567
|
-
const relPath =
|
|
35958
|
+
const filePath = cat === "skills" ? path51.join(kit.path, cat, name, "SKILL.md") : path51.join(kit.path, cat, `${name}.md`);
|
|
35959
|
+
if (!fs50.existsSync(filePath)) continue;
|
|
35960
|
+
const relPath = path51.relative(kit.path, filePath);
|
|
35568
35961
|
try {
|
|
35569
35962
|
const { data } = parseMarkdownFrontmatter(filePath);
|
|
35570
35963
|
for (const field of requiredFields) {
|
|
@@ -35589,10 +35982,10 @@ function checkComponentFrontmatter(kit) {
|
|
|
35589
35982
|
}
|
|
35590
35983
|
function checkReservedRootNames(kit) {
|
|
35591
35984
|
const violations = [];
|
|
35592
|
-
if (!
|
|
35985
|
+
if (!fs50.existsSync(kit.path) || !fs50.statSync(kit.path).isDirectory()) {
|
|
35593
35986
|
return violations;
|
|
35594
35987
|
}
|
|
35595
|
-
const entries =
|
|
35988
|
+
const entries = fs50.readdirSync(kit.path, { withFileTypes: true });
|
|
35596
35989
|
for (const entry of entries) {
|
|
35597
35990
|
if (RESERVED_ROOT_NAMES.includes(entry.name)) {
|
|
35598
35991
|
violations.push({
|
|
@@ -35609,8 +36002,8 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
35609
36002
|
const missingSet = new Set(kit.components.commands.missing);
|
|
35610
36003
|
for (const name of kit.components.commands.declared) {
|
|
35611
36004
|
if (missingSet.has(name)) continue;
|
|
35612
|
-
const filePath =
|
|
35613
|
-
if (!
|
|
36005
|
+
const filePath = path51.join(kit.path, "commands", `${name}.md`);
|
|
36006
|
+
if (!fs50.existsSync(filePath)) continue;
|
|
35614
36007
|
let data;
|
|
35615
36008
|
try {
|
|
35616
36009
|
({ data } = parseMarkdownFrontmatter(filePath));
|
|
@@ -35623,7 +36016,7 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
35623
36016
|
if (!barred) {
|
|
35624
36017
|
violations.push({
|
|
35625
36018
|
code: "command-human-only-model-invocable",
|
|
35626
|
-
location:
|
|
36019
|
+
location: path51.relative(kit.path, filePath),
|
|
35627
36020
|
message: "commands: 'launch: human-only' requires 'disable-model-invocation: true' so the model cannot start the command; only a Human-typed launch may"
|
|
35628
36021
|
});
|
|
35629
36022
|
}
|
|
@@ -35632,8 +36025,8 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
35632
36025
|
}
|
|
35633
36026
|
|
|
35634
36027
|
// src/commands/verify.ts
|
|
35635
|
-
import
|
|
35636
|
-
import
|
|
36028
|
+
import fs51 from "fs";
|
|
36029
|
+
import path52 from "path";
|
|
35637
36030
|
function runVerifyCommand(options, logger) {
|
|
35638
36031
|
if (options.target && !isKnownTarget(options.target)) {
|
|
35639
36032
|
throwUnrecognizedTarget(options.target);
|
|
@@ -35814,8 +36207,8 @@ function verifyClaudeCodeGlobalRoots(roots, manifestKeys, mappings) {
|
|
|
35814
36207
|
if (!slotPath) {
|
|
35815
36208
|
continue;
|
|
35816
36209
|
}
|
|
35817
|
-
const fullPath = subPath ?
|
|
35818
|
-
if (!
|
|
36210
|
+
const fullPath = subPath ? path52.join(slotPath, subPath) : slotPath;
|
|
36211
|
+
if (!fs51.existsSync(fullPath)) {
|
|
35819
36212
|
failures.push(
|
|
35820
36213
|
`claude-code/${slot}${subPath ? `/${subPath}` : ""} missing in root ${root}: ${fullPath}`
|
|
35821
36214
|
);
|