@wrenautomation/aerie 0.8.5 → 0.8.7

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 (43) hide show
  1. package/dist/backlog/files.d.ts +2 -0
  2. package/dist/backlog/files.js +8 -0
  3. package/dist/backlog/files.js.map +1 -1
  4. package/dist/backlog/index.d.ts +1 -1
  5. package/dist/backlog/index.js +1 -1
  6. package/dist/backlog/index.js.map +1 -1
  7. package/dist/bin.js +232 -37
  8. package/dist/bin.js.map +4 -4
  9. package/dist/cli-run.d.ts +2 -0
  10. package/dist/cli-run.js +39 -9
  11. package/dist/cli-run.js.map +1 -1
  12. package/dist/cli.js +31 -22
  13. package/dist/cli.js.map +1 -1
  14. package/dist/coord/audit.d.ts +45 -0
  15. package/dist/coord/audit.js +64 -0
  16. package/dist/coord/audit.js.map +1 -0
  17. package/dist/coord/port.d.ts +19 -0
  18. package/dist/coord/postgres.d.ts +5 -1
  19. package/dist/coord/postgres.js +30 -8
  20. package/dist/coord/postgres.js.map +1 -1
  21. package/dist/core/task.d.ts +4 -1
  22. package/dist/core/task.js +9 -0
  23. package/dist/core/task.js.map +1 -1
  24. package/dist/http.d.ts +4 -24
  25. package/dist/http.js +5 -4
  26. package/dist/http.js.map +1 -1
  27. package/dist/mirror.d.ts +2 -0
  28. package/dist/mirror.js +15 -1
  29. package/dist/mirror.js.map +1 -1
  30. package/dist/peers-coord.js +95 -11
  31. package/dist/peers-coord.js.map +2 -2
  32. package/dist/remote.js +7 -0
  33. package/dist/remote.js.map +1 -1
  34. package/dist/schema.d.ts +181 -0
  35. package/dist/schema.js +21 -0
  36. package/dist/schema.js.map +1 -1
  37. package/dist/store.d.ts +1 -0
  38. package/dist/store.js +29 -1
  39. package/dist/store.js.map +1 -1
  40. package/drizzle/0013_coord_lease_event.sql +16 -0
  41. package/drizzle/meta/0013_snapshot.json +2049 -0
  42. package/drizzle/meta/_journal.json +7 -0
  43. package/package.json +1 -1
@@ -20,5 +20,7 @@ export interface Milestone {
20
20
  export declare function readMilestones(root: string): Milestone[];
21
21
  /** Backlog.md's name for a new file; an existing file keeps its name when the title changes. */
22
22
  export declare function fileName(t: Pick<Task, "id" | "title">): string;
23
+ /** `statuses` from the board's config.yml, or null */
24
+ export declare function boardStatuses(root: string): string[] | null;
23
25
  /** `task_prefix` from the board's config.yml, or null. */
24
26
  export declare function taskPrefix(root: string): string | null;
@@ -60,6 +60,14 @@ export function fileName(t) {
60
60
  .replace(/-+/g, "-");
61
61
  return `${t.id.toLowerCase()} - ${slug}.md`;
62
62
  }
63
+ /** `statuses` from the board's config.yml, or null */
64
+ export function boardStatuses(root) {
65
+ const file = join(root, "config.yml");
66
+ if (!existsSync(file))
67
+ return null;
68
+ const v = load(readFileSync(file, "utf8"))?.statuses;
69
+ return Array.isArray(v) && v.length && v.every((x) => typeof x === "string") ? v : null;
70
+ }
63
71
  /** `task_prefix` from the board's config.yml, or null. */
64
72
  export function taskPrefix(root) {
65
73
  const file = join(root, "config.yml");
@@ -1 +1 @@
1
- {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/backlog/files.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/backlog/files.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAUvC,MAAM,KAAK,GAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAC;AAE9E;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,GAAc;IACpD,MAAM,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC7D,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC9B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,CAAC;QAChC,OAAO,WAAW,CAAC,GAAG,CAAC;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;aAChC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;aACtE,IAAI,EAAE;aACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACT,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC5B,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;YACpD,IAAI,CAAC;gBACH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YACtD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;YACxD,CAAC;QACH,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACL,CAAC;AAQD,yEAAyE;AACzE,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACrC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,OAAO,WAAW,CAAC,GAAG,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,6CAA6C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAA4B,CAAC;QAClE,IAAI,EAAE,CAAC,EAAE,IAAI,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAC7D,MAAM,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/E,OAAO;YACL,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YACjB,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;YAChC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxC,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,QAAQ,CAAC,CAA6B;IACpD,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK;SACjB,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC;SACjC,IAAI,EAAE;SACN,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvB,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,IAAI,KAAK,CAAC;AAC9C,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,CAAC,GAAI,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAmC,EAAE,QAAQ,CAAC;IACxF,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1F,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,CAAC,GAAG,iDAAiD,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7F,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACxB,CAAC"}
@@ -1,3 +1,3 @@
1
- export { type BoardFile, fileName, type Milestone, readBoard, readMilestones, taskPrefix, } from "./files.js";
1
+ export { type BoardFile, boardStatuses, fileName, type Milestone, readBoard, readMilestones, taskPrefix, } from "./files.js";
2
2
  export { parseTask, SECTIONS } from "./parse.js";
3
3
  export { renderTask } from "./render.js";
@@ -1,4 +1,4 @@
1
- export { fileName, readBoard, readMilestones, taskPrefix, } from "./files.js";
1
+ export { boardStatuses, fileName, readBoard, readMilestones, taskPrefix, } from "./files.js";
2
2
  export { parseTask, SECTIONS } from "./parse.js";
3
3
  export { renderTask } from "./render.js";
4
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backlog/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAER,SAAS,EACT,cAAc,EACd,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backlog/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,aAAa,EACb,QAAQ,EAER,SAAS,EACT,cAAc,EACd,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
package/dist/bin.js CHANGED
@@ -11,6 +11,11 @@ var __export = (target, all) => {
11
11
  };
12
12
 
13
13
  // src/core/task.ts
14
+ function statusIn(all, s) {
15
+ const hit = all.find((x) => x.toLowerCase() === s.trim().toLowerCase());
16
+ if (!hit) throw new Error(`unknown status "${s}" (one of: ${all.join(", ")})`);
17
+ return hit;
18
+ }
14
19
  function instant(v) {
15
20
  if (v == null || v === "") return void 0;
16
21
  if (v instanceof Date) return v.toISOString().replace(/\.\d{3}Z$/, "Z");
@@ -37,6 +42,7 @@ var init_task = __esm({
37
42
  STATUSES = [
38
43
  "To Do",
39
44
  "In Progress",
45
+ "In Testing",
40
46
  "Needs Human Input",
41
47
  "Backlog",
42
48
  "Parked",
@@ -30266,7 +30272,7 @@ function oneOf(name, col, values) {
30266
30272
  const list2 = values.map((v) => `'${v.replaceAll("'", "''")}'`).join(", ");
30267
30273
  return check2(name, sql.raw(`"${col.name}" IN (${list2})`));
30268
30274
  }
30269
- var aerie, ACTOR_KINDS, AREA_ROLES, TASK_ROLES, LAYOUTS, PLACES, at, area, actor, areaRole, task, taskArea, taskActor, taskHolder, view, tsvector, taskEvent, milestone, mirrorFile, setting, coordGen, coordLease, coordClosing, coordTask, coordQueue, decision, routeRule, intake2, remoteCall;
30275
+ var aerie, ACTOR_KINDS, AREA_ROLES, TASK_ROLES, LAYOUTS, PLACES, at, area, actor, areaRole, task, taskArea, taskActor, taskHolder, view, tsvector, taskEvent, milestone, mirrorFile, setting, coordGen, coordLease, coordClosing, coordTask, coordLeaseEvent, coordQueue, decision, routeRule, intake2, remoteCall;
30270
30276
  var init_schema2 = __esm({
30271
30277
  "src/schema.ts"() {
30272
30278
  "use strict";
@@ -30565,6 +30571,27 @@ var init_schema2 = __esm({
30565
30571
  },
30566
30572
  (t) => [primaryKey({ columns: [t.ns, t.taskId], name: "pk_coord_task" })]
30567
30573
  );
30574
+ coordLeaseEvent = aerie.table(
30575
+ "coord_lease_event",
30576
+ {
30577
+ id: bigserial({ mode: "number" }).notNull(),
30578
+ ns: text2().notNull(),
30579
+ taskId: text2("task_id").notNull(),
30580
+ holder: text2().notNull(),
30581
+ gen: bigint4({ mode: "number" }).notNull(),
30582
+ /** claim | take (from the queue) | reclaim | release | done | expire (freed by `by`) | lost (lapsed, seen at renew) | reap (lapsed run lane) */
30583
+ kind: text2().notNull(),
30584
+ queued: boolean4().notNull(),
30585
+ expires: at("expires").notNull(),
30586
+ by: text2().notNull(),
30587
+ at: at("at").notNull()
30588
+ },
30589
+ (t) => [
30590
+ primaryKey({ columns: [t.id], name: "pk_coord_lease_event" }),
30591
+ index("coord_lease_event_task_idx").on(t.ns, t.taskId),
30592
+ index("coord_lease_event_at_idx").on(t.ns, t.at)
30593
+ ]
30594
+ );
30568
30595
  coordQueue = aerie.table(
30569
30596
  "coord_queue",
30570
30597
  {
@@ -31163,6 +31190,8 @@ function aerieStore(o) {
31163
31190
  async function create(input2, by, opts = {}) {
31164
31191
  const id = await write3(by, async (tx) => {
31165
31192
  const parent = input2.parentId ? await must(input2.parentId, tx) : null;
31193
+ if (input2.status !== void 0)
31194
+ input2 = { ...input2, status: await statusName(tx, input2.status) };
31166
31195
  if (input2.milestone)
31167
31196
  input2 = { ...input2, milestone: await milestoneOf(tx, input2.milestone) };
31168
31197
  const id2 = await nextId(tx, parent?.id);
@@ -31201,6 +31230,7 @@ function aerieStore(o) {
31201
31230
  if (opts.expect !== void 0 && opts.expect !== row.version)
31202
31231
  throw new AerieError(`stale: ${row.id} is at version ${row.version}`, 409);
31203
31232
  const was = await must(row.id, tx);
31233
+ if (e.status !== void 0) e = { ...e, status: await statusName(tx, e.status) };
31204
31234
  if (e.parentId) e = { ...e, parentId: (await must(e.parentId, tx)).id };
31205
31235
  if (e.milestone) e = { ...e, milestone: await milestoneOf(tx, e.milestone) };
31206
31236
  const t = applyEdit(was, e, now());
@@ -31320,7 +31350,7 @@ function aerieStore(o) {
31320
31350
  if (Object.keys(set3).length) await tx.update(actor).set(set3).where(eq(actor.id, id));
31321
31351
  });
31322
31352
  }
31323
- async function statusOf2(ids) {
31353
+ async function statusOf(ids) {
31324
31354
  if (!ids.length) return /* @__PURE__ */ new Map();
31325
31355
  const rows3 = await db.select({ id: task.id, status: task.status }).from(task).where(inArray(sql`upper(${task.id})`, [...new Set(ids.map((x) => x.toUpperCase()))]));
31326
31356
  return new Map(rows3.map((r) => [r.id.toUpperCase(), r.status]));
@@ -31335,6 +31365,22 @@ function aerieStore(o) {
31335
31365
  dependencies: task.dependencies
31336
31366
  }).from(task);
31337
31367
  }
31368
+ async function statuses(q = db) {
31369
+ const r = await q.select({ v: setting.value }).from(setting).where(eq(setting.key, "statuses"));
31370
+ try {
31371
+ const v = JSON.parse(r[0]?.v ?? "null");
31372
+ if (Array.isArray(v) && v.length && v.every((x) => typeof x === "string")) return v;
31373
+ } catch {
31374
+ }
31375
+ return [...STATUSES];
31376
+ }
31377
+ async function statusName(q, v) {
31378
+ try {
31379
+ return statusIn(await statuses(q), v);
31380
+ } catch (e) {
31381
+ throw new AerieError(e.message);
31382
+ }
31383
+ }
31338
31384
  async function getSetting(key) {
31339
31385
  const r = await db.select({ v: setting.value }).from(setting).where(eq(setting.key, key));
31340
31386
  return r[0]?.v ?? null;
@@ -31492,7 +31538,7 @@ function aerieStore(o) {
31492
31538
  setActor,
31493
31539
  milestones,
31494
31540
  putMilestones,
31495
- statusOf: statusOf2,
31541
+ statusOf,
31496
31542
  dependencyRows,
31497
31543
  mirrorFiles,
31498
31544
  setMirrorFile,
@@ -31505,6 +31551,7 @@ function aerieStore(o) {
31505
31551
  ask,
31506
31552
  decide,
31507
31553
  prefixOf,
31554
+ statuses,
31508
31555
  getSetting,
31509
31556
  setSetting
31510
31557
  };
@@ -33024,6 +33071,7 @@ function pgCoord(o) {
33024
33071
  const C = coordClosing;
33025
33072
  const T = coordTask;
33026
33073
  const Q = coordQueue;
33074
+ const E = coordLeaseEvent;
33027
33075
  const lockQueue = (tx) => tx.execute(
33028
33076
  sql`select pg_advisory_xact_lock(hashtextextended(${`aerie.coord:${ns}:queue`}, 0))`
33029
33077
  );
@@ -33043,7 +33091,7 @@ function pgCoord(o) {
33043
33091
  if (!hit[0] || hit[0].status === name) return;
33044
33092
  await aerieStore({ db: tx }).edit(id, { status: name }, by);
33045
33093
  };
33046
- const lease = async (tx, id, holder, leaseMs, queued, key) => {
33094
+ const lease = async (tx, id, holder, leaseMs, queued, key, how = "claim") => {
33047
33095
  const t = clock();
33048
33096
  const others = await rows2(
33049
33097
  tx,
@@ -33056,13 +33104,17 @@ function pgCoord(o) {
33056
33104
  );
33057
33105
  const gen = num(g?.gen);
33058
33106
  await tx.execute(sql`
33059
- insert into ${L} (ns, task_id, holder, gen, expires, queued, lane, pin, take_key)
33107
+ with up as (insert into ${L} (ns, task_id, holder, gen, expires, queued, lane, pin, take_key)
33060
33108
  values (${ns}, ${id}, ${holder}, ${gen}, ${plus(t, leaseMs)}, ${!!queued}, ${queued?.lane ?? null}, ${queued?.pin ?? null}, ${key ?? null})
33061
33109
  on conflict (ns, task_id, holder) do update set gen = excluded.gen, expires = excluded.expires,
33062
33110
  take_key = coalesce(excluded.take_key, ${L}.take_key),
33063
33111
  queued = excluded.queued or ${L}.queued,
33064
33112
  lane = case when excluded.queued then excluded.lane else ${L}.lane end,
33065
- pin = case when excluded.queued then excluded.pin else ${L}.pin end`);
33113
+ pin = case when excluded.queued then excluded.pin else ${L}.pin end
33114
+ returning task_id, holder, gen, queued, expires, (xmax = 0) as fresh)
33115
+ insert into ${E} (ns, task_id, holder, gen, kind, queued, expires, by, at)
33116
+ select ${ns}, task_id, holder, gen, case when fresh then ${how} else 'reclaim' end, queued, expires, holder, ${t}
33117
+ from up`);
33066
33118
  await touch(tx, id, t);
33067
33119
  await setStatus(tx, id, "doing", holder);
33068
33120
  return { gen, others: others.map((r) => r.holder) };
@@ -33075,8 +33127,13 @@ function pgCoord(o) {
33075
33127
  if (!has.length) return { last: true, closeNow: false, status: "ready" };
33076
33128
  const gone = await rows2(
33077
33129
  tx,
33078
- sql`delete from ${L} where ns = ${ns} and task_id = ${id} and holder = any(${textArr(holders)})
33079
- returning holder, queued, lane, pin`
33130
+ sql`with gone as (delete from ${L} where ns = ${ns} and task_id = ${id} and holder = any(${textArr(holders)})
33131
+ returning holder, gen, queued, lane, pin, expires),
33132
+ logged as (insert into ${E} (ns, task_id, holder, gen, kind, queued, expires, by, at)
33133
+ select ${ns}, ${id}, holder, gen,
33134
+ case when holder <> ${x.by} then 'expire' else ${x.done ? "done" : x.why ?? "release"} end,
33135
+ queued, expires, ${x.by}, ${t} from gone)
33136
+ select holder, queued, lane, pin from gone`
33080
33137
  );
33081
33138
  if (x.done && gone.some((l) => l.holder === x.by))
33082
33139
  await tx.execute(sql`insert into ${C} (ns, task_id, holder, reason, at)
@@ -33156,7 +33213,7 @@ function pgCoord(o) {
33156
33213
  );
33157
33214
  if (!still.length) continue;
33158
33215
  lost.push({ id: l.id, holder: l.holder });
33159
- await drop(tx, l.id, [l.holder], { queue: l.queued, by: l.holder });
33216
+ await drop(tx, l.id, [l.holder], { queue: l.queued, by: l.holder, why: "lost" });
33160
33217
  }
33161
33218
  }
33162
33219
  await tx.execute(sql`update ${L} set expires = ${plus(t, leaseMs)}
@@ -33284,7 +33341,8 @@ function pgCoord(o) {
33284
33341
  sql`select 1 from ${L} where ns = ${ns} and task_id = ${l.id} and holder = ${l.holder}
33285
33342
  and expires < ${t}`
33286
33343
  );
33287
- if (still.length) await drop(tx, l.id, [l.holder], { queue: l.queued, by: l.holder });
33344
+ if (still.length)
33345
+ await drop(tx, l.id, [l.holder], { queue: l.queued, by: l.holder, why: "reap" });
33288
33346
  }
33289
33347
  }
33290
33348
  if (x.cap !== void 0) {
@@ -33314,10 +33372,28 @@ function pgCoord(o) {
33314
33372
  holder,
33315
33373
  leaseMs,
33316
33374
  { lane: item.lane, pin: item.pin },
33317
- x.key
33375
+ x.key,
33376
+ "take"
33318
33377
  );
33319
33378
  return { id: item.id, gen: r.gen };
33320
33379
  }),
33380
+ leaseEvents: async ({ since, limit = 1e4 }) => (await rows2(
33381
+ db,
33382
+ sql`select id::float8 as id, task_id, holder, gen::float8 as gen, kind, queued, ${ms(sql`expires`)} as expires,
33383
+ by, ${ms(sql`at`)} as at from ${E} where ns = ${ns} and at >= ${at3(since)} order by id limit ${limit}`
33384
+ )).map(
33385
+ (r) => ({
33386
+ id: num(r.id),
33387
+ task: String(r.task_id),
33388
+ holder: String(r.holder),
33389
+ gen: num(r.gen),
33390
+ kind: r.kind,
33391
+ queued: !!r.queued,
33392
+ expires: num(r.expires),
33393
+ by: String(r.by),
33394
+ at: num(r.at)
33395
+ })
33396
+ ),
33321
33397
  fence: async (id, holder, gen) => (await rows2(
33322
33398
  db,
33323
33399
  sql`select 1 from ${L} where ns = ${ns} and task_id = ${id} and holder = ${holder}
@@ -33424,7 +33500,8 @@ var init_http = __esm({
33424
33500
  EDIT = {
33425
33501
  title: external_exports.string().trim().min(1).max(500).optional(),
33426
33502
  description: TEXT.optional(),
33427
- status: external_exports.enum(STATUSES).optional(),
33503
+ status: external_exports.string().trim().min(1).max(100).optional(),
33504
+ // the store checks it against the board
33428
33505
  priority: external_exports.enum(["high", "medium", "low"]).nullish(),
33429
33506
  type: external_exports.string().max(100).nullish(),
33430
33507
  milestone: external_exports.string().max(200).nullish(),
@@ -33734,6 +33811,7 @@ var init_remote = __esm({
33734
33811
  ]),
33735
33812
  views: read([BY], 0),
33736
33813
  prefixOf: read(),
33814
+ statuses: read(),
33737
33815
  mirrorAreas: read(),
33738
33816
  getSetting: read([external_exports.string().min(1).max(100)]),
33739
33817
  create: write2(
@@ -33876,7 +33954,13 @@ var init_remote = __esm({
33876
33954
  HOLDER,
33877
33955
  MS
33878
33956
  ]),
33879
- fence: read([ID2, HOLDER, external_exports.int().nonnegative()])
33957
+ fence: read([ID2, HOLDER, external_exports.int().nonnegative()]),
33958
+ leaseEvents: read([
33959
+ external_exports.strictObject({
33960
+ since: external_exports.number().nonnegative(),
33961
+ limit: external_exports.int().positive().max(1e4).optional()
33962
+ })
33963
+ ])
33880
33964
  };
33881
33965
  OPS = { store: STORE_OPS, coord: COORD_OPS };
33882
33966
  CALL = external_exports.object({
@@ -40139,6 +40223,12 @@ function fileName(t) {
40139
40223
  const slug = t.title.replace(/[^A-Za-z0-9._\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-");
40140
40224
  return `${t.id.toLowerCase()} - ${slug}.md`;
40141
40225
  }
40226
+ function boardStatuses(root) {
40227
+ const file2 = join(root, "config.yml");
40228
+ if (!existsSync(file2)) return null;
40229
+ const v = load(readFileSync(file2, "utf8"))?.statuses;
40230
+ return Array.isArray(v) && v.length && v.every((x) => typeof x === "string") ? v : null;
40231
+ }
40142
40232
  function taskPrefix(root) {
40143
40233
  const file2 = join(root, "config.yml");
40144
40234
  if (!existsSync(file2)) return null;
@@ -40739,6 +40829,69 @@ function registerIntakeCommands(program3, ctx) {
40739
40829
  );
40740
40830
  }
40741
40831
 
40832
+ // src/coord/audit.ts
40833
+ var START = /* @__PURE__ */ new Set(["claim", "take", "reclaim"]);
40834
+ function leaseAudit(events, held, o) {
40835
+ const starts = {};
40836
+ const ends = {};
40837
+ const doubleDelivery = [];
40838
+ const orphans = [];
40839
+ const mins = (ms2) => Math.round(ms2 / 6e3) / 10;
40840
+ const open3 = /* @__PURE__ */ new Map();
40841
+ for (const e of [...events].sort((a, b) => a.id - b.id)) {
40842
+ const byTask = open3.get(e.task) ?? /* @__PURE__ */ new Map();
40843
+ open3.set(e.task, byTask);
40844
+ if (START.has(e.kind)) {
40845
+ starts[e.kind] = (starts[e.kind] ?? 0) + 1;
40846
+ if (!e.queued) continue;
40847
+ const had = byTask.get(e.holder);
40848
+ if (e.kind !== "reclaim" || !had) {
40849
+ const others = [...byTask].filter(([h]) => h !== e.holder);
40850
+ if (others.length)
40851
+ doubleDelivery.push({
40852
+ task: e.task,
40853
+ holder: e.holder,
40854
+ at: e.at,
40855
+ open: others.map(([h, l]) => ({ holder: h, since: l.since }))
40856
+ });
40857
+ }
40858
+ byTask.set(e.holder, { since: had?.since ?? e.at });
40859
+ continue;
40860
+ }
40861
+ ends[e.kind] = (ends[e.kind] ?? 0) + 1;
40862
+ byTask.delete(e.holder);
40863
+ if ((e.kind === "expire" || e.kind === "reap") && e.at - e.expires > o.graceMs)
40864
+ orphans.push({
40865
+ task: e.task,
40866
+ holder: e.holder,
40867
+ expires: e.expires,
40868
+ lapsedMin: mins(e.at - e.expires),
40869
+ freed: { kind: e.kind, by: e.by, at: e.at }
40870
+ });
40871
+ }
40872
+ for (const t of held)
40873
+ for (const l of t.holders)
40874
+ if (o.now - l.expires > o.graceMs)
40875
+ orphans.push({
40876
+ task: t.id,
40877
+ holder: l.holder,
40878
+ expires: l.expires,
40879
+ lapsedMin: mins(o.now - l.expires),
40880
+ freed: null
40881
+ });
40882
+ return {
40883
+ since: o.since,
40884
+ until: o.now,
40885
+ graceMin: mins(o.graceMs),
40886
+ events: events.length,
40887
+ starts,
40888
+ ends,
40889
+ doubleDelivery,
40890
+ orphans,
40891
+ ok: !doubleDelivery.length && !orphans.length
40892
+ };
40893
+ }
40894
+
40742
40895
  // src/cli-run.ts
40743
40896
  init_core3();
40744
40897
 
@@ -41496,18 +41649,21 @@ async function work(o) {
41496
41649
 
41497
41650
  // src/cli-run.ts
41498
41651
  var each = (v, prev = []) => [...prev, v];
41652
+ function sinceOf(v, now) {
41653
+ const m = /^(\d+(?:\.\d+)?)([dh])$/.exec(v);
41654
+ if (m) return now - Number(m[1]) * (m[2] === "d" ? 864e5 : 36e5);
41655
+ const t = Date.parse(v);
41656
+ if (Number.isNaN(t)) throw new Error(`aerie: --since ${v}: give an ISO time or Nd / Nh`);
41657
+ return t;
41658
+ }
41499
41659
  var print2 = (x) => void process.stdout.write(typeof x === "string" ? x : `${JSON.stringify(x, null, 2)}
41500
41660
  `);
41501
41661
  async function pickerOf(a) {
41502
41662
  const spec = await a.getSetting("router_model");
41503
41663
  return spec ? modelPicker(spec) : void 0;
41504
41664
  }
41505
- function ruleFilter(o) {
41506
- const status = (o.status ?? []).map((x) => {
41507
- const hit = STATUSES.find((s) => s.toLowerCase() === x.toLowerCase());
41508
- if (!hit) throw new Error(`unknown status "${x}"`);
41509
- return hit;
41510
- });
41665
+ function ruleFilter(o, statuses) {
41666
+ const status = (o.status ?? []).map((x) => statusIn(statuses, x));
41511
41667
  return {
41512
41668
  ...o.area?.length ? { area: o.area } : {},
41513
41669
  ...o.onlyArea ? { subtree: false } : {},
@@ -41558,7 +41714,7 @@ function registerRunCommands(program3, ctx) {
41558
41714
  const o = cmd.optsWithGlobals();
41559
41715
  const r = await a.addRouteRule(
41560
41716
  {
41561
- filter: ruleFilter(o),
41717
+ filter: ruleFilter(o, await a.statuses()),
41562
41718
  runner: runnerOf(o.runner),
41563
41719
  model: o.model ?? null,
41564
41720
  lane: o.lane ?? null,
@@ -41727,6 +41883,27 @@ function registerRunCommands(program3, ctx) {
41727
41883
  ` : "No pool sessions.\n"
41728
41884
  );
41729
41885
  });
41886
+ program3.command("coord").description("the coord store").command("audit").description("double delivery and orphan holders from the lease log (WA-1364.3 AC #5)").option("--since <when>", "ISO time, or Nd / Nh back", "3d").option("--grace <min>", "minutes past expiry before a lease counts as orphaned", "60").option("--json", "JSON out").action(
41887
+ (o) => board(async (_a3, c) => {
41888
+ if (!c.leaseEvents) throw new Error(`aerie: coord store ${c.name} keeps no lease log`);
41889
+ const now = Date.now();
41890
+ const since = sinceOf(String(o.since), now);
41891
+ const [events, held] = await Promise.all([c.leaseEvents({ since }), c.held()]);
41892
+ const r = leaseAudit(events, held, { since, now, graceMs: Number(o.grace) * 6e4 });
41893
+ print2(
41894
+ o.json ? r : `${r.ok ? "ok" : "FAIL"}: ${r.events} lease events since ${new Date(since).toISOString()}; starts ${JSON.stringify(r.starts)}, ends ${JSON.stringify(r.ends)}; ${r.doubleDelivery.length} double deliveries, ${r.orphans.length} orphans
41895
+ ${[
41896
+ ...r.doubleDelivery.map(
41897
+ (d) => `double ${d.task} ${d.holder} at ${new Date(d.at).toISOString()}; open: ${d.open.map((x) => x.holder).join(", ")}`
41898
+ ),
41899
+ ...r.orphans.map(
41900
+ (x) => `orphan ${x.task} ${x.holder} ${x.lapsedMin} min past expiry${x.freed ? `, ${x.freed.kind} by ${x.freed.by}` : ", still held"}`
41901
+ )
41902
+ ].map((l) => `${l}
41903
+ `).join("")}`
41904
+ );
41905
+ })
41906
+ );
41730
41907
  program3.command("events").description("the event log across tasks").command("search").argument("<words>", 'web-search words: "a phrase", -not, or').option("--task <id>", "one task").option("--kind <kind>", "one kind, e.g. run.tool or routed").option("--limit <n>", "at most n", "50").option("--json", "JSON out").action(
41731
41908
  (words, o) => ctx.withStore(async (a) => {
41732
41909
  const rs = await a.searchEvents(words, {
@@ -41766,6 +41943,14 @@ init_core3();
41766
41943
  init_store();
41767
41944
  var sha = (s) => createHash("sha256").update(s).digest("hex");
41768
41945
  var ALL = ["tasks", "drafts", "archive/tasks", "archive/drafts"];
41946
+ async function syncStatuses(a, root, by) {
41947
+ const list2 = boardStatuses(root);
41948
+ if (!list2) return false;
41949
+ const v = JSON.stringify(list2);
41950
+ if (await a.getSetting("statuses") === v) return false;
41951
+ await a.setSetting("statuses", v, by);
41952
+ return true;
41953
+ }
41769
41954
  async function mirror(a, root, o = {}) {
41770
41955
  const r = {
41771
41956
  wrote: [],
@@ -41776,6 +41961,7 @@ async function mirror(a, root, o = {}) {
41776
41961
  left: [],
41777
41962
  committed: false
41778
41963
  };
41964
+ if (!o.only && !o.dryRun) await syncStatuses(a, root, o.by ?? "@backlog");
41779
41965
  const areas = new Set(await a.mirrorAreas());
41780
41966
  const state = new Map((await a.mirrorFiles(o.only)).map((m) => [m.taskId, m]));
41781
41967
  const disk = /* @__PURE__ */ new Map();
@@ -42338,12 +42524,6 @@ var nums = (v, prev = []) => [
42338
42524
  ];
42339
42525
  var print3 = (x) => void process.stdout.write(typeof x === "string" ? x : `${JSON.stringify(x, null, 2)}
42340
42526
  `);
42341
- function statusOf(s) {
42342
- if (s === void 0) return void 0;
42343
- const hit = STATUSES.find((x) => x.toLowerCase() === s.trim().toLowerCase());
42344
- if (!hit) throw new Error(`unknown status "${s}" (one of: ${STATUSES.join(", ")})`);
42345
- return hit;
42346
- }
42347
42527
  function checksEdit(o, k) {
42348
42528
  const K = k === "ac" ? "Ac" : "Dod";
42349
42529
  const e = {
@@ -42363,7 +42543,7 @@ function editOf(o) {
42363
42543
  };
42364
42544
  put("title", o.title);
42365
42545
  put("description", o.description ?? o.desc);
42366
- put("status", statusOf(o.status));
42546
+ put("status", o.status);
42367
42547
  put("priority", o.priority);
42368
42548
  put("type", o.type);
42369
42549
  put("milestone", o.clearMilestone ? null : o.milestone);
@@ -42414,11 +42594,21 @@ function editFlags(c, create) {
42414
42594
  }
42415
42595
  function registerCommands(program3, ctx) {
42416
42596
  program3.version(ctx.version, "-v, --version");
42597
+ async function statusesOf(a) {
42598
+ return ctx.mirrorDir && boardStatuses(ctx.mirrorDir) || a.statuses();
42599
+ }
42600
+ async function syncBoard(a, o) {
42601
+ if (ctx.mirrorDir && o.status !== void 0) await syncStatuses(a, ctx.mirrorDir, ctx.by);
42602
+ }
42417
42603
  async function show(a, t, o, kind) {
42418
- const [rows3, file2] = await Promise.all([a.dependencyRows(), fileOf(a, t.id)]);
42604
+ const [rows3, file2, statuses] = await Promise.all([
42605
+ a.dependencyRows(),
42606
+ fileOf(a, t.id),
42607
+ statusesOf(a)
42608
+ ]);
42419
42609
  const v = {
42420
42610
  rows: rows3,
42421
- statuses: STATUSES,
42611
+ statuses,
42422
42612
  ...file2 ? { file: file2, path: relative(dirname3(ctx.mirrorDir), file2) } : {},
42423
42613
  ...ctx.exact ? { exact: true } : {}
42424
42614
  };
@@ -42448,6 +42638,7 @@ function registerCommands(program3, ctx) {
42448
42638
  const task2 = program3.command("task").description("tasks, with Backlog.md's flags");
42449
42639
  editFlags(task2.command("create").argument("<title>").description("make a task"), true).action(
42450
42640
  (title, o) => ctx.withStore(async (a) => {
42641
+ await syncBoard(a, o);
42451
42642
  const e = editOf(o);
42452
42643
  if (o.acceptanceCriteria?.length)
42453
42644
  e.ac = { add: [...e.ac?.add ?? [], ...o.acceptanceCriteria] };
@@ -42469,6 +42660,7 @@ ${file2 ? `File: ${file2}
42469
42660
  );
42470
42661
  editFlags(task2.command("edit").argument("<id>").description("change a task"), false).action(
42471
42662
  (id, o) => ctx.withStore(async (a) => {
42663
+ await syncBoard(a, o);
42472
42664
  const e = editOf(o);
42473
42665
  if (o.archive) {
42474
42666
  const cur = await a.get(id);
@@ -42507,8 +42699,9 @@ ${file2 ? `File: ${file2}
42507
42699
  );
42508
42700
  const listCmd = (c) => c.option("-s, --status <status>", "status").option("-a, --assignee <name>", "assignee").option("-l, --label <labels>", "all of these labels", many).option("-p, --parent <id>", "children of").option("-m, --milestone <m>", "milestone id").option("--priority <p>", "priority").option("--type <type>", "type").option("--area <path>", "area and its subtree (repeatable)", each2).option("--only-area", "the area itself, not its subtree").option("--holder <holder>", "held by (peers holder)").option("--open-checks", "some AC or DoD open").option("--all", "drafts and archive too").option("--sort <field[:desc]>", `sort by ${SORT_FIELDS.join(", ")} (repeatable)`, each2).option("--plain", "plain text (default)").option("--json", "JSON");
42509
42701
  async function runList(a, o) {
42702
+ const statuses = await statusesOf(a);
42510
42703
  const f = {
42511
- ...o.status ? { status: [statusOf(o.status)] } : {},
42704
+ ...o.status ? { status: [statusIn(statuses, o.status)] } : {},
42512
42705
  ...o.assignee ? { assignee: o.assignee } : {},
42513
42706
  ...o.label ? { label: o.label } : {},
42514
42707
  ...o.parent ? { parent: (await a.get(o.parent))?.id ?? o.parent } : {},
@@ -42532,9 +42725,9 @@ ${file2 ? `File: ${file2}
42532
42725
  print3({
42533
42726
  schemaVersion: 1,
42534
42727
  kind: "task-list",
42535
- tasks: ts.map((t) => listItem(t, status, STATUSES))
42728
+ tasks: ts.map((t) => listItem(t, status, statuses))
42536
42729
  });
42537
- } else print3(listPlain(ts, STATUSES));
42730
+ } else print3(listPlain(ts, statuses));
42538
42731
  }
42539
42732
  listCmd(task2.command("list").description("list tasks")).action(
42540
42733
  (o) => ctx.withStore((a) => runList(a, o))
@@ -42543,14 +42736,15 @@ ${file2 ? `File: ${file2}
42543
42736
  (query, o) => ctx.withStore(async (a) => {
42544
42737
  if (o.type && o.type !== "task")
42545
42738
  throw new Error(`aerie holds tasks only; ${o.type}s stay in Backlog.md`);
42739
+ const statuses = await statusesOf(a);
42546
42740
  const ts = await a.list({
42547
- ...o.status ? { status: o.status.map(statusOf) } : {},
42741
+ ...o.status ? { status: o.status.map((x) => statusIn(statuses, x)) } : {},
42548
42742
  ...o.priority ? { priority: [o.priority] } : {},
42549
42743
  ...o.taskType ? { type: o.taskType } : {},
42550
42744
  ...o.area ? { area: o.area } : {},
42551
42745
  ...o.all ? { place: ["tasks", "drafts", "archive/tasks", "archive/drafts"] } : {}
42552
42746
  });
42553
- const out = new Set((o.excludeStatus ?? []).map(statusOf));
42747
+ const out = new Set((o.excludeStatus ?? []).map((x) => statusIn(statuses, x)));
42554
42748
  let hits = rank(
42555
42749
  ts.filter((t) => !out.has(t.status)),
42556
42750
  query ?? ""
@@ -42565,7 +42759,7 @@ ${file2 ? `File: ${file2}
42565
42759
  print3({
42566
42760
  schemaVersion: 1,
42567
42761
  kind: "search",
42568
- results: hits.map((h) => ({ type: "task", data: listItem(h.task, status, STATUSES) }))
42762
+ results: hits.map((h) => ({ type: "task", data: listItem(h.task, status, statuses) }))
42569
42763
  });
42570
42764
  } else print3(searchPlain(hits));
42571
42765
  })
@@ -42584,8 +42778,8 @@ ${file2 ? `File: ${file2}
42584
42778
  ];
42585
42779
  const config2 = program3.command("config").description(`board settings: statuses, task_prefix, ${SETTINGS.join(", ")}`);
42586
42780
  config2.command("get").argument("<key>").action(
42587
- (key) => key === "statuses" ? print3(`${STATUSES.join(", ")}
42588
- `) : key === "task_prefix" || key === "prefix" ? ctx.withStore(async (a) => print3(`${(await a.prefixOf()).toLowerCase()}
42781
+ (key) => key === "statuses" ? ctx.withStore(async (a) => print3(`${(await statusesOf(a)).join(", ")}
42782
+ `)) : key === "task_prefix" || key === "prefix" ? ctx.withStore(async (a) => print3(`${(await a.prefixOf()).toLowerCase()}
42589
42783
  `)) : SETTINGS.includes(key) ? ctx.withStore(async (a) => print3(`${await a.getSetting(key) ?? ""}
42590
42784
  `)) : print3("\n")
42591
42785
  );
@@ -42757,6 +42951,7 @@ ${ms2.map((m) => ` ${m.id}: ${m.title} (${m.done}/${m.total} done)`).join("\n")
42757
42951
  }
42758
42952
  const pre = taskPrefix(dir);
42759
42953
  if (pre) await a.setSetting("prefix", pre, ctx.by, true);
42954
+ await syncStatuses(a, dir, ctx.by);
42760
42955
  await a.putMilestones(ms2, ctx.by);
42761
42956
  const r = await a.importTasks(
42762
42957
  files.map((f) => ({ task: f.task, place: f.where })),