@mmmbuto/nexuscrew 0.9.16 → 0.9.18

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.
Files changed (68) hide show
  1. package/CHANGELOG.md +157 -3
  2. package/docs/ALIBABA_TOKEN_PLAN.md +70 -0
  3. package/docs/AUDIO_SHARE.md +119 -0
  4. package/docs/CELL_PANEL.md +156 -0
  5. package/docs/CONFIGURATION.md +122 -0
  6. package/docs/FLEET.md +222 -0
  7. package/docs/INSTALLATION.md +128 -0
  8. package/docs/LIVE_PROMPT.md +110 -0
  9. package/docs/MCP.md +151 -0
  10. package/docs/NODES.md +214 -0
  11. package/docs/NOTIFICATIONS.md +101 -0
  12. package/docs/OPERATIONS.md +114 -0
  13. package/docs/README.md +55 -0
  14. package/docs/SECURITY.md +185 -0
  15. package/docs/VL_MICRO_NODES.md +107 -0
  16. package/docs/img/fleet-deck-desktop.png +0 -0
  17. package/docs/img/session-mobile.png +0 -0
  18. package/docs/live-prompt-templates/LIVE_PROMPT.en.md +67 -0
  19. package/docs/live-prompt-templates/LIVE_PROMPT.es.md +70 -0
  20. package/docs/live-prompt-templates/LIVE_PROMPT.it.md +67 -0
  21. package/frontend/dist/assets/{index-CwsGpQwK.js → index-DmpQoCsc.js} +1 -1
  22. package/frontend/dist/index.html +1 -1
  23. package/frontend/dist/version.json +1 -1
  24. package/lib/auth/middleware.js +1 -1
  25. package/lib/cells/scope-guard.js +2 -2
  26. package/lib/cli/commands.js +7 -7
  27. package/lib/cli/fleet-service.js +2 -2
  28. package/lib/cli/pidfile.js +15 -15
  29. package/lib/cli/service.js +2 -2
  30. package/lib/cli/stable-alias.js +1 -1
  31. package/lib/files/routes.js +2 -2
  32. package/lib/fleet/builtin.js +6 -6
  33. package/lib/fleet/catalogs/zai-responses.json +82 -0
  34. package/lib/fleet/cell-exec.js +4 -4
  35. package/lib/fleet/cell-lease-server.js +17 -17
  36. package/lib/fleet/definitions.js +28 -17
  37. package/lib/fleet/launch-broker.js +3 -3
  38. package/lib/fleet/lease-client.js +1 -1
  39. package/lib/fleet/managed.js +86 -26
  40. package/lib/fleet/prompt-delivery.js +1 -1
  41. package/lib/fleet/runtime.js +3 -3
  42. package/lib/live-host/bridge.js +3 -3
  43. package/lib/live-host/routes.js +1 -1
  44. package/lib/mcp/server.js +7 -8
  45. package/lib/mcp/tools.js +1 -1
  46. package/lib/nodes/commands.js +2 -2
  47. package/lib/nodes/health.js +1 -1
  48. package/lib/nodes/identity.js +10 -13
  49. package/lib/nodes/store.js +2 -2
  50. package/lib/nodes/tunnel-supervisor.js +7 -7
  51. package/lib/nodes/tunnel.js +10 -11
  52. package/lib/notify/asks.js +4 -4
  53. package/lib/notify/persist.js +1 -1
  54. package/lib/notify/push.js +4 -4
  55. package/lib/notify/routes.js +12 -12
  56. package/lib/proxy/node-proxy.js +4 -4
  57. package/lib/proxy/panel-proxy.js +2 -2
  58. package/lib/pty/attach.js +1 -1
  59. package/lib/server.js +3 -3
  60. package/lib/settings/pairing-coordinator.js +1 -1
  61. package/lib/settings/routes.js +4 -4
  62. package/lib/tmux/lifecycle.js +4 -4
  63. package/lib/tmux/preview.js +1 -1
  64. package/lib/update/runner.js +9 -9
  65. package/lib/vl-nodes/broker.js +1 -1
  66. package/lib/ws/bridge.js +1 -1
  67. package/package.json +20 -2
  68. package/frontend/index.html +0 -20
@@ -560,7 +560,7 @@ async function probeNexusCrew(port, token, opts = {}) {
560
560
  // dice che il servizio E' IN PIEDI e che il token locale non vale — e chi deve
561
561
  // spiegare un riavvio ha bisogno di distinguerle, altrimenti dichiara fallito
562
562
  // un riavvio riuscito e manda a cercare un processo morto che e' vivo.
563
- // Rilievo dell'audit: il caso token-assente era gia' coperto, questo no.
563
+ // Rilievo della revisione: il caso token-assente era gia' coperto, questo no.
564
564
  async function probeNexusCrewStatus(port, token, opts = {}) {
565
565
  const fetchImpl = opts.fetchImpl || globalThis.fetch;
566
566
  if (typeof fetchImpl !== 'function') return null;
@@ -932,7 +932,7 @@ function autoUpdateCommand(args, opts = {}) {
932
932
  // stesso file: tmp nella stessa directory, 0600, rename. Un `writeFileSync`
933
933
  // diretto puo' lasciare un config.json troncato se il processo muore a
934
934
  // meta' — e un config.json illeggibile e' un nodo che non riparte, cioe'
935
- // proprio il guasto che questo comando serve a evitare. Rilievo dell'audit.
935
+ // proprio il guasto che questo comando serve a evitare. Rilievo della revisione.
936
936
  try {
937
937
  if (fs.lstatSync(configPath).isSymbolicLink()) {
938
938
  log('autoupdate: config.json e\' un symlink, non lo scrivo');
@@ -975,7 +975,7 @@ function autoUpdateCommand(args, opts = {}) {
975
975
 
976
976
  // update: npm i -g @latest + sanazione definizioni di boot + restart se attivo.
977
977
  // Fallimento npm -> messaggio chiaro, code 1.
978
- // R28-rimedio, difetto 1 (audit): la via manuale attraversa la STESSA
978
+ // rimedio da revisione, difetto 1: la via manuale attraversa la STESSA
979
979
  // sanazione del runner (healBootDefinitions: rigenera le definizioni sul
980
980
  // node vivo e APPLICA l'attivazione differita). Prima update() reinstallava
981
981
  // e riavviava soltanto: chi aggiornava a mano con un node appena cambiato
@@ -1177,7 +1177,7 @@ async function dispatchNodes(rest, flags, opts = {}) {
1177
1177
  if (!cells.length) { log('nodes cells: elenco vuoto — usa `none` se intendi nessuna cella'); return { code: 1 }; }
1178
1178
  return { code: nodesCmds.nodesEdit({ ...opts, log, ref, patch: { cellVisibility: 'selected', cells } }).code };
1179
1179
  }
1180
- // Accesso ai pannelli (D8): dietro un pannello c'e' un browser con sessioni
1180
+ // Accesso ai pannelli (da revisione): dietro un pannello c'e' un browser con sessioni
1181
1181
  // gia' autenticate, e quell'accesso non si revoca cambiando una chiave. Il
1182
1182
  // resto del modello tratta un peer pairato come l'operatore stesso; qui no:
1183
1183
  // default negato, si concede un nodo per volta.
@@ -1407,7 +1407,7 @@ function dispatch(argv, opts = {}) {
1407
1407
  // SENZA TOKEN NON SI PUO' DIRE NIENTE SULLA SALUTE, e soprattutto non si
1408
1408
  // deve dire qualcosa di sbagliato: la sonda fallirebbe per autenticazione e
1409
1409
  // il messaggio incolperebbe la porta o il processo, mandando a cercare dove
1410
- // il problema non e'. Rilievo dell'audit. Il riavvio e' comunque partito,
1410
+ // il problema non e'. Rilievo della revisione. Il riavvio e' comunque partito,
1411
1411
  // quindi non e' un fallimento: e' una verifica che non si e' potuta fare, e
1412
1412
  // si dice cosi'.
1413
1413
  if (!token) {
@@ -1460,8 +1460,8 @@ function dispatch(argv, opts = {}) {
1460
1460
  // processi sulla stessa porta, e il nostro sopravvivrebbe allo stop del
1461
1461
  // servizio. Li' si riferisce e basta.
1462
1462
  //
1463
- // Difetto mio, trovato rileggendo prima dell'audit: la prima stesura
1464
- // chiamava `startPortable` in ogni caso.
1463
+ // Invariante: il ramo managed non chiama `startPortable`; un fallback
1464
+ // locale creerebbe un secondo processo fuori dal controllo del gestore.
1465
1465
  if (result.runtimeOwner === 'managed') {
1466
1466
  log(`restart: il servizio NON risponde su 127.0.0.1:${port} dopo il riavvio.`);
1467
1467
  log(' Il runtime e\' gestito dal servizio di sistema: non avvio un processo accanto.');
@@ -238,7 +238,7 @@ function fleetInstallCommands(platform, target, ctx) {
238
238
  // Install no-symlink + atomic rename (come service.js). execImpl iniettabile per test;
239
239
  // default execFileSync (argv diretto, MAI shell string). Su activation fallita il file
240
240
  // e' PRESERVATO e le failure raccolte per diagnosi (M1: non si ingoia, non si rollback).
241
- // R28: `activate: false` (speculare a installService) scrive la definizione SENZA
241
+ // da revisione: `activate: false` (speculare a installService) scrive la definizione SENZA
242
242
  // toccare il service manager — per chi rigenera a meta' aggiornamento: il companion
243
243
  // e' RunAtLoad/oneshot, un bootstrap adesso eseguirebbe le celle boot:true mentre
244
244
  // il servizio principale sta per essere riavviato. I comandi saltati sono dichiarati
@@ -313,7 +313,7 @@ function installFleetService(platform, content, ctx, {
313
313
 
314
314
  // Gemello di isOurService (service.js): stessa ragione, stessa disciplina —
315
315
  // l'ancora vive accanto al template della companion.
316
- // Stessa disciplina di service.js (R28, terzo giro): la riga identificativa e'
316
+ // Stessa disciplina di service.js (da revisione): la riga identificativa e'
317
317
  // definita una volta e usata SIA dal template SIA dall'ancora, e l'ancora e' la
318
318
  // riga ESATTA — un prefisso lascia passare il servizio di terzi che comincia la
319
319
  // propria Description col nostro nome.
@@ -72,7 +72,7 @@ function readProcessStart(pid) {
72
72
  }
73
73
 
74
74
  // Campi che SOLO writePidfile puo' scrivere: mai dal chiamante via `extra`.
75
- // Misurato (2026-08-17): con lo spread di extra per ultimo,
75
+ // Misurato in revisione: con lo spread di extra per ultimo,
76
76
  // writePidfile(f, pid, cmd, {processStart:'FINTO', attestation:'unsupported'})
77
77
  // vinceva sul valore vero calcolato da probeProcessStart — un chiamante
78
78
  // poteva scrivere un'attestazione INVENTATA. safeExtra la filtra qui, e i
@@ -105,7 +105,7 @@ const RESERVED_META_FIELDS = new Set(['pid', 'cmd', 'startTs', 'uid', 'processSt
105
105
  // controlla quella variabile d'ambiente controlla anche la finestra — non
106
106
  // un confine di sicurezza reale (chi setta l'ambiente del processo ha gia'
107
107
  // vinto), ma va detto: il marker non e' una garanzia piu' forte di questa.
108
- // 3. R-pidfile-5: claimSchemaMarker (sotto) crea il marker al KILL, non solo
108
+ // 3. da revisione: claimSchemaMarker (sotto) crea il marker al KILL, non solo
109
109
  // al write — quindi un pidfile che sta per essere RIMOSSO puo' lasciare
110
110
  // dietro un marker in una directory che magari non ospitera' mai piu' un
111
111
  // runtime. E' INNOCUO: il marker non ha altro effetto che rendere PIU'
@@ -119,7 +119,7 @@ function schemaMarkerPath(pidfilePath) {
119
119
  return path.join(path.dirname(pidfilePath), '.pidfile-schema-v2');
120
120
  }
121
121
 
122
- // R-pidfile-4 (2026-08-17, audit su develop@437d29f): misurato dall'auditor
122
+ // da revisione interna: misurato in revisione
123
123
  // sul frozen — se .pidfile-schema-v2 esiste come DIRECTORY (o symlink, o
124
124
  // qualunque cosa non sia un file regolare), il vecchio hasSchemaMarker
125
125
  // tornava `false` per costruzione (isFile() falso), e ensureSchemaMarker
@@ -192,7 +192,7 @@ function hasSchemaMarker(pidfilePath) {
192
192
  // pidfile e' gia' stato scritto quando arriviamo qui, ed e' lui
193
193
  // l'informazione che conta.
194
194
  //
195
- // R-pidfile-5 (2026-08-17, audit su develop@fa8bd90): questa funzione NON
195
+ // da revisione interna: questa funzione NON
196
196
  // garantisce piu' nulla sul futuro — prima il commento qui diceva "il
197
197
  // prossimo killPidfile lo scoprira' da solo", ed era FALSO: se questa
198
198
  // scrittura fallisce con ENOSPC/EROFS/quota/permesso transitorio, non resta
@@ -215,7 +215,7 @@ function ensureSchemaMarker(pidfilePath) {
215
215
  }
216
216
  }
217
217
 
218
- // R-pidfile-5: LA decisione di sicurezza. checkSchemaMarker (sopra) guarda
218
+ // da revisione: LA decisione di sicurezza. checkSchemaMarker (sopra) guarda
219
219
  // un EVENTO PASSATO — "il marker e' stato scritto" — che puo' fallire in
220
220
  // silenzio senza lasciare traccia (vedi ensureSchemaMarker): il percorso
221
221
  // resta ENOENT, indistinguibile da "mai tentato". claimSchemaMarker sposta
@@ -444,14 +444,14 @@ function killPidfile(p, signal = 'SIGTERM', impl = {}) {
444
444
  // Prima di questo controllo (nascita, aggiunta dopo cmd) il segnale
445
445
  // partiva sul solo cmd, senza verifica di identità, per QUALUNQUE pidfile
446
446
  // senza processStart — vecchio o nuovo, piattaforma capace o no: era
447
- // esattamente il buco piu' largo trovato dall'audit (2026-08-17), perche'
447
+ // esattamente il buco piu' largo trovato in revisione, perche'
448
448
  // "nessuna nascita nel meta" copriva sia "questa macchina non sa attestare"
449
449
  // sia "l'attestazione e' fallita alla creazione per un motivo che non
450
450
  // conosciamo" con lo STESSO comportamento permissivo. Il ramo sotto separa
451
451
  // i due casi guardando cosa writePidfile ha DICHIARATO al momento in cui
452
452
  // contava (probeProcessStart, sopra), non ricalcolando una sonda adesso —
453
453
  // rifarla qui confonderebbe di nuovo "non so attestare" con "non ci sono
454
- // riuscito in QUESTO istante", l'errore di categoria che l'audit ha
454
+ // riuscito in QUESTO istante", l'errore di categoria che la revisione ha
455
455
  // contestato nel primo disegno di questo fix.
456
456
  let unverifiedBirth = false;
457
457
  let schemaMarker = null; // calcolato pigro: solo se serve davvero (vedi sotto)
@@ -489,7 +489,7 @@ function killPidfile(p, signal = 'SIGTERM', impl = {}) {
489
489
  // altro probe su PID/cmd (la stessa prova debole con un altro nome): serve
490
490
  // una prova ALTERNATIVA del proprietario — per esempio un runId verificato
491
491
  // contro un endpoint locale autenticato. Non e' implementata: e' un lavoro
492
- // a se', con un suo giro di audit (registrato qui, non eseguito).
492
+ // a se', con un suo giro di revisione dedicato (non eseguito).
493
493
  unverifiedBirth = 'unsupported';
494
494
  } else if (meta.attestation === 'indeterminate') {
495
495
  // Il codice NUOVO (questo, o una versione successiva a questo fix) ha
@@ -497,7 +497,7 @@ function killPidfile(p, signal = 'SIGTERM', impl = {}) {
497
497
  // che non sa classificare come proprieta' della piattaforma (vedi
498
498
  // probeProcessStart sopra) — sa che avrebbe potuto, su questo pid,
499
499
  // adesso, e non ce l'ha fatta. Trattarlo come "la piattaforma non sa
500
- // attestare" sarebbe l'errore di categoria contestato dall'audit:
500
+ // attestare" sarebbe l'errore di categoria contestato in revisione:
501
501
  // un'assenza non e' una proprieta' stabile solo perche' e' comoda da
502
502
  // leggere cosi'. Si rifiuta: il cmd da solo matcha per inclusioni, e non
503
503
  // basta a chi non sa nemmeno perche' la nascita manca QUI. Il pidfile
@@ -512,7 +512,7 @@ function killPidfile(p, signal = 'SIGTERM', impl = {}) {
512
512
  // forma di meta la puo' produrre anche un chiamante non nostro): "nessun
513
513
  // campo" da solo non prova la provenienza.
514
514
  //
515
- // R-pidfile-5: la domanda che decide non e' piu' "il marker e' gia'
515
+ // da revisione: la domanda che decide non e' piu' "il marker e' gia'
516
516
  // stato scritto?" (un evento passato che puo' fallire in silenzio —
517
517
  // vedi ensureSchemaMarker/claimSchemaMarker sopra) ma "posso scriverlo
518
518
  // ADESSO?" — claimSchemaMarker prova a crearlo in questo esatto istante:
@@ -534,9 +534,9 @@ function killPidfile(p, signal = 'SIGTERM', impl = {}) {
534
534
  // scrivere qui, verificato nell'istante in cui
535
535
  // conta, non dedotto da uno passato. Si rifiuta.
536
536
  //
537
- // MISURATO (2026-08-17): trattare OGNI meta senza attestazione come
537
+ // MISURATO IN REVISIONE: trattare OGNI meta senza attestazione come
538
538
  // indeterminate rompe l'aggiornamento automatico per ogni nodo il cui
539
- // runtime e' ancora precedente a quando processStart e' nato (8fe514f,
539
+ // runtime e' ancora precedente a quando processStart e' nato (introdotto in
540
540
  // v0.9.0) — npm install sovrascrive pidfile.js PRIMA che il runner lo
541
541
  // richieda, il runner legge il pidfile VECCHIO del runtime in esecuzione,
542
542
  // killPidfile rifiuta, stopPortableRuntime torna killed:false,
@@ -555,9 +555,9 @@ function killPidfile(p, signal = 'SIGTERM', impl = {}) {
555
555
  // morire (il difetto gia' visto sul campo che l'ingresso unico di
556
556
  // riavvio doveva chiudere); un ramo "legacy" permanente basato sulla sola
557
557
  // FORMA del meta (lasciava aperti per sempre restore da backup,
558
- // corruzione e downgrade — l'auditor l'ha contestato); un marker
559
- // controllato ma mai riprovato al kill (questo giro — R-pidfile-5:
560
- // l'auditor ha dimostrato che una scrittura fallita in silenzio riapre
558
+ // corruzione e downgrade — la revisione l'ha contestata); un marker
559
+ // controllato ma mai riprovato al kill (da revisione:
560
+ // una scrittura fallita in silenzio riapre
561
561
  // lo stesso buco senza lasciare traccia).
562
562
  schemaMarker = (impl.claimSchemaMarkerImpl || claimSchemaMarker)(p);
563
563
  if (schemaMarker.state === 'created') {
@@ -407,7 +407,7 @@ function installCommands(platform, target, ctx) {
407
407
  }
408
408
 
409
409
 
410
- // --- Riconoscimento di PROPRIETA' (R28, audit rev2) -------------------------
410
+ // --- Riconoscimento di PROPRIETA' (da revisione) -------------------------
411
411
  // La sanazione automatica riscrive una definizione solo se e' NOSTRA. La prima
412
412
  // versione cercava /nexuscrew/i nel contenuto: un unit di terzi che ci nomina
413
413
  // in un commento («Avviato dopo NexusCrew») veniva sovrascritto. La parola non
@@ -426,7 +426,7 @@ function installCommands(platform, target, ctx) {
426
426
  // dall'ancora: cosi' non possono divergere per costruzione, e il test guardia
427
427
  // diventa una seconda difesa invece dell'unica.
428
428
  //
429
- // R28, terzo giro (audit 2026-08-18): l'ancora linux era un PREFISSO
429
+ // da revisione: l'ancora linux era un PREFISSO
430
430
  // (`/^Description=NexusCrew\b/`) e un servizio di terzi che comincia la sua
431
431
  // Description con il nostro nome — «NexusCrew-compatible proxy», «NexusCrew
432
432
  // fork by tizio» — veniva riconosciuto come nostro e sovrascritto. Il mac era
@@ -109,7 +109,7 @@ function resolveBootPaths({ nodeBin, entryPath, env = process.env, realpath } =
109
109
  };
110
110
  }
111
111
 
112
- // R28: il runner dell'aggiornamento puo' girare con un process.execPath gia'
112
+ // da revisione: il runner dell'aggiornamento puo' girare con un process.execPath gia'
113
113
  // MORTO su disco — l'upgrade di node (Homebrew) unlinka il Cellar vecchio
114
114
  // mentre il processo resta in memoria, e npm reinstalla il pacchetto nel
115
115
  // prefix del node NUOVO. In quel caso resolveBootPaths scriverebbe il path
@@ -47,7 +47,7 @@ function filesRoutes({ cfg, sessionExists, paste, notifier, readonly = () => fal
47
47
  // pasteToSession). Il nome upload e' sanitizzato: se scatta, la causa e'
48
48
  // il filesRoot di configurazione (control char) o un path oltre i 4096
49
49
  // char. Rifiuto noto PRIMA di tmux: la PTY non va neanche tentata.
50
- // 500, non 502 (rilievo audit su d6c47c6): qui il valle NON e' stato
50
+ // 500, non 502 (rilievo da revisione interna): qui il valle NON e' stato
51
51
  // contattato — a rifiutare siamo noi, per configurazione nostra. 502
52
52
  // affermerebbe «il servizio a monte non risponde» e sveglierebbe un
53
53
  // allarme su un tmux che sta benissimo. La coppia di codici e'
@@ -75,7 +75,7 @@ function filesRoutes({ cfg, sessionExists, paste, notifier, readonly = () => fal
75
75
  // nell'outbox della sessione mittente. Path sorgente fail-closed: stringa
76
76
  // assoluta, realpath ESISTENTE sotto HOME (i symlink si risolvono PRIMA del
77
77
  // check: un link che esce da HOME viene rifiutato), file regolare.
78
- // F3 (audit): gated READONLY — la copia e' una scrittura su disco; il gate
78
+ // da revisione: gated READONLY — la copia e' una scrittura su disco; il gate
79
79
  // sta PRIMA di ogni altro check (nessun probe di sessione/path in READONLY).
80
80
  const bridgeReadonly = () => (cfg.readonlyDefault === true || process.env.NEXUSCREW_READONLY === '1');
81
81
  router.post('/outbox', express.json({ limit: '8kb' }), (req, res) => {
@@ -188,7 +188,7 @@ function risolviEseguibile(nome) {
188
188
  function dirScrivibileDaTutti(file) {
189
189
  // Tutta la CATENA, non il solo genitore: con `/a` scrivibile da chiunque,
190
190
  // `/a/b/docker` resta sostituibile rinominando `b` — il binario e la sua
191
- // directory immediata possono essere ineccepibili e il percorso no. Un audit
191
+ // directory immediata possono essere ineccepibili e il percorso no. Una revisione
192
192
  // ha riprodotto esattamente questo caso su un controllo fermo al genitore.
193
193
  //
194
194
  // Lo sticky bit interrompe la risalita per quel livello: li' il kernel
@@ -586,11 +586,11 @@ async function createBuiltinFleet(cfg = {}) {
586
586
  // passano il flag, quindi la suite esistente non vede endpoint lease aperti da up().
587
587
  const cellLeaseEnabled = cfg.cellLeaseEnabled === true;
588
588
 
589
- // --- P1-2 (audit 3405df0): TUTTI i gate availability AVVENGONO PRIMA di creare
589
+ // --- da revisione interna: TUTTI i gate availability AVVENGONO PRIMA di creare
590
590
  // leaseManager/launchBroker e di leaseManager.boot(). leaseManager non esiste finche'
591
591
  // la Fleet non e' confermata disponibile, quindi NESSUN endpoint lease resta vivo su
592
592
  // un early return (off/blocked) finche' ogni gate resta sopra questa boundary.
593
- // P2 (audit 2a05db2): questo e' un fatto contingente del ref corrente, NON una
593
+ // da revisione interna: questo e' un fatto contingente del ref corrente, NON una
594
594
  // garanzia anti-refactor. Un gate aggiunto DOPO la creazione del manager passerebbe
595
595
  // inosservato senza un controllo statico/mutation-sensitive: il commento non impedisce
596
596
  // un `return off` futuro oltre la boundary. La promessa vera e' limitata: oggi nessun
@@ -617,7 +617,7 @@ async function createBuiltinFleet(cfg = {}) {
617
617
  }
618
618
 
619
619
  if (!readonly()) {
620
- // Audit 093, rilievo 3: lo snapshot della BASE si prende QUI, alla lettura
620
+ // da revisione (rilievo 3): lo snapshot della BASE si prende QUI, alla lettura
621
621
  // che ha prodotto `boot` — non con una rilettura dopo la migrazione. Il
622
622
  // vecchio `primaDelloScrivere` era una rilettura: una scrittura arrivata
623
623
  // DURANTE migrateLegacyTmuxSessions (una catena di chiamate tmux: finestra
@@ -694,8 +694,8 @@ async function createBuiltinFleet(cfg = {}) {
694
694
  // il canale lease del supervisore.
695
695
  ...(leaseManager ? {
696
696
  onLease: (socket, lease) => {
697
- // P1-3 (reaudit dd38c83): attachInitial restituisce false se la
698
- // persistenza del bind fallisce. F-B (audit 2a @ 142e272): ora il
697
+ // da revisione interna: attachInitial restituisce false se la
698
+ // persistenza del bind fallisce. da revisione interna: ora il
699
699
  // broker chiama onLease PRIMA di scrivere il payload. Il ritorno
700
700
  // ESPLICITO false (o la socket distrutta qui) comunica al broker di NON
701
701
  // consegnare il payload: il supervisore riceve la chiusura prima del
@@ -0,0 +1,82 @@
1
+ {
2
+ "models": [
3
+ {
4
+ "slug": "glm-5.3",
5
+ "display_name": "glm-5.3",
6
+ "description": "Z.ai's latest flagship model",
7
+ "default_reasoning_level": "max",
8
+ "supported_reasoning_levels": [
9
+ {
10
+ "description": "Light reasoning",
11
+ "effort": "low"
12
+ },
13
+ {
14
+ "description": "Enhanced reasoning",
15
+ "effort": "high"
16
+ },
17
+ {
18
+ "description": "Deep reasoning",
19
+ "effort": "max"
20
+ }
21
+ ],
22
+ "shell_type": "shell_command",
23
+ "visibility": "list",
24
+ "supported_in_api": true,
25
+ "priority": 0,
26
+ "base_instructions": "",
27
+ "supports_reasoning_summaries": true,
28
+ "default_reasoning_summary": "none",
29
+ "support_verbosity": false,
30
+ "apply_patch_tool_type": "freeform",
31
+ "truncation_policy": {
32
+ "limit": 10000,
33
+ "mode": "bytes"
34
+ },
35
+ "supports_parallel_tool_calls": true,
36
+ "availability_nux": null,
37
+ "upgrade": null,
38
+ "default_verbosity": null,
39
+ "web_search_tool_type": "text",
40
+ "supports_image_detail_original": false
41
+ },
42
+ {
43
+ "slug": "glm-5.3-flash",
44
+ "display_name": "glm-5.3-flash",
45
+ "description": "Fast multimodal coding model",
46
+ "default_reasoning_level": "max",
47
+ "supported_reasoning_levels": [
48
+ {
49
+ "description": "Light reasoning",
50
+ "effort": "low"
51
+ },
52
+ {
53
+ "description": "Enhanced reasoning",
54
+ "effort": "high"
55
+ },
56
+ {
57
+ "description": "Deep reasoning",
58
+ "effort": "max"
59
+ }
60
+ ],
61
+ "shell_type": "shell_command",
62
+ "visibility": "list",
63
+ "supported_in_api": true,
64
+ "priority": 1,
65
+ "base_instructions": "",
66
+ "supports_reasoning_summaries": true,
67
+ "default_reasoning_summary": "none",
68
+ "support_verbosity": false,
69
+ "apply_patch_tool_type": "freeform",
70
+ "truncation_policy": {
71
+ "limit": 10000,
72
+ "mode": "bytes"
73
+ },
74
+ "supports_parallel_tool_calls": true,
75
+ "availability_nux": null,
76
+ "upgrade": null,
77
+ "default_verbosity": null,
78
+ "web_search_tool_type": "text_and_image",
79
+ "supports_image_detail_original": true
80
+ }
81
+ ]
82
+ }
@@ -19,7 +19,7 @@ const DEFAULT_SUPERVISE = Object.freeze({
19
19
  maxRapidRestarts: 8,
20
20
  });
21
21
 
22
- // F-B (audit 2a, correzione escalation): limite ESPLICITO fra SIGTERM e
22
+ // da revisione (correzione escalation): limite ESPLICITO fra SIGTERM e
23
23
  // SIGKILL quando la lease e' persa (onLost, main()). Un figlio che ignora
24
24
  // SIGTERM non deve restare appeso a tempo indeterminato.
25
25
  const LEASE_LOST_KILL_ESCALATION_MS = 5000;
@@ -303,7 +303,7 @@ async function main(argv = process.argv.slice(2), seams = {}) {
303
303
  // inherit. Il proof (2b) vive nel lease-client, MAI nell'env del child.
304
304
  let generation = 0;
305
305
  let leaseCtl = null;
306
- // F-B (audit 2a): current/stopping vivono QUI (prima del lease-client) perche'
306
+ // da revisione interna: current/stopping vivono QUI (prima del lease-client) perche'
307
307
  // la callback onLost qui sotto li riferisce dalla closure.
308
308
  let current = null; let stopping = false;
309
309
  if (payload.lease && leaseSocket && !leaseSocket.destroyed) {
@@ -315,7 +315,7 @@ async function main(argv = process.argv.slice(2), seams = {}) {
315
315
  // generation += 1). Passiamo un getter cosicche' il reconnect presenti
316
316
  // sempre la generation corrente, non 0 fisso (riconcilia :301 con :381).
317
317
  generation: () => generation,
318
- // F-B (audit 2a @ 142e272): lease persa per tutta la grace senza un
318
+ // da revisione interna: lease persa per tutta la grace senza un
319
319
  // reconnect riuscito. Prima il lease-client desisteva in silenzio dopo
320
320
  // 60s e il child restava un orfano senza lease per tutta la sua vita.
321
321
  // Ora il supervisore viene avvisato: ferma il child (stopping + SIGTERM)
@@ -324,7 +324,7 @@ async function main(argv = process.argv.slice(2), seams = {}) {
324
324
  // Correzione (seconda riconsegna): un SOLO SIGTERM senza escalation
325
325
  // lascia appeso un child che lo ignora (misurato sul percorso reale:
326
326
  // {spawned:1, kills:['SIGTERM'], state:'pending'}) — l'orfano non NASCE
327
- // piu' (F-B originale chiuso davvero), ma un figlio gia' vivo che non
327
+ // piu' (caso originale chiuso davvero), ma un figlio gia' vivo che non
328
328
  // collabora non muore. LEASE_LOST_KILL_ESCALATION_MS e' il limite
329
329
  // ESPLICITO, scritto qui: se il child non e' uscito entro questa
330
330
  // finestra dal SIGTERM, si passa a SIGKILL. `target` fissa il processo
@@ -9,7 +9,7 @@
9
9
  // issuedAt+60s). Il proof supervisore arriva al detentore sul canale lease
10
10
  // (all'attach e a ogni refresh) e non transita mai nel child (R3.1.2 invariato).
11
11
  //
12
- // Storage per-cella (D1/D2): un file per cella in <run>/cell-leases/. Il
12
+ // Storage per-cella (da revisione): un file per cella in <run>/cell-leases/. Il
13
13
  // refresh di una cella rilegge e riscrive SOLO il proprio file: scompare la
14
14
  // read-modify-write dell'intero store condiviso, la race su di essa e
15
15
  // l'amplificazione O(N^2) misurata in 2a (N letture + N scritture complete
@@ -51,7 +51,7 @@ function sanitizeCell(cellId) {
51
51
  const CELL_ID_RE = /^[A-Za-z0-9._-]{1,64}$/;
52
52
  function validCellId(cellId) { return typeof cellId === 'string' && CELL_ID_RE.test(cellId); }
53
53
 
54
- // F-A (audit 2a @ 142e272): il formato che il runtime produce per un'identity.
54
+ // da revisione interna: il formato che il runtime produce per un'identity.
55
55
  // Condiviso da loadPersisted (primo ingresso, al boot) e track (secondo
56
56
  // ingresso): la validazione e' UNA, non due copie da tenere allineate.
57
57
  const EPOCH_RE = /^[a-f0-9]{16}$/;
@@ -112,7 +112,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
112
112
  // IC1.1 (rev28, emendata da rev29): quando il proof nasce da un commit del
113
113
  // bound, issuedAt è DERIVATO da D (D − PROOF_TTL_MS), mai letto dal clock:
114
114
  // expiresAt = issuedAt + TTL è esattamente D, senza toccare verifyProof,
115
- // KIND_FIELDS o wire (vincolo M6 dell'audit rev28).
115
+ // KIND_FIELDS o wire (vincolo della revisione).
116
116
  function issueLeaseProof(cellId, entry, lease, { issuedAt } = {}) {
117
117
  return signProof(ensureVerifier(), {
118
118
  kind: 'lease',
@@ -142,7 +142,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
142
142
  throw e;
143
143
  }
144
144
  const obj = JSON.parse(raw);
145
- // P1-1b: la FORMA del dato. La root deve essere l'entry attesa: plain-object
145
+ // da revisione: la FORMA del dato. La root deve essere l'entry attesa: plain-object
146
146
  // con i campi del formato per-cell. Qualunque altra cosa e' illeggibile.
147
147
  if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) {
148
148
  throw new Error(`store lease: entry per-cella non e' un oggetto: ${sanitizeCell(cellId)}`);
@@ -211,7 +211,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
211
211
  const prev = entry.graceDeadline;
212
212
  entry.graceDeadline = D;
213
213
  if (!persistEntry(cellId, entry)) {
214
- entry.graceDeadline = prev; // rollback (P1-2b): nessun commit, nessun ACK
214
+ entry.graceDeadline = prev; // rollback (revisione): nessun commit, nessun ACK
215
215
  return null;
216
216
  }
217
217
  return { t, deadline: D, issuedAt: D - PROOF_TTL_MS };
@@ -242,7 +242,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
242
242
  }
243
243
 
244
244
  function bindLiveSocket(cellId, entry, socket, { lease }) {
245
- // P1-2b (audit 2a05db2): persiste il bound PRIMA di associare il socket. Se il
245
+ // da revisione interna: persiste il bound PRIMA di associare il socket. Se il
246
246
  // record non committa, rollback e ritorna false: il caller non dichiarera' lease.
247
247
  // Diverso da EOF (onEOF): li una write fallita lascia un bound ANTERIORE (fail-closed
248
248
  // anticipato, accettabile); qui il bind prometterebbe stato live senza commit durevole.
@@ -314,7 +314,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
314
314
  socket.on('data', onData);
315
315
  socket.once('close', onEOF);
316
316
  socket.once('end', onEOF);
317
- // Correzione (audit 2a, segnalazione precisata in revisione): questo E' il socket
317
+ // Correzione (da revisione, segnalazione precisata): questo E' il socket
318
318
  // su cui il server SCRIVE (l'ack di refresh — proprio dove l'EPIPE nasce se
319
319
  // il peer muore mentre la write e' in volo). Un EventEmitter che emette
320
320
  // 'error' senza listener fa un throw che termina l'INTERO processo — non
@@ -345,7 +345,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
345
345
  socket.setEncoding('utf8');
346
346
  socket.on('data', onData);
347
347
  socket.once('close', () => { try { socket.destroy(); } catch (_) {} });
348
- // Correzione (audit 2a): stesso motivo di bindLiveSocket — il server scrive
348
+ // Correzione (da revisione interna): stesso motivo di bindLiveSocket — il server scrive
349
349
  // 'deny' su questo socket (onData sopra, JSON malformato); senza un
350
350
  // handler 'error' un peer che muore mentre quella write e' in volo manda
351
351
  // in throw fatale l'intero processo. Se la connessione avanza a
@@ -448,7 +448,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
448
448
  const server = netImpl.createServer((sock) => onStableConnection(cellId, sock));
449
449
  await new Promise((resolve, reject) => {
450
450
  server.once('error', reject);
451
- // F-C (audit 2a @ 142e272): niente piu' set/restore di process.umask.
451
+ // da revisione interna: niente piu' set/restore di process.umask.
452
452
  // process.umask e' GLOBALE e la coppia set/restore non e' atomica: sotto
453
453
  // openEndpoint concorrenti il restore di uno ripristinava lo 0o177 appena
454
454
  // settato dall'altro e il processo restava driftato. La protezione e'
@@ -475,7 +475,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
475
475
  return sp;
476
476
  }
477
477
 
478
- // F-C (audit 2a @ 142e272): track() serializzato PER CELLA. Due track
478
+ // da revisione interna: track() serializzato PER CELLA. Due track
479
479
  // simultanei sulla stessa cella vedevano entrambi cells.get() vuoto, generavano
480
480
  // due identity divergenti e il perdente restava con un'identity inutile. La
481
481
  // catena per cellId fa attendere al secondo la fine del primo; poi
@@ -501,7 +501,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
501
501
  // server NON si genera una nuova launchEpoch, perche' il supervisore vivo
502
502
  // reconnecta con quella originale (e il suo proof la porta firmata).
503
503
  const existing = cells.get(cellId);
504
- // P1-2 (reaudit dd38c83): snapshot dell'entry preesistente prima di mutare
504
+ // da revisione interna: snapshot dell'entry preesistente prima di mutare
505
505
  // qualunque cosa. Se persistEntry fallisce su una cella gia' viva, il cleanup
506
506
  // deve ripristinare lo stato precedente, NON cancellarlo.
507
507
  const hadExisting = !!existing;
@@ -513,7 +513,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
513
513
  } : null;
514
514
  // openEndpoint puo' aver creato un nuovo stableServer se l'entry non ne aveva uno.
515
515
  const serverBeforeOpen = existing ? existing.stableServer : null;
516
- // F-A (audit 2a): il SECONDO INGRESSO valida come il primo. Un valore
516
+ // da revisione interna: il SECONDO INGRESSO valida come il primo. Un valore
517
517
  // persistito e' riusato SOLO se ha il formato che il runtime produce
518
518
  // (hex-16 l'epoch); malformato -> identity NUOVA generata, e la persistEntry
519
519
  // qui sotto la scrive, riparando la entry corrotta sul disco.
@@ -541,8 +541,8 @@ function createLeaseManager(cfg = {}, seams = {}) {
541
541
  await openEndpoint(cellId, entry);
542
542
  cells.set(cellId, entry);
543
543
  if (!persistEntry(cellId, entry)) {
544
- // P1-2b: il record durevole (identity) e' essenziale per la recovery post-restart.
545
- // P1-2 (reaudit dd38c83): se la cella era GIA' viva, NON cancellarla — ripristina
544
+ // da revisione: il record durevole (identity) e' essenziale per la recovery post-restart.
545
+ // da revisione interna: se la cella era GIA' viva, NON cancellarla — ripristina
546
546
  // lo stato precedente. Solo le risorse create in QUESTO tentativo vengono pulite.
547
547
  if (hadExisting) {
548
548
  entry.launchEpoch = existingSnapshot.launchEpoch;
@@ -590,7 +590,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
590
590
  // payload il canale appartiene al protocollo del broker (frame length-
591
591
  // prefixed u32): una riga JSON scritta prima del payload corromperebbe la
592
592
  // lettura di receivePayload e il child non nascerebbe — misurato dal gate
593
- // (lease-audit-2a-fixes, F-B positivo). Il proof supervisore arriva con
593
+ // (da revisione interna, esito positivo). Il proof supervisore arriva con
594
594
  // l'ACK del primo refresh, che il lease-client invia IMMEDIATAMENTE
595
595
  // all'avvio: la finestra attach->primo-ack senza proof detenuto e' fail-closed
596
596
  // (reconnect negato -> grace -> onLost), coerente col modello per cui nessun
@@ -628,7 +628,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
628
628
  log(`cell-lease: loadPersisted entry '${cellId}' illeggibile, saltata: ${e && e.message}`);
629
629
  continue;
630
630
  }
631
- // P1-4 (reaudit dd38c83): forma <> semantica. Il runtime produce launchEpoch
631
+ // da revisione interna: forma <> semantica. Il runtime produce launchEpoch
632
632
  // come hex di 16 char. Fail-closed: formato errato = entry saltata.
633
633
  if (!info || typeof info.launchEpoch !== 'string' || !EPOCH_RE.test(info.launchEpoch)) {
634
634
  log(`cell-lease: loadPersisted entry '${cellId}' malformata, saltata`);
@@ -640,7 +640,7 @@ function createLeaseManager(cfg = {}, seams = {}) {
640
640
  cells.set(cellId, {
641
641
  launchEpoch: info.launchEpoch,
642
642
  // IC8.5 (rev29): graceDeadline assente/illeggibile/non-intero = bound trattato come scaduto (0 -> deny sempre).
643
- // P1-4: forma <> semantica — un bound oltre now()+2*GRACE_MS non e' producibile
643
+ // da revisione: forma <> semantica — un bound oltre now()+2*GRACE_MS non e' producibile
644
644
  // da questa fetta: trattato come scaduto (0). Tolleranza 2*GRACE_MS per un
645
645
  // restart durante la grace. Fail-closed: bound assurdo = scaduto.
646
646
  graceDeadline: (Number.isInteger(info.graceDeadline) && info.graceDeadline > 0