Skip to content
This repository was archived by the owner on Aug 6, 2026. It is now read-only.

Commit 65ea453

Browse files
committed
Merge branch 'main' into posthog-code/skip-clean-jsonl-sanitize
Picks up the vr-cli install fix from #4029 so the visual-regression check passes. Generated-By: PostHog Code Task-Id: 58678630-1e4b-4565-9de0-c74c91b9d995
2 parents 8cc4a26 + a4c32df commit 65ea453

329 files changed

Lines changed: 20953 additions & 2386 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.claude/skills/merging-prs/SKILL.md‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ To merge, you enqueue the PR with a comment, then watch it until Trunk lands it.
1212

1313
When a developer says "merge this PR", "merge it when it's ready", "land it",
1414
"ship it", or "babysit this PR", do the full loop below — enqueue **and** watch
15-
to completion, reporting the outcome. See also [docs/merge-queue.md](../../../docs/merge-queue.md).
15+
to completion, reporting the outcome.
1616

1717
`<n>` below is the PR number. Resolve the repo slug once if you need it:
1818
`REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)`.
@@ -29,8 +29,21 @@ gh pr view <n> --json state,isDraft,mergeable,reviewDecision,statusCheckRollup
2929
- **Failing required checks** (`statusCheckRollup`) → the queue will just reject
3030
it. Report which checks are red and stop; fix them first. **Pending** checks
3131
are fine — the queue waits for them.
32+
- **Not yet approved** (`reviewDecision` empty or `REVIEW_REQUIRED`) → fine,
33+
enqueue anyway. See below.
3234
- **Merge conflicts** (`mergeable == "CONFLICTING"`) → report and stop; rebase first.
3335

36+
Enqueueing before approval is safe, and is the closest thing this repo has to
37+
auto-merge. A submitted PR sits in Trunk's `Queued` state until GitHub's branch
38+
protection on `main` is satisfied — one approving review, code-owner review, and
39+
the required checks (`build`, `quality`, `unit-test`, `integration-test`,
40+
`typecheck`) — and Trunk merges it once they land. Trunk is not a bypass actor on
41+
those rules, so it cannot merge an unapproved or red PR.
42+
43+
The catch: **pushing new commits drops the PR from the queue.** If review
44+
feedback is likely, either wait for approval before enqueueing, or re-enqueue
45+
with `/trunk merge` after each push.
46+
3447
## 2. Enqueue
3548

3649
```bash
@@ -68,7 +81,10 @@ sleep 60
6881
- Watch the **check run + PR state**, not `gh pr checks --watch`: the queue runs
6982
CI on Trunk's own draft/`trunk-merge/**` branch, so this PR's own checks don't
7083
reflect the queue's testing.
71-
- Stop at the timeout with a status summary rather than looping forever.
84+
- If it's parked in `Queued` waiting on a human review, say so once and slow the
85+
cadence to ~5 minutes. Keep watching — the merge still has to be reported.
86+
- Stop at the timeout with a status summary rather than looping forever. If it
87+
was still waiting on review, say that's why and offer to keep watching.
7288

7389
## 4. Handle failure
7490

‎.github/workflows/code-storybook.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ jobs:
169169

170170
- name: Install Visual Review CLI
171171
if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'push'
172-
run: cd vr-cli/products/visual_review/cli && npm ci && npm run build && npm link
172+
run: cd vr-cli/products/visual_review/cli && (npm ci || npm install) && npm run build && npm link
173173

174174
- name: Submit snapshots to Visual Review
175175
# Fork PRs can't read the token; their captures still ran above, so a

‎README.md‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
> [!IMPORTANT]
2-
> Interested in the PostHog desktop app? [Join the waitlist](https://posthog.com/code) or hop into our [Discord](https://discord.gg/aSrHKVNVdR).
3-
4-
**[Download the latest version](https://github.com/PostHog/code/releases/latest)**
5-
6-
Found a bug or have feedback? [Open an issue](https://github.com/PostHog/code/issues/new) on GitHub.
2+
> This repository has migrated to the [PostHog monorepo](https://github.com/PostHog/posthog/tree/master/products/desktop). Development, issues and pull requests now live there.
73
84
# PostHog
95

‎apps/code/snapshots.yml‎

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -537,21 +537,17 @@ snapshots:
537537
git-dialogs--sync-success--light:
538538
hash: v1.k4693efd2.8d79d77c9338aeaa73734836f0e17fde987f6d3239914f4013889d3110e5088d.Rq-w2o1uhes_a5hUWqMXeiDkfnoPCZPt932LkEQXCco
539539
loops-loopslistview--comprehensive--dark:
540-
hash: v1.k4693efd2.c128012b7f910839e65e8eaf14d5456c93f90d77747d0625ca35fddd8d5adf7a.fuugB5Ov6boP7fg6fWP7A7IG2yYnPUAAWLKZLuV8rZ0
540+
hash: v1.k4693efd2.25744a9471ec664c70e346ac5cb330c025a031626bc486abe8820b7b6dbc1a19.Shh8Yl7SdombnNc4-uJjlIbx-n4C0MGXxtOGB1bjJTY
541541
loops-loopslistview--comprehensive--light:
542-
hash: v1.k4693efd2.4d25a48e0bd7e60d3bbb433e246486e4c9ac95979db86e20eb8bf5cb119d1eb2.EzrENjVHwVMyV00pEA-71TeVomJtchiym5DqWFkujlA
542+
hash: v1.k4693efd2.ef8e012cc506a0bf5e761ec8e89943820d4b391f7023f506da7d79586b49a356.ATiN8Y0hUmfGvr0rUytYWX-fITyHRTgeN1i_HOOGZuc
543543
loops-loopslistview--long-mixed-list--dark:
544-
hash: v1.k4693efd2.fdbf0c24cb386c4345279db3e648efe72aa8a2a984d491361522f62074a771c9.2QmRxRMWYFFfBFrbMm0Dm9rWcvd1lfRbc0egfzoESnY
544+
hash: v1.k4693efd2.c9915e22655fe1f6b77eabaf11d8876648c387ceebac6cd8be1880e7255bd7a5.y-gyTKSp7wYbuS57TABRbEyMSL9_U1wvHYvbyCeAbiQ
545545
loops-loopslistview--long-mixed-list--light:
546-
hash: v1.k4693efd2.aa17d9b6f40fbd3914bd742951db9f90add0bd233c54170803c8483aeb45b43b.yXpqqGczOq1uW5k4Ie7ddNTnne-cFTglZ9cL800pXB4
547-
loops-loopslistview--shared-page-header--dark:
548-
hash: v1.k4693efd2.14ab860dcb0df51b4019f012288e45f3a2c4c23fa08e809efef8c04b5687fe36.qoMLHprZmV2wON156NBbl3sqP84a4nXgdYm1H6WpTVM
549-
loops-loopslistview--shared-page-header--light:
550-
hash: v1.k4693efd2.23be5408ff3b4a912a0ce0457af8638124b99a01c88a499d0f4204cee2c62487.dGBP1K08MA2Fvhml-BPl5eFra8U83JXmy04NK9wOQnM
546+
hash: v1.k4693efd2.5fec9e1a3c14f1bc319cd7e5abc24b3d66ed787986a103b5330f49341d4983ad.mpD-eTS6vkSbsJdOYaHXASHQd5IiJGWRCb6uDGlzhpk
551547
loops-loopslistview--with-builder-sessions--dark:
552-
hash: v1.k4693efd2.df4a1a4764e1de7b69905814b09c30d9b43f705f5e66c7ad83829c567d4faa1a.jthufoX_KPbbxScjj3pPBA4lEtT9Ym6zUCH-v1759GM
548+
hash: v1.k4693efd2.06b404e4016ba0eb86769331a574bc640be1ad26ebf3a04d0256334d1da041a3.fPfF8c2wNFREfy8dVRdsw7W9Fpqj7HEtuaERMroNHMA
553549
loops-loopslistview--with-builder-sessions--light:
554-
hash: v1.k4693efd2.eb65c38bb0de7efedbc0d7a6c27a6695528e2e6b60949617e7d22335b1e68c8b.fJr9uykvc8S7LI_ASXk5KRqxXCwIqh6ld9zfzs4shP0
550+
hash: v1.k4693efd2.30f89915a12cadf313216403fb0f3e221f3c33cee763f0692ae2b96b4332e2b9.j00vexnH4QS0wJAHn7pQNpeITYYRtOxlvB2ngyzqU0c
555551
primitives-pageheader--title-only--dark:
556552
hash: v1.k4693efd2.f7f8c560b1e5cf20050189e10fc0f129e555ba672300a7a09bef5827c171a743.yP9Pp_k51agu_9Ri55Y7uCAPBQ1UTeUQJA9U9dPMKfQ
557553
primitives-pageheader--title-only--light:
@@ -696,10 +692,6 @@ snapshots:
696692
hash: v1.k4693efd2.e747a3b5d0983a7a125335f1d95cc7735dafda73abdb3f63ccfadde0482c5ce9.tjc4lMKeaOJjLLxd9tivmgKLshzHZwuSAa_MbqwN_20
697693
skill-buttons-skillbuttonactionmessage--run-experiment--light:
698694
hash: v1.k4693efd2.c18264887c67224ea1196646ff27f31ef9d79add87b5e9dfead377fcaf0dc941.MwzR7Yyd4le31Qm7RB2yk-qLk5ujgLkN-cMAB2WQ9_k
699-
skill-buttons-skillbuttonsmenu--default--dark:
700-
hash: v1.k4693efd2.cfff4c6bbb0acef1c9941b21d2f69c24b234c2c206282acf6fcada0cb2bd2386.xILjVPp8ecQmGbPjGDdhbRyi9KFPpA_1nfYF3bfjwuc
701-
skill-buttons-skillbuttonsmenu--default--light:
702-
hash: v1.k4693efd2.eb9bd49b9700641f6f3c90653447c9767c52e997afec9843e8649b90752faad3.VdxEtBwtkU3ioy2evcNbrEKxPjQ1GDUpZAQzFe-Uho4
703695
spaces-taskfeedrow--agent-origin--dark:
704696
hash: v1.k4693efd2.82f8c70a399c9ea768201933e202fcc2fde74332c5153aeabf6835ace79beee6.yEZq_qnKxItv5u0Ydcqa1B4VCwv8lwXUvcaFScE2XO0
705697
spaces-taskfeedrow--agent-origin--light:

‎apps/code/src/main/window.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,14 @@ export function createWindow(): void {
208208
const platformWindowConfig =
209209
process.platform === "darwin"
210210
? {
211-
titleBarStyle: "hiddenInset" as const,
211+
// "hidden", not "hiddenInset": hiddenInset keeps macOS's own inset and
212+
// ignores trafficLightPosition's y, which parked the dots near the
213+
// bottom of the bar. "hidden" honours the position we ask for.
214+
titleBarStyle: "hidden" as const,
212215
// Centre the traffic lights vertically with the title bar's back/forward
213216
// buttons (40px bar, 24px buttons → centre at y=20; 12px dots → top at 14).
214217
// x mirrors y so the inset from the top and the left match.
215-
trafficLightPosition: { x: 14, y: 14 },
218+
trafficLightPosition: { x: 14, y: 12 },
216219
// Exposes the titlebar-area-* CSS env vars so the renderer can
217220
// clear the traffic lights exactly; their size varies by macOS
218221
// version (bigger on Tahoe), so it must not hardcode a width.

‎apps/mobile/package.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
"clean": "node ../../scripts/rimraf.mjs .turbo .expo"
2525
},
2626
"expo": {
27+
"autolinking": {
28+
"buildFromSource": [
29+
"react-native-worklets"
30+
]
31+
},
2732
"doctor": {
2833
"reactNativeDirectoryCheck": {
2934
"exclude": [

‎apps/mobile/src/app/inbox/[...id].tsx‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import {
4646
DismissReportSheet,
4747
} from "@/features/inbox/components/DismissReportSheet";
4848
import { ReportActivity } from "@/features/inbox/components/ReportActivity";
49+
import { ReportFeedbackFooter } from "@/features/inbox/components/ReportFeedbackFooter";
4950
import { SignalCard } from "@/features/inbox/components/SignalCard";
5051
import {
5152
type ReviewerActionExtra,
@@ -463,7 +464,7 @@ export default function ReportDetailScreen() {
463464

464465
{/* Title */}
465466
<Text className="mb-2 font-semibold text-[18px] text-gray-12">
466-
{report.title ?? "Untitled signal"}
467+
{report.title ?? "Untitled report"}
467468
</Text>
468469

469470
{/* Meta row */}
@@ -573,6 +574,9 @@ export default function ReportDetailScreen() {
573574

574575
{/* Activity log */}
575576
<ReportActivity reportId={report.id} artefacts={artefacts} />
577+
578+
{/* Usefulness feedback */}
579+
<ReportFeedbackFooter report={report} />
576580
</ScrollView>
577581

578582
<View
@@ -638,7 +642,7 @@ export default function ReportDetailScreen() {
638642
<DismissReportSheet
639643
visible={dismissOpen}
640644
reportId={report.id}
641-
reportTitle={report.title?.trim() ? report.title : "Untitled signal"}
645+
reportTitle={report.title?.trim() ? report.title : "Untitled report"}
642646
onClose={() => setDismissOpen(false)}
643647
onDismissed={handleDismissed}
644648
/>

‎apps/mobile/src/app/settings/index.tsx‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import { Text } from "@components/text";
2+
import {
3+
EFFORT_LEVEL_LABELS,
4+
EFFORT_LEVELS,
5+
} from "@posthog/shared/domain-types";
26
import { router } from "expo-router";
37
import { ArrowSquareOut, CaretRight, SpeakerHigh } from "phosphor-react-native";
48
import { useState } from "react";
@@ -103,11 +107,10 @@ const REASONING_EFFORT_OPTIONS: ReadonlyArray<{
103107
label: "Last used",
104108
description: "Remember the effort level you picked last time",
105109
},
106-
{ value: "low", label: "Low" },
107-
{ value: "medium", label: "Medium" },
108-
{ value: "high", label: "High" },
109-
{ value: "xhigh", label: "Extra High" },
110-
{ value: "max", label: "Max" },
110+
...EFFORT_LEVELS.map((value) => ({
111+
value,
112+
label: EFFORT_LEVEL_LABELS[value],
113+
})),
111114
];
112115

113116
function themeLabel(theme: ThemePreference): string {
@@ -415,7 +418,7 @@ export default function SettingsScreen() {
415418
/>
416419
<SettingsRow
417420
label="Messaging mode"
418-
description="What happens when you send while a turn is running"
421+
description="Mode new sessions start in. Steer applies messages mid-turn. Queue holds them until the turn ends."
419422
onPress={() => setMessagingModeSheetOpen(true)}
420423
rightSlot={
421424
<>

‎apps/mobile/src/app/task/[id].tsx‎

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
isModalModelId,
1717
isSupportedReasoningEffort,
1818
KIMI_MODEL_FLAG,
19+
readPrUrls,
1920
type SupportedReasoningEffort,
2021
serializeCloudPrompt,
2122
type Task,
@@ -44,6 +45,10 @@ import { StopRunButton } from "@/features/tasks/components/StopRunButton";
4445
import { TaskSessionView } from "@/features/tasks/components/TaskSessionView";
4546
import { buildCloudPromptBlocks } from "@/features/tasks/composer/attachments/buildCloudPrompt";
4647
import type { PendingAttachment } from "@/features/tasks/composer/attachments/types";
48+
import {
49+
type ContextWindow,
50+
DEFAULT_CONTEXT_WINDOW,
51+
} from "@/features/tasks/composer/options";
4752
import { QueuedMessagesDock } from "@/features/tasks/composer/QueuedMessagesDock";
4853
import { TaskChatComposer } from "@/features/tasks/composer/TaskChatComposer";
4954
import {
@@ -214,6 +219,13 @@ export default function TaskDetailScreen() {
214219
)
215220
? requestedComposerReasoning
216221
: DEFAULT_REASONING_EFFORT;
222+
const composerContextWindow: ContextWindow =
223+
(composerConfigMatchesAdapter
224+
? composerConfig?.contextWindow
225+
: undefined) ?? DEFAULT_CONTEXT_WINDOW;
226+
const composerFastMode: boolean =
227+
(composerConfigMatchesAdapter ? composerConfig?.fastMode : undefined) ??
228+
false;
217229

218230
const messagingMode = useMessagingMode(taskId);
219231
const queuedCount = useQueuedCount(taskId);
@@ -367,6 +379,8 @@ export default function TaskDetailScreen() {
367379
mode: composerMode,
368380
model: composerModel,
369381
reasoning: composerReasoning,
382+
contextWindow: composerContextWindow,
383+
fastMode: composerFastMode,
370384
}),
371385
rtkEnabled: usePreferencesStore.getState().rtkEnabledCloud,
372386
},
@@ -396,6 +410,8 @@ export default function TaskDetailScreen() {
396410
composerAdapter,
397411
composerModel,
398412
composerReasoning,
413+
composerContextWindow,
414+
composerFastMode,
399415
],
400416
);
401417

@@ -553,10 +569,14 @@ export default function TaskDetailScreen() {
553569
const handleAdapterChange = useCallback(
554570
(selection: CloudComposerSelection) => {
555571
if (!taskId) return;
556-
setComposerConfig(taskId, selection);
557-
const preferences = usePreferencesStore.getState();
558-
preferences.setLastNewTaskMode(selection.mode);
559-
preferences.setLastUsedReasoningEffort(selection.reasoning);
572+
setComposerConfig(taskId, {
573+
...selection,
574+
contextWindow: DEFAULT_CONTEXT_WINDOW,
575+
fastMode: false,
576+
});
577+
usePreferencesStore
578+
.getState()
579+
.resetLastUsedAgentConfig(selection.mode, selection.reasoning);
560580
},
561581
[taskId, setComposerConfig],
562582
);
@@ -584,6 +604,24 @@ export default function TaskDetailScreen() {
584604
[taskId, composerAdapter, setComposerConfig, setConfigOption],
585605
);
586606

607+
const handleContextWindowChange = useCallback(
608+
(value: ContextWindow) => {
609+
if (!taskId) return;
610+
setComposerConfig(taskId, { contextWindow: value });
611+
usePreferencesStore.getState().setLastUsedContextWindow(value);
612+
},
613+
[taskId, setComposerConfig],
614+
);
615+
616+
const handleFastModeChange = useCallback(
617+
(value: boolean) => {
618+
if (!taskId) return;
619+
setComposerConfig(taskId, { fastMode: value });
620+
usePreferencesStore.getState().setLastUsedFastMode(value);
621+
},
622+
[taskId, setComposerConfig],
623+
);
624+
587625
const handleStop = useCallback(() => {
588626
if (!taskId) return;
589627
// cancelPrompt returns false on failure — no need to alert,
@@ -638,6 +676,8 @@ export default function TaskDetailScreen() {
638676
mode: composerMode,
639677
model: composerModel,
640678
reasoning: composerReasoning,
679+
contextWindow: composerContextWindow,
680+
fastMode: composerFastMode,
641681
}),
642682
rtkEnabled: usePreferencesStore.getState().rtkEnabledCloud,
643683
},
@@ -665,6 +705,8 @@ export default function TaskDetailScreen() {
665705
composerModel,
666706
composerReasoning,
667707
composerMode,
708+
composerContextWindow,
709+
composerFastMode,
668710
]);
669711

670712
// Clear retrying once the agent finishes a turn or the run terminates.
@@ -696,7 +738,7 @@ export default function TaskDetailScreen() {
696738
[router],
697739
);
698740

699-
const prUrl = task?.latest_run?.output?.pr_url as string | undefined;
741+
const prUrl = readPrUrls(task?.latest_run?.output)[0];
700742

701743
const activityPhase = getSessionActivityPhase({ retrying, session });
702744
const isConnecting = activityPhase === "connecting";
@@ -795,6 +837,7 @@ export default function TaskDetailScreen() {
795837
<TaskSessionView
796838
events={session?.events ?? []}
797839
taskId={taskId}
840+
runId={task?.latest_run?.id}
798841
pendingPermissions={session?.pendingPermissions}
799842
isConnecting={isConnecting}
800843
isThinking={isThinking}
@@ -875,10 +918,14 @@ export default function TaskDetailScreen() {
875918
mode={composerMode}
876919
model={composerModel}
877920
reasoning={composerReasoning}
921+
contextWindow={composerContextWindow}
922+
fastMode={composerFastMode}
878923
onAdapterChange={handleAdapterChange}
879924
onModeChange={handleModeChange}
880925
onModelChange={handleModelChange}
881926
onReasoningChange={handleReasoningChange}
927+
onContextWindowChange={handleContextWindowChange}
928+
onFastModeChange={handleFastModeChange}
882929
messagingMode={messagingMode}
883930
queuedCount={queuedCount}
884931
onToggleMessagingMode={toggleMessagingMode}

0 commit comments

Comments
 (0)