You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Unknown action param "selectedIds" — not declared on this action.
Did you mean the built-in "_selectedIds"? It is injected by an aggregate
bulk dispatch and read as ctx.params._selectedIds; it is never declared.
Triage: domain:spec → domain:spec-surface (seat #6298; existing-stock migration pass, maintainer-instructed 2026-08-07). Error guidance, in the seat's declared face: selectedIds is rejected before and after — the fix only adds the near-miss hint pointing at _selectedIds, so the accepted parameter set does not move.
Claim: PM loop round 2 (domain:spec-surface seat #6298)
Session: session_01JTSZAjgtL3oR6YcpNDhW3T
Branch: claude/issue-5622-param-near-miss-hint
Worktree: objectstack-issue-5622
Domain: domain:spec-surface
File surface: packages/spec/src/ui/action-params.zod.ts (message construction in validateActionParams only — the rejection verdict itself is untouched), its co-located test file, .changeset/*.md (stop on breach; explain in the report)
Serial constraints cleared: none — no in-flight PR or claim touches action-params.zod.ts (in-flight sweep #6243's file list checked; #4415 is flow-family). ACTION_PARAM_BUILTIN_KEYS verified present on origin/main.
Container weight: S, mode:subagent shared container.
Review: ACCEPT on substance — PR #6368 (landing gated on CI convergence)
Reviewed by the domain:spec-surface seat (#6298, session session_01JTSZAjgtL3oR6YcpNDhW3T) against the diff, not the report.
Scope — 3 files, all within the declared claim surface: .changeset/action-param-builtin-near-miss-hint.md (@objectstack/spec: patch), action-params.zod.ts (+71/−1), action-params.test.ts (+139). No content/docs/releases/ edits, nothing unrelated.
The verdict does not move, and it is pinned. The only production change is appending ${builtinNearMissHint(key, allow)} to the existing unknown_field message; the issues.push and its code are otherwise byte-identical. A dedicated case (moves the ACCEPTED SET by nothing) asserts selectedIds still rejects, _selectedIds still accepts, and ACTION_PARAM_BUILTIN_KEYS is unchanged. No second acceptance channel was opened.
The dev overrode the issue's proposed copy, on measurement, and was right to
The issue prescribed one hint sentence — "injected by an aggregate bulk dispatch". That is true of _selectedIds and false of the other two: recordId / objectName are merged in server-side by the dispatcher. The dev traced all three producers to file:line and made the origin sentence per-key.
The part worth recording is what that verification prevented: for recordId, a generic "send params.recordId" hint would have been actively wrong, because the dispatcher's params: { ...reqParams, recordId, objectName } spread overwrites whatever the caller put under that key — with undefined when neither route nor body carries a record id. A hint that confidently prescribes a broken call is worse than the terse message this card set out to improve; a card about fixing misleading copy would have shipped new misleading copy. Keys arriving via a custom builtinKeys override correctly fall back to a generic sentence that is true by that option's own definition.
Test discipline meets the clause it was dispatched under. Every case asserts codeand message content — never bare failure, which here is zero information since the key is refused on both sides of the fix. The negative case pins the untouched message byte for byte, and a six-variant case (selected_ids, selectedIDs, recordID, …) pins that the match is one leading underscore and not a similarity score. Reverse verification was predicted before it was run and landed exactly as predicted: stubbing builtinNearMissHint to '' turns 4 message cases red while every codes(...) assertion stays green.
Called out for the record: the honest companion labelling. The dev flags that "an ordinary unknown key keeps today's message" is a companion, not a pin of this change — green on both sides of the revert by construction — and then argues for keeping it anyway, because it is the one assertion in the file that would catch a future loosening into fuzzy matching. Correctly distinguishing a test that proves your change from a test that guards a different regression, and saying so in the diff rather than letting a green count imply coverage it does not have, is the standard this lane wants.
Checked independently: the key.replace(/^_/, '') candidate collapsing to key for a non-underscore key cannot produce a spurious self-hint — the loop only reaches this push for keys allow does not hold, so allow.has(key) is false there. The reasoning in the JSDoc is sound.
Landing
⛔ Not flipped to ready — ESLint and TypeScript Type Check are both in_progress, and those two jobs carry the check:* gate family. ACCEPT requires each to reach conclusion: success, not merely "no failure yet". Flip check is armed; ready + merge queue follow once both conclude green.
Landing order in this batch: #5622 (this, first) → #5767 → #5783 → #5955. This PR has no generated-artifact exposure, so it is not subject to the four-step resync.
Activity
os-zhuang commentedon Aug 5, 2026
发现分诊(#4949 纪律):晋级
pm:queue+domain:spec(摘finding)。一行理由:纯消息层的 near-miss 指路(判定逻辑与契约不变),已实际烧掉一次完整调查(#5568 的错误前提正是从这条无指路的拒绝消息长出来的),修法具体 —— 落点
packages/spec/src/ui/action-params.zod.ts的validateActionParams,对ACTION_PARAM_BUILTIN_KEYS做前导下划线双向比对即可。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
hotlong commentedon Aug 7, 2026
Triage:
domain:spec→domain:spec-surface(seat #6298; existing-stock migration pass, maintainer-instructed 2026-08-07). Error guidance, in the seat's declared face:selectedIdsis rejected before and after — the fix only adds the near-miss hint pointing at_selectedIds, so the accepted parameter set does not move.Generated by Claude Code
hotlong commentedon Aug 7, 2026
Claim: PM loop round 2 (
domain:spec-surfaceseat #6298)Session:
session_01JTSZAjgtL3oR6YcpNDhW3TBranch:
claude/issue-5622-param-near-miss-hintWorktree:
objectstack-issue-5622Domain:
domain:spec-surfaceFile surface:
packages/spec/src/ui/action-params.zod.ts(message construction invalidateActionParamsonly — the rejection verdict itself is untouched), its co-located test file,.changeset/*.md(stop on breach; explain in the report)Serial constraints cleared: none — no in-flight PR or claim touches
action-params.zod.ts(in-flight sweep #6243's file list checked; #4415 is flow-family).ACTION_PARAM_BUILTIN_KEYSverified present onorigin/main.Container weight: S,
mode:subagentshared container.Generated by Claude Code
hotlong commentedon Aug 7, 2026
Review: ACCEPT on substance — PR #6368 (landing gated on CI convergence)
Reviewed by the
domain:spec-surfaceseat (#6298, sessionsession_01JTSZAjgtL3oR6YcpNDhW3T) against the diff, not the report.Scope — 3 files, all within the declared claim surface:
.changeset/action-param-builtin-near-miss-hint.md(@objectstack/spec: patch),action-params.zod.ts(+71/−1),action-params.test.ts(+139). Nocontent/docs/releases/edits, nothing unrelated.The verdict does not move, and it is pinned. The only production change is appending
${builtinNearMissHint(key, allow)}to the existingunknown_fieldmessage; theissues.pushand itscodeare otherwise byte-identical. A dedicated case (moves the ACCEPTED SET by nothing) assertsselectedIdsstill rejects,_selectedIdsstill accepts, andACTION_PARAM_BUILTIN_KEYSis unchanged. No second acceptance channel was opened.The dev overrode the issue's proposed copy, on measurement, and was right to
The issue prescribed one hint sentence — "injected by an aggregate bulk dispatch". That is true of
_selectedIdsand false of the other two:recordId/objectNameare merged in server-side by the dispatcher. The dev traced all three producers to file:line and made the origin sentence per-key.The part worth recording is what that verification prevented: for
recordId, a generic "sendparams.recordId" hint would have been actively wrong, because the dispatcher'sparams: { ...reqParams, recordId, objectName }spread overwrites whatever the caller put under that key — withundefinedwhen neither route nor body carries a record id. A hint that confidently prescribes a broken call is worse than the terse message this card set out to improve; a card about fixing misleading copy would have shipped new misleading copy. Keys arriving via a custombuiltinKeysoverride correctly fall back to a generic sentence that is true by that option's own definition.Test discipline meets the clause it was dispatched under. Every case asserts
codeand message content — never bare failure, which here is zero information since the key is refused on both sides of the fix. The negative case pins the untouched message byte for byte, and a six-variant case (selected_ids,selectedIDs,recordID, …) pins that the match is one leading underscore and not a similarity score. Reverse verification was predicted before it was run and landed exactly as predicted: stubbingbuiltinNearMissHintto''turns 4 message cases red while everycodes(...)assertion stays green.Called out for the record: the honest companion labelling. The dev flags that "an ordinary unknown key keeps today's message" is a companion, not a pin of this change — green on both sides of the revert by construction — and then argues for keeping it anyway, because it is the one assertion in the file that would catch a future loosening into fuzzy matching. Correctly distinguishing a test that proves your change from a test that guards a different regression, and saying so in the diff rather than letting a green count imply coverage it does not have, is the standard this lane wants.
Checked independently: the
key.replace(/^_/, '')candidate collapsing tokeyfor a non-underscore key cannot produce a spurious self-hint — the loop only reaches this push for keysallowdoes not hold, soallow.has(key)is false there. The reasoning in the JSDoc is sound.Landing
⛔ Not flipped to ready —
ESLintandTypeScript Type Checkare bothin_progress, and those two jobs carry thecheck:*gate family. ACCEPT requires each to reachconclusion: success, not merely "no failure yet". Flip check is armed; ready + merge queue follow once both conclude green.Landing order in this batch: #5622 (this, first) → #5767 → #5783 → #5955. This PR has no generated-artifact exposure, so it is not subject to the four-step resync.
Generated by Claude Code
fix(spec): 参数门拒绝「差一个下划线」的内建键时指出那个内建键 (objectstack-ai#5622) (objectsta…