Commit Graph
71 Commits
Author SHA1 Message Date
marcopanandClaude Sonnet 4.6 2d680c958c feat(backend): SessionBridge widget-descriptor <-> RPC + pending widget
Decodes native extension_ui_request (method:input, title=JSON) into
ui_request ClientEvent; encodes respond() as extension_ui_response with
value payload; tracks pending widget; handles notify→info and steer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 20:56:26 +02:00
marcopan df5d2c36ac feat(backend): RpcClient (spawn/send/request/event) over JSONL 2026-06-27 20:52:22 +02:00
marcopanandClaude Opus 4.8 de56694433 feat(backend): LF-only JSONL line splitter
Implement attachJsonlReader to split streams on \n only, handling
trailing \r, and reassembling lines split across chunk boundaries.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 20:49:00 +02:00
marcopanandClaude Sonnet 4.6 b09de85c6f feat(backend): scaffold Fastify+TS + /health
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 20:46:08 +02:00
marcopanandClaude Sonnet 4.6 17c277bb99 test(harness): fake-pi-rpc protocol double + F1 widget contract golden (D10)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 20:36:23 +02:00
marcopanandClaude Opus 4.8 ae9308470b chore(harness): quietStartup + project-local trust for clean RPC spawn
Set quietStartup:true in .pi/settings.json to suppress Pi banner on RPC stdout.
Add test pinning both quietStartup and theme values. Document project-local trust
requirement (--approve) so no trust prompt blocks RPC loop iteration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 20:33:03 +02:00
marcopanandClaude Sonnet 4.6 5d9a0bb548 feat(harness): manifest provider/model/thinking/name + session new options (BE-6/7)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 20:29:40 +02:00
marcopanandClaude Sonnet 4.6 5e0e1cee03 test(harness): pin session list/show json keys + schema alias
- test_list_sessions_required_keys: assert full spec key set
  (adds summary/updated_at/author) so dropping any goes caught.
- test_cli_show_json_valid: assert "schema" in / "db_schema" not in
  data to pin by_alias=True on the alias-sensitive field.

Production code unchanged. 8 passed; full suite 230 passed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 20:27:18 +02:00
marcopanandClaude Sonnet 4.6 a10a872a99 feat(cli): tht session list --json + session show --json (Task 7)
- Add _list_sessions(sessions_root) pure helper: scans sessions dir,
  returns list[dict] with id/status/question/summary/created_at/
  updated_at/author, sorted by created_at desc.
- Add `tht session list` command: --json emits pristine JSON array,
  human mode prints one line per session.
- Add --json flag to `tht session show`: emits manifest
  (model_dump by_alias) + phase (current_phase) + has_schema_linking.
- Tests: 8 tests in test_session_list_json.py (TDD red→green).
- Full suite: 230 passed (--ignore=tests/l2).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 20:23:46 +02:00
marcopanandClaude Opus 4.8 85e2fdc00a fix(harness): correct truncated signalling for sql preview offset>0
When offset>0 the wrapper added an outer LIMIT N, so run_controlled's
_inject_limit bailed (a LIMIT IS present) and truncated was always False —
AGGrid could never detect more rows. Fix: for offset>0 probe with LIMIT (N+1)
OFFSET M, then compute truncated = len(rows) > N in do_run and slice back to N.
offset==0 path unchanged (delegates to extracted _run_transport helper). JSON
still reports the user's requested limit N and correct truncated. Adds 3 tests
exercising the real do_run offset>0 path (N+1 -> truncated True, N -> False,
offset==0 verbatim). 222/222 passing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 20:18:58 +02:00
marcopanandClaude Sonnet 4.6 7d9769cfff feat(harness): tht sql preview --json + --offset for AGGrid paging (BE-2)
Add inject_limit_offset (tht/execute/limit.py) — pure subquery wrapper that
applies LIMIT/OFFSET non-destructively without clobbering user-supplied LIMITs.
Wire offset param into do_run (pre-processing when offset>0) and add --offset /
--json flags to preview_cmd; JSON mode emits pristine stdout with columns, rows,
execution_ms, truncated, limit, offset. 5 new tests (4 unit + 1 JSON-purity),
219/219 total passing (no regressions).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 20:13:20 +02:00
marcopanandClaude Sonnet 4.6 0240242f5c feat(harness): gate uses externally-provided THT_SESSION id (BE-5)
When THT_SESSION env var is set, /nuova-domanda injects a kickoff that
tells the model to use the pre-created session id instead of running
`tht session new`. /riprendi-sessione and no-env-var paths unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 20:07:25 +02:00
marcopan 8c4a1798da fix(harness): gate widget round-trip via native ctx.ui.input (no sendRaw); no-limbo 2026-06-27 20:02:19 +02:00
marcopanandClaude Sonnet 4.6 c55df2ad0f fix(harness): gate kickoff/lock entry works in RPC mode (not only interactive)
- Removed event.source === "interactive" guard from entry detection so
  /nuova-domanda and /riprendi-sessione activate lockActive+pendingKickoff
  regardless of source (TUI or RPC prompt).
- Removed event.source !== "interactive" from free-input filter; lock now
  blocks/steers all user input when active, not only interactive keystrokes.
- Added typebox@1.1.38 devDep + fake_pi_runtime.registerCommand (gap from Task 2).
- New test: gate_entry.test.js (2 tests: lock activates on RPC; !-steer passes).
- Full suite: 19/19 pass, zero regressions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 19:57:38 +02:00
marcopan b72183ef2a docs(plans): test setup per importare il gate (typebox devDep, import ESM) 2026-06-27 19:52:00 +02:00
marcopan f850c391d8 test(harness): fake-pi-runtime mock for gate CI tests 2026-06-27 19:48:04 +02:00
marcopanandClaude Opus 4.8 aecc86f328 docs(plans): correggi wire contract post-spike (ctx.ui.input nativo, niente sendRaw)
Lo spike Task 1 ha provato che ctx.sendRaw non esiste e pi.on(extension_ui_response)
non e' dispatchato. Aggiornati: Piano1 Task2 (mock ctx.ui), Task4 (rewrite gate a
ctx.ui.input con descriptor in title), Task10 (fake-pi-rpc shape nativa); Piano2
Task3/Task4 (SessionBridge decodifica title<->value). Contratto FE invariato.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 19:47:21 +02:00
marcopanandClaude Sonnet 4.6 59bd6135e2 spike(harness): probe gate behavior in pi --mode rpc + findings
Static analysis of Pi runtime (rpc-mode.js, agent-session.js, runner.js)
confirms all 4 decisive questions:
- Q1 kickoff: NO — source:"rpc" bypasses the "interactive" guard (agent-session.js:720)
- Q2 widget emission: NO — ctx.sendRaw does not exist, crashes (0 refs in core/extensions/)
- Q3 response routing: NO — rpc-mode.js returns after consuming extension_ui_response;
  pi.on("extension_ui_response") never fires (not in runner.js)
- Q4 steering: YES — steer() bypasses emitInput entirely

Decision: both Task 3 (kickoff guard) and Task 4 (emitAndWait → ctx.ui.* / Variant A)
require gate adaptation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 19:38:04 +02:00
marcopanandClaude Opus 4.8 c9c150c942 docs(plans): piano Harness RPC-readiness + piano Backend
Due piani separati (decomposizione concordata): il backend dipende da lavoro
harness non testato (gate RPC-ready, id injection, prereq CLI --json/--offset,
fake-Pi). Piano 1 rende l'harness pilotabile via RPC; Piano 2 costruisce il
backend Node/Fastify testato contro il fake-pi-rpc.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 19:26:46 +02:00
marcopanandClaude Opus 4.8 aad6299c99 docs(backend): design del backend ThothII (brainstorming)
Decisioni BE-1..BE-7: un Pi per sessione attiva, SQL finale delegato a tht
(codepath unico, rischio D7 eliminato), resilienza via ricostruzione da disco +
re-emit del widget pendente, test con fake-Pi condiviso, backend pre-crea la
sessione, model/thinking/provider per-sessione persistiti, settings Pi MVP.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 18:09:51 +02:00
marcopanandClaude Opus 4.8 c4d130828f fix(harness): remediation difetti review — gate↔CLI, D15, D7/D6, D14, robustezza
Implementazione del piano di remediation progressiva sui difetti emersi
dall'analisi dell'harness. Tutto verificato: 214 test Python (incl. L0 su
Postgres reale), 14 test JS del gate, ruff pulito.

Blocco 1 (CRITICA, integrazione gate↔CLI):
- phase advance: gate usa --auto + exit 6; reviewer_confirm kind:phase fa
  advance esplicito che applica i prerequisiti (prima non avanzava per le
  fasi a conferma umana).
- cte plan riceve i --name dal gate (param names); set-question con id
  posizionale; skill `tht search find`; nuovo comando `tht memory save-one`
  con dedup hash client-side in save_one_memory.

Blocco 2 (D15, stato post-rollback):
- campo `phase` su DecisionRecord + effective_decisions phase-aware per i
  subject "a nome" (cte_approved ecc.); _compute_promotions e finalize sulla
  vista effective; finalize confronta col piano CTE effettivo, non glob;
  `decision add --retracts` + comando `decision retract`.

Blocco 3 (D7 read-only + D6 manifest):
- assert_read_only su tutti e quattro i codepath (direct + REST);
- manifest author/summary/updated_at/updated_by/schema_version popolati +
  helper touch_manifest sulle mutazioni.

Blocco 4-5 (D14a/D14b):
- decision_min_phase data-driven via `emits:` in workflow.yaml;
- formula evidence: status auto, search_formulas, gruppo CLI `tht formula`,
  `search find --kind formula`, load_evidence_dir salta i .sql.md.

Blocco 6 (robustezza):
- taskdoc slice promoted_tables + bound enforced; report escaping/bound +
  rsplit note; filtro kind reader REST/direct; conteggio upserted robusto;
  guard REST run_query non-list; LSH disallineato -> LshIndexError.

Blocco 7 (pulizia):
- dead code gate e KIND_TO_TABLE morto rimossi; doc Postgres-only
  (README + connection.py).

Blocco 0 (parziale): test di compatibilità firma gate↔CLI
(tests/integration). Rinviati: fake-Pi runtime completo, artifact-gate da
disco (#23), parità eligibility REST/direct (#28), unificazione
reserved-labels (#30), memory_rejected da deselezione (#33).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 17:16:51 +02:00
marcopan daf33f77fe 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.
2026-06-27 16:14:46 +02:00
marcopan 386ec3b833 fix(harness): integrazione sessione L2 — _YamlModel to_yaml + config/tht.yaml symlink
Bug di porting emerso in L2 prep: tht session new falliva con
'AttributeError: SessionManifest has no to_yaml'. Lo stub locale _YamlModel in
session/models.py (placeholder pre-porting mschema) definiva solo
populate_by_name, senza i metodi to_yaml/from_yaml che store.py e session_cmd.py
usano. Aggiunti gli stessi metodi della controparte mschema (mantenendo
populate_by_name, necessario per db_schema alias='schema').

config/tht.yaml: symlink locale al workspace cliente attivo (psd.yaml). Il gate
chiama tht senza -c (default config/tht.yaml), quindi serve questo ponte per il
deployment per-cliente. Gitignored (per-cliente). .gitignore: + config/tht.yaml,
+ artifacts/.

Verifica: pytest 165 passed; tht session new crea sessione nel repo cliente;
pi vede i 3 tool reviewer_* (gate caricato); GLM 5.2 e' il model default di pi.
2026-06-27 15:41:21 +02:00
marcopan 0a9ebddaec feat(harness): Onda 0b — setup workspace per-cliente + build LSH (D14a validato)
Repo workspace per-cliente tht-workspace-psd/ (git separato): 35 evidence Thoth
frontmatturate (da etl/docs/evidence/, non tutto etl/docs), psd.yaml con path
assoluti ancorati al repo, THT_DOCS_ROOT -> radice repo cliente. README documeta
il deployment shape (2 checkout + .env).

LSH build sul DWH reale (REST, VPN): 75737 valori / 491 colonne eligible -> indice
175M nel repo cliente. tht lsh query 'ablazione' -> 8 colonne (D14a non-collapsing
validato end-to-end: procedure_type, descrizione_procedura, intervento, ...).

Correzioni al piano eseguite durante l'implementazione:
- aggiunto 'tht schema introspect' (prerequisito di lsh build, omesso nel piano)
- uso -c (il cmd ha --config, non --workspace residuo)
- path assoluti nel psd.yaml (paths sono relativi alla CWD, non al file YAML)
- evidence corretta: solo etl/docs/evidence/ (35), non tutto etl/docs (895)

Test L2 riallineato: WORKSPACE -> psd.yaml nel repo cliente (non tht-test.yaml),
index_dir -> paths.indexes/'lsh', nome -> db_schema (non letterale 'datawarehouse').
Bug latente del test (path mismatch) mai emerso prima: ora PASS invece di SKIP.

Verifica: pytest 165 passed, 5 deselected; pytest -m l2 test_value_grounding_real PASS.
2026-06-27 15:31:03 +02:00
marcopan 292048f777 feat(harness): language workspace param + skill riscritta in inglese (semantica completa)
Due cambiamenti interconnessi da user review:

1. language come parametro workspace (spec decisione 9):
   - Config.language (default 'en') + workspaces PSD con 'language: it'
   - Generalizza Thoth oltre l'italiano: descrizioni tabelle/colonne ed evidence
     sono nel workspace language; le istruzioni della skill restano in inglese
     (piu' affidabili per modelli piccoli, meno ambigue)

2. Skill riscritta in INGLESE preservando la semantica COMPLETA dell'originale
   (autocritica: la mia riscrittura precedente aveva perso ~10 vincoli precisi):
   - 'promuovere' ambiguo (3 accezioni: phase advance / recommend / memory promote)
     -> 'never advance a phase or record a decision without confirmation'
   - recuperati vincoli persi: choice-is-confirmation (no reviewer_confirm dopo
     reviewer_decide), reviewer_select SOLO per iterazione no-decision, messaggi
     auto-contenuti obbligatori, artefatto = superficie di decisione (gate rilegge
     da disco per CTE/SQL), candidati con provenienza+score non verita', opzione
     'leave ambiguity open', F1 passa lista completa non solo ultima
   - language contract esplicito (istruzioni EN, output nel workspace language)

Sottomoduli cte/memoria/rewriting/sql-generation in inglese, semantica tecnica
intatta (regole AV-SQL, dim_time trick, max 5 memorie solo 3 tipi riusabili).

Verifica: 0 residui nsp/chirone, tutti i tht <cmd> citati registrati, 165 passed.
2026-06-27 14:50:30 +02:00
marcopan de61034a8d feat(harness): riscrittura skill tht-sessione (F1-F8 + 4 sottomoduli)
Skill ex-novo che riflette Thoth (non copia di ChironeWp3):
- vocabolario widget-descriptor (reviewer_select/decide/confirm) invece di 'dialog native'
- D11 save-one in F2 (upsert mirato vs full resync)
- D14a value_grounded (LSH multi-colonna non collassa) + D14b concept_formula in F4
- D13 free-text e D15 rollback nelle discipline trasversali
- memory vive SOLO nel vectordb (drop registry, spec 5): save-one/promote senza registry
- F8 datamart onesto (stub NotImplementedError)

Sottomoduli cte/memoria/rewriting/sql-generation portati adattando nsp->tht, con
i vincoli precisi trasferiti fedelmente (max 5 memorie, solo 3 tipi riusabili,
CTE solo WITH senza SELECT, dim_time join non aritmetica, sql_final pulito).

Verifica: zero residui nsp/chirone/psd nella skill; ogni 'tht <cmd>' citato e'
registrato (correzione: 'tht formula retrieve' era inesistente -> riformulato in
'ricerca nelle evidence'). Suite: 165 passed.
2026-06-27 14:24:20 +02:00
marcopan 91a374492c feat(harness): port sql/cte/datamart/lsh cmd (Onda 4) — CLI completa F1→F8
Ultima onda CLI. 4 cmd portati con rename + grep-per-file (3 residui nsp nei messaggi
fixati). Nessun drift costanti phase in questi cmd.

La CLI tht e' ora COMPLETA: 14 gruppi di comandi (phase config schema session vector
memory search evidence db decision sql cte datamart lsh). tht --help li list tutti.
Suite: 165 passed.

Il loop skill->LLM->gate ora ha tutti i comandi che la skill chiamera'. Resta:
skill riscritta (S), setup pre-sessione (0b), sessione L2 manuale.
2026-06-27 14:16:35 +02:00
marcopan 99b01b0407 feat(harness): port memory/search/evidence/db/decision cmd (Onda 3.2)
5 cmd foglia portati con rename + drift fix:
- memory_cmd: portato col modello registry INTATTO (TODO marker per il drop registry
  decisione spec 5 — task separato, richiede L2 per validare il rewrite su vectordb)
- search_cmd: creata search_app sub-app (era funzione standalone in ChironeWp3),
  registrata come 'tht search find'
- evidence_cmd, db_cmd, decision_cmd: port verbatim

Drift fix decision_cmd: DECISION_MIN_PHASE.get(type,1) -> load_workflow().decision_min_phase(type).
Check grep-per-file: ~15 residui nsp/PSD_SSL_CA nei messaggi utente fixati (nsp <cmd>
-> tht <cmd>, nsp.yaml -> workspace yaml, PSD_SSL_CA -> THT_SSL_CA).

Suite: 165 passed. tht --help ora mostra 10 sottocomandi.
2026-06-27 14:14:48 +02:00
marcopan 159207a8f1 feat(harness): arricchisci metadata memory (subject/detail/rationale) — Onda 3.1 TDD
Correzione del gap ereditato (resosi NECESSARIO dal drop del registry, spec 5): il
metadata del VectorRecord memory ora porta subject/detail/rationale oltre a
type/session_id/tables/concepts. pack_metadata li serializza nel jsonb via
**record.metadata. search_similar proietta metadata completo -> la F2 ricostruisce
la decisione direttamente dall'hit, senza lookup registro.

L1: 4 test (subject/detail/rationale presenti, campi esistenti preservati,
no cross-contamination multi-record, save_one_memory propaga il metadata alla riga).
Suite: 165 passed.
2026-06-27 14:10:39 +02:00
marcopan 40b3bac6c6 feat(harness): port vector_cmd (Onda 2) — helper vector condivisi
Esporta make_embedder/open_store/open_searcher/require_vector_cfg usati da
memory/search/evidence cmd (Onda 3). 3 residui nsp nei messaggi fixati (grep-per-file).
2026-06-27 14:08:54 +02:00
marcopan 3120bdc192 feat(harness): port config_cmd + schema_cmd + session_cmd (Onda 1.3-1.4, radici CLI)
Le 3 radici intra-CLI, portate con rename psdwp3->tht + fix path import (session.phase
-> phase). Espongono gli helper condivisi: CONFIG_OPT (config_cmd), _load_config_or_exit/
physical_path/annotations_path (schema_cmd), session_dir/load_session_or_exit (session_cmd).

Drift phase fix in session_cmd (7 siti): MAX_PHASE -> wf.max_phase, PHASE_NAMES ->
wf.phase_name(), SCHEMA_LINKING_PHASE -> wf.schema_linking_phase(). Le vecchie costanti
non esistono piu' in tht.phase (sono metodi su Workflow dalla Onda -1/F2).

Check grep-per-file applicato: trovati e fixati 4 residui (config/nsp.yaml, 2x
'nsp schema introspect', 'Sessioni PsdWp3') che il sed psdwp3->tht non tocca. Lesson
del fix precedente applicata.

session_cmd importa sql_cmd lazy (dentro finalize_cmd) -> non si rompe finche' sql_cmd
(Onda 4) non sara' portato.

Suite: 161 passed. tht --help ora mostra phase, config, schema, session.
2026-06-27 14:08:08 +02:00
marcopan 16ec5a5138 fix(harness): 'datawarehouse Chirone' residuo in VENDORED.md (stessa causa Onda 0)
Stesso bug del precedente: VENDORED.md e' arrivato con Onda 0 (dopo l'Onda -1 che
aveva pulito i riferimenti cliente). Neutralizzato a 'il datawarehouse' (coerente
con le altre neutralizzazioni). Sweep completo tht/ ora vuoto per chirone/psdwp3/
policlinico/sandonato.
2026-06-27 14:02:39 +02:00
marcopan 1b8a13b864 fix(harness): nsp residuo nei moduli Onda 0 (lshindex msg + VENDORED.md)
User review ha trovato 2 residui 'nsp' sfuggiti al renaming: erano nei moduli
portati in Onda 0 (DOPO l'Onda -1 che aveva pulito), in messaggi utente/docstring
non in import. L'import-smoke di Onda 0 non li catturava (verifica solo import, non
stringhe). Corretti a tht: 'tht lsh build' (lshindex:61), 'tht schema introspect'
(VENDORED.md:25).

Lesson: dopo ogni port di file sorgente, grep di nsp su quel file, non solo import-smoke.
Suite: 161 passed, zero residui nsp nel codice.
2026-06-27 13:59:51 +02:00
marcopan a312746fc8 feat(harness): require_phase_or_exit + phase advance/reopen/show (Onda 1.2)
require_phase_or_exit: guard riscritto vs Workflow (load_workflow().phase_name invece
della costante PHASE_NAMES drift). Exit 1 se la sessione e' sotto soglia. Usato da
cte/decision/datamart cmd.

Comandi phase (portati + adattati al modello ThothII, non copia cieca):
- advance: persiste phase_approved; --auto exit 6 se la fase non e' completa
  (contratto col gate)
- reopen: persiste phase_reopened + teardown_to_phase degli artefatti oltre il target
- show: stato sessione (fase corrente, ultime decisioni)

session_dir helper tenuto qui (mirror di session_cmd) per evitare circular import.
_cfg() fa fallback a THT_WORKSPACE env finche' _load_config_or_exit (Onda 1.4) non
sara' portato.

L1: 4 test require_phase_or_exit (allow at/above, exit below, message con nome fase
dal workflow). Suite: 161 passed.
2026-06-27 13:15:12 +02:00
marcopan 37bb074efe feat(harness): Workflow.schema_linking_phase() (Onda 1.1, TDD)
Aggiunge il metodo che i cmd CLI useranno al posto della vecchia costante
SCHEMA_LINKING_PHASE (drift fix Onda 1). Ritorna il num della fase il cui
artifacts_out contiene schema_linking.json, default 5 se nessuna la dichiara.

L1: 4 test (fase reale F4, posizione arbitraria, default 5, artefatti multipli).
Suite: 157 passed.
2026-06-27 13:09:51 +02:00
marcopan 31552782c0 test(harness): L1 characterization tests per Onda 0 (sqlcheck, ctetest, execute)
44 test L1 sui 3 moduli backend con logica non banale (opzione 2 della user review):

- sqlcheck.validate_sql (16 test): parse/single-statement, read-only enforcement
  (INSERT/UPDATE/DELETE/CREATE/DROP/ALTER/TRUNCATE/GRANT rifiutati, WITH/UNION ok),
  forbidden functions (dblink default blacklist, custom set, allowed not flagged),
  object-existence (tabella inesistente, CTE non flaggata, perimetro promoted warning,
  colonna inesistente con alias). Documenta una limitazione reale: le funzioni
  aggregate specializzate (count/sum/coalesce) NON sono catturate dal name-matcher
  perche' sqlglot modella .name come argomento, non come nome funzione.

- ctetest (14 test): has_trailing_select (semantica controintuitiva: True = violazione),
  last_cte_name, build_test_sql, ledger I/O (load/append roundtrip, JSON-array e
  JSONL tolleranti, corrupt-ledger raise).

- execute._inject_limit (6 test): LIMIT iniettato quando assente (limit+1 per
  troncamento), rispettato quando presente, non iniettato su non-query, UNION/WITH ok.

Suite: 153 passed (109 + 44). Bonus: __psd_probe__ -> __tht_probe__ (riferimento
cliente neutralizzato in ctetest).
2026-06-27 13:04:34 +02:00
marcopan d857004f47 docs(plan): allinea piano alle 3 correzioni spec (drop registry, repo workspace, LSH)
- Task 3.2: nuovo Step 1b — drop funzioni registry da memory_cmd + tht/memory.py
  (load/save/update/delete/promote/reusable_promotions); promotion (F5) riscritta
  come upsert batch al vectordb; memory list/delete su vectordb (no registry).
- Skill F2/F5: drop riferimenti a 'memory promote + memory index' con registry.
- Onda 0b riscritta: repo workspace per-cliente separato (no copia in harness/),
  LSH scarica-tutti-i-valori-distinti (no 'campiona'), indice nel repo workspace cliente.
2026-06-27 12:52:58 +02:00
marcopan 20e3820bd7 docs(spec): drop registry memory + evidence repo separato + LSH scarica-tutto
Tre correzioni da user review:

5. Memory SOLO pgvector, niente registry. Il registry.jsonl di ChironeWp3 è vestigiale:
   una volta che il metadata del vectordb ha subject/detail/rationale (decisione 6), il
   registry non serve. Promotion (F5) = upsert diretto a vectordb. tht/memory.py non
   porta le 6 funzioni registry. 'Cancellare' = metadata.status='superseded' (audit
   trail; il writer e' upsert-only). Multi-workstation OK per costruzione.

7. Evidence: repo workspace separato per-cliente, NON dentro ThothII. ThothII e'
   generico; un repo tht-workspace-<cliente>/ contiene evidence/ + workspace YAML +
   indici LSH. Deploy = checkout ThothII + checkout workspace-cliente. Niente copia
   in harness/.

8. LSH: scarica TUTTI i valori distinti (non 'campiona'), costruisce MinHash+LSH
   dentro harness come preprocessing. Indice per-cliente (nel repo workspace cliente).

Sezione 3 punto 2 (F2) riscritta: save-one diretto, drop reference a promote/index
con registry. Arricchimento metadata ora 'obbligatorio' (non opzionale): senza
registry, il vectordb e' l'unica fonte. Residui nsp nei path spec corretti a tht.
2026-06-27 12:50:15 +02:00
marcopan ea6412fafc feat(harness): port backend Onda 0 — vendor, lshindex, sqlcheck, execute, rest/exec, ctetest, report, datamart
8 moduli leaf portati verbatim da ChironeWp3 con rename psdwp3→tht:
- vendor/thoth_lsh (MinHash/LSH, leaf puro datasketch+tqdm) + VENDORED.md
- lshindex/ (build/save/load/query, dipende vendor + LshConfig)
- sqlcheck/ (validate_sql, leaf ExecutionConfig+mschema)
- execute/ + execute/warnings (run_controlled/explain, leaf sqlglot+sqlalchemy)
- rest/execute + rest/explain (REST variants, dipendono execute+rest.client)
- ctetest (CTE test records, leaf sqlglot+pydantic)
- report (validation report rendering, dipende execute+sqlcheck)
- datamart (stub NotImplementedError)

Verifica: import smoke catena completa OK, pytest 109 passed. Deps (datasketch, sqlglot,
sqlalchemy, pydantic, requests, tqdm) già in pyproject. VENDORED.md neutralizzato
(riferimenti PsdWp3→Thoth).
2026-06-27 10:34:23 +02:00
marcopan fc5fbe6b65 refactor(harness): renaming prodotto tht (Onda -1)
Thoth (tht) è il prodotto, PSD è il cliente. Nessun riferimento al contesto
clinico nel codice.

Rinomine:
- comando+package nsp→tht (dir nsp/→tht/, 46 import, pyproject entry point)
- gate nsp-gate.js→tht-gate.js (+ rewrite token, relayIfNspFails→relayIfThtFails)
- workspace chirone.{example,test}.yaml→tht.{example,test}.yaml (generici)
- env THOTH_→THT_ (19 var) + NSP_ stragglers (NSP_HARNESS_ROOT, NSP_SESSION)
- commenti/docstring chirone/psdwp3/policlinico neutralizzati ('the reference
  implementation', 'the DWH')

Aggiunto [tool.setuptools.packages.find] include=['tht*'] (necessario: l'auto-
discovery rompeva con tht/ + workspaces/ come top-level multipli).

.env operatore aggiornato in-place (prefissi THT_, valori preservati, gitignored).

Verifica: pytest 109 passed, npm test 14 pass, tht phase meta --json OK, zero
residui nsp/THOTH_/NSP_/chirone nel package.
2026-06-27 10:33:16 +02:00
marcopan 0dcc0246dc docs(plan): tht porting CLI + skill — implementation plan
Piano da spec 2026-06-27-cli-port-completo-skill-riscritta-design.md.
Struttura in onde: -1 (renaming tht isolato), 0 (backend), 0b (evidence+LSH setup),
1 (radici CLI + phase drift), 2 (vector), 3 (foglia + metadata memory), 4 (SQL/CTE),
S (skill riscritta), L2 (sessione manuale).

TDD per logica nuova (schema_linking_phase, require_phase_or_exit, arricchimento
metadata memory); port+smoke+commit per i port verbatim (logica gia' validata in
ChironeWp3). pytest verde (109 passed) a ogni task come gate di regressione.

Self-review: copertura spec completa (11 decisioni), nessun placeholder, type
consistency verificata. Gap residui onesti: circularita' session_cmd<->sql_cmd
(risolto con import lazy), RPC server mancanti (fuori piano codice), L2 manuale.
2026-06-27 10:13:44 +02:00
marcopan 46dec04299 docs(spec): renaming prodotto tht come Onda -1 isolata
Renaming richiesto in user review: Thoth (tht) e' il prodotto, PSD e' il cliente.
Nessun riferimento al contesto clinico nel codice.

Decisioni 8-10:
8. Rinomine: nsp->tht (comando+package+46 import), nsp-sessione->tht-sessione,
   nsp-gate.js->tht-gate.js, chirone.*->tht.{example,test}.yaml (generici; il deploy
   cliente crea il suo psd.yaml non-committato), THOTH_*->THT_* env.
9. Neutralizzazione riferimenti chirone/psd/policlinico/sandonato nei commenti/
   docstring (resi generici o rimossi). Il contesto cliente vive SOLO nei file di
   config reali (.env gitignored, workspace cliente non-committato).
10. Onda -1 isolata PRIMA del porting CLI: pytest resta 109 passed (rename verificato
    da solo), poi il porting avviene col nome nuovo (niente doppio lavoro).

Ordine esecuzione aggiornato a 7 step (Onda -1 prima di tutto). Self-review:
corretti i residui incoerenti di nsp/chirone nello spec (righe che usavano ancora
i nomi vecchi dove dovevano essere tht). Residui rimasti sono legittimi (descrivono
il renaming o il path sorgente one-shot della copia evidence).
2026-06-27 10:00:54 +02:00
marcopan 19c646bb21 docs(spec): indipendenza ChironeWp3 + registro memory locale + evidence in ThothII
Tre decisioni su dipendenze implicite (domanda user review):

4. Indipendenza da ChironeWp3 (proprieta' architetturale): quando ThothII e' pronto,
   il server non deve avere ChironeWp3 — solo Supabase (RPC SECURITY DEFINER nel DB,
   indipendenti dal codice app) + cartella evidence (dentro ThothII). Verificato:
   codice ThothII non ha riferimenti ChironeWp3/psdwp3, .env non punta a path chirone.

5. Registro memory: locale per-workstation (registry.jsonl in harness/artifacts/memory/
   su ciascuna). La F2 legge dal vectordb condiviso e, grazie all'arricchimento metadata
   (decisione 6), ricostruisce la decisione senza lookup registro. Il registro serve
   solo per la F5 (promozione: locale + indicizza condiviso). Multi-workstation OK.

7. Evidence: dentro ThothII. La cartella (229 markdown statici curati, 11M, nessun ETL)
   si sposta in harness/evidence/. ThothII self-contained. Nota: revisionare per PII
   prima di committare.

Onda 0b aggiornata: cp evidence in harness/evidence/ invece di puntare path esterno.
2026-06-27 09:51:01 +02:00
marcopan 5e9553fde8 docs(spec): arricchisci metadata memory vectordb (no lookup registro)
Gap trovato in user review: la tabella vectors.memory aveva metadata
{type,session_id,tables,concepts} — mancavano subject/detail/rationale strutturati,
quindi l'hit vettoriale non bastava per applicare la memoria. ChironeWp3 faceva
lookup nel registro canonico via mem_id; stesso difetto ereditato in ThothII.

Decisione: arricchire il metadata del VectorRecord memory con subject/detail/rationale
(in memory_vector_records, nsp/memory.py). pack_metadata (rest_writer.py:26) li
serializza gia' nel jsonb via **record.metadata. Nessuna modifica al writer RPC,
nessuna modifica allo schema DB. search_similar proietta gia' metadata completo ->
la F2 ricostruisce la decisione direttamente dall'hit, senza lookup registro.

Momento ideale: tabella memory vuota, niente re-indicizzazione. Aggiunto come task
esplicito in Onda 3 (dove si porta memory_cmd). Registro globale resta source-of-truth
per la promozione (F5), ma la F2 legge solo dal vectordb.
2026-06-27 09:43:56 +02:00
marcopan 9f14a13594 docs(spec): aggiungi Onda 0b — setup pre-sessione evidence + LSH build
Buco trovato prima della user review: lo spec claims D14 value-grounding ed
evidence-based F4, ma non setup né evidence né l'indice LSH. Senza, la sessione
L2 girerebbe degradata (solo segnali vettoriali) e i claim sarebbero falsi.

Onda 0b (dopo Onda 0 + 4, prima della sessione L2):
- Evidence: cablare THOTH_DOCS_ROOT=/Users/mp/Chirone/chirone/etl/docs nel .env +
  blocco evidence nel chirone-test.yaml. La cartella esiste già.
- LSH: nsp lsh build sul workspace chirone-test (one-shot, richiede VPN + Ollama).
  Verifica: nsp search ritorna match multi-colonna + test_value_grounding_real
  smette di skip-piare.

Ordine esecuzione aggiornato (6 step), D14a value-grounding marcato 'sì (se Onda 0b)',
nsp lsh build tolto dal fuori-scope (ora dentro).
2026-06-27 09:38:38 +02:00
marcopan 96499e70d6 docs(spec): porting CLI completo + riscrittura skill nsp-sessione
Design approvato in brainstorming per sbloccare il loop skill→LLM→gate (oggi
non testabile: 11/12 cmd CLI mancanti + skill assente).

Decisioni chiave:
- Scope F1→F8 completo (tutti i cmd + 3 cluster backend + skill riscritta)
- Drift phase.py: riscrittura diretta dei 12 siti cmd che usano le vecchie
  costanti (MAX_PHASE/PHASE_NAMES/SCHEMA_LINKING_PHASE/DECISION_MIN_PHASE) ->
  load_workflow() + metodi Workflow. Niente wrapper.
- Skill: riscrittura completa ex-novo che riflette ThothII (widget-descriptor,
  D11 save-one, D13 free-text, D14 value-grounding/formula, D15 rollback),
  prendendo spunto da ChironeWp3 ma non copiandola.

5 onde topologiche (backend -> radici CLI -> vector -> foglia -> SQL/CTE).
Test: pytest verde a ogni onda + import smoke; sessione L2 manuale su domanda
complessa (cardioversione + ablazione same-year) che esercita F4 complesso,
D14, F6 CTE.

Spec self-reviewdato: corretta ambiguità su save-one (discriminante = comando,
non profilo dedotto dal modello) e nota onesta su F2 (memory azzerata = D11
validato in seconda sessione).
2026-06-27 09:32:42 +02:00
marcopan e58f6c092e fix(harness): workspace + write-URL + L2 tests per accesso REST reale
Bug trovato provando la connessione reale col .env: il write endpoint vive su un
PATH DEDICATO /vector/write/v1/ (non /vector/v1/), e il modello Config ha write_rest/
vector_write_rest a TOP-LEVEL (non nidificati in vector_db).

- .env.example: aggiunge THOTH_VEC_WRITE_REST_URL (path dedicato del writer, con
  avviso che le due chiavi valgono su path separati).
- workspaces/chirone-test.yaml: riscritto allineato a chirone.example.yaml + config.py
  (vector_rest/vector_write_rest top-level; write_rest punta a THOTH_VEC_WRITE_REST_URL).
- tests/l2/*: corretti gli accessi strutturali (ws.vector_write_rest invece di
  ws.vector_db.write_rest; ws.vector_rest invece di ws.vector_db.rest).
  test_value_grounding_real skip-when-import-fails su nsp.lshindex (modulo deferred da B3).

Verificato end-to-end: save_one_memory (embeddings -> writer REST /vector/write/v1/
-> upsert pgvector -> read-back reader) PASSED. Suite L0+L1: 109 passed. Suite L2:
4 passed, 1 skipped (lshindex deferred).

Nota operativa: THOTH_SSL_CA va lasciato VUOTO sulla workstation (cert GoDaddy
pubblico in certifi). I campi direct-transport (THOTH_DB_*, THOTH_VEC_PASSWORD)
sono obbligatori per il modello ma inutilizzati in transport=rest: riempiti con
dummy nel .env locale (come faceva ChironeWp3).
2026-06-27 08:20:36 +02:00
marcopan 276717005d fix(harness): drop THOTH_SSL_CA from REQUIRED_L2 + isolate profile in workspace test
Two fixes found while unblocking the L2 setup:

1. conftest: THOTH_SSL_CA is NOT an L2 prerequisite. The DWH endpoint presents a
   public cert (*.policlinicosandonato.it, signed by GoDaddy), already in the
   certifi bundle, so the REST clients validate TLS with verify=True -- no CA file
   needed. The ssl_ca line was commented out in ChironeWp3's nsp.yaml too.

2. test_workspace: the profile-default assertion collided with the operator's real
   harness/.env once load_dotenv (D3) started injecting THOTH_PROFILE into the
   process env. The test now dels THOTH_PROFILE to assert the actual *default*
   (server), regardless of what the operator set in .env.

Suite: 109 passed.
2026-06-27 06:45:00 +02:00
marcopan 50d5f9c9cf docs(harness): README + workflow editing + testing guide (D6)
README: install, configure (.env + workspaces/), the workflow, run inside Pi, the
three-level test commands, layout, references.

docs/workflow-editing.md: how to edit workflow.yaml (add/reorder/merge/skip phases,
advance kinds, prerequisite predicates, decision_min_phase derivation, artifacts_out
+ teardown) -- referencing spec §5.3. Emphasizes no mirrored constants (the F2 point).

docs/testing.md: the honest L0/L1/L2 split in plain language -- what each covers and
does NOT. States the headline plainly: the skill->LLM->gate loop has NO automated
regression coverage (L2 only, pre-release). Documents the fake-Pi follow-up as the
gap-closer. Security note on keys (.env gitignored, never logged, rotate leaked keys).
2026-06-26 23:20:06 +02:00
marcopan c861a0df9e test(harness): L2 tests -- ablazione session + value grounding + memory save-one (D4, D5)
Pre-release, non-deterministic tests (marker l2, skipped without .env + VPN). They
close the gaps L1 leaves open: real value grounding on the live schema, real memory
save-one upsert to pgvector, and the full GLM 5.2 -> gate conversation on the
'ablazione' question (which exercises D14 value grounding + formula on a multi-
column case + the gate glue L1 cannot reach).

workspaces/chirone-test.yaml points at the remote endpoints (DWH read-only +
pgvector dual-key, TLS self-signed); secrets via ${THOTH_*}.

- test_session_ablazione: precondition checks (workspace loads, env present, pi on
  PATH) + the documented manual run protocol (human-in-the-loop; scripted-answers
  variant is a follow-up). Default run skips cleanly.
- test_value_grounding_real: 'ablazione' grounds to multiple columns on the real
  schema (D14a non-collapsing), needs a built LSH index.
- test_memory_save_one_real: save_one_memory upserts one row via the writer key
  (D11) and search_similar retrieves it via the reader key.

Operator runs before release (pytest -m l2). Default run: 109 passed, 5 skipped.
2026-06-26 23:18:34 +02:00