Scoop bucket updates via daily pull, not release push - ward.json lags releases (~2 behind v0.361.0) #571

Closed
opened 2026-07-03 17:30:50 +00:00 by coilysiren · 2 comments
Owner

Symptom

The Windows scoop channel (coilysiren/scoop-bucket ward.json) lags behind ward releases - currently ~2 versions behind v0.361.0. A Windows user running scoop update ward installs a stale binary.

Root cause

ward's release.yml publishes the Windows .exe + per-asset .sha256 sidecars to the release page (the contract scoop autoupdate reads, ward#561), but it does not push anything to coilysiren/scoop-bucket. The bucket's ward.json version bump was wired (by the codex windows-scoop run) as a daily scheduled autoupdate pull on the bucket side. So the manifest only refreshes once a day and lags however many releases land in that window - releases bump the minor version on every push to main, so a busy day leaves scoop several versions behind.

This is a pull where the rest of the release path is a push. Every other artifact (Forgejo release page, GitHub mirror, homebrew tap) is written at release time by the tag build. Only scoop polls.

Fix direction

Make it push, not poll: ward's release fires a release-time update to coilysiren/scoop-bucket on each tag (a cross-repo repository_dispatch / manifest bump, reusing the GitHub PAT pattern already in mirror-to-github.yml since the bucket is GitHub-hosted). The daily cron demotes to a safety-net fallback rather than the primary path, so a missed dispatch still self-heals within a day but the normal case is immediate.

Note the cross-repo shape: the bucket side needs a listener (an on: repository_dispatch or equivalent workflow) to accept the push, or ward writes the bumped ward.json directly via the PAT. Scope the exact mechanism in the run.

  • ward#561 - the scoop upgrade channel + .sha256 sidecar contract.
  • mirror-to-github.yml - the existing release-time GitHub push pattern to reuse.
## Symptom The Windows `scoop` channel (`coilysiren/scoop-bucket` `ward.json`) lags behind ward releases - currently ~2 versions behind `v0.361.0`. A Windows user running `scoop update ward` installs a stale binary. ## Root cause ward's [`release.yml`](.forgejo/workflows/release.yml) publishes the Windows `.exe` + per-asset `.sha256` sidecars to the **release page** (the contract scoop autoupdate reads, ward#561), but it does **not** push anything to `coilysiren/scoop-bucket`. The bucket's `ward.json` version bump was wired (by the codex windows-scoop run) as a **daily scheduled autoupdate pull** on the bucket side. So the manifest only refreshes once a day and lags however many releases land in that window - releases bump the minor version on every push to main, so a busy day leaves scoop several versions behind. This is a **pull where the rest of the release path is a push**. Every other artifact (Forgejo release page, GitHub mirror, homebrew tap) is written at release time by the tag build. Only scoop polls. ## Fix direction Make it **push, not poll**: ward's release fires a release-time update to `coilysiren/scoop-bucket` on each tag (a cross-repo `repository_dispatch` / manifest bump, reusing the GitHub PAT pattern already in [`mirror-to-github.yml`](.forgejo/workflows/mirror-to-github.yml) since the bucket is GitHub-hosted). The daily cron demotes to a safety-net fallback rather than the primary path, so a missed dispatch still self-heals within a day but the normal case is immediate. Note the cross-repo shape: the bucket side needs a listener (an `on: repository_dispatch` or equivalent workflow) to accept the push, or ward writes the bumped `ward.json` directly via the PAT. Scope the exact mechanism in the run. ## Related - ward#561 - the scoop upgrade channel + `.sha256` sidecar contract. - [`mirror-to-github.yml`](.forgejo/workflows/mirror-to-github.yml) - the existing release-time GitHub push pattern to reuse.
Member

🔒 Reserved by ward agent --driver claude — container engineer-claude-ward-571 on host KAI-DESKTOP-TOWER is carrying this issue (reserved 2026-07-03T17:31:15Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `engineer-claude-ward-571` on host `KAI-DESKTOP-TOWER` is carrying this issue (reserved 2026-07-03T17:31:15Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. **Do not comment on or edit this issue to steer the run while it is reserved.** The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a **new issue, dispatched fresh** — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494). <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Owner

WARD-OUTCOME: done - release.yml now writes bucket/ward.json to the Forgejo scoop bucket at each tag (bump-scoop-manifest), the push-not-poll sibling of bump-tap-formula.

The shape of the fix was easy once I found the right analog: bump-tap-formula already does exactly this for Homebrew (clone sibling packaging repo, rewrite version+hash, push, read back to verify), so the scoop job is that job with a JSON manifest instead of a Ruby formula. Mirroring it kept the fail-loud + verify-after-push discipline for free.

What fought back was the premise. The issue says ward.json lags ~2 behind and that a daily autoupdate cron already runs on the bucket. When I actually looked, the bucket (coilyco-bridge/scoop-bucket, the coilysiren/* redirect) has no ward.json at all and no cron - the "codex windows-scoop run" work never landed. So there was nothing to demote and nothing to bump; the job had to create the manifest from scratch. I made it write the whole file every release (self-healing: the first tag creates it), rather than patch a version line that isn't there.

The other fork: the issue calls the bucket GitHub-hosted and says reuse the mirror PAT. But the bucket is Forgejo-canonical - users "scoop bucket add" from forgejo.coilysiren.me and checkver reads the Forgejo releases.atom - so "scoop update ward" only sees a manifest current on Forgejo. Pushing to the GitHub mirror alone would not clear the lag. I pushed to Forgejo (matching the homebrew-tap sibling) and documented the reasoning in docs/release.md so it is easy to course-correct if that was intended.

Confidence: high on the wiring (YAML validated, node manifest-gen tested against the real v0.363.0 sidecars, output matches the repo-recall.json contract, verify-grep passes). The one thing untested end-to-end is the live cross-repo push, which only exercises on the next real tag and needs a new SCOOP_WRITE_TOKEN secret - unset, the job goes red on an otherwise-green release (deliberate, the tap fail-not-freeze stance).

Follow-ups worth filing: (1) provision SCOOP_WRITE_TOKEN (push scope to the bucket) before the next release; (2) if a real daily-cron safety net is wanted, it has to be added on the bucket repo itself (out of this run scope - I was not granted it); (3) consider dual-pushing the manifest to the GitHub mirror too if scoop users are ever pointed there.

WARD-OUTCOME: done - release.yml now writes bucket/ward.json to the Forgejo scoop bucket at each tag (bump-scoop-manifest), the push-not-poll sibling of bump-tap-formula. The shape of the fix was easy once I found the right analog: bump-tap-formula already does exactly this for Homebrew (clone sibling packaging repo, rewrite version+hash, push, read back to verify), so the scoop job is that job with a JSON manifest instead of a Ruby formula. Mirroring it kept the fail-loud + verify-after-push discipline for free. What fought back was the premise. The issue says ward.json lags ~2 behind and that a daily autoupdate cron already runs on the bucket. When I actually looked, the bucket (coilyco-bridge/scoop-bucket, the coilysiren/* redirect) has **no ward.json at all** and **no cron** - the "codex windows-scoop run" work never landed. So there was nothing to demote and nothing to bump; the job had to *create* the manifest from scratch. I made it write the whole file every release (self-healing: the first tag creates it), rather than patch a version line that isn't there. The other fork: the issue calls the bucket GitHub-hosted and says reuse the mirror PAT. But the bucket is Forgejo-canonical - users "scoop bucket add" from forgejo.coilysiren.me and checkver reads the Forgejo releases.atom - so "scoop update ward" only sees a manifest current on Forgejo. Pushing to the GitHub mirror alone would not clear the lag. I pushed to Forgejo (matching the homebrew-tap sibling) and documented the reasoning in docs/release.md so it is easy to course-correct if that was intended. Confidence: high on the wiring (YAML validated, node manifest-gen tested against the real v0.363.0 sidecars, output matches the repo-recall.json contract, verify-grep passes). The one thing untested end-to-end is the live cross-repo push, which only exercises on the next real tag and needs a new SCOOP_WRITE_TOKEN secret - unset, the job goes red on an otherwise-green release (deliberate, the tap fail-not-freeze stance). Follow-ups worth filing: (1) provision SCOOP_WRITE_TOKEN (push scope to the bucket) before the next release; (2) if a real daily-cron safety net is wanted, it has to be added on the bucket repo itself (out of this run scope - I was not granted it); (3) consider dual-pushing the manifest to the GitHub mirror too if scoop users are ever pointed there.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-flight-deck/ward#571
No description provided.