Skip to content

Fork maintenance: commit stack on upstream, rebase routine and CI #6

Closed

Description

@lukemaj

Outcome

The fork's changes live as a small, reviewable commit stack on upstream pingdotgg/t3code main, and a routine absorbs upstream updates cheaply and safely, so the fork can grow (Model Router, OpenBot mode, VMs) without falling behind.

Acceptance criteria

  • docs/fork.md (or equivalent) describes the model: upstream main is the base; fork work is a stack of topic commits; features go in new files and packages; upstream edits stay minimal and are listed with their files.
  • A script or agent routine fetches upstream, rebases the stack, runs the fork's CI, and reports conflicts per upstream file; it never force-pushes a published branch without the same proof.
  • CI on the fork runs upstream's own checks plus fork tests on every PR and on the rebased stack.
  • One real upstream update has been absorbed through the routine, with the conflicts and time recorded.
  • A list of candidate upstream extension points (for example a real parentThreadId on thread.create, a right-panel tab registry) with the patch each would remove. Offering them upstream is a separate human decision.

Non-goals

Sending anything upstream; releases; mobile builds.

Blockers

Direction confirmation in #5.

Proof

The recorded upstream absorption and CI run.

Objective contribution

First completion criterion of the draft Objective in #5; everything else builds on a maintainable fork.

Activity

  1. lukemaj commented on Sep 25, 2026

    @lukemaj
    ContributorAuthor

    Submitted to Model Router as job t3code-6-1101 (source runner at model-router e837872, state dir ~/.local/share/durable-runner-planner-f1213, planner: Claude thread f1213d48). One PR will follow; not merged.

  2. lukemaj commented on Sep 25, 2026

    @lukemaj
    ContributorAuthor

    First job t3code-6-1101 falsely failed at runner control (see the new model-router bug) after its worker had already committed 30668ed9b and b0e67c7e4. Cancelled it and continued as t3code-6-cont on the same branch.

  3. lukemaj commented on Sep 25, 2026

    @lukemaj
    ContributorAuthor

    Issue #6 done via PR #9 (branch chore/6-fork-maintenance, candidate 3e2af5351, base toolboxmd/t3code main, never merged).

    Kept the earlier worker's 30668ed9b and b0e67c7e4, verified them, and finished the issue:

    • docs/fork.md: fork model, routine, CI, absorption log, extension-point list (offering upstream marked as separate human decision).
    • scripts/fork-rebase.sh / fork-check.sh / fork-upstream-edits.txt (empty: no upstream files touched) / .github/workflows/fork.yml.
    • Added scripts/fork-maintenance.test.ts: 6 tests driving both scripts against throwaway git fixtures.

    Upstream absorption (real, on this branch): range b2b43be..e3e7cc3, 54 commits, verified ancestor with exact count; fetch plus rebase under 2 minutes; conflicts: none. Fresh fetch today confirms upstream tip is still e3e7cc3 (pending 0, cross-checked with git ls-remote).

    Proof on 3e2af5351: install pass; typecheck 0 errors; lint exit 0 (pre-existing warnings only); test: one pre-existing upstream failure (build-desktop-artifact cross-arch Windows probe) reproduced on pristine upstream base in a clean worktree, unrelated to this diff; new tests 6/6 pass; fmt --check pass.

  4. lukemaj commented on Sep 25, 2026

    @lukemaj
    ContributorAuthor

    Re-verification of candidate 3e2af5351 (PR #9, still the single open PR for this branch, head matches): fresh upstream fetch shows tip still e3e7cc3 (pending 0), so the recorded absorption b2b43be..e3e7cc3 with conflicts: none stands. Fresh proof: install exit 0; typecheck exit 0; lint exit 0; fmt --check exit 0; test exit 1 from exactly one failure, the pre-existing upstream build-desktop-artifact Windows cross-arch probe already reproduced on pristine upstream base e3e7cc3 and unrelated to this diff; new fork-maintenance tests 6/6 pass. No code changes were needed; tree clean.

  5. lukemaj commented on Sep 25, 2026

    @lukemaj
    ContributorAuthor

    Elon method review 2026-09-25 (toolboxmd/model-router#106): the user runs the upstream "T3 Code (Alpha).app", so no fork feature reaches them until a fork build is their daily T3. Priority inside this Issue: first a documented way to build and run the fork's desktop app (or server plus web client) as the daily T3, alongside or instead of the upstream app, preserving the user's data; the rebase routine and CI second. Installing it is the user's step.

  6. lukemaj commented on Sep 25, 2026

    @lukemaj
    ContributorAuthor

    Issue #6 implementation complete. Final candidate: 7894006fe on chore/6-fork-maintenance.

    What changed this turn:

    • Diagnosed the turn-2 proof failure as environmental: the live T3 Code desktop instance leaves ELECTRON_RUN_AS_NODE=1 in the environment, which breaks upstream scripts/build-desktop-artifact.test.ts assertions that inspect spawned command envs.
    • Fixed the routine, not the upstream test: scripts/fork-rebase.sh now runs the proof block in a subshell with ELECTRON_RUN_AS_NODE cleared.
    • Updated docs/fork.md to document the cleanup.

    Commit stack on chore/6-fork-maintenance:

    • ce536b283 docs: Project Direction for the toolboxmd workspace fork (docs: Project Direction for the toolboxmd workspace fork #5)
    • 30668ed9b docs(fork): rebase routine, stack check and fork CI
    • b0e67c7e4 fix(fork): fork-rebase listing must survive head closing the pipe
    • b97f1be10 test(fork): focused tests for the rebase routine safety rules
    • 3e2af5351 docs(fork): list maintenance tests and fix formatter whitespace
    • 7894006fe fix(fork): run proof in a subshell cleared of ELECTRON_RUN_AS_NODE

    Upstream absorption (already recorded in docs/fork.md and the PR):

    • Range: b2b43bef7..e3e7cc3fc (54 commits)
    • Conflicts: none
    • Base: b2b43bef7 (fix(server): preserve racy edits in review diff previews (#12613))
    • Absorbed tip: e3e7cc3fc (fix(usage): price Claude fast-mode requests at the fast rate (#13599))
    • Method: git fetch upstream main && git rebase upstream/main via scripts/fork-rebase.sh
    • Wall time: under 2 minutes

    PR: #9 (base: main, head: chore/6-fork-maintenance), never merged.

    Proof on final candidate 7894006fe:

    • pnpm install --frozen-lockfile: pass
    • pnpm exec vp run -r typecheck: pass, 0 errors
    • pnpm exec vp lint: pass (warnings only, pre-existing)
    • pnpm exec vp run -r test: pass — 5360 tests passed, 10 skipped. Required environmental cleanup on this Mac: ELECTRON_RUN_AS_NODE unset, TMPDIR=/private/tmp, PATH stripped of /opt/homebrew/bin, and vp run -r --concurrency-limit 1 test to avoid a flaky upstream openVsxThemes timeout under cross-workload contention.
    • pnpm exec vp fmt --check: pass

    Candidate upstream extension points are listed in docs/fork.md (parentThreadId, thread visibility, right-panel tab registry, thread persona). Offering them upstream remains a separate human decision; nothing was sent upstream.

  7. lukemaj commented on Sep 25, 2026

    @lukemaj
    ContributorAuthor

    Found while merging #11: upstream CI jobs run on paid Blacksmith runners (runs-on: blacksmith-* in .github/workflows/ci.yml and mobile-fingerprint-check.yml). The fork has none, so every fork PR's CI stays queued forever. The fork CI part of this Issue must map these to GitHub-hosted runners (e.g. ubuntu-24.04, macos-15) through a small fork-only patch, or run the fork's checks in a separate workflow.

  8. lukemaj commented on Sep 25, 2026

    @lukemaj
    ContributorAuthor

    Cost check 2026-09-25: every toolboxmd repo is public (verified), so standard GitHub-hosted runners are free and unlimited (org billing usage shows net $0 for Actions minutes). Decision for the fork CI: map blacksmith-*-ubuntu-2404 to ubuntu-24.04 and blacksmith-*-macos-* to macos-15 in a small fork-only patch. No Blacksmith account or self-hosted runner needed; a self-hosted runner on a public repo would run untrusted fork PR code.

  9. lukemaj commented on Sep 25, 2026

    @lukemaj
    ContributorAuthor

    Measure before settling (user, 2026-09-25): once CI runs on GitHub-hosted runners, record wall-clock time per job and per PR run for one commit, next to the same commit's upstream Blacksmith timings (gh api repos/pingdotgg/t3code/actions/runs/<id>/jobs). Report the speedup and whether Blacksmith's 3,000 free min/month would cover our volume (~11 job-minutes per CI run upstream). Switching to Blacksmith needs its GitHub app installed on the org, which is the user's call.

  10. lukemaj commented on Sep 25, 2026

    @lukemaj
    ContributorAuthor

    Fork CI timing on GitHub-hosted runners (PR #9, commit 2c5f346f0, CI run https://github.com/toolboxmd/t3code/actions/runs/36133328921) against upstream Blacksmith for the same jobs (upstream CI push run https://github.com/pingdotgg/t3code/actions/runs/35982894445 on b2b43bef7, the fork's upstream base).

    Job GitHub-hosted Blacksmith Ratio
    Test 268s (ubuntu-24.04) 134s (8vcpu) 2.0x
    Test Server 1 222s 105s 2.1x
    Test Server 2 229s 96s 2.4x
    Test Server 3 216s 101s 2.1x
    Rust 69s 45s (4vcpu) 1.5x
    Release Smoke 62s 36s 1.7x
    Mobile Native Changes 4s 3s (2vcpu) -
    Check, through "Check unused code" 94s 40s 2.4x
    Check, full not measured (stopped at knip, see below) 118s -
    Mobile Native Static Analysis 77s (macos-15) skipped upstream -
    • Wall time per PR run: 268s here vs about 140s upstream, so about 2x slower. The critical path is Test on both; a full Check at 2.4x would take about 280s and become the critical path, so expect about 4.5 to 5 minutes per run.
    • Job time per run: about 21 job-minutes here (includes the 77s macOS job upstream skipped and a partial Check) vs 10.6 upstream. On GitHub-hosted runners this costs $0 (public repo).
    • Blacksmith's 3,000 free minutes/month at about 11 job-minutes per run cover about 270 CI runs/month. The fork ran 18 CI workflow runs today (a busy day of merges and pushes); at that rate (about 540/month) Blacksmith's free tier would run out mid-month. Measured from one day only, so treat it as an estimate. Recommendation: stay on free GitHub-hosted runners; switching costs about 2.5 minutes per run. Installing the Blacksmith GitHub app is your call.

    Current CI state on PR #9: Fork Stack Model, Test, Test Server 1-3, Rust, Release Smoke and both Mobile jobs pass. Check fails in knip: ThreadsToolkitRegistrationLive in apps/server/src/mcp/McpHttpServer.ts:613 is an unused export. #10 added it; PR #9 does not touch that file. The fix is to remove the export keyword (belongs with the #10 follow-up). An earlier run also failed the web test shikiReviewHighlighter.test.ts > initializes source and snippet highlighting without a warmup once; it passed on the rerun (flaky).

  11. 2 remaining items

  12. lukemaj commented on Sep 25, 2026

    @lukemaj
    ContributorAuthor

    Issue #6 delivery update.

    PR #9 is merged by squash as merge commit e15afa0.

    Landed:

    • Removed the unused ThreadsToolkitRegistrationLive export from apps/server/src/mcp/McpHttpServer.ts.
    • Fixed the fork branding dependency in apps/web/src/bundledDev.test.ts by supplying the minimal branding fixture required by the fork's bootError.ts.
    • Added that upstream-file edit to scripts/fork-upstream-edits.txt and documented it in docs/fork.md.
    • The replacement GitHub-hosted CI run 36156360212 passed Check, Test, Fork Stack Model, all server shards, Rust, Release Smoke, and mobile checks.
    • Local proof: bundledDev.test.ts 2/2, scripts/fork-check.sh, and knip:check passed.

    Remaining: upstream absorption of the fork's commit stack into toolboxmd/t3code main, using the documented rebase routine and the user-approved force-with-lease step. No upstream absorption was performed here.

  13. lukemaj commented on Sep 27, 2026

    @lukemaj
    ContributorAuthor

    Issue #6 handoff: upstream absorption done on a branch. Landing on main is waiting on human approval.

    • Branch chore/6-absorb-upstream, head 72ba8f658d155a1edd87be68489718ed80dd9c39. PR for CI and review: chore(fork): absorb upstream through de251fc29 (#6) #45. It lands by force-with-lease, not by merge:
      git push --force-with-lease=main:096e9c0064d83be350b2280308ccbf1598b03661 origin chore/6-absorb-upstream:main
    • Range b2b43bef7..de251fc29: 128 upstream commits. Stack: 17 fork commits replayed, plus one commit that records the absorption in docs/fork.md (the Absorption log format there). The stack is now 18 of the 20 allowed.

    Conflicts, per upstream file

    Adaptations with no conflict (each folded into its owning commit)

    Decisions
    All 278 report rows (98 upstream commits) are decided in the PR comments.

    • Adopt upstream and delete ours: none. No upstream commit provides a fork capability, so the patch set did not shrink this time.
    • #11846 (per-thread auto-settle switch) is a manual opt-out. It does not replace the automatic child-activity guard (Sidebar: show a parent thread as working while its child threads work #31), so ours stays. Its threadAutoSettleOptOut capability merged beside our issues and issueLinks capabilities.
    • #13572 (agents banner) covers provider-native background agents only, so it does not replace our sidebar child-working state.
    • #13516 (sidebar Back) already covers /pull-requests, which also hosts our Issues view. No fork edit is needed.
    • #13060 (shell commands from chat) merged beside our Issue/PR link handling in ChatMarkdown.tsx.
    • Everything else is keyword-only or an unrelated auto-merge: keep ours.

    Time
    Fetch, rebase and the three conflicts took about 2 minutes. Worktree creation to push took about 34 minutes, including the adaptations, the report review and five proof runs.

    Proof
    scripts/fork-rebase.sh --proof on 72ba8f658 passed in 590s:

    • fork check OK
    • install pass
    • typecheck: 0 errors
    • lint: 0 errors, pre-existing warnings only
    • tests: 14 packages, 18,240 passed, 70 skipped, 0 failed
    • fmt --check: pass

    Nothing failed on the final run, so there was no failure to compare against plain upstream.

    One earlier run failed because this fresh worktree's install had no Electron binary: pnpm did not fetch it, and two desktop suites then raced to download it. Running electron/install.js in the worktree fixed it. This is environmental and has not been checked against a plain upstream checkout.

    Unverified

    • Fork CI on PR chore(fork): absorb upstream through de251fc29 (#6) #45 is still running as of this comment.
    • No real-client (browser/desktop) check of the retokenized UI or of the settlement guard in a running server.
    • The pnpm binary is not on PATH on this Mac. The proof used a temporary npx pnpm@11.10.0 shim.
    • The Absorption log entry records candidate bb028be18, the stack below the log commit.

    Fork main has not been touched.

  14. lukemaj commented on Sep 27, 2026

    @lukemaj
    ContributorAuthor

    Elon method pass on the absorption (coordinator, 2026-09-27).

    • Requirement: upstream's 128 changes in fork main and Chromeria without breaking fork features; future absorptions cheap. Proof: CI green on the exact stack plus review of non-replay changes.
    • Kept: pre-landing CI through a base branch at the upstream candidate (without it main can go red after the force-push); review of the settlement conflict (it caught a real perf regression); the Sidebar: show a parent thread as working while its child threads work #31 guard (upstream's opt-out and agents banner don't cover child threads).
    • Cut: the absorption log in docs/fork.md: it duplicates the PR and this Issue, costs a stack commit, cannot hold its own SHA, and contradicts AGENTS.md (a merged PR is the implementation record). The record now lives on the absorption PR and here.
    • Follow-up, not now: require overlap decisions only for real file or code overlaps; keyword-only rows were most of the 278 and carried no decisions of consequence.
    • Constraint: round trips (review, CI, approval), so fixes go in one push with one re-review and one approval.
  15. lukemaj commented on Sep 27, 2026

    @lukemaj
    ContributorAuthor

    Issue #6 update after the review of PR #45 (#45 (comment)). The PR description is now the full absorption record, as docs/fork.md says; this comment is the Issue copy.

    • New head d7ee6ae1d5fe61f6241dd80f546ee184d7a2179a: 17 fork commits on upstream de251fc29. The in-repo absorption log commit is dropped.
    • PR chore(fork): absorb upstream through de251fc29 (#6) #45 base is now absorb-base/de251fc29 (a branch at upstream de251fc29), so CI runs. The Routine in docs/fork.md says so, and the record now goes on the PR and this Issue. Landing is still --force-with-lease onto main after approval, then delete absorb-base/de251fc29.
    • Settlement guard: the all-threads read, settled children included, happens only when a thread is about to settle, once per sweep. Turn-end sweeps keep upstream #13691's gain. The new test covers a settled child with background work on both sweep paths.
    • CI on d7ee6ae1d: every job passes except Test, and it fails only on upstream's packages/client-runtime/src/platform/persistence.test.ts > encodeShellSnapshotForCache. That test timed out at 5000ms after 7.3s on the GitHub-hosted runner. Upstream's own CI ran it at the same commit de251fc29 in 2.3s on Blacksmith, and it takes 0.6s locally. The fork does not touch its schemas; it is a runner-speed problem with a test new in this range (#13767). The fix is a fork-side decision, not yet made.
  16. lukemaj commented on Sep 27, 2026

    @lukemaj
    ContributorAuthor

    Completed. One real upstream update absorbed through the routine: b2b43be..de251fc (128 upstream commits), fork stack 17 commits, landed on main by force-with-lease (096e9c006 -> 8518d0d) with user approval. Record, conflicts, decisions, time and proof: PR #45. CI on main at 8518d0d: CI success, Fork success. Routine now includes the absorb-base/ step so CI runs on absorption PRs.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions