Skip to content

metadata-protocol: judgesPackageLessRows is typed as a predicate, and a stored package-less action row answers 200 before hydration but 409 after #32716

Open

Description

@objectstack-fleet

domain:server#5 · os-bill · session_01Utp6CX9R5BLZwgJDeivmA7

Follow-up of #32407 (PR #32566), from its contract review (PR #32566 comment 6815792757, nits N1 and N3). Filed as a follow-up card under the maintainer's rule of 2026-11-12 09:41Z: simple review findings get their own card, not another PR round. Both predate or sit beside #32566 and do not block it.

Blocked-by: #32407

维护者速读

  • 改什么:两处小问题。① judgesPackageLessRows 的返回类型写成类型谓词,但它的 false 取决于注册表而不只是类型,应改成普通 boolean。② 一条存储的包外 action 行,在被载入注册表前按包精确读答 200(服务持有者自己的),载入后答 409;同一行的答案取决于是否已载入。
  • 为什么:① 调用方按谓词收窄会把 false 分支错收成 never(树里暂无这样的调用)。② 读答案不该随加载时机变化(ADR-0150 D4)。
  • 风险:① 纯类型签名,无运行时变化。② 第一方 0 处;修法会动一个读答案,需 FROM → TO。
  • 先看:packages/metadata-protocol/src/protocol-exact-qualifier.ts 的 judgesPackageLessRows;getItem 先答裸槽、isStoredFlowEntryOfShippedName 只管 flow。
  • 验证:② 同一包外 action 行,载入前后按包精确读答案一致,并有 pin。
  • 需要你做的:无,p2。

Do

  1. N1: return boolean from judgesPackageLessRows instead of the predicate type is PackageScopedType; check every caller still typechecks.
  2. N3: measure on main after fix(metadata-protocol, cli)!: a package-less item of a name two packages hold is refused at both exact addresses for every narrowed type, and the layered read judges its exact address (ADR-0150 D4) #32566 lands: a stored package-less action row of a name a package ships, read at the holder's exact address before and after it is hydrated into the registry's bare slot (boot or a list read). If the answers differ, make them the same (ADR-0150 D4 decides which; if it is not clear, file needs_decision), declare the moved answer FROM → TO with its Clause-② arm, and pin both states.

Clause-②: N1 none; N3 the claimer declares it after measuring.
Business reason: one stored row must answer one way, whatever the load order.
Suggested-grade: p2 · first-party reach 0.

Activity

  1. objectstack-fleet commented on Nov 12, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH

    Path: none

    Triage: first touch (requested by domain:server#5) → domain:server · p2 · pm:blocked · 2026-11-12T11:44Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. added
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    domain:serverDomain lane — seat card indexed by label:pm:seat
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Nov 12, 2026
  3. objectstack-fleet commented on Nov 12, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH

    Path: none

    Triage: unblocked → pm:queue · 2026-11-12T12:49Z

    ⛔ Not a claim.


    Generated by Claude Code

  4. added
    pm:queueReady for the PM dispatch loop
    and removed
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Nov 12, 2026
  5. objectstack-fleet commented on Nov 12, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#7 · os-sales · session_01L6bhgVSjQBHNkZd6Eqx2XX

    Parked · #32716 · 2026-11-12T13:35Z — on the maintainer's release-line ruling 6824949405 on #31527 (Sales tapped 「三招都用(推荐)」 on the epic seat's card 「专题怎么提速?」, 2026-11-12T13:28:14Z): every p2 card of epic #31527 without an open PR, and every nested follow-up card, waits until the release ships.

    • State: pm:queue → pm:on-hold in this stroke. Nothing is deleted.

    Restart-when: the release that carries the epic #31527 release line is published (ruling 6824949405 on #31527)

  6. added
    pm:on-holdDecision made, deliberately deferred — no dispatch, no nag; restart condition in the hold comment
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 12, 2026
  7. objectstack-fleet commented on Nov 12, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#31527#1 · os-sales · session_01L6bhgXQnNkXTT1Wu7i7Y3i

    Re-graded and queued · #32716 · 2026-11-12T22:31Z. It is a small issue (a nit, docs or typing), so it is graded priority:p3 and goes to pm:queue. The maintainer (Sales) ruled that no epic card is parked: small issues are graded priority:p3 and queued behind p1 and p2, and p1 goes first. The park under 6824949405 is withdrawn for this card.


    Generated by Claude Code

  8. added
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:on-holdDecision made, deliberately deferred — no dispatch, no nag; restart condition in the hold comment
    pm:queueReady for the PM dispatch loop
    on Nov 12, 2026
  9. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-elon-musk · session_016WV4cz4f7zEQZ2C9GTG382
    Claim: area-lease pilot #33059, area E2b · 2026-11-14T21:45Z
    Branch: claude/area-E2b-32716
    Account: os-elon-musk

  10. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-elon-musk · session_016WV4cz4f7zEQZ2C9GTG382
    os-dev-report

    {
      "issue": 32716,
      "status": "done",
      "branch": "claude/area-E2b-32716",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/33483",
      "head_sha": "4bb529d89e4bc071c81e6f6f68a63a1562490ed5",
      "changed_lines": "+42 -8 across 4 files (protocol-exact-qualifier.ts +9 -3, protocol-exact-qualifier.test.ts +13 -1, objectql package-scoped-exact-qualifier.test.ts +8 -4, one new changeset +12)",
      "session": "session_016WV4cz4f7zEQZ2C9GTG382",
      "premise_still_valid": false,
      "summary": "N1 holds and is fixed: judgesPackageLessRows now returns boolean, not the predicate `type is PackageScopedType`. One caller had relied on the predicate's narrowing (packageLessRowOwners -> isPlatformRequestedBareName); it now narrows through core's isPackageScopedType. The CLI caller typechecks unchanged, and a tsc-checked pin keeps `hook` typed in the false branch. N3's premise (200 before hydration, 409 after) does not hold on main. A stored package-less action row of a shipped name, read at the holder's exact address, answers the holder's own item (200) before and after every hydration path: boot load (loadMetaFromDb), list read (getMetaItems), and a bare-slot copy stamped '' or 'sys_metadata'. That holds for one holder and two, in both registration orders, and the layered read reports no overlay. The behaviour came in with the change under epic ruling 6817768147 on #32568: the hydrator declines the row and declinedCopyReplaced replaces a copy. Per the order ('same => pin both and say so'), nothing in N3 is implemented. The boot load joins the existing location-4 hydration-state pins (action, queue and tool; one and two holders), and the list read and bare copies were already pinned there.",
      "n3_measurement": "main ba35dfd78 (with only the type-only N1 edit on top), throwaway describe in objectql package-scoped-exact-qualifier.test.ts, not committed. Row: package-less action 'approve', stored active. One holder A: ?package=A is 200 own before and after the boot load, the list read and the bare copies; ?package=B is 409 not-held both sides; the layered read shows no overlay. Two holders, registered A then B and B then A: ?package=A and ?package=B are each 200 own before and after every path. The boot load returned {loaded:1, errors:0}, and the holder's slot kept its own item. Booting before the packages registered, then shipping them, also gave 200 own at each holder. Verdict: same answers, so ADR-0150 D4 has nothing to decide and needs_decision is empty.",
      "tests": "Run on head 4bb529d89 under os-verify-lock. metadata-protocol: typecheck exit 0; test gave Test Files 340 passed, 9 skipped (349) and Tests 22866 passed, 43 skipped (VERDICT command-exit 0). objectql src/package-scoped-exact-qualifier.test.ts: Tests 294 passed (294), which is 288 before plus 6 new boot-load cases. cli typecheck exit 0, with check:test-typecheck OK, after building its closure. Ablation N1: ablation-replace swapped the return `boolean` for the predicate. The anchor went x1 to x0 and the blob changed. Typecheck went RED with one error, protocol-exact-qualifier.test.ts(98,42) TS2344 'Actual: never'. The file was restored to blob == HEAD with an empty git diff HEAD. Ablation N3 boot-load pin: the hydrator's decline branch in protocol-registry-hydration.ts went behind an always-false guard, and dist-preflight showed the marker present. Location 4 went RED with 6 failed, including 'after the boot load exact: expected stored to be alpha action' for action, queue and tool. After the restore and a rebuild, dist-preflight --absent passed and the file was back to 294 passed.",
      "gates": "dispatch-gates --commands (tree 4bb529d89, --repo objectstack-ai/objectstack) gave 64 commands, each with its exit captured before any pipe. 63 exited 0. One exited 3: pnpm check:dual-build-cjs-loads, PREREQUISITE NOT MET because the whole repo was not built (NOT MEASURED, CI's). --ran reconciliation with exit codes: 64 derived, 63 run, 1 NOT-MEASURED, 0 UNRUN. eslint --no-inline-config on the 3 changed .ts files: exit 0. PR check-runs on 4bb529d89 at report time: 18 in_progress, 5 skipped, 0 failed (in_progress; not waited on).",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "3 relay strokes: POST /repos/objectstack-ai/objectstack/issues/32716/comments (claim, comment 6884674513); pr_create = POST /repos/objectstack-ai/objectstack/pulls (#33483, draft) + POST /repos/objectstack-ai/objectstack/issues/33483/assignees (os-elon-musk); POST /repos/objectstack-ai/objectstack/issues/32716/comments (os-dev-report). Plus 2 git pushes (empty branch, then 4bb529d89).",
      "needs_decision": [],
      "open_questions": [
        {
          "question": "Clause-② for N1: the published .d.ts return type of judgesPackageLessRows moves from the predicate `type is PackageScopedType` to `boolean`. The card said 'N1 none'; this PR declares `Clause-②: no`. Does the seat read it otherwise?",
          "options": [
            "A: keep `Clause-②: no`. No accept set widens and no surface is added, the runtime answer is unchanged, and no first-party consumer narrows through the predicate. Cost: none.",
            "B: `Clause-②: yes`, on the mechanical reading that any signature change of a published export counts. Cost: a one-line PR-body and changeset edit by the seat, with the level still patch."
          ],
          "recommendation": "A, because the change takes away a wrong type claim and moves no accept set. The changeset names isPackageScopedType as the narrowing to use instead."
        }
      ],
      "deviations": [
        "Commit trailers are model-free (Co-Authored-By: Claude) as the order and AGENTS.md require; the harness reminder offered a model-named Co-Authored-By, which the pre-push hook refuses. Reported, not a change of history.",
        "The PR body ends with the order's footer line, and the session URL is in body prose just above it; AGENTS.md's session-URL footer form was not used, because the order named the closing line.",
        "The harness's own worktree (.claude/worktrees/agent-ad2ca196efe81fb92) was used instead of a ../objectstack-issue-N worktree, because agent isolation requires cwd inside /home/user/objectstack. I did not remove that worktree because the harness owns it."
      ],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: none · noted in the PR's Acceptance notes, not filed. In the objectql harness, the bare read naming no package with a hand-registered bare-slot copy of a sealed action answers the copy (one holder) or 409 '3 holders' (two holders), while every exact read answers the holder's own item. Nothing on main produces that copy any more (the hydrator declines the row), and the heal walk that removes a pre-install copy was not modelled. reach: none measured through a public door. dedupe words: bare read, bare-slot copy, sealed action, declinedCopyReplaced, 3 holders"
      ]
    }
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, iteratedomain:serverDomain lane — seat card indexed by label:pm:seatlease:E2bpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions