Commit Graph
100 Commits
Author SHA1 Message Date
marcopan ebdd3aa2c5 fix(deploy): unify backend URL policy 2026-07-12 00:54:39 +02:00
marcopan a3a266fd81 fix(deploy): close container final review 2026-07-12 00:44:39 +02:00
marcopan 0ca6346f75 fix(deploy): isolate compose smoke resources 2026-07-11 22:16:51 +02:00
marcopan 767df63a33 feat(deploy): add portable external-service stack 2026-07-11 22:12:21 +02:00
marcopan 715de6649b fix(docker): harden frontend runtime config 2026-07-11 22:03:24 +02:00
marcopan 3d939426b1 build(docker): add runtime-configured frontend image 2026-07-11 21:57:53 +02:00
marcopan 31023f9e7a build(docker): lock core runtime dependencies 2026-07-11 21:50:30 +02:00
marcopan 77923e501f build(docker): add core application image 2026-07-11 21:43:28 +02:00
marcopan 3ac0623247 fix(backend): make data root config authoritative 2026-07-11 21:35:54 +02:00
marcopan c6c00c336a feat(backend): support container runtime paths 2026-07-11 21:32:33 +02:00
marcopan a0daa319ca fix(storage): contain logical corpus root 2026-07-11 21:26:47 +02:00
marcopan 7f3f6f7ce7 fix(storage): harden portable path diagnostics 2026-07-11 21:25:03 +02:00
marcopan eacb139e22 feat(storage): resolve portable workspace roots 2026-07-11 21:21:06 +02:00
marcopan 3e2ad7955c fix(adapter): close final foundation review 2026-07-11 21:14:32 +02:00
marcopan 45d57756aa fix(core): restore adapter command behavior 2026-07-11 21:04:53 +02:00
marcopan a35efa16de fix(core): preserve adapter command contracts 2026-07-11 21:00:50 +02:00
marcopan dbbab6d005 refactor(core): route integrations through adapter factory 2026-07-11 20:52:41 +02:00
marcopan 1e0911bb6a feat(config): add typed resource schema 2026-07-11 20:43:08 +02:00
marcopan fe8d70da47 fix(vector): separate write transport fields 2026-07-11 20:35:57 +02:00
marcopan ff4d662aba refactor(vector): define store contract 2026-07-11 20:24:14 +02:00
marcopan f6302b31dd fix(dwh): validate adapter limits strictly 2026-07-11 20:19:05 +02:00
marcopan 216984aac8 fix(dwh): align adapter sampling contract 2026-07-11 20:14:23 +02:00
marcopan 717e5ecced refactor(dwh): adapt direct and REST transports 2026-07-11 20:03:31 +02:00
marcopan a4eb6cc9e5 refactor(dwh): define adapter contract 2026-07-11 19:57:39 +02:00
marcopan e02e61ea35 chore: ignore local worktrees 2026-07-11 19:54:05 +02:00
marcopan ef46a4ca09 docs: add portable deployment implementation plans 2026-07-11 19:49:26 +02:00
marcopan 586180eaa1 docs: define portable deployment architecture 2026-07-11 19:39:43 +02:00
marcopanandClaude Opus 4.6 1e4bc11418 fix(embed): fast-fail + auto-restart Ollama on solved-search hang
Embeddings timeout was 120s, causing multi-minute hangs when Ollama was
down during F4/F6/F7 solved-search. Now: connect_timeout=5s across all
HTTP clients (REST + Ollama), read_timeout reduced to 30s for embeddings,
and OllamaEmbeddings auto-restarts the server on ConnectionError before
degrading gracefully.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-07 19:49:55 +02:00
marcopanandClaude Opus 4.6 893ad99594 fix(gate): auto-finalize session after last phase approval
The model sometimes stops after receiving 'Fase approvata' without calling
`tht session finalize`, leaving the session open. Now the gate itself calls
finalize after advancing the max phase (F8), making session closure
deterministic regardless of model behavior.

- reviewer_confirm kind:phase: after phase advance at max_phase, gate calls
  `tht session finalize <session>` (best-effort with recovery message)
- SKILL.md updated: model no longer needs to call finalize itself
- Tests: 2 new JS tests (auto-finalize at max phase; no-finalize at non-max)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-07 18:47:19 +02:00
marcopanandClaude Fable 5 ade6838182 docs: add efficiency-levers setup and current-run instructions
- PROJECT_STATE.md: section on three deployed levers (FK annotations, context-pack, recap v2)
  with setup instructions for new workspaces; psd pre-configured
- README.md: one-time setup for workspace (tht schema suggest-fks); note that levers 2+3 auto-activate
- Updated 'How to run' with explicit command and prereq checklist
- Last-updated timestamp: 2026-07-08

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 17:43:51 +02:00
marcopanandClaude Fable 5 e24b41b156 feat(opt): three efficiency levers for NL→SQL workflow
Lever 1: Join-graph via FK logics in annotations + suggest-fks command
  - TableAnnotation.foreign_keys field stores curated logical FKs (DWH has no FK constraints)
  - tht schema suggest-fks: mine from approved SQL, heuristics (time_key → dim_time),
    same-name discovery + explicit --assume flag for multi-owner PKs
  - mschema renders 【Foreign keys】 section populated; validation in merge.py
  - SKILL.md F4 now reads FKs from mschema-text, no custom data_time_key logic

Lever 2: Context-pack consolidation at kickoff (tht search pack)
  - Single embedding of question, reused for schema + evidence + solved searches
  - One command: tht search pack <question> --session <id> → retrieval_pack.md
  - Graceful degradation when Ollama/vector store unreachable (exit 0, empty sections)
  - SKILL.md F1 prescribes as first call; reduces model thinking turns via pre-retrieval

Lever 3: Phase-summary recap v2 auto-construction from session ledger
  - tht session show --json includes full decisions ledger
  - tht phase meta --json exports 'emits' (substantive decision types per phase)
  - Gate appends deterministic 【Decisioni registrate in questa fase】 section (appendLedgerSection)
  - Model authors only summary + checks; recap table comes from persisted state (exact by construction)
  - SKILL.md Disciplina 6: brief model output, gate fills the rest

Tests: 358 Python (including 10 FK + 3 pack + 1 session-ledger tests) + 111 JS gate tests, all pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 17:43:08 +02:00
marcopanandClaude Fable 5 87e875bc81 feat(replay): extract reviewer_schema_linking gates + de-slug question fallback
extract.mjs now emits a schema-linking ui_request descriptor (columns rendered
from the model's suggested_columns, since the live catalog enrichment needs the
DWH) and parses the reviewer's "N tabelle" outcome; when neither the manifest
nor question.md is reachable, the NL question is approximated by de-slugging
the session id. replay.json regenerated from the 2026-07-06-175012 session
(18 answered gates, includes the F4 schema-linking gate).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 16:04:00 +02:00
marcopanandClaude Fable 5 34aeda006e perf(f1): cache-guard schema introspect + F1 toolbox in skill (~-5 min per session)
Transcript analysis (session 2026-07-06-175012, GLM 5.2) showed F1 at 567s:
182s wasted on a useless `tht schema introspect` (re-introspecting the remote
DWH although physical.yaml was already materialized) plus ~220s of model
thinking inflated by ~7 exploratory turns (--help/find/cat). The actual
searches cost ~15s; reviewer gates (~145s, untouched) are the quality contract.

- schema_cmd.py: introspect now exits 0 with "OK (cache)" in ~1s when
  physical.yaml exists; --refresh forces the real re-introspection.
  Deterministic cross-model guarantee, verified live on psd (163 tables, 1.2s).
- SKILL.md: F1 toolbox (only `tht search find` + `tht schema render`; no
  introspect/--help/filesystem browsing; batch all searches in one turn);
  F4 step 1 is render-only with a one-shot introspect fallback.
- tht-gate.js: `tht schema introspect ... --refresh` added to FORBIDDEN
  (maintenance stays shell-only, never in-session).
- tests: 4 new pytest cases (cache hit placement proven with fake credentials,
  refresh bypass, corrupt-catalog fall-through, render fallback message) and
  2 gate anti-bypass JS cases.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 16:02:45 +02:00
marcopanandClaude Opus 4.6 0cad04a8d8 docs(vector): add write-RPC migration instructions (existing_vector_hashes + upsert_vector_records)
The original doc only covered search_similar; the write functions also need
solved_question in their kind whitelist for the memory table.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-07 15:15:55 +02:00
marcopanandClaude Fable 5 3d206bf3ef docs(plans): active-memory implementation plan (promotion gate + solved questions)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 14:38:25 +02:00
marcopanandClaude Fable 5 a26f16ad79 feat(vector): server-side kinds filter for search_similar (legacy fallback) + graceful solved-search degrade
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 14:23:28 +02:00
marcopanandClaude Fable 5 8d427a2ccb fix(gate): actionable recovery for mid-promotion failures; truthful solved-index copy; fast-follow notes
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 14:07:00 +02:00
marcopanandClaude Fable 5 8af0552dcc docs(skill): prescribe solved-question recall in F4/F6/F7; refresh PROJECT_STATE
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 13:54:42 +02:00
marcopanandClaude Fable 5 4c4099df09 fix(finalize): report the unchanged (no-upsert) solved-question case instead of staying silent
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 13:50:53 +02:00
marcopanandClaude Fable 5 2742a1fc42 feat(finalize): auto-index the question->SQL pair (best-effort, never blocks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 13:48:02 +02:00
marcopanandClaude Fable 5 1f429b6b35 feat(cli): tht memory solved-index / solved-search (question->SQL exemplars)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 13:43:52 +02:00
marcopanandClaude Fable 5 c0324c127a feat(solved): solved_question vector kind + one-row upsert (D11 pattern)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 13:38:10 +02:00
marcopanandClaude Fable 5 ae89957175 docs(skill): prescribe the F8 memory-promotion gate; drop optional D11 notes
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 13:34:04 +02:00
marcopanandClaude Fable 5 e25ba5126b feat(gate): reviewer_memory_promote — deterministic F8 memory-promotion gate
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 13:30:35 +02:00
marcopanandClaude Fable 5 bf7e850e6b feat(memory): filter gate-declined candidates from promotion preview
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 13:26:59 +02:00
marcopanandClaude Fable 5 cadbdf177a feat(memory): memory_promoted/memory_promotion_declined decision types (F8 emits)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 13:22:07 +02:00
marcopanandClaude Fable 5 ccc4f4c9dd docs: refresh PROJECT_STATE.md (review gates v2, F4 curation, live E2E + spinner fix)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 11:39:54 +02:00
marcopanandClaude Fable 5 2410f01b34 fix(bridge): forward Pi agent_end so the spinner stops at workflow completion
The FE derived 'working' purely as activeSession && !pendingWidget, so the
final workflow turn — the only one that ends without a follow-up gate —
left the spinner on forever (observed live: 21592s after F8 approve).

- SessionBridge maps Pi's agent_end -> SSE system_event {event: agent_end}
- PiProcessManager notifies the client (info error + synthetic agent_end)
  when the child dies unexpectedly; expected teardowns stay silent
- sessionStore tracks agentActive (on: user entry/text_delta/ui_request,
  off: agent_end); AppShell working now requires it; resume sets it
  optimistically

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 10:14:43 +02:00
marcopanandClaude Fable 5 b59b57c4e6 fix(review-gates): green success badges, null-safe preview rows, optional section items
- Extract shared statusBadgeClass() helper (src/viewers/statusBadge.ts) so
  SqlViewer, CteResultViewer and PhaseSummaryViewer can't drift: ok/success/
  passed/promoted render green (--success), warn renders amber (--warning),
  error/failed stay destructive red, everything else stays neutral outline.
  Previously CteResultViewer/PhaseSummaryViewer mapped "ok"/"promoted" to the
  default badge variant, which is bg-primary (GSD red) — success states
  rendered red.
- enrich.js: buildCteResultV2 now falls back preview.rows to [] instead of
  null when last_test.preview_rows is missing (pre-upgrade ok records), and
  CteResultViewer reads result.preview?.rows?.length with a null-safe
  fallback so it degrades to the "No preview rows" empty state instead of
  crashing.
- PhaseSummaryViewer: section.items is optional (model-authored sections can
  be prose-only); render (section.items ?? []) instead of crashing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 01:37:35 +02:00
marcopan b089482b8d chore(replay): regenerated replay.json fixture (v2 artifact-gate payloads)
Regenerated demo fixture output with augment-schema-linking.mjs +
augment-review-gates.mjs applied, so the F6 cte_plan gate, CTE 1 cte_result
gate, and Fase 5 phase-summary gate carry v2 schema_version payloads and
render via CtePlanViewer/CteResultViewer/PhaseSummaryViewer in the replay
server. Regenerable; committed so the replay server serves it without a
build step.
2026-07-07 01:19:49 +02:00
marcopan 4042d0b44d feat(replay): fixtures + augment script for v2 artifact-gate viewers
Add cte-plan-fixture.json, cte-result-fixture.json, and
phase-summary-fixture.json — realistic Italian-language payloads for the
cardiology DWH replay session, conforming exactly to contracts.md (A/B/C).

Add augment-review-gates.mjs (pattern of augment-schema-linking.mjs): finds
the F6 cte_plan gate, first CTE 1 cte_result gate, and Fase 5 phase-summary
gate by title regex and swaps in the v2 artifact.data, so CtePlanViewer,
CteResultViewer, and PhaseSummaryViewer render in the offline replay.
Idempotent; exits 1 if an expected gate is missing.

Document the augment scripts and re-extract note in tools/replay/README.md.
2026-07-07 01:19:44 +02:00
marcopanandClaude Fable 5 1c97289ed8 feat(frontend): v2 artifact viewers for cte_plan/cte_result/phase
Add CtePlanViewer, CteResultViewer, and PhaseSummaryViewer to render the
structured v2 payloads (schema_version: 2) the harness now emits for
artifact-gate widgets, per contracts.md. Extract PreviewGrid from
ResultsPanel as a reusable AG Grid component shared by CteResultViewer.
ArtifactView dispatches to the new viewers on a schema_version/shape
guard, falling back to the existing legacy renderers unchanged for
older sessions and replay fixtures.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 00:57:20 +02:00
marcopanandClaude Fable 5 3ad93cd02f feat(gate): deterministic v2 review-gate payloads (cte_plan/cte_result/phase)
The tht-gate.js reviewer_confirm now builds structured v2 artifacts before the
widget so the reviewer approves gate-derived data, not raw model text:

- new pure modules gate/artifact-contracts.js (soft validators, {ok,errors},
  legacy-passthrough) and gate/enrich.js (index/description enrichment,
  buildCteResultV2 fusing thin model data with `tht cte info`, phase enrichment)
- cte_plan v2: validate + enrich + persist via `tht cte plan --name … --doc -`
  (names derived from data.ctes[]); legacy `names` param kept as fallback
- cte_result v2: rebuild from `tht cte next`/`tht cte info` (sql + preview from
  the persisted test record); null/error last_test -> actionable textResult
- phase v2: soft-validate + fill phase from meta + catalog descriptions
- prepareReviewerArguments coerces artifact.data too (GLM double-stringify);
  legacy markdown strings pass through unchanged
- SKILL.md: Phase 6 cte_plan payload A + thin cte_result guidance; Discipline 6
  payload C example; Discipline 7 reworded for gate-rebuilt cte_result

Legacy (non-v2) paths unchanged. TypeBox stays Type.Any() for artifact.data;
validation is soft (textResult) so models self-correct instead of looping.
All 102 gate JS tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 00:42:48 +02:00
marcopan 9b4f6b9804 feat(harness): persist CTE preview rows, add tht cte info, --doc for cte plan
WS1 of review-gates-v2: gives the JS gate (WS2) deterministic data to build the
cte_result v2 payload.

- CteTestRecord gains optional preview_rows (JSON-coerced, truncated cells);
  test_cmd populates it from the bounded result rows.
- New read-only `tht cte info <name> --session <id> [--json]`: plan
  index/total, persisted .sql, cte_plan_doc.json entry (if any), last
  CteTestRecord. Exits 1 with a clean stderr message on missing
  session/plan/name/sql.
- `tht cte plan --doc -` validates a chain-doc JSON (ctes[].name must match
  --name, same order) and writes it to cte_plan_doc.json; cte_plan.json stays
  a plain list[str] (load-bearing for tht.phase.next_cte). --doc is optional.
2026-07-07 00:23:50 +02:00
marcopanandMarco Pancotti 7491e8c3ac chore(replay): regenerated replay.json fixture (phase tags + F4 schema-linking gate)
Regenerated demo fixture output of extract.mjs (WorkflowBar phase tags) with the
F4 gate-7 augment applied (tools/replay/augment-schema-linking.mjs, on the F4
branch). Regenerable; committed so the replay server serves it without a build step.
2026-07-06 23:29:49 +02:00
marcopanandMarco Pancotti 9403147c98 feat(replay): infer workflow phase from gate title so WorkflowBar lights the right dot
extract.mjs: inferPhase() maps gate titles ("F1 — …", "Fase 3 completata …") to F1..F8;
server.mjs: carries the inferred phase through the replayed ui_request stream.
2026-07-06 23:29:49 +02:00
e9b2934ef7 style(frontend): look&feel v2 refinements — 70% gate modal, structured cards, mono labels
- ArtifactGateWidget: gate modal 90%→70% of viewport, larger heading, more padding.
- ArtifactView StructuredValue: depth-aware hierarchy (top-level hairline dividers,
  warm bg-muted card surfaces + shadow for object-array items).
- index.css: .thot-label micro-labels switched to the mono register (SF Mono) with
  tightened tracking, distinguishing labels/meta from sans body prose.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:29:49 +02:00
9fe1c9321b feat(frontend): suggested-first ordering + filter box in the schema-linking columns modal
Wide tables (e.g. 116 columns, 3 suggested) made curation a scroll hunt. Now the
modal lists suggested columns first (stable sort on the descriptor flag, so
toggling never reorders rows) and adds a filter box matching name + description,
with a "shown/total" count. Selection stays keyed by column name, so the response
column order is unchanged (catalog order). Applies to read-only (excluded) tables too.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:29:21 +02:00
marcopanandMarco Pancotti d942635085 fix(f4): harden schema-columns enrichment + ValidationError guard + staged-helper note 2026-07-06 23:25:00 +02:00
marcopanandMarco Pancotti 3ed570ee60 feat(tht): promoted_columns_for helper (curated column set) 2026-07-06 23:25:00 +02:00
marcopanandMarco Pancotti ad5a4d938c test(backend): pin schema-linking structured response passthrough 2026-07-06 23:25:00 +02:00
marcopanandMarco Pancotti bd63e3194f docs(skill): Phase 4 uses reviewer_schema_linking; honor curated output columns 2026-07-06 23:25:00 +02:00
ad788278dd feat(gate): reviewer_schema_linking tool with per-column curation + deterministic sync
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:25:00 +02:00
marcopanandMarco Pancotti 559f52e26e feat(gate): buildSchemaLinkingRequest descriptor builder 2026-07-06 23:25:00 +02:00
00365cc6e6 feat(tht): sync-schema-linking projects F4 ledger into schema_linking.json
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:25:00 +02:00
marcopanandMarco Pancotti 1df5d40d05 feat(tht): column_promoted/column_excluded decision types (F4) 2026-07-06 23:25:00 +02:00
marcopanandMarco Pancotti 9339a8272b feat(tht): schema columns reader (name/description/type/pk) from catalog 2026-07-06 23:25:00 +02:00
marcopanandMarco Pancotti bfb54922f7 feat(replay): F4 schema-linking fixture + augment script from real catalog 2026-07-06 23:25:00 +02:00
marcopanandMarco Pancotti 32b8e78032 feat(frontend): register schema-linking widget + response summary 2026-07-06 23:25:00 +02:00
marcopanandMarco Pancotti b6397bd965 fix(frontend): English chrome labels in schema-linking gate (Promote/Exclude/Columns) 2026-07-06 23:25:00 +02:00
marcopanandMarco Pancotti 40a0395a70 feat(frontend): schema-linking gate widget with staged column curation 2026-07-06 23:25:00 +02:00
marcopanandMarco Pancotti 1d877d98ec feat(frontend): schema-linking types + columns modal 2026-07-06 23:25:00 +02:00
9de87d2d51 docs: Plan 2 (harness + persistence + live) for F4 column curation
TDD tasks: schema columns catalog reader, column_promoted/excluded ledger
types (+ F4 emits), deterministic sync-schema-linking projection, the
reviewer_schema_linking gate tool (+ stringified-tables handling), SKILL.md
Phase 4 guidance, backend passthrough test, promoted_columns_for helper, and
live end-to-end verification. Hard SQL enforcement documented as a non-goal
(fragile through CTEs); curated columns are persisted + honored softly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:25:00 +02:00
106a0de047 docs: Plan 1 (frontend + contract + replay) for F4 column curation
Bite-sized TDD tasks: schema-linking types + columns modal, gate widget with
staged per-table column selection, registry/summary wiring, and a replay
fixture generated from the real physical.yaml catalog. Offline-verifiable in
the replay server; harness wiring is Plan 2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:25:00 +02:00
94d171ddf1 docs: design for F4 schema-linking per-table column curation
Reviewer curates, per promoted table, which columns to use over the full
catalog list (suggested pre-selected + bold); selection persists into
schema_linking.json + the decision ledger and softly guides SQL generation
(Option 1). Dedicated structured schema-linking gate widget (Approach A),
staged commit, inline gate + single columns modal. Hard SQL enforcement is
an explicit follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:25:00 +02:00
marcopan e11ffecfc4 feat(frontend): richer gate bodies + replay-friendly session exit
Improves how reviewer gates render their content, and adds two small
hooks that make the frontend cooperate with the standalone replay server
(also useful as generic primitives).

Gate body rendering:
- IntroBody: gate intros now render paragraphs plus real bullet lists
  with a hanging indent and emphasised bullet lead term, filling the
  card width (no narrow measure cap). Backed by introFormat (parser) +
  IntroBody (renderer), with tests.
- GateArtifactBody: artifact-review gates whose artifact is a bare file
  reference (e.g. {kind:"phase", data:{file:"question.md"}}) now fetch
  the referenced session document and render its full content, instead
  of showing the file reference as text. Falls back to ArtifactView for
  inline-content artifacts and unmapped files. Backed by gateArtifact
  (resolver) with tests. ArtifactGateWidget passes sessionId through.
- SelectWidget renders intros via IntroBody.

Replay-friendly session exit:
- AppShell: a system_event {event:"session_exit"} now triggers
  stopSession(), returning to the landing view. Generic primitive (the
  real backend can emit it too); used by the replay server's "Esci".
- SessionMenu: the ⋮ trigger is now always visible (was opacity-0 /
  group-hover only), so Resume is reachable without hovering.

Verified offline against the replay server (no VPN needed); tsc clean.
2026-07-05 18:25:02 +02:00
marcopan c3a3cb8da5 feat(replay): standalone reviewer-gate replay server on :5333
Reproduces the real reviewer UI for any recorded session, with no VPN/Pi/
Python/DWH. The server (node:http, zero deps) serves the built SPA and a
tiny SSE/REST shim that re-emits the reviewer gates captured in a Pi
transcript, in their original order, with the reviewer's real 3-Jul
choices shown as comparison badges.

- tools/replay/extract.mjs: extracts gates from one or many transcripts
  (session-id, file, or directory). Handles sessions split across resume
  re-entries by sorting on message timestamp and dropping unanswered
  gates. Reads the question from session_manifest.yaml, resolving the
  sessions dir from any workspace yaml (no hardcoded paths).
- tools/replay/server.mjs: same-origin :5333. SSE streams gates; POST
  /response advances the cursor and pushes info badges (scelta reale).
  POST /resume and the final "Ripeti/Esci" widget close the SSE so the
  browser EventSource reconnects (cursor resets, gate 1 re-emitted) — the
  replay is re-runnable any number of times. GET /sessions/:id/documents
  reads the real session files so GateArtifactBody resolves file-reference
  artifacts. Exit emits system_event {event:"session_exit"} to return to
  the landing.
- scripts/replay.sh: launcher (extract / build / run / all).
- tools/replay/README.md: data flow, commands, fidelity notes.
- .gitignore: ignore tools/replay/web/ (built artifact, like dist/).
2026-07-05 18:24:26 +02:00
marcopanandClaude Fable 5 2f68b0d109 fix(frontend): contain viewer/widget crashes with error boundaries
A render error in one viewer or gate widget unmounted the whole React root
(white screen). Add a reusable ErrorBoundary (class component, no new dep) with
resetKeys + an on-brand fallback, and wire it at two surfaces:
- WidgetHost: isolates the gate widget (reset on descriptor id) so a malformed
  gate payload no longer blanks the conversation
- SessionDocumentsPanel: wraps each document (reset on doc key/content) so one
  crashing viewer degrades only its section; siblings and the panel survive

The observed crash: a schema-linking doc that parses but lacks `candidates`
makes SchemaLinkingViewer throw. Verified live via Playwright against the mock
backend. TDD throughout; tsc clean, 123/123 vitest (+8 new tests).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 13:18:51 +02:00
marcopanandClaude Fable 5 864b7ee29c docs: add AGENTS.md — Codex-facing mirror of the repo guidance
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 13:04:52 +02:00
marcopanandClaude Fable 5 4cd1cbc493 style(frontend): look&feel v2 — layered shadows, sharper radii, mono data register
Colors (GSD palette) untouched. New visual vocabulary across the whole GUI:
- warm-tinted layered shadow tokens (--shadow-xs/sm/md) replacing flat rings;
  cards/dialogs framed with hairline border + real elevation
- strict radii scale: xl cards / lg inputs / md controls / 2xl dialogs;
  buttons move from pills to rounded-md
- third type register: --font-mono + tabular-nums on SQL, timers, dates, ids;
  standardized .thot-label micro-label tier
- prose: framed tables with uppercase headers, elevated code blocks
- SqlViewer badges moved from hardcoded Tailwind greens/reds to success/
  destructive token tints; ResultsPanel inline styles replaced with classes
- artifact gate: first option rendered as filled primary action

Verified offline via Playwright against a mock backend replaying a real psd
session (no VPN needed). tsc clean, 115/115 vitest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 13:04:46 +02:00
marcopanandClaude Opus 4.8 cc1ffb59fa docs(pi): revise dual-mode gate eval per review (P1/P2)
- present() = presentBlockingWidget: transport + no-limbo loop + response
  validation; both branches share validateUiResponse; the id invariant must be
  validated explicitly in the TUI branch (emitAndWait no longer runs there)
- TUI renderer uses numbered options + index parsing, never label mapping
  (frontend already answers with ids); artifact-gate editor is viewer-only,
  returned content ignored
- guards resolved: both TUI-only notices now ctx.mode === "tui"
- interactive-render.js as two layers (renderTuiDescriptor +
  validateSyntheticResponse); add negative test cases + a real TUI smoke

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 12:41:39 +02:00
marcopanandClaude Opus 4.8 a166d9bc4e fix(gate): guard the steering-during-lock hint on ctx.mode, not ctx.hasUI
The "respond with gate widgets; use '!' for free text" notice is terminal-
flavored. Like the reLoop Esc guard, it used ctx.hasUI, which on pi >=0.80 is
true in RPC too, so it leaked to the browser. Now guarded on ctx.mode === "tui".
The plain text is still swallowed by the `handled` return in all modes; only the
warning is dropped in RPC. No functional ctx.hasUI guard remains in the gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 12:41:39 +02:00
marcopanandClaude Opus 4.8 d6b4729ddf feat(shell): yellow active session, growing composer, phase title, refined activity log, arrow panel toggle
Fix six GUI defects, verified live against the real stack:

- NavSessions: mark the in-progress (active) session in yellow (warning
  token) — both its status dot and its row background.
- SteerInput: the composer is now an auto-growing textarea that wraps and
  grows vertically (caps at 160px, then scrolls); Enter sends, Shift+Enter
  inserts a newline.
- WorkflowBar: show a synthetic title of the current phase under the 8 dots
  from static EN/IT strings (no LLM); English is displayed to match the chrome.
- CentralStatus: reformat the 5-line system-message tail as a structured,
  monospace list with per-line markers and an emphasized last line.
- AppShell + CentralStatus: move the left Model-activity panel toggle off the
  working spinner (now a pure status indicator) onto a dedicated arrow button
  (→ opens, ← closes).
- gate: rename the phase-confirm button "Conferma e prosegui" → "Salva e
  procedi" (builders.js + its L1 test).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 14:32:01 +02:00
marcopanandClaude Opus 4.8 1f9818c50f fix(gate): guard the TUI-only "Esc" notice on ctx.mode, not ctx.hasUI
reLoop's "Esc non chiude il gate..." warning is terminal-specific. On pi 0.73
ctx.hasUI was false in RPC, so `if (ctx.hasUI)` effectively meant "TUI only". On
pi >=0.80 hasUI is true in RPC too (dialog-capable UI via the bridge), so the
notice leaked to the browser on any invalid gate response. Guard on
ctx.mode === "tui" to restore the original intent. The fake pi runtime gains
mode:"tui" so the roundtrip test still exercises the notice.

Audit of the other 5 ctx.ui.notify: left as-is. They are valid in both live
modes (TUI and RPC, both hasUI=true) and the gate cannot run headless
(emitAndWait needs a UI), so a guard would be dead code. Their dual-mode
rationalization belongs with the future present() work (tracked in the eval doc).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 14:21:57 +02:00
marcopanandClaude Opus 4.8 0afa9a2f80 docs(pi): correct dual-mode gate eval — hasUI polarity, info/freetext wiring, citations
- #1 hasUI: real 0.80.3 comment is "true in TUI and RPC modes" (doc had the old
  0.73.1 "false in print/RPC"). hasUI no longer distinguishes TUI from RPC, so it
  is NOT a fallback for the interactive branch — only ctx.mode === "tui" is.
- #2 info/freetext: buildInfoRequest exists in builders.js but is NOT wired into
  tht-gate.js (imports only select/multiselect/artifact-gate). info notices are
  hand-written ctx.ui.notify; freetext is a control, not a descriptor. Table now
  lists only the 3 real present() descriptors.
- #3 cite the REWRITE banner (tht-gate.js:8-10), not :227; id-match quoted verbatim.
- #4 new "Note implementative": 227 comment, 4/6 unguarded notify, and the
  ctx.hasUI guard migration side-effect (now fires in RPC on 0.80.3).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 14:13:26 +02:00
marcopanandClaude Opus 4.8 be02e96f9e chore(pi): consolidate 0.80.3 migration — align extension + docs to @earendil-works
- aritmolab-provider.js: import pi-ai from @earendil-works (was @mariozechner).
  Verified live that the aritmolab/qwen provider still registers under pi 0.80.3
  (get_available_models -> aritmolab, deepseek, zai). Removes the dual-package
  reliance on the frozen @mariozechner install still on disk for rollback.
- docs/general/pi-configuration.md: built-in models package is @earendil-works/pi-ai

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 13:23:46 +02:00
marcopanandClaude Opus 4.8 b35c4b5692 docs(pi): migrate runtime to @earendil-works@0.80.3; update dual-mode gate eval
- live pi repointed 0.73.1 (@mariozechner, frozen) -> 0.80.3 (@earendil-works);
  validated via API/RPC surface diff (stable+additive) + model-matrix smoke
  (GLM 5.2 new+resume CHAINED)
- PROJECT_STATE: item 6 migration note (supersedes the 0.79.4 references)
- dual-mode gate eval: integrate review points (#3,#5,#7,#8,#9,#10) and flip #1
  to ctx.mode === "tui" (0.80.3 exposes ctx.mode: tui|rpc|json|print)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 12:51:56 +02:00
marcopanandClaude Opus 4.8 a0a503b721 fix(gate): coerce stringified object params; block model edits to gate code
Some models (GLM 5.2) send object params (reviewer_confirm's artifact,
write_schema_linking's schema_linking) as JSON-encoded strings. These failed
TypeBox validation before execute(), making the model retry in an unbounded loop
(observed ~2100s hang). jsonObjectOrSelf() coerces them back to objects in
prepareReviewerArguments and write_schema_linking.

Also close an anti-bypass gap: pi's write/edit tools were unrestricted on the gate
code, so a looping model actually patched tht-gate.js. GATE_CODE_FILES now blocks
any write under .pi/extensions. Requires a pi restart to take effect.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 18:28:45 +02:00
marcopanandClaude Opus 4.8 f1b071d165 feat(shell): 30/55/15 layout, formatted activity log, instant resume, stop confirmation
Left panels 30vw / central 55% / right rail 15vw, minimal padding. Model-activity
log and documents render via .thot-prose; decisions become hairline rows with
semantic type chips. Resume switches the view optimistically (instant feedback).
The Stop button now asks for confirmation before interrupting.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 18:15:48 +02:00
marcopanandClaude Opus 4.8 a719ad5990 feat(viewer): artifact modal renders structured text, never raw JSON
ArtifactView's fallback (StructuredValue) turns any object/array into labelled
sections, bullet lists and paragraphs (strings as markdown). Verified against the
real F1 gate (kind:"text", {recap, chiarimenti_risolti[], ...}). MarkdownView
uses the real .thot-prose class (Tailwind Typography is not installed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 18:15:48 +02:00
marcopanandClaude Opus 4.8 cec6620c00 feat(widgets): redesign gate widgets — readable hierarchy, prominent select-all, styled controls
Titles + intro read as a clear prompt (comfortable line length), options as
spaced choice rows, Other/Back/Exit as discreet secondary controls under a
divider. Multiselect gets a prominent Select all/Deselect all at the head of the
list with a live count.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 18:15:48 +02:00
marcopanandClaude Opus 4.8 56ed8b29bd feat(workflow-bar): processing-only elapsed timer + optimistic phase paint on resume
Timer now accumulates only while the harness works, pausing while a gate awaits
the reviewer and freezing when finalized (keyed per session, in-memory). Resume
now colours the re-entry phase immediately from the manifest's phase (1..8),
mirroring the F1 paint for new questions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 14:13:02 +02:00
marcopanandClaude Opus 4.8 e4ada07dab feat(viewer): erDiagram shows real column types when present; ArtifactView accepts a {content} sql wrapper
erDiagram reads data_type/type from the candidate (top-level or signals),
falling back to the generic 'col' token Mermaid needs — real types render as
soon as schema_linking.json carries them. ArtifactView gains a defensive
{content} fallback for sql-kind artifacts, verified against real session shapes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 14:13:02 +02:00
marcopanandClaude Opus 4.8 c3e8f14ad9 test(gate): clarify the 'altrove' first-token guard comment
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 14:13:02 +02:00
marcopan 3f852fd817 feat(workflow-bar): total elapsed timer after the phase circles 2026-07-03 13:26:25 +02:00
marcopan e630ac98f9 feat(workflow-bar): optimistic F1 at start; all-green when session finalized 2026-07-03 13:22:09 +02:00
marcopan 37b3eb45e9 feat(gate): render reviewer artifacts in a 90% modal (fix empty artifact.data gate) 2026-07-03 13:17:54 +02:00
marcopan 0975a8a72b feat(viewer): ArtifactView routes artifact.data by kind (schema/sql/cte/question) 2026-07-03 13:13:51 +02:00
marcopan 893e9e4059 feat(viewer): schema linking renders a Mermaid erDiagram (tables + relations) 2026-07-03 13:09:09 +02:00
marcopan 168a72372b fix(gate): robust isReserved strips model Altro/other variants (no duplicate free-text option) 2026-07-03 13:05:21 +02:00