"""Record the owner's binary-identity confirmation without new source/requirement rows.""" from pathlib import Path from datetime import datetime, timezone from collections import Counter import csv, hashlib, json, shutil, sys csv.field_size_limit(20_000_000) root=Path(__file__).resolve().parent.parent private=root/'storage/app/private/investmoz-v2/portal-audit' source_dir=private/'segmentation-reconciliation-20261011' directory=private/'segmentation-identity-confirmation-20261011' docs=root/'docs/investmoz/v2/auditoria-portal' out=root/'outputs/investmoz-segmentation-reconciliation-20261011' read=lambda p:json.loads(p.read_text(encoding='utf-8-sig')) sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest() write=lambda p,v:p.write_text(json.dumps(v,ensure_ascii=False,indent=2),encoding='utf-8') digest='bf26caeee0437a8d292bf29be59247e2862c14e79b5ae465c00322747af72af5' local=Path('C:/Mac/Home/Documents/TEMPO/Portal Tempo/Servicos Tempo/Relatorios/novos/segmentar processos v1.docx') old_tag='[Segmentação bf26caeee043 — exemplar v1 local; identidade v1(3) pendente] ' new_tag='[Segmentação bf26caeee043 — identidade confirmada; nome local v1.docx] ' counts=read(source_dir/'counts.json') ids=set(counts['reused_requirement_IDs']+counts['new_IDs']) assert sha(local)==digest and sha(Path(read(source_dir/'source-provenance.json')['retained']))==digest if sys.argv[1]=='prepare': assert not directory.exists(), 'Confirmation preparation already exists; do not duplicate.' directory.mkdir() before=directory/'before';before.mkdir() for f in ['matriz-requisitos.csv','backlog-priorizado.csv','inventario-fontes.csv','backlog.md','relatorio-executivo.md','segmentacao-processos-reconciliacao-20261011.md']: shutil.copy2(docs/f,before/f) for f in ['source-provenance.json','correspondence.json','final-integrity.json']: shutil.copy2(source_dir/f,before/f) shutil.copytree(out,before/'outputs') receipt={'at':datetime.now(timezone.utc).isoformat(),'confirmed_by':'responsável, mensagem desta sessão de 11/10/2026', 'owner_statement':'Confirmada a identidade binária com segmentar processos v1(3).docx; v1.docx é nome local do mesmo exemplar.', 'confirmation_basis':'Confirmação binária do responsável e hash calculado do nome local igual ao exemplar anteriormente incorporado. Não foi fingido acesso independente ao nome v1(3).', 'requested_name':'segmentar processos v1(3).docx','local_name':local.name,'local_path':str(local),'resolved_path':str(local.resolve()), 'sha256':digest,'bytes':local.stat().st_size,'exact_requested_exemplar_confirmed':True, 'new_documents':0,'new_requirements':0,'reimport':False,'active_writes':0,'functional_states_changed':False} write(directory/'identity-confirmation.json',receipt) files=[] for filename in ['matriz-requisitos.csv','backlog-priorizado.csv','inventario-fontes.csv']: rows=list(csv.reader((docs/filename).open(encoding='utf-8-sig',newline='')));headers=rows[0];patches=[] for rowno,row in enumerate(rows[1:],1): values={} eligible=(row[headers.index('SHA256')]==digest if filename=='inventario-fontes.csv' else row[headers.index('ID')] in ids) if not eligible:continue for col,v in enumerate(row): revised=v.replace(old_tag,new_tag) revised=revised.replace('Confirmar exemplar solicitado v1(3). ','') revised=revised.replace('Identidade v1(3) pendente.','Identidade binária com v1(3).docx confirmada pelo responsável em 11/10/2026; v1.docx é o nome local do mesmo exemplar.') revised=revised.replace('; v1(3) pendente.','; mesmo exemplar de v1(3).docx, confirmado pelo responsável em 11/10/2026.') if headers[col]=='Critérios e versões por origem (JSON)': entries=json.loads(v) for item in entries: if item.get('source_sha256')==digest: item['exact_requested_exemplar_confirmed']=True revised=json.dumps(entries,ensure_ascii=False) if revised!=v:values[headers[col]]=revised if values:patches.append({'row':rowno,'values':values}) assert len(patches)==(1 if filename=='inventario-fontes.csv' else 47) files.append({'filename':filename,'input_sha256':sha(docs/filename),'rows':rows,'patches':patches, 'allowed_columns':sorted({k for patch in patches for k in patch['values']}),'source_hash_updates':[]}) write(directory/'csv-edits.json',{'files':files}) print(json.dumps({'prepared':True,'matrix_rows_affected':47,'new_rows':0,'sha256':digest})) elif sys.argv[1]=='finalize': receipt=read(directory/'identity-confirmation.json');packet=read(directory/'csv-edits.json') for edit in packet['files']: rows=list(csv.reader((docs/edit['filename']).open(encoding='utf-8-sig',newline=''))) assert len(rows)==len(edit['rows']) and rows[0]==edit['rows'][0] expected=[list(r) for r in edit['rows']] for patch in edit['patches']: for k,v in patch['values'].items():expected[patch['row']][rows[0].index(k)]=v assert expected==rows, 'Only the requested confirmation cells may change.' provenance=read(source_dir/'source-provenance.json') provenance['exact_requested_exemplar_confirmed']=True provenance['local_filename_is_alias_of_requested_exemplar']=True provenance['identity_confirmation']=receipt write(source_dir/'source-provenance.json',provenance) correspondence=read(source_dir/'correspondence.json') for item in correspondence:item['requested_exemplar_confirmation_pending']=False write(source_dir/'correspondence.json',correspondence);write(out/'correspondence.json',correspondence) inventory=read(private/'inventario-fontes.json') # Preserve the old inventory episode and add the current source confirmation explicitly. inventory.setdefault('source_identity_confirmations',[]) assert not any(x.get('sha256')==digest for x in inventory['source_identity_confirmations']) inventory['source_identity_confirmations'].append(receipt) write(private/'inventario-fontes.json',inventory) summary='O responsável confirmou em 11/10/2026 a identidade binária entre `segmentar processos v1(3).docx` e o nome local `segmentar processos v1.docx`. O hash local coincide com o original já incorporado. Não houve nova importação, documento, requisito ou prova funcional por causa do nome. A ressalva anterior foi retirada; a confirmação e o retrato anterior ficam conservados no histórico. As pendências funcionais e a precedência das definições aprovadas permanecem.' for filename in ['backlog.md','relatorio-executivo.md']: p=docs/filename;t=p.read_text(encoding='utf-8') a=t.index('');b=t.index('',a) part=t[a:b] part=part.replace('## Segmentação de processos incorporada em QA com confirmação de exemplar pendente','## Segmentação de processos incorporada em QA com identidade confirmada') old='O pedido identifica`v1(3).docx`, ainda não localizado/confirmado; não declarar os exemplares equivalentes.' assert old in part;part=part.replace(old,summary) p.write_text(t[:a]+part+t[b:],encoding='utf-8') p=docs/'segmentacao-processos-reconciliacao-20261011.md';t=p.read_text(encoding='utf-8') original='O exemplar acessível **segmentar processos v1.docx** foi conservado e importado privadamente na biblioteca QA existente. **Ainda não foi localizado nem confirmado o exemplar solicitado segmentar processos v1(3).docx.** Não se declara identidade entre esses ficheiros; a pergunta sobre o caminho exato permanece pendente. O sufixo de nome (3) não é tratado como versão funcional 3.\n\nEsta reconciliação usa o original disponível e os pedidos expressos desta sessão, preservando o histórico. A confirmação do exemplar solicitado é o critério documental restante; se os bytes forem diferentes, comparar as secções antes de alterar os vínculos. Não repetir provas funcionais por uma simples cópia de nome diferente.' assert original in t t=t.replace(original,'O exemplar **segmentar processos v1.docx** foi conservado e importado privadamente na biblioteca QA existente. '+summary+' O sufixo de nome (3) não é uma versão funcional 3.') p.write_text(t,encoding='utf-8');(out/'relatorio.md').write_text(t,encoding='utf-8') write(out/'confirmacao-identidade.json',receipt) proof=read(source_dir/'final-integrity.json') proof['at']=datetime.now(timezone.utc).isoformat();proof['actual_requested_exemplar_pending']=False proof['exact_requested_exemplar_confirmed']=True;proof['identity_confirmation']=receipt qa=read(directory/'source-identity-qa.json') assert qa['result']=='passed' and qa['metadata_version']==3 and qa['historical_revisions']==3 assert qa['original_import_audit_count']==1 and qa['identity_audit_count']==1 proof['metadata_version']=3 proof['QA_evidence']['source-identity-qa.json']=sha(directory/'source-identity-qa.json') proof['files']={f:sha(docs/f) for f in proof['files']} proof['QA_evidence']['identity-confirmation.json']=sha(directory/'identity-confirmation.json') matrix=list(csv.DictReader((docs/'matriz-requisitos.csv').open(encoding='utf-8-sig',newline=''))) assert len(matrix)==3401 and sum(int(r['Quantidade de linhas de origem']) for r in matrix)==7739 assert Counter(r['Estado'] for r in matrix)==Counter(counts['states']) for name,h in read(private/'functional-active-files-before-20261011.json').items():assert sha(root/name)==h candidate=root/'outputs/investmoz-opportunity-workflow-candidate-20261011' assert sha(candidate/'investmoz-workflow-3d9d392e0a0f.zip')==proof['sealed_workflow_candidate']['zip_sha256'] assert sha(candidate/'manifesto.json')==proof['sealed_workflow_candidate']['manifest_sha256'] proof['result']='passed' write(source_dir/'final-integrity.json',proof);write(out/'verificacao.json',proof) manifest=read(out/'manifesto.json') manifest['scope']='Confirmed v1(3) exemplar, local filename v1.docx; no active activation' manifest['identity_confirmed_by_owner']=True manifest['previous_manifest_sha256']=sha(directory/'before/outputs/manifesto.json') manifest['files']={p.name:sha(p) for p in out.iterdir() if p.is_file() and p.name!='manifesto.json'} write(out/'manifesto.json',manifest) assert all(sha(out/name)==h for name,h in manifest['files'].items()) write(directory/'verification.json',{'result':'passed','requirements':3401,'source_occurrences':7739,'source_inventory_entries':604, 'states_unchanged':True,'new_documents':0,'new_requirements':0,'reimport':False,'active_writes':0,'sealed_workflow_preserved':True}) print(json.dumps({'result':'passed','confirmation_recorded':True,'new_requirements':0,'reimport':False,'active_writes':0})) else:raise ValueError('Use prepare or finalize')