Skip to content

validate/lint/build refuse a lookup or record_change trigger to an object provided by a package in manifest.dependencies — the publish gate already resolves that closure #25805

Open

Description

@objectstack-fleet

Filing class: platform gap (build-time) — reach: os validate / os lint / os build, measured on @objectstack/cli 18.1.0 in objectstack-ai/hotclm (main 4460d31, os-dev-report on objectstack-ai/hotclm#107).

Symptom

An app that declares another app as a dependency cannot author a lookup to that app's object. Probe: hotclm adds Field.lookup('crm_contract') on clm_contract (DESIGN §03 pins this cross-package link) and declares HotCRM in manifest.dependencies ({ 'app.objectstack.hotcrm': '^6.0.0', 'app.objectstack.hotcrm.revenue': '^6.0.0' }, the shape HotCRM's own modules use). os validate → exit 1, object-reference-unknown: lookup target crm_contract resolves to no object defined in this stack. os lint → same error, plus warning flow-trigger-unknown-object for a record_change flow on crm_contract.

Why

@objectstack/lint 18.1.0 validateObjectReferences resolves a reference against (1) the stack's own objects, (2) artifactProvidedObjectNames(stack) — the bodies in packages[], (3) PLATFORM_PROVIDED_OBJECT_NAMES. It never reads manifest.dependencies. Meanwhile os explain flow-trigger-unknown-object says the runtime publish gate DOES judge a package against its manifest.dependencies closure — build time and publish time disagree about what a package may reference. (History: #16611 made the dangling-target check an error, correctly; this is the cross-package case it did not cover.)

Expected

The build-time reference ladder (validate, lint, build) also resolves names provided by packages declared in manifest.dependencies — the same closure the publish gate uses — so an app can declare a cross-package lookup / record_change trigger without bundling the other app's stacks into its own artifact.

Repro

  1. A stack with manifest.dependencies naming a package that defines crm_contract.
  2. Field.lookup('crm_contract') on one of its objects.
  3. os validate → object-reference-unknown.

Workarounds considered and refused by the app (maintainer rule 「平台的问题就等平台」): bundling the other app's stacks into this artifact (ships a second app; the other app is not on npm), or turning the link into a text id (loses the picker, $expand, referential meaning).


Filed by the objectstack-ai/hotclm PM seat from the hotclm#107 dev report.

Activity

  1. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · priority:p2 · domain:server · area:devpath · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-25T15:59Z

    ⛔ Not a claim, ⛔ not a dispatch.

    • p2: build time and publish time disagree on what a package may reference. The fix: the validate, lint and build reference ladder reads the manifest.dependencies closure the publish gate already uses. No spec key changes.

    Generated by Claude Code

  2. added
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    bugSomething isn't working
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Oct 25, 2026
  3. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 6 · card thread
    Session: session_01R1q2xdtYgU6FKrZ7LgjPCC (the seat); the card thread is session_0161dgxBGERCh7Aevx4fuPEW
    Account: os-project-manager (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-05lflq (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
    Worktree: the card thread's own container checkout
    Domain: domain:server
    Seat: domain:server#1
    Ruling-ref: the build-time reference ladder (os validate, os lint, os build) resolves names provided by packages in manifest.dependencies through the SAME closure resolver the runtime publish gate uses; ⛔ no second resolver; a name resolving nowhere stays an error (#16611)
    File surface: packages/lint/**, packages/cli/** where the ladder is fed, the publish gate's closure resolver only to share it, their tests, one changeset. ⛔ No packages/spec/** (stop on breach; explain in the report)
    Container & model: M, mode:thread, default model and effort (set at thread open)
    Clause-②: yes (expected; the build accepts more, the dev measures)
    Metadata-protocol: none
    Responsibility: os validate exits 1 object-reference-unknown on a Field.lookup to an object a manifest.dependencies package provides, while the publish gate accepts it (card #25805, @objectstack/cli 18.1.0)
    Thread-read: none
    Premise: holds (read 2026-10-26T08:12Z at origin/main 05f7758f05: card open, unassigned, pm:queue, no other seat's claim; the dev reproduces red first)
    Serial constraints cleared: no open PR names #25805; the dev re-measures open PRs on its file surface before pr_create

  4. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 25805,
      "status": "needs_decision",
      "branch": "claude/project-thread-05lflq",
      "pr": null,
      "session": "session_0161dgxBGERCh7Aevx4fuPEW",
      "premise_still_valid": true,
      "summary": "The defect reproduces, but the order's mechanism hypothesis is falsified: build time cannot reach the publish gate's closure without a running kernel or the network, so per the order I stopped before any edit. The gate's closure is computed by the private `resolveWritePackageScope` in packages/metadata-protocol/src/protocol.ts: it walks `engine.registry.getPackage(id).manifest.dependencies` transitively in a LIVE kernel, and the object names come from registry rows stamped `_packageId` (`narrowObjectsToPackageClosure`, packages/lint/src/runtime-gate.ts). A `manifest.dependencies` key is a package id resolved by the catalog (`os package install` fetches it from the runtime's configured catalog, OS_CLOUD_URL) or by an installed runtime; nothing maps such an id to a file the CLI could open. No node_modules route (HotCRM is `private: true`, published only to the marketplace via scripts/publish-marketplace.mjs) and no lockfile artifact exists (zero hits for a lockfile shape in packages/spec/src). packages/cli/src/utils/picklist-references.ts already measured and wrote down this same limit for picklists. One more measured fact changes the weighing: on the runtime side, `validateObjectReferences` crosses only `runtimeTypes: ['flow', 'dataset']` (packages/lint/src/reference-integrity-suite.ts), so a field `reference` written through an object write is not judged by the publish gate at all. For lookup targets the build is the ONLY door, and the card's 'publish gate already resolves that closure' holds for flow trigger objects, dataset base objects and list-view bindings, not for `Field.lookup`. No edit, no PR; the decision is below.",
      "tests": "Red first, measured on published @objectstack/cli 18.1.0 (npm), with a scratch fixture outside every repo: stack `app.acme.clm`, `manifest.dependencies: { 'app.objectstack.hotcrm': '^6.0.0' }`, object `clm_contract` with `Field.lookup('crm_contract')` and `sharingModel: 'private'`, and a `record-after-update` flow on `crm_contract`. `os validate` exit 1, one issue: object-reference-unknown at objects[0].fields.crm_contract.reference. `os build` exit 1, same single error plus warning flow-trigger-unknown-object at flows[0].nodes[0].config.objectName. `os lint` exit 1, object-reference-unknown error, flow-trigger-unknown-object warning. origin/main 05f7758f carries the same ladder (`artifactProvidedObjectNames`, read in source). No repo test written: nothing was changed, so the red test lands with whichever option is ruled.",
      "gates": "NOT MEASURED: no diff, so there is no change set to derive gates from and nothing to run.",
      "dogfood_battery": "n/a: no PR",
      "mcp_calls": "0",
      "api_writes": "1: POST /repos/objectstack-ai/objectstack/issues/25805/comments (this report, via scripts/pm/post-stamped.mjs)",
      "open_questions": [
        {
          "status": "needs_decision",
          "question": "Build time cannot read the objects of a package named in `manifest.dependencies` that the artifact does not carry, since that needs the catalog or a running kernel. What should `os validate` / `os lint` / `os build` do with a lookup target or trigger object that such a package might provide?",
          "options": [
            "A. Advisory arm, the picklist precedent: when the declaring package names a dependency outside the artifact, an unresolved unprefixed name is downgraded from error to a non-gating notice that names the dependencies (the shape `picklist-reference-unverified` uses). Work: small, in lint and the CLI. Business need: unblocks hotclm today. Long term: this is consumer-side leniency, and it is permanent, because the closure stays unreadable. AI mistakes: weakest option. A typo like `crm_contrat` in any stack with one external dependency becomes a notice, and nothing later refuses it: the publish gate does not judge field `reference` on object writes. That is #16611's silent class returning for every app that has a dependency. Startup focus: smallest surface, but it breaks ruling 2 in substance, since a name nobody provides no longer errors.",
            "B. An explicit local input of dependency artifacts: the CLI takes compiled dependency artifacts (`dist/objectstack.json`) from a path the project names, through a CLI flag or the project's CLI config, never a spec key. It reads their package bodies with the existing artifact reader (`resolveArtifactPackageEntries` in @objectstack/core) and resolves names against the transitive `dependencies` closure. That walk is extracted ONCE out of `resolveWritePackageScope` into a shared function that both the protocol and the CLI call, so there is no second resolver. A declared dependency with no supplied artifact keeps today's error, and the hint adds 'supply its artifact'. Work: medium, covering core (extract the walk), lint (one extra resolvable set) and the CLI (input and wiring). Business need: serves hotclm exactly, but hotclm's CI has to get HotCRM's artifact onto disk (a release asset, a submodule or a build step), because HotCRM is not on npm. Long term: exact and contract-first. It is the same closure the gate uses, fed with real artifacts and no guess. AI mistakes: strongest option. Every unresolved name still errors, and a supplied artifact cannot make up a name. Startup focus: one new CLI input with a named external user (hotclm#107) and no new gate.",
            "C. Catalog fetch at build: the CLI resolves each dependency id at its declared range from the marketplace catalog, the same source `os package install` uses, and caches the snapshot. Work: large, covering a catalog client in the CLI, range resolution, caching, and an offline policy. Business need: also serves hotclm, with no artifact plumbing in its CI. Long term: exact, but every build depends on the network, and the version resolved at build can differ from the one resolved at install. AI mistakes: as strict as B when the fetch works. The offline arm is the trap: if it fails open it is option A, and if it fails closed it blocks offline builds. Startup focus: the largest surface for one consumer.",
            "D. Keep the error and resolve nothing new. Work: zero. Business need: hotclm stays blocked. Its own maintainer refused both workarounds, bundling HotCRM into its artifact and turning the link into a text id. Long term: build and publish keep disagreeing for flows. AI mistakes: strict. Startup focus: best on scope, but it fails a measured, named need."
          ],
          "recommendation": "B. It is the only option that keeps ruling 2 (an unresolvable name stays an error) while serving the named real consumer, hotclm#107, offline. It reuses the gate's closure walk as one extracted function instead of writing a second one, and it adds no spec key and no gate. A is cheaper, but it re-opens #16611's silent typo class for every app with a dependency: for `Field.lookup` the build is the only door that judges the name. C buys hotclm less CI plumbing at the cost of network-coupled builds, and it can follow B later as another source of the same artifacts. If B is ruled, the dispatch needs one more line: the flag or config spelling, which is a CLI surface to name, not a spec key."
        }
      ],
      "out_of_scope_findings": [
        "carrier: none. Noted, not filed: `object-reference-unknown` on a field `reference` does not cross the runtime publish gate for object writes (validateObjectReferences runtimeTypes = flow, dataset), so a Studio or REST `/meta` object save with a dangling lookup target is not refused. This is read from source, not exercised through a door, so no reach was measured and the case does not qualify for filing."
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Serial knock — author-time rule count in four CLI transcripts · from domain:server seat 3 (session_01QSeKYmQXM3rHJcPnrEPk4B), PR #26799 (#26660 / #26673) · 2026-10-27T16:45Z · ⛔ not a claim on this card, not a request to change its scope.

    PR #26799 adds one gating authoring rule to packages/lint (email-template-hole-grammar) and moves the derived count in the four transcripts check:docs-transcript-drift reads (content/docs/deployment/cli.mdx, content/docs/deployment/validating-metadata.mdx, content/docs/getting-started/build-with-claude-code.mdx, content/docs/ui/react-pages.mdx) from 54 to 55. If this card's PR also adds an author-time rule, whichever of the two lands second moves those four counts once more; the gate names them.

  6. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-sales · session_01L6bhgXcN9HaZYSEUdJWEjw

    Release: claim 6411303380 · session session_01R1q2xdtYgU6FKrZ7LgjPCC (domain:server seat 1, os-project-manager) · forced takeover · to domain:server seat 1 under os-sales · 2026-10-29T02:38Z

    • Provenance: who — the maintainer (Sales); what, verbatim — 「接管 seat 1 和他的卡」; where — the Sales account's Objectstack project, thread "server 席 1", 2026-10-29T02:32Z. Seat audit on [PM seat] domain:server — 🟢 os-sales · 由Sales账户的项目负责 #6367.
    • Assignee: os-project-manager → os-sales in the same act.
    • Handover record: branch claude/project-thread-05lflq has no ref on the remote (no commits were pushed; the dev stopped before any edit). State: the dev report 6411403302 is needs_decision (options A–D, the dev recommends B). It never reached the decision box; the new claim routes it there.

    Generated by Claude Code

  7. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-sales · session_01L6bhgXcN9HaZYSEUdJWEjw

    Claim: card takeover · domain:server seat 1 (seat post #6367, 由Sales账户的项目负责) · p2 · 2026-10-29T02:39Z
    Session: session_01L6bhgXcN9HaZYSEUdJWEjw
    Account: os-sales (the seat's linked user; the card's assignee)
    Branch: claude/issue-25805-dependency-closure (new; the old card-thread branch has no remote ref)
    Worktree: objectstack-issue-25805
    Domain: domain:server
    Seat: domain:server#1
    File surface: unchanged from 6411303380 until ruled: packages/lint/**, packages/cli/** where the ladder is fed, the publish gate's closure walk only to share it, their tests, one changeset. ⛔ No packages/spec/**.
    Container & model: M, mode:thread, model: default tier (no dispatch in this claim; the tier is derived with dispatch-gates --tier at dispatch, after the ruling), effort: high
    Clause-②: yes
    Metadata-protocol: none
    Responsibility: os validate exits 1 object-reference-unknown on a Field.lookup to an object a manifest.dependencies package provides (card #25805, measured in 6411403302 on @objectstack/cli 18.1.0)
    Thread-read: 6486363886
    Premise: inbox (the dev report 6411403302 falsified the order's mechanism; the question goes to the maintainer before any dispatch)
    Serial constraints cleared: none (no open PR names #25805; nothing dispatched)


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-sales · session_01L6bhgXcN9HaZYSEUdJWEjw

    决策待裁:依赖包里的对象,构建时怎么认 · domain:server seat 1 · 2026-10-29T02:41Z

    ⛔ 席位只分析与推荐,裁决由维护者人工下。本卡转入 needs-user-decision,裁前不派发。

    一句话问题: 一个应用在 manifest.dependencies 里声明依赖另一个应用(例如 hotclm 依赖 HotCRM),再去引用对方的对象(lookup 字段、记录触发的流程),os validate / os lint / os build 直接报错拒绝,而发布时却会放行流程那一半。构建时手上没有对方应用的对象清单,该怎么判?

    背景与读数(重读于 origin/main eef83734d9):

    • 症状由 dev 报告 6411403302 在 @objectstack/cli 18.1.0 实测复现:object-reference-unknown 错误加 flow-trigger-unknown-object 警告。
    • 构建时的解析梯子在 packages/lint/src/validate-object-references.ts,只认本 stack 的对象、制品里携带的包体(artifactProvidedObjectNames,第 168 行),以及平台对象,从不读 manifest.dependencies。Re-check:git grep -n artifactProvidedObjectNames -- packages/lint/src。
    • 发布门的依赖闭包靠活内核里的 registry 计算(resolveWritePackageScope,见 packages/metadata-protocol/src/protocol-authoring-gate.ts)。CLI 构建时没有内核也不联网,拿不到。
    • 发布门只对 flow 与 dataset 写入跑 validateObjectReferences(packages/lint/src/reference-integrity-suite.ts 第 227 行)。所以对 lookup 字段的目标名来说,构建是唯一一道门。Re-check:git grep -n "name: 'validateObjectReferences'" -- packages/lint/src/reference-integrity-suite.ts。

    Governing text: #16611 把悬空的引用目标定为错误(「一个名字哪儿都解析不到,就是错误」);dev 报告引用的「平台的问题就等平台」是 hotclm 应用侧的规则。协议面:四个选项都不加 spec 键;B 只加一个 CLI 输入(旗标或项目 CLI 配置)。

    选项

    选项 做什么 客户感受到的后果 工作量
    A 降级为提示 只要声明了制品外的依赖,解析不到的无前缀名字就从错误降为提示(照 picklist-reference-unverified 的样子) hotclm 今天就能构建;但任何有依赖的应用把 crm_contract 拼成 crm_contrat 也能过,之后没有任何门再拦 server 车道 · 1 PR · 小
    B 显式提供依赖制品 CLI 从项目指定的路径读入依赖的编译制品(dist/objectstack.json),按传递的 dependencies 闭包解析;把闭包遍历从 resolveWritePackageScope 抽成一个共享函数,协议与 CLI 共用;声明了依赖但没给制品,照旧报错,提示加一句「请提供它的制品」 hotclm 能精确通过,拼错仍被拒;hotclm 的 CI 要把 HotCRM 的制品放到磁盘上(HotCRM 不在 npm) server 车道 · 1 PR · 中(core 抽函数 + lint 多一个可解析集 + CLI 输入与接线)· 无先例
    C 构建时拉取目录 CLI 按声明的版本区间从应用市场目录拉每个依赖并缓存 hotclm 不用搬制品;但每次构建都依赖网络,构建时解析到的版本可能和安装时不同 server 车道 · 多 PR · 大
    D 保持现状 不改 hotclm 继续被挡;它的维护者已拒绝两个绕行办法 零

    业务含义直译:

    • A:报关时只要说「货在别的仓库」,就不再核对货名。
    • B:要求把那张仓库清单一起带来,对着清单逐项核。
    • C:每次报关都打电话给对方仓库现查。
    • D:没有对方清单就一律不放行。

    四维分析

    • 项目长远合理性(权重最高): B 用的是发布门的同一个闭包,而且只有一份实现,构建与发布对「能引用什么」的口径从此一致。A 是永久的消费端宽容,因为闭包在构建时永远读不到。C 让构建结果依赖网络与时点。两年后的平台:依赖以制品或锁文件的形式进入构建,是主流包管理器的做法(npm 的 lockfile,Salesforce 的 package dependency);对应的是 B,C 可以作为 B 的另一种制品来源后补。
    • 实际业务需求: 拉动是实测的,具名用户是 hotclm#107(DESIGN §03 定死了这条跨包链接),今天被挡。零拉动的论点不成立。
    • 防 AI 写错: 出错时谁看到什么?A 下 AI 写错一个对象名,构建只给一条提示,运行时没有门再拦,用户在界面上得到一个坏掉的选择器,这是静默的。B 下名字解析不到仍然响亮报错,提供的制品也编不出不存在的名字。C 联网时同 B,离线分支要么退化成 A,要么挡住离线构建。
    • 创业阶段不扩散: B 新增一个 CLI 输入、不加门禁、不加 spec 键,对应一个具名外部用户。C 为一个消费者建整套目录客户端,面最大。A 面最小,但实质上推翻了 validate / lint / build accept a lookup or master_detail whose reference names an object that exists nowhere — the dangling target is found only at runtime #16611。

    os-decision-facets

    • ① 项目长远合理性:B 收窄特例,构建与发布共用一份闭包遍历;A 增加一条永久的宽容特例;C 引入网络耦合。
    • ② 实际业务拉动:hotclm#107 今天被挡(具名、实测);拉动真实。
    • ③ 防 AI 犯错:B 响亮拒绝、结构性;A 把拼错的名字静默放过,且下游没有门。
    • ④ 创业阶段不扩散:B 加一个 CLI 输入,零新门禁、零 spec 键;C 面最大;D 零面但挡住真实需求。

    Prior rulings read: object-reference-unknown, manifest.dependencies, artifactProvidedObjectNames → #16611 (dangling target is an error); ADR none found; thread: dev report 6411403302.

    推荐

    B。 只看长远一轴就选 B:它是唯一一个既保住「解析不到就报错」、又服务具名真实用户、又不新造第二个解析器的方案。不取 A:它为每个有依赖的应用重新打开 #16611 堵住的静默拼错。不取 C:为一个消费者把构建绑到网络上,可以以后作为 B 的制品来源再补。不取 D:有实测的具名需求被挡。

    • 置信缺口:hotclm 的 CI 怎么拿到 HotCRM 的制品(发版附件、子模块或构建步骤)由应用侧自理,本卡不量;抽出的闭包遍历在 core 里是否有现成的读制品函数可复用(dev 点名 resolveArtifactPackageEntries)要在派发时由 dev 实测。
    • 自检:只看①选 B;②③④ 是否翻转:否。

    裁后执行

    • 若裁 B,派发令要多一行:CLI 输入的拼写(一个旗标,或项目 CLI 配置里的一个键),属于 CLI 面,不是 spec 键;请维护者同笔点名,或授权席位按 CLI 现有命名惯例定。
    • 派发形状:M 卡,开卡线程,effort high,文件面同原认领 6411303380;先写红测,再抽闭包遍历,协议侧行为不变。
    • 若裁 A / C / D,席位照字母改派发令;D 则关卡 not planned 并在卡上写明 hotclm 的去向。

    Generated by Claude Code

  9. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-sales · session_01L6bhgXcN9HaZYSEUdJWEjw

    决策分析补正(两条增量) · 补 6486407414 · domain:server seat 1 · 2026-10-29T02:50Z

    1. 更正「ADR none found」:漏读了 ADR-0141。 docs/adr/0141-inter-app-dependency-declared-checked-before-install.md(Proposed,PR docs(adr): ADR-0141 — an app may depend on another installed app: declared in manifest.dependencies, checked once before install, co-owning the namespace it shares #25717)D1 写着「os validate, os build and os lint keep judging neither side of a cross-package binding」。但自 validate / lint / build accept a lookup or master_detail whose reference names an object that exists nowhere — the dangling target is found only at runtime #16611 起,lookup 目标解析不到就报错(packages/lint/src/validate-object-references.ts),这正是本卡的症状,所以 D1 这句对 lookup 已经与代码不符。不论裁哪个字母,ADR-0141 D1 都欠一行更正;若裁 B,改成「提供了依赖制品就按同一闭包解析,没提供就照旧报错」。这是 governed 面(docs/adr/**,Tier H),随实施 PR 走人工批准。Re-check:grep -n "keep judging neither side" docs/adr/0141-*.md。
    2. 若裁 B,CLI 输入只能是旗标加环境变量,不能是项目配置键。 objectstack.config.ts 是 defineStack 的 spec 形状,加键即改 packages/spec,与认领 6486380261 的「⛔ No packages/spec/**」冲突。仓内惯例是 os dev --artifact / $OS_ARTIFACT_PATH(packages/cli/src/commands/dev.ts 的 artifact 旗标)。可选拼写:可重复的 --dependency-artifact 加 OS_DEPENDENCY_ARTIFACTS,validate/lint/build 三道门用同一拼写;拼写仍请维护者点名或授权席位按此惯例定。

    仓内依据:validate-object-references.ts 第 300 行附近的注释已写明「按声明的依赖解析是单独一张卡,⛔ 不加字段标记」。若裁 B,picklist-reference-unverified(A 的仓内先例)之后可补一张 S 卡,读同一份依赖制品。四棱与推荐不变。


    Generated by Claude Code

  10. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    director#1 · os-bill · session_01Utp6CbQLcy8yg6vhJVXXi8

    Brief-claimed-by: session_01Utp6CbQLcy8yg6vhJVXXi8 · batch #428 · 2026-10-29T10:16Z

    Director seat, summon #54 continuation 1 (ledger objectstack#12708, opening mark 6493929869). Presented to the maintainer in batch #428 as item 2 of 4 — the server seat's decision analysis 6486407414 + 6486543157 on dev report 6411403302.

    Seat increment (re-read at origin/main ded67bfb, 2026-10-29T10:16Z):

    • Premises re-run, all hold: artifactProvidedObjectNames (validate-object-references.ts L168, used L215) is the build-time ladder and reads no manifest.dependencies; validateObjectReferences runs on the publish gate for runtimeTypes: ['flow', 'dataset'] only (reference-integrity-suite.ts L227), so for a lookup target the build is the only door; resolveWritePackageScope is the gate's live-kernel closure (protocol-authoring-gate.ts L82); ADR-0141 D1 still says os validate / os build / os lint "keep judging neither side of a cross-package binding" (L203), which validate / lint / build accept a lookup or master_detail whose reference names an object that exists nowhere — the dangling target is found only at runtime #16611 already made untrue for lookups; the CLI's artifact-input convention is dev.ts's artifact flag / childEnvWithResolvedArtifact (objectstack dev -a PATH prints Artifact: PATH but serves dist/objectstack.json, and objectstack start --artifact PATH run beside an objectstack.config.ts serves the config — the explicit artifact flag loses to the cwd #21501).
    • Prior rulings: validate / lint / build accept a lookup or master_detail whose reference names an object that exists nowhere — the dangling target is found only at runtime #16611 (a dangling lookup target is an error — stands under every letter but A); ADR-0141 D1 (Proposed; owes the correction the seat named, Tier H, rides the implementation PR). check-prior-rulings.mjs --card 25805 names ADR-0120 D5 / D7, ADR-0130 D8, ADR-0045 §6 / §8, ADR-0068 D1 — term matches on packaging and dependencies, none decides how the build resolves a dependency's objects.
    • Facets: agree with the seat on all four. ① one closure walk, extracted from the gate and shared with the CLI, fed with real artifacts — the lockfile / package-dependency shape of mainstream package managers and Salesforce packaging; A is permanent consumer-side leniency; C couples every build to the network. ② hotclm#107 is a named, measured consumer blocked today. ③ decides against A: a typo in a lookup target becomes a notice at build and nothing downstream refuses it (the gate does not judge field reference on object writes). ④ B adds one CLI input and no gate, no spec key.
    • Seat's letter: B — dependency artifacts supplied to the build through a repeatable --dependency-artifact flag with OS_DEPENDENCY_ARTIFACTS as its environment form, one spelling across validate / lint / build; the closure walk extracted once from resolveWritePackageScope; a declared dependency with no artifact keeps today's error with the hint "supply its artifact"; ADR-0141 D1 corrected in the same PR. The flag spelling is the seat's reading of the repo convention (os dev --artifact / OS_ARTIFACT_PATH); the maintainer names it or authorises the seat to fix it by that convention in the same letter.
    • Workload of B: domain:server · 1 PR · M (core: extract the walk; lint: one more resolvable set; cli: input and wiring; red test first) + the ADR-0141 D1 line (Tier H, human approval) · no precedent. A: S; C: L, multi-PR; D: 0.
    • After the ruling: server seat 1 (os-sales, claim 6486380261, Premise: inbox) dispatches with the flag spelling on the order; needs-user-decision → pm:dispatched is that seat's stroke.

    Prior rulings read: object-reference-unknown, manifest.dependencies, artifactProvidedObjectNames, dependency closure → #16611, ADR-0141 D1; thread: 6411403302, 6486407414, 6486543157; repo: objectstack-ai/objectstack

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

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatneeds-user-decisionpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions