SOS · Sistema Operatiu Social

Els vedes

Les regles que aquest sistema s'ha imposat, amb el motiu escrit al costat. Cap no surt d'una bona intenció: cadascuna surt d'un error concret que ja s'havia comès, i explica què es va trencar.

97 vedes · generades des del codex, que és l'original. Cada veda té enllaç permanent: /vedes#veda-83.

Els vedes originals del kernel Antigravity segueixen intactes (Zero Redundancy · Frontend-only · Context-First AI · Knowledge Loop · W3C · JSON-LD · Glass-Box · Immutable State · Zero localStorage · Local-First). Aquest fitxer els amplia amb els compromisos que hem afegit en aquesta línia de treball.

11

Excel·lència W3C

#

Tota funcionalitat nova prova d'anar per una API W3C nadiua abans d'inclore qualsevol dependència. SubtleCrypto, WebRTC, WebSocket, BarcodeDetector, CompressionStream, SVG, IndexedDB, fetch, WebAuthn. Si una capacitat no és W3C encara però hi ha una proposta W3C activa, s'implementa el patró compatible.

12

Molekulon transmedia

#

Molekulon és el projecte narratiu que dóna cara a SOS: pel·lícula, sèrie, còmic, videojoc, música, performativa. La lògica és "elige tu propia aventura" — cada superheroi que entra a un molekulon obre una branca de la història. Cada branca real (jugada per una persona real) es reflecteix al ledger del SOS: els fluxos ficcionals i els reals són el mateix substrat.

13

Gamificació d'espècie social

#

L'entrada al joc = una aportació al fons cooperatiu. Els espais de creació i ús (biblioteca, banc de temps, MATRIU) són nivells del joc; guanyar = crear valor comptable per a la comunitat. Els Jodes (col·lectius local d'una xarxa) creixen com espècies socials naturals — quantes més interaccions recíproques, més biomassa cooperativa.

14

Fons local com a organisme d'inversió

#

El fons cooperatiu local es dissenya per convertir-se en la infraestructura d'inversió més potent del territori — no com a fons capitalista sinó com a organisme cuidador que reinverteix en l'ecosistema humà i natural. Cura + rendiment son la mateixa cosa perquè el sistema paga en valor comptable + reputació + capacitat, no en dividends extractius.

15

Codex vedes com a font viva

#

El codex evoluciona amb l'ús. Cada nova comprensió que la comunitat aprova (via sabiduria signada) s'afegeix aquí. Sense burocràcia — és el resum del que hem après.

16

Seny · Rauxa · Castells — el llenguatge local

#

L'anclatge mitològic dual Shiva ↔ Shakti que ja tenim al codex es tradueix directament als dos motors cognitius i culturals de Catalunya: seny i rauxa. Els fem servir com a llenguatge de mercat i com a marc pedagògic. No són sinònims literals; són anàlegs funcionals:

Molekulon = la síntesi seny+rauxa en acció: cèl·lula descentralitzada de 5-12 superheroi que baixa al terreny — cada persona amb el seu rol clar (seny) i tota la colla amb energia i risc compartit (rauxa). És la nostra forma d'entendre la colaboració dinàmica del segle XXI.

Aquest llenguatge dual (Shiva/Shakti · Seny/Rauxa · Pinya/Canalla) apareix a tot: al blog, a la landing, a la comunicació comercial, als noms de mòdul quan calgui. Coherència multi-cultural: qui prové de tradicions vèdiques hi troba Shiva/Shakti; qui prové de Catalunya hi troba seny/rauxa/castells; qui prové d'altres llocs hi troba llenguatge secular (estructura/energia/síntesi).

17

Mitologia origen — Mazinguer, Horacio i el Gran Molekulon

#

Enviats a la Terra pel Gran Molekulon (la molècula que governa les galàxies des de l'hiperespai), Mazinguer i Horacio tenen una missió aparentment impossible: reclutar un Comando de 150.000 superherois capaç de vèncer la Corporació Món Mort — l'entitat sistèmica que extreu valor sense retornar-lo, que trenca vincles i deixa les comunitats orfes.

Sense talents propis aparents (potser el seu superpoder és haver perdut el seu ego), Mazinguer i Horacio adopten l'estratègia dels Blues Brothers: munten una banda de música que recorre totes les poblacions de Catalunya i del món per identificar, un a un, els 150.000 superherois amagats a plena vista.

Superherois canònics presentats als còmics 1 i 2:

Rols simbòlics dins del sistema:

18

Missió de SOS i lloc del Comando Molekulon

#

SOS té una missió sola: connectar i empoderar comunitats locals. Cada eina — banc de temps, biblioteca de les coses, MATRIU, Guardians, Sabiduria, Slicing Pie — està al servei d'això.

El Comando Molekulon és una tribu creativa oberta — un dels projectes mestres de la MATRIU, no la totalitat del SOS. Qui vulgui pot participar; qui no vulgui, també pot fer SOS sense entrar-hi. Cromo, cançó, còmic i pel·lícula són l'embolcall narratiu que fa desitjable la infraestructura tècnica.

Superheroi = superpoders + superarmes:

Ambdós apareixen al cromo. Cada cromo té un nivell (Aprenent → Bronze → Plata → Or → Llegenda) amb reptes concrets per desbloquejar el següent.

Transmedia del Comando (canals):

Nivell territorial: quan l'usuari està a país/província/comarca, l'app mostra un panell d'incentiu que empeny cap avall (municipi/barri) — el valor real es crea a peu de carrer.

19

Panteó de 12 — reconeixement de competències

#

Adoptem el model de dotze arquetips de Pantheon.work (CC BY, «Exercici individual de reconeixement de competències i habilitats» v1.0) com a graella de competències del SOS i del Comando. Detall a knowledge/references/pantheon-12.md.

Tres principis que passen a ser veda:

  1. Les paraules clau són un pack, no una etiqueta. Ningú «és» informàtic: algú és més o menys referent d'un pack segons quantes de les seves paraules se li poden associar. La reputació al SOS es calcula així i no d'una altra manera.
  2. Els talents són lliures d'escala. El mateix talent val per propiciar una conversa entre dues persones i per organitzar un congrés de 3.000. Per això el mateix arquetip serveix a un barri i a una comarca, i no es fan models diferents per escala.
  3. És un inventari col·lectiu i viu, no una avaluació individual. Cap vista del SOS pot convertir això en una etiqueta fixa a la fitxa d'una persona. És una fotografia que ha d'evolucionar amb l'activitat registrada.

Regla d'implementació: l'evidència mana sobre el símbol. archetypeAffinity pondera primer el que s'ha fet (ledger, ofertes, rols), després el que es declara i, només en últim lloc i com a desempat suau, els signes o qualsevol altre senyal simbòlic. Un sistema que digui a algú qui és a partir de la seva data de naixement per sobre del que ha fet, trairia tot el model.

Els dotze fundadors del Comando encarnen un arquetip cadascun; els tres supervilans (Max Miedox, Mala Yerbax, Mc Greggor) són els tres modes de fallida d'una comunitat: la por que paralitza, el rumor que corroeix i l'extracció que buida. Serveixen alhora de narrativa i de diagnòstic.

Escala de reputació del Comando: Aprenent → Superheroi/na → Guardià/ana, i es puja amb evidència, mai amb antiguitat.

20

Veda del dossier personal

#

El dossier (CV, recursos, arquetips declarats, personatge) és material que la persona aporta sobre ella mateixa, i mai es barreja amb l'evidència.

Tres regles fixes:

  1. Privadesa estructural, no promesa. Es desa amb type:'dossier', dins de PRIVATE_DB_TYPES, i queda fora de state.nodes. Com que tot el que surt del navegador surt de state.nodes/state.entities, el CV no pot filtrar-se ni per error. El mateix val per a les narratives.
  2. La IA proposa, la persona accepta. Res del que detecti un lector (local o IA) s'afegeix sol al perfil: apareix com a etiqueta acceptable.
  3. L'ordre de prioritat no es toca. Evidència > declaració > símbol. evidenceBased només és cert si el guanyador té evidència real, no declaracions.

Detall a knowledge/vision/dossier-personal.md.

21

Veda dels mapes de valor i de la guia

#

Els mapes neixen sans o no neixen. La forma canònica d'un preset a DYNAMICS és pairs: cada fila és un vincle amb les dues direccions [A, B, tipus A→B, etiqueta A→B, tipus B→A, etiqueta B→A]. Escriure el retorn obliga a pensar-lo. flows queda per a l'excepció unidireccional legítima.

Llindars que cap preset pot baixar: reciprocitat 100%, densitat ≥45%, cap rol aïllat, barreja de tangible i intangible, concentració al rol més connectat ≤40%. Un mapa que neix ambre ensenya a la comunitat que ambre és normal.

vnaAudit(node) és l'únic lloc on es calculen aquests indicadors: la barra de salut, el reforçador i els tests miren exactament el mateix. Diagnosticar sense donar la següent passa és deixar la feina a mitges: per això la salut sempre ofereix openReciprocityFixer.

Cada context s'explica sol. Tota pestanya o vista nova ha de portar entrada a CONTEXT_GUIDES amb flow (3 frases del valor que hi circula), steps (comprovats contra el node real, no un temari) i lens (una frase per als 5 rols). Detall a knowledge/vision/guia-i-flux-de-valor.md.

22

Veda comptable

#

Es comptabilitza tot el valor aportat, i el valor és el que defineix el mapa de valor.

D'aquí en surten quatre regles que no es negocien:

  1. El mapa de valor és l'esquema comptable, no un diagrama il·lustratiu. El que compta com a valor en un node és exactament el que els seus fluxos declaren. Canviar el mapa és canviar què es compta.
  2. Un intangible declarat al mapa és comptabilitzable. Aquesta és la diferència entre reconèixer el treball invisible i limitar-se a anomenar-lo.
  3. Cap agrupació sense mapa. Territorial o temàtica, si una agrupació no té mapa de valor no té comptes, i sense comptes és un filtre de cerca, no una comunitat. Una federació temàtica no necessita cap primitiva nova: és un node amb metaskill, mapa, ledger i governança, lligat per un tema en comptes d'un límit administratiu.
  4. Els mateixos indicadors a qualsevol escala. vnaAudit val per a un banc de temps de barri i per a una federació de federacions, perquè la unitat d'anàlisi sempre és el mapa.

Corol·lari operatiu: qualsevol funcionalitat que reculli aportacions ha de dir a quin flux del mapa corresponen. Si no es pot dir, o el mapa està incomplet o la funcionalitat no aporta valor comptable.

23

Veda del reconeixement

#

La veda V22 diu que es comptabilitza tot el valor aportat. Durant temps això va ser cert al ledger i fals al reconeixement: reputationOf només mirava les aportacions de la MATRIU, així que qui feia 40 h a un banc de temps tenia exactament la mateixa reputació que qui no havia fet res.

Tres regles:

  1. Una hora val una hora, vingui d'on vingui. Les aportacions es compten a tots els nodes i ventures on la persona és membre. Cap dinàmica és de segona.
  2. El diner també és valor, però no es barreja d'amagat: es converteix a hores equivalents amb la tarifa per defecte de l'oracle (20 €/h) i es veu com a tal al camp effort.
  3. Canviar què es compta obliga a recalibrar l'escala. Si no, tothom salta de graó sense haver fet res nou i el reconeixement perd sentit. Els llindars de CROMO_TIERS i el repte de Llegenda es mouen junts, sempre.

Referència de cada esglaó: Bronze ≈ mitja dotzena d'aportacions reals · Plata ≈ una vintena en més d'una comunitat · Or ≈ una seixantena, referent del territori · Llegenda ≈ centenars, infraestructura humana.

24

Veda de la consolidació

#

Una xarxa que suma xifres ja calculades menteix. Si el Bages diu «49 h» i Manresa, que hi és a dins, diu «37 h», sumar-les dóna 86 h que no ha fet ningú: les 37 ja hi eren.

Tres regles:

  1. Cap consolidació es fa sumant consolidacions. Tota xifra es calcula un sol cop sobre el conjunt d'apunts, deduplicats per identitat (node · venture · apunt). measure(nodeIds) és l'únic lloc del sistema on es compta valor territorial; consolidate i consolidateSet només li donen conjunts.
  2. Dues columnes que no es toquen: propi i agregat. El que ha passat en aquest node i el que ha passat a sota mai es barregen en una sola xifra ambigua. El total tampoc és propi+agregat calculat a mà: es torna a mesurar sobre la unió. Coincideixen a l'arbre, però la coincidència és el resultat, no el mètode.
  3. Les persones no se sumen mai — s'uneixen. La mateixa persona aporta a diversos nodes; sumar comptadors la clonaria. Sempre Set de personKey.

Per què és prerequisit de les federacions temàtiques. Una federació no és una branca de l'arbre: és un conjunt de nodes lligats per un tema, i pot contenir alhora una comarca i un municipi de dins. consolidateSet ho resol declarant el node interior redundant (el seu valor ja entra per l'avantpassat) i mesurant una sola vegada sobre l'abast real. Sense això, cada federació que es creï inflaria les xifres de Catalunya.

25

Veda de la identitat portable

#

«La clau privada mai surt del navegador» sonava a virtut i era mitja veritat. També volia dir dues coses que ningú havia dit en veu alta:

Tres regles:

  1. La sobirania no és no poder emportar-te la teva clau; és que ningú més pugui. La còpia és xifrada amb contrasenya (PBKDF2 210k · AES-GCM), la custodies tu, i cap servei hi toca. Al fitxer no hi ha res en clar.
  2. Substituir una identitat és irreversible i es demana explícitament. importIdentity es nega si el dispositiu ja en té una de pròpia mentre no li passis overwrite.
  3. Un passkey no és una còpia de seguretat. És una segona via d'accés. Qui confongui les dues coses perdrà la identitat el dia que perdi l'aparell.
26

Veda de l'ancoratge

#

Ancorar un node no prova el registre. El registre públic travessa tots els nodes i totes les ventures; una empremta d'un sol node no diu res de la resta, i el botó «Ancora» del registre obria justament això — i des del tauler, sense node actiu, no obria res.

buildRegisterPack fa una arrel sobre totes les accions ordenades, amb una fulla per apunt. Canviar un sol valor mou l'arrel i el CID, i el pack publicat deixa de quadrar. Es verifica a la mateixa pantalla on es genera: un ancoratge que digui «signat» sense comprovar-ho no val res (veda V22 aplicada a la permaweb).

27

Veda de la col·laboració

#

Una eina que sincronitza però no diu amb qui no és col·laborativa: és una transferència a cegues. I una que exigeix copiar i enganxar un codi de dos quilobytes cada vegada no la farà servir ningú dues vegades.

Tres regles:

  1. Compartir no és copiar. L'aparellament viatja com a enllaç (#/sync/<codi>), que s'envia pel canal que sigui i s'obre d'un clic. El codi cru i el QR segueixen sent-hi per quan no hi ha canal.
  2. Sempre saps amb qui parles. Cada costat es presenta amb el seu did:sos i el nom amb què treballa, abans que res es fusioni. Obrir el teu SOS sencer a un codi anònim és el que fèiem fins ara i no s'ha de tornar a fer.
  3. La segona vegada no comença de zero. Es recorda l'últim company i quan va ser, de manera que tornar a aparellar és reconèixer algú, no saltar a les fosques.
28

Veda de la federació temàtica

#

Una federació no és una branca de l'arbre territorial: es forma quan et vincules a un tema. El model és del.icio.us — etiquetes una cosa i descobreixes qui més ha etiquetat el mateix. Aquí, en comptes de pàgines, són nodes: bancs de temps, biblioteques, cooperatives, MATRIUs.

Tres regles:

  1. El tema és la porta, no el permís. Etiquetar un node amb un tema ja et posa dins la federació; no hi ha alta, ni aprovació, ni cap llista de socis que mantenir. Sortir-ne és treure l'etiqueta.
  2. Etiquetar només val la pena si et retorna algú. Per això la pantalla de temes ensenya, al mateix moment, qui més treballa els teus temes. Una etiqueta que no connecta amb ningú és metadada morta.
  3. Una federació pot contenir una comarca i un municipi de dins. La veda V24 ho resol: consolidateSet marca el node interior com a redundant i el compta una sola vegada. Sense allò, cada tema nou inflava Catalunya — per això la consolidació era el prerequisit i no una millora a part.

Els temes viuen al node (node.themes), així que viatgen amb la sincronització com qualsevol altra dada: no calen ni servidor ni registre central de federacions.

29

Veda de l'acompanyament

#

Una incubadora sense mentoria és un repositori d'estructures. El SOS sabia quines ventures existien i quant valor movien, però no deixava cap rastre de la feina que les sosté: qui acompanya qui, què es va acordar, i què passa quan un projecte deixa de moure's.

Tres regles:

  1. Acompanyar no és «ajudar en general». Cada mentor porta el seu àmbit (jurídic, econòmic, tècnic, relacional, comunitari). Sense àmbit no se sap què s'està cobrint ni què falta.
  2. El temps d'acompanyament és valor aportat. Cada sessió registrada entra al ledger de la venture, signada i encadenada, i genera slices com qualsevol altra aportació. Si no fos així, l'acompanyament seria l'única feina de la MATRIU que no comptaria — i és justament la principal (veda V22). Una sessió sense hores segueix sent acta, però no inventa cap apunt.
  3. El silenci és un símptoma, i s'ha de veure. Una venture que fa setmanes que no es mou surt marcada a la Cartera i al tauler. Un projecte que mor no avisa; per això ha d'avisar l'eina. Les graduades no s'empaiten: ja no s'acompanyen.
30

Veda de l'ancoratge que es recorda

#

Ancorar era un carreró: generaves el paquet, el descarregaves, el pujaves a Arweave… i el SOS se n'oblidava. Al cap d'un mes no podies dir ni què havies ancorat ni si el registre d'avui encara quadrava amb allò.

Un ancoratge que no es pot tornar a comprovar no demostra res. La gràcia de segellar és poder-hi tornar. Tres regles:

  1. Descarregar un paquet és ancorar-lo, i queda a l'historial amb la seva arrel, les seves fulles i qui el va signar.
  2. On s'ha publicat també és dada. Hi ha un lloc per apuntar la transacció d'Arweave, el CID d'IPFS o l'event de Nostr — perquè si no, l'evidència viu només al cap de qui la va pujar.
  3. La comprovació es fa contra el registre d'avui, fulla per fulla: quantes accions segellades hi són encara, quantes han canviat, quantes n'hi ha de noves. I verifyPack accepta qualsevol dels tres paquets sense que qui el rep hagi de saber quin és.
31

Veda del perfil que s'edita

#

Tornar a prémer «Crea el meu perfil» obria un formulari en blanc i, en desar, tornava a publicar les mateixes habilitats i els mateixos objectes: dues ofertes de «Cuinar en grup» de la mateixa persona, dos trepants iguals. El que semblava una molèstia d'interfície era una font de dades brutes que embrutava el catàleg de tothom.

Tres regles:

  1. Cap formulari d'alta s'obre en blanc si la cosa ja existeix. Si hi ha perfil, s'obre amb tot omplert i marcat, i el botó diu «Desa els canvis». Els botons de tot el sistema (roadmap, llançador, paleta) diuen «Edita» quan toca dir «Edita».
  2. Desar reconcilia, no afegeix. S'afegeix el que és nou, es retira el que s'ha desmarcat i es deixa igual la resta — a tots els nodes on la persona és membre, no només a la població actual.
  3. Reconciliar no pot trencar el que un altre depèn. Un objecte prestat no es retira mai: esborrar-lo deixaria un préstec orfe. Tampoc es toca res que la persona hagi escrit a mà fora de les llistes.
32

Veda de la proximitat honesta

#

Perquè dos bancs de temps veïns puguin operar junts cal respondre «qui té això, i a quina distància». El catàleg estava tancat dins de cada node.

No s'inventen quilòmetres. Posar coordenades a 217 municipis de memòria seria fabricar dades i presentar-les com a exactes. El que sí que és cert és l'arbre territorial: mateixa població < mateixa comarca < mateixa província < a Catalunya. Això ordena bé i no menteix mai, i és el que es mostra: «a la teva comarca», no «a 23 km».

Si un node porta coordenades reals (lat/lon), llavors sí que es calculen quilòmetres de debò i afinen l'ordre dins del mateix nivell — i un projecte hereta les del seu municipi. Honest per defecte, precís quan hi ha amb què.

supplyIndex i searchSupply són el catàleg únic de tot el SOS: habilitats, objectes i demandes de qualsevol node, ordenats de més a prop a més lluny. És això el que fa que un SOS pugui operar amb un altre sense fusionar-se ni demanar permís a ningú.

33

Veda d'operar, no només mirar

#

Trobar una cosa no serveix de res si després has de navegar fins al node i buscar-la una altra vegada. Un catàleg que només mostra fa que dos bancs de temps veïns es mirin; un que deixa tancar l'intercanvi fa que operin.

Tres regles:

  1. Cada resultat porta la seva acció, i és la que li toca: una habilitat es demana en hores, una demanda s'ofereix a cobrir, un objecte lliure es demana en préstec, i un de prestat et posa a la llista d'espera. No un botó genèric.
  2. Buscar allà és voler-hi participar. Si operes amb un node del qual no ets soci, l'alta es fa sola. Demanar permís per donar d'alta algú que ja està actuant és burocràcia inventada.
  3. Operar mai treu res a ningú. Posar-se a la cua no aixeca el préstec de qui el té, i repetir-ho no et duplica a la llista.
34

Veda de les coordenades

#

Les coordenades reals no me les invento: hi ha tres vies i cap és aquesta.

  1. L'aparell — l'API de geolocalització diu on ets i ho desa a la teva població. És la més exacta i no depèn de ningú.
  2. Un fitxer obert — CSV o JSON municipi,lat,lon de l'ICGC, l'Idescat o OpenStreetMap. S'assigna als nodes que coincideixin de nom; no en crea cap de nou i diu quins no ha trobat.
  3. A mà, node a node.

I mentre no n'hi ha, l'eina ho diu: l'ordre és per proximitat territorial i no es mostra cap quilòmetre. Es rebutja el que no és coordenada — capçaleres, text, i qualsevol punt fora del planeta.

35

Res no interromp el que estàs fent

#

modal() buida #modalRoot sencer. Vol dir que qualsevol pantalla que s'obri per iniciativa de l'app destrueix la que tenies oberta, i amb ella tot el que hi havies escrit. El tour d'acollida arribava amb retard i feia exactament això: si mentrestant havies obert el registre d'hores i n'havies omplert la meitat, es perdia.

La norma: cap pantalla automàtica s'obre a sobre d'una d'oberta. Espera i torna-ho a provar; si al cap d'una estona segueixes ocupat, renuncia. Val més un tour que no surt que un formulari perdut.

36

El semàfor no és decoració

#

Cada iniciativa té un color, i el color surt de fets, no d'opinions:

Un risc amb pla baixa a ambre. Aquesta és la diferència que compta: apuntar un risc no és gestionar-lo, escriure què faràs sí. Un bloqueig demana qui el desbloqueja — sense nom no és un bloqueig, és una queixa.

La cartera de la MATRIU mostra el semàfor pitjor primer, i el tauler d'atenció puja els bloquejos encallats per damunt de tota la resta.

37

Comparar no pot ser una opinió

#

Qui coordina una MATRIU no pot obrir dotze pantalles per saber com va la promoció. La vista de cohort posa una fila per iniciativa amb les mateixes columnes: etapa, semàfor, preparació, backlog, hores, equity concentrada, salut del mapa, dies sense moure's, mentores i incidències.

Dues condicions, o la taula menteix:

  1. Cap xifra és nova. Tot surt del mateix estat que ja es podia llegir venture a venture. El semàfor de la taula i el de la cartera són el mateix càlcul; si un dia divergissin, la taula seria una segona veritat.
  2. La salut del mapa és un sol número comparable. Reciprocitat (45), densitat (25), barreja tangible/intangible (15), cap rol aïllat (10) i que no tot passi pel nucli (5). Un mapa amb menys de dos rols o sense fluxos puntua zero i ho diu: «Mapa incomplet», no un 0% que sembli un suspens.

L'embut diu si la MATRIU incuba o acumula: quantes a cada estadi i quin percentatge n'ha sortit. Vint idees i cap graduada no és una cartera, és un calaix.

I surt en CSV, perquè les memòries i les justificacions de subvenció es fan en full de càlcul, no mirant una pantalla.

38

Una subvenció no és un model de negoci

#

fundValue diu què s'ha mobilitzat, no si allò se sosté. Graduar una cooperativa que no sap si cobreix costos és enviar-la a tancar en sis mesos amb la gent que hi ha posat la vida a dins.

Tres decisions perquè el número no menteixi:

  1. Els ajuts no compten al llindar. Un ajut que tapa el forat fa que un model insostenible sembli sostenible fins al dia que s'acaba la convocatòria. El llindar es calcula només amb ingressos propis; els ajuts surten a part, com el coixí que són. Un projecte que quadra només amb ells és dependent, i se li diu quantes unitats li falten per deixar de ser-ho.
  2. Hi ha models que cap volum no salva. Si cada unitat es ven per sota del seu cost variable, vendre'n més accelera la caiguda. Això no és «falta poc»: és impossible, i es diu amb aquesta paraula.
  3. Sense volum no hi ha diagnòstic. Dir «cada unitat perd 0 €» quan no hi ha cap unitat és una frase buida que sona a anàlisi. Es diu incomplet i què falta.

El llindar és costos fixos ÷ marge per unitat. Separar fix de variable no és burocràcia: sense aquesta divisió no hi ha llindar.

A la porta de graduació, els tipus amb ànim de lucre han de tenir el llindar calculat i assolible. A un projecte comunitari no se li demana — però se li mostra igualment, que saber-ho evita ensurts.

El runway del fons és el capital dividit pel que es crema cada mes entre les iniciatives vives. Una graduada ja no crema el fons de ningú. I les que no tenen números es compten a part: el que no es compta no es crema menys.

39

Una persona és una, encara que estigui a cinc llocs

#

newMember encunyava un uid() nou cada vegada. La mateixa persona donada d'alta a la MATRIU, al banc de temps i a la biblioteca eren tres registres sense cap relació, units només perquè s'escriuen igual. Canvia-li el nom en un lloc i es partia en dues. Les seves hores, la seva equity i la seva reputació anaven partides amb ella.

Tres capes, de menys a més compromís:

  1. Triar d'entre qui ja hi és. knownPersons() és un índex derivat, mai desat de tota la gent que el SOS coneix. L'alta té dues portes i la primera és «Ja el coneixem». Triar-hi enllaça en comptes de duplicar.
  2. did a la fitxa. Qui vol reclama la seva fitxa signant {nodeId, memberId, did}. A partir d'aquí el que uneix els registres és la clau, no el nom. Una fitxa reclamada per un altre no es pot prendre: només qui la té la pot deixar anar. La comprovació que ho aguanta tot és signer.did === member.did. Sense ella, qualsevol podria signar una reclamació posant-hi el did d'un altre — i la signatura seria vàlida, perquè l'ha feta de debò. Que la signatura sigui vàlida no vol dir que digui la veritat sobre qui és.
  3. Fusió de duplicats. I aquí la regla que governa la resta:

La fusió no reescriu mai història signada.

Els apunts del ledger conserven el seu memberId original i es llegeixen per una taula d'àlies (node.memberAliases). Reescriure'ls trencaria la seva signatura i la cadena de hash, i la fusió deixaria de ser auditable. El que sí que es repunta és l'estat mutable —ofertes, objectes, mentors, leads, reserves—, que no porta la signatura de ningú.

La línia és aquesta: el que està signat es resol; el que no, es mou.

Equity, saldos, reputació i perfil resolen per àlies, així que fusionar reuneix les hores en comptes de perdre-les. La fitxa absorbida queda com a làpida amb mergedInto: no s'esborra res.

I dos did diferents sota el mateix nom no es fusionen: són dues persones que es diuen igual, es marca com a conflicte i es diu.

40

Una demanda no és una mena de cosa

#

El catàleg tenia tres categories paral·leles: habilitat, objecte i demanda. I això és un error de fons, no de vocabulari:

Una demanda no és una mena de cosa. És una direcció sobre una cosa.

Amb l'esquema vell, buscar «fusteria» eren dues cerques diferents — i partia en dues justament la coincidència que fa que passi alguna cosa. Qui la fa i qui la necessita no es veien mai a la mateixa pantalla.

La forma correcta:

D'aquí surt la banda de coincidències: les coses que algú ofereix i algú altre busca a prop. És l'única part d'aquesta pantalla que produeix un intercanvi tota sola.

Dues conseqüències que semblen detalls i no ho són:

  1. Una llista d'espera és demanda d'objecte declarada, i fins ara no es veia enlloc. Si tres persones esperen un trepant, qui en té un ha de poder-ho saber sense entrar a la fitxa de l'objecte.
  2. «Només disponibles» és sobre el que s'ofereix. Una demanda no està disponible ni deixa d'estar-ho: existeix. I en obrir una coincidència el filtre s'aixeca sol — amagar-ne la meitat faria de la banda una mentida.

I l'ordre no menteix: els encapçalaments de proximitat només surten quan l'ordre és per proximitat. Posar «📍 a la teva població» sobre una llista ordenada per nom seria dir una cosa falsa sobre com està ordenada.

41

Una càrrega parcial no és una càrrega correcta

#

updateAtles s'empassava els errors de cada paquet en un catch buit i després deia «L'atles ja estava al dia». Si tres dels cinc paquets no arribaven, l'usuari veia exactament el mateix missatge que si tot hagués anat bé.

Callar un error de xarxa no el fa desaparèixer: fa que algú es fiï de dades que no hi són. Ara es compten els paquets que fallen i es diu —«Atles incomplet · 3 de 5 paquets no han arribat»— i queda a updateAtles.last per si algú ho vol comprovar.

I la segona meitat del mateix defecte: la càrrega automàtica d'arrencada corria alhora que la manual, i totes dues fusionaven els mateixos paquets des de dos punts diferents. D'aquí que dues càrregues seguides donessin un nombre d'entitats diferent cada vegada (18 · 17 · 20 · 28). Amb un pany d'una sola càrrega en vol: 17 · 17 · 17.

La regla general: tota operació que fusiona estat compartit ha de ser una a la vegada, i ha de dir la veritat sobre què ha entrat i què no.

42

Qui exporta ha de saber què s'emporta

#

La còpia de la identitat (V25) resolia una pèrdua: esborrar el navegador destruïa el did:sos. Però la identitat sola no és el teu SOS. Si perds el navegador amb els nodes, els socis, el registre d'hores i la biblioteca, el que et queda és una clau sense res a obrir.

exportBackup s'emporta la base de dades sencera. I aquí hi ha la decisió que importa: la contrasenya en blanc és una opció legítima —hi ha gent que fa la còpia en un disc que ja té xifrat, o que necessita poder-la obrir sense recordar res— però un fitxer en clar amb la teva clau privada dins no és una còpia de seguretat qualsevol. Qui el tingui no només et pot llegir: et pot signar coses en nom teu, i les signatures del SOS són el que fa que el registre valgui alguna cosa.

Per això el botó no diu el mateix en els dos casos. Amb contrasenya: «Descarrega la còpia xifrada». Sense: «⚠ Descarrega SENSE xifrar», i l'avís diu exactament què implica. No es bloqueja, no es fa un sermó: es diu. I hi ha una casella per treure la identitat de la còpia, que és la resposta raonable per a qui vol les dades però no el poder de signar.

L'altra meitat és la restauració. Importar és sobreescriure, i ningú hauria de sobreescriure a cegues: primer es llegeix el paquet i es diu què porta —quants registres, de quin dia, si hi ha identitat a dins— i només llavors s'importa. Substituir-ho tot (esborrar el que hi ha abans d'entrar el nou) és una casella a part, apagada per defecte, amb confirmació.

I una cosa que semblava un detall: un fitxer malmès sense la llista de registres restaurava zero i deia que tot havia anat bé. Un || [] que amagava un fitxer trencat. Ara distingeix «no hi ha registres» de «no hi ha llista de registres», que no és el mateix.

43

Un apunt parla de dues persones; només una l'escrivia

#

Operar des d'un resultat de cerca deixava el moviment fet. Registres dues hores i ja està: el saldo de l'altre s'ha mogut, i l'altre no se n'ha assabentat. Dit sense embuts, es podien escriure hores en nom d'algú altre. En un grup de deu persones és una anècdota; en un de cent és el motiu pel qual la gent deixa de creure's el registre.

La temptació és fer que tot demani permís. Seria correcte i inservible: avui la majoria de fitxes no tenen ningú al darrere a qui preguntar —són noms que algú ha donat d'alta— i demanar-los un vistiplau que ningú pot signar és teatre.

Per això la regla és la mínima que resol el problema: cal el vistiplau de qui ha reclamat la seva fitxa. Mentre ningú no l'ha reclamada, el SOS es comporta exactament com abans i no es trenca res. Des del moment que dius «aquesta sóc jo» amb el teu did i una reclamació signada (V39), ningú escriu al teu nom sense que hi diguis la teva. La firma protegeix el nom de qui l'ha posat, i reclamar la fitxa passa a tenir una conseqüència pràctica i no només simbòlica.

Tres conseqüències que no són negociables:

I una que se sol oblidar: un did sense reclamació signada no dona dret a res. Copiar un did a un camp no és reclamar una fitxa —si ho fos, la protecció la podria activar qualsevol contra qualsevol.

44

Dues llistes raonables poden no parlar-se

#

El banc de temps té «petites reparacions de la llar». La biblioteca de les coses té «bricolatge i eines». Cadascuna és correcta al seu lloc i cap de les dues està mal feta. El problema apareix quan es creuen: qui ofereix reparar i qui busca un trepant no s'han trobat mai, encara que a la vida vagin sempre plegats — són la mateixa tarda de dissabte.

La sortida fàcil seria unificar les dues llistes. Seria un error: la categoria d'un objecte i la d'un servei no volen dir el mateix ni serveixen per al mateix, i fondre-les faria pitjors les dues pantalles per arreglar una tercera.

L'àmbit és la capa de sobre. No substitueix cap taxonomia, no en canvia cap fitxa, i no s'inventa equivalències: només uneix el que de debò es fa junt. Set àmbits fan de pont de veritat; vuit en tenen una sola banda, i així ha de ser —dir que «tràmits i paperassa» té un objecte equivalent seria fer-ho quadrar a la força, i un pont que va a lloc no es nota.

Dues regles que eviten que la banda de coincidències menteixi:

I una conseqüència d'interfície que era un defecte esperant: un àmbit no es pot escriure a la caixa de cerca. «Reparar i bricolar» no és el text de cap fitxa, així que clicar-hi i posar-ho al camp de text hauria donat zero resultats. Es filtra pel que és —un xip d'àmbit que es pot treure—, no per un text que ho imita.

45

Donar una cosa i deixar-la no és el mateix

#

Posar un objecte a la biblioteca no valia res al registre: es publicava i prou. Però una biblioteca de les coses produeix valor real, i el que no es compta no es pot ni certificar ni retribuir.

Hi havia dues coses confoses en una:

D'aquí surt la decisió que ho canvia tot: es valora per préstec, no d'una sola vegada. Una eina elèctrica prestada quaranta vegades no aporta el mateix que una tenda plantada dues, i una declaració inicial no pot saber quina de les dues serà. Cada retorn genera un apunt petit i signat a favor de qui l'ha posat a disposició, i el valor s'acumula amb l'ús real. Es compta al retorn i no en prestar, perquè el desgast encara no s'ha produït quan surt per la porta.

L'aprenent no és un cost. A la sessió de reparació hi ha dues aportacions, no una amb un beneficiari: qui ensenya hi posa ofici i transferència de coneixement —l'intangible que a la VNA sosté tota la resta— i qui aprèn repara de debò, i aquella reparació és valor lliurat a la comunitat. Els dos generen apunt. Un model fair no és el que reparteix bé al final: és el que compta bé pel camí, i que compta el que normalment no es compta.

I la regla que impedeix que tot això es converteixi en fum: un valor estimat no pot passar per diner real. Els objectes tenen el seu propi tipus d'apunt (objecte), amb estimate:true i la font de l'oracle a dins. No sumen amb les hores, no sumen amb el capital, i a l'equity entren com a aportació no dinerària ja valorada en euros —passar-los per la tarifa horària els hauria multiplicat per quinze. La pantalla diu sempre quins números són estimació i quins surten del registre signat. Un número inventat que sembli comptabilitat és pitjor que no tenir-lo.

46

Una persona no és un rol

#

roleOfPerson retornava un rol, i amb aquell rol es decidia la lent de tot el SOS. Hi fallaven dues coses alhora, i la segona és pitjor que la primera.

La primera és de model: la mateixa persona és superheroina al seu barri i mentora d'una MATRIU de la comarca a la vegada. La implicació no és un estat global —depèn del node i del que hi fa— i aplanar-la a un sol valor obliga a triar quina de les dues veritats s'esborra.

La segona és pitjor perquè era invisible: quan la casella no deia res, el rol sortia del primer node que es trobava recorrent la llista. Dues persones idèntiques podien acabar amb lents diferents per l'ordre en què s'havien creat els nodes. Un resultat que depèn de l'ordre d'iteració no és un resultat, és un accident.

Ara el rol es dedueix de l'evidència que el sistema ja tenia: qui acompanya ventures és mentora (mentorsOf), qui reclama o custodia un node és guardiana (govOf), qui aporta hores i objectes és superheroina. Cada rol porta el seu perquè —«acompanya 2 iniciatives», «3 aportacions · 1 objecte»— perquè un rol que no es pot explicar és una etiqueta.

Tres coses que això obliga a decidir bé:

47

Publicar no és publicar-ho tot

#

L'objectiu és que algú d'un poble premi un botó i el que ha decidit compartir quedi publicat perquè algú altre ho trobi. La temptació és òbvia: agafar el catàleg i penjar-lo. Però publicar «hi ha algú a Manresa que fa fusteria» no és publicar qui és, ni el seu telèfon, ni el seu registre. I publicar és irreversible a la pràctica: un paquet que algú ja ha copiat no es retira.

Per això la decisió del gra va abans que el botó, i és aquesta: el que surt és agregat. Categoria + municipi + quants. El paquet et diu on preguntar, no a qui. El node és la porta, i un node és una comunitat, no una persona.

D'aquí surten tres coses que semblaven detalls i no ho són:

I la mateixa porta funciona en tots dos sentits: el paquet que entra passa pel mateix sedàs que el que surt. Un paquet manipulat amb camps de més no pot afegir res de nou al SOS de qui el llegeix.

Finalment, la pantalla ensenya la taula sencera del que sortirà abans de deixar-te descarregar res. Qui no ho entengui no ha de poder prémer el botó sense haver-ho vist.

48

Una versió és un canvi, no una data

#

Publicar una vegada és fàcil. El problema és el segon dia: has canviat coses, i ni tu ni ningú sap què va sortir l'última vegada ni què ha canviat des de llavors. Sense això, «torna-ho a publicar» és una acció a cegues, i qui la fa no pot respondre la pregunta que importa —*què estic canviant del que la gent ja té?*

Cada publicació guarda el seu CID i el CID del seu pare, i d'aquí surten les tres coses que ho fan utilitzable: saber si el que tens ara és diferent del que vas publicar, veure què ha canviat, i poder tornar enrere.

La decisió que ho fa funcionar és petita i fàcil de fer malament: el CID no inclou la data de generació. Si la inclogués, construir el paquet dues vegades seguides en donaria dues versions diferents sense haver tocat res, i l'historial passaria a ser un registre del rellotge en comptes d'un registre dels canvis. Per la mateixa raó, publicar contingut idèntic a l'últim no crea cap versió nova: repetir el mateix amb una data diferent no és versionar, és fer soroll.

Tornar enrere no esborra res. Restaurar publica una versió nova amb el contingut d'una d'antiga, encadenada a sobre de la que hi havia. Esborrar la versió intermèdia seria mentir sobre el que es va publicar —i el que ja s'ha replicat no es desfà igualment.

I una que val per a qualsevol automatisme: l'automàtic no es salta la comprovació. Si verifyNoLeak troba una fuita, el versionat automàtic s'atura. Un automatisme que es salta la revisió perquè «ja anirà bé» és pitjor que no tenir-lo, perquè la fa a la teva esquena.

Finalment, l'automatisme es diu amb el que fa i amb el que no: estampa versions al teu historial, no puja res a cap servidor. Anomenar-ho «sincronització» quan el destí depèn de relés de tercers que encara no hi són seria vendre el que no hi ha.

49

Una capacitat que no hi és s'ha de dir, no suplir a qualsevol preu

#

El QR ja es generava, però escanejar-lo obligava a sortir a l'app de càmera del sistema, copiar un text llarguíssim i tornar a entrar. BarcodeDetector —W3C, natiu— ho resol des de dins.

El problema: no hi és a tot arreu. Comprovat en aquest entorn, el Chromium d'escriptori (Linux) no el porta; Android i ChromeOS sí. Hi havia dues sortides fàcils i totes dues dolentes: fer veure que va i deixar l'usuari clicant un botó mort, o encastar un descodificador de tercers de 250 KB al fitxer per cobrir un navegador que no és el que escaneja.

Perquè aquí hi ha el detall que decideix: el que escaneja és el mòbil. El d'escriptori és el que ensenya el codi. La capacitat falta exactament on no fa falta, i per tant la resposta correcta no és suplir-la sinó dir-ho: la pantalla anomena l'API que li manca, diu on sí que funciona, i deixa sempre a la vista el camí d'enganxar el text, que no depèn de res.

La mateixa regla val per als trackers WSS del codi de sala: es van provar i en aquest entorn no responen. Escriure codi de xarxa que no es pot verificar de cap manera és pitjor que no escriure'l —queda com si estigués fet, i el dia que falli ningú sabrà si va funcionar mai. Es queda al tram bloquejat, amb la prova anotada, i el que sí que funciona (enganxar, enllaç, QR) segueix sent el camí.

Dues coses més que un escàner ha de fer bé i és fàcil oblidar: apagar la càmera quan es tanca el modal per qualsevol via —també per fora—, i demanar només el format que vol (formats:['qr_code']) en comptes de tots.

50

Mesurar abans de patir, i comprovar que la prova comprova

#

500 nodes i 5.000 apunts —l'ordre de magnitud d'una comarca al cap de dos anys— per veure si el SOS s'ofega. No s'ofega: el render triga 33 ms, el segon 5 ms, i cap funció que recorri tot el SOS passa de 25 ms. Val la pena haver-ho mesurat precisament perquè el resultat és aquest: ara ja no cal optimitzar res «per si de cas», i qualsevol regressió futura es veurà contra un número i no contra una impressió.

La única cara és verifyNoLeak (211 ms), i és cara a posta: compara cada nom, contacte i títol del SOS sencer contra el JSON que sortirà. Es paga un cop per publicació i és el preu de no filtrar dades de ningú.

Dos defectes reals que només apareixen a escala i en pantalla petita, tots dos a 360 px —l'amplada de molts Androids, i per això test-mobilenav a 375 px no els veia mai:

I la lliçó que val més que les dues: una prova que passa per no haver-hi res no prova res. Les comprovacions d'accessibilitat corrien sobre la pantalla d'entrada buida i deien «0 camps sense etiqueta» perquè no hi havia cap camp. Ara carreguen dades i obren un formulari de debò —37 botons, 7 camps— i el test comprova primer que hi ha alguna cosa a comprovar. Un verd buit és pitjor que un vermell: el vermell almenys demana atenció.

De la mateixa manera, «aquest element surt de la pantalla» no és un defecte si el seu contenidor llisca a posta. La comprovació ha de ser sobre la pàgina, no sobre el fill.

51

L'app de gestió ensenya estructura; la de la gent ensenya el següent pas

#

El SOS que hem construït fins ara és l'app d'administració: mostra qui, on, quant i per què, i està feta per a qui coordina. Qui participa no necessita estructura —necessita el següent pas. Barrejar les dues coses és el que fa que una eina comunitària només l'acabin fent servir tres persones.

Per això les missions no són un panell més dins del tauler: són una portada pròpia, sense arbre, sense pestanyes i sense res per configurar. Una llista, i cada cosa amb un sol botó gros. La pantalla ho diu de si mateixa: «aquesta pantalla no et deixa configurar res, només fer».

Res d'això inventa dades. Totes les missions surten del que el sistema ja sabia —pendingInbox, dashboardAttention, supplyMatches, dueStatus, journeyProgress, els reptes del tier. El que canvia és què és el centre de la pantalla, i això és precisament el disseny.

Tres decisions que fan que sigui una llista de missions i no una llista de deures:

I la que decideix l'arquitectura: un sol fitxer, una capa de portada. No un segon index.html. Mantenir el zero-servidor i el fitxer únic era la condició, i el cost mesurat és una funció i un bloc de CSS —res comparat amb duplicar l'app.

52

El mur no és la idea, és la data

#

El que atura un projecte comunitari no acostuma a ser que l'idea no valgui: és la paperassa i el calendari de convocatòries. Una subvenció es perd per no haver mirat una data, no per no tenir raó. Per això el pipeline de finançament té una severitat que no té res més al tauler: és l'única cosa que caduca sola. Un termini passat no és una alerta, és una pèrdua, i es diu així —«ha passat fa 3 dies»— en comptes de continuar dient «pendent».

I una separació que sembla comptable i és ètica: el que has demanat no és teu. Demanat i concedit són dues columnes diferents, i una convocatòria denegada es queda a la banda del demanat. Sumar-ho tot és la manera més ràpida de fer un pressupost fals i prendre decisions sobre diners que no existeixen.

Els tràmits eren Zero Redundancy pur: cada PROJECT_TYPE ja portava la seva llista juridic i no servia per a res. Ara cada forma té els seus passos reals. Qui encara no ha decidit què serà veu les opcions; qui ja ho sap, només la seva.

I la decisió que costa més de prendre bé, a la formació lligada a l'etapa: el mòdul que toca a cada etapa surt a la llista de comprovacions però marcat com a soft, i no bloqueja graduar. Es marca a mà, sense examen ni servidor que ho certifiqui —i no es pot aturar ningú per una casella que ell mateix omple. Una porta que qualsevol pot obrir sol no és una porta; posar-la seria donar-li l'aparença d'un requisit a una cosa que és un suggeriment.

53

Graduar no és el final del camí

#

graduatedNodeId existia des del primer dia i no el llegia ningú. La venture sortia de la cartera i el que passés després no es tornava a mirar mai. Una incubadora que no sap què va passar amb el que va graduar no pot millorar el seu mètode: només pot repetir-lo.

Les revisions són a 3, 6 i 12 mesos, i la resposta la posa una persona. No es dedueix del registre a posta: un projecte pot tenir el ledger quiet i estar ben viu, i pot tenir moviment i estar mort. Automatitzar aquesta pregunta seria donar-li precisió a una cosa que no en té.

Tres decisions sobre com es compta, que és on això es fa honest o es fa propaganda:

I a les evidències, la mateixa lògica que a la formació: un checklist marcat és una promesa i un checklist amb proves és un expedient, però la cobertura de proves no és una porta. Demanar-la per graduar convidaria a adjuntar qualsevol cosa per passar-la, i llavors l'expedient deixaria de valer justament per al que serveix. De cada prova se'n guarda el hash, així es pot ancorar sense publicar-ne el contingut; i el fitxer no entra al node —viatjaria pel sync i pel pack públic— sinó a un registre local propi, amb el tipus evidence dins de PRIVATE_DB_TYPES. Al backlog només hi queda el hash i el nom.

54

Un cas particular al lloc d'una plantilla

#

Catalunya no era un cas d'ús del SOS: estava soldada en sis llocs del fitxer. Els nivells (província, comarca, municipi, barri), els rols institucionals del mapa de valor de qualsevol país (Generalitat, Diputacions, Consells comarcals), els tipus d'entitat, el catàleg territorial, els resolutors de cadena amb pais:'Catalunya' escrit a mà, i una funció d'esquelet d'un sol país.

Res d'això era un error de programació —tot funcionava. Era un error de model: hi havia un cas particular al lloc on hi ha d'haver una plantilla. La prova és què passava en clicar «nou país»: sortia un node buit, l'autocompletar oferia una sola opció (Catalunya), i el mapa de valor d'Euskadi naixia amb un rol anomenat «Generalitat».

La separació que ho resol:

Un cas d'ús que no es pot obrir, editar ni copiar no és un cas d'ús: és documentació.

El segon cas és el que ho demostra. Un model sol no prova res —el codi segueix podent tenir supòsits d'un sol país amagats. Euskadi els destapa tots alhora: el nivell intermedi no és una província sinó un Territori Històric amb Diputació Foral i Juntes Generals; el de sota són comarques a Bizkaia i Gipuzkoa però quadrilles a Araba; i el mapa de valor va al revés que el català, perquè amb el Concert Econòmic són les Diputacions les que recapten i aporten al Govern Basc. Un mapa que ho dibuixés a l'inrevés seria fals encara que quedés més simètric.

D'aquí surten dues regles més:

I una de dades, no de codi: els topònims no es tradueixen. Els noms van com són oficialment —bilingües quan ho són— i el que és parcial es diu que és parcial. La llista de municipis d'Euskadi porta els de més població de cada comarca perquè l'autocompletar sigui útil; posar-ne 251 de memòria seria inventar-ne uns quants.

55

El fons cooperatiu ha de tenir porta, i no pot mentir

#

El SOS deia a la seva pròpia documentació que la destinació és un fons cooperatiu, i li posava xifra i any. A l'app, el fons era una funció dins d'una pestanya d'un node MATRIU: tres clics des de la portada, i només si aquell node existia. Un territori amb tres bancs de temps i dues biblioteques movent hores cada setmana tenia un fons de zero, perquè fundValue només sabia comptar el que penjava d'una incubadora.

El múscul d'un territori no és la seva MATRIU: és tot el que hi ha a sota. El fons es mesura sobre l'àmbit sencer (scopeIds + el mateix desduplicat que fa servir measure, perquè dues xifres del mateix fons són pitjor que cap).

Tres regles que la pantalla no pot trencar:

I la cobertura al costat del fons, perquè no són la mateixa pregunta: el fons diu quant s'ha mogut; la cobertura diu on encara no s'ha mogut res. Sense la segona, la primera només és una notícia. Una llista de regions buides no és un retret: és l'única llista que diu on val la pena trucar.

56

Un rànquing en una eina de suport mutu es pot girar en contra

#

Posar un podi on la gent s'ajuda té dues maneres de sortir malament, i totes dues s'han de tancar al càlcul, no amb un text d'advertència a sota:

A més, el que és de fa temps pesa menys (la meitat cada 180 dies). Sense això, el podi se'l queden per sempre els qui hi van ser primer, i deixa de dir res sobre qui mou la xarxa ara.

I una regla d'interfície que és inseparable del càlcul: cada posició ha de poder dir per què hi és. El «perquè» es construeix al mateix lloc que el número —si surten de llocs diferents, un dia deixaran de dir la mateixa cosa. Un número sense desglossament és una autoritat que ningú pot discutir.

«En línia» és una altra cosa i es diu diferent. Sense servidor no hi ha llista de connectats: només se sap de qui té un canal obert amb tu. Dir «en línia» de ningú més seria mentir, així que la resta surt com última activitat, i la pantalla explica per què no pot dir-ne més.

57

Un xat que no diu de què parla és un grup de WhatsApp més

#

Una eina de gestió comunitària amb xat general acaba tenint el mateix problema que el grup de veïns: es parla molt i no queda rastre de a què es referia. Sis mesos després, «això ho vam decidir al xat» no es pot comprovar.

Per això aquí la conversa penja d'un node i cada missatge pot citar una peça concreta: un flux del mapa de valor, un apunt del registre, una tasca, una iniciativa, un objecte, una oferta. La discussió sobre les hores del taller viu al costat de les hores del taller.

Tres regles que ho sostenen:

I una de mida: es reté una finestra de missatges. Un xat sense límit fa créixer el node per sempre, i el sync l'envia sencer a cada canvi.

58

Un relé que pot ser l'amo de la xarxa no és un relé

#

Sense servidor, «en línia» només pot voler dir «connectat amb tu ara». Per tenir una llista de debò cal que algú relaixi la presència, i el perill evident és que aquell algú acabi sent l'amo. Un relé només és acceptable si està dissenyat perquè no pugui ser-ho:

I una que és de codi, no de disseny: s'implementa a pèl sobre WebSocket, sense cap llibreria. El SOS ha de continuar sent un sol fitxer que funciona obert des del disc, i una dependència de CDN ho trencaria just el dia que la CDN no hi sigui.

Com es prova. Contra un servidor de mentida que parla el protocol de debò (SOS/tests/relay-mock.mjs), amb dos navegadors a la mateixa sala. Comprovar només que l'URL es construeix bé no prova res.

59

Unir persones pel nom corromp dades en silenci

#

joinNode, knownPersons, personProfile i el rànquing unien registres pel nom normalitzat. Dues maneres de fer mal sense que res avisi:

El did ja hi era des de V39: claimMember signa {nodeId, memberId, did}. El que no es feia era emparellar per ell. Tres regles:

I la que ho fa reversible: res d'això reescriu història signada. Els apunts conserven el seu memberId i el seu who originals; la identitat es resol en llegir, no es reescriu. Per això reclamar una fitxa vella la uneix a la persona sense tocar cap signatura ni cap cadena de hash.

60

Publicar sense descobriment no és publicar

#

supplyPublicPack generava un paquet agregat, comprovava que no filtra res, el versionava amb CID… i el deixava al teu disc. Ningú el podia trobar. Tota la feina difícil feta i el resultat, invisible.

La solució ja existia al mateix repositori i ningú se n'havia adonat: l'atles és un repositori públic servit per CDN, on s'aporta amb una pull request i d'on qualsevol baixa amb un fetch. Públic, versionat, amb historial, auditable, gratis, i amb revisió humana abans de publicar-se. L'oferta comuna fa el mateix camí.

Dues regles que no es poden relaxar:

I es diu el que és: això no és permaweb. Si algú esborra el repositori, desapareix. És públic, versionat i amb un CID que prova integritat —molt més que tenir-lo al calaix, i menys que Arweave. El mateix fitxer es pot pinnar després; ja porta el seu CID.

61

No es diu «verificat» del que no s'ha verificat

#

El SOS signa amb did:sos i ancorava amb la clau Nostr de l'extensió del navegador, i res no deia que fossin la mateixa persona. Un ancoratge provava que algú amb una clau Nostr havia publicat aquell hash, no que fos qui el va registrar. Per a un registre d'usuaris a la permaweb, aquest era el forat.

El pont és una afirmació signada dues vegades: un registre que diu «el did D i la clau N són la mateixa persona», firmat pel did i publicat sencer com a event Nostr firmat per N.

I aquí la part que importa més que la funcionalitat: la firma Nostr no es pot verificar dins del SOS. És Schnorr sobre secp256k1 i SubtleCrypto no en sap; caldria una biblioteca, i el SOS és un sol fitxer. Davant d'això hi ha dues sortides i només una és acceptable:

I dir també què sí que la prova: els relés rebutgen els events amb firma invàlida. Si el pont és publicat i acceptat, la clau Nostr hi va signar. Això és una prova de debò i s'explica com a tal, sense confondre-la amb una comprovació local.

62

Una eina que només creix acaba sent inservible

#

El SOS ha crescut sempre per addició i no s'hi ha tret mai res. Cada tanda hi posava una portada, una pestanya o una entrada de menú, i com que ningú ho mesurava, ningú ho veia. Tres coses que es van trobar en mirar-ho de debò:

D'aquí surten dues regles:

Una sola manera de tornar. Una funció, un text, un comportament (homeBackBtn). Quan cada pantalla s'inventa la seva sortida, la navegació es parteix i qui es perd no sap per què.

Sostres declarats, no límits tècnics. SOS/tools/check-kiss.js corre a cada PR i mesura el pes gzip, que cap pestanya es quedi sense guia, que el hook de test no tingui duplicats, i quantes portades, rutes i entrades de menú hi ha. No prohibeix créixer: obliga que créixer sigui una decisió que algú pren i escriu al commit. Aquesta fricció és tota la seva utilitat.

Va a tools/ i no als tests de Playwright per un motiu que val la pena saber: els tests de Playwright no corren al CI. El npm test del workflow no fa res perquè no hi ha package.json, i per això el CI sortia verd comprovant només sintaxi. Una guarda que ha de mossegar ha d'anar on de debò s'executa.

63

Una llista plana llarga és un calaix, i el que no és de ningú no es fa

#

Dues coses que la guarda de KISS va treure a la llum en comptar de debò.

El llançador tenia 32 accions en una sola columna. Ningú les havia comptat mai —cada tanda n'hi posava una, i com que la llista no protesta, la llista creixia. Trenta-dues entrades sense cap ordre no són un menú: són un calaix on es busca amb la vista una per una, i on la trenta-dosena no la troba ningú perquè ja s'ha desistit a la desena.

La sortida no era treure'n. Cadascuna serveix a algú i esborrar-ne seria decidir per aquell algú. El que faltava era contestar la pregunta que es fa qui obre el llançador, que no és «quines accions hi ha» sinó «què hi puc fer ara». Set grups (jo · comunitat · govern · xarxa · proves · relat · sistema) i un filtre per a qui ja sap què busca. La mateixa llista, i es troba.

Dues regles que la guarda comprova i no es poden saltar:

I la feina que no és de ningú. Les missions només sabien mirar què t'espera a tu: el que tens pendent, el que has de confirmar, el teu camí. Tot el que el SOS ja diagnosticava sobre la xarxa —regions sense cap dinàmica, mapes de valor amb reciprocitat sota el 50 %, rols aïllats— es calculava, es dibuixava en un panell, i no li tocava a ningú. Un forat que és de tothom no és de ningú, i per tant no es tapa mai.

Ara són missions de veritat (MISSION_KINDS.xarxa), amb dues condicions:

64

Un ordre global vol dir un amo; la triple entrada no en necessita

#

El ledger tenia una sola cadena per node: cada apunt encadenat amb l'anterior, fos de qui fos. Semblava més fort i era més fràgil, perquè obliga a un ordre global —i un ordre global entre gent que apunta sense estar connectada només se sosté si algú diu qui va primer. Aquell algú és un servidor, i un servidor és un amo.

Sense amo, l'única sortida que quedava era que en sincronitzar guanyés un i es perdés l'altre. Es va comprovar amb una sonda: es perdien hores signades, i també socis. Sense avís i sense rastre.

La sortida no és triar quina cadena guanya. És comptabilitat de triple entrada: el que dona, el que rep, i el rebut que tots dos guarden signat. El rebut és la tercera entrada i és la que mana. D'aquí surten dues regles:

I la conseqüència que val més que la funcionalitat: això fa el sistema antifràgil. Amb la cadena única, cada còpia de més era una oportunitat de conflicte i créixer feia el registre pitjor. Amb el rebut compartit, cada persona que en guarda una còpia és una prova de més. Perdre el telèfon deixa de ser perdre la feina, perquè qui era a l'altra banda de l'intercanvi també la té. Que la xarxa creixi deixa de ser un risc a gestionar i passa a ser el que fa que la teva hora sigui indiscutible.

I una que és de tracte, no de codi: no es diu que una cadena antiga està trencada quan només és d'un altre esquema. verifyLedger prova per autor i, si no quadra, com a cadena global; els ledgers escrits abans d'això segueixen sent vàlids i es diu de quin mode són. Marcar de corrupte el que ningú ha tocat és la manera més ràpida de fer que algú deixi de refiar-se del verificador.

65

Un canal que exigeix simultaneïtat és un canal que no s'usa

#

El relé dona presència en viu, i per això demana que dues persones hi siguin alhora. En un poble això no passa gairebé mai: la gent obre l'app el diumenge al vespre, i no totes el mateix diumenge. Fèiem descansar la convergència de la xarxa sobre una coincidència que no es produeix.

El repositori ja feia de bus asíncron dues vegades —l'atles i supply/— i ningú ho havia llegit com el que és: durable, versionat, amb historial, auditable i gratis. Cadascú hi deixa el seu quan pot; qui arriba després se'l troba.

Això només és possible gràcies a la veda 64. Amb apunts idempotents que s'uneixen sense conflicte, un directori al qual tothom afegeix convergeix sol. Amb la cadena única hauria calgut decidir qui va primer —i tornaríem a necessitar algú que ho digués. L'ordre de les dues vedes no és casual: la primera és el que fa possible la segona.

I és la peça antifràgil per excel·lència: cada clon, cada fork i cada CDN que el serveix és una còpia més del registre.

Tres regles que eviten que això sigui una porta oberta:

I una que és de tracte: un paquet que no es pot obrir no és un error. És d'un altre node i és el més normal del món. Es compta a part i es diu «xifrat amb una clau que no és la teva», no «ha fallat».

66

Simplificar és decidir per on comences, no esborrar el que hi ha

#

Tothom veia el mateix: fins a 13 pestanyes al node, 32 accions al llançador, 17 rutes. Una persona que ve a apuntar tres hores al mes n'ha de fer servir sis, i les ha de trobar entre totes les altres. La informació hi era; el que no hi havia era una manera de saber quina et toca a tu.

I les peces per saber-ho ja hi eren, sense connectar: ROLE_JOURNEYS sap què fa cada rol, activeRoleId sap quin ets ara, i cada guia contextual porta la seva lens. El que faltava era que allò decidís, i no només ressaltés.

La temptació era treure funcions. Seria un error i ja el vam evitar a la veda 63: cadascuna serveix a algú, i esborrar-ne és decidir per aquell algú. El que sí que es pot decidir és per on comences.

Tres regles, perquè simplificar no acabi sent amagar:

I una salvaguarda que val per a tot filtre: si el filtre deixaria la llista buida, no es filtra. Val més ensenyar-ho tot que ensenyar el no-res.

67

Una xifra inflada i incompleta és pitjor que cap xifra

#

El toast deia «Sincronitzat · N canvis», i aquell N mentia dues vegades: comptava la mateixa fusió diverses vegades —una pel xat, una per cada col·lecció, una pel node sencer— i no comptava el que s'havia sobreescrit. Un número així no és una aproximació: és una invitació a refiar-se'n.

Des de la veda 64 els apunts ja no es perden —s'uneixen—, però la resta del node segueix resolent-se per LWW: el mapa de valor, el tauler, el nom. Això no és cap defecte a tapar; per a camps que es reescriuen sencers és la decisió correcta. El que no és correcte és no dir-ho. Si en sincronitzar el teu mapa de valor ha estat substituït pel de l'altre, ho has de saber en aquell moment, no descobrir-ho un mes després.

D'aquí surt la regla: el que s'uneix i el que se substitueix no es barregen mai al mateix comptador. Un «+3 a ledger» i un «mapa de valor substituït» són notícies de signe contrari, i sumar-les en un sol número les amaga totes dues.

I el corol·lari de tracte: quan alguna cosa s'ha substituït, no n'hi ha prou amb un toast. Es diu a la cara i es pot mirar què i on. Sense oferir cap botó de desfer que no podríem complir.

68

Qui no es queixa, plega

#

No hi havia cap camí per dir «això s'ha trencat». El senyal del que falla només arribava si algú et trucava, i en una beta amb gent que no et coneix això vol dir que no arriba. Quan una eina falla dues vegades a algú que no hi té cap compromís, aquell algú no obre una incidència: deixa d'apuntar hores i no torna. I nosaltres ho llegim com «no els interessava».

Per això una cosa que costa una tarda anava abans que coses molt més grans: és la que converteix la beta en informació en comptes d'anècdotes.

Dues decisions la fan usable de debò:

Context, no contingut: comptadors i identificadors tècnics. El que ajuda a reproduir un error és saber que hi havia 40 socis, no com es diuen.

69

Designar no és custodiar

#

Si qui sosté el node perd el telèfon, la història del node se'n va amb ell. No és un cas rebuscat: és el cas normal al cap de dos anys. Una persona plega, canvia de mòbil, o simplement se li espatlla — i amb ella marxen les hores que ha apuntat tothom.

Les peces hi eren: exportBackup i els envelopes xifrats per membre de la veda

  1. El que faltava era el rol: algú, a part de qui el sosté, que en tingui

una còpia.

I no va caldre inventar cap rol nou al sistema de rols. És una responsabilitat dins del node, i viu com una marca al soci. Un rol global diria que aquella persona custodia «en general», i el que custodia és aquest node. Quan una responsabilitat és local, fer-la global és perdre informació, no guanyar-ne.

La regla que evita que això sigui teatre: designar no és custodiar. Una persona marcada que encara no ha rebut cap còpia no compta com a còpia, i es diu així de clar. Un comptador que digués «2 custodis» amb zero còpies entregades seria pitjor que no tenir-ne cap: et faria dormir tranquil.

I restaurar és unir, no substituir. Qui restaura una còpia sovint ja té coses del node —ha seguit apuntant mentre l'altre no hi era—, i una restauració que esborrés allò seria la pèrdua de la veda 64 tornant per la porta del darrere.

70

El relé transporta, no escriu història

#

El relé ja existia, ja era opcional i el configurava qui volia, i el topic ja era un hash. Però només portava conversa: per fer arribar els apunts calia quedar cara a cara amb un QR, d'un en un. Amb N nodes això són N trobades, i és el que impedia que la xarxa convergís sola.

Afegir-hi els apunts semblava tornar a posar un servidor al mig. No ho és, perquè el relé no té clau. El patch va xifrat amb la clau del node i signat pel did, i en arribar es comprova el sobre i cada apunt per separat. Qui allotja el relé veu passar bytes que no pot llegir ni alterar sense que es noti, i no pot fer aparèixer nodes al SOS de ningú: un patch d'un node que no tens es descarta.

Aquesta és la diferència entre un transport i un amo, i es pot escriure com una prova: el test corre contra un servidor de debò i llegeix el que el servidor veu. Si algun dia hi passés res llegible, el test ho diria.

I un detall d'educació amb qui allotja: persist es crida a 108 llocs, i una sola acció en dispara uns quants de seguits. Enviar un patch a cada crida convertiria el relé en una tempesta contra un servidor que sovint és el de casa d'algú. S'espera uns segons i se n'envia un de sol amb tot.

71

Tres còpies d'una regla són tres llocs on afluixar-la

#

El canal (veda 65), la custòdia (veda 69) i el relé (veda 70) fan exactament la mateixa feina: agafar el que puc demostrar d'un node, xifrar-ho amb la clau del node, signar-ho; i a l'altra banda comprovar la firma, desxifrar i verificar apunt per apunt.

Escrit tres vegades, són tres llocs on la regla de «el transport no dona veritat» es pot afluixar sense que ningú se n'adoni — i el tercer sempre és el que s'oblida. sealPack i openPack ho fan un sol cop.

Això no és estalviar línies: és que hi hagi un sol lloc on sigui difícil equivocar-se. Quan una garantia es repeteix, el que es multiplica no és el codi, és la superfície on pot fallar.

72

La cadena original és la clau

#

<html lang="ca"> i 2.400 cadenes catalanes incrustades al codi. Per a una beta a Catalunya el català no és cap barrera; per a Euskadi ho és tot. I és l'única feina pendent el cost de la qual creix cada setmana que no es fa: cada tanda hi afegeix text incrustat.

El camí habitual —inventar claus (btn.save, msg.error.2) i substituir-les a 2.400 llocs— és car, es fa d'una tacada i es fa malament. La decisió que ho evita: la cadena catalana és la clau. t('Desa') torna «Desa» en català i «Guardar» en castellà.

D'aquí surten tres propietats que valen molt més que l'estalvi de feina:

I la part que fa que això no torni a passar: el deute es mesura. Un deute que no es veu és el que creix, i per això check-i18n.js no falla mai per tenir poca cobertura —seria mentir sobre l'estat real i bloquejar feina honesta— sinó que posa la xifra davant. Només falla pel que sí que és un error: una traducció buida, una que tradueix a si mateixa, o una que apunta a text que ja no existeix.

L'últim cas és el traïdor: una traducció òrfena no tradueix res i es queda al diccionari fent bonic mentre la cadena de debò surt en català. Sense la guarda, això només es descobreix amb algú davant.

I es diu la cobertura real a qui tria la llengua. «Disponible en castellà» amb 48 textos traduïts seria una decepció programada; dir quants n'hi ha és el que fa que triar-ho no ho sigui.

73

Dos primaris són cap primari

#

La veda 66 va fer que les pestanyes del node les manés el full de ruta del rol. La home es va quedar igual per a tothom, i mesurada donava això: 1.876 px, 6 seccions i 25 botons, idèntics per a qui ve a apuntar tres hores al mes i per a qui sosté el node.

El defecte més barat de veure i el més fàcil de repetir: dos botons primaris competint a la mateixa targeta. Quan tot destaca, no destaca res, i el que hauria de manar —el pas següent del teu camí— quedava a la segona fila darrere de sis botons fantasma. Ara n'hi ha un, va primer, i és sempre el pas següent.

I la targeta va passar de set botons a tres. Els quatre que en van sortir no s'han tret d'enlloc: són al llançador, agrupats des de la veda 63. Repetir una acció a la home no és fer-la més accessible; és competir amb el que aquella pantalla havia de dir.

74

El proper pas surt del que hi ha, no del que falta per estrenar

#

Quan no hi havia res que reclamés atenció, «els teus propers passos» eren tres «Prova: …» — la llista de capacitats que encara no havies tocat. És un ganxo de completista, i el completista no és qui tenim al davant.

A un banc de temps amb cinc socis i cap apunt, el proper pas no és «Prova: MATRIU · incubar»: és registrar les primeres hores. El buit que es nota és el que el SOS ja sap veure —socis sense cap apunt, un node sense ningú— i mirava just per sobre.

L'ordre correcte és: el que reclama atenció, després el buit que es nota, i només al final provar coses noves. Provar coses noves és l'última prioritat de qui ha vingut a fer una feina concreta.

El ganxo de completar no s'ha tret —enganxa, i això és cert—: s'ha plegat a una línia amb la barra. Era la secció més gran de la pantalla: deu targetes de deures a algú que havia vingut a apuntar hores.

I una que val per a qualsevol pantalla: una secció buida no ocupa lloc. Un títol seguit de «res reclama atenció» és una secció sencera per dir que no n'hi ha cap, i empeny cap avall les que sí que en tenen.

75

Un sostre no és una veritat: és una conversa ajornada

#

El pes va arribar al 94 % del sostre de 400 KB i tocava fer alguna cosa. En mesurar d'on venia, la resposta no era on l'esperàvem: no és a les dades —cap bloc en passa de 5 KB gzip— sinó als comentaris. 170 KB en cru, 72 KB gzip, el 20 % del fitxer. És a dir: aquestes vedes, escrites dins del codi.

Pel camí, dues coses van corregir a la baixa el guany que s'esperava, i totes dues valen com a lliçó de mesura:

Amb els números de debò: buidar els 32 blocs restants val 3 punts percentuals a canvi de 32 explicacions. I 16 KB en un fitxer que es cacheja no els nota ningú, ni amb dades mòbils d'un poble.

Així que es puja el sostre i s'escriu per què. Això no és rendir-se davant del límit: és que el límit ha fet exactament la seva feina. No existia per prohibir créixer sinó per obligar que créixer fos una decisió presa i escrita, i aquí n'hi ha una. El dia que el número no es pugui justificar, el que caldrà canviar serà el codi, no el número.

I la que val per a qualsevol guarda que es posi a partir d'ara: una guarda que mai es discuteix no està servint de res, i una que se salta sense escriure per què ja no és una guarda. La fricció és tota la seva utilitat.

76

Un registre públic de coses privades es publica en hashes

#

buildRegisterPack feia tota la feina difícil —arrel, CID, firma, totals— i el paquet es quedava al teu disc. El mateix forat que tenia supply/ abans de la veda 60: publicar sense descobriment no és publicar.

Però abans de publicar-lo calia contestar una pregunta que sembla de tecnologia i és de gent: què vol dir «registre públic» quan el que hi ha dins són hores que uns veïns es van fer els uns als altres? Publicar qui va donar hores a qui és publicar dades de gent que no ho ha demanat, i el SOS existeix precisament perquè aquella gent s'hi pugui refiar.

La sortida: el que surt són hashes i totals, mai files. I d'aquí la propietat que fa que això valgui la pena:

verificable per tothom, llegible només per qui té el rebut.

Amb el teu rebut a la mà comproves que el seu hash hi és, i per tant que aquella hora ja existia en aquella data. Qui no el té veu una llista de hashes que no li diu res de ningú. La prova d'inclusió és el que converteix un tauler d'anuncis en un registre: un registre on no pots assenyalar el teu apunt no és teu.

I «actualitzable sense amo» té una forma concreta: versions immutables i un punter que es mou. Cada versió porta el CID de la seva mare, així que qui no es refiï del punter recorre la cadena des de qualsevol versió que ja tingués.

Tres decisions d'ordre que semblen detalls i no ho són:

I el sedàs de sortida, com a tot el que surt d'aquí: si algun dia un camp nou arrossegués text lliure cap a les fulles, verifyNoLeak ho atura abans.

77

El SOS no recluta: reconeix

#

Ve del cànon del Comando, i corregeix com s'havia explicat el projecte fins ara.

Els 150.000 ja han estat enviats a la Terra pel Gran Molekulón. Els iniciadors són els qui els busquen, amb la banda, per anar arreu i trobar-los.

Ho explicàvem al revés. Si els 150.000 s'han de reclutar, l'app és una eina de captació, l'èxit és convèncer i qui no s'apunta no compta. Si ja hi són, l'app és una eina de reconeixement, l'èxit és fer visible, i qui no s'ha apuntat ja hi era — només no l'hem trobat encara.

I la versió bona descriu millor el que el codi fa de debò: el SOS no crea valor, fa visible el que ja existeix. Una hora que un veí ja va donar. Un saber que algú ja té. Una biblioteca que ja és al menjador d'algú. findMatches no fabrica coincidències: en troba de latents.

D'aquí surt una regla de llenguatge que val per a tota la interfície: no es diu «apunta't» quan el que fem és trobar-te. El primer demana que canviïs; el segon reconeix el que ja fas.

78

Un enemic endèmic demana pràctica, no èpica

#

També del cànon: Mundo Muerto és una corporació que funciona com un virus a la ment de les persones. És endèmic —la part perversa de la ment humana—, sempre hi és, i no es derrota: es controla, amb tècniques de purificació.

Un enemic que es derrota demana una èpica amb final. Un enemic que sempre hi és demana una pràctica que es fa cada dia. I això explica el projecte millor que cap argument tècnic:

Per això les guardes no es poden treure mai, i per això el guió ja ho havia escrit sense que ningú ho llegís així:

«També us mantindrà el nivell d'alarma, l'estat d'alerta… Us mantindrà a ratlla. Perquè no baixeu la guàrdia.»

L'enemic és el que et manté en forma. Una guarda que no molesta mai ja no està guardant res.

79

Ampliar el que es pot connectar obliga a revisar el que se suma

#

linkResource només oferia germanschildren(node.parentId)— i els fills del propi node no hi sortien mai. El cas natural és justament aquell: una MATRIU comarcal amb bancs de temps municipals a sota.

Ampliar la llista era mitja hora. Fer-ho sense mirar res més hauria estat pitjor que deixar-ho com estava, i val la pena entendre per què:

rollup() ja agrega els descendents cap amunt, i ecosystemResources suma el que aporten els enllaços. Enllaçar un fill hauria comptat el mateix dues vegades. I com que el fons distingeix «verificat» d'«estimat», el resultat no hauria estat un número una mica alt: hauria estat un número inflat amb aparença de verificat — el pitjor que li pot passar a un projecte que promet exactament el contrari.

La regla, que ja existia per a la consolidació entre nivells i que aquí es torna a aplicar: propi i agregat no se sumen a mà. Els enllaços es parteixen en dos —el que penja de tu, que ja entra per l'agregat, i el que ve de fora, que no entra per cap altra banda— i només els segons sumen. I es diu a la pantalla, que és el que fa que la xifra sigui defensable davant de qui la miri amb dubtes.

La lliçó general: quan s'amplia el que un sistema pot relacionar, s'ha de tornar a mirar tot el que aquell sistema suma. Les vies noves no porten dades noves: porten les mateixes dades per un camí que abans no existia.

80

Val més dir «això no ho faig jo» que un botó que ho sembla

#

Al registre públic li faltava permanència: el repositori es pot esborrar i els relés de Nostr no guarden res per sempre. Això es paga un cop i es fa a fora.

La temptació era un botó que digués «Puja a Arweave» i que en realitat obrís una pestanya. Ho hauria fet servir tothom i ningú hauria sabut que el que ha quedat pujat és el que hi hagi pujat ell, no el SOS.

Per això el botó diu «fes-lo permanent» i la pantalla diu, sense endolcir-ho, que el SOS no puja res. El projecte porta massa vedes dient «no es diu verificat del que no s'ha verificat» com per fallar aquí.

I la peça que de debò fa la feina no és el fitxer ni el CID: és quedar-se l'adreça on has dit que l'has posat. Un ancoratge del qual no saps tornar no és un ancoratge — i per això, sense adreça no es desa res. Deixar-ho desar buit hauria estat pitjor que no oferir-ho: tindries una llista d'ancoratges que et faria creure que estàs cobert.

Es guarda dins de l'ancoratge que ja existia, no en una llista nova. Dos llocs on mirar el mateix acaben sempre igual: un dels dos menteix.

81

Un relat que no es pot apagar ha deixat de ser una capa

#

Cada pantalla del SOS té ara el seu superheroi del Comando. Zero funcions noves: els personatges ja hi eren i les pantalles també; només calia dir quin va amb quina.

El risc d'afegir relat a una eina és que el relat es posi al davant. Dues regles l'eviten, i totes dues es poden comprovar:

82

Un certificat que el dona algú val el que valgui aquell algú

#

El Programa Pioneres ofereix un certificat després de tres setmanes de feina. La temptació era un diploma d'assistència, que és el que fa tothom i no costa res de defensar perquè no afirma res.

El que s'ofereix, en canvi, s'aguanta sol:

I es diu el que no és: no té reconeixement oficial. Dir-ho no li treu valor; li'n dona, perquè el que sí que és —verificable— és més del que pot dir la majoria de certificats que sí que són oficials.

83

Un cromo que es pot regalar deixa sense sentit el registre que el sosté

#

«Tengo cromos repes… que te lo cambio», canta el Comando Ska. La frase amaga la mecànica més útil que té un àlbum, i que és exactament la que aquesta app no sabia provocar: un repetit no serveix per a res tot sol. T'obliga a sortir a buscar qui té el que et falta, i a tenir alguna cosa per oferir-li. No és un rànquing —és reciprocitat, que és el que el SOS mesura i el que més li costa que passi.

Portar-ho al codi obligava a decidir tres coses, i les tres es podien equivocar d'una manera que hauria semblat innòcua:

D'on surt un cromo. La temptació era reaprofitar els «superpoders» de reputationOf, que ja hi eren. Però aquells es calculen sobre les ofertes publicades: són una declaració, i publicar-ne deu no costa res. Un cromo surt d'una aportació al ledger signada o encadenada —el mateix llistó amb què la reputació separa els apunts firmats dels legacy. Si aquí el llistó fos un altre, la mateixa persona tindria dues veritats sobre el mateix apunt. El que has fet i ningú ha verificat no desapareix: es compta a part i es diu on falta, perquè saber què has de firmar és una acció; que s'esfumi, no.

Què fa el botó de bescanvi. No mou cap cromo. Et diu amb qui val la pena parlar, i prou. El que es bescanvia és l'hora; el cromo apareix sol quan registreu l'intercanvi. Aquí hi ha la línia que no es pot creuar mai: el dia que un cromo es pugui aconseguir sense aportar —regalat, comprat, transferit— el registre deixa de voler dir res i tota la resta cau amb ell. Per això cromoTransfer no existeix, i el test comprova que no existeixi: una funció que no s'ha escrit és més difícil de cridar per error que una de protegida.

Què és la imatge. El cartell compartible porta escrit a dins «una imatge no prova res; el registre signat, sí». Sembla autosabotatge i és el contrari: el cartell viatja sol per llocs on ningú tindrà context, i sense aquesta línia estaríem fabricant credencials de mentida amb la nostra pròpia cara. El que prova és proveInclusion, no un PNG.

I un afinat del sedàs que valia la pena fer bé. verifyNoLeak cridava pel nom que hi ha al cartell —correctament: està escrit per no deixar sortir noms de persona. Però hi ha un cas on un nom no és una fuita: el teu, al teu cromo, que hi poses tu. La sortida barata era no passar el cartell pel sedàs. La bona és excusar-lo nom a nom i explícitament (verifyNoLeak(pack,{allow:[…]})): el d'una altra persona no s'excusa mai, els contactes tampoc, i sense l'excusa el sedàs segueix cridant. Un test ho comprova en totes dues direccions, perquè apagar un sedàs i afinar-lo s'assemblen molt fins que algú se'n fia.

84

Un certificat on el rol és un camp de text és criptografia certificant una mentida

#

La landing del Programa Pioneres promet «un certificat del rol que hagis exercit» des de fa setmanes, i al codi no hi havia res que n'emetés cap. Un compromís amb gent que s'hi pot inscriure avui va davant de qualsevol backlog.

La veda 82 ja deia que un certificat que el dona algú val el que valgui aquell algú. Portar-ho al codi obliga a una cosa que sembla un detall i és tota la peça: el rol no s'hi pot escriure.

Si rol fos un camp del paquet, qualsevol podria posar-hi «coordinadora», signar amb la seva pròpia clau —que és legítimament seva— i el certificat verificaria perfectament. Firma impecable certificant una cosa que no ha passat. La firma diu qui ho ha escrit, no si és cert; confondre les dues coses és l'error que converteix una eina de verificació en una màquina de fabricar credencials.

Per això el rol es recalcula en verificar, des de l'evidència que porta el mateix paquet, amb la mateixa funció que el va deduir en emetre'l (certRole). El test fa la trampa bona —canviar el rol i tornar a signar-ho tot correctament— i comprova que la firma torni a ser vàlida i el certificat no.

La resta surt d'aquí:

I un defecte que va sortir al primer intent i val la pena deixar escrit: les confirmacions no poden entrar al que es firma, perquè arriben després. Però firmar i verificar amb dues idees diferents de què és «el cos» és el mateix defecte de sempre amb una altra cara —va fallar de seguida, i hauria tornat el dia que algú tornés a emetre un certificat que ja en tenia. Ara hi ha una sola funció que diu què es firma (certBody), i les dues bandes la criden.

85

Un número que puja sense que hagi passat res és una mètrica de vanitat

#

COMANDO_TARGET = 150.000 ja sortia a la pantalla del Comando amb un comptador i una barra de progrés. Comptava comandoRoster().lengthtota fitxa de soci de qualsevol node— i ho etiquetava «superherois validats».

Una fitxa no és ningú: la crea qualsevol escrivint un nom en un formulari. El comptador pujava amb altes, no amb feina, i ho feia al lloc més visible d'una eina que existeix precisament per distingir el que s'ha fet del que s'ha dit. No era un error de càlcul: era la contradicció del projecte, en gran, a la portada del seu propi relat.

Ara compta persones amb almenys una aportació signada. Dues coses més, que són la meitat de la correcció:

86

Passar de un a molts no és canviar el singleton: és decidir qui parla amb qui

#

_pc i _dc eren singletons i cada aparellament tancava l'anterior: una trobada de tres persones eren tres torns. La feina òbvia era canviar-los per un mapa de sessions. La feina de debò era una altra, i s'hauria pogut no fer sense que es notés al codi.

Amb A↔B i A↔C oberts, un canvi de la B no arriba mai a la C. Tres persones connectades segueixen sent dues converses separades: s'hauria refet la infraestructura sencera i el problema del backlog —«una trobada de tres són tres torns»— seguiria intacte, amb el mapa de sessions com a coartada. Per això l'A reenvia el que rep als altres canals oberts.

Reenviar obre dos forats que s'han de tapar alhora, i tapar-ne només un és pitjor que no reenviar:

I una conseqüència que no era al backlog i surt sola: si se'n poden tenir diverses, se n'ha de poder acabar una. «Desconnecta» tancava tot el que hi hagués, que amb una sessió era correcte i amb tres és fer fora tothom per treure una persona. També obliga la pantalla a ensenyar-les totes: amagar amb qui estàs compartint el teu SOS és l'última cosa que es pot amagar aquí.

El test són tres SOS de debò parlant per WebRTC, sense mocks. Un company que desapareix sense avisar no s'hi prova, i és a posta: un canal mort només es descobreix quan venç el temps de la connexió, i esperar-ho mesuraria WebRTC en comptes del codi.

87

Detectar sense oferir res és fer de termòmetre

#

El SOS sabia dir que una iniciativa feia seixanta dies que no es movia, i el que oferia en clicar-hi era obrir la fitxa de la iniciativa aturada: tornar a ensenyar el problema. Dir la temperatura no és baixar-la, i un tauler que t'avisa cada dia del mateix sense donar-te res a fer s'aprèn a ignorar molt de pressa. El senyal no es perd de cop: es gasta.

La Bomba Disco no afegeix cap detecció. Afegeix les tres jugades que ja es podien treure del que el SOS sap, i que ningú havia tret:

I tres regles que decideixen com es fa:

88

El que pesa d'una xarxa no és el que la gent hi ha fet: és el bastiment

#

hello enviava state.nodes i state.entities sencers a cada aparellament. La intuïció deia que el problema seria la quantitat de feina registrada. La mesura diu una altra cosa: a una comarca de debò —27 municipis, 81 barris, 6 projectes vius amb 150 persones i 720 apunts signats— la salutació eren 492 KB, i 109 dels 115 nodes no portaven cap contingut humà. L'esquelet geogràfic, amb el mapa buit, el kanban buit i el ledger buit.

Amb un company era car. Amb la veda 86 —tres alhora— es multiplica, i cada reconnexió el torna a pagar sencer.

La correcció és en dos trossos, i cap dels dos canvia què s'acaba compartint:

I la guarda sense la qual tot això seria un desastre silenciós: un esquelet no pot sobreescriure mai un node amb contingut. Els camps que s'uneixen ja estaven protegits per la veda 64, però vna, kanban i metaskill no: un node buit amb updatedAt més nou —cosa que passa amb només tocar-lo— hauria esborrat un mapa de valor sencer. Que el remitent el consideri buit no vol dir que aquí ho sigui.

Hi ha una tercera cosa que no s'ha fet, i val la pena dir-la: dues persones que munten cadascuna el seu esquelet de Catalunya tenen id diferents per al mateix poble, perquè ensureNode els genera per dispositiu. Sincronitzar-los duplica el poble. Això ja passava abans i segueix passant; arreglar-ho és una altra feina, i callar-ho hauria estat vendre aquesta com més completa del que és.

89

Una paraula que vol dir dues coses al mateix text no en vol dir cap

#

El blog feia servir Shiva i Shakti per a dues coses alhora, i totes dues estaven ben explicades per separat:

Són dos eixos diferents. Llegits seguits, el segon diu que qui repara bicicletes és «menys Shiva» que qui coordina un ateneu, cosa que no vol dir res —i pitjor, convida a llegir un judici sobre persones on només hi ha una categoria de servei.

La sortida fàcil era canviar les paraules per «seny» i «rauxa» als dos llocs, que és el que semblava demanar-se. Hauria mogut el problema, no resolt: tindríem la mateixa col·lisió amb vocabulari d'aquí. El primer eix es diu ara pel seu nom d'aquí (seny i rauxa, que és exactament el que descriuen); el segon, pel que mesura: obrir i sembrar contra tallar i renovar.

Tres decisions que van amb això:

90

Dues pantalles que diuen coses contràries sobre la mateixa dada: la pitjor manera de tenir raó

#

Report d'ús real: una MATRIU amb quatre aportacions al registre i la pantalla d'equity dient «Encara no hi ha aportacions». Cap de les dues frases era falsa, i justament per això el defecte era pitjor que un error: qui ho llegeix conclou que l'app s'equivoca —o, molt pitjor, que ha perdut la seva feina.

La causa: dos formularis escriuen al mateix ledger i només un posava memberId. openContributionModal demana el soci; openLedgerEntryModal —el del tauler i el del kanban— demanava «Qui ho ha aportat» com a caixa de text. computeEquityCore salta tot apunt sense memberId, així que el nom escrit a mà no arribava mai a la tarta. Dues persones a l'app: el soci amb el seu id, i el nom escrit en una casella. No s'havien conegut mai.

Arreglat als tres llocs, perquè qualsevol d'ells tot sol hauria deixat el problema a mitges:

La regla general, que val més que aquest cas: quan dues pantalles poden dir coses contràries sobre la mateixa dada, la que ensenya el zero és la que ha d'explicar-se. Un buit que contradiu un número que l'usuari ja ha vist no és un buit: és una acusació contra la seva feina.

91

Una plantilla diu de quina mena és una cosa, no com es diu

#

A la MATRIU, clicar una targeta del catàleg creava el projecte a l'instant i li posava el nom de la plantilla. Cinc comunitats energètiques a cinc pobles es deien totes «Energia», i la persona que l'havia engegat no reconeixia enlloc la cosa que havia fet.

El nom d'un projecte és la primera cosa que la gent hi reconeix, i no pot sortir d'un catàleg. Una plantilla serveix per dir de quina mena és allò —i per portar-hi el mapa de valor i el tauler—, no per batejar-ho.

Tres conseqüències, i la segona és la que no es veu venir:

I un detall petit que val la pena: el suggeriment de nom deia «Energia de MATRIU de l'Alt Penedès». Un suggeriment mal escrit convida a acceptar-lo tal com està, i el que es queda escrit és culpa nostra, no de qui va clicar.

92

El navegador no pot confirmar un cobrament, i cap configuració ho canvia

#

SOS Coop necessita poder carregar crèdit, i carregar crèdit vol dir cobrar. És la primera vegada que aquest projecte toca diner de debò, i porta una frontera dura que val la pena escriure abans que la pressió de la demo la faci semblar negociable.

Confirmar un cobrament vol dir comprovar la firma del banc, i comprovar-la vol dir tenir la clau del comerç. Una clau de comerç dins d'un HTML que qualsevol es descarrega no és una clau: és un regal. Per tant el SOS inicia pagaments i no en confirma cap, i això no és un estat provisional que es resolgui configurant bé: potCobrar és una constant false, no un càlcul. Amb Redsys configurat del tot segueix sent false, i el test ho comprova.

D'aquí surt tota la resta:

I una decisió que no s'ha pres i queda escrita a la pantalla: si la unitat són euros, una unitat interna o aportació al capital social. Canvia què és legalment, i no és cosa del codi decidir-ho per omissió. Fins llavors la unitat és un paràmetre i la pantalla diu que encara no està decidit —que és més honest que triar-ho en silenci i que algú s'ho trobi decidit.

93

Una app que s'explica bé i no deixa operar només serveix per aprendre-la

#

El lateral era un explorador de territoris: bo per entendre l'estructura, inútil per fer-hi res. I tot el que et fa falta cada dia —què t'espera, què tens publicat, què et queda al moneder— vivia darrere d'un modal diferent.

El defecte no era que faltés informació. dashboardAttention, pendingInbox, communityStatus i walletBalance ja existien i cadascun calculava bé la seva part. El que faltava era un lloc on la teva operació es veiés sencera, i per això l'app només servia per aprendre-la.

La distinció que dona sentit al taulell, i que abans no es veia enlloc: tenir una oferta no és que se't pugui trobar. Són dues coses i s'han de comptar per separat —«0/1», i escrit amb lletres: encara no et troben. Un número sol hauria deixat la persona convençuda que ja ho tenia fet.

D'aquí surten dues coses més:

I una cosa que va sortir provant-ho: renderOps penjava de renderTree, i per tant el taulell desapareixia quan no hi havia arbre. El que et diu què fer no pot dependre de tenir ja alguna cosa feta.

94

Una porta que existeix i no es pot obrir compta com si no hi fos

#

Publicar una oferta ja es podia fer d'una tirada, i tot i així gairebé ningú hi arribava. No era un problema de funcionalitat sinó de les tres maneres en què una acció es pot fer inaccessible sense deixar de funcionar, i les tres hi eren alhora:

La sortida del tercer cas és la que dona la regla: crear el que falta és part de l'acció, no un requisit previ. Obrir el banc de temps al municipi, entrar-hi com a soci i publicar l'oferta és la mateixa feina que ja fa l'alta de perfil; l'única cosa que faltava era poder-la fer des d'aquí. Un formulari, un botó, i el mateix resultat tant si el lloc existia com si no.

I la seva germana, que és la que evita substituir un cul-de-sac per un altre: quan encara no se sap qui publica, no es diu «no pots». Es diu què falta — saber qui ets— i s'hi porta amb el botó al costat.

95

Un camp buit llegit com «sense límit» és com es buiden les caixes

#

La veda 92 diu que el navegador no pot confirmar un cobrament. Aquesta és la porta contrària, i és la que fa mal de debò: què impedeix que el que s'ha carregat se'n vagi. Que algú de la casa pagui els orígens no és un model de finançament, és un favor que dura fins que la factura sorprèn.

El defecte que això evita és de configuració, no de codi, i és el més car que hi ha: un sostre que no s'ha posat val 0, i 0 es llegeix com «cap límit». Aquí zero vol dir zero: sense sostre no surt res. És incòmode el primer dia —cal posar un número abans de poder gastar— i és exactament el que ha de passar, perquè l'alternativa és que la primera despesa la faci un valor per omissió que ningú ha decidit.

Tres regles més, i les tres són l'única cosa que separa un sostre d'un registre:

I una que és de govern abans que de codi: la caixa té un operador amb nom —la cooperativa de segon grau o la Fundació SOS MATRIU— i mentre no n'hi hagi cap, no en surt res. Un «nosaltres» difús operant una caixa és la manera educada de dir que no en respon ningú.

El que hi ha a la caixa no és el que es pot gastar. Aquesta era la trampa que tenia la primera versió d'això, i és la que fa fallida a les cooperatives de debò: el crèdit que una sòcia ha carregat i encara no ha gastat és seu, i gastar-lo per pagar servidors és gastar diner que es deu. Per això la caixa té tres xifres i no una: el que hi ha, el que es deu, i el que és lliure. Els sostres es comproven contra el lliure. La conseqüència pràctica és que sostenir les operacions necessita una aportació al fons (newFunding) i no serveix esperar que les càrregues de les sòcies ho paguin: entren pel mateix camí i amb el mateix rebut, però no són la mateixa cosa i no es poden sumar.

Conseqüència de fusió que no és òbvia: carregues i daoDecisions passen a APPEND_ONLY, i una càrrega confirmada porta updatedAt. Sense això, sincronitzar dos dispositius podia despagar una càrrega ja cobrada, perquè guanyava l'última versió escrita i no la més rica.

96

Un origen que cau en silenci es confon amb una xarxa buida

#

Llegir el que altres han publicat ja funcionava, però sortia d'un sol lloc escrit dins del codi. Mentre aquell lloc respon no es nota res; el dia que no respon, la xarxa deixa d'existir per a tothom alhora i ningú té manera d'apuntar a un altre costat. Ara els orígens són una llista que es prova en ordre, i el primer és sempre aquest mateix lloc i no es pot treure —treure'l deixaria algú sense cap manera de llegir res.

La decisió de fons, que va costar més de prendre que d'escriure: el camí de lectura es queda a HTTPS estàtic, no a IPFS ni a WebTorrent. Zero instal·lació, va amb dades mòbils i darrere d'un proxy, i el cacheja qualsevol CDN. El que fa acceptable que ho allotgi algú no és el transport sinó que el contingut és agregat i signat i passa pel sedàs d'entrada. El P2P de debò —WebRTC, V80 i V82— ja cobreix el que ha de cobrir: la sincronització en viu entre qui es coneix. Fer-lo servir també per «baixar el que ha publicat la xarxa» faria que la xarxa fos invisible quan ningú està connectat, que és el contrari d'accessible.

I el que dona nom a la veda, que és una qüestió de què es diu i no de què es fa: quan cap origen respon, no es diu «encara no hi ha res publicat». És la mentida més fàcil d'aquesta pantalla i la que fa que ningú sàpiga mai si la xarxa és buida o si el seu origen és mort. Es diu quants s'han provat i amb quin error va fallar cadascun. Del que sí que arriba es diu qui ho ha servit —sense això, «per què no hi surt tal cosa» no té resposta possible— i de quan és; i si l'índex no porta data, es diu que no en porta, perquè un mirall que s'ha quedat enrere i no ho confessa et fa llegir el passat creient que és el present.

Dues regles més que eviten construir una cosa que no existeix enlloc:

Afegir un origen no és fiar-se'n, i la pantalla ho diu: el que en vingui passa pel mateix sedàs que tota la resta. Per això la llista blanca de camps i el filtre de text són dues xarxes diferents i totes dues calen —la primera atura un camp que ningú ha declarat, la segona atura el correu que s'amaga dins d'un camp legítim.

97

Trobar una cosa no és fiar-se'n, i la pantalla ho ha de dir

#

La llista d'orígens (veda 96) resol que un lloc caigui, però no que en desaparegui un i ningú sàpiga on és el següent: la llista viu al teu navegador, i qui entra de nou no en té cap. Repartir el descobriment sense repartir el contingut és la peça que fa que això sobrevisqui que un lloc desaparegui, i la divisió és l'anunci per Nostr, els fitxers per HTTPS.

Els relés Nostr són molts, gratis, i el navegador hi parla nativament: serveixen per dir «sóc aquí». Un relé no és un magatzem de fitxers, i fer-l'hi servir seria fer-lo caure —que és la temptació òbvia i l'error que hauria fet inútil tota la peça.

Ara la frontera, que és la mateixa de la veda 61 aplicada a un cas nou: la firma Nostr no es verifica al navegador. És Schnorr sobre secp256k1 i SubtleCrypto no en sap; caldria una biblioteca i el SOS és un sol fitxer. Que un anunci arribi d'un relé prova que un relé l'ha acceptat, no qui l'ha escrit. Dues conseqüències que no són negociables:

I el mateix criteri que a mà: una proposta que no sigui https cau, i un anunci que no es pot llegir no atura la cerca —només no compta. Quan no n'apareix cap es diu que ningú n'ha publicat cap, que no és el mateix que dir que no n'hi ha.

98

Un índex que es manté a mà es desincronitza el segon dia

#

Publicar ja se sabia fer: el fitxer del paquet sortia bé. El que no se sabia fer era l'índex que hi apunta, que es mantenia a mà —i un índex escrit a mà acaba anomenant un fitxer que no hi és, o deixant-ne un que ningú anomena. El primer cas el lector el compta com a «paquet fallat» sense saber per què; el segon és un fitxer que no llegirà mai ningú. Ara es genera, i abans de baixar-lo es comprova en totes dues direccions.

Amb això queda tret l'últim lligam: publicar no demana ni token ni el repositori de ningú. Un origen és una carpeta amb dos fitxers estàtics.

I la propietat que sembla un detall i és el que fa que la peça anterior serveixi: el hash que s'anuncia ha de ser el de l'índex que es publica. Si no ho fos, el checkAnnounced de la veda 97 diria «no quadra» del teu propi origen ben publicat. Una comprovació que crida al llop amb les teves dades correctes s'aprèn a ignorar, i llavors ja no hi és per al cas de debò. Una alarma que es desactiva sola per soroll és pitjor que no tenir-ne.

El que va destapar

Aquesta peça va ser la primera a passar el sedàs de sortida abans de descarregar, i va caçar una fuita que hi era de feia temps: quan una oferta té una categoria que no és de la llista —o no en té cap— supplyThing i thingLabel cauen al títol lliure, i el títol sortia de casa com a category i com a label del paquet agregat. «Necessito ajuda amb la hipoteca» convertit en categoria pública.

A dins, aquell recurs està bé: és el que la persona va escriure i l'ha de veure. A fora no, i el motiu és el de la veda 47: el paquet és agregat, i una etiqueta lliure torna a identificar el cas concret que l'agregació havia d'amagar. El que no és de la llista surt com «altres».

La lliçó que val més que l'arreglada: la comprovació existia i era correcta — verifyNoLeak ho detectava perfectament— però cap camí de publicació la cridava. Una guarda que no és a la porta per on es passa no guarda res.

99

El primer que veu tothom és l'últim que mira ningú

#

Revisant l'ajut d'inici van sortir tres defectes, i els tres tenien la mateixa causa: és la pantalla per on tothom passa una vegada i on ningú torna. Es prova el dia que s'escriu i després es queda sola per sempre, mentre la resta de l'app té tests que la vigilen.

El pitjor era visible i portava temps allà: el text dels passos porta èmfasi escrit a mà, i es pintava amb esc(). Resultat: la primera frase que llegeix qualsevol que obre el SOS deia literalment «s'uneixen en una <strong>aventura comuna</strong>». No hi ha manera més ràpida de dir «això no està acabat».

La solució no és treure l'escapament —el dia que algú hi posi una variable, això seria una porta oberta— sinó escapar-ho tot i tornar a obrir només les dues etiquetes que aquest text fa servir. Una llista blanca, com a tot arreu.

Els altres dos són de forma, i tots dos són casos de la veda 62:

I la que ja hi era i s'ha de conservar: una presentació no interromp una feina començada. Si hi ha res obert, el tour espera. modal() buida l'arrel, i un tour que arriba tard es menja el formulari que estiguessis omplint amb el que hi hagis escrit a dins.

100

Dues fonts que no es contradiuen igual es poden desincronitzar

#

Anava a ampliar els mòduls formatius perquè el backlog deia que «FORMACIO_MODULES diu què és cada mòdul i prou; qui l'obre no hi troba res per llegir». Era fals, i val la pena dir per què m'ho vaig creure: ho havia escrit jo mateix mirant només un dels dos costats.

formacio.html tenia el temari sencer —objectius, skills, aptituds, eines, metodologia i exercici per mòdul— i l'app ja hi enllaçava amb l'àncora correcta. L'arquitectura era bona i deliberada: la pàgina és la font única de la docència i FORMACIO_MODULES només n'és l'esquelet referenciable. Escriure contingut nou hauria estat duplicar-lo, que és el pitjor que se li pot fer a una cosa que ja està bé.

El problema real era un altre i no s'assemblava gens: la pàgina tenia 16 mòduls i l'app en modelava 8. Els vuit del Bloc B —facilitació, comunicació, conflictes i cures, finançament, formes jurídiques, mesura d'impacte, RGPD i formació de formadors— existien sencers i cap itinerari de rol els citava mai. Justament la meitat que ensenya a sostenir una comunitat, que és el que de debò fa caure els projectes; la meitat de l'eina, no.

Ningú se n'assabenta perquè els dos costats funcionen. La pàgina es llegeix bé. L'app no dona cap error. No hi ha res trencat: només hi ha una cosa que no existeix en un dels dos llocs, i el silenci és exactament igual que si hi fos. Aquesta és la forma que pren aquest error sempre: no una contradicció —que es veuria— sinó una absència.

La regla que en surt: quan una cosa viu partida en dues fonts a posta, la correspondència entre elles ha de ser una guarda, no una intenció. check-formacio.js falla per dues coses, i totes dues deixen algú a mig camí:

I una que la guarda també ha de fer, perquè si no és una guarda cega: si el lector no entén tants mòduls com n'hi ha escrits, ha de dir que no els ha entesos en comptes de comptar-ne menys i concloure que tot quadra.

101

Una eina de navegació posada de marc obliga tothom a navegar

#

L'app va néixer com un explorador de territoris: una columna fixa de 280 px amb l'arbre, i tota la resta a dins. L'arbre no estava mal fet —fa bé el que fa— però estava mal col·locat: posat de marc, convertia «anar a un lloc» en el pas previ obligatori de qualsevol feina, també per a qui cada dia fa la mateixa cosa al mateix lloc.

El canvi és de jerarquia, no de funció: el tauler passa a ser l'app i l'arbre passa a ser una eina que s'obre quan vols navegar. La condició que fa que això sigui legítim i no una amputació és la veda 62: treure l'arbre del marc no pot deixar cap node inaccessible. Ja no ho deixa —la cerca global hi arriba— i això és exactament el que ha de comprovar el test, no que el calaix s'obri bé.

Dues coses que aquesta fase ha ensenyat i que no s'endevinaven des del disseny:

El bug que va sortir provant això

El toggle d'un <details> és asíncron. Obrir-lo nosaltres també el dispara, i s'apuntava a la memòria per pestanya com si l'hagués obert la persona. La conseqüència era doble i cap de les dues es veia: la memòria «recorda què vas fer tu» no distingia res —cada obertura automàtica hi entrava— i el mode flux no hauria plegat res mai, perquè sempre hi hauria hagut una «decisió» apuntada al davant. Ara només es desa quan l'estat que arriba difereix del que hem posat.

I la seva germana: canviar un mode ha d'esborrar el que el contradiu. Si activar el mode flux no netejava el que s'havia obert a mà, el botó semblava no fer res fins que anessis plegant pestanya per pestanya.

102

El que es declara i el que es demostra no es poden pintar igual

#

L'ikigai eren quatre cercles i la manera òbvia de fer-los era un formulari de quatre camps. Hauria estat un test de personalitat: quatre caselles que la persona omple imaginant-se, i una pantalla bonica que no sap res.

Tres dels quatre ja els sabia el sistema. «Se't dona bé» surt dels cromos verificats, que surten d'aportacions signades. «Fa falta» surt de les demandes obertes d'altres persones, ordenades per proximitat. «Et valoren per» surt del que t'han confirmat i del moneder. Cap dels tres s'ha de preguntar.

El quart —què t'agrada— no es pot deduir de res, i aquí és on hi ha la regla: un quadrant declarat presentat com a evidenciat converteix una intenció en un fet. Es distingeixen a la pantalla sense haver-hi de passar el ratolí: la vora del que està demostrat és sòlida i verda, la del que has dit tu és discontínua, i cadascun porta escrit d'on surt —«de l'evidència» o «ho dius tu». Declarar que cuines no t'omple el quadrant de cuinera: això només ho fa el ledger.

Dues conseqüències que en surten:

I una precisió que no es pot inventar

proximity() torna km:null quan els nodes no tenen coordenades: el que se sap és la jerarquia territorial —mateix municipi, mateixa comarca— i això no és una distància. Dir «a 3 km» quan només saps que sou de la mateixa comarca és inventar-se una precisió que ningú ha mesurat. Les lents de les missions ordenen per rang i diuen «al barri del costat», no un número.

I la que ve de la veda 51: canviar de lent —urgència, proximitat, afinitat— reordena, mai filtra. Cap missió desapareix perquè hagis triat mirar-les d'una altra manera, i qui t'espera segueix sortint primer passi el que passi.

103

Un rànquing necessita gent per ser segur

#

activityRanking({scopeId}) sabia limitar-se a un subarbre des del primer dia i ningú hi podia arribar. Té sentit que s'hi pugui: veure't a la xarxa sencera diu poc —al costat de 500 persones, ser el 340è no vol dir res— i al teu banc de temps sí. «Fill o pare» tampoc és una preferència d'interfície: al node veus qui mou el que fas tu, i al que el conté veus si el teu node aporta o només rep.

El que no és obvi és que reduir l'àmbit empitjora el problema que la veda 56 ja avisava, en comptes de deixar-lo igual. Un rànquing en una eina de suport mutu es pot girar en contra, i com més petit és el grup, més. Entre 500 persones, l'última posició no la mira ningú. Entre cinc, l'últim lloc assenyala algú concret —i sovint qui aporta menys és qui té menys temps o menys salut, no qui té menys ganes.

D'aquí la regla: per sota de cinc persones no hi ha ordre. Es veu què ha aportat cadascú, sense número, sense podi i sense cua. I es diu a la pantalla, perquè una regla que actua sense dir-se sembla un error de l'app: qui no entén per què no hi ha números pensa que s'ha trencat alguna cosa.

La distinció que sosté la decisió: no ordenar no és amagar. Les aportacions segueixen sortint totes; el que desapareix és la comparació, que és l'única part que pot fer mal. Si haguéssim tret les files, hauríem tapat feina de gent real per protegir-la, que és una manera cara de no protegir ningú.

104

Quan una cosa deixa de ser omnipresent, ha de quedar-ne un rastre

#

El taulell d'operacions vivia al lateral i es veia des de qualsevol pantalla. Passar-lo al tauler (veda 101) va guanyar un marc i va perdre exactament això: mirant un node, el que t'esperava no era enlloc. I com que la ruta desada és la de l'últim node que miraves, qui torna a l'app hi aterra i no veu mai el tauler. Vist des de fora: «el tauler surt buit».

Era un defecte meu i el va trobar qui fa servir l'app, no els tests. Els meus provaven que el taulell fos al tauler —hi era— i cap provava què passa quan no hi ets.

La correcció que NO es fa: tornar-lo a posar també al lateral. Tenir la mateixa cosa a dos llocs és pitjor que no tenir-la —cada còpia és una que es pot quedar enrere, i llavors quina mana? El que queda és un rastre que hi porta: un botó permanent amb el compte del que t'espera, que s'encén quan hi ha alguna cosa i s'amaga quan ja ets al tauler, perquè un botó cap a on ja ets és soroll.

D'aquí la regla general: moure una cosa de lloc no és gratuït encara que la cosa segueixi existint. Si abans es veia sempre i ara no, la pregunta que s'ha de contestar no és «on és» sinó «com sap algú que hi és».

I el progrés, que existia i no es veia

levelOfPerson calculava els nivells des del primer dia i no sortien enlloc del tauler: la persona pujava de N1 a N2 sense assabentar-se'n. El que fa que això sigui útil en comptes de decoratiu és una sola cosa: es diu exactament què falta, amb el número. «Et falten 12 h i dues comunitats» és un pas. «Segueix així» no ho és. I quan el que falta no es pot dir amb un número —liderar una iniciativa— es diu amb paraules i no s'inventa una barra de progrés.

El que no fa, i és deliberat: no compara amb ningú. Un nivell és contra tu mateix. Comparar ja ho fa el rànquing, amb les seves proteccions (veda 103), i barrejar les dues coses convertiria el progrés personal en una classificació encoberta.

105

Una pantalla que peta a mig pintar es queda muda, i el silenci menteix

#

Restaurar una còpia deixava el tauler en blanc. Dues causes, i la segona val més que la primera.

La causa directa: una còpia antiga porta nodes sense els camps que s'han anat afegint —vna, kanban, ledger a null— i el codi que els llegeix dona per fet que hi són. Es normalitzen en llegir-los, no en desar-los: el fitxer de la còpia és el que és i no s'ha de tocar; qui ha de ser tolerant és qui el llegeix. I es normalitzen buits: assegurar la forma no és inventar contingut.

La causa de fons, que és la que estabilitza: renderWorkspace buida la pantalla i després pinta. Si el pintat peta, queda un blanc sense una sola paraula. I vist des de fora, tres coses molt diferents s'assemblen exactament:

Només una és certa, i el silenci deixa que la persona es cregui la pitjor. Per això ara una vista que peta pinta l'error: què ha fallat, on, i el que sí que se sap del cert —que això és un error dibuixant i que el que hi ha desat segueix sencer— amb tres sortides que funcionen de debò: tornar al tauler, fer una còpia ara mateix, i dir què s'ha trencat.

Dues coses que això ensenya i que no s'endevinaven:

I una guarda que va deixar de comptar bé, dues vegades

La guarda de KISS comptava les portades llegint state.homeView==='x' pel codi. Això la lligava a com estigués escrit el switch, i va fallar dues vegades seguides: primer va comptar «tauler» dues vegades (hi sumava 1 a cegues donant per fet que la portada per omissió mai es compararia explícitament), i després va perdre de vista «mapa» el dia que en va sortir una variable local.

Les dues xifres eren falses, però no són igual de greus: comptar de més fa soroll i es corregeix; comptar de menys deixa de protegir sense dir-ho. Ara llegeix una llista declarada —HOME_VIEWS— i, si no la troba, crida en comptes d'aprovar: una guarda que no troba el que mesura mai ha de dir que tot va bé.

106

Un test que deixa un camp buit no passa mai per la branca que el llegeix

#

El taulell petava per a qui hagués declarat arquetips: (ARCHETYPES||[]).find(...) sobre una taula que és un objecte indexat per clau, no una llista. El ||[] feia bona cara —semblava una precaució— i era el contrari: amagava que allò mai havia estat un array. Les taules d'arquetips no tenen ni camp id; la clau és la identitat, i buscar-hi x.id===a no hauria trobat res ni sent una llista.

El que val la pena no és l'errata, és per què va passar el test. La prova guardava declared: [] i comprovava la frontera entre declarat i evidenciat amb les habilitats escrites a mà. Amb la llista buida, el forEach no s'executa mai i la línia que peta no s'arriba a llegir. El test verd no deia «això funciona»: deia «això no s'ha provat». La regla que en surt:

Un camp posat a buit en una prova no és un cas límit provat: és una branca no executada. Si un test toca un camp de llista, n'ha de tenir una versió amb elements a dins, i no només perquè el buit també importa.

I dues conseqüències més, que són les que fan que això no torni:

El que sí que va funcionar: la veda 105. La pantalla no es va quedar muda —va dir què havia fallat i on, i d'aquí va sortir un informe d'incidència amb el navegador, el rol i la pestanya. La xarxa de seguretat va fer exactament la seva feina, que és convertir una caiguda en una frase.

107

Un mètode que només s'entén de dins no és un mètode: és un gremi

#

La portada explicava el que fem amb el vocabulari amb què ho pensem: «Value Network Analysis», «local-first», «Slicing Pie», «tauler àgils», «capacitat instal·lada», «Social Operating System». Cap d'aquestes paraules és falsa. Totes són il·legibles per a qui les ha de llegir —una regidora, un tècnic de promoció econòmica, la junta d'un ateneu—, i el titular en deia «comunitats antifràgils, comptables i verificables», que són tres adjectius abstractes seguits.

La regla que en surt, i que val per a tota pantalla d'aquesta casa:

Primer el que és, després com es diu. La descripció plana encapçala; el nom tècnic va una sola vegada, entre parèntesis, i només allà on afegeix crèdit a qui sí que el reconeixerà. «El mapa de qui es passa què amb qui» primer; «el mètode que en diuen VNA» després. Al revés, la persona ha d'aprendre el nom abans de saber per a què serveix, i abandona pel camí.

I el corol·lari, que és el que fa que no torni: si una paraula cal, s'explica a la mateixa pàgina i abans de fer-la servir. El glossari va davant de la secció que la introdueix, no al peu —un glossari que arriba després del text que l'exigia arriba quan ja s'ha decidit que allò no s'entén.

Tres coses més que la revisió va deixar escrites:

Context: el que no és una veda però la sosté

Nous vedes
Ancoratges mitològics (opcionals per l'usuari)

Els arquetips vèdics són presets funcionals, no obligació religiosa. Un projecte pot triar qualsevol sistema simbòlic (celta, andí, secular, propi) — el sistema tècnic no distingeix:

  • Brahman — veu de la missió/visió (metaskill)
  • Brahmà — disseny d'iniciatives
  • Vishnu — coordinació/operació
  • Shiva — auditoria/renovació/transformació
  • Devi/Shakti — execució creativa
  • Ganesha — facilitació/desbloqueig
  • Saraswati — formació (LMS)
  • Lakshmi — gestió del fons

Shiva (Tapas · transformació) i Shakti (Kriya · creació) són els dos vectors polars de cada superheroi. Un sense l'altre col·lapsa; junts són la gràcia.

Backlog infraestructura crítica pendent (no oblidar)

Ordenat per crítica → nice-to-have. Es revisa a cada onada d'ampliació:

  1. Sync live per pings offer/demand — quan un banc de temps registra una demanda que casa amb una oferta d'un altre node aparellat, notifica en directe. Descentralitzat pur (WebRTC + hash de skill matching).
  2. Guardian request UI visible — flux per demanar rol de steward + validació pel creator/owner amb un clic. Model ja hi és (proposeChange type steward_add); només falta el flux.
  3. Sign records via WebAuthn — passar de did:key a signatures amb passkey per als registres reals (no només vinculació). Requereix conservar did:sos com a identitat i afegir un signer.type='webauthn' alternatiu.
  4. Ancoratge Nostr P1 — publicació signada de mainHash a relés públics. Test smoke amb wss://relay.damus.io quan l'entorn ho permeti.
  5. Snapshot Arweave P2 / IPFS+OTS P3 — notarització permanent opt-in del mainHash.
  6. AI review PRs deep integration — mode subscripció (workflow GitHub Actions crida al SOS via webhook local o GitHub App). Actualment un-shot.
  7. Xifratge AES-GCM per node distribuït entre múltiples membres — clau vinculada al did:sos de cada membre autoritzat. Base ja hi és; falta el flux de repartiment.
  8. Onboarding tour primer arrencament — 3-4 pantalles guiades explicant SOS + Comando + Guardians.
  9. Cerca global (⌘K) — cercar nodes, socis, superherois, entitats des de qualsevol lloc.
  10. Wallets W2/W3 — Nostr NIP-07, EIP-712 (adapters per contracte).