@wrenautomation/aerie 0.8.4 → 0.8.6
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.
- package/dist/bin.js +195 -17
- package/dist/bin.js.map +4 -4
- package/dist/cli-run.d.ts +2 -0
- package/dist/cli-run.js +35 -0
- package/dist/cli-run.js.map +1 -1
- package/dist/cli.js +15 -5
- package/dist/cli.js.map +1 -1
- package/dist/coord/audit.d.ts +45 -0
- package/dist/coord/audit.js +64 -0
- package/dist/coord/audit.js.map +1 -0
- package/dist/coord/port.d.ts +19 -0
- package/dist/coord/postgres.d.ts +5 -1
- package/dist/coord/postgres.js +30 -8
- package/dist/coord/postgres.js.map +1 -1
- package/dist/peers-coord.js +90 -11
- package/dist/peers-coord.js.map +2 -2
- package/dist/remote.js +6 -0
- package/dist/remote.js.map +1 -1
- package/dist/schema.d.ts +181 -0
- package/dist/schema.js +23 -0
- package/dist/schema.js.map +1 -1
- package/dist/shim.js +11 -1
- package/dist/shim.js.map +2 -2
- package/dist/store.js +35 -2
- package/dist/store.js.map +1 -1
- package/drizzle/0012_task_event_at.sql +1 -0
- package/drizzle/0013_coord_lease_event.sql +16 -0
- package/drizzle/meta/0012_snapshot.json +1926 -0
- package/drizzle/meta/0013_snapshot.json +2049 -0
- package/drizzle/meta/_journal.json +14 -0
- package/package.json +3 -3
package/dist/bin.js
CHANGED
|
@@ -30266,7 +30266,7 @@ function oneOf(name, col, values) {
|
|
|
30266
30266
|
const list2 = values.map((v) => `'${v.replaceAll("'", "''")}'`).join(", ");
|
|
30267
30267
|
return check2(name, sql.raw(`"${col.name}" IN (${list2})`));
|
|
30268
30268
|
}
|
|
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;
|
|
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, coordLeaseEvent, coordQueue, decision, routeRule, intake2, remoteCall;
|
|
30270
30270
|
var init_schema2 = __esm({
|
|
30271
30271
|
"src/schema.ts"() {
|
|
30272
30272
|
"use strict";
|
|
@@ -30496,6 +30496,8 @@ var init_schema2 = __esm({
|
|
|
30496
30496
|
(t) => [
|
|
30497
30497
|
primaryKey({ columns: [t.seq], name: "pk_task_event" }),
|
|
30498
30498
|
index("task_event_task_idx").on(t.taskId, t.seq),
|
|
30499
|
+
// list updatedAfter: tasks with an event since the cursor (archive keeps updatedAt)
|
|
30500
|
+
index("task_event_at_idx").on(t.at),
|
|
30499
30501
|
index("task_event_words_idx").using("gin", t.words)
|
|
30500
30502
|
]
|
|
30501
30503
|
);
|
|
@@ -30563,6 +30565,27 @@ var init_schema2 = __esm({
|
|
|
30563
30565
|
},
|
|
30564
30566
|
(t) => [primaryKey({ columns: [t.ns, t.taskId], name: "pk_coord_task" })]
|
|
30565
30567
|
);
|
|
30568
|
+
coordLeaseEvent = aerie.table(
|
|
30569
|
+
"coord_lease_event",
|
|
30570
|
+
{
|
|
30571
|
+
id: bigserial({ mode: "number" }).notNull(),
|
|
30572
|
+
ns: text2().notNull(),
|
|
30573
|
+
taskId: text2("task_id").notNull(),
|
|
30574
|
+
holder: text2().notNull(),
|
|
30575
|
+
gen: bigint4({ mode: "number" }).notNull(),
|
|
30576
|
+
/** claim | take (from the queue) | reclaim | release | done | expire (freed by `by`) | lost (lapsed, seen at renew) | reap (lapsed run lane) */
|
|
30577
|
+
kind: text2().notNull(),
|
|
30578
|
+
queued: boolean4().notNull(),
|
|
30579
|
+
expires: at("expires").notNull(),
|
|
30580
|
+
by: text2().notNull(),
|
|
30581
|
+
at: at("at").notNull()
|
|
30582
|
+
},
|
|
30583
|
+
(t) => [
|
|
30584
|
+
primaryKey({ columns: [t.id], name: "pk_coord_lease_event" }),
|
|
30585
|
+
index("coord_lease_event_task_idx").on(t.ns, t.taskId),
|
|
30586
|
+
index("coord_lease_event_at_idx").on(t.ns, t.at)
|
|
30587
|
+
]
|
|
30588
|
+
);
|
|
30566
30589
|
coordQueue = aerie.table(
|
|
30567
30590
|
"coord_queue",
|
|
30568
30591
|
{
|
|
@@ -30864,7 +30887,15 @@ function aerieStore(o) {
|
|
|
30864
30887
|
)
|
|
30865
30888
|
);
|
|
30866
30889
|
const ctx = f.role ? { grants: await grants() } : {};
|
|
30867
|
-
|
|
30890
|
+
const since = f.updatedAfter;
|
|
30891
|
+
if (!since) return all.filter((t) => matches(t, f, ctx)).sort(compare(sorts));
|
|
30892
|
+
const { updatedAfter: _, ...rest } = f;
|
|
30893
|
+
const moved = new Set(
|
|
30894
|
+
(await db.selectDistinct({ id: taskEvent.taskId }).from(taskEvent).where(gte(taskEvent.at, since))).map((r) => r.id)
|
|
30895
|
+
);
|
|
30896
|
+
return all.filter(
|
|
30897
|
+
(t) => matches(t, rest, ctx) && ((t.updatedAt ?? t.createdAt) >= since || moved.has(t.id))
|
|
30898
|
+
).sort(compare(sorts));
|
|
30868
30899
|
}
|
|
30869
30900
|
async function views(owner) {
|
|
30870
30901
|
const rows3 = await db.select().from(view).where(eq(view.owner, owner)).orderBy(asc(view.name));
|
|
@@ -31145,6 +31176,11 @@ function aerieStore(o) {
|
|
|
31145
31176
|
await tx.insert(setting).values({ key, value }).onConflictDoUpdate({ target: setting.key, set: { value } });
|
|
31146
31177
|
return `${base}${max + 1}`;
|
|
31147
31178
|
}
|
|
31179
|
+
async function tailOrdinal(tx) {
|
|
31180
|
+
const [r] = await tx.select({ top: sql`max(${task.ordinal})`, n: sql`count(*)::int` }).from(task).where(eq(task.place, "tasks"));
|
|
31181
|
+
if (r && r.top !== null) return Number(r.top) + 1e3;
|
|
31182
|
+
return r?.n ? void 0 : 1e3;
|
|
31183
|
+
}
|
|
31148
31184
|
async function create(input2, by, opts = {}) {
|
|
31149
31185
|
const id = await write3(by, async (tx) => {
|
|
31150
31186
|
const parent = input2.parentId ? await must(input2.parentId, tx) : null;
|
|
@@ -31168,6 +31204,10 @@ function aerieStore(o) {
|
|
|
31168
31204
|
};
|
|
31169
31205
|
const t = applyEdit(blank, { ...input2, ...parent ? { parentId: parent.id } : {} }, at4);
|
|
31170
31206
|
delete t.updatedAt;
|
|
31207
|
+
if (t.ordinal === void 0 && (input2.place ?? "tasks") === "tasks") {
|
|
31208
|
+
const tail2 = await tailOrdinal(tx);
|
|
31209
|
+
if (tail2 !== void 0) t.ordinal = tail2;
|
|
31210
|
+
}
|
|
31171
31211
|
const area2 = input2.area ?? parent?.area ?? areaFor(t, rules);
|
|
31172
31212
|
await put(tx, t, await ensureArea(tx, area2), input2.place ?? "tasks");
|
|
31173
31213
|
await setAliases(tx, id2, input2);
|
|
@@ -31185,6 +31225,10 @@ function aerieStore(o) {
|
|
|
31185
31225
|
if (e.parentId) e = { ...e, parentId: (await must(e.parentId, tx)).id };
|
|
31186
31226
|
if (e.milestone) e = { ...e, milestone: await milestoneOf(tx, e.milestone) };
|
|
31187
31227
|
const t = applyEdit(was, e, now());
|
|
31228
|
+
if (Object.keys(e).every((k) => k === "place")) {
|
|
31229
|
+
if (was.updatedAt) t.updatedAt = was.updatedAt;
|
|
31230
|
+
else delete t.updatedAt;
|
|
31231
|
+
}
|
|
31188
31232
|
const areaId = e.area ? await ensureArea(tx, e.area) : await areaIdOf(tx, was.area);
|
|
31189
31233
|
await put(tx, t, areaId, e.place ?? was.place);
|
|
31190
31234
|
await setAliases(tx, row.id, e);
|
|
@@ -33001,6 +33045,7 @@ function pgCoord(o) {
|
|
|
33001
33045
|
const C = coordClosing;
|
|
33002
33046
|
const T = coordTask;
|
|
33003
33047
|
const Q = coordQueue;
|
|
33048
|
+
const E = coordLeaseEvent;
|
|
33004
33049
|
const lockQueue = (tx) => tx.execute(
|
|
33005
33050
|
sql`select pg_advisory_xact_lock(hashtextextended(${`aerie.coord:${ns}:queue`}, 0))`
|
|
33006
33051
|
);
|
|
@@ -33020,7 +33065,7 @@ function pgCoord(o) {
|
|
|
33020
33065
|
if (!hit[0] || hit[0].status === name) return;
|
|
33021
33066
|
await aerieStore({ db: tx }).edit(id, { status: name }, by);
|
|
33022
33067
|
};
|
|
33023
|
-
const lease = async (tx, id, holder, leaseMs, queued, key) => {
|
|
33068
|
+
const lease = async (tx, id, holder, leaseMs, queued, key, how = "claim") => {
|
|
33024
33069
|
const t = clock();
|
|
33025
33070
|
const others = await rows2(
|
|
33026
33071
|
tx,
|
|
@@ -33033,13 +33078,17 @@ function pgCoord(o) {
|
|
|
33033
33078
|
);
|
|
33034
33079
|
const gen = num(g?.gen);
|
|
33035
33080
|
await tx.execute(sql`
|
|
33036
|
-
insert into ${L} (ns, task_id, holder, gen, expires, queued, lane, pin, take_key)
|
|
33081
|
+
with up as (insert into ${L} (ns, task_id, holder, gen, expires, queued, lane, pin, take_key)
|
|
33037
33082
|
values (${ns}, ${id}, ${holder}, ${gen}, ${plus(t, leaseMs)}, ${!!queued}, ${queued?.lane ?? null}, ${queued?.pin ?? null}, ${key ?? null})
|
|
33038
33083
|
on conflict (ns, task_id, holder) do update set gen = excluded.gen, expires = excluded.expires,
|
|
33039
33084
|
take_key = coalesce(excluded.take_key, ${L}.take_key),
|
|
33040
33085
|
queued = excluded.queued or ${L}.queued,
|
|
33041
33086
|
lane = case when excluded.queued then excluded.lane else ${L}.lane end,
|
|
33042
|
-
pin = case when excluded.queued then excluded.pin else ${L}.pin end
|
|
33087
|
+
pin = case when excluded.queued then excluded.pin else ${L}.pin end
|
|
33088
|
+
returning task_id, holder, gen, queued, expires, (xmax = 0) as fresh)
|
|
33089
|
+
insert into ${E} (ns, task_id, holder, gen, kind, queued, expires, by, at)
|
|
33090
|
+
select ${ns}, task_id, holder, gen, case when fresh then ${how} else 'reclaim' end, queued, expires, holder, ${t}
|
|
33091
|
+
from up`);
|
|
33043
33092
|
await touch(tx, id, t);
|
|
33044
33093
|
await setStatus(tx, id, "doing", holder);
|
|
33045
33094
|
return { gen, others: others.map((r) => r.holder) };
|
|
@@ -33052,8 +33101,13 @@ function pgCoord(o) {
|
|
|
33052
33101
|
if (!has.length) return { last: true, closeNow: false, status: "ready" };
|
|
33053
33102
|
const gone = await rows2(
|
|
33054
33103
|
tx,
|
|
33055
|
-
sql`delete from ${L} where ns = ${ns} and task_id = ${id} and holder = any(${textArr(holders)})
|
|
33056
|
-
|
|
33104
|
+
sql`with gone as (delete from ${L} where ns = ${ns} and task_id = ${id} and holder = any(${textArr(holders)})
|
|
33105
|
+
returning holder, gen, queued, lane, pin, expires),
|
|
33106
|
+
logged as (insert into ${E} (ns, task_id, holder, gen, kind, queued, expires, by, at)
|
|
33107
|
+
select ${ns}, ${id}, holder, gen,
|
|
33108
|
+
case when holder <> ${x.by} then 'expire' else ${x.done ? "done" : x.why ?? "release"} end,
|
|
33109
|
+
queued, expires, ${x.by}, ${t} from gone)
|
|
33110
|
+
select holder, queued, lane, pin from gone`
|
|
33057
33111
|
);
|
|
33058
33112
|
if (x.done && gone.some((l) => l.holder === x.by))
|
|
33059
33113
|
await tx.execute(sql`insert into ${C} (ns, task_id, holder, reason, at)
|
|
@@ -33133,7 +33187,7 @@ function pgCoord(o) {
|
|
|
33133
33187
|
);
|
|
33134
33188
|
if (!still.length) continue;
|
|
33135
33189
|
lost.push({ id: l.id, holder: l.holder });
|
|
33136
|
-
await drop(tx, l.id, [l.holder], { queue: l.queued, by: l.holder });
|
|
33190
|
+
await drop(tx, l.id, [l.holder], { queue: l.queued, by: l.holder, why: "lost" });
|
|
33137
33191
|
}
|
|
33138
33192
|
}
|
|
33139
33193
|
await tx.execute(sql`update ${L} set expires = ${plus(t, leaseMs)}
|
|
@@ -33261,7 +33315,8 @@ function pgCoord(o) {
|
|
|
33261
33315
|
sql`select 1 from ${L} where ns = ${ns} and task_id = ${l.id} and holder = ${l.holder}
|
|
33262
33316
|
and expires < ${t}`
|
|
33263
33317
|
);
|
|
33264
|
-
if (still.length)
|
|
33318
|
+
if (still.length)
|
|
33319
|
+
await drop(tx, l.id, [l.holder], { queue: l.queued, by: l.holder, why: "reap" });
|
|
33265
33320
|
}
|
|
33266
33321
|
}
|
|
33267
33322
|
if (x.cap !== void 0) {
|
|
@@ -33291,10 +33346,28 @@ function pgCoord(o) {
|
|
|
33291
33346
|
holder,
|
|
33292
33347
|
leaseMs,
|
|
33293
33348
|
{ lane: item.lane, pin: item.pin },
|
|
33294
|
-
x.key
|
|
33349
|
+
x.key,
|
|
33350
|
+
"take"
|
|
33295
33351
|
);
|
|
33296
33352
|
return { id: item.id, gen: r.gen };
|
|
33297
33353
|
}),
|
|
33354
|
+
leaseEvents: async ({ since, limit = 1e4 }) => (await rows2(
|
|
33355
|
+
db,
|
|
33356
|
+
sql`select id::float8 as id, task_id, holder, gen::float8 as gen, kind, queued, ${ms(sql`expires`)} as expires,
|
|
33357
|
+
by, ${ms(sql`at`)} as at from ${E} where ns = ${ns} and at >= ${at3(since)} order by id limit ${limit}`
|
|
33358
|
+
)).map(
|
|
33359
|
+
(r) => ({
|
|
33360
|
+
id: num(r.id),
|
|
33361
|
+
task: String(r.task_id),
|
|
33362
|
+
holder: String(r.holder),
|
|
33363
|
+
gen: num(r.gen),
|
|
33364
|
+
kind: r.kind,
|
|
33365
|
+
queued: !!r.queued,
|
|
33366
|
+
expires: num(r.expires),
|
|
33367
|
+
by: String(r.by),
|
|
33368
|
+
at: num(r.at)
|
|
33369
|
+
})
|
|
33370
|
+
),
|
|
33298
33371
|
fence: async (id, holder, gen) => (await rows2(
|
|
33299
33372
|
db,
|
|
33300
33373
|
sql`select 1 from ${L} where ns = ${ns} and task_id = ${id} and holder = ${holder}
|
|
@@ -33853,7 +33926,13 @@ var init_remote = __esm({
|
|
|
33853
33926
|
HOLDER,
|
|
33854
33927
|
MS
|
|
33855
33928
|
]),
|
|
33856
|
-
fence: read([ID2, HOLDER, external_exports.int().nonnegative()])
|
|
33929
|
+
fence: read([ID2, HOLDER, external_exports.int().nonnegative()]),
|
|
33930
|
+
leaseEvents: read([
|
|
33931
|
+
external_exports.strictObject({
|
|
33932
|
+
since: external_exports.number().nonnegative(),
|
|
33933
|
+
limit: external_exports.int().positive().max(1e4).optional()
|
|
33934
|
+
})
|
|
33935
|
+
])
|
|
33857
33936
|
};
|
|
33858
33937
|
OPS = { store: STORE_OPS, coord: COORD_OPS };
|
|
33859
33938
|
CALL = external_exports.object({
|
|
@@ -40716,6 +40795,69 @@ function registerIntakeCommands(program3, ctx) {
|
|
|
40716
40795
|
);
|
|
40717
40796
|
}
|
|
40718
40797
|
|
|
40798
|
+
// src/coord/audit.ts
|
|
40799
|
+
var START = /* @__PURE__ */ new Set(["claim", "take", "reclaim"]);
|
|
40800
|
+
function leaseAudit(events, held, o) {
|
|
40801
|
+
const starts = {};
|
|
40802
|
+
const ends = {};
|
|
40803
|
+
const doubleDelivery = [];
|
|
40804
|
+
const orphans = [];
|
|
40805
|
+
const mins = (ms2) => Math.round(ms2 / 6e3) / 10;
|
|
40806
|
+
const open3 = /* @__PURE__ */ new Map();
|
|
40807
|
+
for (const e of [...events].sort((a, b) => a.id - b.id)) {
|
|
40808
|
+
const byTask = open3.get(e.task) ?? /* @__PURE__ */ new Map();
|
|
40809
|
+
open3.set(e.task, byTask);
|
|
40810
|
+
if (START.has(e.kind)) {
|
|
40811
|
+
starts[e.kind] = (starts[e.kind] ?? 0) + 1;
|
|
40812
|
+
if (!e.queued) continue;
|
|
40813
|
+
const had = byTask.get(e.holder);
|
|
40814
|
+
if (e.kind !== "reclaim" || !had) {
|
|
40815
|
+
const others = [...byTask].filter(([h]) => h !== e.holder);
|
|
40816
|
+
if (others.length)
|
|
40817
|
+
doubleDelivery.push({
|
|
40818
|
+
task: e.task,
|
|
40819
|
+
holder: e.holder,
|
|
40820
|
+
at: e.at,
|
|
40821
|
+
open: others.map(([h, l]) => ({ holder: h, since: l.since }))
|
|
40822
|
+
});
|
|
40823
|
+
}
|
|
40824
|
+
byTask.set(e.holder, { since: had?.since ?? e.at });
|
|
40825
|
+
continue;
|
|
40826
|
+
}
|
|
40827
|
+
ends[e.kind] = (ends[e.kind] ?? 0) + 1;
|
|
40828
|
+
byTask.delete(e.holder);
|
|
40829
|
+
if ((e.kind === "expire" || e.kind === "reap") && e.at - e.expires > o.graceMs)
|
|
40830
|
+
orphans.push({
|
|
40831
|
+
task: e.task,
|
|
40832
|
+
holder: e.holder,
|
|
40833
|
+
expires: e.expires,
|
|
40834
|
+
lapsedMin: mins(e.at - e.expires),
|
|
40835
|
+
freed: { kind: e.kind, by: e.by, at: e.at }
|
|
40836
|
+
});
|
|
40837
|
+
}
|
|
40838
|
+
for (const t of held)
|
|
40839
|
+
for (const l of t.holders)
|
|
40840
|
+
if (o.now - l.expires > o.graceMs)
|
|
40841
|
+
orphans.push({
|
|
40842
|
+
task: t.id,
|
|
40843
|
+
holder: l.holder,
|
|
40844
|
+
expires: l.expires,
|
|
40845
|
+
lapsedMin: mins(o.now - l.expires),
|
|
40846
|
+
freed: null
|
|
40847
|
+
});
|
|
40848
|
+
return {
|
|
40849
|
+
since: o.since,
|
|
40850
|
+
until: o.now,
|
|
40851
|
+
graceMin: mins(o.graceMs),
|
|
40852
|
+
events: events.length,
|
|
40853
|
+
starts,
|
|
40854
|
+
ends,
|
|
40855
|
+
doubleDelivery,
|
|
40856
|
+
orphans,
|
|
40857
|
+
ok: !doubleDelivery.length && !orphans.length
|
|
40858
|
+
};
|
|
40859
|
+
}
|
|
40860
|
+
|
|
40719
40861
|
// src/cli-run.ts
|
|
40720
40862
|
init_core3();
|
|
40721
40863
|
|
|
@@ -41473,6 +41615,13 @@ async function work(o) {
|
|
|
41473
41615
|
|
|
41474
41616
|
// src/cli-run.ts
|
|
41475
41617
|
var each = (v, prev = []) => [...prev, v];
|
|
41618
|
+
function sinceOf(v, now) {
|
|
41619
|
+
const m = /^(\d+(?:\.\d+)?)([dh])$/.exec(v);
|
|
41620
|
+
if (m) return now - Number(m[1]) * (m[2] === "d" ? 864e5 : 36e5);
|
|
41621
|
+
const t = Date.parse(v);
|
|
41622
|
+
if (Number.isNaN(t)) throw new Error(`aerie: --since ${v}: give an ISO time or Nd / Nh`);
|
|
41623
|
+
return t;
|
|
41624
|
+
}
|
|
41476
41625
|
var print2 = (x) => void process.stdout.write(typeof x === "string" ? x : `${JSON.stringify(x, null, 2)}
|
|
41477
41626
|
`);
|
|
41478
41627
|
async function pickerOf(a) {
|
|
@@ -41704,6 +41853,27 @@ function registerRunCommands(program3, ctx) {
|
|
|
41704
41853
|
` : "No pool sessions.\n"
|
|
41705
41854
|
);
|
|
41706
41855
|
});
|
|
41856
|
+
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(
|
|
41857
|
+
(o) => board(async (_a3, c) => {
|
|
41858
|
+
if (!c.leaseEvents) throw new Error(`aerie: coord store ${c.name} keeps no lease log`);
|
|
41859
|
+
const now = Date.now();
|
|
41860
|
+
const since = sinceOf(String(o.since), now);
|
|
41861
|
+
const [events, held] = await Promise.all([c.leaseEvents({ since }), c.held()]);
|
|
41862
|
+
const r = leaseAudit(events, held, { since, now, graceMs: Number(o.grace) * 6e4 });
|
|
41863
|
+
print2(
|
|
41864
|
+
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
|
|
41865
|
+
${[
|
|
41866
|
+
...r.doubleDelivery.map(
|
|
41867
|
+
(d) => `double ${d.task} ${d.holder} at ${new Date(d.at).toISOString()}; open: ${d.open.map((x) => x.holder).join(", ")}`
|
|
41868
|
+
),
|
|
41869
|
+
...r.orphans.map(
|
|
41870
|
+
(x) => `orphan ${x.task} ${x.holder} ${x.lapsedMin} min past expiry${x.freed ? `, ${x.freed.kind} by ${x.freed.by}` : ", still held"}`
|
|
41871
|
+
)
|
|
41872
|
+
].map((l) => `${l}
|
|
41873
|
+
`).join("")}`
|
|
41874
|
+
);
|
|
41875
|
+
})
|
|
41876
|
+
);
|
|
41707
41877
|
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(
|
|
41708
41878
|
(words, o) => ctx.withStore(async (a) => {
|
|
41709
41879
|
const rs = await a.searchEvents(words, {
|
|
@@ -42392,11 +42562,7 @@ function editFlags(c, create) {
|
|
|
42392
42562
|
function registerCommands(program3, ctx) {
|
|
42393
42563
|
program3.version(ctx.version, "-v, --version");
|
|
42394
42564
|
async function show(a, t, o, kind) {
|
|
42395
|
-
const [rows3,
|
|
42396
|
-
a.dependencyRows(),
|
|
42397
|
-
ctx.mirrorDir ? a.mirrorFiles([t.id]) : Promise.resolve([])
|
|
42398
|
-
]);
|
|
42399
|
-
const file2 = files[0] && ctx.mirrorDir ? join6(ctx.mirrorDir, files[0].path) : void 0;
|
|
42565
|
+
const [rows3, file2] = await Promise.all([a.dependencyRows(), fileOf(a, t.id)]);
|
|
42400
42566
|
const v = {
|
|
42401
42567
|
rows: rows3,
|
|
42402
42568
|
statuses: STATUSES,
|
|
@@ -42404,8 +42570,15 @@ function registerCommands(program3, ctx) {
|
|
|
42404
42570
|
...ctx.exact ? { exact: true } : {}
|
|
42405
42571
|
};
|
|
42406
42572
|
if (o.json) print3({ schemaVersion: 1, kind, task: viewItem(t, v) });
|
|
42573
|
+
else if (ctx.exact && kind !== "task-view")
|
|
42574
|
+
print3(viewPlain(t, v).replace(/^Parent: (\S+) - .*$/m, "Parent: $1"));
|
|
42407
42575
|
else print3(viewPlain(t, v));
|
|
42408
42576
|
}
|
|
42577
|
+
async function fileOf(a, id) {
|
|
42578
|
+
if (!ctx.mirrorDir) return void 0;
|
|
42579
|
+
const [f] = await a.mirrorFiles([id]);
|
|
42580
|
+
return f ? join6(ctx.mirrorDir, f.path) : void 0;
|
|
42581
|
+
}
|
|
42409
42582
|
const withBoardOrStore = (fn) => ctx.withBoard ? ctx.withBoard(fn) : ctx.withStore((a) => fn(a, null));
|
|
42410
42583
|
async function after(a, id) {
|
|
42411
42584
|
if (!ctx.mirrorDir) return;
|
|
@@ -42432,7 +42605,12 @@ function registerCommands(program3, ctx) {
|
|
|
42432
42605
|
);
|
|
42433
42606
|
await after(a, t.id);
|
|
42434
42607
|
if (o.json || o.plain) await show(a, t, o, "task-create");
|
|
42435
|
-
else
|
|
42608
|
+
else if (ctx.exact) {
|
|
42609
|
+
const file2 = await fileOf(a, t.id);
|
|
42610
|
+
print3(`Created task ${t.id}
|
|
42611
|
+
${file2 ? `File: ${file2}
|
|
42612
|
+
` : ""}`);
|
|
42613
|
+
} else print3(`Created task ${t.id} (area ${t.area})
|
|
42436
42614
|
`);
|
|
42437
42615
|
})
|
|
42438
42616
|
);
|