diff --git a/apps/api/src/app/seed-activities.ts b/apps/api/src/app/seed-activities.ts index 03e9dab..c94bd7c 100644 --- a/apps/api/src/app/seed-activities.ts +++ b/apps/api/src/app/seed-activities.ts @@ -15,7 +15,8 @@ import { readFile } from 'node:fs/promises'; import { join, resolve } from 'node:path'; import { activityManifestSchema } from '@contracts'; import type { Container } from './container.ts'; -import { MASTER_OBJECTS, MASTER_SAMPLE_ROWS } from './seed-mvp-data.ts'; +import { MASTER_DOMAINS, MASTER_OBJECTS, MASTER_SAMPLE_ROWS } from './seed-mvp-data.ts'; +import { W05_TOOLS, W05_TOOL_SAMPLE } from './tools-w05.ts'; /** 已开发完成、要随播种装上的真活动包(目录名 = 包目录,不是 activityId) */ /* @@ -29,8 +30,9 @@ import { MASTER_OBJECTS, MASTER_SAMPLE_ROWS } from './seed-mvp-data.ts'; * 再跑 activities:install 即可 —— 它们的 dist 照旧随 activities:build 产出。 * 退役名单:quote-intake · quote-alternative · quote-sourcing · quote-pricing · * quote-negotiate · quote-archive + * 2026-08-26 加 ACT-WORK-05(part-substitution-assessment):差异评估活动开发完成,随本轮登记进安装通道。 */ -const REAL_PACKAGES = ['crm-relationship-coverage', 'brand-content-toolkit'] as const; +const REAL_PACKAGES = ['crm-relationship-coverage', 'brand-content-toolkit', 'part-substitution-assessment'] as const; /** * 活动包根目录。 @@ -61,10 +63,21 @@ export async function installRealActivities(container: Container): Promise const applied = await container.ledger.applyDeclarations(MASTER_OBJECTS); const conflicts = applied.flatMap((r) => r.conflicts); log( - ` 主数据四域已物化:${MASTER_OBJECTS.length} 张表` + + ` 主数据 ${MASTER_DOMAINS.length} 域已物化:${MASTER_OBJECTS.length} 张表` + // 冲突要如实报:静默吞掉的话,表结构和声明对不上而没人知道 (conflicts.length === 0 ? '' : ` —— 合并冲突 ${conflicts.length} 处:${conflicts.map((c) => c.field).join('、')}`), ); + + /* + * **纯工具随活动一起注册**(2026-08-26):从前工具契约只在 db:seed 里注册,只跑 activities:install 的 + * 开发机上,活动清单声明了工具、白名单也发了,`sys.tool` 里却没有那件工具 —— 第一次跑就撞「工具不存在」。 + * 「安装即用」包含它声明过的纯工具能调得动。register 按 name+version 幂等,重复装是 no-op。 + */ + for (const contract of W05_TOOLS) { + const verdict = await container.toolbox.register({ contract, samples: [W05_TOOL_SAMPLE] }); + if (!verdict.accepted) log(` 工具 ${contract.name} 未过两审:${verdict.staticFindings.map((f) => f.message).join('; ')}`); + } + const root = activitiesRoot(); for (const dir of REAL_PACKAGES) { diff --git a/tools/build-activities.ts b/tools/build-activities.ts index 511fc07..1b1955b 100644 --- a/tools/build-activities.ts +++ b/tools/build-activities.ts @@ -19,6 +19,7 @@ import { manifest as quoteSourcing } from '../activities/quote-sourcing/src/mani import { manifest as quoteAlternative } from '../activities/quote-alternative/src/manifest.ts'; import { manifest as crmRelationshipCoverage } from '../activities/crm-relationship-coverage/src/manifest.ts'; import { manifest as brandContentToolkit } from '../activities/brand-content-toolkit/src/manifest.ts'; +import { manifest as partSubstitutionAssessment } from '../activities/part-substitution-assessment/src/manifest.ts'; const root = dirname(dirname(fileURLToPath(import.meta.url))); @@ -31,6 +32,7 @@ const PACKAGES = [ { dir: 'quote-alternative', manifest: quoteAlternative }, { dir: 'crm-relationship-coverage', manifest: crmRelationshipCoverage }, { dir: 'brand-content-toolkit', manifest: brandContentToolkit }, + { dir: 'part-substitution-assessment', manifest: partSubstitutionAssessment }, ] as const; for (const pkg of PACKAGES) {