@uzysjung/agent-harness 26.151.0 → 26.152.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.
package/dist/index.js CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  INTERNAL_BUNDLED_SKILL_IDS,
15
15
  POLICY_DIRS,
16
16
  RENAMED_SKILL_IDS,
17
+ RETIRED_AGENTS,
17
18
  RETIRED_AGENT_IDS,
18
19
  RETIRED_SKILL_IDS,
19
20
  TRACKS,
@@ -62,7 +63,7 @@ import {
62
63
  upsertHarnessImport,
63
64
  withContinuousSkillsNote,
64
65
  writeInstallLog
65
- } from "./chunk-3QBHZUVB.js";
66
+ } from "./chunk-EQDC2AAU.js";
66
67
 
67
68
  // node_modules/sisteransi/src/index.js
68
69
  var require_src = __commonJS({
@@ -747,7 +748,7 @@ var cac = (name = "") => new CAC(name);
747
748
  // package.json
748
749
  var package_default = {
749
750
  name: "@uzysjung/agent-harness",
750
- version: "26.151.0",
751
+ version: "26.152.0",
751
752
  description: "Curate vetted AI-coding skills & plugins by your tech stack \u2014 install only what you need, across Claude Code, Codex, OpenCode & Antigravity",
752
753
  type: "module",
753
754
  publishConfig: {
@@ -986,14 +987,13 @@ function padDisplay(s, width) {
986
987
  init_esm_shims();
987
988
  import {
988
989
  chmodSync as chmodSync3,
989
- existsSync as existsSync14,
990
+ existsSync as existsSync13,
990
991
  mkdirSync as mkdirSync4,
991
992
  readdirSync as readdirSync4,
992
- readFileSync as readFileSync13,
993
- unlinkSync as unlinkSync3,
993
+ readFileSync as readFileSync12,
994
994
  writeFileSync as writeFileSync6
995
995
  } from "fs";
996
- import { basename as basename5, dirname as dirname4, join as join13, resolve } from "path";
996
+ import { basename as basename5, dirname as dirname4, join as join12, resolve } from "path";
997
997
 
998
998
  // src/ci-scaffold.ts
999
999
  init_esm_shims();
@@ -2089,53 +2089,18 @@ function writeMcpJson(path, mcp) {
2089
2089
  `);
2090
2090
  }
2091
2091
 
2092
- // src/superseded.ts
2093
- init_esm_shims();
2094
- import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
2095
- import { join as join11 } from "path";
2096
- function sameTracks(a, b2) {
2097
- if (a.length !== b2.length) return false;
2098
- const sa = [...a].sort();
2099
- const sb = [...b2].sort();
2100
- return sa.every((t, i) => t === sb[i]);
2101
- }
2102
- function policyKey(claudeRelative) {
2103
- return POLICY_DIRS.some(
2104
- ({ dir, ext }) => claudeRelative.startsWith(`${dir}/`) && claudeRelative.endsWith(ext)
2105
- ) ? claudeRelative : null;
2106
- }
2107
- function findSuperseded(projectDir, spec, previous) {
2108
- if (!previous) return [];
2109
- if (!sameTracks(previous.spec.tracks, spec.tracks)) return [];
2110
- const baseline = new Map((previous.policyFiles ?? []).map((f) => [f.path, f.sha256]));
2111
- if (baseline.size === 0) return [];
2112
- const out = [];
2113
- for (const entry of buildManifest(spec)) {
2114
- if (entry.applies(spec)) continue;
2115
- const id = classifyBaselineTarget(entry.target)?.id;
2116
- if (!id) continue;
2117
- const key = policyKey(entry.target.slice(".claude/".length));
2118
- if (!key) continue;
2119
- const abs = join11(projectDir, entry.target);
2120
- if (!existsSync12(abs)) continue;
2121
- if (!isHarnessOwned(baseline, key, readFileSync11(abs, "utf-8"))) continue;
2122
- out.push({ target: entry.target, id, source: entry.source });
2123
- }
2124
- return out;
2125
- }
2126
-
2127
2092
  // src/update-mode.ts
2128
2093
  init_esm_shims();
2129
2094
  import {
2130
2095
  copyFileSync,
2131
- existsSync as existsSync13,
2096
+ existsSync as existsSync12,
2132
2097
  mkdirSync as mkdirSync3,
2133
2098
  readdirSync as readdirSync3,
2134
- readFileSync as readFileSync12,
2099
+ readFileSync as readFileSync11,
2135
2100
  unlinkSync as unlinkSync2,
2136
2101
  writeFileSync as writeFileSync5
2137
2102
  } from "fs";
2138
- import { basename as basename4, dirname as dirname3, join as join12 } from "path";
2103
+ import { basename as basename4, dirname as dirname3, join as join11 } from "path";
2139
2104
  var LEGACY_ANCHOR_FILE = ".claude/CLAUDE.md";
2140
2105
  function buildUpdateSpec(projectDir, tracks) {
2141
2106
  return {
@@ -2147,7 +2112,7 @@ function buildUpdateSpec(projectDir, tracks) {
2147
2112
  };
2148
2113
  }
2149
2114
  function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}) {
2150
- const claudeDir = join12(projectDir, ".claude");
2115
+ const claudeDir = join11(projectDir, ".claude");
2151
2116
  const report = {
2152
2117
  updated: {},
2153
2118
  pruned: {},
@@ -2179,8 +2144,8 @@ function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}) {
2179
2144
  report.needsReinstall = fresh.needsReinstall;
2180
2145
  const policyBase = policyBaseline(projectDir);
2181
2146
  for (const { dir, ext } of POLICY_DIRS) {
2182
- const target = join12(claudeDir, dir);
2183
- const source = join12(templatesDir, dir);
2147
+ const target = join11(claudeDir, dir);
2148
+ const source = join11(templatesDir, dir);
2184
2149
  const label = `.claude/${dir}`;
2185
2150
  const ctx = { prefix: dir, baseline: policyBase };
2186
2151
  const synced = updateDir(target, source, ext, ctx);
@@ -2190,8 +2155,8 @@ function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}) {
2190
2155
  }
2191
2156
  refreshPolicyBaseline(projectDir, templatesDir);
2192
2157
  const skillSync = syncSkills(
2193
- join12(claudeDir, "skills"),
2194
- join12(templatesDir, "skills"),
2158
+ join11(claudeDir, "skills"),
2159
+ join11(templatesDir, "skills"),
2195
2160
  skillBaseline(projectDir),
2196
2161
  /* @__PURE__ */ new Date(),
2197
2162
  (relInSkills) => foreignOwnedTarget(projectDir, `.claude/skills/${relInSkills}`)
@@ -2201,11 +2166,11 @@ function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}) {
2201
2166
  report.skillsSkippedLinks = skillSync.skippedLinks;
2202
2167
  refreshSkillBaseline(projectDir);
2203
2168
  const installLog = readInstallLog(projectDir);
2204
- if (existsSync13(claudeDir) && (installLog === null || installLog.spec.cli.includes("claude"))) {
2169
+ if (existsSync12(claudeDir) && (installLog === null || installLog.spec.cli.includes("claude"))) {
2205
2170
  syncHarnessAnchor(projectDir, templatesDir, report);
2206
2171
  }
2207
- const settingsPath = join12(claudeDir, "settings.json");
2208
- if (existsSync13(settingsPath)) {
2172
+ const settingsPath = join11(claudeDir, "settings.json");
2173
+ if (existsSync12(settingsPath)) {
2209
2174
  report.staleHookRefs = cleanStaleHookRefs(settingsPath, claudeDir);
2210
2175
  }
2211
2176
  report.mcpAllowlistRetired = retireMcpAllowlist(projectDir);
@@ -2234,14 +2199,14 @@ function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}) {
2234
2199
  return report;
2235
2200
  }
2236
2201
  function staleSkillDirs(claudeDir) {
2237
- const dir = join12(claudeDir, "skills");
2238
- if (!existsSync13(dir)) return [];
2202
+ const dir = join11(claudeDir, "skills");
2203
+ if (!existsSync12(dir)) return [];
2239
2204
  const stale = (id) => RENAMED_SKILL_IDS[id] !== void 0 || RETIRED_SKILL_IDS.includes(id);
2240
2205
  return readdirSync3(dir, { withFileTypes: true }).filter((e2) => e2.isDirectory() && stale(e2.name)).map((e2) => e2.name);
2241
2206
  }
2242
2207
  function staleAgentFiles(claudeDir) {
2243
- const dir = join12(claudeDir, "agents");
2244
- if (!existsSync13(dir)) return [];
2208
+ const dir = join11(claudeDir, "agents");
2209
+ if (!existsSync12(dir)) return [];
2245
2210
  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));
2246
2211
  }
2247
2212
  function installNewAssets(projectDir, templatesDir) {
@@ -2256,15 +2221,15 @@ function installNewAssets(projectDir, templatesDir) {
2256
2221
  for (const entry of trackOnlyFileAssets(installedTracks(projectDir))) {
2257
2222
  if (entry.target === HARNESS_ANCHOR_FILE) continue;
2258
2223
  if (isBaselineExcluded(entry.target, baselineExcluded)) continue;
2259
- const target = join12(projectDir, entry.target);
2224
+ const target = join11(projectDir, entry.target);
2260
2225
  const foreign = foreignOwnedTarget(projectDir, entry.target);
2261
2226
  if (foreign !== null) {
2262
2227
  if (!foreignOwned.includes(foreign)) foreignOwned.push(foreign);
2263
2228
  continue;
2264
2229
  }
2265
- if (existsSync13(target)) continue;
2266
- const source = join12(templatesDir, entry.source);
2267
- if (!existsSync13(source)) continue;
2230
+ if (existsSync12(target)) continue;
2231
+ const source = join11(templatesDir, entry.source);
2232
+ if (!existsSync12(source)) continue;
2268
2233
  if (entry.target.startsWith(".claude/")) {
2269
2234
  if (!claudeSelected) continue;
2270
2235
  if (entry.target.startsWith(".claude/hooks/") || entry.target === ".claude/settings.json") {
@@ -2289,13 +2254,13 @@ function trackOnlyFileAssets(tracks) {
2289
2254
  );
2290
2255
  }
2291
2256
  function syncHarnessAnchor(projectDir, templatesDir, report) {
2292
- if (existsSync13(join12(projectDir, LEGACY_ANCHOR_FILE))) {
2257
+ if (existsSync12(join11(projectDir, LEGACY_ANCHOR_FILE))) {
2293
2258
  report.legacyAnchor = LEGACY_ANCHOR_FILE;
2294
2259
  }
2295
- const templateMd = join12(templatesDir, "CLAUDE.md");
2296
- if (!existsSync13(templateMd)) return;
2297
- const anchor = join12(projectDir, HARNESS_ANCHOR_FILE);
2298
- const existed = existsSync13(anchor);
2260
+ const templateMd = join11(templatesDir, "CLAUDE.md");
2261
+ if (!existsSync12(templateMd)) return;
2262
+ const anchor = join11(projectDir, HARNESS_ANCHOR_FILE);
2263
+ const existed = existsSync12(anchor);
2299
2264
  copyFileSync(templateMd, anchor);
2300
2265
  if (existed) {
2301
2266
  report.claudeMdUpdated = true;
@@ -2307,15 +2272,15 @@ function syncHarnessAnchor(projectDir, templatesDir, report) {
2307
2272
  recordAnchorBaseline(projectDir, anchor);
2308
2273
  }
2309
2274
  function upsertRootImport(projectDir) {
2310
- const target = join12(projectDir, "CLAUDE.md");
2311
- const existing = existsSync13(target) ? readFileSync12(target, "utf8") : null;
2275
+ const target = join11(projectDir, "CLAUDE.md");
2276
+ const existing = existsSync12(target) ? readFileSync11(target, "utf8") : null;
2312
2277
  const next = upsertHarnessImport(existing, {
2313
2278
  projectName: basename4(projectDir),
2314
2279
  tracks: installedTracks(projectDir),
2315
2280
  // ADR-085 — update 는 선택 목록을 인자로 받지 않는다. `syncSkills` 와 같은 판정을 쓴다:
2316
2281
  // `.claude/skills/<id>` 가 있으면 그 스킬은 이 설치가 고른 것이다.
2317
2282
  continuousSkills: CONTINUOUS_SKILLS.map((s) => s.id).filter(
2318
- (id) => existsSync13(join12(projectDir, ".claude/skills", id))
2283
+ (id) => existsSync12(join11(projectDir, ".claude/skills", id))
2319
2284
  )
2320
2285
  });
2321
2286
  if (next === existing) return false;
@@ -2335,7 +2300,7 @@ function recordAnchorBaseline(projectDir, anchor) {
2335
2300
  ...log.templates,
2336
2301
  rootClaudeMd: {
2337
2302
  path: HARNESS_ANCHOR_FILE,
2338
- sha256: hashContent(readFileSync12(anchor, "utf8"))
2303
+ sha256: hashContent(readFileSync11(anchor, "utf8"))
2339
2304
  }
2340
2305
  }
2341
2306
  };
@@ -2377,16 +2342,16 @@ function isHarnessOwned2(ctx, rel, current) {
2377
2342
  return isHarnessOwned(ctx.baseline, `${ctx.prefix}/${rel}`, current);
2378
2343
  }
2379
2344
  function updateDir(target, source, ext, ctx, now = /* @__PURE__ */ new Date()) {
2380
- if (!existsSync13(target) || !existsSync13(source)) return { updated: 0, backedUp: [] };
2345
+ if (!existsSync12(target) || !existsSync12(source)) return { updated: 0, backedUp: [] };
2381
2346
  let updated = 0;
2382
2347
  const backedUp = [];
2383
2348
  for (const file of readdirSync3(target)) {
2384
2349
  if (!file.endsWith(ext)) continue;
2385
- const targetFile = join12(target, file);
2386
- const sourceFile = join12(source, file);
2387
- if (!existsSync13(sourceFile)) continue;
2388
- const next = readFileSync12(sourceFile, "utf8");
2389
- const current = readFileSync12(targetFile, "utf8");
2350
+ const targetFile = join11(target, file);
2351
+ const sourceFile = join11(source, file);
2352
+ if (!existsSync12(sourceFile)) continue;
2353
+ const next = readFileSync11(sourceFile, "utf8");
2354
+ const current = readFileSync11(targetFile, "utf8");
2390
2355
  if (current === next) continue;
2391
2356
  if (!isHarnessOwned2(ctx, file, current)) {
2392
2357
  backupFile(targetFile, now);
@@ -2398,7 +2363,7 @@ function updateDir(target, source, ext, ctx, now = /* @__PURE__ */ new Date()) {
2398
2363
  return { updated, backedUp };
2399
2364
  }
2400
2365
  function syncSkills(targetDir, sourceDir, baseline, now = /* @__PURE__ */ new Date(), foreignOf) {
2401
- if (!existsSync13(targetDir) || !existsSync13(sourceDir))
2366
+ if (!existsSync12(targetDir) || !existsSync12(sourceDir))
2402
2367
  return { updated: 0, backedUp: [], skippedLinks: [], foreignOwned: [] };
2403
2368
  let updated = 0;
2404
2369
  const backedUp = [];
@@ -2406,27 +2371,27 @@ function syncSkills(targetDir, sourceDir, baseline, now = /* @__PURE__ */ new Da
2406
2371
  const foreignOwned = [];
2407
2372
  for (const skill of readdirSync3(sourceDir, { withFileTypes: true })) {
2408
2373
  if (!skill.isDirectory()) continue;
2409
- const targetSkill = join12(targetDir, skill.name);
2374
+ const targetSkill = join11(targetDir, skill.name);
2410
2375
  if (occupiedByNonDirectory(targetSkill)) {
2411
2376
  skippedLinks.push(skill.name);
2412
2377
  continue;
2413
2378
  }
2414
- if (!existsSync13(targetSkill)) continue;
2415
- for (const rel of listFilesRecursive(join12(sourceDir, skill.name))) {
2416
- const targetFile = join12(targetSkill, rel);
2379
+ if (!existsSync12(targetSkill)) continue;
2380
+ for (const rel of listFilesRecursive(join11(sourceDir, skill.name))) {
2381
+ const targetFile = join11(targetSkill, rel);
2417
2382
  const foreign = foreignOf(`${skill.name}/${rel}`);
2418
2383
  if (foreign !== null) {
2419
2384
  if (!foreignOwned.includes(foreign)) foreignOwned.push(foreign);
2420
2385
  continue;
2421
2386
  }
2422
- const next = readFileSync12(join12(sourceDir, skill.name, rel), "utf8");
2423
- if (!existsSync13(targetFile)) {
2387
+ const next = readFileSync11(join11(sourceDir, skill.name, rel), "utf8");
2388
+ if (!existsSync12(targetFile)) {
2424
2389
  mkdirSync3(dirname3(targetFile), { recursive: true });
2425
2390
  writeFileSync5(targetFile, next);
2426
2391
  updated++;
2427
2392
  continue;
2428
2393
  }
2429
- const current = readFileSync12(targetFile, "utf8");
2394
+ const current = readFileSync11(targetFile, "utf8");
2430
2395
  if (current === next) continue;
2431
2396
  const recorded = baseline.get(`${skill.name}/${rel}`);
2432
2397
  if (recorded === void 0 || hashContent(current) !== recorded) {
@@ -2472,16 +2437,16 @@ function refreshSkillBaseline(projectDir) {
2472
2437
  }
2473
2438
  }
2474
2439
  function pruneOrphans(target, source, ext, ctx, now = /* @__PURE__ */ new Date()) {
2475
- if (!existsSync13(target) || !existsSync13(source)) return [];
2440
+ if (!existsSync12(target) || !existsSync12(source)) return [];
2476
2441
  const removed = [];
2477
2442
  for (const file of readdirSync3(target)) {
2478
2443
  if (!file.endsWith(ext)) continue;
2479
- const sourceFile = join12(source, file);
2480
- if (!existsSync13(sourceFile)) {
2481
- const targetFile = join12(target, file);
2444
+ const sourceFile = join11(source, file);
2445
+ if (!existsSync12(sourceFile)) {
2446
+ const targetFile = join11(target, file);
2482
2447
  if (!ctx.baseline.has(`${ctx.prefix}/${file}`)) continue;
2483
2448
  try {
2484
- const current = readFileSync12(targetFile, "utf8");
2449
+ const current = readFileSync11(targetFile, "utf8");
2485
2450
  if (!isHarnessOwned2(ctx, file, current)) backupFile(targetFile, now);
2486
2451
  unlinkSync2(targetFile);
2487
2452
  removed.push(file);
@@ -2492,8 +2457,8 @@ function pruneOrphans(target, source, ext, ctx, now = /* @__PURE__ */ new Date()
2492
2457
  return removed;
2493
2458
  }
2494
2459
  function retireMcpAllowlist(projectDir, now = /* @__PURE__ */ new Date()) {
2495
- const target = join12(projectDir, ".mcp-allowlist");
2496
- if (!existsSync13(target)) return null;
2460
+ const target = join11(projectDir, ".mcp-allowlist");
2461
+ if (!existsSync12(target)) return null;
2497
2462
  try {
2498
2463
  const backup = backupFile(target, now);
2499
2464
  unlinkSync2(target);
@@ -2505,7 +2470,7 @@ function retireMcpAllowlist(projectDir, now = /* @__PURE__ */ new Date()) {
2505
2470
  function cleanStaleHookRefs(settingsPath, claudeDir) {
2506
2471
  let settings;
2507
2472
  try {
2508
- settings = JSON.parse(readFileSync12(settingsPath, "utf8"));
2473
+ settings = JSON.parse(readFileSync11(settingsPath, "utf8"));
2509
2474
  } catch {
2510
2475
  return [];
2511
2476
  }
@@ -2532,7 +2497,7 @@ function cleanStaleHookRefs(settingsPath, claudeDir) {
2532
2497
  function keepHookRef(hook, claudeDir, removed) {
2533
2498
  const relPath = projectAnchoredRef(hook?.command ?? "", claudeDir);
2534
2499
  if (relPath === void 0) return true;
2535
- const exists = existsSync13(join12(claudeDir, relPath));
2500
+ const exists = existsSync12(join11(claudeDir, relPath));
2536
2501
  if (!exists && !removed.includes(relPath)) removed.push(relPath);
2537
2502
  return exists;
2538
2503
  }
@@ -2559,14 +2524,14 @@ function projectAnchoredRef(command, claudeDir) {
2559
2524
  function runInstall(ctx) {
2560
2525
  const { harnessRoot, projectDir, spec } = ctx;
2561
2526
  const mode = ctx.mode ?? "fresh";
2562
- const templatesDir = join13(harnessRoot, "templates");
2563
- if (!existsSync14(templatesDir)) {
2527
+ const templatesDir = join12(harnessRoot, "templates");
2528
+ if (!existsSync13(templatesDir)) {
2564
2529
  throw new Error(`Templates dir not found: ${templatesDir}`);
2565
2530
  }
2566
- const claudeDir = join13(projectDir, ".claude");
2531
+ const claudeDir = join12(projectDir, ".claude");
2567
2532
  const previousLog = readInstallLog(projectDir);
2568
2533
  const claudeWasSelected = previousLog?.spec.cli.includes("claude") ?? false;
2569
- if (mode === "update" && !existsSync14(claudeDir) && (previousLog === null || claudeWasSelected)) {
2534
+ if (mode === "update" && !existsSync13(claudeDir) && (previousLog === null || claudeWasSelected)) {
2570
2535
  throw new Error(
2571
2536
  claudeWasSelected ? `Update mode found a broken install at ${projectDir} \u2014 this project installed Claude Code assets but \`.claude/\` is gone. Reinstall instead: agent-harness install --track <name>` : `Update mode requires an existing install at ${projectDir}`
2572
2537
  );
@@ -2578,7 +2543,6 @@ function runInstall(ctx) {
2578
2543
  const manifestSpec = buildManifestSpec(spec);
2579
2544
  const policyBase = new Map((previousLog?.policyFiles ?? []).map((f) => [f.path, f.sha256]));
2580
2545
  const baselineExcluded = new Set(spec.baselineExclude ?? []);
2581
- const supersededFound = findSuperseded(projectDir, manifestSpec, previousLog);
2582
2546
  const base = spec.cli.includes("claude") ? installClaudeBaseline(manifestSpec, projectDir, templatesDir, policyBase, baselineExcluded) : (
2583
2547
  // claude 미선택이어도 CLI 중립 자산은 깔린다. manifest 전체가 `.claude/` baseline 안에서만
2584
2548
  // 돌던 탓에 이 자산들이 claude 설치에만 도달했는데, **배포 룰 본문이 이 스크립트들을
@@ -2634,10 +2598,7 @@ function runInstall(ctx) {
2634
2598
  baselineForeignOwned: [
2635
2599
  ...base.foreignOwned,
2636
2600
  ...externalForeignOwned.filter((f) => !base.foreignOwned.includes(f))
2637
- ],
2638
- // 밀려난 자산 정리는 **manifest 복사가 끝난 뒤**에 한다. 앞에서 지우면 이번 설치가 다시
2639
- // 깔 수도 있는 파일을 지웠다 되돌리는 셈이라, 무엇이 최종 상태인지 보고가 흐려진다.
2640
- superseded: applySupersededCleanup(spec, projectDir, supersededFound)
2601
+ ]
2641
2602
  };
2642
2603
  ctx.onProgress?.({ type: "baseline-complete", baseline });
2643
2604
  const external = runExternalPhase(ctx);
@@ -2653,26 +2614,11 @@ function runInstall(ctx) {
2653
2614
  );
2654
2615
  return { ...baseline, external, staleHookRefs };
2655
2616
  }
2656
- function applySupersededCleanup(spec, projectDir, found) {
2657
- if (found.length === 0) return { removed: [], kept: [] };
2658
- if (!spec.cleanSuperseded) return { removed: [], kept: found.map((f) => f.target) };
2659
- const removed = [];
2660
- const kept = [];
2661
- for (const asset of found) {
2662
- try {
2663
- unlinkSync3(join13(projectDir, asset.target));
2664
- removed.push(asset.target);
2665
- } catch {
2666
- kept.push(asset.target);
2667
- }
2668
- }
2669
- return { removed, kept };
2670
- }
2671
2617
  function healStaleHookRefs(spec, projectDir) {
2672
2618
  if (!spec.cli.includes("claude")) return [];
2673
- const settingsPath = join13(projectDir, ".claude/settings.json");
2674
- if (!existsSync14(settingsPath)) return [];
2675
- return cleanStaleHookRefs(settingsPath, join13(projectDir, ".claude"));
2619
+ const settingsPath = join12(projectDir, ".claude/settings.json");
2620
+ if (!existsSync13(settingsPath)) return [];
2621
+ return cleanStaleHookRefs(settingsPath, join12(projectDir, ".claude"));
2676
2622
  }
2677
2623
  function resolveBackupPath(ctx, mode, claudeDir) {
2678
2624
  const wantBackup = ctx.backup ?? (mode === "update" || mode === "reinstall");
@@ -2688,9 +2634,6 @@ function runUpdateInstall(ctx, templatesDir, backupPath) {
2688
2634
  baselineExcluded: [],
2689
2635
  baselineExcludedOnDisk: [],
2690
2636
  baselineForeignOwned: [],
2691
- // update 는 밀려난 자산을 다루지 않는다 — 그 판정은 사용자가 옵션을 고르는 설치 경로의
2692
- // 것이고, update 는 무엇을 골랐는지 다시 묻지 않는다.
2693
- superseded: { removed: [], kept: [] },
2694
2637
  backup: backupPath,
2695
2638
  installedTracks: [...ctx.spec.tracks].sort(),
2696
2639
  mcpServers: [],
@@ -2741,12 +2684,12 @@ function installCliNeutralAssets(manifestSpec, projectDir, templatesDir, baselin
2741
2684
  continue;
2742
2685
  }
2743
2686
  if (!isCliNeutralTarget(entry.target)) continue;
2744
- const source = join13(templatesDir, entry.source);
2745
- if (!existsSync14(source)) {
2687
+ const source = join12(templatesDir, entry.source);
2688
+ if (!existsSync13(source)) {
2746
2689
  result.skipped += 1;
2747
2690
  continue;
2748
2691
  }
2749
- copyFile(source, join13(projectDir, entry.target));
2692
+ copyFile(source, join12(projectDir, entry.target));
2750
2693
  result.filesCopied += 1;
2751
2694
  }
2752
2695
  return result;
@@ -2758,9 +2701,9 @@ function backupEditedPolicyFile(entryTarget, target, source, baseline) {
2758
2701
  if (!POLICY_DIRS.some(({ dir, ext }) => rel.startsWith(`${dir}/`) && rel.endsWith(ext))) {
2759
2702
  return null;
2760
2703
  }
2761
- if (!existsSync14(target)) return null;
2762
- const current = readFileSync13(target, "utf-8");
2763
- if (current === readFileSync13(source, "utf-8")) return null;
2704
+ if (!existsSync13(target)) return null;
2705
+ const current = readFileSync12(target, "utf-8");
2706
+ if (current === readFileSync12(source, "utf-8")) return null;
2764
2707
  const recorded = baseline.get(rel);
2765
2708
  if (recorded !== void 0 && recorded === hashContent(current)) return null;
2766
2709
  return backupFile(target);
@@ -2773,14 +2716,14 @@ function installClaudeBaseline(manifestSpec, projectDir, templatesDir, policyBas
2773
2716
  if (!entry.applies(manifestSpec)) {
2774
2717
  continue;
2775
2718
  }
2776
- const target = join13(projectDir, entry.target);
2719
+ const target = join12(projectDir, entry.target);
2777
2720
  if (isBaselineExcluded(entry.target, baselineExcluded)) {
2778
2721
  result.excluded.push(entry.target);
2779
- if (existsSync14(target)) result.excludedOnDisk.push(entry.target);
2722
+ if (existsSync13(target)) result.excludedOnDisk.push(entry.target);
2780
2723
  continue;
2781
2724
  }
2782
- const source = join13(templatesDir, entry.source);
2783
- if (!existsSync14(source)) {
2725
+ const source = join12(templatesDir, entry.source);
2726
+ if (!existsSync13(source)) {
2784
2727
  result.skipped += 1;
2785
2728
  continue;
2786
2729
  }
@@ -2791,7 +2734,7 @@ function installClaudeBaseline(manifestSpec, projectDir, templatesDir, policyBas
2791
2734
  }
2792
2735
  if (entry.type === "file") {
2793
2736
  if (entry.target === ".claude/settings.json") {
2794
- const backup = backupFileIfChanged(target, readFileSync13(source, "utf-8"));
2737
+ const backup = backupFileIfChanged(target, readFileSync12(source, "utf-8"));
2795
2738
  if (backup) {
2796
2739
  result.backups.push(backup);
2797
2740
  }
@@ -2815,8 +2758,8 @@ function installClaudeBaseline(manifestSpec, projectDir, templatesDir, policyBas
2815
2758
  }
2816
2759
  accumulateCategory(result.categories, entry);
2817
2760
  }
2818
- const hookDir = join13(projectDir, ".claude/hooks");
2819
- if (existsSync14(hookDir)) {
2761
+ const hookDir = join12(projectDir, ".claude/hooks");
2762
+ if (existsSync13(hookDir)) {
2820
2763
  chmodHooksSync(hookDir);
2821
2764
  }
2822
2765
  writeInstalledTracks(projectDir, manifestSpec.tracks);
@@ -2830,9 +2773,9 @@ function installClaudeBaseline(manifestSpec, projectDir, templatesDir, policyBas
2830
2773
  return result;
2831
2774
  }
2832
2775
  function harnessAnchorLog(projectDir) {
2833
- const anchor = join13(projectDir, HARNESS_ANCHOR_FILE);
2834
- if (!existsSync14(anchor)) return null;
2835
- return { path: HARNESS_ANCHOR_FILE, sha256: hashContent(readFileSync13(anchor, "utf-8")) };
2776
+ const anchor = join12(projectDir, HARNESS_ANCHOR_FILE);
2777
+ if (!existsSync13(anchor)) return null;
2778
+ return { path: HARNESS_ANCHOR_FILE, sha256: hashContent(readFileSync12(anchor, "utf-8")) };
2836
2779
  }
2837
2780
  function writeEnvironmentFiles(projectDir, tracks) {
2838
2781
  return {
@@ -2891,7 +2834,7 @@ function writeInstallLogSafe(ctx, externalFiles, external, rootClaudeMdLog, prev
2891
2834
  rootFiles
2892
2835
  );
2893
2836
  const skillFiles = collectSkillHashes(ctx.projectDir);
2894
- const policyFiles = collectPolicyHashes(ctx.projectDir, join13(ctx.harnessRoot, "templates"));
2837
+ const policyFiles = collectPolicyHashes(ctx.projectDir, join12(ctx.harnessRoot, "templates"));
2895
2838
  const merged = mergeExternalFiles(ctx.projectDir, previousLog?.externalFiles, externalFiles);
2896
2839
  writeInstallLog(ctx.projectDir, {
2897
2840
  ...log,
@@ -2907,11 +2850,11 @@ function writeInstallLogSafe(ctx, externalFiles, external, rootClaudeMdLog, prev
2907
2850
  }
2908
2851
  }
2909
2852
  function composeAndWriteMcp(harnessRoot, projectDir, spec) {
2910
- const mcpPath = join13(projectDir, ".mcp.json");
2911
- const created = !existsSync14(mcpPath);
2853
+ const mcpPath = join12(projectDir, ".mcp.json");
2854
+ const created = !existsSync13(mcpPath);
2912
2855
  const composed = composeMcpJson({
2913
- templateMcpPath: join13(harnessRoot, "templates/mcp.json"),
2914
- trackMapPath: join13(harnessRoot, "templates/track-mcp-map.tsv"),
2856
+ templateMcpPath: join12(harnessRoot, "templates/mcp.json"),
2857
+ trackMapPath: join12(harnessRoot, "templates/track-mcp-map.tsv"),
2915
2858
  existingPath: mcpPath,
2916
2859
  tracks: spec.tracks
2917
2860
  });
@@ -2964,15 +2907,15 @@ function accumulateCategory(cats, entry) {
2964
2907
  }
2965
2908
  }
2966
2909
  function writeInstalledTracks(projectDir, tracks) {
2967
- const path = join13(projectDir, ".claude/.installed-tracks");
2910
+ const path = join12(projectDir, ".claude/.installed-tracks");
2968
2911
  mkdirSync4(dirname4(path), { recursive: true });
2969
2912
  const sorted = [...new Set(tracks)].sort().join("\n");
2970
2913
  writeFileSync6(path, `${sorted}
2971
2914
  `);
2972
2915
  }
2973
2916
  function writeRootClaudeMd(projectDir, tracks, continuousSkills) {
2974
- const target = join13(projectDir, "CLAUDE.md");
2975
- const existing = existsSync14(target) ? readFileSync13(target, "utf-8") : null;
2917
+ const target = join12(projectDir, "CLAUDE.md");
2918
+ const existing = existsSync13(target) ? readFileSync12(target, "utf-8") : null;
2976
2919
  const content = upsertHarnessImport(existing, {
2977
2920
  projectName: basename5(projectDir),
2978
2921
  tracks,
@@ -3401,11 +3344,12 @@ function renderPhase1Rows(log, baseline, verbose = false, withEcc = false, claud
3401
3344
  );
3402
3345
  }
3403
3346
  for (const id of baseline.updateMode.retiredAgents) {
3347
+ const instead = RETIRED_AGENTS.find((a) => a.id === id)?.instead;
3404
3348
  log(
3405
3349
  assetRow(
3406
3350
  "skip",
3407
3351
  "agents",
3408
- `${id} \xB7 \uC774 \uB9B4\uB9AC\uC988\uC5D0\uC11C \uC740\uD1F4 \u2014 .claude/agents/${id}.md \uB97C \uC9C0\uC6CC\uB3C4 \uB41C\uB2E4 \xB7 Claude Code \uC758 \`/code-review\` \xB7 \`/security-review\` \uAC00 \uAC19\uC740 \uC77C\uC744 \uD55C\uB2E4`
3352
+ `${id} \xB7 \uC774 \uB9B4\uB9AC\uC988\uC5D0\uC11C \uC740\uD1F4 \u2014 .claude/agents/${id}.md \uB97C \uC9C0\uC6CC\uB3C4 \uB41C\uB2E4` + (instead === void 0 ? "" : ` \xB7 ${instead}`)
3409
3353
  )
3410
3354
  );
3411
3355
  }
@@ -3532,7 +3476,7 @@ function renderPhase1Rows(log, baseline, verbose = false, withEcc = false, claud
3532
3476
  phase1Row(
3533
3477
  "agents",
3534
3478
  cats.agents.length,
3535
- "SOD reviewer (opus, independent verifier) + 3 base",
3479
+ "independent verifier \xB7 implementation lane \xB7 domain lanes (track)",
3536
3480
  cats.agents
3537
3481
  );
3538
3482
  }
@@ -3546,7 +3490,7 @@ function renderPhase1Rows(log, baseline, verbose = false, withEcc = false, claud
3546
3490
  phase1Row(
3547
3491
  "skills",
3548
3492
  cats.skills.length,
3549
- "deep-research \xB7 ui-visual-review \xB7 eval-harness (modified)",
3493
+ "bundled methodology skills (track \xB7 opt-in)",
3550
3494
  cats.skills
3551
3495
  );
3552
3496
  }
@@ -3577,24 +3521,6 @@ function renderPhase1Rows(log, baseline, verbose = false, withEcc = false, claud
3577
3521
  )
3578
3522
  );
3579
3523
  }
3580
- if (baseline.superseded.removed.length > 0) {
3581
- log(
3582
- assetRow(
3583
- "success",
3584
- "superseded \u2014 cleaned",
3585
- `${baseline.superseded.removed.length} \u2014 ${baseline.superseded.removed.map((t) => t.replace(/^\.claude\//, "")).join(", ")} \xB7 \uB418\uB3CC\uB9AC\uB824\uBA74 \uADF8 \uC790\uC0B0 \uC5C6\uC774 \uC7AC\uC124\uCE58`
3586
- )
3587
- );
3588
- }
3589
- if (baseline.superseded.kept.length > 0) {
3590
- log(
3591
- assetRow(
3592
- "skip",
3593
- "superseded \u2014 kept",
3594
- `${baseline.superseded.kept.length} \u2014 ${baseline.superseded.kept.map((t) => t.replace(/^\.claude\//, "")).join(", ")} \xB7 \uC774\uBC88 \uC120\uD0DD\uC774 \uB300\uCCB4\uD588\uC9C0\uB9CC \uC9C0\uC6B0\uC9C0 \uC54A\uC558\uB2E4 (\uC81C\uAC70: agent-harness uninstall)`
3595
- )
3596
- );
3597
- }
3598
3524
  const TEMPLATES_COL = 28;
3599
3525
  if (baseline.rootClaudeMd) {
3600
3526
  const n = baseline.rootClaudeMd.tracks.length;
@@ -3874,8 +3800,8 @@ function registerInstallCommand(cli2) {
3874
3800
 
3875
3801
  // src/commands/list.ts
3876
3802
  init_esm_shims();
3877
- import { existsSync as existsSync15, readFileSync as readFileSync14 } from "fs";
3878
- import { join as join14, resolve as resolve3 } from "path";
3803
+ import { existsSync as existsSync14, readFileSync as readFileSync13 } from "fs";
3804
+ import { join as join13, resolve as resolve3 } from "path";
3879
3805
  function listAction(options = {}, deps = {}) {
3880
3806
  const log = deps.log ?? console.log;
3881
3807
  const err = deps.err ?? console.error;
@@ -3938,8 +3864,8 @@ function formatTemplateRows(log, projectDir) {
3938
3864
  const rows = [` ${c.dim(dirs.join(" "))}`];
3939
3865
  const rootMd = log.templates.rootClaudeMd;
3940
3866
  if (rootMd) {
3941
- const path = join14(projectDir, rootMd.path);
3942
- const modified = existsSync15(path) && hashContent(readFileSync14(path, "utf8")) !== rootMd.sha256;
3867
+ const path = join13(projectDir, rootMd.path);
3868
+ const modified = existsSync14(path) && hashContent(readFileSync13(path, "utf8")) !== rootMd.sha256;
3943
3869
  rows.push(
3944
3870
  modified ? ` ${c.dim(rootMd.path)} ${c.yellow("(\uC218\uC815\uB428 \u2014 uninstall \uC2DC \uBCF4\uC874)")}` : ` ${c.dim(rootMd.path)}`
3945
3871
  );
@@ -3947,7 +3873,7 @@ function formatTemplateRows(log, projectDir) {
3947
3873
  return rows;
3948
3874
  }
3949
3875
  function formatRootFileRows(rootFiles, projectDir) {
3950
- const present = rootFiles.filter((f) => existsSync15(join14(projectDir, f.path)));
3876
+ const present = rootFiles.filter((f) => existsSync14(join13(projectDir, f.path)));
3951
3877
  const width = Math.max(0, ...present.map((f) => f.path.length));
3952
3878
  return present.map(
3953
3879
  (f) => ` ${c.dim(padDisplay(f.path, width))} ${c.dim(f.change === "created" ? "\uC0DD\uC131" : "\uBCD1\uD569")} ${c.dim(f.notes.join(" / "))}`
@@ -3965,15 +3891,15 @@ function registerListCommand(cli2) {
3965
3891
  init_esm_shims();
3966
3892
  import { spawnSync as spawnSync2 } from "child_process";
3967
3893
  import {
3968
- existsSync as existsSync16,
3894
+ existsSync as existsSync15,
3969
3895
  lstatSync as lstatSync2,
3970
3896
  readdirSync as readdirSync5,
3971
- readFileSync as readFileSync15,
3897
+ readFileSync as readFileSync14,
3972
3898
  rmdirSync,
3973
3899
  rmSync,
3974
3900
  writeFileSync as writeFileSync7
3975
3901
  } from "fs";
3976
- import { dirname as dirname5, join as join15, relative as relative2, resolve as resolve4, sep as sep2 } from "path";
3902
+ import { dirname as dirname5, join as join14, relative as relative2, resolve as resolve4, sep as sep2 } from "path";
3977
3903
 
3978
3904
  // src/uninstall-interactive.ts
3979
3905
  init_esm_shims();
@@ -5213,7 +5139,7 @@ function settleLog(ctx, io) {
5213
5139
  return true;
5214
5140
  }
5215
5141
  } else {
5216
- io.rm(join15(projectDir, INSTALL_LOG_DIR));
5142
+ io.rm(join14(projectDir, INSTALL_LOG_DIR));
5217
5143
  io.rm(legacyInstallLogPath(projectDir));
5218
5144
  io.log(` ${status.success("install log removed")}`);
5219
5145
  }
@@ -5263,7 +5189,7 @@ function advisoryLines(plan, projectDir, rootFiles) {
5263
5189
  return lines;
5264
5190
  }
5265
5191
  function rootFileAdvisoryLines(rootFiles, projectDir) {
5266
- const present = rootFiles.filter((f) => existsSync16(join15(projectDir, f.path)));
5192
+ const present = rootFiles.filter((f) => existsSync15(join14(projectDir, f.path)));
5267
5193
  if (present.length === 0) return [];
5268
5194
  return [
5269
5195
  "",
@@ -5364,16 +5290,16 @@ function buildGlobalAdvisoryCmd(asset) {
5364
5290
  }
5365
5291
  }
5366
5292
  function removeTemplates(log, projectDir, rm) {
5367
- rm(join15(projectDir, log.templates.claudeDir));
5368
- if (log.templates.codexDir) rm(join15(projectDir, log.templates.codexDir));
5369
- if (log.templates.opencodeDir) rm(join15(projectDir, log.templates.opencodeDir));
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));
5370
5296
  const external = removeExternalFiles(log, projectDir, rm);
5371
5297
  const importStripped = stripRootImport(projectDir);
5372
5298
  const rootMd = log.templates.rootClaudeMd;
5373
5299
  if (rootMd) {
5374
5300
  if (rootClaudeMdModified(log, projectDir))
5375
5301
  return { rootClaudeMdKept: true, importStripped, external };
5376
- rm(join15(projectDir, rootMd.path));
5302
+ rm(join14(projectDir, rootMd.path));
5377
5303
  }
5378
5304
  return { rootClaudeMdKept: false, importStripped, external };
5379
5305
  }
@@ -5381,17 +5307,17 @@ function removeExternalFiles(log, projectDir, rm) {
5381
5307
  const removed = [];
5382
5308
  const kept = [];
5383
5309
  for (const { path, sha256 } of log.externalFiles ?? []) {
5384
- const abs = join15(projectDir, path);
5385
- if (!existsSync16(abs)) continue;
5310
+ const abs = join14(projectDir, path);
5311
+ if (!existsSync15(abs)) continue;
5386
5312
  if (!lstatSync2(abs).isFile()) continue;
5387
- if (hashContent(readFileSync15(abs, "utf8")) !== sha256) {
5313
+ if (hashContent(readFileSync14(abs, "utf8")) !== sha256) {
5388
5314
  kept.push(path);
5389
5315
  continue;
5390
5316
  }
5391
5317
  rm(abs);
5392
5318
  removed.push(path);
5393
5319
  }
5394
- for (const path of removed) pruneEmptyDirsUpward(projectDir, dirname5(join15(projectDir, path)));
5320
+ for (const path of removed) pruneEmptyDirsUpward(projectDir, dirname5(join14(projectDir, path)));
5395
5321
  return { removed, kept };
5396
5322
  }
5397
5323
  function pruneEmptyDirsUpward(projectDir, startDir) {
@@ -5413,7 +5339,7 @@ function stripRootImport(projectDir) {
5413
5339
  const stripped = current === null ? null : stripHarnessImport(current);
5414
5340
  if (stripped === null) return false;
5415
5341
  try {
5416
- writeFileSync7(join15(projectDir, "CLAUDE.md"), stripped, "utf8");
5342
+ writeFileSync7(join14(projectDir, "CLAUDE.md"), stripped, "utf8");
5417
5343
  return true;
5418
5344
  } catch {
5419
5345
  return false;
@@ -5423,9 +5349,9 @@ function previewExternalLines(installLog, projectDir) {
5423
5349
  const lines = [];
5424
5350
  let removable = 0;
5425
5351
  for (const { path, sha256 } of installLog.externalFiles ?? []) {
5426
- const abs = join15(projectDir, path);
5427
- if (!existsSync16(abs)) continue;
5428
- if (hashContent(readFileSync15(abs, "utf8")) !== sha256) {
5352
+ const abs = join14(projectDir, path);
5353
+ if (!existsSync15(abs)) continue;
5354
+ if (hashContent(readFileSync14(abs, "utf8")) !== sha256) {
5429
5355
  lines.push(` \u25CB keep ${path} (modified since install \u2014 preserved)`);
5430
5356
  continue;
5431
5357
  }
@@ -5451,10 +5377,10 @@ function hasRootImport(projectDir) {
5451
5377
  return current !== null && stripHarnessImport(current) !== null;
5452
5378
  }
5453
5379
  function readRootClaudeMd(projectDir) {
5454
- const path = join15(projectDir, "CLAUDE.md");
5455
- if (!existsSync16(path)) return null;
5380
+ const path = join14(projectDir, "CLAUDE.md");
5381
+ if (!existsSync15(path)) return null;
5456
5382
  try {
5457
- return readFileSync15(path, "utf8");
5383
+ return readFileSync14(path, "utf8");
5458
5384
  } catch {
5459
5385
  return null;
5460
5386
  }
@@ -5462,9 +5388,9 @@ function readRootClaudeMd(projectDir) {
5462
5388
  function rootClaudeMdModified(log, projectDir) {
5463
5389
  const rootMd = log.templates.rootClaudeMd;
5464
5390
  if (!rootMd) return false;
5465
- const path = join15(projectDir, rootMd.path);
5466
- if (!existsSync16(path)) return false;
5467
- return hashContent(readFileSync15(path, "utf8")) !== rootMd.sha256;
5391
+ const path = join14(projectDir, rootMd.path);
5392
+ if (!existsSync15(path)) return false;
5393
+ return hashContent(readFileSync14(path, "utf8")) !== rootMd.sha256;
5468
5394
  }
5469
5395
  function formatTemplateList(log) {
5470
5396
  const items = [log.templates.claudeDir];
@@ -5476,7 +5402,7 @@ function defaultSpawn2(cmd, args) {
5476
5402
  return spawnSync2(cmd, [...args], { encoding: "utf8", stdio: "pipe", timeout: 12e4 });
5477
5403
  }
5478
5404
  function defaultRm(path) {
5479
- if (existsSync16(path)) {
5405
+ if (existsSync15(path)) {
5480
5406
  rmSync(path, { recursive: true, force: true });
5481
5407
  }
5482
5408
  }
@@ -5524,8 +5450,8 @@ import { resolve as resolve5 } from "path";
5524
5450
 
5525
5451
  // src/state.ts
5526
5452
  init_esm_shims();
5527
- import { existsSync as existsSync17, readFileSync as readFileSync16 } from "fs";
5528
- import { join as join16 } from "path";
5453
+ import { existsSync as existsSync16, readFileSync as readFileSync15 } from "fs";
5454
+ import { join as join15 } from "path";
5529
5455
  var META_FILE = ".claude/.installed-tracks";
5530
5456
  var LEGACY_SIGNATURES = [
5531
5457
  { rule: "htmx.md", track: "ssr-htmx" },
@@ -5535,11 +5461,11 @@ var LEGACY_SIGNATURES = [
5535
5461
  { rule: "cli-development.md", track: "tooling" }
5536
5462
  ];
5537
5463
  function detectInstallState(projectDir) {
5538
- const claudeDir = join16(projectDir, ".claude");
5539
- const hasClaudeDir = existsSync17(claudeDir);
5464
+ const claudeDir = join15(projectDir, ".claude");
5465
+ const hasClaudeDir = existsSync16(claudeDir);
5540
5466
  if (hasClaudeDir) {
5541
- const metaPath = join16(projectDir, META_FILE);
5542
- if (existsSync17(metaPath)) {
5467
+ const metaPath = join15(projectDir, META_FILE);
5468
+ if (existsSync16(metaPath)) {
5543
5469
  const tracks2 = readMetafile(metaPath);
5544
5470
  return { state: "existing", tracks: tracks2, source: "metafile", hasClaudeDir: true };
5545
5471
  }
@@ -5561,7 +5487,7 @@ function tracksFromLog(tracks) {
5561
5487
  return [...new Set(tracks.filter(isTrack))].sort();
5562
5488
  }
5563
5489
  function readMetafile(path) {
5564
- const raw = readFileSync16(path, "utf8");
5490
+ const raw = readFileSync15(path, "utf8");
5565
5491
  const seen = /* @__PURE__ */ new Set();
5566
5492
  for (const line of raw.split(/\s+/)) {
5567
5493
  const trimmed = line.trim();
@@ -5572,13 +5498,13 @@ function readMetafile(path) {
5572
5498
  return [...seen].sort();
5573
5499
  }
5574
5500
  function inferFromLegacySignatures(projectDir) {
5575
- const rulesDir = join16(projectDir, ".claude/rules");
5576
- if (!existsSync17(rulesDir)) {
5501
+ const rulesDir = join15(projectDir, ".claude/rules");
5502
+ if (!existsSync16(rulesDir)) {
5577
5503
  return [];
5578
5504
  }
5579
5505
  const found = /* @__PURE__ */ new Set();
5580
5506
  for (const sig of LEGACY_SIGNATURES) {
5581
- if (existsSync17(join16(rulesDir, sig.rule))) {
5507
+ if (existsSync16(join15(rulesDir, sig.rule))) {
5582
5508
  found.add(sig.track);
5583
5509
  }
5584
5510
  }
@@ -5890,23 +5816,6 @@ Proceed?`,
5890
5816
  });
5891
5817
  return q(result) ? null : result;
5892
5818
  },
5893
- confirmSupersededCleanup: async (items, context) => {
5894
- const names = items.map((i) => i.target.replace(/^\.claude\//, "")).join("\n ");
5895
- const result = await ue({
5896
- message: [
5897
- `${context.by.join(" \xB7 ")} \uC744(\uB97C) \uACE8\uB77C\uC11C \uC544\uB798 ${items.length}\uAC1C\uAC00 \uC124\uCE58 \uB300\uC0C1\uC5D0\uC11C \uBE60\uC84C\uC2B5\uB2C8\uB2E4.`,
5898
- "\uADF8\uB7F0\uB370 \uC774\uC804 \uC124\uCE58\uBCF8\uC774 \uB514\uC2A4\uD06C\uC5D0 \uADF8\uB300\uB85C \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4:",
5899
- ` ${names}`,
5900
- "",
5901
- `\uADF8\uB300\uB85C \uB450\uBA74 \uAC19\uC740 \uC77C\uC744 \uD558\uB294 \uC5D0\uC774\uC804\uD2B8\uAC00 \uB450 \uBC8C\uC774\uACE0, \uB9E4 \uC138\uC158 ~${context.tokens} tok \uB97C \uACC4\uC18D \uBB45\uB2C8\uB2E4.`,
5902
- "(\uD558\uB124\uC2A4\uAC00 \uAE54\uC558\uACE0 \uC218\uC815\uB418\uC9C0 \uC54A\uC740 \uD30C\uC77C\uB9CC \uB300\uC0C1\uC785\uB2C8\uB2E4 \u2014 \uC9C1\uC811 \uACE0\uCE5C \uD30C\uC77C\uC740 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4)",
5903
- "",
5904
- "\uC815\uB9AC\uD560\uAE4C\uC694?"
5905
- ].join("\n"),
5906
- initialValue: true
5907
- });
5908
- return q(result) ? null : result;
5909
- },
5910
5819
  selectInstallTargets: async (initialChecked, step, recap) => {
5911
5820
  const pages = INSTALL_TARGET_PAGES;
5912
5821
  const baselineTargets = listBaselineTargets({ tracks: recap?.tracks ?? [] });
@@ -6172,50 +6081,11 @@ ${summary}`
6172
6081
  ...userOverride ? { userOverride } : {},
6173
6082
  ...baselineExclude.length > 0 ? { baselineExclude } : {}
6174
6083
  };
6175
- const superseded = findSuperseded(
6176
- projectDir,
6177
- buildManifestSpec(spec),
6178
- readInstallLog(projectDir)
6179
- );
6180
- let cleanSuperseded = false;
6181
- if (superseded.length > 0) {
6182
- const cause = supersededCause(projectDir, spec, readInstallLog(projectDir), superseded);
6183
- const answer = await prompts.confirmSupersededCleanup(superseded, {
6184
- by: cause.length > 0 ? cause : ["\uC774\uBC88 \uC120\uD0DD"],
6185
- tokens: supersededTokens(superseded)
6186
- });
6187
- if (answer === null) {
6188
- step = "confirm";
6189
- continue;
6190
- }
6191
- cleanSuperseded = answer;
6192
- }
6193
6084
  prompts.outro(stepLabel(WIZARD.INSTALL, "Installing..."));
6194
- return {
6195
- ok: true,
6196
- mode,
6197
- spec: { ...spec, ...cleanSuperseded ? { cleanSuperseded } : {} }
6198
- };
6085
+ return { ok: true, mode, spec };
6199
6086
  }
6200
6087
  }
6201
6088
  }
6202
- function supersededTokens(items) {
6203
- const r = residentCost(items.map((i) => ({ source: i.source, target: i.target })));
6204
- return r.rules + r.agentDescriptors + r.skillDescriptors;
6205
- }
6206
- function supersededCause(projectDir, spec, log, found) {
6207
- const selected = spec.userOverride?.forceInclude ?? [];
6208
- return selected.filter((id) => {
6209
- const without = {
6210
- ...spec,
6211
- userOverride: {
6212
- forceInclude: selected.filter((x) => x !== id),
6213
- forceExclude: [...spec.userOverride?.forceExclude ?? [], id]
6214
- }
6215
- };
6216
- return findSuperseded(projectDir, buildManifestSpec(without), log).length < found.length;
6217
- });
6218
- }
6219
6089
  function tracksEqual(a, b2) {
6220
6090
  if (a.length !== b2.length) return false;
6221
6091
  const sortedA = [...a].sort();