feat(content/knowledge/ai): B 四维 VERIFIED_ZERO 贡献者 + 机械化断言[P2]
5 维度贡献者齐全(Planning REAL_COUNT 已落,本次补四个 VERIFIED_ZERO): - Work/Export(content):work 仅绑 schemaId 不存字段值、ExportTaskDO 零 schema 引用→VERIFIED_ZERO;机械化断言 DO 无动态字段值列(漂移即失败)。 - KnowledgeProjection(knowledge)/AIContext(ai):零 meta 引用(projection 是 CQRS 读模型、metadataFields 是向量库)→VERIFIED_ZERO;knowledge/ai-server 加 meta-api 依赖;机械化断言贡献者无数据依赖字段。 验证:content 9/9(Verified 4+Planning 5)、knowledge 2/2、ai 2/2。下一步:单体装配验证 RealMetaImpactFacade 收齐 5 维度、all-real 不再 fail-closed。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
94a23797ff
commit
f3f7a0962f
@ -48,6 +48,12 @@
|
||||
<artifactId>muse-module-ai-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<!-- Meta Schema 用量投影:实现 MetaSchemaUsageContributor 端口(AIContext 维度 VERIFIED_ZERO) -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>muse-module-meta-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>muse-module-events-api</artifactId>
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
package cn.iocoder.muse.module.ai.application.impact;
|
||||
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaImpactDimension;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaDimensionImpact;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaImpactProbe;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaUsageContributor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* AIContext 维度 Meta Schema 用量贡献者(ai 域)。
|
||||
*
|
||||
* <p>ai 全域零 Meta Schema 引用:AI 上下文 / prompt 构建不读 schema 字段可见性(aiContext);
|
||||
* "metadataFields" 是向量库(Redis/Milvus)字段定义,非 Meta Schema。schema 侧 aiContext 可见性仅在 meta 域定义、
|
||||
* 不在 ai 实例持久化,运行时注入不留痕 → 已验证真实 0。
|
||||
* (若未来 AI 运行时按 schema aiContext 裁剪并留痕计数,须重评,见 execution §九.5。)
|
||||
* 机械化断言见 {@code AiContextUsageContributorTest}。</p>
|
||||
*/
|
||||
@Service
|
||||
public class AiContextUsageContributor implements MetaSchemaUsageContributor {
|
||||
|
||||
@Override
|
||||
public MetaImpactDimension dimension() {
|
||||
return MetaImpactDimension.AI_CONTEXT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaSchemaDimensionImpact previewDimensionImpact(MetaSchemaImpactProbe probe) {
|
||||
return MetaSchemaDimensionImpact.verifiedZero(MetaImpactDimension.AI_CONTEXT);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package cn.iocoder.muse.module.ai.application.impact;
|
||||
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaImpactDimension;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaDimensionImpact;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaImpactProbe;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* AIContext 维度 VERIFIED_ZERO 贡献者测试 + 机械化漂移断言。
|
||||
*/
|
||||
class AiContextUsageContributorTest {
|
||||
|
||||
@Test
|
||||
void isVerifiedZero() {
|
||||
AiContextUsageContributor contributor = new AiContextUsageContributor();
|
||||
assertEquals(MetaImpactDimension.AI_CONTEXT, contributor.dimension());
|
||||
MetaSchemaDimensionImpact impact = contributor.previewDimensionImpact(
|
||||
new MetaSchemaImpactProbe(1L, "k", 1, "h", Set.of("a"), Set.of(), Set.of()));
|
||||
assertEquals(MetaSchemaDimensionImpact.RealityKind.VERIFIED_ZERO, impact.realityKind());
|
||||
assertEquals(0, impact.affectedInstanceCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasNoDataDependency() {
|
||||
// 机械化断言:VERIFIED_ZERO 贡献者不得注入数据依赖;一旦出现字段说明开始读 ai 数据,须改 REAL_COUNT 重评。
|
||||
long fields = Arrays.stream(AiContextUsageContributor.class.getDeclaredFields())
|
||||
.filter(f -> !f.isSynthetic()).count();
|
||||
assertEquals(0, fields, "VERIFIED_ZERO 贡献者出现字段依赖,疑似开始消费 schema,须重新评估真实计数");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.muse.module.content.application.impact;
|
||||
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaImpactDimension;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaDimensionImpact;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaImpactProbe;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaUsageContributor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Export 维度 Meta Schema 用量贡献者(content 域)。
|
||||
*
|
||||
* <p>{@code ExportTaskDO} 零 schema 引用,导出按 work 正文内容生成(非 schema 字段投影);
|
||||
* schema 侧的 exportable 可见性仅在 meta 域定义、不在 export 任务实例持久化——故「已验证真实 0」。
|
||||
* (若未来导出改为按 schema exportable 字段裁剪并记录字段级用量,须改置 meta-server 真实计数,
|
||||
* 见 execution §三 Export 行。)机械化断言见 {@code ContentVerifiedZeroContributorTest}。</p>
|
||||
*/
|
||||
@Service
|
||||
public class ContentExportUsageContributor implements MetaSchemaUsageContributor {
|
||||
|
||||
@Override
|
||||
public MetaImpactDimension dimension() {
|
||||
return MetaImpactDimension.EXPORT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaSchemaDimensionImpact previewDimensionImpact(MetaSchemaImpactProbe probe) {
|
||||
return MetaSchemaDimensionImpact.verifiedZero(MetaImpactDimension.EXPORT);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.muse.module.content.application.impact;
|
||||
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaImpactDimension;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaDimensionImpact;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaImpactProbe;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaUsageContributor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Work 维度 Meta Schema 用量贡献者(content 域)。
|
||||
*
|
||||
* <p>work 仅通过 work_schema_id 绑定 schema(关联引用),不在 work 表持久化任何 schema 字段值——
|
||||
* 删 / 改 schema 字段不破坏 work 实例数据,故为「已验证真实 0」(非 unknown)。
|
||||
* 机械化断言见 {@code ContentVerifiedZeroContributorTest}:work 域不得出现承载 schema 字段值的动态列,
|
||||
* 漂移即测试失败,强制重评 VERIFIED_ZERO。</p>
|
||||
*/
|
||||
@Service
|
||||
public class ContentWorkUsageContributor implements MetaSchemaUsageContributor {
|
||||
|
||||
@Override
|
||||
public MetaImpactDimension dimension() {
|
||||
return MetaImpactDimension.WORK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaSchemaDimensionImpact previewDimensionImpact(MetaSchemaImpactProbe probe) {
|
||||
return MetaSchemaDimensionImpact.verifiedZero(MetaImpactDimension.WORK);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package cn.iocoder.muse.module.content.application.impact;
|
||||
|
||||
import cn.iocoder.muse.module.content.dal.dataobject.ExportTaskDO;
|
||||
import cn.iocoder.muse.module.content.dal.dataobject.WorkDO;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaImpactDimension;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaDimensionImpact;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaImpactProbe;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Work / Export 维度 VERIFIED_ZERO 贡献者测试 + 机械化漂移断言。
|
||||
*
|
||||
* <p>机械化断言:一旦 work / export 实例表出现承载 schema 字段值的动态列,说明该域开始消费 schema,
|
||||
* VERIFIED_ZERO 假设失效,断言失败以强制重新评估(防止静默漂移放行错误的 0)。</p>
|
||||
*/
|
||||
class ContentVerifiedZeroContributorTest {
|
||||
|
||||
/** 承载「按 schema fieldKey 的字段值」的典型列名;出现任一即视为该域开始消费 schema。 */
|
||||
private static final Set<String> DYNAMIC_FIELD_VALUE_COLUMNS =
|
||||
Set.of("dynamicFields", "fieldValues", "customFields", "metaFieldValues", "contentPayload", "schemaFields");
|
||||
|
||||
private MetaSchemaImpactProbe anyProbe() {
|
||||
return new MetaSchemaImpactProbe(100L, "work_core", 2, "hash",
|
||||
Set.of("title"), Set.of("desc"), Set.of("tag"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void workContributor_isVerifiedZero() {
|
||||
ContentWorkUsageContributor contributor = new ContentWorkUsageContributor();
|
||||
assertEquals(MetaImpactDimension.WORK, contributor.dimension());
|
||||
MetaSchemaDimensionImpact impact = contributor.previewDimensionImpact(anyProbe());
|
||||
assertEquals(MetaSchemaDimensionImpact.RealityKind.VERIFIED_ZERO, impact.realityKind());
|
||||
assertEquals(0, impact.affectedInstanceCount());
|
||||
assertEquals(0, impact.fieldRemovedInstanceCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
void exportContributor_isVerifiedZero() {
|
||||
ContentExportUsageContributor contributor = new ContentExportUsageContributor();
|
||||
assertEquals(MetaImpactDimension.EXPORT, contributor.dimension());
|
||||
MetaSchemaDimensionImpact impact = contributor.previewDimensionImpact(anyProbe());
|
||||
assertEquals(MetaSchemaDimensionImpact.RealityKind.VERIFIED_ZERO, impact.realityKind());
|
||||
assertEquals(0, impact.affectedInstanceCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
void workDO_hasNoDynamicFieldValueColumn() {
|
||||
assertNoDynamicFieldValueColumn(WorkDO.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void exportTaskDO_hasNoDynamicFieldValueColumn() {
|
||||
assertNoDynamicFieldValueColumn(ExportTaskDO.class);
|
||||
}
|
||||
|
||||
private void assertNoDynamicFieldValueColumn(Class<?> doClass) {
|
||||
Set<String> fieldNames = Arrays.stream(doClass.getDeclaredFields())
|
||||
.map(Field::getName).collect(Collectors.toSet());
|
||||
Set<String> hit = fieldNames.stream().filter(DYNAMIC_FIELD_VALUE_COLUMNS::contains).collect(Collectors.toSet());
|
||||
assertTrue(hit.isEmpty(),
|
||||
doClass.getSimpleName() + " 出现动态字段值列 " + hit + ";该域疑似开始消费 schema,VERIFIED_ZERO 假设失效,须重新评估真实计数");
|
||||
}
|
||||
}
|
||||
@ -22,6 +22,12 @@
|
||||
<artifactId>muse-module-knowledge-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<!-- Meta Schema 用量投影:实现 MetaSchemaUsageContributor 端口(KnowledgeProjection 维度 VERIFIED_ZERO) -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>muse-module-meta-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>muse-module-events-api</artifactId>
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.muse.module.knowledge.application.impact;
|
||||
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaImpactDimension;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaDimensionImpact;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaImpactProbe;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaUsageContributor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* KnowledgeProjection 维度 Meta Schema 用量贡献者(knowledge 域)。
|
||||
*
|
||||
* <p>knowledge 全域零 Meta Schema 引用:其 "projection" 是跨来源 CQRS 读模型
|
||||
* (MuseKnowledgeSourceBindingProjection),与 Meta Schema 字段投影无关;KB 自有 visibilityPolicy 是知识域概念,
|
||||
* 非 schema 可见性。删 / 改 schema 字段不影响 knowledge 任何实例 → 已验证真实 0(非 unknown)。
|
||||
* 机械化断言见 {@code KnowledgeProjectionUsageContributorTest}:本贡献者无数据依赖字段(漂移即失败)。</p>
|
||||
*/
|
||||
@Service
|
||||
public class KnowledgeProjectionUsageContributor implements MetaSchemaUsageContributor {
|
||||
|
||||
@Override
|
||||
public MetaImpactDimension dimension() {
|
||||
return MetaImpactDimension.KNOWLEDGE_PROJECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaSchemaDimensionImpact previewDimensionImpact(MetaSchemaImpactProbe probe) {
|
||||
return MetaSchemaDimensionImpact.verifiedZero(MetaImpactDimension.KNOWLEDGE_PROJECTION);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package cn.iocoder.muse.module.knowledge.application.impact;
|
||||
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaImpactDimension;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaDimensionImpact;
|
||||
import cn.iocoder.muse.module.meta.api.impact.MetaSchemaImpactProbe;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* KnowledgeProjection 维度 VERIFIED_ZERO 贡献者测试 + 机械化漂移断言。
|
||||
*/
|
||||
class KnowledgeProjectionUsageContributorTest {
|
||||
|
||||
@Test
|
||||
void isVerifiedZero() {
|
||||
KnowledgeProjectionUsageContributor contributor = new KnowledgeProjectionUsageContributor();
|
||||
assertEquals(MetaImpactDimension.KNOWLEDGE_PROJECTION, contributor.dimension());
|
||||
MetaSchemaDimensionImpact impact = contributor.previewDimensionImpact(
|
||||
new MetaSchemaImpactProbe(1L, "k", 1, "h", Set.of("a"), Set.of(), Set.of()));
|
||||
assertEquals(MetaSchemaDimensionImpact.RealityKind.VERIFIED_ZERO, impact.realityKind());
|
||||
assertEquals(0, impact.affectedInstanceCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasNoDataDependency() {
|
||||
// 机械化断言:VERIFIED_ZERO 贡献者不得注入数据依赖;一旦出现字段说明开始查 knowledge 数据,须改 REAL_COUNT 重评。
|
||||
long fields = Arrays.stream(KnowledgeProjectionUsageContributor.class.getDeclaredFields())
|
||||
.filter(f -> !f.isSynthetic()).count();
|
||||
assertEquals(0, fields, "VERIFIED_ZERO 贡献者出现字段依赖,疑似开始消费 schema,须重新评估真实计数");
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user