push_to_wiki: idempotent delete on missing page#16
Merged
Conversation
…uccess
Before: a delete API call for a page that no longer exists on the wiki
returned `error.code = "missingtitle"`, the script counted it as a
generic error, and the workflow exited 1 — even though the post-state
("page not on wiki") matched the intent.
This is a real-world case: pages may be manually deleted by a curator on
the wiki, or be cleaned up by a previous sync that ran with a different
base_ref. The recent dispatch with `base_ref=6348e17` hit this on the
two phantom keys from the initial commit (`aharoni2019`, `cai2016`) —
both already absent, both reported as "errors", workflow failed despite
both real-target pages being created successfully.
Make delete_page idempotent on `missingtitle`: return success with a
sentinel `MISSING_PAGE` marker. Caller logs it as `(already absent)` and
keeps a separate `already_missing` counter so it stays out of the
deleted-count (the wiki didn't actually do anything) but doesn't trip
the error path. Summary line includes the new counter only when it's
non-zero, so output stays clean for the common case.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Citations Summary
|
Merged
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.
A delete API call for a page that no longer exists currently returns `error.code = "missingtitle"`, gets counted as a generic error, and trips `sys.exit(1)` — even though the post-state ("page not on the wiki") matches the intent.
Real failure mode
The recent dispatch with `base_ref=6348e17` (force re-sync from the initial commit) hit this: the diff included two phantom keys (`aharoni2019`, `cai2016`) whose pages had been manually deleted on the wiki long ago. Both got reported as errors, workflow exited 1, despite the two real-target pages (`Publication/guo_2023_miniscopelfov`, `Publication/zhao_2025_minixl`) being created successfully.
The same pattern will recur every time a curator manually cleans up a page on the wiki and a later sync's diff still thinks it needs to delete it.
Fix
Treat `missingtitle` on delete as idempotent success: the page is absent, which is what the intent was.
`WikiClient.delete_page` now returns `(True, MISSING_PAGE)` on `missingtitle`. The caller logs it as `(already absent)` and bumps a separate `already_missing` counter so the summary line stays accurate (deleted-count means "actually deleted by this run") without tripping the error path.
Output examples:
```
...
Done: 2 created, 0 updated, 0 unchanged, 1 deleted, 1 already absent, 0 errors
```
The summary's `already absent` segment only appears when non-zero, so the common no-deletion case stays the same shape as before.
Tests
112/112 pass. No new tests — this is a 3-line behavior change to a function with no existing test coverage. Adding a tests/test_push_to_wiki.py with WikiClient mocks would be a worthwhile follow-up but is out of scope here.
🤖 Generated with Claude Code