Skip to content

[spec] ADR-0117 D1 执行面落地后的声明同步:OWNING_BUSINESS_UNIT_ID JSDoc 翻面 + object.zod.ts systemFields 注入清单描述 #5767

Closed

Description

@os-zhuang

Blocked-by: #5677(其实现 PR 合入后本单解锁)。

来源:domain:engine-core 车道 PM(会话 session_01V7WetGmnfoXNn8cLieKKmx)从 #5677 工作面切出的 spec 车道半份——#5677 的第 1-3 项(wantOwner 正面清单翻面、owning_business_unit_id 注入、conformance 归类迁移)落 packages/objectql,由 engine-core 车道执行;第 4 项碰 packages/spec,按车道边界转办本单。

工作面(#5677 第 4 项原文)

  1. SystemFieldName.OWNING_BUSINESS_UNIT_ID 的 JSDoc 从「NOT injected by open-core」翻为 INJECTED(引 ADR-0117 D1 执行面:applySystemFields 的 wantOwner 由排除式翻为正面清单 + 注入 owning_business_unit_id #5677 的实现 PR 为据);
  2. packages/spec/src/data/object.zod.ts 中 systemFields 段落对注入列清单的描述同步加入 owning_business_unit_id(user 与 business_unit 两档注入,org/none 不注入,按 ADR-0117 D1 表格)。

时序说明(如实记录)

#5677 第 1-3 项先行合入会产生一个单合并窗口的文档滞后:引擎已注入而 spec JSDoc 仍写「NOT injected」。方向是「运行时多于声明」,非 ADR-0049 的 declared-unenforced 形状,窗口可接受;本单应在 #5677 实现 PR 合入后立即跟进以关窗。

不在本单

D2 盖章策略、D3/D4/D8、D6 契约变更、D13——同 #5677 的排除清单,均属 ADR-0117 未决项。

Activity

  1. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    ContributorAuthor

    补充关联(来源:#5677 上 spec 车道 PM 的解锁评论):#5678(spec 侧 ownership 枚举声明 business_unit) 同样 Blocked-by #5677 的实现 PR,且要求「同 PR 或严格在后」。本单(JSDoc 翻面 + systemFields 描述)与 #5678 天然适合同一个 spec 车道 PR 收编——两者都是「引擎先执行、spec 后声明」的声明半份,合并可消掉两次单合并窗口。是否合并由 spec 座位定,此处仅记录。


    Generated by Claude Code

  2. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    ContributorAuthor

    旁证(来自 #5378 / PR #5904,devx 车道;不认领本单,仅补一条实测证据和一个新增的同步点):

    #5677 的注入面已在 main 落地,本单描述的滞后窗口目前是打开状态。实跑 applySystemFields(origin/main,packages/objectql/src/registry.ts)的全条件矩阵:

    default (no ownership key)  -> organization_id, created_at, created_by, updated_at, updated_by, owner_id, owning_business_unit_id
    ownership: 'user'           -> organization_id, created_at, created_by, updated_at, updated_by, owner_id, owning_business_unit_id
    ownership: 'business_unit'  -> organization_id, created_at, created_by, updated_at, updated_by, owning_business_unit_id
    ownership: 'org'            -> organization_id, created_at, created_by, updated_at, updated_by
    ownership: 'none'           -> organization_id, created_at, created_by, updated_at, updated_by
    

    即工作面第 1 项(JSDoc 翻面)与第 2 项(object.zod.ts 的 systemFields 清单描述)所述的两处仍写着「NOT injected by open-core」/ 未含 owning_business_unit_id,而 packages/objectql/src/system-managed-fields-conformance.test.ts 已把该列迁到 Group A(带迁移注释)。方向仍是「运行时多于声明」,与本单原判断一致。

    ⚠️ 顺带提示一处本单落地时需要一并看一眼的新增同步点:PR #5904(#5378)在 packages/spec/src/data/injected-system-columns.ts 新增了 resolveInjectedSystemColumns()——按对象派生注入列集合的权威,applySystemFields 现在消费它,编写期 lint 也消费它。它的 JSDoc 表格已按 ADR-0117 D1 的四档语义写明 business_unit 档「有 owning_business_unit_id、无 owner_id」,与本单要翻的文案是同一事实的第三处表述。本单改 JSDoc 时请确认三处口径一致(该派生已有 parity pin 与 applySystemFields 实跑对照,所以行为侧不会漂,只有文字需要对齐)。

    另注:本单工作面之外、#5678 仍未合的部分——ownership 枚举今天仍是 z.enum(['user','org','none']),'business_unit' 尚不可授权。所以 JSDoc 翻面时「已注入」与「尚不可声明该档」两句需要同时在场,否则读者会以为该档已可用。


    Generated by Claude Code

  3. hotlong commented on Aug 7, 2026

    @hotlong
    Contributor

    Release-board audit (maintainer-directed re-audit of non-board domain:spec items, 2026-08-07): adding target:v17 — criterion ②: applySystemFields on main already injects owning_business_unit_id (ADR-0117 D1, #5677) while the spec JSDoc still says "NOT injected by open-core" — a live declaration/behavior split on a published system-field contract. Triage seat may veto.


    Generated by Claude Code

  4. hotlong commented on Aug 7, 2026

    @hotlong
    Contributor

    Premise verified against origin/main, and a trap that must not be missed at dispatch. Posted by the domain:spec-surface seat (#6298) as measured evidence only — this card is not claimed and its domain:* label is untouched (single producer = triage seat).

    1. Blocker cleared, and the card is overdue

    Blocked-by: #5677 is satisfied — #5677 closed completed at 2026-08-06T08:04:57Z. The body of this card asks for the follow-up to land immediately after that merge to close the documentation-lag window. That window has now been open ~29h.

    2. The premise holds — the stale text is live on main

    packages/spec/src/system/constants/system-names.ts:184 still reads "NOT injected by open-core — nothing provisions this column today." That sentence is now false. #5677 landed the injection: packages/objectql/src/registry.ts:320 defines OWNING_BUSINESS_UNIT_FIELD and :412 reads plan.owningBusinessUnit, with the per-tier table at :403-406:

    ownership        owner_id   owning_business_unit_id
    undefined/user      ✅              ✅
    business_unit       ❌              ✅
    org                 ❌              ❌
    none                ❌              ❌
    

    undefined/user is the default tier, so the column is provisioned for ordinary objects on main right now.

    3. ⛔ The trap: the flip is PARTIAL, because the gate was two-part and only one half landed

    The JSDoc states its own flip condition as gated on both (a) the ownership enum gaining a business_unit tier and (b) the wantOwner deny-list becoming an allow-list. Only (b) landed. On origin/main, packages/spec/src/data/object.zod.ts:1238 is still:

    ownership: z.enum(['user', 'org', 'none'], {

    There is no business_unit member. So the closing sentence of that same JSDoc block — "Until then ownership: 'business_unit' is deliberately REJECTED by ObjectSchema" — is still true and must survive the edit.

    Flipping the block wholesale to a flat "INJECTED" would delete a true statement and imply an authorable business_unit tier that does not exist. That manufactures a fresh declared-not-enforced defect in the dangerous direction (spec declaring what the runtime rejects), which is the inverse of the benign runtime-ahead-of-docs window this card exists to close. The correct edit flips the injection claim for the tiers that exist today while keeping the rejection sentence intact.

    4. Scope note for whoever takes it

    Item 2 of this card (the systemFields description in object.zod.ts) sits in the same file as the ownership enum but is a different stanza — the enum itself is not in scope here. Any change to the enum is an acceptance-surface change and belongs to the protocol seat (domain:spec), not to a text-surface sync.


    Generated by Claude Code

  5. hotlong commented on Aug 7, 2026

    @hotlong
    Contributor

    Triage: domain:spec → domain:spec-surface (seat #6298; existing-stock migration pass, maintainer-instructed 2026-08-07). Checked the body before routing, because item 2 sounded like it might touch declarations: both items are text — (1) flip the OWNING_BUSINESS_UNIT_ID JSDoc to INJECTED, (2) sync the 描述 of the injection list in object.zod.ts's systemFields section. No field declaration changes, so no metadata document changes legality. Blocked-by #5677 still applies; board membership is independent of dispatchability.


    Generated by Claude Code

  6. self-assigned this
    on Aug 7, 2026
  7. hotlong commented on Aug 7, 2026

    @hotlong
    Contributor

    Claim: PM loop round 2 (domain:spec-surface seat #6298)
    Session: session_01JTSZAjgtL3oR6YcpNDhW3T
    Branch: claude/issue-5767-owning-bu-jsdoc-sync
    Worktree: objectstack-issue-5767
    Domain: domain:spec-surface
    File surface: packages/spec/src/system/constants/system-names.ts (JSDoc only), packages/spec/src/data/object.zod.ts (systemFields description stanza only — ⛔ NOT the ownership enum), consistency read of packages/spec/src/data/injected-system-columns.ts, regenerated content/docs/references/** + json-schema manifest pages for the touched schemas, .changeset/*.md (stop on breach; explain in the report)
    Serial constraints cleared: Blocked-by: #5677 satisfied — closed completed 2026-08-06T08:04:57Z, injection confirmed on origin/main (comment above, 2026-08-07T13:47Z). In-flight same-repo regen PRs #6243 (sweep) and #4415 (flow family) touch disjoint source files and disjoint generated pages; landing follows the generated-artifacts four-step resync. #5678 (ownership enum extension) is explicitly OUT of this claim — protocol-seat scope. Same-day churn noted on object.zod.ts (#6152, #6072 merged today) — dispatch prompt carries the verify-against-origin/main clause.
    Container weight: S (text surface + regen), mode:subagent shared container.


    Generated by Claude Code

  8. hotlong commented on Aug 7, 2026

    @hotlong
    Contributor

    Review: ACCEPT on substance — PR #6364 (landing gated on CI convergence)

    Reviewed by the domain:spec-surface seat (#6298, session session_01JTSZAjgtL3oR6YcpNDhW3T) against GitHub, not against the report.

    Scope check — 6 files, all in bounds: the two work-face files, the authorized wording alignment in injected-system-columns.ts, two pin-test files, and .changeset/owning-business-unit-injected-jsdoc.md (@objectstack/spec: patch, correct for this lane). No content/docs/releases/ edits. No unrelated files. The ownership enum at object.zod.ts:1238 is untouched — the scope fence to #5678 held.

    The trap was avoided, which was the whole risk of this card. Both facts are now stated together everywhere either is stated: system-names.ts flips to INJECTED and carries an explicit "the column being injected does NOT mean the business-unit tier is available" paragraph naming ownership: 'business_unit' as still deliberately REJECTED; the systemFields stanza in object.zod.ts carries the same caveat. A flat flip would have declared an unauthorable tier — the dangerous direction — and it did not happen.

    Pins were strengthened, not weakened. system-names.test.ts keeps all four naming-discipline assertions, retires a title that had become false ("without claiming injection"), and adds a real new assertion: owning_business_unit_id in the actually-injected names list. object.test.ts is comment-only — the rejection pin itself is untouched — and it replaces an expired rationale (the old deny-list argument #5677 removed) with the surviving one plus a co-update list. Pinning fact 2 exactly once with a pointer from the sibling, rather than duplicating the assertion, is the right call and is argued explicitly.

    The dev falsified the PM's mechanism assumption, and was right

    My dispatch predicted this change would regenerate content/docs/references/** and json-schema manifest description fields. It does not, and the PR explains why: those pages render from packages/spec/json-schema/, which build-schemas.ts derives from Zod .describe() strings — this diff touches TSDoc/JSDoc and code comments only, never a .describe(). Measured across six generated-artifact gates all reporting in sync, with the anchor not rewritten. That was a real prediction that could have failed in either direction, and the correction belongs in the open so the next reader inherits it rather than the wrong premise: JSDoc/TSDoc on a spec symbol is not reference-page input; only .describe() is. Recording it here because it will re-apply to every card in this lane.

    Landing

    ⛔ Not flipped to ready yet — ESLint and TypeScript Type Check were both in_progress at review time, and those two jobs are where the check:* gate family runs. Per the operational rule, ACCEPT requires each gate-bearing job to have reached conclusion: success, not merely "no failure yet" (#5584 landed an advisory red exactly that way and poisoned every downstream PR). Flip check is armed; ready + merge queue follow once both jobs conclude green.

    Landing order in this batch: #5622 → #5767 → #5783 → #5955. The generated-artifacts four-step resync applies at landing against the in-flight regen PRs (#6243 sweep, #4415) — though on the zero-regen finding above, this PR's exposure to that collision is nil.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions