@webappwiz/arbor 0.0.30 → 0.0.32
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/README.md +2 -2
- package/add.d.ts +23 -0
- package/age.d.ts +2 -0
- package/arbor.d.ts +11 -0
- package/attachments.d.ts +36 -0
- package/claim.d.ts +11 -0
- package/config.d.ts +55 -0
- package/config.js +7 -0
- package/dev/assets.d.ts +11 -0
- package/dev.d.ts +48 -0
- package/escalate.d.ts +28 -0
- package/exit.d.ts +42 -0
- package/git.d.ts +82 -0
- package/index.d.ts +2 -0
- package/index.js +4763 -0
- package/journal.d.ts +29 -0
- package/list.d.ts +18 -0
- package/load-config.d.ts +15 -0
- package/log.d.ts +14 -0
- package/merge.d.ts +24 -0
- package/package.json +15 -32
- package/path.d.ts +13 -0
- package/plan.d.ts +83 -0
- package/remove.d.ts +19 -0
- package/repository.d.ts +25 -0
- package/retry.d.ts +17 -0
- package/shell.d.ts +17 -0
- package/show.d.ts +53 -0
- package/snapshot.d.ts +36 -0
- package/table.d.ts +5 -0
- package/todo.d.ts +202 -0
- package/todos.d.ts +75 -0
- package/wait.d.ts +22 -0
- package/worktree-service.d.ts +51 -0
- package/worktree.d.ts +95 -0
- package/AGENTS.md +0 -7
- package/add.test.ts +0 -125
- package/add.ts +0 -192
- package/age.ts +0 -11
- package/arbor.test.ts +0 -145
- package/arbor.ts +0 -429
- package/assets.d.ts +0 -9
- package/attachments.ts +0 -87
- package/build.ts +0 -98
- package/claim.test.ts +0 -89
- package/claim.ts +0 -73
- package/components.json +0 -21
- package/config.ts +0 -58
- package/dev/api.ts +0 -120
- package/dev/app.test.tsx +0 -645
- package/dev/app.tsx +0 -80
- package/dev/assets.ts +0 -16
- package/dev/build/main.txt +0 -68
- package/dev/build/shell.txt +0 -21
- package/dev/build/styles.txt +0 -2263
- package/dev/components/ui/badge.tsx +0 -51
- package/dev/components/ui/button.tsx +0 -57
- package/dev/components/ui/dialog.tsx +0 -154
- package/dev/components/ui/empty.tsx +0 -100
- package/dev/components/ui/input-group.tsx +0 -155
- package/dev/components/ui/input.tsx +0 -19
- package/dev/components/ui/progress.tsx +0 -80
- package/dev/components/ui/textarea.tsx +0 -17
- package/dev/components/ui/toast.tsx +0 -227
- package/dev/feed.ts +0 -69
- package/dev/files.tsx +0 -191
- package/dev/index.html +0 -21
- package/dev/lib/utils.ts +0 -7
- package/dev/main.tsx +0 -22
- package/dev/markdown.test.tsx +0 -133
- package/dev/markdown.tsx +0 -124
- package/dev/mentions.tsx +0 -319
- package/dev/shadcn.css +0 -649
- package/dev/styles.css +0 -107
- package/dev/tags.tsx +0 -44
- package/dev/tasks.tsx +0 -151
- package/dev/todos.tsx +0 -759
- package/dev.test.ts +0 -439
- package/dev.ts +0 -386
- package/e2e.test.ts +0 -256
- package/escalate.test.ts +0 -76
- package/escalate.ts +0 -112
- package/exit.test.ts +0 -71
- package/exit.ts +0 -74
- package/git.ts +0 -294
- package/index.ts +0 -9
- package/journal.ts +0 -89
- package/list.test.ts +0 -82
- package/list.ts +0 -137
- package/load-config.test.ts +0 -121
- package/load-config.ts +0 -62
- package/log.test.ts +0 -65
- package/log.ts +0 -40
- package/merge.test.ts +0 -332
- package/merge.ts +0 -283
- package/path.test.ts +0 -35
- package/path.ts +0 -38
- package/plan.test.ts +0 -318
- package/plan.ts +0 -302
- package/progress.test.ts +0 -54
- package/progress.ts +0 -31
- package/remove.test.ts +0 -68
- package/remove.ts +0 -88
- package/repository.ts +0 -83
- package/retry.test.ts +0 -43
- package/retry.ts +0 -48
- package/shell.ts +0 -44
- package/show.test.ts +0 -91
- package/show.ts +0 -151
- package/snapshot.test.ts +0 -33
- package/snapshot.ts +0 -84
- package/table.ts +0 -20
- package/testing.ts +0 -229
- package/todo.test.ts +0 -490
- package/todo.ts +0 -834
- package/wait.test.ts +0 -61
- package/wait.ts +0 -77
- package/worktree-service.test.ts +0 -158
- package/worktree-service.ts +0 -193
- package/worktree.ts +0 -239
package/worktree.ts
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import type { GitResult } from "./git";
|
|
2
|
-
import type { WorktreeService } from "./worktree-service";
|
|
3
|
-
|
|
4
|
-
/** The status a task's own record carries. */
|
|
5
|
-
export type RecordStatus = "working" | "merging" | "escalated";
|
|
6
|
-
|
|
7
|
-
/** What a task's record stores about who is driving it. */
|
|
8
|
-
export interface LeaseState {
|
|
9
|
-
pid: number;
|
|
10
|
-
hostname: string;
|
|
11
|
-
heartbeatAt: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface Escalation {
|
|
15
|
-
reason: string;
|
|
16
|
-
at: string;
|
|
17
|
-
/**
|
|
18
|
-
* For a task handed over to be approved rather than to answer questions,
|
|
19
|
-
* the question in its plan that asks for the approval, `4`.
|
|
20
|
-
*/
|
|
21
|
-
review?: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface TaskState {
|
|
25
|
-
task: string;
|
|
26
|
-
branch: string;
|
|
27
|
-
worktree: string;
|
|
28
|
-
/** The branch this task lands on. Absent in old records: trunk. */
|
|
29
|
-
base?: string;
|
|
30
|
-
status: RecordStatus;
|
|
31
|
-
lease: LeaseState | null;
|
|
32
|
-
mergeAttempts: number;
|
|
33
|
-
createdAt: string;
|
|
34
|
-
updatedAt: string;
|
|
35
|
-
escalations?: Escalation[];
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Everything a name can turn out to be. The record's own status when the
|
|
40
|
-
* task is intact, and otherwise the way in which it is not.
|
|
41
|
-
*/
|
|
42
|
-
export type WorktreeStatus =
|
|
43
|
-
| RecordStatus
|
|
44
|
-
| "absent" // nothing under this name, and no memory of one
|
|
45
|
-
| "removed" // discarded earlier; still remembered
|
|
46
|
-
| "orphaned" // a record whose directory is gone
|
|
47
|
-
| "stray" // a leftover branch, with no directory or record
|
|
48
|
-
| "unrecorded" // a directory with no record
|
|
49
|
-
| "unknown"; // a record that would not parse
|
|
50
|
-
|
|
51
|
-
/** What the service found on disk. */
|
|
52
|
-
export interface WorktreeSnapshot {
|
|
53
|
-
task: string;
|
|
54
|
-
branch: string;
|
|
55
|
-
path: string;
|
|
56
|
-
state: TaskState | null;
|
|
57
|
-
exists: boolean;
|
|
58
|
-
hasBranch: boolean;
|
|
59
|
-
removedAt: string | null;
|
|
60
|
-
corrupt: boolean;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* One task, whether or not it is still there. Commands ask the service for
|
|
65
|
-
* one of these and read its status rather than assembling the same handful of
|
|
66
|
-
* existence checks themselves.
|
|
67
|
-
*/
|
|
68
|
-
export class Worktree {
|
|
69
|
-
// scry-ignore classes-over-function-exports: the service is what hands out Worktrees, so the two are one design in two files, and an interface here would have one implementation and still expose the service's Git
|
|
70
|
-
constructor(
|
|
71
|
-
private readonly service: WorktreeService,
|
|
72
|
-
private readonly snapshot: WorktreeSnapshot,
|
|
73
|
-
) {}
|
|
74
|
-
|
|
75
|
-
get task(): string {
|
|
76
|
-
return this.snapshot.task;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
get branch(): string {
|
|
80
|
-
return this.snapshot.branch;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** Where this task's work lands: its recorded base branch, else trunk. */
|
|
84
|
-
get base(): string {
|
|
85
|
-
return this.snapshot.state?.base ?? this.service.trunk;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
get path(): string {
|
|
89
|
-
return this.snapshot.path;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
get state(): TaskState | null {
|
|
93
|
-
return this.snapshot.state;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
get lease(): LeaseState | null {
|
|
97
|
-
return this.snapshot.state?.lease ?? null;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
get leaseHeld(): boolean {
|
|
101
|
-
// The pid check matters because every arbor command is its own short-lived
|
|
102
|
-
// process: without it a tree would stay locked for the whole staleness
|
|
103
|
-
// window after a command that merely finished, and `add` would block the
|
|
104
|
-
// `merge` that follows it.
|
|
105
|
-
const { lease } = this;
|
|
106
|
-
const { ps, config } = this.service;
|
|
107
|
-
if (!lease) {
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
if (Date.now() - Date.parse(lease.heartbeatAt) >= config.leaseStalenessMs) {
|
|
111
|
-
return false;
|
|
112
|
-
}
|
|
113
|
-
return lease.hostname === ps.hostname ? ps.alive(lease.pid) : true;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
get leaseStatus(): "held" | "stale" | "none" {
|
|
117
|
-
return !this.lease ? "none" : this.leaseHeld ? "held" : "stale";
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
get leaseOurs(): boolean {
|
|
121
|
-
const { ps } = this.service;
|
|
122
|
-
return this.lease?.pid === ps.pid && this.lease.hostname === ps.hostname;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
get leaseHeldByOther(): boolean {
|
|
126
|
-
return this.leaseHeld && !this.leaseOurs;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
get mergeAttempts(): number {
|
|
130
|
-
return this.snapshot.state?.mergeAttempts ?? 0;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
get exists(): boolean {
|
|
134
|
-
return this.snapshot.exists;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
get hasBranch(): boolean {
|
|
138
|
-
return this.snapshot.hasBranch;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
get removedAt(): string | null {
|
|
142
|
-
return this.snapshot.removedAt;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
get status(): WorktreeStatus {
|
|
146
|
-
const { state, exists, hasBranch, removedAt, corrupt } = this.snapshot;
|
|
147
|
-
if (corrupt) {
|
|
148
|
-
return "unknown";
|
|
149
|
-
}
|
|
150
|
-
if (state) {
|
|
151
|
-
return exists ? state.status : "orphaned";
|
|
152
|
-
}
|
|
153
|
-
if (exists) {
|
|
154
|
-
return "unrecorded";
|
|
155
|
-
}
|
|
156
|
-
if (hasBranch) {
|
|
157
|
-
return "stray";
|
|
158
|
-
}
|
|
159
|
-
return removedAt ? "removed" : "absent";
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
get gone(): boolean {
|
|
163
|
-
return this.status === "absent" || this.status === "removed";
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Merges changes into the record and writes it. Works on a name that has no
|
|
168
|
-
* record yet, which is how `add` writes the first one and how `claim`
|
|
169
|
-
* rebuilds one from a worktree found on disk.
|
|
170
|
-
*/
|
|
171
|
-
async save(changes: Partial<TaskState> = {}): Promise<Worktree> {
|
|
172
|
-
const now = new Date().toISOString();
|
|
173
|
-
const state: TaskState = {
|
|
174
|
-
task: this.task,
|
|
175
|
-
branch: this.branch,
|
|
176
|
-
worktree: this.path,
|
|
177
|
-
status: "working",
|
|
178
|
-
lease: null,
|
|
179
|
-
mergeAttempts: 0,
|
|
180
|
-
createdAt: now,
|
|
181
|
-
...(this.snapshot.state ?? {}),
|
|
182
|
-
...changes,
|
|
183
|
-
updatedAt: now,
|
|
184
|
-
};
|
|
185
|
-
await this.service.saveRecord(state);
|
|
186
|
-
return new Worktree(this.service, {
|
|
187
|
-
...this.snapshot,
|
|
188
|
-
state,
|
|
189
|
-
corrupt: false,
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
take(changes: Partial<TaskState> = {}): Promise<Worktree> {
|
|
194
|
-
const { ps } = this.service;
|
|
195
|
-
return this.save({
|
|
196
|
-
...changes,
|
|
197
|
-
lease: {
|
|
198
|
-
pid: ps.pid,
|
|
199
|
-
hostname: ps.hostname,
|
|
200
|
-
heartbeatAt: new Date().toISOString(),
|
|
201
|
-
},
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/** Re-reads from disk. `merge` needs this: the record is the truth. */
|
|
206
|
-
reload(): Promise<Worktree> {
|
|
207
|
-
return this.service.find(this.task);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/** Removes the directory, the branch, and the record; remembers the name. */
|
|
211
|
-
discard(): Promise<GitResult> {
|
|
212
|
-
return this.service.discard(this);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
commitsAhead(): Promise<number | null> {
|
|
216
|
-
return this.service.git.commitsAhead(this.base, this.branch);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
diffStat(): Promise<{ added: number; removed: number } | null> {
|
|
220
|
-
return this.service.git.diffStat(this.base, this.branch);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/** Committed and uncommitted paths this task touches; null without a branch. */
|
|
224
|
-
changedFiles(): Promise<string[] | null> {
|
|
225
|
-
return this.service.git.changedFiles(
|
|
226
|
-
this.base,
|
|
227
|
-
this.branch,
|
|
228
|
-
this.exists ? this.path : null,
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
uncommitted(): Promise<string[]> {
|
|
233
|
-
return this.service.git.porcelain(this.path);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
interruptedOps(): Promise<string[]> {
|
|
237
|
-
return this.service.git.interruptedOps(this.path);
|
|
238
|
-
}
|
|
239
|
-
}
|