Files
baiyue-firstleg/scripts/agents-index-contract.ps1
T
ouyangxq eab8a1ae5f Merge remote-tracking branch 'origin/test' into dev
# Conflicts:
#	scripts/admin-test-env-modules/phase4-overseas-pda.mjs
#	scripts/agents-index-contract.ps1
2026-09-02 15:21:20 +08:00

866 lines
70 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[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-PathMissing([string]$relativePath) {
$script:checked++
$absolutePath = Join-Path $workspaceRoot $relativePath
if (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
$scriptsAgents = Read-RequiredText (Join-Path $backendRoot 'scripts/AGENTS.md')
$engineeringConstraints = Read-RequiredText (Join-Path $workspaceRoot 'docs/AI工程执行与协作约束.md')
$docsIndex = Read-RequiredText (Join-Path $workspaceRoot 'docs/README.md')
$testTaskRegistry = Read-RequiredText (Join-Path $workspaceRoot 'docs/独立任务协作登记.md')
$devTaskRegistry = Read-RequiredText (Join-Path $workspaceRoot 'docs/开发环境独立任务协作登记.md')
$mapperScanContract = Read-RequiredText (Join-Path $backendRoot 'scripts/mapper-scan-contract.mjs')
# 当前未上线阶段的无兼容原则必须覆盖全部实现与运行状态,不能再次缩窄为文件或数据库专项规则。
Assert-Contains $rootAgents '源码结构、接口与 DTO、字段、状态机、权限、配置键、数据库结构与初始化 SQL、事件、路由、页面、Mock/Fixture、测试和脚本' '根无兼容收敛范围'
Assert-Contains $rootAgents '数据库记录、上传文件、缓存、会话、消息、搜索索引和其他运行状态均视为可丢弃' '根开发运行状态范围'
Assert-Contains $rootAgents '后端 MyBatis Mapper 新增、移动或扫描遗漏' '根 Mapper 快速入口'
Assert-Contains $rootAgents 'node scripts/mapper-scan-contract.mjs' '根 Mapper 静态门禁'
Assert-Contains $rootAgents '脚本管理、全量验证与测试造数' '根脚本管理快速入口'
Assert-Contains $rootAgents 'baiyue-firstleg/scripts/AGENTS.md' '根脚本最近指引'
Assert-Contains $engineeringConstraints '禁止为旧代码、旧调用或开发环境存量保留旧接口/旧字段别名' '工程无兼容执行规则'
Assert-Contains $engineeringConstraints '不授权自动重置数据库、删除数据/文件、执行 SQL、部署或修改环境' '无兼容安全边界'
Assert-Contains $clientAgents '不得继续扩展 `LEGACY_MANUAL`、旧系统入仓码、C02 不可用回退旧 API' 'Client 头程无兼容边界'
Assert-Contains $backendAgents '所有生产 MyBatis Mapper 接口必须显式标记 `@Mapper`' '后端 Mapper 注册规则'
Assert-Contains $backendAgents 'Mapper 新增、移动、Bean 缺失与扫描遗漏' '后端 Mapper 快速路由'
Assert-Contains $backendAgents '脚本管理、全量验证、测试造数与诊断' '后端脚本管理快速路由'
Assert-Contains $backendAgents 'scripts/it-test-wait-split-bulk.mjs' '后端批量待分柜造数入口'
Assert-Contains $backendAgents 'scripts/create-pending-review-orders.mjs' '后端待审核订单造数入口'
Assert-Contains $scriptsAgents 'admin-test-env-acceptance.mjs' '脚本指引 Admin 全量入口'
Assert-Contains $scriptsAgents 'client-test-env-acceptance.mjs' '脚本指引 Client 全量入口'
# 开发与测试独立任务必须按保存项目、cwd 和登记表完全隔离,task_id 不得跨表复用。
Assert-Contains $rootAgents 'docs/开发环境独立任务协作登记.md' '根开发协作登记入口'
Assert-Contains $rootAgents 'docs/独立任务协作登记.md' '根测试协作登记入口'
Assert-Contains $engineeringConstraints '不得同时加载两表后混合选取任务' '工程协作登记选择门禁'
Assert-Contains $docsIndex '[测试环境独立任务协作登记](独立任务协作登记.md)' '文档测试登记入口'
Assert-Contains $docsIndex '[开发环境独立任务协作登记](开发环境独立任务协作登记.md)' '文档开发登记入口'
Assert-Contains $testTaskRegistry 'projectId `c64729ff-6710-43c6-8ef2-d84e9666cc1e`' '测试登记保存项目'
Assert-Contains $testTaskRegistry 'C:\Users\BY-OY\Desktop\code\chongchong-global`' '测试登记工作目录'
Assert-Contains $testTaskRegistry '`01a0194a-259c-7171-8967-074731a27618`' '测试环境系统总控'
Assert-NotContains $testTaskRegistry '01a05b10-a5fc-7d51-8203-c671f3a823ad' '测试登记开发总控'
Assert-NotContains $testTaskRegistry '6f874ec3-d3b2-49bd-8625-327f4d685f98' '测试登记开发 projectId'
Assert-Contains $devTaskRegistry 'projectId `6f874ec3-d3b2-49bd-8625-327f4d685f98`' '开发登记保存项目'
Assert-Contains $devTaskRegistry 'C:\Users\BY-OY\Desktop\code\chongchong-global-dev`' '开发登记工作目录'
Assert-Contains $devTaskRegistry '`01a05b10-a5fc-7d51-8203-c671f3a823ad`' '开发环境五期总控'
Assert-NotContains $devTaskRegistry '01a0194a-259c-7171-8967-074731a27618' '开发登记测试总控'
Assert-NotContains $devTaskRegistry 'c64729ff-6710-43c6-8ef2-d84e9666cc1e' '开发登记测试 projectId'
$testTaskIds = @([regex]::Matches($testTaskRegistry, '(?m)^\|\s*`([0-9a-f-]{36})`\s*\|') | ForEach-Object { $_.Groups[1].Value })
$devTaskIds = @([regex]::Matches($devTaskRegistry, '(?m)^\|\s*`([0-9a-f-]{36})`\s*\|') | ForEach-Object { $_.Groups[1].Value })
foreach ($sharedTaskId in @($testTaskIds | Where-Object { $devTaskIds -contains $_ } | Select-Object -Unique)) {
$script:checked++
Add-Failure "开发/测试登记复用了 task_id: $sharedTaskId"
}
Assert-Contains $scriptsAgents 'script-documentation-contract.test.mjs' '脚本说明防漏门禁'
Assert-Contains $scriptsAgents '不得散落到 `src/test/scripts/`' '服务局部脚本目录边界'
Assert-Path 'baiyue-firstleg/scripts/AGENTS.md'
Assert-Path 'baiyue-firstleg/scripts/README.md'
Assert-Path 'baiyue-firstleg/scripts/script-documentation-contract.test.mjs'
Assert-Contains $mapperScanContract 'annotationClass = Mapper.class' 'Mapper 根包注解过滤合同'
Assert-Contains $mapperScanContract '禁止分散维护 MapperScan' 'Mapper 单一扫描入口合同'
$firstlegAgents = Read-RequiredText (Join-Path $backendRoot 'firstleg/AGENTS.md')
$warehouseAgents = Read-RequiredText (Join-Path $backendRoot 'warehouse/AGENTS.md')
$coloadOpenApi = Read-RequiredText (Join-Path $backendRoot 'firstleg/src/main/resources/openapi/coload-groups-v1.yaml')
Assert-Contains $rootAgents 'modules/unified-orders/api/coLoadGroups.ts' '根同柜不可拆组入口'
Assert-Contains $adminAgents '成员数是入仓片段数,不等于订单票数' 'Admin 同柜成员语义'
Assert-Contains $backendAgents 'loading/coload/controller/PlatformColoadGroupController.java' '后端同柜不可拆组入口'
Assert-Contains $firstlegAgents '服务端冻结每票全部 `WAIT_SPLIT` 可用入仓片段与满箱数' 'Firstleg 同柜建组边界'
Assert-Contains $warehouseAgents 'scripts/warehouse-public-master-data-contract.test.mjs' 'Warehouse 局部脚本入口'
Assert-Contains $coloadOpenApi '允许跨客户及不同目的仓港成组,仅要求国内仓和渠道一致' '同柜资格 OpenAPI'
Assert-Contains $coloadOpenApi '服务端解析每个订单全部 WAIT_SPLIT' '同柜订单展开 OpenAPI'
Assert-Contains $rootAgents '用户可见页面、提示和错误不得展示或以内部数据库 ID 作为业务编号回退' '根业务编号展示边界'
Assert-Contains $adminAgents '/loading-plans/{planId}/lifecycle' 'Admin 装柜清单生命周期入口'
Assert-Contains $adminAgents '合柜报关 / 同柜不可拆组' 'Admin 合柜报关别名入口'
Assert-Contains $clientAgents 'api/inboundCodeAssociations.ts' 'Client 入仓码业务关系入口'
Assert-Contains $pdaAgents 'tests/page-contract.test.mjs' '国内 PDA 页面合同入口'
Assert-Contains $overseasPdaAgents 'tests/business-identifiers-ui.test.mjs' '海外 PDA 内部 ID 隔离合同'
$orderAgents = Read-RequiredText (Join-Path $backendRoot 'order/AGENTS.md')
Assert-Contains $orderAgents '`channelCode` 直接来自 Order/Firstleg 权威快照' 'Order 稳定渠道编码'
Assert-Contains $orderAgents 'InboundCodeAssociationService.java' 'Order 入仓码业务关系入口'
Assert-Contains $firstlegAgents '/loading-plans/{planId}/lifecycle' 'Firstleg 装柜生命周期入口'
# 平台修改客户原始申报必须能从各层索引直达,并锁住 Order -> Firstleg 的版本化同步与渠道门禁。
$orderOpenApi = Read-RequiredText (Join-Path $backendRoot 'order/src/main/resources/openapi/order-v1.yaml')
$firstlegOpenApi = Read-RequiredText (Join-Path $backendRoot 'firstleg/src/main/resources/openapi/firstleg-v1.yaml')
$orderDeclarationService = Read-RequiredText (Join-Path $backendRoot 'order/src/main/java/com/baiyue/order/service/OrderDeclarationUpdateService.java')
$unifiedOrderQueryService = Read-RequiredText (Join-Path $backendRoot 'order/src/main/java/com/baiyue/order/service/UnifiedOrderQueryService.java')
$firstlegDeclarationService = Read-RequiredText (Join-Path $backendRoot 'firstleg/src/main/java/com/baiyue/firstleg/service/OrderDeclarationSyncService.java')
$adminDeclarationEditor = Read-RequiredText (Join-Path $workspaceRoot 'apps/admin-web/src/modules/unified-orders/components/OrderDeclarationEditorDialog.vue')
Assert-Contains $rootAgents '平台修改客户原始申报与履约渠道' '根订单申报快速路由'
Assert-Contains $adminAgents '客户原始申报资料编辑与渠道变更' 'Admin 订单申报快速路由'
Assert-Contains $backendAgents '平台修改客户原始申报、履约渠道变更与跨服务同步' '后端订单申报快速路由'
Assert-Contains $orderAgents '平台版本化修改客户原始申报' 'Order 申报编辑入口'
Assert-Contains $firstlegAgents 'Order 申报同步与渠道变更履约门禁' 'Firstleg 申报同步入口'
Assert-Contains $orderOpenApi '/api/platform/v1/orders/{orderId}/declaration:' 'Order 申报编辑 OpenAPI'
Assert-Contains $orderOpenApi '不覆盖实测、箱码或已确认费用' 'Order 申报与履约事实边界'
Assert-Contains $firstlegOpenApi '/internal/firstleg/v1/inbounds/order-declaration-updated:' 'Firstleg 申报同步 OpenAPI'
Assert-Contains $orderDeclarationService 'OrderStatus.DRAFT, OrderStatus.REJECTED, OrderStatus.SUBMITTED, OrderStatus.APPROVED' 'Order 申报可编辑状态'
Assert-Contains $orderDeclarationService 'ORDER_DECLARATION_UPDATED_V1' 'Order 申报版本事件'
Assert-Contains $firstlegDeclarationService 'mapper.byEvent(event.tenantId(), event.eventId())' 'Firstleg 申报 eventId 幂等'
Assert-Contains $firstlegDeclarationService 'event.version() < current.orderVersion()' 'Firstleg 申报版本单调性'
Assert-Contains $adminDeclarationEditor '仓库/PDA 实测数据不会被覆盖' 'Admin 申报事实边界提示'
Assert-Contains $rootAgents '统一列表仍固定显示 `PENDING_REVIEW` 并提供审核动作' '根待审核订单优先状态'
Assert-Contains $orderAgents '统一主状态/下一动作仍固定为 `PENDING_REVIEW/APPROVE_ORDER`' 'Order 待审核优先状态'
Assert-Contains $unifiedOrderQueryService 'order.getStatus() == OrderStatus.SUBMITTED' 'Order 待审核状态判断'
Assert-Contains $unifiedOrderQueryService 'pendingReview ? "PENDING_REVIEW" : summary.mainStatus()' 'Order 待审核主状态优先'
Assert-Contains $unifiedOrderQueryService 'pendingReview ? "APPROVE_ORDER" : summary.nextAction()' 'Order 待审核动作优先'
# 企业联系信息与账号登录标识已经解耦,资质审核不得重新把法人身份证设为必填。
$authAgents = Read-RequiredText (Join-Path $backendRoot 'auth/AGENTS.md')
$iamAgents = Read-RequiredText (Join-Path $backendRoot 'iam/AGENTS.md')
$iamOpenApi = Read-RequiredText (Join-Path $backendRoot 'iam/src/main/resources/openapi/iam-v1.yaml')
$authAccountService = Read-RequiredText (Join-Path $backendRoot 'auth/src/main/java/com/baiyue/auth/service/AccountManagementService.java')
$iamMemberService = Read-RequiredText (Join-Path $backendRoot 'iam/src/main/java/com/baiyue/iam/service/MemberService.java')
$adminCustomersView = Read-RequiredText (Join-Path $workspaceRoot 'apps/admin-web/src/modules/customers/pages/CustomersView.vue')
$clientCompanyProfile = Read-RequiredText (Join-Path $workspaceRoot 'apps/client-web/src/modules/tenant-management/views/CompanyProfileView.vue')
$clientMembersView = Read-RequiredText (Join-Path $workspaceRoot 'apps/client-web/src/modules/tenant-management/views/MembersView.vue')
Assert-Contains $rootAgents '公司联系电话/邮箱是企业资料,不作为成员登录标识' '根企业联系人边界'
Assert-Contains $adminAgents '公司联系电话只作企业联系信息,不修改管理员/成员登录手机号' 'Admin 企业联系人边界'
Assert-Contains $clientAgents '成员登录手机号可选,修改时同步 Auth、撤销该账号会话并审计' 'Client 成员登录手机号边界'
Assert-Contains $authAgents '登录标识与企业联系人解耦' 'Auth 登录标识入口'
Assert-Contains $iamAgents '公司联系电话/邮箱属于企业资料,不作为登录标识且不要求跨企业唯一' 'IAM 企业联系人边界'
Assert-Contains $iamAgents '审核必填资质仅营业执照与统一社会信用代码,法人身份证选填' 'IAM 必填资质边界'
Assert-Contains $iamOpenApi '公司联系电话,不作为登录标识且不要求跨企业唯一' 'IAM 公司联系电话 OpenAPI'
Assert-Contains $authAccountService 'tokenSessionStore.revokeAll(account.getId())' 'Auth 登录标识变更会话撤销'
Assert-Contains $iamMemberService 'authClient.revokeSessions' 'IAM 成员变更会话撤销'
Assert-Contains $adminCustomersView '不会修改企业管理员登录手机号' 'Admin 公司联系电话提示'
Assert-Contains $clientCompanyProfile '不会修改任何成员的登录手机号' 'Client 公司联系电话提示'
Assert-Contains $clientMembersView '用于该成员手机号登录;修改后会同步认证账号并退出该成员现有会话' 'Client 成员登录手机号提示'
$fileAgents = Read-RequiredText (Join-Path $backendRoot 'file/AGENTS.md')
$qualificationOpenApi = Read-RequiredText (Join-Path $backendRoot 'file/src/main/resources/openapi/qualification-required-package-v1.yaml')
Assert-Contains $rootAgents '法人身份证选填,可在已有营业执照后单独补传或替换' '根法人身份证单独上传语义'
Assert-Contains $fileAgents '法人身份证选填,客户可在已有营业执照后通过 `/api/merchant/v1/files/qualifications` 单独新增或替换' 'File 法人身份证单独上传入口'
Assert-Contains $qualificationOpenApi '/api/merchant/v1/files/qualifications:' '客户单文件资质 OpenAPI'
Assert-Contains $qualificationOpenApi 'LEGAL_PERSON_ID 可在已有营业执照后单独新增或替换' '客户法人身份证单独上传契约'
Assert-Contains $qualificationOpenApi 'BUSINESS_LICENSE 不允许走此入口' '营业执照整包上传边界'
Assert-Contains $clientCompanyProfile '法人身份证已保存,尚未提交审核' 'Client 法人身份证单独上传反馈'
Assert-NotContains $clientCompanyProfile '当前文件服务尚未开放法人身份证单独上传或替换' 'Client 已移除法人身份证旧阻断'
$truckOpenApi = Read-RequiredText (Join-Path $backendRoot 'firstleg/src/main/resources/openapi/truck-appointments-v1.yaml')
$loadingListsOpenApi = Read-RequiredText (Join-Path $backendRoot 'firstleg/src/main/resources/openapi/loading-lists-v1.yaml')
$pdaLoadingApi = Read-RequiredText (Join-Path $workspaceRoot 'apps/pda-uniapp/api/pda-loading.js')
$cabinetEvidenceService = Read-RequiredText (Join-Path $backendRoot 'firstleg/src/main/java/com/baiyue/firstleg/loading/service/CabinetLoadingEvidenceService.java')
Assert-Contains $rootAgents '拖车预约由 `RELEASED` 订舱拥有,不按客户、柜次、装柜计划或真实柜号归属' '根订舱级拖车语义'
Assert-Contains $rootAgents '证据以 `taskId + warehouseId` 进入任务专用 API' '根柜级证据入口'
Assert-Contains $adminAgents '订舱级拖车预约' 'Admin 拖车快速入口'
Assert-Contains $adminAgents '不选择或提交客户、柜次、装柜计划或真实集装箱号' 'Admin 拖车订舱级边界'
Assert-Contains $backendAgents '订舱级拖车' '后端拖车快速入口'
Assert-Contains $firstlegAgents '请求、实体、查询、响应和附件不得恢复 `customerId/customerName`' 'Firstleg 拖车无客户边界'
Assert-Contains $firstlegAgents '公开 DTO 也不得出现 `containerBookingId/loadingPlanId/cabinetNo/containerNo`' 'Firstleg 拖车无柜次边界'
Assert-Contains $firstlegAgents '每订舱通过查询锁与唯一约束最多一张非终态预约' 'Firstleg 拖车唯一有效预约'
Assert-Contains $fileAgents '`businessType=TRUCK_APPOINTMENT_ATTACHMENT`' 'File 拖车平台附件入口'
Assert-Contains $truckOpenApi 'required: [oceanBookingId, carrierId, plannedLoadingAt, expectedVersion]' '拖车订舱级请求字段'
Assert-NotContains $truckOpenApi 'customerId:' '拖车 OpenAPI 客户字段'
Assert-NotContains $truckOpenApi 'containerBookingId:' '拖车 OpenAPI 柜次字段'
Assert-NotContains $truckOpenApi 'loadingPlanId:' '拖车 OpenAPI 装柜计划字段'
Assert-Contains $truckOpenApi 'Each booking may have at most one non-terminal appointment' '拖车订舱级唯一性'
Assert-Contains $truckOpenApi 'PDA loading completion does not change a booking-level truck appointment' '拖车与 PDA 生命周期解耦'
Assert-Contains $truckOpenApi 'excluding bookings that already have a non-terminal truck appointment' '拖车创建候选过滤'
Assert-Contains $loadingListsOpenApi '真实集装箱号可在PDA确认装柜完成前补录' '预装真实柜号晚录门禁'
Assert-Contains $loadingListsOpenApi '可在 EDITING 或 LOADING 阶段首次补录真实集装箱号' '预装真实柜号首次补录阶段'
Assert-Contains $adminAgents '创建柜次时自动生成唯一预装计划' 'Admin 自动预装计划流程'
Assert-Contains $loadingListsOpenApi '不依赖真实集装箱号,task 已创建后仍为 true' 'PDA task 不依赖真实柜号'
Assert-Contains $adminAgents 'PDA 最终完成前必须补齐' 'Admin 真实柜号最终门禁'
Assert-Contains $pdaAgents '当前 `taskId + warehouseId` 走任务专用 API' '国内 PDA 柜级证据入口'
Assert-Contains $pdaLoadingApi '/first-leg/pda-loading/tasks/${encodeURIComponent(taskId)}/evidence?warehouseId=' '国内 PDA 证据查询 API'
Assert-NotContains $pdaLoadingApi '/inbounds/${encodeURIComponent(inboundId)}/loading/evidence' '国内 PDA 旧入仓证据 API'
Assert-Contains $rootAgents '上传以幂等键绑定包含文件内容的请求哈希' '根装柜证据上传重放边界'
Assert-Contains $firstlegAgents '完全重放返回当前视图且不得再次上传 File' 'Firstleg 装柜证据重放边界'
Assert-Contains $cabinetEvidenceService 'uploadHash(warehouseId, expectedVersion, evidenceType, sealNo, remark, multipart)' '装柜证据上传请求哈希'
Assert-Contains $cabinetEvidenceService 'digest.update(multipart.getBytes())' '装柜证据文件内容哈希'
Assert-Matches $cabinetEvidenceService '(?s)mapper\.byOperation\(taskId, key\).{0,500}?return view\(scope\);.{0,500}?files\.upload' '装柜证据上传先查重放再调用 File'
$mapperModuleAgents = @(
@{ Module = 'audit-service'; Application = 'BaiyueAuditApplication.java' },
@{ Module = 'auth'; Application = 'BaiyueAuthApplication.java' },
@{ Module = 'event-bridge-service'; Application = 'EventBridgeApplication.java' },
@{ Module = 'file'; Application = 'FileServiceApplication.java' },
@{ Module = 'firstleg'; Application = 'BaiyueFirstlegApplication.java' },
@{ Module = 'iam'; Application = 'BaiyueIamApplication.java' },
@{ Module = 'lastleg-service'; Application = 'BaiyueLastlegApplication.java' },
@{ Module = 'order'; Application = 'BaiyueOrderApplication.java' },
@{ Module = 'warehouse'; Application = 'BaiyueWarehouseApplication.java' },
@{ Module = 'warehouse-overseas-service'; Application = 'BaiyueWarehouseOverseasApplication.java' }
)
foreach ($entry in $mapperModuleAgents) {
$moduleAgents = Read-RequiredText (Join-Path $backendRoot "$($entry.Module)/AGENTS.md")
Assert-Contains $moduleAgents $entry.Application "$($entry.Module) Mapper 启动入口"
Assert-Contains $moduleAgents 'scripts/mapper-scan-contract.mjs' "$($entry.Module) Mapper 静态门禁"
}
# 部署单元必须能从根索引进入。
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 拆柜收货开关'
Assert-Matches $overseasWorkbench "(?s)name:\s*'托盘管理'.{0,300}?available:\s*true.{0,200}?route:\s*'/pages/pallet/pallet'" '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 订舱列表无详情扇出合同'
# 五期海外出库、派送、异常和回访必须从根路由贯通到 Admin 与 Lastleg;PDA 后端存在不等于设备端已挂载。
$adminOverseasRoutes = Read-RequiredText (Join-Path $workspaceRoot 'apps/admin-web/src/modules/overseas-warehouse/routes.ts')
$lastlegAgents = Read-RequiredText (Join-Path $backendRoot 'lastleg-service/AGENTS.md')
foreach ($phase5OverseasRoute in @(
'overseas-warehouse/outbounds',
'overseas-warehouse/delivery-orders',
'overseas-warehouse/exception-orders',
'overseas-warehouse/customer-visits'
)) {
Assert-Contains $adminOverseasRoutes "path: '$phase5OverseasRoute'" "Admin 五期正式路由 $phase5OverseasRoute"
}
foreach ($phase5RootEntry in @(
'OutboundsView.vue', 'DeliveryOrdersView.vue', 'ExceptionOrdersView.vue', 'CustomerVisitsView.vue'
)) {
Assert-Contains $rootAgents $phase5RootEntry '根正式五期业务路由'
}
Assert-Contains $adminAgents '五期海外排车、出库与派送' 'Admin 五期出库派送入口'
Assert-Contains $adminAgents '五期海外异常退回与客户回访' 'Admin 五期异常回访入口'
Assert-Contains $backendAgents '五期海外排车执行、PDA 出库、派送与一件代发' '后端五期出库派送入口'
Assert-Contains $backendAgents '五期一件代发 SKU/箱唛与暂扣跨区协同' '后端五期跨区协同入口'
Assert-Contains $lastlegAgents '五期范围承接排车编辑/取消/发车' 'Lastleg 五期范围边界'
Assert-Contains $overseasPdaAgents '五期排车拣货与发车' '海外 PDA 五期排车入口'
Assert-Contains $overseasPdaAgents '五期普通/一件代发出库' '海外 PDA 五期出库入口'
# 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 || '/gateway-api'" '国内 PDA H5 同源 API'
Assert-Contains $domesticPdaVite "'/gateway-api'" '国内 PDA H5 独立代理前缀'
Assert-Contains $domesticPdaVite 'path.replace(/^\/gateway-api/, ''/api'')' '国内 PDA H5 Gateway 重写'
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 会话持久化'
# 国内和海外 PDA 使用相同协议但完全独立的 APK/WGT 更新通道。
$domesticPdaUpdater = Read-RequiredText (Join-Path $workspaceRoot 'apps/pda-uniapp/utils/app-update.js')
$domesticPdaApp = Read-RequiredText (Join-Path $workspaceRoot 'apps/pda-uniapp/App.vue')
$overseasPdaUpdater = Read-RequiredText (Join-Path $workspaceRoot 'apps/pda-overseas-uniapp/src/utils/app-update.js')
$overseasPdaApp = Read-RequiredText (Join-Path $workspaceRoot 'apps/pda-overseas-uniapp/src/App.vue')
foreach ($pdaUpdate in @(
@{ Source = $domesticPdaUpdater; Scope = '国内 PDA 在线更新' },
@{ Source = $overseasPdaUpdater; Scope = '海外 PDA 在线更新' }
)) {
Assert-Contains $pdaUpdate.Source 'VITE_PDA_UPDATE_URL' $pdaUpdate.Scope
Assert-Contains $pdaUpdate.Source "['apk', 'wgt'].includes(packageType)" $pdaUpdate.Scope
Assert-Contains $pdaUpdate.Source '更新包必须使用 HTTPS 地址' $pdaUpdate.Scope
Assert-Contains $pdaUpdate.Source 'plus.runtime.install' $pdaUpdate.Scope
}
Assert-Contains $domesticPdaApp '#ifdef APP-PLUS' '国内 PDA App 更新平台边界'
Assert-Contains $overseasPdaApp '#ifdef APP-PLUS' '海外 PDA App 更新平台边界'
Assert-Contains $pdaAgents '不得复用海外 PDA' '国内 PDA 独立更新通道'
Assert-Contains $overseasPdaAgents '不得与国内 PDA 混用' '海外 PDA 独立更新通道'
# 人工分柜到 LOADED 只允许使用已登记的可选 fixture/verify 链,不进入默认全量。
$adminAcceptanceEntry = Read-RequiredText (Join-Path $backendRoot 'scripts/admin-test-env-acceptance.mjs')
$adminAcceptanceModuleIndex = Read-RequiredText (Join-Path $backendRoot 'scripts/admin-test-env-modules/README.md')
$scriptsIndex = Read-RequiredText (Join-Path $backendRoot 'scripts/README.md')
Assert-Contains $adminAcceptanceEntry "const OPTIONAL_MODULES = ['manual-order-splitting-fixture'" '人工验收可选模块注册'
Assert-Contains $adminAcceptanceModuleIndex '人工分柜通过后可继续执行 `manual-preload-push-fixture.mjs`' '人工分柜到预装链路'
Assert-Contains $adminAcceptanceModuleIndex 'PDA 待复核通过后,`manual-loading-complete-fixture.mjs`' '人工 PDA 到 LOADED 链路'
Assert-Contains $scriptsIndex 'manual-*-fixture/verify' '人工分段验收根索引'
# 同步 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 自动配置注册'
# 全部仓库主档统一归国内 Warehouse;海外服务只保存 warehouseId 引用和物理资源。
$warehouseAgents = Read-RequiredText (Join-Path $backendRoot 'warehouse/AGENTS.md')
$overseasWarehouseAgents = Read-RequiredText (Join-Path $backendRoot 'warehouse-overseas-service/AGENTS.md')
$domesticWarehouseService = Read-RequiredText (Join-Path $backendRoot 'warehouse/src/main/java/com/baiyue/warehouse/service/WarehouseApplicationService.java')
$domesticWarehouseController = Read-RequiredText (Join-Path $backendRoot 'warehouse/src/main/java/com/baiyue/warehouse/controller/InternalWarehouseController.java')
$overseasWarehouseSql = Read-RequiredText (Join-Path $backendRoot 'warehouse-overseas-service/src/main/resources/db/warehouse.sql')
$adminIamApi = Read-RequiredText (Join-Path $workspaceRoot 'apps/admin-web/src/modules/iam/api/platformIam.ts')
Assert-Contains $backendAgents '全部仓库 ID、类型、状态、地址和能力主档归国内 `warehouse`' '后端仓库主档权威'
Assert-Contains $warehouseAgents '/internal/warehouses/shared-overseas' '国内 Warehouse 共享海外目录'
Assert-Contains $warehouseAgents '/internal/warehouses/0/{warehouseId}/active' '国内 Warehouse FBA 内部校验入口'
Assert-Contains $overseasWarehouseAgents '只保存国内仓库 ID 引用' '海外 Warehouse 引用边界'
Assert-Contains $domesticWarehouseController '@GetMapping("/shared-overseas")' '共享海外仓列表入口'
Assert-Contains $domesticWarehouseService 'hasReceivingCapability' '共享海外收货能力筛选'
Assert-Contains $adminIamApi "capabilityCode: 'RECEIVING'" 'Admin 海外收货仓候选'
Assert-NotContains $overseasWarehouseSql 'CREATE TABLE IF NOT EXISTS wh_warehouse' '海外仓库主档表'
Assert-NotContains $overseasWarehouseSql 'CREATE TABLE IF NOT EXISTS wh_warehouse_address' '海外仓库地址表'
# 国内出仓按真实货柜原子确认,船节点实际进度只允许严格向后推进。
$outboundDispatchOpenApi = Read-RequiredText (Join-Path $backendRoot 'firstleg/src/main/resources/openapi/phase3-outbound-dispatch-v1.yaml')
$carrierScheduleOpenApi = Read-RequiredText (Join-Path $backendRoot 'firstleg/src/main/resources/openapi/carrier-schedule-query-v1.yaml')
$adminContainerDetail = Read-RequiredText (Join-Path $workspaceRoot 'apps/admin-web/src/modules/container-loading/pages/ContainerDetailView.vue')
Assert-Contains $outboundDispatchOpenApi 'No partial success is possible.' '整柜出仓原子性'
Assert-Contains $outboundDispatchOpenApi 'truckAppointmentStatus: {type: string, nullable: true, description: Reference-only status' '拖车状态非门禁语义'
Assert-Contains $carrierScheduleOpenApi 'strictly greater standard-node sequence than latestActualNode' '手工实际节点单调推进'
Assert-Contains $carrierScheduleOpenApi 'estimated facts never advance actual progress' '预计节点不推进实际进度'
Assert-Contains $adminContainerDetail 'confirmDeparture' 'Admin 货柜详情确认离仓'
# 装柜完成后的整柜报关必须保持客户退税资料、平台冻结/完成与 File 二进制边界一致。
$firstlegAgents = Read-RequiredText (Join-Path $backendRoot 'firstleg/AGENTS.md')
$containerCustomsOpenApi = Read-RequiredText (Join-Path $backendRoot 'firstleg/src/main/resources/openapi/customs-v1.yaml')
$adminContainerCustomsApi = Read-RequiredText (Join-Path $workspaceRoot 'apps/admin-web/src/modules/container-loading/api/platformContainerCustoms.ts')
$clientContainerCustomsApi = Read-RequiredText (Join-Path $workspaceRoot 'apps/client-web/src/modules/first-leg/api/customs.ts')
$customsFileOpenApi = Read-RequiredText (Join-Path $backendRoot 'file/src/main/resources/openapi/customs-file-and-export-v1.yaml')
Assert-Contains $rootAgents 'ContainerCustomsPanel.vue' '根整柜报关 Admin 入口'
Assert-Contains $rootAgents 'CustomsDocumentsDialog.vue' '根整柜报关 Client 入口'
Assert-Contains $adminAgents 'components/ContainerCustomsPanel.vue' 'Admin 整柜报关入口'
Assert-Contains $adminAgents 'complete-all-buy' 'Admin 全买单柜入口'
Assert-Contains $clientAgents 'components/CustomsDocumentsDialog.vue' 'Client 退税报关资料入口'
Assert-Contains $clientAgents '开始后只读冻结资料' 'Client 报关冻结边界'
Assert-Contains $firstlegAgents 'customs/container/controller/PlatformContainerCustomsController.java' 'Firstleg 平台整柜报关入口'
Assert-Contains $firstlegAgents 'customs/container/controller/MerchantContainerCustomsController.java' 'Firstleg 客户整柜报关入口'
Assert-Contains $containerCustomsOpenApi '/api/merchant/v1/customs/loading-plans/{planId}/documents/upload:' '客户退税资料上传契约'
Assert-Contains $containerCustomsOpenApi '/api/merchant/v1/customs/documents/{documentId}/inbounds:' '客户资料入仓码范围契约'
Assert-Contains $containerCustomsOpenApi '/api/platform/v1/customs/loading-plans/{planId}/start:' '平台开始报关冻结契约'
Assert-Contains $containerCustomsOpenApi '/api/platform/v1/customs/loading-plans/documents/{documentId}/completion/upload:' '平台完成文件契约'
Assert-Contains $containerCustomsOpenApi '/api/platform/v1/customs/loading-plans/{planId}/complete-all-buy:' '全买单柜完成契约'
Assert-Contains $containerCustomsOpenApi 'enum: [TAX_REFUND, BUY_DECLARATION]' '整柜报关税务模式'
Assert-Contains $adminContainerCustomsApi "const basePath = '/platform/v1/customs/loading-plans'" 'Admin 整柜报关真实调用'
Assert-Contains $clientContainerCustomsApi '/merchant/v1/customs/orders/' 'Client 订单报关真实调用'
Assert-Contains $clientContainerCustomsApi 'Idempotency-Key' 'Client 报关写入幂等'
Assert-Contains $customsFileOpenApi 'LOADING_LIST_CUSTOMS_SOURCE' 'File 报关源文件类别'
Assert-Contains $customsFileOpenApi 'LOADING_LIST_CUSTOMS_RESULT' 'File 报关完成文件类别'
# 平台商品图片和海外 PDA 签收照片都必须走鉴权下载,不暴露内部存储路径。
$productImageController = Read-RequiredText (Join-Path $backendRoot 'file/src/main/java/com/baiyue/file/controller/PlatformProductImageController.java')
$receivingController = Read-RequiredText (Join-Path $backendRoot 'lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/controller/ReceivingContainerController.java')
Assert-Contains $productImageController '/api/platform/v1/files/product-images' '平台商品图片入口'
Assert-Contains $productImageController "hasAuthority('platform:order:list')" '平台商品图片权限'
Assert-Contains $receivingController '/current/unload-photos/files/{fileId}/download' '海外 PDA 签收照片预览'
Assert-Contains $receivingController 'CacheControl.noStore()' '海外 PDA 签收照片缓存边界'
# 尾程订单按来源柜展示服务端计划进度,整柜转换每票独立计划且整批原子。
$lastlegBusinessOpenApi = Read-RequiredText (Join-Path $backendRoot 'lastleg-service/src/main/resources/openapi/overseas-business-v1.yaml')
$lastlegAgents = Read-RequiredText (Join-Path $backendRoot 'lastleg-service/AGENTS.md')
$adminLastMileApi = Read-RequiredText (Join-Path $workspaceRoot 'apps/admin-web/src/modules/overseas-warehouse/api/lastMileOrders.ts')
Assert-Contains $lastlegBusinessOpenApi '/api/platform/v1/last-leg/orders/container-summaries:' 'Lastleg 柜级摘要契约'
Assert-Contains $lastlegBusinessOpenApi '/api/platform/v1/last-leg/inbound-plans/convert-container:' 'Lastleg 整柜计划转换契约'
Assert-Contains $lastlegBusinessOpenApi 'sourceContainerBookingId' 'Lastleg 稳定来源柜身份'
Assert-Contains $adminAgents '/orders/container-summaries' 'Admin 柜级摘要目标入口'
Assert-Contains $rootAgents '只分页返回仍有入仓码待生成有效独立计划的柜' '根柜级计划待处理筛选'
Assert-Contains $backendAgents '分页前排除全部入仓码均已生成有效独立计划的柜' '后端柜级计划待处理筛选'
Assert-Contains $adminAgents '返回仍有待生成计划入仓码的柜' 'Admin 柜级计划待处理筛选'
Assert-Contains $lastlegAgents '分页前排除全部入仓码均已生成有效独立计划的柜' 'Lastleg 柜级计划待处理筛选'
Assert-Contains $lastlegBusinessOpenApi '仅返回仍有入仓码待生成有效独立计划的柜' 'Lastleg 柜级计划待处理 OpenAPI'
Assert-Contains $adminAgents 'ACTIVE + FBA' 'Admin FBA 权威仓候选'
Assert-Contains $adminAgents '/inbound-plans/convert-container' 'Admin 整柜转换目标入口'
Assert-Contains $adminLastMileApi '/orders/container-summaries' 'Admin 柜级摘要真实调用'
Assert-NotContains $adminLastMileApi '/orders/pending-containers' 'Admin 旧柜级摘要调用'
Assert-Contains $lastlegBusinessOpenApi 'ContainerPlanProgressSummary' 'Lastleg 柜级计划进度摘要模型'
Assert-Contains $lastlegBusinessOpenApi 'ContainerPlanProgressDetail' 'Lastleg 柜级计划进度详情模型'
Assert-Contains $lastlegBusinessOpenApi 'allPlansReady' 'Lastleg 全柜计划就绪事实'
Assert-Contains $lastlegBusinessOpenApi 'plannedArrivalAt' 'Lastleg 计划到仓冻结事实'
Assert-Contains $lastlegAgents 'service/FbaWarehouseValidator.java' 'Lastleg FBA 权威仓校验入口'
# 国内 PDA 当前以页面、API 和作业状态合同覆盖部分拣货及库位不足反馈。
Assert-Contains $pdaAgents 'tests/page-contract.test.mjs' '国内 PDA 页面合同'
Assert-Contains $pdaAgents 'tests/pda-loading-api.test.mjs' '国内 PDA API 合同'
# 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/lastMileOrders.ts',
'apps/pda-overseas-uniapp/src/api/pallet.js',
'apps/pda-overseas-uniapp/src/pages/pallet/pallet.vue',
'apps/pda-overseas-uniapp/tests/pallet-operations.test.mjs',
'apps/admin-web/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue',
'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/components/ContainerCustomsPanel.vue',
'apps/admin-web/src/modules/container-loading/api/platformContainerCustoms.ts',
'apps/admin-web/src/modules/container-loading/api/platformContainerCustoms.test.ts',
'apps/admin-web/src/modules/container-loading/api/platformContainerLoading.ts',
'apps/admin-web/src/modules/loading-lists/pages/PreloadPlanDetailView.lifecycle.test.ts',
'apps/admin-web/src/modules/unified-orders/api/coLoadGroups.ts',
'apps/admin-web/src/modules/unified-orders/pages/UnifiedOrdersView.vue',
'apps/admin-web/src/modules/ocean-bookings/api/platformOceanBookings.ts',
'apps/admin-web/src/modules/ocean-bookings/pages/OceanBookingsView.vue',
'apps/admin-web/src/modules/ocean-bookings/components/OceanBookingDocumentsPanel.vue',
'apps/admin-web/src/modules/ocean-bookings/components/OceanBookingPrintDialog.vue',
'apps/admin-web/src/modules/trucking/components/TruckAppointmentForm.vue',
'apps/admin-web/src/modules/trucking/api/platformTrucking.ts',
'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/overseas-warehouse/api/deliveryOrders.ts',
'apps/admin-web/src/modules/overseas-warehouse/pages/DeliveryOrdersView.vue',
'apps/admin-web/src/modules/overseas-warehouse/pages/DeliveryOrderDetailView.vue',
'apps/admin-web/src/modules/overseas-warehouse/api/exceptionOrders.ts',
'apps/admin-web/src/modules/overseas-warehouse/pages/ExceptionOrdersView.vue',
'apps/admin-web/src/modules/overseas-warehouse/api/customerVisits.ts',
'apps/admin-web/src/modules/overseas-warehouse/pages/CustomerVisitsView.vue',
'apps/admin-web/src/modules/iam/pages/InternalUsersView.vue',
'apps/admin-web/src/modules/iam/api/platformIam.ts',
'apps/admin-web/src/modules/unified-orders/api/unifiedOrders.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/client-web/src/modules/first-leg/components/CustomsDocumentsDialog.vue',
'apps/client-web/src/modules/first-leg/api/customs.ts',
'apps/client-web/src/modules/first-leg/api/customs.test.mjs',
'apps/client-web/src/modules/first-leg/api/inboundCodeAssociations.ts',
'apps/client-web/src/modules/first-leg/components/InboundCodeAssociationDialog.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/app-update.js',
'apps/pda-uniapp/tests/app-update.test.mjs',
'apps/pda-uniapp/tests/page-contract.test.mjs',
'apps/pda-uniapp/tests/pda-loading-api.test.mjs',
'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/pages/dispatch/dispatch.vue',
'apps/pda-overseas-uniapp/src/pages/outbound/outbound.vue',
'apps/pda-overseas-uniapp/src/api/fulfillment.js',
'apps/pda-overseas-uniapp/src/stores/fulfillment.js',
'apps/pda-overseas-uniapp/tests/fulfillment-workflows.test.mjs',
'apps/pda-overseas-uniapp/src/stores/receiving.js',
'apps/pda-overseas-uniapp/tests/receiving-photo-ui-contract.test.mjs',
'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',
'apps/pda-overseas-uniapp/src/utils/app-update.js',
'apps/pda-overseas-uniapp/tests/app-update.test.mjs',
'apps/pda-overseas-uniapp/tests/business-identifiers-ui.test.mjs',
'apps/pda-overseas-uniapp/src/i18n/index.js',
'apps/pda-overseas-uniapp/src/i18n/locales/zh-CN.js',
'apps/pda-overseas-uniapp/src/i18n/locales/en.js',
'apps/pda-overseas-uniapp/src/i18n/locales/es.js',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/FeePaymentSnapshotValidator.java',
'baiyue-firstleg/scripts/mapper-scan-contract.mjs',
'baiyue-firstleg/scripts/mapper-scan-contract.test.mjs',
'baiyue-firstleg/firstleg/src/test/java/com/baiyue/firstleg/MapperRegistrationArchitectureTest.java',
'baiyue-firstleg/lastleg-service/src/test/java/com/baiyue/lastleg/MapperRegistrationArchitectureTest.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/controller/DispatchController.java',
'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/pda/controller/DispatchPdaController.java',
'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/controller/DeliveryTransferController.java',
'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/controller/OutboundPdaController.java',
'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/controller/MerchantDeliveryController.java',
'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/exceptionorder/controller/ExceptionOrderController.java',
'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/customervisit/controller/CustomerVisitController.java',
'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dropship/service/DropshipOrderService.java',
'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/service/InboundOrderDetainedOutboxService.java',
'baiyue-firstleg/common-event-contract/src/main/java/com/baiyue/common/event/OverseasInboundOrderDetainedChangedV1.java',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/LoadingWorkPalletService.java',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/OverseasInboundOrderDetainedConsumer.java',
'baiyue-firstleg/order/src/main/java/com/baiyue/order/controller/InternalOrderCargoController.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/controller/PlatformContainerController.java',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/mapper/ContainerOverviewMapper.java',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/customs/container/controller/PlatformContainerCustomsController.java',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/customs/container/controller/MerchantContainerCustomsController.java',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/customs/container/service/ContainerCustomsService.java',
'baiyue-firstleg/firstleg/src/main/resources/openapi/customs-v1.yaml',
'baiyue-firstleg/firstleg/src/main/resources/openapi/coload-groups-v1.yaml',
'baiyue-firstleg/firstleg/src/main/resources/openapi/loading-lists-v1.yaml',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/controller/PlatformColoadGroupController.java',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/service/ColoadGroupService.java',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/oceanbooking/service/OceanBookingDocumentService.java',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/oceanbooking/service/OceanBookingPrintService.java',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/service/TruckAppointmentService.java',
'baiyue-firstleg/firstleg/src/main/resources/openapi/truck-appointments-v1.yaml',
'baiyue-firstleg/file/src/main/resources/openapi/customs-file-and-export-v1.yaml',
'baiyue-firstleg/order/src/main/java/com/baiyue/order/service/InboundCodeAssociationService.java',
'baiyue-firstleg/order/src/main/java/com/baiyue/order/service/UnifiedOrderQueryService.java',
'baiyue-firstleg/order/src/main/resources/openapi/order-v1.yaml',
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/outbound/dispatch/controller/PlatformOutboundDispatchController.java',
'baiyue-firstleg/firstleg/src/main/resources/openapi/phase3-container-overview-v1.yaml',
'baiyue-firstleg/firstleg/src/main/resources/openapi/phase3-outbound-dispatch-v1.yaml',
'baiyue-firstleg/firstleg/src/main/resources/openapi/carrier-schedule-query-v1.yaml',
'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/dto/ContainerPlanProgressSummary.java',
'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/dto/ContainerPlanProgressDetail.java',
'baiyue-firstleg/lastleg-service/src/test/java/com/baiyue/lastleg/service/ContainerPlanProgressContractTest.java',
'baiyue-firstleg/lastleg-service/src/main/resources/openapi/overseas-business-v1.yaml',
'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/inboundplan/pda/gateway/UnloadPhotoFileGateway.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/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/client/DomesticWarehouseDirectoryClient.java',
'baiyue-firstleg/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/service/DomesticWarehouseDirectory.java',
'baiyue-firstleg/warehouse/src/main/java/com/baiyue/warehouse/controller/InternalWarehouseController.java',
'baiyue-firstleg/warehouse/src/main/java/com/baiyue/warehouse/dto/SharedOverseasWarehouseResponse.java',
'baiyue-firstleg/file/src/main/java/com/baiyue/file/controller/PlatformProductImageController.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',
'baiyue-firstleg/scripts/admin-test-env-modules/manual-order-splitting-contract.test.mjs',
'baiyue-firstleg/scripts/admin-test-env-modules/manual-preload-push-contract.test.mjs',
'baiyue-firstleg/scripts/admin-test-env-modules/manual-pda-ready-contract.test.mjs',
'baiyue-firstleg/scripts/admin-test-env-modules/manual-pda-batch-contract.test.mjs',
'baiyue-firstleg/scripts/admin-test-env-modules/manual-loading-complete-contract.test.mjs',
'docs/四期/船节点标准化契约.md',
'docs/一期/一期头程订单闭环设计.md',
'docs/二期/二期需求优化版-v2-测量计费入库主流程.md',
'docs/墨家设备测量上传接口说明-V3.md',
'docs/三期/三期需求确认表.md',
'docs/统一订单主状态与操作契约.md',
'docs/开发环境独立任务协作登记.md',
'docs/独立任务协作登记.md',
'docs/财务管理/财务管理产品确认表.md',
'docs/财务管理/Firstleg-Finance跨服务契约.md'
)
$criticalPaths | ForEach-Object { Assert-Path $_ }
foreach ($removedOverseasWarehouseMasterPath in @(
'baiyue-firstleg/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/controller/PlatformWarehouseController.java',
'baiyue-firstleg/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/controller/MerchantWarehouseController.java',
'baiyue-firstleg/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/entity/WarehouseEntity.java',
'baiyue-firstleg/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/entity/WarehouseAddressEntity.java',
'baiyue-firstleg/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/entity/ServiceCapabilityEntity.java'
)) {
Assert-PathMissing $removedOverseasWarehouseMasterPath
}
# 只检查明确维护的快速索引表,避免把排除规则正文中的目录名误判为业务入口。
$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 'warehouse/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 路由、脚本目录治理、企业联系信息与登录标识解耦、选填法人身份证独立上传、待审核订单状态优先、订单申报版本同步与渠道门禁、装柜证据内容哈希重放、业务编号与内部 ID 隔离、装柜清单生命周期与真实柜号后补、订舱级拖车与柜级证据、四/五期范围边界、四期柜级待处理计划筛选与范围漂移、仓库主档唯一权威、订舱候选与柜量语义、整柜出仓与船节点单调性、Gateway 覆盖、PDA 页面/运行配置/独立更新/语言预留/能力开关、人工分段验收链、Maven 模块、Lastleg 海外安全投影、同步 Trace、关键入口和排除目录。" -ForegroundColor Green
exit 0