// Reconcile historical missing-ID audit against the actual configured regional asset graph. import assert from 'node:assert/strict' import {readFileSync,writeFileSync} from 'node:fs' import {resolve,join,dirname} from 'node:path' import {createHash} from 'node:crypto' const root=resolve('tools/city-massing/city/cad-bim'),read=p=>JSON.parse(readFileSync(p)),sha=p=>createHash('sha256').update(readFileSync(p)).digest('hex') const config=read(resolve('public/cockpit/config.json')),plan=config.map.tilesets.find(p=>p.regionManifest) assert.ok(plan&&plan.url.startsWith('/gis/cad-bim/')) const manifestPath=join(root,plan.regionManifest.replace('/gis/cad-bim/','')),manifest=read(manifestPath),sourcePath=join(root,manifest.source,'manifest.json'),source=read(sourcePath),sources=new Map(source.records.filter(r=>r.level==='fine').map(r=>[resolve(dirname(sourcePath),r.uri),r])) const active=new Set(),owners=new Map(),seen=new Set(),perRegion=[] for(const region of manifest.regions){ const count=new Set() for(const file of region.fineRecords){const path=resolve(dirname(sourcePath),file.sourceUri),record=sources.get(path);assert.ok(record,'untraced fine '+path);assert.ok(!seen.has(path),'fine reused');seen.add(path) assert.ok(record.buildingIds?.length);for(const id of record.buildingIds){assert.ok(!owners.has(id)||owners.get(id)===record.sourceCell,'building owned by multiple cells '+id);owners.set(id,record.sourceCell);active.add(id);count.add(id)} } perRegion.push({region:region.id,buildings:count.size}) } assert.equal(seen.size,3023);assert.equal(active.size,30172);assert.equal(active.size,manifest.buildings) const auditPath=resolve('.scratch/cockpit-shell-panel-layout/verify/artifacts/t35/large-building-audit/audit.json'),audit=read(auditPath),nearPath=join(root,'near-estate-pilot-input/seated-plan.json'),near=read(nearPath) const accounted=audit.candidates.filter(b=>active.has(b.id)),remaining=audit.candidates.filter(b=>!active.has(b.id)),counts={} for(const b of remaining)counts[b.status]=(counts[b.status]||0)+1 assert.equal(near.buildings.length,13);assert.ok(near.buildings.every(b=>active.has(b.id)));assert.equal(accounted.length,13) const report={passed:true,configuredUrl:plan.url,configuredRegionManifest:plan.regionManifest,sourceBuildingIdsReferenced:active.size,evidenceLevel:'source-cell metadata IDs referenced by configured fine graph',geometryDecodedThisAudit:false,renderedCoverageValidated:false,activeBuildings:active.size,tracedFineFiles:seen.size,regions:perRegion.length, sourceHashes:{currentManifest:sha(manifestPath),sourceManifest:sha(sourcePath),historicalGapAudit:sha(auditPath),nearEstateInput:sha(nearPath)}, historicalMissingCandidates:audit.candidateCount,nowCovered:accounted.map(b=>({id:b.id,areaSqm:b.areaSqm,previousStatus:b.status})),remainingCandidateCount:remaining.length, remainingUrbanCandidates:remaining.filter(b=>b.tier==='urban').length,remainingReasonCounts:counts, urbanSeatedOutsideSelection:remaining.filter(b=>b.tier==='urban'&&b.status==='seated-outside-active-selection').map(({id,areaSqm,center,terrainRelief})=>({id,areaSqm,center,terrainRelief})), perRegion,caveat:'Remaining IDs are unverified candidates, not confirmed missing buildings. No geometry added; no rural reinstatement. Existing 13 additions traced to actual fine asset source records.'} writeFileSync(process.argv[2]||'.scratch/cockpit-shell-panel-layout/verify/artifacts/t35/active-large-building-reconciliation-v7.json',JSON.stringify(report,null,2)) console.log(JSON.stringify({passed:report.passed,active:active.size,nowCovered:accounted.length,remaining:remaining.length,urbanRemaining:report.remainingUrbanCandidates,urbanSeatedOutsideSelection:report.urbanSeatedOutsideSelection.length,remainingReasonCounts:counts}))