Skip to content

Commit 81fcc5b

Browse files
committed
chore: add stabilization delay to client's startFlow
1 parent 5635d40 commit 81fcc5b

13 files changed

+629
-107
lines changed

.claude/skills/restack/SKILL.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
# Restack
2-
3-
Use when user asks to "restack", "resolve conflicts", "gt restack", or mentions restack conflicts. Guides through gt restack conflicts with intelligent diagnostics and resolution. (project)
1+
---
2+
name: restack
3+
description: Use when user asks to "restack", "resolve conflicts", "gt restack", or mentions restack conflicts. Guides through gt restack conflicts with intelligent diagnostics and resolution.
4+
allowed-tools: Bash(gt restack:*), Bash(gt continue:*), Bash(git show:*), Bash(git diff:*), Bash(git log:*), Bash(git ls-tree:*), Bash(pnpm install:*), Bash(git status:*), Bash(gt log:*), Bash(rm pnpm-lock.yaml), Bash(gt add -A:*),
5+
---
46

57
<critical>
68
- ALWAYS check current state first (supports both: starting fresh or mid-conflict)
@@ -21,12 +23,14 @@ git status
2123
```
2224

2325
**Check for**:
26+
2427
- "rebase in progress"
2528
- "You are currently rebasing"
2629
- "Unmerged paths"
2730
- "both modified:" or other conflict indicators
2831

2932
**Outcomes**:
33+
3034
- Already in conflict (user ran `gt restack` manually) → Skip to step 3 (Gather Diagnostics)
3135
- Clean state → Proceed to step 2 (Run Restack)
3236

@@ -37,6 +41,7 @@ gt restack
3741
```
3842

3943
**Outcomes**:
44+
4045
- Success → Acknowledge and exit
4146
- Conflicts → Proceed to step 3
4247

@@ -61,11 +66,13 @@ git diff <file>
6166
### 3. Explain Conflict Type
6267

6368
**Simple conflict** (lockfile-only):
69+
6470
- Only `pnpm-lock.yaml` in unmerged files
6571
- Explain: Lockfile is generated content, safe to regenerate
6672
- Propose: `pnpm install && gt add -A && gt continue`
6773

6874
**Complex conflict** (multi-file):
75+
6976
- Multiple files in unmerged files
7077
- Explain each file's conflict
7178
- Guide through resolution strategy
@@ -75,6 +82,7 @@ git diff <file>
7582
#### Simple Conflict Resolution
7683

7784
Use AskUserQuestion:
85+
7886
```
7987
question: "Only pnpm-lock.yaml is conflicted. Regenerate and continue?"
8088
header: "Simple Resolution"
@@ -86,6 +94,7 @@ options:
8694
```
8795

8896
If confirmed → Execute → Check output of `gt continue`:
97+
8998
- Another conflict → Loop back to step 3 (Gather Diagnostics)
9099
- Success message → Proceed to step 6 (Success & Reminder)
91100

@@ -94,16 +103,19 @@ If confirmed → Execute → Check output of `gt continue`:
94103
For each non-lockfile conflict:
95104

96105
**a) Show the conflict**:
106+
97107
```bash
98108
git diff <file>
99109
```
100110

101111
**b) Explain the conflict** (extract from diff):
112+
102113
- What changed in base (HEAD)
103114
- What changed in branch (incoming)
104115
- Why it conflicts
105116

106117
**c) Ask resolution strategy** using AskUserQuestion:
118+
107119
```
108120
question: "How to resolve <file>?"
109121
header: "Resolution"
@@ -119,17 +131,20 @@ options:
119131
```
120132

121133
**d) Execute choice**:
134+
122135
- `--theirs`: `git checkout --theirs <file>`
123136
- `--ours`: `git checkout --ours <file>`
124137
- Manual: Wait for user confirmation
125138
- Show original: Display and ask again
126139

127140
**e) After all non-lockfile conflicts resolved**:
141+
128142
```bash
129143
pnpm install && gt add -A && gt continue
130144
```
131145

132146
**f) Check output of `gt continue`**:
147+
133148
- Another conflict → Loop back to step 3 (Gather Diagnostics)
134149
- Success message → Proceed to step 6 (Success & Reminder)
135150

@@ -138,6 +153,7 @@ pnpm install && gt add -A && gt continue
138153
If diagnostics show "broken lockfile" warning:
139154

140155
Use AskUserQuestion:
156+
141157
```
142158
question: "Lockfile is corrupted. Delete and regenerate?"
143159
header: "Broken Lockfile"
@@ -149,6 +165,7 @@ options:
149165
```
150166

151167
After executing choice, check output of command:
168+
152169
- Another conflict → Loop back to step 3 (Gather Diagnostics)
153170
- Success message → Proceed to step 6 (Success & Reminder)
154171

@@ -170,36 +187,42 @@ Note: Always use --force-with-lease for safety
170187
## Quick Reference
171188

172189
**Simple lockfile conflict**:
190+
173191
```bash
174192
pnpm install && gt add -A && gt continue
175193
```
176194

177195
**Multiple files conflicted**:
196+
178197
```bash
179198
git diff <file> # Inspect
180199
git checkout --ours/--theirs <file> # Resolve
181200
pnpm install && gt add -A && gt continue
182201
```
183202

184203
**Broken lockfile**:
204+
185205
```bash
186206
rm pnpm-lock.yaml
187207
pnpm install && gt add -A && gt continue
188208
```
189209

190210
**Cancel restack**:
211+
191212
```bash
192213
gt abort
193214
```
194215

195216
## Resolution Strategy Guide
196217

197218
**When to use `--theirs` (accept main's version)**:
219+
198220
- Style/formatting conflicts (e.g., quoted vs unquoted YAML)
199221
- Configuration files where consistency with main matters
200222
- Files you didn't intentionally change
201223

202224
**When to use `--ours` (keep branch's version)**:
225+
203226
- Your branch added dependencies (e.g., pnpm-workspace.yaml)
204227
- Feature changes you need to preserve
205228
- Files where your changes are the whole point

pkgs/client/__tests__/integration/concurrent-operations.test.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ describe('Concurrent Operations Tests', () => {
4141
expect(run1.flow_slug).toBe(flow1.slug);
4242
expect(run2.flow_slug).toBe(flow2.slug);
4343

44-
// Give realtime subscriptions time to establish
45-
await new Promise(resolve => setTimeout(resolve, 300));
46-
4744
// Get and complete tasks from both flows
4845
console.log('=== Completing steps ===');
4946

@@ -203,9 +200,6 @@ describe('Concurrent Operations Tests', () => {
203200
const uniqueRunIds = [...new Set(runIds)];
204201
expect(uniqueRunIds.length).toBe(3);
205202

206-
// Give subscriptions time to establish
207-
await new Promise(resolve => setTimeout(resolve, 300));
208-
209203
// Poll for all tasks and complete them sequentially for reliability
210204
const allTasks = await readAndStart(sql, sqlClient, testFlow.slug, 5, 5);
211205
expect(allTasks.length).toBe(3); // One task per run
@@ -280,9 +274,6 @@ describe('Concurrent Operations Tests', () => {
280274
const runA = await pgflowClient.startFlow(flowA.slug, { type: 'flow-a' });
281275
const runB = await pgflowClient.startFlow(flowB.slug, { type: 'flow-b' });
282276

283-
// Give subscriptions time to establish
284-
await new Promise(resolve => setTimeout(resolve, 300));
285-
286277
// Get tasks from both flows
287278
const tasksA = await readAndStart(sql, sqlClient, flowA.slug, 2, 5);
288279
const tasksB = await readAndStart(sql, sqlClient, flowB.slug, 2, 5);

pkgs/client/__tests__/integration/full-stack-dsl.test.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,6 @@ describe('Full Stack DSL Integration', () => {
8787
expect(run.flow_slug).toBe(SimpleFlow.slug);
8888
expect(run.input).toEqual(input);
8989

90-
// Give realtime subscription time to establish
91-
await new Promise((resolve) => setTimeout(resolve, 200));
92-
9390
// 7. Execute the complete flow lifecycle
9491
console.log('=== Step 1: Completing fetch step ===');
9592
let tasks = await readAndStart(sql, sqlClient, SimpleFlow.slug, 1, 5);

pkgs/client/__tests__/integration/happy-path-e2e.test.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ describe('Happy Path E2E Integration', () => {
6565
expect(run.status).toBe(FlowRunStatus.Started);
6666
expect(run.input).toEqual(input);
6767

68-
// Give realtime subscription time to establish
69-
await new Promise(resolve => setTimeout(resolve, 200));
70-
7168
// Step 1: Complete fetch step
7269
console.log('=== Step 1: Completing fetch step ===');
7370
let tasks = await readAndStart(sql, sqlClient, testFlow.slug, 1, 5);

pkgs/client/__tests__/integration/input-validation.test.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,6 @@ describe('Input Validation', () => {
215215
run.on('*', runTracker.callback);
216216
run.step('producer').on('*', stepTracker.callback);
217217

218-
// Give realtime subscription time to establish
219-
await new Promise(resolve => setTimeout(resolve, 100));
220-
221218
// Execute the producer step
222219
const tasks = await readAndStart(sql, sqlClient, testFlow.slug, 1, 5);
223220
expect(tasks).toHaveLength(1);
@@ -294,9 +291,6 @@ describe('Input Validation', () => {
294291

295292
const run = await pgflowClient.startFlow(testFlow.slug, { data: 'test' });
296293

297-
// Give realtime subscription time to establish
298-
await new Promise(resolve => setTimeout(resolve, 100));
299-
300294
// Execute the producer step
301295
const tasks = await readAndStart(sql, sqlClient, testFlow.slug, 1, 5);
302296
expect(tasks).toHaveLength(1);

pkgs/client/__tests__/integration/network-resilience.test.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ describe('Network Resilience Tests', () => {
4444
}
4545
});
4646

47-
// Give subscription time to establish
48-
await new Promise((resolve) => setTimeout(resolve, 200));
49-
5047
// Complete first step before disconnection
5148
let tasks = await readAndStart(sql, sqlClient, testFlow.slug, 1, 5);
5249
expect(tasks).toHaveLength(1);
@@ -151,9 +148,6 @@ describe('Network Resilience Tests', () => {
151148
});
152149
}
153150

154-
// Give subscription time to establish
155-
await new Promise((resolve) => setTimeout(resolve, 200));
156-
157151
// Complete step while monitoring connection
158152
const tasks = await readAndStart(sql, sqlClient, testFlow.slug, 1, 5);
159153
expect(tasks).toHaveLength(1);

pkgs/client/__tests__/integration/real-flow-execution.test.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ describe('Real Flow Execution', () => {
3535
expect(run.run_id).toBeDefined();
3636
expect(run.flow_slug).toBe(testFlow.slug);
3737

38-
// Give realtime subscription time to establish properly
39-
await new Promise((resolve) => setTimeout(resolve, 2000));
40-
4138
// Poll for task
4239
const tasks = await readAndStart(sql, sqlClient, testFlow.slug, 1, 5);
4340

@@ -111,9 +108,6 @@ describe('Real Flow Execution', () => {
111108
const step = run.step('event_step');
112109
step.on('*', stepTracker.callback);
113110

114-
// Give realtime subscription time to establish
115-
await new Promise((resolve) => setTimeout(resolve, 100));
116-
117111
// Poll and complete task
118112
const tasks = await readAndStart(sql, sqlClient, testFlow.slug, 1, 5);
119113
await sqlClient.completeTask(tasks[0], { hello: 'world' });
@@ -217,9 +211,6 @@ describe('Real Flow Execution', () => {
217211
const tracker = createEventTracker();
218212
dependentStep.on('*', tracker.callback);
219213

220-
// Give realtime subscription time to establish
221-
await new Promise((resolve) => setTimeout(resolve, 100));
222-
223214
// Complete root step - this will trigger dependent_step to start
224215
const rootTasks = await readAndStart(sql, sqlClient, testFlow.slug, 1, 5);
225216
expect(rootTasks[0].step_slug).toBe('root_step');
@@ -401,9 +392,6 @@ describe('Real Flow Execution', () => {
401392
expect(step.status).toBe(FlowStepStatus.Started);
402393
expect(step.started_at).toBeDefined();
403394

404-
// Give realtime subscription time to establish
405-
await new Promise((resolve) => setTimeout(resolve, 100));
406-
407395
// waitForStatus should resolve immediately since step is already Started
408396
const waitPromise = step.waitForStatus(FlowStepStatus.Started, {
409397
timeoutMs: 5000,

pkgs/client/__tests__/integration/realtime-send.test.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ describe('Realtime Send Integration', () => {
3737
await subscriptionPromise;
3838
console.log('Channel fully subscribed and ready');
3939

40-
// Additional wait to ensure realtime connection is stable
41-
await new Promise((resolve) => setTimeout(resolve, 200));
42-
4340
// 4. Send event via SQL realtime.send() function
4441
const dbPayload = {
4542
test_message: 'Hello from SQL realtime.send()!',

pkgs/client/__tests__/integration/reconnection.test.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ describe('Reconnection Integration Tests', () => {
4343
reconnectionEvents.push(event.event_type);
4444
});
4545

46-
// Give realtime subscription time to establish
47-
await new Promise((resolve) => setTimeout(resolve, 200));
48-
4946
// Simulate network interruption by creating a new client
5047
// This forces the underlying channel to be recreated
5148
const newSupabaseClient = createTestSupabaseClient();
@@ -110,9 +107,6 @@ describe('Reconnection Integration Tests', () => {
110107
expect(run.status).toBe(FlowRunStatus.Started);
111108
expect(run.input).toEqual(input);
112109

113-
// Give initial subscription time to establish
114-
await new Promise((resolve) => setTimeout(resolve, 200));
115-
116110
// Simulate disconnection by disposing the client and creating a new one
117111
pgflowClient.dispose(run.run_id);
118112

@@ -174,9 +168,6 @@ describe('Reconnection Integration Tests', () => {
174168
const input = { data: 'rapid-test' };
175169
const originalRun = await pgflowClient.startFlow(testFlow.slug, input);
176170

177-
// Give initial subscription time to establish
178-
await new Promise((resolve) => setTimeout(resolve, 200));
179-
180171
// Create multiple run instances rapidly (simulates rapid reconnections)
181172
const runs = await Promise.all([
182173
pgflowClient.getRun(originalRun.run_id),

pkgs/client/__tests__/integration/regressions/step-failed-event-bug.test.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ describe('Step Failed Event Broadcasting', () => {
3838
step.on('*', stepTracker.callback);
3939
run.on('*', runTracker.callback);
4040

41-
// Give realtime subscription time to establish
42-
await new Promise(resolve => setTimeout(resolve, 100));
43-
4441
// Poll and start the task (uses pgmq.read_with_poll and pgflow.start_tasks internally)
4542
const tasks = await readAndStart(sql, sqlClient, testFlow.slug, 1, 5);
4643
expect(tasks).toHaveLength(1);

0 commit comments

Comments
 (0)