@alessandroraffa/tangyr 4.1.0 → 5.0.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/README.md +23 -3
- package/dist/index.js +975 -673
- package/mappings/README.md +3 -3
- package/mappings/loss-severity.yaml +10 -0
- package/mappings/platform-paths.yaml +9 -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":
|
|
@@ -21625,6 +21625,19 @@ var lossSeverityByEntryType = {
|
|
|
21625
21625
|
"rule-as-instruction": "info",
|
|
21626
21626
|
"rule-mode-downgrade": "warning",
|
|
21627
21627
|
"rule-path-scoping": "warning",
|
|
21628
|
+
// The rule is not there. Measured on the files each target reads, after every
|
|
21629
|
+
// target has written, so this says what arrived rather than what a compiler
|
|
21630
|
+
// intended — the two have disagreed, most often where several targets write
|
|
21631
|
+
// one instructions file and only the last writer's content survives.
|
|
21632
|
+
//
|
|
21633
|
+
// Error by the severity ladder's own definition: `warning` is "a real
|
|
21634
|
+
// reduction in fidelity that still produces a working artifact", and an
|
|
21635
|
+
// absent rule is not reduced, it is absent. `error` is "an intent that could
|
|
21636
|
+
// not be emitted at all and requires a manual step or a kit change", which is
|
|
21637
|
+
// exactly the remedy the run prints: give the target an instructions path of
|
|
21638
|
+
// its own, or disable it. `acceptedLoss` is how a project that has decided to
|
|
21639
|
+
// live with it says so.
|
|
21640
|
+
"rule-not-delivered": "error",
|
|
21628
21641
|
"hook-event-drop": "warning",
|
|
21629
21642
|
// A declaration the parser refuses installs nothing, anywhere, and used to
|
|
21630
21643
|
// do so silently. Error severity is what makes install and sync exit 3.
|
|
@@ -21991,7 +22004,7 @@ function reportHooksSourceConflict(report, targets, hooksDir, hookNames) {
|
|
|
21991
22004
|
|
|
21992
22005
|
// src/adapters/hook-scripts-bridge.ts
|
|
21993
22006
|
import fs25 from "fs";
|
|
21994
|
-
import
|
|
22007
|
+
import path23 from "path";
|
|
21995
22008
|
|
|
21996
22009
|
// src/utils/fs.ts
|
|
21997
22010
|
import fs23 from "fs";
|
|
@@ -22121,8 +22134,62 @@ function compareArtifactState(recorded, artifactPath) {
|
|
|
22121
22134
|
return current === recorded ? "current" : "modified";
|
|
22122
22135
|
}
|
|
22123
22136
|
|
|
22137
|
+
// src/core/shared-artifacts.ts
|
|
22138
|
+
import path22 from "path";
|
|
22139
|
+
var SHARED_NAMESPACE = "shared";
|
|
22140
|
+
var SHARED_INSTRUCTIONS_KEY = `${SHARED_NAMESPACE}/AGENTS.md`;
|
|
22141
|
+
var SHARED_INSTRUCTIONS_FILE = "AGENTS.md";
|
|
22142
|
+
var SHARED_HOOK_SCRIPTS_KEY = `${SHARED_NAMESPACE}/hook_scripts`;
|
|
22143
|
+
function sharedArtifactKey(destination, scope, projectRoot) {
|
|
22144
|
+
if (scope !== "project") {
|
|
22145
|
+
return null;
|
|
22146
|
+
}
|
|
22147
|
+
const root = projectRoot ?? process.cwd();
|
|
22148
|
+
const shared = path22.resolve(root, SHARED_INSTRUCTIONS_FILE);
|
|
22149
|
+
return path22.resolve(destination) === shared ? SHARED_INSTRUCTIONS_KEY : null;
|
|
22150
|
+
}
|
|
22151
|
+
function resolveSharedArtifactKey(key, scope, projectRoot) {
|
|
22152
|
+
if (key !== SHARED_INSTRUCTIONS_KEY || scope !== "project") {
|
|
22153
|
+
return null;
|
|
22154
|
+
}
|
|
22155
|
+
return path22.join(projectRoot ?? process.cwd(), SHARED_INSTRUCTIONS_FILE);
|
|
22156
|
+
}
|
|
22157
|
+
var SHARED_SKILLS_PREFIX = `${SHARED_NAMESPACE}/skills`;
|
|
22158
|
+
function sharedKeyForDestination(destination, scope, projectRoot, platformPaths) {
|
|
22159
|
+
const instructions = sharedArtifactKey(destination, scope, projectRoot);
|
|
22160
|
+
if (instructions) {
|
|
22161
|
+
return instructions;
|
|
22162
|
+
}
|
|
22163
|
+
const resolved = path22.resolve(destination);
|
|
22164
|
+
let profiles;
|
|
22165
|
+
try {
|
|
22166
|
+
profiles = resolveTargetPaths({
|
|
22167
|
+
scope,
|
|
22168
|
+
projectRoot,
|
|
22169
|
+
mappings: platformPaths
|
|
22170
|
+
});
|
|
22171
|
+
} catch {
|
|
22172
|
+
return null;
|
|
22173
|
+
}
|
|
22174
|
+
if (resolved === path22.resolve(profiles.codex.hook_scripts)) {
|
|
22175
|
+
return SHARED_HOOK_SCRIPTS_KEY;
|
|
22176
|
+
}
|
|
22177
|
+
const skillsRoot = path22.resolve(profiles.opencode.skills_shared);
|
|
22178
|
+
if (resolved.startsWith(`${skillsRoot}${path22.sep}`)) {
|
|
22179
|
+
const inside = path22.relative(skillsRoot, resolved).split(path22.sep).join("/");
|
|
22180
|
+
return `${SHARED_SKILLS_PREFIX}/${inside}`;
|
|
22181
|
+
}
|
|
22182
|
+
return null;
|
|
22183
|
+
}
|
|
22184
|
+
function resolveSharedSkillsKey(key, sharedSkillsRoot) {
|
|
22185
|
+
if (!key.startsWith(`${SHARED_SKILLS_PREFIX}/`) || !sharedSkillsRoot) {
|
|
22186
|
+
return null;
|
|
22187
|
+
}
|
|
22188
|
+
const inside = key.slice(SHARED_SKILLS_PREFIX.length + 1);
|
|
22189
|
+
return path22.join(sharedSkillsRoot, ...inside.split("/"));
|
|
22190
|
+
}
|
|
22191
|
+
|
|
22124
22192
|
// src/adapters/hook-scripts-bridge.ts
|
|
22125
|
-
var SHARED_HOOK_SCRIPTS_KEY = "shared/hook_scripts";
|
|
22126
22193
|
function syncHookScriptsBridge(args) {
|
|
22127
22194
|
const { source, destination, config, sourceRoot, options, logger } = args;
|
|
22128
22195
|
if (!fs25.existsSync(source)) {
|
|
@@ -22147,7 +22214,7 @@ function syncHookScriptsBridge(args) {
|
|
|
22147
22214
|
} else if (artifactClass === "managed-symlink") {
|
|
22148
22215
|
fs25.unlinkSync(destination);
|
|
22149
22216
|
}
|
|
22150
|
-
ensureDir(
|
|
22217
|
+
ensureDir(path23.dirname(destination));
|
|
22151
22218
|
createRelativeSymlink(source, destination, "dir");
|
|
22152
22219
|
if (args.manifest) {
|
|
22153
22220
|
const state = describeArtifactState(destination);
|
|
@@ -22176,26 +22243,6 @@ function isSymlinkTo(linkPath, source) {
|
|
|
22176
22243
|
}
|
|
22177
22244
|
}
|
|
22178
22245
|
|
|
22179
|
-
// src/core/shared-artifacts.ts
|
|
22180
|
-
import path23 from "path";
|
|
22181
|
-
var SHARED_NAMESPACE = "shared";
|
|
22182
|
-
var SHARED_INSTRUCTIONS_KEY = `${SHARED_NAMESPACE}/AGENTS.md`;
|
|
22183
|
-
var SHARED_INSTRUCTIONS_FILE = "AGENTS.md";
|
|
22184
|
-
function sharedArtifactKey(destination, scope, projectRoot) {
|
|
22185
|
-
if (scope !== "project") {
|
|
22186
|
-
return null;
|
|
22187
|
-
}
|
|
22188
|
-
const root = projectRoot ?? process.cwd();
|
|
22189
|
-
const shared = path23.resolve(root, SHARED_INSTRUCTIONS_FILE);
|
|
22190
|
-
return path23.resolve(destination) === shared ? SHARED_INSTRUCTIONS_KEY : null;
|
|
22191
|
-
}
|
|
22192
|
-
function resolveSharedArtifactKey(key, scope, projectRoot) {
|
|
22193
|
-
if (key !== SHARED_INSTRUCTIONS_KEY || scope !== "project") {
|
|
22194
|
-
return null;
|
|
22195
|
-
}
|
|
22196
|
-
return path23.join(projectRoot ?? process.cwd(), SHARED_INSTRUCTIONS_FILE);
|
|
22197
|
-
}
|
|
22198
|
-
|
|
22199
22246
|
// src/core/remove.ts
|
|
22200
22247
|
import fs26 from "fs";
|
|
22201
22248
|
function removeManagedPath(managedPath) {
|
|
@@ -22316,6 +22363,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
22316
22363
|
const claudeRoots = scope === "global" && selectedTools.has("claude-code") ? resolveClaudeRootsForUninstall(manifest, runtime) : [];
|
|
22317
22364
|
let removedCount = 0;
|
|
22318
22365
|
const removedParentDirs = /* @__PURE__ */ new Set();
|
|
22366
|
+
const keptSurfaces = [];
|
|
22319
22367
|
for (const file of useManifestPathRemoval ? manifestArtifacts : []) {
|
|
22320
22368
|
if (isMergeSurfaceKey(file.relativePath)) {
|
|
22321
22369
|
const surfacePath = file.path ?? resolveManifestKeyToPath(
|
|
@@ -22327,6 +22375,9 @@ async function runUninstallCommand(options, logger) {
|
|
|
22327
22375
|
if (surfacePath && stripTangyrFromMergeSurface(surfacePath, logger)) {
|
|
22328
22376
|
removedParentDirs.add(path24.dirname(surfacePath));
|
|
22329
22377
|
removedCount++;
|
|
22378
|
+
if (fs27.existsSync(surfacePath)) {
|
|
22379
|
+
keptSurfaces.push(surfacePath);
|
|
22380
|
+
}
|
|
22330
22381
|
} else {
|
|
22331
22382
|
logger.verbose(
|
|
22332
22383
|
` left in place (merge surface, nothing of ours in it): ${surfacePath ?? file.relativePath}`
|
|
@@ -22429,10 +22480,6 @@ ${String(kept.length)} later backup(s) were NOT restored: the earliest copy of e
|
|
|
22429
22480
|
logger.verbose(` removed manifest: ${manifestPath}`);
|
|
22430
22481
|
}
|
|
22431
22482
|
pruneEmptyDirs(path24.join(scopePath, "backups"), logger);
|
|
22432
|
-
const pruneBoundary = path24.dirname(scopePath);
|
|
22433
|
-
for (const dir of removedParentDirs) {
|
|
22434
|
-
pruneEmptyAncestors(dir, pruneBoundary, logger);
|
|
22435
|
-
}
|
|
22436
22483
|
try {
|
|
22437
22484
|
const remaining = fs27.readdirSync(scopePath);
|
|
22438
22485
|
if (remaining.length === 0) {
|
|
@@ -22455,6 +22502,22 @@ ${String(kept.length)} later backup(s) were NOT restored: the earliest copy of e
|
|
|
22455
22502
|
} else {
|
|
22456
22503
|
logger.verbose(" no manifest to update after partial residue cleanup");
|
|
22457
22504
|
}
|
|
22505
|
+
const pruneBoundary = path24.dirname(scopePath);
|
|
22506
|
+
for (const dir of removedParentDirs) {
|
|
22507
|
+
pruneEmptyAncestors(dir, pruneBoundary, logger);
|
|
22508
|
+
}
|
|
22509
|
+
if (keptSurfaces.length > 0) {
|
|
22510
|
+
logger.warn(
|
|
22511
|
+
`
|
|
22512
|
+
${String(keptSurfaces.length)} shared file(s) kept, with Tangyr's own block removed from each:`
|
|
22513
|
+
);
|
|
22514
|
+
for (const surface of keptSurfaces) {
|
|
22515
|
+
logger.warn(` ${surface}`);
|
|
22516
|
+
}
|
|
22517
|
+
logger.warn(
|
|
22518
|
+
" 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."
|
|
22519
|
+
);
|
|
22520
|
+
}
|
|
22458
22521
|
logger.info(`
|
|
22459
22522
|
Uninstallation complete: ${removedCount} file(s) removed.`);
|
|
22460
22523
|
}
|
|
@@ -22470,6 +22533,13 @@ function resolveManifestKeyToPath(key, scope, runtime, projectRootOverride) {
|
|
|
22470
22533
|
if (component === "hook_scripts") {
|
|
22471
22534
|
return resolveSharedHookScriptsPath(runtime, scope, projectRoot);
|
|
22472
22535
|
}
|
|
22536
|
+
const sharedSkill = resolveSharedSkillsKey(
|
|
22537
|
+
key,
|
|
22538
|
+
resolveSharedSkillsPath(runtime, scope, projectRoot)
|
|
22539
|
+
);
|
|
22540
|
+
if (sharedSkill) {
|
|
22541
|
+
return sharedSkill;
|
|
22542
|
+
}
|
|
22473
22543
|
return resolveSharedArtifactKey(key, scope, projectRoot);
|
|
22474
22544
|
}
|
|
22475
22545
|
if (tool === "claude-code") {
|
|
@@ -23867,6 +23937,27 @@ function resolveSharedHookScriptsPath(runtime, scope, projectRoot) {
|
|
|
23867
23937
|
}
|
|
23868
23938
|
return resolveTargetPath("~/.agents/hooks");
|
|
23869
23939
|
}
|
|
23940
|
+
function resolveSharedSkillsPath(runtime, scope, projectRoot) {
|
|
23941
|
+
if (runtime) {
|
|
23942
|
+
try {
|
|
23943
|
+
const mappings = loadMappings(
|
|
23944
|
+
runtime.sourceRoot,
|
|
23945
|
+
runtime.config,
|
|
23946
|
+
runtime.configDir
|
|
23947
|
+
);
|
|
23948
|
+
return resolveTargetPaths({
|
|
23949
|
+
scope,
|
|
23950
|
+
projectRoot,
|
|
23951
|
+
mappings: mappings.platformPaths
|
|
23952
|
+
}).opencode.skills_shared;
|
|
23953
|
+
} catch {
|
|
23954
|
+
}
|
|
23955
|
+
}
|
|
23956
|
+
if (scope === "project") {
|
|
23957
|
+
return path24.join(projectRoot ?? process.cwd(), ".agents", "skills");
|
|
23958
|
+
}
|
|
23959
|
+
return resolveTargetPath("~/.agents/skills");
|
|
23960
|
+
}
|
|
23870
23961
|
function resolveOpenCodePaths(runtime, scope = "global", projectRoot) {
|
|
23871
23962
|
if (runtime) {
|
|
23872
23963
|
try {
|
|
@@ -25223,8 +25314,8 @@ function toConflictPolicy2(value) {
|
|
|
25223
25314
|
}
|
|
25224
25315
|
|
|
25225
25316
|
// src/commands/install.ts
|
|
25226
|
-
import
|
|
25227
|
-
import
|
|
25317
|
+
import fs46 from "fs";
|
|
25318
|
+
import path46 from "path";
|
|
25228
25319
|
|
|
25229
25320
|
// src/core/channel-state.ts
|
|
25230
25321
|
import fs32 from "fs";
|
|
@@ -26171,12 +26262,15 @@ function findContestedInstructions(instructionsByTarget) {
|
|
|
26171
26262
|
}
|
|
26172
26263
|
return contested;
|
|
26173
26264
|
}
|
|
26174
|
-
function reportContestedInstructions(instructionsByTarget, kitDeclaresRules, logger) {
|
|
26265
|
+
function reportContestedInstructions(instructionsByTarget, kitDeclaresRules, logger, missingByTarget) {
|
|
26175
26266
|
if (!kitDeclaresRules) {
|
|
26176
26267
|
return;
|
|
26177
26268
|
}
|
|
26178
26269
|
for (const contested of findContestedInstructions(instructionsByTarget)) {
|
|
26179
|
-
|
|
26270
|
+
const losers = missingByTarget ? contested.losers.filter(
|
|
26271
|
+
(target) => (missingByTarget.get(target)?.length ?? 0) > 0
|
|
26272
|
+
) : contested.losers;
|
|
26273
|
+
if (losers.length === 0) {
|
|
26180
26274
|
continue;
|
|
26181
26275
|
}
|
|
26182
26276
|
logger.warn(
|
|
@@ -26186,7 +26280,7 @@ ${contested.destination} is the instructions file for ${contested.claimants.join
|
|
|
26186
26280
|
if (contested.survivor) {
|
|
26187
26281
|
logger.warn(` The content on disk is ${contested.survivor}'s.`);
|
|
26188
26282
|
}
|
|
26189
|
-
for (const target of
|
|
26283
|
+
for (const target of losers) {
|
|
26190
26284
|
logger.warn(
|
|
26191
26285
|
` ${target} does NOT get its rules: ${FOLDS_RULES_INTO_INSTRUCTIONS[target]}, and that content is overwritten here.`
|
|
26192
26286
|
);
|
|
@@ -26209,12 +26303,161 @@ function instructionsByActiveTarget(tools, scope, projectRoot, mappings) {
|
|
|
26209
26303
|
byTarget.set(tool, instructions);
|
|
26210
26304
|
}
|
|
26211
26305
|
}
|
|
26306
|
+
if (scope === "project" && projectRoot && tools.includes("copilot")) {
|
|
26307
|
+
byTarget.set("copilot", path31.join(projectRoot, "AGENTS.md"));
|
|
26308
|
+
}
|
|
26212
26309
|
return byTarget;
|
|
26213
26310
|
}
|
|
26214
26311
|
|
|
26312
|
+
// src/core/rules-coverage.ts
|
|
26313
|
+
import fs35 from "fs";
|
|
26314
|
+
import path32 from "path";
|
|
26315
|
+
function readingSurfaces(profile) {
|
|
26316
|
+
const record = profile;
|
|
26317
|
+
return {
|
|
26318
|
+
slot: typeof record?.rules === "string" ? record.rules : null,
|
|
26319
|
+
instructions: typeof record?.instructions === "string" ? record.instructions : null
|
|
26320
|
+
};
|
|
26321
|
+
}
|
|
26322
|
+
function inRulesSlot(slot, rule) {
|
|
26323
|
+
let entries;
|
|
26324
|
+
try {
|
|
26325
|
+
entries = fs35.readdirSync(slot);
|
|
26326
|
+
} catch {
|
|
26327
|
+
return false;
|
|
26328
|
+
}
|
|
26329
|
+
return entries.some(
|
|
26330
|
+
(entry) => entry === rule || entry.startsWith(`${rule}.`)
|
|
26331
|
+
);
|
|
26332
|
+
}
|
|
26333
|
+
function inInstructions(instructions, rule) {
|
|
26334
|
+
let content;
|
|
26335
|
+
try {
|
|
26336
|
+
content = fs35.readFileSync(instructions, "utf8");
|
|
26337
|
+
} catch {
|
|
26338
|
+
return false;
|
|
26339
|
+
}
|
|
26340
|
+
return content.split("\n").some((line) => line.trim() === `## ${rule}`);
|
|
26341
|
+
}
|
|
26342
|
+
function recordedRulesLoss(lossReport, target) {
|
|
26343
|
+
const entries = lossReport.targets[target]?.rules ?? [];
|
|
26344
|
+
for (const artifact of entries) {
|
|
26345
|
+
for (const field of artifact.fields) {
|
|
26346
|
+
if (field.detail.length > 0) {
|
|
26347
|
+
return field.detail;
|
|
26348
|
+
}
|
|
26349
|
+
}
|
|
26350
|
+
}
|
|
26351
|
+
return null;
|
|
26352
|
+
}
|
|
26353
|
+
function measureRulesCoverage(tools, declaredRules, scope, projectRoot, mappings, lossReport, instructionsByTarget) {
|
|
26354
|
+
const resolved = resolveTargetPaths({
|
|
26355
|
+
scope,
|
|
26356
|
+
projectRoot,
|
|
26357
|
+
mappings: mappings.platformPaths
|
|
26358
|
+
});
|
|
26359
|
+
const contestedByPath = new Map(
|
|
26360
|
+
findContestedInstructions(instructionsByTarget).map((contested) => [
|
|
26361
|
+
contested.destination,
|
|
26362
|
+
contested
|
|
26363
|
+
])
|
|
26364
|
+
);
|
|
26365
|
+
return tools.map((target) => {
|
|
26366
|
+
const surfaces = readingSurfaces(resolved[target]);
|
|
26367
|
+
const missing = declaredRules.filter((rule) => {
|
|
26368
|
+
if (surfaces.slot && inRulesSlot(surfaces.slot, rule)) {
|
|
26369
|
+
return false;
|
|
26370
|
+
}
|
|
26371
|
+
return !(surfaces.instructions && inInstructions(surfaces.instructions, rule));
|
|
26372
|
+
});
|
|
26373
|
+
return {
|
|
26374
|
+
target,
|
|
26375
|
+
missing,
|
|
26376
|
+
declared: declaredRules.length,
|
|
26377
|
+
reason: missing.length === 0 ? null : explain(target, surfaces, contestedByPath, lossReport, projectRoot)
|
|
26378
|
+
};
|
|
26379
|
+
});
|
|
26380
|
+
}
|
|
26381
|
+
function explain(target, surfaces, contestedByPath, lossReport, projectRoot) {
|
|
26382
|
+
if (surfaces.instructions) {
|
|
26383
|
+
const contested = contestedByPath.get(path32.resolve(surfaces.instructions));
|
|
26384
|
+
if (contested && contested.survivor !== null && contested.survivor !== target) {
|
|
26385
|
+
return `its rules are folded into ${display(surfaces.instructions, projectRoot)}, which ${contested.survivor} wrote last`;
|
|
26386
|
+
}
|
|
26387
|
+
}
|
|
26388
|
+
const recorded = recordedRulesLoss(lossReport, target);
|
|
26389
|
+
if (recorded) {
|
|
26390
|
+
return recorded;
|
|
26391
|
+
}
|
|
26392
|
+
if (!surfaces.slot) {
|
|
26393
|
+
return "it has no rules surface in this scope";
|
|
26394
|
+
}
|
|
26395
|
+
return `not in ${display(surfaces.slot, projectRoot)}, nor folded into the instructions file`;
|
|
26396
|
+
}
|
|
26397
|
+
function display(target, projectRoot) {
|
|
26398
|
+
if (!projectRoot) {
|
|
26399
|
+
return target;
|
|
26400
|
+
}
|
|
26401
|
+
const relative = path32.relative(projectRoot, target);
|
|
26402
|
+
return relative.startsWith("..") ? target : relative;
|
|
26403
|
+
}
|
|
26404
|
+
function reportRulesCoverage(coverage, logger) {
|
|
26405
|
+
if (coverage.length === 0 || coverage[0].declared === 0) {
|
|
26406
|
+
return;
|
|
26407
|
+
}
|
|
26408
|
+
const complete = coverage.every((entry) => entry.missing.length === 0);
|
|
26409
|
+
const say = complete ? (line) => {
|
|
26410
|
+
logger.verbose(line);
|
|
26411
|
+
} : (line) => {
|
|
26412
|
+
logger.warn(line);
|
|
26413
|
+
};
|
|
26414
|
+
const declared = coverage[0].declared;
|
|
26415
|
+
const width = Math.max(...coverage.map((entry) => entry.target.length));
|
|
26416
|
+
say(
|
|
26417
|
+
`
|
|
26418
|
+
Rules reaching each target (${String(declared)} declared, measured on disk):`
|
|
26419
|
+
);
|
|
26420
|
+
for (const entry of coverage) {
|
|
26421
|
+
const delivered = declared - entry.missing.length;
|
|
26422
|
+
const counts = `${String(delivered)}/${String(declared)}`;
|
|
26423
|
+
const head = ` ${entry.target.padEnd(width)} ${counts}`;
|
|
26424
|
+
if (entry.missing.length === 0) {
|
|
26425
|
+
say(head);
|
|
26426
|
+
continue;
|
|
26427
|
+
}
|
|
26428
|
+
say(`${head} missing: ${entry.missing.join(", ")}`);
|
|
26429
|
+
if (entry.reason) {
|
|
26430
|
+
say(` ${" ".repeat(width)} ${entry.reason}`);
|
|
26431
|
+
}
|
|
26432
|
+
}
|
|
26433
|
+
}
|
|
26434
|
+
function missingRulesByTarget(coverage) {
|
|
26435
|
+
return new Map(coverage.map((entry) => [entry.target, entry.missing]));
|
|
26436
|
+
}
|
|
26437
|
+
function recordRulesCoverageLoss(coverage, lossReport) {
|
|
26438
|
+
for (const entry of coverage) {
|
|
26439
|
+
if (entry.missing.length === 0) {
|
|
26440
|
+
continue;
|
|
26441
|
+
}
|
|
26442
|
+
addLoss(lossReport, entry.target, "rules", {
|
|
26443
|
+
source: "rules",
|
|
26444
|
+
fields: entry.missing.map((rule) => ({
|
|
26445
|
+
field: rule,
|
|
26446
|
+
action: "rule-not-delivered",
|
|
26447
|
+
severity: resolveLossSeverity(
|
|
26448
|
+
"agent-field",
|
|
26449
|
+
rule,
|
|
26450
|
+
"rule-not-delivered"
|
|
26451
|
+
),
|
|
26452
|
+
detail: `${rule}: not readable by ${entry.target}${entry.reason ? ` \u2014 ${entry.reason}` : ""}`
|
|
26453
|
+
}))
|
|
26454
|
+
});
|
|
26455
|
+
}
|
|
26456
|
+
}
|
|
26457
|
+
|
|
26215
26458
|
// src/adapters/claude-code.ts
|
|
26216
|
-
import
|
|
26217
|
-
import
|
|
26459
|
+
import fs38 from "fs";
|
|
26460
|
+
import path36 from "path";
|
|
26218
26461
|
|
|
26219
26462
|
// src/core/shim.ts
|
|
26220
26463
|
import crypto4 from "crypto";
|
|
@@ -26236,8 +26479,8 @@ ${SHIM_BODY}`;
|
|
|
26236
26479
|
}
|
|
26237
26480
|
|
|
26238
26481
|
// src/core/skills-slot.ts
|
|
26239
|
-
import
|
|
26240
|
-
import
|
|
26482
|
+
import fs36 from "fs";
|
|
26483
|
+
import path33 from "path";
|
|
26241
26484
|
function isForeignSkillsSlotSymlink(destination, config, sourceRoot, source) {
|
|
26242
26485
|
if (!isSymlinkPath(destination)) {
|
|
26243
26486
|
return false;
|
|
@@ -26250,7 +26493,7 @@ function isForeignSkillsSlotSymlink(destination, config, sourceRoot, source) {
|
|
|
26250
26493
|
}
|
|
26251
26494
|
function syncSkillsSlot(sync) {
|
|
26252
26495
|
const { source, destination, logger } = sync;
|
|
26253
|
-
if (!
|
|
26496
|
+
if (!fs36.existsSync(source)) {
|
|
26254
26497
|
return [
|
|
26255
26498
|
{
|
|
26256
26499
|
component: "skills",
|
|
@@ -26278,7 +26521,7 @@ function syncSkillsSlot(sync) {
|
|
|
26278
26521
|
if (isLegacyWholesaleSymlink) {
|
|
26279
26522
|
for (const name of foreignSkillNames(source, declaredNames)) {
|
|
26280
26523
|
logger.info(
|
|
26281
|
-
`[dry-run] skills: migrate foreign skill ${
|
|
26524
|
+
`[dry-run] skills: migrate foreign skill ${path33.join(source, name)} -> ${path33.join(destination, name)}`
|
|
26282
26525
|
);
|
|
26283
26526
|
}
|
|
26284
26527
|
logger.info(
|
|
@@ -26286,9 +26529,9 @@ function syncSkillsSlot(sync) {
|
|
|
26286
26529
|
);
|
|
26287
26530
|
}
|
|
26288
26531
|
for (const name of declaredNames ?? listSkillDirNames(source)) {
|
|
26289
|
-
const skillDestination =
|
|
26532
|
+
const skillDestination = path33.join(destination, name);
|
|
26290
26533
|
logger.info(
|
|
26291
|
-
`[dry-run] skills: symlink ${
|
|
26534
|
+
`[dry-run] skills: symlink ${path33.join(source, name)} -> ${skillDestination}`
|
|
26292
26535
|
);
|
|
26293
26536
|
outcomes2.push({
|
|
26294
26537
|
component: "skills",
|
|
@@ -26315,9 +26558,9 @@ function syncSkillsSlot(sync) {
|
|
|
26315
26558
|
}
|
|
26316
26559
|
function syncSingleSkill(sync, name) {
|
|
26317
26560
|
const { config, sourceRoot, source, destination } = sync;
|
|
26318
|
-
const skillSource =
|
|
26319
|
-
const skillDestination =
|
|
26320
|
-
if (!
|
|
26561
|
+
const skillSource = path33.join(source, name);
|
|
26562
|
+
const skillDestination = path33.join(destination, name);
|
|
26563
|
+
if (!fs36.existsSync(skillSource)) {
|
|
26321
26564
|
return {
|
|
26322
26565
|
component: "skills",
|
|
26323
26566
|
status: "skipped",
|
|
@@ -26333,29 +26576,29 @@ function syncSingleSkill(sync, name) {
|
|
|
26333
26576
|
};
|
|
26334
26577
|
}
|
|
26335
26578
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(skillDestination, /* @__PURE__ */ new Set([skillDestination]), config)) {
|
|
26336
|
-
|
|
26579
|
+
fs36.unlinkSync(skillDestination);
|
|
26337
26580
|
} else if (artifactClass === "unmanaged-conflict" && !sync.onUnmanagedConflict(skillDestination)) {
|
|
26338
26581
|
return { component: "skills", status: "conflict", path: skillDestination };
|
|
26339
26582
|
} else if (artifactClass === "managed-symlink") {
|
|
26340
|
-
|
|
26583
|
+
fs36.unlinkSync(skillDestination);
|
|
26341
26584
|
}
|
|
26342
26585
|
createRelativeSymlink(skillSource, skillDestination, "dir");
|
|
26343
26586
|
return { component: "skills", status: "success", path: skillDestination };
|
|
26344
26587
|
}
|
|
26345
26588
|
function migrateWholesaleSkillsSymlink(source, destination, declaredNames, logger) {
|
|
26346
26589
|
const foreignNames = foreignSkillNames(source, declaredNames);
|
|
26347
|
-
|
|
26590
|
+
fs36.unlinkSync(destination);
|
|
26348
26591
|
ensureDir(destination);
|
|
26349
26592
|
for (const name of foreignNames) {
|
|
26350
|
-
const from =
|
|
26351
|
-
const to =
|
|
26352
|
-
if (
|
|
26593
|
+
const from = path33.join(source, name);
|
|
26594
|
+
const to = path33.join(destination, name);
|
|
26595
|
+
if (fs36.existsSync(to)) {
|
|
26353
26596
|
logger.warn(
|
|
26354
26597
|
`skills migration: ${to} already exists \u2014 skipping ${from} to avoid overwrite. Nothing in the kit was changed.`
|
|
26355
26598
|
);
|
|
26356
26599
|
continue;
|
|
26357
26600
|
}
|
|
26358
|
-
|
|
26601
|
+
fs36.cpSync(from, to, { recursive: true, verbatimSymlinks: true });
|
|
26359
26602
|
logger.warn(
|
|
26360
26603
|
`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.`
|
|
26361
26604
|
);
|
|
@@ -26369,44 +26612,44 @@ function foreignSkillNames(source, declaredNames) {
|
|
|
26369
26612
|
return listSkillDirNames(source).filter((name) => !declaredSet.has(name));
|
|
26370
26613
|
}
|
|
26371
26614
|
function listSkillDirNames(dir) {
|
|
26372
|
-
if (!
|
|
26615
|
+
if (!fs36.existsSync(dir)) {
|
|
26373
26616
|
return [];
|
|
26374
26617
|
}
|
|
26375
|
-
return
|
|
26618
|
+
return fs36.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
|
|
26376
26619
|
}
|
|
26377
26620
|
function isSymlinkPath(filePath) {
|
|
26378
26621
|
try {
|
|
26379
|
-
return
|
|
26622
|
+
return fs36.lstatSync(filePath).isSymbolicLink();
|
|
26380
26623
|
} catch {
|
|
26381
26624
|
return false;
|
|
26382
26625
|
}
|
|
26383
26626
|
}
|
|
26384
26627
|
function isSymlinkTo2(linkPath, source) {
|
|
26385
26628
|
try {
|
|
26386
|
-
return
|
|
26629
|
+
return fs36.realpathSync(linkPath) === fs36.realpathSync(source);
|
|
26387
26630
|
} catch {
|
|
26388
26631
|
return false;
|
|
26389
26632
|
}
|
|
26390
26633
|
}
|
|
26391
26634
|
|
|
26392
26635
|
// src/core/hook-scripts.ts
|
|
26393
|
-
import
|
|
26636
|
+
import path34 from "path";
|
|
26394
26637
|
function hookScriptsDir(bridge, target, projectRoot) {
|
|
26395
26638
|
const globalBridge = resolveTargetPath("~/.agents/hooks");
|
|
26396
|
-
if (
|
|
26639
|
+
if (path34.resolve(bridge) === path34.resolve(globalBridge)) {
|
|
26397
26640
|
return { prefix: GLOBAL_HOOK_SCRIPTS_DIR, machineLocal: false };
|
|
26398
26641
|
}
|
|
26399
|
-
const relative =
|
|
26400
|
-
const insideProject = !relative.startsWith("..") && !
|
|
26642
|
+
const relative = path34.relative(projectRoot ?? process.cwd(), bridge);
|
|
26643
|
+
const insideProject = !relative.startsWith("..") && !path34.isAbsolute(relative) && relative !== "";
|
|
26401
26644
|
const variable = PROJECT_DIR_VARIABLE[target];
|
|
26402
26645
|
if (insideProject && variable) {
|
|
26403
|
-
const posix =
|
|
26404
|
-
relative.split(
|
|
26646
|
+
const posix = path34.posix.join(
|
|
26647
|
+
relative.split(path34.sep).join("/"),
|
|
26405
26648
|
"scripts"
|
|
26406
26649
|
);
|
|
26407
26650
|
return { prefix: `$${variable.slice(1)}/${posix}`, machineLocal: false };
|
|
26408
26651
|
}
|
|
26409
|
-
return { prefix:
|
|
26652
|
+
return { prefix: path34.join(bridge, "scripts"), machineLocal: true };
|
|
26410
26653
|
}
|
|
26411
26654
|
var PROJECT_DIR_VARIABLE = {
|
|
26412
26655
|
"claude-code": "$CLAUDE_PROJECT_DIR"
|
|
@@ -26416,19 +26659,19 @@ function machineLocalScriptPathNotice(target, prefix) {
|
|
|
26416
26659
|
}
|
|
26417
26660
|
|
|
26418
26661
|
// src/core/instructions-source.ts
|
|
26419
|
-
import
|
|
26420
|
-
import
|
|
26662
|
+
import fs37 from "fs";
|
|
26663
|
+
import path35 from "path";
|
|
26421
26664
|
var PORTABLE_INSTRUCTIONS_NAME = "AGENTS.md";
|
|
26422
26665
|
var InstructionsSourceMissingError = class extends Error {
|
|
26423
26666
|
constructor(kitRoot, expected, declaredBy) {
|
|
26424
26667
|
super(
|
|
26425
|
-
`${
|
|
26668
|
+
`${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.`
|
|
26426
26669
|
);
|
|
26427
26670
|
this.name = "InstructionsSourceMissingError";
|
|
26428
26671
|
}
|
|
26429
26672
|
};
|
|
26430
26673
|
function normalizeLabel(kitRoot, file) {
|
|
26431
|
-
return
|
|
26674
|
+
return path35.relative(kitRoot, file).split(path35.sep).join("/");
|
|
26432
26675
|
}
|
|
26433
26676
|
function isExplicitOverride(configured) {
|
|
26434
26677
|
const normalize = (value) => value.replace(/\\/gu, "/").replace(/^\.\//u, "");
|
|
@@ -26437,8 +26680,8 @@ function isExplicitOverride(configured) {
|
|
|
26437
26680
|
function resolveInstructionsSource(kitRoot, config) {
|
|
26438
26681
|
const configured = config.source.instructions;
|
|
26439
26682
|
if (isExplicitOverride(configured)) {
|
|
26440
|
-
const file =
|
|
26441
|
-
if (!
|
|
26683
|
+
const file = path35.resolve(kitRoot, configured);
|
|
26684
|
+
if (!fs37.existsSync(file)) {
|
|
26442
26685
|
throw new InstructionsSourceMissingError(
|
|
26443
26686
|
kitRoot,
|
|
26444
26687
|
configured,
|
|
@@ -26453,8 +26696,8 @@ function resolveInstructionsSource(kitRoot, config) {
|
|
|
26453
26696
|
}
|
|
26454
26697
|
const declared = resolveKitEntrypointName(kitRoot);
|
|
26455
26698
|
if (declared !== void 0) {
|
|
26456
|
-
const file =
|
|
26457
|
-
if (!
|
|
26699
|
+
const file = path35.resolve(kitRoot, declared);
|
|
26700
|
+
if (!fs37.existsSync(file)) {
|
|
26458
26701
|
throw new InstructionsSourceMissingError(
|
|
26459
26702
|
kitRoot,
|
|
26460
26703
|
declared,
|
|
@@ -26468,13 +26711,13 @@ function resolveInstructionsSource(kitRoot, config) {
|
|
|
26468
26711
|
};
|
|
26469
26712
|
}
|
|
26470
26713
|
for (const name of [DEFAULT_ENTRYPOINT, PORTABLE_INSTRUCTIONS_NAME]) {
|
|
26471
|
-
const file =
|
|
26472
|
-
if (
|
|
26714
|
+
const file = path35.resolve(kitRoot, name);
|
|
26715
|
+
if (fs37.existsSync(file)) {
|
|
26473
26716
|
return { file, label: name, origin: "convention" };
|
|
26474
26717
|
}
|
|
26475
26718
|
}
|
|
26476
|
-
const legacy =
|
|
26477
|
-
if (
|
|
26719
|
+
const legacy = path35.resolve(kitRoot, LEGACY_ENTRYPOINT);
|
|
26720
|
+
if (fs37.existsSync(legacy)) {
|
|
26478
26721
|
return {
|
|
26479
26722
|
file: legacy,
|
|
26480
26723
|
label: LEGACY_ENTRYPOINT,
|
|
@@ -26486,7 +26729,7 @@ function resolveInstructionsSource(kitRoot, config) {
|
|
|
26486
26729
|
}
|
|
26487
26730
|
function instructionsSourcePath(kitRoot, config) {
|
|
26488
26731
|
const resolved = resolveInstructionsSource(kitRoot, config);
|
|
26489
|
-
return resolved ? resolved.file :
|
|
26732
|
+
return resolved ? resolved.file : path35.resolve(kitRoot, config.source.instructions);
|
|
26490
26733
|
}
|
|
26491
26734
|
function instructionsSourceLabel(kitRoot, config) {
|
|
26492
26735
|
const resolved = resolveInstructionsSource(kitRoot, config);
|
|
@@ -26607,7 +26850,7 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
|
|
|
26607
26850
|
if (!shouldSkipComponent(options, "hooks")) {
|
|
26608
26851
|
outcomes.push(
|
|
26609
26852
|
syncHookScriptsBridge({
|
|
26610
|
-
source:
|
|
26853
|
+
source: path36.resolve(sourceRoot, config.source.hooks),
|
|
26611
26854
|
destination: profile.hook_scripts,
|
|
26612
26855
|
config,
|
|
26613
26856
|
sourceRoot,
|
|
@@ -26659,13 +26902,13 @@ function syncClaudeCode(config, sourceRoot, options, logger, mappings, manifest,
|
|
|
26659
26902
|
}
|
|
26660
26903
|
function syncProviderLoss(config, sourceRoot, mappings, lossReport) {
|
|
26661
26904
|
if (!mappings.modelTiers.custom_provider) return;
|
|
26662
|
-
const agentsDir =
|
|
26663
|
-
if (!
|
|
26664
|
-
for (const agentFile of ts(
|
|
26905
|
+
const agentsDir = path36.join(sourceRoot, config.source.agents);
|
|
26906
|
+
if (!fs38.existsSync(agentsDir)) return;
|
|
26907
|
+
for (const agentFile of ts(path36.join(agentsDir, "*.md")).sort()) {
|
|
26665
26908
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
26666
26909
|
const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
26667
26910
|
if (hasProvider) {
|
|
26668
|
-
const basename =
|
|
26911
|
+
const basename = path36.basename(agentFile);
|
|
26669
26912
|
addLoss(lossReport, "claude-code", "agents", {
|
|
26670
26913
|
source: `agents/${basename}`,
|
|
26671
26914
|
fields: [
|
|
@@ -26690,7 +26933,7 @@ function shouldSkipComponent(options, component) {
|
|
|
26690
26933
|
var SHIM_MANIFEST_KEY = "claude-code/instructions_shim";
|
|
26691
26934
|
function lstatOrNull(p) {
|
|
26692
26935
|
try {
|
|
26693
|
-
return
|
|
26936
|
+
return fs38.lstatSync(p);
|
|
26694
26937
|
} catch {
|
|
26695
26938
|
return null;
|
|
26696
26939
|
}
|
|
@@ -26702,12 +26945,12 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
26702
26945
|
if (shimLink?.isSymbolicLink()) {
|
|
26703
26946
|
backupFile(shimPath, manifest, scopePath);
|
|
26704
26947
|
writeManifest(scopePath, manifest);
|
|
26705
|
-
|
|
26948
|
+
fs38.unlinkSync(shimPath);
|
|
26706
26949
|
logger?.verbose(
|
|
26707
26950
|
`instructions-shim: replaced an unmanaged symlink at ${shimPath}`
|
|
26708
26951
|
);
|
|
26709
26952
|
}
|
|
26710
|
-
if (!
|
|
26953
|
+
if (!fs38.existsSync(shimPath)) {
|
|
26711
26954
|
addArtifactToManifest(manifest, {
|
|
26712
26955
|
relativePath: SHIM_MANIFEST_KEY,
|
|
26713
26956
|
path: shimPath,
|
|
@@ -26715,12 +26958,12 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
26715
26958
|
origin: "tangyr-managed"
|
|
26716
26959
|
});
|
|
26717
26960
|
writeManifest(scopePath, manifest);
|
|
26718
|
-
|
|
26719
|
-
|
|
26961
|
+
fs38.mkdirSync(path36.dirname(shimPath), { recursive: true });
|
|
26962
|
+
fs38.writeFileSync(shimPath, shimContent);
|
|
26720
26963
|
logger?.verbose(`instructions-shim: wrote @AGENTS.md shim -> ${shimPath}`);
|
|
26721
26964
|
return;
|
|
26722
26965
|
}
|
|
26723
|
-
const existing =
|
|
26966
|
+
const existing = fs38.readFileSync(shimPath, "utf8");
|
|
26724
26967
|
const firstNonEmptyLine = existing.split("\n").find((l) => l.trim().length > 0) ?? "";
|
|
26725
26968
|
const marker = extractProvenanceMarker(firstNonEmptyLine);
|
|
26726
26969
|
if (marker !== null && marker.hash === expectedBodyHash) {
|
|
@@ -26737,7 +26980,7 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
26737
26980
|
}
|
|
26738
26981
|
backupFile(shimPath, manifest, scopePath);
|
|
26739
26982
|
writeManifest(scopePath, manifest);
|
|
26740
|
-
|
|
26983
|
+
fs38.writeFileSync(shimPath, shimContent);
|
|
26741
26984
|
addArtifactToManifest(manifest, {
|
|
26742
26985
|
relativePath: SHIM_MANIFEST_KEY,
|
|
26743
26986
|
path: shimPath,
|
|
@@ -26747,10 +26990,10 @@ function applyClaudeCodeShimUpgrade(shimPath, agentsMdPath, manifest, scopePath,
|
|
|
26747
26990
|
logger?.verbose(`instructions-shim: backed up and replaced -> ${shimPath}`);
|
|
26748
26991
|
}
|
|
26749
26992
|
function syncDirectComponent(config, sourceRoot, options, logger, directComponent, manifest, scopePath) {
|
|
26750
|
-
const source = directComponent.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) :
|
|
26993
|
+
const source = directComponent.sourceKey === "instructions" ? instructionsSourcePath(sourceRoot, config) : path36.resolve(sourceRoot, config.source[directComponent.sourceKey]);
|
|
26751
26994
|
const sourceLabel = directComponent.sourceKey === "instructions" ? instructionsSourceLabel(sourceRoot, config) : config.source[directComponent.sourceKey];
|
|
26752
26995
|
const destination = directComponent.destination;
|
|
26753
|
-
if (!
|
|
26996
|
+
if (!fs38.existsSync(source)) {
|
|
26754
26997
|
return skippedMissingSource(directComponent.component, source);
|
|
26755
26998
|
}
|
|
26756
26999
|
if (options.dryRun) {
|
|
@@ -26772,7 +27015,7 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
26772
27015
|
};
|
|
26773
27016
|
}
|
|
26774
27017
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
26775
|
-
|
|
27018
|
+
fs38.unlinkSync(destination);
|
|
26776
27019
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict(destination, config, options, logger, manifest, scopePath)) {
|
|
26777
27020
|
return {
|
|
26778
27021
|
component: directComponent.component,
|
|
@@ -26780,11 +27023,11 @@ function syncDirectComponent(config, sourceRoot, options, logger, directComponen
|
|
|
26780
27023
|
path: destination
|
|
26781
27024
|
};
|
|
26782
27025
|
} else if (artifactClass === "managed-symlink") {
|
|
26783
|
-
|
|
27026
|
+
fs38.unlinkSync(destination);
|
|
26784
27027
|
} else if (artifactClass === "managed-compiled") {
|
|
26785
|
-
|
|
27028
|
+
fs38.unlinkSync(destination);
|
|
26786
27029
|
}
|
|
26787
|
-
ensureDir(
|
|
27030
|
+
ensureDir(path36.dirname(destination));
|
|
26788
27031
|
createRelativeSymlink(source, destination, directComponent.type, {
|
|
26789
27032
|
logger,
|
|
26790
27033
|
provenanceMarker: directComponent.type === "file" ? formatProvenanceMarker(
|
|
@@ -26804,7 +27047,7 @@ function syncClaudeCodeSkills(config, sourceRoot, options, logger, destination,
|
|
|
26804
27047
|
return syncSkillsSlot({
|
|
26805
27048
|
config,
|
|
26806
27049
|
sourceRoot,
|
|
26807
|
-
source:
|
|
27050
|
+
source: path36.resolve(sourceRoot, config.source.skills),
|
|
26808
27051
|
destination,
|
|
26809
27052
|
dryRun: options.dryRun,
|
|
26810
27053
|
logger,
|
|
@@ -26838,7 +27081,7 @@ function syncHooks(config, sourceRoot, options, logger, destination, scriptsBrid
|
|
|
26838
27081
|
destination,
|
|
26839
27082
|
settings,
|
|
26840
27083
|
stringifyJson2,
|
|
26841
|
-
!
|
|
27084
|
+
!fs38.existsSync(destination),
|
|
26842
27085
|
logger
|
|
26843
27086
|
);
|
|
26844
27087
|
return {
|
|
@@ -26848,8 +27091,8 @@ function syncHooks(config, sourceRoot, options, logger, destination, scriptsBrid
|
|
|
26848
27091
|
};
|
|
26849
27092
|
}
|
|
26850
27093
|
function syncMcp(config, sourceRoot, options, logger, destination) {
|
|
26851
|
-
const source =
|
|
26852
|
-
if (!
|
|
27094
|
+
const source = path36.resolve(sourceRoot, config.source.mcp);
|
|
27095
|
+
if (!fs38.existsSync(source)) {
|
|
26853
27096
|
return skippedMissingSource("mcp", source);
|
|
26854
27097
|
}
|
|
26855
27098
|
if (options.dryRun) {
|
|
@@ -26874,7 +27117,7 @@ function syncMcp(config, sourceRoot, options, logger, destination) {
|
|
|
26874
27117
|
destination,
|
|
26875
27118
|
hostConfig,
|
|
26876
27119
|
stringifyJson2,
|
|
26877
|
-
!
|
|
27120
|
+
!fs38.existsSync(destination),
|
|
26878
27121
|
logger
|
|
26879
27122
|
);
|
|
26880
27123
|
return {
|
|
@@ -26884,8 +27127,8 @@ function syncMcp(config, sourceRoot, options, logger, destination) {
|
|
|
26884
27127
|
};
|
|
26885
27128
|
}
|
|
26886
27129
|
function syncSettings(config, sourceRoot, options, logger, destination) {
|
|
26887
|
-
const source =
|
|
26888
|
-
if (!
|
|
27130
|
+
const source = path36.resolve(sourceRoot, config.source.settings);
|
|
27131
|
+
if (!fs38.existsSync(source)) {
|
|
26889
27132
|
return skippedMissingSource("settings", source);
|
|
26890
27133
|
}
|
|
26891
27134
|
if (options.dryRun) {
|
|
@@ -26903,7 +27146,7 @@ function syncSettings(config, sourceRoot, options, logger, destination) {
|
|
|
26903
27146
|
destination,
|
|
26904
27147
|
settings,
|
|
26905
27148
|
stringifyJson2,
|
|
26906
|
-
!
|
|
27149
|
+
!fs38.existsSync(destination),
|
|
26907
27150
|
logger
|
|
26908
27151
|
);
|
|
26909
27152
|
return {
|
|
@@ -26927,7 +27170,7 @@ function handleConflict(destination, config, options, logger, manifest, scopePat
|
|
|
26927
27170
|
if (manifest && scopePath) {
|
|
26928
27171
|
backupFile(destination, manifest, scopePath);
|
|
26929
27172
|
writeManifest(scopePath, manifest);
|
|
26930
|
-
|
|
27173
|
+
fs38.rmSync(destination, { recursive: true, force: true });
|
|
26931
27174
|
} else {
|
|
26932
27175
|
const parked = parkConflictingPath(
|
|
26933
27176
|
destination,
|
|
@@ -26942,7 +27185,7 @@ function handleConflict(destination, config, options, logger, manifest, scopePat
|
|
|
26942
27185
|
}
|
|
26943
27186
|
return true;
|
|
26944
27187
|
}
|
|
26945
|
-
|
|
27188
|
+
fs38.rmSync(destination, { recursive: true, force: true });
|
|
26946
27189
|
return true;
|
|
26947
27190
|
}
|
|
26948
27191
|
function skippedMissingSource(component, source) {
|
|
@@ -26954,16 +27197,16 @@ function skippedMissingSource(component, source) {
|
|
|
26954
27197
|
}
|
|
26955
27198
|
function isSymlinkTo3(linkPath, source) {
|
|
26956
27199
|
try {
|
|
26957
|
-
return
|
|
27200
|
+
return fs38.realpathSync(linkPath) === fs38.realpathSync(source);
|
|
26958
27201
|
} catch {
|
|
26959
27202
|
return false;
|
|
26960
27203
|
}
|
|
26961
27204
|
}
|
|
26962
27205
|
function readJsonObject3(filePath) {
|
|
26963
|
-
if (!
|
|
27206
|
+
if (!fs38.existsSync(filePath)) {
|
|
26964
27207
|
return {};
|
|
26965
27208
|
}
|
|
26966
|
-
const parsed = JSON.parse(
|
|
27209
|
+
const parsed = JSON.parse(fs38.readFileSync(filePath, "utf8"));
|
|
26967
27210
|
return isRecord3(parsed) ? parsed : {};
|
|
26968
27211
|
}
|
|
26969
27212
|
function markManaged(value) {
|
|
@@ -26990,13 +27233,13 @@ function isRecord3(value) {
|
|
|
26990
27233
|
// src/adapters/codex.ts
|
|
26991
27234
|
var TOML3 = __toESM(require_toml(), 1);
|
|
26992
27235
|
import crypto6 from "crypto";
|
|
26993
|
-
import
|
|
26994
|
-
import
|
|
27236
|
+
import fs41 from "fs";
|
|
27237
|
+
import path40 from "path";
|
|
26995
27238
|
|
|
26996
27239
|
// src/compiler/agents.ts
|
|
26997
27240
|
var TOML = __toESM(require_toml(), 1);
|
|
26998
27241
|
var import_yaml8 = __toESM(require_dist(), 1);
|
|
26999
|
-
import
|
|
27242
|
+
import path37 from "path";
|
|
27000
27243
|
var writeCapabilityClasses = /* @__PURE__ */ new Set(["filesystem-write", "shell-execution"]);
|
|
27001
27244
|
var copilotToolAliasesByClass = {
|
|
27002
27245
|
delegation: "agent",
|
|
@@ -27008,7 +27251,7 @@ var copilotToolAliasesByClass = {
|
|
|
27008
27251
|
};
|
|
27009
27252
|
function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
27010
27253
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
27011
|
-
const relativeSource = `agents/${
|
|
27254
|
+
const relativeSource = `agents/${path37.basename(sourceFile)}`;
|
|
27012
27255
|
if (target === "opencode") {
|
|
27013
27256
|
return compileOpenCodeAgent(
|
|
27014
27257
|
sourceFile,
|
|
@@ -27049,7 +27292,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
|
27049
27292
|
mappings,
|
|
27050
27293
|
lossReport
|
|
27051
27294
|
);
|
|
27052
|
-
const overlayKey = `agents/${
|
|
27295
|
+
const overlayKey = `agents/${path37.basename(sourceFile, ".md")}.${target}.yaml`;
|
|
27053
27296
|
const targetFields = {
|
|
27054
27297
|
...translated.fields,
|
|
27055
27298
|
...extensions[overlayKey] ?? {}
|
|
@@ -27083,7 +27326,7 @@ ${TOML.stringify({
|
|
|
27083
27326
|
function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
27084
27327
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
27085
27328
|
throw new Error(
|
|
27086
|
-
`${
|
|
27329
|
+
`${path37.basename(sourceFile)}: OpenCode agent requires a non-empty description field`
|
|
27087
27330
|
);
|
|
27088
27331
|
}
|
|
27089
27332
|
const frontmatter = {
|
|
@@ -27137,7 +27380,7 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
|
|
|
27137
27380
|
"permission",
|
|
27138
27381
|
"permission-coarsening"
|
|
27139
27382
|
),
|
|
27140
|
-
detail: `${
|
|
27383
|
+
detail: `${path37.basename(sourceFile)}: per-tool permission '${tool}' mapped to coarse allow|deny action`
|
|
27141
27384
|
}
|
|
27142
27385
|
]
|
|
27143
27386
|
});
|
|
@@ -27162,7 +27405,7 @@ ${(0, import_yaml8.stringify)(frontmatter).trim()}
|
|
|
27162
27405
|
function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
27163
27406
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
27164
27407
|
throw new Error(
|
|
27165
|
-
`${
|
|
27408
|
+
`${path37.basename(sourceFile)}: Cursor agent requires a non-empty description field`
|
|
27166
27409
|
);
|
|
27167
27410
|
}
|
|
27168
27411
|
const frontmatter = {
|
|
@@ -27199,7 +27442,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
27199
27442
|
"permission",
|
|
27200
27443
|
"permission-coarsening"
|
|
27201
27444
|
),
|
|
27202
|
-
detail: `${
|
|
27445
|
+
detail: `${path37.basename(sourceFile)}: per-agent tool allow set coarsened to readonly=${readonly} boolean (Cursor only exposes readonly control)`
|
|
27203
27446
|
}
|
|
27204
27447
|
]
|
|
27205
27448
|
});
|
|
@@ -27218,7 +27461,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
27218
27461
|
"provider",
|
|
27219
27462
|
"provider-not-representable"
|
|
27220
27463
|
),
|
|
27221
|
-
detail: `${
|
|
27464
|
+
detail: `${path37.basename(sourceFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
27222
27465
|
}
|
|
27223
27466
|
]
|
|
27224
27467
|
});
|
|
@@ -27250,7 +27493,7 @@ function compileClineAgent(sourceFile, _data, _body, relativeSource, lossReport)
|
|
|
27250
27493
|
"persona",
|
|
27251
27494
|
"persona-not-representable"
|
|
27252
27495
|
),
|
|
27253
|
-
detail: `${
|
|
27496
|
+
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.`
|
|
27254
27497
|
}
|
|
27255
27498
|
]
|
|
27256
27499
|
});
|
|
@@ -27298,7 +27541,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
27298
27541
|
field,
|
|
27299
27542
|
"model-not-representable"
|
|
27300
27543
|
),
|
|
27301
|
-
detail: `${
|
|
27544
|
+
detail: `${path37.basename(sourceFile)}: model tier '${String(value)}' has no stable Copilot model literal; omitted so VS Code uses the selected model.`
|
|
27302
27545
|
});
|
|
27303
27546
|
return;
|
|
27304
27547
|
}
|
|
@@ -27316,9 +27559,9 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
27316
27559
|
lossReport,
|
|
27317
27560
|
target,
|
|
27318
27561
|
"agents",
|
|
27319
|
-
`agents/${
|
|
27562
|
+
`agents/${path37.basename(sourceFile)}`,
|
|
27320
27563
|
"info",
|
|
27321
|
-
`${
|
|
27564
|
+
`${path37.basename(sourceFile)}: ${field} is delivered through another managed surface.`
|
|
27322
27565
|
);
|
|
27323
27566
|
return;
|
|
27324
27567
|
}
|
|
@@ -27327,7 +27570,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
27327
27570
|
field,
|
|
27328
27571
|
action: entryType,
|
|
27329
27572
|
severity: resolveLossSeverity("agent-field", field, entryType),
|
|
27330
|
-
detail: `${
|
|
27573
|
+
detail: `${path37.basename(sourceFile)}: ${field} has no emitted field for this target.`
|
|
27331
27574
|
});
|
|
27332
27575
|
}
|
|
27333
27576
|
function mapToolsToCapabilities(value, mappings) {
|
|
@@ -27515,23 +27758,6 @@ function compileOpenCodeHooks(sourceHooksJson, lossReport, sourceLabel) {
|
|
|
27515
27758
|
]
|
|
27516
27759
|
});
|
|
27517
27760
|
}
|
|
27518
|
-
if (Object.keys(sourceHooks).length === 0) {
|
|
27519
|
-
addLoss(lossReport, "opencode", "hooks", {
|
|
27520
|
-
source: sourceLabel,
|
|
27521
|
-
fields: [
|
|
27522
|
-
{
|
|
27523
|
-
field: "hooks",
|
|
27524
|
-
action: "hook-as-plugin",
|
|
27525
|
-
severity: resolveLossSeverity(
|
|
27526
|
-
"agent-field",
|
|
27527
|
-
"hooks",
|
|
27528
|
-
"hook-as-plugin"
|
|
27529
|
-
),
|
|
27530
|
-
detail: "OpenCode exposes hooks only as plugin code \u2014 no declarative hook file emitted"
|
|
27531
|
-
}
|
|
27532
|
-
]
|
|
27533
|
-
});
|
|
27534
|
-
}
|
|
27535
27761
|
return { payload: {}, translated: 0, dropped: 0, droppedEvents: [] };
|
|
27536
27762
|
}
|
|
27537
27763
|
function compileClineHooks(sourceHooksJson, lossReport, sourceLabel) {
|
|
@@ -27553,23 +27779,6 @@ function compileClineHooks(sourceHooksJson, lossReport, sourceLabel) {
|
|
|
27553
27779
|
]
|
|
27554
27780
|
});
|
|
27555
27781
|
}
|
|
27556
|
-
if (Object.keys(sourceHooks).length === 0) {
|
|
27557
|
-
addLoss(lossReport, "cline", "hooks", {
|
|
27558
|
-
source: sourceLabel,
|
|
27559
|
-
fields: [
|
|
27560
|
-
{
|
|
27561
|
-
field: "hooks",
|
|
27562
|
-
action: "hook-as-plugin",
|
|
27563
|
-
severity: resolveLossSeverity(
|
|
27564
|
-
"agent-field",
|
|
27565
|
-
"hooks",
|
|
27566
|
-
"hook-as-plugin"
|
|
27567
|
-
),
|
|
27568
|
-
detail: "Cline exposes hooks only as @cline/sdk AgentPlugin TypeScript/JS code \u2014 no declarative hook file emitted"
|
|
27569
|
-
}
|
|
27570
|
-
]
|
|
27571
|
-
});
|
|
27572
|
-
}
|
|
27573
27782
|
return { payload: {}, translated: 0, dropped: 0, droppedEvents: [] };
|
|
27574
27783
|
}
|
|
27575
27784
|
function compileCopilotHooks(sourceHooksJson, mappings, lossReport, sourceLabel) {
|
|
@@ -27791,13 +28000,13 @@ function addHookLoss(lossReport, target, eventName, sourceLabel, severity, reaso
|
|
|
27791
28000
|
|
|
27792
28001
|
// src/compiler/command-as-skill.ts
|
|
27793
28002
|
var import_yaml9 = __toESM(require_dist(), 1);
|
|
27794
|
-
import
|
|
27795
|
-
import
|
|
28003
|
+
import fs39 from "fs";
|
|
28004
|
+
import path38 from "path";
|
|
27796
28005
|
var CARRIED_OVER = ["argument-hint", "agent", "launch"];
|
|
27797
28006
|
function compileCommandAsSkill(commandFile, target) {
|
|
27798
|
-
const name =
|
|
28007
|
+
const name = path38.basename(commandFile, ".md");
|
|
27799
28008
|
const { data, body } = parseMarkdownFrontmatter(commandFile);
|
|
27800
|
-
const relativeSource = `commands/${
|
|
28009
|
+
const relativeSource = `commands/${path38.basename(commandFile)}`;
|
|
27801
28010
|
const description = typeof data.description === "string" && data.description.trim().length > 0 ? data.description.trim() : `The ${name} command.`;
|
|
27802
28011
|
const frontmatter = { name, description };
|
|
27803
28012
|
for (const key of CARRIED_OVER) {
|
|
@@ -27820,11 +28029,11 @@ ${body.trim()}
|
|
|
27820
28029
|
return { name, content, relativeSource };
|
|
27821
28030
|
}
|
|
27822
28031
|
function compileCommandsAsSkills(commandsRoot, target) {
|
|
27823
|
-
if (!
|
|
28032
|
+
if (!fs39.existsSync(commandsRoot)) {
|
|
27824
28033
|
return [];
|
|
27825
28034
|
}
|
|
27826
|
-
return
|
|
27827
|
-
(entry) => compileCommandAsSkill(
|
|
28035
|
+
return fs39.readdirSync(commandsRoot).filter((entry) => entry.endsWith(".md")).sort().map(
|
|
28036
|
+
(entry) => compileCommandAsSkill(path38.join(commandsRoot, entry), target)
|
|
27828
28037
|
);
|
|
27829
28038
|
}
|
|
27830
28039
|
|
|
@@ -28107,9 +28316,9 @@ function compileOpenCodeMcp(sourceMcpJson, lossReport, sourceLabel) {
|
|
|
28107
28316
|
}
|
|
28108
28317
|
|
|
28109
28318
|
// src/compiler/rules.ts
|
|
28110
|
-
import
|
|
28319
|
+
import path39 from "path";
|
|
28111
28320
|
var import_yaml10 = __toESM(require_dist(), 1);
|
|
28112
|
-
import
|
|
28321
|
+
import fs40 from "fs";
|
|
28113
28322
|
function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
28114
28323
|
if (target === "copilot") {
|
|
28115
28324
|
addLoss(lossReport, "copilot", "rules", {
|
|
@@ -28146,13 +28355,13 @@ function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
|
28146
28355
|
}
|
|
28147
28356
|
const appendixParts = [];
|
|
28148
28357
|
const dotRulesFiles = [];
|
|
28149
|
-
for (const ruleFile of ts(
|
|
28358
|
+
for (const ruleFile of ts(path39.join(sourceRulesDir, "*.md")).sort()) {
|
|
28150
28359
|
const parsed = parseRule(ruleFile);
|
|
28151
|
-
const name =
|
|
28360
|
+
const name = path39.basename(ruleFile, ".md");
|
|
28152
28361
|
if (parsed.mode === "exec-policy") {
|
|
28153
28362
|
dotRulesFiles.push({
|
|
28154
28363
|
name: `${name}.rules`,
|
|
28155
|
-
content: `${formatProvenanceMarker("toml", `rules/${
|
|
28364
|
+
content: `${formatProvenanceMarker("toml", `rules/${path39.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
|
|
28156
28365
|
${parsed.body}`
|
|
28157
28366
|
});
|
|
28158
28367
|
continue;
|
|
@@ -28161,7 +28370,7 @@ ${parsed.body}`
|
|
|
28161
28370
|
|
|
28162
28371
|
${parsed.body.trim()}`);
|
|
28163
28372
|
addLoss(lossReport, "codex", "rules", {
|
|
28164
|
-
source: `rules/${
|
|
28373
|
+
source: `rules/${path39.basename(ruleFile)}`,
|
|
28165
28374
|
fields: [
|
|
28166
28375
|
{
|
|
28167
28376
|
field: "mode",
|
|
@@ -28171,7 +28380,7 @@ ${parsed.body.trim()}`);
|
|
|
28171
28380
|
"mode",
|
|
28172
28381
|
"rule-as-instruction"
|
|
28173
28382
|
),
|
|
28174
|
-
detail: `${
|
|
28383
|
+
detail: `${path39.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
|
|
28175
28384
|
}
|
|
28176
28385
|
]
|
|
28177
28386
|
});
|
|
@@ -28179,7 +28388,7 @@ ${parsed.body.trim()}`);
|
|
|
28179
28388
|
return { agentsAppendix: appendixParts.join("\n\n"), dotRulesFiles };
|
|
28180
28389
|
}
|
|
28181
28390
|
function parseRule(ruleFile) {
|
|
28182
|
-
const content =
|
|
28391
|
+
const content = fs40.readFileSync(ruleFile, "utf8");
|
|
28183
28392
|
if (!content.startsWith("---\n")) {
|
|
28184
28393
|
return { mode: "guidance", body: content };
|
|
28185
28394
|
}
|
|
@@ -28203,14 +28412,14 @@ function isRuleMode(value) {
|
|
|
28203
28412
|
}
|
|
28204
28413
|
function compileOpenCodeRules(sourceRulesDir, lossReport) {
|
|
28205
28414
|
const appendixParts = [];
|
|
28206
|
-
for (const ruleFile of ts(
|
|
28415
|
+
for (const ruleFile of ts(path39.join(sourceRulesDir, "*.md")).sort()) {
|
|
28207
28416
|
const parsed = parseRule(ruleFile);
|
|
28208
|
-
const name =
|
|
28417
|
+
const name = path39.basename(ruleFile, ".md");
|
|
28209
28418
|
appendixParts.push(`## ${name}
|
|
28210
28419
|
|
|
28211
28420
|
${parsed.body.trim()}`);
|
|
28212
28421
|
addLoss(lossReport, "opencode", "rules", {
|
|
28213
|
-
source: `rules/${
|
|
28422
|
+
source: `rules/${path39.basename(ruleFile)}`,
|
|
28214
28423
|
fields: [
|
|
28215
28424
|
{
|
|
28216
28425
|
field: "rule",
|
|
@@ -28220,7 +28429,7 @@ ${parsed.body.trim()}`);
|
|
|
28220
28429
|
"rule",
|
|
28221
28430
|
"rule-path-scoping"
|
|
28222
28431
|
),
|
|
28223
|
-
detail: `${
|
|
28432
|
+
detail: `${path39.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to AGENTS.md instructions`
|
|
28224
28433
|
}
|
|
28225
28434
|
]
|
|
28226
28435
|
});
|
|
@@ -28229,9 +28438,9 @@ ${parsed.body.trim()}`);
|
|
|
28229
28438
|
}
|
|
28230
28439
|
function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
28231
28440
|
const dotRulesFiles = [];
|
|
28232
|
-
for (const ruleFile of ts(
|
|
28233
|
-
const content =
|
|
28234
|
-
const name =
|
|
28441
|
+
for (const ruleFile of ts(path39.join(sourceRulesDir, "*.md")).sort()) {
|
|
28442
|
+
const content = fs40.readFileSync(ruleFile, "utf8");
|
|
28443
|
+
const name = path39.basename(ruleFile, ".md");
|
|
28235
28444
|
let frontmatterData = {};
|
|
28236
28445
|
let body = content;
|
|
28237
28446
|
if (content.startsWith("---\n")) {
|
|
@@ -28260,7 +28469,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
|
28260
28469
|
}
|
|
28261
28470
|
const marker = formatProvenanceMarker(
|
|
28262
28471
|
"markdown",
|
|
28263
|
-
`rules/${
|
|
28472
|
+
`rules/${path39.basename(ruleFile)}`,
|
|
28264
28473
|
computeSourceHash(ruleFile),
|
|
28265
28474
|
"cursor"
|
|
28266
28475
|
);
|
|
@@ -28276,9 +28485,9 @@ ${body}`;
|
|
|
28276
28485
|
}
|
|
28277
28486
|
function compileClineRules(sourceRulesDir, lossReport) {
|
|
28278
28487
|
const dotRulesFiles = [];
|
|
28279
|
-
for (const ruleFile of ts(
|
|
28280
|
-
const content =
|
|
28281
|
-
const name =
|
|
28488
|
+
for (const ruleFile of ts(path39.join(sourceRulesDir, "*.md")).sort()) {
|
|
28489
|
+
const content = fs40.readFileSync(ruleFile, "utf8");
|
|
28490
|
+
const name = path39.basename(ruleFile, ".md");
|
|
28282
28491
|
let frontmatterData = {};
|
|
28283
28492
|
let body = content;
|
|
28284
28493
|
if (content.startsWith("---\n")) {
|
|
@@ -28295,13 +28504,13 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
28295
28504
|
}
|
|
28296
28505
|
const marker = formatProvenanceMarker(
|
|
28297
28506
|
"markdown",
|
|
28298
|
-
`rules/${
|
|
28507
|
+
`rules/${path39.basename(ruleFile)}`,
|
|
28299
28508
|
computeSourceHash(ruleFile),
|
|
28300
28509
|
"cline"
|
|
28301
28510
|
);
|
|
28302
28511
|
if (frontmatterData.mode === "exec-policy") {
|
|
28303
28512
|
addLoss(lossReport, "cline", "rules", {
|
|
28304
|
-
source: `rules/${
|
|
28513
|
+
source: `rules/${path39.basename(ruleFile)}`,
|
|
28305
28514
|
fields: [
|
|
28306
28515
|
{
|
|
28307
28516
|
field: "mode",
|
|
@@ -28311,7 +28520,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
28311
28520
|
"mode",
|
|
28312
28521
|
"rule-mode-downgrade"
|
|
28313
28522
|
),
|
|
28314
|
-
detail: `${
|
|
28523
|
+
detail: `${path39.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
|
|
28315
28524
|
}
|
|
28316
28525
|
]
|
|
28317
28526
|
});
|
|
@@ -28331,12 +28540,12 @@ ${frontmatterYaml}${body}`;
|
|
|
28331
28540
|
return { agentsAppendix: "", dotRulesFiles };
|
|
28332
28541
|
}
|
|
28333
28542
|
function compileCopilotRules(sourceRulesDir) {
|
|
28334
|
-
if (!
|
|
28543
|
+
if (!fs40.existsSync(sourceRulesDir)) {
|
|
28335
28544
|
return [];
|
|
28336
28545
|
}
|
|
28337
28546
|
const files = [];
|
|
28338
|
-
for (const ruleFile of ts(
|
|
28339
|
-
const name =
|
|
28547
|
+
for (const ruleFile of ts(path39.join(sourceRulesDir, "*.md")).sort()) {
|
|
28548
|
+
const name = path39.basename(ruleFile, ".md");
|
|
28340
28549
|
const { data } = parseMarkdownFrontmatter(ruleFile);
|
|
28341
28550
|
const { body } = parseRule(ruleFile);
|
|
28342
28551
|
const declared = data.paths;
|
|
@@ -28345,7 +28554,7 @@ function compileCopilotRules(sourceRulesDir) {
|
|
|
28345
28554
|
"---",
|
|
28346
28555
|
`applyTo: ${JSON.stringify(applyTo)}`,
|
|
28347
28556
|
"x-tangyr:",
|
|
28348
|
-
` source: rules/${
|
|
28557
|
+
` source: rules/${path39.basename(ruleFile)}`,
|
|
28349
28558
|
` hash: ${computeSourceHash(ruleFile)}`,
|
|
28350
28559
|
" target: copilot",
|
|
28351
28560
|
"---"
|
|
@@ -28382,7 +28591,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
28382
28591
|
rules: profile.rules
|
|
28383
28592
|
};
|
|
28384
28593
|
const rules = compileRules(
|
|
28385
|
-
|
|
28594
|
+
path40.join(sourceRoot, config.source.rules),
|
|
28386
28595
|
"codex",
|
|
28387
28596
|
mappings,
|
|
28388
28597
|
lossReport
|
|
@@ -28462,7 +28671,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
28462
28671
|
if (!shouldSkipComponent2(options, "hooks")) {
|
|
28463
28672
|
outcomes.push(
|
|
28464
28673
|
syncHookScriptsBridge({
|
|
28465
|
-
source:
|
|
28674
|
+
source: path40.resolve(sourceRoot, config.source.hooks),
|
|
28466
28675
|
destination: resolveTargetPath(paths.hook_scripts),
|
|
28467
28676
|
config,
|
|
28468
28677
|
sourceRoot,
|
|
@@ -28561,9 +28770,9 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
28561
28770
|
function buildProviderTomlSection(config, sourceRoot, mappings, scope, lossReport) {
|
|
28562
28771
|
const cp = mappings.modelTiers.custom_provider;
|
|
28563
28772
|
if (!cp) return "";
|
|
28564
|
-
const agentsDir =
|
|
28565
|
-
if (!
|
|
28566
|
-
const agentFiles = ts(
|
|
28773
|
+
const agentsDir = path40.join(sourceRoot, config.source.agents);
|
|
28774
|
+
if (!fs41.existsSync(agentsDir)) return "";
|
|
28775
|
+
const agentFiles = ts(path40.join(agentsDir, "*.md")).sort();
|
|
28567
28776
|
const hasProviderAgent = agentFiles.some((agentFile) => {
|
|
28568
28777
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
28569
28778
|
return typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
@@ -28628,7 +28837,7 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
|
|
|
28628
28837
|
}
|
|
28629
28838
|
];
|
|
28630
28839
|
for (const ruleFile of rules.dotRulesFiles) {
|
|
28631
|
-
const destination =
|
|
28840
|
+
const destination = path40.join(rulesRoot, ruleFile.name);
|
|
28632
28841
|
if (options.dryRun) {
|
|
28633
28842
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
28634
28843
|
outcomes.push({
|
|
@@ -28658,16 +28867,16 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
|
|
|
28658
28867
|
function syncInstructions(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
|
|
28659
28868
|
const source = instructionsSourcePath(sourceRoot, config);
|
|
28660
28869
|
const destination = resolveTargetPath(paths.instructions);
|
|
28661
|
-
if (!
|
|
28870
|
+
if (!fs41.existsSync(source)) {
|
|
28662
28871
|
return skippedMissingSource2("instructions", source);
|
|
28663
28872
|
}
|
|
28664
|
-
const composed = `${
|
|
28873
|
+
const composed = `${fs41.readFileSync(source, "utf8").trim()}
|
|
28665
28874
|
|
|
28666
28875
|
--- tangyr managed rules ---
|
|
28667
28876
|
${agentsAppendix}`.trim();
|
|
28668
28877
|
const marker = formatProvenanceMarker(
|
|
28669
28878
|
"markdown",
|
|
28670
|
-
|
|
28879
|
+
path40.basename(instructionsSourceLabel(sourceRoot, config)),
|
|
28671
28880
|
hashString(composed),
|
|
28672
28881
|
"codex"
|
|
28673
28882
|
);
|
|
@@ -28697,7 +28906,7 @@ function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopeP
|
|
|
28697
28906
|
return syncSkillsSlot({
|
|
28698
28907
|
config,
|
|
28699
28908
|
sourceRoot,
|
|
28700
|
-
source:
|
|
28909
|
+
source: path40.resolve(sourceRoot, config.source.skills),
|
|
28701
28910
|
destination: resolveTargetPath(paths.skills),
|
|
28702
28911
|
dryRun: options.dryRun,
|
|
28703
28912
|
logger,
|
|
@@ -28712,13 +28921,13 @@ function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopeP
|
|
|
28712
28921
|
});
|
|
28713
28922
|
}
|
|
28714
28923
|
function syncCommandsAsSkills(config, sourceRoot, paths, options, _lossReport, logger, manifest, scopePath) {
|
|
28715
|
-
const commandsRoot =
|
|
28716
|
-
if (!
|
|
28924
|
+
const commandsRoot = path40.resolve(sourceRoot, config.source.commands);
|
|
28925
|
+
if (!fs41.existsSync(commandsRoot)) {
|
|
28717
28926
|
return [skippedMissingSource2("commands", commandsRoot)];
|
|
28718
28927
|
}
|
|
28719
28928
|
const skillsRoot = resolveTargetPath(paths.skills);
|
|
28720
28929
|
return compileCommandsAsSkills(commandsRoot, "codex").map((skill) => {
|
|
28721
|
-
const destination =
|
|
28930
|
+
const destination = path40.join(skillsRoot, skill.name, "SKILL.md");
|
|
28722
28931
|
if (options.dryRun) {
|
|
28723
28932
|
logger.info(
|
|
28724
28933
|
`[dry-run] commands: compile ${skill.relativeSource} -> ${destination}`
|
|
@@ -28744,16 +28953,16 @@ function syncCommandsAsSkills(config, sourceRoot, paths, options, _lossReport, l
|
|
|
28744
28953
|
});
|
|
28745
28954
|
}
|
|
28746
28955
|
function syncAgents(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
28747
|
-
const sourceAgentsRoot =
|
|
28748
|
-
if (!
|
|
28956
|
+
const sourceAgentsRoot = path40.join(sourceRoot, config.source.agents);
|
|
28957
|
+
if (!fs41.existsSync(sourceAgentsRoot)) {
|
|
28749
28958
|
return [skippedMissingSource2("agents", sourceAgentsRoot)];
|
|
28750
28959
|
}
|
|
28751
|
-
const sourceAgents = ts(
|
|
28960
|
+
const sourceAgents = ts(path40.join(sourceAgentsRoot, "*.md")).sort();
|
|
28752
28961
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
28753
28962
|
return sourceAgents.map((agentFile) => {
|
|
28754
|
-
const destination =
|
|
28963
|
+
const destination = path40.join(
|
|
28755
28964
|
agentsRoot,
|
|
28756
|
-
`${
|
|
28965
|
+
`${path40.basename(agentFile, ".md")}.toml`
|
|
28757
28966
|
);
|
|
28758
28967
|
const compiled = compileAgent(
|
|
28759
28968
|
agentFile,
|
|
@@ -28831,7 +29040,7 @@ function syncHooks2(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
28831
29040
|
destination,
|
|
28832
29041
|
hostHooks,
|
|
28833
29042
|
stringifyJson3,
|
|
28834
|
-
!
|
|
29043
|
+
!fs41.existsSync(destination),
|
|
28835
29044
|
logger
|
|
28836
29045
|
);
|
|
28837
29046
|
return {
|
|
@@ -28844,7 +29053,7 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger, provid
|
|
|
28844
29053
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
28845
29054
|
const sourceLabel = mcpSourceLabel(config);
|
|
28846
29055
|
const destination = resolveTargetPath(paths.mcp_shared_file);
|
|
28847
|
-
if (!
|
|
29056
|
+
if (!fs41.existsSync(source)) {
|
|
28848
29057
|
if (providerToml && !options.dryRun) {
|
|
28849
29058
|
const changed2 = writeTomlManagedSection(
|
|
28850
29059
|
destination,
|
|
@@ -28859,7 +29068,7 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger, provid
|
|
|
28859
29068
|
}
|
|
28860
29069
|
return skippedMissingSource2("mcp", source);
|
|
28861
29070
|
}
|
|
28862
|
-
const sourceMcpJson = JSON.parse(
|
|
29071
|
+
const sourceMcpJson = JSON.parse(fs41.readFileSync(source, "utf8"));
|
|
28863
29072
|
const compiled = compileMcp(sourceMcpJson, "codex", lossReport, sourceLabel);
|
|
28864
29073
|
const managedContent = providerToml ? `${compiled.trimEnd()}${providerToml}` : compiled;
|
|
28865
29074
|
if (options.dryRun) {
|
|
@@ -28884,18 +29093,18 @@ function writeCompiledArtifact(component, destination, content, expectedHash, co
|
|
|
28884
29093
|
if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
28885
29094
|
return { component, status: "conflict", path: destination };
|
|
28886
29095
|
}
|
|
28887
|
-
ensureDir(
|
|
29096
|
+
ensureDir(path40.dirname(destination));
|
|
28888
29097
|
const clearedLink = clearSymlinkAtDestination(destination);
|
|
28889
29098
|
if (clearedLink !== null) {
|
|
28890
29099
|
logger.verbose(
|
|
28891
29100
|
` ${destination}: replaced a symlink to ${clearedLink} with generated content`
|
|
28892
29101
|
);
|
|
28893
29102
|
}
|
|
28894
|
-
|
|
29103
|
+
fs41.writeFileSync(destination, content);
|
|
28895
29104
|
return { component, status: "success", path: destination };
|
|
28896
29105
|
}
|
|
28897
29106
|
function writeTomlManagedSection(destination, managedContent, logger) {
|
|
28898
|
-
const current =
|
|
29107
|
+
const current = fs41.existsSync(destination) ? fs41.readFileSync(destination, "utf8") : "";
|
|
28899
29108
|
const isFirstWrite = current.length > 0 && !current.includes(managedMcpStart);
|
|
28900
29109
|
if (isFirstWrite) {
|
|
28901
29110
|
logger.warn(
|
|
@@ -28911,8 +29120,8 @@ ${managedMcpEnd}
|
|
|
28911
29120
|
if (current === next.trimStart()) {
|
|
28912
29121
|
return false;
|
|
28913
29122
|
}
|
|
28914
|
-
ensureDir(
|
|
28915
|
-
|
|
29123
|
+
ensureDir(path40.dirname(destination));
|
|
29124
|
+
fs41.writeFileSync(destination, next.trimStart());
|
|
28916
29125
|
return true;
|
|
28917
29126
|
}
|
|
28918
29127
|
function removeManagedTomlSection(content) {
|
|
@@ -28938,7 +29147,7 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
|
|
|
28938
29147
|
if (manifest && scopePath) {
|
|
28939
29148
|
backupFile(destination, manifest, scopePath);
|
|
28940
29149
|
writeManifest(scopePath, manifest);
|
|
28941
|
-
|
|
29150
|
+
fs41.rmSync(destination, { recursive: true, force: true });
|
|
28942
29151
|
} else {
|
|
28943
29152
|
const parked = parkConflictingPath(
|
|
28944
29153
|
destination,
|
|
@@ -28953,12 +29162,12 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
|
|
|
28953
29162
|
}
|
|
28954
29163
|
return true;
|
|
28955
29164
|
}
|
|
28956
|
-
|
|
29165
|
+
fs41.rmSync(destination, { recursive: true, force: true });
|
|
28957
29166
|
return true;
|
|
28958
29167
|
}
|
|
28959
29168
|
function isCompiledCurrent(destination, expectedContent, _expectedHash) {
|
|
28960
29169
|
try {
|
|
28961
|
-
return
|
|
29170
|
+
return fs41.readFileSync(destination, "utf8") === expectedContent;
|
|
28962
29171
|
} catch {
|
|
28963
29172
|
return false;
|
|
28964
29173
|
}
|
|
@@ -28974,10 +29183,10 @@ function shouldSkipComponent2(options, component) {
|
|
|
28974
29183
|
return Boolean(options.component && options.component !== component);
|
|
28975
29184
|
}
|
|
28976
29185
|
function readJsonObject4(filePath) {
|
|
28977
|
-
if (!
|
|
29186
|
+
if (!fs41.existsSync(filePath)) {
|
|
28978
29187
|
return {};
|
|
28979
29188
|
}
|
|
28980
|
-
const parsed = JSON.parse(
|
|
29189
|
+
const parsed = JSON.parse(fs41.readFileSync(filePath, "utf8"));
|
|
28981
29190
|
return isRecord5(parsed) ? parsed : {};
|
|
28982
29191
|
}
|
|
28983
29192
|
function stringifyJson3(value) {
|
|
@@ -28993,16 +29202,16 @@ function hashString(value) {
|
|
|
28993
29202
|
|
|
28994
29203
|
// src/adapters/copilot.ts
|
|
28995
29204
|
import crypto7 from "crypto";
|
|
28996
|
-
import
|
|
28997
|
-
import
|
|
29205
|
+
import fs42 from "fs";
|
|
29206
|
+
import path42 from "path";
|
|
28998
29207
|
|
|
28999
29208
|
// src/compiler/commands.ts
|
|
29000
29209
|
var import_yaml11 = __toESM(require_dist(), 1);
|
|
29001
|
-
import
|
|
29210
|
+
import path41 from "path";
|
|
29002
29211
|
function compileCommandPrompt(sourceFile) {
|
|
29003
29212
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
29004
|
-
const relativeSource = `commands/${
|
|
29005
|
-
const fields = promptFrontmatter(data,
|
|
29213
|
+
const relativeSource = `commands/${path41.basename(sourceFile)}`;
|
|
29214
|
+
const fields = promptFrontmatter(data, path41.basename(sourceFile, ".md"));
|
|
29006
29215
|
const marker = formatProvenanceMarker(
|
|
29007
29216
|
"markdown",
|
|
29008
29217
|
relativeSource,
|
|
@@ -29143,7 +29352,7 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
29143
29352
|
if (!shouldSkipComponent3(options, "hooks")) {
|
|
29144
29353
|
outcomes.push(
|
|
29145
29354
|
syncHookScriptsBridge({
|
|
29146
|
-
source:
|
|
29355
|
+
source: path42.resolve(sourceRoot, config.source.hooks),
|
|
29147
29356
|
destination: resolveTargetPath(paths.hook_scripts),
|
|
29148
29357
|
config,
|
|
29149
29358
|
sourceRoot,
|
|
@@ -29224,13 +29433,13 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
29224
29433
|
}
|
|
29225
29434
|
function syncProviderLoss2(config, sourceRoot, mappings, lossReport) {
|
|
29226
29435
|
if (!mappings.modelTiers.custom_provider) return;
|
|
29227
|
-
const agentsDir =
|
|
29228
|
-
if (!
|
|
29229
|
-
for (const agentFile of ts(
|
|
29436
|
+
const agentsDir = path42.join(sourceRoot, config.source.agents);
|
|
29437
|
+
if (!fs42.existsSync(agentsDir)) return;
|
|
29438
|
+
for (const agentFile of ts(path42.join(agentsDir, "*.md")).sort()) {
|
|
29230
29439
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
29231
29440
|
const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
29232
29441
|
if (hasProvider) {
|
|
29233
|
-
const basename =
|
|
29442
|
+
const basename = path42.basename(agentFile);
|
|
29234
29443
|
addLoss(lossReport, "copilot", "agents", {
|
|
29235
29444
|
source: `agents/${basename}`,
|
|
29236
29445
|
fields: [
|
|
@@ -29256,22 +29465,22 @@ function syncCopilotInstructions(config, sourceRoot, options, lossReport, logger
|
|
|
29256
29465
|
return [{ component: "instructions", status: "skipped", path: message }];
|
|
29257
29466
|
}
|
|
29258
29467
|
const source = instructionsSourcePath(sourceRoot, config);
|
|
29259
|
-
if (!
|
|
29468
|
+
if (!fs42.existsSync(source)) {
|
|
29260
29469
|
return [skippedMissingSource3("instructions", source)];
|
|
29261
29470
|
}
|
|
29262
|
-
const rawContent =
|
|
29471
|
+
const rawContent = fs42.readFileSync(source, "utf8");
|
|
29263
29472
|
const contentHash = hashString2(rawContent);
|
|
29264
29473
|
const marker = formatProvenanceMarker(
|
|
29265
29474
|
"markdown",
|
|
29266
|
-
|
|
29475
|
+
path42.basename(instructionsSourceLabel(sourceRoot, config)),
|
|
29267
29476
|
contentHash,
|
|
29268
29477
|
"copilot"
|
|
29269
29478
|
);
|
|
29270
29479
|
const composedContent = `${marker}
|
|
29271
29480
|
${rawContent}`;
|
|
29272
29481
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
29273
|
-
const agentsMdDest =
|
|
29274
|
-
const mirrorDest =
|
|
29482
|
+
const agentsMdDest = path42.resolve(projectRoot, "AGENTS.md");
|
|
29483
|
+
const mirrorDest = path42.resolve(
|
|
29275
29484
|
projectRoot,
|
|
29276
29485
|
".github",
|
|
29277
29486
|
"copilot-instructions.md"
|
|
@@ -29325,14 +29534,14 @@ function writeInstructionsFile(component, destination, content, contentHash, con
|
|
|
29325
29534
|
if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
|
|
29326
29535
|
return { component, status: "conflict", path: destination };
|
|
29327
29536
|
}
|
|
29328
|
-
ensureDir(
|
|
29537
|
+
ensureDir(path42.dirname(destination));
|
|
29329
29538
|
const clearedLink = clearSymlinkAtDestination(destination);
|
|
29330
29539
|
if (clearedLink !== null) {
|
|
29331
29540
|
logger.verbose(
|
|
29332
29541
|
` ${destination}: replaced a symlink to ${clearedLink} with generated content`
|
|
29333
29542
|
);
|
|
29334
29543
|
}
|
|
29335
|
-
|
|
29544
|
+
fs42.writeFileSync(destination, content);
|
|
29336
29545
|
return { component, status: "success", path: destination };
|
|
29337
29546
|
}
|
|
29338
29547
|
function hashString2(value) {
|
|
@@ -29342,7 +29551,7 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
29342
29551
|
return syncSkillsSlot({
|
|
29343
29552
|
config,
|
|
29344
29553
|
sourceRoot,
|
|
29345
|
-
source:
|
|
29554
|
+
source: path42.resolve(sourceRoot, config.source.skills),
|
|
29346
29555
|
destination: resolveTargetPath(paths.skills),
|
|
29347
29556
|
dryRun: options.dryRun,
|
|
29348
29557
|
logger,
|
|
@@ -29357,16 +29566,16 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
29357
29566
|
});
|
|
29358
29567
|
}
|
|
29359
29568
|
function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
29360
|
-
const sourceAgentsRoot =
|
|
29361
|
-
if (!
|
|
29569
|
+
const sourceAgentsRoot = path42.join(sourceRoot, config.source.agents);
|
|
29570
|
+
if (!fs42.existsSync(sourceAgentsRoot)) {
|
|
29362
29571
|
return [skippedMissingSource3("agents", sourceAgentsRoot)];
|
|
29363
29572
|
}
|
|
29364
|
-
const sourceAgents = ts(
|
|
29573
|
+
const sourceAgents = ts(path42.join(sourceAgentsRoot, "*.md")).sort();
|
|
29365
29574
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
29366
29575
|
return sourceAgents.map((agentFile) => {
|
|
29367
|
-
const destination =
|
|
29576
|
+
const destination = path42.join(
|
|
29368
29577
|
agentsRoot,
|
|
29369
|
-
`${
|
|
29578
|
+
`${path42.basename(agentFile, ".md")}.agent.md`
|
|
29370
29579
|
);
|
|
29371
29580
|
const compiled = compileAgent(
|
|
29372
29581
|
agentFile,
|
|
@@ -29394,16 +29603,16 @@ function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, l
|
|
|
29394
29603
|
});
|
|
29395
29604
|
}
|
|
29396
29605
|
function syncCommands(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
29397
|
-
const sourceCommandsRoot =
|
|
29398
|
-
if (!
|
|
29606
|
+
const sourceCommandsRoot = path42.join(sourceRoot, config.source.commands);
|
|
29607
|
+
if (!fs42.existsSync(sourceCommandsRoot)) {
|
|
29399
29608
|
return [skippedMissingSource3("commands", sourceCommandsRoot)];
|
|
29400
29609
|
}
|
|
29401
|
-
const sourceCommands = ts(
|
|
29610
|
+
const sourceCommands = ts(path42.join(sourceCommandsRoot, "*.md")).sort();
|
|
29402
29611
|
const promptsRoot = resolveTargetPath(paths.prompts);
|
|
29403
29612
|
return sourceCommands.map((commandFile) => {
|
|
29404
|
-
const destination =
|
|
29613
|
+
const destination = path42.join(
|
|
29405
29614
|
promptsRoot,
|
|
29406
|
-
`${
|
|
29615
|
+
`${path42.basename(commandFile, ".md")}.prompt.md`
|
|
29407
29616
|
);
|
|
29408
29617
|
const compiled = compileCommandPrompt(commandFile);
|
|
29409
29618
|
if (options.dryRun) {
|
|
@@ -29427,7 +29636,7 @@ function syncCommands(config, sourceRoot, paths, options, logger, manifest, scop
|
|
|
29427
29636
|
});
|
|
29428
29637
|
}
|
|
29429
29638
|
function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, logger) {
|
|
29430
|
-
const destination =
|
|
29639
|
+
const destination = path42.join(
|
|
29431
29640
|
resolveTargetPath(paths.hooks),
|
|
29432
29641
|
"tangyr-managed.json"
|
|
29433
29642
|
);
|
|
@@ -29490,10 +29699,10 @@ function syncMcp3(config, sourceRoot, paths, options, lossReport, logger) {
|
|
|
29490
29699
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
29491
29700
|
const sourceLabel = mcpSourceLabel(config);
|
|
29492
29701
|
const destination = resolveTargetPath(paths.mcp_shared_file);
|
|
29493
|
-
if (!
|
|
29702
|
+
if (!fs42.existsSync(source)) {
|
|
29494
29703
|
return skippedMissingSource3("mcp", source);
|
|
29495
29704
|
}
|
|
29496
|
-
const sourceMcpJson = JSON.parse(
|
|
29705
|
+
const sourceMcpJson = JSON.parse(fs42.readFileSync(source, "utf8"));
|
|
29497
29706
|
const compiled = compileMcp(
|
|
29498
29707
|
sourceMcpJson,
|
|
29499
29708
|
"copilot",
|
|
@@ -29516,13 +29725,13 @@ function syncMcp3(config, sourceRoot, paths, options, lossReport, logger) {
|
|
|
29516
29725
|
);
|
|
29517
29726
|
}
|
|
29518
29727
|
function syncRules2(config, sourceRoot, rulesSlot, options, logger, manifest, scopePath) {
|
|
29519
|
-
const sourceRulesDir =
|
|
29520
|
-
if (!
|
|
29728
|
+
const sourceRulesDir = path42.resolve(sourceRoot, config.source.rules);
|
|
29729
|
+
if (!fs42.existsSync(sourceRulesDir)) {
|
|
29521
29730
|
return [skippedMissingSource3("rules", sourceRulesDir)];
|
|
29522
29731
|
}
|
|
29523
29732
|
const destinationRoot = resolveTargetPath(rulesSlot);
|
|
29524
29733
|
return compileCopilotRules(sourceRulesDir).map((file) => {
|
|
29525
|
-
const destination =
|
|
29734
|
+
const destination = path42.join(destinationRoot, file.name);
|
|
29526
29735
|
if (options.dryRun) {
|
|
29527
29736
|
logger.info(`[dry-run] rules: compile -> ${destination}`);
|
|
29528
29737
|
return {
|
|
@@ -29556,19 +29765,19 @@ function writeCompiledArtifact2(component, destination, content, expectedHash, c
|
|
|
29556
29765
|
if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
|
|
29557
29766
|
return { component, status: "conflict", path: destination };
|
|
29558
29767
|
}
|
|
29559
|
-
ensureDir(
|
|
29768
|
+
ensureDir(path42.dirname(destination));
|
|
29560
29769
|
const clearedLink = clearSymlinkAtDestination(destination);
|
|
29561
29770
|
if (clearedLink !== null) {
|
|
29562
29771
|
logger.verbose(
|
|
29563
29772
|
` ${destination}: replaced a symlink to ${clearedLink} with generated content`
|
|
29564
29773
|
);
|
|
29565
29774
|
}
|
|
29566
|
-
|
|
29775
|
+
fs42.writeFileSync(destination, content);
|
|
29567
29776
|
return { component, status: "success", path: destination };
|
|
29568
29777
|
}
|
|
29569
29778
|
function isCompiledCurrent2(destination, expectedContent, _expectedHash) {
|
|
29570
29779
|
try {
|
|
29571
|
-
return
|
|
29780
|
+
return fs42.readFileSync(destination, "utf8") === expectedContent;
|
|
29572
29781
|
} catch {
|
|
29573
29782
|
return false;
|
|
29574
29783
|
}
|
|
@@ -29588,7 +29797,7 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
|
|
|
29588
29797
|
if (manifest && scopePath) {
|
|
29589
29798
|
backupFile(destination, manifest, scopePath);
|
|
29590
29799
|
writeManifest(scopePath, manifest);
|
|
29591
|
-
|
|
29800
|
+
fs42.rmSync(destination, { recursive: true, force: true });
|
|
29592
29801
|
} else {
|
|
29593
29802
|
const parked = parkConflictingPath(
|
|
29594
29803
|
destination,
|
|
@@ -29603,7 +29812,7 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
|
|
|
29603
29812
|
}
|
|
29604
29813
|
return true;
|
|
29605
29814
|
}
|
|
29606
|
-
|
|
29815
|
+
fs42.rmSync(destination, { recursive: true, force: true });
|
|
29607
29816
|
return true;
|
|
29608
29817
|
}
|
|
29609
29818
|
function shouldSkipComponent3(options, component) {
|
|
@@ -29612,12 +29821,12 @@ function shouldSkipComponent3(options, component) {
|
|
|
29612
29821
|
function cleanupLegacyAgents(paths, options, logger) {
|
|
29613
29822
|
const currentAgentsRoot = resolveTargetPath(paths.agents);
|
|
29614
29823
|
const legacyAgentsRoot = resolveTargetPath(legacyCopilotAgentsPath);
|
|
29615
|
-
if (
|
|
29824
|
+
if (path42.resolve(currentAgentsRoot) === path42.resolve(legacyAgentsRoot)) {
|
|
29616
29825
|
return [];
|
|
29617
29826
|
}
|
|
29618
29827
|
const outcomes = [];
|
|
29619
29828
|
for (const filePath of ts(
|
|
29620
|
-
|
|
29829
|
+
path42.join(legacyAgentsRoot, "*.agent.md")
|
|
29621
29830
|
).sort()) {
|
|
29622
29831
|
if (!isCopilotManagedCompiledFile(filePath)) {
|
|
29623
29832
|
continue;
|
|
@@ -29627,14 +29836,14 @@ function cleanupLegacyAgents(paths, options, logger) {
|
|
|
29627
29836
|
outcomes.push({ component: "agents", status: "dry-run", path: filePath });
|
|
29628
29837
|
continue;
|
|
29629
29838
|
}
|
|
29630
|
-
|
|
29839
|
+
fs42.rmSync(filePath, { force: true });
|
|
29631
29840
|
outcomes.push({ component: "agents", status: "success", path: filePath });
|
|
29632
29841
|
}
|
|
29633
29842
|
return outcomes;
|
|
29634
29843
|
}
|
|
29635
29844
|
function isCopilotManagedCompiledFile(filePath) {
|
|
29636
29845
|
try {
|
|
29637
|
-
return extractProvenanceMarker(
|
|
29846
|
+
return extractProvenanceMarker(fs42.readFileSync(filePath, "utf8"))?.target === "copilot";
|
|
29638
29847
|
} catch {
|
|
29639
29848
|
return false;
|
|
29640
29849
|
}
|
|
@@ -29649,8 +29858,8 @@ function skippedMissingSource3(component, source) {
|
|
|
29649
29858
|
|
|
29650
29859
|
// src/adapters/cursor.ts
|
|
29651
29860
|
import crypto8 from "crypto";
|
|
29652
|
-
import
|
|
29653
|
-
import
|
|
29861
|
+
import fs43 from "fs";
|
|
29862
|
+
import path43 from "path";
|
|
29654
29863
|
function syncCursor(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
29655
29864
|
const scope = options.scope ?? "global";
|
|
29656
29865
|
const profile = resolveTargetPaths({
|
|
@@ -29762,7 +29971,7 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
|
|
|
29762
29971
|
if (!shouldSkipComponent4(options, "hooks")) {
|
|
29763
29972
|
outcomes.push(
|
|
29764
29973
|
syncHookScriptsBridge({
|
|
29765
|
-
source:
|
|
29974
|
+
source: path43.resolve(sourceRoot, config.source.hooks),
|
|
29766
29975
|
destination: resolveTargetPath(paths.hook_scripts),
|
|
29767
29976
|
config,
|
|
29768
29977
|
sourceRoot,
|
|
@@ -29827,7 +30036,7 @@ function syncInstructions2(config, sourceRoot, paths, options, lossReport, logge
|
|
|
29827
30036
|
const composed = composeCursorInstructions(config, sourceRoot, lossReport);
|
|
29828
30037
|
const marker = formatProvenanceMarker(
|
|
29829
30038
|
"markdown",
|
|
29830
|
-
|
|
30039
|
+
path43.basename(instructionsSourceLabel(sourceRoot, config)),
|
|
29831
30040
|
hashString3(composed),
|
|
29832
30041
|
"cursor"
|
|
29833
30042
|
);
|
|
@@ -29853,7 +30062,7 @@ ${composed}
|
|
|
29853
30062
|
}
|
|
29854
30063
|
function composeCursorInstructions(config, sourceRoot, lossReport) {
|
|
29855
30064
|
const source = instructionsSourcePath(sourceRoot, config);
|
|
29856
|
-
const baseContent =
|
|
30065
|
+
const baseContent = fs43.existsSync(source) ? fs43.readFileSync(source, "utf8").trim() : "";
|
|
29857
30066
|
const personaContent = extractPrimaryPersonaContent(
|
|
29858
30067
|
config,
|
|
29859
30068
|
sourceRoot,
|
|
@@ -29866,11 +30075,11 @@ function composeCursorInstructions(config, sourceRoot, lossReport) {
|
|
|
29866
30075
|
${personaContent}`.trim() : baseContent;
|
|
29867
30076
|
}
|
|
29868
30077
|
function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
29869
|
-
const agentsDir =
|
|
29870
|
-
if (!
|
|
30078
|
+
const agentsDir = path43.join(sourceRoot, config.source.agents);
|
|
30079
|
+
if (!fs43.existsSync(agentsDir)) {
|
|
29871
30080
|
return null;
|
|
29872
30081
|
}
|
|
29873
|
-
const agentFiles = ts(
|
|
30082
|
+
const agentFiles = ts(path43.join(agentsDir, "*.md")).sort();
|
|
29874
30083
|
if (agentFiles.length === 0) {
|
|
29875
30084
|
return null;
|
|
29876
30085
|
}
|
|
@@ -29893,7 +30102,7 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
|
29893
30102
|
return null;
|
|
29894
30103
|
}
|
|
29895
30104
|
addLoss(lossReport, "cursor", "instructions", {
|
|
29896
|
-
source: `agents/${
|
|
30105
|
+
source: `agents/${path43.basename(primaryFile)}`,
|
|
29897
30106
|
fields: [
|
|
29898
30107
|
{
|
|
29899
30108
|
field: "persona",
|
|
@@ -29903,23 +30112,23 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
|
29903
30112
|
"persona",
|
|
29904
30113
|
"instructions-shim"
|
|
29905
30114
|
),
|
|
29906
|
-
detail: `Primary persona from ${
|
|
30115
|
+
detail: `Primary persona from ${path43.basename(primaryFile)} folded into AGENTS.md (Cursor has no custom modes surface)`
|
|
29907
30116
|
}
|
|
29908
30117
|
]
|
|
29909
30118
|
});
|
|
29910
30119
|
return body.trim();
|
|
29911
30120
|
}
|
|
29912
30121
|
function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
29913
|
-
const sourceAgentsRoot =
|
|
29914
|
-
if (!
|
|
30122
|
+
const sourceAgentsRoot = path43.join(sourceRoot, config.source.agents);
|
|
30123
|
+
if (!fs43.existsSync(sourceAgentsRoot)) {
|
|
29915
30124
|
return [skippedMissingSource4("agents", sourceAgentsRoot)];
|
|
29916
30125
|
}
|
|
29917
|
-
const sourceAgents = ts(
|
|
30126
|
+
const sourceAgents = ts(path43.join(sourceAgentsRoot, "*.md")).sort();
|
|
29918
30127
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
29919
30128
|
return sourceAgents.map((agentFile) => {
|
|
29920
|
-
const destination =
|
|
30129
|
+
const destination = path43.join(
|
|
29921
30130
|
agentsRoot,
|
|
29922
|
-
`${
|
|
30131
|
+
`${path43.basename(agentFile, ".md")}.md`
|
|
29923
30132
|
);
|
|
29924
30133
|
let compiled;
|
|
29925
30134
|
try {
|
|
@@ -29960,14 +30169,14 @@ function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, l
|
|
|
29960
30169
|
});
|
|
29961
30170
|
}
|
|
29962
30171
|
function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
|
|
29963
|
-
const sourceRulesDir =
|
|
29964
|
-
if (!
|
|
30172
|
+
const sourceRulesDir = path43.join(sourceRoot, config.source.rules);
|
|
30173
|
+
if (!fs43.existsSync(sourceRulesDir)) {
|
|
29965
30174
|
return [skippedMissingSource4("rules", sourceRulesDir)];
|
|
29966
30175
|
}
|
|
29967
30176
|
const compiled = compileRules(sourceRulesDir, "cursor", mappings, lossReport);
|
|
29968
30177
|
const rulesDir = resolveTargetPath(paths.rules);
|
|
29969
30178
|
return compiled.dotRulesFiles.map(({ name, content }) => {
|
|
29970
|
-
const destination =
|
|
30179
|
+
const destination = path43.join(rulesDir, name);
|
|
29971
30180
|
if (options.dryRun) {
|
|
29972
30181
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
29973
30182
|
return {
|
|
@@ -29991,15 +30200,15 @@ function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
29991
30200
|
});
|
|
29992
30201
|
}
|
|
29993
30202
|
function syncCommands2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
29994
|
-
const sourceCommandsRoot =
|
|
29995
|
-
if (!
|
|
30203
|
+
const sourceCommandsRoot = path43.join(sourceRoot, config.source.commands);
|
|
30204
|
+
if (!fs43.existsSync(sourceCommandsRoot)) {
|
|
29996
30205
|
return [skippedMissingSource4("commands", sourceCommandsRoot)];
|
|
29997
30206
|
}
|
|
29998
|
-
const sourceCommands = ts(
|
|
30207
|
+
const sourceCommands = ts(path43.join(sourceCommandsRoot, "*.md")).sort();
|
|
29999
30208
|
const skillsRoot = resolveTargetPath(paths.skills);
|
|
30000
30209
|
return sourceCommands.map((commandFile) => {
|
|
30001
|
-
const baseName =
|
|
30002
|
-
const destination =
|
|
30210
|
+
const baseName = path43.basename(commandFile, ".md");
|
|
30211
|
+
const destination = path43.join(skillsRoot, baseName, "SKILL.md");
|
|
30003
30212
|
const { content } = compileCommandAsSkill(commandFile, "cursor");
|
|
30004
30213
|
if (options.dryRun) {
|
|
30005
30214
|
logger.info(
|
|
@@ -30029,7 +30238,7 @@ function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, _
|
|
|
30029
30238
|
return syncSkillsSlot({
|
|
30030
30239
|
config,
|
|
30031
30240
|
sourceRoot,
|
|
30032
|
-
source:
|
|
30241
|
+
source: path43.resolve(sourceRoot, config.source.skills),
|
|
30033
30242
|
destination,
|
|
30034
30243
|
dryRun: options.dryRun,
|
|
30035
30244
|
logger,
|
|
@@ -30077,18 +30286,18 @@ function syncHooks4(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
30077
30286
|
}
|
|
30078
30287
|
const hooksFileContent = `${JSON.stringify({ version: 1, hooks: compiled.payload }, null, 2)}
|
|
30079
30288
|
`;
|
|
30080
|
-
ensureDir(
|
|
30081
|
-
|
|
30289
|
+
ensureDir(path43.dirname(destination));
|
|
30290
|
+
fs43.writeFileSync(destination, hooksFileContent);
|
|
30082
30291
|
return { component: "hooks", status: "success", path: destination };
|
|
30083
30292
|
}
|
|
30084
30293
|
function syncMcp4(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
|
|
30085
30294
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
30086
30295
|
const sourceLabel = mcpSourceLabel(config);
|
|
30087
30296
|
const destination = resolveTargetPath(paths.mcp_file);
|
|
30088
|
-
if (!
|
|
30297
|
+
if (!fs43.existsSync(source)) {
|
|
30089
30298
|
return skippedMissingSource4("mcp", source);
|
|
30090
30299
|
}
|
|
30091
|
-
const sourceMcpJson = JSON.parse(
|
|
30300
|
+
const sourceMcpJson = JSON.parse(fs43.readFileSync(source, "utf8"));
|
|
30092
30301
|
const mcpJson = compileMcp(sourceMcpJson, "cursor", lossReport, sourceLabel);
|
|
30093
30302
|
if (options.dryRun) {
|
|
30094
30303
|
logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
|
|
@@ -30141,13 +30350,13 @@ function syncPermissions(config, paths, options, _lossReport, logger, manifest,
|
|
|
30141
30350
|
);
|
|
30142
30351
|
}
|
|
30143
30352
|
function syncProviderPin(config, sourceRoot, lossReport) {
|
|
30144
|
-
const agentsDir =
|
|
30145
|
-
if (!
|
|
30146
|
-
for (const agentFile of ts(
|
|
30353
|
+
const agentsDir = path43.join(sourceRoot, config.source.agents);
|
|
30354
|
+
if (!fs43.existsSync(agentsDir)) return;
|
|
30355
|
+
for (const agentFile of ts(path43.join(agentsDir, "*.md")).sort()) {
|
|
30147
30356
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
30148
30357
|
const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
30149
30358
|
if (hasCustomProvider) {
|
|
30150
|
-
const relativeSource = `agents/${
|
|
30359
|
+
const relativeSource = `agents/${path43.basename(agentFile)}`;
|
|
30151
30360
|
addLoss(lossReport, "cursor", "agents", {
|
|
30152
30361
|
source: relativeSource,
|
|
30153
30362
|
fields: [
|
|
@@ -30159,7 +30368,7 @@ function syncProviderPin(config, sourceRoot, lossReport) {
|
|
|
30159
30368
|
"provider",
|
|
30160
30369
|
"provider-not-representable"
|
|
30161
30370
|
),
|
|
30162
|
-
detail: `${
|
|
30371
|
+
detail: `${path43.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
30163
30372
|
}
|
|
30164
30373
|
]
|
|
30165
30374
|
});
|
|
@@ -30177,14 +30386,14 @@ function writeCompiledArtifact3(component, destination, content, expectedHash, c
|
|
|
30177
30386
|
if (artifactClass === "unmanaged-conflict" && !handleConflict4(destination, config, options, logger, manifest, scopePath)) {
|
|
30178
30387
|
return { component, status: "conflict", path: destination };
|
|
30179
30388
|
}
|
|
30180
|
-
ensureDir(
|
|
30389
|
+
ensureDir(path43.dirname(destination));
|
|
30181
30390
|
const clearedLink = clearSymlinkAtDestination(destination);
|
|
30182
30391
|
if (clearedLink !== null) {
|
|
30183
30392
|
logger.verbose(
|
|
30184
30393
|
` ${destination}: replaced a symlink to ${clearedLink} with generated content`
|
|
30185
30394
|
);
|
|
30186
30395
|
}
|
|
30187
|
-
|
|
30396
|
+
fs43.writeFileSync(destination, content);
|
|
30188
30397
|
return { component, status: "success", path: destination };
|
|
30189
30398
|
}
|
|
30190
30399
|
function handleConflict4(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -30202,7 +30411,7 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
|
|
|
30202
30411
|
if (manifest && scopePath) {
|
|
30203
30412
|
backupFile(destination, manifest, scopePath);
|
|
30204
30413
|
writeManifest(scopePath, manifest);
|
|
30205
|
-
|
|
30414
|
+
fs43.rmSync(destination, { recursive: true, force: true });
|
|
30206
30415
|
} else {
|
|
30207
30416
|
const parked = parkConflictingPath(
|
|
30208
30417
|
destination,
|
|
@@ -30217,12 +30426,12 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
|
|
|
30217
30426
|
}
|
|
30218
30427
|
return true;
|
|
30219
30428
|
}
|
|
30220
|
-
|
|
30429
|
+
fs43.rmSync(destination, { recursive: true, force: true });
|
|
30221
30430
|
return true;
|
|
30222
30431
|
}
|
|
30223
30432
|
function isCompiledCurrent3(destination, expectedContent, _expectedHash) {
|
|
30224
30433
|
try {
|
|
30225
|
-
return
|
|
30434
|
+
return fs43.readFileSync(destination, "utf8") === expectedContent;
|
|
30226
30435
|
} catch {
|
|
30227
30436
|
return false;
|
|
30228
30437
|
}
|
|
@@ -30243,8 +30452,8 @@ function hashString3(value) {
|
|
|
30243
30452
|
|
|
30244
30453
|
// src/adapters/cline.ts
|
|
30245
30454
|
import crypto9 from "crypto";
|
|
30246
|
-
import
|
|
30247
|
-
import
|
|
30455
|
+
import fs44 from "fs";
|
|
30456
|
+
import path44 from "path";
|
|
30248
30457
|
function syncCline(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
30249
30458
|
const scope = options.scope ?? "global";
|
|
30250
30459
|
const profile = resolveTargetPaths({
|
|
@@ -30357,7 +30566,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
30357
30566
|
function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport, logger, manifest, scopePath) {
|
|
30358
30567
|
if (scope === "global" || paths.instructions === null) {
|
|
30359
30568
|
addLoss(lossReport, "cline", "instructions", {
|
|
30360
|
-
source:
|
|
30569
|
+
source: path44.basename(instructionsSourceLabel(sourceRoot, config)),
|
|
30361
30570
|
fields: [
|
|
30362
30571
|
{
|
|
30363
30572
|
field: "instructions",
|
|
@@ -30379,10 +30588,10 @@ function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport
|
|
|
30379
30588
|
}
|
|
30380
30589
|
const source = instructionsSourcePath(sourceRoot, config);
|
|
30381
30590
|
const destination = resolveTargetPath(paths.instructions);
|
|
30382
|
-
const baseContent =
|
|
30591
|
+
const baseContent = fs44.existsSync(source) ? fs44.readFileSync(source, "utf8").trim() : "";
|
|
30383
30592
|
const marker = formatProvenanceMarker(
|
|
30384
30593
|
"markdown",
|
|
30385
|
-
|
|
30594
|
+
path44.basename(instructionsSourceLabel(sourceRoot, config)),
|
|
30386
30595
|
hashString4(baseContent),
|
|
30387
30596
|
"cline"
|
|
30388
30597
|
);
|
|
@@ -30407,11 +30616,11 @@ ${baseContent}
|
|
|
30407
30616
|
);
|
|
30408
30617
|
}
|
|
30409
30618
|
function syncAgents4(config, sourceRoot, mappings, extensions, options, lossReport, logger) {
|
|
30410
|
-
const sourceAgentsRoot =
|
|
30411
|
-
if (!
|
|
30619
|
+
const sourceAgentsRoot = path44.join(sourceRoot, config.source.agents);
|
|
30620
|
+
if (!fs44.existsSync(sourceAgentsRoot)) {
|
|
30412
30621
|
return [skippedMissingSource5("agents", sourceAgentsRoot)];
|
|
30413
30622
|
}
|
|
30414
|
-
const sourceAgents = ts(
|
|
30623
|
+
const sourceAgents = ts(path44.join(sourceAgentsRoot, "*.md")).sort();
|
|
30415
30624
|
return sourceAgents.map((agentFile) => {
|
|
30416
30625
|
compileAgent(agentFile, "cline", mappings, extensions, lossReport);
|
|
30417
30626
|
if (options.dryRun) {
|
|
@@ -30427,14 +30636,14 @@ function syncAgents4(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
30427
30636
|
});
|
|
30428
30637
|
}
|
|
30429
30638
|
function syncRules4(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
|
|
30430
|
-
const sourceRulesDir =
|
|
30431
|
-
if (!
|
|
30639
|
+
const sourceRulesDir = path44.join(sourceRoot, config.source.rules);
|
|
30640
|
+
if (!fs44.existsSync(sourceRulesDir)) {
|
|
30432
30641
|
return [skippedMissingSource5("rules", sourceRulesDir)];
|
|
30433
30642
|
}
|
|
30434
30643
|
const compiled = compileRules(sourceRulesDir, "cline", mappings, lossReport);
|
|
30435
30644
|
const rulesDir = resolveTargetPath(paths.rules);
|
|
30436
30645
|
return compiled.dotRulesFiles.map(({ name, content }) => {
|
|
30437
|
-
const destination =
|
|
30646
|
+
const destination = path44.join(rulesDir, name);
|
|
30438
30647
|
if (options.dryRun) {
|
|
30439
30648
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
30440
30649
|
return {
|
|
@@ -30458,17 +30667,17 @@ function syncRules4(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
30458
30667
|
});
|
|
30459
30668
|
}
|
|
30460
30669
|
function syncCommands3(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
30461
|
-
const sourceCommandsRoot =
|
|
30462
|
-
if (!
|
|
30670
|
+
const sourceCommandsRoot = path44.join(sourceRoot, config.source.commands);
|
|
30671
|
+
if (!fs44.existsSync(sourceCommandsRoot)) {
|
|
30463
30672
|
return [skippedMissingSource5("commands", sourceCommandsRoot)];
|
|
30464
30673
|
}
|
|
30465
|
-
const sourceCommands = ts(
|
|
30674
|
+
const sourceCommands = ts(path44.join(sourceCommandsRoot, "*.md")).sort();
|
|
30466
30675
|
const workflowsRoot = resolveTargetPath(paths.workflows);
|
|
30467
30676
|
return sourceCommands.map((commandFile) => {
|
|
30468
|
-
const baseName =
|
|
30469
|
-
const destination =
|
|
30470
|
-
const commandContent =
|
|
30471
|
-
const relativeSource = `commands/${
|
|
30677
|
+
const baseName = path44.basename(commandFile);
|
|
30678
|
+
const destination = path44.join(workflowsRoot, baseName);
|
|
30679
|
+
const commandContent = fs44.readFileSync(commandFile, "utf8");
|
|
30680
|
+
const relativeSource = `commands/${path44.basename(commandFile)}`;
|
|
30472
30681
|
const marker = formatProvenanceMarker(
|
|
30473
30682
|
"markdown",
|
|
30474
30683
|
relativeSource,
|
|
@@ -30506,7 +30715,7 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
30506
30715
|
return syncSkillsSlot({
|
|
30507
30716
|
config,
|
|
30508
30717
|
sourceRoot,
|
|
30509
|
-
source:
|
|
30718
|
+
source: path44.resolve(sourceRoot, config.source.skills),
|
|
30510
30719
|
destination: resolveTargetPath(paths.skills),
|
|
30511
30720
|
dryRun: options.dryRun,
|
|
30512
30721
|
logger,
|
|
@@ -30539,10 +30748,10 @@ function syncMcp5(config, sourceRoot, paths, options, lossReport, logger, manife
|
|
|
30539
30748
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
30540
30749
|
const sourceLabel = mcpSourceLabel(config);
|
|
30541
30750
|
const destination = resolveTargetPath(paths.mcp_file);
|
|
30542
|
-
if (!
|
|
30751
|
+
if (!fs44.existsSync(source)) {
|
|
30543
30752
|
return skippedMissingSource5("mcp", source);
|
|
30544
30753
|
}
|
|
30545
|
-
const sourceMcpJson = JSON.parse(
|
|
30754
|
+
const sourceMcpJson = JSON.parse(fs44.readFileSync(source, "utf8"));
|
|
30546
30755
|
const mcpJson = compileMcp(sourceMcpJson, "cline", lossReport, sourceLabel);
|
|
30547
30756
|
if (options.dryRun) {
|
|
30548
30757
|
logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
|
|
@@ -30585,11 +30794,11 @@ function syncSettings2(lossReport) {
|
|
|
30585
30794
|
};
|
|
30586
30795
|
}
|
|
30587
30796
|
function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
30588
|
-
const agentsDir =
|
|
30589
|
-
if (!
|
|
30590
|
-
for (const agentFile of ts(
|
|
30797
|
+
const agentsDir = path44.join(sourceRoot, config.source.agents);
|
|
30798
|
+
if (!fs44.existsSync(agentsDir)) return;
|
|
30799
|
+
for (const agentFile of ts(path44.join(agentsDir, "*.md")).sort()) {
|
|
30591
30800
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
30592
|
-
const relativeSource = `agents/${
|
|
30801
|
+
const relativeSource = `agents/${path44.basename(agentFile)}`;
|
|
30593
30802
|
const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
30594
30803
|
if (hasCustomProvider) {
|
|
30595
30804
|
addLoss(lossReport, "cline", "agents", {
|
|
@@ -30603,7 +30812,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
|
30603
30812
|
"provider",
|
|
30604
30813
|
"provider-not-representable"
|
|
30605
30814
|
),
|
|
30606
|
-
detail: `${
|
|
30815
|
+
detail: `${path44.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
|
|
30607
30816
|
}
|
|
30608
30817
|
]
|
|
30609
30818
|
});
|
|
@@ -30621,7 +30830,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
|
30621
30830
|
"model",
|
|
30622
30831
|
"model-not-representable"
|
|
30623
30832
|
),
|
|
30624
|
-
detail: `${
|
|
30833
|
+
detail: `${path44.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
|
|
30625
30834
|
}
|
|
30626
30835
|
]
|
|
30627
30836
|
});
|
|
@@ -30639,14 +30848,14 @@ function writeCompiledArtifact4(component, destination, content, expectedHash, c
|
|
|
30639
30848
|
if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
|
|
30640
30849
|
return { component, status: "conflict", path: destination };
|
|
30641
30850
|
}
|
|
30642
|
-
ensureDir(
|
|
30851
|
+
ensureDir(path44.dirname(destination));
|
|
30643
30852
|
const clearedLink = clearSymlinkAtDestination(destination);
|
|
30644
30853
|
if (clearedLink !== null) {
|
|
30645
30854
|
logger.verbose(
|
|
30646
30855
|
` ${destination}: replaced a symlink to ${clearedLink} with generated content`
|
|
30647
30856
|
);
|
|
30648
30857
|
}
|
|
30649
|
-
|
|
30858
|
+
fs44.writeFileSync(destination, content);
|
|
30650
30859
|
return { component, status: "success", path: destination };
|
|
30651
30860
|
}
|
|
30652
30861
|
function handleConflict5(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -30664,7 +30873,7 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
|
|
|
30664
30873
|
if (manifest && scopePath) {
|
|
30665
30874
|
backupFile(destination, manifest, scopePath);
|
|
30666
30875
|
writeManifest(scopePath, manifest);
|
|
30667
|
-
|
|
30876
|
+
fs44.rmSync(destination, { recursive: true, force: true });
|
|
30668
30877
|
} else {
|
|
30669
30878
|
const parked = parkConflictingPath(
|
|
30670
30879
|
destination,
|
|
@@ -30679,12 +30888,12 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
|
|
|
30679
30888
|
}
|
|
30680
30889
|
return true;
|
|
30681
30890
|
}
|
|
30682
|
-
|
|
30891
|
+
fs44.rmSync(destination, { recursive: true, force: true });
|
|
30683
30892
|
return true;
|
|
30684
30893
|
}
|
|
30685
30894
|
function isCompiledCurrent4(destination, expectedContent, _expectedHash) {
|
|
30686
30895
|
try {
|
|
30687
|
-
return
|
|
30896
|
+
return fs44.readFileSync(destination, "utf8") === expectedContent;
|
|
30688
30897
|
} catch {
|
|
30689
30898
|
return false;
|
|
30690
30899
|
}
|
|
@@ -30705,9 +30914,9 @@ function hashString4(value) {
|
|
|
30705
30914
|
|
|
30706
30915
|
// src/adapters/opencode.ts
|
|
30707
30916
|
import crypto10 from "crypto";
|
|
30708
|
-
import
|
|
30917
|
+
import fs45 from "fs";
|
|
30709
30918
|
import os6 from "os";
|
|
30710
|
-
import
|
|
30919
|
+
import path45 from "path";
|
|
30711
30920
|
var import_yaml12 = __toESM(require_dist(), 1);
|
|
30712
30921
|
function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
30713
30922
|
const scope = options.scope ?? "global";
|
|
@@ -30725,7 +30934,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
30725
30934
|
config_doc: profile.config_doc
|
|
30726
30935
|
};
|
|
30727
30936
|
const rules = compileRules(
|
|
30728
|
-
|
|
30937
|
+
path45.join(sourceRoot, config.source.rules),
|
|
30729
30938
|
"opencode",
|
|
30730
30939
|
mappings,
|
|
30731
30940
|
lossReport
|
|
@@ -30733,7 +30942,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
30733
30942
|
const outcomes = [];
|
|
30734
30943
|
if (!shouldSkipComponent6(options, "instructions")) {
|
|
30735
30944
|
outcomes.push(
|
|
30736
|
-
syncInstructions4(
|
|
30945
|
+
...syncInstructions4(
|
|
30737
30946
|
config,
|
|
30738
30947
|
sourceRoot,
|
|
30739
30948
|
paths,
|
|
@@ -30829,14 +31038,14 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
30829
31038
|
function syncInstructions4(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
|
|
30830
31039
|
const source = instructionsSourcePath(sourceRoot, config);
|
|
30831
31040
|
const destination = resolveTargetPath(paths.instructions);
|
|
30832
|
-
const baseContent =
|
|
31041
|
+
const baseContent = fs45.existsSync(source) ? fs45.readFileSync(source, "utf8").trim() : "";
|
|
30833
31042
|
const composed = agentsAppendix ? `${baseContent}
|
|
30834
31043
|
|
|
30835
31044
|
--- tangyr managed rules ---
|
|
30836
31045
|
${agentsAppendix}`.trim() : baseContent;
|
|
30837
31046
|
const marker = formatProvenanceMarker(
|
|
30838
31047
|
"markdown",
|
|
30839
|
-
|
|
31048
|
+
path45.basename(instructionsSourceLabel(sourceRoot, config)),
|
|
30840
31049
|
hashString5(composed),
|
|
30841
31050
|
"opencode"
|
|
30842
31051
|
);
|
|
@@ -30847,9 +31056,11 @@ ${composed}
|
|
|
30847
31056
|
logger.info(
|
|
30848
31057
|
`[dry-run] instructions: generate ${source} + rules appendix -> ${destination}`
|
|
30849
31058
|
);
|
|
30850
|
-
return
|
|
31059
|
+
return [
|
|
31060
|
+
{ component: "instructions", status: "dry-run", path: destination }
|
|
31061
|
+
];
|
|
30851
31062
|
}
|
|
30852
|
-
|
|
31063
|
+
const written = writeCompiledArtifact5(
|
|
30853
31064
|
"instructions",
|
|
30854
31065
|
destination,
|
|
30855
31066
|
content,
|
|
@@ -30861,18 +31072,60 @@ ${composed}
|
|
|
30861
31072
|
manifest,
|
|
30862
31073
|
scopePath
|
|
30863
31074
|
);
|
|
31075
|
+
const declared = declareInstructions(paths);
|
|
31076
|
+
return declared === null ? [written] : [
|
|
31077
|
+
written,
|
|
31078
|
+
{ component: "instructions", status: "success", path: declared }
|
|
31079
|
+
];
|
|
31080
|
+
}
|
|
31081
|
+
function declaredInstructionsPath(paths) {
|
|
31082
|
+
const configDir = path45.dirname(resolveTargetPath(paths.config_doc));
|
|
31083
|
+
const instructions = resolveTargetPath(paths.instructions);
|
|
31084
|
+
const relative = path45.relative(configDir, instructions);
|
|
31085
|
+
if (relative === "AGENTS.md" || relative.startsWith("..")) {
|
|
31086
|
+
return null;
|
|
31087
|
+
}
|
|
31088
|
+
return relative.split(path45.sep).join("/");
|
|
31089
|
+
}
|
|
31090
|
+
function withDeclaredInstructions(existing, reference) {
|
|
31091
|
+
const listed = Array.isArray(existing) ? existing.filter((entry) => typeof entry === "string") : [];
|
|
31092
|
+
return listed.includes(reference) ? listed : [...listed, reference];
|
|
31093
|
+
}
|
|
31094
|
+
function declareInstructions(paths) {
|
|
31095
|
+
const reference = declaredInstructionsPath(paths);
|
|
31096
|
+
if (reference === null) {
|
|
31097
|
+
return null;
|
|
31098
|
+
}
|
|
31099
|
+
const destination = resolveTargetPath(paths.config_doc);
|
|
31100
|
+
let existing = {};
|
|
31101
|
+
if (fs45.existsSync(destination)) {
|
|
31102
|
+
try {
|
|
31103
|
+
existing = JSON.parse(fs45.readFileSync(destination, "utf8"));
|
|
31104
|
+
} catch {
|
|
31105
|
+
existing = {};
|
|
31106
|
+
}
|
|
31107
|
+
}
|
|
31108
|
+
const config = {
|
|
31109
|
+
$schema: "https://opencode.ai/config.json",
|
|
31110
|
+
...existing,
|
|
31111
|
+
instructions: withDeclaredInstructions(existing.instructions, reference)
|
|
31112
|
+
};
|
|
31113
|
+
ensureDir(path45.dirname(destination));
|
|
31114
|
+
fs45.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
|
|
31115
|
+
`);
|
|
31116
|
+
return destination;
|
|
30864
31117
|
}
|
|
30865
31118
|
function syncAgents5(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
30866
|
-
const sourceAgentsRoot =
|
|
30867
|
-
if (!
|
|
31119
|
+
const sourceAgentsRoot = path45.join(sourceRoot, config.source.agents);
|
|
31120
|
+
if (!fs45.existsSync(sourceAgentsRoot)) {
|
|
30868
31121
|
return [skippedMissingSource6("agents", sourceAgentsRoot)];
|
|
30869
31122
|
}
|
|
30870
|
-
const sourceAgents = ts(
|
|
31123
|
+
const sourceAgents = ts(path45.join(sourceAgentsRoot, "*.md")).sort();
|
|
30871
31124
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
30872
31125
|
return sourceAgents.map((agentFile) => {
|
|
30873
|
-
const destination =
|
|
31126
|
+
const destination = path45.join(
|
|
30874
31127
|
agentsRoot,
|
|
30875
|
-
`${
|
|
31128
|
+
`${path45.basename(agentFile, ".md")}.md`
|
|
30876
31129
|
);
|
|
30877
31130
|
let compiled;
|
|
30878
31131
|
try {
|
|
@@ -30936,11 +31189,11 @@ function applyProviderModelBinding(compiled, mappings) {
|
|
|
30936
31189
|
return `${before}${(0, import_yaml12.stringify)(fields).trim()}${after}`;
|
|
30937
31190
|
}
|
|
30938
31191
|
function syncCommands4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
30939
|
-
const sourceCommandsRoot =
|
|
30940
|
-
if (!
|
|
31192
|
+
const sourceCommandsRoot = path45.join(sourceRoot, config.source.commands);
|
|
31193
|
+
if (!fs45.existsSync(sourceCommandsRoot)) {
|
|
30941
31194
|
return [skippedMissingSource6("commands", sourceCommandsRoot)];
|
|
30942
31195
|
}
|
|
30943
|
-
const sourceCommands = ts(
|
|
31196
|
+
const sourceCommands = ts(path45.join(sourceCommandsRoot, "*.md")).sort();
|
|
30944
31197
|
const commandsRoot = resolveTargetPath(paths.commands);
|
|
30945
31198
|
return sourceCommands.map((commandFile) => {
|
|
30946
31199
|
const { data, body } = parseCommandFile(commandFile);
|
|
@@ -30954,7 +31207,7 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
|
|
|
30954
31207
|
if (typeof data.model === "string") {
|
|
30955
31208
|
frontmatter.model = data.model;
|
|
30956
31209
|
}
|
|
30957
|
-
const relativeSource = `commands/${
|
|
31210
|
+
const relativeSource = `commands/${path45.basename(commandFile)}`;
|
|
30958
31211
|
const marker = formatProvenanceMarker(
|
|
30959
31212
|
"markdown",
|
|
30960
31213
|
relativeSource,
|
|
@@ -30970,9 +31223,9 @@ ${body.trimEnd()}
|
|
|
30970
31223
|
` : `${marker}
|
|
30971
31224
|
${body.trimEnd()}
|
|
30972
31225
|
`;
|
|
30973
|
-
const destination =
|
|
31226
|
+
const destination = path45.join(
|
|
30974
31227
|
commandsRoot,
|
|
30975
|
-
`${
|
|
31228
|
+
`${path45.basename(commandFile, ".md")}.md`
|
|
30976
31229
|
);
|
|
30977
31230
|
if (options.dryRun) {
|
|
30978
31231
|
logger.info(
|
|
@@ -31002,7 +31255,7 @@ function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scop
|
|
|
31002
31255
|
return syncSkillsSlot({
|
|
31003
31256
|
config,
|
|
31004
31257
|
sourceRoot,
|
|
31005
|
-
source:
|
|
31258
|
+
source: path45.resolve(sourceRoot, config.source.skills),
|
|
31006
31259
|
destination,
|
|
31007
31260
|
dryRun: options.dryRun,
|
|
31008
31261
|
logger,
|
|
@@ -31020,13 +31273,13 @@ function syncMcp6(config, sourceRoot, paths, mappings, options, lossReport, logg
|
|
|
31020
31273
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
31021
31274
|
const sourceLabel = mcpSourceLabel(config);
|
|
31022
31275
|
const destination = resolveTargetPath(paths.config_doc);
|
|
31023
|
-
if (!
|
|
31276
|
+
if (!fs45.existsSync(source)) {
|
|
31024
31277
|
if (!options.dryRun) {
|
|
31025
31278
|
syncConfigDoc(paths, {}, lossReport, {}, mappings);
|
|
31026
31279
|
}
|
|
31027
31280
|
return skippedMissingSource6("mcp", source);
|
|
31028
31281
|
}
|
|
31029
|
-
const sourceMcpJson = JSON.parse(
|
|
31282
|
+
const sourceMcpJson = JSON.parse(fs45.readFileSync(source, "utf8"));
|
|
31030
31283
|
const mcpJson = compileMcp(
|
|
31031
31284
|
sourceMcpJson,
|
|
31032
31285
|
"opencode",
|
|
@@ -31092,9 +31345,9 @@ function syncProviderBlock(mappings) {
|
|
|
31092
31345
|
function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings) {
|
|
31093
31346
|
const destination = resolveTargetPath(paths.config_doc);
|
|
31094
31347
|
let existing = {};
|
|
31095
|
-
if (
|
|
31348
|
+
if (fs45.existsSync(destination)) {
|
|
31096
31349
|
try {
|
|
31097
|
-
existing = JSON.parse(
|
|
31350
|
+
existing = JSON.parse(fs45.readFileSync(destination, "utf8"));
|
|
31098
31351
|
} catch {
|
|
31099
31352
|
existing = {};
|
|
31100
31353
|
}
|
|
@@ -31107,6 +31360,13 @@ function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings)
|
|
|
31107
31360
|
...mcpEntries
|
|
31108
31361
|
}
|
|
31109
31362
|
};
|
|
31363
|
+
const instructionsRef = declaredInstructionsPath(paths);
|
|
31364
|
+
if (instructionsRef !== null) {
|
|
31365
|
+
config.instructions = withDeclaredInstructions(
|
|
31366
|
+
existing.instructions,
|
|
31367
|
+
instructionsRef
|
|
31368
|
+
);
|
|
31369
|
+
}
|
|
31110
31370
|
if (Object.keys(permissionMap).length > 0) {
|
|
31111
31371
|
config.permission = permissionMap;
|
|
31112
31372
|
}
|
|
@@ -31119,8 +31379,8 @@ function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings)
|
|
|
31119
31379
|
};
|
|
31120
31380
|
}
|
|
31121
31381
|
}
|
|
31122
|
-
ensureDir(
|
|
31123
|
-
|
|
31382
|
+
ensureDir(path45.dirname(destination));
|
|
31383
|
+
fs45.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
|
|
31124
31384
|
`);
|
|
31125
31385
|
}
|
|
31126
31386
|
function writeCompiledArtifact5(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
|
|
@@ -31134,14 +31394,14 @@ function writeCompiledArtifact5(component, destination, content, expectedHash, c
|
|
|
31134
31394
|
if (artifactClass === "unmanaged-conflict" && !handleConflict6(destination, config, options, logger, manifest, scopePath)) {
|
|
31135
31395
|
return { component, status: "conflict", path: destination };
|
|
31136
31396
|
}
|
|
31137
|
-
ensureDir(
|
|
31397
|
+
ensureDir(path45.dirname(destination));
|
|
31138
31398
|
const clearedLink = clearSymlinkAtDestination(destination);
|
|
31139
31399
|
if (clearedLink !== null) {
|
|
31140
31400
|
logger.verbose(
|
|
31141
31401
|
` ${destination}: replaced a symlink to ${clearedLink} with generated content`
|
|
31142
31402
|
);
|
|
31143
31403
|
}
|
|
31144
|
-
|
|
31404
|
+
fs45.writeFileSync(destination, content);
|
|
31145
31405
|
return { component, status: "success", path: destination };
|
|
31146
31406
|
}
|
|
31147
31407
|
function handleConflict6(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -31159,7 +31419,7 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
|
|
|
31159
31419
|
if (manifest && scopePath) {
|
|
31160
31420
|
backupFile(destination, manifest, scopePath);
|
|
31161
31421
|
writeManifest(scopePath, manifest);
|
|
31162
|
-
|
|
31422
|
+
fs45.rmSync(destination, { recursive: true, force: true });
|
|
31163
31423
|
} else {
|
|
31164
31424
|
const parked = parkConflictingPath(
|
|
31165
31425
|
destination,
|
|
@@ -31174,12 +31434,12 @@ function handleConflict6(destination, config, options, logger, manifest, scopePa
|
|
|
31174
31434
|
}
|
|
31175
31435
|
return true;
|
|
31176
31436
|
}
|
|
31177
|
-
|
|
31437
|
+
fs45.rmSync(destination, { recursive: true, force: true });
|
|
31178
31438
|
return true;
|
|
31179
31439
|
}
|
|
31180
31440
|
function isCompiledCurrent5(destination, expectedContent, _expectedHash) {
|
|
31181
31441
|
try {
|
|
31182
|
-
return
|
|
31442
|
+
return fs45.readFileSync(destination, "utf8") === expectedContent;
|
|
31183
31443
|
} catch {
|
|
31184
31444
|
return false;
|
|
31185
31445
|
}
|
|
@@ -31198,7 +31458,7 @@ function hashString5(value) {
|
|
|
31198
31458
|
return `sha256:${crypto10.createHash("sha256").update(value).digest("hex")}`;
|
|
31199
31459
|
}
|
|
31200
31460
|
function parseCommandFile(commandFile) {
|
|
31201
|
-
const content =
|
|
31461
|
+
const content = fs45.readFileSync(commandFile, "utf8");
|
|
31202
31462
|
if (!content.startsWith("---\n")) {
|
|
31203
31463
|
return { data: {}, body: content };
|
|
31204
31464
|
}
|
|
@@ -31218,7 +31478,7 @@ function parseCommandFile(commandFile) {
|
|
|
31218
31478
|
// src/commands/install.ts
|
|
31219
31479
|
function isBackupablePath(targetPath) {
|
|
31220
31480
|
try {
|
|
31221
|
-
const lstat =
|
|
31481
|
+
const lstat = fs46.lstatSync(targetPath);
|
|
31222
31482
|
return lstat.isSymbolicLink() || lstat.isFile() || lstat.isDirectory();
|
|
31223
31483
|
} catch {
|
|
31224
31484
|
return false;
|
|
@@ -31255,7 +31515,7 @@ async function runInstallCommand(options, logger) {
|
|
|
31255
31515
|
);
|
|
31256
31516
|
}
|
|
31257
31517
|
const kitName = resolvedKitName ?? config.kit;
|
|
31258
|
-
const kitPath = kitPathOverride ?? (options.kitPath ?
|
|
31518
|
+
const kitPath = kitPathOverride ?? (options.kitPath ? path46.resolve(options.kitPath) : config.kitPath);
|
|
31259
31519
|
if (!kitName && !kitPath) {
|
|
31260
31520
|
logger.error(
|
|
31261
31521
|
"No kit specified. Use --kit <name>, --kit-path <path>, or set 'kit'/'kitPath' in tangyr.config.yaml."
|
|
@@ -31360,8 +31620,8 @@ async function runInstallCommand(options, logger) {
|
|
|
31360
31620
|
config: options.config,
|
|
31361
31621
|
scope
|
|
31362
31622
|
});
|
|
31363
|
-
const skillsSource =
|
|
31364
|
-
const isPerSkillSkillsSlot = (f) => (f.tool === "claude-code" || f.tool === "copilot") &&
|
|
31623
|
+
const skillsSource = path46.resolve(kitInfo.path, config.source.skills);
|
|
31624
|
+
const isPerSkillSkillsSlot = (f) => (f.tool === "claude-code" || f.tool === "copilot") && path46.basename(f.path) === "skills";
|
|
31365
31625
|
const foreignSkillsSlots = new Set(
|
|
31366
31626
|
assessResult.findings.filter(
|
|
31367
31627
|
(f) => isPerSkillSkillsSlot(f) && isForeignSkillsSlotSymlink(
|
|
@@ -31399,7 +31659,7 @@ async function runInstallCommand(options, logger) {
|
|
|
31399
31659
|
let instructionsLabel;
|
|
31400
31660
|
try {
|
|
31401
31661
|
const resolved = resolveInstructionsSource(kitInfo.path, config);
|
|
31402
|
-
instructionsLabel = resolved ?
|
|
31662
|
+
instructionsLabel = resolved ? path46.relative(kitInfo.path, resolved.file) : "(none \u2014 no instructions file resolves in this kit)";
|
|
31403
31663
|
} catch (err) {
|
|
31404
31664
|
logger.error(
|
|
31405
31665
|
`[dry-run] ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -31427,7 +31687,7 @@ async function runInstallCommand(options, logger) {
|
|
|
31427
31687
|
}
|
|
31428
31688
|
}
|
|
31429
31689
|
logger.info(
|
|
31430
|
-
`[dry-run] Total: ${plannedTotal} destination(s); manifest at ${
|
|
31690
|
+
`[dry-run] Total: ${plannedTotal} destination(s); manifest at ${path46.join(scopePath, "manifest.json")}`
|
|
31431
31691
|
);
|
|
31432
31692
|
return;
|
|
31433
31693
|
}
|
|
@@ -31486,7 +31746,7 @@ ACCEPTED CONFLICTS (posture: ${posture}; ${replaceable.length} target(s)):`
|
|
|
31486
31746
|
logger.info(` - ${finding.path}`);
|
|
31487
31747
|
logger.info(` source: ${sources}`);
|
|
31488
31748
|
logger.info(
|
|
31489
|
-
` action: backup-and-replace${
|
|
31749
|
+
` action: backup-and-replace${fs46.lstatSync(finding.path).isDirectory() ? " (directory)" : ""}`
|
|
31490
31750
|
);
|
|
31491
31751
|
logger.info(` backup: ${backupLocation}`);
|
|
31492
31752
|
continue;
|
|
@@ -31594,11 +31854,29 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
|
|
|
31594
31854
|
installLossReport
|
|
31595
31855
|
);
|
|
31596
31856
|
}
|
|
31857
|
+
const instructionsByTarget = instructionsByActiveTarget(
|
|
31858
|
+
tools,
|
|
31859
|
+
scope,
|
|
31860
|
+
projectRoot,
|
|
31861
|
+
mappings
|
|
31862
|
+
);
|
|
31863
|
+
const rulesCoverage = measureRulesCoverage(
|
|
31864
|
+
tools,
|
|
31865
|
+
kitInfo.components.rules?.declared ?? [],
|
|
31866
|
+
scope,
|
|
31867
|
+
projectRoot,
|
|
31868
|
+
mappings,
|
|
31869
|
+
installLossReport,
|
|
31870
|
+
instructionsByTarget
|
|
31871
|
+
);
|
|
31597
31872
|
reportContestedInstructions(
|
|
31598
|
-
|
|
31873
|
+
instructionsByTarget,
|
|
31599
31874
|
(kitInfo.components.rules?.declared.length ?? 0) > 0,
|
|
31600
|
-
logger
|
|
31875
|
+
logger,
|
|
31876
|
+
missingRulesByTarget(rulesCoverage)
|
|
31601
31877
|
);
|
|
31878
|
+
reportRulesCoverage(rulesCoverage, logger);
|
|
31879
|
+
recordRulesCoverageLoss(rulesCoverage, installLossReport);
|
|
31602
31880
|
for (const [relativePath, sourcePath] of collectAllFiles(kitInfo, config)) {
|
|
31603
31881
|
addFileToManifest(manifest, {
|
|
31604
31882
|
relativePath,
|
|
@@ -31610,20 +31888,20 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
|
|
|
31610
31888
|
writeManifest(scopePath, manifest);
|
|
31611
31889
|
logger.info(`
|
|
31612
31890
|
Installation complete: ${installedCount} files installed.`);
|
|
31613
|
-
logger.info(`Manifest written to ${
|
|
31891
|
+
logger.info(`Manifest written to ${path46.join(scopePath, "manifest.json")}`);
|
|
31614
31892
|
logger.info(`Kit: ${kitInfo.name} (archetype: ${kitInfo.archetype})`);
|
|
31615
31893
|
logger.info(`Scope: ${scope}`);
|
|
31616
31894
|
logger.info(`Tools: ${tools.join(", ")}`);
|
|
31617
31895
|
reportHookRejections(
|
|
31618
31896
|
installLossReport,
|
|
31619
31897
|
tools,
|
|
31620
|
-
|
|
31898
|
+
path46.resolve(kitInfo.path, "hooks"),
|
|
31621
31899
|
kitInfo.components.hooks.declared
|
|
31622
31900
|
);
|
|
31623
31901
|
const hooksConflict = reportHooksSourceConflict(
|
|
31624
31902
|
installLossReport,
|
|
31625
31903
|
tools,
|
|
31626
|
-
|
|
31904
|
+
path46.resolve(kitInfo.path, "hooks"),
|
|
31627
31905
|
kitInfo.components.hooks.declared
|
|
31628
31906
|
);
|
|
31629
31907
|
if (hooksConflict) {
|
|
@@ -31929,7 +32207,8 @@ function installClaudeCodeAdapterSlots(args) {
|
|
|
31929
32207
|
profile,
|
|
31930
32208
|
outcome,
|
|
31931
32209
|
scope,
|
|
31932
|
-
projectRoot
|
|
32210
|
+
projectRoot,
|
|
32211
|
+
mappings
|
|
31933
32212
|
);
|
|
31934
32213
|
if (!key) {
|
|
31935
32214
|
continue;
|
|
@@ -31954,8 +32233,13 @@ function installClaudeCodeAdapterSlots(args) {
|
|
|
31954
32233
|
}
|
|
31955
32234
|
return count;
|
|
31956
32235
|
}
|
|
31957
|
-
function claudeCodeOutcomeToManifestKey(profile, outcome, scope, projectRoot) {
|
|
31958
|
-
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
|
+
);
|
|
31959
32243
|
if (shared) {
|
|
31960
32244
|
return shared;
|
|
31961
32245
|
}
|
|
@@ -31982,7 +32266,7 @@ function installClaudeCodeSkills(config, kitInfo, manifest, options, logger, sco
|
|
|
31982
32266
|
return 0;
|
|
31983
32267
|
}
|
|
31984
32268
|
try {
|
|
31985
|
-
const stat =
|
|
32269
|
+
const stat = fs46.lstatSync(destination);
|
|
31986
32270
|
if (stat.isFile() && !stat.isSymbolicLink()) {
|
|
31987
32271
|
logger.warn(
|
|
31988
32272
|
`${destination}: a regular file occupies the skills slot \u2014 skipping skills. Move or remove it, then re-run install.`
|
|
@@ -32010,17 +32294,17 @@ function installClaudeCodeSkills(config, kitInfo, manifest, options, logger, sco
|
|
|
32010
32294
|
manifest,
|
|
32011
32295
|
scopePath
|
|
32012
32296
|
);
|
|
32013
|
-
const skillsSource =
|
|
32297
|
+
const skillsSource = path46.resolve(kitInfo.path, config.source.skills);
|
|
32014
32298
|
let count = 0;
|
|
32015
32299
|
for (const outcome of outcomes) {
|
|
32016
32300
|
if (outcome.status !== "success" && outcome.status !== "skipped-current") {
|
|
32017
32301
|
continue;
|
|
32018
32302
|
}
|
|
32019
|
-
const skillName =
|
|
32303
|
+
const skillName = path46.basename(outcome.path);
|
|
32020
32304
|
addArtifactToManifest(manifest, {
|
|
32021
32305
|
relativePath: `claude-code/skills/${skillName}`,
|
|
32022
32306
|
path: outcome.path,
|
|
32023
|
-
hash: describeArtifactState(outcome.path) ?? `dir:${
|
|
32307
|
+
hash: describeArtifactState(outcome.path) ?? `dir:${path46.join(skillsSource, skillName)}`,
|
|
32024
32308
|
origin: "tangyr-managed"
|
|
32025
32309
|
});
|
|
32026
32310
|
count++;
|
|
@@ -32034,10 +32318,10 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
|
|
|
32034
32318
|
logger.verbose(` skipped (operator choice): ${placement.destination}`);
|
|
32035
32319
|
continue;
|
|
32036
32320
|
}
|
|
32037
|
-
const destDir =
|
|
32038
|
-
|
|
32321
|
+
const destDir = path46.dirname(placement.destination);
|
|
32322
|
+
fs46.mkdirSync(destDir, { recursive: true });
|
|
32039
32323
|
if (placement.type === "symlink") {
|
|
32040
|
-
if (
|
|
32324
|
+
if (fs46.existsSync(placement.destination) || isSymlink2(placement.destination)) {
|
|
32041
32325
|
removeManagedPath(placement.destination);
|
|
32042
32326
|
}
|
|
32043
32327
|
createRelativeSymlink(
|
|
@@ -32054,7 +32338,7 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
|
|
|
32054
32338
|
` symlink: ${placement.source} \u2192 ${placement.destination}`
|
|
32055
32339
|
);
|
|
32056
32340
|
} else {
|
|
32057
|
-
|
|
32341
|
+
fs46.copyFileSync(placement.source, placement.destination);
|
|
32058
32342
|
logger.verbose(` copy: ${placement.source} \u2192 ${placement.destination}`);
|
|
32059
32343
|
}
|
|
32060
32344
|
addArtifactToManifest(manifest, {
|
|
@@ -32304,7 +32588,12 @@ function countInstalledArtifacts(outcomes) {
|
|
|
32304
32588
|
).length;
|
|
32305
32589
|
}
|
|
32306
32590
|
function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", projectRoot) {
|
|
32307
|
-
const shared =
|
|
32591
|
+
const shared = sharedKeyForDestination(
|
|
32592
|
+
outcome.path,
|
|
32593
|
+
scope,
|
|
32594
|
+
projectRoot,
|
|
32595
|
+
mappings.platformPaths
|
|
32596
|
+
);
|
|
32308
32597
|
if (shared) {
|
|
32309
32598
|
return shared;
|
|
32310
32599
|
}
|
|
@@ -32346,11 +32635,11 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
32346
32635
|
if (outcome.path === mcpFile2) {
|
|
32347
32636
|
return "cline/mcp.json";
|
|
32348
32637
|
}
|
|
32349
|
-
if (outcome.path.startsWith(`${workflowsRoot}${
|
|
32350
|
-
return `cline/workflows/${
|
|
32638
|
+
if (outcome.path.startsWith(`${workflowsRoot}${path46.sep}`)) {
|
|
32639
|
+
return `cline/workflows/${path46.basename(outcome.path)}`;
|
|
32351
32640
|
}
|
|
32352
|
-
if (outcome.path.startsWith(`${rulesRoot2}${
|
|
32353
|
-
return `cline/rules/${
|
|
32641
|
+
if (outcome.path.startsWith(`${rulesRoot2}${path46.sep}`)) {
|
|
32642
|
+
return `cline/rules/${path46.basename(outcome.path)}`;
|
|
32354
32643
|
}
|
|
32355
32644
|
return null;
|
|
32356
32645
|
}
|
|
@@ -32386,14 +32675,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
32386
32675
|
if (outcome.path === permissionsFile) {
|
|
32387
32676
|
return "cursor/permissions.json";
|
|
32388
32677
|
}
|
|
32389
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
32390
|
-
return `cursor/agents/${
|
|
32678
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path46.sep}`)) {
|
|
32679
|
+
return `cursor/agents/${path46.basename(outcome.path)}`;
|
|
32391
32680
|
}
|
|
32392
|
-
if (outcome.path.startsWith(`${rulesRoot2}${
|
|
32393
|
-
return `cursor/rules/${
|
|
32681
|
+
if (outcome.path.startsWith(`${rulesRoot2}${path46.sep}`)) {
|
|
32682
|
+
return `cursor/rules/${path46.basename(outcome.path)}`;
|
|
32394
32683
|
}
|
|
32395
|
-
if (outcome.path.startsWith(`${skillsRoot2}${
|
|
32396
|
-
const rel =
|
|
32684
|
+
if (outcome.path.startsWith(`${skillsRoot2}${path46.sep}`)) {
|
|
32685
|
+
const rel = path46.relative(skillsRoot2, outcome.path);
|
|
32397
32686
|
return `cursor/skills/${rel}`;
|
|
32398
32687
|
}
|
|
32399
32688
|
return null;
|
|
@@ -32419,14 +32708,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
32419
32708
|
if (outcome.path === skillsSharedRoot) {
|
|
32420
32709
|
return "opencode/skills_shared";
|
|
32421
32710
|
}
|
|
32422
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
32423
|
-
return `opencode/agents/${
|
|
32711
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path46.sep}`)) {
|
|
32712
|
+
return `opencode/agents/${path46.basename(outcome.path)}`;
|
|
32424
32713
|
}
|
|
32425
|
-
if (outcome.path.startsWith(`${commandsRoot}${
|
|
32426
|
-
return `opencode/commands/${
|
|
32714
|
+
if (outcome.path.startsWith(`${commandsRoot}${path46.sep}`)) {
|
|
32715
|
+
return `opencode/commands/${path46.basename(outcome.path)}`;
|
|
32427
32716
|
}
|
|
32428
32717
|
if (outcome.path === configDocFile) {
|
|
32429
|
-
return `opencode/${
|
|
32718
|
+
return `opencode/${path46.basename(outcome.path)}`;
|
|
32430
32719
|
}
|
|
32431
32720
|
return null;
|
|
32432
32721
|
}
|
|
@@ -32443,29 +32732,29 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
32443
32732
|
const hooksRoot = resolveTargetPath(copilot.hooks);
|
|
32444
32733
|
const mcpFile2 = resolveTargetPath(copilot.mcp_shared_file);
|
|
32445
32734
|
const instructionsMirror = copilot.instructions !== null ? resolveTargetPath(copilot.instructions) : null;
|
|
32446
|
-
if (copilot.rules !== null && outcome.path.startsWith(`${resolveTargetPath(copilot.rules)}${
|
|
32447
|
-
return `copilot/rules/${
|
|
32735
|
+
if (copilot.rules !== null && outcome.path.startsWith(`${resolveTargetPath(copilot.rules)}${path46.sep}`)) {
|
|
32736
|
+
return `copilot/rules/${path46.relative(resolveTargetPath(copilot.rules), outcome.path)}`;
|
|
32448
32737
|
}
|
|
32449
|
-
if (outcome.path.startsWith(`${skillsRoot2}${
|
|
32450
|
-
return `copilot/skills/${
|
|
32738
|
+
if (outcome.path.startsWith(`${skillsRoot2}${path46.sep}`)) {
|
|
32739
|
+
return `copilot/skills/${path46.relative(skillsRoot2, outcome.path)}`;
|
|
32451
32740
|
}
|
|
32452
32741
|
if (outcome.path === skillsRoot2) {
|
|
32453
32742
|
return "copilot/skills";
|
|
32454
32743
|
}
|
|
32455
32744
|
if (instructionsMirror !== null && outcome.path === instructionsMirror) {
|
|
32456
|
-
return `copilot/${
|
|
32745
|
+
return `copilot/${path46.basename(outcome.path)}`;
|
|
32457
32746
|
}
|
|
32458
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
32459
|
-
return `copilot/agents/${
|
|
32747
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path46.sep}`)) {
|
|
32748
|
+
return `copilot/agents/${path46.basename(outcome.path)}`;
|
|
32460
32749
|
}
|
|
32461
|
-
if (outcome.path.startsWith(`${promptsRoot}${
|
|
32462
|
-
return `copilot/prompts/${
|
|
32750
|
+
if (outcome.path.startsWith(`${promptsRoot}${path46.sep}`)) {
|
|
32751
|
+
return `copilot/prompts/${path46.basename(outcome.path)}`;
|
|
32463
32752
|
}
|
|
32464
|
-
if (outcome.path.startsWith(`${hooksRoot}${
|
|
32465
|
-
return `copilot/hooks/${
|
|
32753
|
+
if (outcome.path.startsWith(`${hooksRoot}${path46.sep}`)) {
|
|
32754
|
+
return `copilot/hooks/${path46.basename(outcome.path)}`;
|
|
32466
32755
|
}
|
|
32467
32756
|
if (outcome.path === mcpFile2) {
|
|
32468
|
-
return `copilot/${
|
|
32757
|
+
return `copilot/${path46.basename(outcome.path)}`;
|
|
32469
32758
|
}
|
|
32470
32759
|
return null;
|
|
32471
32760
|
}
|
|
@@ -32482,17 +32771,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
32482
32771
|
if (outcome.path === skillsRoot) {
|
|
32483
32772
|
return "codex/skills";
|
|
32484
32773
|
}
|
|
32485
|
-
if (outcome.path.startsWith(`${agentsRoot}${
|
|
32486
|
-
return `codex/agents/${
|
|
32774
|
+
if (outcome.path.startsWith(`${agentsRoot}${path46.sep}`)) {
|
|
32775
|
+
return `codex/agents/${path46.basename(outcome.path)}`;
|
|
32487
32776
|
}
|
|
32488
|
-
if (outcome.path.startsWith(`${rulesRoot}${
|
|
32489
|
-
return `codex/rules/${
|
|
32777
|
+
if (outcome.path.startsWith(`${rulesRoot}${path46.sep}`)) {
|
|
32778
|
+
return `codex/rules/${path46.basename(outcome.path)}`;
|
|
32490
32779
|
}
|
|
32491
32780
|
if (outcome.path === hooksFile) {
|
|
32492
|
-
return `codex/${
|
|
32781
|
+
return `codex/${path46.basename(outcome.path)}`;
|
|
32493
32782
|
}
|
|
32494
32783
|
if (outcome.path === mcpFile) {
|
|
32495
|
-
return `codex/${
|
|
32784
|
+
return `codex/${path46.basename(outcome.path)}`;
|
|
32496
32785
|
}
|
|
32497
32786
|
return null;
|
|
32498
32787
|
}
|
|
@@ -32561,8 +32850,8 @@ function getClaudeCodePlacements(kitInfo, config, scope = "global", projectRoot,
|
|
|
32561
32850
|
rules: resolvedPaths.rules
|
|
32562
32851
|
};
|
|
32563
32852
|
for (const [component, targetPath] of Object.entries(componentDirMap)) {
|
|
32564
|
-
const componentDir =
|
|
32565
|
-
if (
|
|
32853
|
+
const componentDir = path46.join(kitInfo.path, component);
|
|
32854
|
+
if (fs46.existsSync(componentDir) && fs46.statSync(componentDir).isDirectory()) {
|
|
32566
32855
|
placements.push({
|
|
32567
32856
|
source: componentDir,
|
|
32568
32857
|
destination: targetPath,
|
|
@@ -32592,8 +32881,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile, config) {
|
|
|
32592
32881
|
rules: profile.rules
|
|
32593
32882
|
};
|
|
32594
32883
|
for (const [component, targetPath] of Object.entries(componentDirMap)) {
|
|
32595
|
-
const componentDir =
|
|
32596
|
-
if (
|
|
32884
|
+
const componentDir = path46.join(kitInfo.path, component);
|
|
32885
|
+
if (fs46.existsSync(componentDir) && fs46.statSync(componentDir).isDirectory()) {
|
|
32597
32886
|
placements.push({
|
|
32598
32887
|
source: componentDir,
|
|
32599
32888
|
destination: targetPath,
|
|
@@ -32609,7 +32898,7 @@ function collectAllFiles(kitInfo, config) {
|
|
|
32609
32898
|
const files = /* @__PURE__ */ new Map();
|
|
32610
32899
|
const entrypoint = resolveInstructionsSource(kitInfo.path, config);
|
|
32611
32900
|
if (entrypoint) {
|
|
32612
|
-
files.set(
|
|
32901
|
+
files.set(path46.basename(entrypoint.file), entrypoint.file);
|
|
32613
32902
|
}
|
|
32614
32903
|
for (const [component, reconciliation] of Object.entries(
|
|
32615
32904
|
kitInfo.components
|
|
@@ -32618,22 +32907,22 @@ function collectAllFiles(kitInfo, config) {
|
|
|
32618
32907
|
const missingSet = new Set(reconciliation.missing);
|
|
32619
32908
|
for (const entry of reconciliation.declared) {
|
|
32620
32909
|
if (missingSet.has(entry)) continue;
|
|
32621
|
-
const relPath = isSkills ?
|
|
32622
|
-
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));
|
|
32623
32912
|
}
|
|
32624
32913
|
}
|
|
32625
32914
|
return files;
|
|
32626
32915
|
}
|
|
32627
32916
|
function readLinkTarget(p) {
|
|
32628
32917
|
try {
|
|
32629
|
-
return
|
|
32918
|
+
return fs46.readlinkSync(p);
|
|
32630
32919
|
} catch {
|
|
32631
32920
|
return null;
|
|
32632
32921
|
}
|
|
32633
32922
|
}
|
|
32634
32923
|
function isSymlink2(p) {
|
|
32635
32924
|
try {
|
|
32636
|
-
return
|
|
32925
|
+
return fs46.lstatSync(p).isSymbolicLink();
|
|
32637
32926
|
} catch {
|
|
32638
32927
|
return false;
|
|
32639
32928
|
}
|
|
@@ -32652,10 +32941,10 @@ function skillsSubPathKey(tool, outcomePath, mappings, scope, projectRoot) {
|
|
|
32652
32941
|
continue;
|
|
32653
32942
|
}
|
|
32654
32943
|
const root = resolveTargetPath(slot);
|
|
32655
|
-
if (!outcomePath.startsWith(`${root}${
|
|
32944
|
+
if (!outcomePath.startsWith(`${root}${path46.sep}`)) {
|
|
32656
32945
|
continue;
|
|
32657
32946
|
}
|
|
32658
|
-
const inside =
|
|
32947
|
+
const inside = path46.relative(root, outcomePath).split(path46.sep).join("/");
|
|
32659
32948
|
return `${tool}/skills/${inside}`;
|
|
32660
32949
|
}
|
|
32661
32950
|
return null;
|
|
@@ -32700,14 +32989,14 @@ async function runKitUpdateCommand(options, logger) {
|
|
|
32700
32989
|
}
|
|
32701
32990
|
|
|
32702
32991
|
// src/commands/list.ts
|
|
32703
|
-
import
|
|
32992
|
+
import path47 from "path";
|
|
32704
32993
|
function runListCommand(options, logger) {
|
|
32705
32994
|
let searchPaths = [];
|
|
32706
|
-
let directKitPath = options.kitPath ?
|
|
32995
|
+
let directKitPath = options.kitPath ? path47.resolve(options.kitPath) : void 0;
|
|
32707
32996
|
try {
|
|
32708
32997
|
const { config, configDir } = resolveConfig(options.config);
|
|
32709
32998
|
searchPaths = config.kitSearchPaths ?? [
|
|
32710
|
-
|
|
32999
|
+
path47.join(configDir, "operating-kits")
|
|
32711
33000
|
];
|
|
32712
33001
|
directKitPath = directKitPath ?? config.kitPath;
|
|
32713
33002
|
} catch (err) {
|
|
@@ -32782,7 +33071,7 @@ function withDirectKit(kits, directKitPath) {
|
|
|
32782
33071
|
return kits;
|
|
32783
33072
|
}
|
|
32784
33073
|
const directKit = loadKit(directKitPath);
|
|
32785
|
-
if (kits.some((kit) =>
|
|
33074
|
+
if (kits.some((kit) => path47.resolve(kit.path) === directKit.path)) {
|
|
32786
33075
|
return kits;
|
|
32787
33076
|
}
|
|
32788
33077
|
return [...kits, directKit];
|
|
@@ -32790,8 +33079,8 @@ function withDirectKit(kits, directKitPath) {
|
|
|
32790
33079
|
|
|
32791
33080
|
// src/commands/probe.ts
|
|
32792
33081
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
32793
|
-
import
|
|
32794
|
-
import
|
|
33082
|
+
import fs47 from "fs";
|
|
33083
|
+
import path48 from "path";
|
|
32795
33084
|
function runProbeCommand(options, logger) {
|
|
32796
33085
|
const { config, configDir, configSource, sourceRoot } = resolveRuntime(
|
|
32797
33086
|
options,
|
|
@@ -32819,7 +33108,7 @@ function runProbeCommand(options, logger) {
|
|
|
32819
33108
|
toProbeRow(
|
|
32820
33109
|
target,
|
|
32821
33110
|
key,
|
|
32822
|
-
scope === "project" ?
|
|
33111
|
+
scope === "project" ? path48.resolve(projectRoot ?? process.cwd(), rawPath) : rawPath
|
|
32823
33112
|
)
|
|
32824
33113
|
);
|
|
32825
33114
|
}
|
|
@@ -32841,7 +33130,7 @@ function toProbeRow(target, key, rawPath) {
|
|
|
32841
33130
|
const resolved = resolveTargetPath(rawPath);
|
|
32842
33131
|
let accessible = false;
|
|
32843
33132
|
try {
|
|
32844
|
-
|
|
33133
|
+
fs47.accessSync(resolved);
|
|
32845
33134
|
accessible = true;
|
|
32846
33135
|
} catch {
|
|
32847
33136
|
accessible = false;
|
|
@@ -32850,7 +33139,7 @@ function toProbeRow(target, key, rawPath) {
|
|
|
32850
33139
|
target,
|
|
32851
33140
|
key,
|
|
32852
33141
|
path: resolved,
|
|
32853
|
-
exists:
|
|
33142
|
+
exists: fs47.existsSync(resolved),
|
|
32854
33143
|
accessible
|
|
32855
33144
|
};
|
|
32856
33145
|
}
|
|
@@ -32868,7 +33157,7 @@ function codexRuntimeProbeRows() {
|
|
|
32868
33157
|
["binary_snap", "/snap/bin/codex"],
|
|
32869
33158
|
["binary_flatpak", "/var/lib/flatpak/exports/bin/codex"]
|
|
32870
33159
|
]) {
|
|
32871
|
-
if (
|
|
33160
|
+
if (fs47.existsSync(candidatePath)) {
|
|
32872
33161
|
rows.push(toProbeRow("codex", key, candidatePath));
|
|
32873
33162
|
}
|
|
32874
33163
|
}
|
|
@@ -32884,8 +33173,8 @@ function commandProbeRows(target, key, command, args) {
|
|
|
32884
33173
|
|
|
32885
33174
|
// src/commands/status.ts
|
|
32886
33175
|
import crypto11 from "crypto";
|
|
32887
|
-
import
|
|
32888
|
-
import
|
|
33176
|
+
import fs48 from "fs";
|
|
33177
|
+
import path49 from "path";
|
|
32889
33178
|
function runStatusCommand(options, logger) {
|
|
32890
33179
|
const { config, configDir, configSource, sourceRoot } = resolveRuntime(
|
|
32891
33180
|
options,
|
|
@@ -32991,11 +33280,11 @@ function classifyTargetRows(target, config, sourceRoot, configDir, scope, projec
|
|
|
32991
33280
|
}
|
|
32992
33281
|
}
|
|
32993
33282
|
function sourceMarkdownFiles(sourceRoot, componentPath) {
|
|
32994
|
-
const root =
|
|
32995
|
-
if (!
|
|
33283
|
+
const root = path49.join(sourceRoot, componentPath);
|
|
33284
|
+
if (!fs48.existsSync(root)) {
|
|
32996
33285
|
return [];
|
|
32997
33286
|
}
|
|
32998
|
-
return ts(
|
|
33287
|
+
return ts(path49.join(root, "*.md")).sort();
|
|
32999
33288
|
}
|
|
33000
33289
|
function notRepresentableRow(component, detail) {
|
|
33001
33290
|
return {
|
|
@@ -33006,11 +33295,11 @@ function notRepresentableRow(component, detail) {
|
|
|
33006
33295
|
};
|
|
33007
33296
|
}
|
|
33008
33297
|
function readTargetJson(filePath) {
|
|
33009
|
-
if (!
|
|
33298
|
+
if (!fs48.existsSync(filePath)) {
|
|
33010
33299
|
return { kind: "missing" };
|
|
33011
33300
|
}
|
|
33012
33301
|
try {
|
|
33013
|
-
const parsed = JSON.parse(
|
|
33302
|
+
const parsed = JSON.parse(fs48.readFileSync(filePath, "utf8"));
|
|
33014
33303
|
return { kind: "object", value: isRecord(parsed) ? parsed : {} };
|
|
33015
33304
|
} catch (err) {
|
|
33016
33305
|
return {
|
|
@@ -33099,7 +33388,7 @@ function classifyInstructions(filePath, target, expectedHash, config, sourceRoot
|
|
|
33099
33388
|
}
|
|
33100
33389
|
function compiledMcpDocument(config, sourceRoot, target) {
|
|
33101
33390
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
33102
|
-
if (!
|
|
33391
|
+
if (!fs48.existsSync(source)) {
|
|
33103
33392
|
return {};
|
|
33104
33393
|
}
|
|
33105
33394
|
const compiled = compileMcp(
|
|
@@ -33112,7 +33401,7 @@ function compiledMcpDocument(config, sourceRoot, target) {
|
|
|
33112
33401
|
return isRecord(parsed) ? parsed : {};
|
|
33113
33402
|
}
|
|
33114
33403
|
function classifyMcpDocument(config, sourceRoot, target, filePath) {
|
|
33115
|
-
if (!
|
|
33404
|
+
if (!fs48.existsSync(resolveMcpSourceFile(sourceRoot, config))) {
|
|
33116
33405
|
return notConfiguredRow("mcp", filePath);
|
|
33117
33406
|
}
|
|
33118
33407
|
return classifyJsonDocument(
|
|
@@ -33142,12 +33431,12 @@ function classifyOpenCodeFiles(config, sourceRoot, configDir, scope, projectRoot
|
|
|
33142
33431
|
const rows = [];
|
|
33143
33432
|
const instructionsSource = instructionsSourcePath(sourceRoot, config);
|
|
33144
33433
|
const rules = compileRules(
|
|
33145
|
-
|
|
33434
|
+
path49.join(sourceRoot, config.source.rules),
|
|
33146
33435
|
"opencode",
|
|
33147
33436
|
mappings,
|
|
33148
33437
|
createLossReport()
|
|
33149
33438
|
);
|
|
33150
|
-
const baseInstructions =
|
|
33439
|
+
const baseInstructions = fs48.existsSync(instructionsSource) ? fs48.readFileSync(instructionsSource, "utf8").trim() : "";
|
|
33151
33440
|
const composedInstructions = rules.agentsAppendix ? `${baseInstructions}
|
|
33152
33441
|
|
|
33153
33442
|
--- tangyr managed rules ---
|
|
@@ -33169,10 +33458,10 @@ ${rules.agentsAppendix}`.trim() : baseInstructions;
|
|
|
33169
33458
|
)) {
|
|
33170
33459
|
rows.push(
|
|
33171
33460
|
classifyCompiledFile(
|
|
33172
|
-
`agents/${
|
|
33173
|
-
|
|
33461
|
+
`agents/${path49.basename(agentFile, ".md")}`,
|
|
33462
|
+
path49.join(
|
|
33174
33463
|
resolveTargetPath(paths.agents),
|
|
33175
|
-
`${
|
|
33464
|
+
`${path49.basename(agentFile, ".md")}.md`
|
|
33176
33465
|
),
|
|
33177
33466
|
"opencode",
|
|
33178
33467
|
computeSourceHash(agentFile),
|
|
@@ -33187,10 +33476,10 @@ ${rules.agentsAppendix}`.trim() : baseInstructions;
|
|
|
33187
33476
|
)) {
|
|
33188
33477
|
rows.push(
|
|
33189
33478
|
classifyCompiledFile(
|
|
33190
|
-
`commands/${
|
|
33191
|
-
|
|
33479
|
+
`commands/${path49.basename(commandFile, ".md")}`,
|
|
33480
|
+
path49.join(
|
|
33192
33481
|
resolveTargetPath(paths.commands),
|
|
33193
|
-
`${
|
|
33482
|
+
`${path49.basename(commandFile, ".md")}.md`
|
|
33194
33483
|
),
|
|
33195
33484
|
"opencode",
|
|
33196
33485
|
computeSourceHash(commandFile),
|
|
@@ -33272,10 +33561,10 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
|
|
|
33272
33561
|
)) {
|
|
33273
33562
|
rows.push(
|
|
33274
33563
|
classifyCompiledFile(
|
|
33275
|
-
`agents/${
|
|
33276
|
-
|
|
33564
|
+
`agents/${path49.basename(agentFile, ".md")}`,
|
|
33565
|
+
path49.join(
|
|
33277
33566
|
resolveTargetPath(paths.agents),
|
|
33278
|
-
`${
|
|
33567
|
+
`${path49.basename(agentFile, ".md")}.md`
|
|
33279
33568
|
),
|
|
33280
33569
|
"cursor",
|
|
33281
33570
|
computeSourceHash(agentFile),
|
|
@@ -33292,7 +33581,7 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
|
|
|
33292
33581
|
rows.push(
|
|
33293
33582
|
classifyCompiledFile(
|
|
33294
33583
|
`rules/${ruleFile.name}`,
|
|
33295
|
-
|
|
33584
|
+
path49.join(resolveTargetPath(paths.rules), ruleFile.name),
|
|
33296
33585
|
"cursor",
|
|
33297
33586
|
void 0,
|
|
33298
33587
|
config,
|
|
@@ -33306,11 +33595,11 @@ function classifyCursorFiles(config, sourceRoot, configDir, scope, projectRoot)
|
|
|
33306
33595
|
sourceRoot,
|
|
33307
33596
|
config.source.commands
|
|
33308
33597
|
)) {
|
|
33309
|
-
const baseName =
|
|
33598
|
+
const baseName = path49.basename(commandFile, ".md");
|
|
33310
33599
|
rows.push(
|
|
33311
33600
|
classifyCompiledFile(
|
|
33312
33601
|
`commands/${baseName}`,
|
|
33313
|
-
|
|
33602
|
+
path49.join(resolveTargetPath(paths.skills), baseName, "SKILL.md"),
|
|
33314
33603
|
"cursor",
|
|
33315
33604
|
computeSourceHash(commandFile),
|
|
33316
33605
|
config,
|
|
@@ -33393,7 +33682,7 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
|
|
|
33393
33682
|
rows.push(
|
|
33394
33683
|
classifyCompiledFile(
|
|
33395
33684
|
`rules/${ruleFile.name}`,
|
|
33396
|
-
|
|
33685
|
+
path49.join(resolveTargetPath(paths.rules), ruleFile.name),
|
|
33397
33686
|
"cline",
|
|
33398
33687
|
void 0,
|
|
33399
33688
|
config,
|
|
@@ -33409,10 +33698,10 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
|
|
|
33409
33698
|
)) {
|
|
33410
33699
|
rows.push(
|
|
33411
33700
|
classifyCompiledFile(
|
|
33412
|
-
`commands/${
|
|
33413
|
-
|
|
33701
|
+
`commands/${path49.basename(commandFile, ".md")}`,
|
|
33702
|
+
path49.join(
|
|
33414
33703
|
resolveTargetPath(paths.workflows),
|
|
33415
|
-
|
|
33704
|
+
path49.basename(commandFile)
|
|
33416
33705
|
),
|
|
33417
33706
|
"cline",
|
|
33418
33707
|
computeSourceHash(commandFile),
|
|
@@ -33453,14 +33742,14 @@ function classifyClineFiles(config, sourceRoot, configDir, scope, projectRoot) {
|
|
|
33453
33742
|
return rows;
|
|
33454
33743
|
}
|
|
33455
33744
|
function compileRulesFiles(config, sourceRoot, target, mappings) {
|
|
33456
|
-
const rulesSource =
|
|
33457
|
-
if (!
|
|
33745
|
+
const rulesSource = path49.join(sourceRoot, config.source.rules);
|
|
33746
|
+
if (!fs48.existsSync(rulesSource)) {
|
|
33458
33747
|
return [];
|
|
33459
33748
|
}
|
|
33460
33749
|
return compileRules(rulesSource, target, mappings, createLossReport()).dotRulesFiles;
|
|
33461
33750
|
}
|
|
33462
33751
|
function classifyDirectoryPresence(component, dirPath) {
|
|
33463
|
-
const present =
|
|
33752
|
+
const present = fs48.existsSync(dirPath) && fs48.statSync(dirPath).isDirectory();
|
|
33464
33753
|
return {
|
|
33465
33754
|
component,
|
|
33466
33755
|
className: present ? "current" : "missing",
|
|
@@ -33479,7 +33768,7 @@ function slotsForScope2(scopeMap, scope, projectRoot) {
|
|
|
33479
33768
|
const root = projectRoot ?? process.cwd();
|
|
33480
33769
|
const resolved = {};
|
|
33481
33770
|
for (const [slot, value] of Object.entries(projectSlots)) {
|
|
33482
|
-
resolved[slot] = typeof value === "string" ?
|
|
33771
|
+
resolved[slot] = typeof value === "string" ? path49.resolve(root, value) : value;
|
|
33483
33772
|
}
|
|
33484
33773
|
return resolved;
|
|
33485
33774
|
}
|
|
@@ -33499,21 +33788,21 @@ function classifyCodexFiles(config, sourceRoot, configDir, scope, projectRoot) {
|
|
|
33499
33788
|
rules: paths.rules
|
|
33500
33789
|
};
|
|
33501
33790
|
const rules = compileRules(
|
|
33502
|
-
|
|
33791
|
+
path49.join(sourceRoot, config.source.rules),
|
|
33503
33792
|
"codex",
|
|
33504
33793
|
mappings,
|
|
33505
33794
|
createLossReport()
|
|
33506
33795
|
);
|
|
33507
|
-
const instructionsSource =
|
|
33796
|
+
const instructionsSource = fs48.readFileSync(instructionsSourcePath(sourceRoot, config), "utf8").trim();
|
|
33508
33797
|
const composedInstructions = `${instructionsSource}
|
|
33509
33798
|
|
|
33510
33799
|
--- tangyr managed rules ---
|
|
33511
33800
|
${rules.agentsAppendix}`.trim();
|
|
33512
33801
|
const agentFiles = ts(
|
|
33513
|
-
|
|
33802
|
+
path49.join(sourceRoot, config.source.agents, "*.md")
|
|
33514
33803
|
).sort();
|
|
33515
33804
|
const hooksPresent = hooksSourceExists(sourceRoot, config);
|
|
33516
|
-
const mcpSource =
|
|
33805
|
+
const mcpSource = path49.join(sourceRoot, config.source.mcp);
|
|
33517
33806
|
const ruleRows = rules.dotRulesFiles.length === 0 ? [
|
|
33518
33807
|
{
|
|
33519
33808
|
component: "rules",
|
|
@@ -33524,7 +33813,7 @@ ${rules.agentsAppendix}`.trim();
|
|
|
33524
33813
|
] : rules.dotRulesFiles.map(
|
|
33525
33814
|
(ruleFile) => classifyCompiledFile(
|
|
33526
33815
|
`rules/${ruleFile.name}`,
|
|
33527
|
-
|
|
33816
|
+
path49.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
|
|
33528
33817
|
"codex",
|
|
33529
33818
|
void 0,
|
|
33530
33819
|
config,
|
|
@@ -33542,10 +33831,10 @@ ${rules.agentsAppendix}`.trim();
|
|
|
33542
33831
|
),
|
|
33543
33832
|
...agentFiles.map(
|
|
33544
33833
|
(agentFile) => classifyCompiledFile(
|
|
33545
|
-
`agents/${
|
|
33546
|
-
|
|
33834
|
+
`agents/${path49.basename(agentFile, ".md")}`,
|
|
33835
|
+
path49.join(
|
|
33547
33836
|
resolveTargetPath(codexPaths.agents),
|
|
33548
|
-
`${
|
|
33837
|
+
`${path49.basename(agentFile, ".md")}.toml`
|
|
33549
33838
|
),
|
|
33550
33839
|
"codex",
|
|
33551
33840
|
computeSourceHash(agentFile),
|
|
@@ -33573,7 +33862,7 @@ ${rules.agentsAppendix}`.trim();
|
|
|
33573
33862
|
"hooks",
|
|
33574
33863
|
resolveTargetPath(codexPaths.hooksSharedFile)
|
|
33575
33864
|
),
|
|
33576
|
-
|
|
33865
|
+
fs48.existsSync(mcpSource) ? classifyCompiledFile(
|
|
33577
33866
|
"mcp",
|
|
33578
33867
|
resolveTargetPath(codexPaths.mcpSharedFile),
|
|
33579
33868
|
"codex",
|
|
@@ -33639,20 +33928,20 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
|
|
|
33639
33928
|
mcpSharedFile: paths.mcp_shared_file
|
|
33640
33929
|
};
|
|
33641
33930
|
const agentFiles = ts(
|
|
33642
|
-
|
|
33931
|
+
path49.join(sourceRoot, config.source.agents, "*.md")
|
|
33643
33932
|
).sort();
|
|
33644
33933
|
const commandFiles = ts(
|
|
33645
|
-
|
|
33934
|
+
path49.join(sourceRoot, config.source.commands, "*.md")
|
|
33646
33935
|
).sort();
|
|
33647
33936
|
const hooksPresent = hooksSourceExists(sourceRoot, config);
|
|
33648
|
-
const mcpSource =
|
|
33937
|
+
const mcpSource = path49.join(sourceRoot, config.source.mcp);
|
|
33649
33938
|
return [
|
|
33650
33939
|
...agentFiles.map(
|
|
33651
33940
|
(agentFile) => classifyCompiledFile(
|
|
33652
|
-
`agents/${
|
|
33653
|
-
|
|
33941
|
+
`agents/${path49.basename(agentFile, ".md")}`,
|
|
33942
|
+
path49.join(
|
|
33654
33943
|
resolveTargetPath(copilotPaths.agents),
|
|
33655
|
-
`${
|
|
33944
|
+
`${path49.basename(agentFile, ".md")}.agent.md`
|
|
33656
33945
|
),
|
|
33657
33946
|
"copilot",
|
|
33658
33947
|
computeSourceHash(agentFile),
|
|
@@ -33669,10 +33958,10 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
|
|
|
33669
33958
|
),
|
|
33670
33959
|
...commandFiles.map(
|
|
33671
33960
|
(commandFile) => classifyCompiledFile(
|
|
33672
|
-
`commands/${
|
|
33673
|
-
|
|
33961
|
+
`commands/${path49.basename(commandFile, ".md")}`,
|
|
33962
|
+
path49.join(
|
|
33674
33963
|
resolveTargetPath(copilotPaths.prompts),
|
|
33675
|
-
`${
|
|
33964
|
+
`${path49.basename(commandFile, ".md")}.prompt.md`
|
|
33676
33965
|
),
|
|
33677
33966
|
"copilot",
|
|
33678
33967
|
computeSourceHash(commandFile),
|
|
@@ -33691,19 +33980,19 @@ function classifyCopilotFiles(config, sourceRoot, configDir, scope, projectRoot)
|
|
|
33691
33980
|
sourceRoot
|
|
33692
33981
|
),
|
|
33693
33982
|
hooksPresent ? classifyCompiledHooksByProvenance(
|
|
33694
|
-
|
|
33983
|
+
path49.join(
|
|
33695
33984
|
resolveTargetPath(copilotPaths.hooks),
|
|
33696
33985
|
"tangyr-managed.json"
|
|
33697
33986
|
),
|
|
33698
33987
|
"copilot"
|
|
33699
33988
|
) : notConfiguredRow(
|
|
33700
33989
|
"hooks",
|
|
33701
|
-
|
|
33990
|
+
path49.join(
|
|
33702
33991
|
resolveTargetPath(copilotPaths.hooks),
|
|
33703
33992
|
"tangyr-managed.json"
|
|
33704
33993
|
)
|
|
33705
33994
|
),
|
|
33706
|
-
|
|
33995
|
+
fs48.existsSync(mcpSource) ? classifyCompiledFile(
|
|
33707
33996
|
"mcp",
|
|
33708
33997
|
resolveTargetPath(copilotPaths.mcpSharedFile),
|
|
33709
33998
|
"copilot",
|
|
@@ -33723,7 +34012,7 @@ function notConfiguredRow(component, filePath) {
|
|
|
33723
34012
|
}
|
|
33724
34013
|
function classifyDirectArtifact(artifact, config, sourceRoot) {
|
|
33725
34014
|
const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
|
|
33726
|
-
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;
|
|
33727
34016
|
if (artifact.sourceKey === "skills" && artifactClass === "unmanaged-conflict") {
|
|
33728
34017
|
const perSkill = classifyPerSkillSlot(artifact.path, sourceRoot);
|
|
33729
34018
|
if (perSkill) {
|
|
@@ -33819,11 +34108,11 @@ function classifyClaudeCodeRows(sourceRoot, config, configDir, scope, projectRoo
|
|
|
33819
34108
|
function classifyPerSkillSlot(slotPath, sourceRoot) {
|
|
33820
34109
|
let entries;
|
|
33821
34110
|
try {
|
|
33822
|
-
const stat =
|
|
34111
|
+
const stat = fs48.lstatSync(slotPath);
|
|
33823
34112
|
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
33824
34113
|
return null;
|
|
33825
34114
|
}
|
|
33826
|
-
entries =
|
|
34115
|
+
entries = fs48.readdirSync(slotPath, { withFileTypes: true });
|
|
33827
34116
|
} catch {
|
|
33828
34117
|
return null;
|
|
33829
34118
|
}
|
|
@@ -33835,7 +34124,7 @@ function classifyPerSkillSlot(slotPath, sourceRoot) {
|
|
|
33835
34124
|
return null;
|
|
33836
34125
|
}
|
|
33837
34126
|
const ours = links.filter(
|
|
33838
|
-
(entry) => isOurSymlink(
|
|
34127
|
+
(entry) => isOurSymlink(path49.join(slotPath, entry.name), sourceRoot)
|
|
33839
34128
|
);
|
|
33840
34129
|
if (ours.length === 0) {
|
|
33841
34130
|
return null;
|
|
@@ -33847,9 +34136,9 @@ function classifyClaudeSharedFiles(config, sourceRoot, settingsPath, claudeJsonP
|
|
|
33847
34136
|
classifyHooks(settingsPath),
|
|
33848
34137
|
classifySettings(
|
|
33849
34138
|
settingsPath,
|
|
33850
|
-
|
|
34139
|
+
path49.resolve(sourceRoot, config.source.settings)
|
|
33851
34140
|
),
|
|
33852
|
-
classifyMcp(claudeJsonPath,
|
|
34141
|
+
classifyMcp(claudeJsonPath, path49.resolve(sourceRoot, config.source.mcp))
|
|
33853
34142
|
];
|
|
33854
34143
|
}
|
|
33855
34144
|
function claudeSharedFileRows(config, sourceRoot, configDir, scope, projectRoot) {
|
|
@@ -33946,14 +34235,14 @@ function classifyMcp(filePath, sourcePath) {
|
|
|
33946
34235
|
}
|
|
33947
34236
|
function isSymlinkCurrent(linkPath, sourcePath) {
|
|
33948
34237
|
try {
|
|
33949
|
-
return
|
|
34238
|
+
return fs48.realpathSync(linkPath) === fs48.realpathSync(sourcePath);
|
|
33950
34239
|
} catch {
|
|
33951
34240
|
return false;
|
|
33952
34241
|
}
|
|
33953
34242
|
}
|
|
33954
34243
|
function isCompiledCurrent6(filePath, sourcePath) {
|
|
33955
34244
|
try {
|
|
33956
|
-
const marker = extractProvenanceMarker(
|
|
34245
|
+
const marker = extractProvenanceMarker(fs48.readFileSync(filePath, "utf8"));
|
|
33957
34246
|
return marker?.hash === computeSourceHash(sourcePath) && marker.target === "claude-code";
|
|
33958
34247
|
} catch {
|
|
33959
34248
|
return false;
|
|
@@ -33983,7 +34272,7 @@ function classifyCompiledFile(component, filePath, target, expectedHash, config,
|
|
|
33983
34272
|
}
|
|
33984
34273
|
function readCompiledContent(filePath) {
|
|
33985
34274
|
try {
|
|
33986
|
-
return
|
|
34275
|
+
return fs48.readFileSync(filePath, "utf8");
|
|
33987
34276
|
} catch {
|
|
33988
34277
|
return null;
|
|
33989
34278
|
}
|
|
@@ -34014,8 +34303,8 @@ function hashString6(value) {
|
|
|
34014
34303
|
}
|
|
34015
34304
|
|
|
34016
34305
|
// src/commands/sync.ts
|
|
34017
|
-
import
|
|
34018
|
-
import
|
|
34306
|
+
import fs49 from "fs";
|
|
34307
|
+
import path50 from "path";
|
|
34019
34308
|
|
|
34020
34309
|
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
34021
34310
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -34685,29 +34974,42 @@ async function runSyncCommand(options, logger) {
|
|
|
34685
34974
|
reportHookRejections(
|
|
34686
34975
|
lossReport,
|
|
34687
34976
|
targets,
|
|
34688
|
-
|
|
34977
|
+
path50.resolve(kitInfo.path, "hooks"),
|
|
34689
34978
|
kitInfo.components.hooks.declared
|
|
34690
34979
|
);
|
|
34691
34980
|
const hooksConflict = reportHooksSourceConflict(
|
|
34692
34981
|
lossReport,
|
|
34693
34982
|
targets,
|
|
34694
|
-
|
|
34983
|
+
path50.resolve(kitInfo.path, "hooks"),
|
|
34695
34984
|
kitInfo.components.hooks.declared
|
|
34696
34985
|
);
|
|
34697
34986
|
if (hooksConflict) {
|
|
34698
34987
|
logger.warn(hooksConflict);
|
|
34699
34988
|
}
|
|
34700
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
|
+
);
|
|
34701
35005
|
reportContestedInstructions(
|
|
34702
|
-
|
|
34703
|
-
targets,
|
|
34704
|
-
syncOptions.scope,
|
|
34705
|
-
syncOptions.projectRoot,
|
|
34706
|
-
allMappings
|
|
34707
|
-
),
|
|
35006
|
+
instructionsByTarget,
|
|
34708
35007
|
kitInfo.components.rules.declared.length > 0,
|
|
34709
|
-
logger
|
|
35008
|
+
logger,
|
|
35009
|
+
missingRulesByTarget(rulesCoverage)
|
|
34710
35010
|
);
|
|
35011
|
+
reportRulesCoverage(rulesCoverage, logger);
|
|
35012
|
+
recordRulesCoverageLoss(rulesCoverage, lossReport);
|
|
34711
35013
|
}
|
|
34712
35014
|
}
|
|
34713
35015
|
writeLossReport(options.lossReport, lossReport);
|
|
@@ -34894,8 +35196,8 @@ function reconcileSyncedArtifacts(manifest, results, mappings, scope, projectRoo
|
|
|
34894
35196
|
}
|
|
34895
35197
|
}
|
|
34896
35198
|
function resolveKitFilePath(kitPath, relativePath) {
|
|
34897
|
-
const fullPath =
|
|
34898
|
-
return
|
|
35199
|
+
const fullPath = path50.join(kitPath, relativePath);
|
|
35200
|
+
return fs49.existsSync(fullPath) ? fullPath : null;
|
|
34899
35201
|
}
|
|
34900
35202
|
function cleanupRemovedManagedArtifacts(config, mappings, targets, options, removedSourcePaths, logger) {
|
|
34901
35203
|
if (removedSourcePaths.length === 0 || !mappings) {
|
|
@@ -34958,9 +35260,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
34958
35260
|
}
|
|
34959
35261
|
if (relativePath.startsWith("agents/")) {
|
|
34960
35262
|
removeManagedCompiledArtifact2(
|
|
34961
|
-
|
|
35263
|
+
path50.join(
|
|
34962
35264
|
resolveTargetPath(paths.agents ?? ""),
|
|
34963
|
-
`${
|
|
35265
|
+
`${path50.parse(relativePath).name}.agent.md`
|
|
34964
35266
|
),
|
|
34965
35267
|
"copilot",
|
|
34966
35268
|
relativePath,
|
|
@@ -34970,9 +35272,9 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
34970
35272
|
}
|
|
34971
35273
|
if (relativePath.startsWith("commands/")) {
|
|
34972
35274
|
removeManagedCompiledArtifact2(
|
|
34973
|
-
|
|
35275
|
+
path50.join(
|
|
34974
35276
|
resolveTargetPath(paths.prompts ?? ""),
|
|
34975
|
-
`${
|
|
35277
|
+
`${path50.parse(relativePath).name}.prompt.md`
|
|
34976
35278
|
),
|
|
34977
35279
|
"copilot",
|
|
34978
35280
|
relativePath,
|
|
@@ -34982,7 +35284,7 @@ function cleanupRemovedCopilotArtifact(relativePath, paths, logger) {
|
|
|
34982
35284
|
}
|
|
34983
35285
|
if (relativePath.endsWith("hooks.json")) {
|
|
34984
35286
|
removeManagedCompiledArtifact2(
|
|
34985
|
-
|
|
35287
|
+
path50.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
|
|
34986
35288
|
"copilot",
|
|
34987
35289
|
relativePath,
|
|
34988
35290
|
logger
|
|
@@ -35012,9 +35314,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
|
|
|
35012
35314
|
}
|
|
35013
35315
|
if (relativePath.startsWith("agents/")) {
|
|
35014
35316
|
removeManagedCompiledArtifact2(
|
|
35015
|
-
|
|
35317
|
+
path50.join(
|
|
35016
35318
|
resolveTargetPath(paths.agents ?? ""),
|
|
35017
|
-
`${
|
|
35319
|
+
`${path50.parse(relativePath).name}.toml`
|
|
35018
35320
|
),
|
|
35019
35321
|
"codex",
|
|
35020
35322
|
relativePath,
|
|
@@ -35024,9 +35326,9 @@ function cleanupRemovedCodexArtifact(relativePath, paths, logger) {
|
|
|
35024
35326
|
}
|
|
35025
35327
|
if (relativePath.startsWith("rules/")) {
|
|
35026
35328
|
removeManagedCompiledArtifact2(
|
|
35027
|
-
|
|
35329
|
+
path50.join(
|
|
35028
35330
|
resolveTargetPath(paths.rules ?? ""),
|
|
35029
|
-
`${
|
|
35331
|
+
`${path50.parse(relativePath).name}.rules`
|
|
35030
35332
|
),
|
|
35031
35333
|
"codex",
|
|
35032
35334
|
relativePath,
|
|
@@ -35065,9 +35367,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
|
|
|
35065
35367
|
}
|
|
35066
35368
|
if (relativePath.startsWith("agents/")) {
|
|
35067
35369
|
removeManagedCompiledArtifact2(
|
|
35068
|
-
|
|
35370
|
+
path50.join(
|
|
35069
35371
|
resolveTargetPath(paths.agents ?? ""),
|
|
35070
|
-
`${
|
|
35372
|
+
`${path50.parse(relativePath).name}.md`
|
|
35071
35373
|
),
|
|
35072
35374
|
"opencode",
|
|
35073
35375
|
relativePath,
|
|
@@ -35077,9 +35379,9 @@ function cleanupRemovedOpenCodeArtifact(relativePath, paths, logger) {
|
|
|
35077
35379
|
}
|
|
35078
35380
|
if (relativePath.startsWith("commands/")) {
|
|
35079
35381
|
removeManagedCompiledArtifact2(
|
|
35080
|
-
|
|
35382
|
+
path50.join(
|
|
35081
35383
|
resolveTargetPath(paths.commands ?? ""),
|
|
35082
|
-
`${
|
|
35384
|
+
`${path50.parse(relativePath).name}.md`
|
|
35083
35385
|
),
|
|
35084
35386
|
"opencode",
|
|
35085
35387
|
relativePath,
|
|
@@ -35111,9 +35413,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
35111
35413
|
}
|
|
35112
35414
|
if (relativePath.startsWith("agents/")) {
|
|
35113
35415
|
removeManagedCompiledArtifact2(
|
|
35114
|
-
|
|
35416
|
+
path50.join(
|
|
35115
35417
|
resolveTargetPath(paths.agents ?? ""),
|
|
35116
|
-
`${
|
|
35418
|
+
`${path50.parse(relativePath).name}.md`
|
|
35117
35419
|
),
|
|
35118
35420
|
"cursor",
|
|
35119
35421
|
relativePath,
|
|
@@ -35123,9 +35425,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
35123
35425
|
}
|
|
35124
35426
|
if (relativePath.startsWith("rules/")) {
|
|
35125
35427
|
removeManagedCompiledArtifact2(
|
|
35126
|
-
|
|
35428
|
+
path50.join(
|
|
35127
35429
|
resolveTargetPath(paths.rules ?? ""),
|
|
35128
|
-
`${
|
|
35430
|
+
`${path50.parse(relativePath).name}.mdc`
|
|
35129
35431
|
),
|
|
35130
35432
|
"cursor",
|
|
35131
35433
|
relativePath,
|
|
@@ -35135,9 +35437,9 @@ function cleanupRemovedCursorArtifact(relativePath, paths, logger) {
|
|
|
35135
35437
|
}
|
|
35136
35438
|
if (relativePath.startsWith("commands/")) {
|
|
35137
35439
|
removeManagedCompiledArtifact2(
|
|
35138
|
-
|
|
35440
|
+
path50.join(
|
|
35139
35441
|
resolveTargetPath(paths.skills ?? ""),
|
|
35140
|
-
|
|
35442
|
+
path50.parse(relativePath).name,
|
|
35141
35443
|
"SKILL.md"
|
|
35142
35444
|
),
|
|
35143
35445
|
"cursor",
|
|
@@ -35181,9 +35483,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
35181
35483
|
}
|
|
35182
35484
|
if (relativePath.startsWith("rules/")) {
|
|
35183
35485
|
removeManagedCompiledArtifact2(
|
|
35184
|
-
|
|
35486
|
+
path50.join(
|
|
35185
35487
|
resolveTargetPath(paths.rules ?? ""),
|
|
35186
|
-
`${
|
|
35488
|
+
`${path50.parse(relativePath).name}.md`
|
|
35187
35489
|
),
|
|
35188
35490
|
"cline",
|
|
35189
35491
|
relativePath,
|
|
@@ -35193,9 +35495,9 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
35193
35495
|
}
|
|
35194
35496
|
if (relativePath.startsWith("commands/")) {
|
|
35195
35497
|
removeManagedCompiledArtifact2(
|
|
35196
|
-
|
|
35498
|
+
path50.join(
|
|
35197
35499
|
resolveTargetPath(paths.workflows ?? ""),
|
|
35198
|
-
|
|
35500
|
+
path50.basename(relativePath)
|
|
35199
35501
|
),
|
|
35200
35502
|
"cline",
|
|
35201
35503
|
relativePath,
|
|
@@ -35213,17 +35515,17 @@ function cleanupRemovedClineArtifact(relativePath, paths, logger) {
|
|
|
35213
35515
|
}
|
|
35214
35516
|
}
|
|
35215
35517
|
function removeManagedCompiledArtifact2(artifactPath, expectedTarget, expectedSource, logger) {
|
|
35216
|
-
if (!
|
|
35518
|
+
if (!fs49.existsSync(artifactPath)) {
|
|
35217
35519
|
return;
|
|
35218
35520
|
}
|
|
35219
|
-
if (!
|
|
35521
|
+
if (!fs49.statSync(artifactPath).isFile()) {
|
|
35220
35522
|
return;
|
|
35221
35523
|
}
|
|
35222
|
-
const marker = extractProvenanceMarker(
|
|
35524
|
+
const marker = extractProvenanceMarker(fs49.readFileSync(artifactPath, "utf8"));
|
|
35223
35525
|
if (marker?.source !== expectedSource || marker.target !== expectedTarget) {
|
|
35224
35526
|
return;
|
|
35225
35527
|
}
|
|
35226
|
-
|
|
35528
|
+
fs49.rmSync(artifactPath, { force: true });
|
|
35227
35529
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
35228
35530
|
}
|
|
35229
35531
|
function removeManagedCopilotMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
@@ -35254,10 +35556,10 @@ function removeManagedCodexHooksArtifact2(artifactPath, expectedSource, logger)
|
|
|
35254
35556
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
35255
35557
|
}
|
|
35256
35558
|
function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
35257
|
-
if (!
|
|
35559
|
+
if (!fs49.existsSync(artifactPath)) {
|
|
35258
35560
|
return;
|
|
35259
35561
|
}
|
|
35260
|
-
const content =
|
|
35562
|
+
const content = fs49.readFileSync(artifactPath, "utf8");
|
|
35261
35563
|
const startMarker = "# tangyr: managed mcp start";
|
|
35262
35564
|
const endMarker = "# tangyr: managed mcp end";
|
|
35263
35565
|
const startIndex = content.indexOf(startMarker);
|
|
@@ -35274,19 +35576,19 @@ function removeManagedCodexMcpArtifact2(artifactPath, expectedSource, logger) {
|
|
|
35274
35576
|
const after = content.slice(endIndex + endMarker.length).trimStart();
|
|
35275
35577
|
const cleaned = [before, after].filter((entry) => entry.length > 0).join("\n\n");
|
|
35276
35578
|
if (cleaned.length === 0) {
|
|
35277
|
-
|
|
35579
|
+
fs49.rmSync(artifactPath, { force: true });
|
|
35278
35580
|
} else {
|
|
35279
|
-
|
|
35581
|
+
fs49.writeFileSync(artifactPath, `${cleaned}
|
|
35280
35582
|
`);
|
|
35281
35583
|
}
|
|
35282
35584
|
logger.verbose(` removed stale target artifact: ${artifactPath}`);
|
|
35283
35585
|
}
|
|
35284
35586
|
function readJsonObject5(filePath) {
|
|
35285
|
-
if (!
|
|
35587
|
+
if (!fs49.existsSync(filePath)) {
|
|
35286
35588
|
return null;
|
|
35287
35589
|
}
|
|
35288
35590
|
try {
|
|
35289
|
-
const parsed = JSON.parse(
|
|
35591
|
+
const parsed = JSON.parse(fs49.readFileSync(filePath, "utf8"));
|
|
35290
35592
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
35291
35593
|
} catch {
|
|
35292
35594
|
return null;
|
|
@@ -35300,10 +35602,10 @@ function readJsonMetadata(value) {
|
|
|
35300
35602
|
}
|
|
35301
35603
|
function writeJsonOrRemove2(filePath, parsed) {
|
|
35302
35604
|
if (isEmptyJsonValue2(parsed)) {
|
|
35303
|
-
|
|
35605
|
+
fs49.rmSync(filePath, { force: true });
|
|
35304
35606
|
return;
|
|
35305
35607
|
}
|
|
35306
|
-
|
|
35608
|
+
fs49.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
|
|
35307
35609
|
`);
|
|
35308
35610
|
}
|
|
35309
35611
|
function isEmptyJsonValue2(value) {
|
|
@@ -35363,8 +35665,8 @@ function removeManagedHookEntries(value, expectedSource) {
|
|
|
35363
35665
|
}
|
|
35364
35666
|
|
|
35365
35667
|
// src/commands/validate.ts
|
|
35366
|
-
import
|
|
35367
|
-
import
|
|
35668
|
+
import fs50 from "fs";
|
|
35669
|
+
import path51 from "path";
|
|
35368
35670
|
var SUPPORTED_KIT_FORMATS2 = [1];
|
|
35369
35671
|
var SUPPORTED_DISCIPLINE_VERSIONS = [
|
|
35370
35672
|
"0.14.0",
|
|
@@ -35479,12 +35781,12 @@ function checkArchetype(kit) {
|
|
|
35479
35781
|
}
|
|
35480
35782
|
function checkHookScriptsExist(kit) {
|
|
35481
35783
|
const violations = [];
|
|
35482
|
-
const hooksDir =
|
|
35784
|
+
const hooksDir = path51.join(kit.path, "hooks");
|
|
35483
35785
|
const missingSet = new Set(kit.components.hooks.missing);
|
|
35484
35786
|
for (const name of kit.components.hooks.declared) {
|
|
35485
35787
|
if (missingSet.has(name)) continue;
|
|
35486
|
-
const declarationPath =
|
|
35487
|
-
if (!
|
|
35788
|
+
const declarationPath = path51.join(hooksDir, `${name}.md`);
|
|
35789
|
+
if (!fs50.existsSync(declarationPath)) continue;
|
|
35488
35790
|
let data;
|
|
35489
35791
|
try {
|
|
35490
35792
|
({ data } = parseMarkdownFrontmatter(declarationPath));
|
|
@@ -35494,8 +35796,8 @@ function checkHookScriptsExist(kit) {
|
|
|
35494
35796
|
if (typeof data.command === "string" && data.command.trim().length > 0) {
|
|
35495
35797
|
continue;
|
|
35496
35798
|
}
|
|
35497
|
-
const scriptPath =
|
|
35498
|
-
if (!
|
|
35799
|
+
const scriptPath = path51.join(hooksDir, "scripts", `${name}.ts`);
|
|
35800
|
+
if (!fs50.existsSync(scriptPath)) {
|
|
35499
35801
|
violations.push({
|
|
35500
35802
|
code: "hook-script-missing",
|
|
35501
35803
|
location: `hooks/scripts/${name}.ts`,
|
|
@@ -35508,10 +35810,10 @@ function checkHookScriptsExist(kit) {
|
|
|
35508
35810
|
function checkOptionalSourceDocuments(kit) {
|
|
35509
35811
|
const violations = [];
|
|
35510
35812
|
for (const name of [".mcp.json", "settings.json", ".lsp.json"]) {
|
|
35511
|
-
const filePath =
|
|
35512
|
-
if (!
|
|
35813
|
+
const filePath = path51.join(kit.path, name);
|
|
35814
|
+
if (!fs50.existsSync(filePath)) continue;
|
|
35513
35815
|
try {
|
|
35514
|
-
const parsed = JSON.parse(
|
|
35816
|
+
const parsed = JSON.parse(fs50.readFileSync(filePath, "utf8"));
|
|
35515
35817
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
35516
35818
|
violations.push({
|
|
35517
35819
|
code: "optional-source-malformed",
|
|
@@ -35533,10 +35835,10 @@ function checkSkillSubfolderNames(kit) {
|
|
|
35533
35835
|
const notices = [];
|
|
35534
35836
|
const canonical = new Set(CANONICAL_SKILL_SUBFOLDERS);
|
|
35535
35837
|
for (const name of kit.components.skills.declared) {
|
|
35536
|
-
const skillDir =
|
|
35838
|
+
const skillDir = path51.join(kit.path, "skills", name);
|
|
35537
35839
|
let entries;
|
|
35538
35840
|
try {
|
|
35539
|
-
entries =
|
|
35841
|
+
entries = fs50.readdirSync(skillDir, { withFileTypes: true });
|
|
35540
35842
|
} catch {
|
|
35541
35843
|
continue;
|
|
35542
35844
|
}
|
|
@@ -35554,7 +35856,7 @@ function checkSkillSubfolderNames(kit) {
|
|
|
35554
35856
|
return notices;
|
|
35555
35857
|
}
|
|
35556
35858
|
function checkHooksSourceForm(kit) {
|
|
35557
|
-
const hooksDir =
|
|
35859
|
+
const hooksDir = path51.join(kit.path, "hooks");
|
|
35558
35860
|
const message = describeHooksSourceConflict(
|
|
35559
35861
|
hooksDir,
|
|
35560
35862
|
kit.components.hooks.declared
|
|
@@ -35566,12 +35868,12 @@ function checkHooksSourceForm(kit) {
|
|
|
35566
35868
|
} : null;
|
|
35567
35869
|
}
|
|
35568
35870
|
function checkHookDeclarations(kit) {
|
|
35569
|
-
const hooksDir =
|
|
35871
|
+
const hooksDir = path51.join(kit.path, "hooks");
|
|
35570
35872
|
return collectHookRejections(hooksDir, kit.components.hooks.declared).map(
|
|
35571
35873
|
(r) => ({
|
|
35572
35874
|
code: "hook-declaration-invalid",
|
|
35573
|
-
location: `hooks/${
|
|
35574
|
-
message: `hooks: '${
|
|
35875
|
+
location: `hooks/${path51.basename(r.file)}`,
|
|
35876
|
+
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.`
|
|
35575
35877
|
})
|
|
35576
35878
|
);
|
|
35577
35879
|
}
|
|
@@ -35591,11 +35893,11 @@ function checkKitFormatSupported(kit) {
|
|
|
35591
35893
|
function checkEntrypointExists(kit) {
|
|
35592
35894
|
const declared = kit.entrypoint;
|
|
35593
35895
|
const entrypoint = declared ?? DEFAULT_ENTRYPOINT;
|
|
35594
|
-
const entrypointPath =
|
|
35595
|
-
if (
|
|
35896
|
+
const entrypointPath = path51.join(kit.path, entrypoint);
|
|
35897
|
+
if (fs50.existsSync(entrypointPath)) {
|
|
35596
35898
|
return null;
|
|
35597
35899
|
}
|
|
35598
|
-
const legacyPresent = declared === void 0 &&
|
|
35900
|
+
const legacyPresent = declared === void 0 && fs50.existsSync(path51.join(kit.path, LEGACY_ENTRYPOINT));
|
|
35599
35901
|
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.`;
|
|
35600
35902
|
return {
|
|
35601
35903
|
code: "entrypoint-missing",
|
|
@@ -35654,9 +35956,9 @@ function checkComponentFrontmatter(kit) {
|
|
|
35654
35956
|
const missingSet = new Set(kit.components[cat].missing);
|
|
35655
35957
|
for (const name of kit.components[cat].declared) {
|
|
35656
35958
|
if (missingSet.has(name)) continue;
|
|
35657
|
-
const filePath = cat === "skills" ?
|
|
35658
|
-
if (!
|
|
35659
|
-
const relPath =
|
|
35959
|
+
const filePath = cat === "skills" ? path51.join(kit.path, cat, name, "SKILL.md") : path51.join(kit.path, cat, `${name}.md`);
|
|
35960
|
+
if (!fs50.existsSync(filePath)) continue;
|
|
35961
|
+
const relPath = path51.relative(kit.path, filePath);
|
|
35660
35962
|
try {
|
|
35661
35963
|
const { data } = parseMarkdownFrontmatter(filePath);
|
|
35662
35964
|
for (const field of requiredFields) {
|
|
@@ -35681,10 +35983,10 @@ function checkComponentFrontmatter(kit) {
|
|
|
35681
35983
|
}
|
|
35682
35984
|
function checkReservedRootNames(kit) {
|
|
35683
35985
|
const violations = [];
|
|
35684
|
-
if (!
|
|
35986
|
+
if (!fs50.existsSync(kit.path) || !fs50.statSync(kit.path).isDirectory()) {
|
|
35685
35987
|
return violations;
|
|
35686
35988
|
}
|
|
35687
|
-
const entries =
|
|
35989
|
+
const entries = fs50.readdirSync(kit.path, { withFileTypes: true });
|
|
35688
35990
|
for (const entry of entries) {
|
|
35689
35991
|
if (RESERVED_ROOT_NAMES.includes(entry.name)) {
|
|
35690
35992
|
violations.push({
|
|
@@ -35701,8 +36003,8 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
35701
36003
|
const missingSet = new Set(kit.components.commands.missing);
|
|
35702
36004
|
for (const name of kit.components.commands.declared) {
|
|
35703
36005
|
if (missingSet.has(name)) continue;
|
|
35704
|
-
const filePath =
|
|
35705
|
-
if (!
|
|
36006
|
+
const filePath = path51.join(kit.path, "commands", `${name}.md`);
|
|
36007
|
+
if (!fs50.existsSync(filePath)) continue;
|
|
35706
36008
|
let data;
|
|
35707
36009
|
try {
|
|
35708
36010
|
({ data } = parseMarkdownFrontmatter(filePath));
|
|
@@ -35715,7 +36017,7 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
35715
36017
|
if (!barred) {
|
|
35716
36018
|
violations.push({
|
|
35717
36019
|
code: "command-human-only-model-invocable",
|
|
35718
|
-
location:
|
|
36020
|
+
location: path51.relative(kit.path, filePath),
|
|
35719
36021
|
message: "commands: 'launch: human-only' requires 'disable-model-invocation: true' so the model cannot start the command; only a Human-typed launch may"
|
|
35720
36022
|
});
|
|
35721
36023
|
}
|
|
@@ -35724,8 +36026,8 @@ function checkHumanOnlyCommandInvocation(kit) {
|
|
|
35724
36026
|
}
|
|
35725
36027
|
|
|
35726
36028
|
// src/commands/verify.ts
|
|
35727
|
-
import
|
|
35728
|
-
import
|
|
36029
|
+
import fs51 from "fs";
|
|
36030
|
+
import path52 from "path";
|
|
35729
36031
|
function runVerifyCommand(options, logger) {
|
|
35730
36032
|
if (options.target && !isKnownTarget(options.target)) {
|
|
35731
36033
|
throwUnrecognizedTarget(options.target);
|
|
@@ -35906,8 +36208,8 @@ function verifyClaudeCodeGlobalRoots(roots, manifestKeys, mappings) {
|
|
|
35906
36208
|
if (!slotPath) {
|
|
35907
36209
|
continue;
|
|
35908
36210
|
}
|
|
35909
|
-
const fullPath = subPath ?
|
|
35910
|
-
if (!
|
|
36211
|
+
const fullPath = subPath ? path52.join(slotPath, subPath) : slotPath;
|
|
36212
|
+
if (!fs51.existsSync(fullPath)) {
|
|
35911
36213
|
failures.push(
|
|
35912
36214
|
`claude-code/${slot}${subPath ? `/${subPath}` : ""} missing in root ${root}: ${fullPath}`
|
|
35913
36215
|
);
|