Skip to content

feat(kix): run the Worker locally with seeded data - #168

Merged
kixelated merged 6 commits into
mainfrom
quest/m0/kix/harness
Oct 21, 2026
Merged

kixelated merged 6 commits into
mainfrom
quest/m0/kix/harness

Conversation

@kixelated

@kixelated kixelated commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Completes quest/m0/kix/harness.md and removes it from the kix epic.

Problem

There was no way to check a UI change against representative data in a browser, and wrangler dev hangs in sandboxed agent environments.

Result

just worker-seeded (optionally --port 8788) serves the real Worker at http://localhost:8787 with seeded data:

  • Server (cloudflare/dev/serve.ts): bundles the Worker the way wrangler deploy --dry-run --outdir does, then serves it on Miniflare with in-memory D1, R2, and Durable Objects. Bindings and assets come from wrangler.jsonc, and the checked-in migrations are applied. Every run starts from the same seed.
  • Fake GitHub (cloudflare/dev/github.ts): handles every outbound request, so nothing leaves localhost and no real credential is used. It covers OAuth, App installation tokens, maintainer roles, the snapshot tree and blob GraphQL, the activity scan, issue and PR reads, flake.nix, inbox merges, and SPDX. Anything else gets a logged 501.
  • Sign-in: a small entry Worker rewrites GitHub's authorize redirect to the callback, so "Sign in with GitHub" completes as the seeded maintainer. Agents can use curl: curl -sL -c jar -b jar -H 'Origin: http://localhost:8787' -d provider=github http://localhost:8787/sign-in.
  • Seed (cloudflare/dev/seed.ts): signs in, enrolls, refreshes, pauses, and delivers a signed issues webhook, all through the Worker's own routes. The result has ready, claimed, and blocked quests; a pointer-only issue and a long-titled one; PRs whose checks succeed, fail, or are pending, with reviews and one clean to merge; and a paused project. Runners and jobs are written to D1 directly: queued, running, failed, waiting on a three-question agent prompt, waiting on a tool permission, and limited by an account.
  • Test (cloudflare/test/seed.test.ts): runs the same seed in the Worker tests, checks every inbox state renders, opens each item, and merges the clean PR. If the schema or routes drift, the seed fails in CI.
  • Docs: cloudflare/README.md documents the command as the way to check UI changes in a browser.

Bugs found and fixed

The tests mock fetch, so they hid two bugs that broke every GitHub App call in the deployed Worker. Running the real runtime exposed both:

  1. workerd's fetch refuses redirect: "error" with a TypeError. GitHubService and osiApproved now use redirect: "manual", and a 3xx still fails closed because it is not ok.
  2. this.#fetch(...) calls the global fetch as a method, which throws "Illegal invocation". The default is now wrapped.

The fake now builds a real Request and rejects method calls the way workerd does, so seed.test.ts reproduces both bugs. I confirmed it failed before each fix.

Validation

  • just check and just test pass in the Nix shell (CLI 232 tests, Worker 261 tests across 13 files).
  • Live run inside the agent sandbox, where wrangler dev hangs:
    • The curl sign-in lands on /inbox (200) and the page shows the seeded decisions.
    • /inbox, /projects, the project's state, board, and jobs pages, /account, /site.css, and /health all return 200.
    • A refresh returns 303 and fills in the webhook-only issue's title.
    • Ctrl-C (SIGINT) stops the server cleanly.

Decisions (made unattended, recommended options)

  • The recipe is just worker-seeded, after the existing worker-* recipes, rather than the quest's example name dev-seeded.
  • The server runs Miniflare directly, using Wrangler's unstable_getMiniflareWorkerOptions and unstable_splitSqlQuery. miniflare is now a dev dependency pinned to the version Wrangler pins. A Wrangler upgrade could rename these APIs, and just check would catch that.
  • The OAuth short-circuit lives in the harness's entry Worker. No Worker code changes for development.
  • test/project-fixtures.ts is not migrated onto the fake. It imports vitest and cloudflare:workers, so it can't run under Bun, its mock has per-test toggles, and kixelated/quest#165 edits it in parallel. The shared code is now the fake and the seed, which the new test uses.
  • The two production fixes ship here because the command can't work without them. They change three lines.

Follow-ups

  • The kix epic's stubbed end-to-end test can start from dev/seed.ts and dev/github.ts (the epic now says so). It still needs a fake runner over the WebSocket and fake publication endpoints (Git data API, forks, PR creation), which the fake does not model yet.
  • When kixelated/quest#165 lands, if it adds required secrets such as VAPID keys, dev/serve.ts needs local values for them.

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

kixelated and others added 4 commits October 21, 2026 11:44
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
just worker-seeded bundles the Worker as wrangler deploy --dry-run does
and serves it on Miniflare with in-memory storage, the checked-in
migrations, a fake GitHub, and a local sign-in. It works where wrangler
dev hangs. The seed goes through the Worker's own routes and runs in the
Worker tests too.

Running the real fetch exposed two bugs that broke every GitHub App call
in the deployed Worker: workerd refuses redirect: "error", and calling
fetch as this.#fetch() throws Illegal invocation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's inbox merge reads mergeStateStatus and merges through the pulls
merge endpoint, so the fake reports both and the seed has a clean pull
request to merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated marked this pull request as ready for review October 21, 2026 19:11
@kixelated

Copy link
Copy Markdown
Collaborator Author

Outcome: the quest is complete. just worker-seeded serves the seeded Worker on localhost, and it works inside the agent sandbox where wrangler dev hangs. Verified there with a curl sign-in followed by 200s on the inbox, project, board, jobs, and account pages. Running the real runtime also exposed two production bugs that broke every GitHub App call (redirect: "error" and an Illegal invocation on this.#fetch). Both are fixed here, with test/seed.test.ts as the regression test. just check and just test pass. The decisions I made unattended and the follow-ups are listed in the description.

(Written by Claude Opus 5.5)

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 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-21T19:45:19.981964Z 7a66d35 New commits
🔒 Security Review ✅ Completed 2026-10-21T19:45:06.642294Z 7a66d35 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.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Merge summary for just worker-seeded, the local harness that serves the real Worker on Miniflare with seeded data and a fake GitHub.

Changes since the last summary: two clean merges of main, with no conflicts:

Neither merge changed the schema. The seed test still passes against the new inbox redirects and the retry changes.

Validation on 7a66d35:

  • just check and just test pass in the Nix shell (CLI 237 tests, Worker 265 tests).
  • Live run: the curl sign-in lands on /inbox (200) with the seeded decisions. /projects, /account, /site.css, and /health return 200.
  • CI passes. Codex's code and security review of 7a66d35 has no findings.

Decisions accepted by the maintainer:

  • The recipe is named just worker-seeded.
  • The harness uses Miniflare directly, through Wrangler's unstable APIs.
  • The OAuth short-circuit lives in the harness's entry Worker.
  • test/project-fixtures.ts is not migrated onto the fake.
  • The two workerd fixes (redirect: "manual" and the wrapped fetch) ship here.

Follow-ups:

  • When kixelated/quest#165 lands, give cloudflare/dev/serve.ts local VAPID values or leave push disabled.
  • Miniflare starts listening before the seed finishes, so /health answers 200 while /inbox still returns 500. Scripts should wait for the "Seeded kix at" line. Alternatively, the entry Worker could hold requests until seeding is done.

(Written by Claude Opus 5.5)

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