fix(mcp): drop dead ESLint selector + suppress redundant grammar warning

Two minor PR #1383 review findings:

1. eslint.config.mjs: removed Selector 3 (`Property[key.name='write'].properties:has(...)`).
   `.properties` is not a valid attribute on a Property node in the ESTree
   AST, so the :has clause never matched — dead code. Selector 4 covers
   the canonical `const { write } = process.stdout` shape; tightened its
   comment to make that explicit.

2. cli/mcp.ts: removed the unconditional warnMissingOptionalGrammars call
   at MCP startup. The analyze path already emits this warning at index
   time with relevantExtensions filtered to the repo's actual file types,
   and a repo can only be served by MCP after analyze has run. Repeating
   the warning unconditionally on every MCP session was pure noise on
   machines whose indexed repos don't use .dart/.proto.
This commit is contained in:
Gergo Magyar 2026-05-07 08:09:15 +01:00
parent af1968f0fe
commit ca617552b0
2 changed files with 16 additions and 17 deletions

View file

@ -99,12 +99,11 @@ export default [
'Direct process.stdout.write is forbidden in MCP-reachable code. Route diagnostics through console.error or process.stderr.write — the MCP stdio transport owns stdout for JSON-RPC frames.', 'Direct process.stdout.write is forbidden in MCP-reachable code. Route diagnostics through console.error or process.stderr.write — the MCP stdio transport owns stdout for JSON-RPC frames.',
}, },
{ {
selector: // Catches the canonical destructuring shape:
"VariableDeclarator > ObjectPattern > Property[key.name='write'].properties:has(MemberExpression[object.name='process'][property.name='stdout'])", // const { write } = process.stdout;
message: // (and any other ObjectPattern destructure rooted at process.stdout)
'Destructuring write off process.stdout is forbidden in MCP-reachable code — bypasses the sentinel. Use process.stderr.write for diagnostics.', // which would otherwise capture a reference to the original write
}, // and bypass the sentinel.
{
selector: selector:
"VariableDeclarator[init.type='MemberExpression'][init.object.name='process'][init.property.name='stdout'] > ObjectPattern", "VariableDeclarator[init.type='MemberExpression'][init.object.name='process'][init.property.name='stdout'] > ObjectPattern",
message: message:

View file

@ -43,18 +43,18 @@ export const mcpCommand = async () => {
// Now safe to dynamically import the heavy backend modules. Anything // Now safe to dynamically import the heavy backend modules. Anything
// they emit to stdout during evaluation will route through the sentinel. // they emit to stdout during evaluation will route through the sentinel.
const [{ startMCPServer }, { LocalBackend }, { warnMissingOptionalGrammars }] = await Promise.all( const [{ startMCPServer }, { LocalBackend }] = await Promise.all([
[ import('../mcp/server.js'),
import('../mcp/server.js'), import('../mcp/local/local-backend.js'),
import('../mcp/local/local-backend.js'), ]);
import('./optional-grammars.js'),
],
);
// Surface missing optional grammars at startup so users learn why // Note: missing-optional-grammar warnings are emitted by `gitnexus analyze`
// .dart/.proto files won't be parsed instead of silently getting a // (with `relevantExtensions` filtered to the repo's actual file types) at
// degraded index. // index time. A repo can only be served by MCP after it has been analyzed,
warnMissingOptionalGrammars({ context: 'mcp' }); // so the user has already been warned through the path that knows whether
// the repo even contains .dart/.proto files. Repeating an unconditional
// warning at every MCP startup would be pure noise on machines whose
// indexed repos don't use those grammars.
// Initialize multi-repo backend from registry. // Initialize multi-repo backend from registry.
// The server starts even with 0 repos — tools call refreshRepos() lazily, // The server starts even with 0 repos — tools call refreshRepos() lazily,