Skip to content

docs(analytics,administration): write the first-response claims, the Lead reports section and two behavioural claims to source (#936, #951, #952) - #954

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-936-951-952-metrics-claims
Aug 6, 2026
Merged

yinlianghui merged 2 commits into
mainfrom
claude/issue-936-951-952-metrics-claims

Conversation

@yinlianghui

@yinlianghui yinlianghui commented Aug 6, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #936
Fixes #951
Fixes #952

三单并单(R31),外加 PM 在 #948 验收时判归本单的《Service reports》整表收口。四个页面 × 3 语言,src/ 零改动,content/docs/releases/ 未触碰。基线 origin/main = b7791caf(PR #950 落地后),全部行号 fresh main 重定位;PR #923 / #950 的落地行零回退。

#936 —— 「可度量的首次响应 SLA」三处

先复核前提,三处全部成立:

  • first_response_date 有写入方:src/actions/global.actions.ts 的 logActivityAction 在工单第一次记录「已经发生过」的通话/会议时打戳(读回旧值,不覆盖)。这一半是真的。
  • 但没有目标、没有度量、没有告警:case_metrics(src/datasets/case.dataset.ts)三个 measure 是 case_count / avg_resolution / avg_sla_violated,无任何首次响应项;grep -rn "first_response_date" src/flows/ src/reports/ src/datasets/ 零命中;content/docs/service/sla-and-escalation 全页 first response 计数为 0 —— 而 setup §11 正是把「SLA matrix」链到那一页。

三处按 #933 / #946 已落地的写法抄平(service/cases.mdx:179 是同族的标准句式):

  1. administration/setup §11:删掉整列 First response(1 小时 → 1 个工作日),保留解决目标表,点名 Critical 那行是 case_sla_defaults 真正盖出来的期限、其余三行是服务承诺;另起一段写实「这里没有首次响应目标可确认」+ 戳的真实写入时机 + 三条否定(无度量、无报表磁贴、无告警)。收尾把「请自行调整」指向 src/objects/case.hook.ts,不再暗示存在某个设置屏。
  2. analytics/reports:SLA Performance → 真名 SLA Performance Report,口径按 case.report.ts 写实;表下一段说清它没有首次响应数字,且那个 SLA 数是违约率(is_sla_violated 的平均)而非准时率。
  3. analytics/cubes Service Cube:删掉 First-response time (minutes) 与 SLA met % (first response and resolution) 两条,换成 case_metrics 真实声明的 SLA Violation Rate 并注明它是违约率不是达标率;补一段「这里没有首次响应度量」。

一处越出 issue 列举但属同一主张:cubes 的示例问题 "SLA met % by priority by month." 与被删的那条度量是同一个名字 —— 若只删度量、留下示例问题,页面会自相矛盾。改写为 "SLA Violation Rate by priority."(顺带去掉 by month:created_date 粒度是 day,#924 已在 sla 页写明)。

#595「是否应该有首次响应 SLA」不预判,三处都只写现状。

#951 —— Lead reports 整节

src/reports/ 六个文件里 lead 侧只有 lead.report.ts 一份,label 是 Lead Engagement by Month × Source;页面列的三份 grep -rn "Lead Conversion Funnel\|Lead Source ROI\|Aged Leads" src/ 零命中。沿 #939 在 service/cases「Standard list views」的口径重写整节:

  • 先列真实那一份,并说清它按什么切(行 = 来源,列 = Last Contacted 的月份,未联系过的线索被 runtimeFilter 排除)。
  • 再逐条点名三份不存在的,并纠正 Working:它是 src/mappings/lead_import.mapping.ts 里 'Working': 'contacted' 这一行导入别名,不是 crm_lead.status 的取值;真实状态词按 PR docs(administration): write the state-machine status vocabulary and the last two behavioural claims to source (#921, #940) #950 的词表写成 New → Contacted → Qualified → Unqualified → Converted(Unqualified 从任何开放状态可入)。
  • Lead Source ROI 额外说清语义层为什么答不出来:lead_metrics 只有一个度量(线索计数)+ 四个维度,收入根本不在这个数据集里。
  • 末尾给真实替代品:Open Leads 磁贴(Executive Overview 仪表盘,同一数据集)。

PM 面扩 —— 《Service reports》整表(#948 卫星命中)

第二个 commit。原计划只改 SLA 那一行,PM 判定整表归本单一次收口。src/reports/case.report.ts 只发布三份,页面列了六份:

真名(逐字对源码) 口径
Cases by Status and Priority rows: ['status','priority']、values: ['case_count','avg_resolution'],带一张按状态的柱状图
SLA Performance Report rows: ['priority']、values: ['case_count','avg_sla_violated','avg_resolution']、runtimeFilter: { is_closed: true }
Cases Opened by Priority × Day matrix,rows: ['priority'] × columns: ['created_date'](day 粒度)

另外五份(Case Volume by Origin / Case Resolution Time / Top Accounts by Case Volume / Reopened Cases / CSAT by Agent)在 src/ 零命中,且多数连自建都建不出来 —— 逐条给出理由:case_metrics 无 owner 维(所以「by agent」两处都够不着,与我在 cubes/setup 消除的同族一致)、无 account 维、工单上没有任何字段标记「曾被重开」、Customer Satisfaction(customer_rating)虽是真字段但数据集没有为它声明度量。唯一建得出来的是 Case Volume by Origin(Origin 是维度),如实写明。

《订阅与定时推送》里两条示例点名了刚被判定为不存在的报表(SLA Performance / Top Accounts by Case Volume)—— 这是我这次改动自己造成的自相矛盾,一并换成真实报表。Sales / Revenue / Marketing 三节未动(见「边界」)。

#952 —— 两条枚举外行为主张

验证

六道门全部在 flock -w 7200 /tmp/os-heavy-verify.lock 内串行,面扩后重跑一遍,退出码均为 0:

validate_exit=0    typecheck_exit=0    lint_exit=0
hygiene_exit=0     build_exit=0        test_exit=0
Test Files  70 passed (70)
Tests  1602 passed | 1 skipped (1603)

CI(head 9f097de2)8 项全绿,含 link-check 与 Check Changeset。

守卫盲区如实报告:本 PR 改的四个页面里,只有 docs-conversion-rate-spelling(carriers 钉住 analytics/reports 两个中文页必须仍写「转化率 / 轉化率」)与 docs-drift 的 callout 数量平价真正读到我的改动面;setup §11、cubes 度量列表、reports 各表、state-machines 的 Tips 段落没有任何守卫读,改动正确性靠 src/ 逐条回源,不靠测试变红。

docs-conversion-rate-spelling 是本 PR 最接近踩掉的守卫:改前 analytics/reports.zh-Hans 全页仅有的一处「转化率」就在我重写的 Lead Source ROI 那一行。反向验证(预测方向:RED)——把重写后新写法里的「转化率」临时换成别的词,单跑该守卫:

Tests  1 failed | 3 passed (4)
  118|  const file = join(DOCS_ROOT, `${carrier.page}.${locale}.mdx`);
  119|  expect(readFileSync(file, 'utf8')).toContain(carrier[locale]);

与预测一致变红,随后还原(两个中文页各保留一处该词,语义上正是 ROI 报表答不出来的那个「转化率」)。还原后 docs-conversion-rate-spelling / docs-drift / status-state-machines 三个守卫单跑 77 passed。status-state-machines 的 roster 守卫只读 state-machines 页第一个 ## 小节,我的 Tips 改动在其扫描面之外,预测 GREEN 且实测 GREEN。

关于 PR #955 的新守卫 test/docs-service-index-analytics.test.ts:已从其分支取来在本分支单跑,结果 13 failed | 7 passed —— 红的原因与本 PR 无关,该守卫钉的是 #955 自己重写的 content/docs/service/index*.mdx 三页文本,而那三页在我的 base(b7791caf)上还是旧文本。它的输入面是 service/index 三页 + service.dashboard.ts + case.report.ts / case.dataset.ts,与本 PR 的改动面(analytics 两页、administration 两页)零交集,两个 PR 也没有共同文件。顺带一提:该守卫从源码导出的三个报表 label 与我这次写进 reports 页的三个逐字一致。

边界

…Lead reports section and two behavioural claims to source (#936, #951, #952)

Three pages presented a measurable first-response SLA the app has never had.
`first_response_date` does have a writer - logActivityAction stamps it when a
held call or meeting is logged on a case - but nothing compares that stamp
against a target: case_metrics declares no first-response measure, no report or
tile reads it, no flow alerts on it, and the four target numbers appear nowhere
in src. administration/setup section 11 loses the First response column and
names the stamp; analytics/reports states what SLA Performance Report really
reports (violation rate, not on-time percentage); analytics/cubes drops the
phantom first-response measure and the SLA met % and names the real measure.

#951: the Lead reports section listed three reports that src publishes nowhere
and omitted the only real one. It now lists Lead Engagement by Month x Source,
names the three absent ones, and corrects the Working status - an import alias
for Contacted, not a value of crm_lead.status.

#952: the Setup -> Opportunity -> Stages screen does not exist (stages are the
stage field's options, probabilities are STAGE_PROBABILITY in the hook, which
re-derives probability on every save), and automation cannot hang off a state
machine transition - the table is a warning-severity validation that logs and
emits nothing, so the "much more performant" advice named a mechanism this app
does not have.

All three locales. Documentation only; src/ unchanged.
@vercel

vercel Bot commented Aug 6, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hotcrm Ignored Ignored Aug 6, 2026 1:35pm

Request Review

…satellite, PM scope extension)

The table listed six reports where src/reports/case.report.ts publishes three.
Cases by Status and Priority, SLA Performance Report and Cases Opened by
Priority x Day are real; Case Volume by Origin, Case Resolution Time, Top
Accounts by Case Volume, Reopened Cases and CSAT by Agent are published nowhere,
and most of them ask case_metrics for something it does not carry - no agent
dimension, no account dimension, no reopen marker on the case, no measure over
Customer Satisfaction. Only Case Volume by Origin is buildable as a custom
report, because Origin is a dimension; the section now says so per name.

Two subscription examples named reports from the phantom list and now name
published ones.

All three locales. Documentation only; src/ unchanged.
@yinlianghui
yinlianghui marked this pull request as ready for review August 6, 2026 13:41
@yinlianghui
yinlianghui added this pull request to the merge queue Aug 6, 2026
Merged via the queue into main with commit 60b5012 Aug 6, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment