@openagt/skill-branches 0.0.2 → 0.1.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 (46) hide show
  1. package/SKILL.md +6 -6
  2. package/dist/checkout.d.ts +6 -0
  3. package/dist/checkout.d.ts.map +1 -1
  4. package/dist/checkout.js +11 -2
  5. package/dist/checkout.js.map +1 -1
  6. package/dist/cleanup.d.ts +8 -0
  7. package/dist/cleanup.d.ts.map +1 -1
  8. package/dist/cleanup.js +19 -3
  9. package/dist/cleanup.js.map +1 -1
  10. package/dist/command-link.d.ts +37 -13
  11. package/dist/command-link.d.ts.map +1 -1
  12. package/dist/command-link.js +48 -26
  13. package/dist/command-link.js.map +1 -1
  14. package/dist/index.d.ts +4 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +4 -3
  17. package/dist/index.js.map +1 -1
  18. package/dist/skill-links.d.ts +7 -1
  19. package/dist/skill-links.d.ts.map +1 -1
  20. package/dist/skill-links.js +12 -3
  21. package/dist/skill-links.js.map +1 -1
  22. package/package.json +2 -2
  23. package/dist/file-branch.d.ts +0 -150
  24. package/dist/file-branch.d.ts.map +0 -1
  25. package/dist/file-branch.js +0 -371
  26. package/dist/file-branch.js.map +0 -1
  27. package/dist/git-exclude.d.ts +0 -17
  28. package/dist/git-exclude.d.ts.map +0 -1
  29. package/dist/git-exclude.js +0 -30
  30. package/dist/git-exclude.js.map +0 -1
  31. package/dist/git.d.ts +0 -73
  32. package/dist/git.d.ts.map +0 -1
  33. package/dist/git.js +0 -164
  34. package/dist/git.js.map +0 -1
  35. package/dist/merge-hold.d.ts +0 -20
  36. package/dist/merge-hold.d.ts.map +0 -1
  37. package/dist/merge-hold.js +0 -64
  38. package/dist/merge-hold.js.map +0 -1
  39. package/dist/merge-watch.d.ts +0 -68
  40. package/dist/merge-watch.d.ts.map +0 -1
  41. package/dist/merge-watch.js +0 -97
  42. package/dist/merge-watch.js.map +0 -1
  43. package/dist/publish.d.ts +0 -138
  44. package/dist/publish.d.ts.map +0 -1
  45. package/dist/publish.js +0 -215
  46. package/dist/publish.js.map +0 -1
@@ -1,150 +0,0 @@
1
- import { type GitRunner } from './git.js';
2
- /** The persistent checkout of `branch` under a project: `<repo>/.branches/<branch>`. */
3
- export declare function fileBranchPath(repo: string, branch: string): string;
4
- /** Injectable seams; production takes the defaults. */
5
- export interface FileBranchDeps {
6
- git?: GitRunner;
7
- log?: (message: string) => void;
8
- }
9
- /**
10
- * Make sure the branch and its persistent checkout exist. Idempotent and cheap when everything is
11
- * in place (one `git rev-parse` against the checkout); never throws — a project this cannot be
12
- * set up in reports why and is left alone.
13
- */
14
- export declare function ensureFileBranch(repo: string, branch: string, deps?: FileBranchDeps): Promise<{
15
- ok: boolean;
16
- error?: string;
17
- }>;
18
- /**
19
- * What one funneled write did. `changed: false` is the clean no-op (the op wrote nothing new).
20
- * A failure says whether the change still landed as a local commit (`committed` — the push is
21
- * what failed, and the next cycle carries it out) or nothing survived at all.
22
- */
23
- export type FileBranchWrite = {
24
- ok: true;
25
- changed: boolean;
26
- pushed: boolean;
27
- } | {
28
- ok: false;
29
- committed: boolean;
30
- error: string;
31
- };
32
- /** A writer's message: fixed, or resolved after the op ran (a batch only knows what it did then). */
33
- export type CommitMessage = string | (() => string);
34
- /**
35
- * Apply one change to the branch through its persistent checkout: sync with origin, run `op`
36
- * against the checkout, commit whatever it changed, push. The single funnel a long-lived
37
- * process's writes go through.
38
- *
39
- * `op` must be re-runnable: when the push loses a race with another writer, the cycle re-syncs
40
- * and runs it again against the fresher state rather than force-fitting a stale commit — the op
41
- * *is* the intent, the commit is just its serialization. Two attempts; a push that still fails
42
- * (the network, most likely) keeps the commit local and reports the error — the next cycle's sync
43
- * rebases it onto whatever origin has by then, and the next push carries it.
44
- *
45
- * Never throws: callers run on background ticks with nothing to catch it.
46
- */
47
- export declare function withFileBranch(repo: string, branch: string, message: CommitMessage, op: (dir: string) => Promise<void>, deps?: FileBranchDeps): Promise<FileBranchWrite>;
48
- /** How a pull went: converged with origin, or why it could not. */
49
- export type FileBranchSync = {
50
- ok: true;
51
- } | {
52
- ok: false;
53
- error: string;
54
- };
55
- /**
56
- * The eager pull: sync the persistent checkout with origin so this machine reads what other
57
- * machines and cloud sessions committed, without waiting for the next local write — and push
58
- * anything a failed cycle left stranded locally, via the same owed-push rule as the writer.
59
- * Ensures the checkout exists, so a fresh clone converges on its first tick. Never throws.
60
- *
61
- * Reports why it could not converge: a push origin rejects, or no origin to converge with at
62
- * all. The writer treats a remote-less repo as fine — the commit is safe locally — but a sync's
63
- * whole job is to meet the other machines, and a repo nothing can reach is an error state the
64
- * caller has to surface, not a mode this supports.
65
- */
66
- export declare function pullFileBranch(repo: string, branch: string, deps?: FileBranchDeps): Promise<FileBranchSync>;
67
- /**
68
- * The repository `cwd` belongs to: the directory holding the repo's real `.git`. From the main
69
- * checkout that is `cwd` itself; from an agent's worktree it is the repo the worktree was made
70
- * from — where the persistent checkout lives, and the address every funneled write goes to.
71
- * `undefined` outside any repo.
72
- */
73
- export declare function fileBranchRepo(cwd: string, git?: GitRunner): Promise<string | undefined>;
74
- /**
75
- * Read one file off the branch, from anywhere in the repo: the persistent checkout when this
76
- * `cwd`'s repo has one, else `git show` against the local branch (worktrees share the repo's
77
- * refs, so an agent's checkout reads the same files without holding any of them), else against
78
- * `origin/…`. `undefined` when the file exists in none of them. Never throws.
79
- */
80
- export declare function readBranchFile(cwd: string, branch: string, rel: string, opts?: {
81
- fresh?: boolean;
82
- }, deps?: FileBranchDeps): Promise<string | undefined>;
83
- /**
84
- * The entries of one directory on the branch, by name — a read off the ref, like
85
- * {@link readBranchFile}, for a reader that holds no checkout. `[]` for a directory the branch
86
- * does not have. Never throws.
87
- */
88
- export declare function listBranchDir(cwd: string, branch: string, dir: string, opts?: {
89
- fresh?: boolean;
90
- }, deps?: FileBranchDeps): Promise<string[]>;
91
- /** Reads off one ref of the branch, for a reader that opens many files: fetched once, up front. */
92
- export interface BranchReader {
93
- /** The ref every read goes to: origin's copy when the repo has a remote, else the local branch. */
94
- ref: string;
95
- /** One file's content, or `undefined` when the ref has no such file. */
96
- read: (rel: string) => Promise<string | undefined>;
97
- /** One directory's entries by name; `[]` when the ref has no such directory. */
98
- list: (dir: string) => Promise<string[]>;
99
- }
100
- /**
101
- * Open the branch for reading from any clone, holding no checkout: fetch origin's copy once and
102
- * read that (a one-shot reader — a command an agent runs — must see what other writers pushed,
103
- * its own detached write included, which the local ref never moves for), else the local branch
104
- * when there is no remote. Every read then goes to that one ref; nothing is fetched again.
105
- */
106
- export declare function openBranchReader(cwd: string, branch: string, deps?: FileBranchDeps): Promise<BranchReader>;
107
- /** What a detached write did, or why it could not: the repo has no remote to carry it. */
108
- export type DetachedWrite = {
109
- ok: true;
110
- changed: boolean;
111
- } | {
112
- ok: false;
113
- reason: 'no-remote';
114
- };
115
- /**
116
- * Apply one change to the branch as a one-shot remote writer, from any clone: fetch origin's
117
- * tip, check it out in a throwaway worktree, run `op` against it, commit, push straight to the
118
- * branch, remove the worktree. A push that loses a race re-fetches, resets to origin's tip and
119
- * re-runs the op, twice, the same intent rule as the funnel; a push that still fails throws with
120
- * git's reason.
121
- *
122
- * Never the persistent checkout: that is a long-lived process's, whose funnel sweeps its
123
- * checkout with `git add -A` and resets it on failure, so a second writer inside it would be
124
- * committed under the wrong message or wiped. The local branch ref is not moved either — the
125
- * persistent checkout, when there is one, converges on its own next pull.
126
- *
127
- * A branch origin does not have yet is born by the write itself, parentless. A repo with no
128
- * remote refuses: a change nothing can reach is the caller's error state, not a mode.
129
- */
130
- export declare function writeFileBranchDetached(cwd: string, branch: string, message: CommitMessage, op: (dir: string) => Promise<void>, deps?: FileBranchDeps): Promise<DetachedWrite>;
131
- /**
132
- * The file seams an operation inside a funneled write needs — read, write, delete and list plain
133
- * files under the directory the funnel hands it. Injectable so an operation is unit-testable off
134
- * disk and git; production takes the defaults. Parents are created on write because the
135
- * directory itself is not a given: retiring the last file removes it (git keeps no empty dirs),
136
- * and a branch is born without it.
137
- */
138
- export interface BranchFileFs {
139
- /** Read one file; rejects when it cannot — a caller reads the rejection as "absent". */
140
- read: (path: string) => Promise<string>;
141
- /** Write one file, creating parents. */
142
- write: (path: string, content: string) => Promise<void>;
143
- /** Delete one file. */
144
- remove: (path: string) => Promise<void>;
145
- /** The files under a directory, by filename; a missing directory reads as none. */
146
- list: (dir: string) => Promise<string[]>;
147
- }
148
- /** {@link BranchFileFs} over `node:fs/promises`. */
149
- export declare function nodeBranchFileFs(): BranchFileFs;
150
- //# sourceMappingURL=file-branch.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-branch.d.ts","sourceRoot":"","sources":["../src/file-branch.ts"],"names":[],"mappings":"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"}
@@ -1,371 +0,0 @@
1
- import { dirname, join } from 'node:path';
2
- import { BRANCHES_DIR } from './branch-names.js';
3
- import { nodeGitRunner } from './git.js';
4
- import { excludeFromGit } from './git-exclude.js';
5
- // A branch used as a file store: a branch of the project's repository that holds files nobody
6
- // edits in a working tree — the way `gh-pages` holds a site — read and written by programs, and
7
- // safe to push and pull eagerly because nothing on it is anyone's checkout. The caller names the
8
- // branch; this module knows git, not what the files mean.
9
- //
10
- // Two writers, one rule. A long-lived process (a daemon) keeps a persistent checkout of the
11
- // branch under `.branches/<branch>` and writes through {@link withFileBranch}: one serialized
12
- // cycle per branch — sync, apply, commit, push. A one-shot writer in any clone (a command an
13
- // agent runs) writes through {@link writeFileBranchDetached}: a throwaway worktree on origin's
14
- // tip, the same apply-commit-push, gone afterwards — it never touches the persistent checkout,
15
- // which is another process's. Both treat the change as an intent: when the push loses a race,
16
- // the cycle re-syncs and re-applies rather than force-fitting a stale commit.
17
- /** The persistent checkout of `branch` under a project: `<repo>/.branches/<branch>`. */
18
- export function fileBranchPath(repo, branch) {
19
- return join(repo, BRANCHES_DIR, branch);
20
- }
21
- /**
22
- * git's well-known empty tree, present in every repository without being written first. Committing
23
- * it is how a branch is born parentless with no working-tree gymnastics: `git commit-tree` +
24
- * `git branch` never touches any checkout, and no code commit is ever an ancestor of the history.
25
- */
26
- const EMPTY_TREE = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';
27
- function resolveDeps(deps) {
28
- return { git: deps.git ?? nodeGitRunner(), log: deps.log ?? (() => { }) };
29
- }
30
- /** Whether the repo has any remote to sync the branch with. */
31
- async function hasRemote(cwd, git) {
32
- try {
33
- return (await git(['remote'], cwd)).trim().length > 0;
34
- }
35
- catch {
36
- return false;
37
- }
38
- }
39
- /** Whether a ref exists locally. */
40
- async function refExists(cwd, ref, git) {
41
- return git(['rev-parse', '--verify', '--quiet', ref], cwd).then(() => true, () => false);
42
- }
43
- /** The message a failed git invocation carries, or the value itself as text. */
44
- function errorMessage(err) {
45
- return err instanceof Error ? err.message : String(err);
46
- }
47
- /**
48
- * One serialized cycle per branch of a project, so a writer and the eager pull can never
49
- * interleave: the promise chain is the lock, and every public entry point below joins it.
50
- */
51
- const chains = new Map();
52
- function serialize(repo, branch, task) {
53
- const key = `${repo}\0${branch}`;
54
- const next = (chains.get(key) ?? Promise.resolve()).then(task, task);
55
- chains.set(key, next.catch(() => { }));
56
- return next;
57
- }
58
- /** Make the branch exist locally: origin's copy when there is one, else born here, parentless. */
59
- async function ensureBranchRef(repo, branch, git) {
60
- if (await refExists(repo, `refs/heads/${branch}`, git))
61
- return;
62
- if (await hasRemote(repo, git))
63
- await git(['fetch', 'origin', branch], repo).catch(() => { });
64
- if (await refExists(repo, `refs/remotes/origin/${branch}`, git)) {
65
- await git(['branch', branch, `origin/${branch}`], repo);
66
- }
67
- else {
68
- const commit = (await git(['commit-tree', EMPTY_TREE, '-m', `create the ${branch} branch`], repo)).trim();
69
- await git(['branch', branch, commit], repo);
70
- }
71
- }
72
- /**
73
- * The unserialized ensure: branch and checkout. Split from {@link ensureFileBranch} so the
74
- * writer and the pull can run it inside the cycle they already hold the chain for.
75
- */
76
- async function ensureCore(repo, branch, r) {
77
- const path = fileBranchPath(repo, branch);
78
- // Already checked out on the right branch: done. The common case, taken on every tick.
79
- const onBranch = await r.git(['rev-parse', '--abbrev-ref', 'HEAD'], path).then(out => out.trim() === branch, () => false);
80
- if (onBranch)
81
- return;
82
- await ensureBranchRef(repo, branch, r.git);
83
- // A stale registration at this path (the dir was deleted by hand) blocks the add.
84
- await r.git(['worktree', 'prune'], repo).catch(() => { });
85
- await r.git(['worktree', 'add', path, branch], repo);
86
- // The checkout sits under `.branches/` like the agent checkouts, and is hidden the same way
87
- // (git's own exclude, no tracked file) — this may be the first checkout the project gets.
88
- await excludeFromGit(repo, '/' + BRANCHES_DIR, undefined, r.git).catch(() => { });
89
- }
90
- /**
91
- * Bring the checkout up to date with origin: fetch, then rebase whatever local commits exist (a
92
- * push that could not land earlier) onto origin's tip. A conflict resolves toward origin — the
93
- * writer re-applies the local intent afterwards, which is the "re-run on conflict" rule the whole
94
- * cycle is built on.
95
- */
96
- async function syncCore(repo, branch, r) {
97
- if (!(await hasRemote(repo, r.git)))
98
- return;
99
- const path = fileBranchPath(repo, branch);
100
- await r.git(['fetch', 'origin', branch], repo).catch(() => { });
101
- if (!(await refExists(repo, `refs/remotes/origin/${branch}`, r.git)))
102
- return;
103
- try {
104
- await r.git(['rebase', `origin/${branch}`], path);
105
- }
106
- catch {
107
- await r.git(['rebase', '--abort'], path).catch(() => { });
108
- await r.git(['reset', '--hard', `origin/${branch}`], path);
109
- }
110
- }
111
- /**
112
- * Make sure the branch and its persistent checkout exist. Idempotent and cheap when everything is
113
- * in place (one `git rev-parse` against the checkout); never throws — a project this cannot be
114
- * set up in reports why and is left alone.
115
- */
116
- export async function ensureFileBranch(repo, branch, deps = {}) {
117
- const r = resolveDeps(deps);
118
- return serialize(repo, branch, async () => {
119
- try {
120
- await ensureCore(repo, branch, r);
121
- return { ok: true };
122
- }
123
- catch (err) {
124
- return { ok: false, error: errorMessage(err) };
125
- }
126
- });
127
- }
128
- function resolveMessage(message) {
129
- return typeof message === 'function' ? message() : message;
130
- }
131
- /**
132
- * Apply one change to the branch through its persistent checkout: sync with origin, run `op`
133
- * against the checkout, commit whatever it changed, push. The single funnel a long-lived
134
- * process's writes go through.
135
- *
136
- * `op` must be re-runnable: when the push loses a race with another writer, the cycle re-syncs
137
- * and runs it again against the fresher state rather than force-fitting a stale commit — the op
138
- * *is* the intent, the commit is just its serialization. Two attempts; a push that still fails
139
- * (the network, most likely) keeps the commit local and reports the error — the next cycle's sync
140
- * rebases it onto whatever origin has by then, and the next push carries it.
141
- *
142
- * Never throws: callers run on background ticks with nothing to catch it.
143
- */
144
- export async function withFileBranch(repo, branch, message, op, deps = {}) {
145
- const r = resolveDeps(deps);
146
- const path = fileBranchPath(repo, branch);
147
- return serialize(repo, branch, async () => {
148
- try {
149
- await ensureCore(repo, branch, r);
150
- const remote = await hasRemote(repo, r.git);
151
- for (let attempt = 0;; attempt++) {
152
- await syncCore(repo, branch, r);
153
- // The tip before this op's commit: what a lost push winds back to before re-applying, so
154
- // the op's first serialization is dropped rather than rebased under its second run.
155
- const before = (await r.git(['rev-parse', 'HEAD'], path)).trim();
156
- await op(path);
157
- await r.git(['add', '-A'], path);
158
- const staged = (await r.git(['status', '--porcelain'], path)).trim();
159
- if (staged)
160
- await r.git(['commit', '-m', resolveMessage(message)], path);
161
- if (!remote)
162
- return { ok: true, changed: Boolean(staged), pushed: false };
163
- // Unpushed commits — this cycle's, or an earlier cycle's that the sync just rebased. The
164
- // push is owed whenever any exist, even when this op itself wrote nothing new.
165
- const ahead = (await refExists(repo, `refs/remotes/origin/${branch}`, r.git))
166
- ? (await r.git(['rev-list', '--count', `origin/${branch}..${branch}`], repo)).trim() !== '0'
167
- : true;
168
- if (!ahead)
169
- return { ok: true, changed: false, pushed: false };
170
- try {
171
- await r.git(['push', 'origin', `${branch}:${branch}`], path);
172
- return { ok: true, changed: Boolean(staged), pushed: true };
173
- }
174
- catch (err) {
175
- if (attempt >= 1)
176
- return { ok: false, committed: true, error: `the ${branch} branch could not be pushed: ${errorMessage(err)}` };
177
- if (staged)
178
- await r.git(['reset', '--hard', before], path);
179
- }
180
- }
181
- }
182
- catch (err) {
183
- // The op's half-written files must not ride a later, unrelated commit: put the checkout
184
- // back to its committed state before reporting.
185
- await r.git(['reset', '--hard'], path).catch(() => { });
186
- await r.git(['clean', '-fd'], path).catch(() => { });
187
- return { ok: false, committed: false, error: errorMessage(err) };
188
- }
189
- });
190
- }
191
- /**
192
- * The eager pull: sync the persistent checkout with origin so this machine reads what other
193
- * machines and cloud sessions committed, without waiting for the next local write — and push
194
- * anything a failed cycle left stranded locally, via the same owed-push rule as the writer.
195
- * Ensures the checkout exists, so a fresh clone converges on its first tick. Never throws.
196
- *
197
- * Reports why it could not converge: a push origin rejects, or no origin to converge with at
198
- * all. The writer treats a remote-less repo as fine — the commit is safe locally — but a sync's
199
- * whole job is to meet the other machines, and a repo nothing can reach is an error state the
200
- * caller has to surface, not a mode this supports.
201
- */
202
- export async function pullFileBranch(repo, branch, deps = {}) {
203
- const r = resolveDeps(deps);
204
- const result = await withFileBranch(repo, branch, 'sync', async () => { }, deps);
205
- const outcome = !result.ok
206
- ? { ok: false, error: result.error }
207
- : (await hasRemote(repo, r.git))
208
- ? { ok: true }
209
- : { ok: false, error: `the repository has no remote, so the ${branch} branch cannot be shared with other machines` };
210
- if (!outcome.ok)
211
- r.log(`[branches] ${branch}: ${outcome.error}`);
212
- return outcome;
213
- }
214
- /**
215
- * The repository `cwd` belongs to: the directory holding the repo's real `.git`. From the main
216
- * checkout that is `cwd` itself; from an agent's worktree it is the repo the worktree was made
217
- * from — where the persistent checkout lives, and the address every funneled write goes to.
218
- * `undefined` outside any repo.
219
- */
220
- export async function fileBranchRepo(cwd, git = nodeGitRunner()) {
221
- try {
222
- const gitDir = (await git(['rev-parse', '--path-format=absolute', '--git-common-dir'], cwd)).trim();
223
- return gitDir ? dirname(gitDir) : undefined;
224
- }
225
- catch {
226
- return undefined;
227
- }
228
- }
229
- /**
230
- * The refs a read looks at, in order. `fresh` fetches first and prefers origin's copy — for a
231
- * reader about to act on the files from a long-lived process, where the local ref may trail what
232
- * other writers pushed. Otherwise the local branch first, then origin's copy (a fresh clone that
233
- * fetched but never branched — the cloud case).
234
- */
235
- async function readRefs(repo, branch, fresh, git) {
236
- const remote = fresh && (await hasRemote(repo, git));
237
- if (remote)
238
- await git(['fetch', 'origin', branch], repo).catch(() => { });
239
- return remote ? [`origin/${branch}`, branch] : [branch, `origin/${branch}`];
240
- }
241
- /**
242
- * Read one file off the branch, from anywhere in the repo: the persistent checkout when this
243
- * `cwd`'s repo has one, else `git show` against the local branch (worktrees share the repo's
244
- * refs, so an agent's checkout reads the same files without holding any of them), else against
245
- * `origin/…`. `undefined` when the file exists in none of them. Never throws.
246
- */
247
- export async function readBranchFile(cwd, branch, rel, opts = {}, deps = {}) {
248
- const r = resolveDeps(deps);
249
- const repo = (await fileBranchRepo(cwd, r.git)) ?? cwd;
250
- if (!opts.fresh) {
251
- const path = fileBranchPath(repo, branch);
252
- const fromCheckout = await r.git(['rev-parse', '--abbrev-ref', 'HEAD'], path).then(out => out.trim() === branch, () => false);
253
- if (fromCheckout) {
254
- const { readFile } = await import('node:fs/promises');
255
- const md = await readFile(join(path, rel), 'utf8').catch(() => undefined);
256
- if (md !== undefined)
257
- return md;
258
- }
259
- }
260
- for (const ref of await readRefs(repo, branch, opts.fresh, r.git)) {
261
- const md = await r.git(['show', `${ref}:${rel}`], cwd).catch(() => undefined);
262
- if (md !== undefined)
263
- return md;
264
- }
265
- return undefined;
266
- }
267
- /**
268
- * The entries of one directory on the branch, by name — a read off the ref, like
269
- * {@link readBranchFile}, for a reader that holds no checkout. `[]` for a directory the branch
270
- * does not have. Never throws.
271
- */
272
- export async function listBranchDir(cwd, branch, dir, opts = {}, deps = {}) {
273
- const r = resolveDeps(deps);
274
- const repo = (await fileBranchRepo(cwd, r.git)) ?? cwd;
275
- for (const ref of await readRefs(repo, branch, opts.fresh, r.git)) {
276
- const out = await r.git(['ls-tree', '--name-only', `${ref}:${dir}`], cwd).catch(() => undefined);
277
- if (out !== undefined)
278
- return out.split('\n').map(line => line.trim()).filter(Boolean);
279
- }
280
- return [];
281
- }
282
- /**
283
- * Open the branch for reading from any clone, holding no checkout: fetch origin's copy once and
284
- * read that (a one-shot reader — a command an agent runs — must see what other writers pushed,
285
- * its own detached write included, which the local ref never moves for), else the local branch
286
- * when there is no remote. Every read then goes to that one ref; nothing is fetched again.
287
- */
288
- export async function openBranchReader(cwd, branch, deps = {}) {
289
- const r = resolveDeps(deps);
290
- const repo = (await fileBranchRepo(cwd, r.git)) ?? cwd;
291
- const [ref] = await readRefs(repo, branch, true, r.git);
292
- const at = (await refExists(repo, `refs/remotes/origin/${branch}`, r.git)) ? ref : branch;
293
- return {
294
- ref: at,
295
- read: rel => r.git(['show', `${at}:${rel}`], cwd).catch(() => undefined),
296
- list: dir => r
297
- .git(['ls-tree', '--name-only', `${at}:${dir}`], cwd)
298
- .then(out => out.split('\n').map(line => line.trim()).filter(Boolean))
299
- .catch(() => []),
300
- };
301
- }
302
- /**
303
- * Apply one change to the branch as a one-shot remote writer, from any clone: fetch origin's
304
- * tip, check it out in a throwaway worktree, run `op` against it, commit, push straight to the
305
- * branch, remove the worktree. A push that loses a race re-fetches, resets to origin's tip and
306
- * re-runs the op, twice, the same intent rule as the funnel; a push that still fails throws with
307
- * git's reason.
308
- *
309
- * Never the persistent checkout: that is a long-lived process's, whose funnel sweeps its
310
- * checkout with `git add -A` and resets it on failure, so a second writer inside it would be
311
- * committed under the wrong message or wiped. The local branch ref is not moved either — the
312
- * persistent checkout, when there is one, converges on its own next pull.
313
- *
314
- * A branch origin does not have yet is born by the write itself, parentless. A repo with no
315
- * remote refuses: a change nothing can reach is the caller's error state, not a mode.
316
- */
317
- export async function writeFileBranchDetached(cwd, branch, message, op, deps = {}) {
318
- const r = resolveDeps(deps);
319
- if (!(await hasRemote(cwd, r.git)))
320
- return { ok: false, reason: 'no-remote' };
321
- const { mkdtemp, rm } = await import('node:fs/promises');
322
- const { tmpdir } = await import('node:os');
323
- const dir = await mkdtemp(join(tmpdir(), `${branch}-write-`));
324
- // The remote's tip, or a parentless start for a branch origin does not have yet.
325
- const tip = async () => {
326
- await r.git(['fetch', 'origin', branch], cwd).catch(() => { });
327
- if (await refExists(cwd, `refs/remotes/origin/${branch}`, r.git))
328
- return `origin/${branch}`;
329
- return (await r.git(['commit-tree', EMPTY_TREE, '-m', `create the ${branch} branch`], cwd)).trim();
330
- };
331
- try {
332
- await r.git(['worktree', 'add', '--detach', dir, await tip()], cwd);
333
- for (let attempt = 0;; attempt++) {
334
- await op(dir);
335
- await r.git(['add', '-A'], dir);
336
- const staged = (await r.git(['status', '--porcelain'], dir)).trim();
337
- if (!staged)
338
- return { ok: true, changed: false };
339
- await r.git(['commit', '-m', resolveMessage(message)], dir);
340
- try {
341
- await r.git(['push', 'origin', `HEAD:refs/heads/${branch}`], dir);
342
- return { ok: true, changed: true };
343
- }
344
- catch (err) {
345
- if (attempt >= 1)
346
- throw err;
347
- await r.git(['reset', '--hard', await tip()], dir);
348
- }
349
- }
350
- }
351
- finally {
352
- await r.git(['worktree', 'remove', '--force', dir], cwd).catch(() => { });
353
- await r.git(['worktree', 'prune'], cwd).catch(() => { });
354
- await rm(dir, { recursive: true, force: true }).catch(() => { });
355
- }
356
- }
357
- /** {@link BranchFileFs} over `node:fs/promises`. */
358
- export function nodeBranchFileFs() {
359
- const fs = () => import('node:fs/promises');
360
- return {
361
- read: path => fs().then(f => f.readFile(path, 'utf8')),
362
- write: async (path, content) => {
363
- const f = await fs();
364
- await f.mkdir(dirname(path), { recursive: true });
365
- await f.writeFile(path, content, 'utf8');
366
- },
367
- remove: path => fs().then(f => f.rm(path)),
368
- list: dir => fs().then(f => f.readdir(dir)).catch(() => []),
369
- };
370
- }
371
- //# sourceMappingURL=file-branch.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-branch.js","sourceRoot":"","sources":["../src/file-branch.ts"],"names":[],"mappings":"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"}
@@ -1,17 +0,0 @@
1
- import { type GitRunner } from './git.js';
2
- /** The filesystem the exclude write needs; `node:fs/promises` in production. */
3
- export interface ExcludeFs {
4
- read(path: string): Promise<string>;
5
- /** Recursive mkdir. */
6
- mkdir(path: string): Promise<void>;
7
- append(path: string, contents: string): Promise<void>;
8
- }
9
- /**
10
- * Append one ignore rule to the repository's `info/exclude` — the ignore file that is git's, not
11
- * the project's, so no tracked file changes and no user ever sees a diff. The rule goes in the
12
- * *common* git dir because git resolves excludes from there; a per-worktree copy looks right and
13
- * is silently never read. One rule there covers every worktree of the repo. Idempotent. Throws on
14
- * a non-repo or unwritable git dir — callers decide whether that is fatal (so far, never).
15
- */
16
- export declare function excludeFromGit(repo: string, rule: string, fs?: ExcludeFs, git?: GitRunner): Promise<void>;
17
- //# sourceMappingURL=git-exclude.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"git-exclude.d.ts","sourceRoot":"","sources":["../src/git-exclude.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,UAAU,CAAA;AAExD,gFAAgF;AAChF,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACnC,uBAAuB;IACvB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACtD;AAWD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,EAAE,GAAE,SAA2B,EAC/B,GAAG,GAAE,SAA2B,GAC/B,OAAO,CAAC,IAAI,CAAC,CASf"}
@@ -1,30 +0,0 @@
1
- import { join, isAbsolute } from 'node:path';
2
- import { nodeGitRunner } from './git.js';
3
- function nodeExcludeFs() {
4
- const fs = () => import('node:fs/promises');
5
- return {
6
- read: path => fs().then(f => f.readFile(path, 'utf8')),
7
- mkdir: path => fs().then(f => f.mkdir(path, { recursive: true })).then(() => { }),
8
- append: (path, contents) => fs().then(f => f.appendFile(path, contents)),
9
- };
10
- }
11
- /**
12
- * Append one ignore rule to the repository's `info/exclude` — the ignore file that is git's, not
13
- * the project's, so no tracked file changes and no user ever sees a diff. The rule goes in the
14
- * *common* git dir because git resolves excludes from there; a per-worktree copy looks right and
15
- * is silently never read. One rule there covers every worktree of the repo. Idempotent. Throws on
16
- * a non-repo or unwritable git dir — callers decide whether that is fatal (so far, never).
17
- */
18
- export async function excludeFromGit(repo, rule, fs = nodeExcludeFs(), git = nodeGitRunner()) {
19
- const common = (await git(['rev-parse', '--git-common-dir'], repo)).trim();
20
- if (!common)
21
- return;
22
- const infoDir = join(isAbsolute(common) ? common : join(repo, common), 'info');
23
- const path = join(infoDir, 'exclude');
24
- const current = await fs.read(path).catch(() => '');
25
- if (current.split('\n').some(line => line.trim() === rule))
26
- return;
27
- await fs.mkdir(infoDir);
28
- await fs.append(path, (current && !current.endsWith('\n') ? '\n' : '') + rule + '\n');
29
- }
30
- //# sourceMappingURL=git-exclude.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"git-exclude.js","sourceRoot":"","sources":["../src/git-exclude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAkB,MAAM,UAAU,CAAA;AAUxD,SAAS,aAAa;IACpB,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAA;IAC3C,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtD,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QAChF,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;KACzE,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAY,EACZ,IAAY,EACZ,EAAE,GAAc,aAAa,EAAE,EAC/B,GAAG,GAAc,aAAa,EAAE;IAEhC,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,WAAW,EAAE,kBAAkB,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAC1E,IAAI,CAAC,MAAM;QAAE,OAAM;IACnB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAA;IAC9E,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IACrC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;IACnD,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC;QAAE,OAAM;IAClE,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACvB,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAA;AACvF,CAAC"}