@kanadego/dsh-heartbeat 1.5.0 → 1.6.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.
@@ -1,8 +1,12 @@
1
1
  import {
2
- loadEncryptedText,
2
+ activeSeeds,
3
+ loadPool,
4
+ normalizeCategory,
5
+ seedsFilePath
6
+ } from "./chunk-SVP2NDRF.js";
7
+ import {
3
8
  loadJson,
4
9
  readText,
5
- saveEncryptedText,
6
10
  saveJson,
7
11
  writeText
8
12
  } from "./chunk-LLD7LUNN.js";
@@ -244,229 +248,12 @@ function loadPolicy(guard, configDir, settingsDir) {
244
248
  return merged;
245
249
  }
246
250
 
247
- // src/seeds/pool.ts
248
- import path5 from "path";
249
-
250
- // src/seeds/types.ts
251
- function emptySeedDb() {
252
- return { seq: 0, seeds: [] };
253
- }
254
- var SEED_SOURCE_DEFAULT_CONFIDENCE = {
255
- hand: 1,
256
- profile: 0.7,
257
- chat: 0.6,
258
- screen: 0.4,
259
- browse: 0.4
260
- };
261
-
262
- // src/seeds/pool.ts
263
- var DAY_MS = 864e5;
264
- var TTL_KEYS = ["news", "fandom", "scene", "promise"];
265
- function normalizeTag(tag) {
266
- if (tag && TTL_KEYS.includes(tag)) return tag;
267
- return "scene";
268
- }
269
- function parseIso(v) {
270
- const t = Date.parse(v);
271
- return Number.isFinite(t) ? t : 0;
272
- }
273
- function seedsFilePath(dataDir) {
274
- return path5.join(dataDir, "seeds.jsonl");
275
- }
276
- function loadPool(guard, file) {
277
- const raw = loadEncryptedText(guard, file);
278
- if (raw === null) return emptySeedDb();
279
- const db = emptySeedDb();
280
- for (const line of raw.split("\n")) {
281
- const trimmed = line.trim();
282
- if (!trimmed) continue;
283
- try {
284
- const obj = JSON.parse(trimmed);
285
- if (typeof obj.id === "string" && obj.id.startsWith("s")) {
286
- db.seeds.push(obj);
287
- const n = Number(obj.id.slice(1));
288
- if (Number.isFinite(n) && n > db.seq) db.seq = n;
289
- }
290
- } catch {
291
- }
292
- }
293
- return db;
294
- }
295
- function savePool(guard, file, db) {
296
- const body = db.seeds.map((s) => JSON.stringify(s)).join("\n");
297
- saveEncryptedText(guard, file, body ? body + "\n" : "");
298
- }
299
- var activeSeeds = (db) => db.seeds.filter((s) => s.status === "active");
300
- var archivedSeeds = (db) => db.seeds.filter((s) => s.status === "archived");
301
- function evictionScore(seed, policy, now) {
302
- const ttlDays = policy.seeds.ttlDays[seed.tag] || 14;
303
- const daysStale = Math.max(0, (now - parseIso(seed.lastEvidenceAt)) / DAY_MS);
304
- const freshness = Math.max(0, 1 - daysStale / ttlDays);
305
- const unused = seed.used === 0 ? 1 : 1 / seed.used;
306
- const w = policy.seeds.scoreWeights;
307
- return freshness * w.freshness + unused * w.unused + seed.confidence * w.confidence;
308
- }
309
- function pickEvictionVictim(db, policy, now) {
310
- const actives = activeSeeds(db);
311
- if (actives.length === 0) return null;
312
- const unprotected = actives.filter((s) => !s.protected);
313
- const candidates = unprotected.length > 0 ? unprotected : actives;
314
- let worst = null;
315
- let worstScore = Number.POSITIVE_INFINITY;
316
- for (const s of candidates) {
317
- const score = evictionScore(s, policy, now);
318
- if (score < worstScore) {
319
- worstScore = score;
320
- worst = s;
321
- }
322
- }
323
- return worst;
324
- }
325
- function archiveSeed(seed, reason, now) {
326
- seed.status = "archived";
327
- seed.retireReason = reason;
328
- seed.retiredAt = new Date(now).toISOString();
329
- }
330
- function addSeed(guard, file, policy, input, now = Date.now()) {
331
- const db = loadPool(guard, file);
332
- const text = input.text.trim();
333
- if (!text) throw new Error("seed text must not be empty");
334
- const tag = normalizeTag(input.tag);
335
- const source = input.source ?? "chat";
336
- const confidence = input.confidence ?? SEED_SOURCE_DEFAULT_CONFIDENCE[source];
337
- const dup = activeSeeds(db).find((s) => s.text === text);
338
- if (dup) return { kind: "duplicate", seed: dup };
339
- const nowIso = new Date(now).toISOString();
340
- const ttlMs = (policy.seeds.ttlDays[tag] || 14) * DAY_MS;
341
- const sameTopic = activeSeeds(db).filter((s) => s.topic === (input.topic ?? text.slice(0, 24)));
342
- let seed;
343
- if (sameTopic.length > 0) {
344
- const kept = sameTopic[0];
345
- kept.text = text;
346
- kept.tag = tag;
347
- kept.source = source;
348
- kept.confidence = Math.max(kept.confidence, confidence);
349
- kept.used = sameTopic.reduce((acc, s) => acc + s.used, 0);
350
- kept.lastEvidenceAt = [kept.lastEvidenceAt, nowIso, ...sameTopic.map((s) => s.lastEvidenceAt)].reduce((a, b) => parseIso(b) > parseIso(a) ? b : a);
351
- kept.expiresAt = new Date(Math.max(parseIso(kept.expiresAt), now + ttlMs)).toISOString();
352
- kept.protected = kept.protected || source === "hand" || source === "profile" && confidence >= 0.7;
353
- for (const extra of sameTopic.slice(1)) {
354
- extra.status = "archived";
355
- extra.retireReason = "completed";
356
- extra.retiredAt = nowIso;
357
- }
358
- seed = kept;
359
- if (activeSeeds(db).length > policy.seeds.maxActive) {
360
- const victim = pickEvictionVictim(db, policy, now);
361
- if (victim && victim.id !== kept.id) {
362
- archiveSeed(victim, "pool_cap", now);
363
- savePool(guard, file, db);
364
- return { kind: "merged", seed: kept, evicted: victim };
365
- }
366
- }
367
- savePool(guard, file, db);
368
- return { kind: "merged", seed: kept };
369
- }
370
- let evicted;
371
- if (activeSeeds(db).length >= policy.seeds.maxActive) {
372
- const victim = pickEvictionVictim(db, policy, now);
373
- if (victim) {
374
- archiveSeed(victim, "pool_cap", now);
375
- evicted = victim;
376
- }
377
- }
378
- db.seq += 1;
379
- seed = {
380
- id: `s${db.seq}`,
381
- text,
382
- topic: input.topic ?? text.slice(0, 24),
383
- tag,
384
- source,
385
- confidence,
386
- protected: source === "hand" || source === "profile" && confidence >= 0.7,
387
- used: 0,
388
- bornAt: nowIso,
389
- expiresAt: new Date(now + ttlMs).toISOString(),
390
- lastUsedAt: null,
391
- lastEvidenceAt: nowIso,
392
- status: "active"
393
- };
394
- db.seeds.push(seed);
395
- savePool(guard, file, db);
396
- return { kind: "added", seed, evicted };
397
- }
398
- function gcPool(guard, file, policy, now = Date.now()) {
399
- const db = loadPool(guard, file);
400
- const report = { consumed: 0, expired: 0, coldBench: 0, activeAfter: 0 };
401
- for (const s of activeSeeds(db)) {
402
- const ageMs = now - parseIso(s.bornAt);
403
- const sinceEvidence = parseIso(s.lastEvidenceAt);
404
- const sinceUsed = s.lastUsedAt ? parseIso(s.lastUsedAt) : 0;
405
- if (s.used >= policy.seeds.retireAfterUsed && sinceEvidence <= sinceUsed) {
406
- archiveSeed(s, "consumed", now);
407
- report.consumed += 1;
408
- } else if (now > parseIso(s.expiresAt)) {
409
- archiveSeed(s, "expired", now);
410
- report.expired += 1;
411
- } else if (s.used === 0 && ageMs >= policy.seeds.coldBenchDays * DAY_MS) {
412
- archiveSeed(s, "cold_bench", now);
413
- report.coldBench += 1;
414
- }
415
- }
416
- report.activeAfter = activeSeeds(db).length;
417
- savePool(guard, file, db);
418
- return report;
419
- }
420
- function surfaceSeed(guard, file, policy, id, now = Date.now()) {
421
- const db = loadPool(guard, file);
422
- const s = db.seeds.find((x) => x.id === id && x.status === "active");
423
- if (!s) return null;
424
- s.used += 1;
425
- s.lastUsedAt = new Date(now).toISOString();
426
- if (s.used >= policy.seeds.retireAfterUsed && parseIso(s.lastEvidenceAt) <= parseIso(s.lastUsedAt)) {
427
- archiveSeed(s, "consumed", now);
428
- }
429
- savePool(guard, file, db);
430
- return s;
431
- }
432
- function archiveSeedById(guard, file, id, reason = "completed", now = Date.now()) {
433
- const db = loadPool(guard, file);
434
- const s = db.seeds.find((x) => x.id === id && x.status === "active");
435
- if (!s) return null;
436
- archiveSeed(s, reason, now);
437
- savePool(guard, file, db);
438
- return s;
439
- }
440
- function restoreSeed(guard, file, policy, id, now = Date.now()) {
441
- const db = loadPool(guard, file);
442
- const s = db.seeds.find((x) => x.id === id && x.status === "archived");
443
- if (!s) return { ok: false, reason: "archived seed not found" };
444
- if (activeSeeds(db).length >= policy.seeds.maxActive) {
445
- return { ok: false, reason: `pool full (${policy.seeds.maxActive}); archive something first` };
446
- }
447
- s.status = "active";
448
- s.retireReason = void 0;
449
- s.retiredAt = void 0;
450
- s.expiresAt = new Date(now + (policy.seeds.ttlDays[s.tag] || 14) * DAY_MS).toISOString();
451
- s.lastEvidenceAt = new Date(now).toISOString();
452
- savePool(guard, file, db);
453
- return { ok: true, seed: s };
454
- }
455
- function deleteSeed(guard, file, id) {
456
- const db = loadPool(guard, file);
457
- const before = db.seeds.length;
458
- db.seeds = db.seeds.filter((x) => x.id !== id);
459
- if (db.seeds.length === before) return false;
460
- savePool(guard, file, db);
461
- return true;
462
- }
463
-
464
251
  // src/ledger/ledger.ts
465
- import path6 from "path";
252
+ import path5 from "path";
466
253
  import { randomUUID as randomUUID2 } from "crypto";
467
- var DAY_MS2 = 864e5;
254
+ var DAY_MS = 864e5;
468
255
  function ledgerFilePath(dataDir) {
469
- return path6.join(dataDir, "ledger.md");
256
+ return path5.join(dataDir, "ledger.md");
470
257
  }
471
258
  var LINE_RE = /^- \[(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2})\]\[(open|done)\]\[#([0-9a-f]{6})\] (.*)$/;
472
259
  function renderEntry(e) {
@@ -523,20 +310,20 @@ function scanPending(guard, file, now = Date.now()) {
523
310
  return entries.filter((e) => e.status === "open").sort((a, b) => a.date < b.date ? -1 : 1);
524
311
  }
525
312
  function pendingOlderThan(guard, file, days, now = Date.now()) {
526
- const cutoff = new Date(now - days * DAY_MS2).toISOString().slice(0, 10);
313
+ const cutoff = new Date(now - days * DAY_MS).toISOString().slice(0, 10);
527
314
  return scanPending(guard, file, now).filter((e) => e.date <= cutoff);
528
315
  }
529
316
 
530
317
  // src/browse/browse.ts
531
318
  import fs5 from "fs";
532
- import path7 from "path";
319
+ import path6 from "path";
533
320
  var WATCH_THROTTLE_MS = 6 * 36e5;
534
321
  var UA = { "User-Agent": "dsh-heartbeat/2.0 (+local; personal companion)" };
535
322
  function emptyBrowseState() {
536
- return { targets: {}, last_check_at: 0, wander: { focusHistory: {}, focusCount: {}, last_wander_at: 0 } };
323
+ return { targets: {}, last_check_at: 0, wander: { focusHistory: {}, focusCount: {}, last_wander_at: 0, refillCount: {} } };
537
324
  }
538
325
  function browseStatePath(paths) {
539
- return path7.join(paths.dataDir, "browse.json");
326
+ return path6.join(paths.dataDir, "browse.json");
540
327
  }
541
328
  function readJsonFile(file, fallback) {
542
329
  try {
@@ -546,14 +333,14 @@ function readJsonFile(file, fallback) {
546
333
  }
547
334
  }
548
335
  function loadInterests(paths) {
549
- const userPath = path7.join(paths.settingsDir, "interests.json");
336
+ const userPath = path6.join(paths.settingsDir, "interests.json");
550
337
  if (fs5.existsSync(userPath)) return readJsonFile(userPath, { interests: [], _schedule: {} });
551
- return readJsonFile(path7.join(paths.configDir, "interests.json"), { interests: [], _schedule: {} });
338
+ return readJsonFile(path6.join(paths.configDir, "interests.json"), { interests: [], _schedule: {} });
552
339
  }
553
340
  function loadWatchlist(paths) {
554
- const userPath = path7.join(paths.settingsDir, "watchlist.json");
341
+ const userPath = path6.join(paths.settingsDir, "watchlist.json");
555
342
  if (fs5.existsSync(userPath)) return readJsonFile(userPath, { targets: [] });
556
- return readJsonFile(path7.join(paths.configDir, "watchlist.json"), { targets: [] });
343
+ return readJsonFile(path6.join(paths.configDir, "watchlist.json"), { targets: [] });
557
344
  }
558
345
  function loadState(guard, paths) {
559
346
  return loadJson(guard, browseStatePath(paths)) ?? emptyBrowseState();
@@ -646,20 +433,53 @@ function adviseWander(guard, paths, policy, now = /* @__PURE__ */ new Date()) {
646
433
  if (!focus) return { focus: null, query: null, skipped: "no-focus" };
647
434
  return { focus, query: `${focus} 2026 \u6700\u65B0`, skipped: null };
648
435
  }
649
- function completeWander(guard, paths, focus, now = Date.now()) {
436
+ function completeWander(guard, paths, focus, now = Date.now(), opts = {}) {
650
437
  const state = loadState(guard, paths);
651
438
  state.wander.focusHistory[focus] = now;
652
439
  state.wander.focusCount[focus] = (state.wander.focusCount[focus] ?? 0) + 1;
653
440
  state.wander.last_wander_at = now;
441
+ let refillsToday;
442
+ if (opts.refill) {
443
+ const today = localDayKey(new Date(now));
444
+ state.wander.refillCount = state.wander.refillCount ?? {};
445
+ state.wander.refillCount[today] = (state.wander.refillCount[today] ?? 0) + 1;
446
+ refillsToday = state.wander.refillCount[today];
447
+ }
654
448
  saveJson(guard, browseStatePath(paths), state);
655
- return { focus, count: state.wander.focusCount[focus] };
449
+ return { focus, count: state.wander.focusCount[focus], ...refillsToday === void 0 ? {} : { refillsToday } };
450
+ }
451
+ function localDayKey(d) {
452
+ const y = d.getFullYear();
453
+ const m = String(d.getMonth() + 1).padStart(2, "0");
454
+ const day = String(d.getDate()).padStart(2, "0");
455
+ return `${y}-${m}-${day}`;
456
+ }
457
+ var REFILL_TOPIC_THRESHOLD = 4;
458
+ var REFILL_MAX_PER_DAY = 2;
459
+ function adviseRefillWander(guard, paths, policy, now = /* @__PURE__ */ new Date()) {
460
+ const state = loadState(guard, paths);
461
+ const today = localDayKey(now);
462
+ const refillsToday = state.wander.refillCount?.[today] ?? 0;
463
+ const topicCount = activeSeeds(loadPool(guard, seedsFilePath(paths.dataDir))).filter((s) => normalizeCategory(s.category) === "topic").length;
464
+ if (refillsToday >= REFILL_MAX_PER_DAY) {
465
+ return { focus: null, query: null, skipped: `refill-daily-cap(${refillsToday})`, topicCount, refillsToday };
466
+ }
467
+ if (topicCount > REFILL_TOPIC_THRESHOLD) {
468
+ return { focus: null, query: null, skipped: `topic-stock-ok(${topicCount})`, topicCount, refillsToday };
469
+ }
470
+ const interests = loadInterests(paths);
471
+ const focus = pickFocus(state, interests, now.getTime());
472
+ if (!focus) {
473
+ return { focus: null, query: null, skipped: "no-focus", topicCount, refillsToday };
474
+ }
475
+ return { focus, query: `${focus} 2026 \u6700\u65B0`, skipped: null, topicCount, refillsToday };
656
476
  }
657
477
  function browseStatus(guard, paths) {
658
478
  return loadState(guard, paths);
659
479
  }
660
480
 
661
481
  // src/profile/store.ts
662
- import path9 from "path";
482
+ import path8 from "path";
663
483
  import { randomUUID as randomUUID3 } from "crypto";
664
484
  import fs7 from "fs";
665
485
 
@@ -681,10 +501,10 @@ function emptyProfile() {
681
501
 
682
502
  // src/profile/schema.ts
683
503
  import fs6 from "fs";
684
- import path8 from "path";
504
+ import path7 from "path";
685
505
  function loadProfileSchema(paths) {
686
- const userPath = path8.join(paths.settingsDir, "profile-schema.json");
687
- const file = fs6.existsSync(userPath) ? userPath : path8.join(paths.configDir, "profile-schema.json");
506
+ const userPath = path7.join(paths.settingsDir, "profile-schema.json");
507
+ const file = fs6.existsSync(userPath) ? userPath : path7.join(paths.configDir, "profile-schema.json");
688
508
  try {
689
509
  const raw = JSON.parse(fs6.readFileSync(file, "utf8"));
690
510
  if (!raw.partitions) throw new Error("partitions missing");
@@ -714,12 +534,12 @@ function checkAddAgainstSchema(schema, partition, topic, subTopic, nominated) {
714
534
  }
715
535
 
716
536
  // src/profile/store.ts
717
- var DAY_MS3 = 864e5;
537
+ var DAY_MS2 = 864e5;
718
538
  function profileFilePath(dataDir) {
719
- return path9.join(dataDir, "profile.json");
539
+ return path8.join(dataDir, "profile.json");
720
540
  }
721
541
  function journalFilePath(dataDir) {
722
- return path9.join(dataDir, "profile_journal.jsonl");
542
+ return path8.join(dataDir, "profile_journal.jsonl");
723
543
  }
724
544
  function loadProfile(guard, file) {
725
545
  const doc = loadJson(guard, file);
@@ -729,14 +549,14 @@ function loadProfile(guard, file) {
729
549
  }
730
550
  return doc;
731
551
  }
732
- function parseIso2(v) {
552
+ function parseIso(v) {
733
553
  const t = Date.parse(v);
734
554
  return Number.isFinite(t) ? t : 0;
735
555
  }
736
556
  function refExists(guard, dataDir, ref) {
737
557
  const base = ref.split("#")[0] ?? "";
738
558
  if (!base) return false;
739
- const target = path9.join(dataDir, base);
559
+ const target = path8.join(dataDir, base);
740
560
  try {
741
561
  return fs7.existsSync(guard.assert(target));
742
562
  } catch {
@@ -840,7 +660,7 @@ function applyOpsToDoc(guard, dataDir, doc, ops, schema, policy, now) {
840
660
  rejected.push({ op, reason: "volatile expiry is code-owned (time-driven), not LLM-nominated" });
841
661
  continue;
842
662
  }
843
- const hasNewObservation = (op.evidence ?? []).length > 0 && (op.evidence ?? []).some((e) => parseIso2(e.at) > parseIso2(entry.evidence[entry.evidence.length - 1]?.at ?? ""));
663
+ const hasNewObservation = (op.evidence ?? []).length > 0 && (op.evidence ?? []).some((e) => parseIso(e.at) > parseIso(entry.evidence[entry.evidence.length - 1]?.at ?? ""));
844
664
  if (!hasNewObservation) {
845
665
  rejected.push({ op, reason: "stable INVALIDATE requires a newer contradicting observation" });
846
666
  continue;
@@ -864,15 +684,15 @@ function runDeterministicAging(doc, policy, now) {
864
684
  for (const p of PARTITIONS) {
865
685
  for (const e of doc.partitions[p].entries) {
866
686
  if (e.validTo !== null) continue;
867
- const lastEvidence = Math.max(...e.evidence.map((x) => parseIso2(x.at)), parseIso2(e.updatedAt));
687
+ const lastEvidence = Math.max(...e.evidence.map((x) => parseIso(x.at)), parseIso(e.updatedAt));
868
688
  if (e.temporal === "volatile") {
869
- if (now - lastEvidence > policy.profile.volatileDays * DAY_MS3) {
689
+ if (now - lastEvidence > policy.profile.volatileDays * DAY_MS2) {
870
690
  e.validTo = nowIso;
871
691
  e.updatedAt = nowIso;
872
692
  e.updateCount += 1;
873
693
  volatileExpired += 1;
874
694
  }
875
- } else if (!e.lowActivity && now - lastEvidence > policy.profile.stableLowActivityDays * DAY_MS3) {
695
+ } else if (!e.lowActivity && now - lastEvidence > policy.profile.stableLowActivityDays * DAY_MS2) {
876
696
  e.lowActivity = true;
877
697
  lowActivityMarked += 1;
878
698
  }
@@ -979,7 +799,7 @@ function verifyProfile(guard, dataDir) {
979
799
  function rebuildProfile(guard, dataDir, opts = {}) {
980
800
  const replayed = replayJournal(guard, dataDir);
981
801
  const target = profileFilePath(dataDir);
982
- const tmp = path9.join(dataDir, `.profile.rebuild.${Date.now()}.tmp`);
802
+ const tmp = path8.join(dataDir, `.profile.rebuild.${Date.now()}.tmp`);
983
803
  atomicWriteFileSync(tmp, JSON.stringify(replayed.doc, null, 2));
984
804
  if (opts.check) {
985
805
  const onDisk = loadProfile(guard, target);
@@ -997,7 +817,7 @@ function rebuildProfile(guard, dataDir, opts = {}) {
997
817
  if (replayed.truncatedTail > 0) {
998
818
  writeText(
999
819
  guard,
1000
- path9.join(dataDir, "logs", "rebuild-report.txt"),
820
+ path8.join(dataDir, "logs", "rebuild-report.txt"),
1001
821
  `rebuild truncated ${replayed.truncatedTail} torn line(s) at journal tail; ${replayed.records} records applied
1002
822
  `
1003
823
  );
@@ -1007,11 +827,11 @@ function rebuildProfile(guard, dataDir, opts = {}) {
1007
827
 
1008
828
  // src/notify/notify.ts
1009
829
  import { spawnSync } from "child_process";
1010
- import path10 from "path";
830
+ import path9 from "path";
1011
831
  function runNotify(paths, args) {
1012
832
  const r = spawnSync(
1013
833
  "powershell.exe",
1014
- ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", path10.join(paths.assetsDir, "notify.ps1"), ...args],
834
+ ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", path9.join(paths.assetsDir, "notify.ps1"), ...args],
1015
835
  { timeout: 2e4, encoding: "utf8" }
1016
836
  );
1017
837
  return { status: r.status ?? -1, out: `${r.stdout ?? ""}${r.stderr ?? ""}`.trim() };
@@ -1030,7 +850,7 @@ function sendNewMessageHint(paths) {
1030
850
  // src/core/preset-install.ts
1031
851
  import fs8 from "fs";
1032
852
  import os from "os";
1033
- import path11 from "path";
853
+ import path10 from "path";
1034
854
  import { fileURLToPath } from "url";
1035
855
  var COMPOSITION_FILE = "agent.cordis.yml";
1036
856
  var METADATA_FILE = "preset.yml";
@@ -1038,14 +858,14 @@ var BUNDLED_PRESET_ID = "heartbeat";
1038
858
  function bundledPresetDir(moduleUrl, id = BUNDLED_PRESET_ID) {
1039
859
  let dir;
1040
860
  try {
1041
- dir = path11.dirname(fileURLToPath(moduleUrl));
861
+ dir = path10.dirname(fileURLToPath(moduleUrl));
1042
862
  } catch {
1043
863
  return void 0;
1044
864
  }
1045
865
  for (let depth = 0; depth < 5; depth += 1) {
1046
- const candidate = path11.join(dir, "assets", "presets", id);
1047
- if (fs8.existsSync(path11.join(candidate, COMPOSITION_FILE))) return candidate;
1048
- const parent = path11.dirname(dir);
866
+ const candidate = path10.join(dir, "assets", "presets", id);
867
+ if (fs8.existsSync(path10.join(candidate, COMPOSITION_FILE))) return candidate;
868
+ const parent = path10.dirname(dir);
1049
869
  if (parent === dir) break;
1050
870
  dir = parent;
1051
871
  }
@@ -1055,12 +875,12 @@ function userPresetRoot(roots) {
1055
875
  const found = roots?.find(
1056
876
  (root) => root?.trust === "user" && typeof root.path === "string" && root.path.length > 0
1057
877
  );
1058
- return found?.path === void 0 ? void 0 : path11.resolve(found.path);
878
+ return found?.path === void 0 ? void 0 : path10.resolve(found.path);
1059
879
  }
1060
880
  function conventionalUserPresetRoot(env = process.env, home = os.homedir()) {
1061
881
  const override = env.DSH_HOME?.trim();
1062
- const root = override && override.length > 0 ? override : path11.join(home, ".dsh");
1063
- return path11.join(root, ".agent-presets");
882
+ const root = override && override.length > 0 ? override : path10.join(home, ".dsh");
883
+ return path10.join(root, ".agent-presets");
1064
884
  }
1065
885
  function installBundledPreset(options) {
1066
886
  const id = options.id && options.id.length > 0 ? options.id : BUNDLED_PRESET_ID;
@@ -1092,12 +912,12 @@ function installBundledPreset(options) {
1092
912
  detail: "the roster mounts no user preset root (includeUserRoot=false)"
1093
913
  };
1094
914
  }
1095
- const dir = path11.join(root, id);
1096
- const composition = path11.join(dir, COMPOSITION_FILE);
915
+ const dir = path10.join(root, id);
916
+ const composition = path10.join(dir, COMPOSITION_FILE);
1097
917
  try {
1098
918
  if (fs8.existsSync(composition)) {
1099
919
  if (options.force !== true) {
1100
- const drifted = !sameBytes(composition, path11.join(bundledDir, COMPOSITION_FILE));
920
+ const drifted = !sameBytes(composition, path10.join(bundledDir, COMPOSITION_FILE));
1101
921
  return {
1102
922
  action: "exists",
1103
923
  id,
@@ -1106,7 +926,7 @@ function installBundledPreset(options) {
1106
926
  detail: drifted ? "kept as-is (differs from the bundled template)" : "kept as-is"
1107
927
  };
1108
928
  }
1109
- fs8.copyFileSync(path11.join(bundledDir, COMPOSITION_FILE), composition);
929
+ fs8.copyFileSync(path10.join(bundledDir, COMPOSITION_FILE), composition);
1110
930
  return {
1111
931
  action: "restored",
1112
932
  id,
@@ -1117,9 +937,9 @@ function installBundledPreset(options) {
1117
937
  }
1118
938
  const existed = fs8.existsSync(dir);
1119
939
  fs8.mkdirSync(dir, { recursive: true });
1120
- fs8.copyFileSync(path11.join(bundledDir, COMPOSITION_FILE), composition);
1121
- const metadata = path11.join(dir, METADATA_FILE);
1122
- if (!fs8.existsSync(metadata)) fs8.copyFileSync(path11.join(bundledDir, METADATA_FILE), metadata);
940
+ fs8.copyFileSync(path10.join(bundledDir, COMPOSITION_FILE), composition);
941
+ const metadata = path10.join(dir, METADATA_FILE);
942
+ if (!fs8.existsSync(metadata)) fs8.copyFileSync(path10.join(bundledDir, METADATA_FILE), metadata);
1123
943
  return {
1124
944
  action: existed ? "repaired" : "created",
1125
945
  id,
@@ -1137,16 +957,16 @@ function describeInstall(result) {
1137
957
  return `preset ${result.id} ${result.action}${where}${why}`;
1138
958
  }
1139
959
  function presetStatus(moduleUrl, id = BUNDLED_PRESET_ID, root = conventionalUserPresetRoot()) {
1140
- const dir = path11.join(root, id);
960
+ const dir = path10.join(root, id);
1141
961
  const bundledDir = bundledPresetDir(moduleUrl, id);
1142
- const installed = fs8.existsSync(path11.join(dir, COMPOSITION_FILE));
962
+ const installed = fs8.existsSync(path10.join(dir, COMPOSITION_FILE));
1143
963
  return {
1144
964
  id,
1145
965
  dir,
1146
966
  ...bundledDir === void 0 ? {} : { bundledDir },
1147
967
  installed,
1148
- compositionMatches: installed && bundledDir !== void 0 && sameBytes(path11.join(dir, COMPOSITION_FILE), path11.join(bundledDir, COMPOSITION_FILE)),
1149
- metadataMatches: bundledDir !== void 0 && fs8.existsSync(path11.join(dir, METADATA_FILE)) && sameBytes(path11.join(dir, METADATA_FILE), path11.join(bundledDir, METADATA_FILE))
968
+ compositionMatches: installed && bundledDir !== void 0 && sameBytes(path10.join(dir, COMPOSITION_FILE), path10.join(bundledDir, COMPOSITION_FILE)),
969
+ metadataMatches: bundledDir !== void 0 && fs8.existsSync(path10.join(dir, METADATA_FILE)) && sameBytes(path10.join(dir, METADATA_FILE), path10.join(bundledDir, METADATA_FILE))
1150
970
  };
1151
971
  }
1152
972
  function sameBytes(left, right) {
@@ -1165,16 +985,6 @@ export {
1165
985
  pruneAuditFile,
1166
986
  deepMerge,
1167
987
  loadPolicy,
1168
- seedsFilePath,
1169
- loadPool,
1170
- activeSeeds,
1171
- archivedSeeds,
1172
- addSeed,
1173
- gcPool,
1174
- surfaceSeed,
1175
- archiveSeedById,
1176
- restoreSeed,
1177
- deleteSeed,
1178
988
  ledgerFilePath,
1179
989
  readLedger,
1180
990
  appendEntry,
@@ -1186,6 +996,7 @@ export {
1186
996
  checkWatchlist,
1187
997
  adviseWander,
1188
998
  completeWander,
999
+ adviseRefillWander,
1189
1000
  browseStatus,
1190
1001
  loadProfileSchema,
1191
1002
  profileFilePath,
@@ -1204,4 +1015,4 @@ export {
1204
1015
  describeInstall,
1205
1016
  presetStatus
1206
1017
  };
1207
- //# sourceMappingURL=chunk-2M35HRL6.js.map
1018
+ //# sourceMappingURL=chunk-5TNGUHIR.js.map