@uzysjung/agent-harness 26.160.0 → 26.160.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +116 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -754,7 +754,7 @@ var cac = (name = "") => new CAC(name);
|
|
|
754
754
|
// package.json
|
|
755
755
|
var package_default = {
|
|
756
756
|
name: "@uzysjung/agent-harness",
|
|
757
|
-
version: "26.160.
|
|
757
|
+
version: "26.160.1",
|
|
758
758
|
description: "Curate vetted AI-coding skills & plugins by your tech stack \u2014 install only what you need, across Claude Code, Codex, OpenCode & Antigravity",
|
|
759
759
|
type: "module",
|
|
760
760
|
publishConfig: {
|
|
@@ -1210,6 +1210,39 @@ function mergeAgentsMd(params) {
|
|
|
1210
1210
|
}
|
|
1211
1211
|
return bodies.size === 0 ? rendered : assemble(rendered, names, bodies);
|
|
1212
1212
|
}
|
|
1213
|
+
function installerLines(body, m) {
|
|
1214
|
+
if (body === null) return [];
|
|
1215
|
+
const at2 = blockRange(body, m);
|
|
1216
|
+
return at2 === null ? [...body] : [...body.slice(0, at2[0]), ...body.slice(at2[1] + 1)];
|
|
1217
|
+
}
|
|
1218
|
+
function compact(lines) {
|
|
1219
|
+
return lines.map((l) => l.replace(/\r$/, "").trimEnd()).filter((l) => l.trim() !== "");
|
|
1220
|
+
}
|
|
1221
|
+
function trimBlankEdges(lines) {
|
|
1222
|
+
const out = trimTrailingBlanks(lines);
|
|
1223
|
+
while (out.length > 0 && (out[0] ?? "").trim() === "") out.shift();
|
|
1224
|
+
return out;
|
|
1225
|
+
}
|
|
1226
|
+
function stripHarnessFromAgentsMd(params) {
|
|
1227
|
+
const { existing, template } = params;
|
|
1228
|
+
const lines = existing.split("\n");
|
|
1229
|
+
if (blockRange(lines, ANCHOR_BLOCK) === null && blockRange(lines, SKILLS_BLOCK) === null) {
|
|
1230
|
+
return null;
|
|
1231
|
+
}
|
|
1232
|
+
const names = sectionNames(template);
|
|
1233
|
+
const context = installerLines(sectionBody(existing, names, CONTEXT_SECTION), SKILLS_BLOCK);
|
|
1234
|
+
const rules = installerLines(sectionBody(existing, names, RULES_SECTION), ANCHOR_BLOCK);
|
|
1235
|
+
const scaffold = compact(renderFillScaffold("agents-md").split("\n"));
|
|
1236
|
+
const contextFilled = compact(context).join("\n") !== scaffold.join("\n");
|
|
1237
|
+
const rulesFilled = compact(rules).length > 0;
|
|
1238
|
+
if (!contextFilled && !rulesFilled) return null;
|
|
1239
|
+
const out = [];
|
|
1240
|
+
const title = (lines[0] ?? "").replace(/\r$/, "");
|
|
1241
|
+
if (/^# /.test(title)) out.push(title, "");
|
|
1242
|
+
out.push(`## ${CONTEXT_SECTION}`, "", ...trimBlankEdges(context), "");
|
|
1243
|
+
if (rulesFilled) out.push(`## ${RULES_SECTION}`, "", ...trimBlankEdges(rules), "");
|
|
1244
|
+
return out.join("\n");
|
|
1245
|
+
}
|
|
1213
1246
|
|
|
1214
1247
|
// src/codex/agents-md.ts
|
|
1215
1248
|
function renameSlashes(text) {
|
|
@@ -2625,13 +2658,21 @@ function installedBundledSkills(projectDir) {
|
|
|
2625
2658
|
(id) => existsSync13(join12(projectDir, ".claude/skills", id)) || existsSync13(join12(projectDir, ".agents/skills", id))
|
|
2626
2659
|
);
|
|
2627
2660
|
}
|
|
2661
|
+
function installedCliTargets(log) {
|
|
2662
|
+
if (log === null) return ALL_CLI_TARGETS;
|
|
2663
|
+
return ALL_CLI_TARGETS.filter((cli2) => {
|
|
2664
|
+
if (cli2 === "codex") return log.templates.codexDir !== void 0;
|
|
2665
|
+
if (cli2 === "opencode") return log.templates.opencodeDir !== void 0;
|
|
2666
|
+
return true;
|
|
2667
|
+
});
|
|
2668
|
+
}
|
|
2628
2669
|
function refreshExternalCli(projectDir, harnessRoot) {
|
|
2629
2670
|
const log = readInstallLog(projectDir);
|
|
2630
2671
|
const baselineExcluded = new Set(log?.spec.baselineExclude ?? []);
|
|
2631
2672
|
const result = runCliTransforms({
|
|
2632
2673
|
harnessRoot,
|
|
2633
2674
|
projectDir,
|
|
2634
|
-
cli:
|
|
2675
|
+
cli: installedCliTargets(log),
|
|
2635
2676
|
// 스킬은 **디스크에 있는 것만** 넘긴다. 스킬 *파일*은 전체 목록을 넘겨도 refreshOnly 가
|
|
2636
2677
|
// 없는 것을 건너뛰지만, `AGENTS.md` 의 상시 스킬 안내(ADR-085)는 이 목록 그대로 렌더돼
|
|
2637
2678
|
// `--without` 으로 뺀 스킬(#505)·opt-in 스킬을 "열어라"고 적었다(실측 2026-09-21). 판정은
|
|
@@ -5410,6 +5451,7 @@ function uninstallAction(options, deps = {}) {
|
|
|
5410
5451
|
const spawn = deps.spawn ?? defaultSpawn2;
|
|
5411
5452
|
const rm = deps.rm ?? defaultRm;
|
|
5412
5453
|
const writeLog = deps.writeLog ?? writeInstallLog;
|
|
5454
|
+
const harnessRoot = (deps.resolveHarnessRoot ?? defaultHarnessRoot)();
|
|
5413
5455
|
const projectDir = resolve4(options.projectDir ?? process.cwd());
|
|
5414
5456
|
const installLog = readInstallLog(projectDir);
|
|
5415
5457
|
if (!installLog) {
|
|
@@ -5438,7 +5480,14 @@ function uninstallAction(options, deps = {}) {
|
|
|
5438
5480
|
const plan = planReverse(targetAssets, spawn);
|
|
5439
5481
|
for (const line of headerLines(installLog, selectedIds, targetAssets.length)) log(line);
|
|
5440
5482
|
if (options.dryRun) {
|
|
5441
|
-
for (const line of dryRunLines(
|
|
5483
|
+
for (const line of dryRunLines(
|
|
5484
|
+
plan,
|
|
5485
|
+
installLog,
|
|
5486
|
+
projectDir,
|
|
5487
|
+
keepTemplates,
|
|
5488
|
+
rootFiles,
|
|
5489
|
+
harnessRoot
|
|
5490
|
+
)) {
|
|
5442
5491
|
log(line);
|
|
5443
5492
|
}
|
|
5444
5493
|
exit(0);
|
|
@@ -5450,7 +5499,8 @@ function uninstallAction(options, deps = {}) {
|
|
|
5450
5499
|
const { rootClaudeMdKept, importStripped, external } = removeTemplates(
|
|
5451
5500
|
installLog,
|
|
5452
5501
|
projectDir,
|
|
5453
|
-
rm
|
|
5502
|
+
rm,
|
|
5503
|
+
harnessRoot
|
|
5454
5504
|
);
|
|
5455
5505
|
log(` ${status.success(`templates removed: ${formatTemplateList(installLog)}`)}`);
|
|
5456
5506
|
for (const line of externalRemovalLines(external)) log(line);
|
|
@@ -5557,7 +5607,7 @@ function settleLog(ctx, io) {
|
|
|
5557
5607
|
}
|
|
5558
5608
|
return false;
|
|
5559
5609
|
}
|
|
5560
|
-
function dryRunLines(plan, installLog, projectDir, keepTemplates, rootFiles) {
|
|
5610
|
+
function dryRunLines(plan, installLog, projectDir, keepTemplates, rootFiles, harnessRoot) {
|
|
5561
5611
|
const lines = [c.yellow("[DRY RUN] reverse list (\uC2E4\uC81C \uBCC0\uACBD \uC5C6\uC74C):"), ""];
|
|
5562
5612
|
if (plan.reverseSteps.length === 0) {
|
|
5563
5613
|
lines.push(c.dim(" (no project-scope assets to reverse)"));
|
|
@@ -5579,7 +5629,7 @@ function dryRunLines(plan, installLog, projectDir, keepTemplates, rootFiles) {
|
|
|
5579
5629
|
if (hasRootImport(projectDir)) {
|
|
5580
5630
|
lines.push(" \u25CB strip harness @import from CLAUDE.md (\uBCF8\uBB38 \uBCF4\uC874)");
|
|
5581
5631
|
}
|
|
5582
|
-
lines.push(...previewExternalLines(installLog, projectDir));
|
|
5632
|
+
lines.push(...previewExternalLines(installLog, projectDir, harnessRoot));
|
|
5583
5633
|
}
|
|
5584
5634
|
lines.push(...advisoryLines(plan, projectDir, rootFiles), "");
|
|
5585
5635
|
return lines;
|
|
@@ -5701,11 +5751,11 @@ function buildGlobalAdvisoryCmd(asset) {
|
|
|
5701
5751
|
return "(no standard reverse \u2014 manual)";
|
|
5702
5752
|
}
|
|
5703
5753
|
}
|
|
5704
|
-
function removeTemplates(log, projectDir, rm) {
|
|
5754
|
+
function removeTemplates(log, projectDir, rm, harnessRoot) {
|
|
5705
5755
|
rm(join16(projectDir, log.templates.claudeDir));
|
|
5706
5756
|
if (log.templates.codexDir) rm(join16(projectDir, log.templates.codexDir));
|
|
5707
5757
|
if (log.templates.opencodeDir) rm(join16(projectDir, log.templates.opencodeDir));
|
|
5708
|
-
const external = removeExternalFiles(log, projectDir, rm);
|
|
5758
|
+
const external = removeExternalFiles(log, projectDir, rm, harnessRoot);
|
|
5709
5759
|
const importStripped = stripRootImport(projectDir);
|
|
5710
5760
|
const rootMd = log.templates.rootClaudeMd;
|
|
5711
5761
|
if (rootMd) {
|
|
@@ -5715,22 +5765,55 @@ function removeTemplates(log, projectDir, rm) {
|
|
|
5715
5765
|
}
|
|
5716
5766
|
return { rootClaudeMdKept: false, importStripped, external };
|
|
5717
5767
|
}
|
|
5718
|
-
|
|
5768
|
+
var AGENTS_MD = "AGENTS.md";
|
|
5769
|
+
function readAgentsMdTemplate(harnessRoot, log) {
|
|
5770
|
+
const flavor = log.templates.opencodeDir ? "opencode" : "codex";
|
|
5771
|
+
try {
|
|
5772
|
+
return readFileSync15(join16(harnessRoot, "templates", flavor, "AGENTS.md.template"), "utf8");
|
|
5773
|
+
} catch {
|
|
5774
|
+
return null;
|
|
5775
|
+
}
|
|
5776
|
+
}
|
|
5777
|
+
function agentsMdRemainder(current, harnessRoot, log) {
|
|
5778
|
+
const template = readAgentsMdTemplate(harnessRoot, log);
|
|
5779
|
+
if (template === null) return { ok: false };
|
|
5780
|
+
return { ok: true, remainder: stripHarnessFromAgentsMd({ existing: current, template }) };
|
|
5781
|
+
}
|
|
5782
|
+
function removeExternalFiles(log, projectDir, rm, harnessRoot) {
|
|
5719
5783
|
const removed = [];
|
|
5720
5784
|
const kept = [];
|
|
5785
|
+
const stripped = [];
|
|
5786
|
+
const unjudged = [];
|
|
5721
5787
|
for (const { path, sha256 } of log.externalFiles ?? []) {
|
|
5722
5788
|
const abs = join16(projectDir, path);
|
|
5723
5789
|
if (!existsSync17(abs)) continue;
|
|
5724
5790
|
if (!lstatSync2(abs).isFile()) continue;
|
|
5725
|
-
|
|
5791
|
+
const current = readFileSync15(abs, "utf8");
|
|
5792
|
+
if (hashContent(current) !== sha256) {
|
|
5726
5793
|
kept.push(path);
|
|
5727
5794
|
continue;
|
|
5728
5795
|
}
|
|
5796
|
+
if (path === AGENTS_MD) {
|
|
5797
|
+
const verdict = agentsMdRemainder(current, harnessRoot, log);
|
|
5798
|
+
if (!verdict.ok) {
|
|
5799
|
+
unjudged.push(path);
|
|
5800
|
+
continue;
|
|
5801
|
+
}
|
|
5802
|
+
if (verdict.remainder !== null) {
|
|
5803
|
+
try {
|
|
5804
|
+
writeFileSync7(abs, verdict.remainder, "utf8");
|
|
5805
|
+
stripped.push(path);
|
|
5806
|
+
} catch {
|
|
5807
|
+
unjudged.push(path);
|
|
5808
|
+
}
|
|
5809
|
+
continue;
|
|
5810
|
+
}
|
|
5811
|
+
}
|
|
5729
5812
|
rm(abs);
|
|
5730
5813
|
removed.push(path);
|
|
5731
5814
|
}
|
|
5732
5815
|
for (const path of removed) pruneEmptyDirsUpward(projectDir, dirname5(join16(projectDir, path)));
|
|
5733
|
-
return { removed, kept };
|
|
5816
|
+
return { removed, kept, stripped, unjudged };
|
|
5734
5817
|
}
|
|
5735
5818
|
function pruneEmptyDirsUpward(projectDir, startDir) {
|
|
5736
5819
|
let cursor = startDir;
|
|
@@ -5757,16 +5840,28 @@ function stripRootImport(projectDir) {
|
|
|
5757
5840
|
return false;
|
|
5758
5841
|
}
|
|
5759
5842
|
}
|
|
5760
|
-
function previewExternalLines(installLog, projectDir) {
|
|
5843
|
+
function previewExternalLines(installLog, projectDir, harnessRoot) {
|
|
5761
5844
|
const lines = [];
|
|
5762
5845
|
let removable = 0;
|
|
5763
5846
|
for (const { path, sha256 } of installLog.externalFiles ?? []) {
|
|
5764
5847
|
const abs = join16(projectDir, path);
|
|
5765
5848
|
if (!existsSync17(abs)) continue;
|
|
5766
|
-
|
|
5849
|
+
const current = readFileSync15(abs, "utf8");
|
|
5850
|
+
if (hashContent(current) !== sha256) {
|
|
5767
5851
|
lines.push(` \u25CB keep ${path} (modified since install \u2014 preserved)`);
|
|
5768
5852
|
continue;
|
|
5769
5853
|
}
|
|
5854
|
+
if (path === AGENTS_MD) {
|
|
5855
|
+
const verdict = agentsMdRemainder(current, harnessRoot, installLog);
|
|
5856
|
+
if (!verdict.ok) {
|
|
5857
|
+
lines.push(` \u25CB keep ${path} (harness sections could not be separated \u2014 preserved)`);
|
|
5858
|
+
continue;
|
|
5859
|
+
}
|
|
5860
|
+
if (verdict.remainder !== null) {
|
|
5861
|
+
lines.push(` \u25CB strip harness sections from ${path} (\uBCF8\uBB38 \uBCF4\uC874)`);
|
|
5862
|
+
continue;
|
|
5863
|
+
}
|
|
5864
|
+
}
|
|
5770
5865
|
removable += 1;
|
|
5771
5866
|
}
|
|
5772
5867
|
if (removable > 0) lines.unshift(` \u25CB remove ${removable} CLI output file(s)`);
|
|
@@ -5777,6 +5872,14 @@ function externalRemovalLines(external) {
|
|
|
5777
5872
|
if (external.removed.length > 0) {
|
|
5778
5873
|
lines.push(` ${status.success(`CLI outputs removed: ${external.removed.length} file(s)`)}`);
|
|
5779
5874
|
}
|
|
5875
|
+
for (const path of external.stripped) {
|
|
5876
|
+
lines.push(` ${status.success(`${path} \u2014 harness sections removed (\uBCF8\uBB38 \uBCF4\uC874)`)}`);
|
|
5877
|
+
}
|
|
5878
|
+
for (const path of external.unjudged) {
|
|
5879
|
+
lines.push(
|
|
5880
|
+
` ${c.yellow("\u2298")} ${path} kept \u2014 harness sections could not be separated (template unreadable or write failed). Remove manually if intended.`
|
|
5881
|
+
);
|
|
5882
|
+
}
|
|
5780
5883
|
for (const path of external.kept) {
|
|
5781
5884
|
lines.push(
|
|
5782
5885
|
` ${c.yellow("\u2298")} ${path} kept \u2014 modified since install. Remove manually if intended.`
|