import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; import test from 'node:test'; const api = (path: string) => readFileSync(resolve(process.cwd(), path), 'utf8'); const web = (path: string) => readFileSync(resolve(process.cwd(), '..', 'web-v2', path), 'utf8'); test('F6.1 field Inventory is bounded by the frozen Yacimiento scope', () => { const source = api('src/inspection-visits/field-inventory.service.ts'); assert.match(source, /COALESCE\(visit\.scope_asset_id, visit\.operational_area_id\) AS "scopeAssetId"/); assert.match(source, /const effectiveParentId = parentId \?\? context\.scopeAssetId/); assert.match(source, /const parentId = dto\.parentId \?\? context\.scopeAssetId/); assert.match(source, /\[parentId, context\.scopeAssetId\]/); assert.match(source, /\[assetId, context\.scopeAssetId\]/); assert.match(source, /AS "insideScope"/); assert.doesNotMatch(source, /insideArea/); }); test('F6.1 field Findings reject Inventory outside the frozen Yacimiento scope', () => { const source = api('src/inspection-visits/field-findings.service.ts'); assert.match(source, /COALESCE\(visit\.scope_asset_id, visit\.operational_area_id\) AS "scopeAssetId"/); assert.match(source, /AS "insideScope"/); assert.match(source, /if \(!row\.insideScope\)/); assert.match(source, /Yacimiento definido como alcance/); assert.doesNotMatch(source, /AS "insideArea"/); }); test('F6.1 planning preserves Yacimiento and never validates descendant Inventory ownership', () => { const source = api('src/inspection-visits/inspection-visits.service.ts'); assert.match(source, /const nextScope = dto\.scopeAssetId === undefined \? visit\.scopeAssetId : dto\.scopeAssetId/); assert.match(source, /validateInspectionPlanningScope\(manager, nextAreaId, nextScope\)/); assert.match(source, /visit\.scopeAssetId \?\? visit\.operationalAreaId/); assert.match(source, /visit\.plannedStartAt,/); assert.doesNotMatch(source, /visit\.scopeAssetId = nextAreaId/); assert.doesNotMatch(source, /assertAssetsMatchContext/); assert.doesNotMatch(source, /assertCurrentAssetsMatchContext/); }); test('F6.1 creation selects actionable checklist Inventory automatically', () => { const source = api('src/inspection-visits/inspection-planning-create.service.ts'); assert.match(source, /INSERT INTO inspection_visit_assets/); assert.match(source, /COMPANY_OVERDUE','VERIFICATION_OVERDUE','UPCOMING_CONTROL/); assert.match(source, /'AUTO_INCLUDED'/); }); test('Authoritative operator choices are projected from Yacimientos of the selected Area', () => { const hierarchy = api('src/inspection-visits/inspection-planning-hierarchy.service.ts'); const controller = api('src/inspection-visits/inspection-visits.controller.ts'); const createPage = web('src/pages/InspectionVisitCreateF61Page.tsx'); assert.match(hierarchy, /operatorsForArea\([\s\S]*at\?: string/); assert.match(hierarchy, /FROM assets yacimiento/); assert.match(hierarchy, /yacimiento\.parent_id=\$1::uuid/); assert.match(hierarchy, /yacimiento\.operator_company_id/); assert.match(hierarchy, /SELECT DISTINCT company\.id/); assert.doesNotMatch(hierarchy, /FROM area_company_relations relation/); assert.match(controller, /@Query\('at'\) at\?: string/); assert.match(createPage, /operators\?at=\$\{at\}/); assert.match(createPage, /\[areaId, plannedStartAt\]/); }); test('F6.1 WEB keeps Area and Yacimiento as separate concepts and freezes context after creation', () => { const source = web('src/pages/InspectionVisitEditorF4Page.tsx'); assert.doesNotMatch(source, /Área \/ Yacimiento<\/span>/); assert.match(source, /Área<\/span>/); assert.match(source, /Yacimiento<\/span>/); assert.match(source, /Operadora<\/span>/); assert.match(source, /visit\.operationalArea\.name[\s\S]{0,160}readOnly/); assert.match(source, /visit\.scopeAsset\.name[\s\S]{0,160}readOnly/); assert.match(source, /visit\.operatorCompany\.name[\s\S]{0,160}readOnly/); assert.doesNotMatch(source, /updateInspectionVisit\(id, \{[\s\S]{0,300}scopeAssetId:/); assert.doesNotMatch(source, /updateInspectionVisit\(id, \{[\s\S]{0,300}operationalAreaId:/); assert.doesNotMatch(source, /updateInspectionVisit\(id, \{[\s\S]{0,300}operatorCompanyId:/); });