Skip to content

Recover GraphRAG extraction and keep corpus operations consistent - #93

Merged
DMontgomery40 merged 1 commit into
mainfrom
feat/graphrag-extraction-recovery-20260905
Sep 5, 2026
Merged

Recover GraphRAG extraction and keep corpus operations consistent#93
DMontgomery40 merged 1 commit into
mainfrom
feat/graphrag-extraction-recovery-20260905

Conversation

@DMontgomery40

@DMontgomery40 DMontgomery40 commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Failed semantic index replacements discarded completed extraction work and reported whole-file failures as measured attempts. This change durably checkpoints validated official chunk graphs in Postgres and reuses them only when source bytes, provenance, approved schema, prompt, model route and recipe match exactly. Existing generation and provenance checks still decide whether a replacement can be published. Cancellation drains active writers before releasing ownership; completed files release their snapshots, payloads and successful tasks. Corrupt checkpoints fail without a silent paid retry.

Run history now persists measured admission, durable success, reuse, failure and unfinished counts while preserving accounting. The Indexing page restores a saved current schema through a typed read-only request, respects unapplied edits, and keeps technical details behind disclosure controls. Semantic estimates use the actual extraction contract and qualified native usage; missing evidence remains unavailable. Both saved-schema reads map database outages to the shared retryable 503.

Corpus controls refresh after indexing and when reopened. Cleanup requires a successful fresh registry read and an atomic only_unindexed condition under the existing database lock. If indexing finishes during cleanup, the API returns typed 409 and the UI preserves that corpus. Conditional cleanup also resolves configuration without inserting or migrating stored settings or warming caches; ordinary configuration reads and explicit manual deletion retain their existing behavior. Mobile Graph and Source panes, drawers and error footers remain reachable across narrow layouts and desktop resize boundaries.

The documentation generator and normal autopilot remove recognized whole-page Markdown wrappers before strict build and publication. Repair preserves internal code fences, rejects unfamiliar page shapes before writing, and is available without a provider call. Generated pages remain bot-owned.

Validation on LXC100: 700 extraction/storage/progress/lifecycle cases, 142 outage/schema/estimate cases, 112 corpus deletion, dependency and configuration cases, and 67 documentation cases passed. Real HTTP, PostgreSQL locks, commit cancellation and cross-store assertions cover the failure families. Six independent browser regressions reproduced stale corpus state and unsafe cleanup before passing with the correction. The 32-case graph ordering suite and four unchanged Chat registry cases passed, alongside the 17-case schema matrix and mobile pane/drawer/error-footer/resize coverage. Whole-server Ruff/mypy, generated types/contracts, 454 configuration keys, 435 capability rows, banned-pattern and docs-ownership checks pass. Independent Sol xhigh reviews cover each material slice. Full CI on the previous head passed 3,947 tests; this updated head still requires CI, deployment and actual operator acceptance. The approved Apollo replacement follows deployment; historical lost extraction outputs cannot be recovered by these checkpoints.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-05T23:05:05.133204Z e99ee66 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 012a9ea5c7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/api/index.py Outdated
continue
fingerprint = await graph_schema_input_fingerprint(corpus, cfg)
postgres = PostgresClient(cfg.indexing.postgres_url)
await postgres.connect()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Map proposal-read outages to the typed 503 response

When PostgreSQL is unreachable during the UI's automatic saved-schema restoration, this connect() exception is not passed through raise_postgres_unavailable_if_applicable, so the new endpoint returns a generic 500 instead of the structured, retryable dependency-unavailable 503 used by the other index read boundaries. Catch transport/Postgres failures around both corpus/config loading and proposal retrieval, and declare the 503 response contract on this route.

Useful? React with 👍 / 👎.

Comment thread server/api/index.py Outdated
continue
if _semantic_kg_usage_run_matches(run, corpus_id=corpus_id, alias=alias, schema_hash=schema_hash):
candidates.append(run)
return max(candidates, key=lambda run: (run.started_at, run.run_id), default=None)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Continue past newer runs without usable output evidence

When the newest matching run has only failed, cached, conflicting, or not-yet-ingested native rows, this eagerly selected run makes _semantic_kg_usage_sample return None and prevents an older matching run with valid successful requests from contributing any output-token estimate. The resulting quote incorrectly reports that no matching settled sample exists; candidates need to be tried newest-to-oldest until one yields usable evidence.

Useful? React with 👍 / 👎.

@DMontgomery40
DMontgomery40 force-pushed the feat/graphrag-extraction-recovery-20260905 branch from 012a9ea to ac4f83a Compare September 5, 2026 21:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ac4f83a711

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/api/index.py
async def capture_source(path: Path) -> SourceSnapshot:
snapshot = await asyncio.to_thread(SourceSnapshot.capture, path, max_bytes=max_indexable_bytes)
assert source_snapshots is not None
source_snapshots.enter_context(snapshot)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Release source snapshots after each file completes

For semantic corpora whose aggregate source size exceeds the LXC's temporary-disk capacity, registering every snapshot on the run-wide ExitStack keeps a complete second copy of all files until _run_index_body finishes, even though a snapshot is no longer read after that file's document, chunks, checkpoint, and graph have been written. This can exhaust /tmp and fail otherwise valid large indexing runs; scope each snapshot to its file and release it after the retained extraction/checkpoint work for that file has drained.

Useful? React with 👍 / 👎.

_examples_digest=extraction_digest(examples),
_template_digest=extraction_digest(prompt_template.template),
)
self._files[file_path] = file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Evict completed file payloads from checkpoint context

For semantic runs near the supported 40,000–100,000 chunk ceiling, this run-wide map retains every ExtractionFileCheckpoint, including _official_chunks containing serialized full chunk text, until final promotion. Consequently memory grows with the entire corpus even after file_graph_chunks.clear() releases the normal per-file batch, which can cause large runs to be killed after successfully checkpointing substantial work; replace completed entries with lightweight file-completion metadata or discard their bulky input fields after mark_written().

Useful? React with 👍 / 👎.

Fence durable chunk checkpoints, release completed file resources, restore truthful graph progress and saved schemas, and qualify extraction estimates. Refresh corpus controls and guard cleanup atomically. Repair mobile panes and generated documentation wrappers.

@codex review
@DMontgomery40 DMontgomery40 changed the title Preserve completed GraphRAG extraction across failed replacements Recover GraphRAG extraction and keep corpus operations consistent Sep 5, 2026
@DMontgomery40
DMontgomery40 force-pushed the feat/graphrag-extraction-recovery-20260905 branch from ac4f83a to e99ee66 Compare September 5, 2026 22:58

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e99ee66868

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +114 to +117
await asyncio.to_thread(
persist_graph_progress, self.path, repo_id=self.state.repo_id,
run_id=self.state.run_id, extraction=self.state.extraction.model_copy(deep=True),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Batch durable graph-progress updates

For large semantic runs, this persists the entire run summary once for every chunk transition: each reused chunk emits at least selected/admitted/reused, while each fresh chunk also emits dispatching. Since persist_graph_progress atomically rewrites the JSON and fsyncs both the file and directory, the supported default 40,000-chunk run performs roughly 120,000–160,000 summary rewrites, and close() blocks promotion until that queue fully drains. This can make otherwise completed large runs spend hours on progress I/O; apply every event in order in memory, but coalesce or checkpoint the latest sequence at a bounded interval plus final drain.

Useful? React with 👍 / 👎.

@DMontgomery40
DMontgomery40 merged commit 671f84d into main Sep 5, 2026
3 checks passed
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