Skip to content

ci(pages): reconcile owned deployment records safely - #1029

Merged
qnbs merged 15 commits into
mainfrom
ci/1028-pages-record-pruning
Oct 13, 2026
Merged

qnbs merged 15 commits into
mainfrom
ci/1028-pages-record-pruning

Conversation

@qnbs

@qnbs qnbs commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

User description

GitHub deployment-record pruning currently applies retention to every environment and can attempt deletion after failed inactivation. This change confines authority to positively identified github-pages records, keeps the newest three plus current/previous publication and explicit holds, and stops on ambiguous inventories or API outcomes.

Daily reconciliation replaces privileged workflow_run follow-ups. Only own-repository main schedule executions can write; manual dispatch and the local CLI are read-only. Each inactivate/delete operation repeats complete inventory, identity/status, successful main-push Pages job and immutable-main hold checks. Writes are serialized, limited to ten records, and never blindly retried.

References #1028 (implementation owner); #550/QNB-41 (measurement). This PR does not close #1028 or enable the manually disabled workflow. The six existing records are explicit incident-evidence holds pending owner disposition. Other environments, provider objects, required CI, signing and reviewer governance are unchanged.

Validation on the prepared delta:

  • node --test --test-reporter=spec tests/unit/tooling/prunePagesDeployments.test.mjs: 73 passed. Cases include retention/ties/holds, wrong environments and ownership, untrusted events and publication evidence, complete/truncated pagination, failed writes/GET exhaustion, 404/409/429/5xx, stale identity/status/main, partial outcomes, bounded batches, idempotence and zero-write dry-run.
  • Required Vitest integration plus existing workflow-policy checker: 111 passed; existing workflow structural suite additionally verified separately. Actionlint and Zizmor reported no new findings; the existing write-permission allowlist is unchanged.
  • Authenticated live local dry-run: queried/classified/protected 6, candidates/attempted/inactivated/deleted/failed 0; follow-up required for hold disposition. This is pre-merge implementation evidence, not post-merge admission.
  • Budget and signing/prepush evidence will be finalized on the published head. Generated README test metrics accompany the single new Vitest integration test.

Measured cohort: 2026-10-05 through 2026-10-11 UTC, exhaustive Actions pagination. 308 completed CI runs (214 PR, 93 push, 1 manual); 52 successful main-push runs had a successful Pages deploy job. Thus 256 old completion-trigger opportunities lacked that publication evidence. 256 actual prune runs were observed, all workflow_run; these counts do not prove a one-to-one mapping to the 256 unnecessary opportunities. Assuming enabled operation and the same cohort, old automatic starts would be 308 completions + 1 weekly cron = 309, versus 7 daily starts (302 fewer, ~97.7%). No savings are yet realized while disabled; CPU minutes and dollars were not measured.

Independent final-delta review must specifically assess ownership/current-publication proof, immutable-main hold admission, each write boundary and partial-failure accounting. GitHub exposes no conditional status-version POST/DELETE transaction: fresh reads detect observed races, but there is a residual interval between the last read and a write. Pruning concurrency does not serialize the publisher or external status writers. This limitation must be reviewed substantively rather than inferred safe from green CI.

Operational hold: after normal protected merge, verify resulting-main CI/CodeQL/Production, repeat a zero-write dry-run, reconcile evidence holds, and obtain separate explicit owner approval before enablement or a first controlled real pass. No enablement, real record deletion, historical non-execution claim, support communication or Vercel mutation is performed here.


Summary by cubic

Replaces broad CI-completion deployment-record pruning with a daily, fail-closed reconciliation that only touches positively identified github-pages records. Keeps the newest three records plus the current and previous successful publication and explicit rollback/evidence holds; failed inactivation never reaches deletion.

  • Every read is gated on the live rate allowance and a 100-request CI reserve; a reserve refusal before a candidate's first write ends the pass as a budget-limit stop, and a successful response without a usable rate header stops the run as rate-unknown.
  • The per-candidate request reservation scales with observed pagination depth; the proof scan, the inactive-status POST, and any standalone DELETE share one local-plus-live budget at the full retry count per read, and the DELETE proceeds only for a recognised inactive Pages status.
  • Publication proof accepts both push and workflow_dispatch on main, matches authors by account id and login together, requires the classifier's pages-status shape and site ownership, and binds the referenced job's head SHA and workflow path to its run; scans past unprovable records until 20 are proven, and keeps unprovable or status-blocked records protected and listed in the manifest.
  • The proof cache is bypassed at both write boundaries so deleted or unreadable run and job evidence still protects its record; the POST also needs the live remaining allowance to cover the finish cost plus the CI reserve, and the local CLI requests the github.com token explicitly.
  • Scheduled runs on main write at most ten records per pass; manual dispatch and the local CLI are read-only dry-runs.
  • Adds a unit suite (plus a Vitest integration wrapper) and documents the procedure and operational enablement in docs/PAGES-DEPLOYMENT-RECORD-PRUNING.md; the workflow's CI-AUDIT.md inventory row is pinned by a test. The workflow remains disabled pending separate owner approval. References ci(pages): restore safe continuous GitHub Pages deployment-record pruning #1028 (implementation) and ci(efficiency): reduce redundant cost and latency without weakening required quality/security gates #550/QNB-41 (efficiency measurement).

Migration

  • Merge must be followed by a zero-write dry-run, evidence-hold disposition, and explicit owner approval before the workflow is enabled or any real record deletion occurs.

Written for commit 064e665. Summary will update on new commits.

View guided diff Turn on auto-fix

Summary by Sourcery

Replace broad deployment pruning with a fail-closed, evidence-checked GitHub Pages reconciliation that remains read-only until separately approved.

New Features:

  • Add a fail-closed GitHub Pages deployment-record reconciliation process that retains recent, proven current and rollback, and explicitly held records.
  • Add read-only manual and local CLI inventory modes alongside bounded scheduled reconciliation.

Bug Fixes:

  • Prevent pruning of non-Pages environments or records with unverified ownership and publication evidence.
  • Prevent deletion when inactivation fails, returns an ambiguous result, or concurrent inventory and publication changes are detected.

Enhancements:

  • Replace workflow-completion follow-ups with serialized daily main-branch reconciliation using immutable execution authority, bounded batches, live rate-limit reserves, and no blind write retries.
  • Require fresh identity, status, publication, and trusted-main validation at each mutation boundary and report protected, unexamined, and partial outcomes explicitly.

CI:

  • Update CI inventory and workflow permissions to reflect the daily Pages-only reconciliation and closed destructive gate.

Documentation:

  • Document Pages deployment-record retention, evidence requirements, writer-fence limitations, budgets, and owner-controlled enablement.

Tests:

  • Add comprehensive unit and integration coverage for retention, ownership, provenance, pagination, rate limits, failures, races, dry-run behavior, and bounded mutations.

Chores:

  • Record the Pages reconciliation changes in the changelog and update README test metrics.

Summary by CodeRabbit

  • Chores
    • GitHub Pages deployment records are reviewed daily at 03:00 UTC, with manual checks available on main. Reports identify records that may be eligible for cleanup while protecting the three newest records, proven current and rollback publications, and evidence-backed records.
    • Scheduled and manual checks do not delete records. Cleanup remains disabled pending additional safety measures.
  • Documentation
    • Added guidance on record retention, publication verification, safety limits, and requirements for enabling cleanup. Updated repository test-count references.

CodeAnt-AI Description

Add read-only, evidence-checked GitHub Pages deployment reconciliation

What Changed

  • Reconcile GitHub Pages deployment records on a daily main-branch schedule instead of after every CI run; manual runs and the local command are read-only.
  • Keep the newest three records, proven current and rollback publications, and explicit holds. Protect records when publication evidence is missing or does not match.
  • Recheck records before any destructive action, and stop if inactivation fails or its outcome is unclear. Destructive writes remain disabled, so scheduled runs only report and do not change records.

Impact

✅ Zero deployment deletions while the write gate is closed
✅ Production and preview records remain untouched
✅ Unverified Pages publications remain protected

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@vercel

vercel Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
worldscript-studio Ready Ready Preview Oct 13, 2026 10:08am UTC

@codeant-ai

codeant-ai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR 2b1e677 Oct 13, 2026 · 09:21 09:21
✅ Incremental review completed 2b1e677 Oct 13, 2026 · 09:12 09:13
✅ Incremental review completed 2b1e677 Oct 13, 2026 · 09:12 09:27
✅ Reviewed your PR cdfd049 Oct 13, 2026 · 08:57 09:05
✅ Reviewed your PR 97206e2 Oct 13, 2026 · 08:29 08:35

@codeant-ai

codeant-ai Bot commented Oct 12, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 12, 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-10-13T10:14:55.264898Z 064e665 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.

@sourcery-ai

sourcery-ai Bot commented Oct 12, 2026

Copy link
Copy Markdown

Sorry @qnbs, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 2 days and 6 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@codeant-ai

codeant-ai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

🏁 CodeAnt Quality Gate Results

Commit: 064e665a
Scan Time: 2026-10-13 10:35:30 UTC

✅ Overall Status: PASSED

Quality Gate Details

Quality Gate Status Details
Secrets ✅ PASSED 0 secrets found, 1 false positive secret suppressed
Duplicate Code ✅ PASSED 0.0% duplicated
SAST ✅ PASSED No security issues
Bugs ✅ PASSED Rating S: No bugs
IAC ✅ PASSED Rating S: No issues

View Full Results

@sourcery-ai

sourcery-ai Bot commented Oct 12, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR replaces broad workflow_run-based deployment deletion with a daily, main-schedule-only reconciliation that authorizes only positively identified GitHub Pages records, preserves publication and incident holds, revalidates every mutation, and fails closed on ambiguous inventories or API outcomes; it also adds extensive regression coverage and operational documentation while leaving the workflow disabled pending separate owner approval.

Sequence diagram for safe GitHub Pages record reconciliation

sequenceDiagram
    participant Scheduler
    participant Workflow
    participant Reconciler
    participant GitHub

    Scheduler->>Workflow: Daily schedule
    Workflow->>Reconciler: runAction(github, context, holds, workflowRef)
    Reconciler->>Reconciler: admission(repository, ref, sha, workflowRef, eventName)
    Reconciler->>GitHub: GET Pages configuration
    GitHub-->>Reconciler: Pages site identity
    Reconciler->>GitHub: GET deployments and statuses
    GitHub-->>Reconciler: Complete inventory
    Reconciler->>Reconciler: planPruning(records, holds)
    Reconciler->>GitHub: GET successful CI run and Pages job
    GitHub-->>Reconciler: Publication evidence
    loop Each bounded candidate
        Reconciler->>GitHub: GET fresh inventory and main branch
        GitHub-->>Reconciler: Unchanged identity and hold evidence
        Reconciler->>GitHub: POST deployment status inactive
        GitHub-->>Reconciler: Inactivation result
        Reconciler->>GitHub: GET fresh inventory and statuses
        GitHub-->>Reconciler: Revalidated inactive record
        Reconciler->>GitHub: DELETE deployment
        GitHub-->>Reconciler: Deletion result
    end
Loading

Flow diagram for trigger admission and fail-closed behavior

flowchart TD
    A[Reconciliation trigger] --> B{Own repository, main ref, trusted workflow?}
    B -- No --> C[Refuse execution]
    B -- Yes --> D{Event is schedule?}
    D -- No: workflow_dispatch --> E[Read-only dry run]
    D -- Yes --> F[Read complete Pages inventory]
    F --> G{Inventory, identity, status, and publication evidence unambiguous?}
    G -- No --> H[Stop and report follow-up]
    G -- Yes --> I[Protect newest three, current, previous, and explicit holds]
    I --> J[Select up to ten owned candidates]
    J --> K[Revalidate candidate before mutation]
    K --> L{Still unchanged and main SHA current?}
    L -- No --> M[Skip candidate or stop]
    L -- Yes --> N[Inactivate record]
    N --> O{Inactivation succeeded and response valid?}
    O -- No --> P[Do not delete; stop failed closed]
    O -- Yes --> Q[Revalidate complete inventory]
    Q --> R{Candidate remains safe?}
    R -- No --> S[Skip or stop; require later pass]
    R -- Yes --> T[Delete deployment]
    T --> U[Report confirmed partial outcomes]
Loading

File-Level Changes

Change Details Files
Replaces event-driven broad deployment pruning with a bounded, fail-closed daily reconciliation workflow.
  • Removes the privileged workflow_run trigger and changes the schedule to daily.
  • Restricts execution to the owning repository’s main branch, serializes runs, and limits each batch to ten records.
  • Uses immutable-SHA checkout, scoped permissions, no persisted credentials, and read-only manual dispatch/local CLI behavior.
.github/workflows/prune-deployments.yml
scripts/prune-pages-deployments.mjs
docs/PAGES-DEPLOYMENT-RECORD-PRUNING.md
Adds strict ownership, publication-evidence, retention, and hold admission before any mutation.
  • Targets only positively identified github-pages deployment records with exact metadata and GitHub Actions identity.
  • Protects the newest three records, current and previous successful publication, explicit evidence/rollback holds, and ambiguous or unsafe records.
  • Verifies successful own-repository main-push CI and Pages job evidence, current site identity, immutable-main state, and complete paginated inventories.
scripts/prune-pages-deployments.mjs
.github/pages-pruning-holds.json
docs/PAGES-DEPLOYMENT-RECORD-PRUNING.md
Makes inactivation and deletion race-aware and fail closed with explicit partial-outcome reporting.
  • Re-reads inventory, statuses, publication evidence, and main branch state before each write and again between inactivation and deletion.
  • Stops deletion when inactivation fails or revalidation is ambiguous; never blindly retries writes.
  • Adds bounded GET retries, API error classification, sanitized summaries, follow-up signaling, and zero-write behavior for incomplete or uncertain inventories.
scripts/prune-pages-deployments.mjs
tests/unit/tooling/prunePagesDeployments.test.mjs
Adds comprehensive regression coverage and updates project documentation and test metrics.
  • Covers retention ties, ownership, holds, publication proof, pagination, trigger authority, races, API failures, idempotence, batch limits, and dry-run guarantees.
  • Adds a Vitest integration wrapper for the standalone Node test suite.
  • Documents operational admission and hold-disposition procedures and updates README/CHANGELOG test counts.
tests/unit/tooling/prunePagesDeployments.test.mjs
tests/unit/tooling/prunePagesDeployments.test.ts
docs/PAGES-DEPLOYMENT-RECORD-PRUNING.md
README.md
CHANGELOG.md

Assessment against linked issues

Issue Objective Addressed Explanation
#1028 Prune only positively identified GitHub Pages deployment records, retaining the newest three plus current, rollback, and evidence-protected records; fail closed on uncertain ownership, inventory, or API outcomes. ✅
#1028 Run bounded, serialized reconciliation with trusted-main authority, read-only manual dispatch, revalidation before mutations, and no deletion after failed inactivation; add regression tests and measure the trigger optimization without changing required CI gates. ✅
#1028 Complete the required post-merge operational verification, including a zero-write dry run against current GitHub state, before treating the retention restoration as operationally verified. ❌ The PR reports only a pre-merge dry run and explicitly leaves the post-merge dry run, evidence-hold disposition, and any separately approved enablement for later. It correctly keeps the workflow disabled, but the issue's post-merge verification exit criterion is not yet satisfied.

Possibly linked issues

  • #unknown: The PR implements the issue’s Pages-record pruning work, including ownership checks, retention protections, revalidation, and failure-safe deletion; its trigger strategy differs.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@codeant-ai codeant-ai Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files label Oct 12, 2026
codescene-access[bot]

This comment was marked as outdated.

@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

[check-pr-size] PR size is over the hard tier (normal profile): 15 files, 2884 meaningful lines, 15 commits — limit ≤20 files / ≤1200 lines / ≤10 commits. Consider splitting into smaller, independently reviewable PRs.

@coderabbitai

coderabbitai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: qnbs/WorldScript-Studio/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: ffc9c874-463c-4bb7-b96f-356d8a343dbd
📥 Commits

Reviewing files that changed from the base of the PR and between 026c155 and 2b1e677.

📒 Files selected for processing (6)
  • docs/PAGES-DEPLOYMENT-RECORD-PRUNING.md
  • scripts/pages-pruning/github.mjs
  • scripts/pages-pruning/provenance.mjs
  • scripts/pages-pruning/reconcile.mjs
  • tests/unit/tooling/prunePagesDeployments.test.mjs
  • tests/unit/tooling/support/pagesPruningFixture.mjs

Included review availability: This review used your included allowance. 0 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

📝 Walkthrough

The change adds bounded reconciliation for GitHub Pages deployment records. It validates ownership and publication evidence, protects retained and held records, and revalidates candidates before mutations. The workflow runs daily or by manual dispatch with read-only permissions; manual dispatch and the local CLI are read-only.

Changes: Pages deployment reconciliation

Layer / File(s) Summary
Define pruning eligibility
.github/pages-pruning-holds.json, scripts/pages-pruning/evidence.mjs, scripts/pages-pruning/policy.mjs, tests/unit/tooling/prunePagesDeployments.test.mjs
Defines evidence holds, validates ownership and inventory, and plans retention. Tests cover protected records, unknown ownership, authority, and invalid inputs.
Collect inventory and prove publications
scripts/pages-pruning/github.mjs, scripts/pages-pruning/provenance.mjs, tests/unit/tooling/support/pagesPruningFixture.mjs, tests/unit/tooling/prunePagesDeployments.test.mjs
Adds bounded API reads, validated pagination, and publication proof for current, rollback, and candidate records. Tests cover incomplete inventories and invalid or missing proof.
Revalidate and reconcile candidates
scripts/pages-pruning/provenance.mjs, scripts/pages-pruning/reconcile.mjs, tests/unit/tooling/support/pagesPruningFixture.mjs, tests/unit/tooling/prunePagesDeployments.test.mjs
Examines candidates and revalidates them and publication slots before mutation. Inactivation must succeed before deletion. Request budgets, batch limits, partial outcomes, and reporting are covered by tests.
Connect workflow and document operation
scripts/prune-pages-deployments.mjs, .github/workflows/prune-deployments.yml, tests/unit/tooling/prunePagesDeployments.test.ts, tests/unit/tooling/prunePagesDeployments.test.mjs, .github/CI-AUDIT.md, docs/PAGES-DEPLOYMENT-RECORD-PRUNING.md, CHANGELOG.md, README.md
Connects reconciliation to the scheduled workflow and Action reporting. The local CLI and manual dispatch are read-only. Documentation records the safeguards and enablement constraints; README test totals are updated.

Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 2b1e6

The change adds daily reconciliation of GitHub Pages deployment records. Deletion is still turned off by a code-level switch and by read-only workflow permissions. Manual runs and local runs make no changes. No concrete defect stands in the way of merging.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

qnbs commented Oct 12, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Please assess the exact final delta at a06078dd982e05ba60146ba21027b7f58a2385f6 against main ee526cb405f9ad94b0650a9b8b1704cdccde4bb9. This is destructive deployment-record maintenance; CI green alone is insufficient. Focus on positive Pages ownership and current/rollback proof, schedule/main authority and immutable evidence holds, revalidation before each POST/DELETE, failed/ambiguous inactivation, pagination/retries, partial counters, and zero-write dispatch. In particular assess the documented final-GET-to-write race: the pruning concurrency group does not serialize the Pages publisher or external status writers. Identify any unsafe assumptions; do not infer historical non-execution or hold release. Workflow remains disabled and no real deletion is admitted.

codescene-access[bot]

This comment was marked as outdated.

qnbs commented Oct 12, 2026

Copy link
Copy Markdown
Owner Author

@CodeAnt-AI review

Final head: a06078dd982e05ba60146ba21027b7f58a2385f6. Please review the complete Pages-record safety boundary, especially ownership/current-publication assumptions, each inactivate/delete revalidation, partial API failure and the documented non-transactional API race. The second commit only supplies this PR's required Changelog reference; the implementation delta is unchanged. Workflow enablement and real record deletion remain separately owner-gated.

Comment thread scripts/prune-pages-deployments.mjs Outdated
@codeant-ai

codeant-ai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

CodeAnt PR Risk: Medium Risk

  • The PR needs attention before merging because its rate-limit safeguard can rely on stale quota data.
  • In scripts/pages-pruning/github.mjs, a missing rate-limit header leaves the previous allowance unchanged, so repeated reads may pass the 100-request reserve; the destructive gate is currently closed.

Assessed commit: dec972c20314

@codeant-ai

codeant-ai Bot commented Oct 12, 2026

Copy link
Copy Markdown

Question: review

final head: a06078dd982e05ba60146ba21027b7f58a2385f6. please review the complete pages-record safety boundary, especially ownership/current-publication assumptions, each inactivate/delete revalidation, partial api failure and the documented non-transactional api race. the second commit only supplies this pr's required changelog reference; the implementation delta is unchanged. workflow enablement and real record deletion remain separately owner-gated.

Answer:

Finding

[P1 — before workflow enablement] The preflight checks are not atomic with the writes — scripts/prune-pages-deployments.mjs:318–359

revalidate() checks the main SHA immediately before returning, but the subsequent POST or DELETE is not conditional on that SHA or on the status version it observed. If main advances after the check to add a hold, the in-flight run can still delete that record. If a deployment is promoted after the check but before the inactivation POST, the follow-up inventory can prevent the DELETE, but it cannot undo the newly written inactive status. The pruning concurrency group does not serialize against the Pages deploy job in ci.yml, so that writer can overlap too.

This is an inherent API boundary rather than something another read can eliminate. The docs disclose the status race, but should also make clear that the main-hold check has the same gap and that a post-write recheck cannot reverse an inactivation. Since the workflow remains disabled and enablement is separately owner-gated, this is not an immediate deletion risk from merging; I would treat explicit owner acceptance and a decision about writer quiescence or snapshot semantics as a prerequisite to enablement.

The ownership checks, current-publication proof, bounded sequential writes, and fail-closed handling of ambiguous API outcomes otherwise look consistent with the stated policy.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository: qnbs/WorldScript-Studio/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: a7786ed6-4311-4085-824b-06ba23a044a4
📥 Commits

Reviewing files that changed from the base of the PR and between ee526cb and a06078d.

📒 Files selected for processing (8)
  • .github/pages-pruning-holds.json
  • .github/workflows/prune-deployments.yml
  • CHANGELOG.md
  • README.md
  • docs/PAGES-DEPLOYMENT-RECORD-PRUNING.md
  • scripts/prune-pages-deployments.mjs
  • tests/unit/tooling/prunePagesDeployments.test.mjs
  • tests/unit/tooling/prunePagesDeployments.test.ts

Included review availability: This review used your included allowance. 1 included review remains after this review. Your included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.

Comment thread scripts/prune-pages-deployments.mjs Outdated
Comment thread scripts/prune-pages-deployments.mjs Outdated

@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: a06078dd98

ℹ️ 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 .github/workflows/prune-deployments.yml
Comment thread scripts/prune-pages-deployments.mjs Outdated
Comment thread scripts/prune-pages-deployments.mjs Outdated
qnbs added 2 commits October 13, 2026 01:05
Resolve the independent-review findings on the Pages record reconciler.

Rollback slot: the current and previous publication are now proven against
the API before any candidate is classified. An unproved newer success is
protected and no longer consumes the rollback slot; no provable rollback
stops the run instead of exposing the prior known-good record.

Provenance: log_url is caller-written, so a record is deletable only when
the deployment and its newest success status were authored by the actor of
the referenced run and not by github-actions[bot]. This holds for all six
live records. A candidate that cannot be proven is protected and skipped
rather than failing the whole run.

Writer fence: GitHub has no compare-and-delete. A stale snapshot is shown
to stay safe against genuine publications, and in-repository record
writers are pinned by a test. Hold changes and external status writers
remain unfenced, so destructive writes stay closed in code and the
workflow token holds deployments: read only.

Scale: revalidation re-reads the list plus the candidate and both slots
instead of every history. A run is budgeted at 450 requests with a live
rate-limit reserve and a graceful stop. /repositories/{id} next links are
accepted for the verified repository id only.

Complexity: split into evidence, policy, github, provenance and reconcile
modules with single-purpose predicates.
codescene-access[bot]

This comment was marked as outdated.

@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: 031072076a

ℹ️ 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 scripts/pages-pruning/provenance.mjs Outdated
Comment thread scripts/pages-pruning/provenance.mjs
Comment thread scripts/pages-pruning/reconcile.mjs Outdated
@codecov

codecov Bot commented Oct 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@qnbs

qnbs commented Oct 13, 2026

Copy link
Copy Markdown
Owner Author

@CodeAnt-AI review

codescene-access[bot]

This comment was marked as outdated.

Comment thread scripts/pages-pruning/provenance.mjs Outdated
Comment thread scripts/pages-pruning/provenance.mjs Outdated

@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: 97206e2c4e

ℹ️ 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 scripts/pages-pruning/reconcile.mjs Outdated
Comment thread scripts/pages-pruning/reconcile.mjs
Comment thread scripts/pages-pruning/reconcile.mjs
Comment thread scripts/pages-pruning/reconcile.mjs
…e the posted inactive status, keep the manifest when a slot proof fails

funds() moves to the GitHub client so the proof scan, the POST and a DELETE without POST share one local-plus-live budget check. The status created by this run must come back as a recognised inactive Pages status before the DELETE. A stopped slot proof still reports every record as protected or unexamined.
codescene-access[bot]

This comment was marked as outdated.

@qnbs

qnbs commented Oct 13, 2026

Copy link
Copy Markdown
Owner Author

@CodeAnt-AI review

@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: cdfd0495ed

ℹ️ 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 scripts/pages-pruning/github.mjs
Comment thread scripts/pages-pruning/provenance.mjs Outdated
Comment thread scripts/pages-pruning/provenance.mjs
Comment thread scripts/pages-pruning/reconcile.mjs
…o the run SHA, accept the documented workflow path form, stop gracefully on a pre-write budget refusal

Failed reads and writes update the live allowance the scan and the write gates use. The job must report the same head SHA as its run. The CI workflow path matches with or without the documented main suffix. A request-budget refusal before a candidate's first write ends the pass as a budget-limit stop. prepareOrReport takes one input object to stay inside the argument limit.
Comment thread scripts/pages-pruning/reconcile.mjs Outdated
@qnbs

qnbs commented Oct 13, 2026

Copy link
Copy Markdown
Owner Author

@CodeAnt-AI review

codescene-access[bot]

This comment was marked as outdated.

@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: 2b1e677467

ℹ️ 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 scripts/pages-pruning/github.mjs
Comment thread scripts/pages-pruning/github.mjs
read() refuses with rate-reserve before a request that would leave fewer than 100 requests, retries and the whole inventory included, and with rate-unknown once a response succeeded without a rate header. A budget or reserve refusal before a candidate's first write ends the pass gracefully. The fixture answers with a rate header like the real API.
codescene-access[bot]

This comment was marked as outdated.

@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: dec972c203

ℹ️ 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 scripts/pages-pruning/github.mjs Outdated
…ce unknown

A successful response replaces the live allowance, so one that omits or malforms the header no longer leaves a stale value behind and the next read fails closed. Override responses in the fixture carry the default allowance like the real API.

@codescene-access codescene-access 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.

Gates Passed
3 Quality Gates Passed

See analysis details in CodeScene

Quality Gate Profile: The Bare Minimum
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.

@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: 064e665add

ℹ️ 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 scripts/pages-pruning/github.mjs
Comment thread scripts/pages-pruning/reconcile.mjs
@qnbs
qnbs merged commit 35a7866 into main Oct 13, 2026
49 checks passed
@qnbs
qnbs deleted the ci/1028-pages-record-pruning branch October 13, 2026 10:37
qnbs added a commit that referenced this pull request Oct 13, 2026

This branch was successfully deployed

1 active deployment
Preview — 064e665a Deployed Oct 13, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci(pages): restore safe continuous GitHub Pages deployment-record pruning

1 participant