@lamemind/loom-deck 0.30.0 → 0.30.1

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.js CHANGED
@@ -13,7 +13,7 @@ import { discoverProjectSessions } from './sessions.js';
13
13
  import { discoverLiveSessions, liveSig } from './live-sessions.js';
14
14
  import { buildRows, firstRowKey, moveRowSelection, rowIndexOfKey, searchSessions, selectedRow, DEFAULT_OPTIONS, MIN_QUERY, } from './search.js';
15
15
  import { appendNote, appendPin, appendSessionRecord, appendTaskBinding, loadSessionIndex, } from './task-index.js';
16
- import { assembleSessionList, firstSelectableId, moveSelection, neighborId, rowIndexOf, rowLabel, selectedSession, sessionTitle, stripProjectCore, } from './session-list.js';
16
+ import { assembleSessionList, firstSelectableId, moveSelection, neighborId, rowIndexOf, rowLabel, selectedSession, sessionTitle, stripProjectCore, unpinLandingId, } from './session-list.js';
17
17
  import { cellWidth, launchLegend, loadArchivableDays, loadIdentity, loadLaunch, } from './config.js';
18
18
  import { countArchivable, SCAN_INTERVAL_MS } from './archivable.js';
19
19
  import { assignListCapacity, detailCapacity, isCompact, layoutBudget, readerCapacity, searchListCapacity, searchPreviewCapacity, windowRange, } from './viewport.js';
@@ -1824,8 +1824,16 @@ function Deck({ cwd, tasksPath, tasksDir }) {
1824
1824
  }
1825
1825
  else {
1826
1826
  const isPinned = pinned.has(selSessionId);
1827
+ // Dove atterra la selezione: sul pin resta sulla sessione (sale in cima
1828
+ // con lei, il caret la segue perché è l'oggetto dell'azione); sull'unpin
1829
+ // resta IN PLACE nel gruppo pinnate — successiva, precedente, o prima
1830
+ // contestuale se il gruppo si svuota. Calcolato PRIMA della riscrittura
1831
+ // del sidecar, quando la riga pinnata esiste ancora.
1832
+ const landing = isPinned ? unpinLandingId(sessionRows, selSessionId) : null;
1827
1833
  appendPin(cwd, selSessionId, !isPinned);
1828
1834
  reloadSessions();
1835
+ if (landing)
1836
+ setSelSessionId(landing);
1829
1837
  setNote(`${isPinned ? 'unpin' : '📌 pin'} ${selSessionId.slice(0, 8)}`);
1830
1838
  }
1831
1839
  }
@@ -197,6 +197,34 @@ export function neighborId(rows, sessionId) {
197
197
  return null;
198
198
  return selectable[at + 1]?.sessionId ?? selectable[at - 1]?.sessionId ?? null;
199
199
  }
200
+ /**
201
+ * Id su cui atterrare quando la riga pinnata `sessionId` viene SPINNATA: la
202
+ * pinnata successiva, la precedente se era l'ultima, la prima contestuale se il
203
+ * gruppo pinnate si svuota. `null` se `sessionId` non è pinnata o non resta
204
+ * nessuna riga.
205
+ *
206
+ * Non è `neighborId` ristretto al gruppo: quello attraversa il separatore,
207
+ * quindi sull'ULTIMA pinnata atterrerebbe sulla prima contestuale — il caret
208
+ * scavalcherebbe l'intero gruppo invece di risalire di una riga. Qui il confine
209
+ * fra i due gruppi è la regola, non un ostacolo.
210
+ *
211
+ * L'id va calcolato PRIMA di riscrivere il sidecar: dopo, la riga pinnata non
212
+ * c'è più e il vicino nel gruppo non è calcolabile. Serve perché una spinnata
213
+ * non sparisce necessariamente dalla lista — se appartiene al parent
214
+ * selezionato ricompare fra le contestuali, e la selezione keyed sull'id la
215
+ * seguirebbe fin laggiù, trascinando il caret.
216
+ */
217
+ export function unpinLandingId(rows, sessionId) {
218
+ const pinnedRows = rows.filter((r) => r.kind === 'pinned');
219
+ const at = pinnedRows.findIndex((r) => r.sessionId === sessionId);
220
+ if (at < 0)
221
+ return null;
222
+ const inGroup = pinnedRows[at + 1]?.sessionId ?? pinnedRows[at - 1]?.sessionId;
223
+ if (inGroup)
224
+ return inGroup;
225
+ const firstContext = rows.find((r) => r.kind === 'context');
226
+ return firstContext && isSelectable(firstContext) ? firstContext.sessionId : null;
227
+ }
200
228
  /** Session della riga selezionata; null se stale o nessuna selezione. */
201
229
  export function selectedSession(rows, sessionId) {
202
230
  const r = rows.find((row) => isSelectable(row) && row.sessionId === sessionId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lamemind/loom-deck",
3
- "version": "0.30.0",
3
+ "version": "0.30.1",
4
4
  "description": "Deck TUI Ink per-progetto della famiglia loom: legge tasks.md e spawna sessioni Claude Code bound via LOOM_TASK",
5
5
  "type": "module",
6
6
  "bin": {