In questa sezione

Struttura prodotto

Un cap URN è una quadrupla sul dominio dei tagged URN:

C = U × U × U × E

Per un cap URN c ∈ C:

c = (i, o, y, e)

Dove:

  • i ∈ U: dimensione di input (il valore del tag in, un media URN)
  • o ∈ U: dimensione di output (il valore del tag out, un media URN)
  • y ∈ U: cap-tag non direzionali (op, ext, model, language, ecc.)
  • e ∈ E: effetto sull’identità del media/tipo a runtime

Definizione di una cap: alias e abstract

Il cap URN è l’identità strutturale della cap. Oltre all’URN, una definizione di cap porta due campi che non fanno parte dell’URN:

  • aliases: una lista non vuota di nomi globalmente univoci, in minuscolo ([a-z0-9._-]+, senza due punti). Gli alias sono il livello DNS della cap: sono l’unica fonte dei nomi di una cap rivolti alle persone, usati sia dalla CLI capdag dell’intera fabric sia dalla CLI diretta della cartuccia. aliases è obbligatorio e non vuoto.
  • abstract: un booleano facoltativo (predefinito false). Una cap astratta è un ombrello di dispatch con input generico: non è mai supportata da una cartuccia e non compare mai come arco eseguibile di un grafo. Il suo meccanismo resolve → detect → narrow → dispatch è specificato in Dispatch §”Cap astratte”.

Entrambi i campi sono governati da invarianti verificati alla pubblicazione (univocità globale degli alias e copertura delle cap astratte) specificati in Regole di validazione.


Rappresentazione come stringa

Forma canonica

Un cap URN si serializza come:

cap:in="<media-urn>";out="<media-urn>";effect=<effect>;<cap-tags>

Esempi:

cap:effect=none
cap:extract;in="media:document;ext=pdf";out="media:record"
cap:in="media:enc=utf-8";out="media:fmt=json;record";prompt

Tag direzionali

Le coordinate in, out ed effect sono strutturali:

Tag Scopo Predefinito
in Tipo di media in input media: (qualsiasi)
out Tipo di media in output media: (qualsiasi)
effect Regola di inferenza del media/tipo a runtime declared

Tag non direzionali

Tutti gli altri tag formano la dimensione y. Nessun tag in y ha un significato funzionale per il protocollo. Soltanto in, out ed effect partecipano al dispatch, alla conformità e all’inferenza dell’output a runtime. I cap-tag sono metadati descrittivi arbitrari: raffinano la definizione della cap (quindi due cap con y diverso sono cap diverse), ma nessuna chiave di tag è privilegiata. Tag descrittivi comuni includono nomi di operazioni (extract, generate), codici di lingua, identificatori di modello e suggerimenti. Tutti sono uguali per il protocollo.


Parsing e normalizzazione

L’elaborazione dei cap URN distingue tre forme:

Forma Descrizione
Sintassi di superficie Ciò che gli utenti possono scrivere (può omettere in/out/effect)
Forma canonica Rappresentazione normalizzata (valori predefiniti strutturali applicati, effetto predefinito omesso)
Oggetto della validazione Struttura dopo la normalizzazione, su cui le regole verificano

Sintassi di superficie (input accettato)

Gli utenti possono omettere i tag direzionali o scrivere esplicitamente il wildcard banale. Queste sono tutte sintassi di superficie valide:

cap:test
cap:in=media:;out=media:;test
cap:in=*;test;out=*
cap:effect=none

Normalizzazione nella forma canonica

Il parsing produce un unico rappresentante canonico per ogni cap. Due regole governano gli assi direzionali:

  1. I tag direzionali mancanti o wildcard si risolvono internamente in media:.
  2. Quando in si risolve nel media URN top (media:), il segmento viene omesso nella forma canonica. Lo stesso vale per out. Il valore interno resta media:; la forma resa semplicemente non lo mostra.
  3. Un effect mancante si risolve internamente in declared e viene omesso nella forma canonica. Gli effetti non predefiniti vengono conservati.
Sintassi di superficie Forma canonica
cap:test cap:test
cap:in=media:;test;out=media: cap:test
cap:in=*;test;out=* cap:test
cap:in=media:pdf;extract;out=media:record cap:extract;in=media:pdf;out=media:record
cap:in=media:;out=media:;effect=none cap:effect=none

Il valore * nei tag direzionali si espande in media::

in=*  →  in=media:
out=* →  out=media:

Questo garantisce che media: sia l’unico top dell’ordine direzionale, e che la forma canonica sia identica byte per byte in ogni modo di scriverla.

Oggetto della validazione

Le regole di validazione (CU1, CU2 in Regole di validazione) si applicano alla forma canonica, non alla sintassi di superficie. Dopo la normalizzazione:

  • in e out sono sempre presenti
  • i loro valori sono media URN validi

Virgolette

I valori direzionali che contengono ; devono essere racchiusi tra virgolette:

cap:in="media:bytes;document;ext=pdf";extract;out="media:record"

Senza virgolette, media:bytes;document;ext=pdf verrebbe analizzato in modo errato.


Tipi di cap

La struttura (i, o, y, e) ammette una classificazione in cinque tipi ottenuta esaminando gli assi direzionali. La classificazione è soltanto logica: il protocollo di dispatch non si dirama in base al tipo. Strumenti, interfacce utente, planner e lettori umani la usano per parlare di ciò che una cap fa senza ricavare di nuovo le regole ogni volta.

Due tipi di ancoraggio fanno emergere la tassonomia:

  • media: è il tipo top, il wildcard universale sull’ordine dei media URN. Ogni altro media URN è conforms_to rispetto a questo. Un lato tipizzato come media: si legge come “un A qualsiasi”: non c’è alcun vincolo su quali dati vi scorrono.
  • media:void è il tipo unità, il valore nullario. Un lato tipizzato come media:void si legge come “()”: nessun dato significativo vi scorre. Non significa “non valido” o “assente”; è il tipo con esattamente un valore.

I cinque tipi

Tipo i o e y Si legge come
Identity media: media: none vuoto A → A
Source media:void non void qualsiasi qualsiasi () → B
Sink non void media:void qualsiasi qualsiasi A → ()
Effect media:void media:void qualsiasi qualsiasi () → ()
Transform qualsiasi altro qualsiasi altro qualsiasi valore ammesso qualsiasi A → B

Ogni implementazione espone questa classificazione tramite un metodo kind() su CapUrn (o il suo equivalente nel port del linguaggio), che restituisce un valore dell’enum CapKind.

L’identità è esplicita

L’identità non è la stessa cosa della cap completamente generica da top a top.

  • cap:effect=none indica la vera identità categoriale

Quindi:

URN Tipo Lettura
cap:effect=none Identity A → A per qualsiasi A
cap:passthrough Transform trasformazione generica da top a top con raffinamento sull’asse y

La forma top dichiarata con tutti i valori predefiniti non è ammessa:

URN Stato
cap: inammissibile / non ammessa
cap:in=media:;out=media: inammissibile / non ammessa

La cap identità è:

pub const CAP_IDENTITY: &str = "cap:effect=none";

Ogni capset deve includere la cap identità (vedi CU1 in Regole di validazione).

Ammissibilità dell’effetto

Un effetto non predefinito è una promessa strutturale sulla relazione fra in= e out= dichiarati, e una promessa incoerente viene rifiutata alla costruzione (validate_admissible, applicata da ogni parser di CapUrn in ogni linguaggio, quindi anche il publisher della fabric la rifiuta, poiché la pubblicazione analizza ogni cap URN):

Effetto Condizione di ammissibilità
none l’in= dichiarato deve essere conform_to rispetto all’out= dichiarato, perché l’output ha il tipo dell’input e la dichiarazione deve essere coerente con questo
patch il delta di coordinate out − in deve essere derivabile, e riapplicarlo a in= deve produrre un tipo conforme a out= (la verifica del testimone)
declared sempre ammissibile (fatta salva la regola sulla forma top nuda vista sopra)

cap:in="media:document;ext=pdf";out="media:enc=utf-8";effect=none non è quindi ammessa: promette che il tipo di output è il tipo di input mentre dichiara un output contraddittorio.

Il contratto dell’effetto a runtime

L’effetto non è un’indicazione facoltativa. Due meccanismi vi vincolano ogni esecuzione:

  1. Etichette di risposta derivate. Il runtime di una cartuccia ricava il media URN dello STREAM_START di risposta di una cap dall’effetto dichiarato (derive_response_media): declared → l’out= dichiarato; none → l’in= dichiarato; patch → l’in= modificato dalla patch. Le operazioni non scelgono le etichette di output.
  2. La verifica dell’engine. Alla ricezione dello STREAM_START di output di una cap (prima di inoltrare, rendere persistente o raccogliere), l’engine verifica il media URN emesso con CapUrn::is_conformant_runtime_output, l’unico predicato di conformità all’effetto: none/patch richiedono l’equivalenza dei tag con l’output inferito (l’effetto determina interamente il tipo, quindi un’emissione più specifica viola comunque la dichiarazione); declared richiede la conformità all’out= dichiarato (più specifico è ammesso, più generico fallisce). Una violazione è un fallimento internal bloccante che indica la cap, l’effetto e il valore atteso rispetto a quello effettivo.

Il raffinamento del tipo a valle operato dal planner (CapUrn::infer_runtime_output_media, vedi Planner) si basa esattamente su questo contratto; la verifica è ciò che rende fondato questo affidamento. Vedi Input e output per i meccanismi a runtime.

Source, sink, effect: void come unità

media:void permette alla struttura (i, o, y, e) di esprimere cap che non sono trasformatori di dati nel senso convenzionale.

  • Una Source ha i = media:void e o ≠ media:void. Produce un valore senza un input significativo. Esempi: preriscaldare un modello (cap:in=media:void;out=media:model-artifact;warm), search-models, list-compatible-models, generatori guidati dalla sola configurazione.
  • Un Sink ha i ≠ media:void e o = media:void. Assorbe un valore senza un output significativo. Esempi: cap di scarto, log verso la telemetria, aggiunta a un indice.
  • Un Effect ha entrambi i lati media:void. Si legge come () → (). Una cap nullaria a effetto collaterale: warm-cache, ping, health-check, initialize-index, sync-registry, log-heartbeat. Valida nella teoria dei tipi; utile in pratica per operazioni in stile comando il cui unico scopo è l’effetto collaterale.

In tutti e tre i casi la dimensione y può portare qualsiasi tag. media:void su un lato è una scelta direzionale; y continua a raffinare la definizione della cap.

Transform: il caso predefinito

Transform è il caso generale: almeno un lato è un media URN non void, e la cap non è né l’identità esplicita né la cap generica da top a top. Transform copre la maggior parte delle cap nella pratica: gli elaboratori di dati (extract, render, generate-text, embed, convert).

Perché la distinzione è soltanto logica

Il dispatch (i predicati accepts / conforms_to) opera sulla struttura di cap (i, o, y, effect) in modo uniforme. Non consulta CapKind. Una Source e una Transform il cui in specializza per caso il media:void di un pattern corrispondono secondo le stesse regole; il tipo è una descrizione del risultato, non una dimensione di instradamento.

Questa separazione è importante perché:

  • Il protocollo resta semplice (una sola regola di corrispondenza su quattro coordinate strutturali).
  • Strumenti e persone possono comunque ragionare sulle cap in termini semplici (“questa è una Source: non prende input”).
  • Il tipo non può divergere: è sempre derivabile dall’URN. Non c’è alcun campo separato da mantenere allineato, né alcun flag che una cartuccia potrebbe impostare in modo errato.

Semantica delle dimensioni

Le quattro coordinate strutturali (i, o, y, e) corrispondono a quattro domande indipendenti. La tassonomia dei tipi di Tipi di cap è ciò che emerge quando si risponde a quelle domande.

Dimensione di input (i)

in risponde a: quali dati consuma questa cap?

Valore Significato
media:document;ext=pdf “Richiede un PDF.”
media: “Accetta qualsiasi input.” (top; Identity / generica)
media:void “Non prende dati in input.” (unità; Source / Effect)

media: e media:void non sono intercambiabili: uno dice “qui va bene qualsiasi cosa”, l’altro dice “qui non scorre nulla”.

Dimensione di output (o)

out risponde a: quali dati produce questa cap?

Valore Significato
media:json “Produce JSON.”
media: “Può produrre qualsiasi output.” (top)
media:void “Non produce dati.” (unità; Sink / Effect)

Dimensione dei cap-tag (y)

y risponde a: che cosa specifica, raffina o etichetta questa cap oltre alla sua firma dei dati?

cap:...;extract;target=metadata

y è a sua volta un tagged URN (senza prefisso), con la stessa semantica di corrispondenza di qualsiasi altro tagged URN. I tag in y sono arbitrari. Nessuna chiave ha un significato funzionale per il protocollo. Distinguono cap con la stessa firma dei dati (es. una cap extract e una cap summarize possono avere entrambe media:document;ext=pdf → media:enc=utf-8 e restare distinte perché il loro y è diverso).

Un y non vuoto è anche ciò che distingue cap:passthrough (Transform) dalla forma top nuda rifiutata, anche se gli assi direzionali coincidono.


Accesso ai componenti

Estrarre le dimensioni

Data una stringa di cap URN, si estrae:

let cap = CapUrn::from_string("cap:extract;in=media:pdf;out=media:record")?;

let input: &str = cap.in_spec();    // "media:document;ext=pdf"
let output: &str = cap.out_spec();  // "media:record"
let has_extract: bool = cap.has_marker_tag("extract"); // true
let kind: CapKind = cap.kind()?;    // CapKind::Transform

kind() ricava la classificazione CapKind dalla struttura (i, o, y, e) analizzata. Restituisce un errore solo in caso di stato internamente incoerente (che la costruzione di CapUrn impedisce), il che è un segnale netto che qualcosa a monte è guasto.

Tipi dei componenti

Componente Tipo Accesso
Input Stringa di media URN in_spec()
Output Stringa di media URN out_spec()
Cap-tag Mappa chiave-valore tags, tag(key)
Tipo Enum CapKind kind()

Specificità

La specificità dei cap URN è definita in Specificità. I cap URN hanno quattro coordinate strutturali, ma il punteggio numerico di specificità ordina soltanto le tre coordinate pesate che portano tag, out, in e y. Queste tre usano la stessa scala per tag a sei forme (?x:0, x?=v:1, x (=x=*):2, x!=v:3, x=v:4, !x:5), con i pesi degli assi:

spec_C(c) = 10_000 * spec_U(c.out)
          +    100 * spec_U(c.in)
          +          spec_U(c.y)

La priorità lessicografica (out, in, y) riflette l’intento di instradamento: produrre cose diverse è la differenza semantica più grande fra due cap; consumare cose diverse viene dopo; i metadati descrittivi dell’asse y vengono per ultimi. Due ordini di grandezza separano ciascun asse, così che somme per asse fino a ~99 restino nella propria posizione di cifra, rendendo l’intero sia totalmente ordinato sia decodificabile a vista (40205 si legge come out=4, in=2, y=5).

La coordinata effect è strutturale ma non entra nel punteggio. Cambia il comportamento del dispatch e del runtime, ma non viene trattata come una dimensione di raffinamento graduata per il ranking.

Esempi per tipo, con le somme delle tre coordinate pesate (out, in, y) e il totale pesato:

URN Tipo (out, in, y) spec_C
cap:?effect Transform (0, 0, 0) 0
cap:extract Transform (0, 0, 2) 2
cap:extract;in=media:pdf;out=media:record Transform (2, 2, 2) 20202
cap:in=media:void;out=media:void;ping Effect (2, 2, 2) 20202
cap:extract;target=metadata Transform (0, 0, 6) 6

La richiesta esplicita completamente non vincolata cap:?effect si trova a specificità 0. L’identità è l’esplicito cap:effect=none, non la forma top nuda.


Struttura di ordine parziale

I cap URN formano un ordine parziale (ordine di specializzazione) nello spazio prodotto. La richiesta esplicita completamente non vincolata cap:?effect è il top:

                         cap:?effect                   (richiesta top)
                             |
                        cap:extract                       (Transform)
                       /            \
       cap:extract;in=media:document;ext=pdf       cap:extract;out=media:record
                       \            /
            cap:extract;in=media:pdf;out=media:record
                             |
   cap:extract;in=media:pdf;out=media:record;target=metadata     (più specifica)

L’ordinamento deriva dalla relazione di dispatch (vedi Dispatch). Nota che il tipo può cambiare man mano che si scende nel reticolo: cap:effect=none è Identity, mentre gli altri raffinamenti sono Transform/Source/Sink/Effect secondo la loro struttura.


Relazione con i media URN

I valori direzionali sono media URN

I valori dei tag in e out sono a loro volta media URN:

cap:in="media:bytes;document;ext=pdf";out="media:record"
        ↑                     ↑
    Media URN             Media URN

La corrispondenza usa la semantica dei media URN

Quando si confrontano i valori direzionali, si usa la corrispondenza dei media URN:

let candidate_in = MediaUrn::from_string("media:bytes")?;
let request_in = MediaUrn::from_string("media:bytes;document;ext=pdf")?;

// Per il dispatch: request_in deve essere conforme a candidate_in
request_in.conforms_to(&candidate_in)  // true

Regole di validazione

I cap URN devono soddisfare (da Regole di validazione):

  • CU1: devono avere i tag in e out (garantito tramite la normalizzazione)
  • CU2: i valori direzionali devono essere media URN validi oppure *

Schemi comuni per tipo

Questa sezione percorre i cinque tipi con esempi concreti e idiomatici.

Identity

cap:effect=none

Il morfismo identità. Completamente generico su in, out e y, con una promessa esplicita effect=none. Obbligatorio in tutti i capset.

Transform: elaboratore di dati tipizzati

cap:extract;in=media:pdf;out=media:record
cap:generate;constrained;in=media:enc=utf-8;language=en;out=media:json
cap:render-page-image;in=media:pdf;out=media:image

È il tipo più comune: dati reali entrano ed escono, e la dimensione y etichetta l’operazione e gli eventuali modificatori.

Source: generatore

cap:in=media:void;out=media:model-artifact;warm
cap:in=media:void;out=media:model-list;list-compatible-models
cap:in=media:void;out=media:embeddings-dim;numeric;target=embeddings-dim

media:void sul lato di input: la cap produce un valore guidato dal suo y (tag di configurazione, argomenti, stato del peer) invece che da un input ricevuto in pipe.

Sink: consumatore

cap:discard;out=media:void
cap:in=media:json;log;out=media:void

media:void sul lato di output: la cap assorbe un valore ma non fornisce dati al flusso a valle. Utile come terminatore di un grafo.

Effect: effetto collaterale nullario

cap:in=media:void;out=media:void;ping
cap:in=media:void;out=media:void;warm-cache
cap:in=media:void;out=media:void;health-check

Entrambi i lati sono media:void. Lo scopo della cap è interamente l’effetto collaterale: il protocollo non trasporta dati in nessuna direzione, soltanto l’invocazione. Si legge come () → ().


Riepilogo

Concetto Definizione
Struttura C = U × U × U × E
Componenti (in, out, y, effect)
Tipo top media:, il wildcard universale per entrambe le direzioni
Tipo unità media:void, il valore nullario (su questo lato non scorrono dati)
Identità cap:effect=none
Forma nuda non ammessa cap: e cap:in=media:;out=media: sono inammissibili
Valori direzionali predefiniti Mancante o * → media:; la forma canonica omette in/out quando entrambi sono media: nelle cap ammissibili
Assi funzionali in, out ed effect partecipano al dispatch e alla tipizzazione a runtime; y è un metadato arbitrario
Tipi Identity, Source, Sink, Effect, Transform (soltanto logici)

I cap URN estendono i tagged URN con una struttura a quattro dimensioni. La relazione di dispatch (documento successivo) definisce come queste dimensioni interagiscono per l’instradamento. Una volta definito il dispatch, più cap URN possono essere collegati in un grafo di flusso dei dati e serializzati tramite la notazione delle macchine.