import assert from 'node:assert/strict' import fs from 'node:fs' const read = (path) => fs.readFileSync(path, 'utf8') const home = read('backend/src/main/java/com/danyang/match/platform/home/service/HomeApplicationService.java') const caps = fs.existsSync('backend/src/main/java/com/danyang/match/platform/capability/service/CapabilityService.java') ? read('backend/src/main/java/com/danyang/match/platform/capability/service/CapabilityService.java') : home // fallback: CapabilityService 独立化前逻辑在 HomeApplicationService 里 const miniapp = read('miniapp/pages/index/index.ts') const wxml = read('miniapp/pages/index/index.wxml') const project = JSON.parse(read('project.config.json')) const labels = ['找对象', '公益红娘', '公益活动', '婚恋咨询', '婚恋课堂', '婚前辅导', '婚恋反诈', '善缘服务站'] let previous = -1 for (const label of labels) { const position = home.indexOf(`"${label}"`) assert.ok(position > previous, `首页入口顺序错误: ${label}`) previous = position } // 首页实名状态必须来自数据库,但按 AGENTS.md #26 只能经由 CapabilityService 委托, // 首页不得自行持有 userIdentityMapper 复制业务规则。查库断言落在 caps(CapabilityService)侧。 assert.match(caps, /userIdentityMapper\.findByUserId/, 'Capability 实名状态必须来自数据库') assert.match(home, /capabilityService\.isIdentityVerified/, '首页实名状态必须委托 CapabilityService(AGENTS.md #26)') assert.doesNotMatch(home, /userIdentityMapper/, '首页不得绕过 CapabilityService 直接查实名表') assert.match(home, /recommendationEngineService\.getDailyRecommendations/, '首页推荐必须来自正式推荐引擎') assert.match(home, /contentArticleMapper\.findPublishedAll/, '首页课堂内容必须来自内容模块') assert.match(home, /serviceLocationMapper\.selectOne/, '首页服务站必须来自服务站模块') assert.match(caps, /setDisabledReason/, '不可用入口必须返回服务端原因') assert.match(caps, /isIdentityVerified/, 'Capability 必须校验真实实名状态') assert.match(caps, /ACCOUNT_STATUS_NORMAL/, 'Capability 必须拒绝非正常账户') assert.match(home, /\/pages\/counseling-intro\/counseling-intro/, '咨询服务建议必须跳转真实页面') assert.match(home, /\/pages\/premarital-intro\/premarital-intro/, '婚前辅导建议必须跳转真实页面') assert.doesNotMatch(home, /"pages\//, '服务端返回的小程序路由必须以斜杠开头') assert.doesNotMatch(home, /setVerified\(true\)/, '禁止硬编码实名通过') assert.doesNotMatch(home, /card\.setId\("default"\)/, '禁止硬编码服务站') assert.deepEqual(project.setting.useCompilerPlugins, ['typescript']) assert.ok(fs.existsSync('miniapp/pages/index/index.ts')) assert.ok(!fs.existsSync('miniapp/pages/index/index.js'), '首页只能保留 TypeScript 运行源') assert.ok(fs.existsSync('miniapp/pages/discover/discover.ts')) assert.ok(!fs.existsSync('miniapp/pages/discover/discover.js'), '找对象页只能保留 TypeScript 运行源') assert.match(miniapp, /disabledReason/, '小程序必须显示服务端 Disabled 原因') assert.match(miniapp, /loadError: true/, '首页必须有网络错误状态') assert.match(miniapp, /matchStore\.like\(userId\)/, '首页喜欢操作必须调用正式关系服务') assert.match(miniapp, /matchStore\.pass\(userId\)/, '首页略过操作必须调用正式关系服务') assert.doesNotMatch(miniapp, /setTimeout\(/, '首页不得保留演示用延时反馈') assert.match(miniapp, /QUICK_ENTRIES\.map/, '服务端入口必须按固定业务顺序合并') assert.match(wxml, /home-hero-v2\.jpg/, '首页默认 Banner 必须使用参考图夜景主视觉') assert.doesNotMatch(wxml, />› previous, `首页区块顺序错误: ${section}`) previous = position } console.log('Phase 07 home contracts passed')