34 lines
3.7 KiB
Python
34 lines
3.7 KiB
Python
"""Bind the final immutable candidate and shared COUNTRY02 compatibility proof."""
|
|
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';p=json.loads((out/'pacote.json').read_text())
|
|
old=json.loads((private/'functional-finalize-20261011/counts.json').read_text());ids=set(old['changed_IDs'])|{'AUD-COUNTRY-02'}
|
|
folder=private/'functional-fixed-finalize-20261011';folder.mkdir(exist_ok=True);packet={'proof_filename':'csv-authoring-proof.json','files':[]}
|
|
tag='[Revisão fixa workflow QA 11/10/2026] '
|
|
for name in ['matriz-requisitos.csv','backlog-priorizado.csv']:
|
|
f=doc/name;raw=f.read_bytes()
|
|
with f.open(encoding='utf-8-sig',newline='')as stream:rows=list(csv.reader(stream))
|
|
h=rows[0];patches=[]
|
|
for number,row in enumerate(rows[1:],1):
|
|
rid=row[h.index('ID')]
|
|
if rid not in ids:continue
|
|
def append(k,v):
|
|
old_value=row[h.index(k)];assert tag not in old_value
|
|
return old_value+'\n'+tag+v
|
|
evidence=f"Candidata final {p['revision'][:12]}, código {p['code_revision'][:12]}, ZIP SHA-256 {p['sha256']}; outputs/investmoz-opportunity-workflow-candidate-20261011/pacote.json,manifesto.json,relatorio.md,procedimento.md. A preparação5a81cd3c3998 foi substituída apenas por complemento de evidência/efeito no fingerprint COUNTRY02; código/bundle/backup QA idênticos. functional-country-compatibility-qa-20261011.json: ativo162daff6ce08 intacto; candidato b244311e5b28, extensão QA instalada/ON."
|
|
dependency='A alteração futura de PortalProfileAccess muda o fingerprint de COUNTRY02/prévias, sem novas colunas, dados ou mudança de cifra. Renovar prévias/readiness/chaves quando necessário; não reaplicar050000 já instalado. COUNTRY02 ativo e A/B/C37 preservados. Candidata030/040 não autorizada para ativo;190000 apenas percurso integrado. AssinaturasClamD/worker/habilitações legítimas/backup-alvo e geometrias para limites continuam condições explicitadas.'
|
|
if name=='matriz-requisitos.csv':
|
|
values={'Evidência funcional':append('Evidência funcional',evidence),'Dependência':append('Dependência',dependency),'Versões divergentes':append('Versões divergentes','Revisão preparatória5a81substituída por3d9d apenas em prova/metadata, sem mudança de código df6be252f1a0. Fechos/IDs/fontes/aceitação anteriores conservados.')}
|
|
else:values={'Correção/componentes':append('Correção/componentes',evidence),'Dependência/pergunta':append('Dependência/pergunta',dependency)}
|
|
patches.append({'row':number,'values':values})
|
|
assert len(patches)==25
|
|
packet['files'].append({'filename':name,'input_sha256':hashlib.sha256(raw).hexdigest(),'rows':rows,'patches':patches,'allowed_columns':sorted({k for x in patches for k in x['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(x[h.index('Quantidade de linhas de origem')])for x in rows[1:]),'states':dict(collections.Counter(x[h.index('Estado')]for x in rows[1:])),'updated_IDs':sorted(ids),'candidate':p['revision'],'active_writes':0}
|
|
assert counts['states']==old['states'] and counts['requirements']==3393 and counts['source_occurrences']==6845
|
|
(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({'matrix_rows':3393,'source_occurrences':6845,'updated_requirements':25,'states_preserved':True,'candidate':p['revision'][:12]}))
|