cf-memory-mcp 3.38.0 → 3.40.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.
@@ -3912,6 +3912,8 @@ function parseCliArgs(rest) {
3912
3912
  flags.blockers_only = true;
3913
3913
  } else if (a === '--chain') {
3914
3914
  flags.chain = true;
3915
+ } else if (a === '--validate') {
3916
+ flags.validate = true;
3915
3917
  } else if (a === '--older-than') {
3916
3918
  // Accept "7d" / "30d" / "12h" / raw number (days).
3917
3919
  const raw = rest[++i] || '';
@@ -4118,6 +4120,56 @@ async function runResumeCli() {
4118
4120
  process.exit(0);
4119
4121
  }
4120
4122
 
4123
+ // --validate: verify the handoff's file references still exist
4124
+ // on disk. Resolves each path relative to the handoff's repo_path
4125
+ // (or cwd). Reports per-path status. Useful before resuming to
4126
+ // catch "the file was moved or deleted since the handoff".
4127
+ if (flags.validate) {
4128
+ if (!found) {
4129
+ process.stderr.write('No resume handoff available to validate.\n');
4130
+ process.exit(3);
4131
+ }
4132
+ const handoff = payload.resume_handoff.handoff;
4133
+ const repoRoot = handoff.repo_path || process.env.CF_MEMORY_WATCH_PATH || process.cwd();
4134
+ const results = [];
4135
+ const checkPath = (relPath, kind) => {
4136
+ try {
4137
+ const full = path.isAbsolute(relPath) ? relPath : path.join(repoRoot, relPath);
4138
+ const exists = fs.existsSync(full);
4139
+ results.push({ kind, path: relPath, exists });
4140
+ } catch (_) {
4141
+ results.push({ kind, path: relPath, exists: false });
4142
+ }
4143
+ };
4144
+ for (const f of (handoff.files_touched || [])) checkPath(f.path, 'touched');
4145
+ for (const a of (handoff.code_anchors || [])) checkPath(a.file_path, 'anchor');
4146
+ const missing = results.filter(r => !r.exists);
4147
+
4148
+ if (flags.json) {
4149
+ process.stdout.write(JSON.stringify({
4150
+ repo_root: repoRoot,
4151
+ total: results.length,
4152
+ missing_count: missing.length,
4153
+ results,
4154
+ }, null, 2) + '\n');
4155
+ process.exit(missing.length === 0 ? 0 : 4);
4156
+ }
4157
+ process.stdout.write(`Validating ${results.length} file reference${results.length === 1 ? '' : 's'} against ${repoRoot}:\n\n`);
4158
+ for (const r of results) {
4159
+ const mark = r.exists ? '✓' : '✗';
4160
+ process.stdout.write(` ${mark} [${r.kind}] ${r.path}\n`);
4161
+ }
4162
+ process.stdout.write(`\n`);
4163
+ if (missing.length === 0) {
4164
+ process.stdout.write(`All ${results.length} references exist.\n`);
4165
+ process.exit(0);
4166
+ } else {
4167
+ process.stdout.write(`${missing.length} of ${results.length} references are missing.\n`);
4168
+ process.stdout.write(`The repo has moved or these files were deleted since the handoff was written.\n`);
4169
+ process.exit(4);
4170
+ }
4171
+ }
4172
+
4121
4173
  // --md <path>: write the rendered markdown to a file instead of
4122
4174
  // (or in addition to) stdout. Useful for piping to a markdown
4123
4175
  // viewer or saving to the project.
@@ -4247,7 +4299,8 @@ async function runListCli() {
4247
4299
  const status = (h.status || 'unknown').padEnd(11);
4248
4300
  const branch = h.branch ? `[${h.branch}] ` : '';
4249
4301
  const goal = (h.goal || '(no goal)').slice(0, 80);
4250
- process.stdout.write(` ${shortId} ${status} ${age.padStart(4)} ago ${branch}${goal}\n`);
4302
+ const q = typeof h.quality_score === 'number' ? ` q=${h.quality_score.toFixed(2)}` : '';
4303
+ process.stdout.write(` ${shortId} ${status} ${age.padStart(4)} ago${q} ${branch}${goal}\n`);
4251
4304
  if (h.next_step) process.stdout.write(` next: ${h.next_step.slice(0, 80)}\n`);
4252
4305
  }
4253
4306
  process.stdout.write(`\n(Run "npx cf-memory-mcp resume <id>" to see a specific handoff)\n`);
@@ -4559,6 +4612,26 @@ _cf_memory_mcp() {
4559
4612
  fi
4560
4613
  }
4561
4614
  _cf_memory_mcp "\$@"
4615
+ `);
4616
+ } else if (shell === 'powershell' || shell === 'pwsh') {
4617
+ process.stdout.write(`# cf-memory-mcp PowerShell completion
4618
+ # Install: cf-memory-mcp completion powershell | Out-String | Invoke-Expression
4619
+ # To persist: add the above to your $PROFILE
4620
+ Register-ArgumentCompleter -Native -CommandName cf-memory-mcp,cfm -ScriptBlock {
4621
+ param($wordToComplete, $commandAst, $cursorPosition)
4622
+ $commands = @('${commands.join("','")}')
4623
+ $flags = @('${flags.filter(f => f.startsWith('--')).join("','")}')
4624
+ $tokens = $commandAst.CommandElements | ForEach-Object { $_.Extent.Text }
4625
+ if ($tokens.Count -le 2) {
4626
+ $commands | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
4627
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
4628
+ }
4629
+ } elseif ($wordToComplete.StartsWith('--')) {
4630
+ $flags | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
4631
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $_)
4632
+ }
4633
+ }
4634
+ }
4562
4635
  `);
4563
4636
  } else if (shell === 'fish') {
4564
4637
  process.stdout.write(`# cf-memory-mcp fish completion
@@ -4573,7 +4646,7 @@ complete -c cf-memory-mcp -l help -s h -d 'Show help'
4573
4646
  complete -c cf-memory-mcp -l version -s v -d 'Show version'
4574
4647
  `);
4575
4648
  } else {
4576
- process.stderr.write(`Unknown shell "${shell}". Supported: bash, zsh, fish.\n`);
4649
+ process.stderr.write(`Unknown shell "${shell}". Supported: bash, zsh, fish, powershell.\n`);
4577
4650
  process.exit(1);
4578
4651
  }
4579
4652
  process.exit(0);
@@ -4592,8 +4665,10 @@ const PER_COMMAND_HELP = {
4592
4665
  --anchors-only code_anchors as "file:lines symbol".
4593
4666
  --decisions-only decisions, one per line.
4594
4667
  --blockers-only open blockers, one per line.
4668
+ --chain Walk parent_session_id back; show the thread history.
4669
+ --validate Check that files_touched + code_anchors still exist locally.
4595
4670
  --json, -j Full bootstrap payload as JSON.
4596
- Exit codes: 0 = found, 3 = no handoff / no data.`,
4671
+ Exit codes: 0 = found, 3 = no handoff / no data, 4 = --validate found missing files.`,
4597
4672
  list: `cf-memory-mcp list [--status S] [--since ISO] [--repo PATH] [--limit N] [--json]
4598
4673
  List recent handoffs for the current cwd, status-ranked. Header shows
4599
4674
  a status-count summary.
@@ -4633,7 +4708,7 @@ const PER_COMMAND_HELP = {
4633
4708
  cache writability, worker reachability, project indexing, resume
4634
4709
  availability. Exit nonzero if any check fails.
4635
4710
  --json, -j Emit a JSON list of checks.`,
4636
- completion: `cf-memory-mcp completion [bash|zsh|fish]
4711
+ completion: `cf-memory-mcp completion [bash|zsh|fish|powershell]
4637
4712
  Output shell completion script. Pipe to your shell's completion dir.`,
4638
4713
  delete: `cf-memory-mcp delete <session-id-or-prefix> [--json]
4639
4714
  cf-memory-mcp delete [--status STATUS] [--older-than 30d] [--repo PATH] --yes [--json]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cf-memory-mcp",
3
- "version": "3.38.0",
3
+ "version": "3.40.0",
4
4
  "description": "Cloudflare-hosted MCP server for code indexing, retrieval, and assistant memory with a direct remote MCP endpoint and local stdio bridge.",
5
5
  "main": "bin/cf-memory-mcp.js",
6
6
  "bin": {