@sdsrs/code-graph 0.80.0 → 0.80.2

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.
@@ -4,7 +4,7 @@
4
4
  "author": {
5
5
  "name": "sdsrs"
6
6
  },
7
- "version": "0.80.0",
7
+ "version": "0.80.2",
8
8
  "keywords": [
9
9
  "code-graph",
10
10
  "ast",
@@ -520,6 +520,12 @@ async function checkForUpdate({ installMissing = false } = {}) {
520
520
  installedVersion: success ? latest.version : installedVersion,
521
521
  latestVersion: latest.version,
522
522
  updateAvailable: !success,
523
+ // Consecutive failed-download counter. The statusline shows "↻ updating"
524
+ // while updateAvailable is set; without a bound, a persistently-failing
525
+ // update (missing tar/curl, full disk, blocked network) pins "updating"
526
+ // forever, asserting a self-heal that never happens. The statusline stops
527
+ // trusting it past STUCK_UPDATE_ATTEMPTS; success resets to 0.
528
+ updateAttempts: success ? 0 : (state.updateAttempts || 0) + 1,
523
529
  lastUpdate: success ? new Date().toISOString() : state.lastUpdate,
524
530
  rateLimited: false,
525
531
  binaryUpdated: result.binaryUpdated,
@@ -12,10 +12,17 @@ const cleanupDisabledStatusline = lifecycle.cleanupDisabledStatusline || (() =>
12
12
  // True when auto-update has a newer release queued or in flight (the background
13
13
  // downloader in session-init.js hasn't promoted the new binary yet). Used to show
14
14
  // a transient "updating" state instead of the alarming "offline" during that window.
15
+ // After this many consecutive failed download attempts (auto-update.js tracks
16
+ // updateAttempts), a pending update is treated as STUCK: the statusline stops
17
+ // showing "↻ updating" (which asserts an in-progress self-heal) and surfaces the
18
+ // real status instead. Without this, a persistently-failing update (missing
19
+ // tar/curl, full disk, blocked network) pins "updating" forever.
20
+ const STUCK_UPDATE_ATTEMPTS = 5;
15
21
  function updatePending() {
16
22
  try {
17
23
  const st = JSON.parse(fs.readFileSync(
18
24
  path.join(os.homedir(), '.cache', 'code-graph', 'update-state.json'), 'utf8'));
25
+ if ((st.updateAttempts || 0) >= STUCK_UPDATE_ATTEMPTS) return false;
19
26
  if (st.updateAvailable) return true;
20
27
  if (st.latestVersion && st.installedVersion && st.latestVersion !== st.installedVersion) return true;
21
28
  } catch { /* no state file or unreadable — treat as no pending update */ }
@@ -113,7 +120,11 @@ function parseReport(text) {
113
120
  // still downloading. That, or any pending update, is transient: show "updating"
114
121
  // so the user knows it self-heals, rather than the misleading "offline".
115
122
  function statusUnavailable(errText) {
116
- const binaryOutdated = /schema version/i.test(errText || '');
123
+ // Primary signal: the binary's STABLE schema-too-new marker (Rust
124
+ // domain::SCHEMA_TOO_NEW_MARKER) \u2014 not reword-able prose. Fallback to the legacy
125
+ // phrase so a cached binary predating the marker still reads as "updating".
126
+ const errStr = errText || '';
127
+ const binaryOutdated = errStr.includes('code-graph:schema-too-new') || /schema version/i.test(errStr);
117
128
  return (binaryOutdated || updatePending()) ? 'code-graph: \u21bb updating' : 'code-graph: offline';
118
129
  }
119
130
 
@@ -117,6 +117,17 @@ test('no report + update pending → updating', (t) => {
117
117
  assert.equal(runStatusline(home, project), 'code-graph: ↻ updating');
118
118
  });
119
119
 
120
+ test('stuck update (updateAttempts exhausted) → offline, not updating', (t) => {
121
+ // A persistently-failing update must not pin "↻ updating" forever. Past
122
+ // STUCK_UPDATE_ATTEMPTS the statusline drops the optimistic state and surfaces
123
+ // the real one (here: no report → offline).
124
+ const home = mkHome(t);
125
+ const project = mkProject(home);
126
+ installStubBinary(home, { report: 'boom', exitCode: 1 });
127
+ setUpdateState(home, { updateAvailable: true, updateAttempts: 5 });
128
+ assert.equal(runStatusline(home, project), 'code-graph: offline');
129
+ });
130
+
120
131
  test('schema-version error on stderr (no report) → updating', (t) => {
121
132
  const home = mkHome(t);
122
133
  const project = mkProject(home);
@@ -129,6 +140,20 @@ test('schema-version error on stderr (no report) → updating', (t) => {
129
140
  assert.equal(runStatusline(home, project), 'code-graph: ↻ updating');
130
141
  });
131
142
 
143
+ test('schema-too-new MARKER on stderr → updating (keys on the stable token, not prose)', (t) => {
144
+ // The binary appends domain::SCHEMA_TOO_NEW_MARKER; the statusline must detect
145
+ // the post-update window via that token even when the surrounding prose is
146
+ // reworded/translated (the old `/schema version/i` regex would miss this).
147
+ const home = mkHome(t);
148
+ const project = mkProject(home);
149
+ installStubBinary(home, {
150
+ report: '',
151
+ stderr: 'Error: totally reworded wording here [code-graph:schema-too-new]',
152
+ exitCode: 1,
153
+ });
154
+ assert.equal(runStatusline(home, project), 'code-graph: ↻ updating');
155
+ });
156
+
132
157
  test('genuine crash (no report, nothing pending) → offline', (t) => {
133
158
  const home = mkHome(t);
134
159
  const project = mkProject(home);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdsrs/code-graph",
3
- "version": "0.80.0",
3
+ "version": "0.80.2",
4
4
  "description": "MCP server that indexes codebases into an AST knowledge graph with semantic search, call graph traversal, and HTTP route tracing",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -35,10 +35,10 @@
35
35
  "node": ">=16"
36
36
  },
37
37
  "optionalDependencies": {
38
- "@sdsrs/code-graph-linux-x64": "0.80.0",
39
- "@sdsrs/code-graph-linux-arm64": "0.80.0",
40
- "@sdsrs/code-graph-darwin-x64": "0.80.0",
41
- "@sdsrs/code-graph-darwin-arm64": "0.80.0",
42
- "@sdsrs/code-graph-win32-x64": "0.80.0"
38
+ "@sdsrs/code-graph-linux-x64": "0.80.2",
39
+ "@sdsrs/code-graph-linux-arm64": "0.80.2",
40
+ "@sdsrs/code-graph-darwin-x64": "0.80.2",
41
+ "@sdsrs/code-graph-darwin-arm64": "0.80.2",
42
+ "@sdsrs/code-graph-win32-x64": "0.80.2"
43
43
  }
44
44
  }