Repository navigation
Prepare RepoNeedle 1.2.0: Security, MCP and Reliability Improvements - #8
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bring in main's 1.1.0 changes (demo api.py and tests, static playground, README support section). Resolve the change_impact conflict in engine.py: the logic is identical on both sides; keep it with an updated comment. Deduplicate the auto-merged `api` extra in pyproject.toml and document that it serves the root-level demo api.py. Install the `api` extra in the release validate job so the full suite (test_public_api) runs. Correct the release audit's provenance and `api` extra statements. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Release candidate for RepoNeedle 1.2.0. The package version is intentionally still 1.1.0; the version bump, tag and PyPI publication are separate follow-up steps after review.
This PR adds the native MCP server, machine-readable CLI output with anchor files, indexing diagnostics, and an opt-in default for the experimental abstention heuristic. It also fixes a security issue in repository indexing, restores a behaviour from the published 1.1.0 wheel, hardens CI and the release workflow, and reconciles documentation and benchmark claims with the code.
Experimental abstention is now disabled by default. The heuristic is uncalibrated: it correctly abstained on 0 of 82 no-gold queries in the ARB v2 selective split. Out-of-scope queries now return ranked results unless the caller opts in:
BudgetConfig(enable_experimental_abstention=True)orretrieve(..., enable_experimental_abstention=True)--enable-experimental-abstention"enable_experimental_abstention": trueEmpty repositories still return
abstained=True.task_type="selective"does not enable the heuristic.🔒 Security fix: indexing could read files outside the repository through links
RepoNeedleEngine.from_directory()previously opened files reached through symlinks (and, on Windows, NTFS junctions) without a containment check. A cloned repository containing, for example,docs/notes.md → ~/.aws/credentialswould have that file indexed, and its contents could be returned by retrieval, including through the MCPreponeedle_retrievetool. Reproduced against the released 1.1.0 code with a junction and a sentinel file: the sentinel appeared inrendered_context.Fix (
reponeedle/engine.py):os.path.realpath(strict=True)before opening it; broken links and loops are recorded as unreadable.os.path.commonpathon case-normalised paths), not by string prefix.indexing_diagnostics.symlink_outside_repository_paths(reasonsymlink_outside_repository), plus a count-only warning.CLI anchors now apply the same canonical containment check. CLI and MCP path validation are component-aware: legitimate names such as
..cache/x.pyare accepted, and real../traversal is still rejected.Changes
MCP server (new, optional extra
mcp)reponeedle-mcp/python -m reponeedle.mcp, STDIO transport, with toolsreponeedle_retrieve,reponeedle_change_impact,reponeedle_inspect.serverInfo.versionnow reports RepoNeedle's version (previously the MCP SDK's).reponeedle-mcpprints installation instructions.CLI
--json(single JSON document on stdout; diagnostics on stderr only),--include-context,--anchors,--enable-experimental-abstention,--max-file-size-bytes.Python API (backward compatible)
retrieve(anchor_files=...),Query(anchor_files=...),from_directory(max_file_size_bytes=...).engine.indexing_diagnosticsandRetrievalResult.abstention.AbstentionDiagnostics,IndexingDiagnostics,DEFAULT_MAX_FILE_SIZE_BYTES.Compatibility with 1.1.0 (
main)mainhas been merged into this branch (0adfbba). Thechange_impacttask-reporting logic (router-classified task forAUTOqueries) is identical tomain; this PR adds regression tests for it. Reporting only; ranking unchanged.apiextra (fastapi,httpx,uvicorn) for the root-level demoapi.pyis kept. No module inside thereponeedlepackage imports these packages.origin/main. The wheel matches tagv1.1.0.CI and release workflow
pytest-asyncioadded to thedevextra.mcp-security-linux(Ubuntu, Python 3.12,.[dev,mcp]) runs the MCP, symlink-security and compatibility suites withREPONEEDLE_FAIL_ON_SKIP=1: any skipped test fails the job. It also runs a live MCP STDIO smoke test that checksserverInfo.validatejob (read-only, no publishing credentials) verifies that the tag,pyproject.tomlandreponeedle.__version__match, installs.[dev,mcp,api], runs the full suite and the strict MCP/security suites;builddepends on it and checks the built artifact versions;publishdepends on both and is the only job withid-token: write.Documentation and benchmark integrity
8e00425, 2026-10-28). Current-engine official-harness results, a supplemental whole-file evaluation, and experimental studies are reported separately and labelled as not official (docs/BENCHMARK_CONFIGURATION.md,reports/experimental/).comment2contextroot-cause section (structured JSON PR-review queries; verified fusion weights 0.40/0.40/0.20 with a zero graph term by default; removed the unsupported "BM25 ≥ 0.85" recommendation).reports/release_audit_1.2.0/.Testing
main, Python 3.12 (Windows,mcp+apiextras)mcp).pyfiles compiled with Python 3.11 (pre-3.12 f-string grammar)[mcp]serverInfoversion)python -m build+twine check --strictreponeedle/incl. MCP; runtime dependencies unchanged)REPONEEDLE_FAIL_ON_SKIP=1)v1.2.0vs 1.1.0) is refused❗ Remaining verification required on Linux
The six file-symlink security tests in
tests/test_indexing_security.pyand the existing MCP symlink-escape test could not be executed locally: Windows here does not permit symlink creation, and no Linux environment (WSL/Docker) was available. The indexing containment path itself was verified empirically on Windows using NTFS junctions.This PR's
mcp-security-linuxjob must pass with zero skipped tests before the release blockers can be considered fully resolved.Not included
CHANGELOG.mdfromreports/release_audit_1.2.0/PROPOSED_CHANGELOG_1.2.0.md, then tagv1.2.0and let the release workflow publish.🤖 Generated with Claude Code