@dendelion/paper-camp 0.36.0 → 0.37.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.
@@ -1,3064 +0,0 @@
1
- import { readFile as v, mkdir as P, writeFile as E, readdir as K, stat as xt, rename as Ot, access as Dt } from "node:fs/promises";
2
- import { dirname as D, join as f, basename as Mt } from "node:path";
3
- import { parse as W, stringify as jt } from "yaml";
4
- import { spawn as b } from "node:child_process";
5
- import { AGENT_IDS as M, NIGHT_CHECK_IDS as Lt, NOTIFICATION_SETTING_KINDS as Ft, PLAN_KINDS as Ht } from "../types/index.js";
6
- import { createHash as Gt } from "node:crypto";
7
- import { existsSync as ae, readFileSync as Me } from "node:fs";
8
- import { fileURLToPath as Bt } from "node:url";
9
- import { z as Yt, A as qt, e as Ut, n as zt, a as Kt, u as Wt } from "./daemon-state.BeDnhzBY.js";
10
- import { z as d } from "zod";
11
- const Jt = /^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/;
12
- function Vt(e) {
13
- return e.length >= 2 && (e.startsWith('"') && e.endsWith('"') || e.startsWith("'") && e.endsWith("'")) ? e.slice(1, -1) : e;
14
- }
15
- function Se(e) {
16
- return e === "" || /[\s#"]/.test(e) ? `"${e.replace(/"/g, '\\"')}"` : e;
17
- }
18
- function je(e) {
19
- const t = e.trim();
20
- if (!t || t.startsWith("#")) return null;
21
- const n = t.match(Jt);
22
- return n ? { key: n[1], value: Vt(n[2]) } : null;
23
- }
24
- function fr(e) {
25
- const t = [];
26
- for (const n of e.split(`
27
- `)) {
28
- const s = je(n);
29
- s && t.push(s);
30
- }
31
- return t;
32
- }
33
- function pr(e, t) {
34
- const n = new Map(t.map((r) => [r.key, r.value])), s = e.length > 0 ? e.split(`
35
- `) : [], a = [];
36
- for (const r of s) {
37
- const i = je(r);
38
- if (!i) {
39
- a.push(r);
40
- continue;
41
- }
42
- n.has(i.key) && (a.push(`${i.key}=${Se(n.get(i.key) ?? "")}`), n.delete(i.key));
43
- }
44
- for (const [r, i] of n)
45
- a.push(`${r}=${Se(i)}`);
46
- for (; a.length > 0 && a[a.length - 1] === ""; ) a.pop();
47
- return a.length > 0 ? `${a.join(`
48
- `)}
49
- ` : "";
50
- }
51
- function hr(e) {
52
- return e.archived === !0 || e.status === "done";
53
- }
54
- function Z(e) {
55
- const t = e.phases.length > 0 && e.phases.every((s) => s.done), n = (e.fixes ?? []).every((s) => s.done);
56
- return t && n;
57
- }
58
- function J(e, t, n, s = !1) {
59
- return e.kind === "note" || e.status === "dropped" ? e.status : e.archived ? "done" : t ? t.state === "merged" ? Z(e) ? "done" : "planned" : t.state === "closed" ? "dropped" : Z(e) ? "review" : "in-progress" : n ? e.status === "review" || e.status === "done" ? e.status : s && e.phases.length > 0 ? Z(e) ? "review" : "in-progress" : e.phases.length > 0 ? "planned" : "idea" : e.status ?? (e.phases.length > 0 ? "planned" : "idea");
60
- }
61
- function Xt(e, t, n) {
62
- return e.kind === "note" || e.kind === "board" || e.status === "dropped" || e.archived || t ? !1 : !n;
63
- }
64
- function Zt(e, t) {
65
- if (e.kind === "note" || e.archived || (t == null ? void 0 : t.state) !== "merged") return !1;
66
- const n = J(e, t, !0);
67
- return n === "review" || n === "done";
68
- }
69
- function Le(e) {
70
- return e.length === 0 ? "idea" : e.every((t) => t === "done" || t === "dropped") ? "review" : e.some((t) => t !== "idea" && t !== "planned") ? "in-progress" : "planned";
71
- }
72
- function Qt(e = [], t = [], n = [], s = []) {
73
- const a = [
74
- ...e.map((i) => ({ kind: "log", date: i.date, text: i.text })),
75
- ...t.map((i) => ({ kind: "clarification", date: i.date, text: i.text })),
76
- ...s.map((i) => ({ kind: "review", date: i.date, text: i.text }))
77
- ].sort((i, o) => i.date.localeCompare(o.date)), r = n.map((i) => ({
78
- kind: i.kind ?? "note",
79
- text: i.anchor.kind === "phase" ? `[phase ${i.anchor.index}] ${i.prose}` : i.prose,
80
- state: i.state
81
- }));
82
- return [...a, ...r];
83
- }
84
- function re(e, t) {
85
- return e.filter((n) => n.kind === t).map((n) => ({ date: n.date ?? "", text: n.text }));
86
- }
87
- function Fe(e = []) {
88
- return re(e, "log");
89
- }
90
- function en(e = []) {
91
- return re(e, "clarification");
92
- }
93
- function tn(e = []) {
94
- return re(e, "review");
95
- }
96
- function nn(e = []) {
97
- return e.filter(
98
- (t) => t.kind === "note" || t.kind === "decision" || t.kind === "question"
99
- ).map((t) => ({
100
- anchor: { kind: "body" },
101
- prose: t.text,
102
- state: t.state ?? "open",
103
- kind: t.kind
104
- }));
105
- }
106
- function mr(e, t, n) {
107
- return [...(e ?? []).filter((s) => !t.includes(s.kind)), ...n];
108
- }
109
- function gr(e, t, n, s) {
110
- return e.map((a, r) => {
111
- if (r !== t) return a;
112
- const i = s ? `${a.text}
113
-
114
- ${s}` : a.text;
115
- if (n === "decision") return { ...a, kind: n, state: "open", text: i };
116
- const { state: o, ...c } = a;
117
- return { ...c, kind: n, text: i };
118
- });
119
- }
120
- function yr(e = []) {
121
- const t = e.reduce((n, s, a) => s.kind === "log" ? a : n, -1);
122
- return e.slice(t + 1).filter((n) => n.kind === "chat");
123
- }
124
- function He(e, t, n = !1, s = !1) {
125
- return {
126
- title: e.title,
127
- // Non-note entities can't carry the note-only 'open' (schema-enforced).
128
- status: J(e, t, n, s),
129
- statusFallback: Xt(e, t, n),
130
- kind: e.type,
131
- entityKind: e.kind === "note" ? void 0 : e.kind,
132
- id: e.id,
133
- idea: e.idea,
134
- agent: e.agent,
135
- created: e.created,
136
- updated: e.updated,
137
- audited: e.audited,
138
- auditedHash: e.auditedHash,
139
- released: e.released,
140
- tags: e.tags,
141
- subject: e.subject,
142
- order: e.order,
143
- issueSource: e.issueSource,
144
- body: e.body,
145
- phases: e.phases,
146
- fixes: e.fixes,
147
- log: Fe(e.thread),
148
- clarifications: en(e.thread),
149
- notes: nn(e.thread),
150
- review: tn(e.thread),
151
- thread: e.thread,
152
- archived: e.archived,
153
- pr: t
154
- };
155
- }
156
- function sn(e) {
157
- return {
158
- id: e.id,
159
- title: e.title,
160
- body: e.body,
161
- kind: "note",
162
- status: e.status,
163
- subject: e.subject,
164
- order: e.order,
165
- created: e.created,
166
- log: Fe(e.thread)
167
- };
168
- }
169
- const an = /^[0-9a-f]{4,40}$/i, rn = /^Merge pull request #\d+ from \S+\/([a-z]+-\d+)-/i;
170
- function S(e, t) {
171
- return new Promise((n) => {
172
- var r;
173
- const s = b("git", t, { cwd: e, stdio: ["ignore", "pipe", "ignore"] });
174
- let a = "";
175
- (r = s.stdout) == null || r.on("data", (i) => {
176
- a += i.toString();
177
- }), s.on("close", () => n(a)), s.on("error", () => n(""));
178
- });
179
- }
180
- async function Ge(e) {
181
- var n;
182
- return ((n = (await S(e, ["symbolic-ref", "refs/remotes/origin/HEAD"])).trim().match(/refs\/remotes\/origin\/(.+)/)) == null ? void 0 : n[1]) ?? "main";
183
- }
184
- function ee(e) {
185
- const t = e.match(/^Refs:\s*([A-Za-z]+-\d+)\s*$/m);
186
- if (t) return t[1].toUpperCase();
187
- const n = e.split(`
188
- `, 1)[0], s = n.match(/\(([A-Za-z]+-\d+)\)/);
189
- if (s) return s[1].toUpperCase();
190
- const a = n.match(rn);
191
- return a ? a[1].toUpperCase() : null;
192
- }
193
- function on(e) {
194
- return e.length > 0 && e.every((t) => t.startsWith("papercamp/"));
195
- }
196
- async function Be(e) {
197
- const t = await Ge(e), n = await S(e, ["log", "--format=%x02%B%x00", "--name-only", t]), s = /* @__PURE__ */ new Set();
198
- for (const a of n.split("")) {
199
- if (!a) continue;
200
- const [r, i = ""] = a.split("\0"), o = i.split(`
201
- `).map((u) => u.trim()).filter(Boolean);
202
- if (on(o)) continue;
203
- const c = ee(r.trim());
204
- c && s.add(c);
205
- }
206
- return s;
207
- }
208
- const Ye = "", O = "", cn = `${Ye}%H${O}%s${O}%cI${O}%D${O}%(trailers:key=Refs,valueonly)`, dn = /^([a-z]+(?:\([^)]*\))?):\s*(.+)$/i;
209
- function un(e) {
210
- const t = e.match(dn);
211
- return t ? { prefix: t[1], subject: t[2] } : { prefix: "", subject: e };
212
- }
213
- function ln(e, t) {
214
- const n = [];
215
- let s = !1;
216
- for (const a of e.split(",")) {
217
- const r = a.trim().replace(/^HEAD -> /, "");
218
- r && (r.startsWith("tag: ") ? n.push(r.slice(5)) : t && r === t && (s = !0));
219
- }
220
- return { tags: n, isUpstreamHead: s };
221
- }
222
- function fn(e) {
223
- const t = e.trim();
224
- return /^[A-Za-z]+-\d+$/.test(t) ? t.toUpperCase() : null;
225
- }
226
- function pn(e, t, n) {
227
- return e.split(Ye).map((s) => s.trim()).filter(Boolean).map((s) => {
228
- const [a, r = "", i = "", o = "", c = ""] = s.split(O), { prefix: u, subject: l } = un(r), { tags: p, isUpstreamHead: h } = ln(o, t);
229
- return {
230
- hash: a,
231
- subject: l,
232
- prefix: u,
233
- date: i,
234
- tags: p,
235
- isUpstreamHead: h,
236
- pushed: t !== null && !n.has(a),
237
- ideaId: fn(c)
238
- };
239
- });
240
- }
241
- async function hn(e) {
242
- return (await S(e, ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"])).trim() || null;
243
- }
244
- async function wr(e, t, n = 30) {
245
- const s = await hn(e), a = await S(e, [
246
- "log",
247
- "--first-parent",
248
- `--max-count=${n + 1}`,
249
- `--skip=${t}`,
250
- `--format=${cn}`
251
- ]), r = /* @__PURE__ */ new Set();
252
- if (s) {
253
- const c = await S(e, ["rev-list", `${s}..HEAD`]);
254
- for (const u of c.split(`
255
- `)) {
256
- const l = u.trim();
257
- l && r.add(l);
258
- }
259
- }
260
- const i = pn(a, s, r), o = i.length > n;
261
- return { commits: i.slice(0, n), upstream: s, hasMore: o };
262
- }
263
- const k = /* @__PURE__ */ new Map(), mn = 5 * 60 * 1e3, ie = (e) => f(e, "papercamp", "pr-map.json");
264
- async function gn(e, t, n) {
265
- const s = ie(e);
266
- try {
267
- const a = { fetchedAt: n, prs: Object.fromEntries(t) };
268
- await P(D(s), { recursive: !0 }), await E(s, `${JSON.stringify(a, null, 2)}
269
- `, "utf-8");
270
- } catch (a) {
271
- console.error(`papercamp: could not persist PR map for ${e}:`, a);
272
- }
273
- }
274
- async function qe(e) {
275
- try {
276
- const t = await v(ie(e), "utf-8"), n = JSON.parse(t);
277
- return { prs: new Map(Object.entries(n.prs)), fetchedAt: n.fetchedAt };
278
- } catch {
279
- return;
280
- }
281
- }
282
- const yn = {
283
- APPROVED: "approved",
284
- CHANGES_REQUESTED: "changes-requested",
285
- REVIEW_REQUIRED: "review-required"
286
- };
287
- function wn(e) {
288
- const t = e.state === "MERGED" ? "merged" : e.state === "CLOSED" ? "closed" : e.isDraft ? "draft" : "open", n = yn[e.reviewDecision];
289
- return {
290
- number: e.number,
291
- url: e.url,
292
- state: t,
293
- ...n && { reviewDecision: n },
294
- ...e.headRefOid && { headSha: e.headRefOid },
295
- ...e.headRefName && { headBranch: e.headRefName }
296
- };
297
- }
298
- const $e = { merged: 4, open: 3, draft: 2, closed: 1 };
299
- function Ue(e, t) {
300
- const n = e == null ? void 0 : e.match(/\*\*Plan:\*\*\s*`?([A-Za-z]+-\d+)`?/);
301
- if (n) return n[1].toUpperCase();
302
- const s = t == null ? void 0 : t.match(/^[a-z]+\/([a-z]+-\d+)-/);
303
- return s ? s[1].toUpperCase() : null;
304
- }
305
- const bn = `
306
- query($owner: String!, $repo: String!, $number: Int!) {
307
- repository(owner: $owner, name: $repo) {
308
- pullRequest(number: $number) {
309
- reviewThreads(first: 100) { nodes { isResolved } }
310
- commits(last: 1) { nodes { commit { committedDate } } }
311
- comments(last: 1) { nodes { createdAt } }
312
- reviews(last: 20) { nodes { createdAt body } }
313
- }
314
- }
315
- }`;
316
- function vn(e, t) {
317
- return `Paper Scout · ${e} · ${t.slice(0, 7)}`;
318
- }
319
- function j(e) {
320
- const t = e.match(/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/);
321
- if (!t) return null;
322
- const [, n, s, a] = t;
323
- return { owner: n, repo: s, number: a };
324
- }
325
- const En = 15e3;
326
- function ze(e, t) {
327
- return new Promise((n) => {
328
- var c, u;
329
- const s = b("gh", t, { cwd: e, stdio: ["ignore", "pipe", "pipe"] });
330
- let a = !1;
331
- const r = (l) => {
332
- a || (a = !0, clearTimeout(i), l());
333
- }, i = setTimeout(() => {
334
- s.kill(), r(() => n(void 0));
335
- }, En);
336
- let o = "";
337
- (c = s.stdout) == null || c.on("data", (l) => {
338
- o += l.toString();
339
- }), (u = s.stderr) == null || u.on("data", () => {
340
- }), s.on("close", (l) => {
341
- r(() => {
342
- if (l !== 0) {
343
- n(void 0);
344
- return;
345
- }
346
- try {
347
- n(JSON.parse(o));
348
- } catch {
349
- n(void 0);
350
- }
351
- });
352
- }), s.on("error", () => r(() => n(void 0)));
353
- });
354
- }
355
- function Ke(e, t, n, s, a) {
356
- return Je(e, [
357
- "-f",
358
- `query=${t}`,
359
- "-f",
360
- `owner=${n}`,
361
- "-f",
362
- `repo=${s}`,
363
- "-F",
364
- `number=${a}`
365
- ]);
366
- }
367
- function We(e, t, n) {
368
- const s = ["-f", `query=${t}`];
369
- for (const [a, r] of Object.entries(n))
370
- s.push("-f", `${a}=${r}`);
371
- return Je(e, s);
372
- }
373
- function Je(e, t) {
374
- return ze(e, ["api", "graphql", ...t]);
375
- }
376
- async function kn(e, t) {
377
- var l, p, h, w, g;
378
- const n = j(t);
379
- if (!n) return;
380
- const s = await Ke(e, bn, n.owner, n.repo, n.number), a = (p = (l = s == null ? void 0 : s.data) == null ? void 0 : l.repository) == null ? void 0 : p.pullRequest;
381
- if (!a) return;
382
- const r = a.reviewThreads.nodes.filter((m) => !m.isResolved).length, i = (h = a.commits.nodes[0]) == null ? void 0 : h.commit.committedDate, o = [(w = a.comments.nodes[0]) == null ? void 0 : w.createdAt, (g = a.reviews.nodes.at(-1)) == null ? void 0 : g.createdAt].filter((m) => !!m).sort().at(-1), c = !!(i && o && o > i), u = a.reviews.nodes.map((m) => m.body);
383
- return { unresolvedThreadCount: r, hasNewCommentsSincePush: c, reviewBodies: u };
384
- }
385
- const Sn = `
386
- query($owner: String!, $repo: String!, $number: Int!) {
387
- repository(owner: $owner, name: $repo) {
388
- pullRequest(number: $number) {
389
- reviewThreads(first: 100) {
390
- nodes {
391
- id
392
- isResolved
393
- comments(first: 1) { nodes { path line body author { login } } }
394
- }
395
- }
396
- }
397
- }
398
- }`;
399
- async function br(e, t) {
400
- var r, i, o;
401
- const n = j(t);
402
- if (!n) return [];
403
- const s = await Ke(e, Sn, n.owner, n.repo, n.number);
404
- return (((o = (i = (r = s == null ? void 0 : s.data) == null ? void 0 : r.repository) == null ? void 0 : i.pullRequest) == null ? void 0 : o.reviewThreads.nodes) ?? []).filter((c) => !c.isResolved).map((c) => ({ id: c.id, comment: c.comments.nodes[0] })).filter((c) => !!c.comment).map(({ id: c, comment: u }) => {
405
- var l;
406
- return {
407
- id: c,
408
- ...u.path ? { path: u.path } : {},
409
- ...u.line != null ? { line: u.line } : {},
410
- ...(l = u.author) != null && l.login ? { author: u.author.login } : {},
411
- body: u.body
412
- };
413
- });
414
- }
415
- const $n = `
416
- mutation($threadId: ID!) {
417
- resolveReviewThread(input: { threadId: $threadId }) {
418
- thread { id isResolved }
419
- }
420
- }`, In = `
421
- mutation($threadId: ID!, $body: String!) {
422
- addPullRequestReviewThreadReply(input: { pullRequestReviewThreadId: $threadId, body: $body }) {
423
- comment { id }
424
- }
425
- }`;
426
- async function vr(e, t) {
427
- var s, a, r;
428
- const n = await We(e, $n, { threadId: t });
429
- return !!((r = (a = (s = n == null ? void 0 : n.data) == null ? void 0 : s.resolveReviewThread) == null ? void 0 : a.thread) != null && r.isResolved);
430
- }
431
- async function Er(e, t, n) {
432
- var a, r, i;
433
- const s = await We(e, In, { threadId: t, body: n });
434
- return !!((i = (r = (a = s == null ? void 0 : s.data) == null ? void 0 : a.addPullRequestReviewThreadReply) == null ? void 0 : r.comment) != null && i.id);
435
- }
436
- function Ve(e, t, n) {
437
- return new Promise((s) => {
438
- var i, o, c;
439
- const a = b("gh", ["api", t, "-X", "POST", "--input", "-"], {
440
- cwd: e,
441
- stdio: ["pipe", "ignore", "pipe"]
442
- });
443
- let r = "";
444
- (i = a.stderr) == null || i.on("data", (u) => {
445
- r += u;
446
- }), a.on(
447
- "close",
448
- (u) => s(u === 0 ? { delivered: !0 } : { delivered: !1, body: r.trim() })
449
- ), a.on("error", (u) => s({ delivered: !1, body: u.message })), (o = a.stdin) == null || o.on("error", () => {
450
- }), (c = a.stdin) == null || c.end(JSON.stringify(n));
451
- });
452
- }
453
- async function kr(e, t, n) {
454
- const s = j(t);
455
- return s ? Ve(
456
- e,
457
- `repos/${s.owner}/${s.repo}/pulls/${s.number}/reviews`,
458
- n
459
- ) : { delivered: !1 };
460
- }
461
- async function Sr(e, t, n) {
462
- const s = j(t);
463
- return s ? Ve(e, `repos/${s.owner}/${s.repo}/dispatches`, {
464
- event_type: "paper-camp-review",
465
- client_payload: { review: { number: Number(s.number), ...n } }
466
- }) : { delivered: !1 };
467
- }
468
- async function Rn(e, t) {
469
- const n = [...t.entries()].filter(
470
- ([, a]) => a.state === "open" || a.state === "draft"
471
- ), s = await Promise.all(n.map(([, a]) => kn(e, a.url)));
472
- n.forEach(([a, r], i) => {
473
- const o = s[i];
474
- if (!o) return;
475
- const { reviewBodies: c, ...u } = o, l = !!r.headSha && c.some((p) => p.includes(vn(a, r.headSha)));
476
- t.set(a, { ...r, ...u, ...l && { scoutReviewObserved: l } });
477
- });
478
- }
479
- async function An(e) {
480
- const t = await ze(e, [
481
- "pr",
482
- "list",
483
- "--state",
484
- "all",
485
- "--limit",
486
- "2000",
487
- "--json",
488
- "number,url,state,isDraft,headRefName,headRefOid,body,reviewDecision"
489
- ]);
490
- if (!t) return;
491
- const n = /* @__PURE__ */ new Map();
492
- for (const s of t) {
493
- const a = Ue(s.body, s.headRefName);
494
- if (!a) continue;
495
- const r = wn(s), i = n.get(a);
496
- (!i || $e[r.state] > $e[i.state]) && n.set(a, r);
497
- }
498
- return await Rn(e, n), n;
499
- }
500
- async function Xe(e, t = mn) {
501
- let n = k.get(e);
502
- if (!n) {
503
- const a = await qe(e);
504
- a && (k.set(e, a), n = a);
505
- }
506
- if (n && Date.now() - n.fetchedAt < t) return n.prs;
507
- if (!Number.isFinite(t)) return n == null ? void 0 : n.prs;
508
- const s = await An(e);
509
- if (s !== void 0) {
510
- const a = Date.now();
511
- return k.set(e, { prs: s, fetchedAt: a }), await gn(e, s, a), s;
512
- }
513
- return n == null ? void 0 : n.prs;
514
- }
515
- function $r(e) {
516
- var t;
517
- return (t = k.get(e)) == null ? void 0 : t.prs;
518
- }
519
- function Ir(e, t) {
520
- const n = (a) => `${a.number}:${a.headSha ?? "unknown"}`, s = [];
521
- for (const [a, r] of t) {
522
- if (r.reviewDecision !== "changes-requested") continue;
523
- const i = e == null ? void 0 : e.get(a);
524
- ((i == null ? void 0 : i.reviewDecision) === "changes-requested" ? n(i) : void 0) !== n(r) && s.push({ entityId: a, pr: r });
525
- }
526
- return s;
527
- }
528
- async function Rr(e) {
529
- let t = k.get(e);
530
- if (!t) {
531
- const n = await qe(e);
532
- n && (k.set(e, n), t = n);
533
- }
534
- return (t == null ? void 0 : t.fetchedAt) ?? null;
535
- }
536
- async function Ar(e) {
537
- if (e === void 0) {
538
- k.clear();
539
- return;
540
- }
541
- const t = k.get(e);
542
- t && k.set(e, { ...t, fetchedAt: 0 });
543
- const n = ie(e);
544
- try {
545
- const s = await v(n, "utf-8"), a = JSON.parse(s);
546
- a.fetchedAt = 0, await E(n, `${JSON.stringify(a, null, 2)}
547
- `, "utf-8");
548
- } catch {
549
- }
550
- }
551
- const Ze = /^#{2,3}\s+/, G = /^[-*]\s+\[([ xX])\]\s+(.*)$/, Pn = /^\[(review|manual|issue)\]\s+(.*)$/, Cn = /^run:\s*(.+)$/, Ie = /^-\s+(\d{4}-\d{2}-\d{2}):\s*(.*)$/, Tn = /^\[(?:phase:(\d+)|body)\]\s+(?:\[(decision|question)\]\s+)?(.*)$/, Re = /^-\s+\[([ xX])\]\s+(?:(\d{4}-\d{2}-\d{2})\s+)?\[(log|clarification|review|note|decision|question|chat)\]\s+(\[agent\]\s+)?(?:\[\[([A-Za-z]+-\d+)\]\]\s+)?(.*)$/, Nn = ["note", "decision", "question"];
552
- function oe(e, t, n, s) {
553
- const a = [];
554
- let r = t;
555
- for (; r < n; ) {
556
- const i = e[r];
557
- if (i.trim() === "" || !/^\s/.test(i)) break;
558
- const o = i.trimStart();
559
- if (s.test(o) || Ze.test(o)) break;
560
- a.push(o), r++;
561
- }
562
- return { text: a.join(" "), next: r };
563
- }
564
- function ce(e, t) {
565
- return t ? `${e.trim()} ${t}` : e.trim();
566
- }
567
- function Qe(e, t, n) {
568
- const s = [];
569
- let a = t;
570
- for (; a < n; ) {
571
- const r = e[a].match(G);
572
- if (r) {
573
- const i = r[1].toLowerCase() === "x", o = r[2].trim(), c = o.match(Pn), u = c ? c[2].trim() : o, l = c ? c[1] : void 0, p = [];
574
- let h;
575
- for (a++; a < n; ) {
576
- const w = e[a];
577
- if (w.trim() === "" || G.test(w) || Ze.test(w)) break;
578
- if (/^\s/.test(w)) {
579
- const g = w.trimStart(), m = g.match(Cn), y = m ? Yt(m[1]) : void 0;
580
- y ? h = y : p.push(g), a++;
581
- } else
582
- break;
583
- }
584
- s.push({
585
- done: i,
586
- text: u,
587
- description: p.length > 0 ? p.join(`
588
- `) : void 0,
589
- source: l,
590
- run: h
591
- });
592
- } else
593
- a++;
594
- }
595
- return s;
596
- }
597
- function de(e, t, n) {
598
- const s = [];
599
- let a = t;
600
- for (; a < n; ) {
601
- const r = e[a].match(Ie);
602
- if (!r) {
603
- a++;
604
- continue;
605
- }
606
- const i = oe(e, a + 1, n, Ie);
607
- s.push({ date: r[1], text: ce(r[2], i.text) }), a = i.next;
608
- }
609
- return s;
610
- }
611
- function et(e, t) {
612
- const n = [e];
613
- for (const s of t) {
614
- const a = s.source ? `[${s.source}] ${s.text}` : s.text;
615
- if (n.push(`- [${s.done ? "x" : " "}] ${a}`), s.description)
616
- for (const r of s.description.split(`
617
- `)) n.push(` ${r}`);
618
- s.run && n.push(` run: ${qt(s.run)}`);
619
- }
620
- return n;
621
- }
622
- function ue(e, t) {
623
- return [e, ...t.map((n) => `- ${n.date}: ${n.text}`)];
624
- }
625
- function _n(e) {
626
- return e.kind === "phase" ? `[phase:${e.index}]` : "[body]";
627
- }
628
- function xn(e, t, n) {
629
- const s = [];
630
- let a = t;
631
- for (; a < n; ) {
632
- const r = e[a].match(G), i = r ? r[2].trim().match(Tn) : null;
633
- if (!r || !i) {
634
- a++;
635
- continue;
636
- }
637
- const o = i[1] ? { kind: "phase", index: Number(i[1]) } : { kind: "body" }, c = i[2], u = oe(e, a + 1, n, G);
638
- s.push({
639
- anchor: o,
640
- prose: ce(i[3], u.text),
641
- state: r[1].toLowerCase() === "x" ? "resolved" : "open",
642
- ...c ? { kind: c } : {}
643
- }), a = u.next;
644
- }
645
- return s;
646
- }
647
- function On(e) {
648
- const t = ["### Notes"];
649
- for (const n of e) {
650
- const s = n.kind && n.kind !== "note" ? `[${n.kind}] ` : "";
651
- t.push(
652
- `- [${n.state === "resolved" ? "x" : " "}] ${_n(n.anchor)} ${s}${n.prose}`
653
- );
654
- }
655
- return t;
656
- }
657
- const V = {
658
- headingRe: /^#{2,3}\s+Phases\s*$/i,
659
- parseEntries: Qe,
660
- formatLines: (e) => et("### Phases", e)
661
- }, tt = {
662
- headingRe: /^#{2,3}\s+Fixes\s*$/i,
663
- parseEntries: Qe,
664
- formatLines: (e) => et("### Fixes", e)
665
- }, L = {
666
- headingRe: /^#{2,3}\s+Log\s*$/i,
667
- parseEntries: de,
668
- formatLines: (e) => ue("### Log", e)
669
- }, le = {
670
- headingRe: /^#{2,3}\s+Clarifications\s*$/i,
671
- parseEntries: de,
672
- formatLines: (e) => ue("### Clarifications", e)
673
- }, fe = {
674
- headingRe: /^#{2,3}\s+Notes\s*$/i,
675
- parseEntries: xn,
676
- formatLines: On
677
- }, Dn = {
678
- headingRe: /^#{2,3}\s+Review\s*$/i,
679
- parseEntries: de,
680
- formatLines: (e) => ue("### Review", e)
681
- };
682
- function Mn(e, t, n) {
683
- const s = [];
684
- let a = t;
685
- for (; a < n; ) {
686
- const r = e[a].match(Re);
687
- if (!r) {
688
- a++;
689
- continue;
690
- }
691
- const i = r[3], o = oe(e, a + 1, n, Re), c = { kind: i, text: ce(r[6], o.text) };
692
- r[2] && (c.date = r[2]), r[4] && (c.from = "agent"), r[5] && (c.entityId = r[5]), Nn.includes(i) && (c.state = r[1].toLowerCase() === "x" ? "resolved" : "open"), s.push(c), a = o.next;
693
- }
694
- return s;
695
- }
696
- function jn(e) {
697
- const t = ["### Thread"];
698
- for (const n of e) {
699
- const s = n.state ? n.state === "resolved" : !0, a = n.date ? `${n.date} ` : "", r = n.from === "agent" ? "[agent] " : "", i = n.entityId ? `[[${n.entityId}]] ` : "";
700
- t.push(`- [${s ? "x" : " "}] ${a}[${n.kind}] ${r}${i}${n.text}`);
701
- }
702
- return t;
703
- }
704
- const nt = {
705
- headingRe: /^#{2,3}\s+Thread\s*$/i,
706
- parseEntries: Mn,
707
- formatLines: jn
708
- }, $ = d.preprocess(
709
- (e) => typeof e == "string" ? { agent: e } : e,
710
- d.object({
711
- agent: d.enum(M),
712
- model: d.string().optional(),
713
- effort: d.string().optional()
714
- })
715
- ), I = d.string().regex(/^\d{4}-\d{2}-\d{2}$/, "expected YYYY-MM-DD"), Ln = d.object({
716
- status: d.enum(["idea", "planned", "in-progress", "review", "done", "dropped"]),
717
- kind: d.enum(["feat", "fix", "chore", "docs", "refactor"]).optional(),
718
- id: d.string().optional(),
719
- idea: d.string().optional(),
720
- agent: d.enum(M).optional(),
721
- created: I,
722
- updated: I.optional(),
723
- tags: d.string().optional()
724
- }), Fn = d.object({
725
- id: d.string().describe("Permanent plan ID, e.g. FEAT-24"),
726
- title: d.string().describe('Human-readable plan name, e.g. "Plan storage architecture"'),
727
- kind: d.enum(["feat", "fix", "chore", "docs", "refactor"]).describe("Plan kind matching Conventional Commits types"),
728
- status: d.enum(["idea", "planned", "in-progress", "review", "done", "dropped"]).describe("Current lifecycle status"),
729
- idea: d.string().optional().describe("IDEA-N backlink if this plan grew out of an idea"),
730
- agent: d.enum(M).optional().describe("Per-plan agent override"),
731
- created: I.describe("Creation date (YYYY-MM-DD)"),
732
- updated: I.optional().describe("Last significant update date (YYYY-MM-DD)"),
733
- audited: I.optional().describe("Date of last successful convergence audit (YYYY-MM-DD)"),
734
- "audited-hash": d.string().optional().describe("Content hash of the plan at last audit, used to detect edits regardless of mtime"),
735
- tags: d.array(d.string()).optional().describe("Tagging categories")
736
- }).passthrough(), Hn = d.object({
737
- id: d.string().describe("Permanent idea ID, e.g. IDEA-20"),
738
- title: d.string().describe("Short idea headline (3-6 words)"),
739
- kind: d.enum(["idea", "note"]).optional().describe('"note" for ideas that never need a plan; omitted means a plan-bearing idea'),
740
- status: d.enum(["open", "done", "dropped"]).optional().describe("Manual lifecycle, valid only on notes — plan-bearing ideas carry no status")
741
- }).passthrough().refine((e) => e.status === void 0 || e.kind === "note", {
742
- message: "status is only valid on ideas with kind: note",
743
- path: ["status"]
744
- }), st = d.object({
745
- id: d.string().describe("Permanent lifetime entity ID, e.g. IDEA-45 — never changes"),
746
- title: d.string().describe("Human-readable entity name"),
747
- type: d.enum(["feat", "fix", "chore", "docs", "refactor"]).optional().describe(
748
- "Work classification (Conventional Commits values) driving commit types and branch prefixes; usually set once a plan is drafted"
749
- ),
750
- kind: d.enum(["note", "fix", "board", "ticket"]).optional().describe(
751
- '"note" marks an entity that never grows phases; "fix" is a follow-up entity linked to a done/archived parent via `idea`; "board" decomposes into "ticket" children instead of phases; "ticket" is a full entity linked back to its board via `idea`; omitted for normal ideas'
752
- ),
753
- status: d.enum(["idea", "planned", "in-progress", "review", "done", "dropped", "open"]).optional().describe(
754
- "Stored override, no longer the source of truth: most lifecycle states derive from phases/branch/PR. Only dropped, a planless idea/note being closed, or the offline fallback need this set."
755
- ),
756
- agent: d.enum(M).optional().describe("Per-entity agent override"),
757
- created: I.describe("Creation date (YYYY-MM-DD)"),
758
- updated: I.optional().describe("Last significant update date (YYYY-MM-DD)"),
759
- audited: I.optional().describe("Date of last successful convergence audit (YYYY-MM-DD)"),
760
- "audited-hash": d.string().optional().describe(
761
- "Content hash of the entity at last audit, used to detect edits regardless of mtime"
762
- ),
763
- released: d.string().optional().describe(
764
- "Version tag (e.g. v0.13.1) that first shipped this idea, stamped from the release train"
765
- ),
766
- tags: d.array(d.string()).optional().describe("Tagging categories"),
767
- idea: d.string().optional().describe("IDEA-N backlink to the parent this fix addresses; required when kind: fix"),
768
- subject: d.string().optional().describe('Subject group name; absent renders as the virtual "No subject" group'),
769
- order: d.number().int().optional().describe("Run order; absent means unordered, sorting after ordered entries"),
770
- issueSource: d.string().optional().describe(
771
- "sourceKind:sourceKey of the Issue (IDEA-192) this entity was promoted from, if any"
772
- )
773
- }).passthrough(), Gn = new Set(
774
- Object.keys(st.shape)
775
- ), at = st.refine(
776
- (e) => e.kind !== "note" || e.status === void 0 || ["open", "done", "dropped"].includes(e.status),
777
- {
778
- message: "a note entity must use status open, done, or dropped",
779
- path: ["status"]
780
- }
781
- ).refine((e) => e.kind === "note" || e.status !== "open", {
782
- message: "status open is only valid on entities with kind: note",
783
- path: ["status"]
784
- }).refine((e) => e.kind !== "fix" || e.idea !== void 0, {
785
- message: "a kind: fix entity requires an idea: link to its parent",
786
- path: ["idea"]
787
- }).refine((e) => e.kind !== "ticket" || e.idea !== void 0, {
788
- message: "a kind: ticket entity requires an idea: link to its board",
789
- path: ["idea"]
790
- }), Bn = d.object({
791
- name: d.string(),
792
- cmd: d.string(),
793
- port: d.number().int().positive().optional(),
794
- healthcheck: d.string().optional()
795
- }), Yn = d.object({
796
- name: d.string(),
797
- cmd: d.string(),
798
- fixCmd: d.string().optional()
799
- }), qn = d.object({
800
- repo: d.string(),
801
- branch: d.string().optional(),
802
- releasePlease: d.boolean().optional()
803
- }), Un = d.object({
804
- services: d.array(Bn).optional(),
805
- checks: d.array(Yn).optional(),
806
- ci: qn.optional()
807
- }), zn = d.object({
808
- from: d.string(),
809
- to: d.string()
810
- }), Kn = d.object({
811
- name: d.string(),
812
- prompt: d.string()
813
- }), Wn = d.object({
814
- ceiling: d.number().optional(),
815
- floor: d.number().optional(),
816
- window: zn.optional(),
817
- roots: d.array(d.string()).optional(),
818
- maxChunks: d.number().int().positive().optional(),
819
- threshold: d.number().min(0).max(100).optional(),
820
- checks: d.record(d.enum(Lt), d.boolean()).optional(),
821
- customChecks: d.array(Kn).optional(),
822
- maxTurns: d.number().int().positive().optional(),
823
- maxCostUsd: d.number().positive().optional()
824
- }), Jn = d.object({
825
- kinds: d.record(d.enum(Ft), d.boolean()).optional()
826
- }), Vn = d.object({
827
- endpoint: d.string(),
828
- keys: d.object({ p256dh: d.string(), auth: d.string() })
829
- }), Pr = d.discriminatedUnion("transport", [
830
- d.object({
831
- transport: d.literal("webpush"),
832
- name: d.string(),
833
- subscription: Vn
834
- }),
835
- d.object({ transport: d.literal("expo"), name: d.string(), token: d.string() })
836
- ]), Cr = d.discriminatedUnion("transport", [
837
- d.object({ transport: d.literal("webpush"), endpoint: d.string() }),
838
- d.object({ transport: d.literal("expo"), token: d.string() })
839
- ]), Xn = d.object({
840
- version: d.number().int().describe("Corpus format version (see CORPUS_FORMAT_VERSION), not the package version"),
841
- projectName: d.string(),
842
- initializedAt: d.string(),
843
- nextId: d.object({
844
- // idea: unified-entity counter minting lifetime IDEA-N ids. ticket: board/ticket
845
- // counter (IDEA-201) minting TICKET-N ids. The rest are legacy per-kind counters.
846
- idea: d.number().optional(),
847
- ticket: d.number().optional(),
848
- feat: d.number().optional(),
849
- fix: d.number().optional(),
850
- chore: d.number().optional(),
851
- docs: d.number().optional(),
852
- refactor: d.number().optional()
853
- }).optional(),
854
- defaultAgent: d.enum(M).optional(),
855
- defaultAgents: d.object({
856
- phase: $,
857
- planDraft: $,
858
- ideaExtend: $,
859
- commitSuggest: $,
860
- feedback: $,
861
- codeReview: $,
862
- deskDiscovery: $,
863
- nightShift: $
864
- }).optional(),
865
- desk: Un.optional(),
866
- night: Wn.optional(),
867
- notifications: Jn.optional()
868
- }), Zn = d.object({
869
- id: d.string(),
870
- kind: d.enum([
871
- "completed",
872
- "reply",
873
- "check-failed",
874
- "pr-review-changes-requested",
875
- "night-review-findings",
876
- "service-stopped"
877
- ]),
878
- entityId: d.string(),
879
- entityTitle: d.string(),
880
- text: d.string(),
881
- date: d.string(),
882
- read: d.boolean(),
883
- outcome: d.enum(["done", "error"]).optional(),
884
- push: d.boolean().optional().default(!0)
885
- }), Ae = /^##\s+(.+?)\s*$/, Qn = /^\*\*([A-Za-z][A-Za-z-]*):\*\*\s*(.*)$/, es = /^#{2,3}\s+/;
886
- function B(e, t) {
887
- const n = e.split(`
888
- `), s = n.findIndex((o) => t.headingRe.test(o));
889
- if (s === -1) return { body: e, entries: [] };
890
- let a = n.length;
891
- for (let o = s + 1; o < n.length; o++)
892
- if (es.test(n[o])) {
893
- a = o;
894
- break;
895
- }
896
- const r = t.parseEntries(n, s + 1, a);
897
- return { body: [...n.slice(0, s), ...n.slice(a)].join(`
898
- `).trim(), entries: r };
899
- }
900
- const Pe = {
901
- phases: V,
902
- log: L,
903
- clarifications: le,
904
- notes: fe,
905
- review: Dn
906
- };
907
- function pe(e) {
908
- const t = {
909
- phases: [],
910
- log: [],
911
- clarifications: [],
912
- notes: [],
913
- review: []
914
- };
915
- let n = e;
916
- for (const s of Object.keys(Pe)) {
917
- const a = B(n, Pe[s]);
918
- n = a.body, t[s] = a.entries;
919
- }
920
- return { body: n, ...t };
921
- }
922
- function ts(e) {
923
- const t = e.split(`
924
- `), n = [];
925
- for (let a = 0; a < t.length; a++)
926
- Ae.test(t[a]) && n.push(a);
927
- const s = [];
928
- for (let a = 0; a < n.length; a++) {
929
- const r = n[a], i = a + 1 < n.length ? n[a + 1] : t.length, o = t[r].match(Ae)[1], c = t.slice(r + 1, i);
930
- let u = 0;
931
- for (; u < c.length && c[u].trim() === ""; ) u++;
932
- const l = {};
933
- for (; u < c.length; ) {
934
- const F = c[u].match(Qn);
935
- if (!F) break;
936
- l[F[1].toLowerCase()] = F[2].trim(), u++;
937
- }
938
- for (; u < c.length && c[u].trim() === ""; ) u++;
939
- const p = c.slice(u).join(`
940
- `).trim(), { body: h, phases: w, log: g, clarifications: m, notes: y, review: x } = pe(p);
941
- s.push({ title: o, fields: l, body: h, phases: w, log: g, clarifications: m, notes: y, review: x });
942
- }
943
- return s;
944
- }
945
- function Tr(e) {
946
- const t = [], n = [];
947
- for (const s of ts(e)) {
948
- const a = Ln.safeParse(s.fields);
949
- if (!a.success) {
950
- n.push({
951
- title: s.title,
952
- message: a.error.issues.map((i) => i.message).join("; ")
953
- });
954
- continue;
955
- }
956
- const r = a.data;
957
- t.push({
958
- title: s.title,
959
- status: r.status,
960
- kind: r.kind,
961
- id: r.id,
962
- idea: r.idea,
963
- agent: r.agent,
964
- created: r.created,
965
- updated: r.updated,
966
- tags: r.tags ? r.tags.split(",").map((i) => i.trim()).filter(Boolean) : [],
967
- body: s.body,
968
- phases: s.phases,
969
- log: s.log,
970
- clarifications: s.clarifications,
971
- notes: s.notes,
972
- review: s.review
973
- });
974
- }
975
- return { entries: t, warnings: n };
976
- }
977
- const ns = /^---\s*\r?\n([\s\S]*?)\r?\n---\s*(?:\r?\n)?/;
978
- function he(e, t) {
979
- const n = [], s = e.match(ns);
980
- if (!s)
981
- return { data: null, body: e.trim(), warnings: n };
982
- const a = s[1], r = e.slice(s[0].length).trim();
983
- let i;
984
- try {
985
- i = W(a);
986
- } catch (c) {
987
- return n.push({
988
- title: "(frontmatter)",
989
- message: `Invalid YAML frontmatter: ${c.message}`
990
- }), { data: null, body: r, warnings: n };
991
- }
992
- if (typeof i != "object" || i === null || Array.isArray(i))
993
- return n.push({
994
- title: "(frontmatter)",
995
- message: "YAML frontmatter did not produce an object"
996
- }), { data: null, body: r, warnings: n };
997
- const o = t.safeParse(i);
998
- if (!o.success) {
999
- const c = i.id;
1000
- return n.push({
1001
- title: c ?? "(frontmatter)",
1002
- message: o.error.issues.map((u) => u.message).join("; ")
1003
- }), { data: null, body: r, warnings: n };
1004
- }
1005
- return { data: o.data, body: r, warnings: n };
1006
- }
1007
- function ss(e, t) {
1008
- const n = Object.fromEntries(
1009
- Object.entries(e).filter(([s]) => !t.has(s))
1010
- );
1011
- return Object.keys(n).length > 0 ? n : void 0;
1012
- }
1013
- function rt(e) {
1014
- const t = [], {
1015
- data: n,
1016
- body: s,
1017
- warnings: a
1018
- } = he(e, at);
1019
- if (t.push(...a), !n)
1020
- return { entries: [], warnings: t };
1021
- const {
1022
- body: r,
1023
- phases: i,
1024
- log: o,
1025
- clarifications: c,
1026
- notes: u,
1027
- review: l
1028
- } = pe(s), { body: p, entries: h } = B(r, tt), { body: w, entries: g } = B(p, nt), m = [...g, ...Qt(o, c, u, l)];
1029
- n.kind === "note" && i.length > 0 && t.push({
1030
- title: n.title,
1031
- message: "note entities must not carry a Phases section — kept, but fix the file"
1032
- });
1033
- const y = ss(n, Gn);
1034
- return { entries: [{
1035
- id: n.id,
1036
- title: n.title,
1037
- type: n.type,
1038
- kind: n.kind,
1039
- status: n.status,
1040
- idea: n.idea,
1041
- agent: n.agent,
1042
- created: n.created,
1043
- updated: n.updated,
1044
- audited: n.audited,
1045
- auditedHash: n["audited-hash"],
1046
- released: n.released,
1047
- tags: n.tags ?? [],
1048
- subject: n.subject,
1049
- order: n.order,
1050
- issueSource: n.issueSource,
1051
- body: w,
1052
- phases: i,
1053
- ...h.length > 0 && { fixes: h },
1054
- ...m.length > 0 && { thread: m },
1055
- ...y && { unknownFrontmatter: y }
1056
- }], warnings: t };
1057
- }
1058
- function Nr(e) {
1059
- const t = [], {
1060
- data: n,
1061
- body: s,
1062
- warnings: a
1063
- } = he(e, Fn);
1064
- if (t.push(...a), !n)
1065
- return { entries: [], warnings: t };
1066
- const { body: r, phases: i, log: o, clarifications: c, notes: u, review: l } = pe(s);
1067
- return { entries: [{
1068
- title: n.title,
1069
- status: n.status,
1070
- kind: n.kind,
1071
- id: n.id,
1072
- idea: n.idea,
1073
- agent: n.agent,
1074
- created: n.created,
1075
- updated: n.updated,
1076
- audited: n.audited,
1077
- auditedHash: n["audited-hash"],
1078
- tags: n.tags ?? [],
1079
- body: r,
1080
- phases: i,
1081
- log: o,
1082
- clarifications: c,
1083
- notes: u,
1084
- review: l
1085
- }], warnings: t };
1086
- }
1087
- function _r(e) {
1088
- const {
1089
- data: t,
1090
- body: n,
1091
- warnings: s
1092
- } = he(e, Hn);
1093
- if (!t)
1094
- return { entries: [], warnings: s };
1095
- const { body: a, entries: r } = B(n, L);
1096
- return { entries: [{
1097
- id: t.id,
1098
- title: t.title,
1099
- body: a || "",
1100
- ...t.kind && { kind: t.kind },
1101
- ...t.status && { status: t.status },
1102
- ...r.length > 0 && { log: r }
1103
- }], warnings: s };
1104
- }
1105
- const as = /^(IDEA-\d+):\s*/, rs = /\n---+\n/;
1106
- function xr(e) {
1107
- return e.split(rs).filter(Boolean).map((n) => {
1108
- var c;
1109
- const s = n.match(/^#{1,3}\s+(.+)/m), a = s ? s[1].trim() : ((c = n.trim().split(`
1110
- `)[0]) == null ? void 0 : c.trim()) ?? "Untitled", r = a.match(as), i = (r == null ? void 0 : r[1]) ?? null, o = i ? a.slice(r[0].length) : a;
1111
- return { id: i, title: o, body: n.trim() };
1112
- });
1113
- }
1114
- const Ce = 40;
1115
- function is(e, t = []) {
1116
- const n = [];
1117
- for (const s of e)
1118
- if (!s.archived && (t.length > 0 && s.subject && !t.includes(s.subject) && n.push({
1119
- kind: "orphan-subject",
1120
- section: "plans",
1121
- title: s.title,
1122
- planId: s.id,
1123
- message: `Subject "${s.subject}" isn't in the roadmap vocabulary — "${s.title}"`
1124
- }), s.status !== "done" && s.status !== "dropped")) {
1125
- const a = [];
1126
- s.title.length > Ce && a.push(`${s.title.length} chars over the ${Ce}-char limit`), s.title.includes("—") && a.push("em-dash subtitle"), a.length > 0 && n.push({
1127
- kind: "title-style",
1128
- section: "plans",
1129
- title: s.title,
1130
- planId: s.id,
1131
- message: `Title style — ${a.join(", ")}; the detail belongs in the body: "${s.title}"`
1132
- });
1133
- }
1134
- return n;
1135
- }
1136
- function os(e) {
1137
- const t = /* @__PURE__ */ new Map(), n = [];
1138
- for (const s of e.split(`
1139
- `)) {
1140
- const a = s.trim();
1141
- if (!a) continue;
1142
- let r;
1143
- try {
1144
- r = JSON.parse(a);
1145
- } catch {
1146
- continue;
1147
- }
1148
- const i = t.get(r.id);
1149
- i ? t.set(r.id, { ...i, ...r }) : (t.set(r.id, r), n.push(r.id));
1150
- }
1151
- return n.map((s) => t.get(s));
1152
- }
1153
- function Or(e) {
1154
- const t = [];
1155
- for (const n of e.split(`
1156
- `)) {
1157
- const s = n.trim();
1158
- if (s)
1159
- try {
1160
- const a = Zn.safeParse(JSON.parse(s));
1161
- a.success && t.push(a.data);
1162
- } catch {
1163
- }
1164
- }
1165
- return t;
1166
- }
1167
- const it = /^-\s+(\d{4}-\d{2}-\d{2}):\s+(.+?)\s+—\s+(.*)$/;
1168
- function Dr(e) {
1169
- const t = [];
1170
- for (const n of e.split(`
1171
- `)) {
1172
- const s = n.match(it);
1173
- s && t.push({ date: s[1], title: s[2].trim(), description: s[3].trim() });
1174
- }
1175
- return t;
1176
- }
1177
- const te = " — ";
1178
- function cs(e) {
1179
- return e.split(`
1180
- `).map((t) => t.trim()).filter((t) => t.length > 0).map((t) => {
1181
- const n = t.indexOf(te);
1182
- return n === -1 ? { id: t, title: "" } : {
1183
- id: t.slice(0, n).trim(),
1184
- title: t.slice(n + te.length).trim()
1185
- };
1186
- });
1187
- }
1188
- function Mr(e) {
1189
- return e.length === 0 ? "" : `${e.map((t) => `${t.id}${te}${t.title}`).join(`
1190
- `)}
1191
- `;
1192
- }
1193
- async function ds(e) {
1194
- try {
1195
- return await K(e);
1196
- } catch {
1197
- return [];
1198
- }
1199
- }
1200
- async function ot(e) {
1201
- try {
1202
- return await v(e, "utf-8");
1203
- } catch {
1204
- return "";
1205
- }
1206
- }
1207
- async function us(e) {
1208
- const t = await ot(f(e, "..", "run-order.md"));
1209
- return new Map(cs(t).map((n, s) => [n.id, s + 1]));
1210
- }
1211
- async function _(e) {
1212
- const t = [], n = [];
1213
- let s = 0;
1214
- const a = await us(e);
1215
- for (const r of [e, f(e, "archive")]) {
1216
- const i = r !== e, o = (await ds(r)).filter((u) => u.endsWith(".md") && u !== "index.md");
1217
- s += o.length;
1218
- const c = await Promise.all(
1219
- o.map(async (u) => {
1220
- const l = await ot(f(r, u));
1221
- return l ? rt(l) : { warnings: [{ title: u, message: "Could not read entity file" }] };
1222
- })
1223
- );
1224
- for (const u of c)
1225
- "entries" in u && t.push(
1226
- ...u.entries.map((l) => ({
1227
- ...l,
1228
- archived: i,
1229
- storedOrder: l.order,
1230
- order: a.get(l.id) ?? l.order
1231
- }))
1232
- ), n.push(...u.warnings);
1233
- }
1234
- return { entries: t, warnings: n, fileCount: s };
1235
- }
1236
- async function me(e, t) {
1237
- const { entries: n, warnings: s } = await _(e), a = f(e, "..", ".."), [r, i] = await Promise.all([
1238
- Xe(a, t),
1239
- Be(a)
1240
- ]);
1241
- return { entries: n, warnings: s, prs: r, resolved: r !== void 0, mainActivityIds: i };
1242
- }
1243
- async function jr(e) {
1244
- const { entries: t, warnings: n, prs: s, resolved: a, mainActivityIds: r } = await me(e), i = t.map((c) => ({
1245
- ...c,
1246
- status: J(c, s == null ? void 0 : s.get(c.id), a, r.has(c.id))
1247
- }));
1248
- return { entries: i.map((c) => {
1249
- if (c.kind !== "board" || c.archived || c.status === "done" || c.status === "dropped") return c;
1250
- const u = i.filter((l) => l.kind === "ticket" && l.idea === c.id).map((l) => l.status ?? "idea");
1251
- return { ...c, status: Le(u) };
1252
- }), warnings: n };
1253
- }
1254
- async function Lr(e, t) {
1255
- const { entries: n, warnings: s, prs: a, resolved: r, mainActivityIds: i } = await me(
1256
- e,
1257
- t
1258
- ), o = n.filter((u) => u.kind !== "note").map((u) => He(u, a == null ? void 0 : a.get(u.id), r, i.has(u.id)));
1259
- return { entries: o.map((u) => {
1260
- if (u.entityKind !== "board" || u.archived || u.status === "done" || u.status === "dropped")
1261
- return u;
1262
- const l = o.filter((p) => p.entityKind === "ticket" && p.idea === u.id).map((p) => p.status);
1263
- return { ...u, status: Le(l) };
1264
- }), warnings: s, resolved: r };
1265
- }
1266
- async function Fr(e) {
1267
- const { entries: t, prs: n, resolved: s } = await me(e);
1268
- return {
1269
- entries: t.flatMap((a) => {
1270
- const r = n == null ? void 0 : n.get(a.id);
1271
- return r && Zt(a, r) ? [{ id: a.id, title: a.title, pr: r }] : [];
1272
- }),
1273
- resolved: s
1274
- };
1275
- }
1276
- async function Hr(e) {
1277
- const { entries: t, warnings: n } = await _(e);
1278
- return {
1279
- entries: t.filter((s) => s.kind === "note").map(sn),
1280
- warnings: n
1281
- };
1282
- }
1283
- const ls = [
1284
- {
1285
- id: "frontmatter-schema",
1286
- category: "metadata",
1287
- severity: "error",
1288
- summary: "Frontmatter fails entityFrontmatterSchema — missing required field, bad enum, malformed date, or a violated note/status refinement."
1289
- },
1290
- {
1291
- id: "filename-id-mismatch",
1292
- category: "metadata",
1293
- severity: "error",
1294
- summary: "Frontmatter id does not match the file name (IDEA-N.md); references break silently."
1295
- },
1296
- {
1297
- id: "duplicate-id",
1298
- category: "metadata",
1299
- severity: "error",
1300
- summary: "Two entity files share one id; whichever loads last wins and the other disappears."
1301
- },
1302
- {
1303
- id: "id-counter-stale",
1304
- category: "metadata",
1305
- severity: "error",
1306
- summary: "An entity id is greater than or equal to config.nextId.idea, so the next mint collides with an existing file."
1307
- },
1308
- {
1309
- id: "corpus-format-too-new",
1310
- category: "metadata",
1311
- severity: "error",
1312
- summary: "config.version is newer than the format this paper-camp understands; reads stay tolerant but writes are refused until it upgrades."
1313
- },
1314
- {
1315
- id: "phases-list-split",
1316
- category: "structural",
1317
- severity: "error",
1318
- summary: "A checkbox line lives outside the Phases section — a mid-file heading split the list and orphaned phases, so the entity parses as fewer phases than it has."
1319
- },
1320
- {
1321
- id: "note-has-phases",
1322
- category: "structural",
1323
- severity: "error",
1324
- summary: "A kind: note entity carries a Phases section; notes never grow phases."
1325
- },
1326
- {
1327
- id: "duplicate-phases-section",
1328
- category: "structural",
1329
- severity: "error",
1330
- summary: "A file carries more than one Phases heading — a redraft appended instead of replacing the existing list in place."
1331
- },
1332
- {
1333
- id: "archive-placement",
1334
- category: "structural",
1335
- severity: "warning",
1336
- summary: "File location contradicts status — a done/dropped entity still under ideas/, or an active entity already under ideas/archive/."
1337
- },
1338
- {
1339
- id: "dangling-link",
1340
- category: "structural",
1341
- severity: "warning",
1342
- summary: "A [[IDEA-N]] wikilink targets an id that no entity in the corpus defines."
1343
- },
1344
- {
1345
- id: "missing-permissions-allow",
1346
- category: "tooling",
1347
- severity: "warning",
1348
- summary: ".claude/settings.json has no permissions.allow list, so a headless run denies every edit and shell command outside the defaults — run `paper-camp init --settings` to add it."
1349
- }
1350
- ], fs = Object.fromEntries(
1351
- ls.map((e) => [e.id, e])
1352
- );
1353
- function Y(e) {
1354
- return fs[e.rule].severity;
1355
- }
1356
- const Te = { error: 0, warning: 1 };
1357
- function ct(e) {
1358
- return [...e].sort(
1359
- (t, n) => t.file.localeCompare(n.file) || t.line - n.line || Te[Y(t)] - Te[Y(n)] || t.rule.localeCompare(n.rule)
1360
- );
1361
- }
1362
- function Gr(e) {
1363
- const t = ct(e).map((n) => ({
1364
- ...n,
1365
- severity: Y(n)
1366
- }));
1367
- return {
1368
- findings: t,
1369
- errorCount: t.filter((n) => n.severity === "error").length,
1370
- warningCount: t.filter((n) => n.severity === "warning").length
1371
- };
1372
- }
1373
- function Br(e) {
1374
- const t = ct(e);
1375
- let n = 0, s = 0;
1376
- const a = t.map((i) => {
1377
- const o = Y(i);
1378
- return o === "error" ? n++ : s++, `${i.file}:${i.line} ${o.padEnd(7)} ${i.rule} ${i.message}`;
1379
- }), r = t.length === 0 ? "paper-camp doctor: no issues found." : `paper-camp doctor: ${n} error(s), ${s} warning(s).`;
1380
- return {
1381
- text: [...a, ...a.length > 0 ? [""] : [], r].join(`
1382
- `),
1383
- errorCount: n,
1384
- warningCount: s
1385
- };
1386
- }
1387
- const R = 1;
1388
- class ps extends Error {
1389
- constructor(t) {
1390
- super(
1391
- `This corpus is in format version ${t}, newer than the format version ${R} this paper-camp understands. Writes are refused so a field this version doesn’t recognise is never dropped — upgrade paper-camp to edit this corpus.`
1392
- ), this.name = "CorpusTooNewError";
1393
- }
1394
- }
1395
- async function dt(e) {
1396
- let t;
1397
- try {
1398
- t = await v(e, "utf-8");
1399
- } catch {
1400
- return null;
1401
- }
1402
- try {
1403
- const n = JSON.parse(t);
1404
- return n && typeof n == "object" && !Array.isArray(n) ? n : null;
1405
- } catch {
1406
- return null;
1407
- }
1408
- }
1409
- function ut(e) {
1410
- const t = e == null ? void 0 : e.version;
1411
- return typeof t == "number" ? t : null;
1412
- }
1413
- async function Yr(e) {
1414
- const t = ut(await dt(e));
1415
- if (t !== null && t > R)
1416
- throw new ps(t);
1417
- }
1418
- async function qr(e) {
1419
- const t = await dt(e);
1420
- if (!t) return null;
1421
- const n = ut(t);
1422
- return n !== null && n >= R ? null : (t.version = R, await E(e, `${JSON.stringify(t, null, 2)}
1423
- `, "utf-8"), { from: n, to: R });
1424
- }
1425
- const lt = /^---\s*\r?\n([\s\S]*?)\r?\n---\s*(?:\r?\n)?/, hs = 2;
1426
- function ge(e) {
1427
- const t = e.content.match(lt);
1428
- if (!t) return null;
1429
- let n = null;
1430
- try {
1431
- const s = W(t[1]);
1432
- s && typeof s == "object" && !Array.isArray(s) && (n = s);
1433
- } catch {
1434
- }
1435
- return { yaml: t[1], data: n };
1436
- }
1437
- function ft(e, t) {
1438
- const n = new RegExp(`^\\s*${t}:`), s = e.split(`
1439
- `).findIndex((a) => n.test(a));
1440
- return s === -1 ? 1 : hs + s;
1441
- }
1442
- function ye(e) {
1443
- const t = ge(e);
1444
- return t ? ft(t.yaml, "id") : 1;
1445
- }
1446
- function pt(e) {
1447
- var n, s;
1448
- const t = (s = (n = ge(e)) == null ? void 0 : n.data) == null ? void 0 : s.id;
1449
- return typeof t == "string" ? t : e.id;
1450
- }
1451
- function A(e, t, n, s) {
1452
- return { file: e.path, line: t, rule: n, message: s };
1453
- }
1454
- const ms = ({ files: e }) => e.flatMap((t) => {
1455
- const n = t.content.match(lt);
1456
- if (!n)
1457
- return [A(t, 1, "frontmatter-schema", "missing YAML frontmatter block")];
1458
- let s;
1459
- try {
1460
- s = W(n[1]);
1461
- } catch (r) {
1462
- return [A(t, 1, "frontmatter-schema", `invalid YAML: ${r.message}`)];
1463
- }
1464
- if (typeof s != "object" || s === null || Array.isArray(s))
1465
- return [A(t, 1, "frontmatter-schema", "frontmatter is not a key/value mapping")];
1466
- const a = at.safeParse(s);
1467
- return a.success ? [] : a.error.issues.map((r) => {
1468
- const i = String(r.path[0] ?? ""), o = r.path.length > 0 ? `${r.path.join(".")}: ${r.message}` : r.message;
1469
- return A(t, i ? ft(n[1], i) : 1, "frontmatter-schema", o);
1470
- });
1471
- }), gs = ({ files: e }) => e.flatMap((t) => {
1472
- var s, a;
1473
- const n = (a = (s = ge(t)) == null ? void 0 : s.data) == null ? void 0 : a.id;
1474
- return typeof n != "string" || n === t.id ? [] : [
1475
- A(
1476
- t,
1477
- ye(t),
1478
- "filename-id-mismatch",
1479
- `frontmatter id "${n}" does not match file name ${t.id}.md`
1480
- )
1481
- ];
1482
- }), ys = ({ files: e }) => {
1483
- const t = /* @__PURE__ */ new Map();
1484
- for (const s of e) {
1485
- const a = pt(s), r = t.get(a);
1486
- r ? r.push(s) : t.set(a, [s]);
1487
- }
1488
- const n = [];
1489
- for (const [s, a] of t) {
1490
- if (a.length < 2) continue;
1491
- const r = a.map((i) => i.path).join(", ");
1492
- for (const i of a)
1493
- n.push(
1494
- A(
1495
- i,
1496
- ye(i),
1497
- "duplicate-id",
1498
- `id ${s} is defined by ${a.length} files: ${r}`
1499
- )
1500
- );
1501
- }
1502
- return n;
1503
- }, ws = ({ files: e, config: t }) => {
1504
- var s;
1505
- const n = (s = t == null ? void 0 : t.nextId) == null ? void 0 : s.idea;
1506
- return n == null ? [] : e.flatMap((a) => {
1507
- const r = pt(a), i = r.match(/^IDEA-(\d+)$/);
1508
- return i ? Number(i[1]) < n ? [] : [
1509
- A(
1510
- a,
1511
- ye(a),
1512
- "id-counter-stale",
1513
- `id ${r} is >= config nextId.idea (${n}); the next minted id would collide`
1514
- )
1515
- ] : [];
1516
- });
1517
- }, bs = ({ config: e }) => {
1518
- const t = e == null ? void 0 : e.version;
1519
- return typeof t != "number" || t <= R ? [] : [
1520
- {
1521
- file: "papercamp/config.json",
1522
- line: 1,
1523
- rule: "corpus-format-too-new",
1524
- message: `config.version ${t} is newer than the format version ${R} this paper-camp understands; writes are refused until it's upgraded`
1525
- }
1526
- ];
1527
- }, vs = [
1528
- ms,
1529
- gs,
1530
- ys,
1531
- ws,
1532
- bs
1533
- ], Es = /^---\s*\r?\n([\s\S]*?)\r?\n---\s*(?:\r?\n)?/, ks = /^#{1,6}\s+(.+?)\s*$/, Ss = /^[-*]\s+\[[ xX]\]\s+(.*)$/, $s = /^(phases|fixes)$/i, ht = /^#{1,6}\s+Phases\s*$/i, Is = /^(?:\d{4}-\d{2}-\d{2}\s+)?\[(?:log|clarification|review|note|decision|question|chat)\]/, Rs = /^\[(?:phase:\d+|body)\]/, As = /\[\[\s*((?:IDEA|TICKET)-\d+)(?:\s*\|[^\]]*)?\s*\]\]/g, Ps = /* @__PURE__ */ new Set(["idea", "planned", "in-progress", "review", "open"]), Cs = /* @__PURE__ */ new Set(["done", "dropped"]);
1534
- function we(e) {
1535
- const t = e.match(Es);
1536
- if (!t) return null;
1537
- try {
1538
- const n = W(t[1]);
1539
- if (n && typeof n == "object" && !Array.isArray(n))
1540
- return n;
1541
- } catch {
1542
- }
1543
- return null;
1544
- }
1545
- function Ts(e, t) {
1546
- const n = e.split(`
1547
- `).findIndex((s) => t.test(s));
1548
- return n === -1 ? 1 : n + 1;
1549
- }
1550
- function N(e, t, n, s) {
1551
- return { file: e.path, line: t, rule: n, message: s };
1552
- }
1553
- const Ns = ({ files: e }) => e.flatMap((t) => {
1554
- const n = t.content.split(`
1555
- `), s = [];
1556
- let a = !1;
1557
- for (let r = 0; r < n.length; r++) {
1558
- const i = n[r].match(ks);
1559
- if (i) {
1560
- a = $s.test(i[1].trim());
1561
- continue;
1562
- }
1563
- if (a) continue;
1564
- const o = n[r].match(Ss);
1565
- if (!o) continue;
1566
- const c = o[1].trim();
1567
- Is.test(c) || Rs.test(c) || s.push(
1568
- N(
1569
- t,
1570
- r + 1,
1571
- "phases-list-split",
1572
- `orphaned phase checkbox outside any Phases section: "${n[r].trim()}"`
1573
- )
1574
- );
1575
- }
1576
- return s;
1577
- }), _s = ({ files: e }) => e.flatMap((t) => {
1578
- var a;
1579
- if (((a = we(t.content)) == null ? void 0 : a.kind) !== "note") return [];
1580
- const s = t.content.split(`
1581
- `).findIndex((r) => ht.test(r));
1582
- return s === -1 ? [] : [N(t, s + 1, "note-has-phases", "a kind: note entity carries a Phases section")];
1583
- }), xs = ({ files: e }) => e.flatMap((t) => t.content.split(`
1584
- `).flatMap((a, r) => ht.test(a) ? [r] : []).slice(1).map(
1585
- (a) => N(
1586
- t,
1587
- a + 1,
1588
- "duplicate-phases-section",
1589
- "a second Phases heading exists — a redraft must replace the existing list in place, not append a new one"
1590
- )
1591
- )), Os = ({ files: e }) => e.flatMap((t) => {
1592
- var a;
1593
- const n = (a = we(t.content)) == null ? void 0 : a.status;
1594
- if (typeof n != "string") return [];
1595
- const s = Ts(t.content, /^status:/);
1596
- return t.archived && Ps.has(n) ? [
1597
- N(
1598
- t,
1599
- s,
1600
- "archive-placement",
1601
- `status "${n}" is active but the file is under ideas/archive/`
1602
- )
1603
- ] : !t.archived && Cs.has(n) ? [
1604
- N(
1605
- t,
1606
- s,
1607
- "archive-placement",
1608
- `status "${n}" is closed but the file is still under ideas/ — it should be archived`
1609
- )
1610
- ] : [];
1611
- }), Ds = ({ files: e }) => {
1612
- var n;
1613
- const t = /* @__PURE__ */ new Set();
1614
- for (const s of e) {
1615
- t.add(s.id);
1616
- const a = (n = we(s.content)) == null ? void 0 : n.id;
1617
- typeof a == "string" && t.add(a);
1618
- }
1619
- return e.flatMap((s) => {
1620
- const a = s.content.split(`
1621
- `), r = [];
1622
- for (let i = 0; i < a.length; i++)
1623
- for (const o of a[i].matchAll(As))
1624
- t.has(o[1]) || r.push(
1625
- N(
1626
- s,
1627
- i + 1,
1628
- "dangling-link",
1629
- `[[${o[1]}]] points at an id no entity in the corpus defines`
1630
- )
1631
- );
1632
- return r;
1633
- });
1634
- }, Ms = [
1635
- Ns,
1636
- _s,
1637
- xs,
1638
- Os,
1639
- Ds
1640
- ], js = ".claude/settings.json", Ls = ({ hasPermissionsAllow: e }) => e === !1 ? [
1641
- {
1642
- file: js,
1643
- line: 1,
1644
- rule: "missing-permissions-allow",
1645
- message: "no permissions.allow list — headless runs deny every edit and shell command outside the defaults; run `paper-camp init --settings` to add it."
1646
- }
1647
- ] : [], Fs = [Ls], Hs = [
1648
- ...vs,
1649
- ...Ms,
1650
- ...Fs
1651
- ];
1652
- function be(e) {
1653
- return (e == null ? void 0 : e.code) === "ENOENT";
1654
- }
1655
- async function Gs(e) {
1656
- try {
1657
- return await K(e);
1658
- } catch (t) {
1659
- if (be(t)) return [];
1660
- throw t;
1661
- }
1662
- }
1663
- async function Bs(e) {
1664
- let t;
1665
- try {
1666
- t = await v(e, "utf-8");
1667
- } catch (n) {
1668
- if (be(n)) return null;
1669
- throw n;
1670
- }
1671
- try {
1672
- return JSON.parse(t);
1673
- } catch {
1674
- return null;
1675
- }
1676
- }
1677
- async function Ys(e) {
1678
- var n;
1679
- let t;
1680
- try {
1681
- t = await v(f(e, ".claude", "settings.json"), "utf-8");
1682
- } catch (s) {
1683
- if (be(s)) return !1;
1684
- throw s;
1685
- }
1686
- try {
1687
- const s = JSON.parse(t);
1688
- return Array.isArray((n = s.permissions) == null ? void 0 : n.allow) && s.permissions.allow.length > 0;
1689
- } catch {
1690
- return !1;
1691
- }
1692
- }
1693
- async function qs(e) {
1694
- const t = f(e, "ideas"), n = [], s = [
1695
- { dir: t, archived: !1, names: await K(t) },
1696
- {
1697
- dir: f(t, "archive"),
1698
- archived: !0,
1699
- names: await Gs(f(t, "archive"))
1700
- }
1701
- ];
1702
- for (const { dir: a, archived: r, names: i } of s) {
1703
- const o = i.filter((c) => c.endsWith(".md") && c !== "index.md").sort();
1704
- for (const c of o)
1705
- n.push({
1706
- id: Mt(c, ".md"),
1707
- path: `papercamp/ideas${r ? "/archive" : ""}/${c}`,
1708
- content: await v(f(a, c), "utf-8"),
1709
- archived: r
1710
- });
1711
- }
1712
- return {
1713
- files: n,
1714
- config: await Bs(f(e, "config.json")),
1715
- hasPermissionsAllow: await Ys(D(e))
1716
- };
1717
- }
1718
- function Us(e) {
1719
- return Hs.flatMap((t) => t(e));
1720
- }
1721
- async function Ur(e) {
1722
- return Us(await qs(e));
1723
- }
1724
- const zs = {
1725
- rule: "archive-placement",
1726
- fix: (e, t) => ({
1727
- kind: "move",
1728
- from: t.path,
1729
- to: t.archived ? t.path.replace("/archive/", "/") : t.path.replace(/\/(?=[^/]+$)/, "/archive/")
1730
- })
1731
- }, Ks = [zs], Ws = new Map(
1732
- Ks.map((e) => [e.rule, e])
1733
- );
1734
- function zr(e, t) {
1735
- const n = new Map(e.files.map((o) => [o.path, o])), s = [], a = [], r = [], i = [];
1736
- for (const o of t) {
1737
- const c = Ws.get(o.rule), u = n.get(o.file), l = c && u ? c.fix(o, u) : null;
1738
- if (!l) {
1739
- r.push(o);
1740
- continue;
1741
- }
1742
- if (l.kind === "move" && n.has(l.to)) {
1743
- i.push(o);
1744
- continue;
1745
- }
1746
- s.push(l), a.push(o);
1747
- }
1748
- return { actions: s, fixed: a, unfixable: r, rejected: i };
1749
- }
1750
- async function q(e) {
1751
- try {
1752
- return await v(e, "utf-8");
1753
- } catch {
1754
- return "";
1755
- }
1756
- }
1757
- function mt(e, t) {
1758
- var n;
1759
- return (n = e.split(`
1760
- `).find((s) => s.includes(`(${t})`))) == null ? void 0 : n.trim();
1761
- }
1762
- const Js = /^## \[.+?\]\(.*\/compare\/(.+?)\.\.\.(.+?)\)/;
1763
- function Vs(e) {
1764
- return e.split(`
1765
- `).map((t) => Js.exec(t)).filter((t) => t !== null).map((t) => ({ version: t[2], range: `${t[1]}..${t[2]}` }));
1766
- }
1767
- function Xs(e, t) {
1768
- return e.split(`
1769
- `).find((n) => {
1770
- const s = n.match(/\/commit\/([0-9a-f]+)\)/i);
1771
- return s ? s[1].startsWith(t) || t.startsWith(s[1]) : !1;
1772
- });
1773
- }
1774
- const Zs = /^[a-z]+\/([a-z]+-\d+)-/;
1775
- async function Qs(e, t) {
1776
- var a;
1777
- const n = await S(e, [
1778
- "for-each-ref",
1779
- "--format=%(refname)",
1780
- "refs/heads",
1781
- "refs/remotes"
1782
- ]), s = t.toLowerCase();
1783
- for (const r of n.split(`
1784
- `)) {
1785
- const i = r.replace(/^refs\/heads\//, "").replace(/^refs\/remotes\/[^/]+\//, "");
1786
- if (((a = Zs.exec(i)) == null ? void 0 : a[1]) === s) return i;
1787
- }
1788
- }
1789
- async function ea(e, t) {
1790
- const n = await Qs(e, t);
1791
- if (!n) return [];
1792
- const s = await Ge(e);
1793
- return (await S(e, ["log", "--format=%s", `${s}..${n}`])).split(`
1794
- `).map((r) => r.trim()).filter(Boolean);
1795
- }
1796
- async function ta(e, t) {
1797
- if (!an.test(t)) return null;
1798
- const n = await S(e, ["log", "-1", "--format=%B", t]), s = n ? ee(n) : null;
1799
- if (s) return s;
1800
- const a = await q(f(e, "CHANGELOG.md")), r = Xs(a, t);
1801
- return r ? ee(r) : null;
1802
- }
1803
- async function na(e, t) {
1804
- const s = (await S(e, ["log", "--format=%H", "--reverse", t])).split(`
1805
- `).map((i) => i.trim()).filter(Boolean), a = await Promise.all(s.map((i) => ta(e, i))), r = /* @__PURE__ */ new Map();
1806
- return s.forEach((i, o) => {
1807
- const c = a[o];
1808
- if (!c) return;
1809
- const u = r.get(c);
1810
- u ? u.push(i) : r.set(c, [i]);
1811
- }), r;
1812
- }
1813
- async function Kr(e, t) {
1814
- const [{ entries: n }, s, a, r, i, o] = await Promise.all([
1815
- _(f(e, "papercamp", "ideas")),
1816
- Xe(e),
1817
- q(f(e, "papercamp", "tasks.log")),
1818
- q(f(e, "CHANGELOG.md")),
1819
- ea(e, t),
1820
- Be(e)
1821
- ]), c = n.find((h) => h.id === t), u = s == null ? void 0 : s.get(t), l = os(a).filter((h) => h.planId === t), p = mt(r, t);
1822
- return {
1823
- id: t,
1824
- idea: c ? {
1825
- reached: !0,
1826
- data: {
1827
- title: c.title,
1828
- status: J(c, u, s !== void 0, o.has(t)),
1829
- type: c.type
1830
- }
1831
- } : { reached: !1 },
1832
- phases: c ? { reached: c.phases.length > 0, data: c.phases } : { reached: !1 },
1833
- taskRuns: l.length > 0 ? { reached: !0, data: l } : { reached: !1 },
1834
- commits: i.length > 0 ? { reached: !0, data: i } : { reached: !1 },
1835
- pr: u ? { reached: !0, data: u } : { reached: !1 },
1836
- releaseLine: p ? { reached: !0, data: p } : { reached: !1 }
1837
- };
1838
- }
1839
- const H = /^##\s+/, sa = /^##\s+The goal\s*$/i, gt = /^##\s+(Horizon\s+\d+\s*[—-].*)\r?$/i, aa = /^##\s+Standing concerns\s*$/i, U = /^-\s+\*\*(.+?)\*\*\s+[—-]\s+(.*)\r?$/, ra = /^\s+-\s+→\s+(.+?)\r?$/, yt = /^\s+-\s+(.+?)\r?$/, wt = /^\s+\S/;
1840
- function Ne(e, t, n) {
1841
- const s = [];
1842
- let a = t;
1843
- for (; a < n; ) {
1844
- const r = e[a].match(U);
1845
- if (!r) {
1846
- a++;
1847
- continue;
1848
- }
1849
- const i = [r[2].trim()], o = [], c = [];
1850
- for (a++; a < n && !U.test(e[a]); ) {
1851
- const u = e[a].match(ra);
1852
- if (u) {
1853
- c.push(u[1].trim()), a++;
1854
- continue;
1855
- }
1856
- const l = e[a].match(yt);
1857
- if (l) {
1858
- o.push(l[1].trim()), a++;
1859
- continue;
1860
- }
1861
- if (!wt.test(e[a])) break;
1862
- i.push(e[a].trim()), a++;
1863
- }
1864
- s.push({ name: r[1].trim(), description: i.join(" "), candidates: o, linked: c });
1865
- }
1866
- return s;
1867
- }
1868
- function ia(e) {
1869
- const t = e.split(`
1870
- `);
1871
- let n = "";
1872
- const s = [];
1873
- let a = [];
1874
- for (let r = 0; r < t.length; r++) {
1875
- if (sa.test(t[r])) {
1876
- let o = r + 1;
1877
- for (; o < t.length && !H.test(t[o]); ) o++;
1878
- n = t.slice(r + 1, o).join(`
1879
- `).trim(), r = o - 1;
1880
- continue;
1881
- }
1882
- const i = t[r].match(gt);
1883
- if (i) {
1884
- let o = r + 1;
1885
- for (; o < t.length && !H.test(t[o]); ) o++;
1886
- s.push({ title: i[1].trim(), items: Ne(t, r + 1, o) }), r = o - 1;
1887
- continue;
1888
- }
1889
- if (aa.test(t[r])) {
1890
- let o = r + 1;
1891
- for (; o < t.length && !H.test(t[o]); ) o++;
1892
- a = Ne(t, r + 1, o), r = o - 1;
1893
- }
1894
- }
1895
- return { goal: n, horizons: s, standingConcerns: a };
1896
- }
1897
- function bt(e, t) {
1898
- for (let n = 0; n < e.length; n++) {
1899
- const s = e[n].match(gt);
1900
- if (!s || s[1].trim() !== t) continue;
1901
- let a = n + 1;
1902
- for (; a < e.length && !H.test(e[a]); ) a++;
1903
- return { start: n + 1, end: a };
1904
- }
1905
- }
1906
- function ve(e, t, n) {
1907
- const s = bt(e, t);
1908
- if (s)
1909
- for (let a = s.start; a < s.end; a++) {
1910
- const r = e[a].match(U);
1911
- if (!r || r[1].trim() !== n) continue;
1912
- let i = a + 1;
1913
- for (; i < s.end && !U.test(e[i]) && wt.test(e[i]); )
1914
- i++;
1915
- return { start: a, end: i };
1916
- }
1917
- }
1918
- function Wr(e, t, n, s) {
1919
- const a = e.split(`
1920
- `), r = ve(a, t, n);
1921
- if (!r) return e;
1922
- if (s === void 0)
1923
- return a.splice(r.start, r.end - r.start), a.join(`
1924
- `);
1925
- for (let i = r.start + 1; i < r.end; i++) {
1926
- const o = a[i].match(yt);
1927
- if (o && o[1].trim() === s)
1928
- return a.splice(i, 1), a.join(`
1929
- `);
1930
- }
1931
- return e;
1932
- }
1933
- function Jr(e, t, n, s) {
1934
- const a = e.split(`
1935
- `), r = bt(a, t);
1936
- if (!r) return e;
1937
- let i = r.end;
1938
- for (; i > r.start && a[i - 1].trim() === ""; ) i--;
1939
- return a.splice(i, 0, `- **${n}** — ${s}`), a.join(`
1940
- `);
1941
- }
1942
- function Vr(e, t, n, s) {
1943
- const a = e.split(`
1944
- `), r = ve(a, t, n);
1945
- return r ? (a.splice(r.end, 0, ` - ${s}`), a.join(`
1946
- `)) : e;
1947
- }
1948
- function Xr(e, t, n, s) {
1949
- const a = e.split(`
1950
- `), r = ve(a, t, n);
1951
- return r ? (a.splice(r.end, 0, ` - → ${s}`), a.join(`
1952
- `)) : e;
1953
- }
1954
- function oa(e) {
1955
- return [
1956
- ...e.horizons.flatMap((t) => t.items.map((n) => n.name)),
1957
- ...e.standingConcerns.map((t) => t.name)
1958
- ];
1959
- }
1960
- function Zr(e, t, n = [], s = "") {
1961
- const a = new Map(t.filter((c) => c.id).map((c) => [c.id, c])), r = /* @__PURE__ */ new Map();
1962
- for (const c of n)
1963
- c.planId && r.set(c.planId, (r.get(c.planId) ?? 0) + 1);
1964
- const i = e.horizons.map((c) => {
1965
- const u = c.items.map((p) => {
1966
- const h = p.linked.flatMap((g) => {
1967
- const m = a.get(g);
1968
- return m != null && m.status ? [
1969
- {
1970
- id: g,
1971
- status: m.status,
1972
- taskRuns: r.get(g) ?? 0,
1973
- pr: m.pr,
1974
- released: mt(s, g) !== void 0
1975
- }
1976
- ] : [];
1977
- }), w = { total: h.length, done: h.filter((g) => g.status === "done").length };
1978
- return { ...p, links: h, rollup: w };
1979
- }), l = u.reduce(
1980
- (p, h) => ({
1981
- total: p.total + h.rollup.total,
1982
- done: p.done + h.rollup.done
1983
- }),
1984
- { total: 0, done: 0 }
1985
- );
1986
- return { title: c.title, items: u, rollup: l };
1987
- }), o = ca(e, t, n);
1988
- return { goal: e.goal, horizons: i, events: o };
1989
- }
1990
- function ca(e, t, n) {
1991
- const s = /* @__PURE__ */ new Map();
1992
- for (const r of e.horizons)
1993
- for (const i of r.items)
1994
- for (const o of i.linked)
1995
- s.set(o, { horizonTitle: r.title, itemName: i.name });
1996
- const a = [];
1997
- for (const r of t) {
1998
- if (!r.id) continue;
1999
- const i = s.get(r.id);
2000
- i && a.push({
2001
- date: r.created,
2002
- kind: "created",
2003
- entityId: r.id,
2004
- horizonTitle: i.horizonTitle,
2005
- itemName: i.itemName,
2006
- label: `${r.title} created`
2007
- });
2008
- }
2009
- for (const r of n) {
2010
- if (!r.planId) continue;
2011
- const i = s.get(r.planId);
2012
- i && a.push({
2013
- date: r.startedAt,
2014
- kind: "task-run",
2015
- entityId: r.planId,
2016
- horizonTitle: i.horizonTitle,
2017
- itemName: i.itemName,
2018
- label: `${r.taskKind} run (${r.outcome})`
2019
- });
2020
- }
2021
- return a.sort((r, i) => Date.parse(r.date) - Date.parse(i.date));
2022
- }
2023
- function da(e) {
2024
- const t = JSON.stringify({
2025
- body: e.body,
2026
- phases: e.phases.map((n) => ({
2027
- done: n.done,
2028
- text: n.text,
2029
- description: n.description ?? null,
2030
- source: n.source ?? null
2031
- }))
2032
- });
2033
- return Gt("sha256").update(t).digest("hex");
2034
- }
2035
- const Ee = /* @__PURE__ */ new Set([
2036
- "core",
2037
- "cli",
2038
- "app",
2039
- "server",
2040
- "agent",
2041
- "audit",
2042
- "plans",
2043
- "ideas",
2044
- "docs",
2045
- "settings",
2046
- "stack",
2047
- "ui",
2048
- "ci",
2049
- "config",
2050
- "deps",
2051
- "repo",
2052
- "release",
2053
- "main"
2054
- ]);
2055
- function ua(e, t) {
2056
- return (e == null ? void 0 : e.find((n) => Ee.has(n))) ?? t;
2057
- }
2058
- function vt(e, t) {
2059
- return new Promise((n) => {
2060
- var r, i;
2061
- const s = b(
2062
- "gh",
2063
- ["pr", "view", t, "--json", "title,body,headRefName,labels,isDraft,state,url,comments"],
2064
- {
2065
- cwd: e,
2066
- stdio: ["ignore", "pipe", "pipe"]
2067
- }
2068
- );
2069
- let a = "";
2070
- (r = s.stdout) == null || r.on("data", (o) => {
2071
- a += o.toString();
2072
- }), (i = s.stderr) == null || i.on("data", () => {
2073
- }), s.on("close", (o) => {
2074
- if (o !== 0) {
2075
- n(void 0);
2076
- return;
2077
- }
2078
- try {
2079
- n(JSON.parse(a));
2080
- } catch {
2081
- n(void 0);
2082
- }
2083
- }), s.on("error", () => n(void 0));
2084
- });
2085
- }
2086
- const la = 6e4;
2087
- function Qr(e, t, n = la) {
2088
- return new Promise((s) => {
2089
- var i, o;
2090
- const a = b("gh", ["pr", "diff", t], { cwd: e, stdio: ["ignore", "pipe", "pipe"] });
2091
- let r = "";
2092
- (i = a.stdout) == null || i.on("data", (c) => {
2093
- r += c.toString();
2094
- }), (o = a.stderr) == null || o.on("data", () => {
2095
- }), a.on("close", (c) => {
2096
- if (c !== 0) {
2097
- s(void 0);
2098
- return;
2099
- }
2100
- s(
2101
- r.length > n ? `${r.slice(0, n)}
2102
- ... (diff truncated, exceeds size cap)` : r
2103
- );
2104
- }), a.on("error", () => s(void 0));
2105
- });
2106
- }
2107
- async function fa(e, t) {
2108
- for (const n of ["ideas", f("ideas", "archive")]) {
2109
- const s = f(e, "papercamp", n, `${t}.md`);
2110
- try {
2111
- return await xt(s), s;
2112
- } catch {
2113
- }
2114
- }
2115
- return null;
2116
- }
2117
- async function C(e, t) {
2118
- const n = await vt(e, t), s = Ue(n == null ? void 0 : n.body, (n == null ? void 0 : n.headRefName) ?? t);
2119
- if (!s) return;
2120
- const a = await fa(e, s);
2121
- if (!a) return;
2122
- const { entries: r } = rt(await v(a, "utf-8")), i = r[0];
2123
- if (i)
2124
- return { id: s, view: n, entry: i };
2125
- }
2126
- async function ei(e, t) {
2127
- const n = await C(e, t);
2128
- if (!n) return;
2129
- const { id: s, entry: a } = n;
2130
- return { id: s, kind: a.type, tags: a.tags, phases: a.phases };
2131
- }
2132
- const Et = "<!-- papercamp:phases:start -->", kt = "<!-- papercamp:phases:end -->", _e = new RegExp(`${Et}[\\s\\S]*?${kt}`);
2133
- function pa(e, t) {
2134
- const n = t.map((r) => `- [${r.done ? "x" : " "}] ${r.text}`).join(`
2135
- `), s = `${Et}
2136
- ### Phases
2137
- ${n}
2138
- ${kt}`;
2139
- if (_e.test(e)) return e.replace(_e, () => s);
2140
- const a = e.trimEnd();
2141
- return a.length > 0 ? `${a}
2142
-
2143
- ${s}` : s;
2144
- }
2145
- function ha(e, t, n) {
2146
- return new Promise((s) => {
2147
- var r, i;
2148
- const a = b("gh", ["pr", "edit", t, "--body-file", "-"], {
2149
- cwd: e,
2150
- stdio: ["pipe", "ignore", "pipe"]
2151
- });
2152
- (r = a.stderr) == null || r.on("data", () => {
2153
- }), a.on("close", (o) => s(o === 0)), a.on("error", () => s(!1)), (i = a.stdin) == null || i.end(n);
2154
- });
2155
- }
2156
- async function ti(e, t) {
2157
- const n = await C(e, t);
2158
- if (!(n != null && n.view)) return "unresolved";
2159
- const { view: s, entry: a } = n, r = pa(s.body, a.phases);
2160
- return r === s.body ? "unchanged" : await ha(e, t, r) ? "updated" : "unresolved";
2161
- }
2162
- function ma(e) {
2163
- const t = /* @__PURE__ */ new Set();
2164
- e.kind && t.add(e.kind);
2165
- for (const n of e.tags)
2166
- Ee.has(n) && t.add(n);
2167
- return [...t];
2168
- }
2169
- function ga(e) {
2170
- return new Promise((t) => {
2171
- var a, r;
2172
- const n = b("gh", ["label", "list", "--limit", "200", "--json", "name"], {
2173
- cwd: e,
2174
- stdio: ["ignore", "pipe", "pipe"]
2175
- });
2176
- let s = "";
2177
- (a = n.stdout) == null || a.on("data", (i) => {
2178
- s += i.toString();
2179
- }), (r = n.stderr) == null || r.on("data", () => {
2180
- }), n.on("close", (i) => {
2181
- if (i !== 0) {
2182
- t(void 0);
2183
- return;
2184
- }
2185
- try {
2186
- const o = JSON.parse(s);
2187
- t(new Set(o.map((c) => c.name)));
2188
- } catch {
2189
- t(void 0);
2190
- }
2191
- }), n.on("error", () => t(void 0));
2192
- });
2193
- }
2194
- function ya(e, t) {
2195
- return new Promise((n) => {
2196
- var a;
2197
- const s = b("gh", ["label", "create", t, "--color", "ededed"], {
2198
- cwd: e,
2199
- stdio: ["ignore", "ignore", "pipe"]
2200
- });
2201
- (a = s.stderr) == null || a.on("data", () => {
2202
- }), s.on("close", (r) => n(r === 0)), s.on("error", () => n(!1));
2203
- });
2204
- }
2205
- function wa(e, t, n) {
2206
- return new Promise((s) => {
2207
- var r;
2208
- const a = b("gh", ["pr", "edit", t, "--add-label", n.join(",")], {
2209
- cwd: e,
2210
- stdio: ["ignore", "ignore", "pipe"]
2211
- });
2212
- (r = a.stderr) == null || r.on("data", () => {
2213
- }), a.on("close", (i) => s(i === 0)), a.on("error", () => s(!1));
2214
- });
2215
- }
2216
- async function ni(e, t) {
2217
- const n = await C(e, t);
2218
- if (!(n != null && n.view)) return "unresolved";
2219
- const { view: s, entry: a } = n, r = ma({ kind: a.type, tags: a.tags }), i = new Set((s.labels ?? []).map((l) => l.name)), o = r.filter((l) => !i.has(l));
2220
- if (o.length === 0) return "unchanged";
2221
- const c = await ga(e);
2222
- if (c) {
2223
- const l = o.filter((p) => !c.has(p));
2224
- for (const p of l)
2225
- await ya(e, p);
2226
- }
2227
- return await wa(e, t, o) ? "updated" : "unresolved";
2228
- }
2229
- function St(e, t) {
2230
- const n = t.type ?? "feat", s = ua(t.tags, "repo");
2231
- return `${n}(${s}): ${t.title} (${e})`;
2232
- }
2233
- const ba = new RegExp(`^(${Ht.join("|")})\\(([a-z-]+)\\): .+$`);
2234
- function va(e) {
2235
- const t = e.match(ba);
2236
- return !!t && Ee.has(t[2]);
2237
- }
2238
- function Ea(e, t, n) {
2239
- return new Promise((s) => {
2240
- var r;
2241
- const a = b("gh", ["pr", "edit", t, "--title", n], {
2242
- cwd: e,
2243
- stdio: ["ignore", "ignore", "pipe"]
2244
- });
2245
- (r = a.stderr) == null || r.on("data", () => {
2246
- }), a.on("close", (i) => s(i === 0)), a.on("error", () => s(!1));
2247
- });
2248
- }
2249
- async function si(e, t) {
2250
- const n = await C(e, t);
2251
- if (!(n != null && n.view)) return "unresolved";
2252
- const { id: s, view: a, entry: r } = n, i = St(s, r);
2253
- return a.title === i ? "unchanged" : await Ea(e, t, i) ? "updated" : "unresolved";
2254
- }
2255
- async function ai(e, t) {
2256
- const n = await vt(e, t);
2257
- if (!n) return "no-pr";
2258
- const s = await C(e, t);
2259
- return s ? n.title === St(s.id, s.entry) ? "valid" : "invalid" : va(n.title) ? "valid" : "invalid";
2260
- }
2261
- function ri(e, t) {
2262
- return new Promise((n) => {
2263
- var r;
2264
- const s = b("gh", ["pr", "merge", t, "--squash"], {
2265
- cwd: e,
2266
- stdio: ["ignore", "ignore", "pipe"]
2267
- });
2268
- let a = "";
2269
- (r = s.stderr) == null || r.on("data", (i) => {
2270
- a += i.toString();
2271
- }), s.on("close", (i) => {
2272
- n(i === 0 ? { ok: !0 } : {
2273
- ok: !1,
2274
- message: a.trim() || `gh pr merge ${t} --squash exited with code ${i}`
2275
- });
2276
- }), s.on("error", (i) => n({ ok: !1, message: i.message }));
2277
- });
2278
- }
2279
- function ka(e, t) {
2280
- return new Promise((n) => {
2281
- var a;
2282
- const s = b("gh", ["pr", "ready", t], {
2283
- cwd: e,
2284
- stdio: ["ignore", "ignore", "pipe"]
2285
- });
2286
- (a = s.stderr) == null || a.on("data", () => {
2287
- }), s.on("close", (r) => n(r === 0)), s.on("error", () => n(!1));
2288
- });
2289
- }
2290
- function Sa(e, t) {
2291
- return new Promise((n) => {
2292
- var a;
2293
- const s = b("gh", ["pr", "close", t], {
2294
- cwd: e,
2295
- stdio: ["ignore", "ignore", "pipe"]
2296
- });
2297
- (a = s.stderr) == null || a.on("data", () => {
2298
- }), s.on("close", (r) => n(r === 0)), s.on("error", () => n(!1));
2299
- });
2300
- }
2301
- async function ii(e, t) {
2302
- const n = await C(e, t);
2303
- if (!(n != null && n.view)) return "unresolved";
2304
- const { view: s, entry: a } = n;
2305
- return a.status === "dropped" ? s.state !== "OPEN" ? "unchanged" : await Sa(e, t) ? "closed" : "unresolved" : !(a.phases.length > 0 && a.phases.every((o) => o.done)) || !s.isDraft ? "unchanged" : await ka(e, t) ? "ready" : "unresolved";
2306
- }
2307
- const $t = "<!-- papercamp:consistency:start -->", $a = "<!-- papercamp:consistency:end -->";
2308
- function Ia(e, t) {
2309
- const n = ["### Paper Camp checks", ""];
2310
- if (e.length === 0)
2311
- n.push("No consistency issues found.");
2312
- else
2313
- for (const s of e)
2314
- n.push(`- **${s.kind}** (${s.section}): ${s.message}`);
2315
- return t && (n.push(""), n.push(
2316
- t.stale ? `Convergence audit: last run \`${t.audited}\`, plan has changed since — due for a re-audit.` : `Convergence audit: last run \`${t.audited}\`, still current.`
2317
- )), `${$t}
2318
- ${n.join(`
2319
- `)}
2320
- ${$a}`;
2321
- }
2322
- function Ra(e, t, n) {
2323
- return new Promise((s) => {
2324
- var r, i;
2325
- const a = b("gh", ["pr", "comment", t, "--body-file", "-"], {
2326
- cwd: e,
2327
- stdio: ["pipe", "ignore", "pipe"]
2328
- });
2329
- (r = a.stderr) == null || r.on("data", () => {
2330
- }), a.on("close", (o) => s(o === 0)), a.on("error", () => s(!1)), (i = a.stdin) == null || i.end(n);
2331
- });
2332
- }
2333
- function Aa(e, t, n, s, a) {
2334
- return new Promise((r) => {
2335
- var o, c;
2336
- const i = b(
2337
- "gh",
2338
- [
2339
- "api",
2340
- `repos/${t}/${n}/issues/comments/${s}`,
2341
- "-X",
2342
- "PATCH",
2343
- "-F",
2344
- "body=@-"
2345
- ],
2346
- { cwd: e, stdio: ["pipe", "ignore", "pipe"] }
2347
- );
2348
- (o = i.stderr) == null || o.on("data", () => {
2349
- }), i.on("close", (u) => r(u === 0)), i.on("error", () => r(!1)), (c = i.stdin) == null || c.end(a);
2350
- });
2351
- }
2352
- async function oi(e, t) {
2353
- var g, m;
2354
- const n = await C(e, t);
2355
- if (!((g = n == null ? void 0 : n.view) != null && g.url)) return "unresolved";
2356
- const { view: s, entry: a } = n, [{ entries: r }, i] = await Promise.all([
2357
- _(f(e, "papercamp", "ideas")),
2358
- v(f(e, "ROADMAP.md"), "utf-8").catch(() => "")
2359
- ]), o = r.filter((y) => y.kind !== "note").map((y) => He(y)), c = i ? oa(ia(i)) : [], u = is(o, c), l = a.audited && a.auditedHash ? {
2360
- audited: a.audited,
2361
- stale: da(a) !== a.auditedHash
2362
- } : void 0, p = Ia(u, l), h = (s.comments ?? []).find((y) => y.body.includes($t));
2363
- if (h) {
2364
- if (h.body === p) return "unchanged";
2365
- const y = j(s.url), x = (m = h.url.match(/issuecomment-(\d+)/)) == null ? void 0 : m[1];
2366
- return !y || !x ? "unresolved" : await Aa(e, y.owner, y.repo, x, p) ? "updated" : "unresolved";
2367
- }
2368
- return await Ra(e, t, p) ? "created" : "unresolved";
2369
- }
2370
- function ci(e, t, n) {
2371
- if (!e) return;
2372
- const s = (t ?? "feat").toLowerCase(), a = n.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""), r = a.length <= 40 ? a : a[40] === "-" ? a.slice(0, 40) : a.slice(0, 40).replace(/-[^-]*$/, "");
2373
- return `${s}/${e.toLowerCase()}-${r}`;
2374
- }
2375
- function X(e, t) {
2376
- for (const { entries: n, section: s } of t)
2377
- n && n.length > 0 && e.push(s.formatLines(n).join(`
2378
- `));
2379
- }
2380
- function It() {
2381
- return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2382
- }
2383
- function di(e, t = "log", n) {
2384
- return {
2385
- kind: t,
2386
- date: It(),
2387
- text: e,
2388
- from: "agent",
2389
- ...t === "question" ? { state: "open" } : {},
2390
- ...n ? { entityId: n } : {}
2391
- };
2392
- }
2393
- function ui(e) {
2394
- const t = [`## ${e.title}`, "", `**Status:** ${e.status}`];
2395
- e.kind && t.push(`**Kind:** ${e.kind}`), e.id && t.push(`**Id:** ${e.id}`), e.idea && t.push(`**Idea:** ${e.idea}`), e.agent && t.push(`**Agent:** ${e.agent}`), t.push(`**Created:** ${e.created}`), e.updated && t.push(`**Updated:** ${e.updated}`), e.tags && e.tags.length > 0 && t.push(`**Tags:** ${e.tags.join(", ")}`);
2396
- const n = [t.join(`
2397
- `)];
2398
- return e.body && n.push(e.body), X(n, [
2399
- { entries: e.clarifications, section: le },
2400
- { entries: e.phases, section: V },
2401
- { entries: e.log, section: L },
2402
- { entries: e.notes, section: fe }
2403
- ]), n.join(`
2404
-
2405
- `).trimEnd();
2406
- }
2407
- function ke(e) {
2408
- return `---
2409
- ${jt(e).trimEnd()}
2410
- ---`;
2411
- }
2412
- function li(e) {
2413
- const t = {
2414
- id: e.id,
2415
- title: e.title,
2416
- kind: e.kind,
2417
- status: e.status,
2418
- created: e.created
2419
- };
2420
- e.idea && (t.idea = e.idea), e.agent && (t.agent = e.agent), e.updated && (t.updated = e.updated), e.audited && (t.audited = e.audited), e.auditedHash && (t["audited-hash"] = e.auditedHash), e.tags && e.tags.length > 0 && (t.tags = e.tags);
2421
- const n = [ke(t)];
2422
- return e.body && n.push(e.body), X(n, [
2423
- { entries: e.clarifications, section: le },
2424
- { entries: e.phases, section: V },
2425
- { entries: e.log, section: L },
2426
- { entries: e.notes, section: fe }
2427
- ]), n.join(`
2428
-
2429
- `).trimEnd();
2430
- }
2431
- function Pa(e) {
2432
- const t = {
2433
- id: e.id,
2434
- title: e.title
2435
- };
2436
- e.type && (t.type = e.type), e.kind && (t.kind = e.kind), e.status && (t.status = e.status), e.idea && (t.idea = e.idea), t.created = e.created, e.agent && (t.agent = e.agent), e.updated && (t.updated = e.updated), e.audited && (t.audited = e.audited), e.auditedHash && (t["audited-hash"] = e.auditedHash), e.released && (t.released = e.released), e.tags && e.tags.length > 0 && (t.tags = e.tags), e.subject && (t.subject = e.subject), e.order !== void 0 && (t.order = e.order), e.issueSource && (t.issueSource = e.issueSource);
2437
- for (const s of Object.keys(e.unknownFrontmatter ?? {}).sort())
2438
- t[s] = e.unknownFrontmatter[s];
2439
- const n = [ke(t)];
2440
- return e.body && n.push(e.body), X(n, [
2441
- { entries: e.phases, section: V },
2442
- { entries: e.fixes, section: tt },
2443
- { entries: e.thread, section: nt }
2444
- ]), n.join(`
2445
-
2446
- `).trimEnd();
2447
- }
2448
- function fi(e) {
2449
- const t = {
2450
- id: e.id,
2451
- title: e.title
2452
- };
2453
- e.kind && (t.kind = e.kind), e.status && (t.status = e.status);
2454
- const n = [ke(t)], s = `## ${e.id}: ${e.title}`;
2455
- return n.push(e.body ? `${s}
2456
-
2457
- ${e.body}` : s), X(n, [{ entries: e.log, section: L }]), n.join(`
2458
-
2459
- `).trimEnd();
2460
- }
2461
- function pi(e, t) {
2462
- let n = !1;
2463
- const s = e.split(`
2464
- `).filter((a) => {
2465
- if (!n) {
2466
- const r = a.match(it);
2467
- if (r && r[1] === t.date && r[2].trim() === t.title && r[3].trim() === t.description)
2468
- return n = !0, !1;
2469
- }
2470
- return !0;
2471
- });
2472
- return n ? s.join(`
2473
- `) : e;
2474
- }
2475
- let z = Promise.resolve();
2476
- async function Ca(e, t) {
2477
- const n = new RegExp(`^${t.toUpperCase()}-(\\d+)\\.md$`), s = [
2478
- f(e, "ideas"),
2479
- f(e, "ideas", "archive"),
2480
- f(e, "plans"),
2481
- f(e, "plans", "archive")
2482
- ];
2483
- let a = 0;
2484
- for (const r of s) {
2485
- let i;
2486
- try {
2487
- i = await K(r);
2488
- } catch {
2489
- continue;
2490
- }
2491
- for (const o of i) {
2492
- const c = n.exec(o);
2493
- c && (a = Math.max(a, Number(c[1])));
2494
- }
2495
- }
2496
- return a;
2497
- }
2498
- async function Rt(e, t) {
2499
- const n = z.then(async () => {
2500
- let s = null;
2501
- try {
2502
- s = JSON.parse(await v(e, "utf-8"));
2503
- } catch {
2504
- return;
2505
- }
2506
- if (!(s != null && s.nextId)) return;
2507
- const a = s.nextId[t] ?? 1, r = await Ca(D(e), t), i = Math.max(a, r + 1), o = `${t.toUpperCase()}-${i}`;
2508
- return s.nextId[t] = i + 1, await E(e, `${JSON.stringify(s, null, 2)}
2509
- `), o;
2510
- });
2511
- return z = n.catch(() => {
2512
- }), n;
2513
- }
2514
- async function hi(e) {
2515
- return Rt(e, "idea");
2516
- }
2517
- async function mi(e) {
2518
- return Rt(e, "ticket");
2519
- }
2520
- async function gi(e, t) {
2521
- const n = z.then(async () => {
2522
- let s = null;
2523
- try {
2524
- s = JSON.parse(await v(e, "utf-8"));
2525
- } catch {
2526
- return;
2527
- }
2528
- const a = s.subjects ?? [];
2529
- a.includes(t) || (s.subjects = [...a, t], await E(e, `${JSON.stringify(s, null, 2)}
2530
- `));
2531
- });
2532
- return z = n.catch(() => {
2533
- }), n;
2534
- }
2535
- async function yi(e, t) {
2536
- const n = f(e, "papercamp", "ideas"), s = f(n, "archive"), a = f(n, `${t}.md`), r = f(s, `${t}.md`);
2537
- await P(s, { recursive: !0 });
2538
- try {
2539
- return await Ot(a, r), !0;
2540
- } catch (i) {
2541
- if (i.code === "ENOENT") return !1;
2542
- throw i;
2543
- }
2544
- }
2545
- const Ta = [
2546
- ["pnpm-lock.yaml", "pnpm"],
2547
- ["yarn.lock", "yarn"],
2548
- ["bun.lockb", "bun"],
2549
- ["package-lock.json", "npm"]
2550
- ];
2551
- function At(e) {
2552
- for (const [t, n] of Ta)
2553
- if (ae(f(e, t))) return n;
2554
- return "npm";
2555
- }
2556
- function Na(e) {
2557
- const t = f(e, "package.json");
2558
- if (ae(t))
2559
- try {
2560
- return JSON.parse(Me(t, "utf-8"));
2561
- } catch {
2562
- return;
2563
- }
2564
- }
2565
- const xe = "@dendelion/paper-camp";
2566
- function _a(e) {
2567
- const t = Na(e);
2568
- if (!t) return !1;
2569
- const n = t.dependencies, s = t.devDependencies;
2570
- return !!(n != null && n[xe] || s != null && s[xe]);
2571
- }
2572
- const xa = ["*.json", "*.ts", "*.tsx", "*.md", "*.config.*"], Oa = ["src/**", "app/**", "scripts/**", "papercamp/**"], Da = ["git status*", "git diff*", "git log*"], Ma = ["ls*", "cat*", "wc*"], ja = ["run *", "test*", "install*", "view *", "pack*", "ls*"], La = ["npx tsc*", "npx biome check*", "npx vitest*", "npx jest*", "npx expo *"];
2573
- function Pt(e) {
2574
- const t = Oa.flatMap((a) => [`Edit(${a})`, `Write(${a})`]), n = xa.flatMap((a) => [`Edit(${a})`, `Write(${a})`]), s = [
2575
- ...Da,
2576
- ...Ma,
2577
- ...ja.map((a) => `${e} ${a}`),
2578
- ...La
2579
- ].map((a) => `Bash(${a})`);
2580
- return [...t, ...n, ...s];
2581
- }
2582
- function Fa(e) {
2583
- return e ? `"${Ya}" session-focus` : "paper-camp session-focus";
2584
- }
2585
- function Ha(e, t) {
2586
- let n;
2587
- try {
2588
- n = JSON.parse(e);
2589
- } catch {
2590
- return e;
2591
- }
2592
- const s = Pt(At(t)), a = n.permissions ?? {}, r = Array.isArray(a.allow) ? a.allow : [], i = s.filter((o) => !r.includes(o));
2593
- return i.length === 0 && n.permissions !== void 0 ? e : (n.permissions = { ...a, allow: [...r, ...i] }, `${JSON.stringify(n, null, 2)}
2594
- `);
2595
- }
2596
- function Ga(e) {
2597
- const t = At(e), n = Fa(_a(e));
2598
- return `${JSON.stringify(
2599
- {
2600
- permissions: {
2601
- allow: Pt(t)
2602
- },
2603
- hooks: {
2604
- SessionStart: [
2605
- {
2606
- matcher: "*",
2607
- hooks: [{ type: "command", command: n }]
2608
- }
2609
- ]
2610
- }
2611
- },
2612
- null,
2613
- 2
2614
- )}
2615
- `;
2616
- }
2617
- const Ba = `---
2618
- name: paper-camp
2619
- description: Work inside a project that has a papercamp/ folder — its unified idea entities (each holding its plan as a section), with decisions and open questions logged as notes on the idea they bind. Use this whenever the working directory contains papercamp/ (papercamp/ideas/), and especially before starting, continuing, or completing any plan phase, drafting an idea, logging a decision, or answering "what are we working on / what's next".
2620
- ---
2621
-
2622
- # Paper Camp
2623
-
2624
- Paper Camp is this project's planning methodology: plans and ideas are one
2625
- thing, a unified entity file under \`papercamp/ideas/\`, with decisions and
2626
- open questions logged as notes bound to the idea they concern. This skill
2627
- tells you how to read that state before acting and how to keep it honest as
2628
- you work.
2629
-
2630
- If a \`papercamp\` MCP server is connected in this session, prefer its tools
2631
- (list/get plans, update phase, etc.) over raw file access —
2632
- they enforce the same guards (id allocation, branch conflicts) that the file
2633
- grammar below assumes. Everything in this skill still applies conceptually;
2634
- only the mechanism changes.
2635
-
2636
- ## Before doing any work
2637
-
2638
- Read, in this order, whatever exists:
2639
-
2640
- 1. \`papercamp/ideas/\` — one file per entity, named by id. Ideas and plans are
2641
- one thing: an entity is an *idea* for its whole life, and its plan is a
2642
- \`### Phases\` section inside the same file.
2643
- 2. The specific entity file at \`papercamp/ideas/<ID>.md\` (e.g. \`IDEA-43.md\`)
2644
- for the work you're about to do — YAML frontmatter (\`id\`, \`title\`,
2645
- \`type\`, \`status\`, \`tags\`, ...) plus prose rationale, then optionally a
2646
- \`### Phases\` list of \`- [ ]\`/\`- [x]\` checkboxes with an indented
2647
- description under each. Done/dropped entities live in
2648
- \`papercamp/ideas/archive/\`.
2649
- Its notes carry any decision or open question bound to it — settled calls
2650
- you shouldn't re-litigate without flagging it to the user first, and
2651
- unresolved questions that might block or redirect the work you're about
2652
- to start.
2653
-
2654
- Skip files that don't exist yet (a fresh project may have empty logs).
2655
-
2656
- ## While working
2657
-
2658
- - Work one plan phase at a time unless told otherwise — don't cascade into
2659
- later phases just because they look quick.
2660
- - If a phase's boundary or intent is unclear, ask before continuing.
2661
- - Prose in plans and ideas is more current than your memory of past
2662
- conversations. If they conflict, the files win — say so and resync.
2663
-
2664
- ## Keep the project current as you go
2665
-
2666
- - **Plan phases**: when you finish a phase, flip its checkbox from \`- [ ]\` to
2667
- \`- [x]\` in the plan's frontmatter file. Change only that line — don't touch
2668
- other phases or prose.
2669
- - **Plan status**: keep the plan's \`status:\` frontmatter honest
2670
- (\`planned\` / \`in-progress\` / \`review\` / \`done\`). When every phase is
2671
- checked, set status to \`review\` — never \`done\`. \`done\` is a human-only
2672
- promotion after review; an agent finishing the last phase does not close
2673
- the plan itself.
2674
- - **Decisions / open questions**: if you settle something ambiguous while
2675
- working, log it as a decision note on the idea it bounds; if you surface a
2676
- question you can't resolve yourself, add it as a question note on that idea
2677
- rather than guessing silently.
2678
-
2679
- ## What this skill deliberately does not do
2680
-
2681
- It does not maintain a separate "current focus" file — that's derived at
2682
- session start from live plan data, not hand-maintained here. It does
2683
- not define the file formats in full; treat the existing files under
2684
- \`papercamp/\` as the grammar reference (mirror their structure exactly rather
2685
- than inventing a new shape).
2686
- `, Ya = "$CLAUDE_PROJECT_DIR/node_modules/.bin/paper-camp", qa = 5;
2687
- function Ua() {
2688
- try {
2689
- let e = D(Bt(import.meta.url));
2690
- for (let t = 0; t < qa; t++) {
2691
- const n = f(e, "package.json");
2692
- if (ae(n))
2693
- return JSON.parse(Me(n, "utf-8")).version ?? "0.0.0";
2694
- e = D(e);
2695
- }
2696
- return "0.0.0";
2697
- } catch {
2698
- return "0.0.0";
2699
- }
2700
- }
2701
- const wi = Ua();
2702
- class za extends Error {
2703
- constructor(t) {
2704
- super(`Paper Camp is already initialized in ${t} (papercamp/config.json exists).`);
2705
- }
2706
- }
2707
- async function T(e) {
2708
- try {
2709
- return await Dt(e), !0;
2710
- } catch {
2711
- return !1;
2712
- }
2713
- }
2714
- const Ka = ["suggestions.md"];
2715
- async function bi(e, t) {
2716
- const n = f(e, "papercamp"), s = f(n, "config.json");
2717
- if (await T(s))
2718
- throw new za(e);
2719
- const a = {
2720
- version: R,
2721
- projectName: t.projectName,
2722
- initializedAt: (/* @__PURE__ */ new Date()).toISOString(),
2723
- nextId: { idea: 2 }
2724
- };
2725
- Xn.parse(a), await P(n, { recursive: !0 });
2726
- const r = f(n, "ideas");
2727
- await P(r, { recursive: !0 });
2728
- const i = f(r, "archive");
2729
- await P(i, { recursive: !0 });
2730
- const o = f(r, "IDEA-1.md");
2731
- if (!await T(o)) {
2732
- const c = Pa({
2733
- id: "IDEA-1",
2734
- title: "Capture your first idea",
2735
- status: "idea",
2736
- created: It(),
2737
- body: `This is an example idea, in the format Paper Camp expects: a short title, a status, and a paragraph of context. Read it, then archive or delete it once you've written your own.
2738
-
2739
- Use the New idea button to capture what you're building next, or ask an agent for suggestions.`
2740
- });
2741
- await E(o, `${c}
2742
- `, "utf-8");
2743
- }
2744
- for (const c of Ka) {
2745
- const u = f(n, c);
2746
- await T(u) || await E(u, "", "utf-8");
2747
- }
2748
- await E(s, `${JSON.stringify(a, null, 2)}
2749
- `, "utf-8"), await Ja(e), await Va(e), await Wa(e, t.projectName);
2750
- }
2751
- async function Wa(e, t) {
2752
- const n = Ut(), s = await zt(n), { registry: a, created: r } = Kt(s, e, t);
2753
- r && await Wt(n, a);
2754
- }
2755
- const Q = "papercamp/.pairing.json";
2756
- async function Ja(e) {
2757
- const t = f(e, ".gitignore"), n = await T(t) ? await v(t, "utf-8") : "", s = n.length > 0 ? n.split(`
2758
- `) : [];
2759
- if (s.some((r) => r.trim() === Q)) return;
2760
- const a = s.reduce(
2761
- (r, i, o) => i.startsWith("papercamp/") ? o : r,
2762
- -1
2763
- );
2764
- if (a === -1) {
2765
- const r = n.length > 0 && !n.endsWith(`
2766
- `) ? `
2767
- ` : "";
2768
- await E(t, `${n}${r}${Q}
2769
- `, "utf-8");
2770
- return;
2771
- }
2772
- s.splice(a + 1, 0, Q), await E(t, s.join(`
2773
- `), "utf-8");
2774
- }
2775
- async function Va(e) {
2776
- const t = f(e, ".claude", "skills", "paper-camp");
2777
- await P(t, { recursive: !0 });
2778
- const n = f(t, "SKILL.md");
2779
- await T(n) || await E(n, Ba, "utf-8");
2780
- const s = f(e, ".claude");
2781
- await P(s, { recursive: !0 });
2782
- const a = f(s, "settings.json");
2783
- if (await T(a)) {
2784
- const r = await v(a, "utf-8"), i = Ha(r, e);
2785
- i !== r && await E(a, i, "utf-8");
2786
- } else
2787
- await E(a, Ga(e), "utf-8");
2788
- }
2789
- const Ct = {
2790
- feat: "Features",
2791
- fix: "Bug Fixes",
2792
- refactor: "Code Refactoring",
2793
- docs: "Documentation",
2794
- chore: "Miscellaneous"
2795
- }, Xa = Array.from(new Set(Object.values(Ct)));
2796
- async function vi(e, t) {
2797
- const n = await q(f(e, "CHANGELOG.md")), s = Vs(n).find((o) => o.version === t);
2798
- if (!s) return null;
2799
- const [{ entries: a }, r] = await Promise.all([
2800
- _(f(e, "papercamp", "ideas")),
2801
- na(e, s.range)
2802
- ]), i = /* @__PURE__ */ new Map();
2803
- for (const o of r.keys()) {
2804
- const c = a.find((p) => p.id === o);
2805
- if (!c) continue;
2806
- const u = Ct[c.type ?? "chore"], l = i.get(u) ?? [];
2807
- l.push({ id: c.id, title: c.title }), i.set(u, l);
2808
- }
2809
- return Xa.filter((o) => i.has(o)).map((o) => ({
2810
- label: o,
2811
- ideas: i.get(o)
2812
- }));
2813
- }
2814
- function Ei(e, t) {
2815
- const n = [`## ${e}`];
2816
- for (const s of t) {
2817
- n.push("", `### ${s.label}`, "");
2818
- for (const a of s.ideas)
2819
- n.push(`- ${a.title} (${a.id})`);
2820
- }
2821
- return n.join(`
2822
- `);
2823
- }
2824
- function Za(e) {
2825
- return Math.floor((Date.now() - Date.parse(e)) / 864e5);
2826
- }
2827
- const Tt = (e, t) => e === "question" && (t ?? "open") === "open", Nt = (e) => !!e.archived || e.status === "done" || e.status === "dropped";
2828
- function Qa(e) {
2829
- return e.filter((t) => !Nt(t)).flatMap(
2830
- (t) => (t.thread ?? []).filter((n) => Tt(n.kind, n.state)).map((n) => ({
2831
- entityId: t.id,
2832
- entityTitle: t.title,
2833
- text: n.text,
2834
- date: n.date,
2835
- ageDays: n.date ? Za(n.date) : Number.POSITIVE_INFINITY
2836
- }))
2837
- ).sort((t, n) => n.ageDays - t.ageDays);
2838
- }
2839
- async function ki(e) {
2840
- const { entries: t } = await _(e);
2841
- return Qa(t);
2842
- }
2843
- const er = /\[\[([A-Z]+-\d+)\]\]/;
2844
- function Si(e, t) {
2845
- const n = new Set(t.filter(Nt).map((s) => s.id));
2846
- return e.map((s) => {
2847
- var r;
2848
- if (!Tt(s.kind, s.state)) return s;
2849
- const a = (r = s.text.match(er)) == null ? void 0 : r[1];
2850
- return a && n.has(a) ? { ...s, state: "resolved" } : s;
2851
- });
2852
- }
2853
- const ne = 0.95, _t = 3e4, se = {
2854
- implement: { from: 0, to: 0.6 },
2855
- verify: { from: 0.6, to: 0.9 },
2856
- checkbox: { from: 0.95, to: 0.95 }
2857
- }, Oe = {
2858
- implement: 0,
2859
- verify: 1,
2860
- checkbox: 2
2861
- };
2862
- function De(e, ...t) {
2863
- for (const n of t)
2864
- if (typeof (e == null ? void 0 : e[n]) == "string") return e[n];
2865
- return "";
2866
- }
2867
- function $i(e, t) {
2868
- const n = e.toLowerCase();
2869
- if (n === "bash")
2870
- return (typeof (t == null ? void 0 : t.command) == "string" ? t.command : "").includes("check-types") ? "verify" : null;
2871
- if (n === "edit" || n === "multiedit" || n === "write") {
2872
- const s = De(t, "old_string", "oldString"), a = De(t, "new_string", "newString");
2873
- return s.includes("- [ ]") && a.includes("- [x]") ? "checkbox" : "implement";
2874
- }
2875
- return null;
2876
- }
2877
- function Ii(e, t) {
2878
- return e ? Oe[t] > Oe[e] ? t : e : t;
2879
- }
2880
- function Ri(e, t) {
2881
- return e === void 0 ? !1 : t - e >= _t;
2882
- }
2883
- function tr(e) {
2884
- const t = [...e].sort((s, a) => s - a), n = Math.floor(t.length / 2);
2885
- return t.length % 2 === 0 ? (t[n - 1] + t[n]) / 2 : t[n];
2886
- }
2887
- function Ai(e) {
2888
- const t = e.filter((a) => a.taskKind === "phase" && a.outcome === "done").map(
2889
- (a) => (a.endedAt ? Date.parse(a.endedAt) : Number.NaN) - Date.parse(a.startedAt)
2890
- ).filter((a) => Number.isFinite(a) && a > 0);
2891
- if (t.length === 0) return {};
2892
- const n = tr(t), s = {};
2893
- for (const a of ["implement", "verify"]) {
2894
- const r = se[a].to - se[a].from;
2895
- s[a] = n * r / ne;
2896
- }
2897
- return s;
2898
- }
2899
- function Pi({
2900
- anchor: e,
2901
- anchorEnteredAt: t,
2902
- lastStreamAt: n,
2903
- now: s,
2904
- medians: a
2905
- }) {
2906
- if (!e) return 0;
2907
- const r = se[e], i = Math.min(r.from, ne), o = a == null ? void 0 : a[e];
2908
- if (!o || o <= 0 || t === void 0 || r.to === r.from)
2909
- return i;
2910
- const c = n === void 0 ? s : Math.min(s, n + _t), u = Math.min(1, Math.max(0, c - t) / o);
2911
- return Math.min(r.from + u * (r.to - r.from), ne);
2912
- }
2913
- export {
2914
- Fr as $,
2915
- za as A,
2916
- St as B,
2917
- Ee as C,
2918
- Hs as D,
2919
- kr as E,
2920
- I as F,
2921
- ma as G,
2922
- ca as H,
2923
- oa as I,
2924
- Gr as J,
2925
- Yn as K,
2926
- qn as L,
2927
- Ce as M,
2928
- Un as N,
2929
- Bn as O,
2930
- wi as P,
2931
- At as Q,
2932
- Sr as R,
2933
- Ba as S,
2934
- gi as T,
2935
- Ir as U,
2936
- Gn as V,
2937
- at as W,
2938
- sn as X,
2939
- He as Y,
2940
- Qr as Z,
2941
- br as _,
2942
- an as a,
2943
- Vs as a$,
2944
- is as a0,
2945
- mt as a1,
2946
- Y as a2,
2947
- Pa as a3,
2948
- fi as a4,
2949
- ui as a5,
2950
- li as a6,
2951
- Ei as a7,
2952
- Rr as a8,
2953
- _a as a9,
2954
- zr as aA,
2955
- Ln as aB,
2956
- Fn as aC,
2957
- Pr as aD,
2958
- Cr as aE,
2959
- _ as aF,
2960
- jr as aG,
2961
- q as aH,
2962
- Hr as aI,
2963
- ki as aJ,
2964
- os as aK,
2965
- Lr as aL,
2966
- Wr as aM,
2967
- pi as aN,
2968
- Ia as aO,
2969
- pa as aP,
2970
- Er as aQ,
2971
- Br as aR,
2972
- Si as aS,
2973
- ta as aT,
2974
- Kr as aU,
2975
- ee as aV,
2976
- na as aW,
2977
- ei as aX,
2978
- ua as aY,
2979
- Xe as aZ,
2980
- vi as a_,
2981
- Hn as aa,
2982
- bi as ab,
2983
- Nt as ac,
2984
- va as ad,
2985
- Ri as ae,
2986
- Xr as af,
2987
- Ai as ag,
2988
- Ha as ah,
2989
- Wn as ai,
2990
- Kn as aj,
2991
- zn as ak,
2992
- Jn as al,
2993
- Xn as am,
2994
- rt as an,
2995
- fr as ao,
2996
- he as ap,
2997
- _r as aq,
2998
- xr as ar,
2999
- Or as as,
3000
- Nr as at,
3001
- Tr as au,
3002
- ts as av,
3003
- ia as aw,
3004
- Dr as ax,
3005
- $r as ay,
3006
- Pi as az,
3007
- Ks as b,
3008
- vr as b0,
3009
- Zr as b1,
3010
- Ur as b2,
3011
- Us as b3,
3012
- Va as b4,
3013
- vn as b5,
3014
- ke as b6,
3015
- ct as b7,
3016
- ri as b8,
3017
- Zn as b9,
3018
- oi as ba,
3019
- ti as bb,
3020
- ni as bc,
3021
- ii as bd,
3022
- si as be,
3023
- It as bf,
3024
- ai as bg,
3025
- Vn as bh,
3026
- nt as bi,
3027
- Yr as bj,
3028
- cs as bk,
3029
- Mr as bl,
3030
- hr as bm,
3031
- gr as bn,
3032
- Fe as bo,
3033
- S as bp,
3034
- yr as bq,
3035
- mr as br,
3036
- wr as bs,
3037
- Qt as bt,
3038
- qr as bu,
3039
- ls as c,
3040
- fs as d,
3041
- ne as e,
3042
- _t as f,
3043
- it as g,
3044
- Vr as h,
3045
- Jr as i,
3046
- Ii as j,
3047
- $ as k,
3048
- di as l,
3049
- pr as m,
3050
- yi as n,
3051
- hi as o,
3052
- Rt as p,
3053
- mi as q,
3054
- ci as r,
3055
- Ga as s,
3056
- Pt as t,
3057
- Fa as u,
3058
- $i as v,
3059
- Ar as w,
3060
- qs as x,
3061
- Qa as y,
3062
- da as z
3063
- };
3064
- //# sourceMappingURL=phase-progress.r-Xs-Sr0.js.map