Skip to content

docs(revenue): write the index page's "Where to find things" section to the real navigation (#943) - #953

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-943-revenue-nav
Aug 6, 2026
Merged

yinlianghui merged 1 commit into
mainfrom
claude/issue-943-revenue-nav

Conversation

@yinlianghui

Copy link
Copy Markdown
Contributor

Fixes #943

《Where to find things》一节告诉读者去哪里点击,它点名了四样东西:三样在 src/apps/crm.app.ts 里读不到,剩下那一样写的是应用从不显示的名字。

逐条对源码(基线 origin/main = b7791caf,平台 17.0.0-rc.3)

文档原断言 源码实况 处理
存在 Products 分组 不存在。全应用只有 7 个分组:Sales / My Work / Activity / Marketing / Service / Insights / Approvals。产品目录唯一的侧边栏入口是 group_marketing 下的 nav_product(label Products,:126);grep -rn "crm_product" src/apps/ 只有这一行 保留读者带来的名字,明说没有这个分组,并指向 Marketing 分组(内链到 #938 / PR #942 刚写实的 Marketing 概览页)
Sales 分组含 Contracts ✅ 成立,nav_contract(:60),且是全应用通往合同的唯一侧边栏入口 保留,并补上"唯一入口"这一事实
Approvals 含 Approval Requests label 不对。group_approvals(:159-:171)只有 1 个 child nav_approval_requests,label 是 Inbox(:165);全仓没有任何元数据叫 Approval Requests 改为 Inbox,并注明"没有任何条目叫 Approval Requests"
Approvals 含 Action History 侧边栏无此条目。但它背后的数据是真的:@objectstack/plugin-approvals 注册了 sys_approval_action(连同 sys_approval / sys_approval_approver / sys_approval_delegation / sys_approval_request / sys_approval_token,从已安装包里枚举得出),只是本应用没有任何导航条目能打开它 不静默删名:保留名字,写清"数据真实存在、导航打不开"
Approvals 含 Processes 不存在,且是刻意删掉的——:166-:169 的注释写明:任何已安装插件里都不存在 sys_approval_process 对象,旧条目的 requiresObject 守卫会在每一次安装里把它永远隐藏。上面的枚举独立复核了这一缺席 保留名字,把源码给出的删除原因如实写进页面

全量核对补记

本节涉及的三个分组 children 逐个核过,另外两条源码事实一并写实:

  • group_marketing 与 group_approvals 都没有声明 expanded,而 Sales / My Work / Activity / Service 都是 expanded: true;GroupNavItemSchema.expanded 的默认值是 false(z.boolean().default(false)),所以这两个分组加载时是折叠的——这正是"照文档找不到产品目录"的现场。
  • zh-Hans 页补上简体界面下这一项真正显示的 label 待我审批(src/translations/zh-CN.ts:1219),与源码 label Inbox 并列。zh-Hant 页注明本应用只提供 en / zh-CN / ja-JP / es-ES 四种界面语言。

产品判断不预判(#595 / #596 同族):Products 该不该有自己的分组、Approvals 该不该补审计轨迹条目,都是产品决定,本 PR 只记录当前形状。

三语同址同改;zh 内链不带锚;src/ 零改动;@objectstack/* 版本未动;content/docs/releases/ 未动。

验证

守卫盲区如实报告:仓内没有任何测试把 content/docs/** 的导航断言对 src/apps/crm.app.ts 做钉子(test/docs-object-coverage.test.ts 只查"每个对象有没有页面",test/docs-drift.test.ts 查 flow / 仪表盘磁贴 / callout 数量),所以本改动预期全绿,六道门是回归保护而非正向证据。

门 退出码 关键行
pnpm validate 0 Data: 17 Objects 344 Fields / UI: 1 Apps 14 Views …(既有 5 条 author-time warning,与本改动无关)
pnpm typecheck 0 tsc --noEmit 无输出
pnpm lint 0 13 warning(s), 14 suggestion(s) (960ms)(全部为既有项)
pnpm hygiene 0 ✓ no raw control bytes in first-party files / ✓ source hygiene clean(扫描面含 content、.changeset)
pnpm build 0 ✓ Build complete (1555ms) / Artifact: dist/objectstack.json (1921.4 KB)
pnpm test -- --maxWorkers=2 0 Test Files 70 passed (70) / Tests 1602 passed | 1 skipped (1603)

推送前另做控制字节自扫:grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]' 覆盖三个 mdx 与 changeset,无命中。未启动任何 dev server。


Generated by Claude Code

…to the real navigation (#943)

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 #938 / PR #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 #870 / #877 / #885 / #894 / #913 / #924 /
#932 / #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 (#595 / #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 #943

Co-authored-by: Claude <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 1:21pm

Request Review

@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 2b750ff Aug 6, 2026
9 checks passed
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>
yinlianghui added a commit to yinlianghui/hotcrm that referenced this pull request Aug 10, 2026
objectstack-ai#963) (objectstack-ai#969)

* docs(revenue): write the approvals page's navigation section to source (objectstack-ai#963)

The `Where to find pending approvals` section carried the same phantom sidebar
`revenue/index` carried until objectstack-ai#943/PR objectstack-ai#953, so two pages in one directory gave
readers two different answers.

Measured against `src/apps/crm.app.ts` and the installed
`@objectstack/plugin-approvals` (17.0.0-rc.3):

- `group_approvals` holds exactly one child, labelled `Inbox` (zh-CN 待我审批),
  and the group is collapsed by default. `Approval Requests` is no navigation
  entry -- but the name is the plugin's own label for the OBJECT, so the section
  says where it really lives instead of claiming nothing carries it.
- `Pending My Approval` / `Submitted by Me` / `Recently Approved` hit nothing in
  `src/` and nothing in the plugin. The four views that do exist -- `My Pending`,
  `I Submitted`, `Completed`, `All` -- are what the nav item opens, since it pins
  no `viewName`, so the section names those.
- `Action History` labels no item anywhere. The trail is real data
  (`sys_approval_action`, its own three views, a `request_id` back-link); only
  the entry point is missing.

All three locales updated; `src/` untouched.
`test/docs-revenue-approvals-navigation.test.ts` pins both directions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa

* test(docs): read src/ with dirent types, not stat-then-read (CodeQL objectstack-ai#969)

CodeQL flagged the `src/` walk in the new approvals-navigation guard as a
potential file-system race: it called `statSync(full).isDirectory()` and then
re-opened the same path with `readFileSync`, the check-then-use pair.

`readdirSync(dir, { withFileTypes: true })` carries each entry's type from the
directory read itself, so there is no second syscall to race against, and a
`readFileSync` that throws on a file removed mid-walk is what this guard wants
anyway. No assertion or branch changed — 30/30 still pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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