@cueloop/client 0.1.0-alpha.64 → 0.1.0-alpha.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/src/App.autoclose.test.tsx +2 -2
- package/src/App.export.test.tsx +2 -2
- package/src/App.plan-review.test.tsx +76 -247
- package/src/App.readonly.test.tsx +80 -35
- package/src/App.rendering.test.tsx +5 -6
- package/src/App.review-panel.test.tsx +29 -32
- package/src/App.submit-confirm.test.tsx +27 -12
- package/src/App.test.tsx +73 -49
- package/src/App.toast.test.tsx +17 -8
- package/src/App.tree.test.tsx +224 -0
- package/src/App.tsx +120 -84
- package/src/app-screens.tsx +27 -1
- package/src/app-view-model.ts +4 -96
- package/src/components/AnnotationCard.tsx +2 -2
- package/src/components/KeybindsDialog.tsx +61 -17
- package/src/components/ReviewPanel.stories.tsx +14 -0
- package/src/components/ReviewRail.stories.tsx +14 -0
- package/src/components/ReviewRail.tsx +13 -6
- package/src/components/ThreadView.selection.test.tsx +812 -0
- package/src/components/ThreadView.stories.tsx +26 -0
- package/src/components/ThreadView.tsx +1620 -0
- package/src/components/TreePane.stories.tsx +106 -0
- package/src/components/TreePane.tsx +156 -0
- package/src/components/__snapshots__/stories.test.tsx.snap +120 -172
- package/src/diff-hunk-curate.ts +4 -104
- package/src/index.ts +1 -0
- package/src/intent-dispatch.test.ts +136 -3
- package/src/intent-dispatch.ts +92 -24
- package/src/key-bindings.test.ts +1 -1
- package/src/keymap.test.ts +4 -4
- package/src/keymap.ts +14 -7
- package/src/session-controller.curate.test.ts +89 -2
- package/src/session-controller.share.test.ts +195 -55
- package/src/session-controller.tree.test.ts +228 -0
- package/src/session-controller.ts +322 -68
- package/src/share.ts +114 -16
- package/src/test-support.test.ts +193 -1
- package/src/test-support.ts +64 -0
- package/src/thread-chords.test.ts +154 -0
- package/src/thread-chords.ts +144 -0
- package/src/thread-selection.test.ts +210 -0
- package/src/thread-selection.ts +243 -0
- package/src/tree-view.test.ts +128 -0
- package/src/tree-view.ts +148 -0
- package/src/view-plan.ts +29 -12
- package/src/components/PlanSheet.stories.tsx +0 -113
- package/src/components/PlanSheet.tsx +0 -419
- package/src/components/plan-sheet-run-style.ts +0 -88
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { DARK } from "../theme";
|
|
3
|
+
import type { Story, StoryMeta } from "./story";
|
|
4
|
+
import { TreePane } from "./TreePane";
|
|
5
|
+
import type { TreeRow } from "../tree-view";
|
|
6
|
+
|
|
7
|
+
export const meta: StoryMeta = { title: "TreePane" };
|
|
8
|
+
|
|
9
|
+
const callbacks = {
|
|
10
|
+
onSelect: () => {},
|
|
11
|
+
onGo: () => {},
|
|
12
|
+
onBranch: () => {},
|
|
13
|
+
onLabel: () => {},
|
|
14
|
+
onFork: () => {},
|
|
15
|
+
onForkAndShare: () => {},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/** rev1 -> comment (labelled, a branch hangs off it) -> the branch's comment -> rev2 as main's tip. */
|
|
19
|
+
const ROWS: TreeRow[] = [
|
|
20
|
+
{
|
|
21
|
+
entryId: "e1",
|
|
22
|
+
depth: 0,
|
|
23
|
+
glyph: "◉",
|
|
24
|
+
text: "revision 1",
|
|
25
|
+
onPath: true,
|
|
26
|
+
tips: [],
|
|
27
|
+
isCurrentTip: false,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
entryId: "e2",
|
|
31
|
+
depth: 0,
|
|
32
|
+
glyph: "·",
|
|
33
|
+
text: "comment",
|
|
34
|
+
onPath: true,
|
|
35
|
+
tips: [],
|
|
36
|
+
isCurrentTip: false,
|
|
37
|
+
label: "start",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
entryId: "e3",
|
|
41
|
+
depth: 1,
|
|
42
|
+
glyph: "·",
|
|
43
|
+
text: "comment",
|
|
44
|
+
onPath: false,
|
|
45
|
+
tips: ["alt"],
|
|
46
|
+
isCurrentTip: false,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
entryId: "e4",
|
|
50
|
+
depth: 0,
|
|
51
|
+
glyph: "◉",
|
|
52
|
+
text: "revision 2",
|
|
53
|
+
onPath: true,
|
|
54
|
+
tips: ["main"],
|
|
55
|
+
isCurrentTip: true,
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
/** The rail expects a height-constrained parent, like the app's main row. */
|
|
60
|
+
function PaneFrame({ children }: { children: React.ReactNode }): React.ReactNode {
|
|
61
|
+
return (
|
|
62
|
+
<box
|
|
63
|
+
style={{ flexDirection: "column", width: 40, height: "100%", backgroundColor: DARK.panel }}
|
|
64
|
+
>
|
|
65
|
+
{children}
|
|
66
|
+
</box>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const OwnerWithBranch: Story = {
|
|
71
|
+
render: () => (
|
|
72
|
+
<PaneFrame>
|
|
73
|
+
<TreePane rows={ROWS} selectedEntryId="e2" canMove canFork {...callbacks} />
|
|
74
|
+
</PaneFrame>
|
|
75
|
+
),
|
|
76
|
+
expectedColors: [DARK.accent],
|
|
77
|
+
size: { width: 40, height: 16 },
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const CollaboratorReadsOnly: Story = {
|
|
81
|
+
render: () => (
|
|
82
|
+
<PaneFrame>
|
|
83
|
+
<TreePane rows={ROWS} canMove={false} canFork={false} {...callbacks} />
|
|
84
|
+
</PaneFrame>
|
|
85
|
+
),
|
|
86
|
+
size: { width: 40, height: 16 },
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/** A resolved review: the owner can still fork, not move. */
|
|
90
|
+
export const ResolvedForkOnly: Story = {
|
|
91
|
+
render: () => (
|
|
92
|
+
<PaneFrame>
|
|
93
|
+
<TreePane rows={ROWS} canMove={false} canFork {...callbacks} />
|
|
94
|
+
</PaneFrame>
|
|
95
|
+
),
|
|
96
|
+
size: { width: 40, height: 16 },
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const NoHistory: Story = {
|
|
100
|
+
render: () => (
|
|
101
|
+
<PaneFrame>
|
|
102
|
+
<TreePane rows={[]} canMove canFork {...callbacks} />
|
|
103
|
+
</PaneFrame>
|
|
104
|
+
),
|
|
105
|
+
size: { width: 40, height: 8 },
|
|
106
|
+
};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rail's Tree tab: the session's history as one row per entry. The active
|
|
3
|
+
* path reads bright, everything else dim; a branch tip carries its name, the
|
|
4
|
+
* current tip a marker, a checkpoint its label. Clicking a row selects it,
|
|
5
|
+
* clicking the selected row goes there; the buttons underneath are the mouse
|
|
6
|
+
* path to the same primitives the option chords reach.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React, { useEffect, useRef } from "react";
|
|
10
|
+
import { createTextAttributes, type ScrollBoxRenderable } from "@opentui/core";
|
|
11
|
+
import type { Theme } from "../theme";
|
|
12
|
+
import type { TreeRow } from "../tree-view";
|
|
13
|
+
import { useComponentTheme } from "./theme-context";
|
|
14
|
+
import { Button } from "./primitives/Button";
|
|
15
|
+
import { Toolbar } from "./primitives/Toolbar";
|
|
16
|
+
|
|
17
|
+
export interface TreePaneProps {
|
|
18
|
+
rows: TreeRow[];
|
|
19
|
+
selectedEntryId?: string;
|
|
20
|
+
/** The owner of an open review may move the tree; everyone else reads it. */
|
|
21
|
+
canMove: boolean;
|
|
22
|
+
/** The owner may fork, a resolved review included. */
|
|
23
|
+
canFork: boolean;
|
|
24
|
+
onSelect: (entryId: string) => void;
|
|
25
|
+
onGo: (entryId: string) => void;
|
|
26
|
+
onBranch: () => void;
|
|
27
|
+
onLabel: () => void;
|
|
28
|
+
onFork: () => void;
|
|
29
|
+
onForkAndShare: () => void;
|
|
30
|
+
theme?: Theme;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const DIM = createTextAttributes({ dim: true });
|
|
34
|
+
const BOLD = createTextAttributes({ bold: true });
|
|
35
|
+
|
|
36
|
+
/** The marker column: the current tip stands out, every other row keeps its kind's glyph. */
|
|
37
|
+
function markerFor(row: TreeRow): string {
|
|
38
|
+
return row.isCurrentTip ? "●" : row.glyph;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** What follows the entry's name: the branches whose tip it is, and its checkpoint. */
|
|
42
|
+
function trailerFor(row: TreeRow): string {
|
|
43
|
+
const parts: string[] = [];
|
|
44
|
+
|
|
45
|
+
if (row.tips.length) parts.push(`← ${row.tips.join(", ")}`);
|
|
46
|
+
if (row.label !== undefined) parts.push(`⚑ ${row.label}`);
|
|
47
|
+
|
|
48
|
+
return parts.length ? ` ${parts.join(" ")}` : "";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function TreePane({
|
|
52
|
+
rows,
|
|
53
|
+
selectedEntryId,
|
|
54
|
+
canMove,
|
|
55
|
+
canFork,
|
|
56
|
+
onSelect,
|
|
57
|
+
onGo,
|
|
58
|
+
onBranch,
|
|
59
|
+
onLabel,
|
|
60
|
+
onFork,
|
|
61
|
+
onForkAndShare,
|
|
62
|
+
theme,
|
|
63
|
+
}: TreePaneProps): React.ReactNode {
|
|
64
|
+
const tokens = useComponentTheme(theme);
|
|
65
|
+
const scrollRef = useRef<ScrollBoxRenderable | null>(null);
|
|
66
|
+
const revealId = selectedEntryId ?? rows.find((row) => row.isCurrentTip)?.entryId;
|
|
67
|
+
|
|
68
|
+
// the trunk draws last, so a long history opens with its tip below the fold: keep the row in view
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (revealId === undefined) return;
|
|
71
|
+
try {
|
|
72
|
+
scrollRef.current?.scrollChildIntoView(`tree-row-${revealId}`);
|
|
73
|
+
} catch {
|
|
74
|
+
// reveal is best-effort; the selection is already correct
|
|
75
|
+
}
|
|
76
|
+
}, [revealId]);
|
|
77
|
+
|
|
78
|
+
if (rows.length === 0)
|
|
79
|
+
return (
|
|
80
|
+
<box style={{ flexGrow: 1, alignItems: "center", justifyContent: "center" }}>
|
|
81
|
+
<text fg={tokens.textDim}>no history yet</text>
|
|
82
|
+
</box>
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<box style={{ flexGrow: 1, flexDirection: "column" }}>
|
|
87
|
+
<scrollbox ref={scrollRef} style={{ flexGrow: 1 }} focused={false}>
|
|
88
|
+
{rows.map((row) => {
|
|
89
|
+
const selected = row.entryId === selectedEntryId;
|
|
90
|
+
const foreground = row.onPath ? tokens.text : tokens.textDim;
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<box
|
|
94
|
+
key={row.entryId}
|
|
95
|
+
id={`tree-row-${row.entryId}`}
|
|
96
|
+
style={{
|
|
97
|
+
flexDirection: "row",
|
|
98
|
+
paddingLeft: 1 + row.depth * 2,
|
|
99
|
+
backgroundColor: selected ? tokens.elevated : undefined,
|
|
100
|
+
}}
|
|
101
|
+
onMouseUp={() => (selected && canMove ? onGo(row.entryId) : onSelect(row.entryId))}
|
|
102
|
+
>
|
|
103
|
+
<text
|
|
104
|
+
fg={row.isCurrentTip ? tokens.accent : foreground}
|
|
105
|
+
attributes={row.onPath ? undefined : DIM}
|
|
106
|
+
>
|
|
107
|
+
{markerFor(row)} {row.text}
|
|
108
|
+
</text>
|
|
109
|
+
<text fg={tokens.textMuted} attributes={row.label === undefined ? undefined : BOLD}>
|
|
110
|
+
{trailerFor(row)}
|
|
111
|
+
</text>
|
|
112
|
+
</box>
|
|
113
|
+
);
|
|
114
|
+
})}
|
|
115
|
+
</scrollbox>
|
|
116
|
+
{canMove || canFork ? (
|
|
117
|
+
<box style={{ paddingLeft: 1 }}>
|
|
118
|
+
<Toolbar>
|
|
119
|
+
{canMove ? (
|
|
120
|
+
<Button
|
|
121
|
+
onPress={() => {
|
|
122
|
+
if (selectedEntryId !== undefined) onGo(selectedEntryId);
|
|
123
|
+
}}
|
|
124
|
+
isDisabled={selectedEntryId === undefined}
|
|
125
|
+
marginRight={1}
|
|
126
|
+
theme={theme}
|
|
127
|
+
>
|
|
128
|
+
Go
|
|
129
|
+
</Button>
|
|
130
|
+
) : null}
|
|
131
|
+
{canMove ? (
|
|
132
|
+
<Button onPress={onBranch} marginRight={1} theme={theme}>
|
|
133
|
+
Branch
|
|
134
|
+
</Button>
|
|
135
|
+
) : null}
|
|
136
|
+
{canMove ? (
|
|
137
|
+
<Button onPress={onLabel} marginRight={1} theme={theme}>
|
|
138
|
+
Label
|
|
139
|
+
</Button>
|
|
140
|
+
) : null}
|
|
141
|
+
{canFork ? (
|
|
142
|
+
<Button onPress={onFork} marginRight={1} theme={theme}>
|
|
143
|
+
Fork
|
|
144
|
+
</Button>
|
|
145
|
+
) : null}
|
|
146
|
+
{canFork ? (
|
|
147
|
+
<Button onPress={onForkAndShare} theme={theme}>
|
|
148
|
+
Fork+share
|
|
149
|
+
</Button>
|
|
150
|
+
) : null}
|
|
151
|
+
</Toolbar>
|
|
152
|
+
</box>
|
|
153
|
+
) : null}
|
|
154
|
+
</box>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Bun Snapshot v1, https://
|
|
1
|
+
// Bun Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`stories catalog AnnotationCard/CommentDraft renders, snapshots, and carries its colors: AnnotationCard/CommentDraft 1`] = `
|
|
4
4
|
"╭─ comment on "persists sessions" ─────────────────────────────────────────────╮
|
|
@@ -618,168 +618,6 @@ exports[`stories catalog MenuBar/Open renders, snapshots, and carries its colors
|
|
|
618
618
|
"
|
|
619
619
|
`;
|
|
620
620
|
|
|
621
|
-
exports[`stories catalog PlanSheet/AnnotatedPlan renders, snapshots, and carries its colors: PlanSheet/AnnotatedPlan 1`] = `
|
|
622
|
-
"╭────────────────────────────────────────────────────────────────────────────────────────╮
|
|
623
|
-
│ Migration Plan │
|
|
624
|
-
│ │
|
|
625
|
-
│ Context │
|
|
626
|
-
│ │
|
|
627
|
-
│ ▎ The daemon persists sessions to disk atomically. │
|
|
628
|
-
│ │
|
|
629
|
-
│ Steps │
|
|
630
|
-
│ │
|
|
631
|
-
│ - move the store │
|
|
632
|
-
│ - add recovery │
|
|
633
|
-
│ │
|
|
634
|
-
│ ts │
|
|
635
|
-
│ │
|
|
636
|
-
│ export function persist(session: Session): void { │
|
|
637
|
-
│ // one JSON document per session │
|
|
638
|
-
│ writeAtomically(pathFor(session.id), serialize(session)); │
|
|
639
|
-
│ } │
|
|
640
|
-
│ │
|
|
641
|
-
│ │
|
|
642
|
-
│ │
|
|
643
|
-
│ │
|
|
644
|
-
│ │
|
|
645
|
-
│ │
|
|
646
|
-
│ │
|
|
647
|
-
│ │
|
|
648
|
-
│ │
|
|
649
|
-
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
|
650
|
-
"
|
|
651
|
-
`;
|
|
652
|
-
|
|
653
|
-
exports[`stories catalog PlanSheet/InlineCompose renders, snapshots, and carries its colors: PlanSheet/InlineCompose 1`] = `
|
|
654
|
-
"╭────────────────────────────────────────────────────────────────────────────────────────╮
|
|
655
|
-
│ Migration Plan │
|
|
656
|
-
│ │
|
|
657
|
-
│ Context │
|
|
658
|
-
│ │
|
|
659
|
-
│ ▎ The daemon persists sessions to disk atomically. │
|
|
660
|
-
│ ╭─ comment on "The daemon" ───────────────────────────────────────────────────────────╮│
|
|
661
|
-
│ │ Which daemon? ││
|
|
662
|
-
│ │ Save Cancel ││
|
|
663
|
-
│ ╰─────────────────────────────────────────────────────────────────────────────────────╯│
|
|
664
|
-
│ │
|
|
665
|
-
│ Steps │
|
|
666
|
-
│ │
|
|
667
|
-
│ - move the store │
|
|
668
|
-
│ - add recovery │
|
|
669
|
-
│ │
|
|
670
|
-
│ ts │
|
|
671
|
-
│ │
|
|
672
|
-
│ export function persist(session: Session): void { │
|
|
673
|
-
│ // one JSON document per session │
|
|
674
|
-
│ writeAtomically(pathFor(session.id), serialize(session)); │
|
|
675
|
-
│ } │
|
|
676
|
-
│ │
|
|
677
|
-
│ │
|
|
678
|
-
│ │
|
|
679
|
-
│ │
|
|
680
|
-
│ │
|
|
681
|
-
│ │
|
|
682
|
-
│ │
|
|
683
|
-
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
|
684
|
-
"
|
|
685
|
-
`;
|
|
686
|
-
|
|
687
|
-
exports[`stories catalog PlanSheet/OrphanBanner renders, snapshots, and carries its colors: PlanSheet/OrphanBanner 1`] = `
|
|
688
|
-
"╭────────────────────────────────────────────────────────────────────────────────────────╮
|
|
689
|
-
│ 1 annotation no longer match - the passage was removed. │
|
|
690
|
-
│ ▎ Migration Plan │
|
|
691
|
-
│ │
|
|
692
|
-
│ Context │
|
|
693
|
-
│ │
|
|
694
|
-
│ The daemon persists sessions to disk atomically. │
|
|
695
|
-
│ │
|
|
696
|
-
│ Steps │
|
|
697
|
-
│ │
|
|
698
|
-
│ - move the store │
|
|
699
|
-
│ - add recovery │
|
|
700
|
-
│ │
|
|
701
|
-
│ ts │
|
|
702
|
-
│ │
|
|
703
|
-
│ export function persist(session: Session): void { │
|
|
704
|
-
│ // one JSON document per session │
|
|
705
|
-
│ writeAtomically(pathFor(session.id), serialize(session)); │
|
|
706
|
-
│ } │
|
|
707
|
-
│ │
|
|
708
|
-
│ │
|
|
709
|
-
│ │
|
|
710
|
-
│ │
|
|
711
|
-
│ │
|
|
712
|
-
│ │
|
|
713
|
-
│ │
|
|
714
|
-
│ │
|
|
715
|
-
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
|
716
|
-
"
|
|
717
|
-
`;
|
|
718
|
-
|
|
719
|
-
exports[`stories catalog PlanSheet/SpanSelection renders, snapshots, and carries its colors: PlanSheet/SpanSelection 1`] = `
|
|
720
|
-
"╭────────────────────────────────────────────────────────────────────────────────────────╮
|
|
721
|
-
│ Migration Plan │
|
|
722
|
-
│ │
|
|
723
|
-
│ Context │
|
|
724
|
-
│ │
|
|
725
|
-
│ ▎ The daemon persists sessions to disk atomically. │
|
|
726
|
-
│ │
|
|
727
|
-
│ Steps │
|
|
728
|
-
│ │
|
|
729
|
-
│ - move the store │
|
|
730
|
-
│ - add recovery │
|
|
731
|
-
│ │
|
|
732
|
-
│ ts │
|
|
733
|
-
│ │
|
|
734
|
-
│ export function persist(session: Session): void { │
|
|
735
|
-
│ // one JSON document per session │
|
|
736
|
-
│ writeAtomically(pathFor(session.id), serialize(session)); │
|
|
737
|
-
│ } │
|
|
738
|
-
│ │
|
|
739
|
-
│ │
|
|
740
|
-
│ │
|
|
741
|
-
│ │
|
|
742
|
-
│ │
|
|
743
|
-
│ │
|
|
744
|
-
│ │
|
|
745
|
-
│ │
|
|
746
|
-
│ │
|
|
747
|
-
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
|
748
|
-
"
|
|
749
|
-
`;
|
|
750
|
-
|
|
751
|
-
exports[`stories catalog PlanSheet/WithCutBlock renders, snapshots, and carries its colors: PlanSheet/WithCutBlock 1`] = `
|
|
752
|
-
"╭────────────────────────────────────────────────────────────────────────────────────────╮
|
|
753
|
-
│ ▎ Migration Plan │
|
|
754
|
-
│ │
|
|
755
|
-
│ Context │
|
|
756
|
-
│ │
|
|
757
|
-
│ The daemon persists sessions to disk atomically. │
|
|
758
|
-
│ │
|
|
759
|
-
│ Steps │
|
|
760
|
-
│ │
|
|
761
|
-
│ - move the store │
|
|
762
|
-
│ - add recovery │
|
|
763
|
-
│ │
|
|
764
|
-
│ ts │
|
|
765
|
-
│ │
|
|
766
|
-
│ export function persist(session: Session): void { │
|
|
767
|
-
│ // one JSON document per session │
|
|
768
|
-
│ writeAtomically(pathFor(session.id), serialize(session)); │
|
|
769
|
-
│ } │
|
|
770
|
-
│ │
|
|
771
|
-
│ │
|
|
772
|
-
│ │
|
|
773
|
-
│ │
|
|
774
|
-
│ │
|
|
775
|
-
│ │
|
|
776
|
-
│ │
|
|
777
|
-
│ │
|
|
778
|
-
│ │
|
|
779
|
-
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
|
780
|
-
"
|
|
781
|
-
`;
|
|
782
|
-
|
|
783
621
|
exports[`stories catalog PromptDialog/NameYourself renders, snapshots, and carries its colors: PromptDialog/NameYourself 1`] = `
|
|
784
622
|
"
|
|
785
623
|
|
|
@@ -878,7 +716,7 @@ exports[`stories catalog ReviewPanel/Compact renders, snapshots, and carries its
|
|
|
878
716
|
|
|
879
717
|
exports[`stories catalog ReviewPanel/ExpandedNarrow renders, snapshots, and carries its colors: ReviewPanel/ExpandedNarrow 1`] = `
|
|
880
718
|
" The plan takes the width the panel hands back. ╭──────────────────────╮
|
|
881
|
-
│ Review Agent
|
|
719
|
+
│ Review Tree Agent │
|
|
882
720
|
╰──────────────────────╯
|
|
883
721
|
╭─ COMMENT · me ───────╮
|
|
884
722
|
│ Whichidaemonsownss" │
|
|
@@ -906,7 +744,7 @@ exports[`stories catalog ReviewPanel/ExpandedNarrow renders, snapshots, and carr
|
|
|
906
744
|
|
|
907
745
|
exports[`stories catalog ReviewPanel/ExpandedWide renders, snapshots, and carries its colors: ReviewPanel/ExpandedWide 1`] = `
|
|
908
746
|
" The plan takes the width the panel ╭────────────────────────────────────────────────╮
|
|
909
|
-
hands back. │ Review Agent
|
|
747
|
+
hands back. │ Review Tree Agent │
|
|
910
748
|
╰────────────────────────────────────────────────╯
|
|
911
749
|
╭─ COMMENT · me ─────────────────────────────────╮
|
|
912
750
|
│ "persists sessions" │
|
|
@@ -962,7 +800,7 @@ exports[`stories catalog ReviewPanel/Hidden renders, snapshots, and carries its
|
|
|
962
800
|
|
|
963
801
|
exports[`stories catalog ReviewRail/AgentTab renders, snapshots, and carries its colors: ReviewRail/AgentTab 1`] = `
|
|
964
802
|
"╭────────────────────────────────╮
|
|
965
|
-
│ Review Agent
|
|
803
|
+
│ Review Tree Agent │
|
|
966
804
|
╰────────────────────────────────╯
|
|
967
805
|
╭────────────────────────────────╮
|
|
968
806
|
│ Claude Code │
|
|
@@ -990,7 +828,7 @@ plan context: seed the plan
|
|
|
990
828
|
|
|
991
829
|
exports[`stories catalog ReviewRail/AnnotationStack renders, snapshots, and carries its colors: ReviewRail/AnnotationStack 1`] = `
|
|
992
830
|
"╭────────────────────────────────╮
|
|
993
|
-
│ Review Agent
|
|
831
|
+
│ Review Tree Agent │
|
|
994
832
|
╰────────────────────────────────╯
|
|
995
833
|
╭─ COMMENT · me ─────────────────╮
|
|
996
834
|
│ "persists sessions" │
|
|
@@ -1018,7 +856,7 @@ Submit review
|
|
|
1018
856
|
|
|
1019
857
|
exports[`stories catalog ReviewRail/InterleavedStack renders, snapshots, and carries its colors: ReviewRail/InterleavedStack 1`] = `
|
|
1020
858
|
"╭────────────────────────────────╮
|
|
1021
|
-
│ Review Agent
|
|
859
|
+
│ Review Tree Agent │
|
|
1022
860
|
╰────────────────────────────────╯
|
|
1023
861
|
╭─ CUT · me ─────────────────────╮
|
|
1024
862
|
│ - add recovery │
|
|
@@ -1046,7 +884,7 @@ Submit review
|
|
|
1046
884
|
|
|
1047
885
|
exports[`stories catalog ReviewRail/MixedOwnershipStack renders, snapshots, and carries its colors: ReviewRail/MixedOwnershipStack 1`] = `
|
|
1048
886
|
"╭────────────────────────────────╮
|
|
1049
|
-
│ Review Agent
|
|
887
|
+
│ Review Tree Agent │
|
|
1050
888
|
╰────────────────────────────────╯
|
|
1051
889
|
╭─ COMMENT · me ─────────────────╮
|
|
1052
890
|
│ "persists sessions" │
|
|
@@ -1074,7 +912,7 @@ Submit review
|
|
|
1074
912
|
|
|
1075
913
|
exports[`stories catalog ReviewRail/Removals renders, snapshots, and carries its colors: ReviewRail/Removals 1`] = `
|
|
1076
914
|
"╭────────────────────────────────╮
|
|
1077
|
-
│ Review Agent
|
|
915
|
+
│ Review Tree Agent │
|
|
1078
916
|
╰────────────────────────────────╯
|
|
1079
917
|
╭─ REJECT · me ──────────────────╮
|
|
1080
918
|
│ - private items = []; │
|
|
@@ -1102,7 +940,7 @@ Submit review
|
|
|
1102
940
|
|
|
1103
941
|
exports[`stories catalog ReviewRail/Resolved renders, snapshots, and carries its colors: ReviewRail/Resolved 1`] = `
|
|
1104
942
|
"╭────────────────────────────────╮
|
|
1105
|
-
│ Review Agent
|
|
943
|
+
│ Review Tree Agent │
|
|
1106
944
|
╰────────────────────────────────╯
|
|
1107
945
|
╭─ COMMENT · me · ORPHANED ──────╮
|
|
1108
946
|
│ "persists sessions" │
|
|
@@ -1130,7 +968,7 @@ resolved: approve
|
|
|
1130
968
|
|
|
1131
969
|
exports[`stories catalog ReviewRail/SubmitConfirmOpen renders, snapshots, and carries its colors: ReviewRail/SubmitConfirmOpen 1`] = `
|
|
1132
970
|
"╭────────────────────────────────╮
|
|
1133
|
-
│ Review Agent
|
|
971
|
+
│ Review Tree Agent │
|
|
1134
972
|
╰────────────────────────────────╯
|
|
1135
973
|
╭─ COMMENT · me · ORPHANED ──────╮
|
|
1136
974
|
│ "persists sessions" │
|
|
@@ -1289,6 +1127,44 @@ exports[`stories catalog SettingsRows/AllKinds renders, snapshots, and carries i
|
|
|
1289
1127
|
|
|
1290
1128
|
|
|
1291
1129
|
|
|
1130
|
+
"
|
|
1131
|
+
`;
|
|
1132
|
+
|
|
1133
|
+
exports[`stories catalog ThreadView/InlineThreads renders, snapshots, and carries its colors: ThreadView/InlineThreads 1`] = `
|
|
1134
|
+
"
|
|
1135
|
+
Migration Plan
|
|
1136
|
+
|
|
1137
|
+
Context
|
|
1138
|
+
|
|
1139
|
+
The daemon persists sessions to disk atomically.
|
|
1140
|
+
|
|
1141
|
+
╷─────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
1142
|
+
│ ● Which daemon owns this? │
|
|
1143
|
+
╵─────────────────────────────────────────────────────────────────────────────────────────────┘
|
|
1144
|
+
|
|
1145
|
+
Steps
|
|
1146
|
+
|
|
1147
|
+
· move the store
|
|
1148
|
+
|
|
1149
|
+
╷─────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
1150
|
+
│ ● move the store behind one interface │ ○
|
|
1151
|
+
╵─────────────────────────────────────────────────────────────────────────────────────────────┘ ○
|
|
1152
|
+
· add recovery
|
|
1153
|
+
|
|
1154
|
+
ts
|
|
1155
|
+
export function persist(session: Session): void {
|
|
1156
|
+
// one JSON document per session
|
|
1157
|
+
writeAtomically(pathFor(session.id), serialize(session));
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
|
|
1167
|
+
|
|
1292
1168
|
"
|
|
1293
1169
|
`;
|
|
1294
1170
|
|
|
@@ -1308,6 +1184,78 @@ exports[`stories catalog Toast/ShareLink renders, snapshots, and carries its col
|
|
|
1308
1184
|
"
|
|
1309
1185
|
`;
|
|
1310
1186
|
|
|
1187
|
+
exports[`stories catalog TreePane/CollaboratorReadsOnly renders, snapshots, and carries its colors: TreePane/CollaboratorReadsOnly 1`] = `
|
|
1188
|
+
" ◉ revision 1
|
|
1189
|
+
· comment ⚑ start
|
|
1190
|
+
· comment ← alt
|
|
1191
|
+
● revision 2 ← main
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
"
|
|
1205
|
+
`;
|
|
1206
|
+
|
|
1207
|
+
exports[`stories catalog TreePane/NoHistory renders, snapshots, and carries its colors: TreePane/NoHistory 1`] = `
|
|
1208
|
+
"
|
|
1209
|
+
|
|
1210
|
+
|
|
1211
|
+
no history yet
|
|
1212
|
+
|
|
1213
|
+
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
"
|
|
1217
|
+
`;
|
|
1218
|
+
|
|
1219
|
+
exports[`stories catalog TreePane/OwnerWithBranch renders, snapshots, and carries its colors: TreePane/OwnerWithBranch 1`] = `
|
|
1220
|
+
" ◉ revision 1
|
|
1221
|
+
· comment ⚑ start
|
|
1222
|
+
· comment ← alt
|
|
1223
|
+
● revision 2 ← main
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
|
|
1229
|
+
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
|
|
1234
|
+
|
|
1235
|
+
Go Branch Label Fork Fork+share
|
|
1236
|
+
"
|
|
1237
|
+
`;
|
|
1238
|
+
|
|
1239
|
+
exports[`stories catalog TreePane/ResolvedForkOnly renders, snapshots, and carries its colors: TreePane/ResolvedForkOnly 1`] = `
|
|
1240
|
+
" ◉ revision 1
|
|
1241
|
+
· comment ⚑ start
|
|
1242
|
+
· comment ← alt
|
|
1243
|
+
● revision 2 ← main
|
|
1244
|
+
|
|
1245
|
+
|
|
1246
|
+
|
|
1247
|
+
|
|
1248
|
+
|
|
1249
|
+
|
|
1250
|
+
|
|
1251
|
+
|
|
1252
|
+
|
|
1253
|
+
|
|
1254
|
+
|
|
1255
|
+
Fork Fork+share
|
|
1256
|
+
"
|
|
1257
|
+
`;
|
|
1258
|
+
|
|
1311
1259
|
exports[`stories catalog WalkWizard/EndCard renders, snapshots, and carries its colors: WalkWizard/EndCard 1`] = `
|
|
1312
1260
|
"
|
|
1313
1261
|
|