Skip to content

feat(docs): in-app Help group with three manuals and nine bilingual package docs - #2355

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/project-thread-4tg14s
Oct 28, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/project-thread-4tg14s

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Irene · project thread
Fixes #2327

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:HotCRM 侧边栏最后新增折叠的「帮助」组,内含三本应用内手册:使用手册(所有成员)、管理员手册(仅系统管理员;多组织部署下为租户管理员)、收入手册(由收入模块挂入,卸载即消失)。原来的四篇包文档拆成九篇,每篇都有中文版。
  • 为什么改:In-app docs, batch 1: a Help group at the end of the HotCRM menu, three books, and the four package docs split into nine with Chinese variants #2327 第一批应用内文档:用户在应用里就能读到与真实配置一致的说明,管理员内容不再对普通成员可见。
  • 风险与回滚:只加导航条目、书和文档,不动数据和权限集;各角色的落地页不变(帮助组在最后)。旧文档名 crm_sales、crm_admin、crm_service 被删除,指向它们的链接会显示「未找到」。回滚即还原本 PR。
  • 先看:src/sales/books/crm-admin-manual.book.ts 与 objectstack.composition.ts 里 saas 下把受众换成 tenant_admin 的那段;src/sales/apps/crm.app.ts 的 group_help;test/docs-books.test.ts。
  • 两分钟验证:pnpm vitest run test/docs-books.test.ts test/docs-lifecycle-diagrams.test.ts,预期 19 个用例通过;或以 na.rep 登录,展开「帮助」只见使用手册和收入手册,管理员登录多一本管理员手册。
  • 需要你做的:无,席位落地。

What changes

A Help group, last and collapsed. crm.app.ts gains group_help after Reports, expanded: false, with two type: 'doc' entries: User Manual (crm_manual) and Admin Manual (crm_admin_manual). The revenue module adds Revenue Manual (crm_revenue_manual) into the same group through a navigationContributions row in src/revenue/index.ts, so the entry leaves with the module. Labels are translated in the zh-CN, es-ES and ja-JP packs (帮助 / 使用手册 / 管理员手册 / 收入手册 …); en adds the group label only, as it lists groups only.

Three books (ADR-0046 §6).

  • src/sales/books/crm-manual.book.ts: Getting Started (pages: ['crm_overview']), Sales (include: 'crm_sales_*'), Service (include: 'crm_service_*', package: 'app.objectstack.hotcrm.service').
  • src/sales/books/crm-admin-manual.book.ts: one group, include: 'crm_admin_*', audience: { permissionSet: 'system_admin' }.
  • src/revenue/books/crm-revenue-manual.book.ts: one group, include: 'crm_revenue_*'.

The app-package books are registered through appBooks in objectstack.composition.ts. Under HOTCRM_COMPOSITION=saas the composition swaps the Admin Manual's audience to tenant_admin, the admin set that shape registers in place of system_admin (measured below: a book gated on a set the stack does not declare is readable by nobody).

Nine pages, each with a .zh.md sibling. crm_sales.md, crm_admin.md and crm_service.md are split by topic:

Book Pages
User Manual crm_overview, crm_sales_leads, crm_sales_opportunities, crm_sales_contracts, src/service/docs/crm_service_cases, src/service/docs/crm_service_knowledge
Admin Manual crm_admin_access, crm_admin_automation
Revenue Manual src/revenue/docs/crm_revenue_quotes

Each page carries order: for its place in its group. The overview has a mermaid lifecycle flowchart and a "which guide to read" table, and links only to sales, service and admin pages, never to revenue (the module can be uninstalled). The lead, opportunity, contract, case and quote pages each draw their object's lifecycle as a mermaid stateDiagram-v2 with the option labels of the locale. The opportunity page keeps the #2342 approval wording. The Forecasts sharing rule that #2338 added to crm_admin.md on main is carried into crm_admin_access.md and its Chinese sibling.

Code comments that pointed at the removed pages now name the new ones (opportunity.actions.ts, opportunity.hook.ts, opportunity-stagnation.flow.ts, _thresholds.ts, one test).

Changeset. .changeset/2327-in-app-help-manuals.md (minor), naming the removed doc names.

Tests

  • New test/docs-books.test.ts (8 cases), computed with the platform's own resolvers (resolveBookClaimedDocs, resolveDocAudiences from @objectstack/spec/system): every page is claimed by a group of some book and has a zh sibling; every book is opened by exactly one doc entry and every doc entry opens a registered book; the admin pages' audience is exactly [{ permissionSet: 'system_admin' }] and every other page includes 'org'; that set is registered; no app-package page links to a revenue or marketing page.
  • New test/docs-lifecycle-diagrams.test.ts (11 cases): for each of the five diagrams in en and zh, the drawn states equal the field's options, each label equals the pack label, and every arrow is a transition the state_machine rule allows; no other page draws a state diagram.
  • Updated: docs-drift (retargeted to the new pages, zh siblings included; cron and day displays in Chinese), docs-runnable-samples (module doc dirs), app-navigation-shape (doc is a known kind; destination key includes book/doc), docs-quick-tour-navigation (eight groups; Reports and Help collapsed), saas-composition (the Admin Manual's audience per composition).
Reverse checks: six one-shot mutations, each red, each restored

Each mutation was made on disk after the commit, the targeted file run, and the file restored with git checkout HEAD -- PATH; git status --short and git diff HEAD --stat read empty after the set.

A1 quotes.md: add arrow accepted --> draft     × crm_revenue_quotes.md draws crm_quote's machine        1 failed | 10 passed
A2 quotes.zh.md: label 草稿 → 草案               × crm_revenue_quotes.zh.md draws crm_quote's machine     1 failed | 10 passed
A3 crm_manual: extra group include crm_admin_*  × the administrator pages are published to the administrator set and nobody else   1 failed | 7 passed
A4 rename crm_sales_contracts → contracts       × every page is claimed by a group of some book — none falls to Uncategorized       1 failed | 7 passed
A5 drop nav_help_admin                          × every book is opened by exactly one doc entry …                                   1 failed | 7 passed
A6 composition: no saas audience swap           × gates the Admin Manual on tenant_admin, the admin set this shape registers        1 failed | 20 passed

Acceptance notes

  • Mermaid, not live embeds. The card asked for ```metadata state-machine embeds with mermaid as the fallback. On 18.2.0 objectstack build refuses every such embed in this artifact (reading below), so the diagrams are hand-written and docs-lifecycle-diagrams holds them to the compiled machines. Filed as objectstack#27090. Swap them for embeds once the platform builds them, and retire that test with the last one.

  • Book and group titles stay English in Chinese. Page titles and bodies switch to Chinese, but the book title ("HotCRM User Manual") and group headings ("Getting Started", "Sales", "Service") show in English to a zh-CN user: 18.2.0 has no books translation namespace (objectstack#26819 is not in this pin). The sidebar entries are translated.

  • Uncategorized sweep, admin only. The console's per-book Uncategorized group lists docs of the same package that the book does not claim, even when a sibling book claims them. An administrator sees the two admin pages under the User Manual's Uncategorized, and the app-package user pages under the Admin Manual's. Members without the admin set see neither (the REST tree prunes by audience); the pages themselves are gated correctly. Filed as objectstack#27091.

  • Cross-package doc links (review round 2, seat ruling: keep the by-name form, teach link-check). Eight links name a page in another package's docs directory: crm_revenue_quotes (en, zh) → crm_sales_opportunities; crm_overview (en, zh) → crm_service_cases and crm_service_knowledge; crm_admin_automation (en, zh) → crm_service_cases. CI link-check on d23812d read them dead, because on disk the target sits in another directory. Measured on the dev server, starting on the quotes page as admin:

    • A, ./crm_sales_opportunities.md (ADR-0046 §3.3: resolved by name, across packages). The console rewrites it to /_console/docs/crm_sales_opportunities, which lands on that page in the User Manual. ./crm_service_cases.md opens the service page the same way.
    • B, ../../docs/crm_sales_opportunities.md (valid on disk). The console's rewrite takes a bare name only, so it is left alone and the browser goes to /docs/crm_sales_opportunities.md, which answers ENDPOINT_NOT_FOUND. The build's docs/broken-link lint skips path-shaped links too.

    So form A stays. .github/markdown-link-check-config.json gains replacementPatterns, each anchored to the bare ./NAME.md form (^\./(crm_service_[a-z_]+\.md)$ → {{BASEURL}}/src/service/docs/$1), module prefixes (crm_service_, crm_revenue_) before the src/docs ones (crm_overview, crm_sales_, crm_admin_). Every other link shape is judged as before. Measured locally with markdown-link-check@3.13.7, the version the action installs:

    18 package doc files: 0 dead links (8 cross-package links resolved, e.g. file:///…/src/service/docs/crm_service_cases.md ✓)
    negative control, quotes.md → ./crm_sales_opportunity.md:  [✖] file:///…/src/docs/crm_sales_opportunity.md → Status: 400
    control, unanchored shapes: ./crm_sales_leads.md#a · crm_sales_leads.md · ../docs/crm_sales_leads.md → each ✖ Status: 400, as before
    
  • Surface beyond the claim, declared. .github/markdown-link-check-config.json (above, accepted by the seat in round 2); objectstack.composition.ts (book registration and the saas audience swap); the comment-pointer fixes in four src/ files and one test; the saas-composition, app-navigation-shape and docs-quick-tour-navigation test edits; and content/docs/getting-started/quick-tour (en, zh-Hans, zh-Hant), whose Help row the quick-tour navigation test requires (accepted by the seat as a surface extension).

Verification

At d9b47b3 (after merging origin/main 3801c17): pnpm verify, exit 0.

 Test Files  239 passed (239)
      Tests  4583 passed | 1 skipped (4584)

d23812d adds only the claim's Clause-② and Metadata-protocol lines to the changeset; test/changeset-version-wrapper.test.ts 4/4 at that head.

At 5b07331 (round 2, config only): markdown-link-check@3.13.7 with the repo config over the 19 changed .md files, 0 dead links; docs-books, docs-lifecycle-diagrams, docs-drift, docs-runnable-samples, docs-quick-tour-navigation, app-navigation-shape: Test Files 6 passed (6), Tests 102 passed (102).

main has since moved to 08bbdd5 (#2354, refusal labels for converted leads and closed-deal line items; no file in common with this diff), so CI's merge ref is the reading for that tip.

Platform readings on 18.2.0 (probe artifact, then this branch)

1. Metadata embeds refused at build. A probe doc in the app package and one in the service package, each with a ```metadata state-machine embed, npx objectstack build:

✗ Package docs validation failed (4 issues)
• docs/crm_probe_app: state_machine embed in "crm_probe_app" references object "crm_case", which does not exist in this package.
    rule: docs/metadata-embed-ref
• packages[0].docs/crm_probe_service: state_machine embed in "crm_probe_service" references object "crm_case", which does not exist in this package.
    rule: docs/metadata-embed-ref

The service package's own page naming its own crm_case is refused too: the lint looks the object up on the artifact's top level, which a multi-package artifact leaves empty.

2. An audience set the stack does not declare locks everyone out. A probe book gated on tenant_admin under the community composition: the build warns security-book-audience-unknown-set ("The runtime fails closed — no holder means NO reader can open the book") and GET /api/v1/meta/book/NAME/tree answers 403 to the admin too. Gated on system_admin: admin 200, rep and service agent 403 on the tree and on the doc, and the nav entry is pruned server-side. Hence the composition swap.

3. A group's package: claims another package's docs. The User Manual's Service group (package: 'app.objectstack.hotcrm.service') lists both service pages; holds.

4. This branch, dev server, demo staff seeded. GET /api/v1/meta/book/BOOK/tree and GET /api/v1/meta/doc/DOC per persona:

crm_manual crm_admin_manual crm_revenue_manual doc crm_admin_access doc crm_overview / crm_service_cases / crm_revenue_quotes
admin 200 200 200 200 200
na.rep 200 403 200 403 200
service.agent 200 403 200 403 200

The rep's crm_manual tree has Getting Started, Sales, Service; the admin's adds Uncategorized with the two admin pages (acceptance note above).

Browser pass (branch head, dev server, en and zh-CN)

Playwright, one run per persona and locale, signed in through /api/v1/auth/sign-in/email:

persona landing sidebar groups (last two) Help entries
admin Executive Overview Reports (collapsed), Help (collapsed) User Manual, Admin Manual, Revenue Manual
na.rep Sales Home Reports (collapsed), Help (collapsed) User Manual, Revenue Manual
service.agent Service Overview Reports (collapsed), Help (collapsed) User Manual, Revenue Manual
  • In zh-CN the group reads 帮助 and the entries 使用手册 / 管理员手册 / 收入手册; page titles and bodies are Chinese (e.g. 报价单——生成与过期, 有效期(天)——默认 30).
  • Each entry opens its book on its first page (/docs/crm_manual/crm_overview, /docs/crm_admin_manual/crm_admin_access, /docs/crm_revenue_manual/crm_revenue_quotes).
  • Mermaid renders: one svg[aria-roledescription=stateDiagram] per diagram page, no raw fence text. Nodes read: opportunities (en) Prospecting … Closed Won, Closed Lost; contracts (en) Draft, In Approval, Activated, Expired, Terminated; cases (zh) 新建, 处理中, 等待客户回复, 等待支持回复, 已升级, 已解决, 已关闭; quotes (zh) 草稿, 审核中, 已提交, 已接受, 已拒绝, 已过期.
  • na.rep opening /docs/crm_admin_manual/crm_admin_access directly: "You do not have access to this documentation".

Screenshots: project files issue-2327/ (*-1-help, *-2-book1..3, *-3-diagram, rep-en-4-admin-direct).


Generated by Claude Code

🤖 Generated with Claude Code

https://claude.ai/code/session_01J8VVAn2ZxhfvpehmexXYC6

… three books

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8VVAn2ZxhfvpehmexXYC6
…arget the docs tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8VVAn2ZxhfvpehmexXYC6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8VVAn2ZxhfvpehmexXYC6
Keeps main's Lead Engagement rename in the quick-tour Reports row beside the
new Help row, and carries the Forecasts sharing rule main added to the old
crm_admin.md into crm_admin_access.md and its Chinese sibling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8VVAn2ZxhfvpehmexXYC6
@vercel

vercel Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated
hotcrm Ignored Ignored Oct 28, 2026 5:01am UTC

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation ci/cd CI plumbing and the verification pipeline metadata Declarative metadata — schema, security posture, UI surfaces configuration Build and app configuration files backend Server-side behaviour — hooks, flows, actions labels Oct 28, 2026
…ch package ships (#2327)

Package docs link to each other by name (ADR-0046 §3.3), and the console
resolves ./NAME.md across packages. On disk the service and revenue pages
live in their own module's docs directory, so a by-name link between
packages read as dead to markdown-link-check. The replacement patterns
map each bare ./crm_PREFIX_NAME.md link to the directory that package's
docs live in; any other link shape is judged as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8VVAn2ZxhfvpehmexXYC6
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对

Verdict: ACCEPT · repo:hotcrm seat 1 · huangyiirene · session session_01J8VVAnPkgK6CWrJa6t7Fk5 · 2026-10-28T05:03Z · head 5b07331
Implemented-by: card thread session session_01J8VVAn2ZxhfvpehmexXYC6 (report 6461000907 on #2327; round 2 in the seat thread). Reviewed-by: the seat, against the 48-file diff and hotcrm origin/main 08bbdd5.

  • Shape:
    • Draft, base main, assignee huangyiirene. The body reads Fixes #2327.
    • No governed path is touched.
    • The diff stays within claim 6456125666's surface plus the extensions declared in the PR body, which the seat accepts:
      • objectstack.composition.ts (book registration and the saas audience swap)
      • comment-pointer fixes in four src/ files and one test
      • the saas-composition, app-navigation-shape and docs-quick-tour-navigation test edits
      • the quick-tour Help row (en, zh-Hans, zh-Hant)
      • .github/markdown-link-check-config.json (round 2)
    • git merge-tree against 08bbdd5 is clean.
  • Card held:
  • Readings and rulings:
    • Reading 1: objectstack build refuses every metadata embed in this multi-package artifact. The card allows mermaid as the fallback, and docs-lifecycle-diagrams holds the five diagrams to the compiled state machines.
    • Reading 2: a book gated on a set the stack does not declare is closed to everyone. The Admin Manual is therefore gated on system_admin, and the saas composition swaps it to tenant_admin, matching the set by identity. The card's "unless reading 2 says otherwise" covers this.
    • Round 2 (link-check red on d23812d): 8 cross-package by-name links (ADR-0046 §3.3 form) are dead on disk.
      • Measured in the browser: the by-name form opens the right page, and the path form ../../docs/… lands on ENDPOINT_NOT_FOUND.
      • The seat ruled option 1: keep the by-name form, and add replacementPatterns anchored to ^\./(crm_PREFIX…\.md)$ that map each prefix to its package's docs directory. Module prefixes come first.
      • All 8 links now resolve, and the negative control ./crm_sales_opportunity.md is still dead.
      • Link-check is success on 5b07331.
  • Tests:
    • New docs-books (8) and docs-lifecycle-diagrams (11).
    • Ablations A1–A6 each went red and were restored.
    • The round-2 docs suites pass 102 of 102.
  • Gates:
    • pnpm verify exit 0 at d9b47b3: 239 files, 4583 passed, 1 skipped.
    • 5b07331 changes only the link-check config.
    • CI on 5b07331: link-check, Quality Checks and Check Changeset are success. The rest are still running, and auto-merge waits for them.
  • Out of scope, filed by the seat:
    • objectstack#27090: docs/metadata-embed-ref judges a package's docs against the artifact's top level.
    • objectstack#27091: a book's Uncategorized catches docs a sibling book claims, which only admins see here.
    • The English book and group titles are already objectstack#26819.
  • Landing: non-governed. The seat flips the PR to ready and arms auto-merge in this stroke.

Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Server-side behaviour — hooks, flows, actions ci/cd CI plumbing and the verification pipeline configuration Build and app configuration files documentation Improvements or additions to documentation metadata Declarative metadata — schema, security posture, UI surfaces

Projects

None yet

Development

Successfully merging this pull request may close these issues.

In-app docs, batch 1: a Help group at the end of the HotCRM menu, three books, and the four package docs split into nine with Chinese variants

2 participants