Archived
**资料文件全链**(用户:审核资料这一步要真产出 word/excel/md/html,前端能渲、点资料名能开)
接手时这一步一个文件都产不出来 —— S3 剧本白纸黑字写着「file_ref 本 MVP 阶段可留空」。
文件是台账那一行的投影,不另存一份:
· 声明 `file:{titleColumn,bodyColumn,formatColumn}`,它同时是授权面(没声明就点不开)
· 现造真字节 —— docx/xlsx 是自己打的 OOXML 包(zip-write:store+CRC32,零依赖)
· 读回来渲 —— 解的就是造出来那份字节,渲得出来才证明文件是真的
· 件上 `data-file-of` → 工作区二级界面(Word 纸面/Excel 网格/渲好的 md/沙箱 html)+ 下载原件
放行落地前把每一份冻进 `sys.task_asset_file`(迁移 0029):归档件点开的必须是签字那一刻
那一份,而资料落在主数据上、试跑单不落正式表 —— 不存这一份,收工后一个都点不开。
工作成果里「产出的资料」自成一摞。Markdown 富文本渲染顺带销账(仍零依赖)。
**Harness**
· 画面按「这一拍办完之后」在办的那一步挑 —— 从前拿拍首的局面决定拍尾的事:
收掉 S4、发出 S5 的卡,而屏上还摆着 S4 的只读件,人无处可填(墙要配路第四次现形)
· 验收「重做」真能退回重做,且打回后台账没动就不许再提交(软硬两段,不锁死单子)
· 立监听的授权面是清单声明;发卡的授权面是调人预算,不是计划项
· 读工具同参重调有兜底;空转写身后还有行动就不废串;finish 的 doneWhen 按写完后的草稿算
**界面**
· 翻件与翻页各归各位(从前二选一,多卡多页时页翻不动);没得翻写「—」不写 0/0
· 工作成果详情能翻份;表宽超出能横滑(E04/I01 抄版式时把 overflow-x 抄丢了)
· 查看面灰底滚过一屏变白 —— 两条独立的路都治了(沙箱内不同色 / 弹性子项不长个)
· 测试台「取不到」不再当成「还活着」
**活动**
E04 关系覆盖、I01 品牌内容各自补到验收线:判据全读基座数、判据指向的东西摆上卡面、
样例满载且名字 ≤14 字;提交前要裁的判据搬进说明书(模型会压拍,压过之后只有说明书还在)。
验收:e2e i01 4/4、e04 3/3 全部 released,资料在办中渲得出、放行后存了档点得开;
门禁 typecheck/lint/depcruise/1628 测全绿。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EEJX8Z7CHejvwmDQyPQuBX
527 lines
26 KiB
TypeScript
527 lines
26 KiB
TypeScript
/**
|
|
* 活动包清单 —— I01 品牌形象与销售工具包管理(案例活动)。
|
|
*
|
|
* 业务出处:`docs/SS01-客户与市场/i01-html/I01-活动流程与工单说明.md`(7 步业务链条,
|
|
* 工单只针对生产流程①→⑤,收成 1 张执行工单 + 2 张验收工单)、
|
|
* `docs/SS01-客户与市场/Demo-E04-I01-Activity台账关联与设计.html`(L-01 宏观市场台账 /
|
|
* L-05 品牌内容库的字段表与读写关系)。
|
|
*
|
|
* 这是本仓库第二个不属于 `quote-*` A1-A7 报价管线的活动,方法论照抄第一个
|
|
* (`crm-relationship-coverage` / E04)已验证过的样子:双级下拉入参、活动自有工作台账
|
|
* + 共享主数据、decide 决策卡循环做中间验收、六步案例模型。
|
|
*
|
|
* 两处与 E04 的刻意不同:
|
|
* ① E04 核心是**读写**共享主数据(`customer.profile`/`customer.contact`),
|
|
* I01 核心是**只读** L-01(`market.signal`)、**读写**它独有的 L-05
|
|
* (`content.asset`)——本 Demo 范围内 I01 是 `content.asset` 唯一的读写者,
|
|
* 不追加列合并,是这份活动包**第一次**完整声明这两张台账的物理结构。
|
|
* ② I01 没有 E04 那种「AI 做不到、必须人去线下执行」的环节(内容初稿由 AI 草拟,
|
|
* 人只审不做)——所以只有 1 张执行工单(S2_requirement_confirm),
|
|
* 验收工单反倒有 2 张(S4_draft_review 审初稿 + T_release 发布确认),
|
|
* 与 E04(1 张验收决策 + 1 张终局放行)结构同型,只是执行工单少一张。
|
|
*/
|
|
import type { ActivityManifest, DmnModel } from '@contracts';
|
|
import { activityIdSchema } from '@contracts';
|
|
import { CONTENT_SKILLS } from './skills.ts';
|
|
import { CMMN_XML, NARRATIVE, CONTENT_PHASES, CONTENT_STEPS } from './case-model.ts';
|
|
import { REQUIREMENT_LIST, DRAFT_REVIEW, PUBLISH_CONFIRM } from './views/report.ts';
|
|
|
|
const D = 'content_brand';
|
|
const ACTIVITY_ID = activityIdSchema.parse('brand-content-toolkit');
|
|
|
|
/** 没有判定表 —— 触发事件→内容类型、BT 层级→内容结构都是文字规则,不是离散分支命中表。 */
|
|
const EMPTY_DMN: DmnModel = { drd: [], tables: [] };
|
|
|
|
export const manifest: ActivityManifest = {
|
|
identity: {
|
|
activityId: ACTIVITY_ID,
|
|
name: 'I01 · 品牌形象与销售工具包管理',
|
|
packageVersion: '1.2.2',
|
|
category: '内容生产',
|
|
sdkVersion: '0.1.0-m5',
|
|
checksum: 'dev-checksum-brand-content-toolkit',
|
|
},
|
|
|
|
/* ── 契约七件 ────────────────────────────────────────────────── */
|
|
contract: {
|
|
activityId: ACTIVITY_ID,
|
|
version: '1.0.0',
|
|
input: {
|
|
/*
|
|
* 不是来件解析(没有唯一「这封信」),是触发参数 —— 与 E04 同一处置
|
|
* (两级下拉 + 选填客户/说明):
|
|
* ① `trigger` 必填 —— 主动 / 被动,显式下拉,不接受省略;
|
|
* ② `reason`/`requester` 选填,只在对应 `trigger` 值时现身(`showWhen`);
|
|
* ③ `targetCustomer` 选填字符串 —— 定向客户编码,通用内容留空。
|
|
*/
|
|
data: {
|
|
type: 'object',
|
|
required: ['trigger'],
|
|
properties: {
|
|
trigger: {
|
|
type: 'string',
|
|
enum: ['proactive', 'reactive'],
|
|
enumNames: ['主动触发(战略调整/新市场/工具过期/月度更新)', '被动触发(使用方请求)'],
|
|
title: '触发方式',
|
|
},
|
|
reason: {
|
|
type: 'string',
|
|
enum: ['strategy_shift', 'new_market', 'tool_outdated', 'monthly_update'],
|
|
enumNames: ['战略调整', '进入新市场', '工具过期', '月度定期内容更新'],
|
|
title: '主动触发的原因(仅主动触发时选)',
|
|
showWhen: { field: 'trigger', equals: 'proactive' },
|
|
},
|
|
requester: {
|
|
type: 'string',
|
|
enum: ['E04', 'T03', 'T04', 'E03'],
|
|
enumNames: [
|
|
'E04 关系覆盖需要价值传递素材',
|
|
'T03 触达需要材料',
|
|
'T04 攻坚需要定制内容',
|
|
'E03 方案需要支撑',
|
|
],
|
|
title: '被动触发的使用方(仅被动触发时选)',
|
|
showWhen: { field: 'trigger', equals: 'reactive' },
|
|
},
|
|
targetCustomer: {
|
|
type: 'string',
|
|
title: '定向客户编码(选填,为特定客户定制素材时填;通用内容留空)',
|
|
examples: ['CU-0142'],
|
|
},
|
|
note: {
|
|
type: 'string',
|
|
title: '本轮说明(选填,背景信息 —— 帮AI判断内容侧重与紧迫程度)',
|
|
examples: ['进入俄罗斯市场,需要一份中俄双语的公司介绍与能力声明,月底展会要用'],
|
|
},
|
|
},
|
|
},
|
|
messageAllowed: true,
|
|
messageHint: '内容运营可在此说明本轮生产的特殊要求、目标受众、或需要重点突出的内容侧重',
|
|
},
|
|
output: {
|
|
/* 单一必发口,无分支:I01 生产流程线性(①→②③→④→⑤),没有岔路口。 */
|
|
mandatory: [
|
|
{
|
|
name: 'content-published',
|
|
description:
|
|
'本轮已发布的内容资产 —— 供 E04/T03/T04/E03 分发调用;当前代码库尚未实现这些下游活动的读取消费者,此口暂无消费者,仅按"载荷=已落地事实"的契约纪律预先声明',
|
|
payload: {
|
|
type: 'object',
|
|
required: ['roundRef', 'publishedContentTotal'],
|
|
properties: {
|
|
roundRef: { type: 'string', title: '本轮案号' },
|
|
publishedContentTotal: { type: 'integer', title: '本轮已发布内容份数' },
|
|
},
|
|
},
|
|
},
|
|
],
|
|
selective: [],
|
|
},
|
|
/*
|
|
* 三份必交付物,逐一对应三张工单产出的成果。全部 `editableAtRelease: []`——
|
|
* 业务说明明文"验收工单只读展示,不可修改"(内容初稿与拟发布明细都是 AI 的结论,
|
|
* 人只做通过/驳回或签字,不在验收页上就地改)。
|
|
*/
|
|
requiredDeliverables: [
|
|
{
|
|
key: 'requirement-confirm',
|
|
label: '内容需求清单',
|
|
ledger: `${D}.requirement`,
|
|
ledgers: [`${D}.requirement`, `${D}.verdict`],
|
|
editableAtRelease: [],
|
|
},
|
|
{ key: 'draft-review', label: '内容初稿', ledger: 'content.asset', editableAtRelease: [] },
|
|
{ key: 'publish-confirm', label: '拟发布内容', ledger: 'content.asset', editableAtRelease: [] },
|
|
],
|
|
/*
|
|
* 验收判据 —— **机检(L1/L2)只读基座数得出来的数**:`_rows`/`_missing`/按值计数基座现数,
|
|
* 与执行卡的提交闸同一个数同一套算法。L4 三条是纯裁量(版本状态对不对、标签齐不齐、
|
|
* 多语言够不够)——机器数得出「有没有值」,数不出「对不对、够不够」,那是人对结果负责的地方。
|
|
*/
|
|
acceptanceCriteria: [
|
|
/*
|
|
* 两条 L1 的「人过了没有」一半靠记账旗(只有人回卡之后模型才记 —— 与 A1 的
|
|
* confirmed_total 同款,规范 §5.3-4 背书的人环凭据);但**每条都必须再钉一半
|
|
* 基座数**(2026-08-23 照 E04 的账整改):旗是模型写的,单独成谓词就是
|
|
* 「机检只读基座数」第 N 次违反的伪装形 —— E04 那单抢跑写旗、活单熔断,
|
|
* 正是踩着这半边过的门。
|
|
*/
|
|
{
|
|
key: 'requirement-confirmed',
|
|
label: '内容需求已经内容运营核对确认(执行工单已交回,清单有行且内容类型齐)',
|
|
level: 'L1',
|
|
predicate: `requirement_confirmed_total > 0 and ${D}_requirement_rows > 0 and ${D}_requirement_missing = 0`,
|
|
},
|
|
{
|
|
key: 'draft-approved',
|
|
label: '内容初稿已经 AM Lead 审核通过(验收工单1已过,不处在驳回待改状态)',
|
|
level: 'L1',
|
|
predicate: 'draft_approved_total > 0 and content_asset_rows > 0 and content_asset_missing = 0',
|
|
},
|
|
{
|
|
key: 'draft-complete',
|
|
label: '内容初稿逐份完整:标题、内容类型、语言版本、状态都有',
|
|
level: 'L2',
|
|
predicate: 'content_asset_rows > 0 and content_asset_missing = 0',
|
|
},
|
|
/*
|
|
* **资料文件真产出了没有** —— 两边都是基座现数:每一行都报了一种格式
|
|
* (四档计数之和 = 行数),而正文空着的行会被 `_missing` 数出来(body_md 是必填)。
|
|
* 从前这一步只产出一行标题,人点不开也下不来 —— 判据得能指向一个看得见的东西:
|
|
* 这一条为真,件上每个资料名都点得开。
|
|
*/
|
|
{
|
|
key: 'asset-file-ready',
|
|
label: '每份内容都产出了资料文件(格式已定、正文已写,件上点资料名即可打开)',
|
|
level: 'L2',
|
|
predicate:
|
|
'content_asset_rows > 0 and content_asset_missing = 0 and ' +
|
|
'content_asset_file_format_md + content_asset_file_format_html + ' +
|
|
'content_asset_file_format_docx + content_asset_file_format_xlsx = content_asset_rows',
|
|
},
|
|
{
|
|
key: 'publish-registered',
|
|
label: '拟发布内容已登记为已发布状态且逐项完整',
|
|
level: 'L2',
|
|
predicate: 'content_asset_content_status_published > 0 and content_asset_missing = 0',
|
|
},
|
|
{ key: 'version-status-correct', label: '版本号与状态是否正确:版本号已更新、状态流转无误', level: 'L4' },
|
|
{ key: 'scene-tag-complete', label: '场景与 BT 标签是否登记完整', level: 'L4' },
|
|
{ key: 'language-complete', label: '多语言版本是否齐全', level: 'L4' },
|
|
/* L5 是责任关:那张卡本身就是这道关,卡面上不摆它(基座统一滤) */
|
|
{ key: 'owner-release', label: '发布入库放行:签下去即正式生效并写入 L-05', level: 'L5' },
|
|
],
|
|
revisableAtRelease: [],
|
|
prohibitions: [
|
|
{ key: 'no-fabricate-signal', statement: '市场信号读不到相关内容时不得编造 —— 如实基于已有资产与客户信息拟定' },
|
|
{ key: 'no-skip-review', statement: '内容状态流转不得跳步 —— draft → reviewed → published 每一步都要真的写过' },
|
|
{ key: 'no-external-write', statement: '放行前不得触达外部系统 —— 触达世界的动作集中在放行那一刻' },
|
|
],
|
|
authorization: {
|
|
discretion: [],
|
|
preauthorizedActions: [],
|
|
/* 基线三次(S2/S4通过/T_release)+ 决策卡循环预留两轮(每轮驳回+重提交各算一次,+4),留够余量 */
|
|
humanCallBudget: 10,
|
|
},
|
|
resources: {
|
|
tools: [],
|
|
skills: CONTENT_SKILLS.map((s) => s.id),
|
|
models: ['deepseek-v4-flash'],
|
|
roles: ['AM Lead'],
|
|
budget: { steps: 60, tokens: 400_000, activeMinutes: 60, humanCalls: 10 },
|
|
},
|
|
},
|
|
|
|
/* ── 声明 ────────────────────────────────────────────────────── */
|
|
declarations: {
|
|
models: ['deepseek-v4-flash'],
|
|
tools: [],
|
|
ledger: [
|
|
/*
|
|
* ── L-01 宏观市场台账(kind:'master',I01 只读)──
|
|
* 首次完整声明:本仓库尚无其它活动读写它,不是追加列。
|
|
*/
|
|
{
|
|
domain: 'market',
|
|
object: 'signal',
|
|
kind: 'master',
|
|
label: '宏观市场台账',
|
|
fields: [
|
|
{ name: 'signal_id', type: 'text', primaryKey: true, masked: false, label: '信号ID' },
|
|
{
|
|
name: 'signal_type',
|
|
type: 'text',
|
|
primaryKey: false,
|
|
masked: false,
|
|
tally: ['macro_economy', 'industry_trend', 'competition', 'policy', 'customer_market'],
|
|
label: '信号类型',
|
|
},
|
|
{ name: 'title', type: 'text', primaryKey: false, masked: false, label: '标题' },
|
|
{ name: 'content', type: 'text', primaryKey: false, masked: false, label: '详情' },
|
|
{ name: 'source', type: 'text', primaryKey: false, masked: false, label: '信号来源' },
|
|
{ name: 'signal_date', type: 'date', primaryKey: false, masked: false, label: '信号日期' },
|
|
{ name: 'market_region', type: 'text', primaryKey: false, masked: false, label: '所属市场' },
|
|
{ name: 'industry', type: 'text', primaryKey: false, masked: false, label: '细分行业' },
|
|
{ name: 'chip_category', type: 'text', primaryKey: false, masked: false, label: '关联芯片品类' },
|
|
{ name: 'importance', type: 'integer', primaryKey: false, masked: false, label: '重要性评分(1-5)' },
|
|
{
|
|
name: 'impact_dir',
|
|
type: 'text',
|
|
primaryKey: false,
|
|
masked: false,
|
|
tally: ['opportunity', 'threat', 'neutral'],
|
|
label: '影响方向',
|
|
},
|
|
{
|
|
name: 'signal_status',
|
|
type: 'text',
|
|
primaryKey: false,
|
|
masked: false,
|
|
tally: ['pending', 'evaluated', 'archived', 'expired'],
|
|
label: '信号状态',
|
|
},
|
|
{ name: 'version', type: 'text', primaryKey: false, masked: false, label: '版本号' },
|
|
{ name: 'review_note', type: 'text', primaryKey: false, masked: false, label: '复盘备注' },
|
|
],
|
|
},
|
|
/*
|
|
* ── L-05 品牌内容库(kind:'master',I01 唯一读写者)──
|
|
* 首次完整声明并持有全部基本列(不是追加,`declarations.ledger` 里明写 required/expect,
|
|
* 因为没有别的活动会与 I01 在这张表上"谁先立谁的字段"打架)。
|
|
*/
|
|
{
|
|
domain: 'content',
|
|
object: 'asset',
|
|
kind: 'master',
|
|
label: '品牌内容库',
|
|
fields: [
|
|
{ name: 'content_id', type: 'text', primaryKey: true, masked: false, label: '内容ID' },
|
|
{ name: 'content_type', type: 'text', primaryKey: false, masked: false, required: true, label: '内容类型' },
|
|
{ name: 'title', type: 'text', primaryKey: false, masked: false, required: true, label: '内容标题' },
|
|
{
|
|
name: 'language',
|
|
type: 'text',
|
|
primaryKey: false,
|
|
masked: false,
|
|
required: true,
|
|
label: '语言版本(多语言用" · "连接)',
|
|
},
|
|
{ name: 'version', type: 'text', primaryKey: false, masked: false, required: true, label: '版本号' },
|
|
/*
|
|
* **发布那一刻才必填**(2026-08-23):S5 的剧本明写「发布前场景必须登记」,
|
|
* 而声明只标 expect —— 机器数不出来,那句话就只能靠 L4 让人肉眼核。
|
|
* `requiredWhen` 把必填钉在**已发布**的那几行:草稿态不拦(那时还没定场景),
|
|
* 一旦状态流到 published,红带/提交闸/放行门 L2 三处同源同数地拦。
|
|
*/
|
|
{
|
|
name: 'scene',
|
|
type: 'text',
|
|
primaryKey: false,
|
|
masked: false,
|
|
expect: true,
|
|
requiredWhen: { column: 'content_status', value: 'published' },
|
|
label: '适用场景',
|
|
},
|
|
/*
|
|
* BT 标签 —— 目标件的验收工单1 就有这一列,而从前 `content.asset` 压根没有它:
|
|
* L4 判据「场景与 BT 标签是否登记完整」让人核一个卡面上不存在的东西
|
|
* (判据指向的东西必须摆得出来,E04 那一课)。与 `scene` 同款:发布那一刻才必填。
|
|
*
|
|
* **不带 tally** —— 与 `requirement.scene` 同一条教训(2026-08-21):
|
|
* tally 的取值域得是 ASCII(`data-class-of` 只认 ASCII),而这一列在件上是
|
|
* 普通格子、走 `data-slot` 直显,没有翻译层 —— 存 `bt_03` 人看到的就是 `bt_03`。
|
|
* 存人读值("BT-01"/"BT-02"/"BT-03"),屏上与目标件一字不差。
|
|
*/
|
|
{
|
|
name: 'bt_tag',
|
|
type: 'text',
|
|
primaryKey: false,
|
|
masked: false,
|
|
expect: true,
|
|
requiredWhen: { column: 'content_status', value: 'published' },
|
|
label: 'BT 层级标签',
|
|
},
|
|
{
|
|
name: 'content_status',
|
|
type: 'text',
|
|
primaryKey: false,
|
|
masked: false,
|
|
required: true,
|
|
tally: ['draft', 'reviewed', 'published', 'deprecated'],
|
|
label: '内容状态',
|
|
},
|
|
{ name: 'brand_tone', type: 'text', primaryKey: false, masked: false, expect: true, label: '品牌调性标签' },
|
|
{ name: 'target_customer', type: 'text', primaryKey: false, masked: false, label: '定向客户版本' },
|
|
/*
|
|
* ── 一份内容 = 一份**资料文件**(2026-08-23 用户:「审核资料这一步要真实
|
|
* 产出资料文件,格式可以是 word/excel/md/html,点资料名能打开渲染」)──
|
|
*
|
|
* 从前只有一句 `file_ref: '文件位置'`,而 S3 的剧本明写「本 MVP 阶段可留空」:
|
|
* **这一步压根没产出过任何文件** —— 屏上一行标题,点不开、下不来,
|
|
* 人要审的那份初稿根本不在系统里。
|
|
*
|
|
* 现在正文落 `body_md`(Markdown 原文,AI 写的就是它),格式落 `file_format`,
|
|
* 基座按 `file` 段现造成真字节(见 `apps/api/src/app/file-compose.ts`):
|
|
* .docx 用 Word 打得开、.xlsx 用 Excel 打得开,屏上渲的就是那份字节读回来的样子。
|
|
*
|
|
* 为什么正文只写一种(Markdown)而不是四种各写一遍:四份就是四份事实,
|
|
* 改一处就分叉。**写一份,按格式投影** —— 与「文件是台账的投影」同一条。
|
|
*/
|
|
{
|
|
name: 'body_md',
|
|
type: 'text',
|
|
primaryKey: false,
|
|
masked: false,
|
|
required: true,
|
|
label: '内容正文(Markdown 原文)',
|
|
},
|
|
{
|
|
name: 'file_format',
|
|
type: 'text',
|
|
primaryKey: false,
|
|
masked: false,
|
|
required: true,
|
|
tally: ['md', 'html', 'docx', 'xlsx'],
|
|
label: '资料文件格式',
|
|
},
|
|
{ name: 'file_ref', type: 'text', primaryKey: false, masked: false, label: '文件位置' },
|
|
{ name: 'reviewer', type: 'text', primaryKey: false, masked: false, label: '审核人' },
|
|
],
|
|
/**
|
|
* 这张表的每一行还是**一份资料文件**:标题、正文、格式各取哪一列。
|
|
* 这一段同时是授权面 —— 不声明它,件上的资料名就点不开(基座 403)。
|
|
*/
|
|
file: { titleColumn: 'title', bodyColumn: 'body_md', formatColumn: 'file_format' },
|
|
},
|
|
/* ── I01 自有工作台账(kind:'record',caseKey:'round_ref') ── */
|
|
{
|
|
domain: D,
|
|
object: 'requirement',
|
|
kind: 'record',
|
|
caseKey: 'round_ref',
|
|
label: '内容需求清单',
|
|
fields: [
|
|
{ name: 'round_ref', type: 'text', primaryKey: true, masked: false, label: '案号' },
|
|
{ name: 'req_seq', type: 'integer', primaryKey: true, masked: false, label: '本轮需求序号' },
|
|
{ name: 'content_type', type: 'text', primaryKey: false, masked: false, required: true, label: '内容类型' },
|
|
{ name: 'source', type: 'text', primaryKey: false, masked: false, expect: true, label: '需求来源' },
|
|
{ name: 'target_customer', type: 'text', primaryKey: false, masked: false, expect: true, label: '目标客户' },
|
|
/*
|
|
* **不带 tally**(2026-08-21 实测逼出的修死):这一列是编辑面上的普通格子
|
|
* (`REQUIREMENT_TABLE` 里就是一个 `<span data-col>`,不是 `data-class-of` 徽标),
|
|
* tally 过的 ASCII 码没有翻译层就直接摆上屏——实测人看见的是裸的 "solution",
|
|
* 不是"方案"。`content.asset.scene`(S3 照抄这一列)本来就是自由文本,两处
|
|
* 现在口径一致:AI 写人读标签(首触/方案/攻坚/展会/报价),不写 ASCII 码。
|
|
*/
|
|
{ name: 'scene', type: 'text', primaryKey: false, masked: false, expect: true, label: '适用场景' },
|
|
{
|
|
name: 'priority',
|
|
type: 'text',
|
|
primaryKey: false,
|
|
masked: false,
|
|
tally: ['high', 'medium', 'low'],
|
|
label: '优先级',
|
|
},
|
|
{ name: 'origin', type: 'text', primaryKey: false, masked: false, label: '来源(ai/human-added)' },
|
|
],
|
|
},
|
|
{
|
|
domain: D,
|
|
object: 'verdict',
|
|
kind: 'record',
|
|
caseKey: 'round_ref',
|
|
label: '本轮内容生产结论',
|
|
fields: [
|
|
{ name: 'round_ref', type: 'text', primaryKey: true, masked: false, label: '案号' },
|
|
{ name: 'trigger', type: 'text', primaryKey: false, masked: false, label: '触发方式(人读标签,非入参英文码)' },
|
|
{ name: 'trigger_detail', type: 'text', primaryKey: false, masked: false, label: '触发细节(人读标签)' },
|
|
{ name: 'target_customer', type: 'text', primaryKey: false, masked: false, label: '定向客户' },
|
|
{ name: 'note', type: 'text', primaryKey: false, masked: false, label: '本轮说明' },
|
|
{ name: 'requirement_confirmed_total', type: 'integer', primaryKey: false, masked: false, label: '需求已确认' },
|
|
{ name: 'draft_approved_total', type: 'integer', primaryKey: false, masked: false, label: '初稿已审核通过' },
|
|
{ name: 'publish_prepared_total', type: 'integer', primaryKey: false, masked: false, label: '发布准备已收口' },
|
|
{ name: 'content_produced_total', type: 'integer', primaryKey: false, masked: false, label: '本轮产出内容份数' },
|
|
{ name: 'summary', type: 'text', primaryKey: false, masked: false, label: '本轮生产结论' },
|
|
],
|
|
},
|
|
],
|
|
listeners: [],
|
|
harness: {
|
|
memoryWindow: 24,
|
|
/* 内容生产不是紧迫单,给够时间让人审核 */
|
|
stallAfter: 'PT4H',
|
|
nudge: [{ after: 'PT2H', action: 'nudge' }],
|
|
retry: { times: 2, backoff: 'PT30S' },
|
|
},
|
|
},
|
|
|
|
/* ── 资产初始版 ──────────────────────────────────────────────── */
|
|
assets: {
|
|
businessModel: {
|
|
cmmnXml: CMMN_XML,
|
|
narrative: NARRATIVE,
|
|
dmn: EMPTY_DMN,
|
|
steps: CONTENT_STEPS,
|
|
phases: CONTENT_PHASES,
|
|
},
|
|
skills: CONTENT_SKILLS,
|
|
/*
|
|
* 三个局面各一张:
|
|
* · `requirement-list` —— S1/S2 摆,内容需求清单,可编辑;
|
|
* · `draft-review` —— S3/S4 摆,内容初稿,只读(业务说明明文"人只审不改");
|
|
* · `publish-confirm` —— S5/T_release 摆,拟发布内容,只读,放行后即归档件。
|
|
*/
|
|
viewTemplates: [
|
|
{ name: 'requirement-list', html: REQUIREMENT_LIST },
|
|
{ name: 'draft-review', html: DRAFT_REVIEW },
|
|
{ name: 'publish-confirm', html: PUBLISH_CONFIRM },
|
|
],
|
|
cardSchemas: {},
|
|
distillHooks: [
|
|
{
|
|
on: 'terminal',
|
|
prompt: '归纳本轮内容生产:需求识别依据、审核是否被驳回过(为什么)、市场依据来自哪些信号、发布的内容覆盖哪些场景与语言。',
|
|
},
|
|
],
|
|
},
|
|
|
|
/*
|
|
* ── 样例集 —— 三条形状真不同 ────────────────────────────────
|
|
*
|
|
* **第一条必须是满载的那条**(2026-08-23,与 E04 同一课):测试台落到一个活动上
|
|
* 就自动铺 `samples[0]`(activity-run.tsx 的 useEffect),第一条就是人打开这一屏
|
|
* 看见的那份入参。从前第一条是月度更新、只有两个键,表单大半是空的,看着像没预填。
|
|
* **样例名一律 ≤14 字**:超了测试台的样例钮只显示「样例 N」,那等于没名字。
|
|
*/
|
|
samples: [
|
|
{
|
|
name: 'E04 请求定向素材',
|
|
input: {
|
|
trigger: 'reactive',
|
|
requester: 'E04',
|
|
targetCustomer: 'CU-0142',
|
|
note: 'E04 关系覆盖与关键人经营需要一份面向 Itelma 的价值传递素材,用于下轮拜访',
|
|
},
|
|
expect: { ports: ['content-published'] },
|
|
},
|
|
{
|
|
name: '月度定期内容更新',
|
|
input: {
|
|
trigger: 'proactive',
|
|
reason: 'monthly_update',
|
|
note: '八月例行内容刷新:优先看版本最旧、最久未更新的那几份工具包',
|
|
},
|
|
expect: { ports: ['content-published'] },
|
|
},
|
|
{
|
|
name: '进入新市场 · 俄罗斯',
|
|
input: {
|
|
trigger: 'proactive',
|
|
reason: 'new_market',
|
|
note: '公司战略进入俄罗斯市场,需要一份中俄双语的公司介绍与能力声明,月底展会要用',
|
|
},
|
|
expect: { ports: ['content-published'] },
|
|
},
|
|
/*
|
|
* **一轮里三种形态各要一份** —— 这一条样例是为「资料文件」那一环常备的
|
|
* (2026-08-23):前三条要的都是成篇的文档,模型一律挑 docx 并不算错,
|
|
* 于是表格型与网页型那两条路平时走不到。这一条把三种形态摆在同一封需求里:
|
|
* 对照表是表(xlsx)、落地页是网页(html)、销售速记是短要点(md)。
|
|
*/
|
|
{
|
|
name: '对照表与落地页',
|
|
input: {
|
|
trigger: 'reactive',
|
|
requester: 'FAE 华东',
|
|
note:
|
|
'客户要一份 TI 车规 MCU 的替代料参数对照表(逐型号列封装/温度/认证/交期,做成表格发过去);' +
|
|
'同时官网要上一版车规 MCU 能力的落地页文案(网页直接看);' +
|
|
'再给销售一页随身速记,三五条要点即可。',
|
|
},
|
|
expect: { ports: ['content-published'] },
|
|
},
|
|
],
|
|
|
|
entry: { file: 'index.js', checksum: 'dev-entry-brand-content-toolkit' },
|
|
};
|