lovarch-cli 0.3.0__tar.gz → 0.3.1__tar.gz
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.
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/CHANGELOG.md +10 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/PKG-INFO +1 -1
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/do_cmd.py +34 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/verifica_cmd.py +82 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/verify/__init__.py +6 -1
- lovarch_cli-0.3.1/lovarch_cli/verify/computo.py +149 -0
- lovarch_cli-0.3.1/lovarch_cli/verify/pratica.py +122 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/version.py +1 -1
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/workflows/platform.py +31 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/.gitignore +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/LICENSE +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/README.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/__init__.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/__main__.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/agents/__init__.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/agents/prompts.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/agents/runner.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/ai/__init__.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/ai/gateway.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/api.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/auth/__init__.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/auth/keyring_store.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/auth/local_server.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/auth/pkce.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/auth/session.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/cli.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/clients/__init__.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/clients/factory.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/clients/local_client.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/clients/lovarch_storage.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/clients/lovarch_supabase.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/clients/persistence.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/clients/storage.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/__init__.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/account.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/agent_cmd.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/audit.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/config_cmd.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/consolidate.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/context_cmd.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/dev.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/init.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/jobs_cmd.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/login.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/mcp_cmd.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/run.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/signup.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/skills_cmd.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/status.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/commands/upgrade.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/config.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/config_store.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/credits/__init__.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/credits/base.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/credits/factory.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/credits/local.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/credits/lovarch.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/i18n/__init__.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/i18n/loader.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/i18n/translations/en.json +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/i18n/translations/es.json +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/i18n/translations/it.json +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/i18n/translations/pt.json +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/mcp/__init__.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/mcp/server.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/mcp/tools.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/sample_downloader.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/skills/lovarch-capitolato/SKILL.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/skills/lovarch-direzione-lavori/SKILL.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/skills/lovarch-interior-designer/SKILL.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/skills/lovarch-preventivi/SKILL.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/skills/lovarch-render/SKILL.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/skills/lovarch-verifica-normativa/SKILL.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/README.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/auditor-input.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/bim-engineer.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/briefing-architect.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/cad-engineer.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/capitolato-writer.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/computo-engineer.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/concept-designer.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/contratto-architect.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/deliverable-builder.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/energy-prelim.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/pratiche-it.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/progetto-chief.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/quality-dati.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/quality-misure.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/quality-normativa.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/quality-output.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/agents/regolatorio-it.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/checklists/handoff-quality-gate.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/checklists/quality-dati-checklist.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/checklists/quality-misure-checklist.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/checklists/quality-normativa-checklist.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/checklists/quality-output-checklist.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/config.yaml +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/data/CHANGELOG.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/data/agents-prd.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/data/architettura-progetto-rules.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/data/handoff-card-template.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/data/mocks/catasto-visura.json +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/data/mocks/firma-envelope.json +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/data/prezzario-lombardia-sample.json +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/api_clients.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/architect_profile.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/deliverable_generators.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/generate_attico_brera_dwg.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/generate_chianti_dxf.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/generate_chianti_images.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/generate_real_sample_images.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/generate_sample_assets.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/input_parser.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/lovarch_client.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/pipeline_runner.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/render_dxf_to_png.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/run_palestra_demo.sh +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/simulate_squad_execution.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/validate-squad.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/tasks/audit-input.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/tasks/compute-metric.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/tasks/consolidate-dossier.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/tasks/generate-cad-plan.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/tasks/generate-ifc-model.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/tasks/write-capitolato.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/templates/asseverazione-tecnica.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/templates/capitolato-uni-11337.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/templates/cila-comune-milano.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/templates/contratto-cnappc.md +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/workflows/dal-brief-al-cantiere.yaml +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad_loader.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/verify/contratto.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/verify/dossier.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/verify/misure.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/verify/normativa.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/workflows/__init__.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/pyproject.toml +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/scripts/refresh_squad_vendor.py +0 -0
- {lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/scripts/sync_squad.py +0 -0
|
@@ -5,6 +5,16 @@ All notable changes to `lovarch-cli` are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.1] — 2026-07-04
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `lovarch do script <topic>` — script di contenuto strutturato via piattaforma (schema drift della EF scripts-generate corretto lato monorepo; refund resiliente).
|
|
12
|
+
- `lovarch verifica computo <file> [--region --version]` — confronto deterministico (gratis) delle voci di un computo col prezzario regionale (tabella `prezzari`, seed Lombardia): codici inesistenti, prezzi fuori tolleranza (±20%), unità incoerenti, totale.
|
|
13
|
+
- `lovarch verifica pratica <file> [--tipo CILA|SCIA]` — verifica adversarial (2 modelli) di una pratica edilizia: completezza (catasto, titolo, asseverazione) e coerenza titolo↔intervento.
|
|
14
|
+
|
|
15
|
+
### Notes
|
|
16
|
+
- Persistenza premium: il runner ora crea il progetto CRM completo nell'account dell'utente tramite la EF `cli-persist` (scrittura controllata lato server, nessuna scrittura cross-tenant).
|
|
17
|
+
|
|
8
18
|
## [Unreleased]
|
|
9
19
|
|
|
10
20
|
(No unreleased changes yet — last release was v0.3.0.)
|
|
@@ -154,3 +154,37 @@ def site_command(
|
|
|
154
154
|
err_console.print(f"[red]✗ {out.get('error')}[/red]"); raise typer.Exit(1)
|
|
155
155
|
console.print(f"[green]✓[/green] Sito: [bold]{out['saved_to']}[/bold] ({out.get('bytes', 0)} bytes)")
|
|
156
156
|
|
|
157
|
+
|
|
158
|
+
@do_app.command("script")
|
|
159
|
+
def script_command(
|
|
160
|
+
topic: str = typer.Argument(..., help="Argomento dello script."),
|
|
161
|
+
type: str = typer.Option("reel", "--type", help="reel | post | carousel | video…"),
|
|
162
|
+
goal: str = typer.Option("educare", "--goal", help="Obiettivo del contenuto."),
|
|
163
|
+
tone: str = typer.Option("professionale", "--tone", help="Tono di voce."),
|
|
164
|
+
cta: str = typer.Option("", "--cta", help="Call-to-action."),
|
|
165
|
+
output: Path = typer.Option(None, "--output", "-o", help="Salva lo script su file."),
|
|
166
|
+
language: str = typer.Option(None, "--language"),
|
|
167
|
+
) -> None:
|
|
168
|
+
"""Script di contenuto strutturato via piattaforma (addebita crediti)."""
|
|
169
|
+
wf = _workflows()
|
|
170
|
+
from lovarch_cli.workflows import WorkflowError
|
|
171
|
+
|
|
172
|
+
try:
|
|
173
|
+
s = asyncio.run(wf.script(topic, type=type, goal=goal, tone=tone, cta=cta,
|
|
174
|
+
language=_lang(language)))
|
|
175
|
+
except WorkflowError as exc:
|
|
176
|
+
err_console.print(f"[red]✗ {exc}[/red]"); raise typer.Exit(1)
|
|
177
|
+
|
|
178
|
+
title = s.get("title") or topic
|
|
179
|
+
content = s.get("content") or ""
|
|
180
|
+
console.print(f"\n[bold gold1]{title}[/bold gold1]\n")
|
|
181
|
+
if content:
|
|
182
|
+
console.print(content)
|
|
183
|
+
if s.get("keywords"):
|
|
184
|
+
console.print("\n[dim]" + " ".join(s["keywords"]) + "[/dim]")
|
|
185
|
+
if not s.get("persisted", True):
|
|
186
|
+
console.print("\n[yellow]⚠ Non salvato nel tuo account (crediti rimborsati).[/yellow]")
|
|
187
|
+
if output:
|
|
188
|
+
Path(output).expanduser().write_text(content or title, encoding="utf-8")
|
|
189
|
+
console.print(f"\n[green]✓[/green] salvato: {output}")
|
|
190
|
+
|
|
@@ -49,6 +49,88 @@ def misure_command(
|
|
|
49
49
|
raise typer.Exit(0 if report.verdict == "PASS" else (2 if report.verdict == "CONCERNS" else 1))
|
|
50
50
|
|
|
51
51
|
|
|
52
|
+
@verifica_app.command("computo")
|
|
53
|
+
def computo_command(
|
|
54
|
+
computo: Path = typer.Argument(..., help="Computo metrico (.csv o .json: codice,quantita,prezzo_unitario)."),
|
|
55
|
+
region: str = typer.Option("Lombardia", "--region", help="Regione del prezzario di riferimento."),
|
|
56
|
+
version: str = typer.Option(None, "--version", help="Versione del prezzario (opzionale)."),
|
|
57
|
+
) -> None:
|
|
58
|
+
"""Confronta le voci del computo col prezzario regionale (gratis, deterministico)."""
|
|
59
|
+
from lovarch_cli.auth.session import LovarchSession
|
|
60
|
+
from lovarch_cli.verify import verify_computo
|
|
61
|
+
from lovarch_cli.verify.computo import ComputoError
|
|
62
|
+
|
|
63
|
+
session = LovarchSession.load()
|
|
64
|
+
if session is None:
|
|
65
|
+
err_console.print("[red]✗ Non autenticato. Esegui `lovarch login --premium`.[/red]")
|
|
66
|
+
raise typer.Exit(1)
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
report = asyncio.run(verify_computo(session, computo, region=region, version=version))
|
|
70
|
+
except ComputoError as exc:
|
|
71
|
+
err_console.print(f"[red]✗ {exc}[/red]")
|
|
72
|
+
raise typer.Exit(1)
|
|
73
|
+
|
|
74
|
+
table = Table(title=f"verifica computo — {computo.name}", header_style="bold gold1")
|
|
75
|
+
table.add_column("Metrica", style="cyan")
|
|
76
|
+
table.add_column("Valore", justify="right")
|
|
77
|
+
table.add_row("Prezzario", str(report.stats.get("prezzario", "—")))
|
|
78
|
+
table.add_row("Voci totali", str(report.stats.get("voci_totali", "—")))
|
|
79
|
+
table.add_row("Voci verificate", str(report.stats.get("voci_verificate", "—")))
|
|
80
|
+
table.add_row("Codici sconosciuti", str(report.stats.get("codici_sconosciuti", 0)))
|
|
81
|
+
table.add_row("Prezzi fuori tolleranza", str(report.stats.get("prezzi_fuori_tolleranza", 0)))
|
|
82
|
+
table.add_row("Unità incoerenti", str(report.stats.get("unita_incoerenti", 0)))
|
|
83
|
+
table.add_row("Totale computo (€)", f"{report.stats.get('totale_computo_eur', 0):,.2f}")
|
|
84
|
+
console.print(table)
|
|
85
|
+
for f in report.findings:
|
|
86
|
+
console.print(f" [yellow]·[/yellow] {f}")
|
|
87
|
+
_print_verdict(report.verdict)
|
|
88
|
+
raise typer.Exit(0 if report.verdict == "PASS" else (2 if report.verdict == "CONCERNS" else 1))
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@verifica_app.command("pratica")
|
|
92
|
+
def pratica_command(
|
|
93
|
+
documento: Path = typer.Argument(..., help="Pratica edilizia (.pdf, .md, .txt)."),
|
|
94
|
+
tipo: str = typer.Option(None, "--tipo", help="CILA | SCIA (se noto)."),
|
|
95
|
+
language: str = typer.Option(None, "--language", help="Lingua del report."),
|
|
96
|
+
) -> None:
|
|
97
|
+
"""Verifica adversarial di una pratica CILA/SCIA (2 modelli · debita crediti)."""
|
|
98
|
+
from lovarch_cli.ai import LovarchAiGateway
|
|
99
|
+
from lovarch_cli.auth.session import LovarchSession
|
|
100
|
+
from lovarch_cli.i18n import current_lang
|
|
101
|
+
from lovarch_cli.verify import verify_pratica
|
|
102
|
+
from lovarch_cli.verify.normativa import NormativaError
|
|
103
|
+
|
|
104
|
+
session = LovarchSession.load()
|
|
105
|
+
if session is None:
|
|
106
|
+
err_console.print("[red]✗ Non autenticato. Esegui `lovarch login --premium`.[/red]")
|
|
107
|
+
raise typer.Exit(1)
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
report = asyncio.run(verify_pratica(
|
|
111
|
+
LovarchAiGateway(session), documento, tipo=tipo,
|
|
112
|
+
language=language or current_lang(),
|
|
113
|
+
))
|
|
114
|
+
except NormativaError as exc:
|
|
115
|
+
err_console.print(f"[red]✗ {exc}[/red]")
|
|
116
|
+
raise typer.Exit(1)
|
|
117
|
+
|
|
118
|
+
console.print(f"[dim]Tipo pratica: {report.tipo}[/dim]")
|
|
119
|
+
table = Table(title=f"verifica pratica — {documento.name}", header_style="bold gold1")
|
|
120
|
+
table.add_column("Area", style="cyan")
|
|
121
|
+
table.add_column("Severità", justify="center")
|
|
122
|
+
table.add_column("Motivo")
|
|
123
|
+
for f in report.findings:
|
|
124
|
+
sev = str(f.get("severity", "")).lower()
|
|
125
|
+
icon = {"critical": "[red]✗[/red]", "concern": "[yellow]?[/yellow]", "info": "[dim]·[/dim]"}.get(sev, "?")
|
|
126
|
+
table.add_row(str(f.get("area", "—")), icon, str(f.get("reason", ""))[:100])
|
|
127
|
+
console.print(table)
|
|
128
|
+
console.print("[dim]Firma e responsabilità restano del tecnico abilitato (BOZZA).[/dim]")
|
|
129
|
+
console.print(f"[dim]Crediti addebitati: {report.credits_charged}[/dim]")
|
|
130
|
+
_print_verdict(report.verdict)
|
|
131
|
+
raise typer.Exit(0 if report.verdict == "PASS" else (2 if report.verdict == "CONCERNS" else 1))
|
|
132
|
+
|
|
133
|
+
|
|
52
134
|
@verifica_app.command("normativa")
|
|
53
135
|
def normativa_command(
|
|
54
136
|
documento: Path = typer.Argument(..., help="Documento da verificare (.pdf, .md, .txt)."),
|
|
@@ -7,9 +7,14 @@ Sonnet 5 (executor) extracts/structures → Opus 4.8 (verifier) tries to refute
|
|
|
7
7
|
each claim independently. Credits are debited per real tokens via cli-ai-text;
|
|
8
8
|
deterministic checks are free.
|
|
9
9
|
"""
|
|
10
|
+
from lovarch_cli.verify.computo import verify_computo
|
|
10
11
|
from lovarch_cli.verify.contratto import verify_contratto
|
|
11
12
|
from lovarch_cli.verify.dossier import verify_dossier
|
|
12
13
|
from lovarch_cli.verify.misure import verify_misure
|
|
13
14
|
from lovarch_cli.verify.normativa import verify_normativa
|
|
15
|
+
from lovarch_cli.verify.pratica import verify_pratica
|
|
14
16
|
|
|
15
|
-
__all__ = [
|
|
17
|
+
__all__ = [
|
|
18
|
+
"verify_computo", "verify_contratto", "verify_dossier",
|
|
19
|
+
"verify_misure", "verify_normativa", "verify_pratica",
|
|
20
|
+
]
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""verifica computo — deterministic check of a computo metrico against the
|
|
2
|
+
regional prezzario (table `prezzari`). No LLM, no credits: it compares each
|
|
3
|
+
voce's unit price and unit of measure to the official reference and flags
|
|
4
|
+
codes that don't exist, prices out of tolerance, and unit mismatches.
|
|
5
|
+
|
|
6
|
+
Input file: CSV (header: codice,descrizione,quantita,prezzo_unitario[,unita])
|
|
7
|
+
or JSON (list of {codice, quantita, prezzo_unitario, unita?}).
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import csv
|
|
12
|
+
import io
|
|
13
|
+
import json
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
# A unit price this far from the prezzario reference is flagged (±%).
|
|
19
|
+
PRICE_TOLERANCE = 0.20
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ComputoError(Exception):
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class ComputoReport:
|
|
28
|
+
verdict: str # PASS | CONCERNS | REJECT
|
|
29
|
+
findings: list[str] = field(default_factory=list)
|
|
30
|
+
stats: dict = field(default_factory=dict)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _parse_computo(path: Path) -> list[dict]:
|
|
34
|
+
text = path.read_text(encoding="utf-8")
|
|
35
|
+
if path.suffix.lower() == ".json":
|
|
36
|
+
data = json.loads(text)
|
|
37
|
+
if not isinstance(data, list):
|
|
38
|
+
raise ComputoError("il JSON del computo deve essere una lista di voci")
|
|
39
|
+
return data
|
|
40
|
+
# CSV
|
|
41
|
+
reader = csv.DictReader(io.StringIO(text))
|
|
42
|
+
return [dict(row) for row in reader]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _num(v: Any) -> float | None:
|
|
46
|
+
if v is None or v == "":
|
|
47
|
+
return None
|
|
48
|
+
try:
|
|
49
|
+
return float(str(v).replace(",", ".").replace("€", "").strip())
|
|
50
|
+
except ValueError:
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def verify_computo(
|
|
55
|
+
session: Any,
|
|
56
|
+
computo_path: str | Path,
|
|
57
|
+
*,
|
|
58
|
+
region: str = "Lombardia",
|
|
59
|
+
version: str | None = None,
|
|
60
|
+
) -> ComputoReport:
|
|
61
|
+
"""Compare a computo file's voci against the prezzari reference for a region."""
|
|
62
|
+
path = Path(computo_path).expanduser()
|
|
63
|
+
if not path.is_file():
|
|
64
|
+
return ComputoReport(verdict="REJECT", findings=[f"file non trovato: {path}"])
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
voci = _parse_computo(path)
|
|
68
|
+
except Exception as exc: # noqa: BLE001 — parse errors are the finding
|
|
69
|
+
return ComputoReport(verdict="REJECT", findings=[f"computo non leggibile: {str(exc)[:150]}"])
|
|
70
|
+
|
|
71
|
+
if not voci:
|
|
72
|
+
return ComputoReport(verdict="REJECT", findings=["nessuna voce nel computo"])
|
|
73
|
+
|
|
74
|
+
# Load the prezzario for the region (RLS: authenticated read).
|
|
75
|
+
params = {"region": f"eq.{region}", "select": "codice,prezzo,unita,descrizione"}
|
|
76
|
+
if version:
|
|
77
|
+
params["version"] = f"eq.{version}"
|
|
78
|
+
resp = await session.request("GET", "/rest/v1/prezzari", params=params)
|
|
79
|
+
if resp.status_code != 200:
|
|
80
|
+
raise ComputoError(f"prezzari non disponibili: HTTP {resp.status_code}")
|
|
81
|
+
ref_rows = resp.json()
|
|
82
|
+
ref = {r["codice"]: r for r in ref_rows if isinstance(r, dict) and r.get("codice")}
|
|
83
|
+
if not ref:
|
|
84
|
+
raise ComputoError(f"nessun prezzario per regione '{region}'"
|
|
85
|
+
+ (f" versione '{version}'" if version else ""))
|
|
86
|
+
|
|
87
|
+
findings: list[str] = []
|
|
88
|
+
unknown = 0
|
|
89
|
+
out_of_range = 0
|
|
90
|
+
unit_mismatch = 0
|
|
91
|
+
total_computo = 0.0
|
|
92
|
+
checked = 0
|
|
93
|
+
|
|
94
|
+
for i, voce in enumerate(voci, 1):
|
|
95
|
+
codice = str(voce.get("codice") or "").strip()
|
|
96
|
+
if not codice:
|
|
97
|
+
findings.append(f"voce {i}: codice mancante")
|
|
98
|
+
continue
|
|
99
|
+
qta = _num(voce.get("quantita") or voce.get("quantità"))
|
|
100
|
+
prezzo = _num(voce.get("prezzo_unitario") or voce.get("prezzo"))
|
|
101
|
+
unita = str(voce.get("unita") or voce.get("unità") or "").strip()
|
|
102
|
+
|
|
103
|
+
if qta is not None and prezzo is not None:
|
|
104
|
+
total_computo += qta * prezzo
|
|
105
|
+
|
|
106
|
+
r = ref.get(codice)
|
|
107
|
+
if not r:
|
|
108
|
+
unknown += 1
|
|
109
|
+
findings.append(f"voce {i} [{codice}]: codice non presente nel prezzario {region}")
|
|
110
|
+
continue
|
|
111
|
+
checked += 1
|
|
112
|
+
|
|
113
|
+
ref_price = float(r["prezzo"])
|
|
114
|
+
if prezzo is not None and ref_price > 0:
|
|
115
|
+
delta = (prezzo - ref_price) / ref_price
|
|
116
|
+
if abs(delta) > PRICE_TOLERANCE:
|
|
117
|
+
out_of_range += 1
|
|
118
|
+
findings.append(
|
|
119
|
+
f"voce {i} [{codice}]: prezzo {prezzo:.2f} vs riferimento "
|
|
120
|
+
f"{ref_price:.2f} ({delta:+.0%}) — fuori tolleranza ±{PRICE_TOLERANCE:.0%}"
|
|
121
|
+
)
|
|
122
|
+
if unita and r.get("unita") and unita.lower() != str(r["unita"]).lower():
|
|
123
|
+
unit_mismatch += 1
|
|
124
|
+
findings.append(
|
|
125
|
+
f"voce {i} [{codice}]: unità '{unita}' ≠ prezzario '{r['unita']}'"
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
stats = {
|
|
129
|
+
"voci_totali": len(voci),
|
|
130
|
+
"voci_verificate": checked,
|
|
131
|
+
"codici_sconosciuti": unknown,
|
|
132
|
+
"prezzi_fuori_tolleranza": out_of_range,
|
|
133
|
+
"unita_incoerenti": unit_mismatch,
|
|
134
|
+
"totale_computo_eur": round(total_computo, 2),
|
|
135
|
+
"prezzario": f"{region}"
|
|
136
|
+
+ (f" {version}" if version else "")
|
|
137
|
+
+ f" ({len(ref)} voci)",
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if unknown or out_of_range:
|
|
141
|
+
verdict = "CONCERNS"
|
|
142
|
+
else:
|
|
143
|
+
verdict = "PASS"
|
|
144
|
+
# A computo where nothing could be matched is not trustworthy.
|
|
145
|
+
if checked == 0:
|
|
146
|
+
verdict = "REJECT"
|
|
147
|
+
findings.insert(0, "nessuna voce del computo trovata nel prezzario")
|
|
148
|
+
|
|
149
|
+
return ComputoReport(verdict=verdict, findings=findings, stats=stats)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""verifica pratica — adversarial check of a building permit filing (CILA/SCIA).
|
|
2
|
+
|
|
3
|
+
Same two-model pattern as contratto/normativa: Sonnet 5 (executor) extracts the
|
|
4
|
+
filing's structure and declared data, Opus 4.8 (verifier) adversarially checks
|
|
5
|
+
completeness and coherence against the required elements of a CILA (Comunicazione
|
|
6
|
+
Inizio Lavori Asseverata) or SCIA (Segnalazione Certificata di Inizio Attività):
|
|
7
|
+
identificativi catastali, titolo di legittimità, asseverazione del tecnico,
|
|
8
|
+
elaborati allegati, e coerenza dell'intervento col titolo scelto (una CILA non
|
|
9
|
+
copre interventi che richiedono SCIA/permesso di costruire).
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from lovarch_cli.verify.normativa import NormativaError, _parse_json, extract_text
|
|
18
|
+
|
|
19
|
+
# Required elements per filing type (used to prompt the verifier, not as a
|
|
20
|
+
# rigid checklist — the LLM judges presence/coherence adversarially).
|
|
21
|
+
CILA_REQUIRED = [
|
|
22
|
+
"dati anagrafici del committente", "identificativi catastali (foglio/mappale/sub)",
|
|
23
|
+
"titolo di legittimità dell'immobile", "descrizione dell'intervento",
|
|
24
|
+
"asseverazione del tecnico abilitato", "elaborati grafici allegati",
|
|
25
|
+
"dichiarazione di conformità urbanistica",
|
|
26
|
+
]
|
|
27
|
+
SCIA_REQUIRED = CILA_REQUIRED + [
|
|
28
|
+
"relazione tecnica di asseverazione", "eventuali pareri/nulla osta (paesaggistico, ecc.)",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
_EXTRACT_SYSTEM = (
|
|
32
|
+
"Sei un assistente per pratiche edilizie italiane (CILA/SCIA). Estrai dalla "
|
|
33
|
+
"pratica la struttura e i dati dichiarati. Rispondi SOLO con JSON valido: "
|
|
34
|
+
'{"tipo": "CILA|SCIA|sconosciuto", "sezioni_presenti": ["..."], '
|
|
35
|
+
'"sezioni_mancanti": ["..."], "identificativi_catastali": "... o null", '
|
|
36
|
+
'"titolo_legittimita": "... o null", "asseverazione_presente": true|false, '
|
|
37
|
+
'"intervento": "descrizione sintetica", "note": ["..."]}'
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
_REFUTE_SYSTEM = (
|
|
41
|
+
"Sei un verificatore ADVERSARIALE di pratiche edilizie (CILA/SCIA). "
|
|
42
|
+
"Controlla: (1) completezza degli elementi obbligatori per il tipo dichiarato; "
|
|
43
|
+
"(2) presenza di identificativi catastali e titolo di legittimità; "
|
|
44
|
+
"(3) presenza dell'asseverazione del tecnico abilitato; (4) COERENZA tra "
|
|
45
|
+
"l'intervento descritto e il titolo scelto — una CILA NON copre interventi "
|
|
46
|
+
"strutturali o che incidono su prospetti/volumi (quelli richiedono SCIA o "
|
|
47
|
+
"permesso di costruire); segnala il possibile sottodimensionamento del titolo. "
|
|
48
|
+
"Nel dubbio sii scettico. La firma e la responsabilità restano del tecnico "
|
|
49
|
+
"abilitato. Rispondi SOLO con JSON valido: "
|
|
50
|
+
'{"findings": [{"area": "...", "severity": "critical" | "concern" | "info", '
|
|
51
|
+
'"reason": "..."}], "overall": "PASS" | "CONCERNS" | "REJECT"}'
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass
|
|
56
|
+
class PraticaReport:
|
|
57
|
+
verdict: str
|
|
58
|
+
tipo: str = "sconosciuto"
|
|
59
|
+
structure: dict = field(default_factory=dict)
|
|
60
|
+
findings: list[dict] = field(default_factory=list)
|
|
61
|
+
credits_charged: int = 0
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
async def verify_pratica(
|
|
65
|
+
gateway: Any,
|
|
66
|
+
document_path: str,
|
|
67
|
+
*,
|
|
68
|
+
tipo: str | None = None,
|
|
69
|
+
language: str = "it",
|
|
70
|
+
max_chars: int = 60_000,
|
|
71
|
+
) -> PraticaReport:
|
|
72
|
+
"""Adversarial CILA/SCIA filing check. Debits credits (2 calls)."""
|
|
73
|
+
text = extract_text(document_path)
|
|
74
|
+
if not text.strip():
|
|
75
|
+
raise NormativaError("documento vuoto o testo non estraibile.")
|
|
76
|
+
if len(text) > max_chars:
|
|
77
|
+
text = text[:max_chars]
|
|
78
|
+
|
|
79
|
+
credits = 0
|
|
80
|
+
hint = f" (tipo dichiarato dall'utente: {tipo.upper()})" if tipo else ""
|
|
81
|
+
extraction = await gateway.generate_text(
|
|
82
|
+
f"PRATICA EDILIZIA{hint}:\n\n{text}",
|
|
83
|
+
role="executor",
|
|
84
|
+
system=_EXTRACT_SYSTEM,
|
|
85
|
+
max_tokens=1500,
|
|
86
|
+
language=language,
|
|
87
|
+
operation_type="verify:pratica:extract",
|
|
88
|
+
)
|
|
89
|
+
credits += extraction.credits_charged
|
|
90
|
+
structure = _parse_json(extraction.text)
|
|
91
|
+
|
|
92
|
+
resolved_tipo = (tipo or str(structure.get("tipo") or "sconosciuto")).upper()
|
|
93
|
+
required = SCIA_REQUIRED if resolved_tipo == "SCIA" else CILA_REQUIRED
|
|
94
|
+
|
|
95
|
+
refutation = await gateway.generate_text(
|
|
96
|
+
"STRUTTURA ESTRATTA DALLA PRATICA:\n\n"
|
|
97
|
+
+ json.dumps(structure, ensure_ascii=False)
|
|
98
|
+
+ f"\n\nTipo: {resolved_tipo}. Elementi obbligatori attesi: "
|
|
99
|
+
+ ", ".join(required),
|
|
100
|
+
role="verifier",
|
|
101
|
+
system=_REFUTE_SYSTEM,
|
|
102
|
+
max_tokens=2000,
|
|
103
|
+
language=language,
|
|
104
|
+
operation_type="verify:pratica:refute",
|
|
105
|
+
)
|
|
106
|
+
credits += refutation.credits_charged
|
|
107
|
+
judged = _parse_json(refutation.text)
|
|
108
|
+
findings = judged.get("findings") or []
|
|
109
|
+
|
|
110
|
+
overall = str(judged.get("overall", "")).upper()
|
|
111
|
+
if overall not in ("PASS", "CONCERNS", "REJECT"):
|
|
112
|
+
severities = [str(f.get("severity", "")).lower() for f in findings]
|
|
113
|
+
overall = ("REJECT" if "critical" in severities
|
|
114
|
+
else ("CONCERNS" if "concern" in severities else "PASS"))
|
|
115
|
+
|
|
116
|
+
return PraticaReport(
|
|
117
|
+
verdict=overall,
|
|
118
|
+
tipo=resolved_tipo,
|
|
119
|
+
structure=structure,
|
|
120
|
+
findings=findings,
|
|
121
|
+
credits_charged=credits,
|
|
122
|
+
)
|
|
@@ -253,7 +253,38 @@ class MoreWorkflowsMixin:
|
|
|
253
253
|
raise WorkflowError("ai-site-generate non ha restituito HTML.")
|
|
254
254
|
return str(html)
|
|
255
255
|
|
|
256
|
+
async def script(
|
|
257
|
+
self,
|
|
258
|
+
topic: str,
|
|
259
|
+
*,
|
|
260
|
+
type: str = "reel",
|
|
261
|
+
goal: str = "educare",
|
|
262
|
+
tone: str = "professionale",
|
|
263
|
+
cta: str = "",
|
|
264
|
+
language: str = "it",
|
|
265
|
+
) -> dict:
|
|
266
|
+
"""Structured content script via scripts-generate. Returns the script
|
|
267
|
+
dict (title, content, outline, hashtags). `persisted` is True when it was
|
|
268
|
+
saved to the account; the platform refunds credits if it couldn't save."""
|
|
269
|
+
data = await self._invoke("scripts-generate", {
|
|
270
|
+
"type": type,
|
|
271
|
+
"topic": topic,
|
|
272
|
+
"goal": goal,
|
|
273
|
+
"tone": tone,
|
|
274
|
+
"cta": cta,
|
|
275
|
+
"editorial_line_id": "none",
|
|
276
|
+
"brainstorm_idea_id": "none",
|
|
277
|
+
"language": language,
|
|
278
|
+
}, timeout=_RENDER_TIMEOUT)
|
|
279
|
+
script = data.get("script") or {}
|
|
280
|
+
if not script:
|
|
281
|
+
raise WorkflowError(f"scripts-generate: {data.get('error', 'nessuno script')}")
|
|
282
|
+
# Normalize content field (real schema uses `content`; resilient path `full_script`).
|
|
283
|
+
script.setdefault("content", script.get("full_script"))
|
|
284
|
+
script["persisted"] = bool(data.get("persisted", True))
|
|
285
|
+
return script
|
|
256
286
|
|
|
257
287
|
|
|
258
288
|
PlatformWorkflows.logo = MoreWorkflowsMixin.logo # type: ignore[attr-defined]
|
|
259
289
|
PlatformWorkflows.site = MoreWorkflowsMixin.site # type: ignore[attr-defined]
|
|
290
|
+
PlatformWorkflows.script = MoreWorkflowsMixin.script # type: ignore[attr-defined]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/skills/lovarch-direzione-lavori/SKILL.md
RENAMED
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/skills/lovarch-interior-designer/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/skills/lovarch-verifica-normativa/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/checklists/handoff-quality-gate.md
RENAMED
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/checklists/quality-dati-checklist.md
RENAMED
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/checklists/quality-misure-checklist.md
RENAMED
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/checklists/quality-normativa-checklist.md
RENAMED
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/checklists/quality-output-checklist.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/data/architettura-progetto-rules.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/data/prezzario-lombardia-sample.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/generate_attico_brera_dwg.py
RENAMED
|
File without changes
|
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/generate_chianti_images.py
RENAMED
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/generate_real_sample_images.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/scripts/simulate_squad_execution.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/templates/asseverazione-tecnica.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lovarch_cli-0.3.0 → lovarch_cli-0.3.1}/lovarch_cli/squad/workflows/dal-brief-al-cantiere.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|