docs: align 05/06/09/11 with implemented GUI Phases A–D

* docs/11-gui-streamlit.md — replaces the original spec with what was
  actually built: implementation status table, real page filenames
  (1_Status, 2_Audit, 3_Equity, 4_History, 5_Position), per-page
  inventory of implemented vs deferred sections, GUI ↔ engine table
  showing arm_kill/disarm_kill via manual_actions and the
  not_supported markers for force_close + approve/reject_proposal,
  consumer signature with cron */1, lock model clarified (no GUI
  lockfile), DoD updated with current state.
* docs/05-data-model.md — manual_actions is no longer "pianificata":
  populated by gui/data_layer.py, drained by the manual_actions job;
  per-kind status table (arm/disarm OK, others not_supported).
* docs/09-development-roadmap.md — Phase 4.5 marked implemented with
  per-task / markers for the deferred items (auto-refresh,
  AppTest, force-close hook).
* docs/06-operational-flow.md — adds Flusso 5b describing the
  manual_actions consumer pattern (enqueue → KillSwitch transition →
  audit log linkage).

360/360 tests still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-30 13:31:25 +02:00
parent e8345a29c8
commit da88e7f746
4 changed files with 251 additions and 160 deletions
+23 -10
View File
@@ -152,27 +152,40 @@ CREATE TABLE dvol_history (
### `manual_actions`
Coda di azioni manuali generate dalla GUI Streamlit (vedi
`11-gui-streamlit.md`). Schema previsto in vista della Fase 4.5; al
momento la GUI non è implementata e la tabella resta vuota.
`11-gui-streamlit.md`). La tabella è popolata dal layer
`gui/data_layer.py` (`enqueue_arm_kill`, `enqueue_disarm_kill`) ed è
drenata dal job APScheduler `manual_actions`
(`runtime/manual_actions_consumer.consume_manual_actions`, cron
`*/1 * * * *`).
```sql
CREATE TABLE manual_actions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
kind TEXT NOT NULL, -- approve_proposal, reject_proposal,
-- force_close, arm_kill, disarm_kill
kind TEXT NOT NULL, -- arm_kill, disarm_kill,
-- force_close, approve_proposal, reject_proposal
proposal_id TEXT, -- NULL se l'azione non è legata a una proposta
payload_json TEXT, -- JSON con motivo, conferma typed, ecc.
payload_json TEXT, -- JSON con reason, conferma typed, ecc.
created_at TEXT NOT NULL,
consumed_at TEXT, -- NULL = ancora da processare
consumed_by TEXT,
result TEXT
consumed_by TEXT, -- "engine" quando applicata dal consumer
result TEXT -- "ok" / "not_supported" / "error: ..."
);
CREATE INDEX idx_manual_actions_unconsumed ON manual_actions(consumed_at);
```
Le `manual_actions` non bypassano i risk control: il consumer
(quando esisterà) applicherà gli stessi check di
`safety.system_healthy()` prima di eseguire.
Stato implementativo per `kind`:
| `kind` | Implementato | Effetto |
|---|---|---|
| `arm_kill` | ✅ | `KillSwitch.arm(reason, source="manual_gui")` |
| `disarm_kill` | ✅ | `KillSwitch.disarm(reason, source="manual_gui")` |
| `force_close` | ⏳ | Marcato `result="not_supported"` finché l'orchestrator non espone `handle_force_close` |
| `approve_proposal` / `reject_proposal` | ⏳ | Idem |
Le `manual_actions` **non** bypassano i risk control: ogni azione di
kill switch passa dalla classe `KillSwitch`, che valida lo stato e
appende l'evento corrispondente alla audit chain. La typed
confirmation lato GUI è gating prima dell'enqueue.
### `system_state`