Skip to content

Commit 0647dab

Browse files
docs(adr): ADR-0141 records that its first consumer, revenue shipped on its own, is shelved (#31415)
<!-- claude-projects-attribution: {"github_login":"zhuangjianguo"} --> _Requested by **Steedos** · [project thread](https://claude.ai/code/project/chan_018ETKaNwMZCNRYD7D8Q9Ubb?thread=cmsg_018ETKaNwMZCNRYD7D8Q9UbbWagjUjVja22Skg9kGUisd3)_ Fixes #31362 Clause-②: no Metadata-protocol: none ## 维护者速读 - **改了什么**:ADR-0141 新增两段注明日期(2026-11-08)的附注,一段在 TL;DR 末句下,一段在 D7 标题下。附注记录:首个消费者「HotCRM 收入模块作为独立制品单独发布」已搁置;HotCRM 以一个套件发布,客户在设置里关闭不用的模块。原有文字一字未改。 - **为什么改**:维护者在 #26986 裁决 A(2026-11-08,记录 6717108024):模块缺席形态不是目标,#25805 的裁决 D「大包 + 设置里启用模块」成立。ADR-0141 还写着「首个消费者是单独发布的 HotCRM 模块,收入优先」,agent 读到会把 hotcrm#2271(已按 not_planned 关闭)的拆分当成平台方向去规划。 - **风险与回滚**:只改一个 ADR 文件,纯文字,零代码,不需要 changeset。没有推翻任何决定:D2 安装前检查与 D5 命名空间共有已在 main 上,保持不变,留给将来跨制品的消费者。回滚即 revert 本 PR。 - **先看**:`docs/adr/0141-inter-app-dependency-declared-checked-before-install.md` 的 D7 标题下附注,尤其最后一条,它列出保留原文、改作示例阅读的句子;再看 TL;DR 末句下的短附注。 - **两分钟验证**:`pnpm check:adr-anchors && pnpm check:adr-symbol-anchors && node scripts/check-adr-links.mjs`,预期三条都打印 OK、退出码 0,附注里的两个代码锚点和 ADR-0070 链接都能解析。 - **需要你做的**:审阅两段附注的措辞后批准本 PR(`docs/adr/**` 属 Tier H,批准后由席位落地)。 ## What changes One file, `docs/adr/0141-inter-app-dependency-declared-checked-before-install.md`, +42 / −0. Two dated addendum notes in the blockquote form `docs/adr/` uses for a note under the text it governs (ADR-0058's `Addendum (2026-07, #3278)`, ADR-0066's `Note (2026-10-30, …)`), labelled `Addendum` as this record's own D8 addendum is: 1. **Under the TL;DR's closing sentence** (pre-edit L97): the first consumer is shelved, HotCRM ships as one suite artifact with modules turned off in settings (#25805 ruling D, #28117 ruling A), the sentence stays as written, and the D7 note says what stands. 2. **Under the §D7 header** (pre-edit L461): the maintainer's words verbatim (「所以hotcrm 以套件的形式发布就没有后续的问题了对吧,」, then 「A」), what letter A means, the disabled-shape measurement 6716259819, and four readings: - no decision is reversed; D2's pre-install check and D5's co-owner sources are on `main` and stay as built for a future cross-artifact consumer; - that consumer reopens #26986's Q1–Q5 (deferred, not rejected) and #25805; - the one-artifact suite still reads D1 (each HotCRM module declares the app package, and the disable door reads that tie); - the sentences that plan the shelved consumer stay as written, read as worked examples, and D4's open section stays open, decided with the first consumer, whoever that becomes. Nothing else in the record changes. ### The measured sentences Read on `origin/main` `405a78ea` (pre-edit line numbers; the file is byte-identical at `3a0aa915` and `77a675db`). **Plan the shelved consumer**: left as written, and each one is named in the D7 note's last reading. | Pre-edit lines | Section | Text | |---|---|---| | L97 | TL;DR, closing | "The first consumer is a HotCRM module shipping on its own, revenue first." | | L178–180 | Context §2 | "The HotCRM seat's two module cards frame the sequence: hotcrm#2270 …; hotcrm#2271 ships revenue on its own once the check is released" | | L323–324 | D4, open section lead | "Three questions, measured on HotCRM's revenue module … before its runtime card is cut" | | L384–397 | D5, "The depended-on app's companions must declare it" | "… the HotCRM lane's reading before hotcrm#2271 ships." | | L461–493 | D7, all of it | the header, the scenario paragraph, the three HotCRM preconditions ("before hotcrm#2271 ships"), the closing paragraph ("hotcrm#2271 moves revenue to its own artifact once the check is released") | | L536 | Consequences, positive | "A customer installs CRM now and PSA — or a HotCRM module — later" | | L557–558 | Consequences, negative | "D5 holds for a module only if its app's own companions declare the app (D5, D7) — a HotCRM-side precondition not yet verified" | | L598 | Open items 1 | "D4's three questions, measured on HotCRM's revenue module." | | L611–613 | Open items 6 | "The carved-out module's `type`. D7 states `type: 'app'`." | | L614–615 | Open items 7 | "… before hotcrm#2271 ships" | | L739–742 | Execution plan 5 | "hotcrm#2271 ships revenue as its own artifact once (1) is released" | **Not listed, by reading:** - **Worked examples of a shipped mechanism.** D5's sibling-arm, read-from-either-end and hydrate-order bullets (L363–368, L377–383, L407–408) use revenue to show why a rule exists. The rule landed, and the example still explains it. - **Generic "first consumer", no HotCRM name.** TL;DR item 5 (L94–95), Consequences L555 and L564. These stay true for whoever the first consumer becomes. - **Historical readings.** Verification notes L703–704, References L766 and the Status line ("Until the pre-install check ships, a composite product keeps shipping as one release artifact"). Under A the suite ships as one artifact anyway. - **The ruling's own example** 「请先安装 HotCRM 6.x」 (TL;DR item 3, D2). It is quoted text from the #25403 ruling, not a consumer. ## Why The maintainer ruled on #26986 Q0 = A (ruling record 6717108024, 2026-11-08T04:12Z), then said 「按照这个方案修订相关的任务」. The module-absent shape (hotcrm#2271, revenue as its own artifact) is not a target, and #25805 ruling D stands. ADR-0141's TL;DR and §D7 still name that shape as the record's first consumer, so an agent reading the record would plan carve-out work against a shelved shape. The card owes a dated addendum that reverses nothing. ## Tests None. ADR prose only, so there is no ablation. Two facts the D7 note states beyond the card text were measured here: - **D2 and D5 are on `main`** (`405a78ea`). The doors in `packages/metadata-protocol/src/protocol-package-install.ts` and `packages/runtime/src/domains/packages.ts` call `assertDeclaredDependencies`. `checkDeclaredDependencies` admits a same-act delivered id for presence only. The D5 dependency and sibling co-owner source sits in `packages/objectql/src/registry.ts#installPackage`, pinned by `registry-artifact-co-ownership.test.ts`, "ADR-0141 D5 — a declared dependency is a second co-owner source". - **HotCRM** `main` `6961ab1`: `src/service`, `src/revenue`, `src/marketing` and `src/o2c` are each `type: 'module'` with `dependencies: { 'app.objectstack.hotcrm': '^6.1.0' }`. The disable door reads that tie (`packages/runtime/src/domains/packages.ts`, `isDisableableAppModule`, the ADR-0070 2026-10-31 amendment). ## Acceptance notes - **No status-header pointer line.** The card owes the TL;DR and §D7 notes only, and the Status line names no consumer. If the approver wants a header pointer, like the ADR-0146 line this record already carries, it is one more line. - **Open items 7 reads as met but is left as written.** On hotcrm `main` `6961ab1`, service and marketing (and o2c) directly declare the app package `app.objectstack.hotcrm`, which is the sales package. That is D5's companion precondition. The item is moot under A, and the card asks that the record not change beyond the addendum. - **hotcrm#2271 was closed `not_planned`** at 2026-11-08T05:16:36Z (read at drafting time). hotcrm#2404, cited for the empty-picker lookup, merged 2026-11-04. - **No changeset.** `docs/adr/**` publishes nothing, so this PR carries `skip-changeset`. - **Tier H** (`docs/adr/**`): the PR stays draft until a governed approver approves. `dispatch-gates --tier` answers MANDATORY CONTRACT_REVIEW_TIER with no one-line exit. The build ran at the default tier under the maintainer's no-Fable rule, as the claim's `Container & model` line records, and the at-tier contract review is the director seat's. ## Verification <details><summary>Derived gate union at 82a6044 (main 405a78e merged): 21 of 21 exit 0</summary> `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 21 commands on a 1-path change set (+42 / −0). Each ran with its exit code captured before any pipe: - `node scripts/check-adr-links.mjs` and `--self-test`: exit 0, 0 - `node scripts/check-closing-keyword-parity.mjs` and `--self-test`: exit 0, 0 - `node scripts/check-comment-mask-corpus.mjs`: exit 0 - `node scripts/ci/plan-test-core-shards.mjs --self-test`: exit 0 - `pnpm --filter @objectstack/lint run check:doc-formula-expressions`: exit 0. The first run exited 3 (PREREQUISITE NOT MET: formula and lint not built). It went green after `pnpm exec turbo run build --concurrency=2 --filter=@objectstack/formula --filter=@objectstack/lint` under `os-verify-lock.sh` (VERDICT command-exit 0, 5 tasks). - `pnpm check:adr-anchors`: exit 0 ("66695 citation(s) across 9687 file(s) resolve") - `pnpm check:adr-symbol-anchors`: exit 0 ("3207 anchors across 150 records resolve") - `pnpm check:adr-index`, `check:ci-filter-parity`, `check:closed-ceremony-text`, `check:cross-package-test-inputs`, `check:doc-authoring`, `check:driver-memory-census`, `check:gitlink-declared`, `check:nul-bytes`, `check:pm-governed-merges`, `check:pm-prior-rulings`, `check:refd-timer-probe`, `check:watch-hint-literal`: exit 0 each `dispatch-gates --ran`: "21 derived famil(ies) accounted for — 21 run, 0 NOT-MEASURED". The same 21 ran green at `7e501f36` before the merge of main. The rest is CI's: the always-runs tail, the type-check lanes and the path-scheduled `Plan Test Core shards` step are NOT MEASURED locally, so cite the PR's check-runs for them. </details> ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. (No schema touched.) - [x] 2. Every name I added uses the casing for its kind. (No names added.) - [x] 3. No formatter ran; `pnpm lint` passes. (No code; CI runs lint.) - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (Publishes nothing: `skip-changeset`.) - [x] 6. `packages/spec` touched: its generated artifacts are regenerated and committed. (Not touched.) - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English, except the 维护者速读 section the dispatch contract asks for in Chinese and the verbatim rulings, which AGENTS.md keeps untranslated. - [x] The *Before Submitting* list in CONTRIBUTING.md is done. --- _Generated by [Claude Code](https://claude.ai/code/session_01QsR2jTEzneERuP7wQHyJHM)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent acfc86c commit 0647dab

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

‎docs/adr/0141-inter-app-dependency-declared-checked-before-install.md‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ added; one gate learns a second source of co-owners:
9696

9797
The first consumer is a HotCRM module shipping on its own, revenue first.
9898

99+
> **Addendum (2026-11-08, [#26986](https://github.com/objectstack-ai/objectstack/issues/26986) — ruling of record
100+
> [`6717108024`](https://github.com/objectstack-ai/objectstack/issues/26986#issuecomment-6717108024), Q0 = A) — this
101+
> first consumer is shelved.** HotCRM ships as one suite artifact whose modules a customer turns off in settings
102+
> (#25805 ruling D, #28117 ruling A); revenue shipped as its own artifact is not a target. The sentence above is left as
103+
> written, and the note under [D7](#d7--the-first-consumer-a-hotcrm-module-shipping-on-its-own-revenue-first) says what
104+
> stands. No decision of this record is reversed, and the open section stays open, decided with the first consumer —
105+
> whoever that becomes.
106+
99107
---
100108

101109
## Context
@@ -460,6 +468,40 @@ it. Renaming a module's objects to dodge the gate stays refused (ADR-0129; lette
460468

461469
### D7 — The first consumer: a HotCRM module shipping on its own, revenue first
462470

471+
> **Addendum (2026-11-08, [#26986](https://github.com/objectstack-ai/objectstack/issues/26986) — ruling of record
472+
> [`6717108024`](https://github.com/objectstack-ai/objectstack/issues/26986#issuecomment-6717108024), Q0 = A) — the
473+
> consumer this section names is shelved; what the record declares stands.** The maintainer, verbatim and untranslated:
474+
> 「所以hotcrm 以套件的形式发布就没有后续的问题了对吧,」 (2026-11-08T04:06:30Z), then 「A」 (04:12:06Z). Letter A: the
475+
> module-absent shape — revenue as its own artifact, hotcrm#2271, since closed `not_planned` — is not a target. The
476+
> shape that ships is the one [#25805](https://github.com/objectstack-ai/objectstack/issues/25805) ruling D chose
477+
> ([`6500011525`](https://github.com/objectstack-ai/objectstack/issues/25805#issuecomment-6500011525),
478+
> 「大包 + 设置里启用模块」): one artifact, its modules turned off in settings, with "disabled" carrying the one meaning
479+
> [#28117](https://github.com/objectstack-ai/objectstack/issues/28117) ruling A
480+
> ([`6545646924`](https://github.com/objectstack-ai/objectstack/issues/28117#issuecomment-6545646924)) binds — hidden,
481+
> refused on the data plane and the by-name reads, data kept, and an app's own in-process access to the module's objects
482+
> still served. With the module disabled, measurement
483+
> [`6716259819`](https://github.com/objectstack-ai/objectstack/issues/26986#issuecomment-6716259819) (`main` `604a2b3b`)
484+
> finds that #26986's gaps F3–F6 no longer reproduce, and that F2 leaves only an editable lookup whose picker is empty,
485+
> as hotcrm#2404 documents. Four readings follow; nothing else in this record changes:
486+
>
487+
> - **No decision is reversed.** D1–D6 and D8 stand as declared, with their earlier notes. D2's pre-install check
488+
> (`packages/metadata-core/src/protocol-handshake.ts#assertDeclaredDependencies`) and D5's dependency and sibling
489+
> co-owner sources (`packages/objectql/src/registry.ts#installPackage`) are on `main` and stay as built, for a future
490+
> cross-artifact consumer: an app in another artifact that depends on an installed app.
491+
> - **That consumer reopens two deferrals**: #26986's Q1–Q5, the per-gap options, deferred and not rejected (the option
492+
> table stays in that card's body and in `6716259819`); and #25805, closed `not_planned`, whose trigger is an app
493+
> built and installed on its own that depends on another app's objects across repositories.
494+
> - **The one-artifact suite still reads D1.** Each HotCRM module is `type: 'module'` and declares the app package in
495+
> `manifest.dependencies` (hotcrm `main` `6961ab1`); at install, D2's second arm judges that entry for presence only,
496+
> and the disable door reads it as the module's tie to its app
497+
> ([ADR-0070](./0070-package-first-authoring.md)'s 2026-10-31 amendment).
498+
> - **The sentences that plan the shelved consumer stay as written**, read as worked examples of D2 and D5, not as a
499+
> plan of record: the TL;DR's closing sentence; Context §2's sentence on hotcrm#2270 and hotcrm#2271; the lead of D4's
500+
> open section; D5's "The depended-on app's companions must declare it" bullet; this section, its three HotCRM
501+
> preconditions and its closing paragraph; the Consequences lines on "a HotCRM module" and on the companions
502+
> precondition; Open items 1, 6 and 7; Execution plan item 5. D4's three questions stay open, decided with the first
503+
> consumer — whoever that becomes.
504+
463505
The scenario this record is accepted against is HotCRM's module split as its `docs/architecture/module-split-plan.md`
464506
records it — the 2026-09-14 shape: the sales app plus service, revenue and marketing modules (**not re-verified**). The
465507
revenue module ships as its own artifact whose consumer-installable package is **`type: 'app'`** — only that type

0 commit comments

Comments
 (0)