dw-sdlc 0.21.0 → 0.21.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 (94) hide show
  1. package/dist/agentic-config.d.ts +16 -0
  2. package/dist/agentic-config.js +28 -23
  3. package/dist/cannot-run.d.ts +27 -0
  4. package/dist/cannot-run.js +48 -0
  5. package/dist/catalogue.js +2 -1
  6. package/dist/checks/agents-map.js +7 -8
  7. package/dist/checks/check.d.ts +10 -8
  8. package/dist/checks/check.js +9 -7
  9. package/dist/checks/decision-records.js +3 -2
  10. package/dist/checks/file-size-ratchet.js +13 -17
  11. package/dist/checks/index.d.ts +6 -5
  12. package/dist/checks/index.js +10 -9
  13. package/dist/checks/markdown-refs.js +1 -1
  14. package/dist/checks/primitives.js +5 -5
  15. package/dist/checks/routed-docs.js +1 -3
  16. package/dist/checks/skill-sections.js +12 -20
  17. package/dist/checks/tree.js +7 -7
  18. package/dist/cli.d.ts +2 -1
  19. package/dist/cli.js +26 -5
  20. package/dist/commands/check.js +27 -42
  21. package/dist/commands/config.js +22 -27
  22. package/dist/commands/doctor.d.ts +2 -0
  23. package/dist/commands/doctor.js +11 -18
  24. package/dist/commands/gate.js +35 -40
  25. package/dist/commands/lead-start.js +28 -42
  26. package/dist/commands/pr-reviewed.js +41 -59
  27. package/dist/commands/pr-ship.js +71 -89
  28. package/dist/commands/primitives.js +38 -40
  29. package/dist/commands/recap.js +23 -74
  30. package/dist/commands/references-setup.js +28 -76
  31. package/dist/commands/references-sync.js +29 -53
  32. package/dist/commands/setup.d.ts +2 -7
  33. package/dist/commands/setup.js +38 -90
  34. package/dist/commands/sweep.js +46 -157
  35. package/dist/commands/worker-ls.js +15 -31
  36. package/dist/commands/worker-report.js +36 -52
  37. package/dist/commands/worker-start.js +43 -57
  38. package/dist/drift.js +2 -1
  39. package/dist/exec.d.ts +20 -0
  40. package/dist/exec.js +37 -4
  41. package/dist/gate-cache.js +2 -1
  42. package/dist/git.d.ts +32 -0
  43. package/dist/git.js +60 -0
  44. package/dist/json-schema.js +1 -3
  45. package/dist/landed.js +11 -22
  46. package/dist/paused-operation.d.ts +2 -0
  47. package/dist/paused-operation.js +17 -0
  48. package/dist/pins.js +2 -1
  49. package/dist/pr/decide.d.ts +4 -16
  50. package/dist/pr/decide.js +48 -84
  51. package/dist/pr/delta.d.ts +3 -4
  52. package/dist/pr/delta.js +10 -19
  53. package/dist/pr/read.d.ts +27 -30
  54. package/dist/pr/read.js +94 -182
  55. package/dist/pr/reply.js +3 -5
  56. package/dist/pr/route.d.ts +11 -3
  57. package/dist/pr/route.js +5 -5
  58. package/dist/pr/standing.d.ts +138 -0
  59. package/dist/pr/standing.js +181 -0
  60. package/dist/pr/state.d.ts +10 -69
  61. package/dist/pr/state.js +42 -72
  62. package/dist/pr/upstream.d.ts +1 -6
  63. package/dist/pr/upstream.js +2 -2
  64. package/dist/primitives-diff.js +1 -1
  65. package/dist/recap-next.js +34 -47
  66. package/dist/recap-primitives.js +1 -1
  67. package/dist/references-key.d.ts +0 -1
  68. package/dist/references-key.js +3 -4
  69. package/dist/run-command.d.ts +4 -1
  70. package/dist/run-command.js +32 -11
  71. package/dist/setup-gate.d.ts +1 -7
  72. package/dist/setup-rules.js +2 -6
  73. package/dist/setup-writer.d.ts +32 -0
  74. package/dist/setup-writer.js +60 -0
  75. package/dist/shell-line.d.ts +2 -0
  76. package/dist/shell-line.js +5 -0
  77. package/dist/sweep-removal.d.ts +31 -0
  78. package/dist/sweep-removal.js +133 -0
  79. package/dist/sweep-terminals.d.ts +1 -1
  80. package/dist/sweep-terminals.js +21 -57
  81. package/dist/sweep-trees.d.ts +19 -3
  82. package/dist/sweep-trees.js +67 -31
  83. package/dist/worker/herdr.d.ts +67 -23
  84. package/dist/worker/herdr.js +126 -77
  85. package/dist/worker/launch.js +32 -45
  86. package/dist/worker/origin.d.ts +1 -1
  87. package/dist/worker/origin.js +9 -11
  88. package/dist/worker/tabs.js +11 -7
  89. package/dist/working-tree.d.ts +0 -8
  90. package/dist/working-tree.js +6 -22
  91. package/dist/worktree-lock.js +1 -1
  92. package/package.json +1 -1
  93. package/dist/git-env.d.ts +0 -2
  94. package/dist/git-env.js +0 -10
@@ -1,4 +1,5 @@
1
- import type { PrMerge, PrReview, ResolvedConfig, ReviewDepth } from "../agentic-config.ts";
1
+ import type { PrMerge, ResolvedConfig } from "../agentic-config.ts";
2
+ import { type ReviewPolicy } from "./standing.ts";
2
3
  import { type PrState, REVIEW } from "./state.ts";
3
4
  export { REVIEW };
4
5
  export type Status = "act" | "wait" | "park" | "done";
@@ -6,24 +7,13 @@ export type Actor = "script" | "agent" | "dev";
6
7
  export type Action = "done" | "stop" | "wait" | "fix-conflicts" | "update-branch" | "fix-ci" | "address-review" | "review" | "review-limit" | "mark-reviewed" | "unverified" | "ci-stuck" | "awaiting-reply" | "awaiting-review" | "mark-ready" | "awaiting-author" | "awaiting-approval" | "partial-read" | "ready-to-merge" | "merge";
7
8
  /** The Actions the script performs itself, each one gh command. */
8
9
  export type ScriptAction = "update-branch" | "mark-ready" | "mark-reviewed" | "merge";
9
- /**
10
- * Where a Review depth comes from: the dev's `--review` for this call, a depth `pr.review` sets, or the
11
- * rules `pr.review: auto` routes it by.
12
- */
13
- export type DepthSource = "flag" | "config" | "auto";
14
10
  /**
15
11
  * What the decision reads beside the pull request: who merges it, how closely a Review reads it, the
16
12
  * dev's word or `pr.review`, and the slash command a `full` Review runs.
17
13
  */
18
14
  export type Policy = {
19
15
  merge: PrMerge;
20
- review: {
21
- depth: ReviewDepth;
22
- source: "flag";
23
- } | {
24
- depth: PrReview;
25
- source: "config";
26
- };
16
+ review: ReviewPolicy;
27
17
  reviewCommand: string;
28
18
  };
29
19
  /** The policy a repository's `pr` key declares; a flag for one call goes over it. */
@@ -48,14 +38,12 @@ export type Answer = Blocker & {
48
38
  * head the fix then leaves behind. A pending status would turn the pull request unstable.
49
39
  */
50
40
  export declare const REVIEW_STATE = "success";
51
- /** The words as one POSIX shell command line, each word that needs it single-quoted. */
52
- export declare function shellLine(words: string[]): string;
53
41
  /**
54
42
  * The gh arguments that post `dw-sdlc/review` on the head, a success unless `state` says otherwise,
55
43
  * `description` saying how it was read. The path names the repository, so the call reads the same from
56
44
  * any checkout.
57
45
  */
58
- export declare function reviewStatusArgs(pr: PrState, description: string, state?: string): string[];
46
+ export declare function reviewStatusArgs(pr: Pick<PrState, "url" | "repo" | "head">, description: string, state?: string): string[];
59
47
  export declare function isScriptAction(action: Action): action is ScriptAction;
60
48
  /**
61
49
  * The gh arguments of a script Action, `-R` naming the repository when `named`. The update merges the
package/dist/pr/decide.js CHANGED
@@ -1,23 +1,18 @@
1
1
  // The decision of the Ship script: one ordered list of rows, and the first row whose `when` holds for
2
2
  // the pull request answers its Action at the time given; every later row that holds rides in its
3
3
  // blockers. The last rows say who merges what no row before them holds back.
4
- import { route } from "./route.js";
4
+ import { shellLine } from "../shell-line.js";
5
+ import { reviewCall } from "./standing.js";
5
6
  import { awaitsReview, OFF_PREFIX, REVIEW } from "./state.js";
6
7
  export { REVIEW };
7
8
  /** The policy a repository's `pr` key declares; a flag for one call goes over it. */
8
9
  export function declaredPolicy({ merge, review, reviewCommand }) {
9
10
  return { merge, review: { depth: review, source: "config" }, reviewCommand };
10
11
  }
11
- /** How long a head may carry no check before it parks as unverified, from its commit. */
12
+ /** How long a head may carry no check before it parks as unverified, from when its CI could start. */
12
13
  const GRACE_SECONDS = 120;
13
14
  /** How long CI may stay pending before it parks as stuck, from the first start among the pending checks. */
14
15
  const BUDGET_MINUTES = 40;
15
- /**
16
- * How many Reviews that each left a Finding open, with no success between them, the script lets run: the
17
- * next call parks the pull request for the dev. A constant, like the depth rules, so no repository turns
18
- * the loop back on.
19
- */
20
- const REVIEW_LIMIT = 3;
21
16
  /** The prefix of the contexts the script posts itself, as `dw-sdlc/review`: never CI. */
22
17
  const OWN_PREFIX = "dw-sdlc/";
23
18
  /**
@@ -25,9 +20,9 @@ const OWN_PREFIX = "dw-sdlc/";
25
20
  * head the fix then leaves behind. A pending status would turn the pull request unstable.
26
21
  */
27
22
  export const REVIEW_STATE = "success";
28
- /** The words as one POSIX shell command line, each word that needs it single-quoted. */
29
- export function shellLine(words) {
30
- return words.map((word) => (/^[\w./:=@%+,-]+$/.test(word) ? word : `'${word.replaceAll("'", `'\\''`)}'`)).join(" ");
23
+ /** When the head's CI could start: its commit, or its ready when it left draft later, since a draft runs nothing. */
24
+ function ciStartOf(pr) {
25
+ return Math.max(Date.parse(pr.headCommittedAt), Date.parse(pr.readyAt ?? pr.headCommittedAt));
31
26
  }
32
27
  function ciOf(pr) {
33
28
  return pr.checks.filter((check) => !check.name.startsWith(OWN_PREFIX));
@@ -73,48 +68,19 @@ export function reviewStatusArgs(pr, description, state = REVIEW_STATE) {
73
68
  const flags = Object.entries(fields).flatMap(([key, value]) => ["-f", `${key}=${value}`]);
74
69
  return ["api", `repos/${pr.repo}/statuses/${pr.head}`, "--method", "POST", "--silent", ...flags];
75
70
  }
76
- /** Whether the dev named a depth for a head that would carry the status: their word beats the carry. */
77
- function flagOverCarry(pr, { review }) {
78
- return pr.carried && review.source === "flag";
79
- }
80
- /** The reviewed commit whose success the head carries, if it does and the dev named no depth. */
81
- function carriedFrom(pr, policy) {
82
- return pr.carried && !flagOverCarry(pr, policy) ? (pr.lastRead?.commit ?? null) : null;
83
- }
84
- /**
85
- * The commit the Review reads from: the last one a Review read, clean or not, so the Review after a fix
86
- * reads the fix. Over a carry the dev's depth reads the whole diff, since the changes after that commit
87
- * are only the base's.
88
- */
89
- function sinceOf(pr, policy) {
90
- return flagOverCarry(pr, policy) ? null : (pr.lastRead?.commit ?? null);
91
- }
92
- /** The depth a Review reads the head at: the dev's or the one `pr.review` sets, else the one the rules route. */
93
- function depthOf(pr, { review }) {
94
- const { depth, source } = review;
95
- if (depth === "off") {
96
- return { depth, source, why: source === "flag" ? "--review off" : "pr.review" };
97
- }
98
- if (depth !== "auto") {
99
- return { depth, source };
100
- }
101
- return { ...route(pr.changed), source: "auto" };
102
- }
103
71
  /** Why the head carries the success the script posts: the Review it carries, else why its depth is off. */
104
72
  function markedDescription(pr, policy) {
105
- const carried = carriedFrom(pr, policy);
106
- if (carried !== null) {
107
- return `carried from ${carried.slice(0, 7)}`;
73
+ const call = reviewCall(pr, policy.review);
74
+ if (call.kind === "carry") {
75
+ return `carried from ${call.from.slice(0, 7)}`;
108
76
  }
109
- const depth = depthOf(pr, policy);
110
- if (depth.depth !== "off") {
111
- throw new Error(`the script marks ${pr.url} reviewed at ${depth.depth}, neither off nor a carry`);
77
+ if (call.kind !== "review" || call.depth !== "off") {
78
+ throw new Error(`the script marks ${pr.url} reviewed, neither off nor a carry`);
112
79
  }
113
- return `${OFF_PREFIX} ${depth.why}`;
80
+ return `${OFF_PREFIX} ${call.why}`;
114
81
  }
115
82
  /** The park at the limit: the dev accepts the head as it stands, or names a depth for one more Review. */
116
- function reviewLimit(pr) {
117
- const { count, since } = pr.marks;
83
+ function reviewLimit(pr, { count, since }) {
118
84
  const from = since === null ? "the start of the pull request" : `the success on ${since.slice(0, 7)}`;
119
85
  return {
120
86
  status: "park",
@@ -124,6 +90,36 @@ function reviewLimit(pr) {
124
90
  command: shellLine(["dw-sdlc", "pr", "reviewed", String(pr.number), "-R", pr.repo, "--head", pr.head, "--accept"])
125
91
  };
126
92
  }
93
+ /**
94
+ * The Review a head that awaits one gets: the script posts the success of a carry or under off, the agent
95
+ * reviews at the depth, else it parks at the limit. Auto names the command at any depth, since the agent
96
+ * may raise a routed one to full.
97
+ */
98
+ function reviewAnswer(pr, policy) {
99
+ const head = { status: "act", reason: `no ${REVIEW} success on ${pr.head.slice(0, 7)}` };
100
+ const call = reviewCall(pr, policy.review);
101
+ if (call.kind === "carry") {
102
+ return { ...head, action: "mark-reviewed", actor: "script", details: { since: call.from } };
103
+ }
104
+ if (call.kind === "limit") {
105
+ return reviewLimit(pr, call);
106
+ }
107
+ const { depth, source, since, paths, open } = call;
108
+ const byScript = depth === "off";
109
+ return {
110
+ ...head,
111
+ action: byScript ? "mark-reviewed" : "review",
112
+ actor: byScript ? "script" : "agent",
113
+ details: {
114
+ depth,
115
+ source,
116
+ ...(depth === "full" || source === "auto" ? { reviewCommand: policy.reviewCommand } : {}),
117
+ ...(since === null ? {} : { since }),
118
+ ...(paths === null ? {} : { paths }),
119
+ ...(open === null ? {} : { open })
120
+ }
121
+ };
122
+ }
127
123
  /** A script Action's gh arguments; `repo` is `-R` and the repository when the call names it, else empty. */
128
124
  const HOST = {
129
125
  "update-branch": (pr, repo) => ["pr", "update-branch", String(pr.number), ...repo],
@@ -221,53 +217,22 @@ const ROWS = [
221
217
  answer: () => ({ status: "act", action: "address-review", actor: "agent", reason: "changes requested" })
222
218
  },
223
219
  {
224
- // Another author's pull request needs no Review: the dev merges it. The script posts the success
225
- // under off, and over a carry, which reads at no depth.
220
+ // Another author's pull request needs no Review: the dev merges it.
226
221
  when: awaitsReview,
227
- answer: (pr, _, policy) => {
228
- const since = sinceOf(pr, policy);
229
- const head = { status: "act", reason: `no ${REVIEW} success on ${pr.head.slice(0, 7)}` };
230
- const after = since === null ? {} : { since };
231
- if (carriedFrom(pr, policy) !== null) {
232
- return { ...head, action: "mark-reviewed", actor: "script", details: after };
233
- }
234
- const { depth, source } = depthOf(pr, policy);
235
- // The dev's own depth buys one Review past the limit, and only one: the flag rides on every
236
- // later call. A Review under off needs none.
237
- const limit = source === "flag" ? REVIEW_LIMIT + 1 : REVIEW_LIMIT;
238
- if (depth !== "off" && pr.marks.count >= limit) {
239
- return reviewLimit(pr);
240
- }
241
- const byScript = depth === "off";
242
- return {
243
- ...head,
244
- action: byScript ? "mark-reviewed" : "review",
245
- actor: byScript ? "script" : "agent",
246
- details: {
247
- depth,
248
- source,
249
- // The agent may raise a routed depth to full, so auto names the command at any depth.
250
- ...(depth === "full" || source === "auto" ? { reviewCommand: policy.reviewCommand } : {}),
251
- ...after,
252
- ...(pr.scope === null ? {} : { paths: pr.scope }),
253
- ...(pr.open === null ? {} : { open: pr.open })
254
- }
255
- };
256
- }
222
+ answer: (pr, _, policy) => reviewAnswer(pr, policy)
257
223
  },
258
224
  {
259
225
  // A head whose every check was skipped, or that has none, has run nothing. A draft's runs skip or
260
226
  // never start until `ready` starts the run, so a draft is no case of it: `mark-ready` is its row.
261
227
  when: (pr) => !pr.draft && (ciOf(pr).length === 0 || ciOf(pr).every((check) => check.bucket === "skipping")),
262
- answer: (pr, now, policy) => now - Math.max(Date.parse(pr.headCommittedAt), Date.parse(pr.readyAt ?? pr.headCommittedAt)) <=
263
- GRACE_SECONDS * 1000
228
+ answer: (pr, now, policy) => now - ciStartOf(pr) <= GRACE_SECONDS * 1000
264
229
  ? { status: "wait", action: "wait", actor: "script", reason: "unverified", recheckAfter: 15 }
265
230
  : {
266
231
  status: "park",
267
232
  action: "unverified",
268
233
  actor: "dev",
269
234
  reason: ciOf(pr).length === 0
270
- ? `no check reported on ${pr.head.slice(0, 7)} within ${GRACE_SECONDS} s of its commit`
235
+ ? `no check reported on ${pr.head.slice(0, 7)} within ${GRACE_SECONDS} s of its commit or its ready`
271
236
  : `every check on ${pr.head.slice(0, 7)} was skipped, ${GRACE_SECONDS} s after its commit or its ready`,
272
237
  command: devCommand(pr, "merge", policy)
273
238
  }
@@ -276,8 +241,7 @@ const ROWS = [
276
241
  when: (pr) => pendingOf(pr).length > 0,
277
242
  answer: (pr, now) => {
278
243
  const pending = pendingOf(pr);
279
- // A check queued and not yet started counts from the head's commit.
280
- const start = Math.min(...pending.map((check) => Date.parse(check.startedAt ?? pr.headCommittedAt)));
244
+ const start = Math.min(...pending.map((check) => (check.startedAt === null ? ciStartOf(pr) : Date.parse(check.startedAt))));
281
245
  const minutes = Math.floor((now - start) / 60_000);
282
246
  return now - start <= BUDGET_MINUTES * 60_000
283
247
  ? { status: "wait", action: "wait", actor: "script", reason: "ci-pending", recheckAfter: 60 }
@@ -1,11 +1,10 @@
1
- import type { ChangedFile } from "./state.ts";
1
+ import type { ChangedFile } from "./route.ts";
2
+ import type { OwnChange } from "./standing.ts";
2
3
  /** The gh arguments of the compare from `from` to `commit`, the files on its one page. */
3
4
  export declare function compareArgs(repo: string, from: string, commit: string): string[];
4
5
  /** How many commits of the compare's base its head lacks: 0 when the head carries all of it. */
5
6
  export declare function behindOf(reply: string): number;
6
7
  /** The own changes a compare reply lists, file by file; null when it cannot show them whole. */
7
- export declare function changesOf(reply: string): string[] | null;
8
+ export declare function changesOf(reply: string): OwnChange[] | null;
8
9
  /** The files a compare reply lists with their changed lines; `unsized` when it may hold some back. */
9
10
  export declare function changedOf(reply: string): ChangedFile[] | "unsized";
10
- /** Whether the own changes at the head are those at the reviewed commit; unknown changes never are. */
11
- export declare function sameChanges(then: string[] | null, now: string[] | null): boolean;
package/dist/pr/delta.js CHANGED
@@ -1,6 +1,6 @@
1
- // GitHub's compare of two commits, read two ways: whether a head carries the Review of an earlier commit,
2
- // the pull request's own changes from the base the same at both, since a merge of the base in adds none
3
- // of its own; and the files a Review would read, with their changed lines, for `pr.review: auto`.
1
+ // GitHub's compare of two commits as gh prints it, read three ways: the pull request's own changes at a
2
+ // commit, from the base; the files a Review would read, with their changed lines, for `pr.review: auto`;
3
+ // and how far a head is behind a base, which says whether an update merged it in.
4
4
  import { fieldOf, integer, object, ReplyError, rootOf, shown, string } from "./reply.js";
5
5
  /** GitHub's compare lists at most this many files; one that lists as many may hold back the rest. */
6
6
  const FILE_LIMIT = 300;
@@ -24,17 +24,15 @@ export function behindOf(reply) {
24
24
  function optional(file, key) {
25
25
  return file.value[key] === undefined || file.value[key] === null ? null : string(file, key);
26
26
  }
27
- /**
28
- * A file's own change: its status, its names and the lines its patch adds and removes, in order,
29
- * without the hunk headers and context a moved base shifts; null when the compare shows no patch.
30
- */
27
+ /** A file's own change; null when the compare shows no patch for it. */
31
28
  function changeOf(file) {
32
- const names = [string(file, "filename"), string(file, "status"), optional(file, "previous_filename")];
29
+ const path = string(file, "filename");
30
+ const status = string(file, "status");
31
+ const previous = optional(file, "previous_filename");
33
32
  const patch = optional(file, "patch");
34
- if (patch === null) {
35
- return null;
36
- }
37
- return JSON.stringify([...names, patch.split("\n").filter((line) => /^[-+\\]/.test(line))]);
33
+ return patch === null
34
+ ? null
35
+ : { path, status, previous, lines: patch.split("\n").filter((line) => /^[-+\\]/.test(line)) };
38
36
  }
39
37
  /** The own changes a compare reply lists, file by file; null when it cannot show them whole. */
40
38
  export function changesOf(reply) {
@@ -51,10 +49,3 @@ export function changedOf(reply) {
51
49
  }));
52
50
  return files.length >= FILE_LIMIT ? "unsized" : files;
53
51
  }
54
- /** Whether the own changes at the head are those at the reviewed commit; unknown changes never are. */
55
- export function sameChanges(then, now) {
56
- if (then === null || now === null) {
57
- return false;
58
- }
59
- return JSON.stringify(then.toSorted()) === JSON.stringify(now.toSorted());
60
- }
package/dist/pr/read.d.ts CHANGED
@@ -1,9 +1,5 @@
1
- import { type PrState } from "./state.ts";
2
- /** What stops a pr command or recap before it answers: exit 2, the problem and its remedy on one line. */
3
- export declare class CannotRun extends Error {
4
- remedy: string;
5
- constructor(message: string, remedy: string);
6
- }
1
+ import { type Called } from "../exec.ts";
2
+ import { type PrState, type PullRequest } from "./state.ts";
7
3
  /** The pull request a command line names; what it leaves out, `gh pr view` resolves. */
8
4
  export type Named = {
9
5
  number: number | undefined;
@@ -13,33 +9,34 @@ export type Named = {
13
9
  export declare function namedProblem(number: string | undefined, repo: string | undefined): string | undefined;
14
10
  /** What gh said went wrong: the first line of its stderr, without its `gh: ` prefix or its `X` icon. */
15
11
  export declare function said(stderr: string): string;
16
- export declare function gh(args: string[]): {
17
- status: number;
18
- stdout: string;
19
- stderr: string;
20
- };
12
+ /** `gh args` as a child process; not on PATH, or past its limit, it stops the command as any failed read does. */
13
+ export declare function gh(args: string[]): Called;
21
14
  /** The remedy for a pull request `command`, as `pr ship`, cannot find by itself: name it in full. */
22
15
  export declare function nameItRemedy(command: string): string;
23
- /**
24
- * The state of the pull request `named`; `command`, as `pr ship`, names the call in a remedy. With
25
- * `sized`, as `pr.review: auto` needs, the read sizes the changes a Review would read.
26
- */
27
- export declare function read(named: Named, command: string, sized: boolean): PrState;
28
- /**
29
- * The current branch's pull request, open or not, or null. gh tries `@{push}`, else the local name, which
30
- * misses a branch pushed under another name; then `upstreamName` is asked, and `byUpstream` says so.
31
- */
32
- export declare function readBranch(sized: boolean, upstreamName: string | undefined): {
33
- pr: PrState;
34
- byUpstream: boolean;
35
- } | null;
16
+ /** Why this checkout names no pull request to read; `lacksHead` when the one its upstream's name finds lacks HEAD. */
17
+ export type NoPr = {
18
+ problem: string;
19
+ lacksHead: boolean;
20
+ };
36
21
  /** The default branch of the repository gh resolves from the current directory. */
37
22
  export declare function defaultBranch(): string;
38
23
  /** The time the decision reads: DW_SDLC_NOW, an ISO 8601 time a test sets, else the system clock. */
39
24
  export declare function now(): number;
40
- /** The state of `pr` once more, after an action the script performed on it: the same pull request. */
41
- export declare function readAgain(pr: PrState, sized: boolean): PrState;
42
- /** For a test that runs the command in its own process: each case starts with no compare read. */
43
- export declare function forgetCompares(): void;
44
- /** Whether the head of `after` carries the base `before` read: the compare shows it behind by none. */
45
- export declare function carriesBase(before: PrState, after: PrState): boolean;
25
+ /** The pull request `named` from the one GraphQL request alone, without the compares the Review's standing reads. */
26
+ export declare function pullRequestNamed(named: Named, command: string): PullRequest;
27
+ /** The reads of pull requests one command makes through gh, each one's compares kept for the reads' life. */
28
+ export type Reads = {
29
+ /** The state of the pull request `named`; `command`, as `pr ship`, names the call in a remedy. */
30
+ named: (named: Named, command: string) => PrState;
31
+ /**
32
+ * The pull request of the branch checked out at `root`, open or not. gh tries `@{push}`, else the local
33
+ * name, which misses a branch pushed under another name: then it asks by the name the upstream gives.
34
+ */
35
+ checkout: (root: string) => PrState | NoPr;
36
+ /** The state of `pr` once more, after an action the script performed on it. */
37
+ again: (pr: PrState) => PrState;
38
+ /** Whether the head of `after` carries the base `before` read: the compare shows it behind by none. */
39
+ carriesBase: (before: PrState, after: PrState) => boolean;
40
+ };
41
+ /** The reads of one command; with `sized`, as `pr.review: auto` needs, each sizes the changes a Review would read. */
42
+ export declare function ghReads(sized: boolean): Reads;