You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
repowise update --index-only advances last_sync_commit to HEAD without regenerating any wiki pages. Because repowise update --docs uses last_sync_commit as its diff base, a later docs run sees an empty diff and regenerates nothing. It prints "No changed files detected" and exits 0.
The result is that page prose silently falls behind the code, permanently, and the command that exists to fix it reports success without doing anything. Since page prose is the entire semantic and full-text retrieval surface, get_answer and search_codebase keep serving descriptions of code that has since changed, with no staleness warning.
This affects any repo that runs index-only updates and later wants docs:
any repo with docs_enabled=false in .repowise/state.json, where the post-commit hook runs index-only updates on every commit
Each of those commits walks last_sync_commit forward past code whose pages were never regenerated. The staleness is then unreachable: the pointer has already moved past it.
Steps to Reproduce
repowise init --index-only on a repo at commit C0. State is written with docs_enabled=false and last_sync_commit=C0.
Make and commit changes to a few source files that already have pages.
repowise update (defaults to index-only here, per docs_enabled=false). It refreshes the graph, symbols, git and health data, regenerates no pages, and writes last_sync_commit=C1.
repowise update --docs to generate the prose.
Expected Behavior
Step 4 regenerates pages for every file that changed since the pages were last generated (C0).
Actual Behavior
Step 4 prints "No changed files detected" and exits 0. No pages are regenerated. base_ref resolves to last_sync_commit (C1), which already equals HEAD, so the diff is empty. The pages from C0 remain, describing code that no longer exists, and nothing reports this.
The only workaround is to know the problem exists and pass an explicit ref reaching back to when the pages were actually generated:
That ref is not recorded anywhere, so a user has to infer it from page timestamps in wiki.db.
Root Cause
last_sync_commit is doing two different jobs: "how far has the index been walked" and "how far has the prose been generated". Index-only updates advance it for the first meaning, which silently destroys the second.
packages/cli/src/repowise/cli/commands/update_cmd/command.py:461 sets the docs diff base:
base_ref=sinceorstate.get("last_sync_commit")
packages/cli/src/repowise/cli/commands/update_cmd/persistence.py:130-184, _persist_index_only_update, whose docstring states "No LLM regeneration", writes at line 172:
command.py:582-587 then treats the resulting empty diff as success and re-stamps the pointer again.
Suggested Fix
Track the two meanings separately. Persist a last_docs_commit (the commit at which pages were last regenerated), write it only on runs that actually generate pages, and have the docs path diff from it:
Backfill for existing state files: fall back to last_sync_commit when last_docs_commit is absent, so current index-only users are no worse off than today.
Related Issues Worth Fixing Alongside
These are separate defects, but they compound the one above and could reasonably land in the same change. Happy to split them into their own issues if preferred.
The cascade budget silently caps regeneration at 50 pages.packages/core/src/repowise/core/ingestion/change_detector.py:80-87 hard-caps the auto-scaled budget at 50. A user who does reach a genuine backlog of stale pages regenerates at most 50 of them and gets a success report with no indication that the rest were skipped. Worth surfacing the number of affected pages that were not regenerated.
Page selection is by importance, not staleness. With an explicit --cascade-budget above the cap, the selected pages are chosen by importance over the affected set, so runs can regenerate pages that are already current while leaving genuinely stale ones untouched. Staleness is arguably the more useful tiebreak for an update, as distinct from an init.
Nothing warns. No stale marker is attached to search results or answers while lagging prose is being served as the whole retrieval surface. A repo can sit in this state indefinitely with no signal in the CLI or in MCP responses.
Environment
OS: Windows 11
Python version: 3.13.5
Repowise version: 0.31.0
Installation method: pip (editable)
Confirmed by reading the code paths above; the reproduction is the sequence a docs_enabled=false repo follows automatically via the post-commit hook.
Describe the Bug
repowise update --index-onlyadvanceslast_sync_committo HEAD without regenerating any wiki pages. Becauserepowise update --docsuseslast_sync_commitas its diff base, a later docs run sees an empty diff and regenerates nothing. It prints "No changed files detected" and exits 0.The result is that page prose silently falls behind the code, permanently, and the command that exists to fix it reports success without doing anything. Since page prose is the entire semantic and full-text retrieval surface,
get_answerandsearch_codebasekeep serving descriptions of code that has since changed, with no staleness warning.This affects any repo that runs index-only updates and later wants docs:
repowise init --index-onlydocs_enabled=False, see fix(release): state migration safety + cost-gate UX #156)docs_enabled=falsein.repowise/state.json, where the post-commit hook runs index-only updates on every commitEach of those commits walks
last_sync_commitforward past code whose pages were never regenerated. The staleness is then unreachable: the pointer has already moved past it.Steps to Reproduce
repowise init --index-onlyon a repo at commitC0. State is written withdocs_enabled=falseandlast_sync_commit=C0.repowise update(defaults to index-only here, perdocs_enabled=false). It refreshes the graph, symbols, git and health data, regenerates no pages, and writeslast_sync_commit=C1.repowise update --docsto generate the prose.Expected Behavior
Step 4 regenerates pages for every file that changed since the pages were last generated (
C0).Actual Behavior
Step 4 prints "No changed files detected" and exits 0. No pages are regenerated.
base_refresolves tolast_sync_commit(C1), which already equals HEAD, so the diff is empty. The pages fromC0remain, describing code that no longer exists, and nothing reports this.The only workaround is to know the problem exists and pass an explicit ref reaching back to when the pages were actually generated:
That ref is not recorded anywhere, so a user has to infer it from page timestamps in
wiki.db.Root Cause
last_sync_commitis doing two different jobs: "how far has the index been walked" and "how far has the prose been generated". Index-only updates advance it for the first meaning, which silently destroys the second.packages/cli/src/repowise/cli/commands/update_cmd/command.py:461sets the docs diff base:packages/cli/src/repowise/cli/commands/update_cmd/persistence.py:130-184,_persist_index_only_update, whose docstring states "No LLM regeneration", writes at line 172:command.py:582-587then treats the resulting empty diff as success and re-stamps the pointer again.Suggested Fix
Track the two meanings separately. Persist a
last_docs_commit(the commit at which pages were last regenerated), write it only on runs that actually generate pages, and have the docs path diff from it:Backfill for existing state files: fall back to
last_sync_commitwhenlast_docs_commitis absent, so current index-only users are no worse off than today.Related Issues Worth Fixing Alongside
These are separate defects, but they compound the one above and could reasonably land in the same change. Happy to split them into their own issues if preferred.
The cascade budget silently caps regeneration at 50 pages.
packages/core/src/repowise/core/ingestion/change_detector.py:80-87hard-caps the auto-scaled budget at 50. A user who does reach a genuine backlog of stale pages regenerates at most 50 of them and gets a success report with no indication that the rest were skipped. Worth surfacing the number of affected pages that were not regenerated.Page selection is by importance, not staleness. With an explicit
--cascade-budgetabove the cap, the selected pages are chosen by importance over the affected set, so runs can regenerate pages that are already current while leaving genuinely stale ones untouched. Staleness is arguably the more useful tiebreak for an update, as distinct from an init.Nothing warns. No stale marker is attached to search results or answers while lagging prose is being served as the whole retrieval surface. A repo can sit in this state indefinitely with no signal in the CLI or in MCP responses.
Environment
Confirmed by reading the code paths above; the reproduction is the sequence a
docs_enabled=falserepo follows automatically via the post-commit hook.