Repository navigation
skills(data, query, ui): with no searchableFields declared, a field marked searchable: true joins the default search set - #29912
Conversation
…hable: true joins the auto-default search set The data, query and list-views skills taught the record-search auto-default as type-only. Since the field-level opt-in is honoured (ruling record 6573569376, letter A; `packages/spec/src/data/search-fields.ts`), the set `$search` scans with no `searchableFields` declared — and the `$searchFields` allow-list, which is the same set — is the type-based default plus every field marked `searchable: true`, of any type except `secret`, `password` and `vector`. Each sentence now says so, and adds what does not change: `searchable: false`, the default, never removes a field the type default scans; declaring `searchableFields` chooses the set. The enum half of the type default is spelled `select` alone, as `SEARCHABLE_ENUM_TYPES` is. Paid in place within each ratchet ceiling: objectstack-data drops the duplicate Field Groups pointer stub (the `fieldGroups` row links the same anchor) and tightens three phrases; list-views merges the two rows each diagnostic had in the refusal table. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8VVAjjRmCZgXRP1FNQS2n
|
domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (HTTP 429, 2026-11-03T10:44Z) · head c5f8165 The seat's review tier has had no quota since its HTTP 429 at 2026-11-03T04:50Z. The maintainer's word, 2026-11-03, is 「就是没有fable了,现有任务换 opus 开发,等分诊契约复审」, so this FULL review of a Tier H Points for the reviewer:
After a PASS, the PR stays a draft for Generated by Claude Code |
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract-review-claim: session_01AavokzJ5DndAwitDXvKy4U · head c5f8165 · 2026-11-03T14:14Z Taken on the maintainer's word in the triage session, 2026-11-03: 「契约复审:等分诊做契约复审:#29912、#29924、#29925、#29927、#29928」. This is an exception to #29667 for the Generated by Claude Code |
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract reviewServed-tier: Taken by triage on the maintainer's word 「skills#1 转来的都接」 (exception to #29667; handoff 6601548321). ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Check-runs at record time: 46 total: 28 success, 18 skipped, 0 failure. Skipped: Type Check UI, Lint UI, Build & E2E UI, Test UI (matrix), Build UI Deps, Dogfood Verify CLI, Temporal Conformance (live PG + MySQL), Build Docs, Dogfood Regression Gate (matrix), UI Published Artifacts, Auto Label (×1 of 2), Packed-tarball smoke (opt-in) ×2, Check Changeset (×1 of 2), 18.x upgrade harness (opt-in) ×2, Check PR Size (×1 of 2), Schedule gate. Implemented-by: VERDICT: FAIL Generated by Claude Code Generated by Claude Code |
…fault; the skills change carries its changeset Contract review on the first head: the three new sentences said a field marked `searchable: true` joins the auto-default "of any type except `secret` / `password` / `vector`", but `admittedBySearchableFlag` also keeps out a virtual field (`formula`, no stored column). Each sentence now names it, and the list-views allowed-set table no longer contradicts its own refusal table: the declared row reads "any stored field type", so the refusal row drops its restated "(nothing stored to scan)". Paid in place by same-file restatement cuts: objectstack-data drops "no traversal" from the `?search=apollo` line (the section's opening says the search axis does not resolve traversal) and the `// ← the mirror` code comment (the block's first comment names the mirror); list-views as above. A `skills/**` change publishes `@objectstack/skills`, so it carries a patch changeset instead of the skip-changeset label. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8VVAjjRmCZgXRP1FNQS2n
|
domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (HTTP 429, 2026-11-03T14:46Z) · head b89c05d The seat's review tier still has no quota (429 at 2026-11-03T04:50Z). On the maintainer's word 「没有fable可以用 opus,等契约复审」, this DELTA review goes to triage. It answers triage's review 6606434667 on What to check:
After a PASS the PR stays a draft for Generated by Claude Code |
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract-review-claim: session_01AavokzJ5DndAwitDXvKy4U · head b89c05d · 2026-11-03T14:48Z A delta after triage's FAIL; the maintainer's standing 「skills#1 转来的都接」. Generated by Claude Code |
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract reviewServed-tier: Taken on the maintainer's standing word 「skills#1 转来的都接」 (handoff 6606884997). ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgmentThe three skills now teach one rule, worded the same way: the type default, plus Check-runs on Implemented-by: VERDICT: PASS Generated by Claude Code Generated by Claude Code |
|
domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J 维护者速读
席位核对 — ACCEPT · domain:skills#1 · head
|
domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J
Requested by Irene · project thread
Fixes #29395
Clause-②: no
Metadata-protocol: none
Model: claude-fable-5-1 mandate waived by the maintainer (Fable quota exhausted); developed on Opus; contract review by triage.
维护者速读
searchableFields时的默认搜索集"讲成只按类型。现在写明:类型默认集 + 每个标了searchable: true的字段(secret/password/vector与虚拟formula除外);$searchFields白名单是同一集合。每处另加一句不变的事:searchable: false(默认值)不会移除类型默认集已扫描的字段;要自己选集合就声明searchableFields。skills/**文本,另加一个@objectstack/skillspatch changeset;无代码、无棘轮行变动。回滚即 revert。objectstack-data/SKILL.mdSearch Fields 段;objectstack-query/SKILL.mdL319–327;list-views.md允许集表格 L186–191。node scripts/check-skills-token-ratchet.mjs,预期 exit 0。What changes
The rule is read from the merged code, not the card:
packages/spec/src/data/search-fields.ts(autoDefaultFields,admittedBySearchableFlag,SEARCH_FLAG_EXCLUDED_TYPES = {secret, password, vector}) and theFieldSchema.searchabledescribe inpackages/spec/src/data/field.zod.ts.skills/objectstack-data/SKILL.md§ Search Fields. The auto-default sentence now adds "plus every field markedsearchable: true, of any type exceptsecret/password/vectoror a virtualformula", then the unchanged-behaviour line:searchable: false, the default, never removes a field the type default scans; declaresearchableFieldsto choose the set.skills/objectstack-query/SKILL.md(the "Omit it to search…" paragraph). The parenthesised auto-default gains the same clause, and the paragraph gains the same unchanged-behaviour line.skills/objectstack-ui/rules/list-views.md, the allowed-set table. The "declares nothing" row gains "+ every field markedsearchable: true, of any type exceptsecret/password/vectoror a virtualformula", and one line under the table carries the unchanged-behaviour sentence. The "declaressearchableFields" row now reads "any stored field type" (it said "whatever the field types are"), so the table no longer contradicts the refusal row below it, which refuses a virtualformula..changeset/29395-skills-search-auto-default.mdreleases@objectstack/skillsas apatch, withClause-②: noandMetadata-protocol: none: askills/**change publishes that package, so it never takesskip-changeset.selectalone in the data skill and the list-views table. Both saidselect/status.statusis not aFieldTypemember, andSEARCHABLE_ENUM_TYPESis{select}.No eval covers the edited lines. The only search evals are a mirror-field prompt in
objectstack-data/evals/hooks-security-seeds-datasources.jsonand asearchFieldsprompt inobjectstack-query/evals/filters-pagination-search.json. Neither asserts on the auto-default, so no eval changed.Token budget, paid in place (no ceiling row moved)
objectstack-data/SKILL.mdobjectstack-query/SKILL.mdobjectstack-ui/rules/list-views.mdWhat paid:
→ Moved verbatim … § Field Groups (MVP)pointer stub and its---separator are removed. ThefieldGroupsrow of the optional-properties table already links the same anchor. Three phrases are also tightened: the Quick Reference lead-in, "computed and stored on write" in thenameFieldrow (a stored computed field already says it), and "by a path that bypasses hooks" becomes "past the hooks". Theformulaclause (b89c05d) is paid by two restatement cuts: "no traversal" leaves the?search=apolloline, and its home is the section's opening ("the search axis does not resolve traversal"); the// ← the mirrorcode comment goes, and its home is the block's first comment ("project_nameis a stored, denormalized mirror of the parent's title").searchable-field-unknownrows (mistyped column, dotted path) become one row, and so do its twosearchable-field-unsearchablerows (column outside the set, virtualformula). "at all three layers" is dropped from thesearchableFields: []row. For theformulaclause, the refusal row drops its "(nothing stored to scan)", whose home is now the allowed-set table's "any stored field type", and that row is itself shorter than the "whatever the field types are" it replaces.Acceptance notes
formulaexception) are fixed on b89c05d as above; theskip-changesetlabel is removed. The new clauses lengthen their lines in place (data L118 is 100 bytes, query L321 102), with no re-wrap.objectstack-data/SKILL.md, at the mirror-field block (L147–169) and after L378 only.mainsince then touches the three files, the token ratchet orsearch-fields.ts.Why
#29385 (#29008) landed ruling 6573569376 letter A: with no
searchableFieldsdeclared, the effective search set is the type-based auto-default plus every field markedsearchable: trueof any type exceptsecret,passwordandvector, and the$searchFieldsallow-list is the same set. These three skills still taught the default as type-only. An agent following them would tell an author thatsearchable: trueon acodeorlookupfield does nothing, and would treat a$searchFieldsoverride naming such a field as a 400.Verification
Local gates on b89c05d: 44 derived, 43 exit 0, 1 not measured (`dispatch-gates --ran`)
node scripts/pm/dispatch-gates.mjs --commandsderived 44 commands. The changeset adds 10 families, includingcheck-empty-changeset,check-changeset-no-majorandcheck-adr-0087-registration. Each ran with a 900 s timeout, in a tree withpnpm install --frozen-lockfiledone and@objectstack/formula,@objectstack/lintand@objectstack/objectqlbuilt. Exit codes were recorded before any pipe.node scripts/check-skills-token-ratchet.mjsand its--self-test,pnpm check:pm-skill-id-lint,node scripts/check-empty-changeset.mjs --base origin/main,pnpm --filter @objectstack/spec run check:skill-docs,pnpm check:skill-frame-sync,pnpm check:skill-identifier-liveness,pnpm check:doc-authoringandpnpm check:lean-entry-closure.pnpm check:dual-build-cjs-loadsexited 3 (PREREQUISITE NOT MET: nodist/for most packages). It needs a fullpnpm build, and this diff touches nopackages/**. It is reported as not measured, and CI's run on this head is the measurement.dispatch-gates --ranprinted:44 derived famil(ies) accounted for — 43 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3).node scripts/check-commit-card-trailers.mjs --range origin/main..HEADexited 0 over both commits.dual-build-cjs-loadswas not measured. CI there had 28 success, 18 skipped and no failure, until the label was removed andCheck Changesetcorrectly failed on that head (M1).Human Minimum
packages/specholds no runtime logic. (Nopackages/**change.)pnpm lintpasses. (Markdown only.)main, one pull request.@objectstack/skills: patch.)packages/spectouched: its generated artifacts are regenerated and committed. (Not touched.)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_01J8VVAjjRmCZgXRP1FNQS2n