Repository navigation
chore(sync): absorb upstream main through 611132c17 - #169
NoahHendrickson wants to merge 192 commits into
Conversation
Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com>
…dotgg#15958) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ingdotgg#15951) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…of encoding a fallback (pingdotgg#16118) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ngdotgg#16167) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ingdotgg#16170) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…pingdotgg#16002) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ingdotgg#15592) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tgg#16200) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…eady passed (pingdotgg#15804) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…r cached (pingdotgg#15500) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ng to the inbox (pingdotgg#16204) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…#10298) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…rver (pingdotgg#16718) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…g#16741) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…16752) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ngdotgg#16290) Co-authored-by: spoukyii <61633921+spoukyii@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ices (pingdotgg#16631) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tgg#16762) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s of untracked files (pingdotgg#16771) Co-authored-by: Braulio Oliveira <brauliobo@gmail.com> Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
…eep (pingdotgg#16760) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ingdotgg#16761) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ingdotgg#16782) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Merges pingdotgg/t3code main (188 commits, 1604ccc..611132c) into the orchestrator-V2 sync branch. 19 conflicted files resolved, three override shadows ported by hand, every fork fence accounted for in a census against the pre-merge baseline. Notable decisions, all fenced and recorded in .fork/customizations.yaml: - Auth scopes (pingdotgg#9786-pingdotgg#9791): the operate / write gates upstream added land on the fork's own controls too (pinned-row drag, pin and settle hover actions, rename, the branch-mismatch Restore, the pending-input card and the composer's primary actions), so a read-only connection sees the same behavior in the fork's chrome as in upstream's. - Thread notices (pingdotgg#16782, pingdotgg#16631): upstream moved the settled / snoozed / woke notices into the timeline-footer status line and replaced the resume-compaction card with compact-on-send. The fork keeps its "Unsettle" wording on the status line and drops the now-vacuous settled-only banner filter; the branch-changed card is the one Figma notice card left. - Fast mode (pingdotgg#16069): rides in the traits label text; the fork's model picker drops its bolt. - Server: the follower keeps its production-only wiring under upstream's namespace-import and layerXyz naming (pingdotgg#16267, pingdotgg#16282); the base-remote identity pick composes with upstream's new origin identity (pingdotgg#16353). - Repository remote origin test, CI runner for the new transfer-report job, and the Phosphor shim gain the icons upstream newly imports. Deliberately not adopted, consistent with the manifest: single-list thread drag and context-drag-to-composer, the connected-environment thread search, and the change-request snapshot wiring (knip ignores name them). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…le pair Upstream's DesktopPreReadyFileSystem test migrates "T3 Code (Alpha)" into "t3code-v2"; the fork's packaged pair is "T3 Code (Fork)" -> "t3code-fork-v2" (fork-app-identity), so the test failed on every CI run of this branch. The directory names are fenced to the fork's and the file joins the entry's watch list. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> (cherry picked from commit 78b5c2e)
There was a problem hiding this comment.
Do not approve. The rest of this sync port is the right shape — settled/snoozed/woke left the banner stack so composerBannerVisibility correctly disappeared, the fast-mode bolt left with the label text, follower wiring tracked layerXyz, and nothing here newly crosses 1k that wasn’t already last-resort.
The operate-scope port for Questions is not.
apps/web/src/overrides/components/chat/ComposerPendingUserInputPanel.tsx ~L91–98 — wrong boundary. Upstream’s card already has three named inputs and one derived flag: responseDisabled = disabled || isResponding || !canRespond. Folding scope-denied into isResponding makes the hook lie, and it is why a call site can forget the prop. Give useComposerPendingUserInputCard a first-class disabled. Keep isResponding as responding. Derive responseDisabled once. The timer-clear and number-key guards then follow the real invariant.
apps/web/src/components/chat/ChatComposer.tsx L7213 vs L7232 — #9786 was bolted onto one mount (!isComposerCollapsedMobile). The compact mount never gets disabled={!canOperateThread}. That path still runs option clicks, number keys, and the 200ms single-select auto-advance, which calls onAdvance directly. Gating Next/Submit in ComposerPrimaryActions does not close the hole.
Judo: first-class disabled on the hook; pass disabled={!canOperateThread} at both ChatComposer sites; guard both literals so the next sync cannot drop the compact one. Do not leave a second, ungated Questions chrome for the viewport this fork designs for.
(Inline comments omitted — GitHub refused the 13k-file diff.)
Sent by Cursor Automation: Thermo nuke 4.6
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: unavailable · PR result: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
NoahHendrickson
left a comment
There was a problem hiding this comment.
Reviewed at bb1ffab. Changes needed.
[P2] Pass the operate-scope gate to the compact Questions panel too. ChatComposer.tsx:7231
The expanded mount passes disabled={!canOperateThread}, but the isComposerCollapsedMobile mount does not. The shadow defaults disabled to false, so on a read-only connection the compact card still enables option clicks and number-key shortcuts, changes the local answers, and schedules its 200ms auto-advance through onAdvanceActivePendingUserInput. The final onRespondToUserInput scope check does prevent submission; the visible result is an apparently answerable flow that advances and then silently cannot submit. Gate both mounts and add coverage for compact read-only interaction and scope withdrawal during auto-advance. This independently confirms the earlier bot finding; it is still present on the latest head.
Scope: fork-specific merge resolutions and auth-scope/preview/notice/override integration, rather than an exhaustive audit of every imported upstream commit. Focused validation on this head: 13 Questions/primary-action tests, 133 branch-follow/launch/finalization/runtime-layer tests, and 9 desktop identity/profile tests pass. Current CI is green, but those tests do not cover the missing compact prop. No browser verification.
NoahHendrickson
left a comment
There was a problem hiding this comment.
Review: #169 absorb through 611132c
Verdict: one upstream hunk was dropped in conflict resolution and two fork-only controls missed the new operate-scope gate. Fix those three and this is good: the server/desktop/CI side is clean, the thread-notice and fast-mode ports are right, the shadows carry upstream's deltas, and the fence census matches the PR's own accounting (fork-composer-banner-surface 17→12, ci-runners 13→14, nothing else moved). GitHub refused inline comments on the 13k-file diff, so anchors are permalinks at this head.
Fix before merge
-
Collapsed-mobile Questions card is not scope-gated (Cursor's second point is correct). ChatComposer.tsx L7232-L7244: two
<ComposerPendingUserInputPanel>mounts; the first (L7213) hasdisabled={!canOperateThread}, theisComposerCollapsedMobileone has none. Upstream at 611132c gates both (L6703 and L6724), so this is a dropped upstream line, not a fork decision. On a read-only phone client the options stay clickable, number keys work, the hook runs its 200ms single-select auto-advance through every question, and the final submit is swallowed byonRespondToUserInput's scope guard: the UI walks the user through answering and then silently does nothing. -
Fork-only "Settle all threads" ignores the operate scope. Sidebar.tsx L4213-L4233 builds
settleAllKeysByProjectKeyon draft / settledOverride /threadSettlementcapability only, and SidebarV2ProjectGroupHeader.tsx L260-L268 disables the item only onsettleAllCount === 0. Upstream's bulk settle in the same file usescanOperateThreads(settlingThreads)(L375, L3497). A read-only connection fires onesettleThreadper thread and gets a toast per rejection. AddingreadEnvironmentScope(thread.environmentId, AuthOrchestrationOperateScope)to the key filter zeroes the count and disables the item. -
The liveness pill's stop square stays enabled when the scope is denied. ComposerMonitoringPill.tsx L65-L73 is
disabled={props.stopping}and ChatView.tsx L7499-L7505 never passescanOperateThread. Upstream's equivalent Stop button isdisabled={!canOperateThread || isStoppingBackgroundWork}(one of the five upstream-added ChatView lines absent from this head).handleStopBackgroundWorkhas thereadEnvironmentScopeguard so no request fires, but the control looks live and does nothing. Lower severity than 1 and 2, same class.
Cursor bot
- Point (ii), the ungated compact mount: correct, see 1.
- Point (i), folding
disabledinto the hook'sisResponding(override L91-L98): functionally equivalent to upstream'sresponseDisabled(click guard, number-key guard, auto-advance timer cleared when the flag flips; the dismiss button is ungated on both sides). A style nit. A first-classdisabledon the hook would make the mount prop harder to forget, which is exactly what happened in 1, so I'd take the suggestion while fixing it.
Nits
- ChatView.tsx L7803:
const backgroundWorkItems = [goalBannerItem].filter(…)is a fork edit (upstream has[goalBannerItem, backgroundWorkBannerItem]) sitting one line above thefork-composer-shellfence that explains it. Pull it inside. __fork_guards__/forkModelPicker.test.ts:232still says "collapses it (and the bolt)" two lines above the comment saying the bolt is gone.forkLocalCheckoutBranchFollow.ts:14sayst3code/…placeholder; the manifest sayst3/….isTemporaryWorktreeBranchis the source of truth either way.- Pre-existing, not from this PR: the pin hover action at Sidebar.tsx L1871 lacks upstream's
!sortable?.isDragging;RepositoryIdentityResolvernames agh-marked third remote while upstream's newbuildRepositoryOriginstill groups under literalorigin(unreachable in the fork's own checkout).
Verified locally (detached checkout of bb1ffab, fresh vp i)
- Fork guards 492/492; web tests for the conflicted chat/usage/preview/custom files 331/331; server tests for
ThreadLaunchService,RunFinalizationService,forkLocalCheckoutBranchFollow,RunExecutionService,RepositoryIdentityResolver124/124; desktop identity/env/Clerk/assets tests 38/38;vp run knip:checkand.fork/lint-owned.mjsclean. - Follower still provided only through
layerRunFinalizationServiceWithFollowerProvided→ effect executor; replay harness builds bareRunFinalizationService.layer, so the no-op default holds. Identity resolver: fork base-remote rule first, falls back topickPrimaryRemote; composes with pingdotgg#16353's origin identity (fork checkout: base=origin →originomitted → same grouping key upstream computes). - Every
ci.ymljob on a hosted runner inside aci-runnersfence,checkneedstransfer-report;release.ymlBlacksmith jobs gated ongithub.repository == 'pingdotgg/t3code'.patchedDependenciesexact-pinned and 1:1 with the lockfile (Release Smoke). - Upstream-added lines missing from the conflict-resolved files are all deliberate fork variants except the Stop gate in 3 and the mount in 1.
composerBannerVisibility.tshas no remaining importers. Both override shadows upstream touched in this range carry the delta. - The cherry-picked Windows-profile test fix is byte-identical to #167's, so merging both is a no-op.
git merge-treewith #168's branch is conflict-free.
Merge mechanics
Retarget to custom with gh pr edit 169 --base custom before #167 merges (merging #167 with --delete-branch first closes this PR and a reopen triggers a fresh full CI run).
Reviewed by Claude Fable 5.1 via Claude Code (T3 Code), with subagents per cluster; every finding above was re-verified against the source.
Review findings on the absorb: upstream pingdotgg#9786 gates both Questions mounts and the collapsed-mobile one lost its gate in conflict resolution, so a read-only phone client could click through answers it could never submit. The fork's "Settle all threads" built its key list without the scope and would have fired one rejected settle per thread, and the liveness pill's stop square stayed enabled while its handler silently declined. The compact mount passes disabled={!canOperateThread} again and a guard pins both mounts. useComposerPendingUserInputCard takes `disabled` as its own input and derives responseDisabled from it, isResponding and canRespond, so the click, number-key and auto-advance guards follow one flag; two hook tests cover a read-only card and a scope withdrawn mid-timer. Settle-all filters its keys through readEnvironmentScope, and the pill takes canStop from ChatView. Nits from the same review: the backgroundWorkItems line moves inside the fence that explains it, the model picker guard stops mentioning the bolt, and the follower comment names the shorter t3/ placeholder prefix. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
NoahHendrickson
left a comment
There was a problem hiding this comment.
Addressed at 720c5f2 (inline anchors still refused on the 13k-file diff, so notes by path).
Fixed
ChatComposer.tsxcollapsed-mobile Questions mount:disabled={!canOperateThread}restored, matching upstream's second mount.__fork_guards__/forkPendingUserInput.test.tsnow asserts both mounts carry the gate so the next sync cannot drop one.Sidebar.tsxsettle-all: the key builder filters throughreadEnvironmentScope(…, AuthOrchestrationOperateScope), so a read-only connection sees a zero count and a disabled item instead of one rejection toast per thread.- Liveness pill stop square:
ComposerMonitoringPill/resolveComposerLivenessPillPropstakecanStop; ChatView passescanOperateThread, so the square is inert when the handler would decline. - Cursor point (i), taken as suggested:
useComposerPendingUserInputCardhas a first-classdisabledinput and derivesresponseDisabled = disabled || isResponding || !canRespond; the shadow passesdisabledandisRespondingseparately. Two hook tests cover a read-only card ignoring selection and a scope withdrawn mid-timer cancelling the pending auto-advance.
Nits: backgroundWorkItems now sits inside the fork-composer-shell fence; the model-picker guard comment no longer mentions the bolt; the follower comment names the t3/ prefix.
Left as is (pre-existing, not from this PR, as noted): the pin hover action's !sortable?.isDragging and the gh-marked third-remote vs buildRepositoryOrigin case. Happy to take either in a follow-up.
Verified: web typecheck clean, fork guards 495/495, pending-input / sidebar / chat view / composer web tests 394/394, lint-owned and knip clean.


Problem
customstill lacks the orchestrator-V2 sync (#167), and upstream has moved another 188 commits past it (1604ccc9d..611132c17): the auth-scope series (pingdotgg#9786–pingdotgg#9791), GitHub API source control, webhooks, the browser on the environment server, and the thread-notice rework. This PR is stacked on #167's branch; retarget it tocustombefore #167 merges.What this does
Merges
upstream/mainthrough611132c17. 19 conflicted files resolved, three override shadows ported by hand, every fork fence accounted for in a census against the pre-merge baseline (only the deltas named below).Decisions, all fenced and recorded in
.fork/customizations.yaml:disabledprop; the fork hook clears its auto-advance timer when the scope is withdrawn) and the composer's primary actions. A read-only connection sees the same behavior in the fork's chrome as in upstream's.custom/composerBannerVisibility.ts); the branch-changed card is the one Figma notice card left. ChatView 51→48 and ChatComposer 63→61 fences.layerXyznaming (refactor(server): import service modules as namespaces, not aliased layers pingdotgg/t3code#16267, refactor: layer variables are named layer or layerXyz pingdotgg/t3code#16282); the base-remote identity pick composes with upstream's new origin identity (fix(server): forks no longer merge into their upstream repo's project group pingdotgg/t3code#16353).ci.yml). The Phosphor shim gains the four icons upstream newly imports; lint-owned baselines move with upstream's ChatView (memo 24, refs 37, preserve 20).Deliberately not adopted, consistent with the manifest: single-list thread drag and context-drag-to-composer, the connected-environment thread search, and the change-request snapshot wiring (knip ignores name them).
Also carries the cherry-pick of #167's Windows-profile test fix so this branch is green on its own.
Verification
vp lint apps/web/src: clean, 0 errors.Resolved by Claude Fable 5.1 in Claude Code, with three subagents for the sidebar, composer/chat view, and override shadows.
🤖 Generated with Claude Code