@uzysjung/agent-harness 26.152.0 → 26.153.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.
Files changed (28) hide show
  1. package/dist/{chunk-EQDC2AAU.js → chunk-OYNSK6QF.js} +20 -11
  2. package/dist/chunk-OYNSK6QF.js.map +1 -0
  3. package/dist/index.js +89 -45
  4. package/dist/index.js.map +1 -1
  5. package/dist/trust-tier-drift.js +1 -1
  6. package/package.json +1 -1
  7. package/templates/CLAUDE.md +93 -145
  8. package/templates/codex/README.md +6 -7
  9. package/templates/codex/config.toml.template +1 -9
  10. package/templates/skills/audit-harness-fit/README.md +76 -43
  11. package/templates/skills/audit-harness-fit/SKILL.md +62 -47
  12. package/templates/skills/audit-harness-fit/evals/scenarios.yaml +179 -22
  13. package/templates/skills/audit-harness-fit/references/apply.md +74 -45
  14. package/templates/skills/audit-harness-fit/references/audit.md +142 -118
  15. package/templates/skills/audit-harness-fit/references/populate.md +53 -49
  16. package/templates/skills/audit-harness-fit/references/verification.md +131 -100
  17. package/templates/skills/clear-korean-communication/SKILL.md +76 -209
  18. package/templates/skills/external-model-consult/scripts/codex-ask.sh +9 -4
  19. package/templates/skills/external-model-consult/scripts/gemini-ask.sh +9 -4
  20. package/templates/skills/model-orchestration/SKILL.md +123 -267
  21. package/templates/skills/objective-brief/SKILL.md +3 -3
  22. package/dist/chunk-EQDC2AAU.js.map +0 -1
  23. package/templates/codex/hooks/README.md +0 -37
  24. package/templates/codex/hooks/session-start.sh +0 -7
  25. package/templates/codex/hooks/uncommitted-check.sh +0 -7
  26. package/templates/skills/clear-korean-communication/references/pre-send-checklist.md +0 -37
  27. package/templates/skills/clear-korean-communication/references/why-it-works.md +0 -24
  28. package/templates/skills/clear-korean-communication/references/worked-examples.md +0 -89
package/dist/index.js CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  RETIRED_AGENT_IDS,
19
19
  RETIRED_SKILL_IDS,
20
20
  TRACKS,
21
+ TRACK_AGENTS,
21
22
  __commonJS,
22
23
  __toESM,
23
24
  anyTrack,
@@ -63,7 +64,7 @@ import {
63
64
  upsertHarnessImport,
64
65
  withContinuousSkillsNote,
65
66
  writeInstallLog
66
- } from "./chunk-EQDC2AAU.js";
67
+ } from "./chunk-OYNSK6QF.js";
67
68
 
68
69
  // node_modules/sisteransi/src/index.js
69
70
  var require_src = __commonJS({
@@ -748,7 +749,7 @@ var cac = (name = "") => new CAC(name);
748
749
  // package.json
749
750
  var package_default = {
750
751
  name: "@uzysjung/agent-harness",
751
- version: "26.152.0",
752
+ version: "26.153.0",
752
753
  description: "Curate vetted AI-coding skills & plugins by your tech stack \u2014 install only what you need, across Claude Code, Codex, OpenCode & Antigravity",
753
754
  type: "module",
754
755
  publishConfig: {
@@ -2136,6 +2137,7 @@ function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}) {
2136
2137
  restored: [],
2137
2138
  needsReinstall: [],
2138
2139
  retiredAgents: [],
2140
+ demotedAgents: [],
2139
2141
  mcpAllowlistRetired: null
2140
2142
  };
2141
2143
  const fresh = installNewAssets(projectDir, templatesDir);
@@ -2175,6 +2177,7 @@ function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}) {
2175
2177
  }
2176
2178
  report.mcpAllowlistRetired = retireMcpAllowlist(projectDir);
2177
2179
  report.retiredAgents = staleAgentFiles(claudeDir);
2180
+ report.demotedAgents = demotedAgentFiles(claudeDir, installedTracks(projectDir));
2178
2181
  const external = refreshExternalCli(projectDir, harnessRoot);
2179
2182
  report.externalUpdated = external.externalUpdated;
2180
2183
  report.externalBackedUp = external.externalBackedUp;
@@ -2209,6 +2212,15 @@ function staleAgentFiles(claudeDir) {
2209
2212
  if (!existsSync12(dir)) return [];
2210
2213
  return readdirSync3(dir, { withFileTypes: true }).filter((e2) => e2.isFile() && e2.name.endsWith(".md")).map((e2) => basename4(e2.name, ".md")).filter((id) => RETIRED_AGENT_IDS.includes(id));
2211
2214
  }
2215
+ function demotedAgentFiles(claudeDir, tracks) {
2216
+ if (tracks.length === 0) return [];
2217
+ const dir = join11(claudeDir, "agents");
2218
+ if (!existsSync12(dir)) return [];
2219
+ const demoted = TRACK_AGENTS.filter(([, pattern]) => !anyTrack(tracks, pattern)).map(
2220
+ ([id]) => id
2221
+ );
2222
+ return readdirSync3(dir, { withFileTypes: true }).filter((e2) => e2.isFile() && e2.name.endsWith(".md")).map((e2) => basename4(e2.name, ".md")).filter((id) => demoted.includes(id));
2223
+ }
2212
2224
  function installNewAssets(projectDir, templatesDir) {
2213
2225
  const installed = [];
2214
2226
  const restored = [];
@@ -2940,6 +2952,8 @@ function listHookFiles(hookDir) {
2940
2952
 
2941
2953
  // src/commands/install-render.ts
2942
2954
  init_esm_shims();
2955
+ import { existsSync as existsSync14, readdirSync as readdirSync5 } from "fs";
2956
+ import { join as join13 } from "path";
2943
2957
 
2944
2958
  // src/preset-recommend.ts
2945
2959
  init_esm_shims();
@@ -3005,12 +3019,14 @@ function renderInstallHeader(log, spec, mode) {
3005
3019
  for (const [cat, ids] of groupAssetsByCategory(finalAssets)) {
3006
3020
  log(` ${c.dim(`\xB7 ${cat}:`)} ${ids.join(", ")}`);
3007
3021
  }
3008
- const assetSpec = buildManifestSpec(spec);
3009
- const cost = formatResidentCostLine(
3010
- residentCost(buildManifest(assetSpec).filter((e2) => e2.applies(assetSpec))),
3011
- summarizeContextCost(finalAssets).unmeasuredCount
3012
- );
3013
- if (cost) log(` ${c.dim(`\xB7 ${cost}`)}`);
3022
+ if (mode !== "update") {
3023
+ const assetSpec = buildManifestSpec(spec);
3024
+ const cost = formatResidentCostLine(
3025
+ residentCost(buildManifest(assetSpec).filter((e2) => e2.applies(assetSpec))),
3026
+ summarizeContextCost(finalAssets).unmeasuredCount
3027
+ );
3028
+ if (cost) log(` ${c.dim(`\xB7 ${cost}`)}`);
3029
+ }
3014
3030
  }
3015
3031
  log("");
3016
3032
  }
@@ -3064,7 +3080,7 @@ function createInstallRenderer(log, spec, verbose) {
3064
3080
  };
3065
3081
  return { callbacks, phase2HeaderPrinted: () => phase2HeaderPrinted };
3066
3082
  }
3067
- function renderUpdateSummary(log, report) {
3083
+ function renderUpdateSummary(log, spec, report) {
3068
3084
  log("");
3069
3085
  log(unifiedSection("Summary"));
3070
3086
  log("");
@@ -3074,8 +3090,26 @@ function renderUpdateSummary(log, report) {
3074
3090
  log(infoRow("BACKUP", shortenPath(report.backup)));
3075
3091
  log(infoRow("ROLLBACK", `rm -rf .claude && mv ${shortenPath(report.backup)} .claude`));
3076
3092
  }
3093
+ const cost = formatResidentCostLine(
3094
+ residentCost(residentEntriesOnDisk(spec)),
3095
+ summarizeContextCost(finalSelectedAssets(spec.tracks, spec.userOverride)).unmeasuredCount
3096
+ );
3097
+ if (cost) log(infoRow("CONTEXT", cost));
3077
3098
  log("");
3078
3099
  }
3100
+ function residentEntriesOnDisk(spec) {
3101
+ const assetSpec = buildManifestSpec(spec);
3102
+ const planned = buildManifest(assetSpec).filter((e2) => e2.applies(assetSpec));
3103
+ const agentsDir = join13(spec.projectDir, ".claude", "agents");
3104
+ const onDisk = existsSync14(agentsDir) ? readdirSync5(agentsDir, { withFileTypes: true }).filter((e2) => e2.isFile() && e2.name.endsWith(".md")).map((e2) => ({
3105
+ source: `agents/${e2.name}`,
3106
+ target: `.claude/agents/${e2.name}`,
3107
+ // 배포판이 아니라 **이 프로젝트의 파일**을 잰다 — 사용자가 고친 descriptor 도,
3108
+ // 배포판에 더는 없는 에이전트도 실제로 상주하는 것은 이쪽이다.
3109
+ file: join13(agentsDir, e2.name)
3110
+ })) : [];
3111
+ return [...planned.filter((e2) => !e2.target.startsWith(".claude/agents/")), ...onDisk];
3112
+ }
3079
3113
  function renderCliArtifacts(log, spec, report) {
3080
3114
  const hasArtifacts = Boolean(report.codex || report.opencode || report.antigravity);
3081
3115
  const cliSelected = targetsInclude(spec.cli, "codex") || targetsInclude(spec.cli, "opencode") || targetsInclude(spec.cli, "antigravity");
@@ -3353,6 +3387,16 @@ function renderPhase1Rows(log, baseline, verbose = false, withEcc = false, claud
3353
3387
  )
3354
3388
  );
3355
3389
  }
3390
+ for (const [id, pattern] of TRACK_AGENTS) {
3391
+ if (!baseline.updateMode.demotedAgents.includes(id)) continue;
3392
+ log(
3393
+ assetRow(
3394
+ "skip",
3395
+ "agents",
3396
+ `${id} \xB7 \uC774 \uD2B8\uB799\uC5D0\uC11C\uB294 \uB354 \uC774\uC0C1 \uC124\uCE58\uD558\uC9C0 \uC54A\uB294\uB2E4 \u2014 ${pattern.split("|").join(" \xB7 ")} \uD2B8\uB799 \uC804\uC6A9 \xB7 .claude/agents/${id}.md \uB97C \uC9C0\uC6CC\uB3C4 \uB41C\uB2E4`
3397
+ )
3398
+ );
3399
+ }
3356
3400
  if (baseline.updateMode.policyBackedUp.length > 0) {
3357
3401
  log(
3358
3402
  assetRow(
@@ -3735,7 +3779,7 @@ function executeSpec(spec, deps = {}) {
3735
3779
  return;
3736
3780
  }
3737
3781
  if (report.updateMode) {
3738
- renderUpdateSummary(log, report);
3782
+ renderUpdateSummary(log, spec, report);
3739
3783
  return;
3740
3784
  }
3741
3785
  if (renderer.phase2HeaderPrinted()) {
@@ -3800,8 +3844,8 @@ function registerInstallCommand(cli2) {
3800
3844
 
3801
3845
  // src/commands/list.ts
3802
3846
  init_esm_shims();
3803
- import { existsSync as existsSync14, readFileSync as readFileSync13 } from "fs";
3804
- import { join as join13, resolve as resolve3 } from "path";
3847
+ import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
3848
+ import { join as join14, resolve as resolve3 } from "path";
3805
3849
  function listAction(options = {}, deps = {}) {
3806
3850
  const log = deps.log ?? console.log;
3807
3851
  const err = deps.err ?? console.error;
@@ -3864,8 +3908,8 @@ function formatTemplateRows(log, projectDir) {
3864
3908
  const rows = [` ${c.dim(dirs.join(" "))}`];
3865
3909
  const rootMd = log.templates.rootClaudeMd;
3866
3910
  if (rootMd) {
3867
- const path = join13(projectDir, rootMd.path);
3868
- const modified = existsSync14(path) && hashContent(readFileSync13(path, "utf8")) !== rootMd.sha256;
3911
+ const path = join14(projectDir, rootMd.path);
3912
+ const modified = existsSync15(path) && hashContent(readFileSync13(path, "utf8")) !== rootMd.sha256;
3869
3913
  rows.push(
3870
3914
  modified ? ` ${c.dim(rootMd.path)} ${c.yellow("(\uC218\uC815\uB428 \u2014 uninstall \uC2DC \uBCF4\uC874)")}` : ` ${c.dim(rootMd.path)}`
3871
3915
  );
@@ -3873,7 +3917,7 @@ function formatTemplateRows(log, projectDir) {
3873
3917
  return rows;
3874
3918
  }
3875
3919
  function formatRootFileRows(rootFiles, projectDir) {
3876
- const present = rootFiles.filter((f) => existsSync14(join13(projectDir, f.path)));
3920
+ const present = rootFiles.filter((f) => existsSync15(join14(projectDir, f.path)));
3877
3921
  const width = Math.max(0, ...present.map((f) => f.path.length));
3878
3922
  return present.map(
3879
3923
  (f) => ` ${c.dim(padDisplay(f.path, width))} ${c.dim(f.change === "created" ? "\uC0DD\uC131" : "\uBCD1\uD569")} ${c.dim(f.notes.join(" / "))}`
@@ -3891,15 +3935,15 @@ function registerListCommand(cli2) {
3891
3935
  init_esm_shims();
3892
3936
  import { spawnSync as spawnSync2 } from "child_process";
3893
3937
  import {
3894
- existsSync as existsSync15,
3938
+ existsSync as existsSync16,
3895
3939
  lstatSync as lstatSync2,
3896
- readdirSync as readdirSync5,
3940
+ readdirSync as readdirSync6,
3897
3941
  readFileSync as readFileSync14,
3898
3942
  rmdirSync,
3899
3943
  rmSync,
3900
3944
  writeFileSync as writeFileSync7
3901
3945
  } from "fs";
3902
- import { dirname as dirname5, join as join14, relative as relative2, resolve as resolve4, sep as sep2 } from "path";
3946
+ import { dirname as dirname5, join as join15, relative as relative2, resolve as resolve4, sep as sep2 } from "path";
3903
3947
 
3904
3948
  // src/uninstall-interactive.ts
3905
3949
  init_esm_shims();
@@ -5139,7 +5183,7 @@ function settleLog(ctx, io) {
5139
5183
  return true;
5140
5184
  }
5141
5185
  } else {
5142
- io.rm(join14(projectDir, INSTALL_LOG_DIR));
5186
+ io.rm(join15(projectDir, INSTALL_LOG_DIR));
5143
5187
  io.rm(legacyInstallLogPath(projectDir));
5144
5188
  io.log(` ${status.success("install log removed")}`);
5145
5189
  }
@@ -5189,7 +5233,7 @@ function advisoryLines(plan, projectDir, rootFiles) {
5189
5233
  return lines;
5190
5234
  }
5191
5235
  function rootFileAdvisoryLines(rootFiles, projectDir) {
5192
- const present = rootFiles.filter((f) => existsSync15(join14(projectDir, f.path)));
5236
+ const present = rootFiles.filter((f) => existsSync16(join15(projectDir, f.path)));
5193
5237
  if (present.length === 0) return [];
5194
5238
  return [
5195
5239
  "",
@@ -5290,16 +5334,16 @@ function buildGlobalAdvisoryCmd(asset) {
5290
5334
  }
5291
5335
  }
5292
5336
  function removeTemplates(log, projectDir, rm) {
5293
- rm(join14(projectDir, log.templates.claudeDir));
5294
- if (log.templates.codexDir) rm(join14(projectDir, log.templates.codexDir));
5295
- if (log.templates.opencodeDir) rm(join14(projectDir, log.templates.opencodeDir));
5337
+ rm(join15(projectDir, log.templates.claudeDir));
5338
+ if (log.templates.codexDir) rm(join15(projectDir, log.templates.codexDir));
5339
+ if (log.templates.opencodeDir) rm(join15(projectDir, log.templates.opencodeDir));
5296
5340
  const external = removeExternalFiles(log, projectDir, rm);
5297
5341
  const importStripped = stripRootImport(projectDir);
5298
5342
  const rootMd = log.templates.rootClaudeMd;
5299
5343
  if (rootMd) {
5300
5344
  if (rootClaudeMdModified(log, projectDir))
5301
5345
  return { rootClaudeMdKept: true, importStripped, external };
5302
- rm(join14(projectDir, rootMd.path));
5346
+ rm(join15(projectDir, rootMd.path));
5303
5347
  }
5304
5348
  return { rootClaudeMdKept: false, importStripped, external };
5305
5349
  }
@@ -5307,8 +5351,8 @@ function removeExternalFiles(log, projectDir, rm) {
5307
5351
  const removed = [];
5308
5352
  const kept = [];
5309
5353
  for (const { path, sha256 } of log.externalFiles ?? []) {
5310
- const abs = join14(projectDir, path);
5311
- if (!existsSync15(abs)) continue;
5354
+ const abs = join15(projectDir, path);
5355
+ if (!existsSync16(abs)) continue;
5312
5356
  if (!lstatSync2(abs).isFile()) continue;
5313
5357
  if (hashContent(readFileSync14(abs, "utf8")) !== sha256) {
5314
5358
  kept.push(path);
@@ -5317,7 +5361,7 @@ function removeExternalFiles(log, projectDir, rm) {
5317
5361
  rm(abs);
5318
5362
  removed.push(path);
5319
5363
  }
5320
- for (const path of removed) pruneEmptyDirsUpward(projectDir, dirname5(join14(projectDir, path)));
5364
+ for (const path of removed) pruneEmptyDirsUpward(projectDir, dirname5(join15(projectDir, path)));
5321
5365
  return { removed, kept };
5322
5366
  }
5323
5367
  function pruneEmptyDirsUpward(projectDir, startDir) {
@@ -5326,7 +5370,7 @@ function pruneEmptyDirsUpward(projectDir, startDir) {
5326
5370
  const rel = relative2(projectDir, cursor);
5327
5371
  if (rel === "" || rel.startsWith(`..${sep2}`) || rel === "..") return;
5328
5372
  try {
5329
- if (readdirSync5(cursor).length > 0) return;
5373
+ if (readdirSync6(cursor).length > 0) return;
5330
5374
  rmdirSync(cursor);
5331
5375
  } catch {
5332
5376
  return;
@@ -5339,7 +5383,7 @@ function stripRootImport(projectDir) {
5339
5383
  const stripped = current === null ? null : stripHarnessImport(current);
5340
5384
  if (stripped === null) return false;
5341
5385
  try {
5342
- writeFileSync7(join14(projectDir, "CLAUDE.md"), stripped, "utf8");
5386
+ writeFileSync7(join15(projectDir, "CLAUDE.md"), stripped, "utf8");
5343
5387
  return true;
5344
5388
  } catch {
5345
5389
  return false;
@@ -5349,8 +5393,8 @@ function previewExternalLines(installLog, projectDir) {
5349
5393
  const lines = [];
5350
5394
  let removable = 0;
5351
5395
  for (const { path, sha256 } of installLog.externalFiles ?? []) {
5352
- const abs = join14(projectDir, path);
5353
- if (!existsSync15(abs)) continue;
5396
+ const abs = join15(projectDir, path);
5397
+ if (!existsSync16(abs)) continue;
5354
5398
  if (hashContent(readFileSync14(abs, "utf8")) !== sha256) {
5355
5399
  lines.push(` \u25CB keep ${path} (modified since install \u2014 preserved)`);
5356
5400
  continue;
@@ -5377,8 +5421,8 @@ function hasRootImport(projectDir) {
5377
5421
  return current !== null && stripHarnessImport(current) !== null;
5378
5422
  }
5379
5423
  function readRootClaudeMd(projectDir) {
5380
- const path = join14(projectDir, "CLAUDE.md");
5381
- if (!existsSync15(path)) return null;
5424
+ const path = join15(projectDir, "CLAUDE.md");
5425
+ if (!existsSync16(path)) return null;
5382
5426
  try {
5383
5427
  return readFileSync14(path, "utf8");
5384
5428
  } catch {
@@ -5388,8 +5432,8 @@ function readRootClaudeMd(projectDir) {
5388
5432
  function rootClaudeMdModified(log, projectDir) {
5389
5433
  const rootMd = log.templates.rootClaudeMd;
5390
5434
  if (!rootMd) return false;
5391
- const path = join14(projectDir, rootMd.path);
5392
- if (!existsSync15(path)) return false;
5435
+ const path = join15(projectDir, rootMd.path);
5436
+ if (!existsSync16(path)) return false;
5393
5437
  return hashContent(readFileSync14(path, "utf8")) !== rootMd.sha256;
5394
5438
  }
5395
5439
  function formatTemplateList(log) {
@@ -5402,7 +5446,7 @@ function defaultSpawn2(cmd, args) {
5402
5446
  return spawnSync2(cmd, [...args], { encoding: "utf8", stdio: "pipe", timeout: 12e4 });
5403
5447
  }
5404
5448
  function defaultRm(path) {
5405
- if (existsSync15(path)) {
5449
+ if (existsSync16(path)) {
5406
5450
  rmSync(path, { recursive: true, force: true });
5407
5451
  }
5408
5452
  }
@@ -5450,8 +5494,8 @@ import { resolve as resolve5 } from "path";
5450
5494
 
5451
5495
  // src/state.ts
5452
5496
  init_esm_shims();
5453
- import { existsSync as existsSync16, readFileSync as readFileSync15 } from "fs";
5454
- import { join as join15 } from "path";
5497
+ import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
5498
+ import { join as join16 } from "path";
5455
5499
  var META_FILE = ".claude/.installed-tracks";
5456
5500
  var LEGACY_SIGNATURES = [
5457
5501
  { rule: "htmx.md", track: "ssr-htmx" },
@@ -5461,11 +5505,11 @@ var LEGACY_SIGNATURES = [
5461
5505
  { rule: "cli-development.md", track: "tooling" }
5462
5506
  ];
5463
5507
  function detectInstallState(projectDir) {
5464
- const claudeDir = join15(projectDir, ".claude");
5465
- const hasClaudeDir = existsSync16(claudeDir);
5508
+ const claudeDir = join16(projectDir, ".claude");
5509
+ const hasClaudeDir = existsSync17(claudeDir);
5466
5510
  if (hasClaudeDir) {
5467
- const metaPath = join15(projectDir, META_FILE);
5468
- if (existsSync16(metaPath)) {
5511
+ const metaPath = join16(projectDir, META_FILE);
5512
+ if (existsSync17(metaPath)) {
5469
5513
  const tracks2 = readMetafile(metaPath);
5470
5514
  return { state: "existing", tracks: tracks2, source: "metafile", hasClaudeDir: true };
5471
5515
  }
@@ -5498,13 +5542,13 @@ function readMetafile(path) {
5498
5542
  return [...seen].sort();
5499
5543
  }
5500
5544
  function inferFromLegacySignatures(projectDir) {
5501
- const rulesDir = join15(projectDir, ".claude/rules");
5502
- if (!existsSync16(rulesDir)) {
5545
+ const rulesDir = join16(projectDir, ".claude/rules");
5546
+ if (!existsSync17(rulesDir)) {
5503
5547
  return [];
5504
5548
  }
5505
5549
  const found = /* @__PURE__ */ new Set();
5506
5550
  for (const sig of LEGACY_SIGNATURES) {
5507
- if (existsSync16(join15(rulesDir, sig.rule))) {
5551
+ if (existsSync17(join16(rulesDir, sig.rule))) {
5508
5552
  found.add(sig.track);
5509
5553
  }
5510
5554
  }