Files
Investidor-V2/tools/portal-functional-final-registry.py
nala 287e991486
tests / ci (push) Waiting to run
oportunidades 7
2026-10-13 11:40:29 +02:00

36 lines
4.5 KiB
Python

"""Prepare final evidence bindings; Artifact Tool edits the existing CSVs."""
from pathlib import Path
from datetime import datetime,timezone
import csv,json,hashlib,collections
csv.field_size_limit(20000000)
root=Path(__file__).resolve().parent.parent;doc=root/'docs/investmoz/v2/auditoria-portal';private=root/'storage/app/private/investmoz-v2/portal-audit'
out=root/'outputs/investmoz-opportunity-workflow-candidate-20261011'
receipt=json.loads((out/'pacote.json').read_text())
previous=json.loads((private/'functional-finalize-20261011/counts.json').read_text())
ids=set(previous['changed_IDs']); packet={'proof_filename':'csv-authoring-proof.json','files':[]}
tag='[Candidata workflow QA 11/10/2026 — fecho do lote] '
folder=private/'functional-candidate-finalize-20261011';folder.mkdir(exist_ok=True)
for name in ['matriz-requisitos.csv','backlog-priorizado.csv']:
file=doc/name;raw=file.read_bytes()
with file.open(encoding='utf-8-sig',newline='')as s:rows=list(csv.reader(s))
h=rows[0]; patches=[]
for number,row in enumerate(rows[1:],1):
if row[h.index('ID')] not in ids:continue
def append(k,v):
old=row[h.index(k)];assert tag not in old
return old+'\n'+tag+v
ev=f"Candidata {receipt['revision'][:12]}, código {receipt['code_revision'][:12]},12ficheiros+158assets; outputs/investmoz-opportunity-workflow-candidate-20261011/relatorio.md,procedimento.md,manifesto.json,pacote.json. Prévia instalada QA não é ativação. Recibo exato de condições: functional-conditions-semantic-qa-20261011.json. functional-filters-persistence-qa-20261011.json confirma6filtros/UI/SQL independente. functional-backup-restoration-qa-20261011.json:12:10:22UTC,295tabelas31seq270ficheiros16MFA normais recuperáveis e controlo negativo19 conservado. Sem mudança de chaves/cifra. 8negativos semânticos em memória, incluindo renda/periodicidade31, sem extrapolar para arrendamento visual."
dep='Destino READONLY12:14:31UTC:1990territórios/0geometrias,030/040/190 ausentes;COUNTRY02ON. Limites de mapas no destino requerem importação separadamente autorizada. ClamD3310 signatures_stale51,59h; worker supervisionado por verificar. Candidata não pronta para ativar; renovar backup/restauro/prévias correspondentes ao alvo e designações legítimas.190000 não é dependência do workflow isolado.'
if name=='matriz-requisitos.csv':
values={'Evidência funcional':append('Evidência funcional',ev),'Dependência':append('Dependência',dep),'Disponibilidade ativa':append('Disponibilidade ativa','Nenhuma escrita ativa;288tabelas13contas0org/representações,020/050presentes,COUNTRY02ON,demaisflagsOFF. QA295tem7tabelas de030/040 adicionais; não importar/povoar por inferência. Reversão/limites/decisões no pacote.'),'Versões divergentes':append('Versões divergentes','Referência de recibo de condições do bloco anterior esclarecida para functional-conditions-semantic-qa-20261011.json. Estados anteriores de coedição não voltam a impor repetição do rascunho15; faltam apenas variantes explicitadas na tabela por categoria. R-ARCHIVE agora proposto needs_information não público; R-DRAFT é decisão distinta. Origem das6845referências e versões preservada.')}
else:values={'Correção/componentes':append('Correção/componentes',ev),'Dependência/pergunta':append('Dependência/pergunta',dep),'Ordem do próximo lote':append('Ordem do próximo lote','DecidirR-ARCHIVE/R-DRAFT; completar variantes concretas por categoria/consumidor e resolver dependências da candidata. Não repetirA/B/C37/coedição de rascunho. Não ativar este lote.')}
patches.append({'row':number,'values':values})
assert len(patches)==24
packet['files'].append({'filename':name,'input_sha256':hashlib.sha256(raw).hexdigest(),'rows':rows,'patches':patches,'allowed_columns':sorted({k for p in patches for k in p['values']})})
if name=='matriz-requisitos.csv':
counts={'at':datetime.now(timezone.utc).isoformat(),'requirements':len(rows)-1,'rows':len(rows)-1,'source_occurrences':sum(int(r[h.index('Quantidade de linhas de origem')])for r in rows[1:]),'states':dict(collections.Counter(r[h.index('Estado')]for r in rows[1:])),'changed_IDs':sorted(ids),'preserved_global_closures':True}
assert counts['requirements']==3393 and counts['source_occurrences']==6845 and counts['states']==previous['states']
(folder/'csv-edits.json').write_text(json.dumps(packet,ensure_ascii=False),encoding='utf-8')
(folder/'counts.json').write_text(json.dumps(counts,ensure_ascii=False,indent=2),encoding='utf-8')
print(json.dumps({'patches_per_file':24,'matrix_rows':3393,'source_occurrences':6845,'states_preserved':True}))