nightralph 0.0.32 → 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/meta.json CHANGED
@@ -142,7 +142,7 @@
142
142
  "format": "esm"
143
143
  },
144
144
  "src/orchestrator.ts": {
145
- "bytes": 60865,
145
+ "bytes": 65884,
146
146
  "imports": [
147
147
  {
148
148
  "path": "node:child_process",
@@ -305,7 +305,7 @@
305
305
  "imports": [],
306
306
  "exports": [],
307
307
  "inputs": {},
308
- "bytes": 169488
308
+ "bytes": 176450
309
309
  },
310
310
  "dist/index.js": {
311
311
  "imports": [
@@ -468,7 +468,7 @@
468
468
  "bytesInOutput": 4265
469
469
  },
470
470
  "src/orchestrator.ts": {
471
- "bytesInOutput": 42892
471
+ "bytesInOutput": 45245
472
472
  },
473
473
  "src/worktree.ts": {
474
474
  "bytesInOutput": 3788
@@ -489,7 +489,7 @@
489
489
  "bytesInOutput": 1937
490
490
  }
491
491
  },
492
- "bytes": 79435
492
+ "bytes": 81788
493
493
  }
494
494
  }
495
495
  }
@@ -111,30 +111,110 @@ function findReadyTickets(tickets) {
111
111
  });
112
112
  }
113
113
  __name(findReadyTickets, "findReadyTickets");
114
- const COMPLETED_RE = /^\[x\]\s+(.+)$/i;
114
+ const COMPLETED_RE = /^\s*[-*+]?\s*\[x\]\s+(.+)$/i;
115
115
  const TOOL_USE_RE = /^\[[\w.]+\]/;
116
+ const CHECKBOX_RE = /^(\s*[-*+] )\[( |x|X)\]( .*)$/;
117
+ const UNCHECKED_BOX_RE = /^(\s*[-*+] )\[( )\]/;
118
+ function normalizeItemText(s) {
119
+ return s.replace(/\s+/g, " ").trim().toLowerCase();
120
+ }
121
+ __name(normalizeItemText, "normalizeItemText");
122
+ function stripCheckboxPrefix(s) {
123
+ return s.replace(/^\s*[-*+]?\s*\[[ xX]\]\s+/, "");
124
+ }
125
+ __name(stripCheckboxPrefix, "stripCheckboxPrefix");
126
+ function parseChecklistItems(lines) {
127
+ const items = [];
128
+ let inFence = false;
129
+ let i = 0;
130
+ while (i < lines.length) {
131
+ if (/^\s*```/.test(lines[i])) {
132
+ inFence = !inFence;
133
+ i++;
134
+ continue;
135
+ }
136
+ if (inFence) {
137
+ i++;
138
+ continue;
139
+ }
140
+ const m = lines[i].match(CHECKBOX_RE);
141
+ if (!m) {
142
+ i++;
143
+ continue;
144
+ }
145
+ const start = i;
146
+ let text = m[3];
147
+ i++;
148
+ while (i < lines.length && /^\s+\S/.test(lines[i]) && !CHECKBOX_RE.test(lines[i])) {
149
+ text += " " + lines[i].trim();
150
+ i++;
151
+ }
152
+ items.push({
153
+ start,
154
+ text: normalizeItemText(text)
155
+ });
156
+ }
157
+ return items;
158
+ }
159
+ __name(parseChecklistItems, "parseChecklistItems");
116
160
  function checkItems(ticket, completedItems) {
117
161
  if (completedItems.length === 0) return;
118
- let body = ticket.body;
119
- for (const item of completedItems) {
120
- const escaped = item.replace(
121
- /[.*+?^${}()|[\]\\]/g,
122
- "\\$&"
123
- );
124
- body = body.replace(
125
- new RegExp(
126
- `- \\[ \\] ${escaped}`,
127
- "i"
128
- ),
129
- `- [x] ${item}`
162
+ let body;
163
+ try {
164
+ body = readFileSync(ticket.filepath, "utf8");
165
+ } catch {
166
+ body = ticket.body;
167
+ }
168
+ const wanted = new Set(
169
+ completedItems.map(
170
+ (item) => normalizeItemText(stripCheckboxPrefix(item))
171
+ )
172
+ );
173
+ const lines = body.split("\n");
174
+ let changed = false;
175
+ for (const item of parseChecklistItems(lines)) {
176
+ if (!wanted.has(item.text)) continue;
177
+ const flipped = lines[item.start].replace(
178
+ UNCHECKED_BOX_RE,
179
+ "$1[x]"
130
180
  );
181
+ if (flipped !== lines[item.start]) {
182
+ lines[item.start] = flipped;
183
+ changed = true;
184
+ }
131
185
  }
186
+ if (!changed) return;
187
+ body = lines.join("\n");
132
188
  writeFileSync(ticket.filepath, body);
133
189
  ticket.body = body;
134
190
  }
135
191
  __name(checkItems, "checkItems");
192
+ function checkAllItems(body) {
193
+ const lines = body.split("\n");
194
+ let inFence = false;
195
+ for (let i = 0; i < lines.length; i++) {
196
+ if (/^\s*```/.test(lines[i])) {
197
+ inFence = !inFence;
198
+ continue;
199
+ }
200
+ if (inFence) continue;
201
+ lines[i] = lines[i].replace(
202
+ UNCHECKED_BOX_RE,
203
+ "$1[x]"
204
+ );
205
+ }
206
+ return lines.join("\n");
207
+ }
208
+ __name(checkAllItems, "checkAllItems");
136
209
  function markDone(ticket) {
137
- const updated = ticket.body.replace(
210
+ let body;
211
+ try {
212
+ body = readFileSync(ticket.filepath, "utf8");
213
+ } catch {
214
+ body = ticket.body;
215
+ }
216
+ body = checkAllItems(body);
217
+ const updated = body.replace(
138
218
  /\*\*Status:\*\*\s*.+/i,
139
219
  "**Status:** done"
140
220
  );
@@ -472,14 +552,21 @@ function killProcessGroup(pid) {
472
552
  try {
473
553
  process.kill(-pid, "SIGKILL");
474
554
  } catch {
555
+ try {
556
+ process.kill(pid, "SIGKILL");
557
+ } catch {
558
+ }
475
559
  }
476
560
  }
477
561
  __name(killProcessGroup, "killProcessGroup");
478
562
  const runningAgents = /* @__PURE__ */ new Set();
479
563
  function killRunningAgents() {
564
+ let killed = 0;
480
565
  for (const pid of runningAgents) {
481
566
  killProcessGroup(pid);
567
+ killed++;
482
568
  }
569
+ return killed;
483
570
  }
484
571
  __name(killRunningAgents, "killRunningAgents");
485
572
  function spawnAgent(opts) {
@@ -542,9 +629,16 @@ function spawnAgent(opts) {
542
629
  proc.stdout.pipe(logStream);
543
630
  const piFormatter = isPi ? createPiStreamFormatter() : null;
544
631
  const completedItems = [];
632
+ const seenItems = /* @__PURE__ */ new Set();
545
633
  function collectCompleted(text) {
546
- const match = text.match(COMPLETED_RE);
547
- if (match) completedItems.push(match[1]);
634
+ for (const line of text.split("\n")) {
635
+ const match = line.match(COMPLETED_RE);
636
+ if (!match) continue;
637
+ const item = match[1].trim();
638
+ if (!item || seenItems.has(item)) continue;
639
+ seenItems.add(item);
640
+ completedItems.push(item);
641
+ }
548
642
  }
549
643
  __name(collectCompleted, "collectCompleted");
550
644
  const rl = createInterface({ input: proc.stdout });
@@ -1474,6 +1568,7 @@ async function runWavesIsolated(opts) {
1474
1568
  }
1475
1569
  }
1476
1570
  } else {
1571
+ failedNums.add(ticket.num);
1477
1572
  d.log(
1478
1573
  ` ${ticket.filename}: merge failed, staying ready-for-agent`
1479
1574
  );