@popoverai/dotrequirements 0.36.0 → 0.36.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.
@@ -102,11 +102,17 @@ Reading it changes nothing.
102
102
  `;
103
103
  /** What `pr wait` does, on its `--help` (PULL-5, PULL-6). */
104
104
  const PR_WAIT_HELP = `
105
- For a reviewer, when the pull request has to change before you can give a result,
106
- as while its checks run. Records where it stands now; then end your session
107
- without a result. You are started again, in this session, when GitHub reports it
108
- changed and nothing on it is still running, or once it is merged or closed. A new
109
- submission ends the wait too, and you review that as you would any other.
105
+ For a reviewer, while the pull request's checks run or GitHub works out whether it
106
+ can merge. Records where it stands now; then end your session without a result.
107
+ You are started again, in this session, once GitHub reports it clean, once it is
108
+ merged or closed, or when the wait is up: ten minutes unless you say, up to an
109
+ hour. A conflict, a failed check or a branch behind doesn't change by waiting:
110
+ judge it now. A new submission ends the wait too, and you review that as you
111
+ would any other.
112
+
113
+ Examples:
114
+ dotreq solution pr wait
115
+ dotreq solution pr wait 30m
110
116
  `;
111
117
  /** What `pr open` does, on its `--help`, where `author --help` sends the agent (PULL-2). */
112
118
  const PULL_REQUEST_HELP = `
@@ -256,8 +262,8 @@ export function registerSolution(program) {
256
262
  .addHelpText("after", PR_STATUS_HELP)
257
263
  .action(wrap(prStatusCommand));
258
264
  whereOptions(pr
259
- .command("wait")
260
- .description("Wait on the pull request with your session ended: you start again when it changes and nothing on it is still running"))
265
+ .command("wait [duration]")
266
+ .description("Wait on the pull request with your session ended, for ten minutes unless you say (as 5m or 1h, up to an hour): you start again once it is clean, merged or closed, or when the time is up"))
261
267
  .addHelpText("after", PR_WAIT_HELP)
262
268
  .action(wrap(prWaitCommand));
263
269
  whereOptions(solution
@@ -25,10 +25,7 @@ export type PullRequestState = {
25
25
  }>;
26
26
  head: string;
27
27
  };
28
- /**
29
- * Where the pull request stood, as a wait records it (PULL-6.4): what a
30
- * reviewer judges by, so a later read that differs is a change.
31
- */
28
+ /** Where the pull request stood, in words, as a wait records it beside what the line shows (PULL-5.1.0). */
32
29
  export declare function seenOf(state: PullRequestState): string;
33
30
  /** Where the pull request stands, as a reviewer reads it (PULL-4). */
34
31
  export declare function describeState(state: PullRequestState): string;
@@ -39,14 +36,17 @@ export declare function describeState(state: PullRequestState): string;
39
36
  export declare function prStatusCommand(options: WhereOptions & {
40
37
  json?: boolean;
41
38
  }): Promise<void>;
39
+ /** A wait's length as an agent types it, `90s`, `5m` or `1h`, in milliseconds; refused past an hour or at none (PULL-5.8 to 5.10). */
40
+ export declare function waitFor(duration: string | undefined): number;
42
41
  /**
43
- * `dotreq solution pr wait`: the reviewer waits on the pull request with
44
- * no session running (PULL-5): it records where the pull request stands,
45
- * and its session can end without a result. It starts again, in the same
46
- * session, when the pull request changes and nothing on it is still running
47
- * (PULL-6).
42
+ * `dotreq solution pr wait [duration]`: the reviewer waits on the pull
43
+ * request with no session running (PULL-5), ten minutes unless it says, up
44
+ * to an hour: it records what it saw, and its session can end without a
45
+ * result. It starts again, in the same session, once the pull request is
46
+ * `clean`, once it is merged or closed, or when the wait is up (PULL-6). A
47
+ * pull request already `clean` needs no wait (5.11).
48
48
  */
49
- export declare function prWaitCommand(options: WhereOptions): Promise<void>;
49
+ export declare function prWaitCommand(duration: string | undefined, options: WhereOptions): Promise<void>;
50
50
  /**
51
51
  * `dotreq solution pr open`: the solution's pull request, opened or
52
52
  * found (PULL-2). Inside a runner the branch is pushed first, as a submission
@@ -7,10 +7,7 @@ import { requireWhere } from "./run-file.js";
7
7
  import { outcomeFor } from "./status.js";
8
8
  /** The command that opens the solution's pull request and prints its reference. */
9
9
  export const OPEN_IT = "dotreq solution pr open";
10
- /**
11
- * Where the pull request stood, as a wait records it (PULL-6.4): what a
12
- * reviewer judges by, so a later read that differs is a change.
13
- */
10
+ /** Where the pull request stood, in words, as a wait records it beside what the line shows (PULL-5.1.0). */
14
11
  export function seenOf(state) {
15
12
  return [
16
13
  state.head,
@@ -72,26 +69,63 @@ export async function prStatusCommand(options) {
72
69
  const state = await stateFor(requireWhere(options));
73
70
  console.log(options.json ? JSON.stringify(state) : describeState(state));
74
71
  }
72
+ /** What a reviewer is told when it asks for a wait it can't have (PULL-5.10), in the backend's words. */
73
+ const WAIT_REFUSED = "Nothing is waiting: a wait is up to an hour, ten minutes unless you say, as `dotreq solution pr wait 5m` or `pr wait 1h`.";
74
+ /** A wait's length as an agent types it, `90s`, `5m` or `1h`, in milliseconds; refused past an hour or at none (PULL-5.8 to 5.10). */
75
+ export function waitFor(duration) {
76
+ if (duration === undefined)
77
+ return 10 * 60 * 1000;
78
+ const found = /^(\d+)(s|m|h)$/.exec(duration.trim());
79
+ const unit = { s: 1000, m: 60 * 1000, h: 60 * 60 * 1000 };
80
+ const ms = found ? Number(found[1]) * unit[found[2]] : 0;
81
+ if (!(ms > 0 && ms <= 60 * 60 * 1000))
82
+ throw new Error(WAIT_REFUSED);
83
+ return ms;
84
+ }
85
+ /** In words, how long a wait is. */
86
+ function forHowLong(ms) {
87
+ if (ms === 3_600_000)
88
+ return "an hour";
89
+ if (ms % 60_000 !== 0) {
90
+ const seconds = Math.round(ms / 1000);
91
+ return `${seconds} second${seconds === 1 ? "" : "s"}`;
92
+ }
93
+ const minutes = ms / 60_000;
94
+ return `${minutes} minute${minutes === 1 ? "" : "s"}`;
95
+ }
75
96
  /**
76
- * `dotreq solution pr wait`: the reviewer waits on the pull request with
77
- * no session running (PULL-5): it records where the pull request stands,
78
- * and its session can end without a result. It starts again, in the same
79
- * session, when the pull request changes and nothing on it is still running
80
- * (PULL-6).
97
+ * `dotreq solution pr wait [duration]`: the reviewer waits on the pull
98
+ * request with no session running (PULL-5), ten minutes unless it says, up
99
+ * to an hour: it records what it saw, and its session can end without a
100
+ * result. It starts again, in the same session, once the pull request is
101
+ * `clean`, once it is merged or closed, or when the wait is up (PULL-6). A
102
+ * pull request already `clean` needs no wait (5.11).
81
103
  */
82
- export async function prWaitCommand(options) {
104
+ export async function prWaitCommand(duration, options) {
105
+ const forMs = waitFor(duration);
83
106
  const where = requireWhere(options);
84
107
  const state = await stateFor(where);
108
+ if (state.mergeState === "clean") {
109
+ throw new Error(`Nothing is waiting: the pull request is already \`clean\`.\n\n${describeState(state)}`);
110
+ }
85
111
  await solutionClient().mutation(api.solutions.waits.waitOnPullRequest, {
86
112
  solutionId: where.solutionId,
87
113
  agent: where.agent,
88
114
  ...(where.outcome ? { outcome: where.outcome } : {}),
89
115
  seen: seenOf(state),
116
+ saw: {
117
+ number: state.number,
118
+ url: state.url,
119
+ conflicting: state.mergeable === "conflicting",
120
+ failed: state.failed.length,
121
+ running: state.running.length,
122
+ },
123
+ forMs,
90
124
  });
91
125
  console.log([
92
126
  describeState(state),
93
127
  "",
94
- "Waiting on it. End your session now: you'll be started again, here, when it changes and nothing on it is still running.",
128
+ `Waiting on it. End your session now: you'll be started again, here, once it is \`clean\`, once it is merged or closed, or in ${forHowLong(forMs)}, whichever comes first.`,
95
129
  ].join("\n"));
96
130
  }
97
131
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@popoverai/dotrequirements",
3
- "version": "0.36.0",
3
+ "version": "0.36.1",
4
4
  "description": "Requirements as testable, human-readable data — CLI and test harness for spec-driven development with AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {