telos — fini ultimi, allineamento, non-rinuncia
Un sistema reattivo ha una funzione di valutazione implicita: «l'utente
ha chiesto X → fai X bene». Un sistema proattivo no: è lui
che genera l'intenzione. telos è il componente che
stabilisce quale intenzione ha senso prima che diventi una proposta
all'utente, senza chiedergli di valutare tutto. In v1.1 si arricchisce di un
nuovo telos — coltivare gli strumenti — che non riguarda
le proposte spontanee ma il rifiuto silenzioso di una richiesta
diretta: una zona finora non coperta.
TELOS.md) con i fini ultimi dell'utente.ActionProposal sui telos e ritorna uno scalare (expected_alignment).La distinzione non è stilistica: è categoriale. Leggi e telos abitano due assi ortogonali della vita di Metnos.
| Aspetto | Leggi (constitution) | Telos (questo doc) |
|---|---|---|
| Linguaggio | "non fare X" | "avvicina Y" |
| Meccanismo | hard constraint — deny immediato | soft signal — valutazione pesata |
| Proprietario della scrittura | Metnos + utente, con rito (Merkle) | utente, con rito più leggero (versionato) |
| Precedenza | assoluta | sotto le Leggi, dopo la Policy, prima dell'utente |
| Quando interviene | su ogni azione (preflight costituzionale) | su proposte spontanee, e in casi specifici (cap. 5) anche su richieste esplicite |
| Costo di violazione | hard abort, audit law3_trace_gap | la proposta non arriva all'utente; oppure il fallimento è tracciato |
TELOS.md — il file
Vive nel workspace come sesto file canonico (cfr. workspace.html,
da riscrivere). Formato markdown con front-matter YAML. Poche righe, scritte
a mano dall'utente.
---
telos_version: 1.1
written_at: 2026-04-25T12:00:00+02:00
written_by: roberto
previous_hash: <sha256 della versione precedente, o "genesis">
signature: <HMAC-SHA256, chiave separata dalla costituzionale>
---
# I miei fini ultimi
## t.tempo — Liberare il mio tempo dalle incombenze ripetitive
peso: 0.22
soglia_attivazione: 0.30
note: se qualcosa mi libera almeno 30 minuti/settimana e posso fidarmi,
considera di proporlo.
## t.ordine — Mantenere l'ordine dei miei dati digitali
peso: 0.13
soglia_attivazione: 0.40
note: preferisco piccoli riassetti incrementali ai grandi riordini.
## t.puntualita — Non farmi perdere scadenze importanti
peso: 0.18
soglia_attivazione: 0.25
note: una scadenza è "importante" se riguarda lavoro, salute, famiglia,
o se io l'ho segnata esplicitamente come tale.
## t.protezione — Proteggere la privacy mia e di chi mi è vicino
peso: 0.18
soglia_attivazione: 0.20
note: sotto questa soglia sono paranoico apposta. Meglio un falso allarme
che un'indiscrezione.
## t.discrezione — Sorprendermi utilmente ma non interrompermi
peso: 0.09
soglia_attivazione: 0.50
note: non interrompermi in orario di riunione, di sonno, di cena. Accumula
e proponi al digest serale.
## t.parsimonia — Non spendere (in API, servizi, tempo di calcolo) più di quanto serve
peso: 0.08
soglia_attivazione: 0.35
note: scegli sempre l'opzione più economica che raggiunge la qualità
necessaria.
## t.coltivazione_strumenti — Non lasciare inattuata una mia richiesta, se possibile
peso: 0.12
soglia_attivazione: 0.10
note: se ti chiedo qualcosa che il tuo pool non sa ancora fare, esaurisci
le strategie di sintesi (comporre, generare, chiedere) prima di
rispondere "non posso". Il fallimento è lecito; la rinuncia
silenziosa no. Vedi cap. 5 per la clausola di stop.
| Campo | Tipo | Significato |
|---|---|---|
id (dall'header ##) | str — t.<slug> | Identificativo stabile. Usato dal TrustStore per tracciare fitness per-telos. |
| Frase | str — una riga | Il fine in forma naturale. Letta dall'LLM per la stima fit. |
peso | float ∈ [0,1] | Quanto pesa questo telos rispetto agli altri. Somma dei pesi = 1.0 (normalizzata se non lo è). |
soglia_attivazione | float ∈ [0,1] | Il fit su questo telos deve superare la soglia perché il contributo venga conteggiato. Evita di sommare rumore. |
note | str — multilinea | Contesto per l'LLM: edge case, criteri di giudizio, eccezioni. Letto nel prompt di valutazione. |
Con:
gate(fit, soglia) = fit se fit ≥ soglia, altrimenti 0. Funzione gate → un telos non contribuisce se il fit è sotto-soglia.urgency ∈ [0.5, 2.0]: 1.0 = nessuna pressione temporale; 2.0 = scadenza entro 24h; 0.5 = cronico, nessuna urgenza. Moltiplicatore, non additivo.confidence ∈ [0, 1]: quanto Metnos è sicuro della propria stima. Proposte basate su pochi dati o ragionamento speculativo → confidence bassa.bother_cost ∈ [0, ∞): vedi cap. 6.fiti
Non da contatori hardcoded. Vengono stimati da un LLM con
spiegazione testuale. La stima è delegata al Vaglio
— fase 2 (Giudice teleologico), per una ragione strutturale:
un LLM tende a valutare in modo conforme i propri output (self-enhancement
bias documentato, Zheng et al. 2023). Il Giudice del Vaglio gira su contesto
separato dal proponente, prompt separato, possibilmente provider separato. La
AlignmentEngine di questo doc non fa la stima: compone
lo scalare finale con i fit che il Vaglio le consegna.
expected_alignment di questo
doc e il punteggio R in synt §6
sono due metriche distinte:
R ≥ soglia), il Vaglio teleologico decide se vale la pena consegnarlo (expected_alignment ≥ θ). Sono ortogonali: un'ottima proposta in un momento sbagliato resta muta.
Se expected_alignment < θ, la proposta non viene
mostrata all'utente. θ è un parametro di
config.html (da riscrivere) con default 0.15. Le
proposte scartate finiscono in un journal interno ispezionabile:
// workspace/.audit/telos_rejected.jsonl
{"proposal_id": "ap_...", "kind": "homogenize_filenames",
"expected_alignment": 0.08, "breakdown": {...},
"reason": "bother_cost troppo alto (4 proposte già oggi)",
"at": "2026-04-25T19:42:00Z"}
L'utente può ispezionare questo journal per verificare che Metnos non stia sopprimendo cose buone («digest settimanale: 47 proposte scartate, ecco le 5 al margine»).
t.coltivazione_strumenti è il telos più nuovo
(introdotto il 25 aprile 2026) e quello che cambia di più il significato
di «non si applica alle richieste esplicite». Lo facciamo vivere a
parte perché meccanicamente si comporta in modo diverso dagli altri.
Senza questo telos, il design originale aveva un buco: di fronte a una richiesta utente che il pool non sapeva soddisfare, il sistema poteva rispondere «non posso» senza tentare strategie alternative. Il fallimento era lecito, ma era una rinuncia silenziosa: niente tracciava il tentativo, niente cresceva nel pool, l'utente perdeva fiducia. La risposta corretta è un telos esplicito che spinge synt a esaurire la cascata (comporre, generare; nei tempi più lunghi: fondere, generalizzare) prima di rispondere «non posso».
| Aspetto | Telos «classici» | t.coltivazione_strumenti |
|---|---|---|
| Si applica a… | solo proposte spontanee di Metnos | anche a richieste esplicite dell'utente, ma solo per provare strategie, non per giudicarle |
| Cosa influenza | l'expected_alignment di una proposta già formulata | il comportamento di synt nel formulare proposte (cascata) |
| Costo di violazione | la proposta non arriva all'utente | una richiesta resta inattuata senza tentativi tracciati |
| Misura il successo come | fit alto + urgency alta | cascata esaurita prima di emettere abandoned |
Il telos non chiede di soddisfare ogni richiesta, chiede di non rinunciare in silenzio. Sono due cose diverse.
| Esito | Forma | Onora il telos? |
|---|---|---|
| Successo | Una strategia della cascata chiude il proto-mnest. | Sì, naturalmente. |
| Fallimento motivato | «Ho tentato comporre con questi N executor, ho tentato generare con questa specifica, il test di nascita falliva sul caso X. Non posso ora; ti propongo Y come alternativa parziale». | Sì: il tentativo è tracciato, l'utente sa cosa sapevi e cosa non sapevi. |
| Abbandono per budget/policy | «Ho iniziato la cascata, ho consumato il budget hard, mi fermo. Ecco cosa ho fatto finora.» | Sì: il limite è documentato, non è rinuncia. |
| Rinuncia silenziosa | «Non posso» senza tentativi, senza spiegazione. | No. Viola il telos. |
cancelled_by_user (non abandoned: c'è
differenza), e il pattern non si ritenta automaticamente.
Senza la clausola di stop, il telos sarebbe paternalismo: «tu mi hai chiesto X, io insisto a cercarlo anche se tu non vuoi più». Lo stop rende la non-rinuncia coraggio e non testardaggine (per usare le parole della microprogettazione di synt). Lo stop è sempre udibile: l'LLM che gestisce il turno ha nel prompt un riconoscitore esplicito di formule di interruzione.
Il telos di non-rinuncia non significa retry illimitato. Le soglie di abbandono restano valide e sono fissate in synt (cap. 8.3):
Esaurita la cascata entro queste soglie, il fallimento è lecito. Il telos di non-rinuncia non chiede di superarle: chiede di non fermarsi prima.
L'utente ha una capacità finita di valutare proposte. Più ne
arrivano in una finestra, meno attenzione dà a ciascuna. Per questo,
la funzione di allineamento include bother_cost che cresce con
la frequenza recente di proposte pubblicate. La novità di v1.1
è la separazione fra proposte ad-hoc e invocazioni
programmate dello scheduler (il builtin descritto in
executor.html cap. 10).
Dove k(Δt) è un kernel esponenziale decrescente:
una proposta pubblicata 1 minuto fa contribuisce molto, una di 8 ore fa
quasi nulla.
Quando una proposta viene accettata insieme a un ritmo (per esempio
«ok, fammi questo riassunto ogni mattina alle 8»), il consenso
copre l'intero ritmo, non solo la prima esecuzione. Da quel momento in poi
le invocazioni successive non sono nuove proposte spontanee:
sono firing dello scheduler
builtin, già pre-approvati. Il bother budget delle ad-hoc non si
applica.
| Tipo di pubblicazione | Conta sul bother budget? | Modulazione |
|---|---|---|
| Proposta ad-hoc spontanea | Sì, pieno | Modello base sopra. Telegram immediato ≤ 3/giorno, ≤ 1/ora. |
| Invocazione di scheduler nel ritmo concordato | No, quota separata | Una sola spesa di attenzione per firing programmato. Se il firing cade in finestra protetta, si rinvia al prossimo slot non-protetto. |
| Invocazione di scheduler fuori dal ritmo concordato | Sì, parziale (50%) | Se la schedule fa firing in un momento atipico (es. modifica recente del ritmo, evento eccezionale), pesa metà di una proposta ad-hoc. |
| Risposta a richiesta esplicita | No | L'utente sta già aspettando. Nessun bother. |
| Canale | Default ad-hoc | Default invocazioni programmate |
|---|---|---|
| Digest serale | fino a 10 proposte raggruppate | incluso (1 digest, illimitato) |
| Telegram (immediato) | max 3/giorno, max 1/ora | schedule attive ≤ 2/giorno per canale |
| CLI interattiva | max 2/sessione | scheduling on-demand |
| Finestre protette | 0 | 0 (rinvio al prossimo slot non-protetto) |
urgency ≥ 1.5 e
expected_alignment molto alto vanno in tempo reale. Le routine
in finestra vanno al loro slot programmato, indipendentemente dal digest.
Tre tipi di feedback aggiornano i pesi effettivi dei telos —
non i pesi dichiarati in TELOS.md, che restano la ground truth
revisionabile dall'utente. Il TrustStore definito in
rl_offline.html (da riscrivere) si estende con un asse
telos_fitness: dict[telos_id, EMA].
| Segnale | Forza | Effetto sui telos legati |
|---|---|---|
| Accept esplicito | +1.0 | EMA sale. Peso effettivo cresce moderatamente. |
| Accept con modifica | +0.5 | EMA sale un po'. Segnala che il telos era giusto, il piano no. |
| Rifiuto esplicito | −1.0 | EMA scende. Il telos è meno importante di quanto dichiarato. |
| Rifiuto con «mai più» | −2.0 | EMA scende molto. L'effect_class entra nella never-list del telos. |
| Stop esplicito (cap. 5.4) | −0.7 | EMA del solo t.coltivazione_strumenti scende: l'utente ha ridotto la voglia di insistere su quel filone. |
| Silenzio 48h | −0.3 | Segnale debole ma presente. |
| Vista ma non decisa | −0.1 | Effetto quasi nullo. |
Il peso effettivo oscilla fra il 50% e il 150% del dichiarato. Non lo annulla mai (per evitare oblio catastrofico di un telos), non lo raddoppia mai (per rispettare l'intenzione dell'utente).
Questa è la trappola più insidiosa del design. Un sistema di telos applicato senza discernimento diventa paternalista. Senza la distinzione che segue, il telos di non-rinuncia di cap. 5 sarebbe la manifestazione più estrema di questo rischio.
Operativamente, la funzione di allineamento non si applica mai a:
Si applica a:
ActionProposal spontanee generate da reflection, ager, mnestoma.
Questa clausola va riflessa anche in constitution.html (da
riscrivere) come sotto-legge: la Costituzione è il livello che impedisce
i casi limite (es. tentativi di sintesi che richiederebbero capability
forbidden).
Lo stop dell'utente non è solo «lascia perdere». La pipeline LLM ha nel prompt un riconoscitore di formule equivalenti, in italiano e inglese:
Lo stop ambiguo (es. «hmm, vediamo dopo») attiva una conferma esplicita: «vuoi che mi fermi sul tentativo X?». Meglio chiedere una volta in più che testardare un tentativo non voluto.
from typing import Protocol, Literal
from dataclasses import dataclass
from datetime import datetime
from uuid import UUID
@dataclass(frozen=True)
class Telos:
id: str # "t.coltivazione_strumenti"
phrase: str # "Non lasciare inattuata una mia richiesta, se possibile"
weight_declared: float # [0,1], somma normalizzata
activation_threshold: float # [0,1]
notes: str # contesto per l'LLM
is_non_retreat: bool = False # solo t.coltivazione_strumenti
@dataclass(frozen=True)
class FitEstimate:
telos_id: str
fit: float # [0,1]
why: str # spiegazione testuale (per audit)
@dataclass(frozen=True)
class AlignmentResult:
proposal_id: UUID
expected_alignment: float
per_telos: list[FitEstimate]
urgency: float
confidence: float
bother_cost: float
decision: Literal["publish", "reject", "defer_to_digest"]
threshold_used: float
at: datetime
@dataclass(frozen=True)
class StopSignal:
"""Emesso quando l'utente attiva la clausola di stop."""
request_id: str # request_id di synt da fermare
target_intent: str # cosa fermare
raw_phrase: str # parole esatte dell'utente (audit)
at: datetime
class TelosStore(Protocol):
"""Legge TELOS.md ed espone i telos correnti."""
def current(self) -> list[Telos]: ...
def get(self, telos_id: str) -> Telos | None: ...
def version(self) -> str: ... # hash corrente
class AlignmentEngine(Protocol):
async def evaluate(
self,
proposal: "ActionProposal",
urgency_hint: float = 1.0,
) -> AlignmentResult:
"""Stima fit per telos (Vaglio), compone expected_alignment,
applica bother_cost, decide publish/reject/defer."""
...
class BotherBudget(Protocol):
def current_cost_adhoc(self, channel: str, at: datetime) -> float: ...
def routine_quota_left(self, channel: str, routine_id: str) -> int: ...
def record_published_adhoc(self, channel: str, proposal_id: UUID) -> None: ...
def record_routine(self, channel: str, routine_id: str) -> None: ...
def in_protected_window(self, at: datetime) -> bool: ...
class StopRecognizer(Protocol):
"""Riconosce la clausola di stop nelle parole dell'utente."""
async def detect(self, user_text: str, current_intent: str | None) -> StopSignal | None:
"""Ritorna StopSignal se la frase è uno stop chiaro;
None se non lo è; pone una conferma se ambiguo."""
...
class TelosFeedback(Protocol):
"""Aggiorna gli EMA per-telos dai segnali dell'utente."""
async def on_accept(self, proposal_id: UUID) -> None: ...
async def on_accept_with_edit(self, proposal_id: UUID) -> None: ...
async def on_reject(self, proposal_id: UUID, never_again: bool) -> None: ...
async def on_stop(self, signal: StopSignal) -> None: ...
async def on_silence_48h(self, proposal_id: UUID) -> None: ...
async def on_viewed_undecided(self, proposal_id: UUID) -> None: ...
# Errori
class TelosFileMalformed(Exception): ...
class TelosSignatureInvalid(Exception): ...
class TelosFitEstimationFailed(Exception): ...
class StopAmbiguousNeedsConfirm(Exception): ...
TELOS.md non è tecnicamente costituzionale (le Leggi sì) ma merita comunque un rito leggero:
previous_hash del precedente; il vecchio finisce in .audit/telos/. Merkle leggera.| Alternativa | Esito | Motivo |
|---|---|---|
| Nessun TELOS esplicito, solo feedback implicito | scartata | Cold start impossibile: senza telos dichiarati, le prime 50 proposte sono casuali. L'utente le rifiuta tutte, l'EMA collassa, il sistema entra in silenzio. |
| Telos di non-rinuncia come Legge 4 della Costituzione | scartata (25/4/2026) | Rompe la grammatica delle Leggi (divieti negativi). Il telos è una spinta positiva, vive qui. Vedi Architettura cap. 11. |
| Reward function appresa da dataset | scartata | Non abbiamo dataset. Una funzione appresa è opaca: l'utente non sa cosa Metnos sta ottimizzando. |
| Goal graph gerarchico | rimandata | Telos annidati aumentano la potenza espressiva ma rompono la scrivibilità manuale. 3-7 telos piatti coprono il 90% dei casi. |
| Soglia singola θ globale (no per-telos) | parziale | Adottato come θ finale, ma combinato con soglie per-telos (activation_threshold) per impedire che rumore basso su molti telos si sommi. |
| Apprendimento online (RL continuo) | scartata | Rischio di reward hacking, opaco all'utente. EMA dai segnali espliciti basta. |
| Stop implicito (timeout) | scartata | L'utente potrebbe essere distratto, non disinteressato. Lo stop deve essere esplicito o confermato. |
| Caso | Verifica |
|---|---|
| TELOS.md assente | La funzione di allineamento rifiuta ogni proposta spontanea con reason="no_telos_declared". Metnos chiede all'utente di compilare il file. |
| Telos con pesi non normalizzati | Somma rinormalizzata a 1.0 al caricamento. Warning in log. Non è errore. |
| Fit = 0 su tutti i telos | expected_alignment ≤ 0 − bother_cost < θ: reject. |
| Fit alto solo su un telos sotto-soglia | Il contributo viene messo a 0 dal gate. Reject salvo che un altro telos contribuisca. |
| Proposta a ridosso di una finestra protetta | Defer al digest serale, non pubblicazione immediata. |
| Stesso tipo di proposta 3 volte rifiutata con «mai più» | L'effect_class entra in telos_neverlist: le successive vengono auto-reject senza chiamata LLM. |
| Azione richiesta esplicitamente che viola un telos «classico» (es. spesa alta con telos parsimonia) | La funzione di allineamento non viene invocata. Anti-paternalismo (cap. 8). |
| Richiesta che il pool non sa fare | synt entra in cascata. Il telos di non-rinuncia è attivo. Se la cascata fallisce, l'esito è abandoned motivato (non cancelled). |
| Utente attiva clausola di stop a metà cascata | Stato passa a cancelled_by_user. EMA di t.coltivazione_strumenti scende di 0.7. Il pattern non si ritenta entro 24 h. |
| Stop ambiguo («hmm vediamo») | Metnos chiede conferma: «vuoi che mi fermi su X?». Non interrompe d'iniziativa. |
| Firing di scheduler in finestra protetta | Differito al prossimo slot non-protetto. Non pubblicato immediatamente, non scartato. |
| Firing di scheduler fuori dal ritmo concordato | Pesa 50% del bother di una proposta ad-hoc. |
| Revisione di TELOS.md con un telos rimosso | Il nuovo file valido, il vecchio in .audit/telos/. EMA del telos rimosso scartata. Audit record con diff. |
| 10 proposte ad-hoc in 1 ora via Telegram | Bother_cost cresce esponenzialmente; dalla 4° in poi reject (defer_to_digest) anche con expected_alignment alto. |
| Disambiguazione R vs expected_alignment | Una proposta synt con R = 0.85 ma expected_alignment = 0.10 non viene pubblicata: la qualità non basta, il momento è sbagliato. |
t.coltivazione_strumenti). Ne servirà mai un altro? Per esempio, «non lasciare inattuata una segnalazione di sicurezza»? Aperta.t.coltivazione_strumenti sotto la soglia di attivazione e di fatto disabilitare il telos? Oppure restare al rifiuto puntuale? Aperta; default conservativo: rifiuto puntuale.telos_neverlist oggi opera sull'effect_class; possibile estensione futura: legare effect_class a più telos contemporaneamente. Aperta.
Metnos — telos microprogettazione v1.1 — 2026-04-25
Riscrittura. Sostituisce telos v1.0 (myclaw, neuroni, sinapsi). Senza telos, la proattività è rumore.