macca-method 2.1.2 → 2.1.3
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/.agents/macca-lock.json +1 -1
- package/bin/macca-method.js +63 -20
- package/package.json +1 -1
- package/scripts/test-install.js +3 -2
package/.agents/macca-lock.json
CHANGED
package/bin/macca-method.js
CHANGED
|
@@ -164,6 +164,11 @@ function parseArgs(argv) {
|
|
|
164
164
|
continue;
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
if (token === "-f" || token === "--force") {
|
|
168
|
+
args.force = true;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
|
|
167
172
|
if (token === "--list-tools") {
|
|
168
173
|
args.listTools = true;
|
|
169
174
|
continue;
|
|
@@ -292,6 +297,7 @@ function printHelp() {
|
|
|
292
297
|
" -t, --tool <name> Repeatable. Also accepts comma-separated values.",
|
|
293
298
|
" -d, --directory <path> Target project directory. Defaults to the current directory.",
|
|
294
299
|
" -y, --yes Skip prompts and use defaults where needed.",
|
|
300
|
+
" -f, --force Overwrite locally modified managed skills.",
|
|
295
301
|
" --name <value> Developer name.",
|
|
296
302
|
" --project <value> Project name.",
|
|
297
303
|
" --communication-language <value>",
|
|
@@ -493,13 +499,37 @@ function hashText(content) {
|
|
|
493
499
|
return crypto.createHash("sha256").update(content).digest("hex");
|
|
494
500
|
}
|
|
495
501
|
|
|
502
|
+
const IGNORED_DIRECTORY_NAMES = new Set([
|
|
503
|
+
OWNERSHIP_MARKER,
|
|
504
|
+
".DS_Store",
|
|
505
|
+
"Thumbs.db",
|
|
506
|
+
"__pycache__",
|
|
507
|
+
".pytest_cache",
|
|
508
|
+
".ruff_cache",
|
|
509
|
+
]);
|
|
510
|
+
|
|
511
|
+
function shouldIgnoreDirectoryEntry(name) {
|
|
512
|
+
if (IGNORED_DIRECTORY_NAMES.has(name)) {
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
if (
|
|
516
|
+
name.endsWith(".pyc") ||
|
|
517
|
+
name.endsWith(".pyo") ||
|
|
518
|
+
name.endsWith(".tmp") ||
|
|
519
|
+
name.startsWith(".tmp-")
|
|
520
|
+
) {
|
|
521
|
+
return true;
|
|
522
|
+
}
|
|
523
|
+
return false;
|
|
524
|
+
}
|
|
525
|
+
|
|
496
526
|
function getDirectoryFileHashes(directoryPath) {
|
|
497
527
|
const hashes = {};
|
|
498
528
|
|
|
499
529
|
function walk(currentPath, relativePath = "") {
|
|
500
530
|
const entries = fs
|
|
501
531
|
.readdirSync(currentPath, { withFileTypes: true })
|
|
502
|
-
.filter((entry) => entry.name
|
|
532
|
+
.filter((entry) => !shouldIgnoreDirectoryEntry(entry.name))
|
|
503
533
|
.sort((left, right) => left.name.localeCompare(right.name));
|
|
504
534
|
|
|
505
535
|
for (const entry of entries) {
|
|
@@ -648,7 +678,10 @@ function isMaccaOwned(targetPath) {
|
|
|
648
678
|
return readOwnershipMarker(targetPath) !== null;
|
|
649
679
|
}
|
|
650
680
|
|
|
651
|
-
function assertManagedDirectoryUnchanged(targetPath) {
|
|
681
|
+
function assertManagedDirectoryUnchanged(targetPath, force = false) {
|
|
682
|
+
if (force) {
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
652
685
|
const marker = readOwnershipMarker(targetPath);
|
|
653
686
|
if (!marker) {
|
|
654
687
|
throw new Error(
|
|
@@ -657,7 +690,8 @@ function assertManagedDirectoryUnchanged(targetPath) {
|
|
|
657
690
|
}
|
|
658
691
|
if (!marker.payloadHash || marker.payloadHash !== hashDirectory(targetPath)) {
|
|
659
692
|
throw new Error(
|
|
660
|
-
`Refusing to overwrite locally modified managed skill: ${targetPath}
|
|
693
|
+
`Refusing to overwrite locally modified managed skill: ${targetPath}. ` +
|
|
694
|
+
"Run upgrade with --force to overwrite local modifications.",
|
|
661
695
|
);
|
|
662
696
|
}
|
|
663
697
|
}
|
|
@@ -674,7 +708,10 @@ function readJsonObject(filePath, label) {
|
|
|
674
708
|
}
|
|
675
709
|
}
|
|
676
710
|
|
|
677
|
-
function assertManagedFilesUnchanged(agentsDirectory) {
|
|
711
|
+
function assertManagedFilesUnchanged(agentsDirectory, force = false) {
|
|
712
|
+
if (force) {
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
678
715
|
const statePath = path.join(agentsDirectory, STATE_FILE);
|
|
679
716
|
if (!fs.existsSync(statePath)) {
|
|
680
717
|
return;
|
|
@@ -684,7 +721,8 @@ function assertManagedFilesUnchanged(agentsDirectory) {
|
|
|
684
721
|
const filePath = path.join(agentsDirectory, fileName);
|
|
685
722
|
if (!fs.existsSync(filePath) || hashFile(filePath) !== expectedHash) {
|
|
686
723
|
throw new Error(
|
|
687
|
-
`Refusing to overwrite locally modified MACCA metadata: ${filePath}
|
|
724
|
+
`Refusing to overwrite locally modified MACCA metadata: ${filePath}. ` +
|
|
725
|
+
"Run upgrade with --force to overwrite local modifications.",
|
|
688
726
|
);
|
|
689
727
|
}
|
|
690
728
|
}
|
|
@@ -938,7 +976,7 @@ function getUniqueDestinations(targetDir, tools) {
|
|
|
938
976
|
return [...destinations.values()];
|
|
939
977
|
}
|
|
940
978
|
|
|
941
|
-
function applySkillTransaction(entries, targetDir) {
|
|
979
|
+
function applySkillTransaction(entries, targetDir, force = false) {
|
|
942
980
|
const suffix = `${process.pid}-${Date.now()}-${crypto.randomBytes(8).toString("hex")}`;
|
|
943
981
|
const prepared = [];
|
|
944
982
|
const committed = [];
|
|
@@ -971,7 +1009,7 @@ function applySkillTransaction(entries, targetDir) {
|
|
|
971
1009
|
}
|
|
972
1010
|
if (kind === "directory") {
|
|
973
1011
|
if (isMaccaOwned(targetPath)) {
|
|
974
|
-
assertManagedDirectoryUnchanged(targetPath);
|
|
1012
|
+
assertManagedDirectoryUnchanged(targetPath, force);
|
|
975
1013
|
} else if (
|
|
976
1014
|
!legacySkillName ||
|
|
977
1015
|
!isLegacyDirectoryUnchanged(targetPath, legacySkillName)
|
|
@@ -1329,7 +1367,8 @@ async function promptForMetadata(seed) {
|
|
|
1329
1367
|
}
|
|
1330
1368
|
}
|
|
1331
1369
|
|
|
1332
|
-
function applyInstall(targetDir, tools, metadata) {
|
|
1370
|
+
function applyInstall(targetDir, tools, metadata, options = {}) {
|
|
1371
|
+
const force = Boolean(options.force);
|
|
1333
1372
|
const managedSkills = getSourceManagedSkills();
|
|
1334
1373
|
const agentsDirectory = path.join(targetDir, ".agents");
|
|
1335
1374
|
ensureDirectory(targetDir);
|
|
@@ -1344,7 +1383,7 @@ function applyInstall(targetDir, tools, metadata) {
|
|
|
1344
1383
|
]) {
|
|
1345
1384
|
assertSafeProjectPath(targetDir, path.join(agentsDirectory, fileName));
|
|
1346
1385
|
}
|
|
1347
|
-
assertManagedFilesUnchanged(agentsDirectory);
|
|
1386
|
+
assertManagedFilesUnchanged(agentsDirectory, force);
|
|
1348
1387
|
const previousManagedSkills = validateManagedSkillNames(
|
|
1349
1388
|
readNonEmptyLines(path.join(agentsDirectory, "macca-managed-skills.txt")),
|
|
1350
1389
|
".agents/macca-managed-skills.txt",
|
|
@@ -1401,10 +1440,11 @@ function applyInstall(targetDir, tools, metadata) {
|
|
|
1401
1440
|
targetPath: path.join(agentsDirectory, STATE_FILE),
|
|
1402
1441
|
},
|
|
1403
1442
|
);
|
|
1404
|
-
applySkillTransaction(entries, targetDir);
|
|
1443
|
+
applySkillTransaction(entries, targetDir, force);
|
|
1405
1444
|
}
|
|
1406
1445
|
|
|
1407
|
-
function applyUpgrade(targetDir) {
|
|
1446
|
+
function applyUpgrade(targetDir, options = {}) {
|
|
1447
|
+
const force = Boolean(options.force);
|
|
1408
1448
|
const agentsDirectory = path.join(targetDir, ".agents");
|
|
1409
1449
|
assertSafeProjectPath(targetDir, agentsDirectory);
|
|
1410
1450
|
assertPackageNotOlderThanInstalled(agentsDirectory);
|
|
@@ -1417,7 +1457,7 @@ function applyUpgrade(targetDir) {
|
|
|
1417
1457
|
]) {
|
|
1418
1458
|
assertSafeProjectPath(targetDir, path.join(agentsDirectory, fileName));
|
|
1419
1459
|
}
|
|
1420
|
-
assertManagedFilesUnchanged(agentsDirectory);
|
|
1460
|
+
assertManagedFilesUnchanged(agentsDirectory, force);
|
|
1421
1461
|
const tools = readNonEmptyLines(
|
|
1422
1462
|
path.join(agentsDirectory, "macca-tools.txt"),
|
|
1423
1463
|
);
|
|
@@ -1447,7 +1487,7 @@ function applyUpgrade(targetDir) {
|
|
|
1447
1487
|
)) {
|
|
1448
1488
|
const oldPath = resolveOwnedSkillPath(destination, skillName);
|
|
1449
1489
|
if (fs.existsSync(oldPath) && isMaccaOwned(oldPath)) {
|
|
1450
|
-
assertManagedDirectoryUnchanged(oldPath);
|
|
1490
|
+
assertManagedDirectoryUnchanged(oldPath, force);
|
|
1451
1491
|
entries.push({ sourcePath: null, targetPath: oldPath });
|
|
1452
1492
|
} else if (isLegacyDirectoryUnchanged(oldPath, skillName)) {
|
|
1453
1493
|
entries.push({
|
|
@@ -1469,7 +1509,7 @@ function applyUpgrade(targetDir) {
|
|
|
1469
1509
|
for (const skillName of previousManagedSkills) {
|
|
1470
1510
|
const oldPath = resolveOwnedSkillPath(legacyOpenCodeRoot, skillName);
|
|
1471
1511
|
if (fs.existsSync(oldPath) && isMaccaOwned(oldPath)) {
|
|
1472
|
-
assertManagedDirectoryUnchanged(oldPath);
|
|
1512
|
+
assertManagedDirectoryUnchanged(oldPath, force);
|
|
1473
1513
|
entries.push({ sourcePath: null, targetPath: oldPath });
|
|
1474
1514
|
} else if (isLegacyDirectoryUnchanged(oldPath, skillName)) {
|
|
1475
1515
|
entries.push({
|
|
@@ -1478,9 +1518,12 @@ function applyUpgrade(targetDir) {
|
|
|
1478
1518
|
legacySkillName: skillName,
|
|
1479
1519
|
});
|
|
1480
1520
|
} else if (fs.existsSync(oldPath)) {
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1521
|
+
if (!force) {
|
|
1522
|
+
throw new Error(
|
|
1523
|
+
`Legacy OpenCode skill was modified; move or back it up before upgrade: ${oldPath}. ` +
|
|
1524
|
+
"Run upgrade with --force to overwrite local modifications.",
|
|
1525
|
+
);
|
|
1526
|
+
}
|
|
1484
1527
|
}
|
|
1485
1528
|
}
|
|
1486
1529
|
}
|
|
@@ -1511,7 +1554,7 @@ function applyUpgrade(targetDir) {
|
|
|
1511
1554
|
targetPath: path.join(agentsDirectory, STATE_FILE),
|
|
1512
1555
|
},
|
|
1513
1556
|
);
|
|
1514
|
-
applySkillTransaction(entries, targetDir);
|
|
1557
|
+
applySkillTransaction(entries, targetDir, force);
|
|
1515
1558
|
|
|
1516
1559
|
if (tools.includes("kimi")) reportLegacyKimiInstall();
|
|
1517
1560
|
}
|
|
@@ -1620,7 +1663,7 @@ async function runInstall(args) {
|
|
|
1620
1663
|
: existingConfig.languagePreferences?.documents?.raw,
|
|
1621
1664
|
});
|
|
1622
1665
|
|
|
1623
|
-
applyInstall(targetDir, tools, metadata);
|
|
1666
|
+
applyInstall(targetDir, tools, metadata, { force: Boolean(args.force) });
|
|
1624
1667
|
|
|
1625
1668
|
printInstallSummary("installed", tools);
|
|
1626
1669
|
process.stdout.write(` Target project: ${targetDir}\n\n`);
|
|
@@ -1633,7 +1676,7 @@ function runUpgrade(args) {
|
|
|
1633
1676
|
const tools = readNonEmptyLines(
|
|
1634
1677
|
path.join(targetDir, ".agents", "macca-tools.txt"),
|
|
1635
1678
|
);
|
|
1636
|
-
applyUpgrade(targetDir);
|
|
1679
|
+
applyUpgrade(targetDir, { force: Boolean(args.force) });
|
|
1637
1680
|
printInstallSummary("updated", tools);
|
|
1638
1681
|
process.stdout.write(` Target project: ${targetDir}\n\n`);
|
|
1639
1682
|
}
|
package/package.json
CHANGED
package/scripts/test-install.js
CHANGED
|
@@ -77,7 +77,7 @@ function runCli(args) {
|
|
|
77
77
|
"exec",
|
|
78
78
|
"--yes",
|
|
79
79
|
"--package",
|
|
80
|
-
"macca-method",
|
|
80
|
+
"macca-method@latest",
|
|
81
81
|
"--",
|
|
82
82
|
"macca-method",
|
|
83
83
|
...args,
|
|
@@ -104,7 +104,7 @@ function expectCliFailure(args, expectedText) {
|
|
|
104
104
|
"exec",
|
|
105
105
|
"--yes",
|
|
106
106
|
"--package",
|
|
107
|
-
"macca-method",
|
|
107
|
+
"macca-method@latest",
|
|
108
108
|
"--",
|
|
109
109
|
"macca-method",
|
|
110
110
|
...args,
|
|
@@ -509,6 +509,7 @@ function main() {
|
|
|
509
509
|
["upgrade", "--directory", driftDir],
|
|
510
510
|
"locally modified managed skill",
|
|
511
511
|
);
|
|
512
|
+
runCli(["upgrade", "--directory", driftDir, "--force"]);
|
|
512
513
|
|
|
513
514
|
assertPathExists(path.join(projectDir, ".agents", "developer-config.json"));
|
|
514
515
|
assertPathExists(
|