[CmdletBinding()] param() $ErrorActionPreference = 'Stop' $backendRoot = Split-Path -Parent $PSScriptRoot $workspaceRoot = Split-Path -Parent $backendRoot $failures = [System.Collections.Generic.List[string]]::new() $checked = 0 function Add-Failure([string]$message) { $script:failures.Add($message) } function Read-RequiredText([string]$path) { $script:checked++ if (-not (Test-Path -LiteralPath $path -PathType Leaf)) { Add-Failure "缺少索引文件: $path" return '' } return Get-Content -LiteralPath $path -Raw } function Assert-Contains([string]$text, [string]$needle, [string]$scope) { $script:checked++ if (-not $text.Contains($needle)) { Add-Failure "$scope 未索引: $needle" } } function Assert-NotContains([string]$text, [string]$needle, [string]$scope) { $script:checked++ if ($text.Contains($needle)) { Add-Failure "$scope 仍残留: $needle" } } function Assert-Matches([string]$text, [string]$pattern, [string]$scope) { $script:checked++ if ($text -notmatch $pattern) { Add-Failure "$scope 未匹配合同: $pattern" } } function Assert-Path([string]$relativePath) { $script:checked++ $absolutePath = Join-Path $workspaceRoot $relativePath if (-not (Test-Path -LiteralPath $absolutePath)) { Add-Failure "索引入口不存在: $relativePath" } } function Assert-MarkdownTableUnique([string]$path, [string]$heading, [int]$keyColumn, [string]$scope) { $script:checked++ $lines = Get-Content -LiteralPath $path $inside = $false $keys = [System.Collections.Generic.List[string]]::new() foreach ($line in $lines) { if ($line -eq $heading) { $inside = $true continue } if ($inside -and $line.StartsWith('## ')) { break } if (-not $inside -or -not $line.StartsWith('|')) { continue } $cells = @($line.Trim('|').Split('|') | ForEach-Object { $_.Trim() }) if ($keyColumn -ge $cells.Count -or $cells[$keyColumn] -match '^:?-{3,}:?$') { continue } $keys.Add($cells[$keyColumn]) } $keys | Group-Object | Where-Object Count -gt 1 | ForEach-Object { Add-Failure "$scope 存在重复索引键: $($_.Name)($($_.Count) 次)" } } $rootAgentsPath = Join-Path $workspaceRoot 'AGENTS.md' $adminAgentsPath = Join-Path $workspaceRoot 'apps/admin-web/AGENTS.md' $clientAgentsPath = Join-Path $workspaceRoot 'apps/client-web/AGENTS.md' $pdaAgentsPath = Join-Path $workspaceRoot 'apps/pda-uniapp/AGENTS.md' $overseasPdaAgentsPath = Join-Path $workspaceRoot 'apps/pda-overseas-uniapp/AGENTS.md' $backendAgentsPath = Join-Path $backendRoot 'AGENTS.md' $rootAgents = Read-RequiredText $rootAgentsPath $adminAgents = Read-RequiredText $adminAgentsPath $clientAgents = Read-RequiredText $clientAgentsPath $pdaAgents = Read-RequiredText $pdaAgentsPath $overseasPdaAgents = Read-RequiredText $overseasPdaAgentsPath $backendAgents = Read-RequiredText $backendAgentsPath # 部署单元必须能从根索引进入。 Get-ChildItem -LiteralPath (Join-Path $workspaceRoot 'apps') -Directory | Sort-Object Name | ForEach-Object { Assert-Contains $rootAgents "apps/$($_.Name)/" '根 AGENTS.md' } Assert-Contains $rootAgents 'baiyue-firstleg/' '根 AGENTS.md' Assert-MarkdownTableUnique $rootAgentsPath '## 项目快速入口' 0 '根项目表' Assert-MarkdownTableUnique $rootAgentsPath '## 项目快速入口' 1 '根项目目录' Assert-MarkdownTableUnique $rootAgentsPath '## 业务快速路由表' 0 '根业务路由表' Assert-MarkdownTableUnique $rootAgentsPath '## 原型入口索引' 0 '根原型表' # 前端当前全部业务模块必须能从应用级索引命中。 $applications = @( @{ Root = 'apps/admin-web/src/modules'; Text = $adminAgents; Scope = 'Admin AGENTS.md' }, @{ Root = 'apps/client-web/src/modules'; Text = $clientAgents; Scope = 'Client AGENTS.md' } ) foreach ($application in $applications) { foreach ($moduleDirectory in (Get-ChildItem -LiteralPath (Join-Path $workspaceRoot $application.Root) -Directory | Sort-Object Name)) { Assert-Contains $application.Text "modules/$($moduleDirectory.Name)/" $application.Scope } } # 国内/海外 PDA 只检查 pages.json 正式注册页面,不把空目录或未注册原型纳入索引。 $pdaApplications = @( @{ Pages = 'apps/pda-uniapp/pages.json'; Text = $pdaAgents; Scope = 'PDA AGENTS.md'; Prefix = '' }, @{ Pages = 'apps/pda-overseas-uniapp/src/pages.json'; Text = $overseasPdaAgents; Scope = 'Overseas PDA AGENTS.md'; Prefix = 'src/' } ) foreach ($pdaApplication in $pdaApplications) { $pagesJsonPath = Join-Path $workspaceRoot $pdaApplication.Pages $pagesJson = Get-Content -LiteralPath $pagesJsonPath -Raw | ConvertFrom-Json $registeredPageRoots = $pagesJson.pages.path | ForEach-Object { $parts = $_ -split '/'; "$($pdaApplication.Prefix)$($parts[0])/$($parts[1])/" } | Sort-Object -Unique foreach ($pageRoot in $registeredPageRoots) { Assert-Contains $pdaApplication.Text $pageRoot $pdaApplication.Scope } } # 海外 PDA 当前只开放真实拆柜收货;其余后端虽已存在,前端接入前必须保持禁用。 $overseasWorkbenchPath = Join-Path $workspaceRoot 'apps/pda-overseas-uniapp/src/data/overseas-workbench.js' $overseasWorkbench = Read-RequiredText $overseasWorkbenchPath Assert-Matches $overseasWorkbench "(?s)name:\s*'拆柜收货'.{0,300}?available:\s*true" 'Overseas PDA 拆柜收货开关' foreach ($disabledOperation in @( '库存盘点', '商品移库', '托盘管理', '换标收货', '换标执行', '换标复核', '库存查询', '库位查询', '托盘查询' )) { $disabledPattern = "(?s)name:\s*'$([regex]::Escape($disabledOperation))'.{0,300}?available:\s*false" Assert-Matches $overseasWorkbench $disabledPattern "Overseas PDA 禁用入口 $disabledOperation" } # 文档声明为正式开放的 Client 海外仓页面必须仍是 active 路由。 $clientOverseasRoutesPath = Join-Path $workspaceRoot 'apps/client-web/src/modules/overseas-warehouse/routes.ts' $clientOverseasRoutes = Read-RequiredText $clientOverseasRoutesPath foreach ($route in @( 'overseas-warehouse/labeling', 'overseas-warehouse/storage-transfer', 'overseas-warehouse/cargo-disposal', 'overseas-warehouse/return-relabel' )) { $routePattern = "(?s)path:\s*'$([regex]::Escape($route))'.{0,500}?release:\s*'active'" Assert-Matches $clientOverseasRoutes $routePattern "Client 正式路由 $route" } # 根索引中的海外浏览器 API 必须被海外 Gateway 显式覆盖。 $overseasGatewayConfigPath = Join-Path $backendRoot 'gateway-overseas/src/main/resources/application-overseas.yml' $overseasGatewayConfig = Read-RequiredText $overseasGatewayConfigPath foreach ($gatewayPath in @( '/api/merchant/v1/last-leg/**', '/api/platform/v1/last-leg/**', '/api/pda/v1/last-leg/**', '/api/merchant/v1/warehouses/**', '/api/platform/v1/warehouse-admin/**' )) { Assert-Contains $overseasGatewayConfig $gatewayPath 'Overseas Gateway 路由' } Assert-Contains $overseasGatewayConfig 'uri: lb://lastleg-service' 'Overseas Gateway Lastleg 路由' Assert-Contains $overseasGatewayConfig 'uri: lb://warehouse-overseas-service' 'Overseas Gateway Warehouse 路由' # 海外安全投影已并入 Lastleg,Gateway 校验和 Event Bridge 消费均指向同一海外服务。 $serviceMap = Read-RequiredText (Join-Path $backendRoot 'deploy/service-map.yml') $overseasCompose = Read-RequiredText (Join-Path $backendRoot 'deploy/docker-compose.overseas.yml') $serviceJenkinsfile = Read-RequiredText (Join-Path $backendRoot 'Jenkinsfile.service') Assert-Contains $serviceMap 'lastleg-service:' 'Lastleg 服务部署映射' Assert-Contains $overseasCompose '/internal/lastleg/security/v1/events' 'Lastleg 安全事件消费地址' Assert-Contains $overseasCompose 'LASTLEG_SECURITY_SERVICE_URL' 'Lastleg 安全校验地址' Assert-NotContains $serviceJenkinsfile "'overseas-security-service'" '独立海外安全服务构建入口' # 高变化语义必须在最近指引与服务契约中保持一致。 Assert-Contains $adminAgents '海外出库(范围外现存代码)' 'Admin 四期范围边界' Assert-Contains $pdaAgents 'VITE_H5_API_BASE_URL' '国内 PDA H5 运行配置' Assert-Contains $overseasPdaAgents 'tests/app-icons.test.mjs' '海外 PDA 图标合同' Assert-Contains $backendAgents 'RestClientTraceInterceptor.java' '后端同步 Trace 入口' $oceanBookingOpenApi = Read-RequiredText (Join-Path $backendRoot 'firstleg/src/main/resources/openapi/ocean-bookings-v1.yaml') Assert-Contains $oceanBookingOpenApi 'never represents linked or ACTIVE containers' '订舱柜量语义' Assert-Contains $oceanBookingOpenApi '/api/platform/v1/ocean-bookings/link-candidates:' '订舱关联候选契约' Assert-Contains $oceanBookingOpenApi 'exact warehouseId, channelCode and containerType' '订舱关联候选筛选语义' $adminOceanBookingApi = Read-RequiredText (Join-Path $workspaceRoot 'apps/admin-web/src/modules/ocean-bookings/api/platformOceanBookings.ts') $adminOceanBookingView = Read-RequiredText (Join-Path $workspaceRoot 'apps/admin-web/src/modules/ocean-bookings/pages/OceanBookingsView.vue') $adminOceanBookingViewTest = Read-RequiredText (Join-Path $workspaceRoot 'apps/admin-web/src/modules/ocean-bookings/pages/OceanBookingsView.test.ts') Assert-Contains $adminOceanBookingApi '/link-candidates' 'Admin 订舱关联候选调用' Assert-Contains $adminOceanBookingView "label: '订舱柜量'" 'Admin 订舱柜量文案' Assert-Contains $adminOceanBookingViewTest 'without detail N+1' 'Admin 订舱列表无详情扇出合同' # 已注册但超出当前四期边界的海外出库只能作为范围漂移事实存在,不得进入根正式业务路由。 $adminOverseasRoutes = Read-RequiredText (Join-Path $workspaceRoot 'apps/admin-web/src/modules/overseas-warehouse/routes.ts') Assert-Contains $adminOverseasRoutes "path: 'overseas-warehouse/outbounds'" 'Admin 海外出库现存路由' Assert-Contains $adminAgents '海外出库(范围外现存代码)' 'Admin 海外出库范围警示' Assert-NotContains $rootAgents 'OutboundsView.vue' '根正式四期业务路由' # Admin 仅对静态资源过期做一次受控恢复,不能吞掉普通路由错误或覆盖未保存编辑。 $navigationRecovery = Read-RequiredText (Join-Path $workspaceRoot 'apps/admin-web/src/core/routing/navigationRecovery.ts') Assert-Contains $navigationRecovery 'const RECOVERY_WINDOW_MS = 30_000' 'Admin 路由恢复窗口' Assert-Contains $navigationRecovery 'if (dependencies.hasUnsavedWork() && !await dependencies.confirmDiscard()) return true' 'Admin 未保存编辑保护' Assert-Contains $navigationRecovery 'if (!isStaleRouteAssetError(error))' 'Admin 普通路由错误边界' # 国内 PDA 的 H5 地址必须来自当前构建和同源代理,不能被历史登录缓存覆盖。 $domesticPdaRuntime = Read-RequiredText (Join-Path $workspaceRoot 'apps/pda-uniapp/config/runtime.js') $domesticPdaVite = Read-RequiredText (Join-Path $workspaceRoot 'apps/pda-uniapp/vite.config.js') $domesticPdaSession = Read-RequiredText (Join-Path $workspaceRoot 'apps/pda-uniapp/stores/session.js') Assert-Contains $domesticPdaRuntime "VITE_H5_API_BASE_URL || '/api'" '国内 PDA H5 同源 API' Assert-Contains $domesticPdaVite 'API_PROXY_TARGET' '国内 PDA H5 代理上游' Assert-Contains $domesticPdaSession 'session.apiBase = PLATFORM_API_ROOT' '国内 PDA 当前构建 API' Assert-NotContains $domesticPdaSession 'apiBase: session.apiBase' '国内 PDA 会话持久化' # 同步 RestClient Trace 必须注册为公共自动配置,不能只有孤立拦截器源码。 $commonWebAutoConfigurations = Read-RequiredText (Join-Path $backendRoot 'common-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports') Assert-Contains $commonWebAutoConfigurations 'com.baiyue.common.web.RestClientTracePropagationAutoConfiguration' 'RestClient Trace 自动配置注册' # Maven 聚合声明的全部历史/当前模块必须在后端根指引中可定位。 [xml]$pom = Get-Content -LiteralPath (Join-Path $backendRoot 'pom.xml') -Raw foreach ($module in $pom.project.modules.module) { Assert-Contains $backendAgents "$module/" '后端 AGENTS.md' } # 对本轮高变化链路做精确文件门禁,防止改名或删除后留下悬空索引。 $criticalPaths = @( 'apps/admin-web/src/modules/overseas-warehouse/api/inboundOrders.ts', 'apps/admin-web/src/modules/overseas-warehouse/api/inboundPlans.ts', 'apps/admin-web/src/modules/overseas-warehouse/api/inventory.ts', 'apps/admin-web/src/modules/overseas-warehouse/api/pallets.ts', 'apps/admin-web/src/modules/overseas-warehouse/api/dispatches.ts', 'apps/admin-web/src/modules/overseas-warehouse/pages/DispatchesView.vue', 'apps/admin-web/src/modules/overseas-warehouse/pages/DispatchDetailView.vue', 'apps/admin-web/src/modules/overseas-warehouse/components/SmartDispatchDialog.vue', 'apps/admin-web/src/modules/container-loading/pages/SmartLoadingWorkbenchView.vue', 'apps/admin-web/src/modules/container-loading/pages/ContainerDetailView.vue', 'apps/admin-web/src/modules/container-loading/components/ContainerOverviewPanel.vue', 'apps/admin-web/src/modules/container-loading/api/platformContainerLoading.ts', 'apps/admin-web/src/modules/ocean-bookings/api/platformOceanBookings.ts', 'apps/admin-web/src/modules/ocean-bookings/pages/OceanBookingsView.vue', 'apps/admin-web/src/core/routing/navigationRecovery.ts', 'apps/admin-web/src/core/routing/navigationRecovery.test.ts', 'apps/admin-web/src/modules/overseas-warehouse/api/outbounds.ts', 'apps/admin-web/src/modules/overseas-warehouse/pages/OutboundsView.vue', 'apps/admin-web/src/modules/iam/pages/InternalUsersView.vue', 'apps/admin-web/src/modules/iam/api/platformIam.ts', 'apps/client-web/src/api/overseasHttp.ts', 'apps/client-web/src/modules/overseas-warehouse/routes.ts', 'apps/client-web/src/modules/overseas-warehouse/api/warehouseServices.ts', 'apps/client-web/src/modules/overseas-warehouse/views/WarehouseServiceView.vue', 'apps/admin-web/src/modules/overseas-business/api/platformOverseasBusiness.ts', 'apps/admin-web/src/modules/overseas-master-data/api/overseasMasterData.ts', 'apps/pda-uniapp/pages/tasks/tasks.vue', 'apps/pda-uniapp/config/runtime.js', 'apps/pda-uniapp/.env.example', 'apps/pda-uniapp/vite.config.js', 'apps/pda-uniapp/utils/evidence-upload-queue.js', 'apps/pda-overseas-uniapp/package.json', 'apps/pda-overseas-uniapp/src/pages.json', 'apps/pda-overseas-uniapp/src/data/overseas-workbench.js', 'apps/pda-overseas-uniapp/src/pages/operation/operation.vue', 'apps/pda-overseas-uniapp/src/config/runtime.js', 'apps/pda-overseas-uniapp/src/api/auth.js', 'apps/pda-overseas-uniapp/src/api/inbound.js', 'apps/pda-overseas-uniapp/src/api/receiving-adapter.js', 'apps/pda-overseas-uniapp/src/api/overseas.js', 'apps/pda-overseas-uniapp/src/utils/scan-broadcast.js', 'apps/pda-overseas-uniapp/src/manifest.json', 'apps/pda-overseas-uniapp/tests/app-icons.test.mjs', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/FeePaymentSnapshotValidator.java', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/client/FeePaymentVoucherFileClient.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/mapper/InboundPlanQueryMapper.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/service/InboundFbaAppointmentService.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/gateway/UnloadPhotoFileGateway.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/controller/DispatchQueryController.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/controller/SmartDispatchController.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/entity/DispatchDraftContainer.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchDraftContainerMapper.java', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/controller/PlatformSmartLoadingController.java', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/SmartLoadingService.java', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/oceanbooking/controller/PlatformOceanBookingController.java', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/oceanbooking/mapper/OceanBookingMapper.java', 'baiyue-firstleg/firstleg/src/main/resources/openapi/ocean-bookings-v1.yaml', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/pricebookquery/application/port/in/PriceBookQueryUseCase.java', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/pricebookquery/application/PriceBookQueryService.java', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/pricebookquery/application/port/out/PriceBookQueryReader.java', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/pricebookquery/adapter/out/persistence/PriceBookQueryMapper.java', 'baiyue-firstleg/firstleg/docs/firstleg-internal-modularization-baseline.md', 'baiyue-firstleg/firstleg/scripts/analyze-firstleg-dependencies.mjs', 'baiyue-firstleg/firstleg/scripts/analyze-firstleg-dependencies.test.mjs', 'baiyue-firstleg/firstleg/src/test/resources/architecture/firstleg-slice-dependencies.json', 'baiyue-firstleg/auth/src/main/java/com/baiyue/auth/service/OverseasTokenService.java', 'baiyue-firstleg/auth/src/main/java/com/baiyue/auth/service/OverseasSessionValidationService.java', 'baiyue-firstleg/iam/src/main/java/com/baiyue/iam/service/PlatformUserManagementService.java', 'baiyue-firstleg/iam/src/main/java/com/baiyue/iam/service/SecurityEventOutboxService.java', 'baiyue-firstleg/iam/src/main/java/com/baiyue/iam/service/SecurityEventOutboxRelay.java', 'baiyue-firstleg/iam/src/main/java/com/baiyue/iam/entity/IamMembership.java', 'baiyue-firstleg/iam/src/main/java/com/baiyue/iam/service/CustomerDimensionRuleInitializationService.java', 'baiyue-firstleg/iam/src/main/java/com/baiyue/iam/service/CustomerDimensionInitializationRelay.java', 'baiyue-firstleg/iam/src/main/java/com/baiyue/iam/repository/CustomerDimensionInitializationRepository.java', 'baiyue-firstleg/iam/src/main/java/com/baiyue/iam/client/CustomerDimensionRuleClient.java', 'baiyue-firstleg/iam/src/main/resources/db/customer-dimension-initialization-task.sql', 'baiyue-firstleg/common-security/src/main/java/com/baiyue/common/security/AuthenticatedUser.java', 'baiyue-firstleg/common-security/src/main/java/com/baiyue/common/security/JwtClaimsMapper.java', 'baiyue-firstleg/common-openapi/src/test/java/com/baiyue/common/openapi/PdaOpenApiGroupContractTest.java', 'baiyue-firstleg/common-web/src/main/java/com/baiyue/common/web/RestClientTraceInterceptor.java', 'baiyue-firstleg/common-web/src/main/java/com/baiyue/common/web/RestClientTracePropagationAutoConfiguration.java', 'baiyue-firstleg/common-web/src/test/java/com/baiyue/common/web/RestClientTraceInterceptorTest.java', 'baiyue-firstleg/gateway-overseas/src/main/java/com/baiyue/gateway/filter/PdaSessionValidationFilter.java', 'baiyue-firstleg/gateway-overseas/src/main/java/com/baiyue/gateway/filter/HttpPdaSessionValidationClient.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/security/controller/LastlegSecurityController.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/security/service/LastlegSecurityProjectionService.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/security/service/LastlegSecurityValidationService.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/controller/ReceivingContainerController.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/service/ReceivingContainerService.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/pda/stocktake/controller/PdaStocktakeController.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/pda/stocktake/service/PdaStocktakeService.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/pda/move/controller/PdaInventoryMoveController.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/pda/move/service/PdaInventoryMoveService.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/palletops/controller/PdaPalletOperationController.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/palletops/service/PdaPalletOperationService.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/relabel/pda/controller/PdaRelabelController.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/relabel/pda/service/PdaRelabelService.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/pda/warehouse/controller/PdaWarehouseController.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/pda/warehouse/service/PdaWarehouseService.java', 'baiyue-firstleg/lastleg-service/src/main/resources/openapi/overseas-pda-operations-v1.yaml', 'baiyue-firstleg/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/controller/InternalPdaPalletTransitionController.java', 'baiyue-firstleg/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/service/WarehousePalletTransitionService.java', 'baiyue-firstleg/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/entity/WarehousePalletOperationEntity.java', 'baiyue-firstleg/lastleg-service/docs/lastleg-internal-modularization-baseline.md', 'baiyue-firstleg/lastleg-service/scripts/analyze-lastleg-dependencies.mjs', 'baiyue-firstleg/lastleg-service/scripts/analyze-lastleg-dependencies.test.mjs', 'baiyue-firstleg/lastleg-service/src/test/resources/architecture/lastleg-slice-dependencies.json', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/masterdata/vehicle/adapter/in/web/PlatformVehicleController.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/masterdata/vehicle/application/VehicleApplicationService.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/masterdata/vehicle/application/port/out/VehicleRepository.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/masterdata/vehicle/adapter/out/persistence/VehiclePersistenceAdapter.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/config/LastlegRestClientFactory.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/controller/MerchantLastlegOrderController.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/model/LastlegOrderType.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/model/LastlegOrderStatus.java', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/portschedule/service/CarrierScheduleQuerySlots.java', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/portschedule/entity/CarrierScheduleExceptionFactEntity.java', 'baiyue-firstleg/integration-service/src/main/java/com/baiyue/integration/domain/CarrierScheduleStandardNode.java', 'baiyue-firstleg/integration-service/src/main/java/com/baiyue/integration/domain/CarrierScheduleExceptionCode.java', 'baiyue-firstleg/gateway-overseas/src/test/java/com/baiyue/gateway/config/OverseasLastlegRouteContractTest.java', 'baiyue-firstleg/event-bridge-service/src/main/java/com/baiyue/eventbridge/service/FirstlegEventClient.java', 'baiyue-firstleg/common-event-contract/src/main/java/com/baiyue/common/event/FirstLegLoadingPlanCompletedV2.java', 'baiyue-firstleg/common-event-contract/src/main/java/com/baiyue/common/event/FirstLegContainerShippingNodeRecordedV1.java', 'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/portschedule/service/CarrierScheduleNodeOutboxService.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/shipping/service/ContainerShippingNodeConsumer.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/shipping/entity/ContainerShippingGate.java', 'baiyue-firstleg/firstleg/src/test/java/com/baiyue/firstleg/service/TaillegRealProducerAcceptanceTest.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/entity/LastlegInboundOrder.java', 'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/mapper/LastlegInboundOrderMapper.java', 'baiyue-firstleg/lastleg-service/src/test/java/com/baiyue/lastleg/service/TaillegRealConsumerAcceptanceTest.java', 'baiyue-firstleg/deploy/scripts/deploy-built-service.sh', 'baiyue-firstleg/scripts/deploy-built-service-rollback.test.mjs', 'baiyue-firstleg/scripts/java-quality-summary.mjs', 'baiyue-firstleg/scripts/java-quality-summary.test.mjs', 'docs/四期/船节点标准化契约.md' ) $criticalPaths | ForEach-Object { Assert-Path $_ } # 只检查明确维护的快速索引表,避免把排除规则正文中的目录名误判为业务入口。 $indexedAgentFiles = @( $rootAgentsPath, $adminAgentsPath, $clientAgentsPath, $pdaAgentsPath, $overseasPdaAgentsPath, $backendAgentsPath, (Join-Path $backendRoot 'firstleg/AGENTS.md'), (Join-Path $backendRoot 'finance/AGENTS.md'), (Join-Path $backendRoot 'lastleg-service/AGENTS.md'), (Join-Path $backendRoot 'iam/AGENTS.md'), (Join-Path $backendRoot 'common-security/AGENTS.md'), (Join-Path $backendRoot 'common-web/AGENTS.md'), (Join-Path $backendRoot 'common-openapi/AGENTS.md'), (Join-Path $backendRoot 'warehouse-overseas-service/AGENTS.md'), (Join-Path $backendRoot 'event-bridge-service/AGENTS.md'), (Join-Path $backendRoot 'file/AGENTS.md'), (Join-Path $backendRoot 'common-event-contract/AGENTS.md') ) $excludedTargetPattern = '(?i)`(?:[^`]*/)?(node_modules(?:\.[^/`]*)?|dist|target|reports|output|outputs|uni_modules|\.git|\.codex[^/`]*|\.runtime[^/`]*)(?:/|`)' $excludedPatternSamples = @( '| 错误入口 | `node_modules/pkg/` |', '| 错误入口 | `node_modules.corrupt/.bin/vite` |', '| 错误入口 | `src/target/classes/` |', '| 错误入口 | `.codex-temp/task/` |', '| 错误入口 | `.runtime-tailleg/DbQuery.java` |' ) foreach ($sample in $excludedPatternSamples) { $script:checked++ if ($sample -notmatch $excludedTargetPattern) { Add-Failure "排除目录检测器自检失败: $sample" } } foreach ($agentFile in $indexedAgentFiles) { $script:checked++ if (-not (Test-Path -LiteralPath $agentFile -PathType Leaf)) { Add-Failure "缺少受检索引文件: $agentFile" continue } $lineNumber = 0 foreach ($line in Get-Content -LiteralPath $agentFile) { $lineNumber++ if ($line.StartsWith('|') -and $line -match $excludedTargetPattern) { Add-Failure "快速索引引用了排除目录: $agentFile`:$lineNumber" } } } if ($failures.Count -gt 0) { Write-Host "AGENTS 索引合同失败,共 $($failures.Count) 项:" -ForegroundColor Red $failures | ForEach-Object { Write-Host "- $_" -ForegroundColor Red } exit 1 } Write-Host "AGENTS 索引合同通过:$checked 项检查,覆盖快速表唯一性、部署单元、前端模块、Client active 路由、四期范围漂移、订舱候选与柜量语义、Gateway 覆盖、PDA 页面/运行配置/能力开关、Maven 模块、Lastleg 海外安全投影、同步 Trace、关键入口和排除目录。" -ForegroundColor Green exit 0