@monoes/monomindcli 2.9.10 → 2.9.12

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.
@@ -277,19 +277,37 @@ async function main() {
277
277
  // pid matches our child. A foreign server answering on DEFAULT_PORT must
278
278
  // NOT be mistaken for ours — that lie misroutes every event emitter in
279
279
  // this project (root cause of orgs running invisibly).
280
+ // Absolute safety net so a wedged-but-still-alive process can't hang this
281
+ // hook forever — CONFIRM_ATTEMPTS below is a minimum grace period, not a
282
+ // hard budget (#142 follow-up).
283
+ const HARD_CEILING_ATTEMPTS = 600; // 500ms/attempt: 5 min
280
284
  async function confirmPort() {
281
285
  let sawForeignOnDefault = false;
282
- for (let attempt = 0; attempt < CONFIRM_ATTEMPTS; attempt++) {
286
+ let attempt = 0;
287
+ for (; attempt < HARD_CEILING_ATTEMPTS; attempt++) {
283
288
  await new Promise(r => setTimeout(r, 500));
284
- // 1) Authoritative: child self-reported its bound port
289
+ // Past the minimum grace period, a dead child means it's not coming
290
+ // back — stop waiting immediately instead of burning the rest of the
291
+ // budget. A LIVE child that simply hasn't reported yet (npm/AV
292
+ // contention on a freshly-written node_modules right after install,
293
+ // measured once at ~142s vs the normal ~5-9s — #142 follow-up) keeps
294
+ // getting the benefit of the doubt up to HARD_CEILING_ATTEMPTS instead
295
+ // of being killed on a fixed guess.
296
+ if (attempt >= CONFIRM_ATTEMPTS && !isPidAlive(child.pid)) break;
297
+ // 1) Authoritative: child self-reported its bound port. Identity comes
298
+ // from BOUND_REPORT's own per-invocation-unique path (nothing else on
299
+ // the machine knows it, since it's only handed to this child via env),
300
+ // NOT a pid match: under shell:true (#141's Windows EINVAL fix),
301
+ // child.pid is the wrapping cmd.exe's pid, not the real server's —
302
+ // rep.pid !== child.pid always, so a pid comparison here can never
303
+ // succeed on the npx-fallback path regardless of how long we wait
304
+ // (#143). rep.pid is the real server pid — use it for control.json.
285
305
  try {
286
306
  const rep = JSON.parse(fs.readFileSync(BOUND_REPORT, 'utf8'));
287
- if (rep && rep.pid === child.pid && typeof rep.port === 'number') {
307
+ if (rep && typeof rep.pid === 'number' && typeof rep.port === 'number') {
288
308
  try { fs.unlinkSync(BOUND_REPORT); } catch { /* ignore */ }
289
- if (rep.port !== DEFAULT_PORT) {
290
- writeStatus(child.pid, rep.port);
291
- if (String(process.env.MONOMIND_HOOK_QUIET || "") !== "1") process.stdout.write(`[control] server bound to port ${rep.port} (updated control.json)\n`);
292
- }
309
+ writeStatus(rep.pid, rep.port);
310
+ if (String(process.env.MONOMIND_HOOK_QUIET || "") !== "1") process.stdout.write(`[control] server bound to port ${rep.port} (pid ${rep.pid})\n`);
293
311
  return;
294
312
  }
295
313
  } catch { /* not written yet or old server — fall through to probe */ }
@@ -365,7 +383,7 @@ async function main() {
365
383
  // The next session-start simply retries.
366
384
  try { process.kill(child.pid, 'SIGTERM'); } catch { /* already gone */ }
367
385
  try { fs.unlinkSync(STATUS_FILE); } catch { /* ignore */ }
368
- process.stdout.write(`[control] server did not respond within ${CONFIRM_ATTEMPTS / 2} s — killed orphan, will retry next session\n`);
386
+ process.stdout.write(`[control] server did not respond within ${((attempt + 1) * 500 / 1000).toFixed(1)} s — killed orphan, will retry next session\n`);
369
387
  }
370
388
 
371
389
  confirmPort().catch(() => {}).finally(() => { releaseSpawnLock(); process.exit(0); });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monoes/monomindcli",
3
- "version": "2.9.10",
3
+ "version": "2.9.12",
4
4
  "type": "module",
5
5
  "description": "CLI engine for Monomind — an open-source MCP server that extends Claude Code with a codebase knowledge graph (tree-sitter + SQLite), persistent memory, multi-agent task coordination, and session hooks. Apache 2.0 licensed, fully local.",
6
6
  "main": "dist/src/index.js",
@@ -119,10 +119,10 @@
119
119
  "@opencode-ai/sdk": "^1.18.15",
120
120
  "monofence-ai": "^1.0.2",
121
121
  "sql.js": "^1.14.1",
122
- "@monoes/routing": "1.0.4",
122
+ "@monoes/mcp": "1.0.3",
123
123
  "@monoes/hooks": "1.0.5",
124
124
  "@monoes/memory": "1.0.15",
125
- "@monoes/mcp": "1.0.3"
125
+ "@monoes/routing": "1.0.4"
126
126
  },
127
127
  "publishConfig": {
128
128
  "access": "public",