Repository navigation
docs(skills,spec): the fieldPatches example patches options only on a field that declares them, so HotCRM accepts it - #30995
Conversation
…ld that declares them HotCRM's crm_account.industry takes its options from the shared industry picklist, so the taught example's options patch was refused at install and by os validate (picklist-option). The skill, the spec description and TSDoc, and the object-extensions docs page now relabel industry only and patch an option of type, which declares its own options. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8VVAmsHMwmra6cg78RoEp
…tion Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8VVAmsHMwmra6cg78RoEp
…atement The .custom paragraph's closing clause restated the relabel paragraph's lead (a base field changes only through fieldPatches), so it goes, and the example's longer options patch fits under the unchanged token ceiling. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8VVAmsHMwmra6cg78RoEp
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 170 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin c5a988aca3958c9f1486f80b922e4d8565fd491b && git checkout c5a988aca3958c9f1486f80b922e4d8565fd491b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 8ae0ab9b0d77d56473e89dae9fe437778172dda8 5a6e8fad3087ae745d71794bc9bc28db0b3153bb && git checkout -B drift-repro 8ae0ab9b0d77d56473e89dae9fe437778172dda8 && git merge --no-ff 5a6e8fad3087ae745d71794bc9bc28db0b3153bb
node scripts/docs-audit/affected-docs.mjs --json 8ae0ab9b0d77d56473e89dae9fe437778172dda8 |
|
domain:skills#3 · huangyiirene · session_01J8VVAj7CvjkGXvgXzd6RZ7 Contract-review-claim: session_01J8VVAj7CvjkGXvgXzd6RZ7 · head 22db7ae · 2026-11-06T16:07Z The seat review runs at CONTRACT_REVIEW_TIER in an isolated subagent. No review seat ( |
|
domain:skills#3 · huangyiirene · session_01J8VVAj7CvjkGXvgXzd6RZ7 Contract reviewServed-tier: Inputs read: card #30944 (body, the triage comment and the claim comment), PR #30995 (body, 6-file list, net diff against merge base ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
No must-fix. Both should-fixes are text-only and do not block this head. Implemented-by: VERDICT: PASS |
…im the changeset claim The ObjectExtensionSchema example extends `contact`, so the comment on why `industry` takes no option patch now names the case it holds for (a picklist-bound `industry`, as on HotCRM's crm_account). The skills changeset no longer says the skill text names `industry` as picklist-bound. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8VVAmsHMwmra6cg78RoEp
|
domain:skills#3 · huangyiirene · session_01J8VVAj7CvjkGXvgXzd6RZ7 Contract-review-claim: session_01J8VVAj7CvjkGXvgXzd6RZ7 · head 7c661de · 2026-11-06T16:37Z Delta review against the PASS at head 22db7ae (comment 6689532077). The delta is one commit answering S1 (skills changeset prose) and S2 (the TSDoc example comment), plus the PR body. The seat review runs at CONTRACT_REVIEW_TIER in an isolated subagent. |
|
domain:skills#3 · huangyiirene · session_01J8VVAj7CvjkGXvgXzd6RZ7 Contract reviewServed-tier: This is a delta review against the PASS recorded on ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
One must-fix (M1). S1 is resolved. S2 is resolved in scope, but its new wording is the must-fix. Implemented-by: VERDICT: FAIL |
…c comment The display keys of a picklist-bound field stay patchable; only its options are out of reach, as the description's own example (inlineHelpText) shows. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8VVAmsHMwmra6cg78RoEp
|
domain:skills#3 · huangyiirene · session_01J8VVAj7CvjkGXvgXzd6RZ7 Contract-review-claim: session_01J8VVAj7CvjkGXvgXzd6RZ7 · head 5a6e8fa · 2026-11-06T16:46Z Delta review against the FAIL at head 7c661de (comment on this PR, must-fix M1: the TSDoc example comment). The delta is one commit rewriting object.zod.ts L5133–5134, plus the PR body. The seat review runs at CONTRACT_REVIEW_TIER in an isolated subagent. |
|
domain:skills#3 · huangyiirene · session_01J8VVAj7CvjkGXvgXzd6RZ7 Contract reviewServed-tier: This is the second delta review. It is judged against the FAIL recorded on ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
No must-fix and no should-fix. M1 is closed, S1 and S2 stay closed, and nothing else moved. Implemented-by: VERDICT: PASS |
|
domain:skills#3 · huangyiirene · session_01J8VVAj7CvjkGXvgXzd6RZ7 维护者速读
席位核对 — ACCEPT · domain:skills#3 · head
|
Requested by Irene · project thread
Fixes #30944
Clause-②: no
Metadata-protocol: none
dispatch-gatesmandates the contract-review model tier forskills/**(clause ①). The maintainer's standing order in this project (2026-11-03) waives it; this PR was developed below that tier, and the dispatching seat runs the contract review.维护者速读
fieldPatches的唯一示例改为只改industry的label,选项补丁移到自带 inlineoptions的type(customer→Client);覆盖objectstack-data技能、spec 的fieldPatchesDescription()与 TSDoc、object-extensions.mdx,references/data/object.mdx由 spec 重新生成。crm_account.industry绑定共享 picklistindustry,fieldPatchTargetMisses对其任何options键返回picklist-option,照抄旧示例会在安装和os validate时被拒。@objectstack/skills与@objectstack/spec各一个 patch;回滚即 revert。.custom段末重复的 "a base field changes only throughfieldPatches" 付账;上限行不动(6068/6078)。skills/objectstack-data/SKILL.mdL364 与packages/spec/src/data/object.zod.tsfieldPatchesDescription()。What changes
skills/objectstack-data/SKILL.mdL364: the example is nowdefineObjectExtension({ extend: 'crm_account', fieldPatches: { industry: { label: 'Sector' }, type: { options: { customer: { label: 'Client' } } } } }).extend: 'crm_account'andlabel: 'Sector'stay whole tokens (eval cases 5 and 7 ofevals/objects-fields-relationships.jsonrequire them). The sentence before it still states that "apicklist-bound field's options are never patchable".packages/spec/src/data/object.zod.ts, description text only:fieldPatchesDescription()now says an option of a field bound to a sharedpicklistis never patchable and only a field declaring its ownoptionstakes an option patch, and its example setsindustry'slabelandinlineHelpTextand patchestype'scustomeroption. TheObjectExtensionSchemaTSDoc example carries the same patch; since that example extendscontact, its comment is conditional: whereindustryis picklist-bound, as on HotCRM'scrm_account, its options are not patchable (its display keys are). No schema change.content/docs/references/data/object.mdx: regenerated withpnpm --filter @objectstack/spec gen:docsafterpnpm --filter @objectstack/spec build; not hand-edited.content/docs/data-modeling/object-extensions.mdxL104-118: theos:checkexample dropsindustry'soptions(a comment says it takes them from a shared picklist) and patchestype: { options: { customer: { label: 'Client' } } }. Its existing bullet on picklist-bound fields (L152-153) now agrees with the example.'@objectstack/skills': patchand'@objectstack/spec': patch, each withClause-②: noandMetadata-protocol: none. Noskip-changeset.Read on HotCRM
mainat6961ab1,src/sales/objects/account.object.ts:industry: Field.select({ label: 'Industry', group: 'basic', picklist: 'industry' }), no inlineoptions(the values,technologyamong them, live insrc/sales/picklists/industry.picklist.tsL23).type: Field.select({ label: 'Account Type', …, options: [...] })declares its own inline options; L305 is{ label: 'Customer', value: 'customer', … }, socustomeris a stored value the patch can address.Read on objectstack
main:fieldPatchTargetMissesinpackages/metadata-core/src/extension-field-patch-targets.tspushesreason: 'picklist-option'for every key under a patch'soptionswhen the target field has a non-emptypicklist, before it looks at option values; a field with inlineoptionsis checked by stored value (reason: 'option'when absent). The new examples pass both checks.Out of scope and left as is: the
optionsshape error message inobject.zod.ts('options: { technology: { label: \'Tech\' } }', near L5034) illustrates the map shape, not a HotCRM patch.Token ratchet.
skills/objectstack-data/SKILL.md: after mergingmainatacd190b2the ceiling is 6078 with 1 byte of slack. The new example adds 10 bytes. Payment, by the seat's ruling: the.customparagraph's closing clause "; a base field changes only throughfieldPatches" (L372 onacd190b2) is deleted. Its home is L355-360 of the same file: "Relabel a field the owner declares withfieldPatches— never by redeclaring it infields" and "the type, values and rules stay the owner's". The file is now 6068 tokens (ceiling 6078, headroom 10). No ratchet row moves, nothing was re-wrapped. Net lines inskills/**: 0.Why
The one concrete
fieldPatchesexample the platform taught, in the skill, the spec description and two docs pages, patched an option of HotCRM's picklist-boundindustry. A verbatim copy was refused at install and byos validate, and the skill paragraph contradicted its own rule.Verification
Head
5a6e8fad: the two edit commits, a merge oforigin/mainatacd190b2(8920b06e, no conflict, no rebase), the ratchet-payment commit, and one commit for the contract review's two should-fixes (TSDoc comment made conditional; a skills-changeset claim the skill text does not make, dropped), and one commit for the delta review's must-fix (the comment said only the label was patchable; a picklist binding blocks only option patches).Local gates on 7c661de (head 5a6e8fa changes one TSDoc comment only): 105 derived, 105 run with exit 0, 0 NOT MEASURED (`dispatch-gates --ran`)
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 105 commands for the 6 changed files. All ran afterpnpm install --frozen-lockfile, a fullpnpm buildof the merged tree and a@objectstack/specrebuild on this head (each exit 0), each under a 900 s timeout withNODE_OPTIONS=--max-old-space-size=8192and its exit code captured before any pipe. The larger heap is for this container: at the script's default 4096 MB,check:test-typecheckinsidecheck:generatedhad tsc exit with no diagnostics; at 10240 MB it was green.check-skills-token-ratchet.mjs,check:generated,check:docs,check:skill-examples,check:skill-identifier-liveness,check:doc-authoring,check:dts-closure,check:dual-build-cjs-loadsandcheck-comment-mask-corpus.mjs. Also run:pnpm --filter @objectstack/spec exec tsc --noEmit(exit 0) andpnpm exec eslint packages/spec/src/data/object.zod.ts(exit 0).--ranprinted:105 derived famil(ies) accounted for — 105 run, 0 NOT-MEASURED (a DERIVED zero — all 105 recorded an exit code and none of them is 3).ad4d96f6(before the merge) also ran all 105 with exit 0; therecheck-plugin-teardown-shape.mjs --self-testfirst exited 3 because the shallow clone lacked its pinned fixture commit, and exited 0 after fetching it.node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD: exit 0 (6 commits) before each push. Heads22db7aeeand7c661decran all 105 with exit 0;5a6e8fadchanges only those two TSDoc comment lines, and on itpnpm --filter @objectstack/spec buildandcheck:generatedexit 0 with nothing stale.Human Minimum
packages/specholds no runtime logic. (Description text only.)eslinton the touched TypeScript file exits 0.main, one pull request. (mainmerged in, no rebase.)packages/spectouched: its generated artifacts are regenerated and committed (check:generatedexit 0).content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_01J8VVAmsHMwmra6cg78RoEp