@lamemind/loom-deck 0.71.0 → 0.71.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/actions.js +35 -2
- package/dist/deck-model.js +5 -0
- package/dist/doc-tree.js +9 -0
- package/dist/ui/doc-pane.js +9 -2
- package/package.json +1 -1
package/dist/actions.js
CHANGED
|
@@ -25,8 +25,8 @@ import { saveView, viewFilePath } from './view-store.js';
|
|
|
25
25
|
import { onInTabCommand, runLaunch, spawnClaudeEmpty, spawnBare, spawnDeck, spawnDeckFork, spawnDeckResume, spawnTerminal, DECK_RUN, } from './spawn.js';
|
|
26
26
|
import { resolveSpawnId } from './spawn-config.js';
|
|
27
27
|
import { useTaskOps } from './task-ops.js';
|
|
28
|
-
import { inboxWords } from './inbox.js';
|
|
29
|
-
import { docWords } from './doc-tree.js';
|
|
28
|
+
import { inboxPrompt, inboxWords } from './inbox.js';
|
|
29
|
+
import { docTargetKind, docWords } from './doc-tree.js';
|
|
30
30
|
import { wrapWords } from './wrap-scan.js';
|
|
31
31
|
export function useDeckActions({ cwd, tasksPath, tasksDir, columns, model, overrides, catalog, setNote, }) {
|
|
32
32
|
// La riga di stato di OGNI spawn di sessione Claude: il comando esatto, come
|
|
@@ -404,6 +404,23 @@ export function useDeckActions({ cwd, tasksPath, tasksDir, columns, model, overr
|
|
|
404
404
|
* un comando che non si è riusciti a comporre.
|
|
405
405
|
*/
|
|
406
406
|
function rebalanceSpawn(row) {
|
|
407
|
+
// La coda inbox PRIMA dei flag: un file inbox porta sempre il suo flag, e
|
|
408
|
+
// senza questo ramo cadrebbe nel ramo del rebalance con l'aria di essere un
|
|
409
|
+
// bersaglio legittimo. La skill è la stessa che offre il pane di destra —
|
|
410
|
+
// il prompt lo compone `inboxPrompt`, unico posto in cui vive la mappa
|
|
411
|
+
// natura → skill, esattamente come per il `⏎` del pane inbox.
|
|
412
|
+
const kind = docTargetKind(row, model.docsRoot);
|
|
413
|
+
if (kind !== 'doc') {
|
|
414
|
+
const f = kind === 'inbox-file' ? inboxFileAt(row.path) : null;
|
|
415
|
+
if (f)
|
|
416
|
+
return { prompt: inboxPrompt(f), hint: '' };
|
|
417
|
+
return {
|
|
418
|
+
prompt: '',
|
|
419
|
+
hint: kind === 'inbox-dir'
|
|
420
|
+
? `${row.path} è la coda inbox: si drena un file alla volta, non si riorganizza`
|
|
421
|
+
: `${row.path} è un file inbox: la sua natura non è ancora stata misurata, aprilo dal pane di destra`,
|
|
422
|
+
};
|
|
423
|
+
}
|
|
407
424
|
if (row.flags.length === 0) {
|
|
408
425
|
return {
|
|
409
426
|
prompt: '',
|
|
@@ -413,6 +430,13 @@ export function useDeckActions({ cwd, tasksPath, tasksDir, columns, model, overr
|
|
|
413
430
|
const d = spawnDefaults('rebalance', { target: row.path, words: docWords(row.path) });
|
|
414
431
|
return { prompt: d.prompt ?? '', hint: '' };
|
|
415
432
|
}
|
|
433
|
+
/** Il file della coda inbox che sta dietro una riga dell'albero doc. Le due
|
|
434
|
+
* misure sono due scan distinti dello stesso script: l'albero conosce il
|
|
435
|
+
* path, la natura la sa solo la coda, e il prompt di drain è una funzione
|
|
436
|
+
* della natura. */
|
|
437
|
+
function inboxFileAt(path) {
|
|
438
|
+
return model.inboxAll.find((f) => f.path === path) ?? null;
|
|
439
|
+
}
|
|
416
440
|
/**
|
|
417
441
|
* T160 — apre la sessione che RIORGANIZZA la topologia attorno a un bersaglio.
|
|
418
442
|
*
|
|
@@ -430,6 +454,15 @@ export function useDeckActions({ cwd, tasksPath, tasksDir, columns, model, overr
|
|
|
430
454
|
function rebalanceDoc(row, prompt) {
|
|
431
455
|
if (!prompt)
|
|
432
456
|
return;
|
|
457
|
+
// Il bersaglio inbox prende la terna della riga `drain`, non quella di
|
|
458
|
+
// `rebalance`: il prompt da solo non basterebbe — modello e titolo della tab
|
|
459
|
+
// verrebbero comunque dalla riga sbagliata, e la conversazione si
|
|
460
|
+
// chiamerebbe «rebalance» mentre esegue un drain.
|
|
461
|
+
const f = inboxFileAt(row.path);
|
|
462
|
+
if (f) {
|
|
463
|
+
drainInbox(f, prompt);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
433
466
|
const sid = randomUUID();
|
|
434
467
|
const d = spawnDefaults('rebalance', { target: row.path, words: docWords(row.path) });
|
|
435
468
|
const title = d.title ?? '';
|
package/dist/deck-model.js
CHANGED
|
@@ -587,12 +587,17 @@ export function useDeckModel({ cwd, tasksPath, tasksDir, bareModel: bareModelDef
|
|
|
587
587
|
// modo del deck
|
|
588
588
|
deckMode,
|
|
589
589
|
// derivazioni del pane inbox
|
|
590
|
+
docsRoot,
|
|
590
591
|
inboxScanned: inbox.scanned,
|
|
591
592
|
inboxOk: inbox.ok,
|
|
592
593
|
inboxViewId,
|
|
593
594
|
inboxCounts,
|
|
594
595
|
inboxStale,
|
|
595
596
|
inboxFiles,
|
|
597
|
+
// La coda INTERA, non filtrata dalla vista: il pane doc la interroga per
|
|
598
|
+
// path e la vista attiva del pane inbox non c'entra niente con quale file
|
|
599
|
+
// l'albero stia mostrando.
|
|
600
|
+
inboxAll: inbox.files,
|
|
596
601
|
selInboxPath,
|
|
597
602
|
selInbox,
|
|
598
603
|
// derivazioni del pane doc
|
package/dist/doc-tree.js
CHANGED
|
@@ -363,6 +363,15 @@ export function countFlagged(data, flags) {
|
|
|
363
363
|
const hit = (f) => f.some((x) => wanted.has(x));
|
|
364
364
|
return data.dirs.filter((d) => hit(d.flags)).length + data.files.filter((f) => hit(f.flags)).length;
|
|
365
365
|
}
|
|
366
|
+
export function inboxDirOf(docsRoot) {
|
|
367
|
+
return `${docsRoot}/inbox`;
|
|
368
|
+
}
|
|
369
|
+
export function docTargetKind(row, docsRoot) {
|
|
370
|
+
const dir = inboxDirOf(docsRoot);
|
|
371
|
+
if (row.kind === 'dir')
|
|
372
|
+
return row.path === dir ? 'inbox-dir' : 'doc';
|
|
373
|
+
return row.path.startsWith(`${dir}/`) || row.flags.includes('INBOX') ? 'inbox-file' : 'doc';
|
|
374
|
+
}
|
|
366
375
|
/**
|
|
367
376
|
* T160 — il buco `{words}` del titolo di una sessione di rebalance: il path reso
|
|
368
377
|
* a parole.
|
package/dist/ui/doc-pane.js
CHANGED
|
@@ -73,13 +73,20 @@ export function DocPane({ rows, counts, activeView, paneCount, selectedPath, foc
|
|
|
73
73
|
? 'misura della doc fallita: plugin assente o script in errore'
|
|
74
74
|
: docView(activeView).empty, width) })) : (rows.map((r) => {
|
|
75
75
|
const sel = r.path === selectedPath;
|
|
76
|
-
|
|
76
|
+
// Il rientro sta FUORI da `cut`, che normalizza il whitespace e taglia
|
|
77
|
+
// gli estremi (`\s+ → spazio`, poi `trim`): passarglielo insieme al
|
|
78
|
+
// nome lo faceva sparire, e l'albero usciva piatto pur avendo le
|
|
79
|
+
// profondità giuste. Il budget si divide qui — prima le colonne del
|
|
80
|
+
// rientro, il resto al nome — e il rientro si ferma una colonna prima
|
|
81
|
+
// della fine, o su un pane strettissimo mangerebbe il nome intero.
|
|
82
|
+
const indentW = Math.min(r.depth * INDENT_W, Math.max(0, nameW - 1));
|
|
83
|
+
const indent = ' '.repeat(indentW);
|
|
77
84
|
// La barra finale distingue una cartella da un file senza spendere una
|
|
78
85
|
// colonna di marcatore: è la convenzione di `ls -F`, e su una riga che
|
|
79
86
|
// porta già una colonna di flag un glifo in più sarebbe la terza cosa
|
|
80
87
|
// da leggere prima del nome.
|
|
81
88
|
const label = r.kind === 'dir' ? `${r.name}/` : r.name;
|
|
82
|
-
const text =
|
|
89
|
+
const text = indent + cut(label, nameW - indentW);
|
|
83
90
|
return (_jsxs(Text, { inverse: sel && focused, bold: sel && !focused, wrap: "truncate-end", children: [sel ? CARET : CARET_OFF, _jsx(Text, { color: flagColor(r), dimColor: r.flags.length === 0, children: flagCell(r.flags) }), ' ', _jsx(Text, { bold: r.kind === 'dir', dimColor: r.kind === 'file' && r.flags.length === 0, children: text })] }, r.path));
|
|
84
91
|
}))] }));
|
|
85
92
|
}
|
package/package.json
CHANGED