Skip to content

fix(noema): don't treat a deleted file's expected head-content 404 as a review-blocking error - #1524

Closed
seonghobae wants to merge 1 commit into
mainfrom
fix/noema-deleted-file-context
Closed

fix(noema): don't treat a deleted file's expected head-content 404 as a review-blocking error#1524
seonghobae wants to merge 1 commit into
mainfrom
fix/noema-deleted-file-context

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

Summary

Noema's required review check produced a real, live false-positive block on ContextualWisdomLab/.github#1486 (which deletes fuzz/fuzz_opencode_normalize_output.py, PR-status "removed" per gh api repos/ContextualWisdomLab/.github/pulls/1486/files). Instead of a real APPROVE/REQUEST_CHANGES verdict, Noema returned:

Unable to review due to missing file content
### Findings
- [high] fuzz/fuzz_opencode_normalize_output.py:1 (LEFT): File content unavailable due to HTTP 404 error
Result: COMMENT

Root cause: fetch_changed_file_paths() (scripts/ci/noema_review_gate.py) only extracted each changed file's filename from gh api .../pulls/{number}/files, discarding the status field the same response already includes (added/modified/removed/renamed). changed_file_context() then unconditionally called fetch_head_file_content() for every changed file at the PR's own head SHA — but a file whose PR status is "removed" cannot exist at head by definition, so this fetch was guaranteed to 404, every time, for every PR that deletes any file. fetch_head_file_content raised on the 404, and changed_file_context's except RuntimeError wrapped it as "Unavailable from head content API: {reason}" — phrasing indistinguishable from a genuine anomaly. The LLM reviewer, seeing that framing, reasonably (but wrongly) treated an entirely expected file-deletion scenario as a high-severity data-integrity problem and refused a full review. Since this org's hollow-path-audit lineage regularly deletes dead-code files, this could affect any such PR's required Noema review, not just #1486.

Fix

  1. Added fetch_changed_files(repo, number) -> list[tuple[str, str]], which extracts (filename, status) pairs from the same gh api pulls/{number}/files response (--jq '.[] | .filename + "\t" + .status'). fetch_changed_file_paths() itself is untouched — it keeps its existing list[str] return type and its other caller (inspect_and_review's changed_paths, used for validate_substantive_verdict's adversarial-probe location checks) needed no change.
  2. changed_file_context() now takes each file's status from fetch_changed_files(). For a "removed" file it no longer probes head_sha (guaranteed 404, zero signal). Instead — per this repo's own evidence-gated review philosophy (CLAUDE.md: OpenCode/Noema approval requires concrete, observed evidence, not the absence of a signal) — it fetches the file's pre-deletion content at the PR's base ref via the new removed_file_context_section() helper, so the reviewer can actually judge whether the deletion is safe. PR_QUERY now also fetches baseRefOid alongside the existing headRefOid, so build_review_context() can pass the base SHA through with no extra API call. If no base SHA is available, or the base-ref fetch itself fails, a clear non-alarming note is emitted instead (no "Unavailable from head content API" framing).
  3. "added" files are unaffected (they exist at head, no special-casing needed). "renamed" files are also unaffected — GitHub's Files API reports their current (post-rename) filename/status, which already worked correctly against head_sha before this change.
  4. The existing genuine-404-on-a-still-existing-file path (a "modified" file whose head-content fetch actually fails) is unchanged and still surfaces as "Unavailable from head content API: {reason}".

Developer experience

  • New regression tests in tests/test_noema_review_gate.py:
    • test_fetch_changed_files_parses_path_and_status — unit coverage for the new (path, status) parser.
    • test_fetch_changed_file_paths_parses_plain_filenames — keeps the untouched original function's real body covered now that changed_file_context no longer calls through it.
    • test_changed_file_context_removed_file_uses_base_content_not_head_error — reproduces PR chore(fuzz): remove dead duplicate fuzz target #1486's exact scenario (a removed fuzz file) and asserts the output contains neither the old "Unavailable from head content API" framing nor a generic error, and instead surfaces the file's pre-deletion content.
    • test_changed_file_context_removed_file_without_base_sha, test_changed_file_context_removed_file_base_fetch_failure, test_changed_file_context_removed_file_base_content_empty — the three non-happy-path branches of the new removed-file handling.
    • test_changed_file_context_non_removed_head_fetch_failure_is_unchanged — pins that a genuine head-content failure on a file that still exists keeps the original error message.
    • test_build_review_context_forwards_base_sha_to_changed_file_context — confirms build_review_context threads pr["baseRefOid"] through.
  • coverage run -m pytest tests -q && coverage report --show-missing: 2134 passed, 1 skipped, 21 subtests passed; 100% coverage repo-wide, including scripts/ci/noema_review_gate.py.
  • interrogate: RESULT: PASSED (minimum: 100.0%, actual: 100.0%).
  • No *-hashes.txt files touched.

User experience

  • Any PR that deletes one or more files — a routine, expected shape for this org's hollow-path-audit work — can now get a real APPROVE/REQUEST_CHANGES verdict from Noema instead of an automatic COMMENT-only refusal caused by a false "high risk" reading of an expected 404.
  • Reviewers reading Noema's output for a deletion PR now see the file's actual pre-deletion content (when available) instead of an alarming "Unavailable ... error" line, giving genuinely more signal for judging whether the deletion is safe.
  • No change to how a real, unexpected head-content failure on a still-existing file is reported.

Test plan

  • coverage run -m pytest tests -q — 2134 passed, 1 skipped, 21 subtests passed
  • coverage report --show-missing — 100% overall, 100% on scripts/ci/noema_review_gate.py
  • interrogate — 100%, PASSED
  • New regression tests reproduce PR chore(fuzz): remove dead duplicate fuzz target #1486's exact failure shape and pass only with the fix
  • CI (required workflows) green on this PR

🤖 Generated with Claude Code

https://claude.ai/code/session_015Gs7KmNvH75nxz1sL8mKjw


Generated by Claude Code

…as a review-blocking error

Noema's required review check on #1486 (which
deletes fuzz/fuzz_opencode_normalize_output.py) refused to complete a real
verdict, citing "File content unavailable due to HTTP 404 error" as a
high-severity finding and returning only COMMENT.

Root cause: fetch_changed_file_paths() discarded each file's PR `status`
field, so changed_file_context() fetched every changed file's content at the
PR's own head SHA — including files whose status is "removed", which by
definition cannot exist at head and always 404. changed_file_context() then
reported that expected 404 with the same "Unavailable ... error" phrasing
used for genuine anomalies, and the LLM reviewer reasonably read it as a
real data-integrity problem serious enough to block a full review.

Fix: add fetch_changed_files() to return each file's (path, status) from the
same `gh api pulls/{n}/files` response, and special-case status "removed" in
changed_file_context(): instead of probing head_sha (guaranteed 404), fetch
the file's pre-deletion content at the PR's base ref (now carried via
PR_QUERY's baseRefOid) so the reviewer sees what's being deleted. A genuine
head-content fetch failure on a still-existing file is unchanged.

fetch_changed_file_paths() itself is untouched and still serves its other
caller (inspect_and_review's changed_paths for validate_substantive_verdict).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Gs7KmNvH75nxz1sL8mKjw
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Contributor Author

Required opencode-review check failure — not this PR's

Same central-pipeline issue reported on several sibling-repo PRs today: the opencode-review required check polled for ~90 minutes and never saw an APPROVED/CHANGES_REQUESTED verdict from opencode-agent on this PR's current head:

::error::No APPROVED or CHANGES_REQUESTED from opencode-agent on the current head.

#1507 (open in this same repo) is actively fixing the review-dispatch pipeline's timing/budget — the poller-budget mismatch is already resolved there, with a repair-retry stale-head fix in progress. Since this PR is a draft still awaiting its own OpenCode review cycle anyway, holding off on any action here until #1507 merges and the fixed pipeline takes effect.


Generated by Claude Code

@seonghobae

Copy link
Copy Markdown
Contributor Author

Contextual-Orchestrator를 같이 손보든 어쩌든 해결하세요. Bypass merge 필요하면 가능 (chicken and eggs 상황이라면) + NVIDIA NIM 만 쓰는 건 허용하지 않아요. Contextual-Orchestrator를 쓰세요. Timeout은 적어도 3시간으로 잡으세요. 120초 같은 건 당황스럽군요.

Copy link
Copy Markdown
Contributor Author

@opencode-agent review

Review exact head e96583bcb3540ecae62ff54c8b994f7bea2606d2. This is the canonical Noema deletion-context repair needed by hollow-path/source-fix cleanup PRs: verify removed files are judged from exact base content, while genuine missing content for files that should exist at HEAD still fails closed. Do not reuse predecessor evidence.

Copy link
Copy Markdown
Contributor Author

Fresh protected-main revalidation after #1546: main@5686de41660d51a7a7f22b8840dfa6ccfe5ff3f1 still lacks fetch_changed_files() / removed_file_context_section() and still cannot distinguish an expected deleted-file head 404 from an anomalous content failure, so the causal review-quality fix remains needed. Current-main compare is cleanly scoped to scripts/ci/noema_review_gate.py and tests/test_noema_review_gate.py, but the branch is 8 commits behind and Draft. Please merge current main into this branch normally (no force/rebase), preserve #1546's new exact-head admission/publication lifecycle, rerun full 100% coverage/docstrings, mark Ready, and request fresh exact-head review.

@opencode-agent fix and review

Copy link
Copy Markdown
Contributor Author

Current-main compare remains restricted to scripts/ci/noema_review_gate.py and tests/test_noema_review_gate.py, and the deleted-file 404 bug remains present on protected main. This PR is still Draft solely because the connected Ready mutation is broken by the connector GraphQL schema mismatch. I am replacing only the PR conversation with a fresh non-draft PR from the identical unchanged branch/head. No predecessor evidence transfers.

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.

2 participants