Skip to content

docs(service): write the index page's 《Where to find things》 list to the real navigation (#927) - #932

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-927-service-index-navigation
Aug 6, 2026
Merged

yinlianghui merged 1 commit into
mainfrom
claude/issue-927-service-index-navigation

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes #927

《Where to find things》是新用户在这一页上找路的第一站,它列了四项;对着 src/apps/crm.app.ts 读一遍,其中三项站不住,而这个分组里真实存在的一项反而被漏掉了。

逐条复核(stale-premise)

基线 origin/main = 4855d50b(rc.3)。本页经 #913 / #922 两轮修改后重定位:该节现在是 :60-:67(issue 正文记的 :63-:67 是改动前的行号),三语同行号。四项逐一对着源码复核,issue 的前提全部成立:

清单原文 源码实况 结论
Cases crm.app.ts:137 nav_case → crm_case,label Cases ✅ 对
Tasks group_service 的 children 里没有 crm_task;它的两个导航项是 nav_my_tasks(:84,label My Tasks)与 nav_all_tasks(:93,label All Tasks),都挂在 group_work / My Work 下 ❌ 分组错
Service Board 全仓元数据里没有这个名字。看板是视图 case_workflow,label: 'Service Workflow'(src/views/case.view.ts:72-:75),经工单列表视图切换器的 Workflow 页签进入(:59),根本不是侧边栏条目 ❌ 名字不存在,且不是导航项
Service Dashboard nav_service_dashboard(:139)确实存在,但 label 是 Service Overview ⚠️ label 写错
(漏) Knowledge nav_knowledge(:138)→ crm_knowledge_article,label Knowledge,真实存在于该分组 ⚠️ 被漏掉

即 group_service(:131-:140)实有且仅有三项:Cases、Knowledge、Service Overview。

改法

三项写实 + 两个读者会带着来的名字给出真实归属,沿 #870 / #877 / #885 / #894 / #913 / #924 已立的口径——点名说清不存在,并给出真名 / 真实所在分组 / 真实 label,不静默删名。Service Board 的措辞与 #924 在 sla-and-escalation 上落的那句保持一致(真名 Service Workflow / case_workflow / Workflow 页签 / 本应用里不存在叫 Service Board 的东西)。

不预判产品(#595 / #596):看板是否应该成为独立导航项、Tasks 是否应该进 Service 分组,都是产品决定,本 PR 只记录当前形状。

边界

验证

六道门在共享锁内串行,全绿:

门 退出码 关键行
pnpm validate 0 Security: 12 Positions 6 Permissions(余为既有 approval/campaign_member 警告)
pnpm typecheck 0 tsc --noEmit 无输出
pnpm lint 0 13 warning(s), 14 suggestion(s),均为既有
pnpm hygiene 0 ✓ no raw control bytes in first-party files(扫描面含 content / .changeset 共 425 个文件)
pnpm build 0 Artifact: dist/objectstack.json (1921.4 KB)
pnpm test 0 Test Files 70 passed (70) / Tests 1602 passed | 1 skipped (1603)

守卫盲区,如实报告:本仓没有任何检查读这一节的导航散文——test/docs-drift.test.ts 的规则覆盖 flow 文档、目录引用、agent 名、dashboard 磁贴(content/docs/analytics/dashboards*.mdx)与译文 callout 数量,没有一条比对左侧导航清单。所以这里没有 before-red / after-green 可拿:把旧的四项写回去,六道门同样全绿。唯一读到本文件的规则是 callout 数量对齐(docs-drift.test.ts:575),本改动未增删 callout,故三语仍然对齐——这也是它 predicted GREEN 且实测 GREEN 的原因,而不是它验证了本次改动的正确性。改动的正确性由上表的源码 file:line 逐条支撑。

控制字节:除 gate 4 外另做自扫 grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]'(三份 mdx + changeset),无命中;file 对四个文件均报 UTF-8 text,未被判为 binary。(scripts/check-nul-bytes.mjs 在本仓不存在,等价扫描在 scripts/check-source-hygiene.mjs 里,即 gate 4。)

未起 dev server。


Generated by Claude Code

…the real navigation (#927)

The section that tells a new user where to click named four items; three of
them did not survive a read of `src/apps/crm.app.ts`, and the one real item
the group does carry was missing.

Measured against `src/apps/crm.app.ts:131-140`, `group_service` has exactly
three children: `nav_case` (Cases), `nav_knowledge` (Knowledge) and
`nav_service_dashboard`, whose label is **Service Overview** — not "Service
Dashboard". `crm_task` has no entry in this group at all: its two nav items
are `nav_my_tasks` (My Tasks) and `nav_all_tasks` (All Tasks), both under
`group_work` / **My Work** (`:84` / `:93`). And no metadata anywhere carries
the name *Service Board*: the kanban is the view `case_workflow` with
`label: 'Service Workflow'` (`src/views/case.view.ts:72-75`), reached from
the **Workflow** tab in the case list's view switcher (`:59`) and never from
the sidebar.

So the list now names the three real items with their real labels, adds the
Knowledge entry it had been dropping, and keeps the two names readers will
arrive with — Tasks and Service Board — pointing at where those things
actually live, per the #870 / #877 / #885 / #894 / #913 / #924 convention of
naming what does not exist rather than deleting it silently.

Product questions are left open on purpose (#595 / #596): whether the kanban
should become its own nav item, and whether Tasks belongs under Service, are
not decided here — only the current shape is recorded.

All three locales, same lines. `src/` untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa
@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 10:06am

Request Review

@yinlianghui
yinlianghui marked this pull request as ready for review August 6, 2026 12:35
@yinlianghui
yinlianghui added this pull request to the merge queue Aug 6, 2026
Merged via the queue into main with commit 834870c Aug 6, 2026
9 checks passed
This was referenced Aug 6, 2026
yinlianghui added a commit to yinlianghui/hotcrm that referenced this pull request Aug 10, 2026
…ngs" (objectstack-ai#938) (objectstack-ai#942)

The section that tells a new reader where to click said the **Marketing**
group holds one item. It holds two.

Measured against `src/apps/crm.app.ts:120-128`, `group_marketing` has exactly
two children: `nav_campaign` (Campaigns) and `nav_product`, labelled
**Products** (`:126`). That second item is the product catalog's ONLY sidebar
entry anywhere in the app — `grep -rn "crm_product" src/apps/` returns that one
line — so a reader looking for the catalog under Marketing, told the group held
Campaigns alone, had no reason to expand it. Everything else about the list
survived the read: the Campaigns label is right and no phantom item was named,
so this is purely the missing entry, the direction opposite to objectstack-ai#927 / PR objectstack-ai#932.

Two further facts from source are recorded with it. `crm_product` carries
`searchableFields` (`src/objects/product.object.ts:27`) and is looked up from
`crm_quote_line_item:62` and `crm_opportunity_line_item:69`, which are the only
other routes to a product record — so the page says that rather than implying
the sidebar item is the sole way in. And `group_marketing` declares no
`expanded` flag while Sales, My Work, Activity and Service all set
`expanded: true`; `GroupNavItemSchema.expanded` defaults to `false`, so this
group is collapsed on load. That is exactly the failure mode the issue
describes, so the page now says to open the group before concluding something
is absent.

The catalog's own pages live under `content/docs/revenue/products`, so the new
bullet links there instead of duplicating the content into Marketing.

All three locales, same lines; zh internal links carry no anchor. `src/`
untouched — no product decision is taken here (objectstack-ai#595 / objectstack-ai#596 stay open).

Fixes objectstack-ai#938


Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa

Co-authored-by: Claude <noreply@anthropic.com>
yinlianghui added a commit to yinlianghui/hotcrm that referenced this pull request Aug 10, 2026
…tack-ai#937) (objectstack-ai#947)

The three service pages called it "Service Dashboard" in all three locales, and
nothing in the app carries that name: `src/apps/crm.app.ts:139` labels the
sidebar item `Service Overview` and `src/dashboards/service.dashboard.ts:22`
titles the dashboard itself `Customer Service`.

Use `Service Overview` — the sidebar label, which is how a reader finds it —
as the running reference, and annotate the dashboard's own title `Customer
Service` once at the first mention on each page, so the heading you land on
matches what you were told to look for. `content/docs/analytics/dashboards.mdx`
already writes that title as its section heading in every locale, which is
where the cross-page links point.

zh pages use 服务概览 / 服務概覽 — the navigation label's own translation in
`src/translations/zh-CN.ts:1209`. The dashboard title stays Latin, matching how
the dashboards page writes it in all three locales.

The negation lines PR objectstack-ai#932 landed on `service/index*.mdx:66` ("no sidebar item
is called *Service Dashboard*") are kept verbatim in English; the zh pair only
loses the phantom name from the descriptive clause before it, which in Chinese
had been reading as the very name the next clause denies.

No metadata changed.


Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa

Co-authored-by: Claude <noreply@anthropic.com>
yinlianghui added a commit to yinlianghui/hotcrm that referenced this pull request Aug 10, 2026
…to the real navigation (objectstack-ai#943) (objectstack-ai#953)

The section that tells a reader where to click named four things; three of them
do not survive a read of `src/apps/crm.app.ts`, and the one that does was
labelled with a name the app never shows.

Measured against `src/apps/crm.app.ts` on `origin/main` (b7791ca, platform
17.0.0-rc.3), the app has seven groups — Sales, My Work, Activity, Marketing,
Service, Insights, Approvals — and none of them is **Products**. The catalog's
only sidebar entry anywhere is `nav_product`, labelled **Products**, under
`group_marketing` (`:126`); `grep -rn "crm_product" src/apps/` returns that one
line. So the page now sends a reader arriving with the name "Products group" to
Marketing instead of to a place that does not exist, and links the Marketing
overview page that objectstack-ai#938 / PR objectstack-ai#942 just brought in line.

`group_approvals` (`:159-171`) has exactly one child: `nav_approval_requests`,
whose label is **Inbox** (`:165`) — not *Approval Requests*, which no metadata
in this repo carries. The other two listed items are re-judged individually
rather than deleted silently, per the objectstack-ai#870 / objectstack-ai#877 / objectstack-ai#885 / objectstack-ai#894 / objectstack-ai#913 / objectstack-ai#924 /
objectstack-ai#932 / objectstack-ai#942 convention:

- **Action History** — no nav item of that name exists. The data behind it does:
  @objectstack/plugin-approvals registers `sys_approval_action` (enumerated from
  the installed package, alongside `sys_approval`, `sys_approval_approver`,
  `sys_approval_delegation`, `sys_approval_request`, `sys_approval_token`), and
  nothing in this app's navigation opens it. The page says exactly that.
- **Processes** — deleted on purpose, and the source records why at `:166-169`:
  no `sys_approval_process` object exists in any installed plugin, so the old
  item's `requiresObject` guard hid it on every install, forever. The enumeration
  above confirms the absence, so the reason is written into the page.

The one true claim survives unchanged: **Contracts** is under **Sales**
(`nav_contract`, `:60`), and it is the app's only sidebar route to a contract.
Two further facts from source are recorded with it: `group_marketing` and
`group_approvals` declare no `expanded` key while Sales, My Work, Activity and
Service set `expanded: true`, and `GroupNavItemSchema.expanded` defaults to
`false` — so both groups are collapsed on load, which is the failure mode that
sends a reader looking for the catalog away empty-handed. And the zh-Hans page
names the label a simplified-Chinese user actually sees, 待我审批
(`src/translations/zh-CN.ts:1219`), next to the source label.

Product questions stay open on purpose (objectstack-ai#595 / objectstack-ai#596): whether Products deserves
its own group and whether Approvals should gain an audit-trail item are product
decisions, not documentation ones. Only the current shape is recorded.

All three locales, same lines; zh internal links carry no anchor. `src/`
untouched.

Fixes objectstack-ai#943


Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa

Co-authored-by: Claude <noreply@anthropic.com>
yinlianghui added a commit to yinlianghui/hotcrm that referenced this pull request Aug 10, 2026
… source (objectstack-ai#948) (objectstack-ai#955)

All four bullets of `content/docs/service/index*.mdx` "Standard dashboards &
reports" were wrong in all three locales, in two independent ways.

The dashboard bullet advertised a `top agents` tile and an `oldest open cases`
tile. `src/dashboards/service.dashboard.ts` ships ten widgets and neither is
among them — and neither is a widget nobody built yet: `case_metrics`
(`src/datasets/case.dataset.ts`) declares Status, Priority, Origin, Type and
Created as its only dimensions, so nothing in analytics can rank agents, and
every widget on the dashboard binds that dataset, i.e. aggregates it, so no tile
lists individual cases by age. `content/docs/service/cases.mdx:188` (objectstack-ai#912 / PR
objectstack-ai#939) had already written the agent half to source, so the two service pages
contradicted each other; this page was the one that was lying. The bullet now
names the ten real tiles and states why the other two cannot be built.

The three report bullets named labels that do not exist in
`src/reports/case.report.ts`: `Cases Opened by Day × Priority` inverts the two
dimensions of the real `Cases Opened by Priority × Day` (priority in `rows`, the
day in `columns` — `sla-and-escalation.mdx` already had the order right after
objectstack-ai#917 / PR objectstack-ai#924), `Cases by Status × Priority` spells `and` as `×`, and
`SLA Performance` drops the `Report` its label ends with. The SLA bullet also
still carried the "% of cases resolved within SLA target" claim PR objectstack-ai#924 removed
from the SLA page: no such measure exists — the report gives case count,
SLA Violation Rate and average resolution time by priority, over closed cases
only.

`test/docs-service-index-analytics.test.ts` pins both directions: every bolded
Latin name in the section must resolve to a real widget title, report label or
dataset label (phantom names stay in the *italics* this page already uses for a
name the product lacks, objectstack-ai#927 / PR objectstack-ai#932); every widget title must appear, so a
new tile cannot land while the summary goes stale; and the source side of both
negative claims is pinned too, so adding an agent dimension or an agent-ranking
tile fails here rather than silently making the prose wrong the other way.
Reverse-verified: restoring the four old lines turns 13 of the 20 assertions
red.

PR objectstack-ai#947's `Service Overview` reference and its first-mention `Customer Service`
annotation are untouched, as are the objectstack-ai#913 / objectstack-ai#922 / objectstack-ai#932 lines elsewhere on the
page. No metadata changed.

Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa

Co-authored-by: Claude <noreply@anthropic.com>
yinlianghui added a commit to yinlianghui/hotcrm that referenced this pull request Aug 10, 2026
… real app (objectstack-ai#960) (objectstack-ai#968)

The first table a new user reads, whose entire job is "here is what the sidebar
holds", had drifted in every one of its eight rows.

Measured against `src/apps/crm.app.ts` on `origin/main` (4705aed, platform
17.0.0-rc.3), the app's `navigation` is one pinned top-level entry plus seven
groups: `nav_home` (Home, :34), `group_sales` (:42), `group_work` (My Work,
:69), `group_activity` (Activity, :103), `group_marketing` (:120),
`group_service` (:131), `group_insights` (Insights, :144) and `group_approvals`
(:160). Row by row, the old table said:

- **Sales** — the group is real, but it carries nine children, not six. The
  table dropped Account Workbench (:52), Pipeline (:55) and Sales Performance
  (:61).
- **Service** — real; the entry the table called *Knowledge Base* is labelled
  **Knowledge** (:138), and **Service Overview** (:139) was missing. Both
  names were already written to source on `service/index` by objectstack-ai#927 / PR objectstack-ai#932
  and objectstack-ai#937 / PR objectstack-ai#947, so the two pages contradicted each other.
- **Marketing** — real, but its children are Campaigns (:125) and Products
  (:126). *Campaign Members* is not a navigation entry at all:
  `grep -rn "crm_campaign_member" src/apps/` returns nothing.
- **Products** — no such group. The catalog's only sidebar entry is
  `nav_product` under `group_marketing`, the same finding objectstack-ai#938 / PR objectstack-ai#942 and
  objectstack-ai#943 / PR objectstack-ai#953 already wrote to two other pages.
- **Activities** — no such group; the real one is **Activity**, and `crm_task`
  is not in it. Its two entries are My Tasks (:84) and All Tasks (:93), both
  under **My Work** — which the table never mentioned at all, though it is the
  group a rep uses every day.
- **Analytics** — no such group; the real one is **Insights**, and no entry
  anywhere is labelled *Dashboards* or *Reports*.
- **AI** — no such group anywhere in the repo, and no entry labelled *Copilot*
  or *Knowledge Bases*. `src/apps/` contains one file; neither name appears in
  it.
- **Approvals** — real, with exactly one child, labelled **Inbox** (:165).
  *Approval Requests* and *Action History* carry no metadata in this repo;
  objectstack-ai#943 / PR objectstack-ai#953 recorded the same two names on the revenue page.

So the table now lists the pinned Home entry and all seven groups with their
real children in source order, and every retired name is re-pointed rather than
deleted silently, per the objectstack-ai#870 / objectstack-ai#877 / objectstack-ai#885 / objectstack-ai#894 / objectstack-ai#913 / objectstack-ai#924 / objectstack-ai#932 / objectstack-ai#942
/ objectstack-ai#953 convention. Two further facts from source ride along: `group_marketing`,
`group_insights` and `group_approvals` declare no `expanded` key while Sales,
My Work, Activity and Service set `expanded: true`, and
`GroupNavItemSchema.expanded` defaults to `false`, so those three are collapsed
on load — the failure mode that makes a reader conclude something is absent.
And the zh pages name the labels a simplified-Chinese user actually sees
(待我审批, 知识库, 我的工作 — `src/translations/zh-CN.ts:1195-1219`), which is
also why the old English *Knowledge Base* read plausibly for so long.

Nothing checked any of it: `os validate` and `pnpm lint` walk authored metadata
and never open `content/docs`. `test/docs-quick-tour-navigation.test.ts` now
compares the table to `CrmApp.navigation` group-for-group and child-for-child in
all three locales, pins the bold-is-real / italic-is-phantom typography the
sibling pages already use, and pins the source facts the prose rests on.
Restoring the old table turns 15 of its 21 assertions red in the predicted
direction.

Product questions stay open on purpose (objectstack-ai#595 / objectstack-ai#596): whether Products or AI
deserve their own groups is a product decision, not a documentation one. Only
the current shape is recorded.

All three locales, same section; zh internal links carry no anchor. `src/`
untouched.

Fixes objectstack-ai#960

Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants