docs: record the stable fork/dev development and release branch - #342
Merged
omegent-app[bot] merged 9 commits intoAug 6, 2026
Merged
Conversation
patroza
added a commit
that referenced
this pull request
Aug 6, 2026
First run of the provenance synchronization from [#342](#342) — and the answer to "get the latest upstream onto `fork/dev`". Five upstream commits enter the product: | | | | --- | --- | | `a2ca89aa` | feat: native subagent & workflow observability (pingdotgg#5219) | | `990bb0b6` | fix: reconnect faster after remote server updates (pingdotgg#5404) | | `7251f1a1` | Prevent terminal loading flash (pingdotgg#5432) | | `30e47153` | fix(web): preserve terminal font size when splitting (pingdotgg#5444) | | `de592a00` | Enrich terminal font previews (pingdotgg#5428) | 54 files, +7,055 / −175. ## Checkpoint ```json { "importedCandidatesCommit": "9655a9ba955197361044ef6f8f97e35841ff779e", "importedCandidatesTree": "50f9bfab717c30a8ea90d52060349e209502d116", "importedUpstreamCommit": "a2ca89aa10f13a2222e08afd98c66285121d5ba2", "previousCandidatesTree": "9b4cd3e1c774c3c436e43305c151edf596b2936a" } ``` `previousCandidatesTree` is C1 from tag `fork-dev/2026-08-06.1`. Tag the merge commit `fork-dev/2026-08-06.2` with the values above once this lands. ## Two resolutions worth reviewing Most of the 7 conflicted files are independent additions on both sides and resolve as unions — upstream's `backgroundLiveness` beside identity's `originSource`/`participantSummaries`, upstream's agent-spawn CTA rows beside the imported user-input Q&A timeline. Two were not unions: **`apps/web/src/components/Sidebar.logic.ts`** — the 3-way merge welded upstream's `hasPlanReadyPrompt` condition onto the `"Wake Required"` return body. Left alone, a plan-ready thread would render as **Wake Required** and no thread could ever reach **Plan Ready**. Both branches are restored with their own bodies. The status rank map is merged onto upstream's new scale with `Wake Required` at the `Working`/`Connecting` tier — its relative position before the import. **That tier placement is a judgement call; say if you want it ranked differently.** **`apps/mobile/src/lib/threadActivity.ts`** — upstream's `isAgentInternalActivity` skip guard must run *before* identity's resolved-user-input enrichment. The other order enriches and pushes exactly the agent-internal rows upstream means to drop. ## Validation - All 12 `fork/candidates` commits replayed onto the rebuilt `fork/tim`; `a2ca89aa1` confirmed an ancestor of the new candidates tip. - No residual conflict markers; brace balance checked on the hand-edited files. - **Typecheck and tests have not run locally** — the rebase workspace has no `node_modules`. Fork CI on this PR is the first real verification. Do not merge on the strength of this description. ## Provenance branches not yet pushed `fork/base` → `4a73589` and `fork/tim` → `b1c5fa5` are rebased and `fork/candidates` → `9655a9ba` is rebuilt, but all three are **local only**. The ruleset *Protect fork/tim, candidates, integration* sets `non_fast_forward` with no bypass actor and the app token has no `administration` scope, so I cannot force-push them. Until they are pushed, `importedCandidatesCommit` refers to a commit that exists nowhere on the remote. The tree is what the delta depends on, but the checkpoint is not fully honest until that push happens. Co-authored by [@patroza](https://github.com/patroza) opened by [Patrick Roza](https://discord.com/users/95218063095377920) in chat thread **Discord** · [Discord](https://discord.com/channels/1083767712431480922/1534783738322485399/1534783738322485399) · [T3](https://t3vm/?thread=584a9ad3-243e-4308-8a13-49acdd758b17) Co-authored-by: omegent-app[bot] <306514130+omegent-app[bot]@users.noreply.github.com> Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
patroza
added a commit
that referenced
this pull request
Aug 6, 2026
Implements the split you asked for, without reintroducing `fork/integration` and without any ops change. ## The problem `fork-ci`'s conclusion is what the smart-host poller promotes on — and it also carried the mobile release dispatch. So `ae4719b1c` passed all four required checks, failed only at `Dispatch Mobile Releases`, and stranded server, Discord, desktop and VS Code deployment of the entire upstream import. A release action could veto a validation verdict. ## The split | Workflow | Answers | Consumed by | | --- | --- | --- | | **Fork CI** | "is this SHA valid?" | the deploy poller, branch protection | | **Fork Release** (new) | "release this validated SHA" | nothing — terminal | Chained with `workflow_run`, which fires only after Fork CI **concludes success** for a `push` on `fork/dev`. Against your four constraints: - **Nothing released unless the SHA is green** — `workflow_run` gates on `conclusion == 'success'`, and the `workflow_dispatch` escape hatch re-checks it against the API rather than trusting the operator. Releasing an unvalidated SHA by hand is the one thing this split must not make easier. - **Release breakage must not turn the SHA red** — the failure is recorded against the release run. The poller queries `fork-ci.yml` runs and never sees it. - **Releases follow the green verdict** — that is precisely `workflow_run` ordering, rather than the previous arrangement where dispatch raced the other jobs inside the same run. - **No `fork/integration`** — not needed, and the ops poller is untouched. ## Two details worth reviewing **Release scope compares against the last SHA _this workflow released_**, not the last that merely passed CI. Otherwise a commit whose release was skipped drops out of scope permanently and its changes are never represented in any release. **Concurrency is keyed per SHA with `cancel-in-progress: false`.** Two releases of different commits may safely overlap, and cancelling a queued one would leave that commit silently unreleased. ## Prerequisite: `fork/dev` must be the default branch `workflow_run` only fires for workflow files present on the **repository default branch**, which is still `fork/changes`. Until that flips, this workflow will not trigger and mobile releases must be dispatched manually (`workflow_dispatch` with an exact SHA — the green check still applies). That was already Step 1 of [#342](#342); this just gives it a concrete forcing reason. ## Validation - Both workflows parse; triggers and job sets confirmed: `fork-ci` → `check, test, mobile_native_static_analysis, release_smoke`; `fork-release` → `release`. - `vp fmt --check` clean. - **The `workflow_run` chain is unexercised** and cannot be until the default branch flips. The gate logic and the green re-check are reviewable by reading; the trigger itself is not yet proven. Worth watching the first merge after the flip. Co-authored by [@patroza](https://github.com/patroza) opened by [Patrick Roza](https://discord.com/users/95218063095377920) in chat thread **Discord** · [Discord](https://discord.com/channels/1083767712431480922/1534783738322485399/1534783738322485399) · [T3](https://t3vm/?thread=584a9ad3-243e-4308-8a13-49acdd758b17) Co-authored-by: omegent-app[bot] <306514130+omegent-app[bot]@users.noreply.github.com> Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
patroza
added a commit
that referenced
this pull request
Aug 6, 2026
Closes the overlay era. `fork/dev` was cut from the composed `fork/integration` tip, so every registered overlay's product content has been in `fork/dev` since the cutover. ## Containment re-verified against the current tip | Overlay | PR | Commits present in `fork/dev` | | --- | --- | --- | | `fork/identity` | #250 | 17 / 17 | | `t3-discord/f7d37879-desktop-deeplinks` | #254 | 8 / 8 | | `fork/discord` | #174 | 9 / 12 | | `fork/vscode` | #175 | 2 / 3 | The four that are not present touch **`pnpm-lock.yaml` only** — checked by path, not by subject. They are regeneration artifacts that compose discards by its own `pnpm-lock.yaml -> theirs` rule and replaces with its own lockfile commit. No product content sits outside `fork/dev`. ## Change - `integrationOverlays` emptied in `.github/pr-stack.json`. - The matching `pull_request` bases dropped from `fork-ci.yml`, which carried an explicit instruction to stay in sync with that list. Overlay PRs #254, #174, #175 and #250 are closed alongside this. Leaving them open against `fork/changes` would duplicate their commits the next time anything composes — the one ordering hazard called out in [#342](#342). ## Scope Deliberately narrow. The overlay machinery itself — `compose-integration`, `rebase-integration-overlays`, `force-update-overlay-tip`, `client-overlay-ownership` and the surrounding docs — is left in place. Removing it touches ~20 files and is a separate decision; it still passes its own tests with an empty manifest. ## Validation - `fork-stack`, `rebase-pr-stack`, `compose-integration-overlays`, `client-overlay-owner` and `rebase-integration-overlays` suites: **69/69 pass** against the empty manifest, so the tooling tolerates zero overlays rather than assuming at least one. - `vp fmt --check` clean. Co-authored by [@patroza](https://github.com/patroza) opened by [Patrick Roza](https://discord.com/users/95218063095377920) in chat thread **Discord** · [Discord](https://discord.com/channels/1083767712431480922/1534783738322485399/1534783738322485399) · [T3](https://t3vm/?thread=584a9ad3-243e-4308-8a13-49acdd758b17) Co-authored-by: omegent-app[bot] <306514130+omegent-app[bot]@users.noreply.github.com> Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
The proposal read as one large migration whose payoff arrived at the end. In practice the benefit is concentrated in two steps — cut fork/dev from the green fork/integration tip, and release exact green fork/dev SHAs — and everything downstream of that is optional. Restructure accordingly: - Add an adopt-now/defer table so the blocking work is visible without reading the whole document. - Promote the fork/dev cutover and release-from-fork/dev into named steps 1 and 2, each a concrete checklist. - Move clean downstream projection, tree-equivalence proofs, and periodic projection releases into a section marked deferred, and say plainly that nothing in steps 1-3 depends on them. - State that provenance synchronization is a manual procedure to begin with; automating it is a convenience, not a prerequisite. - Keep Source-* import trailers as immediate practice, since they are cheap at import time and hard to reconstruct later. Call out the one ordering hazard explicitly: fork/dev is cut from fork/integration, not fork/changes, so overlay content is present from the first commit and every registered overlay must be drained rather than left open against fork/changes. Add an Ops Repository Changes section describing the prerequisite made available in aaaomega/ops: the trusted deploy branch, CI workflow, and CI trigger event become configurable with today's values as defaults, so the cutover is a deploy.env edit and a poller restart, and reverting is the same edit. Note that component checkpoint state keeps its filenames so the cutover does not trigger a full fleet redeploy. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
The ops prerequisite section named the private ops repository and the deployment host directly. Neither is needed to explain the change, and this document lives in a public repository. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
Squash was listed as an open decision. It is decided: every PR into fork/dev becomes exactly one commit. That is also what makes the rest of the document hold together — the PR ledger maps one-to-one onto fork/dev history, release scope is a diff between two commits, and a later clean projection has a single unit to replay per PR. Whether any exception is warranted is deliberately left open rather than pre-specified; it can be argued when a concrete case appears. Until then squash is the only merge method in practice, and step 1 now sets GitHub's default merge method rather than relying on contributors picking the right button. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
The merge-policy section said to "set GitHub's repository default merge method" and that leaving the other methods enabled was fine. There is no such field. GitHub picks the merge button's primary action from whichever methods are enabled, in the order merge commit then squash then rebase, so leaving merge commits enabled would have left merge commit as the default and quietly contradicted the decision. Squash only becomes the default by disabling merge commits and rebase merging. That also gives exceptions the right shape: taking one requires deliberately re-enabling a method, rather than picking a different dropdown entry. Also flag an ordering trap in step 1: required checks must not be configured before CI is wired to run for fork/dev, or the PR that enables that CI can never satisfy them. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
The branch page reports "5 commits behind pingdotgg/t3code:main" immediately after a successful sync, and the count grows with every import. That is a commit-graph artifact: the delta lands as one squashed commit, so fork/dev carries upstream's content without upstream's commit objects, and GitHub computes ahead/behind by reachability alone. Verified against the first real sync — all five upstream commits' content is present in fork/dev and none of them is an ancestor of it. The dangerous part is the "Sync fork" button sitting next to that banner. It merges upstream main into fork/dev, which is precisely the duplicate-history failure this section already warns about for provenance tips, and the banner invites it on every visit. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
The document claimed fork/dev could not carry upstream commits and that the branch page would read N commits behind forever. That was wrong, and the reasoning behind it was over-applied. The no-merge rule protects against branches that are rebased: fork/base, fork/tim and fork/candidates get new commit identities each cycle, so merging their tips repeatedly duplicates history. upstream/main is append-only and its identities are permanent, so nothing stops fork/dev from having them. Importing only a tree delta brings upstream's content without its commit objects, and GitHub measures ahead/behind by reachability alone — so the one number worth reading was permanently wrong. Close the sync with `git merge -s ours <upstream-tip>`, which keeps the tree byte-for-byte and adds only the parent link. Verified against the current tip: tree unchanged at 5ce8e37, upstream a2ca89a becomes an ancestor, behind count 0. State the hazard plainly: -s ours asserts every upstream change is accounted for, so a resolution that silently dropped one makes that loss permanent. It belongs at the end of a verified sync, never run alone to green the banner. Configuration follows from wanting a merge commit without giving up squash. Re-enabling merge commits repo-wide would make Merge the primary button again — GitHub orders merge, squash, rebase — reversing the squash decision for every ordinary PR. So keep squash-only and give the sync automation a ruleset bypass actor to push the ancestry merge directly. The sync PR itself stays squashed; the ancestry merge lands on top. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
The document still read as a plan with "do now" steps while the migration had already been executed and, in places, executed differently. Rewrite it as the record. Corrected to match reality: - fork/dev is the default branch, the contributor target and the release source, live since 2026-08-06, with the actual ruleset, checkpoint tags and SHAs named. - Release now spans two workflows. fork-ci decides whether a SHA is valid and fork-release acts on that verdict via workflow_run, because a release action must never be able to veto a validation verdict. - Ops parameterization and the deploy.env cutover are done, not pending. - fork/changes and fork/integration are frozen, not fallbacks. - Check selection is not path-inferred and the document no longer implies it is. Every PR runs all four required checks; only release scope is classified. A path filter that errs narrow silently skips a check on a protected branch, which is worse than a slightly slower suite. Adds what the cutover surfaced, because each item cost a round trip: fork/dev had no CI path at all, mobile releases would have stopped silently, both mobile workflows hardcoded fork/integration and rejected every fork/dev SHA, a release failure could strand the fleet, and every PR based on fork/changes was already broken by earlier rebases and needed its one real commit cherry-picked rather than its branch replayed. Open decisions are now the ones that are genuinely still open, and the migration steps are the ones genuinely still outstanding. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
The overlays are drained and deregistered, but the instructions an agent or a contributor actually reads before opening a PR still sent them at fork/discord, fork/vscode, fork/identity, the desktop deep-links branch, or fork/changes. Left alone, the next client-owned change would have been opened against a closed overlay on a frozen branch. CLAUDE.md (AGENTS.md symlinks to it) now says branch from fork/dev and target fork/dev for every kind of work, names main, fork/changes and fork/integration as bases never to use, and records that integrationOverlays is empty rather than describing how to register one. The Discord bot's turn rules pointed recovery branches at "the correct base (fork/discord overlay / fork/changes / etc.)" and now point at fork/dev. fork-stack.md, stack-ship-path.md and client-overlays.md describe the previous operating model in detail. They are bannered as superseded rather than rewritten: the provenance stack they document is still current, and they are the record of how the fork worked before the cutover. The two lines in them that literally instructed a base are corrected, so nothing in the repository still directs a PR anywhere but fork/dev. Co-authored-by: Patrick Roza <42661+patroza@users.noreply.github.com>
omegent-app
Bot
force-pushed
the
docs/stable-dev-release-branch-handover
branch
from
August 6, 2026 08:39
7556f09 to
88d47fd
Compare
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.
Records the
fork/devdevelopment and release model — adopted and live since 2026-08-06. Thisstarted as a proposal; the migration then ran ahead of it, so the document is now the record rather
than the plan.
Documentation only. Every mechanism it describes is already merged and running.
The model
fork/devis the default branch, the contributor target and the release source. It is never rebased.The provenance stack
main → fork/base → fork/tim → fork/candidatesstays rebased and feedsfork/devthrough reviewed tree deltas, so contributor bases are never invalidated by an upstreamupdate.
fork/devcut from greenfork/integration21badd04e, trees proven identicalfork-dev/2026-08-06.1fork/devPRs and mergesfork/devSHAsdeploy.env2a04db134..a2ca89aa1fork-dev/2026-08-06.23a7e7a458What this revision corrects
The document had drifted from what was actually built:
fork-cidecides whether a SHA is valid;fork-releaseacts on that verdict via
workflow_run. A release action must never be able to veto a validationverdict — when mobile dispatch lived inside
fork-ci, one failed EAS call marked a valid SHAunapprovable and stranded the whole fleet.
PR runs all four required checks; only release scope is classified. A path filter that errs
narrow silently skips a check on a protected branch, which is worse than a slightly slower suite.
fork/changesandfork/integrationare frozen, not fallbacks.deploy.envcutover are done, not pending.What the cutover surfaced
Added as a section, because each cost a round trip and the old path hid all of them:
fork/devhad no CI path at all — nopushtrigger, not listed as apull_requestbase.ref: fork/integrationand rejected everyfork/devSHA.fork/changeswas already broken by earlier rebases — GitHub reported themas 60–100 commits and 629–741 files. Each was one commit of real work on stale history, fixed by
cherry-picking that commit rather than replaying the branch.
That last one is the clearest evidence for the whole premise: the old model was silently corrupting
in-flight work, and nobody could see it.
Deliberately not done
Clean downstream projection is deferred indefinitely and nothing depends on it. Provenance sync stays
manual. The overlay machinery is still present and still passes its tests with an empty manifest;
removing it touches ~20 files and is a separate decision.
Still open
PRs #317, #226 and #185 conflict when cherry-picked onto
fork/dev; #237 and #238 live in anexternal fork and need their author.
fork/changesandfork/integrationcan be deleted once thoseare drained.
Also: no guidance targets an overlay any more
The overlays were drained in #348, but the instructions an agent or contributor actually reads before
opening a PR still sent them at
fork/discord,fork/vscode,fork/identity, the desktopdeep-links branch, or
fork/changes. Left alone, the next client-owned change would have been openedagainst a closed overlay on a frozen branch.
CLAUDE.md(AGENTS.mdsymlinks to it): branch from and targetfork/devfor every kind ofwork;
main,fork/changesandfork/integrationnamed as bases never to use; the"register an
integrationOverlaysentry" instructions replaced with a record that it is empty.apps/discord-bot/docs/agent-turn-rules.md: recovery branches pointed at "the correct base(
fork/discordoverlay /fork/changes/ etc.)" →fork/dev.fork-stack.md,stack-ship-path.md,client-overlays.md: bannered as superseded rather thanrewritten — the provenance stack they document is still current and they are the record of how the
fork worked before the cutover. The two lines that literally instructed a base are corrected.
Verified by grep: nothing in the repository still directs a PR anywhere but
fork/dev.Validation
vp fmt --checkclean; internal anchors checked. Documentation only — no code, tooling or workflowchanges in this PR.
Co-authored by @patroza
opened by Patrick Roza in chat thread Discord · Discord · T3