Skip to content

composeStacks connector check: say why a top-level connector beside package bodies is refused as ambiguous, and pin the preserve reading of a mixed nested input #28006

Closed

Description

@objectstack-fleet

epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
Filing gate: ① should-fix 1 of the contract review of PR #27939 (record 6516406275, VERDICT PASS), not taken into that PR.
Ruling-ref: none (wording and a test; no accept-set change)
Dedupe (open AND closed): "providedCollectionEntries artifact slot package bodies ambiguous connector" → none this work.
Reader: the epic PM (#27261) dispatches it in the epic subtree.
type: Task

维护者速读

  • 做什么: fix(spec)!: composeStacks refuses a datasource whose external.connector names no connector instance the composed inputs declare #27939 让 composeStacks 在合成时检查数据源借用的连接器。有一种情形:last 产物顶层的连接器和某个包体里的连接器同名。检查的拒收结论是对的,但给出的理由不对。错误信息、slot 文档和测试名都说「运行时每个包保留一条,先注册的那条出借」。实际上,开机时包体已占用的名字,顶层那条会被丢弃;开发态重载时,顶层那条会替换包体那条。这张卡把理由写对,并补一个 preserve 下混合嵌套输入的测试。
  • 为什么: 结论正确但理由错误,会误导作者判断该改哪一条声明。
  • 需要您做的: 无(只改注释、提示文字和测试,不改接受集)。

Task

  • Make the 'artifact' slot's stated mechanism true where a last artifact's top level sits beside package bodies. At boot, unclaimedTopLevel (metadata/plugin.ts) drops a top-level entry whose name a body claims. On a dev reload, mergeDeclaredConnectorSources replaces the body's entry with the top-level one. Do one of two things: word the ambiguity sentence for that case, or state the mechanism once in ProvidedCollectionEntry.slot's doc and in providedCollectionEntries' docblock (packages/spec/src/stack.zod.ts).
  • Rename the test "treats a package body and another input's top level as two slots" so it asserts the refusal, not "two slots".
  • Pin the preserve reading of a mixed nested input: a nested input that carries packages and its own un-reproduced top level gets slot package:${ownId}, while the residual rule registers that top level under the composed artifact's manifest.id (the last input's).
  • The verdict does not change in either direction. If the fix would change one, stop and report to the epic PM.

Clause-②: no expected (message text, docs and tests only) · Metadata-protocol: none. Touches packages/spec/src/**, so a contract review is owed before landing.

Activity

  1. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
    Claim: PM loop round 16 2026-10-30T07:44Z
    Session: session_017ihL2c5z3q4h8inrn5kwqV (epic PM); implementing card thread session_017ihL2cLiZUHvCtV2YGRWAd (it carried #27803 / PR #27939)
    Account: marchtian
    Branch: claude/project-thread-683cod (the card thread's platform-assigned branch, restarted from origin/main after #27939 merged — measured platform exception to claude/issue-<n>-<slug>)
    Worktree: objectstack-issue-28006
    Domain: domain:spec
    Seat: epic:#27261#1 (epic PM; no domain:* seat). Filing gate ① (record 6516406275 should-fix 1)
    File surface: packages/spec/src/stack.zod.ts (the composed connector check's ambiguity sentence, ProvidedCollectionEntry.slot's doc and providedCollectionEntries' docblock), packages/spec/src/stack-datasource-connector.test.ts, .changeset/** (stop on breach; a change to either verdict direction stops and reports to the epic PM)
    Container & model: S, mode:thread, model: default tier (Fable unavailable; 田騏's order of 2026-10-29 19:39Z), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: should-fix 1 of record 6516406275 on #27803 (PR #27939, 6da8c3ccf4)
    Thread-read: none
    Premise: holds — on origin/main (6da8c3ccf4+) the ambiguity refusal for a last artifact's top-level connector beside a package body's same-named entry says the runtime keeps one entry per package; at boot unclaimedTopLevel drops the top-level twin and a dev reload replaces the body's with it. No preserve test of a mixed nested input.
    Serial constraints: none in flight on stack.zod.ts. packages/spec/src/** edit: lands after a CONTRACT_REVIEW_TIER record PASS on the head.

  2. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27261#1 · marchtian · session_017ihL2cLiZUHvCtV2YGRWAd
    os-dev-report

    {
     "issue": 28006,
     "status": "done",
     "branch": "claude/project-thread-683cod",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/28026",
     "head": "55b0c85641",
     "session": "session_017ihL2cLiZUHvCtV2YGRWAd",
     "premise_still_valid": true,
     "summary": "stack.zod.ts: ProvidedCollectionEntry gains a module-private inBody flag (a package body's own item, or a preserve input's top level folded into its own body). Its doc, the slot doc and providedCollectionEntries' docblock state the beside-bodies mechanism: the boot does not register a top-level entry whose name a body declares (unclaimedTopLevel), registers an unclaimed one under the composed manifest.id, and a dev reload replaces the booted entries with the artifact's top-level list (mergeDeclaredConnectorSources). The ambiguity finding picks its reason by where the kept entries sit: two bodies keep the old sentence byte for byte; a body and a top-level entry get the boot-drops / reload-replaces sentence; top-level entries only get their own sentence. The slot stays a stand-in: judging a mixed input's top level in the composed manifest.id slot would accept a case that is refused now. Test renamed; a preserve mixed-input group added. Changeset: spec patch, Clause-② no, ADR-0087 not-required (no-migration-prescription). PR is draft and says a full review at the reviewer tier is owed.",
     "tests": "stack-datasource-connector.test.ts: 28 tests (20 composed), all pass. Verdicts against origin/main's stack.zod.ts: 25 pass, 3 fail only on the new wording (envelope, status and one-finding assertions held). Ablation: mixed top level judged in the composed artifact's slot, both mixed preserve refusal cases red (mixed-first accepted), 26 green; restored 28/28. pnpm --filter @objectstack/spec build / test / typecheck under the lock: build exit 0; 756 files, 22501 tests passed (1 todo); typecheck passed (check:test-typecheck OK).",
     "gates": "dispatch-gates --commands after merging origin/main (e9caebeec): 80 families, all run, exit codes recorded before any pipe, all exit 0. --ran: 80 derived, 80 run, 0 NOT-MEASURED (a DERIVED zero). Tree clean after the run. Dogfood not run (Clause-② no, no verdict moves). os-verify-lock printed its holder-side starvation advisory for the one long run (build + 80 gates + spec test + typecheck in one hold); said here as it asks.",
     "mcp_calls": "github issue_read x2 (#28006 get, get_comments), subscribe_pr_activity x1; gh api read x1 (record 6516406275); no MCP write tool",
     "api_writes": "2: relay pr_create (run 41028448013, PR #28026, 7758 bytes read back identical, no assignees); relay comment on #28006 (this report). git push is not a REST write.",
     "surface_note": "Inside the Claim's file surface: stack.zod.ts, stack-datasource-connector.test.ts, one changeset. The branch was restarted from origin/main; the remote branch had been deleted by the queue, so the push was a new-branch push, not a force.",
     "open_questions": [],
     "out_of_scope_findings": [
      "carrier: none · not measured: the boot registers a residual top-level connector only into the metadata service (objectql registers a residual's objects only), while the lender reads the ObjectQL registry at boot. So a connector a nested or mixed input declares only at its top level, beside package bodies, may not reach the lender at boot. The composed check accepts a borrow of it today. Unverified; worth a measurement before anything is filed."
     ]
    }
  3. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
    Landed · 2026-10-30T11:05Z

    PR #28026 merged through the queue as f3fe6602f3 at 2026-10-30T11:04:47Z (head 541d7f5b).

    Reviews: contract review PASS 6519281283 at CONTRACT_REVIEW_TIER on 55b0c856, with two should-fixes taken. A clean delta review, PASS 6520726439, followed on the landed head. Under the 2026-10-29 19:39Z order these also served as the full review of the spec change. The seat ACCEPT followed.

    The composed connector check's ambiguity refusal now states its mechanism by where the kept entries sit:

    • two package bodies;
    • a package body beside a top-level entry: the boot keeps the body's, a reload takes the first top-level entry;
    • top-level entries only.

    No verdict moved. The record's escalation is #28032 (PR #28046).

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