| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- """Generate complete Skill dictionaries from maintained business definitions and SQLite DDL."""
- import hashlib
- import json
- from pathlib import Path
- import re
- import sqlite3
- import sys
- ROOT=Path(__file__).resolve().parents[1]
- sys.path.insert(0,str(ROOT/'server/voc-library'))
- import schema_catalog
- import retrieval
- from product_insights import ANNOTATION_DDL
- PURPOSES=dict(line.split('|',1) for line in '''_User|平台用户账号,员工身份不由昵称创建
- _Role|平台角色与授权关系
- KfProbe|部署验证记录
- KfSource|原文、文件与数据集来源
- KfSession|工作坊会话与可信员工/Agent归属
- KfInsight|洞察与需求归纳
- KfArtifact|阶段成果与报告
- KfProject|课堂项目与阶段
- KfOpportunity|机会卡片
- KfCategory|业务品类字典
- KfCategoryRelation|品类之间的结构关系
- KfProduct|结构化业务产品
- KfEvidence|逐字证据、出处及研究范围
- KfEvidenceLink|证据与业务对象关系
- KfMarketMetric|市场指标及统计口径
- KfAssessment|验证模型与评估结果
- KfConcept|新品方案版本
- KfStageEvent|项目阶段推进事件
- KfImportJob|入库任务及汇总回执
- KfImportItem|逐条入库结果及依赖
- KfReviewIssue|人工复核问题及状态
- KfSupplier|供应商资料
- KfMaterial|原料资料
- KfProcess|工艺资料
- KfStandard|标准与约束依据
- KfSupplyQuote|供应报价及时间口径
- KfFormulaItem|方案配料及计算基准
- KfVocRun|采集执行与用量回执,不执行采集
- KfRawXhsNote|小红书原始内容
- KfRawXhsComment|小红书原始评论
- KfRawDouyinVideo|抖音原始视频文字与指标
- KfRawDouyinComment|抖音原始评论
- KfRawTaobaoItem|淘宝接口族原始商品
- KfRawTaobaoReview|淘宝接口族原始评价
- KfRawJdItem|京东原始商品
- KfRawJdReview|京东原始评价
- KfRawBilibiliPost|哔哩哔哩原始内容
- KfRaw1688Offer|1688原始货源
- KfSku|业务SKU规格
- KfRetailPriceSnapshot|业务零售价格快照
- KfProcessStep|工艺步骤与约束
- KfQuestionnaireQuestion|问卷问题与字段定义
- KfQuestionnaireAnswer|真实问卷答复,保留原话
- KsfServiceCredential|服务凭据的授权与到期配置
- KsfOperation|幂等操作和回执
- KsfUploadSession|文件上传会话
- KsfReportPreview|报告预览及内容身份
- KsfConfirmationEvent|员工真实确认事件
- KsfRuntimeConfig|运行配置、称呼及分组等受控注册表
- KsfFileObject|已验证文件及字节'''.splitlines())
- EXTRA_LABELS=dict(line.split('|',1) for line in '''objectId|服务生成记录编号
- createdAt|服务创建时间
- updatedAt|服务更新时间
- label|配置显示标签
- tokenHash|服务端凭据指纹,非Agent业务数据
- scopes|授权作用范围
- projectIds|授权项目编号集合
- enabled|是否启用
- expiresAt|到期时间
- ownerId|服务或文件归属编号
- requestId|稳定请求追踪编号
- operation|操作类型
- payloadHash|请求载荷指纹
- receipt|操作实际回执
- fileName|上传文件名
- contentType|文件媒体类型
- sizeBytes|文件字节数
- sha256|完整文件字节指纹
- state|上传状态
- fileReceipt|服务验证的文件回执
- identity|报告版本与内容绑定身份
- file|实际文件引用
- reportType|报告类型代码
- dataMode|实际取得模式
- artifactSubtype|附属成果子类型
- employeeId|真实确认员工编号
- previewId|已生成预览编号
- action|员工确认操作
- confirmedAt|实际确认时间
- key|受控配置项键
- value|受控配置对象
- name|文件或业务名称
- bytesBase64|文件字节的Base64编码'''.splitlines())
- SPECIAL={
- '_User':'平台用户管理;不接受研究资料通用导入', '_Role':'平台角色管理;不接受研究资料通用导入',
- 'KfProbe':'运维部署探测,不接受研究资料导入', 'KfSource':'workshop-import内来源登记;文件走受控上传验证',
- 'KfSession':'workshop-start', 'KfArtifact':'workshop-save;正式报告report-preview/report-submit及真人确认',
- 'KfProject':'project-create/project-progress', 'KfOpportunity':'workshop-save机会卡',
- 'KfConcept':'concept-save', 'KfFormulaItem':'concept-save配料', 'KfStageEvent':'project-progress等流程自动生成',
- 'KfVocRun':'既有ingest采集回执登记', 'KfImportJob':'workshop-import/ingest自动生成',
- 'KfImportItem':'workshop-import/ingest自动生成', 'KfReviewIssue':'审核或噪声反馈服务生成',
- 'KfQuestionnaireAnswer':'ksfApplyReviewFeedback(action=record_answer);当前wrapper无直连命令,须按已部署入口使用,不能冒称可直写',
- 'KsfServiceCredential':'管理员配置;Agent不得写凭据值', 'KsfOperation':'服务幂等处理自动生成',
- 'KsfUploadSession':'受控文件上传流程生成', 'KsfReportPreview':'report-preview服务生成',
- 'KsfConfirmationEvent':'真实员工确认页生成,不代造确认',
- 'KsfRuntimeConfig':'employee-name/分组管理等专用服务,或管理员运行配置;不通用导入',
- 'KsfFileObject':'受控文件上传服务生成',
- }
- def write(path,data):
- path.parent.mkdir(parents=True,exist_ok=True)
- path.write_text(json.dumps(data,ensure_ascii=False,indent=2)+'\n',encoding='utf-8')
- def main():
- source=ROOT/'server/references/runtime-data.json'; data=json.loads(source.read_text(encoding='utf-8'))
- core=(ROOT/'server/src/core.mjs').read_text(encoding='utf-8')
- protected=set(re.findall(r"'([^']+)'",re.search(r'const serverFields=new Set\(\[(.*?)\]\)',core).group(1)))
- managed={'schemaVersion','externalKey','reviewState','recordState'}
- tables={}
- for table,defs in data['tables'].items():
- assert table in PURPOSES, 'UNDOCUMENTED_TABLE:'+table
- fields={}
- for name,definition in defs.items():
- meaning=definition.get('label') or EXTRA_LABELS.get(name)
- assert meaning, 'UNDOCUMENTED_FIELD:'+table+'.'+name
- item={**definition,'meaning':meaning,'requiredByDefinition':bool(definition.get('required')),
- 'allowedInGenericImport':table in data['importClasses'] and name not in protected and definition['type'] in ('String','Number','Boolean','Array','Object','Date','Pointer','File'),
- 'writeOwner':'service' if name in protected or table.startswith('Ksf') or table.startswith('_') else 'relation_service' if definition['type']=='Relation' else 'managed_metadata' if name in managed else 'agent_source_mapping',
- 'nullMeaning':'未取得/不适用,不用0、空姓名或当前日期代替;必填项缺失须补来源',
- 'unit':'g' if name in ('netWeightG','totalNetWeightG') else 'bytes' if name in ('sizeBytes','fileSize') else definition.get('unit')}
- if definition['type'] in ('Object','Array'):item['valueStructure']='开放JSON结构;实体字段已完整列出,内部键按操作合同/真实原载荷,不臆造固定嵌套字段'
- if name=='dataMode':item['allowedValues']=data['reportRules']['dataModes']
- if name=='reviewState':item['importAllowedValues']=['pending','draft']
- if name=='recordState':item['importAllowedValues']=['active','archived']
- fields[name]=item
- tables[table]={'purpose':PURPOSES[table],'readRoute':'workshop-search/workshop-read(受当前授权与noiseContext约束)' if table.startswith('Kf') and not table.startswith('Ksf') else '只提供schema元信息,不通过研究Agent读取内部行值',
- 'writeRoute':SPECIAL.get(table,'workshop-import/ingest(以实际allowedClasses为准)'),
- 'genericImportDeclared':table in data['importClasses'],'fields':fields}
- dictionary={'schema':'ksf.business-data-dictionary.v1','schemaVersion':data['schemaVersion'],
- 'contractRevision':data['contractRevision'],'sourceSha256':hashlib.sha256(source.read_bytes()).hexdigest(),
- 'tableCount':len(tables),'fieldCount':sum(len(t['fields']) for t in tables.values()),'tables':tables,
- 'liveSchemaCommand':'workshop-schema','authority':'本地维护定义;生产实际表列须workshop-schema核对,未部署不能宣称已读取生产全结构',
- 'importAuthority':'workshop-contract实际allowedClasses/字段;本字典不授予写权限','productionVerified':False}
- platform=json.loads((ROOT/'server/references/platform-field-dictionary.json').read_text(encoding='utf-8'))
- physical=json.loads((ROOT/'server/references/production-schema-20261106.json').read_text(encoding='utf-8'))
- dictionary['platformFields']=platform['tables']
- dictionary['platformCommonFields']=platform['commonFields']
- for table in physical['tables']:
- for field in table['fields']:
- definition=tables.get(table['name'],{}).get('fields',{}).get(field['logicalName']) or platform['tables'].get(table['name'],{}).get(field['name']) or platform['commonFields'].get(field['name'])
- assert definition and definition.get('meaning'), 'UNMAPPED_PHYSICAL_FIELD:'+table['name']+'.'+field['name']
- field['meaning']=definition['meaning']
- field['writeOwner']=definition['writeOwner']
- field['allowedInGenericImport']=definition.get('allowedInGenericImport',False)
- dictionary['physicalSchemaSnapshot']=physical
- dictionary['logicalSchemaSnapshot']=json.loads((ROOT/'server/references/production-logical-schema-20261106.json').read_text(encoding='utf-8'))
- dictionary['relationTables']={
- '_Join:'+name+':'+table:{'ownerClass':table,'field':name,'targetClass':definition['targetClass'],
- 'meaning':table+'.'+name+'关系存储;关联'+definition['targetClass']+',由专用业务服务/Parse维护,不直接SQL写入'}
- for table,values in data['tables'].items() for name,definition in values.items() if definition['type']=='Relation'}
- dictionary['physicalFieldCount']=physical['fieldCount']
- dictionary['physicalSnapshotAuthority']='已独立读取的生产元信息快照,仅含列与约束;运行时仍应workshop-schema核差异,不代表可读取内部行值'
- write(ROOT/'server/references/business-data-dictionary.json',dictionary)
- write(ROOT/'skills/ksf-workshop-runtime/references/business-data-dictionary.json',dictionary)
- c=sqlite3.connect(':memory:');c.executescript((ROOT/'server/voc-library/schema.sql').read_text(encoding='utf-8'))
- retrieval.create_index(c);c.executescript(ANNOTATION_DDL)
- c.executescript('CREATE TABLE source_origins(source_record_id TEXT NOT NULL REFERENCES source_records(id),archive_sha256 TEXT NOT NULL,PRIMARY KEY(source_record_id,archive_sha256)); CREATE TABLE record_versions(entity TEXT NOT NULL,record_id TEXT NOT NULL,batch_sha256 TEXT NOT NULL,record_json TEXT NOT NULL,PRIMARY KEY(entity,record_id,batch_sha256)); ANALYZE;')
- research=schema_catalog.catalog(c);assert research['complete'], 'INCOMPLETE_RESEARCH_SEMANTICS'
- research.update(authority='维护DDL生成的完整结构样本;安装状态与实际计数请query_voc.py schema读取',installed=False)
- for t in research['tables']:t['installed']=False;t['recordCount']=None
- write(ROOT/'skills/ksf-voc-library/references/research-data-dictionary.json',research)
- print(json.dumps({'businessTables':len(tables),'businessFields':dictionary['fieldCount'],
- 'researchTables':research['tableCount'],'researchFields':sum(len(t['fields']) for t in research['tables'])}))
- if __name__=='__main__':main()
|