chat-recall 0.5.28 → 0.5.30

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/watch.js CHANGED
@@ -7265,7 +7265,7 @@ async function archiveRawSession(store, sessionId) {
7265
7265
  return await store.putRawSession(sessionId, exp.tool, Math.floor(exp.mtime), gz, size);
7266
7266
  }
7267
7267
  function detectForkPredecessor(sessionPath) {
7268
- const { readFileSync: readFileSync47, readdirSync: readdirSync34 } = requireFs();
7268
+ const { readFileSync: readFileSync47, readdirSync: readdirSync35 } = requireFs();
7269
7269
  const { dirname: dirname26, join: join56, basename: basename28 } = requirePath();
7270
7270
  let text;
7271
7271
  try {
@@ -7295,7 +7295,7 @@ function detectForkPredecessor(sessionPath) {
7295
7295
  const self = basename28(sessionPath);
7296
7296
  let entries;
7297
7297
  try {
7298
- entries = readdirSync34(dir);
7298
+ entries = readdirSync35(dir);
7299
7299
  } catch {
7300
7300
  return null;
7301
7301
  }
@@ -14102,9 +14102,9 @@ function doResolve(realPath) {
14102
14102
  const bot = resolveBotWorktree(realPath);
14103
14103
  if (bot)
14104
14104
  return bot;
14105
- const git = resolveGit(realPath);
14106
- if (git)
14107
- return git;
14105
+ const git2 = resolveGit(realPath);
14106
+ if (git2)
14107
+ return git2;
14108
14108
  const ws = resolveAutoWorkspace(realPath, cfg.autoWorkspaceMinRepos ?? DEFAULT_AUTO_WORKSPACE_MIN_REPOS);
14109
14109
  if (ws)
14110
14110
  return ws;
@@ -14173,9 +14173,9 @@ function resolveGit(realPath) {
14173
14173
  const toplevel = findGitToplevel(realPath);
14174
14174
  if (!toplevel)
14175
14175
  return null;
14176
- const remote = getGitRemote(toplevel);
14177
- if (remote) {
14178
- const parsed = parseGitRemote(remote);
14176
+ const probe = getGitRemote(toplevel);
14177
+ if (probe.kind === "remote") {
14178
+ const parsed = parseGitRemote(probe.url);
14179
14179
  if (parsed) {
14180
14180
  return {
14181
14181
  id: `git:${parsed.host}/${parsed.owner}/${parsed.repo}`,
@@ -14184,6 +14184,9 @@ function resolveGit(realPath) {
14184
14184
  };
14185
14185
  }
14186
14186
  }
14187
+ if (probe.kind === "failed") {
14188
+ console.error(`[project] could not read git remotes in ${toplevel} \u2014 filing it as a local-only repo for now, which is probably wrong: ${probe.reason}`);
14189
+ }
14187
14190
  const hash = createHash7("sha1").update(toplevel).digest("hex").slice(0, 12);
14188
14191
  return {
14189
14192
  id: `git-local:${hash}`,
@@ -14202,23 +14205,39 @@ function findGitToplevel(realPath) {
14202
14205
  }
14203
14206
  return null;
14204
14207
  }
14208
+ function git(toplevel, args) {
14209
+ return execSync(`git ${args}`, {
14210
+ cwd: toplevel,
14211
+ stdio: ["ignore", "pipe", "ignore"],
14212
+ encoding: "utf-8",
14213
+ timeout: GIT_TIMEOUT_MS
14214
+ });
14215
+ }
14216
+ function probeGitRemote(toplevel) {
14217
+ let names;
14218
+ try {
14219
+ names = git(toplevel, "remote").split("\n").map((n) => n.trim()).filter(Boolean);
14220
+ } catch (err) {
14221
+ return { kind: "failed", reason: err instanceof Error ? err.message : String(err) };
14222
+ }
14223
+ if (names.length === 0)
14224
+ return { kind: "none" };
14225
+ const pick = names.includes("origin") ? "origin" : names[0];
14226
+ try {
14227
+ const url = git(toplevel, `remote get-url ${pick}`).trim();
14228
+ return url ? { kind: "remote", url } : { kind: "none" };
14229
+ } catch (err) {
14230
+ return { kind: "failed", reason: err instanceof Error ? err.message : String(err) };
14231
+ }
14232
+ }
14205
14233
  function getGitRemote(toplevel) {
14206
14234
  const cached = gitCache.get(toplevel);
14207
14235
  if (cached)
14208
- return cached.remote;
14209
- let remote = null;
14210
- try {
14211
- remote = execSync("git remote get-url origin", {
14212
- cwd: toplevel,
14213
- stdio: ["ignore", "pipe", "ignore"],
14214
- encoding: "utf-8",
14215
- timeout: 2e3
14216
- }).trim() || null;
14217
- } catch {
14218
- remote = null;
14219
- }
14220
- gitCache.set(toplevel, { remote });
14221
- return remote;
14236
+ return cached;
14237
+ const probe = probeGitRemote(toplevel);
14238
+ if (probe.kind !== "failed")
14239
+ gitCache.set(toplevel, probe);
14240
+ return probe;
14222
14241
  }
14223
14242
  function parseGitRemote(url) {
14224
14243
  const trimmed = url.trim().replace(/\.git$/, "");
@@ -14348,7 +14367,7 @@ function globToRegex(glob) {
14348
14367
  function escapeRe(s) {
14349
14368
  return s.replace(/[.+^${}()|[\]\\]/g, "\\$&");
14350
14369
  }
14351
- var DEFAULT_AUTO_WORKSPACE_MIN_REPOS, BOT_WORKTREE_MARKERS, resolveCache, gitCache, workspaceCache, cachedConfig, AUTO_WORKSPACE_MAX_DEPTH;
14370
+ var DEFAULT_AUTO_WORKSPACE_MIN_REPOS, BOT_WORKTREE_MARKERS, resolveCache, gitCache, workspaceCache, cachedConfig, GIT_TIMEOUT_MS, AUTO_WORKSPACE_MAX_DEPTH;
14352
14371
  var init_project_resolver = __esm({
14353
14372
  "../engine/dist/core/project-resolver.js"() {
14354
14373
  "use strict";
@@ -14359,6 +14378,7 @@ var init_project_resolver = __esm({
14359
14378
  gitCache = /* @__PURE__ */ new Map();
14360
14379
  workspaceCache = /* @__PURE__ */ new Map();
14361
14380
  cachedConfig = null;
14381
+ GIT_TIMEOUT_MS = 1e4;
14362
14382
  AUTO_WORKSPACE_MAX_DEPTH = 2;
14363
14383
  }
14364
14384
  });
@@ -19213,7 +19233,7 @@ var init_http = __esm({
19213
19233
  CLI_VERSION = JSON.parse(readFileSync33(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
19214
19234
  } catch {
19215
19235
  try {
19216
- if (true) CLI_VERSION = "0.5.28";
19236
+ if (true) CLI_VERSION = "0.5.30";
19217
19237
  } catch {
19218
19238
  }
19219
19239
  }
@@ -19721,7 +19741,7 @@ var init_telemetry = __esm({
19721
19741
  init_sync_client();
19722
19742
  cliVersion = () => {
19723
19743
  try {
19724
- return true ? "0.5.28" : "dev";
19744
+ return true ? "0.5.30" : "dev";
19725
19745
  } catch {
19726
19746
  return "dev";
19727
19747
  }
@@ -19998,12 +20018,13 @@ __export(auto_update_exports, {
19998
20018
  planAutoUpdate: () => planAutoUpdate,
19999
20019
  runAutoUpdate: () => runAutoUpdate,
20000
20020
  runningPrefix: () => runningPrefix,
20021
+ sweepStaleStaging: () => sweepStaleStaging,
20001
20022
  tarballUrl: () => tarballUrl
20002
20023
  });
20003
20024
  import { execSync as execSync2 } from "node:child_process";
20004
20025
  import { readFileSync as readFileSync36 } from "node:fs";
20005
20026
  import { fileURLToPath as fileURLToPath2 } from "node:url";
20006
- import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3 } from "node:fs";
20027
+ import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync5, readdirSync as readdirSync32, statSync as statSync38 } from "node:fs";
20007
20028
  import { join as join43, dirname as dirname18, sep as sep2 } from "node:path";
20008
20029
  import { tmpdir as tmpdir2 } from "node:os";
20009
20030
  import { createHash as createHash11 } from "node:crypto";
@@ -20042,6 +20063,31 @@ function planAutoUpdate(base2, caps, ownVersion3, flag) {
20042
20063
  if (compareVersions(rel.version, ownVersion3) <= 0) return { update: false, reason: `already current (own ${ownVersion3} >= server ${rel.version})` };
20043
20064
  return { update: true, reason: `server ${rel.version} > own ${ownVersion3}`, url: tarballUrl(base2), sha256: rel.sha256, from: ownVersion3, to: rel.version };
20044
20065
  }
20066
+ function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
20067
+ const MKDTEMP_SUFFIX = /^cr-update-.{6}$/s;
20068
+ const COLD_MS = 60 * 60 * 1e3;
20069
+ let removed = 0;
20070
+ let entries;
20071
+ try {
20072
+ entries = readdirSync32(root);
20073
+ } catch {
20074
+ return 0;
20075
+ }
20076
+ for (const name of entries) {
20077
+ if (!MKDTEMP_SUFFIX.test(name)) continue;
20078
+ const dir = join43(root, name);
20079
+ try {
20080
+ const st = statSync38(dir);
20081
+ if (!st.isDirectory() || now - st.mtimeMs < COLD_MS) continue;
20082
+ const inside = readdirSync32(dir);
20083
+ if (inside.length > 1 || inside.length === 1 && inside[0] !== "chat-recall.tgz") continue;
20084
+ rmSync5(dir, { recursive: true, force: true });
20085
+ removed++;
20086
+ } catch {
20087
+ }
20088
+ }
20089
+ return removed;
20090
+ }
20045
20091
  async function executeAutoUpdate(plan, deps) {
20046
20092
  if (!plan.update || !plan.url || !plan.sha256) return { updated: false, reason: plan.reason };
20047
20093
  let buf;
@@ -20053,13 +20099,21 @@ async function executeAutoUpdate(plan, deps) {
20053
20099
  const got = createHash11("sha256").update(buf).digest("hex");
20054
20100
  if (got !== plan.sha256) return { updated: false, reason: `checksum mismatch (expected ${plan.sha256.slice(0, 12)}\u2026, got ${got.slice(0, 12)}\u2026) \u2014 NOT installing` };
20055
20101
  const dir = mkdtempSync3(join43(tmpdir2(), "cr-update-"));
20102
+ const discardStaging = () => {
20103
+ try {
20104
+ rmSync5(dir, { recursive: true, force: true });
20105
+ } catch {
20106
+ }
20107
+ };
20056
20108
  const tgz = join43(dir, "chat-recall.tgz");
20057
20109
  writeFileSync8(tgz, buf);
20058
20110
  try {
20059
20111
  deps.install(tgz);
20060
20112
  } catch (e) {
20113
+ discardStaging();
20061
20114
  return { updated: false, reason: `install failed: ${e instanceof Error ? e.message : e}` };
20062
20115
  }
20116
+ discardStaging();
20063
20117
  const landed = (deps.verify ?? installedVersion)();
20064
20118
  if (landed && plan.to && compareVersions(landed, plan.to) < 0) {
20065
20119
  return {
@@ -20141,7 +20195,7 @@ var init_auto_update = __esm({
20141
20195
 
20142
20196
  // src/sync-client.ts
20143
20197
  import { join as join44, dirname as dirname19, basename as basename22 } from "node:path";
20144
- import { readFileSync as readFileSync37, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync4, rmSync as rmSync5, chmodSync as chmodSync3, unlinkSync as unlinkSync2, readdirSync as readdirSync32, statSync as statSync38 } from "node:fs";
20198
+ import { readFileSync as readFileSync37, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync4, rmSync as rmSync6, chmodSync as chmodSync3, unlinkSync as unlinkSync2, readdirSync as readdirSync33, statSync as statSync39 } from "node:fs";
20145
20199
  import { tmpdir as tmpdir3, hostname as hostname2 } from "node:os";
20146
20200
  import { createHash as createHash12 } from "node:crypto";
20147
20201
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -20460,7 +20514,7 @@ function reapStaleScanDirs(dir = tmpdir3(), maxAgeMs = 6 * 36e5, now = Date.now(
20460
20514
  let reaped = 0;
20461
20515
  let names;
20462
20516
  try {
20463
- names = readdirSync32(dir);
20517
+ names = readdirSync33(dir);
20464
20518
  } catch {
20465
20519
  return 0;
20466
20520
  }
@@ -20468,8 +20522,8 @@ function reapStaleScanDirs(dir = tmpdir3(), maxAgeMs = 6 * 36e5, now = Date.now(
20468
20522
  if (!name.startsWith("cr-batchscan-")) continue;
20469
20523
  const p = join44(dir, name);
20470
20524
  try {
20471
- if (now - statSync38(p).mtimeMs < maxAgeMs) continue;
20472
- rmSync5(p, { recursive: true, force: true });
20525
+ if (now - statSync39(p).mtimeMs < maxAgeMs) continue;
20526
+ rmSync6(p, { recursive: true, force: true });
20473
20527
  reaped++;
20474
20528
  } catch {
20475
20529
  }
@@ -20501,7 +20555,7 @@ function batchScanExternal(items, opts = {}) {
20501
20555
  slices++;
20502
20556
  }
20503
20557
  try {
20504
- rmSync5(scanDir, { recursive: true, force: true });
20558
+ rmSync6(scanDir, { recursive: true, force: true });
20505
20559
  } catch {
20506
20560
  }
20507
20561
  safeToId = /* @__PURE__ */ new Map();
@@ -20526,7 +20580,7 @@ function batchScanExternal(items, opts = {}) {
20526
20580
  flushSlice();
20527
20581
  } finally {
20528
20582
  try {
20529
- rmSync5(scanDir, { recursive: true, force: true });
20583
+ rmSync6(scanDir, { recursive: true, force: true });
20530
20584
  } catch {
20531
20585
  }
20532
20586
  }
@@ -20654,9 +20708,10 @@ async function syncToTargetInScope(cred, opts = {}) {
20654
20708
  setServerIngestConcurrency(base2, Math.floor(adv));
20655
20709
  }
20656
20710
  if (body2.cli && body2.cli.version) {
20657
- const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
20711
+ const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
20658
20712
  const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
20659
20713
  const plan = planAutoUpdate2(base2, { cli: body2.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
20714
+ sweepStaleStaging2();
20660
20715
  if (plan.update) {
20661
20716
  void runAutoUpdate2(base2, authHeaders, ownVersion).catch(() => {
20662
20717
  });
@@ -20782,9 +20837,10 @@ async function syncToTargetInScope(cred, opts = {}) {
20782
20837
  if (!res.ok) throw new Error(`append sync failed: HTTP ${res.status} ${await res.text().catch(() => "")}`);
20783
20838
  const body = await res.json().catch(() => ({}));
20784
20839
  if (body.cli && body.cli.version) {
20785
- const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
20840
+ const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
20786
20841
  const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
20787
20842
  const plan = planAutoUpdate2(base2, { cli: body.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
20843
+ sweepStaleStaging2();
20788
20844
  if (plan.update) {
20789
20845
  void runAutoUpdate2(base2, authHeaders, ownVersion).catch(() => {
20790
20846
  });
@@ -21586,7 +21642,7 @@ var init_sync_client = __esm({
21586
21642
  ownVersion = JSON.parse(readFileSync37(join44(dir, "../package.json"), "utf-8")).version || ownVersion;
21587
21643
  } catch {
21588
21644
  try {
21589
- if (true) ownVersion = "0.5.28";
21645
+ if (true) ownVersion = "0.5.30";
21590
21646
  } catch {
21591
21647
  }
21592
21648
  }
@@ -22185,11 +22241,11 @@ var init_toolkit_sync = __esm({
22185
22241
  });
22186
22242
 
22187
22243
  // ../engine/dist/core/which.js
22188
- import { existsSync as existsSync45, statSync as statSync40, accessSync, constants } from "node:fs";
22244
+ import { existsSync as existsSync45, statSync as statSync41, accessSync, constants } from "node:fs";
22189
22245
  import { join as join48, isAbsolute as isAbsolute2, delimiter as delimiter2, sep as sep3 } from "node:path";
22190
22246
  function executable(p) {
22191
22247
  try {
22192
- if (!statSync40(p).isFile())
22248
+ if (!statSync41(p).isFile())
22193
22249
  return false;
22194
22250
  } catch {
22195
22251
  return false;
@@ -22251,11 +22307,11 @@ __export(toolkit_pull_exports, {
22251
22307
  planPull: () => planPull,
22252
22308
  portableCommand: () => portableCommand
22253
22309
  });
22254
- import { existsSync as existsSync46, mkdirSync as mkdirSync12, statSync as statSync41, writeFileSync as writeFileSync12 } from "node:fs";
22310
+ import { existsSync as existsSync46, mkdirSync as mkdirSync12, statSync as statSync42, writeFileSync as writeFileSync12 } from "node:fs";
22255
22311
  import { dirname as dirname22, join as join49, basename as basename25, isAbsolute as isAbsolute3 } from "node:path";
22256
22312
  function isExecutableFile(p) {
22257
22313
  try {
22258
- return statSync41(p).isFile();
22314
+ return statSync42(p).isFile();
22259
22315
  } catch {
22260
22316
  return false;
22261
22317
  }
@@ -22749,14 +22805,14 @@ __export(shadow_prune_exports, {
22749
22805
  DEFAULT_MAX_TOTAL_BYTES: () => DEFAULT_MAX_TOTAL_BYTES,
22750
22806
  pruneShadow: () => pruneShadow
22751
22807
  });
22752
- import { readdirSync as readdirSync33, statSync as statSync43, unlinkSync as unlinkSync3 } from "fs";
22808
+ import { readdirSync as readdirSync34, statSync as statSync44, unlinkSync as unlinkSync3 } from "fs";
22753
22809
  import { join as join52 } from "path";
22754
22810
  function listShadows(isFullyAcked) {
22755
22811
  const out = [];
22756
22812
  const root = shadowRoot();
22757
22813
  let tools;
22758
22814
  try {
22759
- tools = readdirSync33(root);
22815
+ tools = readdirSync34(root);
22760
22816
  } catch {
22761
22817
  return out;
22762
22818
  }
@@ -22764,7 +22820,7 @@ function listShadows(isFullyAcked) {
22764
22820
  const dir = join52(root, tool);
22765
22821
  let names;
22766
22822
  try {
22767
- names = readdirSync33(dir);
22823
+ names = readdirSync34(dir);
22768
22824
  } catch {
22769
22825
  continue;
22770
22826
  }
@@ -22774,7 +22830,7 @@ function listShadows(isFullyAcked) {
22774
22830
  const path = join52(dir, name);
22775
22831
  let st;
22776
22832
  try {
22777
- st = statSync43(path);
22833
+ st = statSync44(path);
22778
22834
  } catch {
22779
22835
  continue;
22780
22836
  }
@@ -22889,7 +22945,7 @@ var init_code_intel = __esm({
22889
22945
  });
22890
22946
 
22891
22947
  // ../engine/dist/core/companions.js
22892
- import { existsSync as existsSync49, mkdirSync as mkdirSync15, statSync as statSync44, chmodSync as chmodSync4, unlinkSync as unlinkSync4, renameSync as renameSync5, createWriteStream, readFileSync as readFileSync44, writeFileSync as writeFileSync15 } from "node:fs";
22948
+ import { existsSync as existsSync49, mkdirSync as mkdirSync15, statSync as statSync45, chmodSync as chmodSync4, unlinkSync as unlinkSync4, renameSync as renameSync5, createWriteStream, readFileSync as readFileSync44, writeFileSync as writeFileSync15 } from "node:fs";
22893
22949
  import { homedir as homedir19 } from "node:os";
22894
22950
  import { join as join53 } from "node:path";
22895
22951
  import { execSync as execSync3 } from "node:child_process";
@@ -22940,7 +22996,7 @@ function checkCodeindexStatus() {
22940
22996
  status.installed = true;
22941
22997
  status.path = foundPath;
22942
22998
  try {
22943
- status.size = statSync44(foundPath).size;
22999
+ status.size = statSync45(foundPath).size;
22944
23000
  } catch {
22945
23001
  }
22946
23002
  try {
@@ -24102,7 +24158,7 @@ import { homedir as homedir18 } from "node:os";
24102
24158
 
24103
24159
  // src/project-tasks.ts
24104
24160
  init_http();
24105
- import { existsSync as existsSync44, readFileSync as readFileSync40, writeFileSync as writeFileSync11, mkdirSync as mkdirSync11, statSync as statSync39 } from "node:fs";
24161
+ import { existsSync as existsSync44, readFileSync as readFileSync40, writeFileSync as writeFileSync11, mkdirSync as mkdirSync11, statSync as statSync40 } from "node:fs";
24106
24162
  import { join as join47, dirname as dirname21 } from "node:path";
24107
24163
  import { homedir as homedir17 } from "node:os";
24108
24164
 
@@ -24213,7 +24269,7 @@ async function pushProjectTaskStatuses(base2, authHeaders, opts = {}) {
24213
24269
  if (!existsSync44(file)) continue;
24214
24270
  let mtime;
24215
24271
  try {
24216
- mtime = statSync39(file).mtimeMs;
24272
+ mtime = statSync40(file).mtimeMs;
24217
24273
  } catch {
24218
24274
  continue;
24219
24275
  }
@@ -24374,7 +24430,7 @@ try {
24374
24430
  ownVersion2 = JSON.parse(readFileSync41(join50(dir, "../package.json"), "utf-8")).version || ownVersion2;
24375
24431
  } catch {
24376
24432
  try {
24377
- if (true) ownVersion2 = "0.5.28";
24433
+ if (true) ownVersion2 = "0.5.30";
24378
24434
  } catch {
24379
24435
  }
24380
24436
  }
@@ -24390,8 +24446,9 @@ async function drainSyncIntents(opts = {}) {
24390
24446
  const data = await res.json();
24391
24447
  pending = data.intents || [];
24392
24448
  if (data.cli && data.cli.version) {
24393
- const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
24449
+ const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
24394
24450
  const plan = planAutoUpdate2(base2, { cli: data.cli }, ownVersion2, process.env.CHAT_RECALL_AUTO_UPDATE);
24451
+ sweepStaleStaging2();
24395
24452
  if (plan.update) {
24396
24453
  void runAutoUpdate2(base2, authHeaders, ownVersion2).catch(() => {
24397
24454
  });
@@ -24658,11 +24715,11 @@ function checkSelfRestart(opts) {
24658
24715
  }
24659
24716
 
24660
24717
  // src/log-rotate.ts
24661
- import { statSync as statSync42, copyFileSync as copyFileSync3, truncateSync } from "fs";
24718
+ import { statSync as statSync43, copyFileSync as copyFileSync3, truncateSync } from "fs";
24662
24719
  var LOG_MAX_BYTES = 32 * 1024 * 1024;
24663
24720
  function rotateLogIfLarge(logPath, maxBytes = LOG_MAX_BYTES) {
24664
24721
  try {
24665
- const size = statSync42(logPath).size;
24722
+ const size = statSync43(logPath).size;
24666
24723
  if (size < maxBytes) return { rotated: false, sizeBefore: 0 };
24667
24724
  copyFileSync3(logPath, `${logPath}.1`);
24668
24725
  truncateSync(logPath, 0);
@@ -24718,7 +24775,7 @@ async function runCollectorMigration(opts) {
24718
24775
  init_sync_ledger();
24719
24776
  init_collector_health();
24720
24777
  import { existsSync as existsSync50, readFileSync as readFileSync46 } from "fs";
24721
- var CLI_VERSION3 = true ? "0.5.28" : "0.0.0";
24778
+ var CLI_VERSION3 = true ? "0.5.30" : "0.0.0";
24722
24779
  var DEBOUNCE_MS = 5e3;
24723
24780
  var CLAUDE_DIR = claudeBackend.projectsDir();
24724
24781
  var PLANS_DIR = claudeBackend.plansDir();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chat-recall",
3
- "version": "0.5.28",
3
+ "version": "0.5.30",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/munhq/chat-recall.git"
@@ -59,12 +59,25 @@ diary conclusions, and cost. Accepts a path, a name substring, or a project id
59
59
 
60
60
  ## Tasks and team (shared, not personal notes)
61
61
 
62
+ **Working the board out loud.** When you take work from here, say so: that you are
63
+ pulling tasks from the chat-recall board, which ones you picked, and — as each one
64
+ lands — that it is done and what changed. The board is the user's, and a card that
65
+ claims and closes itself with no word to them is how it stopped being trusted the
66
+ first time. `recall_tasks detail:true` gives you the brief, the locations and the
67
+ agent prompt for each card, so "what can I pick up" is one call.
68
+
69
+
62
70
  - `mcp__chat-recall__recall_tasks` — the shared task board: status, assignee,
63
71
  project. This is the answer to "what are my open tasks".
64
72
  - `mcp__chat-recall__recall_task_create` — create a task, optionally assigned to
65
73
  a teammate and attached to a project. Returns the new task id.
66
74
  - `mcp__chat-recall__recall_task_update` — change status, reassign, rename or
67
75
  comment. Takes the `t_…` id from `recall_tasks`.
76
+ - **`done` needs the CHANGE.** Pass `diff` — the unified diff of what you changed
77
+ for that card — and `commits` if you committed it. Nothing else can supply it:
78
+ the board cannot see edits made through a shell, and its commit scan only
79
+ searches repositories the session already touched with file tools. The diff you
80
+ record is what the person reads on the card.
68
81
  - **`done` needs the session that did the work.** Pass your own session id;
69
82
  without one the update is refused. A card asserts a problem in the code, so
70
83
  closing it asserts the code changed, and the board shows the files and commits
@@ -73,6 +86,10 @@ diary conclusions, and cost. Accepts a path, a name substring, or a project id
73
86
  - Cards filed from findings also close THEMSELVES once a re-index stops
74
87
  reporting the finding, so fixing the code and re-indexing is usually enough.
75
88
  Attach your session anyway: the closure keeps its evidence.
89
+ - **Stay inside the card's project.** A card names one repository; fix it there
90
+ and nowhere else. If the real fix needs a change in another repo, say so and
91
+ leave the card open — the API refuses evidence whose file paths climb out of
92
+ the project, and a diff spanning repositories cannot be reviewed as one change.
76
93
  - Filing is capped — at most 10 new cards per run and 50 open at once. A board
77
94
  at the ceiling files nothing until cards close; the backlog stays visible in
78
95
  the ranked findings view.