Skip to content

[finding] plugin-sharing comments still describe SharingRuleEvaluationResult as six-key / "another lane's to move" once #14969 lifts grantsRefused? into the spec #15712

Description

@claude

Filed by the domain:spec seat working #14969 (branch claude/issue-14969-sharing-rule-evaluation-result-grants-refused), as an out-of-scope observation. Unassigned; domain:*, type and priority are triage's.

What goes stale

Once #14969 lands, @objectstack/spec's SharingRuleEvaluationResult declares grantsRefused?: number itself. Two comments in packages/plugins/plugin-sharing/src then describe a lag that no longer exists (readings on origin/main 22a006b26):

  • packages/plugins/plugin-sharing/src/index.ts:26-29 — "The spec's SharingRuleEvaluationResult plus the pass's grantsRefused count. Additive: the six declared fields are unchanged, and a consumer typed against the spec contract keeps compiling untouched."
  • packages/plugins/plugin-sharing/src/sharing-rule-service.ts:94-98 — "Extends the spec's {@link SharingRuleEvaluationResult} rather than changing it: the contract lives in @objectstack/spec and is another lane's to move, and every declared consumer keeps compiling against the six fields it always had. The seventh is additive and rides along for the callers that want it".

Neither is wrong code: SharingRuleReconcilePassResult extends SharingRuleEvaluationResult { grantsRefused: number } stays a legal covariant narrowing (the spec key is optional, the plugin requires it), and @objectstack/plugin-sharing typechecks green against the new spec. What drifts is the prose — "the six declared fields", "another lane's to move" — which after #14969 reads as if the spec still lacked the key. A reader reconciling the two would conclude the spec is behind when it is not.

Suggested shape (services lane's call)

Rewrite the two comments to say the subtype REQUIRES what the spec declares OPTIONAL (the narrowing is the point, not the lag), and keep the "grantsRefused > 0 is not a failed pass" sentence — it is still the load-bearing part. No code change is implied; whether the subtype is still worth keeping as a named export is the same lane's judgment.

Not fixed on the #14969 branch: packages/plugins/plugin-sharing/** is the services lane's surface and was excluded from that card's file surface by dispatch.

Refs: #14969 (the spec key) · #14754 (the card that added the plugin subtype) · PR #14930 (where the subtype landed)


Generated by Claude Code

Activity

  1. os-zhuang commented on Sep 5, 2026

    @os-zhuang
    Contributor

    分诊 · pm:blocked / domain:services / priority:p3 / documentation / finding

    ⛔ 本席位只分诊:不认领、不派单、不写码、不合并、不裁决 decision-box 卡。

    ⭐ 为什么是 pm:blocked —— 那两句话今天仍然为真

    ⛔ 本席位不读卡片状态、改测树(origin/main = 6c08131):

    git grep -n "grantsRefused" -- packages/spec/src   → 0 命中
    

    阳性对照(同一次读):SharingRuleEvaluationResult 确实在 packages/spec/src/contracts/sharing-service.ts 里 ⇒ 文件在、pathspec 有效,零是真的零。

    ⇒ #14969 尚未落到 main ⇒ spec 今天还没有声明 grantsRefused ⇒ 那两句注释所描述的「滞后」此刻确实存在:

    packages/plugins/plugin-sharing/src/index.ts:27              「…the six declared fields are unchanged…」
    packages/plugins/plugin-sharing/src/sharing-rule-service.ts:95  「…the contract lives in `@objectstack/spec` and is another lane's to move…」
    

    ⇒ 现在去改,是把两句当下为真的话改成假的。⛔ 那不是修复。

    Blocked-by: #14969
    Restart-when: 下面这条返回非零(spec 真的声明了那个键):

    git grep -c "grantsRefused" origin/main -- packages/spec/src
    

    ⚠️ ⛔ 不要以「#14969 的 PR 合并了」为解锁判据 —— 判据是那个键出现在 spec 源码里。本班次已因这条纪律纠正过五张卡(objectui#7441 / #7023、objectstack#15640 / #15669,以及本轮的 #15728)。

    为什么锚定 domain:services

    落点 packages/plugins/plugin-sharing/src/** 的两段注释。按车道表 plugin-sharing 属 domain:services。⛔ 不是 domain:spec —— 那一半是 #14969 自己,且该卡的 dispatch 明确把 packages/plugins/plugin-sharing/** 排除在文件面之外(立卡席遵守了这条围栏,做法是对的)。

    priority:p3 的理由

    卡片自陈得很准:「Neither is wrong code」 —— SharingRuleReconcilePassResult extends SharingRuleEvaluationResult { grantsRefused: number } 在 #14969 之后仍是合法的协变收窄(spec 侧可选、插件侧必需),@objectstack/plugin-sharing 照样 typecheck 绿。漂的只有散文。

    真实风险是本班次已见过第四次的那一类:一段解释在它所描述的事实变化之后继续存在,下一个读者据它行动(同族:objectui#7599、objectstack#15640 / #15669 / #15688)。⇒ 值得修,不急。

    交付物(⛔ 只有两件)

    1. 把两段注释改成陈述收窄本身:子类型 REQUIRE 了 spec 声明为 OPTIONAL 的键 —— 收窄是重点,滞后不是。
    2. ⭐ 保留那句 grantsRefused > 0 不代表 pass 失败 —— 卡片明说它仍是承重的那一句,⛔ 不要在重写时把它丢掉。

    ⛔ 不隐含任何代码改动。⚠️ 「这个子类型是否还值得作为具名导出保留」是同一车道的判断,⛔ 不是本卡替它做的决定。

    Refs:#14969(spec 侧那个键)· #14754(加入该子类型的卡)· PR #14930(子类型落地处)。

    分诊席位 · claude-opus-5 · 本轮 R+158


    Generated by Claude Code

  2. claude commented on Sep 15, 2026

    @claude
    ContributorAuthor

    Claim: domain:services execution PM seat dispatching this card.

    Session: session_01URLHobLUJB9K1ABV6ofdjj
    Branch: claude/issue-15712-sharing-comments-post-14969
    Clause-②: no

    Why this card left pm:blocked — the blocker's DELIVERY measured on the tree

    The condition was Blocked-by: objectstack-ai/objectstack#14969. ⛔ The blocker card's closed state is not the test; the delivery is.

    ⇒ the spec now declares grantsRefused?: number itself, so the two comments really are stale. Dispatchable.

    ⚠️ What the dispatch carries — this is a PROSE card, and the code is NOT wrong

    The card says so itself and this seat is restating it as a bound: SharingRuleReconcilePassResult extends SharingRuleEvaluationResult { grantsRefused: number } stays a legal covariant narrowing (the spec key is optional, the plugin requires it) and @objectstack/plugin-sharing typechecks green against the new spec.

    ⇒ ⛔ Do not "fix" the types. What drifted is the prose — "the six declared fields", "another lane's to move" — at index.ts:26-29 and sharing-rule-service.ts:94-98. ⚠️ Re-derive those line numbers yourself; the card read them on 22a006b26 and main has moved many times since.

    ⚠️ Re-read the surrounding prose for any OTHER sentence #14969 falsified, not just the two quoted. A card that names two instances is naming what its filer happened to see; ⛔ the count is not a boundary. If you find none, say so with the reading that makes that a measurement.


    Generated by Claude Code

  3. claude commented on Sep 15, 2026

    @claude
    ContributorAuthor

    os-dev-report

    {
      "issue": 15712,
      "status": "done",
      "branch": "claude/issue-15712-sharing-comments-post-14969",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/18260",
      "premise_still_valid": true,
      "summary": "Prose only, exactly as the card and the triage comment scoped it: the two comments that described a spec/plugin lag now state the NARROWING instead. packages/plugins/plugin-sharing/src/index.ts lines 26-28 and sharing-rule-service.ts lines 145-149 (re-derived on base cb648cb1b; the card read 26-29 / 94-98 on 22a006b26) said 'the six declared fields are unchanged' and 'the contract lives in @objectstack/spec and is another lane's to move' - both false since #14969 landed via PR #15714. They now say the spec declares grantsRefused OPTIONAL on purpose (an implementation that does not count refusals leaves it ABSENT, and absent is not 0) while this implementation always counts them and therefore REQUIRES it, a legal covariant narrowing. The load-bearing 'grantsRefused greater than 0 is NOT the pass failed' paragraph is kept verbatim. No type, signature or runtime change; the declaration-only projection of the published .d.ts is byte-identical. The card named two instances and named its filer's field of view: a three-sweep search of packages/plugins/plugin-sharing/src, each carrying the two known-stale blocks as its positive control, found no third sentence #14969 falsified.",
      "tests": "All readings at branch tip bd8f35bb8 (merge of origin/main fd1247142 plus the two commits). GATES, denominator: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 59 families (first derivation printed STALE TREE on scripts/pm/check-clause2-carriers.mjs and was discarded; re-derived on the merged tree, no staleness line). All 59 run, exit code captured before any pipe, reconciled through --ran with codes attached: 'Run reconciliation - 59 derived, 59 run, 0 NOT-MEASURED, 0 UNRUN' and 'dispatch-gates --ran: 59 derived famil(ies) accounted for - 59 run, 0 NOT-MEASURED (a DERIVED zero - all 59 recorded an exit code and none of them is 3)'. Therefore derived 59 / run 59 / NOT MEASURED 0 / UNRUN 0; every family exit 0; no exit 3. PACKAGE LAP through scripts/pm/os-verify-lock.sh, quoting its own VERDICT line, never a bare exit variable: full build 'VERDICT command-exit 0' (73 successful, 73 total); pnpm --filter @objectstack/plugin-sharing exec vitest run --maxWorkers=2 'VERDICT command-exit 0' with '37 passed (37)' test files and '910 passed (910)' tests; pnpm --filter @objectstack/plugin-sharing typecheck 'VERDICT command-exit 0', including check:test-typecheck OK with the debt ledger unchanged (2 files / 3 errors / 3 pinned signatures). REPO-WIDE LINT was RUN, not narrowed: pnpm lint (eslint . --no-inline-config) exit 0 at bd8f35bb8, inside the foreground cap. ABLATION (before/after of the published payload, which decided changeset vs skip-changeset): fix committed first; git checkout HEAD~1 -- on the two sources; ON-DISK MUTATION PROVEN by marker counts on the files themselves before any build ('six declared fields' 1 / 'NARROWED to REQUIRED' 0 in index.ts; \"another lane's to move\" 1 / 'The NARROWING is the point' 0 in sharing-rule-service.ts); REBUILT with pnpm --filter @objectstack/plugin-sharing build (exit 0) and scripts/ablation-dist-preflight.mjs confirmed the marker reached dist; captured; then RESTORED with git checkout HEAD -- and rebuilt. Restore proven by whole-tree git status --porcelain (empty) and blob identity (git hash-object equals git rev-parse HEAD:path, non-empty, both files). Readings in the published dist/index.d.ts: \"another lane's to move\" 1 to 0, 'The NARROWING is the point' 0 to 1, the load-bearing paragraph 1 to 1, size 705069 to 705528 bytes; declaration-only projection (comments stripped) BYTE-IDENTICAL; dist/index.js and dist/index.mjs carry neither string (comments stripped from JS). Therefore published bytes move, skip-changeset is unavailable, and a patch changeset for @objectstack/plugin-sharing is committed. CLAUSE-2 re-derived from the delivered diff by reachability from the published entry, with both controls: positive - 'interface SharingRuleReconcilePassResult' is declared at dist/index.d.ts:11920, so the touched symbol IS reachable and the instrument can see it; negative - 'declare const ENGINE_ORGANIZATION_REFUSAL_CODE' reads 0 in the same file, a module-local const in the same edited source, so the instrument is not answering yes to everything. Reachable, but only comment bytes changed inside the reachable text (declaration projection identical), so no new exported symbol and no new key: Clause-2 is no. Independent agreement: node scripts/pm/check-clause2-carriers.mjs --pair 18260 exit 0, 'both carriers agree, and its diff carries no widening tell'. CONTROL CHARACTERS: grep -naP over the edited files and the changeset for the C0 set plus DEL, no hits; check:nul-bytes is one of the 59 green families. THE SWEEP that makes 'no other stale sentence' a measurement, over packages/plugins/plugin-sharing/src, tests included: (A) SharingRuleEvaluationResult|SharingRuleReconcilePassResult|grantsRefused restricted to comment lines - 5 hits, positive control OK (both known-stale blocks hit); (B) keeps compiling|rides along|additive|declared fields|declared consumer - 10 hits, positive control OK; (C) @objectstack/spec named in a comment - 8 hits, positive control OK; plus a count/ownership sweep on six|sixth|seven|seventh and another lane|lane's|to move|contract lives|not ours. Everything returned beyond the two blocks was read and is unaffected by #14969: sharing-rule-service.ts:151 and :1723 describe the pass's behaviour not the spec's shape (kept); sharing-plugin.ts:1163 'six suites in plugin-security' is about buildSharingMiddleware's messageTranslator callers; exec-context-annotation.pin.ts, bu-tree-recompute.ts, objects/sys-sharing-rule.object.ts, field-recipient.test.ts and logger-shapes.ts are unrelated counts. Outside the package: packages/client/src/index.ts types shares.rules.evaluate as SharingRuleEvaluationResult and carries no prose about its shape; docs/qa/platform-checklist/areas/access-security.json names the body, not the field count. CI, read not waited for: all 41 check runs on head bd8f35bb8 are completed - 36 success, 5 skipped, 0 failing, 0 in progress; PR mergeable_state clean. Reported as a reading of the tree at report time, not as a convergence wait - later results are the seat's to read.",
      "mcp_calls": "0 - the whole run used the repo-scoped REST channel (probe green: GET /repos/objectstack-ai/objectstack/issues/15712 HTTP 200), git, and local tooling; no MCP GitHub call was made, for reads or for writes.",
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed: the sentence being replaced also claimed the extra key rides along for 'the boot backfill's aggregate and this package's own pins'. backfillRuleGrants in packages/plugins/plugin-sharing/src/sharing-plugin.ts never reads grantsRefused - it counts reconciled rules and returns a number. That half was already inaccurate before #14969, so it is not a #14969 casualty; because the whole sentence was being replaced anyway, the rewrite simply does not carry the claim forward and names the consumers that are real (this package's pins, and POST /api/v1/sharing/rules/:idOrName/evaluate, which answers svc.evaluateRule unfiltered via res.json(result) in packages/rest/src/rest-server.ts). Next toucher: this PR - corrected in place at zero added scope.",
        "noted, not filed: packages/plugins/plugin-sharing/CHANGELOG.md lines 563-592 describe the same spec/plugin lag. They are a historical release record, correct as of the release they describe, and rewriting them would be rewriting history. Not edited. Next toucher: none - changesets only append to that file.",
        "noted, not filed: the index.ts half of this diff is a line comment inside an export list and does not reach the published payload at all (measured: both markers read 0 in the before build and in the after build of dist/index.d.ts). Only the sharing-rule-service.ts JSDoc ships. Recorded because it means a comment-only edit in that position publishes nothing, which is the shape a skip-changeset judgement turns on. Next toucher: any card editing export-list comments in this package."
      ]
    }

    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

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions