@openagt/skill-branches 0.0.1

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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/SKILL.md +70 -0
  3. package/bin/branches +11 -0
  4. package/dist/bin-dir.d.ts +7 -0
  5. package/dist/bin-dir.d.ts.map +1 -0
  6. package/dist/bin-dir.js +8 -0
  7. package/dist/bin-dir.js.map +1 -0
  8. package/dist/branch-links.d.ts +37 -0
  9. package/dist/branch-links.d.ts.map +1 -0
  10. package/dist/branch-links.js +67 -0
  11. package/dist/branch-links.js.map +1 -0
  12. package/dist/branch-names.d.ts +41 -0
  13. package/dist/branch-names.d.ts.map +1 -0
  14. package/dist/branch-names.js +54 -0
  15. package/dist/branch-names.js.map +1 -0
  16. package/dist/branch-state.d.ts +68 -0
  17. package/dist/branch-state.d.ts.map +1 -0
  18. package/dist/branch-state.js +146 -0
  19. package/dist/branch-state.js.map +1 -0
  20. package/dist/checkout.d.ts +25 -0
  21. package/dist/checkout.d.ts.map +1 -0
  22. package/dist/checkout.js +37 -0
  23. package/dist/checkout.js.map +1 -0
  24. package/dist/cli.d.ts +36 -0
  25. package/dist/cli.d.ts.map +1 -0
  26. package/dist/cli.js +310 -0
  27. package/dist/cli.js.map +1 -0
  28. package/dist/command-link.d.ts +20 -0
  29. package/dist/command-link.d.ts.map +1 -0
  30. package/dist/command-link.js +37 -0
  31. package/dist/command-link.js.map +1 -0
  32. package/dist/file-branch.d.ts +150 -0
  33. package/dist/file-branch.d.ts.map +1 -0
  34. package/dist/file-branch.js +371 -0
  35. package/dist/file-branch.js.map +1 -0
  36. package/dist/git-exclude.d.ts +17 -0
  37. package/dist/git-exclude.d.ts.map +1 -0
  38. package/dist/git-exclude.js +30 -0
  39. package/dist/git-exclude.js.map +1 -0
  40. package/dist/git.d.ts +73 -0
  41. package/dist/git.d.ts.map +1 -0
  42. package/dist/git.js +164 -0
  43. package/dist/git.js.map +1 -0
  44. package/dist/index.d.ts +15 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +15 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/merge-hold.d.ts +20 -0
  49. package/dist/merge-hold.d.ts.map +1 -0
  50. package/dist/merge-hold.js +64 -0
  51. package/dist/merge-hold.js.map +1 -0
  52. package/dist/merge-watch.d.ts +68 -0
  53. package/dist/merge-watch.d.ts.map +1 -0
  54. package/dist/merge-watch.js +97 -0
  55. package/dist/merge-watch.js.map +1 -0
  56. package/dist/merge.d.ts +70 -0
  57. package/dist/merge.d.ts.map +1 -0
  58. package/dist/merge.js +55 -0
  59. package/dist/merge.js.map +1 -0
  60. package/dist/publish.d.ts +138 -0
  61. package/dist/publish.d.ts.map +1 -0
  62. package/dist/publish.js +215 -0
  63. package/dist/publish.js.map +1 -0
  64. package/dist/push.d.ts +53 -0
  65. package/dist/push.d.ts.map +1 -0
  66. package/dist/push.js +41 -0
  67. package/dist/push.js.map +1 -0
  68. package/dist/reclaim.d.ts +74 -0
  69. package/dist/reclaim.d.ts.map +1 -0
  70. package/dist/reclaim.js +87 -0
  71. package/dist/reclaim.js.map +1 -0
  72. package/dist/skill-links.d.ts +43 -0
  73. package/dist/skill-links.d.ts.map +1 -0
  74. package/dist/skill-links.js +50 -0
  75. package/dist/skill-links.js.map +1 -0
  76. package/dist/worktree-deps.d.ts +30 -0
  77. package/dist/worktree-deps.d.ts.map +1 -0
  78. package/dist/worktree-deps.js +128 -0
  79. package/dist/worktree-deps.js.map +1 -0
  80. package/dist/worktree.d.ts +220 -0
  81. package/dist/worktree.d.ts.map +1 -0
  82. package/dist/worktree.js +397 -0
  83. package/dist/worktree.js.map +1 -0
  84. package/package.json +53 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ import { type GitRunner } from '@gemstack/agent-data';
2
+ /**
3
+ * Publishing a checkout (#1774): the agent's own last step. Push the branch, open its pull
4
+ * request with the title and body the agent wrote, and arm the merge when the agent was told
5
+ * the work may land on its own. One rule before any of it: the tree is clean, since what is
6
+ * published is what is committed, and nothing is committed on the agent's behalf.
7
+ *
8
+ * A branch that already has an open pull request gets no second one: the request is reported as
9
+ * it is, and only the push and the merge arming happen.
10
+ *
11
+ * The merge is GitHub's auto-merge where the repository allows it. Where it does not, this tool's
12
+ * own watcher waits for the checks and merges (`merge-watch.ts`); where the request is already
13
+ * green, GitHub will not arm anything and the request is merged at once.
14
+ *
15
+ * A checkout under a hold (`merge-hold.ts`) arms nothing: the merge is recorded as wanted, the
16
+ * request's body says it is held, and the caller who put the hold releases it (`releaseMerge`).
17
+ *
18
+ * A person publishes a finished agent's work through the same door (#1774), by branch
19
+ * (`publishBranch`): the agent's checkout when one is still on the branch, under the same clean
20
+ * rule; else the branch itself, pushed when this machine has it, as it is when only the remote
21
+ * does. And lands its request (`mergePr`): a draft is marked ready first, then the merge is
22
+ * armed exactly as `--merge` arms it.
23
+ */
24
+ /** A `gh` runner: the standard output of one invocation; rejects with gh's own line on failure. */
25
+ export type GhRunner = (args: string[], cwd: string) => Promise<string>;
26
+ /** `gh` on PATH, one minute per call: these talk to the network. */
27
+ export declare function nodeGhRunner(): GhRunner;
28
+ export interface PublishOptions {
29
+ /** The pull request's title: one line naming what the change does. */
30
+ title: string;
31
+ /** The pull request's body: what changed and why. */
32
+ body?: string;
33
+ /** Arm the merge: the request lands on its own once its checks pass. */
34
+ merge?: boolean;
35
+ /** Start the merge watcher for a request (default {@link spawnMergeWatch}). For tests. */
36
+ watch?: (repo: string, number: number) => Promise<void>;
37
+ /** Open the request as a draft. Not with `merge`: a draft cannot be merged. */
38
+ draft?: boolean;
39
+ git?: GitRunner;
40
+ gh?: GhRunner;
41
+ }
42
+ /** Why a checkout was not published. */
43
+ export type PublishRefusal =
44
+ /** The directory is not a git worktree root. */
45
+ 'not-a-worktree'
46
+ /** The checkout is on no branch. */
47
+ | 'no-branch'
48
+ /** The tree holds uncommitted work: commit or delete it first. */
49
+ | 'dirty'
50
+ /** The branch could not be pushed. */
51
+ | 'push-failed'
52
+ /** The pull request could not be opened. */
53
+ | 'pr-failed';
54
+ export type PublishOutcome = {
55
+ ok: true;
56
+ branch: string;
57
+ pr: {
58
+ number: number;
59
+ url: string;
60
+ };
61
+ /** Whether the request was open already. */
62
+ existing: boolean;
63
+ /**
64
+ * How the merge arming went, when asked for: GitHub's auto-merge armed, merged at once (the
65
+ * request was already green), this tool's watcher started (the repository does not allow
66
+ * auto-merge), or held (the checkout is under a hold; armed at its release).
67
+ */
68
+ merge?: MergeArming | {
69
+ outcome: 'held';
70
+ };
71
+ } | {
72
+ ok: false;
73
+ reason: 'not-a-worktree';
74
+ }
75
+ /** The checkout is on no branch; or, published by name, neither this machine nor the remote has the branch. */
76
+ | {
77
+ ok: false;
78
+ reason: 'no-branch';
79
+ branch?: string;
80
+ } | {
81
+ ok: false;
82
+ reason: 'dirty' | 'push-failed' | 'pr-failed';
83
+ branch: string;
84
+ detail?: string;
85
+ };
86
+ /** How arming a merge went. */
87
+ export type MergeArming = {
88
+ outcome: 'auto-armed' | 'merged' | 'watching';
89
+ } | {
90
+ outcome: 'failed';
91
+ error: string;
92
+ };
93
+ export declare function publishCheckout(path: string, opts: PublishOptions): Promise<PublishOutcome>;
94
+ /**
95
+ * Publish a branch by name, from the project (#1774): the caller's form, for a person landing a
96
+ * finished agent's work. The checkout under `.branches/` that is on the branch, when one is,
97
+ * is published as the agent would publish it, its clean rule included. Without one, the branch
98
+ * itself: pushed when this machine has it; left as it is when only `origin` has it (a branch
99
+ * pushed from elsewhere, with nothing here to push). Neither: `no-branch`. No hold applies
100
+ * without a checkout: a hold is a checkout's.
101
+ */
102
+ export declare function publishBranch(repo: string, branch: string, opts: PublishOptions): Promise<PublishOutcome>;
103
+ /** What landing a request for a person did: armed as `--merge` arms, or why not. */
104
+ export type MergePrOutcome = MergeArming | {
105
+ outcome: 'not-open';
106
+ state: string;
107
+ };
108
+ export interface MergePrOptions {
109
+ gh?: GhRunner;
110
+ /** Start the merge watcher for a request (default {@link spawnMergeWatch}). For tests. */
111
+ watch?: (repo: string, number: number) => Promise<void>;
112
+ }
113
+ /**
114
+ * Land a pull request for a person (#1774): "it is good, land it". A draft is marked ready
115
+ * first, since asking for the merge is the statement that its review happened; then the merge
116
+ * is armed exactly as `publish --merge` arms it. A request that is not open is `not-open` with
117
+ * its state: already merged is an answer, not an action.
118
+ */
119
+ export declare function mergePr(repo: string, number: number, opts?: MergePrOptions): Promise<MergePrOutcome>;
120
+ export type ReleaseOutcome = MergeArming | {
121
+ outcome: 'not-held';
122
+ } | {
123
+ outcome: 'closed';
124
+ state: string;
125
+ };
126
+ export interface ReleaseOptions {
127
+ gh?: GhRunner;
128
+ /** Start the merge watcher for a request (default {@link spawnMergeWatch}). For tests. */
129
+ watch?: (repo: string, number: number) => Promise<void>;
130
+ }
131
+ /**
132
+ * Release a held merge: the request's merge is armed the way `publish --merge` arms it, and then
133
+ * the held note leaves its body. A request with no held merge is `not-held` (its publish never asked
134
+ * to merge), one no longer open is `closed` and its record dropped. A failed arming keeps the
135
+ * record and the note, so the release can be tried again and the request still says it is held.
136
+ */
137
+ export declare function releaseMerge(repo: string, number: number, opts?: ReleaseOptions): Promise<ReleaseOutcome>;
138
+ //# sourceMappingURL=publish.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,215 @@
1
+ import { nodeGitRunner, pushBranch } from '@gemstack/agent-data';
2
+ import { currentBranch, isWorktreeRoot, projectRoot, worktreeBranch, worktreeClean, worktreeDirEntries } from './worktree.js';
3
+ import { spawnMergeWatch } from './merge-watch.js';
4
+ import { dropHeldMerge, heldMergeRecorded, MERGE_HELD_NOTE, mergeHeld, recordHeldMerge, withHeldNote, withoutHeldNote } from './merge-hold.js';
5
+ /** `gh` on PATH, one minute per call: these talk to the network. */
6
+ export function nodeGhRunner() {
7
+ return async (args, cwd) => {
8
+ const { execFile } = await import('node:child_process');
9
+ return new Promise((resolve, reject) => {
10
+ execFile('gh', args, { cwd, timeout: 60_000 }, (err, stdout, stderr) => {
11
+ if (err)
12
+ reject(new Error(String(stderr).trim() || err.message));
13
+ else
14
+ resolve(String(stdout));
15
+ });
16
+ });
17
+ };
18
+ }
19
+ export async function publishCheckout(path, opts) {
20
+ const git = opts.git ?? nodeGitRunner();
21
+ const gh = opts.gh ?? nodeGhRunner();
22
+ if (!(await isWorktreeRoot(path, git)))
23
+ return { ok: false, reason: 'not-a-worktree' };
24
+ const branch = await currentBranch(path, git);
25
+ if (!branch)
26
+ return { ok: false, reason: 'no-branch' };
27
+ if (!(await worktreeClean(path, git).catch(() => false)))
28
+ return { ok: false, reason: 'dirty', branch };
29
+ const repo = await projectRoot(path, git);
30
+ const held = opts.merge === true && (await mergeHeld(path, git));
31
+ const pushed = await pushBranch(repo, branch, git);
32
+ if (!pushed.ok)
33
+ return { ok: false, reason: 'push-failed', branch, detail: pushed.error };
34
+ return openAndArm(repo, path, branch, opts, held, gh);
35
+ }
36
+ /**
37
+ * Publish a branch by name, from the project (#1774): the caller's form, for a person landing a
38
+ * finished agent's work. The checkout under `.branches/` that is on the branch, when one is,
39
+ * is published as the agent would publish it, its clean rule included. Without one, the branch
40
+ * itself: pushed when this machine has it; left as it is when only `origin` has it (a branch
41
+ * pushed from elsewhere, with nothing here to push). Neither: `no-branch`. No hold applies
42
+ * without a checkout: a hold is a checkout's.
43
+ */
44
+ export async function publishBranch(repo, branch, opts) {
45
+ const git = opts.git ?? nodeGitRunner();
46
+ const gh = opts.gh ?? nodeGhRunner();
47
+ for (const entry of await worktreeDirEntries(repo)) {
48
+ if ((await worktreeBranch(entry.path, git)) === branch)
49
+ return publishCheckout(entry.path, opts);
50
+ }
51
+ const local = await git(['rev-parse', '--verify', '--quiet', `refs/heads/${branch}`], repo).then(out => out.trim() !== '', () => false);
52
+ if (local) {
53
+ const pushed = await pushBranch(repo, branch, git);
54
+ if (!pushed.ok)
55
+ return { ok: false, reason: 'push-failed', branch, detail: pushed.error };
56
+ }
57
+ else {
58
+ const remote = await git(['rev-parse', '--verify', '--quiet', `refs/remotes/origin/${branch}`], repo).then(out => out.trim() !== '', () => false);
59
+ if (!remote)
60
+ return { ok: false, reason: 'no-branch', branch };
61
+ }
62
+ return openAndArm(repo, repo, branch, opts, false, gh);
63
+ }
64
+ /** The half after the push: the open request or a new one, then the merge arming, the hold honored. */
65
+ async function openAndArm(repo, cwd, branch, opts, held, gh) {
66
+ let pr = await openPr(cwd, branch, gh);
67
+ let existing = true;
68
+ if (!pr) {
69
+ existing = false;
70
+ try {
71
+ const args = ['pr', 'create', '--head', branch, '--title', opts.title, '--body', held ? withHeldNote(opts.body ?? '') : (opts.body ?? '')];
72
+ if (opts.draft && !opts.merge)
73
+ args.push('--draft');
74
+ const out = await gh(args, cwd);
75
+ const url = out.trim().split('\n').filter(Boolean).at(-1);
76
+ const number = prNumber(url);
77
+ pr = url && number !== undefined ? { number, url } : await openPr(cwd, branch, gh);
78
+ if (!pr)
79
+ return { ok: false, reason: 'pr-failed', branch, detail: 'gh printed no pull request URL' };
80
+ }
81
+ catch (err) {
82
+ return { ok: false, reason: 'pr-failed', branch, detail: errorMessage(err) };
83
+ }
84
+ }
85
+ const outcome = { ok: true, branch, pr, existing };
86
+ if (held) {
87
+ await recordHeldMerge(repo, pr.number);
88
+ if (existing)
89
+ await noteHeld(cwd, pr.number, gh);
90
+ outcome.merge = { outcome: 'held' };
91
+ }
92
+ else if (opts.merge) {
93
+ outcome.merge = await armMerge(repo, pr.number, gh, opts.watch ?? spawnMergeWatch);
94
+ }
95
+ return outcome;
96
+ }
97
+ /**
98
+ * Land a pull request for a person (#1774): "it is good, land it". A draft is marked ready
99
+ * first, since asking for the merge is the statement that its review happened; then the merge
100
+ * is armed exactly as `publish --merge` arms it. A request that is not open is `not-open` with
101
+ * its state: already merged is an answer, not an action.
102
+ */
103
+ export async function mergePr(repo, number, opts = {}) {
104
+ const gh = opts.gh ?? nodeGhRunner();
105
+ let view;
106
+ try {
107
+ view = JSON.parse(await gh(['pr', 'view', String(number), '--json', 'state,isDraft'], repo));
108
+ }
109
+ catch (err) {
110
+ return { outcome: 'failed', error: errorMessage(err) };
111
+ }
112
+ const state = typeof view.state === 'string' ? view.state : 'OPEN';
113
+ if (state !== 'OPEN')
114
+ return { outcome: 'not-open', state };
115
+ if (view.isDraft === true) {
116
+ try {
117
+ await gh(['pr', 'ready', String(number)], repo);
118
+ }
119
+ catch (err) {
120
+ return { outcome: 'failed', error: errorMessage(err) };
121
+ }
122
+ }
123
+ return armMerge(repo, number, gh, opts.watch ?? spawnMergeWatch);
124
+ }
125
+ /** An open request's body gains the held note, once. The note is for a person: an edit gh refuses never fails the publish. */
126
+ async function noteHeld(cwd, number, gh) {
127
+ try {
128
+ const body = String(JSON.parse(await gh(['pr', 'view', String(number), '--json', 'body'], cwd)).body ?? '');
129
+ if (!body.includes(MERGE_HELD_NOTE))
130
+ await gh(['pr', 'edit', String(number), '--body', withHeldNote(body)], cwd);
131
+ }
132
+ catch {
133
+ // The record is written; only the line for a person is missing.
134
+ }
135
+ }
136
+ /**
137
+ * Release a held merge: the request's merge is armed the way `publish --merge` arms it, and then
138
+ * the held note leaves its body. A request with no held merge is `not-held` (its publish never asked
139
+ * to merge), one no longer open is `closed` and its record dropped. A failed arming keeps the
140
+ * record and the note, so the release can be tried again and the request still says it is held.
141
+ */
142
+ export async function releaseMerge(repo, number, opts = {}) {
143
+ const gh = opts.gh ?? nodeGhRunner();
144
+ if (!(await heldMergeRecorded(repo, number)))
145
+ return { outcome: 'not-held' };
146
+ let view;
147
+ try {
148
+ view = JSON.parse(await gh(['pr', 'view', String(number), '--json', 'state,body'], repo));
149
+ }
150
+ catch (err) {
151
+ return { outcome: 'failed', error: errorMessage(err) };
152
+ }
153
+ const state = typeof view.state === 'string' ? view.state : 'OPEN';
154
+ if (state !== 'OPEN') {
155
+ await dropHeldMerge(repo, number);
156
+ return { outcome: 'closed', state };
157
+ }
158
+ const merge = await armMerge(repo, number, gh, opts.watch ?? spawnMergeWatch);
159
+ if (merge.outcome === 'failed')
160
+ return merge;
161
+ await dropHeldMerge(repo, number);
162
+ const body = typeof view.body === 'string' ? view.body : '';
163
+ if (body.includes(MERGE_HELD_NOTE))
164
+ await gh(['pr', 'edit', String(number), '--body', withoutHeldNote(body)], repo).catch(() => { });
165
+ return merge;
166
+ }
167
+ /**
168
+ * GitHub's words for "auto-merge is not allowed in this repository" and for "this request is
169
+ * already green, so there is nothing to wait for". Matched loosely on purpose: a rephrase on
170
+ * GitHub's side lands in `failed`, said out loud, never in a wrong merge.
171
+ */
172
+ const AUTO_MERGE_OFF = /auto[- ]?merge is not allowed/i;
173
+ const ALREADY_GREEN = /clean status/i;
174
+ async function armMerge(repo, number, gh, watch) {
175
+ try {
176
+ await gh(['pr', 'merge', String(number), '--squash', '--auto'], repo);
177
+ return { outcome: 'auto-armed' };
178
+ }
179
+ catch (err) {
180
+ const refusal = errorMessage(err);
181
+ try {
182
+ if (ALREADY_GREEN.test(refusal)) {
183
+ await gh(['pr', 'merge', String(number), '--squash'], repo);
184
+ return { outcome: 'merged' };
185
+ }
186
+ if (AUTO_MERGE_OFF.test(refusal)) {
187
+ await watch(repo, number);
188
+ return { outcome: 'watching' };
189
+ }
190
+ }
191
+ catch (next) {
192
+ return { outcome: 'failed', error: errorMessage(next) };
193
+ }
194
+ return { outcome: 'failed', error: refusal };
195
+ }
196
+ }
197
+ /** The open pull request of a branch, or `undefined`. */
198
+ async function openPr(cwd, branch, gh) {
199
+ try {
200
+ const list = JSON.parse(await gh(['pr', 'list', '--head', branch, '--state', 'open', '--limit', '1', '--json', 'number,url'], cwd));
201
+ const first = list[0];
202
+ return first && typeof first.number === 'number' && typeof first.url === 'string' ? { number: first.number, url: first.url } : undefined;
203
+ }
204
+ catch {
205
+ return undefined;
206
+ }
207
+ }
208
+ function prNumber(url) {
209
+ const match = url?.match(/\/pull\/(\d+)(?:$|[/?#])/);
210
+ return match ? Number(match[1]) : undefined;
211
+ }
212
+ function errorMessage(err) {
213
+ return err instanceof Error ? err.message : String(err);
214
+ }
215
+ //# sourceMappingURL=publish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.js","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"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"}
package/dist/push.d.ts ADDED
@@ -0,0 +1,53 @@
1
+ import { type GitRunner } from '@openagt/agent-data';
2
+ /**
3
+ * Pushing a branch to origin (#1820): the last git step of an agent's work, and the step before
4
+ * whatever the project's git host package does with the branch. This package knows git and nothing
5
+ * beyond it: the pull request, if the project has a git host, is another package's command.
6
+ *
7
+ * One rule before the push: the tree is clean, since what is pushed is what is committed, and
8
+ * nothing is committed on the agent's behalf.
9
+ *
10
+ * A person pushes a finished agent's branch through the same door, by name (`pushBranchByName`):
11
+ * the agent's checkout when one is still on the branch, under the same clean rule; else the
12
+ * branch itself, pushed when this machine has it, left as it is when only origin does.
13
+ */
14
+ /** Why a branch was not pushed. */
15
+ export type PushRefusal =
16
+ /** The directory is not a git worktree root. */
17
+ 'not-a-worktree'
18
+ /** The checkout is on no branch; or, by name, neither this machine nor origin has the branch. */
19
+ | 'no-branch'
20
+ /** The tree holds uncommitted work: commit or delete it first. */
21
+ | 'dirty'
22
+ /** The branch could not be pushed. */
23
+ | 'push-failed';
24
+ export type PushOutcome =
25
+ /** `pushed` is false when only origin had the branch: nothing here to push, and nothing missing there. */
26
+ {
27
+ ok: true;
28
+ branch: string;
29
+ pushed: boolean;
30
+ } | {
31
+ ok: false;
32
+ reason: 'not-a-worktree';
33
+ } | {
34
+ ok: false;
35
+ reason: 'no-branch';
36
+ branch?: string;
37
+ } | {
38
+ ok: false;
39
+ reason: 'dirty' | 'push-failed';
40
+ branch: string;
41
+ detail?: string;
42
+ };
43
+ /** Push the branch the checkout at `path` is on, once the checkout is clean. */
44
+ export declare function pushCheckout(path: string, git?: GitRunner): Promise<PushOutcome>;
45
+ /**
46
+ * Push a branch by name, from the project: the caller's form, for a person landing a finished
47
+ * agent's work. The checkout under `.branches/` that is on the branch, when one is, is pushed as
48
+ * the agent would push it, its clean rule included. Without one, the branch itself: pushed when
49
+ * this machine has it; left as it is when only `origin` has it (a branch pushed from elsewhere,
50
+ * with nothing here to push). Neither: `no-branch`.
51
+ */
52
+ export declare function pushBranchByName(repo: string, branch: string, git?: GitRunner): Promise<PushOutcome>;
53
+ //# sourceMappingURL=push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../src/push.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAG/E;;;;;;;;;;;GAWG;AAEH,mCAAmC;AACnC,MAAM,MAAM,WAAW;AACrB,gDAAgD;AAC9C,gBAAgB;AAClB,iGAAiG;GAC/F,WAAW;AACb,kEAAkE;GAChE,OAAO;AACT,sCAAsC;GACpC,aAAa,CAAA;AAEjB,MAAM,MAAM,WAAW;AACrB,0GAA0G;AACxG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC7C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,GACvC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,OAAO,GAAG,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEnF,gFAAgF;AAChF,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,SAA2B,GAAG,OAAO,CAAC,WAAW,CAAC,CAQvG;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,SAA2B,GAAG,OAAO,CAAC,WAAW,CAAC,CAa3H"}
package/dist/push.js ADDED
@@ -0,0 +1,41 @@
1
+ import { nodeGitRunner, pushBranch } from '@openagt/agent-data';
2
+ import { currentBranch, isWorktreeRoot, projectRoot, worktreeBranch, worktreeClean, worktreeDirEntries } from './worktree.js';
3
+ /** Push the branch the checkout at `path` is on, once the checkout is clean. */
4
+ export async function pushCheckout(path, git = nodeGitRunner()) {
5
+ if (!(await isWorktreeRoot(path, git)))
6
+ return { ok: false, reason: 'not-a-worktree' };
7
+ const branch = await currentBranch(path, git);
8
+ if (!branch)
9
+ return { ok: false, reason: 'no-branch' };
10
+ if (!(await worktreeClean(path, git).catch(() => false)))
11
+ return { ok: false, reason: 'dirty', branch };
12
+ const pushed = await pushBranch(await projectRoot(path, git), branch, git);
13
+ if (!pushed.ok)
14
+ return { ok: false, reason: 'push-failed', branch, detail: pushed.error };
15
+ return { ok: true, branch, pushed: true };
16
+ }
17
+ /**
18
+ * Push a branch by name, from the project: the caller's form, for a person landing a finished
19
+ * agent's work. The checkout under `.branches/` that is on the branch, when one is, is pushed as
20
+ * the agent would push it, its clean rule included. Without one, the branch itself: pushed when
21
+ * this machine has it; left as it is when only `origin` has it (a branch pushed from elsewhere,
22
+ * with nothing here to push). Neither: `no-branch`.
23
+ */
24
+ export async function pushBranchByName(repo, branch, git = nodeGitRunner()) {
25
+ for (const entry of await worktreeDirEntries(repo)) {
26
+ if ((await worktreeBranch(entry.path, git)) === branch)
27
+ return pushCheckout(entry.path, git);
28
+ }
29
+ const local = await git(['rev-parse', '--verify', '--quiet', `refs/heads/${branch}`], repo).then(out => out.trim() !== '', () => false);
30
+ if (local) {
31
+ const pushed = await pushBranch(repo, branch, git);
32
+ if (!pushed.ok)
33
+ return { ok: false, reason: 'push-failed', branch, detail: pushed.error };
34
+ return { ok: true, branch, pushed: true };
35
+ }
36
+ const remote = await git(['rev-parse', '--verify', '--quiet', `refs/remotes/origin/${branch}`], repo).then(out => out.trim() !== '', () => false);
37
+ if (!remote)
38
+ return { ok: false, reason: 'no-branch', branch };
39
+ return { ok: true, branch, pushed: false };
40
+ }
41
+ //# sourceMappingURL=push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.js","sourceRoot":"","sources":["../src/push.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { type GitRunner } from '@openagt/agent-data';
2
+ /**
3
+ * Reclaiming a checkout (#752/#737): the one implementation behind every surface that removes
4
+ * one — a scheduler at a run's end and in its sweep, a dashboard's Remove button, the CLI.
5
+ *
6
+ * **One rule: only what is committed may go.** The checkout is removed only once its branch holds
7
+ * everything in it: a clean tree. The branch stays on this machine, so nothing the agent made
8
+ * goes with the checkout. Nothing is committed on the agent's behalf (#1638): a checkout holding
9
+ * uncommitted work is kept, until a person commits or deletes it. And nothing is pushed:
10
+ * publishing a branch is a person's call, never a cleanup's.
11
+ *
12
+ * What the caller knows and git does not comes in as options: the branch the checkout was created
13
+ * on, and the commit its branch was made at.
14
+ */
15
+ export interface ReclaimOptions {
16
+ /**
17
+ * The branch the checkout was created on, when that may differ from the branch it ended on: an
18
+ * agent that branched away leaves it behind, and it goes with the checkout once the branch the
19
+ * checkout ended on contains it (#1657).
20
+ */
21
+ birthBranch?: string;
22
+ /**
23
+ * The commit the checkout's branch was made at, when the caller knows it. A branch with no
24
+ * commit past it holds nothing of its own.
25
+ */
26
+ from?: string;
27
+ /** Run once removal is decided, just before the checkout goes: stop what serves the tree. */
28
+ beforeRemove?: () => Promise<void>;
29
+ git?: GitRunner;
30
+ }
31
+ /** Why {@link reclaimWorktree} left a checkout where it was. */
32
+ export type ReclaimRefusal =
33
+ /** The directory is not a git worktree root: nothing was run in it (#1654). */
34
+ 'not-a-worktree'
35
+ /** The checkout is on no branch (detached). */
36
+ | 'no-branch'
37
+ /** The tree holds uncommitted work. */
38
+ | 'dirty';
39
+ export type ReclaimOutcome = {
40
+ ok: true;
41
+ /**
42
+ * Branches that went with the checkout: the branch it was on, when that held nothing of
43
+ * its own (#1650); the birth branch, when everything on it is in the branch that stays
44
+ * (#1657). Absent when nothing went.
45
+ */
46
+ branchesDeleted?: string[];
47
+ } | {
48
+ ok: false;
49
+ reason: 'not-a-worktree' | 'no-branch';
50
+ } | {
51
+ ok: false;
52
+ reason: 'dirty';
53
+ /** The branch the checkout is on. */
54
+ branch: string;
55
+ };
56
+ /**
57
+ * Remove one checkout under the rule above. Throws only for a git failure past the decision
58
+ * (the removal itself); every refusal is an outcome.
59
+ */
60
+ export declare function reclaimWorktree(repo: string, path: string, opts: ReclaimOptions): Promise<ReclaimOutcome>;
61
+ /**
62
+ * Discard one checkout (#1774): it goes whatever it holds, uncommitted work included. A person's
63
+ * call, for a run they are throwing away, where the rule above would keep the checkout. The
64
+ * branch and its commits stay: deleting a branch that may carry an open pull request is git's
65
+ * business, never this tool's on the way out of a checkout. Only the not-a-worktree guard
66
+ * applies: a directory git does not know as a worktree is left alone.
67
+ */
68
+ export declare function discardWorktree(repo: string, path: string, opts?: Pick<ReclaimOptions, 'git' | 'beforeRemove'>): Promise<{
69
+ ok: true;
70
+ } | {
71
+ ok: false;
72
+ reason: 'not-a-worktree';
73
+ }>;
74
+ //# sourceMappingURL=reclaim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reclaim.d.ts","sourceRoot":"","sources":["../src/reclaim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAWxF;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,6FAA6F;IAC7F,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAClC,GAAG,CAAC,EAAE,SAAS,CAAA;CAChB;AAED,gEAAgE;AAChE,MAAM,MAAM,cAAc;AACxB,+EAA+E;AAC7E,gBAAgB;AAClB,+CAA+C;GAC7C,WAAW;AACb,uCAAuC;GACrC,OAAO,CAAA;AAEX,MAAM,MAAM,cAAc,GACtB;IACE,EAAE,EAAE,IAAI,CAAA;IACR;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAC3B,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,GAAG,WAAW,CAAA;CAAE,GACrD;IACE,EAAE,EAAE,KAAK,CAAA;IACT,MAAM,EAAE,OAAO,CAAA;IACf,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAEL;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAiC/G;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,cAAc,CAAM,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAO1L"}