Public: anyone can read this; the crew can change it.

An open issue the crew found done on main is held as done_on_main, not stalled, and never handed back to the planner #2508

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/2502-an-open-issue-the-crew-found-done-on-mai → main 2 commits fork 1 thread · 1 unresolved

  • Merged. scout/2502-an-open-issue-the-crew-found-done-on-mai was merged into main as 89fde53.

Review

Sign in to review this change.
1 file changed +37 −0
test/crew-held.test.ts +37
@@ -223,6 +223,43 @@ describe("the tick says why each ready issue cannot start", () => {
223223 expect(replannable(again).map((i) => i.number)).toEqual([done.number]);
224224 });
225225
226 test("an issue the crew found done on main is held as done_on_main, not replannable", async () => {
227 const { repo, mason } = await crewed(app, alice, "finished");
228 const oid = "a".repeat(40);
229 const at = (id: string, ago: number) =>
230 app.db.query("UPDATE comment SET created_at = ?2 WHERE id = ?1").run(id, minutes(ago));
231 const say = (i: Issue, body: string, ago: number) => {
232 const c = addComment(app, alice, getRepoById(app.db, repo.id)!, getIssueById(app.db, i.id)!, body);
233 if (!c.ok) throw new Error(String(c.error));
234 at(c.value.id, ago);
235 };
236 const done = issue(repo, "Already done");
237 ran(repo, done, mason, "declined: it is done", 30);
238 say(done, `${DONE_NOTE}${oid}`, 20);
239 const reparked = issue(repo, "Done, then parked");
240 ran(repo, reparked, mason, "declined: it is done", 30);
241 say(reparked, `${DONE_NOTE}${oid}`, 20);
242 say(reparked, `${PARK_NOTE}not so`, 10);
243 ran(repo, reparked, mason, "declined: it is not done", 5);
244 const spoken = issue(repo, "Done, then a word");
245 ran(repo, spoken, mason, "declined: it is done", 30);
246 say(spoken, `${DONE_NOTE}${oid}`, 20);
247 say(spoken, "Please try again", 10);
248
249 const held = heldNow(app, getRepoById(app.db, repo.id)!);
250 const named = (h: keyof typeof held.by) => held.by[h].map((i) => i.number);
251 expect(named("done_on_main")).toContain(done.number);
252 expect(named("stalled")).not.toContain(done.number);
253 expect(replannable(held).map((i) => i.number)).not.toContain(done.number);
254 // A later park is a newer word: it is the planner's to re-plan again.
255 expect(named("done_on_main")).not.toContain(reparked.number);
256 expect(replannable(held).map((i) => i.number)).toContain(reparked.number);
257 // A person's comment after the done note does not make it startable.
258 expect(held.startable.map((r) => r.issue.number)).not.toContain(spoken.number);
259 expect(named("done_on_main")).toContain(spoken.number);
260 expect(heldWords(held)).toContain("done_on_main=");
261 });
262
226263 test("nothing startable with a slot free asks the planner once, with the breakdown, whatever the plate", async () => {
227264 const { repo, atlas, mason } = await crewed(app, alice, "stuck");
228265 const fresh = () => getRepoById(app.db, repo.id)!;

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs