# 07 — Pessoas (autores/arquitectos) — auditoria da FASE PENDENTE

- **Painel:** MonumentosES — auditoria de fidelidade, agente 7/8
- **Data:** 2026-09-04
- **Datasets auditados:** `raw/interm/*.json` (15 CCAA), `raw/interm/madrid.json` (campo `au`), `www/data/bic-persons.json`, `www/explorer/bic_data.json`, `site/src/pages/{personas,autores}/`, `site/src/page-components/{Personnes,Auteurs}.astro`, `site/public/js/{persons-network,monument}.js`, `tools/build_dataset.py`, `docs/fuentes/*.md`, `MonumentosFR/tools/build_persons.py` (referência), `MonumentosX/prompt-monumentos-es.md` (referência)
- **Marcações:** [C] = confirmado programaticamente no estado actual do repositório (ou citação verbatim de documento-fonte); [I] = inferido/secundário (raciocínio, conhecimento geral ou documento não re-executado nesta auditoria)

---

## Âmbito

1. **Inventário do que existe HOJE** sobre pessoas no ES: o campo `au` (autor) existe apenas em `raw/interm/madrid.json`? Quantos registos, lista integral das strings, sanidade dos nomes.
2. **Potencial por fonte:** que fontes espanholas trazem autores (IPAC Catalunha via API `/autors`; Asturias `te_*`; `docs/fuentes/*.md`), o que seria extraível e como (leitura real por agentes, §3.6 do prompt).
3. **Estado das páginas** `/personas` e `/autores`: confirmar que consomem `bic-persons.json` (stub `{}`) e que renderizam vazio **por design** (Fase C ainda não executada).
4. **Recomendação honesta de fase:** escopo mínimo viável (Madrid 17 + IPAC se activado) vs. construir `build_persons.py` gémeo do FR.

## Método

- Leitura programática (Python 3.12) de todos os 15 ficheiros `raw/interm/*.json`: inventário de chaves por CCAA e contagem de valores não-vazios para chaves tipo-autor (`au`, `autor`, `author`, `autors`, `arquitecto`) [C].
- Enumeração integral dos 17 valores `au` com o monumento associado (`n`, `i`, `t1`) e análise de formato/sanidade caso a caso [C]; plausibilidade biográfica avaliada por conhecimento geral das figuras [I].
- Grep dirigido a `docs/fuentes/*.md` (21 ficheiros) por menções a campos de autor; leitura integral de `madrid.md` e `cataluna.md` [C].
- Leitura integral da cadeia de front-end: `pages/personas/index.astro` → `Personnes.astro` → `/js/persons-network.js` → `fetch('/data/bic-persons.json')`; idem `Auteurs.astro`; uso na ficha em `monument.js` (linhas 107-121, 466-481); verificação byte a byte de `www/data/bic-persons.json` [C].
- Verificação de propagação: chaves da vista `www/explorer/bic_data.json` vs. chaves intermédias; grep a `tools/build_dataset.py` [C].
- Leitura do cabeçalho e corpo de `MonumentosFR/tools/build_persons.py` (140 linhas) para citar o método a replicar [C]; leitura do §3.6 e §2 (regras de ouro 2 e 4) e §9 do `prompt-monumentos-es.md` [C].

## Achados

### 1. Inventário actual: 17 strings `au`, só Madrid — todo o resto do país a zero

- **O campo `au` existe apenas em `raw/interm/madrid.json`** [C]. Nos 15 ficheiros intermédios, nenhum outro tem chave tipo-autor (aragon, asturias, baleares-eivissa, canarias-tenerife, cantabria, castilla-la-mancha, castilla-y-leon, cataluna, extremadura, galicia, la-rioja, navarra, pais-vasco, valenciana: 0 ocorrências) [C].
- Madrid: 443 itens; **17 itens com `au` preenchido, 17 strings distintas** (cada valor aparece 1×) [C]. Corrobora `docs/fuentes/madrid.md` §DATASET 1: «`autor` preenchido em 17» [C — citação verbatim].
- Cobertura nacional: 17 / 22.237 registos da vista (`www/explorer/bic_data.json`, contagem de hoje) ≈ **0,08%** [C].
- **O campo `au` nem chega à vista pública**: `www/explorer/bic_data.json` não tem chave `au` (chaves: cmax, cmin, cp, cu, d, en, est, i, img, la, lo, m, n, ou, owt, p, pr, prc, r, s, src, src_url, t1, t2, uc) e `tools/build_dataset.py` não menciona `au` em lado nenhum [C]. Ou seja: hoje os 17 autores vivem só no intermédio; a única via para o front-end seria o `bic-persons.json` (ainda stub, §3).

### 2. As 17 strings [C — valores verbatim] e sanidade

| # | string `au` verbatim | monumento (`i`) | nota de sanidade |
|---|---|---|---|
| 1 | `Benlliure y Gil, Mariano (1862-1947)` | RBIC-2013-000001 (Mon. ecuestre Gen. Martínez Campos) | plausível: Benlliure, escultor [I] |
| 2 | `Cabecera atribuible a Juan Guas (1430-1496) o taller.` | RBIC-2021-000002 (Igl. N.ª S.ª de las Nieves, Manzanares el Real) | **não é um campo de autor limpo** — frase de atribuição com ponto final; contém Juan Guas + «o taller» [C formato; I identificação] |
| 3 | `Carvajal Ferrer, Javier ( 3 de enero de 1926 Barcelona - 14 de junio de 2013, Madrid)` | RBIC-2022-000004 (Casa García Valdecasas) | grafia A; espaço espúrio após parêntese [C] |
| 4 | `Carvajal Ferrer, Javier (Barcelona 1926- Madrid 2013)` | RBIC-2021-000008 (Casa Carvajal) | grafia B — **mesma pessoa que #3, formatos divergentes**; datas internamente consistentes (1926 Barcelona / 2013 Madrid) [C] |
| 5 | `Fernández-Shaw, Casto (1896-1978)` | RBIC-1977-000048 (gasolinera Alberto Aguilera 18) | plausível [I] |
| 6 | `Fisac Serna, Miguel (1913 - 2006)` | RBIC-2019-000012 (Teologado Dominicos) | plausível [I] |
| 7 | `Gans, Richard (Karlsbad, 1850-Madrid, 1925)` | RBIC-2022-000016 (fundición tipográfica Richard Gans) | epónimo/industrial, não arquitecto de projecto — caso a tratar como `person` com role próprio ou nota [I] |
| 8 | `Higueras, Fernando (1930-2008)` | RBIC-2019-000006 (Casa de Lucio Muñoz) | plausível [I] |
| 9 | `Jiménez Corera, Eugenio (1853 - 1910)` | RBIC-2025-000003 (Fábrica El Águila) | plausível [I] |
| 10 | `Juan de Bolonia (ca. 1529-1608) / Tacca, Pietro (1577-1640) / Sánchez Pescador, José (1839-1887) / Medina de la Torriente, Sabino (1812 -1888)` | RBIC-2017-000001 (Felipe III, Plaza Mayor) | **4 pessoas numa string**, separador ` / ` (escultura + pedestal + remoção 1911) [C formato; I leitura histórica] |
| 11 | `Lemaur, Carlos (1724 - 1785)  (diseño)` | RBIC-2020-000013 (Presa de El Gasco) | sufixo de papel «(diseño)» e espaço duplo [C] |
| 12 | `Luis Gutiérrez Soto, Luis (Madrid, 6 de junio de 1900-4 de febrero de 1977)` | RBIC-2022-000017 (Teatro Barceló) | nome duplicado na própria grafia («Luis … Soto, Luis») [C] |
| 13 | `Martínez - Feduchi Ruiz, Luis (1901-1975) / Eced y Eced, Vicente (1902-1978)` | RBIC-2017-000008 (Edificio Capitol) | **2 pessoas**, hífen espaçado « - » [C formato; I Capitol = Feduchi+Eced] |
| 14 | `Moya Blanco, Luis (1904-1990)` | RBIC-2018-000009 (Igl. San Agustín) | plausível [I] |
| 15 | `Sáenz de Oiza, Francisco Javier (1918-2000)` | RBIC-2018-000005 (Castellana 81, ex-Banco de Bilbao) | plausível [I] |
| 16 | `Sota Martínez, Alejandro de la (1913-1996)` | RBIC-2017-000013 (Gimnasio Maravillas) | grafia A |
| 17 | `de la Sota Martinez, Alejandro (20-10-1913 Pontevedra - 14-02-1996 Madrid)` | RBIC-2024-000003 (Fábrica CLESA) | grafia B — **mesma pessoa que #16** (sem acento em «Martinez», ordem invertida, datas completas) [C] |

**Veredicto de sanidade:** os 17 valores são nomes plausíveis e bem documentados de arquitectos/escultores/engenheiros espanhóis, coerentes com o tipo de monumento a que estão ligados [I — conhecimento geral; nenhuma verificação externa foi feita nesta auditoria]; as datas embebidas são internamente consistentes nas duplas Carvajal/Sota [C]. **17 strings → ~19 pessoas canónicas** (dedup Carvajal e de la Sota: −2; strings multi-pessoa #10 e #13: +4) [I — contagem derivada]. Os formatos são heterogéneos (ordem nome/apelido, datas completas vs. anos, locais de nascimento, «o taller», «(diseño)», separadores ` / `) — **regex às cegas produziria lixo; exige leitura real por agentes**, exactamente como prevê a regra de ouro §2.2 do prompt [C — citação: «Extração de texto livre = LEITURA REAL por agentes LLM em lotes, nunca regex às cegas»].

### 3. Páginas `/personas` e `/autores`: a renderizar vazio POR DESIGN

- `www/data/bic-persons.json` = **`{}` literal (2 bytes)** [C]. O FR correspondente (`merimee-persons.json`) tem 7.791 entidades + 110 firmas [C — FR `www/audit/07-pessoas.md`]. É o maior gap de dados FR↔ES.
- `/personas` → `Personnes.astro` → carrega d3 + `/js/persons-network.js?v=1`, que faz `fetch('/data/bic-persons.json')` e, no `build()`, `data.persons.filter(...)` [C]. Com `{}`, `data.persons` é `undefined` → TypeError não apanhado → o gráfico fica vazio e o statsBar fica em «—» (o resto da página — controlos, SVG — renderiza) [C — leitura do código; comportamento não verificado em browser].
- `/autores` → `Auteurs.astro` → `Personnes.astro auteurs` (mesma página com filtro de roles de concepção) [C].
- Ficha do monumento (`monument.js`): o fetch de persons está embrulhado em `try/catch` (linhas 108-114) → degrada graciosamente: `renderPersonsGantt` escreve a secção «sem pessoas registadas» [C]. A página `/api/` documenta o estado: «`/data/bic-persons.json` — Personas vinculadas (redes) — **en preparación (Fase C)**» [C — citação de `Api.astro`]. **Conclusão: o vazio é intencional e documentado** — a ordem de execução §9 do prompt põe persons no passo 7, depois do site (passo 6) [C].
- Nota menor: as páginas raiz (`/personas`, `/autores`) passam `locale="fr"`, tal como todas as outras páginas raiz do clone (explorador, cronologia, mapa…) — padrão site-wide do fork, não um defeito específico de pessoas; as variantes `[lang]/` passam o locale real [C].
- **Duas minas escondidas para quando houver dados** [C — leitura do código; I comportamento]:
  1. `persons-network.js` tem `minCount` **default = 2**: com Madrid isolado (todas as counts = 1), a rede apareceria vazia até o utilizador arrastar o slider para 1.
  2. `CONCEPTION_ROLES` e `roleColor()` usam rótulos FR **literais** (`architecte`, `ingénieur`, `sculpteur`, `peintre-verrier`…): um build ES que emita roles em espanhol não seria apanhado pelo filtro de `/autores` nem colorido.

### 4. Potencial por fonte

| fonte | campo de autor | estado [C/I] | potencial |
|---|---|---|---|
| **Madrid** — CKAN `spacm_patrimonio_cultural_protegido`, CSV 9 col. | `autor` (17/443) | [C — `madrid.md` §1; já ingerido em `interm/madrid.json`] | já extraído; falta apenas a fase de entidades |
| **IPAC Catalunha** — API invarquit (Angular, não oficial) | `GET https://invarquit.cultura.gencat.cat/api/Inventary/{codarq}/autors` | [C — `cataluna.md` §DATASET 2, endpoint testado por HTTP em 2026-09-03 (Card 1352); doc: «detalhes: `GET /api/Inventary/{codarq}/proteccions\|autors\|epoques\|intervencions\|registreBibliografics`»] | **o maior prémio**: 2.212 ids BCIN edifícios via `advanced-search-range` proteccioId=2 [C]; ~40 mil fichas no inventário completo [I]. ~2,2k pedidos com cortesia de taxa [I] |
| **DIBA** — «Patrimoni cultural» (demarcação de Barcelona) | coluna `Autor…` no CSV de 38 colunas | [C — `cataluna.md` §DATASET 3; 57.150 registos, **CC-BY 4.0**, CSV único] | adição mais barata em volume, mas exigiria cruzar com o corpus ES (o ES só ingeriu BCIN arq. WFS; DIBA é dataset separado) [I] |
| **Asturias** — SHAPE `PATRIM_Sym_BIC*` | campos `te_*`: `te_estadmo, te_declara, te_incoaci, te_pbldecl, te_usoori, te_usoact, te_estiloa, te_municip`, + `te_refmini` | [C — `tools/ingest_asturias.py`; **nenhum `te_*` é autor**] | zero |
| **Restantes 12 CCAA** (`docs/fuentes/*.md`) | nenhuma menção a campo de autor em nenhuma outra fonte (greps só apanham «arquitectónico(s)» e licenças «autoría») | [C] | zero documentado; CLM/CYL etc. poderiam ter dados escondidos em PDFs de fichas [I — não verificado] |

**Como extract** (§3.6 do prompt, verbatim): «**Pessoas** (autores/arquitectos): leitura real por lotes de agentes (Auteur-equivalente por CCAA), `build_persons.py` (fuse_key sem hífens/espaços/vírgulas; firmas marcadas; NAME_FIXES)» [C]. Vagas de ≤8 agentes para pessoas (regra de ouro §2.4) [C].

## Desvios

1. **Fase C persons não iniciada** — esperado pela ordem de execução §9 (persons = passo 7, após site); **não é um desvio do plano, é pendência** [C]. Documentado em `/api/` («en preparación (Fase C)») [C].
2. **`au` perdido na vista** — `build_dataset.py` não propaga `au` para `bic_data.json`: a ficha não consegue mostrar o autor directamente do dataset, e a pesquisa do explorador (alvo dos cliques nos nós da rede, `EXPL_BASE + '?q=' + name`) não indexa autores [C]. Impacto baixo enquanto `bic-persons.json` for a via canónica, mas é uma decisão por documentar.
3. **Roles FR literais em `persons-network.js`** — o JS ES ainda espera `architecte/ingénieur/…`; a adaptação ES ficou por fazer e condiciona o formato de output do futuro build (emitir roles em FR = zero mudança JS; emitir em ES = adaptar JS + bump de cache `?v=`) [C].
4. **`minCount=2` default** tornaria invisível um dataset Madrid-only (todas as counts 1) [C — código; I comportamento].
5. **Duplicados garantidos** nas 17 strings (Carvajal ×2, de la Sota ×2 com acento divergente) — sem `fuse_key` género FR viriam 2 entidades por pessoa [C].
6. Ausência de `04-uso.md`, `06-texto.md`, `07-pessoas.md` (este), `08-agregados.md` e `00-sintese.md` em `site/public/audit/` — painel ainda em curso, não é defeito [C].

## Recomendações

**Recomendação honesta: não construir o «gémeo completo» do FR agora; executar um slice mínimo viável de Fase C-1 (Madrid) e deixar IPAC/DIBA para C-2/C-3, condicionados a decisão de licença/cortesia.** Justificação:

1. **O método FR está pronto a citar e é barato de replicar.** `MonumentosFR/tools/build_persons.py` (header verbatim [C]): «Fase C — funde os outputs dos agentes de pessoas (out_pers_*.json) com o dataset e escreve `www/data/merimee-persons.json` (schema do sipa-persons do PT)… Fusão: por entidade canónica (name; normalizada acentos/minúsculas para agrupar); count = nº de monuments; roles = união; firm = type=='firm'; monuments: [{id, n, d, t, yr:[cmin,cmax]}]». Um `build_persons_es.py` é ~90% copy-paste: input = strings `au` de `raw/interm/*.json` (por CCAA, como o FR fazia por coluna), output = `www/data/bic-persons.json` com `{persons: [...]}` — o schema exacto que `persons-network.js` e `monument.js` já consomem [C].
2. **Mas o ganho com Madrid só é mínimo**: 17 strings → ~19 pessoas, todas count=1. A rede de pessoas ficaria vazia no default (`minCount=2`), `/autores` mostraria 19 nós isolados. Vale a pena pela completude (ficha mostra autor; morto o TypeError silencioso do network), não pela análise [I].
3. **C-1 (escopo mínimo, <1h de agentes — 1 vaga, 17 strings):** leitura real das 17 strings → entidades `{name, type, roles, aka}` (decidir: «o taller» de Guas = entidade própria ou nota; Gans = person com role `industrial`; «(diseño)» de Lemaur = role `diseño`); `build_persons_es.py` com `fuse_key` (merge Carvajal/Sota); escrever `www/data/bic-persons.json`; propagar `au` na vista ou documentar que não; **adaptar `CONCEPTION_ROLES`/`roleColor` ao vocabulário ES** (ou emitir roles FR) + bump `?v=`; considerar default `minCount=1` quando o máx. count do dataset for 1 [C — todos os pontos são locais de código confirmados].
4. **C-2 (o prémio real, se activado):** IPAC `/autors` para os 2.212 BCIN edifícios [C — contagem de hoje], em vagas pequenas com cortesia de taxa (API não oficial, sem licença documentada [C]) — dá a Catalunha ao nível do que o Mérimée dá ao FR. DIBA (`Autor…`, CC-BY 4.0 [C]) como alternativa/complemento mais barato e licenciadamente mais limpo, exigindo crosswalk com o corpus.
5. **C-3:** extender a CCAA restantes só se aparecer campo documentado — hoje, zero fontes para 12 CCAA [C].

## Fontes

**Repositório (todos [C], lidos nesta auditoria):**
- `C:\Users\Atelier X\Nextcloud\Documents\00_Website\MonumentosES\raw\interm\madrid.json` (campo `au`, 17/443) e `raw\interm\*.json` (15 CCAA)
- `C:\Users\Atelier X\Nextcloud\Documents\00_Website\MonumentosES\www\data\bic-persons.json` (stub `{}`, 2 bytes)
- `C:\Users\Atelier X\Nextcloud\Documents\00_Website\MonumentosES\site\src\pages\personas\index.astro`, `site\src\pages\autores\index.astro`, `site\src\pages\[lang]\personas\index.astro`, `site\src\pages\[lang]\autores\index.astro`
- `C:\Users\Atelier X\Nextcloud\Documents\00_Website\MonumentosES\site\src\page-components\Personnes.astro` / `Auteurs.astro`; `site\public\js\persons-network.js`; `site\public\js\monument.js` (linhas 107-121, 466-481); `site\src\page-components\Api.astro` (linha 37)
- `C:\Users\Atelier X\Nextcloud\Documents\00_Website\MonumentosES\tools\build_dataset.py`, `tools\ingest_asturias.py`
- `C:\Users\Atelier X\Nextcloud\Documents\00_Website\MonumentosES\docs\fuentes\madrid.md`, `docs\fuentes\cataluna.md` (+ grep aos restantes 19)
- `C:\Users\Atelier X\Nextcloud\Documents\00_Website\MonumentosFR\tools\build_persons.py`; `MonumentosFR\www\audit\07-pessoas.md`
- `C:\Users\Atelier X\Nextcloud\Documents\00_Website\MonumentosX\prompt-monumentos-es.md` (§2 regras 2 e 4, §3.6, §4, §9)

**Externas (via `docs/fuentes/*.md`, verificação HTTP de 2026-09-03 [C], não re-executada hoje):**
- Madrid CSV BIC: <https://datos.comunidad.madrid/dataset/dde86e1d-a06b-4f65-8668-920a566fa264/resource/1804d79a-8643-4f06-8c20-7a0e40641be0/download/inmuebles_bic.csv>
- IPAC invarquit API (autors): <https://invarquit.cultura.gencat.cat/api/Inventary/1352/autors> (exemplo testado); app <https://invarquit.cultura.gencat.cat/>
- DIBA CSV patrimoni cultural: <https://do.diba.cat/api/dataset/patrimoni_cultural/format/csv>

---

## Comandos (reprodução)

```bash
cd "C:/Users/Atelier X/Nextcloud/Documents/00_Website/MonumentosES"

# 1. inventário au por CCAA (só madrid tem)
python - <<'EOF'
import json, glob
for f in sorted(glob.glob('raw/interm/*.json')):
    d = json.load(open(f, encoding='utf-8'))
    items = d['items'] if isinstance(d, dict) and 'items' in d else d
    keys = set()
    for r in items:
        if isinstance(r, dict): keys.update(r.keys())
    au_like = [k for k in keys if k.lower() in ('au','autor','author','autors','arquitecto')]
    n_au = sum(1 for r in items if isinstance(r, dict) and r.get('au'))
    print(f, len(items), au_like, n_au)
EOF
# → só raw/interm/madrid.json tem ['au']; 443 itens, 17 com au

# 2. as 17 strings + monumento
python - <<'EOF'
import json
d = json.load(open('raw/interm/madrid.json', encoding='utf-8'))
for r in d['items']:
    if r.get('au'): print(repr(r['au']), '=>', r['i'], '|', r['n'])
EOF

# 3. stub persons
wc -c www/data/bic-persons.json          # → 2
cat www/data/bic-persons.json            # → {}

# 4. au NÃO chega à vista
python - <<'EOF'
import json
recs = json.load(open('www/explorer/bic_data.json', encoding='utf-8'))['records']
print(len(recs), sum(1 for r in recs if r.get('au')), 'au' in set().union(*[set(r) for r in recs]))
EOF
# → 22237 0 False

# 5. cadeia front-end
grep -n "bic-persons" site/public/js/persons-network.js site/public/js/monument.js site/src/page-components/Api.astro
grep -n "locale=" site/src/pages/personas/index.astro site/src/pages/autores/index.astro

# 6. potential: endpoints de autor documentados
grep -n "autors\|Autor" docs/fuentes/cataluna.md | head
grep -n "autor" docs/fuentes/madrid.md | head
grep -n "te_" tools/ingest_asturias.py | head    # → sem campo de autor
```
