Skip to content

feat(mcp): pre-execution lint scanner and namespace pre-injection for catalog code#25

Open
paddymul wants to merge 2 commits into
mainfrom
feat/mcp-catalog-lint-preinjection
Open

feat(mcp): pre-execution lint scanner and namespace pre-injection for catalog code#25
paddymul wants to merge 2 commits into
mainfrom
feat/mcp-catalog-lint-preinjection

Conversation

@paddymul

@paddymul paddymul commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • AST lint scanner (lint_catalog_code) runs before any user code executes and immediately rejects import ibis, from ibis import X, import xorq (bare), and import xorq as xo with actionable error messages
  • Pre-injection (_inject_prelude) loads ibis, xo, from_catalog, from_project into the module namespace before exec_module, so catalog scripts need zero import statements for common usage
  • Summary-stats sandbox fix: Exception and 7 other exception types were missing from _SAFE_BUILTIN_NAMES, causing except Exception: to fail with NameError at validation time
  • Docstring update: catalog_run now leads with the pre-injected names and the zero-import minimal pattern, and lists forbidden imports explicitly

Motivation

Session transcript analysis found import ibis and import xorq as xo caused 3 of 5 MCP call failures across two sessions — both patterns required 1-2 retries to recover via runtime hint. The scanner now rejects them immediately before exec; the pre-injection means a well-written script with no imports at all just works.

Test plan

  • tests/test_build.py — 14 new tests: 9 lint_catalog_code unit tests, 1 end-to-end build_and_persist lint-fires-before-exec test, 1 pre-injection test (ibis/xo available without import), 3 existing tests unchanged (error messages still match)
  • All 25 test_build.py tests pass locally
  • Pre-existing failures in test_buckaroo.py and test_diff.py are unrelated (caused by in-progress uncommitted changes to result_cache.py and app.py)

🤖 Generated with Claude Code

@paddymul paddymul force-pushed the feat/mcp-catalog-lint-preinjection branch from 4e1557d to d47bca1 Compare June 10, 2026 15:46
paddymul and others added 2 commits June 10, 2026 12:17
… catalog code

Add a static AST scanner that catches bad import patterns before any user
code executes, and pre-inject the four canonical names (ibis, xo,
from_catalog, from_project) into the module namespace so catalog scripts
need zero import statements for common usage.

Session analysis showed `import ibis` and `import xorq as xo` caused 3 of
5 MCP failures — both required 1-2 retries to recover from runtime errors
with cryptic AttributeErrors. The scanner now returns a clear rejection
before exec; the pre-injection means well-written code works without imports.

Also fix the summary-stats sandbox: Exception and common exception types
were missing from _SAFE_BUILTIN_NAMES, forcing `except Exception:` to fail
with NameError.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@paddymul paddymul force-pushed the feat/mcp-catalog-lint-preinjection branch from d47bca1 to 77b67ca Compare June 10, 2026 16:17
paddymul added a commit that referenced this pull request Jun 25, 2026
…cess in src)

git_revision shelled out via subprocess.run(["git", ...]), which the no-bare-subprocess-git guard (test_no_bare_subprocess_git_in_src, #25/G1) forbids: bare git forks, and forking from the multithreaded server can crash on macOS. Use the sanctioned fork-safe git_util.run_git (posix_spawn).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant