test(harness): report L2 cardioversione+ablazione + fix phase show (#2)
Prima sessione L2 end-to-end dopo il porting. Il loop skill->LLM->gate funziona nel dominio (ricerche, evidence, quadro corretto su fact_cardioversione/fact_see_ablazione) ma si blocca a F1 sul bug fatale #4 (ctx.sendRaw non esiste nel runtime Pi). Bug emersi (4): #1 tht non nel PATH di Pi (basso, workaround wrapper) #2 phase show non passava config (medio, FIXATO: _cfg() risolve env+default) #3 session check signature inconsistente (basso, da verificare) #4 ctx.sendRaw is not a function (FATALE, mismatch architetturale: il porting ha sostituito i dialog nativi ctx.ui.* con ctx.sendRaw, API non esposta in questo Pi) Analisi #4 (verificata sul runtime installato): - ctx.sendRaw non esiste; extension_ui_request e' emesso solo dal runtime (modes/rpc) come traduzione di ctx.ui.select/confirm/input, non come API extension - canali RPC per decisioni: enum chiuso select/confirm/input/editor (no custom) - ctx.ui.custom (multiselect TUI di ChironeWp3) e' no-op in RPC mode - conseguenza: multiselect F4 non ha canale in RPC -> decisione di design del gate aperta (opzioni A/B/C nel report, C=scartato), merita brainstorming dedicato Fix #2 (dal modello in sessione, validato e ripulito): phase_cmd._cfg() ora risolve THT_WORKSPACE/THT_CONFIG env poi fallback config/tht.yaml (stessa convenzione CONFIG_OPT). Testato phase show OK, suite 165 passed. Report: docs/l2-run-report-2026-06-27.md.
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
# L2 Run Report — 2026-06-27 (sessione cardioversione + ablazione)
|
||||
|
||||
> Esito della prima sessione L2 end-to-end dopo il porting CLI+skill (Onda -1→4 +
|
||||
> Skill + 0b). Sessione non-deterministica, esito informativo non bloccante per il
|
||||
> "done" del porting codice (come da piano L2.1, riga 1187).
|
||||
|
||||
## Setup al momento del run
|
||||
|
||||
- Pi: `@earendil-works/pi-coding-agent`, provider `zai`, model `glm-5.2` (default).
|
||||
- Harness: Onda -1→4 + Skill committate; Onda 0b (workspace cliente `tht-workspace-psd`,
|
||||
indice LSH 75737 valori, evidence 35).
|
||||
- `.env` popolato, VPN OK, DWH REST 200, Ollama UP.
|
||||
- Pre-run fix applicati in questa sessione: `_YamlModel.to_yaml` (bloccava `session new`),
|
||||
`config/tht.yaml` symlink al workspace cliente (il gate chiama `tht` senza `-c`).
|
||||
|
||||
## Come è partita la sessione
|
||||
|
||||
Lancio `pi --mode rpc` + `/nuova-domanda "<cardioversione + ablazione same-year>"`.
|
||||
**Nota critica su `--mode rpc`:** la TUI interattiva di Pi (`pi` senza `--mode`) **non
|
||||
renderizza** i widget `extension_ui_request` del gate (gestiti solo in `modes/rpc/`).
|
||||
La modalità RPC emette i widget come JSONL su stdio per un client esterno — che non
|
||||
esiste ancora in ThothII. Il run è stato possibile solo perché il modello, non vedendo
|
||||
UI, ha operato via shell/tool fino al blocco fatale (vedi bug #4).
|
||||
|
||||
## Cosa ha fatto il modello (transcript: 117 eventi, 365KB)
|
||||
|
||||
Sessione Pi: `~/.pi/agent/sessions/--Users-mp-projects-ThothII-harness--/2026-06-27T13-44-51...jsonl`.
|
||||
Sessione tht: `tht-workspace-psd/sessions/2026-06-27-134553-crea-una-lista...` (status: open, F1).
|
||||
|
||||
Il modello ha lavorato molto e correttamente nel dominio:
|
||||
- Ha creato la sessione, caricato la skill, iniziato F1.
|
||||
- Ha eseguito ricerche semantiche (evidence + LSH), individuato le tabelle centrali
|
||||
(`fact_cardioversione_elettrica`, `fact_see_ablazione`, `dim_patient`).
|
||||
- Ha letto evidence molto pertinenti (esempio NLQ, glossario coorti/universi), costruendo
|
||||
un quadro dominio corretto e verificato sulle tabelle reali.
|
||||
|
||||
Il workflow **non è avanzato oltre F1**: nessuna decisione registrata
|
||||
(`review_decisions.jsonl` assente). Il modello si è arenato su bug di porting (sotto).
|
||||
|
||||
## Bug di porting emersi (4, di cui 1 fatale)
|
||||
|
||||
### #1 — `tht` non nel PATH del processo Pi [basso]
|
||||
Il gate chiama `execFileSync("tht", args, {cwd: ctx.cwd})`. L'eseguibile nel venv non è nel
|
||||
PATH di Pi. Il modello ha creato un wrapper in `~/.local/bin` (workaround).
|
||||
**Fix root-cause:** installare `tht` in una dir nel PATH (pip install -e . con entry point
|
||||
globale, o symlink `/usr/local/bin/tht -> harness/.venv/bin/tht`).
|
||||
|
||||
### #2 — `phase show` non passava il config [medio, FIXATO]
|
||||
`phase_cmd._cfg()` non passava il config a `_load_config_or_exit()`, quindi falliva con
|
||||
"File non trovato config/tht.yaml" quando non c'era `THT_WORKSPACE` env.
|
||||
**Fix applicato (dal modello in sessione, validato e pulito):** `_cfg()` ora risolve
|
||||
`THT_WORKSPACE`/`THT_CONFIG` env, poi fallback a `config/tht.yaml` (stessa convenzione di
|
||||
`CONFIG_OPT`). Testato: `phase show` funziona. Suite 165 passed.
|
||||
|
||||
### #3 — `session check` signature inconsistente [basso, da verificare]
|
||||
Il modello ha notato che `session check` prende la sessione come argomento posizionale,
|
||||
non `--session` come gli altri cmd. Da verificare e allineare.
|
||||
|
||||
### #4 — `ctx.sendRaw is not a function` [FATALE, blocca tutti i widget]
|
||||
Il gate `tht-gate.js:164` emette i widget con `ctx.sendRaw({type:"extension_ui_request"...})`.
|
||||
Il runtime Pi installato **non espone `ctx.sendRaw`** sul context delle extensions. Il
|
||||
modello l'ha verificato leggendo le type definitions (`ExtensionContext` espone `ui`,
|
||||
`mode`, `hasUI`, `cwd`, `abort` — ma non `sendRaw`). **Nessun widget può essere emesso in
|
||||
nessuna modalità.** Questo ha fermato il workflow a F1.
|
||||
|
||||
## Analisi del bug #4 (mismatch architetturale, non un typo)
|
||||
|
||||
Il commento nel gate stesso (righe 2-6) dice: *"REWRITE of the reference implementation...
|
||||
replaces ctx.ui.* blocking primitives"*. Il porting ha **sostituito** i dialog nativi di Pi
|
||||
con `ctx.sendRaw`, presumendo un'API widget-descriptor diretta che **questa versione di Pi
|
||||
non espone alle extensions**. Verifiche sul runtime installato:
|
||||
|
||||
- `ctx.sendRaw`: **non esiste** (0 refs in `core/extensions/`).
|
||||
- `extension_ui_request`: emesso **solo dal runtime** (`modes/rpc/rpc-mode.js`), come
|
||||
traduzione dei dialog nativi (`ctx.ui.select` → `{method:"select"}`), non come API per
|
||||
le extensions.
|
||||
- Canali disponibili in RPC mode per ricevere una decisione umana (enum chiuso):
|
||||
`ctx.ui.select` / `confirm` / `input` / `editor` (+ `notify` one-way). I `method` di
|
||||
`extension_ui_request` sono: select/confirm/input/editor/notify/setWidget/setStatus/
|
||||
set_editor_text. **Nessun method custom** per widget-descriptor.
|
||||
- `ctx.ui.custom` (usato da ChironeWp3 per il multiselect TUI): in RPC mode è un **no-op**
|
||||
(`return undefined`, commento: "Custom UI not supported in RPC mode").
|
||||
|
||||
### Conseguenza per i 6 widget della spec §4
|
||||
- `select` (scelta singola) → ✅ `ctx.ui.select`
|
||||
- `confirm` (approvazione) → ✅ `ctx.ui.confirm`
|
||||
- `input` (testo libero / Altro) → ✅ `ctx.ui.input`
|
||||
- `multiselect` (scelta multipla — **critico per F4 schema-linking**) → ❌ nessun canale
|
||||
in RPC. Solo `ctx.ui.custom` lo faceva (TUI only).
|
||||
|
||||
Il multiselect è il vero ostacolo. F4 richiede di promuovere/escludere **più** tabelle/
|
||||
colonne in una volta.
|
||||
|
||||
## Opzioni per il design del gate (decisione architetturale APERTA)
|
||||
|
||||
Il design del gate influenza tutta la relazione harness↔backend↔FE. Non è un fix da
|
||||
inserire in coda a una sessione di porting; merita brainstorming dedicato. Opzioni:
|
||||
|
||||
- **A — Torna a `ctx.ui.*` nativi.** Il gate riscrive `emitAndWait` su `ctx.ui.select`/
|
||||
`confirm`/`input` (come ChironeWp3 originale). Multiselect F4 emulato (serie di select, o
|
||||
un input). Funziona con il Pi installato ora. Perde i widget-descriptor ricchi spec §4;
|
||||
il FE riceve method nativi, la mappatura kind→method va nel backend/FE.
|
||||
- **B — Versione di Pi con API widget custom.** Verificare se un Pi più recente/preview
|
||||
espone `ctx.sendRaw` o un method custom. Se sì, il gate attuale funziona. Rischio:
|
||||
inseguire un'API magari non pubblica; aggiornare Pi può rompere provider/auth.
|
||||
- **C — Wrapper ibrido (valutato, NON realizzabile).** Registrare un handler che intercetti
|
||||
gli `extension_ui_request` nativi e li arricchisca nel formato widget-descriptor spec §4
|
||||
prima di mandarli al client RPC. **Scartato:** non c'è canale per widget-descriptor custom
|
||||
in RPC (method è enum chiuso, `ctx.ui.custom` è no-op in RPC).
|
||||
|
||||
## Artefatti prodotti
|
||||
|
||||
- `tht-workspace-psd/sessions/2026-06-27-134553-.../` (manifest + question.md, F1, open).
|
||||
- Sessione Pi transcript (vedi sopra) — fonte primaria per il debug.
|
||||
- Fix codice: `_cfg()` in `phase_cmd.py` (bug #2), applicato pulito.
|
||||
|
||||
## Conclusione
|
||||
|
||||
**La sessione L2 ha colto bug di porting reali — ha fatto il suo lavoro.** Il loop
|
||||
skill→LLM→gate funziona nel dominio (ricerche, evidence, quadro corretto) ma si blocca a
|
||||
F1 sul bug fatale #4. Tre dei quattro bug sono risolvibili a basso costo (#1, #2 fixato,
|
||||
#3); il #4 è una decisione di design del gate che richiede brainstorming prima del codice.
|
||||
|
||||
**Stato del porting codice (Onda -1→4 + Skill + 0b):** completo e verificato a livello L0/L1
|
||||
(165 passed) + L2 value-grounding (PASS). I bug L2 emersi sono incrementi di qualità, non
|
||||
regressioni del porting — L2 coglie ciò che L0/L1 per design non possono.
|
||||
@@ -146,22 +146,19 @@ def show_cmd(
|
||||
|
||||
|
||||
def _cfg():
|
||||
"""Load the workspace config. Tries the shared helper once schema_cmd is ported
|
||||
(Onda 1.4); falls back to THT_WORKSPACE env + load_config for now."""
|
||||
"""Load the workspace config. Resolves THT_WORKSPACE/THT_CONFIG first, then
|
||||
falls back to the CLI default ``config/tht.yaml`` (same convention as
|
||||
schema_cmd.CONFIG_OPT)."""
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
ws = os.environ.get("THT_WORKSPACE") or os.environ.get("THT_CONFIG")
|
||||
config_path = Path(ws) if ws else Path("config/tht.yaml")
|
||||
try:
|
||||
from tht.cli.schema_cmd import _load_config_or_exit # noqa: F401 (portato in Onda 1.4)
|
||||
|
||||
return _load_config_or_exit()
|
||||
return _load_config_or_exit(config_path)
|
||||
except ImportError:
|
||||
import os
|
||||
|
||||
from tht.workspace import load_config
|
||||
|
||||
ws = os.environ.get("THT_WORKSPACE") or os.environ.get("THT_CONFIG")
|
||||
if not ws:
|
||||
typer.secho(
|
||||
"Nessun workspace: imposta THT_WORKSPACE o usa --config.",
|
||||
fg=typer.colors.RED, err=True,
|
||||
)
|
||||
raise typer.Exit(2)
|
||||
return load_config(ws)
|
||||
return load_config(config_path)
|
||||
|
||||
Reference in New Issue
Block a user