@markmdev/pebble 0.1.20 → 0.1.21

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
@@ -566,10 +566,12 @@ function getBlocking(issueId) {
566
566
  (issue) => issue.blockedBy.includes(issueId)
567
567
  );
568
568
  }
569
- function getChildren(epicId) {
569
+ function getChildren(epicId, includeDeleted = false) {
570
570
  const events = readEvents();
571
571
  const state = computeState(events);
572
- return Array.from(state.values()).filter((issue) => issue.parent === epicId);
572
+ return Array.from(state.values()).filter(
573
+ (issue) => issue.parent === epicId && (includeDeleted || !issue.deleted)
574
+ );
573
575
  }
574
576
  function getVerifications(issueId) {
575
577
  const events = readEvents();
@@ -1148,6 +1150,15 @@ function createCommand(program2) {
1148
1150
  }
1149
1151
  };
1150
1152
  appendEvent(event, pebbleDir);
1153
+ if (parentId) {
1154
+ const parentUpdateEvent = {
1155
+ type: "update",
1156
+ issueId: parentId,
1157
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1158
+ data: {}
1159
+ };
1160
+ appendEvent(parentUpdateEvent, pebbleDir);
1161
+ }
1151
1162
  if (blockedByIds.length > 0) {
1152
1163
  const depEvent = {
1153
1164
  type: "update",
@@ -1322,8 +1333,8 @@ function closeCommand(program2) {
1322
1333
  results.push({ id: resolvedId, success: false, error: `Issue is already closed: ${resolvedId}` });
1323
1334
  continue;
1324
1335
  }
1325
- if (issue.type === "epic" && hasOpenChildren(resolvedId)) {
1326
- results.push({ id: resolvedId, success: false, error: `Cannot close epic with open children: ${resolvedId}` });
1336
+ if (hasOpenChildren(resolvedId)) {
1337
+ results.push({ id: resolvedId, success: false, error: `Cannot close issue with open children: ${resolvedId}` });
1327
1338
  continue;
1328
1339
  }
1329
1340
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
@@ -2805,6 +2816,15 @@ data: ${message}
2805
2816
  }
2806
2817
  };
2807
2818
  appendEvent(event, pebbleDir);
2819
+ if (parent) {
2820
+ const parentUpdateEvent = {
2821
+ type: "update",
2822
+ issueId: parent,
2823
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2824
+ data: {}
2825
+ };
2826
+ appendEvent(parentUpdateEvent, pebbleDir);
2827
+ }
2808
2828
  const issue = getIssue(issueId);
2809
2829
  const result = parentReopened ? { ...issue, _parentReopened: parentReopened } : issue;
2810
2830
  res.status(201).json(result);
@@ -2833,8 +2853,8 @@ data: ${message}
2833
2853
  results.push({ id: issueId, success: true });
2834
2854
  continue;
2835
2855
  }
2836
- if (issue.type === "epic" && hasOpenChildren(issueId)) {
2837
- results.push({ id: issueId, success: false, error: "Cannot close epic with open children" });
2856
+ if (hasOpenChildren(issueId)) {
2857
+ results.push({ id: issueId, success: false, error: "Cannot close issue with open children" });
2838
2858
  continue;
2839
2859
  }
2840
2860
  const pendingVerifications = getVerifications(issueId).filter((v) => v.status !== "closed");
@@ -3084,8 +3104,8 @@ data: ${message}
3084
3104
  res.status(400).json({ error: "Issue is already closed" });
3085
3105
  return;
3086
3106
  }
3087
- if (!isMultiWorktree() && issue.type === "epic" && hasOpenChildren(issueId)) {
3088
- res.status(400).json({ error: "Cannot close epic with open children" });
3107
+ if (!isMultiWorktree() && hasOpenChildren(issueId)) {
3108
+ res.status(400).json({ error: "Cannot close issue with open children" });
3089
3109
  return;
3090
3110
  }
3091
3111
  const { reason } = req.body;
@@ -3898,6 +3918,21 @@ function formatInProgressPretty(issues) {
3898
3918
  }
3899
3919
  return lines.join("\n");
3900
3920
  }
3921
+ function formatClosedIssuesPretty(issues) {
3922
+ if (issues.length === 0) return "";
3923
+ const lines = [];
3924
+ lines.push(`## Recently Closed (${issues.length})`);
3925
+ lines.push("");
3926
+ for (const issue of issues) {
3927
+ lines.push(`\u2713 ${issue.id}: ${issue.title} [${issue.type}]`);
3928
+ lines.push(` Closed: ${formatRelativeTime(issue.closedAt)}${issue.lastSource ? ` | Source: ${issue.lastSource}` : ""}`);
3929
+ if (issue.parent) {
3930
+ lines.push(` Parent: ${issue.parent.title}`);
3931
+ }
3932
+ lines.push("");
3933
+ }
3934
+ return lines.join("\n");
3935
+ }
3901
3936
  function formatSummaryPretty(summaries, sectionHeader) {
3902
3937
  if (summaries.length === 0) {
3903
3938
  return "No epics found.";
@@ -4012,6 +4047,27 @@ function summaryCommand(program2) {
4012
4047
  const limitedClosed = limit > 0 ? closedEpics.slice(0, limit) : closedEpics;
4013
4048
  const openSummaries = limitedOpen.map(buildSummary);
4014
4049
  const closedSummaries = limitedClosed.map(buildSummary);
4050
+ let closedIssues = getIssues({ status: "closed" });
4051
+ closedIssues.sort(
4052
+ (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
4053
+ );
4054
+ closedIssues = closedIssues.slice(0, 20);
4055
+ const recentlyClosedSummaries = closedIssues.map((issue) => {
4056
+ const summary = {
4057
+ id: issue.id,
4058
+ title: issue.title,
4059
+ type: issue.type,
4060
+ closedAt: issue.updatedAt,
4061
+ lastSource: issue.lastSource
4062
+ };
4063
+ if (issue.parent) {
4064
+ const parentIssue = getIssue(issue.parent, true);
4065
+ if (parentIssue) {
4066
+ summary.parent = { id: parentIssue.id, title: parentIssue.title };
4067
+ }
4068
+ }
4069
+ return summary;
4070
+ });
4015
4071
  if (pretty) {
4016
4072
  const output = [];
4017
4073
  const inProgressOutput = formatInProgressPretty(inProgressSummaries);
@@ -4026,12 +4082,16 @@ function summaryCommand(program2) {
4026
4082
  if (output.length > 0) output.push("");
4027
4083
  output.push(formatSummaryPretty(closedSummaries, "Recently Closed Epics (last 72h)"));
4028
4084
  }
4085
+ if (recentlyClosedSummaries.length > 0) {
4086
+ if (output.length > 0) output.push("");
4087
+ output.push(formatClosedIssuesPretty(recentlyClosedSummaries));
4088
+ }
4029
4089
  if (output.length === 0) {
4030
4090
  output.push("No issues in progress and no epics found.");
4031
4091
  }
4032
4092
  console.log(output.join("\n"));
4033
4093
  } else {
4034
- console.log(formatJson({ inProgress: inProgressSummaries, open: openSummaries, closed: closedSummaries }));
4094
+ console.log(formatJson({ inProgress: inProgressSummaries, open: openSummaries, closed: closedSummaries, recentlyClosed: recentlyClosedSummaries }));
4035
4095
  }
4036
4096
  } catch (error) {
4037
4097
  outputError(error, pretty);