agent-skills-standard 2.6.4 → 2.6.6
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 +1 -1
- package/dist/index.js +88 -31
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
**Sync 242 AI coding standards to any project in one command.** Works with Cursor, Claude Code, GitHub Copilot, Gemini, Windsurf, Trae, Kiro, and Roo.
|
|
7
7
|
|
|
8
|
-
**Current release:** `v2.6.
|
|
8
|
+
**Current release:** `v2.6.5` — `ags sync` manifest-check fix for repo-root LICENSE/NOTICE; skill validator accepts package directories under `scripts/`; SkillSpector security scanning, pull request evaluation gates, and verified release tags.
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
11
|
npx agent-skills-standard@latest init # detect your stack
|
package/dist/index.js
CHANGED
|
@@ -50,7 +50,7 @@ let crypto = require("crypto");
|
|
|
50
50
|
crypto = __toESM(crypto);
|
|
51
51
|
var package_default = {
|
|
52
52
|
name: "agent-skills-standard",
|
|
53
|
-
version: "2.6.
|
|
53
|
+
version: "2.6.6",
|
|
54
54
|
description: "A CLI to manage and sync AI agent skills standard for Cursor, Claude, Copilot, Windsurf, and more.",
|
|
55
55
|
main: "dist/index.js",
|
|
56
56
|
bin: {
|
|
@@ -94,7 +94,7 @@ var package_default = {
|
|
|
94
94
|
dependencies: {
|
|
95
95
|
"commander": "^15.0.0",
|
|
96
96
|
"cross-fetch": "^4.1.0",
|
|
97
|
-
"dotenv": "^18.0.
|
|
97
|
+
"dotenv": "^18.0.5",
|
|
98
98
|
"fs-extra": "^11.4.1",
|
|
99
99
|
"inquirer": "^14.2.2",
|
|
100
100
|
"js-yaml": "^5.4.2",
|
|
@@ -102,9 +102,9 @@ var package_default = {
|
|
|
102
102
|
"zod": "^4.6.5"
|
|
103
103
|
},
|
|
104
104
|
devDependencies: {
|
|
105
|
-
"@vitest/coverage-v8": "^5.0.
|
|
106
|
-
"vite": "^8.3.
|
|
107
|
-
"vitest": "^5.0.
|
|
105
|
+
"@vitest/coverage-v8": "^5.0.3",
|
|
106
|
+
"vite": "^8.3.2",
|
|
107
|
+
"vitest": "^5.0.3"
|
|
108
108
|
}
|
|
109
109
|
};
|
|
110
110
|
//#endregion
|
|
@@ -2698,7 +2698,7 @@ var McpConfigService = class {
|
|
|
2698
2698
|
buildEntry(version) {
|
|
2699
2699
|
return {
|
|
2700
2700
|
command: "npx",
|
|
2701
|
-
args: ["-y", `${PACKAGE}@${version || "0.6.
|
|
2701
|
+
args: ["-y", `${PACKAGE}@${version || "0.6.1"}`]
|
|
2702
2702
|
};
|
|
2703
2703
|
}
|
|
2704
2704
|
/** For testing: allows overriding the home directory. */
|
|
@@ -4409,9 +4409,46 @@ async function removeEmptyParents(rootDir, dir) {
|
|
|
4409
4409
|
}
|
|
4410
4410
|
}
|
|
4411
4411
|
//#endregion
|
|
4412
|
+
//#region src/services/install/safePath.ts
|
|
4413
|
+
/**
|
|
4414
|
+
* Asserts that a target file path resides inside rootDir and that NO intermediate
|
|
4415
|
+
* directory or terminal file under rootDir is a symbolic link.
|
|
4416
|
+
*
|
|
4417
|
+
* Requirements:
|
|
4418
|
+
* - rootDir may itself be a symlink (or inside one); components under rootDir must NOT be.
|
|
4419
|
+
* - Both existing files and dangling symlinks must be detected via lstat.
|
|
4420
|
+
* - Fails closed if lexical containment is breached or if any component under rootDir is a symlink.
|
|
4421
|
+
*
|
|
4422
|
+
* @param rootDir The trusted root directory
|
|
4423
|
+
* @param targetPath The destination file/directory path to check
|
|
4424
|
+
*/
|
|
4425
|
+
async function assertNoSymlinksUnderRoot(rootDir, targetPath) {
|
|
4426
|
+
const resolvedRoot = path.default.resolve(rootDir);
|
|
4427
|
+
const resolvedTarget = path.default.resolve(targetPath);
|
|
4428
|
+
const relative = path.default.relative(resolvedRoot, resolvedTarget);
|
|
4429
|
+
if (relative === ".." || relative.startsWith(`..${path.default.sep}`) || path.default.isAbsolute(relative)) throw new Error(`Path traversal or outside target detected: "${targetPath}" is outside "${rootDir}"`);
|
|
4430
|
+
const segments = relative.split(path.default.sep).filter(Boolean);
|
|
4431
|
+
let current = resolvedRoot;
|
|
4432
|
+
for (const segment of segments) {
|
|
4433
|
+
current = path.default.join(current, segment);
|
|
4434
|
+
try {
|
|
4435
|
+
if ((await fs_extra.default.lstat(current)).isSymbolicLink()) throw new Error(`Symlink path component not permitted: "${current}" is a symbolic link under "${rootDir}"`);
|
|
4436
|
+
} catch (err) {
|
|
4437
|
+
if (err instanceof Error && err.message.includes("Symlink path component")) throw err;
|
|
4438
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") break;
|
|
4439
|
+
throw err;
|
|
4440
|
+
}
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
//#endregion
|
|
4412
4444
|
//#region src/services/install/OwnershipWriter.ts
|
|
4413
4445
|
var PassthroughWriter = class {
|
|
4446
|
+
rootDir;
|
|
4447
|
+
constructor(rootDir) {
|
|
4448
|
+
this.rootDir = rootDir;
|
|
4449
|
+
}
|
|
4414
4450
|
async write(absPath, content) {
|
|
4451
|
+
await assertNoSymlinksUnderRoot(this.rootDir, absPath);
|
|
4415
4452
|
await fs_extra.default.outputFile(absPath, content);
|
|
4416
4453
|
}
|
|
4417
4454
|
};
|
|
@@ -4434,6 +4471,7 @@ var OwnershipWriter = class {
|
|
|
4434
4471
|
this.opts = opts;
|
|
4435
4472
|
}
|
|
4436
4473
|
async write(absPath, content, meta) {
|
|
4474
|
+
await assertNoSymlinksUnderRoot(this.opts.rootDir, absPath);
|
|
4437
4475
|
const rel = toPosixRel(this.opts.rootDir, absPath);
|
|
4438
4476
|
this.touched.add(rel);
|
|
4439
4477
|
const incoming = sha256(content);
|
|
@@ -4489,6 +4527,7 @@ var OwnershipWriter = class {
|
|
|
4489
4527
|
continue;
|
|
4490
4528
|
}
|
|
4491
4529
|
const abs = path.default.join(this.opts.rootDir, rel);
|
|
4530
|
+
await assertNoSymlinksUnderRoot(this.opts.rootDir, abs);
|
|
4492
4531
|
if (!await fs_extra.default.pathExists(abs)) continue;
|
|
4493
4532
|
if (sha256(await fs_extra.default.readFile(abs)) !== prev.sha256) {
|
|
4494
4533
|
this.plan.keptOrphans.push(rel);
|
|
@@ -4537,7 +4576,7 @@ var AgentBridgeService = class {
|
|
|
4537
4576
|
* @param rootDir Project root directory
|
|
4538
4577
|
* @param agents List of agents to generate rules for
|
|
4539
4578
|
*/
|
|
4540
|
-
async bridge(rootDir, agents, writer = new PassthroughWriter(), options = {}) {
|
|
4579
|
+
async bridge(rootDir, agents, writer = new PassthroughWriter(rootDir), options = {}) {
|
|
4541
4580
|
const fileNameBase = "agent-skill-standard-rule";
|
|
4542
4581
|
const commonDescription = "Rule for Agent Skills Standard - Always consult AGENTS.md for consolidated project context and technical triggers.";
|
|
4543
4582
|
for (const agentId of agents) {
|
|
@@ -4575,7 +4614,9 @@ var AgentBridgeService = class {
|
|
|
4575
4614
|
"",
|
|
4576
4615
|
"### State 4: Execution & Audit Log (Output Generation)",
|
|
4577
4616
|
"",
|
|
4578
|
-
"- **Action:**
|
|
4617
|
+
"- **Action:**",
|
|
4618
|
+
" - **Multi-task implementation plan (new or existing):** Do NOT edit files directly in the orchestrator session. Present the execution confirmation gate (Subagent-Driven vs. Inline) and use `subagent-driven-development`.",
|
|
4619
|
+
" - **Analysis, review, or single-file fix:** You may begin answering the user or implementing.",
|
|
4579
4620
|
"- **Constraint:** Your very first text output MUST be a \"Pre-Write Audit Log\" confirming which skills were loaded, or explicitly stating \"No project-specific skills applicable.\"",
|
|
4580
4621
|
"",
|
|
4581
4622
|
"## Self-Learning Protocol",
|
|
@@ -5198,17 +5239,22 @@ var SkillSyncService = class {
|
|
|
5198
5239
|
/**
|
|
5199
5240
|
* Writes collected skills to target agent paths.
|
|
5200
5241
|
*/
|
|
5201
|
-
async writeSkills(skills, config, agents, writer = new PassthroughWriter()) {
|
|
5242
|
+
async writeSkills(skills, config, agents, writer = new PassthroughWriter(process.cwd()), rootDir = process.cwd()) {
|
|
5202
5243
|
const overrides = config.custom_overrides || [];
|
|
5244
|
+
for (const agentId of agents) {
|
|
5245
|
+
const basePath = SUPPORTED_AGENTS.find((agent) => agent.id === agentId)?.path;
|
|
5246
|
+
if (!basePath) continue;
|
|
5247
|
+
for (const skill of skills) await this.writeSkillForAgent(agentId, skill, overrides, basePath, writer, config, true, rootDir);
|
|
5248
|
+
}
|
|
5203
5249
|
for (const agentId of agents) {
|
|
5204
5250
|
const agentDef = SUPPORTED_AGENTS.find((agent) => agent.id === agentId);
|
|
5205
5251
|
if (!agentDef?.path) continue;
|
|
5206
5252
|
const basePath = agentDef.path;
|
|
5207
|
-
for (const skill of skills) await this.writeSkillForAgent(agentId, skill, overrides, basePath, writer, config);
|
|
5253
|
+
for (const skill of skills) await this.writeSkillForAgent(agentId, skill, overrides, basePath, writer, config, false, rootDir);
|
|
5208
5254
|
console.log(picocolors.default.gray(` - Updated ${basePath}/ (${agentDef.name})`));
|
|
5209
5255
|
}
|
|
5210
5256
|
}
|
|
5211
|
-
async writeSkillForAgent(agentId, skill, overrides, basePath, writer, config) {
|
|
5257
|
+
async writeSkillForAgent(agentId, skill, overrides, basePath, writer, config, preflightOnly = false, rootDir = basePath) {
|
|
5212
5258
|
const isKiro = agentId === Agent.Kiro;
|
|
5213
5259
|
const skillPath = isKiro ? path.default.join(basePath, `${skill.category}-${skill.skill}`) : path.default.join(basePath, skill.category, skill.skill);
|
|
5214
5260
|
if (!this.isPathSafe(skillPath, basePath)) {
|
|
@@ -5216,7 +5262,7 @@ var SkillSyncService = class {
|
|
|
5216
5262
|
throw new Error(`Invalid skill path ${skill.category}/${skill.skill}`);
|
|
5217
5263
|
}
|
|
5218
5264
|
const source = `skill:${skill.category}/${skill.skill}@${config.skills?.[skill.category]?.ref ?? "main"}`;
|
|
5219
|
-
const pending = [];
|
|
5265
|
+
const pending = preflightOnly ? null : [];
|
|
5220
5266
|
for (const fileItem of skill.files) {
|
|
5221
5267
|
const targetFilePath = path.default.join(skillPath, fileItem.name);
|
|
5222
5268
|
if (!this.isPathSafe(targetFilePath, skillPath)) {
|
|
@@ -5227,12 +5273,15 @@ var SkillSyncService = class {
|
|
|
5227
5273
|
console.log(picocolors.default.yellow(` ⚠️ Skipping overridden: ${this.normalizePath(targetFilePath)}`));
|
|
5228
5274
|
continue;
|
|
5229
5275
|
}
|
|
5276
|
+
await assertNoSymlinksUnderRoot(rootDir, targetFilePath);
|
|
5277
|
+
if (pending === null) continue;
|
|
5230
5278
|
const content = isKiro && fileItem.name === "SKILL.md" ? this.transformSkillForKiro(fileItem.content, skill.category) : fileItem.bytes ?? fileItem.content;
|
|
5231
5279
|
pending.push({
|
|
5232
5280
|
target: targetFilePath,
|
|
5233
5281
|
content
|
|
5234
5282
|
});
|
|
5235
5283
|
}
|
|
5284
|
+
if (pending === null) return;
|
|
5236
5285
|
for (const { target, content } of pending) await writer.write(target, content, {
|
|
5237
5286
|
owner: "skill",
|
|
5238
5287
|
source,
|
|
@@ -5255,6 +5304,7 @@ var SkillSyncService = class {
|
|
|
5255
5304
|
const { ok: files, failed } = await this.githubService.downloadFilesConcurrentBytes(downloadTasks);
|
|
5256
5305
|
const verifier = verifiers[sourceCat] ?? verifiers[category];
|
|
5257
5306
|
if (verifier) for (const f of files) {
|
|
5307
|
+
if (this.isRootAttributionFile(f.path)) continue;
|
|
5258
5308
|
const rejection = verifier.check(f.path, f.content);
|
|
5259
5309
|
if (rejection) failed.push({
|
|
5260
5310
|
path: f.path,
|
|
@@ -5649,7 +5699,7 @@ var WorkflowSyncService = class {
|
|
|
5649
5699
|
* - Copilot: prompt files
|
|
5650
5700
|
* - Cursor/Trae/Codex: skill folders with SKILL.md
|
|
5651
5701
|
*/
|
|
5652
|
-
async writeWorkflows(workflows, config, agents, writer = new PassthroughWriter()) {
|
|
5702
|
+
async writeWorkflows(workflows, config, agents, writer = new PassthroughWriter(process.cwd())) {
|
|
5653
5703
|
if (workflows.length === 0) return;
|
|
5654
5704
|
const overrides = config.custom_overrides || [];
|
|
5655
5705
|
const targetAgents = agents || [Agent.Antigravity];
|
|
@@ -5737,10 +5787,8 @@ function summarizeDeclaredPermissions(metadata) {
|
|
|
5737
5787
|
}
|
|
5738
5788
|
/**
|
|
5739
5789
|
* For platforms with no way to express a declared risk_tier/permissions/
|
|
5740
|
-
* allowed-tools,
|
|
5741
|
-
* the declaration
|
|
5742
|
-
* should not read as unconstrained everywhere else without at least a
|
|
5743
|
-
* trace of what was intended.
|
|
5790
|
+
* allowed-tools, emit a visible warning after native frontmatter rather than
|
|
5791
|
+
* silently dropping the declaration.
|
|
5744
5792
|
*/
|
|
5745
5793
|
function unenforceableWarningComment(metadata, agentName) {
|
|
5746
5794
|
const declared = summarizeDeclaredPermissions(metadata);
|
|
@@ -5780,39 +5828,39 @@ var SpecialistTransformer = class {
|
|
|
5780
5828
|
}
|
|
5781
5829
|
case "cursor-mdc": return {
|
|
5782
5830
|
name: `${fullName}.mdc`,
|
|
5783
|
-
content:
|
|
5831
|
+
content: `---\n${dumpFrontmatter({
|
|
5784
5832
|
description,
|
|
5785
5833
|
globs: ["**/*"]
|
|
5786
|
-
})}\n---\n# Specialist: ${baseName}\n\n${body}`
|
|
5834
|
+
})}\n---\n${unenforceableWarningComment(metadata, "Cursor")}\n# Specialist: ${baseName}\n\n${body}`
|
|
5787
5835
|
};
|
|
5788
5836
|
case "copilot-instructions": return {
|
|
5789
5837
|
name: `${fullName}.instructions.md`,
|
|
5790
|
-
content:
|
|
5838
|
+
content: `---\n${dumpFrontmatter({
|
|
5791
5839
|
description,
|
|
5792
5840
|
applyTo: "**/*"
|
|
5793
|
-
})}\n---\n\n${body}`
|
|
5841
|
+
})}\n---\n${unenforceableWarningComment(metadata, "Copilot")}\n${body}`
|
|
5794
5842
|
};
|
|
5795
5843
|
case "opencode-md": return {
|
|
5796
5844
|
name: `${baseName}.md`,
|
|
5797
|
-
content:
|
|
5845
|
+
content: `---\n${dumpFrontmatter({
|
|
5798
5846
|
description,
|
|
5799
5847
|
mode: "subagent"
|
|
5800
|
-
})}\n---\n\n${body}`
|
|
5848
|
+
})}\n---\n${unenforceableWarningComment(metadata, "OpenCode")}\n${body}`
|
|
5801
5849
|
};
|
|
5802
5850
|
case "gemini-md": return {
|
|
5803
5851
|
name: `${baseName}.md`,
|
|
5804
|
-
content:
|
|
5852
|
+
content: `---\n${dumpFrontmatter({
|
|
5805
5853
|
name: baseName,
|
|
5806
5854
|
description,
|
|
5807
5855
|
kind: "local"
|
|
5808
|
-
})}\n---\n\n${body}`
|
|
5856
|
+
})}\n---\n${unenforceableWarningComment(metadata, "Gemini")}\n${body}`
|
|
5809
5857
|
};
|
|
5810
5858
|
case "kiro-md": return {
|
|
5811
5859
|
name: `${baseName}.md`,
|
|
5812
|
-
content:
|
|
5860
|
+
content: `---\n${dumpFrontmatter({
|
|
5813
5861
|
name: baseName,
|
|
5814
5862
|
description
|
|
5815
|
-
})}\n---\n\n${body}`
|
|
5863
|
+
})}\n---\n${unenforceableWarningComment(metadata, "Kiro")}\n${body}`
|
|
5816
5864
|
};
|
|
5817
5865
|
case "codex-toml": {
|
|
5818
5866
|
const sandboxMode = sandboxModeFor(metadata.risk_tier);
|
|
@@ -5874,7 +5922,7 @@ var SpecialistSyncService = class {
|
|
|
5874
5922
|
}
|
|
5875
5923
|
return specialists;
|
|
5876
5924
|
}
|
|
5877
|
-
async syncCollectedSpecialists(rootDir, agents, specialists, writer = new PassthroughWriter()) {
|
|
5925
|
+
async syncCollectedSpecialists(rootDir, agents, specialists, writer = new PassthroughWriter(rootDir)) {
|
|
5878
5926
|
if (specialists.length === 0) return 0;
|
|
5879
5927
|
for (const agentId of agents) {
|
|
5880
5928
|
const agentDef = SUPPORTED_AGENTS.find((a) => a.id === agentId);
|
|
@@ -5906,7 +5954,7 @@ var SpecialistSyncService = class {
|
|
|
5906
5954
|
* @param agents List of agents to sync for
|
|
5907
5955
|
* @param sourceDir Optional custom source directory for specialists
|
|
5908
5956
|
*/
|
|
5909
|
-
async syncSpecialists(rootDir, agents, sourceDir, writer = new PassthroughWriter()) {
|
|
5957
|
+
async syncSpecialists(rootDir, agents, sourceDir, writer = new PassthroughWriter(rootDir)) {
|
|
5910
5958
|
const specialistsDir = sourceDir || path.default.join(rootDir, "skills/specialists");
|
|
5911
5959
|
if (!await fs_extra.default.pathExists(specialistsDir)) return 0;
|
|
5912
5960
|
const specialistFolders = (await fs_extra.default.readdir(specialistsDir)).filter((f) => {
|
|
@@ -6085,8 +6133,10 @@ var BackupSession = class {
|
|
|
6085
6133
|
const normalized = rel.replace(/\\/g, "/");
|
|
6086
6134
|
if (this.added.has(normalized)) return;
|
|
6087
6135
|
const src = path.default.join(this.rootDir, normalized);
|
|
6136
|
+
await assertNoSymlinksUnderRoot(this.rootDir, src);
|
|
6088
6137
|
if (!await fs_extra.default.pathExists(src)) return;
|
|
6089
6138
|
const dest = path.default.join(this.backupDir, "files", normalized);
|
|
6139
|
+
await assertNoSymlinksUnderRoot(this.rootDir, dest);
|
|
6090
6140
|
await fs_extra.default.copy(src, dest, { overwrite: true });
|
|
6091
6141
|
this.added.add(normalized);
|
|
6092
6142
|
}
|
|
@@ -6097,7 +6147,9 @@ var BackupSession = class {
|
|
|
6097
6147
|
reason: this.reason,
|
|
6098
6148
|
files: Array.from(this.added)
|
|
6099
6149
|
};
|
|
6100
|
-
|
|
6150
|
+
const manifestPath = path.default.join(this.backupDir, "manifest.json");
|
|
6151
|
+
await assertNoSymlinksUnderRoot(this.rootDir, manifestPath);
|
|
6152
|
+
await fs_extra.default.outputJson(manifestPath, manifest, { spaces: 2 });
|
|
6101
6153
|
const backupsDir = path.default.dirname(this.backupDir);
|
|
6102
6154
|
if (await fs_extra.default.pathExists(backupsDir)) {
|
|
6103
6155
|
const dirs = (await fs_extra.default.readdir(backupsDir, { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
@@ -6133,12 +6185,15 @@ var BackupService = class {
|
|
|
6133
6185
|
}
|
|
6134
6186
|
async begin(rootDir, reason) {
|
|
6135
6187
|
const agsDir = path.default.join(rootDir, ".ags");
|
|
6188
|
+
await assertNoSymlinksUnderRoot(rootDir, agsDir);
|
|
6136
6189
|
await fs_extra.default.ensureDir(agsDir);
|
|
6137
6190
|
const gitignorePath = path.default.join(agsDir, ".gitignore");
|
|
6191
|
+
await assertNoSymlinksUnderRoot(rootDir, gitignorePath);
|
|
6138
6192
|
const defaultGitignore = "backups/\npolicy-candidates.json\n";
|
|
6139
6193
|
if (!await fs_extra.default.pathExists(gitignorePath)) await fs_extra.default.writeFile(gitignorePath, defaultGitignore, "utf8");
|
|
6140
6194
|
else if (await fs_extra.default.readFile(gitignorePath, "utf8") === "*\n") await fs_extra.default.writeFile(gitignorePath, defaultGitignore, "utf8");
|
|
6141
6195
|
const backupsDir = path.default.join(agsDir, "backups");
|
|
6196
|
+
await assertNoSymlinksUnderRoot(rootDir, backupsDir);
|
|
6142
6197
|
await fs_extra.default.ensureDir(backupsDir);
|
|
6143
6198
|
const date = this.now();
|
|
6144
6199
|
const baseId = this.formatId(date);
|
|
@@ -6149,6 +6204,7 @@ var BackupService = class {
|
|
|
6149
6204
|
counter++;
|
|
6150
6205
|
}
|
|
6151
6206
|
const backupDir = path.default.join(backupsDir, id);
|
|
6207
|
+
await assertNoSymlinksUnderRoot(rootDir, backupDir);
|
|
6152
6208
|
await fs_extra.default.ensureDir(backupDir);
|
|
6153
6209
|
return new BackupSession(id, rootDir, backupDir, reason, date.toISOString(), this.keep);
|
|
6154
6210
|
}
|
|
@@ -6178,6 +6234,7 @@ var BackupService = class {
|
|
|
6178
6234
|
const src = path.default.join(backupDir, "files", rel);
|
|
6179
6235
|
if (await fs_extra.default.pathExists(src)) {
|
|
6180
6236
|
const dest = path.default.join(rootDir, rel);
|
|
6237
|
+
await assertNoSymlinksUnderRoot(rootDir, dest);
|
|
6181
6238
|
await fs_extra.default.copy(src, dest, { overwrite: true });
|
|
6182
6239
|
restored.push(rel);
|
|
6183
6240
|
}
|
|
@@ -6322,7 +6379,7 @@ var SyncService = class {
|
|
|
6322
6379
|
specialistSyncService = new SpecialistSyncService();
|
|
6323
6380
|
gitService = new GitService();
|
|
6324
6381
|
lockfileService = new LockfileService();
|
|
6325
|
-
writer = new PassthroughWriter();
|
|
6382
|
+
writer = new PassthroughWriter(process.cwd());
|
|
6326
6383
|
ownership = null;
|
|
6327
6384
|
dryRun = false;
|
|
6328
6385
|
cachedRegistryMetadata = void 0;
|