Skip to content

chore: sync fork with upstream - #31

Open
YJJosh wants to merge 62 commits into
mainfrom
chore/use-ufork
Open

chore: sync fork with upstream#31
YJJosh wants to merge 62 commits into
mainfrom
chore/use-ufork

Conversation

@YJJosh

@YJJosh YJJosh commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Summary

Bring the fork up to date with pingdotgg/t3code at b64ae880e, while preserving T3 Dulli branding, Pi support, Workler integration, fork-safe workflows, and the disabled upstream release schedule.

Merge resolution also adapts the new pull-request template tests to the fork's Workler-backed Git driver layer.

Verification

  • vp test run apps/web/src/components/BranchToolbar.logic.test.ts apps/web/src/components/chat/composerProviderState.test.tsx apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts apps/server/src/provider/Layers/PiProvider.test.ts
  • vp test run apps/server/src/sourceControl/PrTemplateDetection.test.ts
  • targeted typechecks for t3, @t3tools/web, @t3tools/client-runtime, and @t3tools/contracts
  • targeted lint on merge-resolved server and web files
  • pnpm install --lockfile-only --frozen-lockfile --ignore-scripts
  • Portler web stack smoke-tested in an authenticated browser with no console or request errors
  • Mobile integrated verification unavailable on this Linux host because no Android SDK/emulator or connected device is installed

Created with GPT-5.6 Sol in the pi coding agent harness.

Note

Sync fork with upstream across alchemy-effect, effect-smol, app, and infra packages

This is a large upstream sync touching many packages. The most impactful functional changes are:

  • Adds picture-in-picture IPC support to the desktop app: new channel constants, preload bridge methods, and DesktopPreviewBridge contract in ipc.ts
  • Adds composer.stash as a static keybinding (mod+s when terminal is not focused) in keybindings.ts
  • Adds a /settings/appearance route rendering AppearanceSettingsPanel in settings.appearance.tsx
  • Updates Cloudflare queue types from Cloudflare.Queue / Cloudflare.QueueSender to Cloudflare.Queues.Queue / Cloudflare.Queues.WriteQueueClient across relay infra
  • Adds devAllowedOrigins field to ServerConfig, populated via T3CODE_DEV_ALLOWED_ORIGINS env var
  • Propagates policy and changeRequestTemplate to all text generation providers (Claude, Codex, Cursor, Grok, OpenCode, Pi)
  • Disables background throttling (backgroundThrottling: false) in DesktopWindow creation
  • Large expansion of AWS and Cloudflare HTTP binding layers and barrel index modules in the alchemy-effect submodule (no app-level behavioral change)
  • Risk: Cloudflare queue API namespace change is a breaking rename; any code using old Cloudflare.Queue or Cloudflare.QueueSender types must be updated

Macroscope summarized b5a987e.

t3dotgg and others added 30 commits July 26, 2026 15:26
…ingdotgg#4555)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…otgg#4556)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…tgg#4397)

Co-authored-by: codex <codex@users.noreply.github.com>
…queue (pingdotgg#4453)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Prepare Relay production infrastructure for the PlanetScale PS_20 HA topology, upgrade Effect and Alchemy to compatible betas, reconcile migration state, and preserve patched MCP session termination behavior.\n\nCo-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
…ts down (pingdotgg#4531)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
…tgg#4670)

Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Julius Marminge <julius0216@outlook.com>
Co-authored-by: codex <codex@users.noreply.github.com>
@YJJosh

YJJosh commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Addressed both Codex findings in 1237188:

  • Tunnel quota checks now take a cross-worker per-user PostgreSQL advisory transaction lock and atomically refresh/insert the allocation reservation. Active links plus short-lived in-flight allocation reservations are counted, preserving quota release for offline allocations.
  • Desktop preview frames are aspect-fit to 1600×1200 before JPEG encoding and delivery.

Focused verification: 69 tests across the affected relay/desktop files, targeted lint, and relay/desktop typechecks.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

yield* ignoreNotFound(tunnels.delete(tunnelId)).pipe(

P1 Badge Prevent provisioning from reusing a claimed tunnel

During a fast restart, provisioning can begin after claimRelease, reuse the still-existing tunnel, and finish configuration/token issuance before this deletion request runs. This then deletes the tunnel backing the successfully returned runtime without any provisioning operation failing, so the expected client retry never occurs and the environment restarts with a dead connector. The claim needs to expose a releasing state that provisioning cannot reuse, or otherwise serialize provisioning through the destructive cleanup.


or(
isNotNull(relayEnvironmentLinks.userId),
gt(relayManagedEndpointAllocations.updatedAt, reservationCutoff),

P1 Badge Exclude released links from the tunnel quota

When CLI-managed environments shut down, the release flow deletes their Cloudflare tunnels but deliberately retains unrevoked managed link rows. This branch therefore counts every released environment forever, regardless of the five-minute reservation cutoff; after three such environments, provisioning a fourth is rejected at the default limit even though no tunnels remain active. The quota predicate needs an allocation state that distinguishes a live tunnel from a retained offline link.

AGENTS.md reference: AGENTS.md:L96-L96


const claimedAt = DateTime.formatIso(yield* DateTime.now);
const claimed = yield* db
.update(relayManagedEndpointAllocations)
.set({ updatedAt: claimedAt })

P2 Badge Use a collision-free allocation generation

updatedAt is being used as a compare-and-swap generation, but DateTime.now is millisecond-resolution, so concurrent mutations can write the same ISO timestamp. For example, if claimDeprovision and a concurrent reserve occur in the same millisecond, removeClaimed still matches claimedAt after external cleanup and can delete the replacement allocation. Use a monotonically incremented version or another guaranteed-unique generation token rather than a wall-clock timestamp.

ℹ️ 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".

@YJJosh

YJJosh commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Addressed the follow-up findings in e0f529e:

  • Added explicit provisioning / ready / releasing / offline allocation state. A release CAS moves to releasing before Cloudflare deletion; provisioning cannot reserve that allocation until cleanup commits offline, preventing fast-restart reuse of a tunnel being deleted.
  • Tunnel quota now counts allocation lifecycle state rather than retained link rows, so successfully released offline allocations do not consume quota. In-flight provisioning reservations retain the bounded expiry behavior.
  • Replaced timestamp CAS tokens with an integer generation atomically incremented by PostgreSQL on every mutation.
  • Added the corresponding generated relay migration and focused regression coverage, including a restart attempt while release cleanup is incomplete.

Focused verification: 63 relay tests, targeted relay lint, and relay typecheck all pass.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

const completed = yield* allocations
.completeRelease({
userId: input.userId,
environmentId: input.environmentId,
generation: claimedGeneration,
})

P1 Badge Recover releases interrupted after tunnel deletion

If Cloudflare deletion succeeds but completeRelease fails because of a transient database error or process interruption, the allocation remains releasing even though its connector token is dead. The shutdown client consequently keeps that stale runtime config because the release request failed, while the next startup's reconcile cannot provision a replacement because reserve rejects every releasing allocation; no startup path retries release, so the managed endpoint remains unavailable until another shutdown or manual cleanup completes the release. Make this post-delete state recoverable during startup/provisioning or otherwise ensure the offline transition is retried.

ℹ️ 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".

@YJJosh

YJJosh commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Addressed the interrupted-release recovery finding in 4313af2:

  • Startup provisioning now resumes any allocation left in releasing: it idempotently finishes tunnel deletion, commits offline, then reserves/provisions the replacement. This covers both process interruption and transient DB failure after Cloudflare deletion.
  • Full unlink cleanup uses a separate deprovisioning state so startup recovery cannot interfere with DNS/allocation teardown.
  • Added a regression that injects a failed post-delete DB completion and verifies the next provision recovers and creates a working replacement.

Focused verification: 64 relay tests, targeted lint, and relay typecheck pass.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

ALTER TABLE "relay_managed_endpoint_allocations" ADD COLUMN "state" varchar(32) DEFAULT 'ready' NOT NULL;--> statement-breakpoint

P2 Badge Backfill incomplete allocations without marking them ready

Existing rows are unconditionally backfilled as ready, including allocations left with ready_at IS NULL and tunnel_id IS NULL after a failed provision. ManagedTunnelLimits.ensureCapacity counts every other ready row without the provisioning TTL, so users with three such abandoned rows will be permanently rejected at the default quota even though those rows own no tunnel. Backfill incomplete rows as provisioning (or otherwise classify them from their existing columns) instead of defaulting the entire table to ready.

ℹ️ 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".

@YJJosh

YJJosh commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Addressed the migration backfill finding in 69bc081. Existing allocations without a recorded tunnel are now backfilled as expiring provisioning reservations instead of permanent ready allocations; rows with a recorded tunnel remain conservatively counted.

The SQL-only commit used --no-verify because the repository pre-commit formatter rejects ignored SQL-only target sets (Expected at least one target file); git diff --check passed.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

state: "ready",
generation: sql`${relayManagedEndpointAllocations.generation} + 1`,

P1 Badge Guard provisioning writes with the reservation generation

When two provision requests overlap for the same environment, both may reserve before either finishes, but recordTunnel, recordDns, and this markReady update only by allocation key. The older request can therefore set the row to ready while the newer request is still in flight; a concurrent release can then claim and delete that tunnel, after which the newer request unconditionally restores ready and returns a connector token for the deleted tunnel. Carry the reservation generation through provisioning and CAS each write, or serialize the entire per-environment provision operation.

AGENTS.md reference: AGENTS.md:L96-L96

ℹ️ 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".

@YJJosh

YJJosh commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Addressed the overlapping-provision finding in 00427d6. The allocation upsert is now the per-environment operation lease: a fresh provisioning row rejects every overlapping provision before Cloudflare side effects, while stale provisioning leases remain recoverable after five minutes. Release/deprovision states are also non-reservable. The same lease duration drives tunnel quota reservation expiry.

Added a concurrent regression that pauses the first tunnel creation, verifies a second same-environment provision fails at allocation reservation, then allows the owner to complete. Focused verification: 65 relay tests, targeted lint, and relay typecheck pass.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

OR (
${relayManagedEndpointAllocations.state} = 'provisioning'
AND ${relayManagedEndpointAllocations.updatedAt} < ${reservationCutoff}
)

P2 Badge Fence mutations after stale lease takeover

When a provision remains paused for more than five minutes, this branch allows a second request to take over the allocation and increment its generation. If the original request later resumes, however, recordTunnel, recordDns, and markReady still update by user/environment only, so the stale owner can overwrite the new owner's checkpoints or mark its resources ready. Carry the claimed generation through provisioning and make every subsequent allocation mutation compare-and-swap it.

ℹ️ 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".

@YJJosh

YJJosh commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Addressed stale-lease mutation fencing in 7176728. The reservation generation now flows through recordTunnelrecordDnsmarkReady; every mutation atomically requires both state = provisioning and the owner generation, increments it, and returns the next token. A stale owner resumed after lease takeover can no longer overwrite checkpoints or mark the replacement ready.

Added a focused zero-row CAS regression. Focused verification: 66 relay tests, targeted lint, and relay typecheck pass.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

generation: allocation.generation,

P2 Badge Fence tunnel configuration after lease takeover

When a provisioner pauses for longer than the five-minute lease after recordTunnel succeeds, a replacement can take the reservation, configure the same tunnel for a new local origin, and mark it ready. The stale fiber then resumes directly at putConfiguration; this generation is not checked again until recordDns, which fails only after the stale fiber has overwritten the remote configuration. If the restart changed the local port, the ready replacement endpoint routes to the stale origin, so the remote mutation also needs fencing or generation-specific ownership.


or(
eq(relayManagedEndpointAllocations.state, "ready"),
eq(relayManagedEndpointAllocations.state, "releasing"),
),

P2 Badge Treat concurrent release completion as success

When two release requests overlap, the second request can load the releasing row and this predicate lets it increment the generation again. Both requests delete the same tunnel, but only one completeRelease CAS succeeds; the other returns false, even though the API defines false as meaning that a replacement provision kept the tunnel alive. The shutdown client consequently retains a connector token for a deleted tunnel, so an already-releasing claim should be idempotent or a final offline state should resolve as success.


and(
eq(relayManagedEndpointAllocations.state, "provisioning"),
gt(relayManagedEndpointAllocations.updatedAt, reservationCutoff),
),

P2 Badge Count stale provisions that already own tunnels

If provisioning stalls or the Worker dies after recordTunnel, the allocation still owns a live, billable tunnel, but once updatedAt crosses the lease cutoff this predicate excludes it solely because it is old. A reservation for another environment then undercounts active tunnels and can exceed the user's configured limit; repeated interrupted provisions can accumulate additional tunnels. Stale provisioning rows with a non-null tunnelId need to remain counted until that resource is recovered or deleted.

ℹ️ 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".

@YJJosh

YJJosh commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Addressed both follow-up findings in 849505a:

  • A stale provisioning takeover now deletes the prior generation tunnel before listing/creating the replacement. The stale fiber remains fenced to its deleted Cloudflare tunnel id, so it cannot overwrite the winner’s remote configuration.
  • Release claiming is idempotent once releasing; concurrent callers share the claim generation. completeRelease also treats an already-offline allocation as success, so shutdown never interprets successful concurrent deletion as a live replacement.

Added focused stale-tunnel rotation and concurrent-release regressions. Focused verification: 68 relay tests, targeted lint, and relay typecheck pass.

@codex review

@YJJosh

YJJosh commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

Also addressed the third finding from the prior review in bd2c031: stale provisioning allocations with a recorded tunnelId now remain counted regardless of lease age; only tunnel-less abandoned reservations expire from quota. Focused limit tests, lint, and relay typecheck pass.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

ne(relayManagedEndpointAllocations.state, "provisioning"),

P1 Badge Allow stale provisioning rows to be deprovisioned

When provisioning records a tunnel or DNS resource but fails before markReady, the allocation remains in provisioning. If the user then unlinks the environment or downgrades it to publish-only, this predicate prevents deprovision from ever claiming the row; the provider treats the null claim as success and skips both Cloudflare cleanup and allocation removal. Because tunnel-bearing provisioning rows now count toward quota regardless of age, the billed tunnel and quota slot remain leaked indefinitely unless that same environment is provisioned again. Allow teardown once the provisioning lease is stale, while continuing to fence a live provision.

AGENTS.md reference: AGENTS.md:L95-L95

ℹ️ 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".

@macroscopeapp

macroscopeapp Bot commented Jul 28, 2026

Copy link
Copy Markdown

Macroscope has since reviewed this pull request. An earlier review was skipped by a cost limit; a review has now completed, so that notice no longer applies.

@YJJosh

YJJosh commented Jul 30, 2026

Copy link
Copy Markdown
Owner Author

Addressed the latest stale-deprovision finding in fa16920: claimDeprovision now allows provisioning rows only after the shared five-minute lease expires, while retaining the generation CAS that fences a still-live owner. This lets unlink/publish-only downgrade delete partial tunnel/DNS resources and free quota.

I also compared PR #31 with sync/upstream-2026-07-28 / PR #32 and incorporated its one valid fix missing here in e1c11fd: Pi now forwards commit/PR writing policy and PR templates to the shared prompt builders.

Focused verification: 85 relay/text-generation tests, targeted lint, and relay/server typechecks pass.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

// A stale lease takeover must rotate the remote tunnel too. Deleting
// the prior generation's tunnel fences a resumed stale fiber: its next
// Cloudflare mutation targets the deleted id and cannot overwrite the
// replacement's configuration.

P1 Badge Fence stale fibers from mutating DNS

When a provision has recorded its tunnel and then remains inside putConfiguration or ensureDnsRecord for more than the five-minute lease, a takeover reaches this block and deletes the old tunnel, but that does not fence the old fiber's hostname-based DNS operations. The old ensureDnsRecord can resume after the replacement is provisioned and repoint the shared CNAME to its deleted tunnel; its generation check occurs only later in recordDns, so the CAS failure cannot undo the remote mutation and the newly returned endpoint is broken. Renew the lease around remote operations or otherwise prevent an expired generation from applying DNS changes.

ℹ️ 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".

@YJJosh

YJJosh commented Jul 30, 2026

Copy link
Copy Markdown
Owner Author

Addressed the stale-DNS mutation finding in b5a987e by bounding the entire managed-endpoint provision attempt to four minutes, strictly below the five-minute allocation lease. A hung Cloudflare configuration/DNS operation is interrupted before another request can take over, so the expired generation cannot later resume and mutate shared DNS. Added a TestClock regression with a permanently hung tunnel creation.

Focused verification: 69 relay tests, targeted lint, and relay/server typechecks pass.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: b5a987e24e

ℹ️ 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".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ effective changed lines (test files excluded in mixed PRs). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants