@lamemind/loom-deck 0.72.2 → 0.73.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
@@ -405,8 +405,8 @@ Apre una tab Ptyxis nella window attiva con `LOOM_TASK=T18 claude 'recap stato t
405
405
 
406
406
  I testi del catalogo stanno in `scripts/prompt-catalog` (formato `kind<TAB>template`, `{TASK}` interpolato), non dentro lo script: li legge anche il deck, per mostrare nel detail il prompt prima dello spawn. `--prompt` passa invece un testo **letterale** ed è esclusivo con `--prompt-kind` — sono due modi di dire la stessa cosa, e accettarli insieme costringerebbe a stabilire quale vince. Il testo viene quotato per la shell in-tab, apici singoli compresi: è l'unico ingresso di testo libero in una riga che una shell parsa.
407
407
 
408
- La tab porta anche `PTYXIS_PROFILE` forzata al profilo bindato al progetto nel registry (`bindings/claude`), letto da dconf: è la chiave con cui loom-compass associa a un progetto lo stato annunciato dagli hook (running/ask/done). Una tab `ptyxis --tab` nuda erediterebbe il profilo di default, e l'annuncio finirebbe keyed su un UUID che nessun progetto dichiara — pallino fermo su idle, senza alcun errore visibile. Override o disattivazione via `LOOM_DECK_STATE_PROFILE`
409
- (settata a vuoto → nessun annuncio); progetto non registrato → nessun prefisso.
408
+ La tab porta anche `PTYXIS_PROFILE` forzata all'`id` del progetto, letto da `.claude/loom-works.json`: è la chiave con cui loom-compass associa a un progetto lo stato annunciato dagli hook (running/ask/done). Il nome della variabile è storico — non contiene l'UUID di un profilo Ptyxis. Una tab `ptyxis --tab` nuda porterebbe l'UUID del profilo di default, e l'annuncio finirebbe keyed su una chiave che nessun progetto dichiara — badge fermo, senza alcun errore visibile. Un `id` fuori da `^[A-Za-z0-9_-]+$` viene scartato con un avviso su stderr, perché il valore entra in una riga che una shell parsa. Override o disattivazione via `LOOM_DECK_STATE_PROFILE`
409
+ (settata a vuoto → nessun annuncio); progetto senza file config → nessun prefisso.
410
410
 
411
411
  ## Sviluppo (TUI Ink)
412
412
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lamemind/loom-deck",
3
- "version": "0.72.2",
3
+ "version": "0.73.0",
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": {
package/scripts/deck-run CHANGED
@@ -45,25 +45,19 @@
45
45
  # Serve a chi spawna deck-run e vuole mostrare l'invocazione vera senza
46
46
  # ricomporla per conto proprio; le diagnostiche restano tutte su stderr.
47
47
  #
48
- # Modalità spawn (LOOM_DECK_SPAWN_MODE):
49
- # inline → ptyxis --tab -- <cmd> (default) comando inline, LOOM_TASK diretta, zero dconf
50
- # profile → ptyxis --tab-with-profile=<UUID> riusa il profilo, riscrive il custom-command via dconf
51
- #
52
- # La scelta fra le due è la Decisione aperta §9 della proposta: la modalità
53
- # "inline" è il default perché non muta stato dconf condiviso. Vedi la nota
54
- # di decisione nella task folder di T18.
48
+ # Spawn: `ptyxis --tab -- bash -lc <cmd>`, comando inline sul profilo di default
49
+ # di Ptyxis — LOOM_TASK e chiave di stato viaggiano dentro il comando, nessuna
50
+ # scrittura dconf e nessun profilo dedicato.
55
51
  #
56
52
  # Env:
57
- # LOOM_DECK_SPAWN_MODE inline|profile (default: inline)
58
- # LOOM_DECK_PROFILE_UUID UUID profilo Ptyxis (default: cc-host)
59
53
  # LOOM_DECK_WORKDIR dir di lavoro della tab (default: $PWD)
60
54
  # LOOM_DECK_ENTER_PROMPT override del prompt iniziale, {TASK}=TaskID (vince sul kind, tranne `none`)
61
55
  # T161: inerte sugli spawn che arrivano dal deck TUI —
62
56
  # quelli passano SEMPRE `--prompt`, su cui non ha mai
63
57
  # vinto. Resta per le invocazioni a mano e per i test.
64
58
  # LOOM_DECK_INTAB_CMD override comando in-tab (default: la sessione CC; usato per i test)
65
- # LOOM_DECK_STATE_PROFILE PTYXIS_PROFILE annunciata a compass (default: bindings/claude
66
- # del progetto, letto da dconf; settata a vuoto = nessun annuncio)
59
+ # LOOM_DECK_STATE_PROFILE PTYXIS_PROFILE annunciata a compass (default: `id` del file
60
+ # config del progetto; settata a vuoto = nessun annuncio)
67
61
  # LOOM_DECK_PERMISSION_MODE override del permissionMode del file config (default: campo file, poi 'manual')
68
62
  # LOOM_DECK_MODEL modello quando --model non è passato (batte il catalogo, default: fable)
69
63
  #
@@ -89,7 +83,6 @@ FORK=0
89
83
  # la tab finisce nella finestra di un altro progetto, o in una a caso.
90
84
  #
91
85
  # Non è un quinto asse: non cambia cosa gira nella tab, solo dove la tab nasce.
92
- # Vale identico nei due rami di spawn (inline e profile).
93
86
  NEW_WINDOW=0
94
87
  TITLE_NOTE=""
95
88
  # Vuoto = flag non passato (≠ un default già risolto): serve a distinguere
@@ -272,8 +265,6 @@ if [[ $PROMPT_GIVEN -eq 1 && -n "$PROMPT_KIND" ]]; then
272
265
  exit 2
273
266
  fi
274
267
 
275
- MODE="${LOOM_DECK_SPAWN_MODE:-inline}"
276
- PROFILE_UUID="${LOOM_DECK_PROFILE_UUID:-5a36ae48df1c4d4882f43060e3e59656}"
277
268
  WORKDIR="${LOOM_DECK_WORKDIR:-$PWD}"
278
269
 
279
270
  # ── Titolo tab = label standard loom (matchabile da compass) ──────────────────
@@ -471,40 +462,34 @@ case "${MODEL:-}" in
471
462
  esac
472
463
  MODEL_FLAG="--model ${MODEL} "
473
464
 
474
- # ── Profilo di stato per compass ─────────────────────────────────────────────
465
+ # ── Chiave di stato per compass ──────────────────────────────────────────────
475
466
  # Lo stato di una sessione (running/ask/done) viaggia verso compass via D-Bus
476
467
  # keyed su $PTYXIS_PROFILE (hook Claude → `compass <stato>`), e compass lo mappa
477
- # a un progetto SOLO se quell'UUID compare in `bindings/<surface>/profile` del
478
- # registry. Ma nel modo `inline` la tab nasce da `ptyxis --tab` nudo, che eredita
479
- # il profilo DEFAULT di Ptyxis: l'annuncio arriva keyed su un UUID che nessun
480
- # progetto dichiara → stato scartato, pallino fermo su idle per sempre. Il match
481
- # della FINESTRA non se ne accorge (passa dal titolo, non dal profilo), quindi il
482
- # progetto risulta presente ma senza stato — un guasto che non si manifesta come
483
- # errore, solo come pallino che non cambia mai.
484
- # Rimedio: forzare in-tab la PTYXIS_PROFILE del binding claude del progetto, così
485
- # l'annuncio è keyed sull'UUID che compass cerca davvero. Il profilo bindato NON
486
- # è usabile come profilo vero della tab (`--tab-with-profile`): ha
487
- # use-custom-command=true, che fa scartare il comando inline — vedi il ramo
488
- # `profile` sotto, che per questo deve riscrivere dconf.
468
+ # a un progetto SOLO se quella chiave è l'`id` di un progetto del registry. La
469
+ # tab nasce da `ptyxis --tab` nudo, e Ptyxis esporta da sé PTYXIS_PROFILE col
470
+ # valore del profilo DEFAULT: senza un prefisso l'annuncio arriverebbe keyed su
471
+ # un UUID che nessun progetto dichiara → stato scartato, badge fermo per sempre.
472
+ # Il match della FINESTRA non se ne accorge (passa dal titolo, non dalla
473
+ # chiave), quindi il progetto risulta presente ma senza stato — un guasto che
474
+ # non si manifesta come errore, solo come badge che non cambia mai.
475
+ # Rimedio: forzare in-tab PTYXIS_PROFILE=<id del progetto>. Il nome della
476
+ # variabile è storico: non contiene l'UUID di un profilo Ptyxis, e nessuna
477
+ # chiamata a Ptyxis la usa. È la stessa chiave che mette il bottone 🤖 di compass.
489
478
  #
490
- # `${VAR+set}`, non `${VAR:-}`: env settata anche a VUOTO = "salta il lookup"
491
- # (deterministico per i test, che altrimenti leggerebbero il dconf della macchina
492
- # su cui gira la suite). Non settata = risolvi dal registry.
493
- # Assente/non risolvibile → nessun prefisso: si degrada al comportamento di prima
494
- # (stato orfano) invece di rompere lo spawn.
479
+ # `${VAR+set}`, non `${VAR:-}`: env settata anche a VUOTO = "nessun annuncio"
480
+ # (deterministico per i test). Non settata = `id` del file config del progetto.
481
+ # Assente/non risolvibile → nessun prefisso: si degrada a stato orfano invece di
482
+ # rompere lo spawn.
495
483
  if [[ -n "${LOOM_DECK_STATE_PROFILE+set}" ]]; then
496
484
  STATE_PROFILE="${LOOM_DECK_STATE_PROFILE}"
497
485
  else
498
486
  STATE_PROFILE=""
499
- if [[ -n "$_cfg" ]] && command -v dconf >/dev/null 2>&1; then
500
- _pid="$(jq -r '.id // empty' "$_cfg" 2>/dev/null || true)"
501
- if [[ -n "$_pid" ]]; then
502
- STATE_PROFILE="$(dconf read "/org/lamemind/loom/projects/${_pid}/bindings/claude/profile" 2>/dev/null | tr -d "'" || true)"
503
- fi
487
+ if [[ -n "$_cfg" ]]; then
488
+ STATE_PROFILE="$(jq -r '.id // empty' "$_cfg" 2>/dev/null || true)"
504
489
  fi
505
490
  fi
506
- # Whitelist come per la nota del titolo: il valore entra in `bash -lc "…"`, e un
507
- # registry è pur sempre un file editabile a mano. Un UUID Ptyxis è esadecimale;
491
+ # Whitelist come per la nota del titolo: il valore entra in `bash -lc "…"`, e il
492
+ # file config è editabile a mano. Lo schema non vincola la forma dell'`id`:
508
493
  # accetto l'alfabeto id-safe e scarto il resto invece di quotare.
509
494
  if [[ -n "$STATE_PROFILE" && ! "$STATE_PROFILE" =~ ^[A-Za-z0-9_-]+$ ]]; then
510
495
  echo "profilo di stato ignorato (caratteri non ammessi): '${STATE_PROFILE}'" >&2
@@ -688,33 +673,10 @@ IN_TAB_CMD="${LOOM_DECK_INTAB_CMD:-$_default_intab}"
688
673
  # vedono comunque quello che vedevano prima.
689
674
  printf 'LOOM_DECK_INTAB %s\n' "$IN_TAB_CMD"
690
675
 
691
- # Verbo di apertura (T162): tab nella finestra attiva, o finestra nuova. Una
692
- # variabile e non due rami duplicati per ogni modalità di spawn — `--new-window`
693
- # è l'unica differenza fra i due casi.
676
+ # Verbo di apertura (T162): tab nella finestra attiva, o finestra nuova —
677
+ # `--new-window` è l'unica differenza fra i due casi.
694
678
  if [[ $NEW_WINDOW -eq 1 ]]; then WIN_FLAG="--new-window"; else WIN_FLAG="--tab"; fi
695
679
 
696
- case "$MODE" in
697
- inline)
698
- # --tab: tab nella window attiva. -- <cmd>: comando inline nella tab.
699
- # LOOM_TASK viaggia dentro il comando → nessuna scrittura dconf.
700
- exec ptyxis "$WIN_FLAG" -d "$WORKDIR" -T "${TITLE}" -- bash -lc "$IN_TAB_CMD"
701
- ;;
702
- profile)
703
- # --tab-with-profile: riusa il profilo (custom-command FISSO) → per iniettare
704
- # LOOM_TASK+task va riscritto il custom-command al volo via dconf (stato condiviso).
705
- # Con --new-window i due flag convivono: la finestra nasce e il profilo
706
- # decide cosa gira nella sua prima tab.
707
- dpath="/org/gnome/Ptyxis/Profiles/${PROFILE_UUID}/"
708
- dconf write "${dpath}use-custom-command" true
709
- dconf write "${dpath}custom-command" "'bash -lc \"${IN_TAB_CMD//\"/\\\"}\"'"
710
- if [[ $NEW_WINDOW -eq 1 ]]; then
711
- exec ptyxis --new-window --tab-with-profile="$PROFILE_UUID" -d "$WORKDIR" -T "${TITLE}"
712
- else
713
- exec ptyxis --tab-with-profile="$PROFILE_UUID" -d "$WORKDIR" -T "${TITLE}"
714
- fi
715
- ;;
716
- *)
717
- echo "LOOM_DECK_SPAWN_MODE ignoto: '$MODE' (usa 'inline' o 'profile')" >&2
718
- exit 2
719
- ;;
720
- esac
680
+ # -- <cmd>: comando inline nella tab. LOOM_TASK e chiave di stato viaggiano
681
+ # dentro il comando → nessuna scrittura dconf, nessun profilo dedicato.
682
+ exec ptyxis "$WIN_FLAG" -d "$WORKDIR" -T "${TITLE}" -- bash -lc "$IN_TAB_CMD"