Skip to content

fix(metadata-protocol): the search palette titles a hit by nameField before the deprecated titleFormat - #24202

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-24087-search-title-namefield-first
Oct 17, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-24087-search-title-namefield-first

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #24087

Clause-②: no

What changed

searchAll (GET /api/v1/search, the console's global search palette) now titles a hit in this order: the primary-title pointer (nameField, then the deprecated alias displayNameField), then the titleFormat template, then the conventional name fields, then first/last name, then the record id. Before, renderTitle rendered titleFormat first and returned it whenever every placeholder resolved. ADR-0079 D3 says "an explicit nameField takes precedence over it", and the spec's titleFormat describe says the same.

  • packages/metadata-protocol/src/protocol.ts: in renderTitle, the pointer is read before the template. The comment above it now states the new order and why. The pointer moved out of the conventional candidate list; the list is otherwise unchanged.
  • packages/metadata-protocol/src/protocol.search-title-namefield.test.ts: the old pin titleFormat still outranks the pointer asserted the defect. It is replaced by a [#24087] block (below).
  • packages/spec/src/api/protocol.zod.ts: SearchAllHitSchema.title's describe stated the old order (titleFormat first). This change made it false, so it now states the new order. content/docs/references/api/protocol.mdx is regenerated from it (check:generated --fix, the check:docs artifact only, two table rows).
  • One changeset: patch for @objectstack/metadata-protocol and @objectstack/spec.

File-surface note. The claim fences out packages/spec, naming resolveDisplayField and the titleFormat describe; both are untouched. The SearchAllHitSchema.title describe is a third spec site: it is the published contract of the very reader this PR changes, and the reorder made its text false. The dev rules require fixing a shipped statement the change makes false, so it is fixed here (describe text only, no shape change) and named in the report.

H1 measured: a provisioned nameField outranks titleFormat

provisionPrimary runs designate-only at the registry's materialization seam (packages/objectql/src/registry.ts, materializeBaseLayer). It stamps nameField on any object that has a title-eligible field. ObjectTitleCompleteness.status's docblock in spec/src/data/display-name.ts records that authorship cannot be recovered after that stamp: "'the author wrote nameField' and 'the read derived nameField' are the same bytes". So searchAll, which reads registry.getAllObjects(), cannot tell an authored pointer from a stamped one. resolveDisplayField does not read titleFormat at all.

Mirroring it means titleFormat titles a row only when (a) the object has no title-eligible field, so nothing is stamped, or (b) the pointer's value is empty on that row. This is wider than "an explicit nameField". It was settled by the four axes and is listed in the report's open_questions. In short: the key is deprecated and lint-warned (title-format-retired), ADR-0079 sets the direction, and the reader cannot see authorship. The changeset gives the migration ADR-0079 prescribes for an author who wants a composite title: a text formula designated as nameField.

Pins

All in protocol.search-title-namefield.test.ts. Each fixture goes through the real provisionPrimary(..., { synthesize: false }), so the pins see the body the registry serves:

  1. THE PIN. The object declares both titleFormat: '{process_name} · {record_id}' and nameField: 'display_title' (a text formula). It is titled Discount Sign-off · opp_45, and not.toBe('flow:deal_desk · opp_45').
  2. Control. An object with only titleFormat and no title-eligible field gets no stamp, and the template still renders (Order 42).
  3. Control. An empty pointer value falls through to the template, not to the id.
  4. Measured H1 consequence. An object with only titleFormat plus a text field is titled by the stamped pointer (TK-9).
  5. The existing [#8786] block is unchanged and still green. It includes an object with neither key, which falls back to name as before.

Ablation (one run, source-resolved). The test imports ./protocol.js relatively, so it reads src/ and no dist/ leg applies. The mutation went through scripts/ablation-replace.mjs: the pointer guard was given && typeof titleFormatSource !== 'string', which restores template-first. The anchor went 1 → 0 and the marker 0 → 1, and the blob changed 375717c98f5d → cd9eb0ea1a25. Result: 2 failed | 7 passed, namely THE PIN and pin 4, as predicted. Restore: blob equals HEAD (375717c98f5d) and git diff HEAD is empty.

Real engine. The pin runs over the boundary double this file already uses, not a real ObjectQL. metadata-protocol cannot import @objectstack/objectql (objectql depends on it, a package cycle; see the header of objectql/src/global-search-palette-recall.test.ts). The real-engine home is in packages/objectql, outside this claim's file surface. Using the real provisionPrimary transform is the part of the engine that decides this behaviour.

Census: other title readers that read titleFormat first

Site Reads titleFormat first? Evidence
metadata-protocol searchAll renderTitle was yes, fixed here this PR
spec resolveDisplayField / resolveRecordDisplayName / objectql resolveRecordTitle no, never reads it display-name.ts: nameField ?? displayNameField ?? derived
metadata-core object-schema-fls-references.ts not a title reader collects the field references of the template for FLS
lint validate-record-title.ts and friends not a title reader warns title-format-retired
objectui renderers (calendar / kanban card title, record H1) yes, by the repo's own description; not measured spec/src/ui/view.zod.ts docblocks state the objectui chain as titleFormat → displayNameField → type-aware derivation → 'Untitled'; the liveness ledger records titleFormat as live via objectui interpolation. objectui is outside this session's scope, so this is a lead for the seat, not a reading.

In this repository, searchAll was the only runtime reader that rendered titleFormat. The remaining family is the objectui display-name chain. It is reported in out_of_scope_findings as one family, and nothing in it is changed here.

Verification (head a8fe932ef)

  • pnpm --filter '@objectstack/metadata-protocol^...' build: exit 0. Spec build + check:generated: 1 stale (check:docs), fixed with --fix, regenerated file committed.
  • pnpm --filter @objectstack/metadata-protocol build && … typecheck: exit 0 (tsconfig includes src/**/*, tests included).
  • pnpm --filter @objectstack/metadata-protocol exec vitest run --maxWorkers=2: exit 0, 243 files passed, 3 skipped; 20631 tests passed, 19 skipped.
  • node scripts/pm/dispatch-gates.mjs --commands (no paths): 111 commands, each run with its exit code captured before any pipe. 110 exit 0. Three first exited 3 (prerequisite) and were rerun to exit 0 after clearing the prerequisite: check-plugin-teardown-shape --self-test (fetched its pinned fixture commit), check:lean-entry-closure (built objectql), check:skill-examples (built client and client-react). check:dual-build-cjs-loads: exit 3, NOT MEASURED, because it needs every package's dist/ (a full pnpm build); CI runs it.
  • --ran reconciliation: 111 derived famil(ies) accounted for — 110 run, 1 NOT-MEASURED.
  • Not run locally: @objectstack/spec's own pnpm test (the spec diff is describe text only, and no test pins the old sentence: git grep finds it only in the regenerated mdx). test:repo is CI's.

Acceptance notes

  • Objects whose palette title changes with this PR are those that declare titleFormat beside a title-eligible field (stamped or authored nameField). sys_approval_request (the card's case, which declares nameField: 'display_title') is measured by THE PIN's fixture shape. The roughly 30 other *.object.ts files declaring titleFormat were not measured one by one. Some sys_* prefixes are skipped by the palette entirely (sys_audit_log, sys_activity, sys_presence, …).
  • objectql/src/registry.ts has a comment saying title-less system tables "keep resolving their title on read via resolveDisplayField / titleFormat". It stays accurate.

Generated by Claude Code

…e deprecated titleFormat

ADR-0079 D3 and the spec's titleFormat describe give an explicit nameField
precedence; renderTitle rendered the template first.

Claude-Session: https://claude.ai/code/session_014pQA9SjSrUuG8NSnD7xyYH
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Oct 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/metadata-protocol, @objectstack/spec, touching 2 documentable anchor(s).

⛔ 1 release-owned page(s) name something this change touched. These are read-only:

  • content/docs/releases/v17/17-1.mdx (via searchAll (symbol, a method of class ObjectStackProtocolImplementation))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 144 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 8a88901be1c317e2e078e6d29f21efcae5b9485e → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 35faf20e10e6987737946b58ce2756e3bc0610b4 — the merge of head a8fe932ef92d227f881c051a17a3916e2abf0545 into base 8a88901be1c317e2e078e6d29f21efcae5b9485e, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 35faf20e10e6987737946b58ce2756e3bc0610b4 && git checkout 35faf20e10e6987737946b58ce2756e3bc0610b4
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 8a88901be1c317e2e078e6d29f21efcae5b9485e a8fe932ef92d227f881c051a17a3916e2abf0545 && git checkout -B drift-repro 8a88901be1c317e2e078e6d29f21efcae5b9485e && git merge --no-ff a8fe932ef92d227f881c051a17a3916e2abf0545

node scripts/docs-audit/affected-docs.mjs --json 8a88901be1c317e2e078e6d29f21efcae5b9485e

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 8a88901be1c317e2e078e6d29f21efcae5b9485e → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: a8fe932ef92d227f881c051a17a3916e2abf0545
Local-runs: none
Scope: packages/spec/src/api/protocol.zod.ts + packages/metadata-protocol/src/protocol.ts, packages/spec/src/data/display-name.ts, packages/metadata-protocol/src/protocol.search-title-namefield.test.ts, content/docs/references/api/protocol.mdx, .changeset/24087-search-title-namefield-first.md

Scope note: the schema face is packages/spec/src/api/protocol.zod.ts (the one hits path). Widened to every other path of the diff plus the cited display-name.ts, each read in the cited code at the head; no path is left as a TIER_DEFAULT remainder. Net diff read as merge-base b0fe9fad → head (5 files, +153/−38; the three-dot diff against origin/main b1845ed6 is byte-identical, and main has not moved under any of the five files or display-name.ts since the merge-base).

① Derived judgments

  1. Schema shape, exports, accept sets — nothing moves. RIGHT. The only change in protocol.zod.ts is the string literal inside SearchAllHitSchema.title's .describe() (lines 2572–2577 at the head). No key added, removed, renamed or retyped; no optionality change; no export touched. Consistent with the file list: no api-surface/, authorable-surface/ or json-schema.manifest/ shard moves, and check:api-surface, check:authorable-surface, check:docs all sit inside the green TypeScript Type Check job. The generated content/docs/references/api/protocol.mdx rows (two occurrences of the hit table) are byte-equal to the new describe. The old sentence survives nowhere at the head (git grep of its distinctive fragment: zero hits).

  2. The describe text is TRUE of the code at this head, word for word. RIGHT. Describe: "resolved in order: the declared primary-title pointer (nameField, ADR-0079; deprecated alias displayNameField still honored) → the object's deprecated titleFormat template → conventional name fields → first/last name → the record ID as a string." renderTitle at protocol.ts:15589–15614: (a) titlePointer = obj.nameField ?? obj.displayNameField, returned when the field exists on the object and the row's value is non-empty after trim; (b) titleFormatSource rendered with {field} / {{field}} placeholders; (c) ['name','full_name','title','subject','label','company'].filter(hasField); (d) first_name / last_name; (e) String(row.id). Five steps, same order, same vocabulary. The alias is consulted only when nameField is absent (the ??), which is what "deprecated alias still honored" meant before this PR too.

  3. The runtime reorder in protocol.ts is the card's Done-when arm 1 and nothing else. RIGHT. The pointer moved out of the conventional candidate list to a first step with the same empty-falls-through semantic (v != null && String(v).trim()) and the same hasField guard; the conventional list is unchanged; the .filter lost its type predicate only because the list is now all string literals. The replaced test titleFormat still outranks the pointer was a searchAll's title rendering reads only the deprecated displayNameField, so a canonically-designated primary title never titles a ⌘K hit #8786 scope-preservation pin asserting the old order, not a ruling; the card records no ruling for a deviation, so arm 1 binds as written. Pre-existing and untouched by this PR (noted, not a finding against it): a partially-resolved template still returns at protocol.ts:15603 although the comment above says unresolved placeholders fall through; same before and after.

  4. Pins. RIGHT, with the real-engine caveat accepted. Four new tests in the [#24087] block, every fixture passed through the real provisionPrimary(…, { synthesize: false }) from @objectstack/spec/data (a declared subpath export; the test file is inside the package's tsc --noEmit program via include: ["src/**/*"], so the green type check covers the fixture typing). THE PIN reproduces the card's measured shape (titleFormat: '{process_name} · {record_id}' beside nameField: 'display_title' text formula) and names the defect's signature negatively; two controls keep the template reachable (no title-eligible field ⇒ no stamp ⇒ Order 42; empty pointer value ⇒ template, not id); the fourth pins the H1 consequence. The dev's single ablation (template-first restored via the pointer guard) failed exactly the two predicted pins. The double is the file's existing boundary stand-in, not ObjectQL: metadata-protocol cannot import @objectstack/objectql (cycle, stated at protocol.ts:15634–15639), and the registry step that decides this behaviour — the stamp — is the real one. The real-engine palette pin's natural home (packages/objectql/src/global-search-palette-recall.test.ts) is correctly recorded as a carrier-less acceptance note.

  5. Census (Done-when 3). RIGHT for this repository. At the head, outside tests, *.object.ts, packages/spec, packages/lint and packages/cli, the only runtime site that renders titleFormat is searchAll (protocol.ts:15575); metadata-core/object-schema-fls-references.ts:743 rewrites the template's field references for FLS and titles nothing; objectql's resolveRecordTitle / resolveDisplayField never read the key (display-name.ts:220–225). The objectui display-name chain is named as a lead, not a reading — correct, objectui was outside this session.

  6. Check-runs on the head, read live at 2026-10-17T17:56Z (40 runs). Required contexts: Lint & Repo Gates success · TypeScript Type Check success · Build Core success · Governed Surface Queue Guard success · Test Core shards 1/6, 2/6, 5/6, 6/6 success, Test Core (3/6) in_progress, Test Core (4/6) in_progress. Every other completed run is success or an expected skip (Console Pin Gate, Temporal Conformance, Dogfood Verify CLI, Packed-tarball smoke, the matrix placeholder); Check Changeset, Check PR Size, Spec property liveness, Dogfood Regression Gate, all three claim-branch checks: success. No failure, cancellation or timeout on the head. The two in-progress shards are the one reading this record could not close; the seat re-reads CI before any landing step, and a red on either shard voids this PASS for that head.

  7. Governed surfaces: none in the file list (no .claude/**, docs/adr/**, skills/**, AGENTS.md, CLAUDE.md, .github/workflows/**). Head repo equals base repo (not a fork). Draft, Fixes #24087, 191 changed lines, labels documentation / size/m / tests / tooling, no skip-changeset.

② Semver level

RIGHT: patch × 2, and the Clause-② line reads no with no arm on both carriers. The changeset .changeset/24087-search-title-namefield-first.md declares @objectstack/metadata-protocol: patch (a reader in a released package now obeys the precedence the contract already declared — a bug fix, so patch, never none and never skip-changeset) and @objectstack/spec: patch (the describe text ships in the tarball and the generated reference; no shape change). The PR body's third line and the changeset body both carry the declaration reading no: no accept set is widened (nothing new parses) and none is narrowed (nothing that parsed is refused), so no (narrowing) arm, no BREAKING, no ADR-0087 disposition marker owed; Check Changeset is green. The body goes beyond what a patch strictly owes by stating the visible consequence and ADR-0079 D3's migration (a text formula designated as nameField), which is the right text for an upgrading agent to grep.

③ Boundary flags

Every deviations entry and the one open_questions entry of os-dev-report 6237615038, answered:

  1. File-surface breach — packages/spec/src/api/protocol.zod.ts + the generated mdx. Accepted; it is why this review exists. The claim fenced out packages/spec naming resolveDisplayField and the titleFormat describe, both untouched. The SearchAllHitSchema.title describe is the published contract of the very reader this PR changes, and the reorder made its sentence false. os-dev's rule 3 states the obligation in one line ("本轮改动令其变假或触碰的已发布缺陷必修"), and AGENTS.md's route rule 4 ("machine-readable surfaces must not lie") agrees. The breach is describe text only, declared in the PR body and the report, and it put the PR on the schema face at CONTRACT_REVIEW_TIER — this record is that review. Owed by the seat, not the dev: the in-place fix's second half under os-dev rule 3 — supplement the claim's declared file surface with packages/spec/src/api/protocol.zod.ts and content/docs/references/api/protocol.mdx in the same round.

  2. Pin not over a real ObjectQL engine. Accepted — package cycle verified in the cited code; the real provisionPrimary is applied to every fixture; the real-engine home is named with carrier: none. Not escalated.

  3. Worktree created from a pre-existing local branch at b0fe9fad = merge-base. No effect on the diff (base identical; empty branch pushed before any edit). Accepted.

  4. @objectstack/spec's own pnpm test not run locally; test:repo not run. Describe-only spec change, no remaining copy of the old sentence at the head, spec build + check:generated reported green by the dev and confirmed by the TypeScript Type Check job. CI's Test Core is the gate — four shards green, two in progress as listed in ① item 6. Accepted on that reading.

  5. PR-body footer in the os-dev session-URL form; 6. zero label writes (changeset present, so skip-changeset rightly not applied); 7. platform PR auto-subscription declined. All consistent with the dispatch contract. Accepted.

  6. H1 (open_questions[0]): a provisioned (stamped) nameField now outranks titleFormat, not only an authored one. Answer: A — accept as landed. Not escalated. Grounds, read in the cited code: ADR-0079 D1 (a title is a real stored field, "not a template"), D4 (one resolution order for every consumer, nameField ?? displayNameField ?? derivation, which never contains titleFormat), D7 (the registry's designate-only stamp at objectql/src/registry.ts:3522 inside materializeBaseLayer, called from registerObject, exists so the pointer "is reliably populated"); and ObjectTitleCompleteness.status's docblock (display-name.ts:326–355): authorship is deliberately not recoverable after the stamp, so option B would need a new provenance surface built to keep a deprecated key alive, against the direction D3 sets. The dispatch's "measured first" item anticipated exactly this and directed mirroring resolveDisplayField; the card's arm 1 says the same. Measured reach at the head, first-party metadata: 65 *.object.ts files declare titleFormat; 60 also declare nameField (those are the card's arm 1, titled by the authored pointer — not H1); 5 are titleFormat-only. Of the five, sys_audience_binding_suggestion and sys_share_link are enable.searchable: false and never reach the palette; three do and change palette title from the template to the stamped field: sys_attachment → file_name (affix tier), sys_notification_template → subject (exact tier), sys_record_share → object_name (its apiMethods: ['get','list'] whitelist serves search through list per api-derivation.ts:145). The changeset discloses this class and the migration; lint already warns title-format-retired. For the seat, not a blocker: those three first-party objects are the one place H1 thins a palette title (sys_record_share titled by its object name alone) — fold them into the family closing card the dispatch already plans for titleFormat readers, as a migration to an explicit nameField (text formula), rather than opening a reader-specific exception.

  7. out_of_scope_findings. The objectui display-name chain (calendar/kanban card title, record H1 reading titleFormat first, per spec/src/ui/view.zod.ts docblocks and the liveness ledger's titleFormat: live row) is the remaining family; correctly left unmeasured here and handed to the seat for one closing card after confirming at the pinned .objectui-sha. The second item is Acceptance-notes material and is recorded as such.

  8. Acceptance-note accuracy, minor: the PR body says "roughly 30 other *.object.ts files declaring titleFormat"; the head count is 65 (60 with a nameField beside it). Not load-bearing for the verdict; the changeset's statement of reach is correct in kind.

Implemented-by: claude/issue-24087-search-title-namefield-first
Reviewed-by: session_01JtSQQ3EWsbNPzyYMug1tXy

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · domain:engine seat 1 · session_01JtSQQ3EWsbNPzyYMug1tXy · 2026-10-17T18:04Z · ACCEPT

Head: a8fe932ef92d227f881c051a17a3916e2abf0545.

Item Reading
Shape Draft PR → main. The body opens Fixes #24087, its only closing keyword (full-body scan).
Scope 5 files (+153 / −38): searchAll's renderTitle and its comment in packages/metadata-protocol/src/protocol.ts, its pin, the changeset, and the SearchAllHitSchema.title describe in packages/spec/src/api/protocol.zod.ts with its two generated mdx rows. The spec hunk is os-dev's bounded in-place fix (a shipped sentence this change made false). The claim is re-declared with it (6238219129), and it is declared to domain:spec on #6017. Not governed (check-governed-merges.mjs --pr 24202); 191 lines.
Premise and ruling Done-when arm 1 as dispatched: the pointer, then titleFormat, then the fallbacks. H1 measured: a provisioned nameField cannot be told from an authored one after the registry's stamp, so the reader mirrors resolveDisplayField.
Contract review CONTRACT_REVIEW_TIER, an isolated reviewer: record 6238191743, PASS on this head (schema face). The seat re-measured its reach count before adopting it: 65 *.object.ts files declare titleFormat, and 5 of them have no nameField.
Prose faces Changeset and mdx, sentence by sentence. GET /api/v1/search is the route (rest-route-ledger.ts). os explain title-format-retired exists (packages/lint rule explanations). The order sentence matches the code. The mdx rows are byte-equal to the new describe.
Pins and ablation 4 pins through the real provisionPrimary. One ablation (template-first restored) turns exactly the 2 predicted pins red; the restore is clean. The double is the file's boundary stand-in, because of the objectql package cycle.
Clause-② no, at a line start in the PR body and the changeset. patch for @objectstack/metadata-protocol and @objectstack/spec.
Gates Dev union: 111 derived, 110 run, 1 NOT MEASURED (check:dual-build-cjs-loads, which CI hosts). CI on this head: 41 check-runs, 36 success, 5 skipped, 0 failed. Every skip is rostered in EXPECTED_SKIPS: Console Pin Gate, Dogfood Verify CLI, Temporal Conformance, the Dogfood matrix template, Packed-tarball smoke.

Disposition:

Landing: ordinary queue (pr_ready + automerge_enable through the relay), in this stroke.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants