@grifhinz/logics-manager 2.3.3 → 2.5.0

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![CI](https://github.com/AlexAgo83/logics-manager/actions/workflows/ci.yml/badge.svg)](https://github.com/AlexAgo83/logics-manager/actions/workflows/ci.yml)
4
4
  [![License](https://img.shields.io/github/license/AlexAgo83/logics-manager)](LICENSE)
5
- ![Version](https://img.shields.io/badge/version-v2.3.3-4C8BF5)
5
+ ![Version](https://img.shields.io/badge/version-v2.5.0-4C8BF5)
6
6
  ![VS Code](https://img.shields.io/badge/VS%20Code-1.86.0-007ACC?logo=visualstudiocode&logoColor=white)
7
7
  ![TypeScript](https://img.shields.io/badge/TypeScript-5.3.3-3178C6?logo=typescript&logoColor=white)
8
8
  ![Vitest](https://img.shields.io/badge/Vitest-2.1.8-6E9F18?logo=vitest&logoColor=white)
@@ -379,6 +379,13 @@ Use these as quick starting points when you want the plugin or the shared Logics
379
379
  - If you think "the system should..." -> spec
380
380
  - If you think "let's do..." -> task
381
381
 
382
+ Companion doc statuses are intentionally separate from workflow statuses:
383
+ product briefs use `Draft`, `Proposed`, `Active`, `Accepted`, `Validated`, `Rejected`,
384
+ `Superseded`, `Settled`, or `Archived`; ADRs use `Draft`, `Proposed`,
385
+ `Accepted`, `Validated`, `Rejected`, `Superseded`, `Settled`, or `Archived`.
386
+ Use `Settled` when the subject is closed, consumed by delivery, and no longer
387
+ needs active attention without implying that the document has been archived.
388
+
382
389
  <table>
383
390
  <tr>
384
391
  <td align="center">
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.3
1
+ 2.5.0
@@ -456,9 +456,9 @@
456
456
  }
457
457
 
458
458
  .activity-panel__entry {
459
- display: flex;
460
- flex-direction: column;
461
- align-items: flex-start;
459
+ display: grid;
460
+ grid-template-columns: 24px minmax(0, 1fr);
461
+ align-items: start;
462
462
  gap: 4px;
463
463
  width: 100%;
464
464
  text-align: left;
@@ -472,6 +472,29 @@
472
472
  white-space: normal;
473
473
  }
474
474
 
475
+ .activity-panel__marker {
476
+ display: inline-flex;
477
+ align-items: center;
478
+ justify-content: center;
479
+ width: 20px;
480
+ height: 20px;
481
+ border: 1px solid var(--vscode-panel-border, #333333);
482
+ border-radius: 50%;
483
+ background: var(--vscode-badge-background, #4d4d4d);
484
+ color: var(--vscode-badge-foreground, #ffffff);
485
+ font-size: 10px;
486
+ font-weight: 700;
487
+ line-height: 1;
488
+ }
489
+
490
+ .activity-panel__body {
491
+ display: flex;
492
+ flex-direction: column;
493
+ align-items: flex-start;
494
+ gap: 4px;
495
+ min-width: 0;
496
+ }
497
+
475
498
  .activity-panel__entry:hover {
476
499
  background: var(--vscode-list-hoverBackground, #2a2d2e);
477
500
  }
@@ -510,6 +533,21 @@
510
533
  word-break: break-word;
511
534
  }
512
535
 
536
+ .activity-panel__reveal {
537
+ width: 100%;
538
+ border: 1px solid var(--vscode-panel-border, #333333);
539
+ border-radius: 6px;
540
+ background: var(--vscode-button-secondaryBackground, transparent);
541
+ color: var(--vscode-button-secondaryForeground, var(--vscode-foreground, #d4d4d4));
542
+ padding: 7px 8px;
543
+ cursor: pointer;
544
+ font-size: 12px;
545
+ }
546
+
547
+ .activity-panel__reveal:hover {
548
+ background: var(--vscode-list-hoverBackground, #2a2d2e);
549
+ }
550
+
513
551
  .help-banner {
514
552
  display: flex;
515
553
  align-items: flex-start;
@@ -337,7 +337,7 @@
337
337
  .preview__body a{color:#0369a1;}
338
338
  .markdown-preview__diagram svg{max-width:100%;height:auto;}
339
339
  .markdown-preview__mermaid-fallback{margin-top:10px;padding:10px 12px;border-radius:10px;color:#991b1b;background:#fee2e2;border:1px solid rgba(248,113,113,.35);}
340
- </style></head><body><div class="preview"><header class="preview__header"><h1 class="preview__title">${safeTitle}</h1><p class="preview__source">File: <code>${safeSourceLabel}</code></p></header><main class="preview__body">${renderedHtml}</main></div><script src="/node_modules/mermaid/dist/mermaid.min.js"></script><script>
340
+ </style></head><body><div class="preview"><header class="preview__header"><h1 class="preview__title">${safeTitle}</h1><p class="preview__source">File: <code>${safeSourceLabel}</code></p></header><main class="preview__body">${renderedHtml}</main></div><script src="/vendor/mermaid.min.js"></script><script>
341
341
  (() => {
342
342
  const fallbackNodes = Array.from(document.querySelectorAll(".markdown-preview__mermaid-fallback"));
343
343
  const showFallback = (message) => {
@@ -70,6 +70,7 @@
70
70
  getShouldRecommendCheckEnvironment
71
71
  })
72
72
  : null;
73
+ let visibleActivityLimit = 10;
73
74
 
74
75
  function setButtonIcon(button, svgMarkup) {
75
76
  if (!button) {
@@ -155,6 +156,7 @@
155
156
  }
156
157
 
157
158
  const entries = getActivityEntries();
159
+ const visibleEntries = entries.slice(0, visibleActivityLimit);
158
160
  activityPanel.innerHTML = "";
159
161
 
160
162
  const header = document.createElement("div");
@@ -171,29 +173,39 @@
171
173
  empty.textContent = "No recent activity is available yet.";
172
174
  list.appendChild(empty);
173
175
  } else {
174
- entries.forEach((entry) => {
176
+ visibleEntries.forEach((entry) => {
175
177
  const button = document.createElement("button");
176
178
  button.type = "button";
177
179
  button.className = "activity-panel__entry";
178
180
  button.dataset.id = entry.id;
179
181
 
180
- const title = document.createElement("div");
182
+ const marker = document.createElement("span");
183
+ marker.className = "activity-panel__marker";
184
+ marker.textContent = entry.marker || String(entry.stage || "?").slice(0, 1).toUpperCase() || "?";
185
+ marker.title = entry.label || "Updated";
186
+ button.appendChild(marker);
187
+
188
+ const body = document.createElement("span");
189
+ body.className = "activity-panel__body";
190
+
191
+ const title = document.createElement("span");
181
192
  title.className = "activity-panel__title";
182
193
  title.textContent = entry.title;
183
- button.appendChild(title);
194
+ body.appendChild(title);
184
195
 
185
- const meta = document.createElement("div");
196
+ const meta = document.createElement("span");
186
197
  meta.className = "activity-panel__meta";
187
- meta.textContent = `${entry.label} ${getStageLabel(entry.stage)} ${entry.id}`;
188
- button.appendChild(meta);
198
+ meta.textContent = `${entry.label} - ${getStageLabel(entry.stage)} - ${entry.id}`;
199
+ body.appendChild(meta);
189
200
 
190
- const updated = document.createElement("div");
201
+ const updated = document.createElement("span");
191
202
  updated.className = "activity-panel__updated";
192
203
  updated.textContent =
193
204
  toolsPanelLayout && typeof toolsPanelLayout.formatActivityUpdated === "function"
194
205
  ? toolsPanelLayout.formatActivityUpdated(entry.updatedAt)
195
206
  : "Updated: Unknown";
196
- button.appendChild(updated);
207
+ body.appendChild(updated);
208
+ button.appendChild(body);
197
209
 
198
210
  button.addEventListener("click", () => {
199
211
  selectItemAndRender(entry.id);
@@ -204,6 +216,17 @@
204
216
 
205
217
  list.appendChild(button);
206
218
  });
219
+ if (entries.length > visibleEntries.length) {
220
+ const reveal = document.createElement("button");
221
+ reveal.type = "button";
222
+ reveal.className = "activity-panel__reveal";
223
+ reveal.textContent = `Show next ${Math.min(10, entries.length - visibleEntries.length)}`;
224
+ reveal.addEventListener("click", () => {
225
+ visibleActivityLimit += 10;
226
+ renderActivityPanel();
227
+ });
228
+ list.appendChild(reveal);
229
+ }
207
230
  }
208
231
 
209
232
  activityPanel.appendChild(list);
@@ -223,25 +223,26 @@
223
223
  return [...getItems()]
224
224
  .filter((item) => !(getHideCompleted() && (isComplete(item) || isClosedWorkflowStatus(getStatusValue(item)))))
225
225
  .sort((left, right) => (Date.parse(right.updatedAt || "") || 0) - (Date.parse(left.updatedAt || "") || 0))
226
- .slice(0, 12)
227
226
  .map((item) => {
228
- const statusValue = getStatusValue(item);
229
227
  let label = "Updated";
230
- if (statusValue.includes("obsolete")) {
231
- label = "Marked obsolete";
232
- } else if (statusValue.includes("done") || statusValue.includes("complete")) {
233
- label = "Marked done";
228
+ let marker = String(item.stage || "?").slice(0, 1).toUpperCase() || "?";
229
+ if (item.activityType === "status-change") {
230
+ label = "Status changed";
231
+ marker = "S";
234
232
  } else if (item.isPromoted) {
235
233
  label = "Promoted";
234
+ marker = "P";
236
235
  } else if (isPrimaryFlowStage(item.stage) && (collectCompanionDocs(item).length > 0 || collectSpecs(item).length > 0)) {
237
236
  label = "Linked companion docs";
237
+ marker = "L";
238
238
  }
239
239
  return {
240
240
  id: item.id,
241
241
  title: item.title,
242
242
  stage: item.stage,
243
243
  updatedAt: item.updatedAt,
244
- label
244
+ label,
245
+ marker
245
246
  };
246
247
  });
247
248
  }