Repository navigation
[Decision] 一个应用能否声明依赖另一个应用并引用其对象(ADR-0019 推迟的应用间依赖) #25403
Description
Ruled: 6369704387 · batch #7 item 1 · letter B′ · 2026-10-23T16:28:30Z (B narrowed by the maintainer: keep the manifest dependencies declaration and the save door's closure as the reference mechanism; add only the pre-install check — dependency installed and version in range, else refuse with a clear message, filling the reserved dependency_missing category; defer uninstall protection, upgrade interception, topological / cascade install and any owner-side publish marker to named later items in the ADR; permissions unchanged; first consumer = a HotCRM module shipping alone)
Ruled: 6377678758 · batch #8 item 2 · letter A · 2026-10-24T00:40:55Z (namespace across artifacts, for the B′ ADR: dependency-declared co-ownership — a package declaring dependencies on an installed package X and sharing X's namespace is X's co-owner at the install gate, one-way; ADR-0130 D3's per-object-name uniqueness check spans those co-owners; no new manifest field; D8's deferral reworded to end at marketplace publishing)
立卡门类别:② 只有维护者能做的决定。动手的读者:裁定后由 domain:spec 席起草 ADR,并按 ADR 切实现卡。
查重(含 closed,仓内语义检索):
inter-App dependency→ 0 张;cross-app reference→ 0 张;per-tenant enablement module→ 0 张;ADR-0019 deferred app consumer unit→ 2 张(ADR-0087 window: a^18artifact built during the v18 prerelease gets no D2 replay of an entry retired after it was built, so it fails to boot (door 1, split from #22994) #23001、ADR-0117 D1 声明面:ownership 枚举扩展 'business_unit'(须与列注入同 PR 或严格后置) #5678,均无关);ADR-0028 sandboxed apps namespace isolation→ 2 张(runtime(sandbox): a sandboxed body whose rejection cannot be flattened (throw '', a null-prototype object, a message getter that throws) is never recorded, so the action door waits for the 30 s wall-clock ceiling and answers 500 #23723、[Decision] security(runtime): may an app-authored body still READ the stored-metadata family's tables, served projected, or is that refused too (#21454 option C) #21594,均无关);app dependencies manifest another app→ 3 张(packages: manifestdependenciescan be set only at create —PATCH /api/v1/packages/:idpersists only name / description / version, so a save refused with "declare a dependency" has no remedy short of recreating the package #24670、metadata-protocol installPackage parses only the manifest id, so the primitive stores manifests the public install door refuses (type 'application', scope 'environment' from cloud's AI authoring) #24086、[finding] AppPlugin's security-metadata registrar drops a manifestpermissionsit cannot read, at both arms, silently — the second consumer of the #18031 two-readings collision #18034,均不涉及应用之间的依赖)。
维护者速读
今天,一个可安装的应用还不能正式依赖另一个应用。以 PSA(项目交付)为例,它要引用 CRM 的客户、商机和合同,现在只有两种做法:
- 把 PSA 做进 CRM,随 CRM 发给所有客户;
- 另出一个「CRM + PSA」组合应用,让客户换装。
同样,CRM 和 SRM 之间也无法共用客户和供应商资料。
要不要让平台支持「应用 B 声明依赖应用 A,可以引用 A 的对象,由平台管安装顺序、卸载保护和版本兼容」?
- A 维持现状:应用之间隔离,要组合的产品打进同一个发布包。
- B 开放应用间依赖(推荐):先写 ADR 定契约,等第一个真实产品需要独立安装时再实现。
- C 平台自带共享主数据:客户、供应商等对象由平台提供,各应用只引用这些对象。
选 A、B 还是 C? 已裁 B′(批 #7 第 1 项,评论 6369704387):声明 + 安装前检查;卸载保护、升级拦截、多包拓扑 / 连带安装、被引用方的发布标记写为 ADR 的推迟项;权限不变。维护者原话(2026-10-23):「包依赖本身没问题,也就是说如果 psa 依赖 crm, 安装psa 之前先检测crm有没有,没有就禁止安装,这个有必要嘛」「往往需要引用的数据并不多,可能就几个对象」「如果这样,hotcrm 岂不是真实的可以分拆出很多模块」「而每个包可以独立安装」「同意」。批 #8 第 2 项补裁 A(评论 6377678758,维护者 2026-10-24 00:40:55Z「同意 #8」):跨发布物共用命名空间 = 声明依赖即共有(单向,D3 对象名唯一检查跨发布物同行,不加字段)。
os-decision-facets
- ① 项目长远合理性:B 把散落的特例收成一条契约——「声明了依赖才可跨应用引用」。现在的特例包括:发布包内可以引用(ADR-0130),保存门按依赖闭包判定,ADR-0028 D4 提议全面隔离,应用仓只能合包。A 的特例会随产品组合数增长。
- ② 实际业务拉动:今天没有已上线的产品被卡住。在途的拉动都在设计阶段:hotcrm 的 PSA 设计想移出 CRM、做成单独产品;集团系统规划里 CRM 和 SRM 要共用主数据;客户仓库要在标准产品上迭代。
- ③ 防 AI 犯错:B 以声明的依赖为闭集,未声明的跨应用引用响亮拒绝,保存门今天已经这样做(
list-view-object-outside-closure返回 422)。A 同样响亮拒绝,但会把需求推向复制对象、靠同步对齐,造成静默的数据分叉。 - ④ 创业阶段不扩散:B 新增四项永久义务:安装顺序、卸载保护、跨应用版本兼容、跨应用权限语义。A 不新增义务。所以按 ④ 只调时序:先定契约,后实现。
Prior rulings read: inter-app,cross-app,app dependency,shared data model → 2 hits; none; thread: not read (no --card); repo: objectstack-ai/objectstack
(两处命中都是 ADR-0028 的 D4、D6,状态为 Deferred / proposed,不是已生效的裁决。)
一句话问题
客户先装了 CRM,以后想加 PSA。做不到「再装一个 PSA」:要么 PSA 早就随 CRM 装给了所有客户,要么客户换装一个更大的组合应用。
背景
- ADR-0019 把「共享 / 发布的数据模型 + 应用间依赖」列入 Out of scope (explored, deferred — a separate gated bet),要求另立 ADR 并做明确的 go/no-go。
- ADR-0130 为同一发布包内的多个包开了路:一个 artifact、N 个 package,按依赖拓扑注册。hotcrm 在这个前提下实测了跨包规则(
docs/architecture/module-split-plan.md):- R1,查找或主从关系指向另一个包的对象:接受;
- R3,包自己的应用导航指向另一个包的对象:拒绝;
- R4,钩子挂在另一个包的对象上:拒绝。
- 运行时保存门已经有依赖闭包:写入某个包的元数据,只能引用以下对象,否则拒绝并提示「declare a dependency」(fix(lint)!: the save door refuses a list view written into a package and bound outside its closure #24630、packages: manifest
dependenciescan be set only at create —PATCH /api/v1/packages/:idpersists only name / description / version, so a save refused with "declare a dependency" has no remedy short of recreating the package #24670,feat(runtime): PATCH /api/v1/packages/:id edits a package's manifest dependencies #24703 已允许事后修改dependencies):- 本包的对象;
- manifest 里
dependencies声明的包的对象; - 平台对象;
- 不属于任何包的租户对象。
- 缺的是可安装应用之间的正式契约:安装时检查被依赖的应用、按依赖排序、卸载保护、版本范围,以及跨应用引用的权限语义。
Governing text
docs/adr/0019-app-as-consumer-unit.md§Out of scope:「Shared/published data model + inter-App dependencies (cross-app data sharing without a "suite").」docs/adr/0028-metadata-naming-and-namespace-isolation.mdD4(状态 Deferred):「Atype: apppackage may reference its own metadata … but may not reference metadata owned by another app.」docs/adr/0130-release-artifact-as-co-ownership-boundary.mdD2、D5:发布包内多包,按依赖拓扑注册。packages/lint/src/rule-explanations.ts的list-view-object-outside-closure:保存门按闭包判定;os validate、os build、os lint不判跨包引用,原文:「a stack there is one app, and an unresolved binding may be a dependency package's object the stack does not carry」。
协议声明、是否改协议
会改协议。选 B 或 C 需要新 ADR;ADR-0028 D4 的提议要改写;ADR-0019 原文不改,只加交叉引用,沿用 ADR-0130 的记录惯例。ManifestSchema.dependencies 这一行已经存在,B 的工作是赋予它在应用之间的安装语义。
前提(每条带 re-check 命令)
- ADR-0019 推迟了应用间依赖:
git grep -n "inter-App dependencies" origin/main -- docs/adr/0019-app-as-consumer-unit.md - ADR-0028 D4 只是提议、状态为推迟:
git grep -n "Apps are sandboxed\|^\*\*Status\*\*" origin/main -- docs/adr/0028-metadata-naming-and-namespace-isolation.md - 保存门的闭包包含声明的依赖:
git grep -n "the objects of the packages its" origin/main -- packages/lint/src/rule-explanations.ts - 构建和校验不判跨包引用:
git grep -n "judge neither" origin/main -- packages/lint/src/rule-explanations.ts - 发布包内 R3 被拒:在 hotcrm 仓运行
grep -n "^| \*\*R3\*\*" docs/architecture/module-split-plan.md 未验证:两个分别安装的 App 今天在安装门上的实际行为——是否按已由总监席核实(2026-10-23,maindependencies排序、缺依赖时是否拒绝、卸载被依赖方时是否阻止。插件层有依赖解析器,但它是否作用于应用安装未测:git grep -n "Missing dependency" origin/main -- packages/core/src/dependency-resolver.tsea33919f):安装路径不读manifest.dependencies;dependency_missing只是packages/spec/src/system/app-install.zod.ts的枚举值,全仓无生产者;packages/runtime/src/domains/packages.ts编辑dependencies只校验形状(⛔ No in-use check);packages/core/src/dependency-resolver.ts只服务 kernel 插件。即:今天不排序、不拒绝、不阻止——这正是 B′ 的安装前检查要补的。
具体问题
应用之间的引用,平台的终态是什么:
- 隔离;
- 声明依赖后可以引用;
- 由平台提供共享主数据。
选项
| 选项 | 做什么 | 客户能感知的后果 | 工作量 |
|---|---|---|---|
| A 维持隔离 | 不改。ADR-0028 D4 的方向照旧;要组合的产品打进同一个发布包 | 后加一个产品,要么它早已随主应用装给所有人,要么换装组合应用;跨应用的主数据靠导入或同步 | 无 |
| B 应用间依赖 | 写 ADR;安装门检查被依赖的应用已安装、版本在范围内,并按依赖排序;卸载被依赖的应用时阻止或提示;跨应用引用沿用保存门的闭包判定,覆盖到安装和构建;控制台显示依赖关系;定义跨应用引用的权限语义 | 先装 CRM,以后再装 PSA;卸 CRM 前提示 PSA 依赖它;未声明的引用保存时直接报错 | spec、运行时、控制台多车道,1 篇 ADR 加若干 PR;无先例(最近的同类工程是 ADR-0130 的包内多包注册,其 PR 行数未测) |
| B′ 声明 + 安装前检查(已裁) | 声明沿用 ManifestSchema.dependencies,引用沿用保存门闭包;安装前检查依赖已装且版本在范围内,否则拒绝并提示;卸载保护、升级拦截、拓扑 / 连带安装、被引用方发布标记写为 ADR 推迟项;权限不变 |
先装 CRM,以后再装 PSA;装反了被拦并提示先装 CRM | spec 席 ADR(S)+ 运行时安装前检查(XS–S)+ 文档 |
| C 平台共享主数据 | 平台提供客户、联系人、供应商、产品、合同等共享业务对象,各应用只引用这些对象,应用之间不互相引用 | 各应用天然共用主数据;但已有应用的对象要迁移到共享对象 | 平台要拥有一套业务数据模型,需要 ADR、多车道,以及现有应用的迁移;无先例 |
业务含义直译
- A:像套装软件——要么买整套,要么各用各的,中间靠导数据。
- B:像 Salesforce 的扩展包依赖基础包——主应用先装,扩展应用后装,主应用不能先被卸掉。
- C:像 Dynamics 的公共数据模型——平台自带客户、联系人等标准表,所有应用共用。
四轴论证(业务立场)
- ①:两年后,市场上会有第一方的 CRM、SRM、PSA,也会有第三方应用;客户按需先后安装是常态。只有 B 让「后加一个产品」不需要换装,也不需要把它塞给所有人。
- ②:拉动真实但还在设计阶段,所以只影响时序,不影响方向。
- ③:B 的闭集判定在保存门已经实现,出错时作者当场看到 422;A 下作者会复制对象,错误表现为两边数据静默不一致,没人当场看到。
- ④:B 的永久义务明确且有限(四项),可以写进一篇 ADR 一次定清;C 的义务是整套业务数据模型,范围大得多。
推荐与置信缺口
推荐 B。 终态是:应用之间通过显式声明的依赖引用对方对象,平台管安装顺序、卸载保护和版本兼容。这是主流平台的共同形状,参照有:
- Salesforce:扩展包依赖基础包;
- Dataverse:解决方案依赖;
- ServiceNow:跨作用域访问策略;
- Odoo:模块的
depends。
不取另外两项的理由:
- 不取 A:组合数随产品数增长,客户后加产品只能换装;
- 不取 C:平台要拥有业务数据模型,内核契约会大幅扩张。有了 B 之后,「主数据应用」可以作为一个普通应用来实现。
置信缺口:
前提 6 未实测,即今天两个分别安装的 App 在安装门上的行为;(已核实,见前提 6)- 跨应用引用的记录级权限语义未设计——依赖方的查找关系,如何受被依赖方的共享规则约束;
- ADR-0028 D4 想要的市场应用之间的隔离,在 B 下靠「必须显式声明依赖」来保留。这是否足够,需要安全方向复核。
自检:只看①选 B;②③④ 是否翻转:否。②、④ 只影响时序:先写 ADR,等第一个真实产品需要独立安装时再实现。
裁后执行
- 裁 B′(已裁,批 Remove explicit pnpm version from workflows to fix version conflict #7 第 1 项):
domain:spec席起草 ADR:声明(现有dependencies)、安装前检查(已装 + 版本在范围内,否则拒绝并提示;填AppCompatibilityCheck已预留的dependency_missing)、跨应用引用沿用保存门闭包、权限语义开放节;卸载保护、升级拦截、拓扑 / 连带安装、被引用方发布标记写为推迟项;manifest 与市场两种dependencies形状对齐;- 同一份 ADR 把 ADR-0028 D4 改为「未声明依赖不得跨应用引用」,并在 ADR-0019 加交叉引用(不改原文);
- ADR 合并后切实现卡:第一张是运行时的安装前检查(XS–S,含控制台拒绝文案);第一个消费者场景写为 HotCRM 模块单独发布(hotcrm
module-split-plan.md2026-09-14 形状,revenue 先); - 检查落地前,需要组合的产品仍按 ADR-0130 打进同一个发布包;
- (批 Convert to monorepo with scoped packages #8 第 2 项,裁 A) 同一份 ADR 增一条决定:声明依赖即命名空间共有——声明
dependencies依赖已装包 X 且命名空间与 X 相同的包,在安装门视为 X 的共有者;单向;ADR-0130 D3 的对象名唯一检查跨发布物同行;不加 manifest 字段;D8 的推迟改为「到市场发布时结束」(对齐 ADR-0048 2026-08-08 附录)。运行时卡把这一处安装门改动与安装前检查一起做。
裁 A:在 ADR-0019 记一条 no-go 的交叉引用;hotcrm 的 PSA 按「同一发布包」写定。裁 C:先立「平台共享业务对象」ADR 的范围卡,评估现有 CRM、SRM 对象的迁移。
相关单与 PR
- ADR-0019、ADR-0028、ADR-0130
- fix(lint)!: the save door refuses a list view written into a package and bound outside its closure #24630(
list-view-object-outside-closure)、packages: manifestdependenciescan be set only at create —PATCH /api/v1/packages/:idpersists only name / description / version, so a save refused with "declare a dependency" has no remedy short of recreating the package #24670 / feat(runtime): PATCH /api/v1/packages/:id edits a package's manifest dependencies #24703(dependencies可事后修改) - hotcrm:
docs/architecture/psa-module-plan.md、docs/architecture/module-split-plan.md(R1–R4)、docs(requirements): REQ-0007 order-to-cash module — what sales must see after the contract hotcrm#2251(订单与回款模块,列出了「按租户启用模块 / 应用间依赖」这一上游需求)
Activity
os-elon-musk commentedon Oct 23, 2026
Ruling: batch #7 item 1 · letter B′ · maintainer 「同意」 2026-10-23T16:28:30Z
What B′ is (the card's B, narrowed by the maintainer's own words in the director thread; the letters A / B / C as filed and the D「发布对象」 variant the director offered at 16:10 were not chosen):
ManifestSchema.dependencies({ packageId: versionRange }, manifest.zod.ts); the save door's closure already honours the declared packages' objects (list-view-object-outside-closure, fix(lint)!: the save door refuses a list view written into a package and bound outside its closure #24630 / packages: manifestdependenciescan be set only at create —PATCH /api/v1/packages/:idpersists only name / description / version, so a save refused with "declare a dependency" has no remedy short of recreating the package #24670 / feat(runtime): PATCH /api/v1/packages/:id edits a package's manifest dependencies #24703), so cross-app references need no new reference mechanism and no owner-side「published object」flag.dependency_missingcategory thatAppCompatibilityCheckSchema(packages/spec/src/system/app-install.zod.ts) already reserves and that today has no producer.The maintainer's reasoning, verbatim, for the ADR author (director thread, 2026-10-23):
Workload of the chosen letter: one ADR by the
domain:specseat (S, half a day to a day): the contract above; ADR-0028 D4 rewritten to「no cross-app reference without a declared dependency」; a cross-reference in ADR-0019 (text unchanged, ADR-0130's recording convention); the deferred gates listed by name; the open permission section; the manifestdependenciesrecord and the marketplacePackageDependencySchemaarray (package-version.zod.ts) aligned. Then one runtime card for the pre-install check (XS–S) with the console's refusal text, plus docs. The first consumer scenario the ADR should name is a HotCRM module shipping on its own (hotcrmdocs/architecture/module-split-plan.md, the 2026-09-14 shape: sales app + service / revenue / marketing;revenuefirst per ADR-0130 §1.3(c)); until the check lands, composite products keep shipping as one artifact under ADR-0130. The card's premise 6 is answered: nothing at install readsmanifest.dependenciestoday (dependency_missingis an enum only;packages.tsvalidates the key's shape;core/dependency-resolver.tsserves kernel plugins), which is exactly the gap item 2 closes.Labels:
needs-user-decision→pm:queue; thedomain:specseat claims and drafts (裁不派). Brief with the four appendices (B business view, D variant, why the check is needed, HotCRM module split state): https://claude.ai/artifact/DKvzE9D3NBheC17fJEfbRW (private to the maintainer's account).Generated by Claude Code
objectstack-fleet commentedon Oct 23, 2026
From
repo:hotcrmseat 1 ·os-elon-musk· sessionsession_014xanhPEmGTMTfVH4UokwJT· 2026-10-23T16:46ZTwo inputs for the ADR this card's ruling (B′,
6369704387) asks for. They come from filing HotCRM's module-split cards: hotcrm#2270 packages revenue and marketing inside the one artifact; hotcrm#2271 ships revenue on its own once the pre-install check is released. This is information for the drafting seat. HotCRM does not rule on either point.namespace: 'crm'(src/sales/index.ts:76,src/service/index.ts:151). ADR-0130 D1 makes a shared namespace legal only inside one release artifact.NamespaceConflictErrorfor a non-co-owner package whose namespace is already installed (packages/objectql/src/registry.ts:5942). ADR-0048 D2 says the gate still refuses to co-install the two.needs-user-decision.not_planned(2026-09-12).5645322259) says a module carved out as its own artifact ships its own permission sets, and that the card is not reopened for that. Its survey (5623464256) measured that module-owned sets already ship.navigationContributions)—— ADR-0130 分拆第二阶段,不挡发版 #14488 as "filed, not decided". That line is stale.Generated by Claude Code
os-elon-musk commentedon Oct 24, 2026
Ruling: batch #8 item 2 · letter A · maintainer 「同意 #8」 2026-10-24T00:40:55Z
Second decision for the B′ ADR, raised by comment 6370024454 and objectstack-ai/hotcrm#2271 premise 1: a standalone revenue artifact keeps
namespace: 'crm', while today's install gate (packages/objectql/src/registry.ts~5929–5942) refuses a package whose namespace an installed non-co-owner owns; co-ownership is proven only within one artifact (ADR-0130 D1) and the owner field is deferred (D8).Chosen A — dependency-declared co-ownership: a package that declares
dependencieson an installed package X and uses X's namespace is treated as X's co-owner at the install gate. One-way: the dependent gains nothing on X's side, and X never declares dependencies on its modules. The ADR-0130 D3 pair holds — the per-object-name uniqueness check now spans those co-owners across artifacts. No new manifest field. Workload: objectql S (one more source forcoOwners, plus a test), riding with the B′ runtime pre-install card. Not chosen: B (end D8's deferral with an owner / publisher field aligned topublisherOrgId— it remains the later superset and needs no undo of A), C (rename module objects — refused, ADR-0129; hotcrm#2271 ⛔).For the
domain:specseat drafting the B′ ADR: add this as its own decision (「声明依赖即命名空间共有,单向,D3 对象名唯一检查跨发布物同行」), state it as a one-way door whose in-tenant trust is the administrator's install choice, and reword ADR-0130 D8's deferral to end at marketplace publishing (ADR-0048's 2026-08-08 addendum, still Proposed) rather than at a module's first standalone artifact. Director brief: https://claude.ai/artifact/DAfU6jpbkvmgLpZUgu5RJM (card 2).Generated by Claude Code
objectstack-fleet commentedon Oct 24, 2026
Claim: PM loop round 1
Session:
session_01HwUcNzGjPhV6xtYkJ469qK(the card thread; seat sessionsession_01K2Tat8JEt4AhLASV4V4QWEposts this claim)Account:
marchtianBranch:
claude/project-thread-uu2cmpWorktree:
objectstack-issue-25403Domain:
domain:specSeat:
domain:spec#4(seat post #18917)File surface:
docs/adr/**only: one new ADR recording rulings6369704387(B′) and6377678758(namespace, letter A), plus the ADR-0028 D4 rewrite, the ADR-0019 cross-reference (text unchanged) and the ADR-0130 D8 / stale #14488 lines. No code, no schema (stop on breach; explain in the report).Container & model:
M(S in size, design judgment rather than gates),mode:thread,model: default tier (dispatch-gates --tier: "no path-derived mandate", floor sonnet · default opus · ceiling fable),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
n/a — not a defect cardThread-read: 6377678758
Premise: holds (at
main47af3dde42: no ADR indocs/adr/records inter-app dependencies;dependency_missingappears only inpackages/spec/src/system/app-install.zod.tsand its test; no open PR names #25403)Ruling-ref: 6369704387, 6377678758
Serial constraints cleared: none. No open PR names #25403 or touches the four ADRs; the lane's in-flight cards (#25696, #25681, #25650, #25608, #25575, #8133, all seat 2) touch no
docs/adr/**file named here.Tier H: the PR stays draft and the maintainer merges it. The dispatch order travelled in the card thread's opening message.
objectstack-fleet commentedon Oct 24, 2026
os-dev-report
{ "issue": 25403, "status": "done", "branch": "claude/project-thread-uu2cmp", "pr": "https://github.com/objectstack-ai/objectstack/pull/25717", "session": "session_01HwUcNzGjPhV6xtYkJ469qK", "premise_still_valid": true, "summary": "Draft PR #25717 (Tier H, docs/adr/** only, head d9b22062): new ADR-0141 (Proposed) recording rulings 6369704387 (B prime) and 6377678758 (namespace, letter A) as D1-D8 per the order: declaration = ManifestSchema.dependencies and reference = the save door's closure (no new mechanism, no publish marker); D2 pre-install check only (installed or co-delivered by the same artifact, version in range, else one ADR-0112 refusal listing every unmet entry as dependency_missing; runs at the install doors that already run the ADR-0087 D1 handshake, not at boot re-registration); D3 the five deferred items by name with interim state and trigger; D4 permissions unchanged, record-level semantics an open section; D5 dependency-declared namespace co-ownership, one-way, D3 uniqueness across co-owners, no new field, ADR-0130 D8 deferral ending at marketplace publishing; D6 ADR-0028 D4 rewritten to 'no cross-app reference without a declared dependency', ADR-0019 one additive Related line (text unchanged), ADR-0130 addendum for D8 and the stale #14488 line (ruling 5645322259); D7 HotCRM revenue shipping alone; D8 the dependency shapes and the alignment the runtime card owes. PM assumptions measured: (1) 'nothing at install reads manifest.dependencies' holds for checking but not for ordering: resolveArtifactPackageEntries (packages/core/src/artifact-packages.ts) reads every declared id as an optional resolvePluginOrder edge and silently skips ids outside the artifact; no door checks presence or version; dependency_missing has zero producers. (2) NamespaceConflictError in packages/objectql/src/registry.ts holds; gate now lines 5989-6005 (throw 6003), co-owner set 5974, artifact scope only. Extra finding recorded in D8: a THIRD shape, AppManifestSchema.dependencies (bare ids, no range, same file as dependency_missing, no reader outside spec). ADR number 0141: 0136 and 0140 belong to proposals that never landed (#18480, #25618 withdrawn); no open PR carries an ADR. Four drafter judgements where the rulings were silent are listed in the ADR's merge-decision section: co-delivered dependency counts as present; install acts only (boot check would be a startup-registry verdict); co-ownership recognised whichever package registers first; direct declarations only.", "tests": "No code changed, so no package build or test suite applies; no ablation (docs only). The only build run was the prerequisite of a derived gate: OS_VERIFY_LOCK_SLOT=issue-25403 bash scripts/pm/os-verify-lock.sh -c 'pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2' -> VERDICT command-exit 0, Tasks 4 successful, 4 total.", "gates": "Derived: node scripts/pm/dispatch-gates.mjs --commands (after git fetch --deepen=200; merge base 47af3dde4, 4 files, +485/-12) -> 20 commands. All 20 run at head d9b22062, exit captured before any pipe, every one exit 0: check-adr-links, check-adr-links --self-test, check-adr-symbol-anchors (2424 anchors across 143 records resolve), check-adr-symbol-anchors --self-test, check-ci-filter-parity, check-closing-keyword-parity, check-closing-keyword-parity --self-test, check-comment-mask-corpus, pnpm --filter @objectstack/lint run check:doc-formula-expressions, check:adr-anchors, 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. --ran reconciliation: 20 derived, 20 run, 0 NOT-MEASURED (derived zero, every line carried its exit code). Earlier run at ffb1c6f8: check-adr-symbol-anchors exit 1 (line-number citations in the new ADR, replaced by symbol/file anchors in d9b22062) and check:doc-formula-expressions exit 3 (prerequisite: @objectstack/lint unbuilt, built under the lock). CI families: in_progress at report time (PR just opened), not re-run locally.", "dogfood_battery": "n/a - no ! in the PR title and no (narrowing) arm", "mcp_calls": "11 - all reads: mcp__github__issue_read x5 (#25403 get, get_comments x2; #14488 get, get_comments), mcp__github__list_pull_requests x1, mcp__github__search_pull_requests x3 (open ADR PRs, ADR-0136, ADR-0140), mcp__github__pull_request_read x2 (#25618 get_comments, #25717 get). No MCP write tool.", "api_writes": "2 relay strokes as objectstack-fleet[bot] via scripts/pm/fleet-write/dispatch.mjs (repository_dispatch, HTTP 204): (1) run 40142863774, pr_create -> POST /repos/objectstack-ai/objectstack/pulls (draft, #25717, body read back 7861/7861 bytes identical) with its labels (skip-changeset) and assignees (marchtian) rows and the relay's governed-review request (hotlong, os-zhuang); (2) this os-dev-report via scripts/pm/post-stamped.mjs -> POST /repos/objectstack-ai/objectstack/issues/25403/comments. git push is not a REST write.", "open_questions": [], "out_of_scope_findings": [ "carrier: the B prime runtime card (cut after ADR-0141 merges) - noted, not filed: os package publish snapshots the compiled manifest's record-shaped dependencies into sys_package_version.manifest_json, whose declared schema PackageManifestSchema.dependencies is an array of PackageDependencySchema; control-plane consumption lives in objectstack-ai/cloud, not measured. Recorded as ADR-0141 D8 item 1.", "carrier: the same runtime card - noted, not filed: AppManifestSchema.dependencies (packages/spec/src/system/app-install.zod.ts) is a third dependency shape (bare ids, no range) with no reader outside packages/spec. Recorded as ADR-0141 D8 item 3.", "carrier: the seat - noted, not filed: ruling 6369704387 cites 'revenue first per ADR-0130 section 1.3(c)'; 1.3(c) names CPQ. Recorded in ADR-0141 Verification notes; no decision moves." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 24, 2026
ACCEPT → PR #25717 comment 6390968082 · seat
domain:spec#4· 2026-10-24T23:39Z. Tier H: the PR stays draft withneeds-user-decision; it lands by the maintainer's merge, or by an authorized approval after which this seat lands it. The card stayspm:dispatcheduntil then.