teamix-evo 0.14.0 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/index.d.ts +31 -6
- package/dist/core/index.js +169 -57
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +269 -81
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -180,12 +180,40 @@ async function readInstalledManifest(projectRoot) {
|
|
|
180
180
|
);
|
|
181
181
|
}
|
|
182
182
|
const result = validateInstalled(data);
|
|
183
|
-
if (
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
if (result.success) {
|
|
184
|
+
return result.data;
|
|
185
|
+
}
|
|
186
|
+
const migrated = migrateManifest(data);
|
|
187
|
+
const retryResult = validateInstalled(migrated);
|
|
188
|
+
if (retryResult.success) {
|
|
189
|
+
logger.warn(
|
|
190
|
+
"Migrated legacy manifest.json \u2014 will be overwritten on next install."
|
|
186
191
|
);
|
|
192
|
+
return retryResult.data;
|
|
187
193
|
}
|
|
188
|
-
|
|
194
|
+
throw new Error(
|
|
195
|
+
`Invalid manifest.json schema: ${result.error}. Fix the file manually or remove it to start fresh.`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
function migrateManifest(data) {
|
|
199
|
+
if (typeof data !== "object" || data === null) return data;
|
|
200
|
+
const obj = data;
|
|
201
|
+
if (!("schemaVersion" in obj)) obj.schemaVersion = 1;
|
|
202
|
+
if (!Array.isArray(obj.installed)) obj.installed = [];
|
|
203
|
+
for (const pkg of obj.installed) {
|
|
204
|
+
if (typeof pkg !== "object" || pkg === null) continue;
|
|
205
|
+
if (!pkg.variant) pkg.variant = "_flat";
|
|
206
|
+
if (!pkg.installedAt) pkg.installedAt = "";
|
|
207
|
+
if (!pkg.version) pkg.version = "0.0.0";
|
|
208
|
+
if (Array.isArray(pkg.resources)) {
|
|
209
|
+
for (const res of pkg.resources) {
|
|
210
|
+
if (typeof res !== "object" || res === null) continue;
|
|
211
|
+
if (!res.hash) res.hash = "sha256:legacy-unknown";
|
|
212
|
+
if (!res.strategy) res.strategy = "frozen";
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return obj;
|
|
189
217
|
}
|
|
190
218
|
async function writeInstalledManifest(projectRoot, manifest) {
|
|
191
219
|
const manifestPath = path4.join(projectRoot, TEAMIX_DIR, MANIFEST_FILE);
|
|
@@ -1296,9 +1324,15 @@ function partitionByVersion(ids, manifest, existing) {
|
|
|
1296
1324
|
onlyIds.push(name);
|
|
1297
1325
|
continue;
|
|
1298
1326
|
}
|
|
1299
|
-
const installedVer = existing.lock?.skills?.[name]?.version;
|
|
1327
|
+
const installedVer = existing.lock?.skills?.[name]?.version ?? existing.pkg?.version;
|
|
1300
1328
|
const latestVer = manifestById.get(name)?.version;
|
|
1301
|
-
if (installedVer
|
|
1329
|
+
if (!installedVer || !latestVer) {
|
|
1330
|
+
if (latestVer) {
|
|
1331
|
+
outdatedSkills.push({ id: name, installed: "0.0.0", latest: latestVer });
|
|
1332
|
+
} else {
|
|
1333
|
+
skippedSkillIds.push(name);
|
|
1334
|
+
}
|
|
1335
|
+
} else if (compareSemver(installedVer, latestVer) < 0) {
|
|
1302
1336
|
outdatedSkills.push({
|
|
1303
1337
|
id: name,
|
|
1304
1338
|
installed: installedVer,
|
|
@@ -3877,18 +3911,24 @@ init_state();
|
|
|
3877
3911
|
var AGENTS_MD_MANAGED_ID = "teamix-evo-skills";
|
|
3878
3912
|
async function runGenerateAgentsMd(options) {
|
|
3879
3913
|
const { projectRoot, variant, skillIds } = options;
|
|
3914
|
+
const globalSkillIds = options.globalSkillIds ?? [];
|
|
3880
3915
|
const mode = options.mode ?? "overwrite";
|
|
3881
3916
|
const config = await readProjectConfig(projectRoot);
|
|
3882
3917
|
const lock = await readSkillsLock(projectRoot);
|
|
3883
3918
|
const ides = config?.packages?.skills?.ides ?? ["qoder", "claude"];
|
|
3884
3919
|
const scope = config?.packages?.skills?.scope ?? lock?.skills[skillIds[0] ?? ""]?.scope ?? "project";
|
|
3885
|
-
const
|
|
3920
|
+
const skillScopeMap = /* @__PURE__ */ new Map();
|
|
3921
|
+
for (const id of skillIds) skillScopeMap.set(id, scope);
|
|
3922
|
+
for (const id of globalSkillIds) skillScopeMap.set(id, "global");
|
|
3923
|
+
const allSkillIds = [...skillIds, ...globalSkillIds];
|
|
3924
|
+
const ordered = allSkillIds.sort(
|
|
3886
3925
|
(a, b) => bucketRank(a) - bucketRank(b) || a.localeCompare(b)
|
|
3887
3926
|
);
|
|
3888
3927
|
const sections = [];
|
|
3889
3928
|
const missingSkillIds = [];
|
|
3890
3929
|
for (const id of ordered) {
|
|
3891
|
-
const
|
|
3930
|
+
const skillScope = skillScopeMap.get(id) ?? scope;
|
|
3931
|
+
const { section, missing } = await renderSkillSection(projectRoot, id, ides, skillScope);
|
|
3892
3932
|
sections.push(section);
|
|
3893
3933
|
if (missing) missingSkillIds.push(id);
|
|
3894
3934
|
}
|
|
@@ -3972,6 +4012,12 @@ async function renderSkillSection(projectRoot, skillId, ides, scope) {
|
|
|
3972
4012
|
if (parts?.coordinates) {
|
|
3973
4013
|
lines.push(`- **Coordinates with**: ${parts.coordinates}`);
|
|
3974
4014
|
}
|
|
4015
|
+
if (scope === "global") {
|
|
4016
|
+
lines.push("");
|
|
4017
|
+
lines.push(
|
|
4018
|
+
"> **\u5168\u5C40\u6280\u80FD** \u2014 \u5B89\u88C5\u5728\u5168\u5C40\u800C\u975E\u9879\u76EE\u5185\uFF0C\u4E0D\u968F\u4EE3\u7801\u4ED3\u5E93\u5206\u53D1\u3002AI \u89E6\u53D1\u65F6\u5E94\u5148\u786E\u8BA4\u672C\u6280\u80FD\u53EF\u7528\uFF1B\u82E5\u4E0D\u53EF\u7528\uFF0C\u5F15\u5BFC\u7528\u6237\u6267\u884C\u5168\u5C40\u5B89\u88C5\u3002"
|
|
4019
|
+
);
|
|
4020
|
+
}
|
|
3975
4021
|
return { section: lines.join("\n"), missing };
|
|
3976
4022
|
}
|
|
3977
4023
|
function renderAgentsMd(args) {
|
|
@@ -4118,13 +4164,34 @@ async function runSkillsUpdate(options) {
|
|
|
4118
4164
|
}
|
|
4119
4165
|
const ides = skillsCfg.ides ?? ["qoder", "claude"];
|
|
4120
4166
|
const scope = skillsCfg.scope ?? "project";
|
|
4121
|
-
|
|
4167
|
+
let existingLock = await readSkillsLock(projectRoot);
|
|
4122
4168
|
if (!existingLock || Object.keys(existingLock.skills).length === 0) {
|
|
4123
|
-
|
|
4169
|
+
const installedManifest2 = await readInstalledManifest(projectRoot);
|
|
4170
|
+
const pkg = installedManifest2?.installed.find(
|
|
4171
|
+
(p2) => p2.package === packageName
|
|
4172
|
+
);
|
|
4173
|
+
if (!pkg || pkg.resources.length === 0) {
|
|
4174
|
+
return { status: "no-skills" };
|
|
4175
|
+
}
|
|
4176
|
+
const derivedSkills = {};
|
|
4177
|
+
for (const r of pkg.resources) {
|
|
4178
|
+
const skillId = r.id.split(":")[0] ?? r.id;
|
|
4179
|
+
if (!derivedSkills[skillId]) {
|
|
4180
|
+
derivedSkills[skillId] = {
|
|
4181
|
+
version: pkg.version,
|
|
4182
|
+
from: packageName,
|
|
4183
|
+
installedAt: "",
|
|
4184
|
+
scope,
|
|
4185
|
+
mirroredTo: []
|
|
4186
|
+
};
|
|
4187
|
+
}
|
|
4188
|
+
}
|
|
4189
|
+
existingLock = { schemaVersion: 1, skills: derivedSkills };
|
|
4124
4190
|
}
|
|
4191
|
+
const activeLock = existingLock;
|
|
4125
4192
|
const { manifest, data, packageRoot } = await loadSkillsData(packageName);
|
|
4126
4193
|
const manifestById = new Map(manifest.skills.map((s) => [s.id, s]));
|
|
4127
|
-
const lockIds = Object.keys(
|
|
4194
|
+
const lockIds = Object.keys(activeLock.skills);
|
|
4128
4195
|
const requestedSet = requestedNames ? new Set(requestedNames) : null;
|
|
4129
4196
|
if (requestedSet) {
|
|
4130
4197
|
const unknown = requestedNames.filter(
|
|
@@ -4161,7 +4228,7 @@ async function runSkillsUpdate(options) {
|
|
|
4161
4228
|
targetIds.push(id);
|
|
4162
4229
|
}
|
|
4163
4230
|
const allSame = targetIds.every((id) => {
|
|
4164
|
-
const lockVer =
|
|
4231
|
+
const lockVer = activeLock.skills[id].version;
|
|
4165
4232
|
const manVer = manifestById.get(id).version;
|
|
4166
4233
|
return lockVer === manVer;
|
|
4167
4234
|
});
|
|
@@ -4175,7 +4242,7 @@ async function runSkillsUpdate(options) {
|
|
|
4175
4242
|
}
|
|
4176
4243
|
if (dryRun) {
|
|
4177
4244
|
const plan = targetIds.map((id) => {
|
|
4178
|
-
const lockVer =
|
|
4245
|
+
const lockVer = activeLock.skills[id].version;
|
|
4179
4246
|
const entry2 = manifestById.get(id);
|
|
4180
4247
|
const sameVersion = lockVer === entry2.version;
|
|
4181
4248
|
return {
|
|
@@ -4247,7 +4314,7 @@ async function runSkillsUpdate(options) {
|
|
|
4247
4314
|
await writeInstalledManifest(projectRoot, installedManifest);
|
|
4248
4315
|
const lock = {
|
|
4249
4316
|
schemaVersion: 1,
|
|
4250
|
-
skills: { ...
|
|
4317
|
+
skills: { ...activeLock.skills }
|
|
4251
4318
|
};
|
|
4252
4319
|
for (const id of targetIds) {
|
|
4253
4320
|
const skillDef = manifestById.get(id);
|
|
@@ -4267,10 +4334,12 @@ async function runSkillsUpdate(options) {
|
|
|
4267
4334
|
const variant = await readTokensVariant(projectRoot);
|
|
4268
4335
|
if (variant) {
|
|
4269
4336
|
const projectSkillIds = Object.entries(lock.skills).filter(([, v]) => v.scope === "project").map(([id]) => id);
|
|
4337
|
+
const globalSkillIds = Object.entries(lock.skills).filter(([, v]) => v.scope === "global").map(([id]) => id);
|
|
4270
4338
|
await runGenerateAgentsMd({
|
|
4271
4339
|
projectRoot,
|
|
4272
4340
|
variant,
|
|
4273
4341
|
skillIds: projectSkillIds,
|
|
4342
|
+
globalSkillIds,
|
|
4274
4343
|
mode: "merge-managed"
|
|
4275
4344
|
});
|
|
4276
4345
|
}
|
|
@@ -4431,11 +4500,14 @@ init_logger();
|
|
|
4431
4500
|
var SKILLS_PACKAGE3 = "@teamix-evo/skills";
|
|
4432
4501
|
var uninstallCommand2 = new Command17("uninstall").description(
|
|
4433
4502
|
"\u5378\u8F7D\u5DF2\u5B89\u88C5\u7684 teamix-evo skills\uFF1B\u4E0D\u4F20 ids \u5219\u5378\u8F7D\u6574\u5305\uFF0C\u4F20 ids \u5219\u6309 skill \u5220\u9664"
|
|
4434
|
-
).argument("[ids...]", "\u53EF\u9009\uFF1A\u4EC5\u5378\u8F7D\u6307\u5B9A skill id\uFF1B\u7701\u7565\u5219\u5378\u8F7D\u6574\u4E2A skills \u5305").option("-y, --yes", "\u8DF3\u8FC7\u786E\u8BA4").
|
|
4503
|
+
).argument("[ids...]", "\u53EF\u9009\uFF1A\u4EC5\u5378\u8F7D\u6307\u5B9A skill id\uFF1B\u7701\u7565\u5219\u5378\u8F7D\u6574\u4E2A skills \u5305").option("-y, --yes", "\u8DF3\u8FC7\u786E\u8BA4").option(
|
|
4504
|
+
"--scope <scope>",
|
|
4505
|
+
"project | global\uFF08\u9ED8\u8BA4\u6309 cwd \u63A8\u65AD\uFF1Acwd \u662F\u9879\u76EE\u2192project\uFF1B\u5426\u5219 fallback \u5230\u5168\u5C40\uFF09"
|
|
4506
|
+
).action(async (ids, opts) => {
|
|
4435
4507
|
try {
|
|
4436
4508
|
const ide = detectIde();
|
|
4437
4509
|
const cwd = ide.getProjectRoot();
|
|
4438
|
-
const projectRoot =
|
|
4510
|
+
const projectRoot = resolveUninstallRoot(cwd, opts.scope);
|
|
4439
4511
|
if (projectRoot !== cwd) {
|
|
4440
4512
|
logger.info(`Using global skills meta root: ${projectRoot}`);
|
|
4441
4513
|
}
|
|
@@ -4637,6 +4709,22 @@ function groupBySkillId(records) {
|
|
|
4637
4709
|
function dedupe(values) {
|
|
4638
4710
|
return Array.from(new Set(values));
|
|
4639
4711
|
}
|
|
4712
|
+
function resolveUninstallRoot(cwd, scopeFlag) {
|
|
4713
|
+
if (scopeFlag === void 0) {
|
|
4714
|
+
return resolveSkillsMaintenanceRoot(cwd);
|
|
4715
|
+
}
|
|
4716
|
+
const scope = parseScope(scopeFlag);
|
|
4717
|
+
if (scope === "global") {
|
|
4718
|
+
const globalRoot = getGlobalMetaRoot();
|
|
4719
|
+
if (!isTeamixEvoProject(globalRoot)) {
|
|
4720
|
+
throw new Error(
|
|
4721
|
+
`No global skills installed at ${globalRoot}. Nothing to uninstall.`
|
|
4722
|
+
);
|
|
4723
|
+
}
|
|
4724
|
+
return globalRoot;
|
|
4725
|
+
}
|
|
4726
|
+
return cwd;
|
|
4727
|
+
}
|
|
4640
4728
|
|
|
4641
4729
|
// src/commands/skills/sync.ts
|
|
4642
4730
|
import { Command as Command18 } from "commander";
|
|
@@ -5157,6 +5245,10 @@ async function loadUiData(packageName) {
|
|
|
5157
5245
|
const packageRoot = resolvePackageRoot2(packageName);
|
|
5158
5246
|
logger.debug(`Resolved ui package root: ${packageRoot}`);
|
|
5159
5247
|
const manifest = await loadUiPackageManifest(packageRoot);
|
|
5248
|
+
const pkgJson = JSON.parse(
|
|
5249
|
+
await fs18.readFile(path23.join(packageRoot, "package.json"), "utf-8")
|
|
5250
|
+
);
|
|
5251
|
+
manifest.version = pkgJson.version;
|
|
5160
5252
|
let data = {};
|
|
5161
5253
|
const dataPath = path23.join(packageRoot, "_data.json");
|
|
5162
5254
|
try {
|
|
@@ -5233,8 +5325,14 @@ async function installUiEntries(options) {
|
|
|
5233
5325
|
const idToEntry = new Map(manifest.entries.map((e) => [e.id, e]));
|
|
5234
5326
|
const resources = [];
|
|
5235
5327
|
const npmDeps = {};
|
|
5236
|
-
let
|
|
5328
|
+
let created = 0;
|
|
5329
|
+
let overwritten = 0;
|
|
5330
|
+
let userModified = 0;
|
|
5237
5331
|
let skipped = 0;
|
|
5332
|
+
const { priorResources } = options;
|
|
5333
|
+
const priorByTarget = new Map(
|
|
5334
|
+
(priorResources ?? []).map((r) => [r.target, r])
|
|
5335
|
+
);
|
|
5238
5336
|
for (const id of orderedIds) {
|
|
5239
5337
|
const entry = idToEntry.get(id);
|
|
5240
5338
|
if (!entry) continue;
|
|
@@ -5268,11 +5366,25 @@ async function installUiEntries(options) {
|
|
|
5268
5366
|
});
|
|
5269
5367
|
continue;
|
|
5270
5368
|
}
|
|
5369
|
+
const relPath = path24.relative(projectRoot, targetAbs);
|
|
5370
|
+
const prior = priorByTarget.get(relPath);
|
|
5371
|
+
if (prior && prior.hash !== "sha256:legacy-unknown") {
|
|
5372
|
+
const onDiskHash = computeHash(current);
|
|
5373
|
+
if (onDiskHash !== prior.hash) {
|
|
5374
|
+
logger.warn(
|
|
5375
|
+
` \u26A0 ${relPath} has local modifications (backed up)`
|
|
5376
|
+
);
|
|
5377
|
+
userModified++;
|
|
5378
|
+
}
|
|
5379
|
+
}
|
|
5271
5380
|
await backupFile(targetAbs, projectRoot);
|
|
5381
|
+
overwritten++;
|
|
5382
|
+
logger.info(` overwrite: ${rel(projectRoot, targetAbs)}`);
|
|
5383
|
+
} else {
|
|
5384
|
+
created++;
|
|
5385
|
+
logger.info(` create: ${rel(projectRoot, targetAbs)}`);
|
|
5272
5386
|
}
|
|
5273
5387
|
await writeFileSafe(targetAbs, transformed);
|
|
5274
|
-
written++;
|
|
5275
|
-
logger.info(` write: ${rel(projectRoot, targetAbs)}`);
|
|
5276
5388
|
resources.push({
|
|
5277
5389
|
id: `${entry.id}:${file.targetName}`,
|
|
5278
5390
|
target: path24.relative(projectRoot, targetAbs),
|
|
@@ -5285,7 +5397,10 @@ async function installUiEntries(options) {
|
|
|
5285
5397
|
orderedIds,
|
|
5286
5398
|
resources,
|
|
5287
5399
|
npmDependencies: npmDeps,
|
|
5288
|
-
written,
|
|
5400
|
+
written: created + overwritten,
|
|
5401
|
+
created,
|
|
5402
|
+
overwritten,
|
|
5403
|
+
userModified,
|
|
5289
5404
|
skipped
|
|
5290
5405
|
};
|
|
5291
5406
|
}
|
|
@@ -5340,17 +5455,22 @@ async function runUiAdd(options) {
|
|
|
5340
5455
|
`Unknown entry id(s): ${unknown.map((s) => `"${s}"`).join(", ")}. Run \`teamix-evo ui list\` to see options.`
|
|
5341
5456
|
);
|
|
5342
5457
|
}
|
|
5458
|
+
const existingManifest = await readInstalledManifest(
|
|
5459
|
+
projectRoot
|
|
5460
|
+
) ?? { schemaVersion: 1, installed: [] };
|
|
5461
|
+
const priorPkg = existingManifest.installed.find(
|
|
5462
|
+
(p2) => p2.package === packageName
|
|
5463
|
+
);
|
|
5343
5464
|
const result = await installUiEntries({
|
|
5344
5465
|
projectRoot,
|
|
5345
5466
|
manifest: effectiveManifest,
|
|
5346
5467
|
packageRoot,
|
|
5347
5468
|
aliases: uiCfg.aliases,
|
|
5348
5469
|
requested: ids,
|
|
5349
|
-
skipExisting: !overwrite
|
|
5470
|
+
skipExisting: !overwrite,
|
|
5471
|
+
priorResources: priorPkg?.resources
|
|
5350
5472
|
});
|
|
5351
|
-
const installed =
|
|
5352
|
-
projectRoot
|
|
5353
|
-
) ?? { schemaVersion: 1, installed: [] };
|
|
5473
|
+
const installed = existingManifest;
|
|
5354
5474
|
const idx = installed.installed.findIndex((p2) => p2.package === packageName);
|
|
5355
5475
|
const prior = idx >= 0 ? installed.installed[idx] : null;
|
|
5356
5476
|
const mergedResources = mergeResources(
|
|
@@ -5375,6 +5495,9 @@ async function runUiAdd(options) {
|
|
|
5375
5495
|
packageName,
|
|
5376
5496
|
orderedIds: result.orderedIds,
|
|
5377
5497
|
written: result.written,
|
|
5498
|
+
created: result.created,
|
|
5499
|
+
overwritten: result.overwritten,
|
|
5500
|
+
userModified: result.userModified,
|
|
5378
5501
|
skipped: result.skipped,
|
|
5379
5502
|
npmDependencies: result.npmDependencies,
|
|
5380
5503
|
resources: result.resources
|
|
@@ -5738,8 +5861,13 @@ var addCommand2 = new Command22("add").description(
|
|
|
5738
5861
|
logger.warn("meta sync failed (non-fatal)");
|
|
5739
5862
|
}
|
|
5740
5863
|
logger.success(
|
|
5741
|
-
`UI add complete: ${result.
|
|
5864
|
+
`UI add complete: ${result.created} created, ${result.overwritten} updated, ${result.skipped} skipped.`
|
|
5742
5865
|
);
|
|
5866
|
+
if (result.userModified > 0) {
|
|
5867
|
+
logger.warn(
|
|
5868
|
+
`${result.userModified} file(s) had local modifications (backed up to .teamix-evo/.backups/)`
|
|
5869
|
+
);
|
|
5870
|
+
}
|
|
5743
5871
|
logger.info("");
|
|
5744
5872
|
logger.info(`Resolved order: ${result.orderedIds.join(" \u2192 ")}`);
|
|
5745
5873
|
const npmDeps = Object.entries(result.npmDependencies);
|
|
@@ -5900,6 +6028,7 @@ import { Command as Command24 } from "commander";
|
|
|
5900
6028
|
// src/core/ui-upgrade.ts
|
|
5901
6029
|
init_state();
|
|
5902
6030
|
import * as path29 from "path";
|
|
6031
|
+
import * as fs23 from "fs/promises";
|
|
5903
6032
|
import { createRequire as createRequire7 } from "module";
|
|
5904
6033
|
import {
|
|
5905
6034
|
loadUiPackageManifest as loadUiPackageManifest3,
|
|
@@ -6071,6 +6200,9 @@ async function buildUiUpgradeStaging(options) {
|
|
|
6071
6200
|
}
|
|
6072
6201
|
if (entries.length === 0) return null;
|
|
6073
6202
|
const byRisk = aggregateByRisk(entries);
|
|
6203
|
+
const localModifiedCount = entries.filter(
|
|
6204
|
+
(e) => e.current.localModified
|
|
6205
|
+
).length;
|
|
6074
6206
|
const manifestOut = {
|
|
6075
6207
|
schemaVersion: 1,
|
|
6076
6208
|
ts: isoTs,
|
|
@@ -6080,7 +6212,11 @@ async function buildUiUpgradeStaging(options) {
|
|
|
6080
6212
|
fromVersion: lineageReport.installedVersion ?? "",
|
|
6081
6213
|
toVersion: options.manifest.version,
|
|
6082
6214
|
lineage: lineageReport.lineage,
|
|
6083
|
-
summary: {
|
|
6215
|
+
summary: {
|
|
6216
|
+
total: entries.length,
|
|
6217
|
+
byRisk,
|
|
6218
|
+
...localModifiedCount > 0 ? { localModifiedCount } : {}
|
|
6219
|
+
},
|
|
6084
6220
|
entries
|
|
6085
6221
|
};
|
|
6086
6222
|
await ensureDir(stagingDir);
|
|
@@ -6096,6 +6232,8 @@ async function processRegistered(args) {
|
|
|
6096
6232
|
const currentSource = await readFileOrNull(
|
|
6097
6233
|
resolveResourceTarget(projectRoot, resource.target)
|
|
6098
6234
|
);
|
|
6235
|
+
const onDiskHash = currentSource !== null ? computeHash(currentSource) : null;
|
|
6236
|
+
const localModified = onDiskHash !== null && resource.hash !== "sha256:legacy-unknown" && onDiskHash !== resource.hash;
|
|
6099
6237
|
if (currentSource === null) {
|
|
6100
6238
|
return buildBreakingEntry({
|
|
6101
6239
|
id,
|
|
@@ -6141,6 +6279,16 @@ async function processRegistered(args) {
|
|
|
6141
6279
|
incomingSource: incomingTransformed,
|
|
6142
6280
|
multiFile: entry.files.length > 1
|
|
6143
6281
|
});
|
|
6282
|
+
if (localModified && diff.riskLevel !== "unchanged") {
|
|
6283
|
+
if (diff.riskLevel === "upgradable-low") {
|
|
6284
|
+
diff.riskLevel = "upgradable-medium";
|
|
6285
|
+
} else if (diff.riskLevel === "upgradable-medium") {
|
|
6286
|
+
diff.riskLevel = "risky";
|
|
6287
|
+
}
|
|
6288
|
+
diff.hints.push(
|
|
6289
|
+
"\u26A0 file has local modifications since installation \u2014 manual merge recommended"
|
|
6290
|
+
);
|
|
6291
|
+
}
|
|
6144
6292
|
const promotion = derivePromotion({
|
|
6145
6293
|
currentSource,
|
|
6146
6294
|
incomingSource: incomingTransformed,
|
|
@@ -6155,7 +6303,9 @@ async function processRegistered(args) {
|
|
|
6155
6303
|
resolveResourceTarget(projectRoot, resource.target)
|
|
6156
6304
|
),
|
|
6157
6305
|
hash: resource.hash,
|
|
6158
|
-
sourceLineage: "teamix-evo"
|
|
6306
|
+
sourceLineage: "teamix-evo",
|
|
6307
|
+
onDiskHash,
|
|
6308
|
+
localModified
|
|
6159
6309
|
},
|
|
6160
6310
|
incoming: {
|
|
6161
6311
|
sourceVersion: args.sourceVersion,
|
|
@@ -6586,6 +6736,7 @@ async function buildStaging(args) {
|
|
|
6586
6736
|
if (category === "blocks") {
|
|
6587
6737
|
const root = args.blocksPackageRoot ?? resolvePackageRoot4("@teamix-evo/blocks");
|
|
6588
6738
|
const manifest = await loadUiPackageManifest3(root);
|
|
6739
|
+
manifest.version = await readPkgVersion(root);
|
|
6589
6740
|
return buildUiUpgradeStaging({
|
|
6590
6741
|
projectRoot,
|
|
6591
6742
|
category,
|
|
@@ -6600,6 +6751,7 @@ async function buildStaging(args) {
|
|
|
6600
6751
|
if (category === "ui") {
|
|
6601
6752
|
const root = args.uiPackageRoot ?? resolvePackageRoot4("@teamix-evo/ui");
|
|
6602
6753
|
const manifest = await loadUiPackageManifest3(root);
|
|
6754
|
+
manifest.version = await readPkgVersion(root);
|
|
6603
6755
|
return buildUiUpgradeStaging({
|
|
6604
6756
|
projectRoot,
|
|
6605
6757
|
category,
|
|
@@ -6631,7 +6783,7 @@ async function buildStaging(args) {
|
|
|
6631
6783
|
const synthetic = {
|
|
6632
6784
|
schemaVersion: 1,
|
|
6633
6785
|
package: "ui",
|
|
6634
|
-
version:
|
|
6786
|
+
version: await readPkgVersion(bizRoot),
|
|
6635
6787
|
engines: variantManifest.engines,
|
|
6636
6788
|
entries: merged
|
|
6637
6789
|
};
|
|
@@ -6647,6 +6799,13 @@ async function buildStaging(args) {
|
|
|
6647
6799
|
onlyIds
|
|
6648
6800
|
});
|
|
6649
6801
|
}
|
|
6802
|
+
async function readPkgVersion(packageRoot) {
|
|
6803
|
+
const raw = await fs23.readFile(
|
|
6804
|
+
path29.join(packageRoot, "package.json"),
|
|
6805
|
+
"utf-8"
|
|
6806
|
+
);
|
|
6807
|
+
return JSON.parse(raw).version;
|
|
6808
|
+
}
|
|
6650
6809
|
|
|
6651
6810
|
// src/commands/_upgrade-command-factory.ts
|
|
6652
6811
|
init_logger();
|
|
@@ -6687,7 +6846,7 @@ function makeUpgradeCommand(category) {
|
|
|
6687
6846
|
`CLI \u4E0D\u4F1A\u81EA\u52A8\u5199\u5165 ${meta.installDirHint}\uFF08ADR 0019 frozen \u8FB9\u754C\uFF09\u3002`
|
|
6688
6847
|
);
|
|
6689
6848
|
logger.error(
|
|
6690
|
-
`\u8BF7\u8FD0\u884C \`teamix-evo ${category}
|
|
6849
|
+
`\u8BF7\u8FD0\u884C \`teamix-evo ${category} update\` \u751F\u6210 staging\uFF0C\u518D\u8BA9 AI \u8C03\u7528 teamix-evo-manage skill \u9010\u6587\u4EF6\u5E94\u7528\u3002`
|
|
6691
6850
|
);
|
|
6692
6851
|
process.exitCode = 1;
|
|
6693
6852
|
return;
|
|
@@ -6740,6 +6899,11 @@ function makeUpgradeCommand(category) {
|
|
|
6740
6899
|
} catch {
|
|
6741
6900
|
logger.warn(" meta sync failed (non-fatal)");
|
|
6742
6901
|
}
|
|
6902
|
+
if (manifest.summary.localModifiedCount) {
|
|
6903
|
+
logger.warn(
|
|
6904
|
+
` \u26A0 ${manifest.summary.localModifiedCount} file(s) have local modifications \u2014 AI will prompt for manual merge`
|
|
6905
|
+
);
|
|
6906
|
+
}
|
|
6743
6907
|
logger.info("");
|
|
6744
6908
|
logger.info(
|
|
6745
6909
|
"Next: \u8BA9 AI \u8C03\u7528 teamix-evo-manage skill\uFF0C\u6309 risk \u5206\u6279 review & apply\u3002"
|
|
@@ -6765,7 +6929,7 @@ import { Command as Command25 } from "commander";
|
|
|
6765
6929
|
|
|
6766
6930
|
// src/core/ui-promote.ts
|
|
6767
6931
|
init_fs();
|
|
6768
|
-
import * as
|
|
6932
|
+
import * as fs25 from "fs/promises";
|
|
6769
6933
|
import * as path31 from "path";
|
|
6770
6934
|
init_logger();
|
|
6771
6935
|
init_error();
|
|
@@ -6773,7 +6937,7 @@ init_state();
|
|
|
6773
6937
|
|
|
6774
6938
|
// src/core/ui-promote-imports.ts
|
|
6775
6939
|
init_fs();
|
|
6776
|
-
import * as
|
|
6940
|
+
import * as fs24 from "fs/promises";
|
|
6777
6941
|
import * as path30 from "path";
|
|
6778
6942
|
var SOURCE_FILE_EXT = /\.(tsx?|jsx?|mts|cts)$/;
|
|
6779
6943
|
var STATIC_IMPORT_FROM = /^(\s*(?:import|export)\s[\s\S]*?from\s+['"])([^'"\n]+)(['"])/;
|
|
@@ -6880,7 +7044,7 @@ async function collectTsFiles(root) {
|
|
|
6880
7044
|
async function walk(dir) {
|
|
6881
7045
|
let entries;
|
|
6882
7046
|
try {
|
|
6883
|
-
entries = await
|
|
7047
|
+
entries = await fs24.readdir(dir, { withFileTypes: true });
|
|
6884
7048
|
} catch (err) {
|
|
6885
7049
|
if (err.code === "ENOENT") return;
|
|
6886
7050
|
throw err;
|
|
@@ -7285,7 +7449,7 @@ async function findLatestUiStagingDir(projectRoot) {
|
|
|
7285
7449
|
const base = path31.join(projectRoot, TEAMIX_DIR5, STAGING_DIR2);
|
|
7286
7450
|
let entries;
|
|
7287
7451
|
try {
|
|
7288
|
-
entries = await
|
|
7452
|
+
entries = await fs25.readdir(base, { withFileTypes: true });
|
|
7289
7453
|
} catch (err) {
|
|
7290
7454
|
if (err.code === "ENOENT") return null;
|
|
7291
7455
|
throw err;
|
|
@@ -7382,7 +7546,7 @@ function posix2(p2) {
|
|
|
7382
7546
|
}
|
|
7383
7547
|
|
|
7384
7548
|
// src/core/file-changes.ts
|
|
7385
|
-
import * as
|
|
7549
|
+
import * as fs26 from "fs/promises";
|
|
7386
7550
|
import * as path32 from "path";
|
|
7387
7551
|
function toRelativePosix(p2, projectRoot) {
|
|
7388
7552
|
let rel2 = p2;
|
|
@@ -7574,6 +7738,7 @@ import { Command as Command27 } from "commander";
|
|
|
7574
7738
|
|
|
7575
7739
|
// src/core/variant-ui-add.ts
|
|
7576
7740
|
import * as path33 from "path";
|
|
7741
|
+
import * as fs27 from "fs/promises";
|
|
7577
7742
|
import { createRequire as createRequire8 } from "module";
|
|
7578
7743
|
import {
|
|
7579
7744
|
loadUiPackageManifest as loadUiPackageManifest4,
|
|
@@ -7609,6 +7774,10 @@ async function runVariantUiAdd(packageName, options) {
|
|
|
7609
7774
|
}
|
|
7610
7775
|
const variantDir = path33.join(packageRoot, "variants", variant);
|
|
7611
7776
|
const variantManifest = await loadVariantUiPackageManifest3(variantDir);
|
|
7777
|
+
const pkgJson = JSON.parse(
|
|
7778
|
+
await fs27.readFile(path33.join(packageRoot, "package.json"), "utf-8")
|
|
7779
|
+
);
|
|
7780
|
+
const packageVersion = pkgJson.version;
|
|
7612
7781
|
const knownIds = new Set(variantManifest.entries.map((e) => e.id));
|
|
7613
7782
|
const unknown = ids.filter((id) => !knownIds.has(id));
|
|
7614
7783
|
if (unknown.length > 0) {
|
|
@@ -7632,28 +7801,27 @@ async function runVariantUiAdd(packageName, options) {
|
|
|
7632
7801
|
const adaptedManifest = {
|
|
7633
7802
|
schemaVersion: 1,
|
|
7634
7803
|
package: "ui",
|
|
7635
|
-
version:
|
|
7804
|
+
version: packageVersion,
|
|
7636
7805
|
engines: variantManifest.engines,
|
|
7637
7806
|
entries: mergedEntries
|
|
7638
7807
|
};
|
|
7808
|
+
const installed = await readInstalledManifest(
|
|
7809
|
+
projectRoot
|
|
7810
|
+
) ?? { schemaVersion: 1, installed: [] };
|
|
7811
|
+
const idx = installed.installed.findIndex(
|
|
7812
|
+
(p2) => p2.package === fullPackageName && p2.variant === variant
|
|
7813
|
+
);
|
|
7814
|
+
const prior = idx >= 0 ? installed.installed[idx] : null;
|
|
7639
7815
|
const result = await installUiEntries({
|
|
7640
7816
|
projectRoot,
|
|
7641
7817
|
manifest: adaptedManifest,
|
|
7642
7818
|
packageRoot: variantDir,
|
|
7643
|
-
// default for variant entries
|
|
7644
7819
|
entryPackageRoot,
|
|
7645
|
-
// ui entries resolve from uiPackageRoot
|
|
7646
7820
|
aliases: uiCfg.aliases,
|
|
7647
7821
|
requested: ids,
|
|
7648
|
-
skipExisting: !overwrite
|
|
7822
|
+
skipExisting: !overwrite,
|
|
7823
|
+
priorResources: prior?.resources
|
|
7649
7824
|
});
|
|
7650
|
-
const installed = await readInstalledManifest(
|
|
7651
|
-
projectRoot
|
|
7652
|
-
) ?? { schemaVersion: 1, installed: [] };
|
|
7653
|
-
const idx = installed.installed.findIndex(
|
|
7654
|
-
(p2) => p2.package === fullPackageName && p2.variant === variant
|
|
7655
|
-
);
|
|
7656
|
-
const prior = idx >= 0 ? installed.installed[idx] : null;
|
|
7657
7825
|
const mergedResources = mergeResources3(
|
|
7658
7826
|
prior?.resources ?? [],
|
|
7659
7827
|
result.resources
|
|
@@ -7661,7 +7829,7 @@ async function runVariantUiAdd(packageName, options) {
|
|
|
7661
7829
|
const entry = {
|
|
7662
7830
|
package: fullPackageName,
|
|
7663
7831
|
variant,
|
|
7664
|
-
version:
|
|
7832
|
+
version: packageVersion,
|
|
7665
7833
|
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7666
7834
|
resources: mergedResources
|
|
7667
7835
|
};
|
|
@@ -7673,6 +7841,9 @@ async function runVariantUiAdd(packageName, options) {
|
|
|
7673
7841
|
variant,
|
|
7674
7842
|
orderedIds: result.orderedIds,
|
|
7675
7843
|
written: result.written,
|
|
7844
|
+
created: result.created,
|
|
7845
|
+
overwritten: result.overwritten,
|
|
7846
|
+
userModified: result.userModified,
|
|
7676
7847
|
skipped: result.skipped,
|
|
7677
7848
|
npmDependencies: result.npmDependencies,
|
|
7678
7849
|
resources: result.resources
|
|
@@ -7772,8 +7943,13 @@ var addCommand3 = new Command27("add").description(
|
|
|
7772
7943
|
logger.warn("meta sync failed (non-fatal)");
|
|
7773
7944
|
}
|
|
7774
7945
|
logger.success(
|
|
7775
|
-
`biz-ui add complete: ${result.
|
|
7946
|
+
`biz-ui add complete: ${result.created} created, ${result.overwritten} updated, ${result.skipped} skipped.`
|
|
7776
7947
|
);
|
|
7948
|
+
if (result.userModified > 0) {
|
|
7949
|
+
logger.warn(
|
|
7950
|
+
`${result.userModified} file(s) had local modifications (backed up to .teamix-evo/.backups/)`
|
|
7951
|
+
);
|
|
7952
|
+
}
|
|
7777
7953
|
logger.info("");
|
|
7778
7954
|
logger.info(`Variant: ${result.variant}`);
|
|
7779
7955
|
logger.info(`Resolved order: ${result.orderedIds.join(" \u2192 ")}`);
|
|
@@ -7889,6 +8065,11 @@ async function runBlocksAdd(options) {
|
|
|
7889
8065
|
`Unknown block id(s): ${unknown.map((s) => `"${s}"`).join(", ")}. Run \`teamix-evo blocks list\` to see options.`
|
|
7890
8066
|
);
|
|
7891
8067
|
}
|
|
8068
|
+
const installed = await readInstalledManifest(
|
|
8069
|
+
projectRoot
|
|
8070
|
+
) ?? { schemaVersion: 1, installed: [] };
|
|
8071
|
+
const idx = installed.installed.findIndex((p2) => p2.package === packageName);
|
|
8072
|
+
const prior = idx >= 0 ? installed.installed[idx] : null;
|
|
7892
8073
|
const result = await installUiEntries({
|
|
7893
8074
|
projectRoot,
|
|
7894
8075
|
manifest,
|
|
@@ -7896,13 +8077,9 @@ async function runBlocksAdd(options) {
|
|
|
7896
8077
|
aliases: uiCfg.aliases,
|
|
7897
8078
|
requested: ids,
|
|
7898
8079
|
skipExisting: !overwrite,
|
|
7899
|
-
flatten: false
|
|
8080
|
+
flatten: false,
|
|
8081
|
+
priorResources: prior?.resources
|
|
7900
8082
|
});
|
|
7901
|
-
const installed = await readInstalledManifest(
|
|
7902
|
-
projectRoot
|
|
7903
|
-
) ?? { schemaVersion: 1, installed: [] };
|
|
7904
|
-
const idx = installed.installed.findIndex((p2) => p2.package === packageName);
|
|
7905
|
-
const prior = idx >= 0 ? installed.installed[idx] : null;
|
|
7906
8083
|
const mergedResources = mergeResources4(
|
|
7907
8084
|
prior?.resources ?? [],
|
|
7908
8085
|
result.resources
|
|
@@ -7921,6 +8098,9 @@ async function runBlocksAdd(options) {
|
|
|
7921
8098
|
packageName,
|
|
7922
8099
|
orderedIds: result.orderedIds,
|
|
7923
8100
|
written: result.written,
|
|
8101
|
+
created: result.created,
|
|
8102
|
+
overwritten: result.overwritten,
|
|
8103
|
+
userModified: result.userModified,
|
|
7924
8104
|
skipped: result.skipped,
|
|
7925
8105
|
npmDependencies: result.npmDependencies,
|
|
7926
8106
|
resources: result.resources
|
|
@@ -7948,8 +8128,13 @@ var addCommand4 = new Command31("add").description("\u5B89\u88C5\u4E00\u4E2A\u62
|
|
|
7948
8128
|
overwrite: opts.overwrite
|
|
7949
8129
|
});
|
|
7950
8130
|
logger.success(
|
|
7951
|
-
`Blocks add complete: ${result.
|
|
8131
|
+
`Blocks add complete: ${result.created} created, ${result.overwritten} updated, ${result.skipped} skipped.`
|
|
7952
8132
|
);
|
|
8133
|
+
if (result.userModified > 0) {
|
|
8134
|
+
logger.warn(
|
|
8135
|
+
`${result.userModified} file(s) had local modifications (backed up to .teamix-evo/.backups/)`
|
|
8136
|
+
);
|
|
8137
|
+
}
|
|
7953
8138
|
logger.info("");
|
|
7954
8139
|
logger.info(`Resolved order: ${result.orderedIds.join(" \u2192 ")}`);
|
|
7955
8140
|
const npmDeps = Object.entries(result.npmDependencies);
|
|
@@ -8047,7 +8232,7 @@ import * as prompts6 from "@clack/prompts";
|
|
|
8047
8232
|
init_fs();
|
|
8048
8233
|
init_logger();
|
|
8049
8234
|
import * as path34 from "path";
|
|
8050
|
-
import * as
|
|
8235
|
+
import * as fs28 from "fs";
|
|
8051
8236
|
import { execa } from "execa";
|
|
8052
8237
|
var ESLINT_CONFIG_CONTENT = `/**
|
|
8053
8238
|
* teamix-evo consumer ESLint preset \u2014 9 token-discipline rules.
|
|
@@ -8139,7 +8324,7 @@ async function runLintInit(options) {
|
|
|
8139
8324
|
let stylelintIgnoreFilesWarning = false;
|
|
8140
8325
|
if (!stylelintNeedsWrite && stylelintTemplateExists) {
|
|
8141
8326
|
try {
|
|
8142
|
-
const existingContent =
|
|
8327
|
+
const existingContent = fs28.readFileSync(stylelintConfigPath, "utf-8");
|
|
8143
8328
|
const usesTeamixPreset = existingContent.includes("@teamix-evo/stylelint-config/presets/") || existingContent.includes("@teamix-evo/stylelint-config/preset/");
|
|
8144
8329
|
const hasTokenIgnore = existingContent.includes("tokens.theme.css") && existingContent.includes("tokens.overrides.css");
|
|
8145
8330
|
if (!usesTeamixPreset && !hasTokenIgnore) {
|
|
@@ -8176,8 +8361,8 @@ async function runLintInit(options) {
|
|
|
8176
8361
|
};
|
|
8177
8362
|
}
|
|
8178
8363
|
function detectPm(projectRoot) {
|
|
8179
|
-
if (
|
|
8180
|
-
if (
|
|
8364
|
+
if (fs28.existsSync(path34.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
8365
|
+
if (fs28.existsSync(path34.join(projectRoot, "yarn.lock"))) return "yarn";
|
|
8181
8366
|
return "npm";
|
|
8182
8367
|
}
|
|
8183
8368
|
async function patchPackageJsonScripts(projectRoot) {
|
|
@@ -8273,7 +8458,7 @@ import { execa as execa2 } from "execa";
|
|
|
8273
8458
|
// src/core/project-state.ts
|
|
8274
8459
|
init_fs();
|
|
8275
8460
|
init_state();
|
|
8276
|
-
import * as
|
|
8461
|
+
import * as fs29 from "fs/promises";
|
|
8277
8462
|
import * as path35 from "path";
|
|
8278
8463
|
var IGNORED_TOP_LEVEL = /* @__PURE__ */ new Set([
|
|
8279
8464
|
".git",
|
|
@@ -8333,7 +8518,7 @@ async function detectProjectState(cwd) {
|
|
|
8333
8518
|
}
|
|
8334
8519
|
let entries;
|
|
8335
8520
|
try {
|
|
8336
|
-
entries = await
|
|
8521
|
+
entries = await fs29.readdir(absCwd);
|
|
8337
8522
|
} catch (err) {
|
|
8338
8523
|
if (err.code === "ENOENT") {
|
|
8339
8524
|
return {
|
|
@@ -8418,7 +8603,7 @@ function assertCommandPrecondition(command, state) {
|
|
|
8418
8603
|
// src/core/deps-install.ts
|
|
8419
8604
|
init_fs();
|
|
8420
8605
|
init_logger();
|
|
8421
|
-
import * as
|
|
8606
|
+
import * as fs30 from "fs/promises";
|
|
8422
8607
|
import * as path36 from "path";
|
|
8423
8608
|
import { exec as exec4 } from "child_process";
|
|
8424
8609
|
import { promisify as promisify4 } from "util";
|
|
@@ -8475,7 +8660,7 @@ async function installProjectDeps(options) {
|
|
|
8475
8660
|
pkg.dependencies = Object.fromEntries(
|
|
8476
8661
|
Object.entries(pkg.dependencies).sort(([a], [b]) => a.localeCompare(b))
|
|
8477
8662
|
);
|
|
8478
|
-
await
|
|
8663
|
+
await fs30.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
8479
8664
|
logger.info(
|
|
8480
8665
|
` patched package.json: +${Object.keys(added).length} dependencies`
|
|
8481
8666
|
);
|
|
@@ -8657,6 +8842,7 @@ async function runProjectInit(options) {
|
|
|
8657
8842
|
`teamix-evo-design-${variant}`,
|
|
8658
8843
|
`teamix-evo-code-${variant}`
|
|
8659
8844
|
],
|
|
8845
|
+
globalSkillIds: ["teamix-evo-manage"],
|
|
8660
8846
|
mode: "merge-managed"
|
|
8661
8847
|
});
|
|
8662
8848
|
record({
|
|
@@ -9443,7 +9629,7 @@ import * as prompts7 from "@clack/prompts";
|
|
|
9443
9629
|
|
|
9444
9630
|
// src/core/snapshot.ts
|
|
9445
9631
|
init_logger();
|
|
9446
|
-
import * as
|
|
9632
|
+
import * as fs31 from "fs/promises";
|
|
9447
9633
|
import * as path42 from "path";
|
|
9448
9634
|
var TEAMIX_DIR6 = ".teamix-evo";
|
|
9449
9635
|
var SNAPSHOTS_DIR = ".snapshots";
|
|
@@ -9461,7 +9647,7 @@ function fsSafeToIso(safe) {
|
|
|
9461
9647
|
async function createSnapshot(projectRoot, opts = {}) {
|
|
9462
9648
|
const teamixDir = path42.join(projectRoot, TEAMIX_DIR6);
|
|
9463
9649
|
try {
|
|
9464
|
-
const stat5 = await
|
|
9650
|
+
const stat5 = await fs31.stat(teamixDir);
|
|
9465
9651
|
if (!stat5.isDirectory()) return null;
|
|
9466
9652
|
} catch (err) {
|
|
9467
9653
|
if (err.code === "ENOENT") return null;
|
|
@@ -9471,19 +9657,19 @@ async function createSnapshot(projectRoot, opts = {}) {
|
|
|
9471
9657
|
const ts = isoToFsSafe3(isoTs);
|
|
9472
9658
|
const snapshotRoot = path42.join(teamixDir, SNAPSHOTS_DIR);
|
|
9473
9659
|
const target = path42.join(snapshotRoot, ts);
|
|
9474
|
-
await
|
|
9475
|
-
const entries = await
|
|
9660
|
+
await fs31.mkdir(target, { recursive: true });
|
|
9661
|
+
const entries = await fs31.readdir(teamixDir, { withFileTypes: true });
|
|
9476
9662
|
for (const entry of entries) {
|
|
9477
9663
|
if (entry.name === SNAPSHOTS_DIR) continue;
|
|
9478
9664
|
const src = path42.join(teamixDir, entry.name);
|
|
9479
9665
|
const dst = path42.join(target, entry.name);
|
|
9480
|
-
await
|
|
9666
|
+
await fs31.cp(src, dst, { recursive: true });
|
|
9481
9667
|
}
|
|
9482
9668
|
const meta = {
|
|
9483
9669
|
ts: isoTs,
|
|
9484
9670
|
reason: opts.reason ?? "manual"
|
|
9485
9671
|
};
|
|
9486
|
-
await
|
|
9672
|
+
await fs31.writeFile(
|
|
9487
9673
|
path42.join(target, META_FILE),
|
|
9488
9674
|
JSON.stringify(meta, null, 2) + "\n",
|
|
9489
9675
|
"utf-8"
|
|
@@ -9499,7 +9685,7 @@ async function listSnapshots(projectRoot) {
|
|
|
9499
9685
|
const snapshotRoot = path42.join(projectRoot, TEAMIX_DIR6, SNAPSHOTS_DIR);
|
|
9500
9686
|
let entries;
|
|
9501
9687
|
try {
|
|
9502
|
-
entries = await
|
|
9688
|
+
entries = await fs31.readdir(snapshotRoot, { withFileTypes: true });
|
|
9503
9689
|
} catch (err) {
|
|
9504
9690
|
if (err.code === "ENOENT") return [];
|
|
9505
9691
|
throw err;
|
|
@@ -9511,7 +9697,7 @@ async function listSnapshots(projectRoot) {
|
|
|
9511
9697
|
let isoTs = null;
|
|
9512
9698
|
let reason = null;
|
|
9513
9699
|
try {
|
|
9514
|
-
const raw = await
|
|
9700
|
+
const raw = await fs31.readFile(path42.join(dir, META_FILE), "utf-8");
|
|
9515
9701
|
const parsed = JSON.parse(raw);
|
|
9516
9702
|
if (typeof parsed.ts === "string") isoTs = parsed.ts;
|
|
9517
9703
|
if (typeof parsed.reason === "string" && ["init", "update", "switch", "restore", "manual"].includes(
|
|
@@ -9536,7 +9722,7 @@ async function pruneSnapshots(projectRoot, keep = DEFAULT_KEEP, opts = {}) {
|
|
|
9536
9722
|
const toRemove = opts.protectedTs ? tail.filter((s) => s.ts !== opts.protectedTs) : tail;
|
|
9537
9723
|
const removed = [];
|
|
9538
9724
|
for (const snap of toRemove) {
|
|
9539
|
-
await
|
|
9725
|
+
await fs31.rm(snap.path, { recursive: true, force: true });
|
|
9540
9726
|
removed.push(snap.ts);
|
|
9541
9727
|
logger.debug(`Pruned snapshot ${snap.ts}`);
|
|
9542
9728
|
}
|
|
@@ -9546,7 +9732,7 @@ async function restoreSnapshot(projectRoot, ts) {
|
|
|
9546
9732
|
const snapshotRoot = path42.join(projectRoot, TEAMIX_DIR6, SNAPSHOTS_DIR);
|
|
9547
9733
|
const target = path42.join(snapshotRoot, ts);
|
|
9548
9734
|
try {
|
|
9549
|
-
const stat5 = await
|
|
9735
|
+
const stat5 = await fs31.stat(target);
|
|
9550
9736
|
if (!stat5.isDirectory()) {
|
|
9551
9737
|
throw new Error(`Snapshot path is not a directory: ${target}`);
|
|
9552
9738
|
}
|
|
@@ -9560,20 +9746,20 @@ async function restoreSnapshot(projectRoot, ts) {
|
|
|
9560
9746
|
}
|
|
9561
9747
|
await createSnapshot(projectRoot, { reason: "restore", protectedTs: ts });
|
|
9562
9748
|
const teamixDir = path42.join(projectRoot, TEAMIX_DIR6);
|
|
9563
|
-
const live = await
|
|
9749
|
+
const live = await fs31.readdir(teamixDir, { withFileTypes: true });
|
|
9564
9750
|
for (const entry of live) {
|
|
9565
9751
|
if (entry.name === SNAPSHOTS_DIR) continue;
|
|
9566
|
-
await
|
|
9752
|
+
await fs31.rm(path42.join(teamixDir, entry.name), {
|
|
9567
9753
|
recursive: true,
|
|
9568
9754
|
force: true
|
|
9569
9755
|
});
|
|
9570
9756
|
}
|
|
9571
|
-
const snapshotEntries = await
|
|
9757
|
+
const snapshotEntries = await fs31.readdir(target, { withFileTypes: true });
|
|
9572
9758
|
for (const entry of snapshotEntries) {
|
|
9573
9759
|
if (entry.name === META_FILE) continue;
|
|
9574
9760
|
const src = path42.join(target, entry.name);
|
|
9575
9761
|
const dst = path42.join(teamixDir, entry.name);
|
|
9576
|
-
await
|
|
9762
|
+
await fs31.cp(src, dst, { recursive: true });
|
|
9577
9763
|
}
|
|
9578
9764
|
logger.debug(`Restored .teamix-evo/ from snapshot ${ts}`);
|
|
9579
9765
|
}
|
|
@@ -9688,7 +9874,7 @@ import * as prompts8 from "@clack/prompts";
|
|
|
9688
9874
|
// src/core/variant-switch.ts
|
|
9689
9875
|
init_fs();
|
|
9690
9876
|
import * as path44 from "path";
|
|
9691
|
-
import * as
|
|
9877
|
+
import * as fs32 from "fs/promises";
|
|
9692
9878
|
import {
|
|
9693
9879
|
loadTokensPackageManifest as loadTokensPackageManifest3,
|
|
9694
9880
|
getVariantEntry as getVariantEntry3
|
|
@@ -9761,7 +9947,7 @@ async function runVariantSwitch(options) {
|
|
|
9761
9947
|
});
|
|
9762
9948
|
continue;
|
|
9763
9949
|
}
|
|
9764
|
-
const upstreamContent = await
|
|
9950
|
+
const upstreamContent = await fs32.readFile(upstreamAbs, "utf-8");
|
|
9765
9951
|
if (resource.strategy === "regenerable") {
|
|
9766
9952
|
const newHash = computeHash(upstreamContent);
|
|
9767
9953
|
if (newHash === resource.hash) {
|
|
@@ -9819,7 +10005,7 @@ async function runVariantSwitch(options) {
|
|
|
9819
10005
|
const upstreamBasename = lookupUpstreamBasename2(consumerBasename);
|
|
9820
10006
|
const upstreamAbs = upstreamBasename ? upstreamByBasename.get(upstreamBasename) : void 0;
|
|
9821
10007
|
if (resource.strategy === "regenerable" && upstreamAbs) {
|
|
9822
|
-
const upstreamContent = await
|
|
10008
|
+
const upstreamContent = await fs32.readFile(upstreamAbs, "utf-8");
|
|
9823
10009
|
await writeFileSafe(consumerAbs, upstreamContent);
|
|
9824
10010
|
logger.debug(`[variant-switch] rewrite regenerable: ${resource.target}`);
|
|
9825
10011
|
refreshedResources.push({
|
|
@@ -9829,8 +10015,8 @@ async function runVariantSwitch(options) {
|
|
|
9829
10015
|
continue;
|
|
9830
10016
|
}
|
|
9831
10017
|
if (resource.strategy === "managed" && upstreamAbs && await fileExists(consumerAbs)) {
|
|
9832
|
-
const upstreamContent = await
|
|
9833
|
-
const consumerContent = await
|
|
10018
|
+
const upstreamContent = await fs32.readFile(upstreamAbs, "utf-8");
|
|
10019
|
+
const consumerContent = await fs32.readFile(consumerAbs, "utf-8");
|
|
9834
10020
|
const merged = mergeManagedRegions(upstreamContent, consumerContent);
|
|
9835
10021
|
if (merged !== consumerContent) {
|
|
9836
10022
|
await writeFileSafe(consumerAbs, merged);
|
|
@@ -9927,10 +10113,12 @@ async function runVariantSwitch(options) {
|
|
|
9927
10113
|
const lock2 = await readSkillsLock(projectRoot);
|
|
9928
10114
|
if (lock2) {
|
|
9929
10115
|
const projectSkillIds = Object.entries(lock2.skills).filter(([, v]) => v.scope === "project").map(([id]) => id);
|
|
10116
|
+
const globalSkillIds = Object.entries(lock2.skills).filter(([, v]) => v.scope === "global").map(([id]) => id);
|
|
9930
10117
|
await runGenerateAgentsMd({
|
|
9931
10118
|
projectRoot,
|
|
9932
10119
|
variant: newVariant,
|
|
9933
10120
|
skillIds: projectSkillIds,
|
|
10121
|
+
globalSkillIds,
|
|
9934
10122
|
mode: "merge-managed"
|
|
9935
10123
|
});
|
|
9936
10124
|
}
|