autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
341 lines (340 loc) • 12.9 kB
JavaScript
/**
* FieldSpec.js — V3 知识条目字段规范(唯一权威来源)
*
* 字段分级:
* REQUIRED — 缺少则立即拒绝(19 个顶层字段 + 4 个嵌套字段)
* EXPECTED — 缺少则 warning + suggestions,不阻塞入库
* OPTIONAL — 缺少不报任何问题
*
* 判决依据: 从 6 条交付管线 (Channel A/B/F, Search, Guard, Quality) 反推,
* 以「缺少时的实际损害」为唯一标准。
*
* 消费方:
* - UnifiedValidator.js → 字段完整性检查
* - dimension-text.js → SUBMISSION_SCHEMA / REQUIRED_FIELDS_DESCRIPTION
* - bootstrap-producer.js → STYLE_GUIDE 字段列表
* - MissionBriefingBuilder.js → submissionSpec 字段描述
* - lifecycle.js → JSON Schema required 数组
* - consolidated.js → 前置校验
*
* @module shared/FieldSpec
*/
// ── 字段级别枚举 ────────────────────────────────────────────
export const FieldLevel = Object.freeze({
REQUIRED: 'required',
EXPECTED: 'expected',
OPTIONAL: 'optional',
});
// ── V3 字段规范 ─────────────────────────────────────────────
export const V3_FIELD_SPEC = [
// ── 核心内容 (5) ──────────────────────────────────────────
{
name: 'title',
level: FieldLevel.REQUIRED,
type: 'string',
rule: '中文 ≤20 字,引用项目真实类名(不以项目名开头)',
pipeline: 'identity + dedup + search + QualityScorer(completeness 0.25)',
},
{
name: 'content',
level: FieldLevel.REQUIRED,
type: 'object',
rule: 'JSON 对象 { markdown, pattern?, rationale }',
pipeline: 'knowledge body container',
},
{
name: 'content.markdown',
level: FieldLevel.REQUIRED,
type: 'string',
rule: '≥200 字符的「项目特写」,含代码块+来源标注',
pipeline: 'search + Skill content + display',
},
{
name: 'content.rationale',
level: FieldLevel.REQUIRED,
type: 'string',
rule: '设计原理说明',
pipeline: 'Channel B **Why** line (via _extractFirstSentence)',
},
{
name: 'description',
level: FieldLevel.REQUIRED,
type: 'string',
rule: '中文简述 ≤80 字',
pipeline: 'search result display + QualityScorer(metadata 0.3 as summary)',
},
// ── Cursor 交付字段 (6) — 直接决定 .mdc 产出 ────────────
{
name: 'trigger',
level: FieldLevel.REQUIRED,
type: 'string',
rule: '@前缀 kebab-case 唯一标识符',
pipeline: 'Channel B ### 标题 + filter 硬依赖 + QualityScorer(completeness 0.25 + format 0.5)',
},
{
name: 'kind',
level: FieldLevel.REQUIRED,
type: 'string',
rule: 'rule | pattern | fact',
pipeline: 'CursorDeliveryPipeline._classify() 路由: rule→A, pattern→B',
},
{
name: 'doClause',
level: FieldLevel.REQUIRED,
type: 'string',
rule: '英文祈使句 ≤60 tokens,以动词开头',
pipeline: '⚠️ Channel A + B 双通道 filter 硬依赖,缺少 → 所有 .mdc 产出为零',
},
{
name: 'dontClause',
level: FieldLevel.REQUIRED,
type: 'string',
rule: '英文反向约束(描述禁止的做法)',
pipeline: 'Channel A "Do NOT" 后缀 + Channel B **Don\'t** 行。知识「禁止」维度',
},
{
name: 'whenClause',
level: FieldLevel.REQUIRED,
type: 'string',
rule: '英文触发场景描述',
pipeline: 'Channel B **When** 行 + filter 硬依赖,缺少 → Channel B 产出为零',
},
{
name: 'coreCode',
level: FieldLevel.REQUIRED,
type: 'string',
rule: '3-8 行纯代码骨架,语法完整可复制',
pipeline: 'Channel B 代码模板块 (via _skeletonize)。最直接可复制的内容',
},
// ── 分类与推理 (5) ────────────────────────────────────────
{
name: 'category',
level: FieldLevel.REQUIRED,
type: 'string',
rule: 'View/Service/Tool/Model/Network/Storage/UI/Utility',
pipeline: 'QualityScorer(metadata 0.35) + 标准分类',
systemInjected: true, // 内部路径系统注入
},
{
name: 'headers',
level: FieldLevel.REQUIRED,
type: 'array',
rule: 'import 语句数组,无 import 时传 []',
pipeline: 'QualityScorer(metadata 0.35 alongside tags)',
},
{
name: 'reasoning',
level: FieldLevel.REQUIRED,
type: 'object',
rule: '{ whyStandard: string, sources: string[], confidence: number }',
pipeline: 'provenance container',
},
{
name: 'reasoning.whyStandard',
level: FieldLevel.REQUIRED,
type: 'string',
rule: '为什么这是标准做法',
pipeline: 'lifecycle.js → aiInsight 注入',
},
{
name: 'reasoning.sources',
level: FieldLevel.REQUIRED,
type: 'array',
rule: '非空文件路径数组',
pipeline: '来源证据链 + lifecycle.js → sourceFile 推断',
},
// ── 类型与语言 (3) ────────────────────────────────────────
{
name: 'knowledgeType',
level: FieldLevel.REQUIRED,
type: 'string',
rule: 'code-pattern / architecture / best-practice 等',
pipeline: '知识维度分类',
systemInjected: true,
},
{
name: 'language',
level: FieldLevel.REQUIRED,
type: 'string',
rule: '编程语言标识 (swift/typescript/python/...)',
pipeline: 'Channel A [language] 前缀 + QualityScorer(format 0.5)',
systemInjected: true,
},
{
name: 'usageGuide',
level: FieldLevel.REQUIRED,
type: 'string',
rule: '### 章节格式使用指南',
pipeline: 'QualityScorer(completeness 0.2) → 影响排名 → 影响 token 预算裁剪',
},
// ── 推荐字段 (EXPECTED) ───────────────────────────────────
{
name: 'topicHint',
level: FieldLevel.EXPECTED,
type: 'string',
rule: 'networking / ui / data / architecture / conventions',
pipeline: 'TopicClassifier._classifyEntry() 路由。缺少 → "general" 优雅降级',
},
// ── 可选字段 (OPTIONAL) ───────────────────────────────────
{
name: 'scope',
level: FieldLevel.OPTIONAL,
type: 'string',
rule: 'universal / project-specific / team-convention',
},
{
name: 'complexity',
level: FieldLevel.OPTIONAL,
type: 'string',
rule: 'basic / intermediate / advanced',
},
{
name: 'content.pattern',
level: FieldLevel.OPTIONAL,
type: 'string',
rule: '代码片段(markdown 已含时可省略)',
},
{
name: 'sourceFile',
level: FieldLevel.OPTIONAL,
type: 'string',
rule: '来源文件相对路径',
},
{
name: 'tags',
level: FieldLevel.OPTIONAL,
type: 'array',
rule: '标签数组',
},
];
// ── 字段统计 ────────────────────────────────────────────────
// REQUIRED: 19 个顶层字段 + 4 个嵌套字段
// 顶层: title, content, description, trigger, kind, doClause, dontClause,
// whenClause, coreCode, category, headers, reasoning, knowledgeType,
// language, usageGuide
// 嵌套: content.markdown, content.rationale, reasoning.whyStandard, reasoning.sources
// EXPECTED: 1 (topicHint)
// OPTIONAL: 5 (scope, complexity, content.pattern, sourceFile, tags)
// ── 标准枚举 ────────────────────────────────────────────────
export const STANDARD_CATEGORIES = [
'View',
'Service',
'Tool',
'Model',
'Network',
'Storage',
'UI',
'Utility',
];
/** category 白名单 — 统一维度 ID + 特殊流程中的合法 category */
export const WHITELISTED_CATEGORIES = [
// ── Layer 1: 通用维度 ──
'architecture',
'coding-standards',
'design-patterns',
'error-resilience',
'concurrency-async',
'data-event-flow',
'networking-api',
'ui-interaction',
'testing-quality',
'security-auth',
'performance-optimization',
'observability-logging',
'agent-guidelines',
// ── Layer 2: 语言维度 ──
'swift-objc-idiom',
'ts-js-module',
'python-structure',
'jvm-annotation',
'go-module',
'rust-ownership',
'csharp-dotnet',
// ── Layer 3: 框架维度 ──
'react-patterns',
'vue-patterns',
'spring-patterns',
'swiftui-patterns',
'django-fastapi',
// ── 特殊来源 ──
'bootstrap',
'knowledge',
'general',
'documentation',
];
export const VALID_KINDS = ['rule', 'pattern', 'fact'];
export const VALID_TOPIC_HINTS = ['networking', 'ui', 'data', 'architecture', 'conventions'];
// ── 查询辅助函数 ────────────────────────────────────────────
/** 获取所有 REQUIRED 级别的顶层字段名 */
export function getRequiredFieldNames() {
return V3_FIELD_SPEC.filter((f) => f.level === FieldLevel.REQUIRED && !f.name.includes('.')).map((f) => f.name);
}
/** 获取所有 REQUIRED 级别的字段名(含嵌套) */
export function getAllRequiredFieldNames() {
return V3_FIELD_SPEC.filter((f) => f.level === FieldLevel.REQUIRED).map((f) => f.name);
}
/** 获取 EXPECTED 级别字段名 */
export function getExpectedFieldNames() {
return V3_FIELD_SPEC.filter((f) => f.level === FieldLevel.EXPECTED).map((f) => f.name);
}
/** 获取 AI 在外部路径必须提供的字段(= REQUIRED 全集,因无系统注入) */
export function getExternalAgentRequiredFields() {
return getRequiredFieldNames();
}
/** 获取 AI 在内部路径必须提供的字段(排除系统注入的 language/category/knowledgeType) */
export function getInternalAgentRequiredFields() {
return V3_FIELD_SPEC.filter((f) => f.level === FieldLevel.REQUIRED && !f.name.includes('.') && !f.systemInjected).map((f) => f.name);
}
/** 获取系统注入的字段名列表 */
export function getSystemInjectedFields() {
return V3_FIELD_SPEC.filter((f) => f.systemInjected).map((f) => f.name);
}
/** 生成人类友好的字段说明列表(供拒绝反馈使用) */
export function getRequiredFieldsDescription() {
return V3_FIELD_SPEC.filter((f) => f.level === FieldLevel.REQUIRED).map((f) => {
if (f.name.includes('.')) {
return `${f.name} (${f.rule})`;
}
return `${f.name} (${f.rule})`;
});
}
/** 根据字段名获取规范定义 */
export function getFieldDef(name) {
return V3_FIELD_SPEC.find((f) => f.name === name);
}
/**
* 生成 Cursor 交付字段描述对象(供 MissionBriefingBuilder.submissionSpec.cursorFields)
*
* 从 V3_FIELD_SPEC 中提取 trigger/kind/doClause/dontClause/whenClause/coreCode 的 rule,
* 并标记 REQUIRED 级别为【必填】前缀。
*/
export function getCursorDeliverySpec() {
const CURSOR_FIELD_NAMES = [
'trigger',
'kind',
'doClause',
'dontClause',
'whenClause',
'coreCode',
];
const result = {};
for (const name of CURSOR_FIELD_NAMES) {
const def = V3_FIELD_SPEC.find((f) => f.name === name);
if (def) {
const prefix = def.level === FieldLevel.REQUIRED ? '【必填】' : '';
result[name] = `${prefix}${def.rule}`;
}
}
return result;
}
/**
* 按 level 分组返回字段
* @returns }
*/
export function getFieldsByLevel() {
return {
required: V3_FIELD_SPEC.filter((f) => f.level === FieldLevel.REQUIRED),
expected: V3_FIELD_SPEC.filter((f) => f.level === FieldLevel.EXPECTED),
optional: V3_FIELD_SPEC.filter((f) => f.level === FieldLevel.OPTIONAL),
};
}