@dosu/cli 0.53.0-beta.12 → 0.53.0-beta.13

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 (2) hide show
  1. package/bin/dosu.js +98 -65
  2. package/package.json +1 -1
package/bin/dosu.js CHANGED
@@ -5018,7 +5018,7 @@ function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
5018
5018
  function getVersionString() {
5019
5019
  return `v${VERSION}`;
5020
5020
  }
5021
- var VERSION = "0.53.0-beta.12", INSTALL_CHANNEL = "npm";
5021
+ var VERSION = "0.53.0-beta.13", INSTALL_CHANNEL = "npm";
5022
5022
 
5023
5023
  // src/debug/logger.ts
5024
5024
  import {
@@ -8595,6 +8595,17 @@ function setSyncPaused(paused, configDir = getConfigDir()) {
8595
8595
  delete state.paused;
8596
8596
  saveSyncState(state, configDir);
8597
8597
  }
8598
+ function resetSyncState(configDir = getConfigDir()) {
8599
+ const previous = loadSyncState(configDir);
8600
+ const fresh = {
8601
+ schema_version: STATE_SCHEMA_VERSION,
8602
+ watermark: null,
8603
+ consecutive_failures: 0,
8604
+ ...previous.project_filter ? { project_filter: previous.project_filter } : {},
8605
+ ...previous.paused ? { paused: true } : {}
8606
+ };
8607
+ saveSyncState(fresh, configDir);
8608
+ }
8598
8609
  function saveSyncState(state, configDir = getConfigDir()) {
8599
8610
  if (!existsSync10(configDir))
8600
8611
  mkdirSync6(configDir, { recursive: true, mode: 448 });
@@ -9256,7 +9267,7 @@ function buildReportHtml(options) {
9256
9267
  const org = options.orgName || "Your team";
9257
9268
  const repo = options.repo || inventory.cwd || "—";
9258
9269
  const branch = options.branch || "—";
9259
- const summary = options.summary || "Local agent session logs were mined into Dosu notes so the next task can reuse them — reducing rediscovery cost.";
9270
+ const summary = options.summary || "Local agent session logs were studied and distilled into Dosu notes so the next task can reuse them — reducing rediscovery cost.";
9260
9271
  const generated = `${(options.generatedAt ?? new Date).toISOString().replace("T", " ").slice(0, 16)} UTC`;
9261
9272
  const derived = tokenTotalsFromCandidates(candidates, inventory);
9262
9273
  const [notesHeading, notesLede, footerTitle, footerBody] = notesSectionCopy(candidates);
@@ -9318,7 +9329,7 @@ function buildReportHtml(options) {
9318
9329
  <p class="muted">No rediscovery estimates on the notes yet — each candidate needs <code>approx_rediscovery_tokens</code>.</p>
9319
9330
  </section>`;
9320
9331
  }
9321
- const notesBody = candidateRows.join("") || '<p class="muted">No write_knowledge payloads yet. Run knowledge sync so the miner extracts learnings.</p>';
9332
+ const notesBody = candidateRows.join("") || '<p class="muted">No write_knowledge payloads yet. Run knowledge sync so Dosu studies your sessions and extracts learnings.</p>';
9322
9333
  const lede = notesLede ? `<p class="lede">${esc(notesLede)}</p>` : "";
9323
9334
  return `<!DOCTYPE html>
9324
9335
  <html lang="en">
@@ -10508,7 +10519,7 @@ async function runKnowledgeSync(options = {}) {
10508
10519
  const state = loadState();
10509
10520
  if (options.quiet) {
10510
10521
  if (state.paused) {
10511
- logger.debug("sync", "skipping quiet sync: mining is paused");
10522
+ logger.debug("sync", "skipping quiet sync: studying is paused");
10512
10523
  return { status: "skipped-paused", readySessions: 0, inFlightSessions: 0, sessions: [] };
10513
10524
  }
10514
10525
  const retryAt = backoffUntil(state);
@@ -10518,7 +10529,7 @@ async function runKnowledgeSync(options = {}) {
10518
10529
  }
10519
10530
  } else if (state.paused) {
10520
10531
  delete state.paused;
10521
- logger.debug("sync", "manual sync resumes paused mining");
10532
+ logger.debug("sync", "manual sync resumes paused studying");
10522
10533
  }
10523
10534
  let ready;
10524
10535
  let open2;
@@ -10608,12 +10619,12 @@ async function runKnowledgeSync(options = {}) {
10608
10619
  trivialSessions: trivial
10609
10620
  };
10610
10621
  }
10611
- logger.debug("sync", `mining ${batch.length} of ${ready.length} ready sessions (${trivial} trivial skipped)`);
10622
+ logger.debug("sync", `studying ${batch.length} of ${ready.length} ready sessions (${trivial} trivial skipped)`);
10612
10623
  const miner = await deps.mine(batch);
10613
10624
  switch (miner.outcome) {
10614
10625
  case "completed": {
10615
10626
  for (const s of batch) {
10616
- logger.debug("sync", `mined session ${s.harness}/${s.id}`);
10627
+ logger.debug("sync", `studied session ${s.harness}/${s.id}`);
10617
10628
  }
10618
10629
  const minedAt = now().toISOString();
10619
10630
  const history = [
@@ -10640,7 +10651,7 @@ async function runKnowledgeSync(options = {}) {
10640
10651
  total_learning_tokens: (state.total_learning_tokens ?? 0) + batchTokens,
10641
10652
  last_refusal: undefined
10642
10653
  });
10643
- logger.debug("sync", `mined ${batch.length} sessions, ${miner.notesWritten} suggested pages; watermark → ${watermark}`);
10654
+ logger.debug("sync", `studied ${batch.length} sessions, ${miner.notesWritten} suggested pages; watermark → ${watermark}`);
10644
10655
  return {
10645
10656
  status: "mined",
10646
10657
  ...base,
@@ -10660,10 +10671,10 @@ async function runKnowledgeSync(options = {}) {
10660
10671
  last_refusal: {
10661
10672
  at,
10662
10673
  outcome: miner.outcome,
10663
- message: miner.message ?? "Mining unavailable right now."
10674
+ message: miner.message ?? "Studying unavailable right now."
10664
10675
  }
10665
10676
  });
10666
- logger.debug("sync", `mining skipped by gateway: ${miner.outcome}`);
10677
+ logger.debug("sync", `studying skipped by gateway: ${miner.outcome}`);
10667
10678
  return { status: "skipped-gateway", ...base, minedSessions: 0, miner };
10668
10679
  }
10669
10680
  default: {
@@ -10672,7 +10683,7 @@ async function runKnowledgeSync(options = {}) {
10672
10683
  last_attempt_at: now().toISOString(),
10673
10684
  consecutive_failures: state.consecutive_failures + 1
10674
10685
  });
10675
- logger.debug("sync", `mining failed: ${miner.outcome}; ${miner.message ?? ""}`);
10686
+ logger.debug("sync", `studying failed: ${miner.outcome}; ${miner.message ?? ""}`);
10676
10687
  return {
10677
10688
  status: "mine-failed",
10678
10689
  ...base,
@@ -72919,7 +72930,7 @@ async function runMiner(options) {
72919
72930
  outcome: "settings_conflict",
72920
72931
  notesWritten: 0,
72921
72932
  turns: 0,
72922
- message: `Refusing to run: conflicting Claude Code settings would override the miner's auth (${detail})`
72933
+ message: `Refusing to run: conflicting Claude Code settings would override the study run's auth (${detail})`
72923
72934
  };
72924
72935
  }
72925
72936
  const gatewayURL = options.gatewayURL ?? getLlmGatewayURL();
@@ -72986,7 +72997,7 @@ async function runMiner(options) {
72986
72997
  if (!allowed.has(toolName)) {
72987
72998
  return {
72988
72999
  behavior: "deny",
72989
- message: `Tool ${toolName} is not permitted in mining runs.`
73000
+ message: `Tool ${toolName} is not permitted in study runs.`
72990
73001
  };
72991
73002
  }
72992
73003
  if (toolName === `mcp__${SESSIONS_SERVER_NAME}__read_session`) {
@@ -73043,7 +73054,7 @@ async function runMiner(options) {
73043
73054
  outcome: "error",
73044
73055
  notesWritten,
73045
73056
  turns,
73046
- message: "Mining run failed; see debug log for details."
73057
+ message: "Study run failed; see debug log for details."
73047
73058
  };
73048
73059
  }
73049
73060
  logger.debug("miner", `run ${runID} completed: ${turns} turns, ${notesWritten} suggested pages`);
@@ -73054,7 +73065,7 @@ async function runMiner(options) {
73054
73065
  outcome: "error",
73055
73066
  notesWritten,
73056
73067
  turns,
73057
- message: "Mining run ended without a result."
73068
+ message: "Study run ended without a result."
73058
73069
  };
73059
73070
  } catch (error61) {
73060
73071
  const text = error61 instanceof Error ? error61.message : String(error61);
@@ -73067,7 +73078,7 @@ async function runMiner(options) {
73067
73078
  outcome: "error",
73068
73079
  notesWritten,
73069
73080
  turns,
73070
- message: abort.signal.aborted ? "Mining run timed out and was aborted." : "Mining run failed; see debug log for details."
73081
+ message: abort.signal.aborted ? "Study run timed out and was aborted." : "Study run failed; see debug log for details."
73071
73082
  };
73072
73083
  } finally {
73073
73084
  clearTimeout(timer);
@@ -73537,7 +73548,7 @@ var init_settings = __esm(() => {
73537
73548
  });
73538
73549
 
73539
73550
  // src/telemetry/debug-id.ts
73540
- var BUNDLE_DEBUG_ID_PLACEHOLDER = "acac034b-488b-746c-6475-6e2164756e21";
73551
+ var BUNDLE_DEBUG_ID_PLACEHOLDER = "6b750395-441b-6515-6475-6e2164756e21";
73541
73552
 
73542
73553
  // src/telemetry/telemetry.ts
73543
73554
  import { randomUUID as randomUUID4 } from "node:crypto";
@@ -75452,6 +75463,8 @@ function reduceActivityViewKey(key) {
75452
75463
  return "sync";
75453
75464
  if (key === "f")
75454
75465
  return "full";
75466
+ if (key === "c")
75467
+ return "clear";
75455
75468
  return "none";
75456
75469
  }
75457
75470
  function cycleTab(tab, delta = 1) {
@@ -75542,12 +75555,12 @@ function foldRunProgress(progress, chunk) {
75542
75555
  let current = progress;
75543
75556
  for (const line of chunk.split(`
75544
75557
  `)) {
75545
- const start = line.match(/\[sync\] mining (\d+) of \d+ ready sessions/);
75558
+ const start = line.match(/\[sync\] (?:studying|mining) (\d+) of \d+ ready sessions/);
75546
75559
  if (start) {
75547
75560
  current = { batch: Number.parseInt(start[1], 10), read: new Set, notes: 0 };
75548
75561
  continue;
75549
75562
  }
75550
- if (/\[sync\] (mined \d+ sessions|mining failed|mining skipped)/.test(line)) {
75563
+ if (/\[sync\] (?:studied|mined) \d+ sessions|\[sync\] (?:studying|mining) (?:failed|skipped)/.test(line)) {
75551
75564
  current = null;
75552
75565
  continue;
75553
75566
  }
@@ -75572,15 +75585,15 @@ function statusLine(status) {
75572
75585
  if (status.running) {
75573
75586
  const since = status.startedAt ? ` · since ${localTime(status.startedAt)}` : "";
75574
75587
  const pid = status.pid !== undefined ? ` (pid ${status.pid})` : "";
75575
- return `⛏️ ${import_picocolors30.default.bold(brand("Mining sessions..."))}${import_picocolors30.default.dim(`${pid}${since}`)}`;
75588
+ return `\uD83D\uDCDA ${import_picocolors30.default.bold(brand("Studying sessions..."))}${import_picocolors30.default.dim(`${pid}${since}`)}`;
75576
75589
  }
75577
75590
  if (status.state.paused) {
75578
- return `${import_picocolors30.default.yellow("○")} ${import_picocolors30.default.bold("Paused")} ${import_picocolors30.default.dim("· mining stays off until you resume")}`;
75591
+ return `${import_picocolors30.default.yellow("○")} ${import_picocolors30.default.bold("Paused")} ${import_picocolors30.default.dim("· studying stays off until you resume")}`;
75579
75592
  }
75580
75593
  if (status.staleLock) {
75581
75594
  return `${import_picocolors30.default.yellow("○")} ${import_picocolors30.default.bold("Not running")} ${import_picocolors30.default.dim("· a previous run exited without cleaning up")}`;
75582
75595
  }
75583
- return `${import_picocolors30.default.dim("○")} ${import_picocolors30.default.bold("Idle")} ${import_picocolors30.default.dim("· hooks mine new sessions automatically")}`;
75596
+ return `${import_picocolors30.default.dim("○")} ${import_picocolors30.default.bold("Idle")} ${import_picocolors30.default.dim("· hooks study new sessions automatically")}`;
75584
75597
  }
75585
75598
  function progressLine(done, ready, width, notes = 0) {
75586
75599
  const total = done + ready;
@@ -75592,12 +75605,12 @@ function progressLine(done, ready, width, notes = 0) {
75592
75605
  const bar = brand("█".repeat(filled)) + import_picocolors30.default.dim("░".repeat(cells - filled));
75593
75606
  const pct = Math.floor(ratio * 100);
75594
75607
  const suffix = notes > 0 ? ` · ${notes} suggested page${notes === 1 ? "" : "s"}` : "";
75595
- return `${bar} ${done}/${total} mined · ${pct}%${suffix}`;
75608
+ return `${bar} ${done}/${total} studied · ${pct}%${suffix}`;
75596
75609
  }
75597
75610
  function tabBar(tab, queuedCount, openCount, minedCount, width) {
75598
75611
  return tabStrip([
75599
75612
  ["activity", "Activity"],
75600
- ["mined", `Mined (${minedCount})`],
75613
+ ["mined", `Studied (${minedCount})`],
75601
75614
  ["queued", `Queued (${queuedCount})`],
75602
75615
  ["open", `Open (${openCount})`]
75603
75616
  ], tab, width);
@@ -75621,10 +75634,11 @@ function wrapLine(text, width, indent = " ") {
75621
75634
  return out;
75622
75635
  }
75623
75636
  function confirmBox(queuedCount, backlog, width, mode = "start") {
75624
- const inFlight = backlog && backlog.inFlight > 0 ? ` (+${backlog.inFlight} open, mined once ${backlog.inFlight === 1 ? "it goes" : "they go"} quiet)` : "";
75625
- const scope = mode === "stop" ? "the run is killed mid-batch · mining stays paused until you resume" : queuedCount > 0 ? `${queuedCount} session${queuedCount === 1 ? "" : "s"} queued${inFlight} · runs in the background` : `queue empty${inFlight} · a run would only pick up sessions that finish from here`;
75626
- const title = mode === "stop" ? "Stop mining?" : mode === "resume" ? "Resume mining?" : "Start mining now?";
75627
- const verb = mode === "stop" ? "stop" : mode === "resume" ? "resume" : "start";
75637
+ const inFlight = backlog && backlog.inFlight > 0 ? ` (+${backlog.inFlight} still open; ${backlog.inFlight === 1 ? "it joins" : "they join"} once quiet)` : "";
75638
+ const sessions = `${queuedCount} session${queuedCount === 1 ? "" : "s"}`;
75639
+ const scope = mode === "clear" ? "Forgets which local sessions Dosu has already studied, so the next run reads them all again. Use this to rebuild knowledge from scratch. Notes already saved in Dosu are kept." : mode === "stop" ? "Kills the run mid-batch and pauses studying, so new sessions pile up in the queue instead of being read. Nothing is lost; press s again to resume from where it left off." : mode === "resume" ? `Studying picks up where it stopped: ${sessions} queued${inFlight}. Runs in the background; new notes appear in Dosu as each batch finishes.` : queuedCount > 0 ? `Dosu reads ${sessions}${inFlight} and distills the durable decisions and gotchas into team knowledge. Runs in the background; new notes appear in Dosu as each batch finishes.` : `Queue is empty${inFlight}. A run now would only pick up sessions that finish from here; hooks already do that automatically.`;
75640
+ const title = mode === "clear" ? "Clear study history?" : mode === "stop" ? "Stop studying?" : mode === "resume" ? "Resume studying?" : "Start studying now?";
75641
+ const verb = mode === "clear" ? "clear" : mode === "stop" ? "stop" : mode === "resume" ? "resume" : "start";
75628
75642
  const maxInner = Math.max(20, Math.min(width, contentWidth()) - 4);
75629
75643
  const rows = [
75630
75644
  import_picocolors30.default.bold(brand(title)),
@@ -75641,7 +75655,7 @@ function confirmBox(queuedCount, backlog, width, mode = "start") {
75641
75655
  ];
75642
75656
  }
75643
75657
  function renderActivityFrame(status, activity, width, backlog = null, pane = DEFAULT_PANE, queued = [], minedBeforeRun = 0, open5 = [], runProgress = null) {
75644
- const mined = status.state.watermark ? `Mined sessions up to ${localTime(status.state.watermark)}` : "Nothing mined yet";
75658
+ const mined = status.state.watermark ? `Studied sessions up to ${localTime(status.state.watermark)}` : "Nothing studied yet";
75645
75659
  const queueDetail = [];
75646
75660
  if (status.backoffUntil) {
75647
75661
  queueDetail.push(`retrying after ${localTime(status.backoffUntil)} · s syncs now`);
@@ -75653,14 +75667,14 @@ function renderActivityFrame(status, activity, width, backlog = null, pane = DEF
75653
75667
  progress = progressLine(minedDelta + stepDone, Math.max(0, backlog.ready - stepDone), width, runProgress?.notes ?? 0);
75654
75668
  }
75655
75669
  const refusal = !status.running && status.state.last_refusal;
75656
- const refusalLines = refusal ? wrapLine(`! Mining paused: ${refusal.message} (${localTime(refusal.at)})`, width).map((line) => import_picocolors30.default.yellow(line)) : [];
75670
+ const refusalLines = refusal ? wrapLine(`! Studying paused: ${refusal.message} (${localTime(refusal.at)})`, width).map((line) => import_picocolors30.default.yellow(line)) : [];
75657
75671
  const fullRows = Boolean(pane.fullRows);
75658
75672
  const minedRows = (status.state.mined_sessions ?? []).map((record2) => fullRows ? formatMinedRow(record2, true) : formatActivityLine(formatMinedRow(record2), width));
75659
75673
  const sessionRow = (session) => fullRows ? formatQueuedRow(session, true) : formatActivityLine(formatQueuedRow(session), width);
75660
75674
  const queuedRows = queued.map(sessionRow);
75661
75675
  const openRows = open5.map(sessionRow);
75662
75676
  const source = pane.tab === "activity" ? activity.map((line) => formatActivityLine(line, width, fullRows)) : pane.tab === "queued" ? queuedRows : pane.tab === "open" ? openRows : minedRows;
75663
- const emptyMined = status.state.watermark ? "No sessions recorded yet. History starts with the next mining run." : "No mined sessions yet.";
75677
+ const emptyMined = status.state.watermark ? "No sessions recorded yet. History starts with the next study run." : "No studied sessions yet.";
75664
75678
  const empty = pane.tab === "activity" ? "No sync activity in the log yet." : pane.tab === "queued" ? "Queue empty. Finished agent sessions appear here." : pane.tab === "open" ? "No open sessions. Live agent sessions sit here until they go quiet." : emptyMined;
75665
75679
  const height = fullRows ? ACTIVITY_VIEW_FULL_LIST_ROWS : ACTIVITY_VIEW_LIST_LINES;
75666
75680
  const { visible, above, below } = windowList(source, pane.scroll, height);
@@ -75685,13 +75699,14 @@ function renderActivityFrame(status, activity, width, backlog = null, pane = DEF
75685
75699
  ...scrollParts.length > 0 ? [import_picocolors30.default.dim(clip(scrollParts.join(" · "), width))] : [],
75686
75700
  "",
75687
75701
  ...pane.confirm ? centerBlock(confirmBox(queued.length, backlog, width, pane.confirm), width) : [
75688
- import_picocolors30.default.dim([
75702
+ ...wrapLine([
75689
75703
  "tab switch",
75690
75704
  "↑↓ scroll",
75691
75705
  fullRows ? "f clip" : "f full rows",
75692
75706
  status.running ? "s stop" : status.state.paused ? "s resume" : "s sync now",
75707
+ ...!status.running && status.state.watermark ? ["c clear"] : [],
75693
75708
  "esc back"
75694
- ].join(" · "))
75709
+ ].join(" · "), width, "").map((line) => import_picocolors30.default.dim(line))
75695
75710
  ]
75696
75711
  ];
75697
75712
  return lines.join(`
@@ -75715,6 +75730,7 @@ function runActivityView(io2 = {}) {
75715
75730
  const startSync = io2.startSync ?? (() => spawnDetachedSelf(["knowledge", "sync", "--bootstrap"]));
75716
75731
  const stopSync = io2.stopSync ?? stopSyncRun;
75717
75732
  const setPaused = io2.setPaused ?? setSyncPaused;
75733
+ const clearHistory = io2.clearHistory ?? resetSyncState;
75718
75734
  const listBacklog = io2.listBacklog ?? listSessionBacklog;
75719
75735
  const pollMs = io2.pollMs ?? ACTIVITY_VIEW_POLL_MS;
75720
75736
  const seed = readLog();
@@ -75761,7 +75777,7 @@ function runActivityView(io2 = {}) {
75761
75777
  queuedWatermark = status.state.watermark;
75762
75778
  sessions = listBacklog();
75763
75779
  }
75764
- if ((confirmSync === "start" || confirmSync === "resume") && status.running)
75780
+ if (confirmSync !== null && confirmSync !== "stop" && status.running)
75765
75781
  confirmSync = null;
75766
75782
  if (confirmSync === "stop" && !status.running)
75767
75783
  confirmSync = null;
@@ -75813,11 +75829,15 @@ ${CLEAR_BELOW}`);
75813
75829
  const mode = confirmSync;
75814
75830
  confirmSync = null;
75815
75831
  let note;
75816
- if (mode === "stop") {
75832
+ if (mode === "clear") {
75833
+ clearHistory();
75834
+ minedBeforeRun = null;
75835
+ note = "[sync] study history cleared · the next run reads every local session again";
75836
+ } else if (mode === "stop") {
75817
75837
  const ok2 = status.pid !== undefined && stopSync(status.pid);
75818
75838
  if (ok2)
75819
75839
  setPaused(true);
75820
- note = ok2 ? "[sync] mining stopped · paused until you resume" : "[sync] could not stop the run · it may have just finished";
75840
+ note = ok2 ? "[sync] studying stopped · paused until you resume" : "[sync] could not stop the run · it may have just finished";
75821
75841
  } else {
75822
75842
  if (mode === "resume")
75823
75843
  setPaused(false);
@@ -75841,6 +75861,11 @@ ${CLEAR_BELOW}`);
75841
75861
  if (action === "sync") {
75842
75862
  confirmSync = syncConfirmMode(status);
75843
75863
  draw();
75864
+ } else if (action === "clear") {
75865
+ if (!status.running && status.state.watermark) {
75866
+ confirmSync = "clear";
75867
+ draw();
75868
+ }
75844
75869
  } else if (action === "tab" || action === "tab-back") {
75845
75870
  tab = cycleTab(tab, action === "tab" ? 1 : -1);
75846
75871
  scroll = 0;
@@ -76726,23 +76751,31 @@ async function stepOfferInitialSync(cfg) {
76726
76751
  s.start("Checking for recent agent sessions...");
76727
76752
  const outcome = await runKnowledgeSync({ bootstrap: true });
76728
76753
  if (outcome.status !== "backlog" || outcome.readySessions === 0) {
76729
- s.stop("No unmined agent sessions found. Dosu will learn as you work.");
76754
+ s.stop("No past agent sessions to study. Dosu will learn from new ones as you work.");
76730
76755
  return;
76731
76756
  }
76732
76757
  const n5 = outcome.readySessions;
76733
- s.stop(`Found ${n5} unmined agent session${n5 === 1 ? "" : "s"} on this machine.`);
76758
+ const them = n5 === 1 ? "it" : "them";
76759
+ s.stop(`Found ${n5} past agent session${n5 === 1 ? "" : "s"} on this machine that Dosu hasn't studied.`);
76760
+ log2.message([
76761
+ `Dosu can read ${them} and pull out the durable knowledge: decisions, gotchas, and`,
76762
+ "how-things-work that your team and agents would otherwise rediscover.",
76763
+ "Only distilled notes are saved to Dosu; your session logs stay on this machine.",
76764
+ "It runs in the background a few sessions at a time; notes appear in Dosu as each batch finishes."
76765
+ ].join(`
76766
+ `));
76734
76767
  const mineNow = await confirm2({
76735
- message: `Mine ${n5 === 1 ? "it" : "them"} for team knowledge now? (runs in the background)`,
76736
- active: "Mine now ⛏️",
76737
- inactive: "Skip",
76768
+ message: `Study ${them} now?`,
76769
+ active: "Study now \uD83D\uDCDA",
76770
+ inactive: "Skip for now",
76738
76771
  initialValue: true
76739
76772
  });
76740
76773
  if (isCancel2(mineNow) || !mineNow) {
76741
- log2.info(`Skipped. Dosu picks sessions up in the background as you work, or run ${info("dosu knowledge sync")} anytime.`);
76774
+ log2.info(`Skipped. Dosu studies new sessions in the background as you work; run ${info("dosu knowledge sync")} anytime to study these too.`);
76742
76775
  return;
76743
76776
  }
76744
76777
  if (spawnDetachedSelf(["knowledge", "sync", "--quiet", "--bootstrap"])) {
76745
- log2.success("⛏️ Currently mining... Dosu is distilling your past sessions into team knowledge, a few at a time in the background.");
76778
+ log2.success(`\uD83D\uDCDA Studying ${n5} session${n5 === 1 ? "" : "s"} in the background. Watch progress on the Activity screen; when it finishes, the new notes are in Dosu and agents connected to this MCP can use them.`);
76746
76779
  const watch = await confirm2({
76747
76780
  message: "What next?",
76748
76781
  active: "Watch it work",
@@ -77572,7 +77605,7 @@ function overviewRows(state) {
77572
77605
  const tokens = state.total_learning_tokens ?? 0;
77573
77606
  if (minedTotal === 0 && notes === 0)
77574
77607
  return [];
77575
- const rows = [`${label("Sessions mined")}${minedTotal}`, `${label("Suggested pages")}${notes}`];
77608
+ const rows = [`${label("Sessions studied")}${minedTotal}`, `${label("Suggested pages")}${notes}`];
77576
77609
  if (tokens > 0) {
77577
77610
  rows.push(`${label("Investigation distilled")}${formatTokenCount(tokens)} tokens`);
77578
77611
  }
@@ -77621,7 +77654,7 @@ function analyticsTabRows(tab, state, pageStats) {
77621
77654
  function renderAnalyticsFrame(state, tab, scroll, pageStats = null, pagesPending = false, width = contentWidth()) {
77622
77655
  const rows = analyticsTabRows(tab, state, pageStats);
77623
77656
  const { visible, above, below } = windowReport(rows, scroll);
77624
- const empty = tab === "overview" ? "No analytics yet. They appear after the first mining run." : tab === "projects" ? "No per-project history yet. It fills in as sessions are mined." : pagesPending ? "Loading page analytics..." : "No page analytics yet.";
77657
+ const empty = tab === "overview" ? "No analytics yet. They appear after the first study run." : tab === "projects" ? "No per-project history yet. It fills in as sessions are studied." : pagesPending ? "Loading page analytics..." : "No page analytics yet.";
77625
77658
  const listRows = visible.length > 0 ? visible.map((row) => import_picocolors32.default.dim(row)) : [import_picocolors32.default.dim(empty)];
77626
77659
  const scrollParts = [];
77627
77660
  if (above > 0)
@@ -77800,7 +77833,7 @@ function checklistRows(ctx) {
77800
77833
  if (ctx.mining) {
77801
77834
  rows.push([
77802
77835
  "sync",
77803
- `⛏️ ${brand("mining sessions...")} ${import_picocolors33.default.dim(`${DOT3} see Activity`)}`
77836
+ `\uD83D\uDCDA ${brand("studying sessions...")} ${import_picocolors33.default.dim(`${DOT3} see Activity`)}`
77804
77837
  ]);
77805
77838
  }
77806
77839
  if (ctx.update) {
@@ -78344,7 +78377,7 @@ async function runMainMenu() {
78344
78377
  const mining = isMining();
78345
78378
  return [
78346
78379
  {
78347
- label: mining ? `Activity ⛏️ ${brand("mining sessions...")}` : "Activity",
78380
+ label: mining ? `Activity \uD83D\uDCDA ${brand("studying sessions...")}` : "Activity",
78348
78381
  value: "sync"
78349
78382
  },
78350
78383
  { label: "Knowledge report", hint: "(opens in browser)", value: "report" },
@@ -78424,7 +78457,7 @@ async function runSettings(cfg) {
78424
78457
  const action = await menuSelect("Settings", [
78425
78458
  { label: "Switch organization", hint: target?.org_name, value: "switch-org" },
78426
78459
  { label: "Switch Library", hint: library, value: "switch-library" },
78427
- { label: "Mining scope", hint: scope, value: "projects" },
78460
+ { label: "Study scope", hint: scope, value: "projects" },
78428
78461
  { label: "Run setup", hint: "rerun the setup wizard", value: "setup" },
78429
78462
  { label: "Log out", hint: "clear stored credentials", value: "logout" },
78430
78463
  { label: "Back", value: "back" }
@@ -78478,7 +78511,7 @@ async function runMiningProjectsSetting() {
78478
78511
  }
78479
78512
  const current = loadSyncState().project_filter;
78480
78513
  const selected = await multiselect2({
78481
- message: "Mine sessions from which folders?",
78514
+ message: "Study sessions from which folders?",
78482
78515
  options: dirs.map((dir) => ({
78483
78516
  label: dir === UNKNOWN_PROJECT ? "(unknown folder)" : displayDir(dir),
78484
78517
  value: dir
@@ -78493,7 +78526,7 @@ async function runMiningProjectsSetting() {
78493
78526
  const all = selected.length === dirs.length;
78494
78527
  saveSyncState(all ? state : { ...state, project_filter: [...selected] });
78495
78528
  const scope = all ? "all folders" : selected.map(displayDir).join(", ");
78496
- log2.success(`Mining scope ${dim(`· ${scope}`)}`);
78529
+ log2.success(`Study scope ${dim(`· ${scope}`)}`);
78497
78530
  }
78498
78531
  async function handleAuthenticate(cfg) {
78499
78532
  const shouldLogin = await confirm2({ message: "Open browser to log in?" });
@@ -82399,7 +82432,7 @@ ${results.length - opts.limit} more results not shown.`));
82399
82432
  console.log(` ID: ${store.id}`);
82400
82433
  console.log(` Space ID: ${store.space_id}`);
82401
82434
  });
82402
- cmd.command("sessions").description("List local agent sessions with full project and session ids (the untruncated view of the Activity screen's tabs)").option("--queued", "Only sessions queued for mining").option("--open", "Only live sessions still inside the quiet period").option("--mined", "Only recent mined-session history").option("--json", "Output as JSON").action((opts) => {
82435
+ cmd.command("sessions").description("List local agent sessions with full project and session ids (the untruncated view of the Activity screen's tabs)").option("--queued", "Only sessions queued for studying").option("--open", "Only live sessions still inside the quiet period").option("--mined", "Only recent studied-session history").option("--json", "Output as JSON").action((opts) => {
82403
82436
  const all = !opts.queued && !opts.open && !opts.mined;
82404
82437
  const wantQueued = all || Boolean(opts.queued);
82405
82438
  const wantOpen = all || Boolean(opts.open);
@@ -82440,10 +82473,10 @@ ${results.length - opts.limit} more results not shown.`));
82440
82473
  section("Open", sessionRows(backlog.open), "Updated", "No open sessions. Live agent sessions sit here until they go quiet.");
82441
82474
  }
82442
82475
  if (wantMined) {
82443
- section("Mined", minedRows, "Mined at", "No mined sessions recorded yet.");
82476
+ section("Studied", minedRows, "Studied at", "No studied sessions recorded yet.");
82444
82477
  }
82445
82478
  });
82446
- cmd.command("sync").description("Scan local agent session history and report the mining backlog").option("--quiet", "Background mode for hooks: honor backoff, exit 0, print nothing").option("--detach", "Re-spawn detached and return immediately (used by agent hooks)").option("--bootstrap", "Backfill mode: mine the full local session history regardless of age and drain the backlog (used by setup)").option("--status", "Show whether a sync is running now, plus watermark and recent activity").option("--report", "Write the same HTML harvest report as the log-to-dosu-knowledge skill and open it").option("--out <path>", "HTML report path (default: tmp/dosu-knowledge-report.html)").option("--json", "Output as JSON").action(async (opts) => {
82479
+ cmd.command("sync").description("Scan local agent session history and report the study backlog").option("--quiet", "Background mode for hooks: honor backoff, exit 0, print nothing").option("--detach", "Re-spawn detached and return immediately (used by agent hooks)").option("--bootstrap", "Backfill mode: study the full local session history regardless of age and drain the backlog (used by setup)").option("--status", "Show whether a sync is running now, plus watermark and recent activity").option("--report", "Write the same HTML harvest report as the log-to-dosu-knowledge skill and open it").option("--out <path>", "HTML report path (default: tmp/dosu-knowledge-report.html)").option("--json", "Output as JSON").action(async (opts) => {
82447
82480
  if (opts.status) {
82448
82481
  const status = getSyncStatus();
82449
82482
  if (opts.json) {
@@ -82529,7 +82562,7 @@ ${results.length - opts.limit} more results not shown.`));
82529
82562
  console.log("All your notes already have a transcript — nothing to backfill.");
82530
82563
  return;
82531
82564
  }
82532
- console.log(`Attributed ${result.updated} of ${result.candidates} notes (${result.ambiguous} ambiguous, ${result.noBatch} without a local mining batch). Run 'dosu knowledge report' to see their traces.`);
82565
+ console.log(`Attributed ${result.updated} of ${result.candidates} notes (${result.ambiguous} ambiguous, ${result.noBatch} without a local study batch). Run 'dosu knowledge report' to see their traces.`);
82533
82566
  });
82534
82567
  cmd.addCommand(hooksCommand());
82535
82568
  return cmd;
@@ -82570,14 +82603,14 @@ function printSyncStatus(status, now = new Date) {
82570
82603
  console.log("○ No sync running.");
82571
82604
  }
82572
82605
  if (status.state.paused) {
82573
- console.log(import_picocolors18.default.yellow(" Mining paused: stopped by you. Resume from the Activity screen or run 'dosu knowledge sync'."));
82606
+ console.log(import_picocolors18.default.yellow(" Studying paused: stopped by you. Resume from the Activity screen or run 'dosu knowledge sync'."));
82574
82607
  }
82575
82608
  const wm2 = status.state.watermark;
82576
- console.log(` Mined through: ${wm2 ? `${wm2} (${formatAge(wm2, now)})` : "nothing mined yet"}`);
82609
+ console.log(` Studied through: ${wm2 ? `${wm2} (${formatAge(wm2, now)})` : "nothing studied yet"}`);
82577
82610
  if (status.state.project_filter?.length) {
82578
82611
  const home = homedir5();
82579
82612
  const scope = status.state.project_filter.map((dir) => dir.startsWith(`${home}/`) ? `~${dir.slice(home.length)}` : dir).join(", ");
82580
- console.log(` Mining scope: ${scope}`);
82613
+ console.log(` Study scope: ${scope}`);
82581
82614
  }
82582
82615
  if ((status.state.total_notes ?? 0) > 0) {
82583
82616
  const tokens = status.state.total_learning_tokens ?? 0;
@@ -82592,7 +82625,7 @@ function printSyncStatus(status, now = new Date) {
82592
82625
  console.log(import_picocolors18.default.yellow(` Backing off after ${n5} failure${n5 === 1 ? "" : "s"}; background syncs retry after ${status.backoffUntil}.`));
82593
82626
  }
82594
82627
  if (status.state.last_refusal) {
82595
- console.log(import_picocolors18.default.yellow(` Mining paused: ${status.state.last_refusal.message} (${formatAge(status.state.last_refusal.at, now)})`));
82628
+ console.log(import_picocolors18.default.yellow(` Studying paused: ${status.state.last_refusal.message} (${formatAge(status.state.last_refusal.at, now)})`));
82596
82629
  }
82597
82630
  if (status.recentActivity.length > 0) {
82598
82631
  console.log(`
@@ -82608,25 +82641,25 @@ function printSyncOutcome(outcome) {
82608
82641
  switch (outcome.status) {
82609
82642
  case "backlog": {
82610
82643
  const inFlight = outcome.inFlightSessions > 0 ? import_picocolors18.default.dim(` (${outcome.inFlightSessions} more still in progress)`) : "";
82611
- console.log(`✓ Scanned. ${outcome.readySessions} new session${outcome.readySessions === 1 ? "" : "s"} ready to mine${inFlight}.`);
82612
- console.log(import_picocolors18.default.dim("Sign in with 'dosu setup' to enable mining."));
82644
+ console.log(`✓ Scanned. ${outcome.readySessions} new session${outcome.readySessions === 1 ? "" : "s"} ready to study${inFlight}.`);
82645
+ console.log(import_picocolors18.default.dim("Sign in with 'dosu setup' to enable studying."));
82613
82646
  break;
82614
82647
  }
82615
82648
  case "mined": {
82616
82649
  const notes = outcome.miner?.notesWritten ?? 0;
82617
82650
  const remaining = outcome.readySessions - (outcome.minedSessions ?? 0);
82618
- console.log(`✓ Mined ${outcome.minedSessions} session${outcome.minedSessions === 1 ? "" : "s"}, ${notes} suggested page${notes === 1 ? "" : "s"} created.`);
82651
+ console.log(`✓ Studied ${outcome.minedSessions} session${outcome.minedSessions === 1 ? "" : "s"}, ${notes} suggested page${notes === 1 ? "" : "s"} created.`);
82619
82652
  if (remaining > 0) {
82620
82653
  console.log(import_picocolors18.default.dim(`${remaining} more in the backlog; run sync again to continue.`));
82621
82654
  }
82622
82655
  break;
82623
82656
  }
82624
82657
  case "skipped-gateway": {
82625
- console.log(import_picocolors18.default.yellow(outcome.miner?.message ?? "Mining unavailable right now."));
82658
+ console.log(import_picocolors18.default.yellow(outcome.miner?.message ?? "Studying unavailable right now."));
82626
82659
  break;
82627
82660
  }
82628
82661
  case "mine-failed": {
82629
- console.error(import_picocolors18.default.red(outcome.miner?.message ?? "Mining run failed."));
82662
+ console.error(import_picocolors18.default.red(outcome.miner?.message ?? "Study run failed."));
82630
82663
  process.exitCode = 1;
82631
82664
  break;
82632
82665
  }
@@ -82649,7 +82682,7 @@ function printSyncOutcome(outcome) {
82649
82682
  break;
82650
82683
  }
82651
82684
  case "skipped-paused": {
82652
- console.log(import_picocolors18.default.dim("Skipped: mining is paused. Run 'dosu knowledge sync' to resume."));
82685
+ console.log(import_picocolors18.default.dim("Skipped: studying is paused. Run 'dosu knowledge sync' to resume."));
82653
82686
  break;
82654
82687
  }
82655
82688
  }
@@ -84654,4 +84687,4 @@ execute().catch((err) => {
84654
84687
  process.exit(1);
84655
84688
  });
84656
84689
 
84657
- //# debugId=acac034b-488b-746c-6475-6e2164756e21
84690
+ //# debugId=6b750395-441b-6515-6475-6e2164756e21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosu/cli",
3
- "version": "0.53.0-beta.12",
3
+ "version": "0.53.0-beta.13",
4
4
  "type": "module",
5
5
  "description": "Dosu CLI - Manage MCP servers for AI tools",
6
6
  "license": "MIT",