feat: add repo staleness detection and refresh across MCP, API, and CLI#18
Open
eddiefleurent wants to merge 5 commits intoHKUDS:mainfrom
Open
feat: add repo staleness detection and refresh across MCP, API, and CLI#18eddiefleurent wants to merge 5 commits intoHKUDS:mainfrom
eddiefleurent wants to merge 5 commits intoHKUDS:mainfrom
Conversation
…s kwarg - FastMCP defaults to 127.0.0.1 which prevents remote connections when running SSE transport. Default to 0.0.0.0 and allow override via FASTMCP_HOST / FASTMCP_PORT env vars. - mcp.run() does not accept sse_params kwarg (raises TypeError). Remove it. The --port arg was always a no-op since FastMCP is instantiated at module level before args are parsed; use FASTMCP_PORT env var instead.
Indexed repositories were treated as immutable — no git pull, no commit comparison, no way to detect upstream changes. The only refresh path was manually deleting index metadata. This adds lightweight staleness detection (git fetch + SHA comparison) and an explicit refresh flow (git pull + re-index) with feature parity across all three interfaces (MCP, REST API, CLI). MCP: code_qa now appends a freshness warning when repos are outdated, nudging the user to call the new refresh_repo tool. Also adds check_repo_freshness for explicit checks. API: POST /check-repo-freshness and POST /refresh-repo endpoints in both api.py and web_app.py. CLI: `check-freshness` and `refresh` commands. Core: VectorStore persists the indexed commit SHA in the metadata pickle. RepositoryLoader gains get_head_commit, check_for_updates, and pull_updates methods. FastCode gains check_repo_for_updates and refresh_repository orchestration methods. Made-with: Cursor
hexsha[:8] was stored at index time but full hexsha used everywhere else, causing equality check to always fail and report repos as stale.
Python evaluates type annotations at import time, so Pydantic models must be defined before the route functions that reference them. Moving the two classes up to the models section fixes the NameError on startup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move repo_info, available_repositories, and loaded_repositories fields from the RefreshRepoRequest model to the StatusResponse model for more appropriate schema organization. Co-Authored-By: Claude Haiku 4.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
git pull, no commit comparison, no TTL. The only way to get fresh data was manually deleting index metadata viadelete_repo_metadataand re-triggering indexing.code_qaappends a tasteful freshness warning when repos are outdated, nudging the user to callrefresh_repo— queries still work against the existing index.Changes
fastcode/loader.pyget_head_commit(),check_for_updates()(git fetch + SHA compare),pull_updates()(git pull); fixedhexsha[:8]→hexshato prevent stale false-positivesfastcode/vector_store.pysave()now persistsindexed_commitSHA in metadata pickle; newget_indexed_commit()readerfastcode/main.pyindex_repository()andload_multiple_repositories()pass commit SHA tosave(); newcheck_repo_for_updates()andrefresh_repository()orchestration methodsmcp_server.py_ensure_repos_ready()checks freshness on indexed repos and collects warnings;code_qaappends "Repository freshness" section when stale; new tools:check_repo_freshness,refresh_repoapi.pyPOST /check-repo-freshness,POST /refresh-repoweb_app.pyPOST /api/check-repo-freshness,POST /api/refresh-repomain.py(CLI)check-freshness --repos <names>,refresh <repo_name>Test plan
code_qa, then push a commit to the remote — subsequentcode_qacall should show a freshness warning in the responsecheck_repo_freshnesstool — should report the repo as OUTDATED with commit SHAsrefresh_repotool — should pull new commits and re-index, reporting old/new commitrefresh_repoagain immediately — reports already up-to-date,reindexed: false, no redundant re-indexPOST /check-repo-freshnessandPOST /refresh-reporeturn correct JSON via REST APIcheck-freshnessandrefreshCLI commands work end-to-endindexed_commitin metadata) still load and work — staleness check reportsindexed_commit: nullandstale: falserather than crashingBug found and fixed during testing
loader.pywas storinghexsha[:8](short SHA) at index time, but all comparison code uses fullhexsha. This causedindexed_commit != current_committo always be true, reporting every repo as stale even when fully up-to-date. Fixed in the final commit by removing the[:8]slice.Tested on
Self-hosted FastCode instance running as systemd services. Confirmed against a live repo: