@nickmeriano/task 0.7.1 → 0.9.0

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 (128) hide show
  1. package/README.md +73 -25
  2. package/dist/asks.test.d.ts +17 -0
  3. package/dist/asks.test.d.ts.map +1 -0
  4. package/dist/asks.test.js +278 -0
  5. package/dist/asks.test.js.map +1 -0
  6. package/dist/check.d.ts +43 -0
  7. package/dist/check.d.ts.map +1 -0
  8. package/dist/check.js +403 -0
  9. package/dist/check.js.map +1 -0
  10. package/dist/check.test.d.ts +9 -0
  11. package/dist/check.test.d.ts.map +1 -0
  12. package/dist/check.test.js +248 -0
  13. package/dist/check.test.js.map +1 -0
  14. package/dist/claim-io.d.ts +73 -0
  15. package/dist/claim-io.d.ts.map +1 -0
  16. package/dist/claim-io.js +344 -0
  17. package/dist/claim-io.js.map +1 -0
  18. package/dist/claim.d.ts +61 -9
  19. package/dist/claim.d.ts.map +1 -1
  20. package/dist/claim.js +197 -67
  21. package/dist/claim.js.map +1 -1
  22. package/dist/claim.test.d.ts +2 -2
  23. package/dist/claim.test.js +235 -64
  24. package/dist/claim.test.js.map +1 -1
  25. package/dist/cli.js +724 -136
  26. package/dist/cli.js.map +1 -1
  27. package/dist/file-store.d.ts +110 -38
  28. package/dist/file-store.d.ts.map +1 -1
  29. package/dist/file-store.js +514 -238
  30. package/dist/file-store.js.map +1 -1
  31. package/dist/git-serve.d.ts +183 -0
  32. package/dist/git-serve.d.ts.map +1 -0
  33. package/dist/git-serve.js +503 -0
  34. package/dist/git-serve.js.map +1 -0
  35. package/dist/git-serve.test.d.ts +16 -0
  36. package/dist/git-serve.test.d.ts.map +1 -0
  37. package/dist/git-serve.test.js +183 -0
  38. package/dist/git-serve.test.js.map +1 -0
  39. package/dist/git.d.ts +65 -0
  40. package/dist/git.d.ts.map +1 -0
  41. package/dist/git.js +114 -0
  42. package/dist/git.js.map +1 -0
  43. package/dist/id.d.ts +39 -0
  44. package/dist/id.d.ts.map +1 -0
  45. package/dist/id.js +67 -0
  46. package/dist/id.js.map +1 -0
  47. package/dist/inbox.d.ts +41 -0
  48. package/dist/inbox.d.ts.map +1 -0
  49. package/dist/inbox.js +56 -0
  50. package/dist/inbox.js.map +1 -0
  51. package/dist/index.d.ts +5 -3
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +5 -3
  54. package/dist/index.js.map +1 -1
  55. package/dist/overview.d.ts +52 -0
  56. package/dist/overview.d.ts.map +1 -0
  57. package/dist/overview.js +61 -0
  58. package/dist/overview.js.map +1 -0
  59. package/dist/overview.test.d.ts +8 -0
  60. package/dist/overview.test.d.ts.map +1 -0
  61. package/dist/overview.test.js +48 -0
  62. package/dist/overview.test.js.map +1 -0
  63. package/dist/promote.test.d.ts +15 -0
  64. package/dist/promote.test.d.ts.map +1 -0
  65. package/dist/promote.test.js +104 -0
  66. package/dist/promote.test.js.map +1 -0
  67. package/dist/publish.d.ts +2 -17
  68. package/dist/publish.d.ts.map +1 -1
  69. package/dist/publish.js +4 -49
  70. package/dist/publish.js.map +1 -1
  71. package/dist/search.d.ts +34 -0
  72. package/dist/search.d.ts.map +1 -0
  73. package/dist/search.js +79 -0
  74. package/dist/search.js.map +1 -0
  75. package/dist/search.test.d.ts +2 -0
  76. package/dist/search.test.d.ts.map +1 -0
  77. package/dist/search.test.js +53 -0
  78. package/dist/search.test.js.map +1 -0
  79. package/dist/server.d.ts.map +1 -1
  80. package/dist/server.js +228 -23
  81. package/dist/server.js.map +1 -1
  82. package/dist/store.d.ts +43 -63
  83. package/dist/store.d.ts.map +1 -1
  84. package/dist/store.js +0 -368
  85. package/dist/store.js.map +1 -1
  86. package/dist/store.test.d.ts +1 -2
  87. package/dist/store.test.d.ts.map +1 -1
  88. package/dist/store.test.js +148 -106
  89. package/dist/store.test.js.map +1 -1
  90. package/dist/ticket-doc.d.ts +74 -5
  91. package/dist/ticket-doc.d.ts.map +1 -1
  92. package/dist/ticket-doc.js +229 -15
  93. package/dist/ticket-doc.js.map +1 -1
  94. package/dist/types.d.ts +115 -28
  95. package/dist/types.d.ts.map +1 -1
  96. package/dist/types.js.map +1 -1
  97. package/package.json +1 -1
  98. package/skill/SKILL.md +153 -40
  99. package/src/asks.test.ts +355 -0
  100. package/src/check.test.ts +328 -0
  101. package/src/check.ts +497 -0
  102. package/src/claim-io.ts +401 -0
  103. package/src/claim.test.ts +301 -71
  104. package/src/claim.ts +238 -81
  105. package/src/cli.ts +740 -131
  106. package/src/file-store.ts +572 -254
  107. package/src/git-serve.test.ts +240 -0
  108. package/src/git-serve.ts +595 -0
  109. package/src/git.ts +141 -0
  110. package/src/id.ts +68 -0
  111. package/src/inbox.ts +77 -0
  112. package/src/index.ts +4 -2
  113. package/src/overview.test.ts +52 -0
  114. package/src/overview.ts +105 -0
  115. package/src/promote.test.ts +143 -0
  116. package/src/publish.ts +6 -53
  117. package/src/search.test.ts +64 -0
  118. package/src/search.ts +105 -0
  119. package/src/server.ts +232 -21
  120. package/src/store.test.ts +166 -116
  121. package/src/store.ts +46 -444
  122. package/src/ticket-doc.ts +284 -21
  123. package/src/types.ts +120 -28
  124. package/ui/dist/assets/index-BjsorZOU.js +229 -0
  125. package/ui/dist/assets/index-CoKCUYic.css +1 -0
  126. package/ui/dist/index.html +2 -2
  127. package/ui/dist/assets/index-COunM-QN.css +0 -1
  128. package/ui/dist/assets/index-D4homvrQ.js +0 -229
@@ -0,0 +1,503 @@
1
+ /**
2
+ * The git surface behind `task serve`'s `/api/git/*` (TAS-42): status,
3
+ * branches, board-scoped commits, checkout, PRs, and claim release — the
4
+ * conductor-style layer that makes board edits (which are plain working-tree
5
+ * writes) visible and committable from the UI.
6
+ *
7
+ * Everything here is deliberately scoped to board files. There is no shadow
8
+ * branch and no auto-commit: edits keep landing in the working tree, and
9
+ * isolation comes from pathspec-scoped commits — `git add`/`git commit`
10
+ * limited to each board's `.task` directory commits board changes cleanly
11
+ * even when the rest of the tree is dirty.
12
+ *
13
+ * The whole surface degrades to absent: no git, no origin, or an unreadable
14
+ * repo means `capability()` returns null, `/api/project` omits its `git`
15
+ * block, and the UI renders nothing — the same self-hiding rule the hosted
16
+ * branch switcher follows. Spawns are the shared non-interactive, bounded
17
+ * ones from git.ts; like the rest of the serve path, a request must fail
18
+ * fast rather than wait on a human.
19
+ */
20
+ import { spawnSync } from "node:child_process";
21
+ import { relative, sep } from "node:path";
22
+ import { claimBranch, claimNamespace, release } from "./claim.js";
23
+ import { remoteClaimTips, syncClaimRefs } from "./claim-io.js";
24
+ import { GIT_NETWORK_TIMEOUT_MS, defaultBase, detectRepo, git, gitOut, runGit } from "./git.js";
25
+ /** A failure the route turns into a JSON error with this status. */
26
+ export class GitServeError extends Error {
27
+ status;
28
+ constructor(message, status = 400) {
29
+ super(message);
30
+ this.status = status;
31
+ }
32
+ }
33
+ /** The gh-less PR fallback: GitHub's compare page, ready to open in a tab. */
34
+ export function compareUrl(repo, base, branch) {
35
+ return `https://github.com/${repo.owner}/${repo.repo}/compare/${encodeURIComponent(base)}...${encodeURIComponent(branch)}?expand=1`;
36
+ }
37
+ const GH_ENV = { GH_PROMPT_DISABLED: "1", GH_NO_UPDATE_NOTIFIER: "1", GH_PAGER: "cat" };
38
+ const CLAIMS_TTL_MS = 30_000;
39
+ const PR_TTL_MS = 30_000;
40
+ function runGh(cwd, args) {
41
+ const result = spawnSync("gh", args, {
42
+ cwd,
43
+ encoding: "utf8",
44
+ timeout: GIT_NETWORK_TIMEOUT_MS,
45
+ env: { ...process.env, ...GH_ENV },
46
+ });
47
+ if (result.error)
48
+ return { status: 1, stdout: "", stderr: result.error.message };
49
+ return {
50
+ status: result.status ?? 1,
51
+ stdout: (result.stdout ?? "").trim(),
52
+ stderr: (result.stderr ?? "").trim(),
53
+ };
54
+ }
55
+ export class GitServe {
56
+ root;
57
+ boards;
58
+ ghChecked = null;
59
+ claimsCache = null;
60
+ prCache = new Map();
61
+ constructor(serveRoot, boards) {
62
+ this.root = serveRoot;
63
+ this.boards = boards;
64
+ }
65
+ /** The repo toplevel, or null when this isn't a git checkout at all. */
66
+ toplevel() {
67
+ return gitOut(this.root, "rev-parse", "--show-toplevel");
68
+ }
69
+ /** Where the actual git dir lives (worktrees put it elsewhere) — for the HEAD watch. */
70
+ gitDir() {
71
+ return gitOut(this.root, "rev-parse", "--absolute-git-dir");
72
+ }
73
+ /**
74
+ * Null is the whole off-switch: not a git repo, no origin, or no resolvable
75
+ * default branch all mean the served UI draws no git surface at all.
76
+ */
77
+ capability() {
78
+ const top = this.toplevel();
79
+ if (!top)
80
+ return null;
81
+ if (gitOut(this.root, "remote", "get-url", "origin") === null)
82
+ return null;
83
+ let base;
84
+ try {
85
+ base = defaultBase(this.root);
86
+ }
87
+ catch {
88
+ return null;
89
+ }
90
+ if (this.ghChecked === null) {
91
+ const gh = spawnSync("gh", ["--version"], { encoding: "utf8", timeout: 10_000 });
92
+ this.ghChecked = !gh.error && gh.status === 0;
93
+ }
94
+ return {
95
+ repo: detectRepo(this.root),
96
+ defaultBranch: base.replace(/^origin\//, ""),
97
+ gh: this.ghChecked,
98
+ };
99
+ }
100
+ /**
101
+ * `git status --porcelain=v2` records as {kind, xy, path}. v2 on purpose,
102
+ * everywhere: its records are token-addressed from the record tag, so the
103
+ * stdout trim in runGit (which eats v1's leading space on the first line)
104
+ * can't shift a path by a character.
105
+ */
106
+ porcelain(...extra) {
107
+ const out = gitOut(this.root, "status", "--porcelain=v2", ...extra);
108
+ return out === null ? null : this.parseRecords(out);
109
+ }
110
+ parseRecords(out) {
111
+ const records = [];
112
+ for (const line of out === "" ? [] : out.split("\n")) {
113
+ const kind = line[0];
114
+ if (kind === "?") {
115
+ records.push({ kind, xy: "", path: line.slice(2) });
116
+ }
117
+ else if (kind === "1" || kind === "u") {
118
+ const parts = line.split(" ");
119
+ records.push({ kind, xy: parts[1] ?? "", path: parts.slice(kind === "1" ? 8 : 10).join(" ") });
120
+ }
121
+ else if (kind === "2") {
122
+ const parts = line.split(" ");
123
+ records.push({ kind, xy: parts[1] ?? "", path: parts.slice(9).join(" ").split("\t")[0] });
124
+ }
125
+ }
126
+ return records;
127
+ }
128
+ /** Each board's `.task` dir as a toplevel-relative posix pathspec. */
129
+ boardDirs(top) {
130
+ const dirs = new Map();
131
+ for (const { id, store } of this.boards()) {
132
+ const rel = relative(top, store.taskDir).split(sep).join("/");
133
+ if (rel === "" || rel.startsWith(".."))
134
+ continue;
135
+ dirs.set(id, rel);
136
+ }
137
+ return dirs;
138
+ }
139
+ status() {
140
+ const cap = this.capability();
141
+ const top = this.toplevel();
142
+ if (!cap || !top)
143
+ throw new GitServeError("no git surface here", 404);
144
+ // One spawn answers branch, upstream, ahead/behind and every path:
145
+ // porcelain v2 with --branch headers. -uall so a freshly added ticket
146
+ // (untracked until its first commit) shows up as board dirt.
147
+ const out = gitOut(this.root, "status", "--porcelain=v2", "--branch", "-uall");
148
+ if (out === null)
149
+ throw new GitServeError("git status failed", 500);
150
+ let branch = null;
151
+ let upstream = null;
152
+ let ahead = null;
153
+ let behind = null;
154
+ const dirty = [];
155
+ let otherDirty = 0;
156
+ const dirs = this.boardDirs(top);
157
+ const classify = (path) => {
158
+ for (const [board, dir] of dirs) {
159
+ if (path === dir || path.startsWith(`${dir}/`)) {
160
+ const rest = path.slice(dir.length + 1);
161
+ const ticket = /^(?:tickets|archive)\/([^/]+)\//.exec(rest);
162
+ return { board, ticket: ticket ? ticket[1] : null };
163
+ }
164
+ }
165
+ return null;
166
+ };
167
+ for (const line of out === "" ? [] : out.split("\n")) {
168
+ if (line.startsWith("# branch.head ")) {
169
+ const name = line.slice("# branch.head ".length);
170
+ branch = name === "(detached)" ? null : name;
171
+ continue;
172
+ }
173
+ if (line.startsWith("# branch.upstream ")) {
174
+ upstream = line.slice("# branch.upstream ".length);
175
+ continue;
176
+ }
177
+ if (line.startsWith("# branch.ab ")) {
178
+ const ab = /^# branch\.ab \+(\d+) -(\d+)$/.exec(line);
179
+ if (ab) {
180
+ ahead = Number(ab[1]);
181
+ behind = Number(ab[2]);
182
+ }
183
+ continue;
184
+ }
185
+ continue;
186
+ }
187
+ for (const { kind, xy, path } of this.parseRecords(out)) {
188
+ const board = classify(path);
189
+ if (board) {
190
+ const status = kind === "?"
191
+ ? "untracked"
192
+ : xy.includes("D")
193
+ ? "deleted"
194
+ : xy.includes("A")
195
+ ? "added"
196
+ : "modified";
197
+ dirty.push({ board: board.board, path, ticket: board.ticket, status });
198
+ }
199
+ else if (kind !== "?") {
200
+ otherDirty++;
201
+ }
202
+ }
203
+ dirty.sort((a, b) => a.path.localeCompare(b.path));
204
+ return {
205
+ branch,
206
+ detached: branch === null,
207
+ defaultBranch: cap.defaultBranch,
208
+ upstream,
209
+ ahead,
210
+ behind,
211
+ dirty,
212
+ otherDirty,
213
+ claims: this.claims(),
214
+ };
215
+ }
216
+ /**
217
+ * Live claims across the served boards — branch name plus the commit count
218
+ * a release would discard. One bounded ls-remote per board (claim-io's
219
+ * moved-tip-only fetch keeps the follow-up cheap), cached briefly because
220
+ * status refetches on every SSE tick and origin doesn't move that fast.
221
+ * Offline degrades to [] — no claims surface, same as the inbox's rule.
222
+ */
223
+ claims() {
224
+ const cached = this.claimsCache;
225
+ if (cached && Date.now() - cached.at < CLAIMS_TTL_MS)
226
+ return cached.claims;
227
+ const claims = [];
228
+ for (const { id, store } of this.boards()) {
229
+ let namespace;
230
+ try {
231
+ namespace = claimNamespace(store.config);
232
+ }
233
+ catch {
234
+ continue;
235
+ }
236
+ const tips = remoteClaimTips(store);
237
+ if (!tips || tips.size === 0)
238
+ continue;
239
+ syncClaimRefs(store, namespace, tips);
240
+ for (const task of store.list({ statuses: ["backlog", "todo", "in_progress"] })) {
241
+ const branch = claimBranch(store.config, task.key);
242
+ if (!tips.has(branch))
243
+ continue;
244
+ const count = gitOut(this.root, "rev-list", "--count", `refs/remotes/origin/${branch}`, "--not", defaultBase(this.root));
245
+ claims.push({ board: id, ticket: task.key, branch, commits: Number(count ?? 0) });
246
+ }
247
+ }
248
+ this.claimsCache = { at: Date.now(), claims };
249
+ return claims;
250
+ }
251
+ branches() {
252
+ const cap = this.capability();
253
+ if (!cap)
254
+ throw new GitServeError("no git surface here", 404);
255
+ const out = gitOut(this.root, "for-each-ref", "--format=%(refname:short)", "refs/heads");
256
+ if (out === null)
257
+ throw new GitServeError("git for-each-ref failed", 500);
258
+ const current = gitOut(this.root, "symbolic-ref", "--quiet", "--short", "HEAD");
259
+ return (out === "" ? [] : out.split("\n")).map((name) => ({
260
+ name,
261
+ current: name === current,
262
+ isDefault: name === cap.defaultBranch,
263
+ }));
264
+ }
265
+ /**
266
+ * Commit the working tree's board changes — and nothing else. `git add` and
267
+ * `git commit` are both pathspec-limited to the boards' `.task` dirs, so a
268
+ * dirty tree elsewhere (half-finished code, scratch files) neither blocks
269
+ * the commit nor leaks into it. With `newBranch` the commit lands on a
270
+ * fresh branch cut from `base` (default: wherever HEAD is now) — the
271
+ * default-branch flow, where board edits shouldn't land on main directly.
272
+ */
273
+ commit(body) {
274
+ const top = this.toplevel();
275
+ if (!this.capability() || !top)
276
+ throw new GitServeError("no git surface here", 404);
277
+ const message = typeof body.message === "string" ? body.message.trim() : "";
278
+ if (!message)
279
+ throw new GitServeError("message is required");
280
+ const dirs = [...this.boardDirs(top).values()];
281
+ if (dirs.length === 0)
282
+ throw new GitServeError("no board directories inside this repository");
283
+ const records = this.porcelain("-uall", "--", ...dirs);
284
+ if (records === null)
285
+ throw new GitServeError("git status failed", 500);
286
+ if (records.length === 0) {
287
+ throw new GitServeError("nothing to commit — no board files have changed");
288
+ }
289
+ const files = records.map((r) => r.path);
290
+ if (body.newBranch !== undefined) {
291
+ const name = typeof body.newBranch === "string" ? body.newBranch.trim() : "";
292
+ if (!name || runGit(this.root, ["check-ref-format", "--branch", name]).status !== 0) {
293
+ throw new GitServeError(`not a valid branch name: ${String(body.newBranch)}`);
294
+ }
295
+ if (git(this.root, "show-ref", "--verify", "--quiet", `refs/heads/${name}`).status === 0) {
296
+ throw new GitServeError(`branch ${name} already exists`);
297
+ }
298
+ const base = typeof body.base === "string" && body.base.trim() !== "" ? body.base.trim() : null;
299
+ if (base && gitOut(this.root, "rev-parse", "--verify", "--quiet", `${base}^{commit}`) === null) {
300
+ throw new GitServeError(`base not found: ${base}`);
301
+ }
302
+ const created = runGit(this.root, ["checkout", "--quiet", "-b", name, ...(base ? [base] : [])]);
303
+ if (created.status !== 0) {
304
+ throw new GitServeError(`couldn't create ${name}: ${created.stderr || created.stdout}`);
305
+ }
306
+ }
307
+ const add = runGit(this.root, ["add", "-A", "--", ...dirs]);
308
+ if (add.status !== 0)
309
+ throw new GitServeError(`git add failed: ${add.stderr}`, 500);
310
+ const commit = runGit(this.root, ["commit", "--quiet", "-m", message, "--", ...dirs]);
311
+ if (commit.status !== 0) {
312
+ throw new GitServeError(`git commit failed: ${commit.stderr || commit.stdout}`, 500);
313
+ }
314
+ return {
315
+ commit: gitOut(this.root, "rev-parse", "HEAD") ?? "",
316
+ branch: gitOut(this.root, "symbolic-ref", "--quiet", "--short", "HEAD"),
317
+ files,
318
+ };
319
+ }
320
+ /**
321
+ * Switch branches — refused while tracked files outside the board dirs are
322
+ * dirty. No stashing magic: board dirt rides along (that's the working
323
+ * style this whole surface supports), but half-finished code does not get
324
+ * silently carried onto another branch by a click in a board UI.
325
+ */
326
+ checkout(body) {
327
+ const top = this.toplevel();
328
+ if (!this.capability() || !top)
329
+ throw new GitServeError("no git surface here", 404);
330
+ const branch = typeof body.branch === "string" ? body.branch.trim() : "";
331
+ if (!branch)
332
+ throw new GitServeError("branch is required");
333
+ if (git(this.root, "show-ref", "--verify", "--quiet", `refs/heads/${branch}`).status !== 0) {
334
+ throw new GitServeError(`no local branch named ${branch}`);
335
+ }
336
+ const tracked = this.porcelain("-uno");
337
+ if (tracked === null)
338
+ throw new GitServeError("git status failed", 500);
339
+ const dirs = [...this.boardDirs(top).values()];
340
+ const outside = tracked
341
+ .map((r) => r.path)
342
+ .filter((p) => !dirs.some((d) => p === d || p.startsWith(`${d}/`)));
343
+ if (outside.length > 0) {
344
+ const shown = outside.slice(0, 3).join(", ");
345
+ throw new GitServeError(`${outside.length} file${outside.length === 1 ? " has" : "s have"} uncommitted changes outside the board (${shown}${outside.length > 3 ? ", …" : ""}) — commit or stash them in a terminal first; switching under them from here would be a surprise`, 409);
346
+ }
347
+ const result = runGit(this.root, ["checkout", "--quiet", branch]);
348
+ if (result.status !== 0) {
349
+ throw new GitServeError(`git checkout failed: ${result.stderr || result.stdout}`);
350
+ }
351
+ return { branch };
352
+ }
353
+ /**
354
+ * Open a PR for a branch: push it, then `gh pr create` when gh is here —
355
+ * falling back to the GitHub compare URL for the UI to open when it isn't.
356
+ * On a created PR the URL is written into the `prs:` frontmatter of every
357
+ * ticket whose files the branch touches: files remember, git informs.
358
+ */
359
+ pr(body) {
360
+ const cap = this.capability();
361
+ const top = this.toplevel();
362
+ if (!cap || !top)
363
+ throw new GitServeError("no git surface here", 404);
364
+ const current = gitOut(this.root, "symbolic-ref", "--quiet", "--short", "HEAD");
365
+ const branch = typeof body.branch === "string" && body.branch.trim() ? body.branch.trim() : current;
366
+ if (!branch)
367
+ throw new GitServeError("no branch to open a PR for — HEAD is detached");
368
+ const base = typeof body.base === "string" && body.base.trim() ? body.base.trim() : cap.defaultBranch;
369
+ if (branch === base)
370
+ throw new GitServeError(`${branch} is the base branch — nothing to open`);
371
+ // No way to end in a PR (or even a compare page)? Say so before pushing.
372
+ if (!cap.gh && !cap.repo) {
373
+ throw new GitServeError("origin isn't a GitHub remote and gh isn't installed — open the PR by hand", 501);
374
+ }
375
+ const push = runGit(this.root, ["push", "--quiet", "-u", "origin", branch], {
376
+ timeoutMs: GIT_NETWORK_TIMEOUT_MS,
377
+ });
378
+ if (push.status !== 0) {
379
+ throw new GitServeError(`push of ${branch} failed: ${push.stderr || push.stdout}`, 502);
380
+ }
381
+ if (!cap.gh) {
382
+ return { url: compareUrl(cap.repo, base, branch), created: false, tickets: [] };
383
+ }
384
+ const title = typeof body.title === "string" && body.title.trim() ? body.title.trim() : branch;
385
+ const description = typeof body.body === "string" ? body.body : "";
386
+ const args = ["pr", "create", "--head", branch, "--base", base, "--title", title, "--body", description];
387
+ if (body.draft === true)
388
+ args.push("--draft");
389
+ const created = runGh(this.root, args);
390
+ if (created.status !== 0) {
391
+ throw new GitServeError(`gh pr create failed: ${created.stderr || created.stdout}`, 502);
392
+ }
393
+ const url = /https:\/\/\S+\/pull\/\d+/.exec(created.stdout)?.[0] ?? created.stdout;
394
+ this.prCache.delete(branch);
395
+ return { url, created: true, tickets: this.attachPrUrl(top, branch, base, url) };
396
+ }
397
+ /** Append `url` to the prs: of every ticket the branch's commits touch. */
398
+ attachPrUrl(top, branch, base, url) {
399
+ const baseRef = gitOut(this.root, "rev-parse", "--verify", "--quiet", `origin/${base}^{commit}`) !== null
400
+ ? `origin/${base}`
401
+ : base;
402
+ const diff = gitOut(this.root, "diff", "--name-only", `${baseRef}...${branch}`);
403
+ if (diff === null || diff === "")
404
+ return [];
405
+ const dirs = this.boardDirs(top);
406
+ const stores = new Map(this.boards().map((b) => [b.id, b.store]));
407
+ const attached = [];
408
+ const seen = new Set();
409
+ for (const path of diff.split("\n")) {
410
+ for (const [board, dir] of dirs) {
411
+ if (!path.startsWith(`${dir}/`))
412
+ continue;
413
+ const ticket = /^tickets\/([^/]+)\//.exec(path.slice(dir.length + 1));
414
+ if (!ticket)
415
+ continue;
416
+ const ticketKey = ticket[1];
417
+ const seenKey = `${board}:${ticketKey}`;
418
+ if (seen.has(seenKey))
419
+ continue;
420
+ seen.add(seenKey);
421
+ const store = stores.get(board);
422
+ const task = store?.get(ticketKey);
423
+ if (!store || !task || task.prs.includes(url))
424
+ continue;
425
+ try {
426
+ store.update(ticketKey, { prs: [...task.prs, url] });
427
+ attached.push(task.id);
428
+ }
429
+ catch {
430
+ // A refused update (archived, gone) must not fail the PR that exists.
431
+ }
432
+ }
433
+ }
434
+ return attached;
435
+ }
436
+ /** Derived, display-only PR state for a branch — gh only, briefly cached. */
437
+ prFor(branch) {
438
+ const cap = this.capability();
439
+ if (!cap)
440
+ throw new GitServeError("no git surface here", 404);
441
+ if (!cap.gh)
442
+ return { pr: null };
443
+ const cached = this.prCache.get(branch);
444
+ if (cached && Date.now() - cached.at < PR_TTL_MS)
445
+ return { pr: cached.pr };
446
+ const out = runGh(this.root, [
447
+ "pr",
448
+ "list",
449
+ "--head",
450
+ branch,
451
+ "--state",
452
+ "all",
453
+ "--json",
454
+ "number,url,title,state,isDraft",
455
+ "--limit",
456
+ "10",
457
+ ]);
458
+ let pr = null;
459
+ if (out.status === 0) {
460
+ try {
461
+ const rows = JSON.parse(out.stdout);
462
+ const pick = rows.find((r) => r.state === "OPEN") ??
463
+ rows.find((r) => r.state === "MERGED") ??
464
+ rows[0] ??
465
+ null;
466
+ if (pick) {
467
+ pr = {
468
+ number: pick.number,
469
+ url: pick.url,
470
+ title: pick.title,
471
+ state: pick.state.toLowerCase(),
472
+ draft: pick.isDraft,
473
+ };
474
+ }
475
+ }
476
+ catch {
477
+ pr = null;
478
+ }
479
+ }
480
+ this.prCache.set(branch, { at: Date.now(), pr });
481
+ return { pr };
482
+ }
483
+ /**
484
+ * The drag-to-release flow's server half (TAS-26): abandon a ticket's claim
485
+ * exactly like `task claim --release` — delete the branch on origin and
486
+ * locally — so the caller can then apply the move as a plain file edit.
487
+ * Fails whole: if the branch can't be deleted (offline, no push access),
488
+ * the claim stands and the caller moves nothing.
489
+ */
490
+ releaseClaim(store, body, author) {
491
+ if (!this.capability())
492
+ throw new GitServeError("no git surface here", 404);
493
+ const key = typeof body.key === "string" ? body.key.trim() : "";
494
+ if (!key)
495
+ throw new GitServeError("key is required");
496
+ const result = release(store, key);
497
+ this.claimsCache = null;
498
+ const note = typeof body.note === "string" ? body.note.trim() : "";
499
+ store.addComment(key, note || "Released the claim from the board — the branch and its commits are gone.", author);
500
+ return { branch: result.branch };
501
+ }
502
+ }
503
+ //# sourceMappingURL=git-serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-serve.js","sourceRoot":"","sources":["../src/git-serve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The git surface's contract (TAS-42), checked over real HTTP against real
3
+ * repositories — the properties that must hold before a board UI is allowed
4
+ * to run git:
5
+ *
6
+ * 1. Board commits are pathspec-scoped: with board AND non-board files dirty,
7
+ * committing from the API commits exactly the board files.
8
+ * 2. Checkout is refused while tracked non-board files are dirty — no
9
+ * stashing magic, the refusal says why.
10
+ * 3. The CSRF gate: a cross-origin browser write is 403 before any handler
11
+ * runs; the board's own origin and origin-less clients pass.
12
+ * 4. Degradation: a repo with no origin advertises no `git` capability and
13
+ * 404s the whole route group — the self-hiding rule the UI builds on.
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=git-serve.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-serve.test.d.ts","sourceRoot":"","sources":["../src/git-serve.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}