nightralph 0.0.33 → 0.0.34

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/index.js CHANGED
@@ -1152,30 +1152,110 @@ function findReadyTickets(tickets) {
1152
1152
  });
1153
1153
  }
1154
1154
  __name(findReadyTickets, "findReadyTickets");
1155
- var COMPLETED_RE = /^\[x\]\s+(.+)$/i;
1155
+ var COMPLETED_RE = /^\s*[-*+]?\s*\[x\]\s+(.+)$/i;
1156
1156
  var TOOL_USE_RE = /^\[[\w.]+\]/;
1157
+ var CHECKBOX_RE = /^(\s*[-*+] )\[( |x|X)\]( .*)$/;
1158
+ var UNCHECKED_BOX_RE = /^(\s*[-*+] )\[( )\]/;
1159
+ function normalizeItemText(s) {
1160
+ return s.replace(/\s+/g, " ").trim().toLowerCase();
1161
+ }
1162
+ __name(normalizeItemText, "normalizeItemText");
1163
+ function stripCheckboxPrefix(s) {
1164
+ return s.replace(/^\s*[-*+]?\s*\[[ xX]\]\s+/, "");
1165
+ }
1166
+ __name(stripCheckboxPrefix, "stripCheckboxPrefix");
1167
+ function parseChecklistItems(lines) {
1168
+ const items = [];
1169
+ let inFence = false;
1170
+ let i = 0;
1171
+ while (i < lines.length) {
1172
+ if (/^\s*```/.test(lines[i])) {
1173
+ inFence = !inFence;
1174
+ i++;
1175
+ continue;
1176
+ }
1177
+ if (inFence) {
1178
+ i++;
1179
+ continue;
1180
+ }
1181
+ const m = lines[i].match(CHECKBOX_RE);
1182
+ if (!m) {
1183
+ i++;
1184
+ continue;
1185
+ }
1186
+ const start = i;
1187
+ let text = m[3];
1188
+ i++;
1189
+ while (i < lines.length && /^\s+\S/.test(lines[i]) && !CHECKBOX_RE.test(lines[i])) {
1190
+ text += " " + lines[i].trim();
1191
+ i++;
1192
+ }
1193
+ items.push({
1194
+ start,
1195
+ text: normalizeItemText(text)
1196
+ });
1197
+ }
1198
+ return items;
1199
+ }
1200
+ __name(parseChecklistItems, "parseChecklistItems");
1157
1201
  function checkItems(ticket, completedItems) {
1158
1202
  if (completedItems.length === 0) return;
1159
- let body = ticket.body;
1160
- for (const item of completedItems) {
1161
- const escaped = item.replace(
1162
- /[.*+?^${}()|[\]\\]/g,
1163
- "\\$&"
1164
- );
1165
- body = body.replace(
1166
- new RegExp(
1167
- `- \\[ \\] ${escaped}`,
1168
- "i"
1169
- ),
1170
- `- [x] ${item}`
1203
+ let body;
1204
+ try {
1205
+ body = readFileSync4(ticket.filepath, "utf8");
1206
+ } catch {
1207
+ body = ticket.body;
1208
+ }
1209
+ const wanted = new Set(
1210
+ completedItems.map(
1211
+ (item) => normalizeItemText(stripCheckboxPrefix(item))
1212
+ )
1213
+ );
1214
+ const lines = body.split("\n");
1215
+ let changed = false;
1216
+ for (const item of parseChecklistItems(lines)) {
1217
+ if (!wanted.has(item.text)) continue;
1218
+ const flipped = lines[item.start].replace(
1219
+ UNCHECKED_BOX_RE,
1220
+ "$1[x]"
1171
1221
  );
1222
+ if (flipped !== lines[item.start]) {
1223
+ lines[item.start] = flipped;
1224
+ changed = true;
1225
+ }
1172
1226
  }
1227
+ if (!changed) return;
1228
+ body = lines.join("\n");
1173
1229
  writeFileSync3(ticket.filepath, body);
1174
1230
  ticket.body = body;
1175
1231
  }
1176
1232
  __name(checkItems, "checkItems");
1233
+ function checkAllItems(body) {
1234
+ const lines = body.split("\n");
1235
+ let inFence = false;
1236
+ for (let i = 0; i < lines.length; i++) {
1237
+ if (/^\s*```/.test(lines[i])) {
1238
+ inFence = !inFence;
1239
+ continue;
1240
+ }
1241
+ if (inFence) continue;
1242
+ lines[i] = lines[i].replace(
1243
+ UNCHECKED_BOX_RE,
1244
+ "$1[x]"
1245
+ );
1246
+ }
1247
+ return lines.join("\n");
1248
+ }
1249
+ __name(checkAllItems, "checkAllItems");
1177
1250
  function markDone(ticket) {
1178
- const updated = ticket.body.replace(
1251
+ let body;
1252
+ try {
1253
+ body = readFileSync4(ticket.filepath, "utf8");
1254
+ } catch {
1255
+ body = ticket.body;
1256
+ }
1257
+ body = checkAllItems(body);
1258
+ const updated = body.replace(
1179
1259
  /\*\*Status:\*\*\s*.+/i,
1180
1260
  "**Status:** done"
1181
1261
  );
@@ -1590,9 +1670,16 @@ function spawnAgent(opts) {
1590
1670
  proc.stdout.pipe(logStream);
1591
1671
  const piFormatter = isPi ? createPiStreamFormatter() : null;
1592
1672
  const completedItems = [];
1673
+ const seenItems = /* @__PURE__ */ new Set();
1593
1674
  function collectCompleted(text) {
1594
- const match = text.match(COMPLETED_RE);
1595
- if (match) completedItems.push(match[1]);
1675
+ for (const line of text.split("\n")) {
1676
+ const match = line.match(COMPLETED_RE);
1677
+ if (!match) continue;
1678
+ const item = match[1].trim();
1679
+ if (!item || seenItems.has(item)) continue;
1680
+ seenItems.add(item);
1681
+ completedItems.push(item);
1682
+ }
1596
1683
  }
1597
1684
  __name(collectCompleted, "collectCompleted");
1598
1685
  const rl = createInterface({ input: proc.stdout });