@lamemind/loom-deck 0.69.0 → 0.70.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/dist/hooks.js +10 -19
- package/dist/session-meta.js +45 -27
- package/package.json +1 -1
package/dist/hooks.js
CHANGED
|
@@ -8,8 +8,8 @@ import { statSync } from 'node:fs';
|
|
|
8
8
|
import { loadTasks, loadTaskDetail } from './tasks.js';
|
|
9
9
|
import { discoverProjectSessions } from './sessions.js';
|
|
10
10
|
import { discoverLiveSessions, liveSig } from './live-sessions.js';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { loadSessionIndex } from './task-index.js';
|
|
12
|
+
import { fillSidecarGaps } from './session-meta.js';
|
|
13
13
|
import { archivableIds, SCAN_INTERVAL_MS } from './archivable.js';
|
|
14
14
|
import { commitTimes } from './commit-times.js';
|
|
15
15
|
import { scanEpicHierarchy, EMPTY_EPIC_HIERARCHY } from './epic-hierarchy.js';
|
|
@@ -213,23 +213,14 @@ export function useSessions(projectRoot, core) {
|
|
|
213
213
|
// Gli append NON entrano nella signature e non producono un re-render: il
|
|
214
214
|
// deck il titolo lo ha dalla `Session`, che è la fonte. Questi campi
|
|
215
215
|
// esistono per un lettore che non può aprire un transcript, cioè compass.
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
})) {
|
|
225
|
-
appendSessionMeta(projectRoot, gap.sessionId, gap);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
catch {
|
|
229
|
-
// sidecar non scrivibile: il poll continua, il buco si riprova al giro
|
|
230
|
-
// dopo. Niente a schermo — è manutenzione di un campo di servizio, non
|
|
231
|
-
// un'azione che l'utente ha chiesto.
|
|
232
|
-
}
|
|
216
|
+
fillSidecarGaps(projectRoot, {
|
|
217
|
+
pinned,
|
|
218
|
+
sessions,
|
|
219
|
+
bindings,
|
|
220
|
+
titles: index.titles,
|
|
221
|
+
models: index.models,
|
|
222
|
+
core,
|
|
223
|
+
});
|
|
233
224
|
// La signature copre anche fork, pin, note e marca di priorità: un record
|
|
234
225
|
// di lineage, un toggle di pin, una nota appena scritta o un 🚨 acceso
|
|
235
226
|
// cambiano la lista renderizzata, quindi devono forzare il re-render come
|
package/dist/session-meta.js
CHANGED
|
@@ -8,14 +8,18 @@
|
|
|
8
8
|
// lì da chi ce l'ha in mano, cioè il deck, che a ogni tick materializza le
|
|
9
9
|
// `Session` complete di titolo e modello.
|
|
10
10
|
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
11
|
+
// Il giudizio è separato dalla scrittura: `sidecarGaps` decide e ritorna i
|
|
12
|
+
// record, `fillSidecarGaps` li scrive. La separazione è ciò che rende testabile
|
|
13
|
+
// la parte non ovvia — la convergenza: un derivato che non combacia mai col
|
|
14
|
+
// valore su disco produrrebbe un append a ogni tick del poll, per sempre, senza
|
|
15
|
+
// nessun errore a dirlo.
|
|
16
|
+
//
|
|
17
|
+
// Nessun import da ink/react: il chiamante è un hook, questo modulo no.
|
|
16
18
|
import { modelAlias } from './glyphs.js';
|
|
17
19
|
import { stripProjectCore, stripTaskId } from './session-list.js';
|
|
18
20
|
import { NO_TITLE } from './sessions.js';
|
|
21
|
+
import { NO_SPAWN } from './spawn.js';
|
|
22
|
+
import { appendSessionMeta } from './task-index.js';
|
|
19
23
|
/**
|
|
20
24
|
* Cap del titolo scritto nel sidecar, in CODE POINT.
|
|
21
25
|
*
|
|
@@ -62,28 +66,6 @@ export function sidecarTitle(s, core, taskId) {
|
|
|
62
66
|
return s.title === NO_TITLE ? '' : capTitle(s.title);
|
|
63
67
|
return capTitle(stripTaskId(stripProjectCore(s.title, core), taskId));
|
|
64
68
|
}
|
|
65
|
-
/**
|
|
66
|
-
* I buchi da riempire in questo giro: per ogni conversazione PINNATA, i campi
|
|
67
|
-
* derivati che nel sidecar mancano o non corrispondono più al valore corrente.
|
|
68
|
-
*
|
|
69
|
-
* Solo le pinnate, e non tutte le conversazioni del progetto, perché sono le
|
|
70
|
-
* sole che un lettore esterno mostra: il resto sarebbe churn su un file
|
|
71
|
-
* append-only, un record per conversazione per ogni deck che si apre.
|
|
72
|
-
*
|
|
73
|
-
* Tre cose che non producono un append, e nessuna delle tre è un errore:
|
|
74
|
-
* - una pinnata STALE (il transcript non c'è più) — nessuna `Session`, quindi
|
|
75
|
-
* nessun valore da cui derivare;
|
|
76
|
-
* - un titolo derivato VUOTO — è l'assenza di P1, e appenderlo scriverebbe la
|
|
77
|
-
* cancellazione di un campo che nessuno ha chiesto di cancellare;
|
|
78
|
-
* - un modello non riconducibile a un alias (`''` o fuori famiglia) — chi
|
|
79
|
-
* riprende cadrà sulla propria cascata, che è meglio di un alias inventato.
|
|
80
|
-
*
|
|
81
|
-
* La CONVERGENZA è l'invariante da tenere: il confronto avviene fra il valore
|
|
82
|
-
* derivato e il valore letto dal sidecar senza riscritture in mezzo (nessuna
|
|
83
|
-
* sanificazione in lettura, cap applicato da questo lato una volta sola),
|
|
84
|
-
* quindi un buco riempito resta riempito e il giro successivo non trova niente
|
|
85
|
-
* da fare.
|
|
86
|
-
*/
|
|
87
69
|
export function sidecarGaps(input) {
|
|
88
70
|
const { pinned, sessions, bindings, titles, models, core } = input;
|
|
89
71
|
if (pinned.size === 0)
|
|
@@ -106,3 +88,39 @@ export function sidecarGaps(input) {
|
|
|
106
88
|
}
|
|
107
89
|
return out;
|
|
108
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Scrive i buchi di questo giro. Ritorna quanti record ha appeso — zero è
|
|
93
|
+
* l'esito normale a regime, non un fallimento.
|
|
94
|
+
*
|
|
95
|
+
* `NO_SPAWN` frena anche questa scrittura, ed è lo stesso freno delle tab
|
|
96
|
+
* Ptyxis per la stessa ragione: il gate su pseudo-terminale avvia il DECK VERO
|
|
97
|
+
* con cwd la project root del cappello, quindi senza freno ogni run della suite
|
|
98
|
+
* appende record nel sidecar reale di chi la lancia. Il valore scritto sarebbe
|
|
99
|
+
* pure corretto — è quello che il deck scriverebbe comunque — ma è una
|
|
100
|
+
* scrittura fuori dalla sandbox del test, che è precisamente ciò che il freno
|
|
101
|
+
* esiste per impedire.
|
|
102
|
+
*
|
|
103
|
+
* Il freno sta QUI e non nel chiamante perché questa è l'unica sede della
|
|
104
|
+
* scrittura: nel chiamante sarebbe una guardia che il prossimo scrittore non
|
|
105
|
+
* vede.
|
|
106
|
+
*
|
|
107
|
+
* Un sidecar non scrivibile non è un errore da mostrare: il giro dopo riprova,
|
|
108
|
+
* e nel frattempo il deck funziona identico — questi campi li legge un altro
|
|
109
|
+
* processo, non lui.
|
|
110
|
+
*/
|
|
111
|
+
export function fillSidecarGaps(projectRoot, input) {
|
|
112
|
+
if (NO_SPAWN)
|
|
113
|
+
return 0;
|
|
114
|
+
let scritti = 0;
|
|
115
|
+
try {
|
|
116
|
+
for (const gap of sidecarGaps(input)) {
|
|
117
|
+
appendSessionMeta(projectRoot, gap.sessionId, gap);
|
|
118
|
+
scritti++;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// sidecar non scrivibile: si riprova al giro dopo, niente a schermo — è
|
|
123
|
+
// manutenzione di un campo di servizio, non un'azione che l'utente ha chiesto.
|
|
124
|
+
}
|
|
125
|
+
return scritti;
|
|
126
|
+
}
|
package/package.json
CHANGED