@markmdev/pebble 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js
CHANGED
|
@@ -1137,11 +1137,31 @@ function closeCommand(program2) {
|
|
|
1137
1137
|
};
|
|
1138
1138
|
appendEvent(closeEvent, pebbleDir);
|
|
1139
1139
|
const unblocked = getNewlyUnblocked(resolvedId);
|
|
1140
|
+
let autoClosed;
|
|
1141
|
+
if (issue.verifies) {
|
|
1142
|
+
const targetIssue = getIssue(issue.verifies);
|
|
1143
|
+
if (targetIssue && targetIssue.status === "pending_verification") {
|
|
1144
|
+
const remainingVerifications = getVerifications(issue.verifies).filter((v) => v.status !== "closed");
|
|
1145
|
+
if (remainingVerifications.length === 0) {
|
|
1146
|
+
const autoCloseEvent = {
|
|
1147
|
+
type: "close",
|
|
1148
|
+
issueId: issue.verifies,
|
|
1149
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1150
|
+
data: {
|
|
1151
|
+
reason: "All verifications completed"
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
appendEvent(autoCloseEvent, pebbleDir);
|
|
1155
|
+
autoClosed = { id: targetIssue.id, title: targetIssue.title };
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1140
1159
|
results.push({
|
|
1141
1160
|
id: resolvedId,
|
|
1142
1161
|
success: true,
|
|
1143
1162
|
status: "closed",
|
|
1144
|
-
unblocked: unblocked.length > 0 ? unblocked.map((i) => ({ id: i.id, title: i.title })) : void 0
|
|
1163
|
+
unblocked: unblocked.length > 0 ? unblocked.map((i) => ({ id: i.id, title: i.title })) : void 0,
|
|
1164
|
+
autoClosed
|
|
1145
1165
|
});
|
|
1146
1166
|
} catch (error) {
|
|
1147
1167
|
results.push({ id, success: false, error: error.message });
|
|
@@ -1169,6 +1189,10 @@ Unblocked:`);
|
|
|
1169
1189
|
console.log(` \u2192 ${u.id} - ${u.title}`);
|
|
1170
1190
|
}
|
|
1171
1191
|
}
|
|
1192
|
+
if (result.autoClosed) {
|
|
1193
|
+
console.log(`
|
|
1194
|
+
\u2713 ${result.autoClosed.id} auto-closed (all verifications complete)`);
|
|
1195
|
+
}
|
|
1172
1196
|
}
|
|
1173
1197
|
} else {
|
|
1174
1198
|
console.log(formatJson({
|
|
@@ -1177,7 +1201,8 @@ Unblocked:`);
|
|
|
1177
1201
|
status: result.status,
|
|
1178
1202
|
...result.pendingVerifications && { pendingVerifications: result.pendingVerifications },
|
|
1179
1203
|
...result.pendingVerifications && { hint: `pb verifications ${result.id}` },
|
|
1180
|
-
...result.unblocked && { unblocked: result.unblocked }
|
|
1204
|
+
...result.unblocked && { unblocked: result.unblocked },
|
|
1205
|
+
...result.autoClosed && { autoClosed: result.autoClosed }
|
|
1181
1206
|
}));
|
|
1182
1207
|
}
|
|
1183
1208
|
} else {
|
|
@@ -1200,6 +1225,9 @@ Unblocked:`);
|
|
|
1200
1225
|
console.log(` \u2192 ${u.id} - ${u.title}`);
|
|
1201
1226
|
}
|
|
1202
1227
|
}
|
|
1228
|
+
if (result.autoClosed) {
|
|
1229
|
+
console.log(` \u2713 ${result.autoClosed.id} auto-closed (all verifications complete)`);
|
|
1230
|
+
}
|
|
1203
1231
|
}
|
|
1204
1232
|
} else {
|
|
1205
1233
|
console.log(`\u2717 ${result.id}: ${result.error}`);
|
|
@@ -1213,7 +1241,8 @@ Unblocked:`);
|
|
|
1213
1241
|
...r.error && { error: r.error },
|
|
1214
1242
|
...r.pendingVerifications && { pendingVerifications: r.pendingVerifications },
|
|
1215
1243
|
...r.pendingVerifications && { hint: `pb verifications ${r.id}` },
|
|
1216
|
-
...r.unblocked && { unblocked: r.unblocked }
|
|
1244
|
+
...r.unblocked && { unblocked: r.unblocked },
|
|
1245
|
+
...r.autoClosed && { autoClosed: r.autoClosed }
|
|
1217
1246
|
}))));
|
|
1218
1247
|
}
|
|
1219
1248
|
}
|
|
@@ -2651,11 +2680,49 @@ data: ${message}
|
|
|
2651
2680
|
data: { reason }
|
|
2652
2681
|
};
|
|
2653
2682
|
appendEventToFile(event, targetFile);
|
|
2683
|
+
let autoClosed;
|
|
2684
|
+
if (issue.verifies) {
|
|
2685
|
+
let targetIssue;
|
|
2686
|
+
let targetVerifications = [];
|
|
2687
|
+
if (isMultiWorktree()) {
|
|
2688
|
+
const found = findIssueInSources(issue.verifies, issueFiles);
|
|
2689
|
+
if (found) {
|
|
2690
|
+
targetIssue = found.issue;
|
|
2691
|
+
const allIssues = mergeIssuesFromFiles(issueFiles);
|
|
2692
|
+
targetVerifications = allIssues.filter(
|
|
2693
|
+
(i) => i.verifies === issue.verifies && i.status !== "closed"
|
|
2694
|
+
);
|
|
2695
|
+
}
|
|
2696
|
+
} else {
|
|
2697
|
+
targetIssue = getIssue(issue.verifies);
|
|
2698
|
+
targetVerifications = getVerifications(issue.verifies).filter((v) => v.status !== "closed");
|
|
2699
|
+
}
|
|
2700
|
+
if (targetIssue && targetIssue.status === "pending_verification" && targetVerifications.length === 0) {
|
|
2701
|
+
const autoCloseEvent = {
|
|
2702
|
+
type: "close",
|
|
2703
|
+
issueId: issue.verifies,
|
|
2704
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2705
|
+
data: { reason: "All verifications completed" }
|
|
2706
|
+
};
|
|
2707
|
+
if (isMultiWorktree()) {
|
|
2708
|
+
const targetFound = findIssueInSources(issue.verifies, issueFiles);
|
|
2709
|
+
if (targetFound) {
|
|
2710
|
+
appendEventToFile(autoCloseEvent, targetFound.targetFile);
|
|
2711
|
+
}
|
|
2712
|
+
} else {
|
|
2713
|
+
const pebbleDir = getOrCreatePebbleDir();
|
|
2714
|
+
appendEventToFile(autoCloseEvent, path2.join(pebbleDir, "issues.jsonl"));
|
|
2715
|
+
}
|
|
2716
|
+
autoClosed = { id: targetIssue.id, title: targetIssue.title };
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2654
2719
|
if (isMultiWorktree()) {
|
|
2655
2720
|
const updated = findIssueInSources(issueId, issueFiles);
|
|
2656
|
-
|
|
2721
|
+
const result = updated?.issue || { ...issue, status: "closed", updatedAt: timestamp };
|
|
2722
|
+
res.json(autoClosed ? { ...result, _autoClosed: autoClosed } : result);
|
|
2657
2723
|
} else {
|
|
2658
|
-
|
|
2724
|
+
const result = getIssue(issueId);
|
|
2725
|
+
res.json(autoClosed ? { ...result, _autoClosed: autoClosed } : result);
|
|
2659
2726
|
}
|
|
2660
2727
|
} catch (error) {
|
|
2661
2728
|
res.status(500).json({ error: error.message });
|
|
@@ -3245,7 +3312,7 @@ function formatSummaryPretty(summaries, sectionHeader) {
|
|
|
3245
3312
|
return lines.join("\n");
|
|
3246
3313
|
}
|
|
3247
3314
|
function summaryCommand(program2) {
|
|
3248
|
-
program2.command("summary").description("Show epic summary with child completion status").option("--status <status>", "Filter epics by status
|
|
3315
|
+
program2.command("summary").description("Show epic summary with child completion status").option("--status <status>", "Filter epics by specific status").option("--limit <n>", "Max epics to return per section", "10").action(async (options) => {
|
|
3249
3316
|
const pretty = program2.opts().pretty ?? false;
|
|
3250
3317
|
try {
|
|
3251
3318
|
getOrCreatePebbleDir();
|
|
@@ -3273,60 +3340,56 @@ function summaryCommand(program2) {
|
|
|
3273
3340
|
return summary;
|
|
3274
3341
|
};
|
|
3275
3342
|
const limit = parseInt(options.limit, 10);
|
|
3276
|
-
if (options.
|
|
3277
|
-
const
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
);
|
|
3282
|
-
|
|
3283
|
-
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
|
3284
|
-
);
|
|
3285
|
-
closedEpics.sort(
|
|
3343
|
+
if (options.status !== void 0) {
|
|
3344
|
+
const status = options.status;
|
|
3345
|
+
if (!STATUSES.includes(status)) {
|
|
3346
|
+
throw new Error(`Invalid status: ${status}. Must be one of: ${STATUSES.join(", ")}`);
|
|
3347
|
+
}
|
|
3348
|
+
let epics = allEpics.filter((e) => e.status === status);
|
|
3349
|
+
epics.sort(
|
|
3286
3350
|
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
|
3287
3351
|
);
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
const
|
|
3352
|
+
if (limit > 0) {
|
|
3353
|
+
epics = epics.slice(0, limit);
|
|
3354
|
+
}
|
|
3355
|
+
const summaries = epics.map(buildSummary);
|
|
3292
3356
|
if (pretty) {
|
|
3293
|
-
|
|
3294
|
-
if (openSummaries.length > 0) {
|
|
3295
|
-
output.push(formatSummaryPretty(openSummaries, "Open Epics"));
|
|
3296
|
-
}
|
|
3297
|
-
if (closedSummaries.length > 0) {
|
|
3298
|
-
if (output.length > 0) output.push("");
|
|
3299
|
-
output.push(formatSummaryPretty(closedSummaries, "Recently Closed Epics (last 72h)"));
|
|
3300
|
-
}
|
|
3301
|
-
console.log(output.join("\n"));
|
|
3357
|
+
console.log(formatSummaryPretty(summaries, `${STATUS_LABELS[status]} Epics`));
|
|
3302
3358
|
} else {
|
|
3303
|
-
console.log(formatJson(
|
|
3359
|
+
console.log(formatJson(summaries));
|
|
3304
3360
|
}
|
|
3305
3361
|
return;
|
|
3306
3362
|
}
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
}
|
|
3314
|
-
epics = epics.filter((e) => e.status === status);
|
|
3315
|
-
sectionHeader = `${STATUS_LABELS[status]} Epics`;
|
|
3316
|
-
} else {
|
|
3317
|
-
epics = epics.filter((e) => e.status !== "closed");
|
|
3318
|
-
}
|
|
3319
|
-
epics.sort(
|
|
3363
|
+
const openEpics = allEpics.filter((e) => e.status !== "closed");
|
|
3364
|
+
const seventyTwoHoursAgo = Date.now() - 72 * 60 * 60 * 1e3;
|
|
3365
|
+
const closedEpics = allEpics.filter(
|
|
3366
|
+
(e) => e.status === "closed" && new Date(e.updatedAt).getTime() > seventyTwoHoursAgo
|
|
3367
|
+
);
|
|
3368
|
+
openEpics.sort(
|
|
3320
3369
|
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
|
3321
3370
|
);
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
const
|
|
3371
|
+
closedEpics.sort(
|
|
3372
|
+
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
|
3373
|
+
);
|
|
3374
|
+
const limitedOpen = limit > 0 ? openEpics.slice(0, limit) : openEpics;
|
|
3375
|
+
const limitedClosed = limit > 0 ? closedEpics.slice(0, limit) : closedEpics;
|
|
3376
|
+
const openSummaries = limitedOpen.map(buildSummary);
|
|
3377
|
+
const closedSummaries = limitedClosed.map(buildSummary);
|
|
3326
3378
|
if (pretty) {
|
|
3327
|
-
|
|
3379
|
+
const output = [];
|
|
3380
|
+
if (openSummaries.length > 0) {
|
|
3381
|
+
output.push(formatSummaryPretty(openSummaries, "Open Epics"));
|
|
3382
|
+
}
|
|
3383
|
+
if (closedSummaries.length > 0) {
|
|
3384
|
+
if (output.length > 0) output.push("");
|
|
3385
|
+
output.push(formatSummaryPretty(closedSummaries, "Recently Closed Epics (last 72h)"));
|
|
3386
|
+
}
|
|
3387
|
+
if (output.length === 0) {
|
|
3388
|
+
output.push("No epics found.");
|
|
3389
|
+
}
|
|
3390
|
+
console.log(output.join("\n"));
|
|
3328
3391
|
} else {
|
|
3329
|
-
console.log(formatJson(
|
|
3392
|
+
console.log(formatJson({ open: openSummaries, closed: closedSummaries }));
|
|
3330
3393
|
}
|
|
3331
3394
|
} catch (error) {
|
|
3332
3395
|
outputError(error, pretty);
|