@yemi33/minions 0.1.152 → 0.1.154

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/dashboard.html CHANGED
@@ -178,8 +178,6 @@
178
178
  .prd-items-list { display: flex; flex-direction: column; gap: 3px; max-height: 400px; overflow-y: auto; padding: 0 8px; }
179
179
  .prd-item-row { display: flex; align-items: center; gap: 8px; padding: 4px 8px; border-radius: var(--radius-sm); font-size: var(--text-base); background: var(--surface2); border: 1px solid var(--border); border-left: 3px solid var(--border); }
180
180
  .prd-item-row.st-done { border-left-color: var(--green); }
181
- .prd-item-row.st-implemented { border-left-color: var(--green); } /* legacy alias */
182
- .prd-item-row.st-in-pr { border-left-color: var(--green); } /* backward compat: treated as done */
183
181
  .prd-item-row.st-in-progress { border-left-color: var(--yellow); animation: prdWipPulse 2s infinite; }
184
182
  @keyframes prdWipPulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(210,153,34,0); } 50% { box-shadow: 0 0 0 4px rgba(210,153,34,0.2); } }
185
183
  .prd-item-row.st-failed { border-left-color: var(--red); }
@@ -1171,7 +1169,7 @@ function renderPrdProgress(prog) {
1171
1169
  // Compute progress from active (non-archived) items only
1172
1170
  const activeItems = (prog.items || []).filter(i => !i._archived);
1173
1171
  if (activeItems.length > 0) {
1174
- const activeDone = activeItems.filter(i => i.status === 'done' || i.status === 'implemented' || i.status === 'in-pr').length; // in-pr counted as done for backward compat
1172
+ const activeDone = activeItems.filter(i => i.status === 'done').length;
1175
1173
  countEl.textContent = Math.round((activeDone / activeItems.length) * 100) + '%';
1176
1174
  } else {
1177
1175
  countEl.textContent = '—';
@@ -1180,7 +1178,7 @@ function renderPrdProgress(prog) {
1180
1178
  function renderGroupStats(items) {
1181
1179
  const total = items.length;
1182
1180
  if (total === 0) return '';
1183
- const done = items.filter(i => i.status === 'done' || i.status === 'implemented' || i.status === 'in-pr').length; // in-pr counted as done for backward compat
1181
+ const done = items.filter(i => i.status === 'done').length;
1184
1182
  const inProgress = items.filter(i => i.status === 'in-progress').length;
1185
1183
  const failed = items.filter(i => i.status === 'failed').length;
1186
1184
  const paused = items.filter(i => i.status === 'paused').length;
@@ -1210,13 +1208,11 @@ function renderPrdProgress(prog) {
1210
1208
  const statusBadge = (s) => {
1211
1209
  const styles = {
1212
1210
  'done': 'background:rgba(63,185,80,0.15);color:var(--green)',
1213
- 'implemented': 'background:rgba(63,185,80,0.15);color:var(--green)', /* legacy alias */
1214
- 'in-pr': 'background:rgba(63,185,80,0.15);color:var(--green)', /* backward compat: displayed as done */
1215
1211
  'in-progress': 'background:rgba(210,153,34,0.15);color:var(--yellow);animation:wipPulse 1.5s infinite',
1216
1212
  'failed': 'background:rgba(248,81,73,0.15);color:var(--red)',
1217
1213
  'paused': 'background:rgba(139,148,158,0.15);color:var(--muted)',
1218
1214
  };
1219
- const labels = { 'done': 'DONE', 'implemented': 'DONE', 'in-pr': 'DONE', 'in-progress': 'WIP', 'failed': 'FAIL', 'paused': 'PAUSED', 'missing': '—' };
1215
+ const labels = { 'done': 'DONE', 'in-progress': 'WIP', 'failed': 'FAIL', 'paused': 'PAUSED', 'missing': '—' };
1220
1216
  const style = styles[s] || 'background:var(--surface);color:var(--muted)';
1221
1217
  const label = labels[s] || '—';
1222
1218
  return '<span style="font-size:9px;font-weight:700;padding:2px 6px;border-radius:3px;letter-spacing:0.5px;white-space:nowrap;' + style + '">' + label + '</span>';
@@ -1295,7 +1291,7 @@ function renderPrdProgress(prog) {
1295
1291
  const timings = prog.planTimings || {};
1296
1292
 
1297
1293
  const renderGroupHeader = (g) => {
1298
- const done = g.items.filter(i => i.status === 'done' || i.status === 'complete' || i.status === 'implemented').length;
1294
+ const done = g.items.filter(i => i.status === 'done').length;
1299
1295
  const wip = g.items.filter(i => i.status === 'in-progress' || i.status === 'dispatched').length;
1300
1296
  const summary = (g.summary || '').replace(/^Convert plan to PRD:\s*/i, '').slice(0, 80);
1301
1297
  const isAwaitingApproval = g.planStatus === 'awaiting-approval';
@@ -1394,7 +1390,7 @@ function renderPrdProgress(prog) {
1394
1390
  });
1395
1391
 
1396
1392
  const statusColor = (s) => {
1397
- if (s === 'done' || s === 'implemented' || s === 'in-pr') return 'var(--green)'; // in-pr treated as done
1393
+ if (s === 'done') return 'var(--green)';
1398
1394
  if (s === 'in-progress') return 'var(--yellow)';
1399
1395
  if (s === 'failed') return 'var(--red)';
1400
1396
  if (s === 'paused') return 'var(--muted)';
@@ -1565,7 +1561,7 @@ function openArchivedPrdModal() {
1565
1561
  // Picker: list archived plans, click to expand
1566
1562
  html = '<div style="margin-bottom:12px;font-size:12px;color:var(--muted)">Select an archived PRD to view:</div>';
1567
1563
  html += groups.map((g, i) => {
1568
- const done = g.items.filter(it => it.status === 'done' || it.status === 'implemented' || it.status === 'complete').length;
1564
+ const done = g.items.filter(it => it.status === 'done').length;
1569
1565
  const failed = g.items.filter(it => it.status === 'failed').length;
1570
1566
  return '<div class="plan-card" style="cursor:pointer;margin-bottom:8px" onclick="showArchivedPrdDetail(' + i + ')">' +
1571
1567
  '<div class="plan-card-title" style="font-size:13px">' + escHtml(g.summary || g.file) + '</div>' +
@@ -1661,7 +1657,7 @@ async function prdItemEdit(source, itemId) {
1661
1657
 
1662
1658
  // Build completion summary section
1663
1659
  let completionHtml = '';
1664
- const isDone = item.status === 'done' || item.status === 'implemented' || item.status === 'complete' || item.status === 'in-pr'; // in-pr treated as done for backward compat
1660
+ const isDone = item.status === 'done';
1665
1661
  const isFailed = item.status === 'failed';
1666
1662
  const isActive = item.status === 'in-progress' || item.status === 'dispatched';
1667
1663
 
@@ -1931,7 +1927,6 @@ function openNotesModal() {
1931
1927
  _modalEditable = 'notes.md';
1932
1928
  _modalFilePath = 'notes.md'; showModalQa();
1933
1929
  document.getElementById('modal-edit-btn').style.display = '';
1934
- // steer btn removed — unified send
1935
1930
  document.getElementById('modal').classList.add('open');
1936
1931
  }
1937
1932
 
@@ -2130,8 +2125,6 @@ function closeModal() {
2130
2125
  // Clear edit/steer state
2131
2126
  _modalEditable = null;
2132
2127
  _modalFilePath = null;
2133
- _modalOriginalPlan = null;
2134
- // steer btn removed — unified send
2135
2128
  const body = document.getElementById('modal-body');
2136
2129
  body.contentEditable = 'false';
2137
2130
  body.style.border = '';
@@ -2194,7 +2187,7 @@ function openArchive(i) {
2194
2187
  html += '<div class="archive-feature">' +
2195
2188
  '<span class="feat-id">' + escHtml(f.id) + '</span> ' +
2196
2189
  '<span class="prd-item-priority ' + pClass + '">' + escHtml(f.priority || '') + '</span>' +
2197
- (f.status ? ' <span class="pr-badge ' + (f.status === 'complete' || f.status === 'done' || f.status === 'in-pr' ? 'approved' : 'draft') + '" style="font-size:9px">' + escHtml(f.status === 'in-pr' ? 'done' : f.status) + '</span>' : '') +
2190
+ (f.status ? ' <span class="pr-badge ' + (f.status === 'done' ? 'approved' : 'draft') + '" style="font-size:9px">' + escHtml(f.status) + '</span>' : '') +
2198
2191
  '<div class="feat-name">' + escHtml(f.name) + '</div>' +
2199
2192
  '<div class="feat-desc">' + escHtml(f.description || '') + '</div>' +
2200
2193
  (f.rationale ? '<div class="feat-desc" style="margin-top:4px;color:var(--yellow)">Rationale: ' + escHtml(f.rationale) + '</div>' : '') +
@@ -3539,7 +3532,6 @@ async function cmdSubmit() {
3539
3532
 
3540
3533
  let _modalDocContext = { title: '', content: '', selection: '' };
3541
3534
  let _modalFilePath = null; // file path for steering (null = read-only Q&A only)
3542
- let _modalOriginalPlan = null; // tracks original plan file when editing a forked version
3543
3535
 
3544
3536
  // ─── Notification Badges ──────────────────────────────────────────────────────
3545
3537
  // Show a red dot on a card/button when a background response arrives
@@ -4131,91 +4123,6 @@ async function planApprove(file) {
4131
4123
  } catch (e) { showToast('cmd-toast', 'Error: ' + e.message, false); }
4132
4124
  }
4133
4125
 
4134
- // Disable all PRD action buttons to prevent double-clicks
4135
- function qaDisablePrdButtons() {
4136
- const container = document.getElementById('qa-generate-prd-btn');
4137
- if (container) container.querySelectorAll('button').forEach(b => { b.disabled = true; b.style.opacity = '0.5'; });
4138
- }
4139
-
4140
- // Show plan version action buttons (Run alongside / Replace / Just save)
4141
- function showPlanVersionActions(thread, newFile, originalFile) {
4142
- const esc = newFile.replace(/'/g, "\\'");
4143
- // Look up existing PRD for the original plan's project
4144
- const allPlans = window._lastStatus?.plans || [];
4145
- const origPlan = allPlans.find(p => p.file === originalFile);
4146
- const project = origPlan?.project || '';
4147
- const existingPrd = allPlans.find(p => p.file.endsWith('.json') && p.project === project && p.status !== 'completed');
4148
-
4149
- const btn = document.createElement('div');
4150
- btn.id = 'qa-generate-prd-btn';
4151
- btn.style.cssText = 'margin:8px 0;padding:8px 12px;background:rgba(63,185,80,0.1);border:1px solid rgba(63,185,80,0.3);border-radius:6px;display:flex;flex-wrap:wrap;align-items:center;gap:8px';
4152
-
4153
- if (existingPrd) {
4154
- btn.innerHTML = '<span style="color:var(--green);font-weight:600;font-size:12px;width:100%">New plan version created — existing PRD running</span>' +
4155
- '<button onclick="qaNewPrd(\'' + esc + '\')" style="background:var(--green);color:#fff;border:none;border-radius:4px;padding:4px 12px;font-size:11px;font-weight:600;cursor:pointer" title="Execute this plan as a separate PRD alongside the current one">Run alongside</button>' +
4156
- '<button onclick="qaReplacePrd(\'' + esc + '\')" style="background:var(--orange);color:#fff;border:none;border-radius:4px;padding:4px 12px;font-size:11px;font-weight:600;cursor:pointer" title="Pause existing PRD, clean pending items, execute this plan instead">Replace old PRD</button>' +
4157
- '<button onclick="qaJustSave(this)" style="background:var(--surface2);color:var(--text);border:1px solid var(--border);border-radius:4px;padding:4px 12px;font-size:11px;cursor:pointer" title="Keep the new version saved without dispatching any work">Just save</button>' +
4158
- '<span style="color:var(--muted);font-size:10px;width:100%">Run alongside keeps current work going. Replace pauses it and starts fresh.</span>';
4159
- } else {
4160
- btn.innerHTML = '<span style="color:var(--green);font-weight:600;font-size:12px;width:100%">New plan version created</span>' +
4161
- '<button onclick="qaNewPrd(\'' + esc + '\')" style="background:var(--green);color:#fff;border:none;border-radius:4px;padding:4px 12px;font-size:11px;font-weight:600;cursor:pointer">Execute plan</button>' +
4162
- '<button onclick="qaJustSave(this)" style="background:var(--surface2);color:var(--text);border:1px solid var(--border);border-radius:4px;padding:4px 12px;font-size:11px;cursor:pointer">Just save</button>' +
4163
- '<span style="color:var(--muted);font-size:10px">Execute dispatches an agent to create PRD items from this plan</span>';
4164
- }
4165
- // Remove any previous action buttons
4166
- const old = thread.querySelector('#qa-generate-prd-btn');
4167
- if (old) old.remove();
4168
- thread.appendChild(btn);
4169
- }
4170
-
4171
- function qaJustSave(el) {
4172
- const container = el.closest('#qa-generate-prd-btn');
4173
- if (container) container.innerHTML = '<span style="color:var(--muted);font-size:11px">Saved. No work dispatched.</span>';
4174
- }
4175
-
4176
- // Replace existing PRD: pause old, clean pending items, regenerate from revised plan
4177
- async function qaReplacePrd(planFile) {
4178
- qaDisablePrdButtons();
4179
- const allPlans = window._lastStatus?.plans || [];
4180
- const mdPlan = allPlans.find(p => p.file === planFile);
4181
- const project = mdPlan?.project || '';
4182
- const existingPrd = allPlans.find(p => p.file.endsWith('.json') && p.project === project);
4183
-
4184
- if (existingPrd) {
4185
- // Pause first to stop materialization, then clean pending items
4186
- try {
4187
- await fetch('/api/plans/pause', {
4188
- method: 'POST', headers: { 'Content-Type': 'application/json' },
4189
- body: JSON.stringify({ file: existingPrd.file })
4190
- });
4191
- } catch {}
4192
- try {
4193
- await fetch('/api/plans/regenerate', {
4194
- method: 'POST', headers: { 'Content-Type': 'application/json' },
4195
- body: JSON.stringify({ source: existingPrd.file })
4196
- });
4197
- } catch {}
4198
- }
4199
-
4200
- planExecute(planFile, project, null);
4201
-
4202
- const btn = document.getElementById('qa-generate-prd-btn');
4203
- if (btn) btn.innerHTML = '<span style="color:var(--orange);font-size:12px">Replacing PRD — old items paused, agent regenerating from revised plan.</span>';
4204
- }
4205
-
4206
- // New PRD: keep existing PRD running, create fresh PRD from revised plan
4207
- async function qaNewPrd(planFile) {
4208
- qaDisablePrdButtons();
4209
- const allPlans = window._lastStatus?.plans || [];
4210
- const mdPlan = allPlans.find(p => p.file === planFile);
4211
- const project = mdPlan?.project || '';
4212
-
4213
- planExecute(planFile, project, null);
4214
-
4215
- const btn = document.getElementById('qa-generate-prd-btn');
4216
- if (btn) btn.innerHTML = '<span style="color:var(--green);font-size:12px">New PRD dispatched — existing work continues, agent creating fresh PRD from revised plan.</span>';
4217
- }
4218
-
4219
4126
  async function planExecute(file, project, btn) {
4220
4127
  if (btn) { btn.textContent = 'Executing...'; btn.disabled = true; btn.style.color = 'var(--blue)'; }
4221
4128
  try {
@@ -4429,7 +4336,6 @@ async function planView(file) {
4429
4336
  // Clear notification badge when opening this document
4430
4337
  const card = findCardForFile(_modalFilePath);
4431
4338
  if (card) clearNotifBadge(card);
4432
- // steer btn removed — unified send
4433
4339
  document.getElementById('modal').classList.add('open');
4434
4340
  } catch (e) { console.error(e); }
4435
4341
  }
@@ -4568,7 +4474,6 @@ async function kbOpenItem(category, file) {
4568
4474
  // Clear notification badge when opening this document
4569
4475
  const card = findCardForFile(_modalFilePath);
4570
4476
  if (card) clearNotifBadge(card);
4571
- // steer btn removed — unified send
4572
4477
  document.getElementById('modal').classList.add('open');
4573
4478
  } catch (e) {
4574
4479
  console.error('Failed to load KB item:', e);
package/dashboard.js CHANGED
@@ -1857,7 +1857,7 @@ If nothing to do: { "duplicates": [], "reclassify": [], "remove": [] }`;
1857
1857
  for (const w of items) {
1858
1858
  if (w.sourcePlan !== body.file) continue;
1859
1859
  // Keep completed items as-is, reset everything else to pending.
1860
- if (w.status === 'done' || w.status === 'implemented' || w.status === 'complete' || w.status === 'in-pr') continue;
1860
+ if (w.status === 'done') continue;
1861
1861
 
1862
1862
  if (w.status === 'dispatched') {
1863
1863
  // Kill the agent working on this item, if any.
@@ -2259,148 +2259,6 @@ If nothing to do: { "duplicates": [], "reclassify": [], "remove": [] }`;
2259
2259
  } catch (e) { return jsonReply(res, 400, { error: e.message }); }
2260
2260
  }
2261
2261
 
2262
- // POST /api/plans/revise-and-regenerate — REMOVED: plan versioning now handled by /api/doc-chat
2263
- // The "Replace old PRD" flow uses qaReplacePrd (frontend) which calls /api/plans/pause + /api/plans/regenerate + planExecute
2264
- async function handlePlansReviseAndRegenerate(req, res) {
2265
- try {
2266
- const body = await readBody(req);
2267
- if (!body.source || !body.instruction) return jsonReply(res, 400, { error: 'source and instruction required' });
2268
-
2269
- // Find the source plan .md file for this PRD
2270
- // Convention: PRD JSON references plan via plan_summary containing the work item ID,
2271
- // or the .md file has a matching name prefix
2272
- const prdPath = path.join(PRD_DIR, body.source);
2273
- if (!fs.existsSync(prdPath)) return jsonReply(res, 404, { error: 'PRD file not found' });
2274
-
2275
- // Look for corresponding .md plan file
2276
- let sourcePlanFile = null;
2277
- const planFiles = safeReadDir(PLANS_DIR).filter(f => f.endsWith('.md'));
2278
- if (body.sourcePlan) {
2279
- // Explicit source plan provided
2280
- sourcePlanFile = body.sourcePlan;
2281
- } else {
2282
- // Heuristic: find .md plan by matching prefix or by reading PRD's generated_from field
2283
- const prd = JSON.parse(safeRead(prdPath) || '{}');
2284
- if (prd.source_plan) {
2285
- sourcePlanFile = prd.source_plan;
2286
- } else {
2287
- // Match by prefix: officeagent-2026-03-15.json → plan-*officeagent* or plan-w025*.md
2288
- const prdBase = body.source.replace('.json', '');
2289
- for (const f of planFiles) {
2290
- // Check if plan file mentions the same project or was created around same time
2291
- const content = safeRead(path.join(PLANS_DIR, f)) || '';
2292
- if (content.includes(prd.project || '___nomatch___') || content.includes(prd.plan_summary?.slice(0, 40) || '___nomatch___')) {
2293
- sourcePlanFile = f;
2294
- break;
2295
- }
2296
- }
2297
- // Last resort: most recent .md plan
2298
- if (!sourcePlanFile && planFiles.length > 0) {
2299
- sourcePlanFile = planFiles.sort((a, b) => {
2300
- try { return fs.statSync(path.join(PLANS_DIR, b)).mtimeMs - fs.statSync(path.join(PLANS_DIR, a)).mtimeMs; } catch { return 0; }
2301
- })[0];
2302
- }
2303
- }
2304
- }
2305
-
2306
- if (!sourcePlanFile) {
2307
- return jsonReply(res, 404, { error: 'No source plan (.md) found for this PRD. You can edit the PRD JSON directly using "Edit Plan".' });
2308
- }
2309
-
2310
- const sourcePlanPath = path.join(PLANS_DIR, sourcePlanFile);
2311
- const planContent = safeRead(sourcePlanPath);
2312
- if (!planContent) return jsonReply(res, 404, { error: 'Source plan file not readable: ' + sourcePlanFile });
2313
-
2314
- // Step 1: Steer the source plan with the user's instruction via CC
2315
- const result = await ccDocCall({
2316
- message: body.instruction,
2317
- document: planContent,
2318
- title: sourcePlanFile,
2319
- filePath: 'plans/' + sourcePlanFile,
2320
- selection: body.selection || '',
2321
- canEdit: true,
2322
- isJson: false,
2323
- });
2324
-
2325
- if (!result.content) {
2326
- return jsonReply(res, 200, { ok: true, answer: result.answer, updated: false });
2327
- }
2328
-
2329
- // Save the revised plan
2330
- safeWrite(sourcePlanPath, result.content);
2331
-
2332
- // Step 2: Pause the old PRD so it stops materializing items
2333
- const prd = JSON.parse(safeRead(prdPath) || '{}');
2334
- prd.status = 'revision-requested';
2335
- prd.revision_feedback = body.instruction;
2336
- prd.revisionRequestedAt = new Date().toISOString();
2337
- safeWrite(prdPath, prd);
2338
-
2339
- // Step 3: Clean up pending/failed work items from old PRD
2340
- let reset = 0, kept = 0;
2341
- const wiPaths = [{ path: path.join(MINIONS_DIR, 'work-items.json'), label: 'central' }];
2342
- for (const proj of PROJECTS) {
2343
- wiPaths.push({ path: shared.projectWorkItemsPath(proj), label: proj.name });
2344
- }
2345
- const deletedItemIds = [];
2346
- for (const wiInfo of wiPaths) {
2347
- try {
2348
- const items = safeJson(wiInfo.path);
2349
- const filtered = [];
2350
- for (const w of items) {
2351
- if (w.sourcePlan === body.source) {
2352
- if (w.status === 'pending' || w.status === 'failed') {
2353
- reset++;
2354
- deletedItemIds.push(w.id);
2355
- } else {
2356
- kept++;
2357
- filtered.push(w);
2358
- }
2359
- } else {
2360
- filtered.push(w);
2361
- }
2362
- }
2363
- if (filtered.length < items.length) safeWrite(wiInfo.path, filtered);
2364
- } catch (e) { console.error('work item deletion:', e.message); }
2365
- }
2366
- for (const itemId of deletedItemIds) {
2367
- cleanDispatchEntries(d =>
2368
- d.meta?.item?.sourcePlan === body.source && d.meta?.item?.id === itemId
2369
- );
2370
- }
2371
-
2372
- // Step 4: Dispatch plan-to-prd to regenerate PRD from revised plan
2373
- const centralWiPath = path.join(MINIONS_DIR, 'work-items.json');
2374
- let centralItems = [];
2375
- try { centralItems = JSON.parse(safeRead(centralWiPath) || '[]'); } catch {}
2376
- const wiId = 'W-' + shared.uid();
2377
- centralItems.push({
2378
- id: wiId,
2379
- title: 'Regenerate PRD from revised plan: ' + sourcePlanFile,
2380
- type: 'plan-to-prd',
2381
- priority: 'high',
2382
- description: `The source plan \`${sourcePlanFile}\` has been revised. Convert it into a fresh PRD JSON.\n\nRevision instruction: ${body.instruction}\n\nRead the revised plan, generate updated PRD items (missing_features), and write to \`prd/${body.source}\`. Set status to "approved". Include \`"source_plan": "${sourcePlanFile}"\` in the JSON root.\n\nPreserve items that are already done (status "implemented" or "complete"). Reset or replace items that were pending/failed.`,
2383
- status: 'pending',
2384
- created: new Date().toISOString(),
2385
- createdBy: 'dashboard:revise-and-regenerate',
2386
- project: prd.project || '',
2387
- planFile: sourcePlanFile,
2388
- });
2389
- safeWrite(centralWiPath, centralItems);
2390
-
2391
- return jsonReply(res, 200, {
2392
- ok: true,
2393
- answer: result.answer,
2394
- updated: true,
2395
- sourcePlan: sourcePlanFile,
2396
- prdPaused: true,
2397
- reset,
2398
- kept,
2399
- workItemId: wiId,
2400
- });
2401
- } catch (e) { return jsonReply(res, 500, { error: e.message }); }
2402
- }
2403
-
2404
2262
  async function handlePlansDiscuss(req, res) {
2405
2263
  try {
2406
2264
  const body = await readBody(req);
@@ -2570,7 +2428,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
2570
2428
  let changed = false;
2571
2429
  for (const w of items) {
2572
2430
  if (w.sourcePlan !== f) continue;
2573
- if (w.status === 'done' || w.status === 'implemented' || w.status === 'complete' || w.status === 'in-pr') continue;
2431
+ if (w.status === 'done') continue;
2574
2432
  if (w.status === 'dispatched') {
2575
2433
  const activeEntry = (dispatch.active || []).find(d => d.meta?.item?.id === w.id || d.meta?.dispatchKey?.includes(w.id));
2576
2434
  if (activeEntry) {
@@ -1,83 +1 @@
1
- [
2
- {
3
- "id": "status-in-pr",
4
- "summary": "in-pr status alias — backward compat shim for done",
5
- "deprecated": "2026-03-21",
6
- "reason": "Simplified status model: agents mark items done directly, no intermediate in-pr state",
7
- "locations": [
8
- "dashboard.html: CSS classes, progress bar, status labels, graph colors (~10 locations)",
9
- "dashboard.js:1525 completedStatuses set",
10
- "engine.js:1165 PRD_MET_STATUSES set",
11
- "engine.js:1180 dependency check",
12
- "engine.js:1974 completedStatuses set",
13
- "engine/lifecycle.js:54,61 plan completion gate",
14
- "engine/queries.js:466,580,597 status ordering and counting"
15
- ],
16
- "cleanup": "Remove in-pr from all status checks, CSS, and display logic. Only keep done."
17
- },
18
- {
19
- "id": "status-implemented",
20
- "summary": "implemented status alias — legacy alias for done",
21
- "deprecated": "2026-03-21",
22
- "reason": "Canonical status is done. implemented was the original name before standardization.",
23
- "locations": [
24
- "dashboard.html: CSS, progress filters, status labels (~8 locations)",
25
- "dashboard.js:1525 completedStatuses set",
26
- "engine.js:1165,1974 status sets",
27
- "engine/lifecycle.js:694 sets implemented on post-merge"
28
- ],
29
- "cleanup": "Replace all implemented references with done. Update lifecycle.js post-merge to set done."
30
- },
31
- {
32
- "id": "status-complete",
33
- "summary": "complete status alias — another legacy alias for done",
34
- "deprecated": "2026-03-21",
35
- "reason": "Canonical status is done. complete appeared in early PRD schemas.",
36
- "locations": [
37
- "dashboard.html: progress filters, completion checks (~4 locations)",
38
- "engine.js:1165 PRD_MET_STATUSES set"
39
- ],
40
- "cleanup": "Remove complete from all status checks. Only keep done."
41
- },
42
- {
43
- "id": "dead-plan-version-actions",
44
- "summary": "showPlanVersionActions, qaJustSave, qaReplacePrd, qaNewPrd, qaDisablePrdButtons — dead code",
45
- "deprecated": "2026-03-21",
46
- "reason": "Doc-chat fork logic removed. These functions are unreachable.",
47
- "locations": [
48
- "dashboard.html:3775-3860 five function definitions (~80 lines)"
49
- ],
50
- "cleanup": "Delete the five functions entirely."
51
- },
52
- {
53
- "id": "dead-modal-original-plan",
54
- "summary": "_modalOriginalPlan variable — dead code",
55
- "deprecated": "2026-03-21",
56
- "reason": "Tracked original plan for fork edits. Fork logic removed.",
57
- "locations": [
58
- "dashboard.html:3187 declaration",
59
- "dashboard.html:2018 reset in closeModal"
60
- ],
61
- "cleanup": "Delete the variable declaration and all references."
62
- },
63
- {
64
- "id": "dead-revise-and-regenerate",
65
- "summary": "/api/plans/revise-and-regenerate endpoint — disabled behind if(false)",
66
- "deprecated": "2026-03-21",
67
- "reason": "Plan versioning handled differently now. Endpoint was explicitly disabled.",
68
- "locations": [
69
- "dashboard.js:1782-1829 (~45 lines of dead code)"
70
- ],
71
- "cleanup": "Delete the entire if(false) block."
72
- },
73
- {
74
- "id": "dead-steer-btn-comments",
75
- "summary": "// steer btn removed — unified send comments",
76
- "deprecated": "2026-03-21",
77
- "reason": "Steer button was removed long ago. Comments are noise.",
78
- "locations": [
79
- "dashboard.html: 4 occurrences"
80
- ],
81
- "cleanup": "Delete the comments."
82
- }
83
- ]
1
+ []