Skip to content

docs(skills): list relatedListTitle under fields.{field_name} in the i18n skill - #30068

Merged
os-zhuang merged 2 commits into
mainfrom
claude/project-thread-2cn4ji
Nov 4, 2026
Merged

os-zhuang merged 2 commits into
mainfrom
claude/project-thread-2cn4ji

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J

Requested by Irene · project thread

Fixes #29990

Clause-②: no
Metadata-protocol: none

The maintainer waived the model-tier mandate for skills/** while that tier had no quota; this PR was developed below it.

维护者速读

  • 改了什么:objectstack-i18n 技能对象级翻译表的 fields.{field_name} 一行,在 inlineTitle 之后加上 relatedListTitle:lookup 或 master_detail 字段在父记录页上画出的相关列表标题;键在子对象的字段上,未翻译时保留作者原文,不会换成子对象的标签。另加一个 '@objectstack/skills': patch changeset。
  • 为什么改:PR feat(spec): a lookup or master-detail field's related-list title is translatable #29989 已让 relatedListTitle 可翻译(translation.zod.ts 的 FieldTranslationSchema 与 i18n-resolver.ts 的 translateObject),技能表还没列它。
  • 风险与回滚:纯技能文本 + changeset。为新文字付账,删掉同文件 Diff & Coverage Schemas 下一段重复说明(getCoverage() / suggestTranslations() 无实现,Service Contract 一节已说);+219 / −222 字节;复审 S1 在 Diff & Coverage Schemas 开头句补回两个 schema 与 getCoverage() / suggestTranslations() 的对应(+111 字节),合计 5646 → 5673 tokens,上限 6333 未动,无 re-wrap。回滚即 revert。
  • 先看:skills/objectstack-i18n/SKILL.md 第 162 行;对照 packages/spec/src/system/translation.zod.ts 的 relatedListTitle TSDoc。
  • 需要你做的:Tier H 受管面(skills/**),需要 GOVERNED_APPROVERS 的批准;PR 保持 draft。

What changes

skills/objectstack-i18n/SKILL.md, the fields.{field_name} row of the object-level table: after inlineTitle it now lists relatedListTitle (the title of the related list a lookup or master_detail field draws on its parent's record page — the key is the child's too; untranslated it keeps its authored text, never the child's label). The wording mirrors the inlineTitle entry beside it.

Facts, read on main at c23501b2 (the merged code of #29989):

  • FieldSchema.relatedListTitle: packages/spec/src/data/field.zod.ts L1952; the field form shows it for lookup and master_detail (field.form.ts L320).
  • Bundle slot: FieldTranslationSchema.relatedListTitle in packages/spec/src/system/translation.zod.ts L248-263, addressed objects.<child>.fields.<field>.relatedListTitle.
  • Untranslated fallback: translateObject in packages/spec/src/system/i18n-resolver.ts L4554-4561 overlays the title only when a bundle entry exists, so an authored title with no entry keeps its text; the child's label is never swapped in (docblock L4478-4487).

The optional example line was not added: it would cost about 110 bytes the deletion below does not cover.

Token ratchet (no ceiling row moved, no re-wrap)

The added text (219 bytes) is paid by deleting a restatement in the same file: the paragraph under Diff & Coverage Schemas saying getCoverage() and suggestTranslations() have no shipped implementation and pointing at os i18n check (222 bytes with its blank line). Its homes stay in the file: Integration with II18nService → Service Contract says the same of the optional methods, and Translation Coverage → os i18n check opens "The working coverage path is the CLI". No test under packages/** or scripts/** pins the cut text.

The cut paragraph was also the one place that tied the two schemas to the methods returning them (packages/spec/src/contracts/i18n-service.ts L215, L228). Per the contract review's S1, the section's opening sentence (L340) now carries that tie in one clause: "The spec models coverage results for tooling — the return shapes of the optional getCoverage() / suggestTranslations() (see Service Contract below):". Only that line changed; no other line is re-wrapped.

file bytes before / after tokens before / after / ceiling
skills/objectstack-i18n/SKILL.md 22604 / 22712 5646 / 5673 / 6333 (headroom 687 → 660)

.changeset/29990-i18n-related-list-title.md: '@objectstack/skills': patch, with both declaration lines.

Tests

  • node scripts/check-skills-token-ratchet.mjs: exit 0, skills/objectstack-i18n/SKILL.md is 5673 tokens (ceiling 6333; headroom 660).
  • No code changed, so no package test or typecheck is owed.

Verification

Head 290d1fc0 (two commits on c23501b2; 284424b8 is the reviewed head, 290d1fc0 adds the S1 clause and its changeset sentence).

Local gates on 284424b and again on 290d1fc: 44 derived, 44 run with exit 0, 0 NOT MEASURED each time (`dispatch-gates --ran`)
  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 44 commands for the two changed files. All ran after pnpm install --frozen-lockfile and a full pnpm build (exit 0), each with a 900 s timeout and its exit code captured before any pipe.
  • All 44 exited 0, among them check-skills-token-ratchet.mjs (and --self-test), check-adr-0087-registration.mjs --base origin/main, check-changeset-no-major.mjs, check-empty-changeset.mjs, check:changeset-gate-self-tests, check-comment-mask-corpus.mjs, check:doc-authoring, check:skill-docs, check:skill-compatibility, check:skill-frame-sync, check:skill-identifier-liveness, check:dts-closure and check:dual-build-cjs-loads.
  • pnpm check:changeset-fixed (artifact roster under .changeset): exit 0.
  • --ran printed: 44 derived famil(ies) accounted for — 44 run, 0 NOT-MEASURED.
  • node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD: exit 0.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (No schema touched.)
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran.
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset.
  • 6. packages/spec not touched.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English (the 维护者速读 block is the repo's own Chinese reading aid).

🤖 Generated with Claude Code

https://claude.ai/code/session_01J8VVAomnWeZNN7jDS3HjjL


Generated by Claude Code

@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Nov 4, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J

Contract-review-claim: session_01J8VVAnMUWA9rufXzFaEh4J · head 284424b · 2026-11-04T12:34Z

The seat review runs at CONTRACT_REVIEW_TIER in an isolated subagent (the seat session is not at that tier). No review seat (lanes/review.md) is seated.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 284424b87de14e7bf98148cd5e0ea0cf33c05c3c
Local-runs: probe — on a detached worktree of the head (merge-base with origin/main c23501b; origin/main at d79eecf when fetched, three commits past the merge-base, none of which touches skills/objectstack-i18n/**, scripts/check-skills-token-ratchet.mjs, packages/spec/src/data/field.zod.ts, field.form.ts, packages/spec/src/system/translation.zod.ts or i18n-resolver.ts; the only movement is two unrelated .changeset/*.md additions): node scripts/check-skills-token-ratchet.mjs on the head (exit 0: skills/objectstack-i18n/SKILL.md 5646 / 6333, headroom 687) and again with the merge-base file swapped into the same worktree (exit 0: 5646 / 6333, then restored, git status clean) plus --self-test (exit 0, 97 cases); node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (44 commands, matching the dev record's 44; the tool warns the tree is three commits behind origin/main and that check-adr-0087-registration.mjs, docs-audit/affected-docs.mjs and regen-artifacts.mjs moved there, none of them in this diff); node scripts/pm/check-skill-id-lint.mjs (110 files clean, exit 0) and --self-test (23 cases); node scripts/check-skill-identifier-liveness.mjs (486 citations over 71 published files, exit 0) and --self-test; check-skill-compatibility-version.mjs, check-skill-frame-sync.mjs, check-role-word.mjs (live and self-test, all exit 0); node scripts/pm/check-governed-merges.mjs --branch HEAD (exit 3, GOVERNED, Tier H, 1 of 2 paths hit skills/**, 18 changed lines); node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD and --range c23501b2b9..HEAD (exit 0, one commit, model-free trailer pair); node scripts/check-empty-changeset.mjs --base origin/main (exit 0, one declaring changeset added, none from the merge-base modified) and --self-test (165 assertions); node scripts/check-changeset-no-major.mjs --base origin/main (exit 0, level axis not applicable locally); check-adr-0087-registration.mjs --base origin/main (exit 1: input problem, no tsx under the worktree — NOT MEASURED here, read from CI), check-doc-authoring.mjs and check-closing-keyword-parity.mjs (both exit 3 PREREQUISITE NOT MET in this container: no typescript, no yaml in node_modules; nothing measured, read from CI); wc -c / wc -l on both trees; diff of the two files with the touched lines removed (byte-identical remainder); git diff --word-diff (4 changed segments, all inside the touched lines); grep over packages/**, scripts/**, skills/** for a pin on the cut text (none); gh api REST reads of the PR, its files, commits, comments and reviews, card #29990 and its comments, and the head's check-runs three times. The worktree was removed after the runs and the main checkout was not touched.
Scope: skills/objectstack-i18n/SKILL.md (the governed hit: the fields.{field_name} row L162; the deleted paragraph under Diff & Coverage Schemas, merge-base L348–351) + read, not reviewed: .changeset/29990-i18n-related-list-title.md (the prose face, checked sentence by sentence here as the dispatch asked), packages/spec/src/data/field.zod.ts L1951–1952 (relatedListTitle and its "defaults to the child object label" TSDoc) and L1891–1893 (inlineEdit, inlineTitle), packages/spec/src/data/field.form.ts L320 (relatedListTitle, visibleWhen lookup / master_detail) and L327 (inlineTitle, master_detail only), packages/spec/src/system/translation.zod.ts L233–263 (FieldTranslationSchema.inlineTitle and .relatedListTitle with their docblocks), packages/spec/src/system/i18n-resolver.ts L3611–3614 (ObjectFieldLike), L4469–4486 (the translateObject docblock) and L4546–4561 (the inlineTitle and relatedListTitle overlays), packages/spec/src/system/i18n-field-related-list-title.test.ts (every pin, L60–122), packages/spec/src/contracts/i18n-service.ts L205–228 (getCoverage? / suggestTranslations? and their return types), ui/packages/app-shell/src/utils/deriveRelatedLists.ts L87, L358 and L388–389 (the title override and its absent-title fallback) and the file list that consumes it (RecordDetailView.tsx), packages/skills/package.json and packages/skills/scripts/sync-catalog.mjs L6–34 (what @objectstack/skills ships), scripts/check-skills-token-ratchet.mjs L515 (the ceiling row), .github/PULL_REQUEST_TEMPLATE.md (the Human Minimum list), scripts/check-commit-card-trailers.mjs L320 and L836–850 (what the repo counts as a model identifier), card #29990 body, comments 6619502065 (triage) and 6630218767 (claim), PR #30068 body and its one comment 6630726780 (the seat's review claim on this head), the dev gate record pr-29990/gates-284424b8.txt (read as input)

Reviewer: an isolated contract reviewer at CONTRACT_REVIEW_TIER, read-only on GitHub (REST reads only; nothing written, pushed or commented), fed the card body and comments, the PR body, the net diff against the merge-base, the head's check-runs, AGENTS.md, the pm-dispatch SKILL.md contract-review section, contract-review.md, review-checklist.md, lanes/skills.md and lanes/review.md. The dev gate record was read as input, not as conclusions; every count and every claim about the spec and the resolver below is this review's own reading of the head tree and of main at the merge-base. No environment variable value is printed anywhere in this record.

① Derived judgments

  1. File surface. One commit (284424b, author Claude, PR author objectstack-fleet[bot], head repo = base repo, draft, base main, trailers Claude-Session: + Co-authored-by: Claude, no model identifier). git diff --numstat c23501b2 284424b8, the REST file listing (+13 / −5, 2 files) and the PR body agree on exactly two paths: skills/objectstack-i18n/SKILL.md +1/−5 (524 → 520 lines) and .changeset/29990-i18n-related-list-title.md +12/−0 (new). The claim (6630218767) named exactly these: the row at L162, optionally the example near L189 (not taken, see ①.9), plus one '@objectstack/skills': patch changeset. Nothing else is touched; the ratchet script is not in the diff. Correct, and on surface.
  2. The code the new row asserts, read at the merge-base. FieldSchema.relatedListTitle (field.zod.ts L1952, describe "Title for the detail-page related list", TSDoc L1951 "defaults to the child object label") is a key of the child object's field: the field form shows it under data.type in ['lookup','master_detail'] with the help text "Title for this relationship's related list on the parent's detail page" (field.form.ts L320), where inlineTitle beside it is master_detail only (L327). The bundle slot is FieldTranslationSchema.relatedListTitle (translation.zod.ts L263), addressed objects.<child>.fields.<field>.relatedListTitle (docblock L252–253), drawn "on its PARENT's record page (the side card, or the full-width table of a relatedList: 'primary' list)" (L250–251), and the console derives that list from the served child field (deriveRelatedLists.ts L388–389, consumed by RecordDetailView.tsx). So "a lookup or master_detail field", "its parent's record page" and "the key is the child's too" are each the code's own words. Correct.
  3. The fallback the new row asserts. translateObject overlays the title only when a bundle entry exists and the served value has not diverged from the packaged field (i18n-resolver.ts L4558–4560, under the comment "an untranslated title keeps its authored text", L4554–4557); the docblock says "An authored title with no entry keeps its text; the child's label is never swapped in for it" (L4484–4485); translation.zod.ts L257–261 says the same, and the test pins it ("keeps an untranslated title as authored — never the child object's label", i18n-field-related-list-title.test.ts L91). The absent-title case renders the child's label (deriveRelatedLists.ts L87 and L358 child.label || child.name), which is why the row says "the child's label" where the inlineTitle entry beside it says "plural label": each names what its own surface would otherwise show. The row says nothing about an entry for a field that authors no title (test L96 pins that it is served) — the inlineTitle entry does not either, and the card did not ask for it. So "untranslated it keeps its authored text, never the child's label" states exactly what the code does. Correct.
  4. Which page. The row distinguishes the two sibling keys by surface — inlineTitle "on its parent's form", relatedListTitle "on its parent's record page" — and that is the distinction the spec draws: inlineEdit "edits its rows inline on the parent's form" (field.zod.ts L99, L1891), relatedList is "the read-side mirror of inlineEdit" on "the parent's detail page" (L1950). The wording mirrors the inlineTitle entry as the card asked ("Mirror the inlineTitle wording"). Correct.
  5. Cut, merge-base L348–351 (three lines and the blank after them, 222 bytes): "These schemas back the optional contract methods getCoverage() and suggestTranslations(), which no shipped adapter implements — point coverage workflows at os i18n check / os lint --i18n-strict instead." Fact by fact against the head: the methods are optional and unimplemented → Service Contract, head L379–382 ("The contract also declares optional methods — getFieldLabels, getCoverage, suggestTranslations — that no shipped implementation provides. Treat them as extension points for a custom workbench or TMS adapter."), a superset; coverage workflows go to the CLI → Translation Coverage → os i18n check, head L297–299 ("The working coverage path is the CLI"), L312 ("os lint --i18n-strict folds it in") and L504. Both facts and the instruction survive, and no test under packages/**, scripts/** or skills/** pins the cut text (grep). What does not survive in the file is the tie the first clause made — that TranslationCoverageResult / TranslationDiffItem (head L340–346) are the return shapes of those two methods. The tie is true (contracts/i18n-service.ts L215 getCoverage?(…): TranslationCoverageResult, L228 suggestTranslations?(…): Promise<TranslationDiffItem[]>) and the file now names the schemas in one section and the methods in another with no sentence joining them; the join lives only in the contract's signature, which the Service Contract section imports. A reader at Diff & Coverage Schemas can no longer learn from the skill that no shipped code emits these shapes (the CLI does not use either type: grep over packages/cli/src). The actionable rule survives; the one lost sentence is a cross-reference, not a rule, and headroom is 687 tokens: S1 (④). Measured 222 bytes with its blank line, 221 without, as the body says.
  6. Token ratchet. Measured on both trees: skills/objectstack-i18n/SKILL.md 5646 → 5646 tokens (ceiling 6333, headroom 687 both before and after); exit 0 on both, the self-test passes (97 cases), and the ratchet script is not in the diff so the ceiling row (L515, ['skills/objectstack-i18n/SKILL.md', 6333]) did not move. Bytes 22604 → 22601: the row grows 350 → 569 (+219), the cut takes 222, net −3, as the body's table says. No re-wrap: with L162 removed from both trees and merge-base L348–351 removed, the remainders are byte-identical; the word-diff shows four changed segments, every one inside those lines. Paid line by line. Correct.
  7. Changeset. .changeset/29990-i18n-related-list-title.md: frontmatter '@objectstack/skills': patch; line-initial Clause-②: no and Metadata-protocol: none; prose "Before" (the row listed label, help, placeholder, options, inlineTitle — true at merge-base L162), "Now" (the row adds relatedListTitle, the key sits on the child object's field, an untranslated title keeps its authored text, never the child's label — each confirmed in ①.2–3), and the cut sentence ("Service Contract in the same file says the same" — true of the two facts, ①.5; "No schema, key or behaviour changes" — true, no packages/** path in the diff). @objectstack/skills is published (packages/skills/package.json has no private, files is dist, README.md, CHANGELOG.md) and sync-catalog.mjs copies skills/** into dist/skills/<skill>/SKILL.md (L26–30), so a change to this file ships and a patch changeset is owed — AGENTS.md's rule and the triage note (6619502065) agree, and skip-changeset would have been wrong. Labels on the PR are documentation, size/s, tooling: no skip-changeset. Check Changeset is success on the head, check-empty-changeset exit 0 here. Correct.
  8. Gates re-run here. The 44 derived commands match the dev record's 44. Of those re-run: token ratchet and self-test, skill-id-lint, skill-identifier-liveness, skill-compatibility, skill-frame-sync, role-word, commit-card-trailers, empty-changeset, changeset-no-major all exit 0; governed-merges exit 3 by design. check-adr-0087-registration refuses a verdict here (no tsx), and check-doc-authoring and check-closing-keyword-parity exit 3 PREREQUISITE NOT MET (no typescript, no yaml under the worktree) — each is read from CI, where Lint · repo & tooling gates, Lint · CI, release & engine gates, Lint · docs & code guards and PR-body guards are all success on the head. The dev record lists all 44 at exit 0 after pnpm install and a full build; nothing I could measure contradicts it. Correct.
  9. PR body against the head. First content line Fixes #29990: the card's Ask is three bullets — add the row (done), optionally one example entry (not taken; the body says so and why: about 110 bytes the cut does not cover, and the card marks it optional), pay within the ratchet (done) — so Fixes is the right verb; the only other number in the body is feat(spec): a lookup or master-detail field's related-list title is translatable #29989 as a reference, never beside a closing keyword, and PR-body guards is success. Clause-②: no and Metadata-protocol: none are line-initial and right (no spec, no key). The cited line numbers reproduce: field.zod.ts L1952, field.form.ts L320, translation.zod.ts L248–263, the resolver's docblock L4478–4487 (L4478–4486 here) and overlay "L4552–4561" (the relatedListTitle block is L4554–4561; L4552 is the last line of the inlineTitle block above it — a two-line slip in a range, immaterial). The byte table (22604 / 22601; 5646 / 5646 / 6333), "+219 / −222", "no re-wrap", "No test under packages/** or scripts/** pins the cut text", "44 derived, 44 run" and the ratchet output line all reproduce. Human Minimum: eight items ticked against the template; item 3 drops the template's "pnpm lint passes" half (Lint · ESLint is success on the head, so nothing is hidden), item 6 is reworded to "not touched" (true), item 8 adds that the 维护者速读 block is the repo's own reading aid (pm-dispatch SKILL.md requires that block in Chinese, so true). The model note names no identifier of the claude-… form and no display name with a version — the two shapes the repo's recogniser binds (check-commit-card-trailers.mjs L320, L836–850) — but does carry a model family word in body prose where a tier word would do: S2 (③). Correct except as S2.
  10. Governance. check-governed-merges.mjs --branch HEAD: 1 of 2 paths hits skills/** (the changeset is not on the register), Tier H, 18 changed lines (+13 / −5) under the 3000 threshold, exit 3 as designed; the PR is a draft, no reviews, no assignee, no requested reviewer, auto_merge null, mergeable_state blocked. Landing is the maintainer's hand or an authorized approval; this record does not lift it.

② Semver level

Patch, and the changeset says patch. @objectstack/skills publishes skills/** through dist/skills/<skill>/SKILL.md, so one rule-text row in a published skill is a user-visible fix with no protocol change: Clause-②: no, Metadata-protocol: none, '@objectstack/skills': patch. No packages/spec/src/**, no TypeScript, no skip-changeset; Check Changeset is success on the head.

③ Boundary flags

  • Dev open_questions: none in the body. The body's acceptance notes (the optional example entry not added for want of 110 bytes; the inlineTitle entry left byte-identical; the cut chosen because its two facts have homes in the same file) are each confirmed by the diff and accepted, with the one qualification in ①.5 / S1.
  • S2, the model note: the PR body's sentence on the waived mandate names a model family word. AGENTS.md forbids a model identifier in a PR body; the repo's own recogniser binds the claude-… id shape anywhere and the family-plus-version display name in the trailer pair, and a bare family word in prose is neither, so no gate reads it and PR-body guards is success. The pm-dispatch claim template still says to write a tier word and never a model id; the cheaper spelling is "developed at the waived tier" or the constant's name. No rule text I was fed (AGENTS.md, the pm-dispatch skill and its references) carries the "mandate for skills/**" the claim calls clause ①; its only trace is the maintainer's quoted ruling in the claim comment, which is a verbatim ruling and exempt. Should-fix, not a blocker.
  • Independence: PR author objectstack-fleet[bot], commit author Claude; no off-relay author note is owed. The PR thread carries the seat's Contract-review-claim: for this head (6630726780) and no other record; no review seat is seated, as the claim says. No assignee or requested reviewer on the PR.
  • Tier H: this record does not lift the landing; the maintainer's hand or an authorized GOVERNED_APPROVERS approval does, and none is on the PR (reviews: none). The one in-progress shard (①.10, below) must be read green before any Tier H act.
  • Pre-existing, not this PR's: the inlineTitle entry says the inline grid is one "a master_detail field draws", matching field.form.ts L327 (master_detail only), while translation.zod.ts L234–235 says "a master_detail / lookup field with inlineEdit". The entry is byte-identical here and the card did not ask for it; whichever surface is right, it is a spec-face question for the spec lane, not a skills follow-up this PR owes.

④ Design judgment

Per hits file, against the card's scenario (an author or agent learning the bundle shape from the skill must find the relatedListTitle slot, know which object's bundle holds it, and know that an untranslated title stays as authored — the self-lookup case #29942 fixed) and the code on main:

  • skills/objectstack-i18n/SKILL.md, the fields.{field_name} row: adding the key as a sixth entry in the same cell, directly after inlineTitle and in its exact grammar (surface, owner, fallback), is the right place and the right form — the cell is where an author looks up what a field's bundle entry may hold, and the two sibling keys now read as a pair that differs in one word each (form / record page; plural label / label), which is precisely the distinction the spec draws. The cell is long, but every clause of the new entry earns its place: the two field types that draw a related list, the surface, the child-owned address (the fact Record page v3: a related list's title cannot be translated, so a self-lookup list on a contract page reads 「合同」 in zh-CN #29942 was about), and the no-swap fallback. Holds.
  • skills/objectstack-i18n/SKILL.md, the Diff & Coverage Schemas cut: a same-file restatement whose two facts and whose instruction each survive at L379–382 and L297–312 — the lane's test (a cut whose content has no other home loses a rule) is met for the rule. What the cut loses is a cross-reference: that the two schemas named in L340–346 are the return shapes of the two unimplemented methods named in L379–382. The file now presents the schemas as "coverage results for tooling" without saying that no shipped tool emits them; the Service Contract section covers the methods but not the schemas. Holds, with S1.

Must-fix: none. Should-fix: S1 — restore the schema-to-method tie in one clause, in either home: at L340, "The spec models coverage results for tooling — the return shapes of the optional getCoverage() / suggestTranslations() (see Service Contract below):", or at L379–380, "getCoverage (returning TranslationCoverageResult), suggestTranslations (over TranslationDiffItem[])". About a dozen tokens against 687 of headroom; no ceiling row moves. S2 — the PR body's model note (③): spell the waiver with a tier word, as the claim template asks, and leave the family word to the maintainer's quotation.

Check-runs at record time (2026-11-04T12:47Z): 40 check-runs on 284424b, 26 success, 13 skipped, 0 failure, 1 in progress on the third read (Test Core 1/8); three reads went 38 → 40 → 40 runs and 15 → 25 → 26 success with no non-success completion at any read (the first read had ten in progress: Test Core 1/8 and 2/8, Type Check · source gates, Type Check · consumer gates, Lint · CI, release & engine gates, Lint · repo & tooling gates, Lint · ESLint, Lint · docs & code guards, and the two umbrella jobs; all but Test Core 1/8 completed success). Success: Lint & Repo Gates, TypeScript Type Check (the two required floors), Lint · repo & tooling gates, Lint · CI, release & engine gates, Lint · PM dispatch-gates, Lint · docs & code guards, Lint · ESLint, Lint · scoped · tooling self-tests, Lint · scoped · slot lookup & corpus, Lint · scoped · query-options erasure, Type Check · workspace / source gates / debt ledger / consumer gates, Build Core, Governed Surface Queue Guard, Dogfood Regression Gate, Test UI, Test Core (2/8), Plan Test Core shards, Live E2E UI, PR-body guards, Check Changeset, Check PR Size, Auto Label, filter. Skipped by path filter or opt-in: Build Docs, Build UI Deps, Build & E2E UI, Lint UI, Type Check UI, UI Published Artifacts, Dogfood Verify CLI, Temporal Conformance, Schedule gate, 18.x upgrade harness, Packed-tarball smoke, and the matrix-templated placeholder rows for Test UI and the Dogfood shards. Combined status pending (statuses API, 0 statuses). The one in-progress shard is a full-battery test lane on a diff that touches no package source; the landing pre-check still owes a read of it green before any Tier H act. mergeable_state blocked, draft, auto_merge null, labels documentation, size/s, tooling; Tier H (skills/**), landing by the maintainer's hand or an authorized approval, not by this record.

Implemented-by: claude/project-thread-2cn4ji
Reviewed-by: session_01J8VVAnMUWA9rufXzFaEh4J

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J

Contract-review-claim: session_01J8VVAnMUWA9rufXzFaEh4J · head 290d1fc · 2026-11-04T13:02Z

The seat delta review (against 6630998230 S1 and S2) runs at CONTRACT_REVIEW_TIER in an isolated subagent (the seat session is not at that tier). No review seat (lanes/review.md) is seated.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 290d1fc0aa4c1dbf877a1b3f3885136b5e458a64
Local-runs: probe — on a detached worktree of the head (merge-base with origin/main still c23501b; origin/main at d79eecf when fetched): node scripts/check-skills-token-ratchet.mjs (exit 0: skills/objectstack-i18n/SKILL.md 5673 / 6333, headroom 660) and --self-test (exit 0, 97 cases); node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD (exit 0, two commits, no card relation and no model identifier in either trailer pair); wc -c / wc -l on the head file and on the same file at 284424b; git diff --stat and git diff --word-diff=porcelain of the delta (one changed segment, inside L340); git diff --stat -- scripts/ over the delta (empty); gh api REST reads of the PR, its files, commits, comments and reviews, comment 6630998230, and the head's check-runs twice. The worktree was removed after the runs and the main checkout was not touched.
Scope: skills/objectstack-i18n/SKILL.md L340 (the governed hit; the one changed line) + read, not reviewed: .changeset/29990-i18n-related-list-title.md L12 (the prose face, the one changed sentence), packages/spec/src/contracts/i18n-service.ts L215 and L228 (getCoverage? / suggestTranslations? and their return types), skills/objectstack-i18n/SKILL.md L352 and L379–382 (the Service Contract heading and its optional-methods sentence), packages/spec/src/system/i18n-resolver.ts L4546–4562 (the inlineTitle and relatedListTitle overlays, for the body's range), scripts/check-skills-token-ratchet.mjs L515 (the ceiling row), scripts/check-commit-card-trailers.mjs L320 and L836–850 (what the repo counts as a model identifier), PR #30068 body and comments 6630726780, 6630998230 (the full review being continued) and 6631340146 (the seat's claim on this head), the dev gate record pr-29990/gates-290d1fc0.txt (read as input)
Delta review of 6630998230 on 284424b8

Reviewer: the same isolated contract reviewer at CONTRACT_REVIEW_TIER, read-only on GitHub (REST reads only; nothing written, pushed or commented). The full review on 284424b (PASS, should-fixes S1 and S2) stands as read; this record judges only the delta 284424b8..290d1fc0 and the PR body as it now reads. The dev gate record was read as input, not as conclusions. No environment variable value is printed anywhere in this record.

① Derived judgments

  1. Delta surface. One new commit (290d1fc, author Claude, subject "docs(skills): tie the i18n coverage schemas to the optional methods that return them", trailers Co-authored-by: Claude <noreply@anthropic.com> + Claude-Session:, no model identifier). git diff --stat 284424b8 290d1fc0: two files, +2 / −2, both already in the PR — skills/objectstack-i18n/SKILL.md one line (L340) and .changeset/29990-i18n-related-list-title.md one line (L12). The REST file listing now reads +2/−6 and +12/−0 (cumulative +14 / −6, 2 files), consistent with the merge-base diff plus this delta. Nothing new is touched; the ratchet script is not in the delta (git diff --stat -- scripts/ is empty). Correct, and on surface.
  2. S1, the tie. Head L340 now reads "The spec models coverage results for tooling — the return shapes of the optional getCoverage() / suggestTranslations() (see Service Contract below): TranslationCoverageResult" and continues unchanged into L341–346. Against the contract: getCoverage?(locale: string, objectName?: string): TranslationCoverageResult (i18n-service.ts L215) and suggestTranslations?(locale: string, items: TranslationDiffItem[]): Promise<TranslationDiffItem[]> (L228) — both optional (?), the first returning TranslationCoverageResult, the second resolving to TranslationDiffItem[]. So "the return shapes of the optional getCoverage() / suggestTranslations()" is the contract's own signature, and it is the first of the two spellings S1 offered, verbatim. The cross-reference resolves: ### Service Contract is at head L352, below L338's ### Diff & Coverage Schemas, and its L379–382 is where the two methods are named as unimplemented. The word-diff of the delta has exactly one changed segment (tooling: → tooling — … below):), so no other line in the file moved or re-wrapped; lines 520 → 520. The lost cross-reference ①.5 of 6630998230 described is restored in one clause. S1 resolved.
  3. Token ratchet. Measured on the head: skills/objectstack-i18n/SKILL.md is 5673 tokens (ceiling 6333; headroom 660), exit 0, self-test 97 cases pass. Bytes 22601 (284424b) → 22712 (head), +111, which is the added clause and nothing else. The ceiling row (L515, ['skills/objectstack-i18n/SKILL.md', 6333]) is byte-identical and the script is not in the delta, so no CEILINGS row moved. 5646 → 5673 is +27 tokens against the 687 of headroom the full review named; about twice the "dozen" S1 estimated, still paid inside the file's ceiling. Correct.
  4. Changeset. Frontmatter '@objectstack/skills': patch unchanged; line-initial Clause-②: no and Metadata-protocol: none unchanged; the "Before" and "Now" bullets unchanged. The third bullet gains one clause: "and the section's opening sentence now names the two schemas as those methods' return shapes" — true of head L340 (①.2). "No schema, key or behaviour changes" remains true (no packages/** path in the diff). Correct.
  5. S2, the PR body. The waiver sentence now reads "The maintainer waived the model-tier mandate for skills/** while that tier had no quota; this PR was developed below it." A grep of the body for claude-, the four family words the repo's recogniser lists as fixtures (check-commit-card-trailers.mjs L836–850), and "model" finds: the harness's <!-- claude-projects-attribution: … --> marker (an attribution comment the harness writes, present unchanged on 284424b where the full review did not read it as a model identifier and PR-body guards was success), the words "model-tier mandate" (a tier phrase, no family word), the "Claude Code" product name in the generated footers, and no family word or claude-… id anywhere. S2 resolved.
  6. PR body, other updated claims against the head. Head line: "Head 290d1fc0 (two commits on c23501b2; 284424b8 is the reviewed head, 290d1fc0 adds the S1 clause and its changeset sentence)" — merge-base is c23501b and the PR has exactly these two commits (REST). Byte table "22604 / 22712" and "5646 / 5673 / 6333 (headroom 687 → 660)" reproduce (22604 is the merge-base file per the full review; 22712 and 5673 / 660 measured here). The 速读 block's "+111 字节" and "5646 → 5673 tokens, 上限 6333 未动, 无 re-wrap" reproduce. The S1 paragraph quotes the new L340 clause exactly and cites i18n-service.ts L215, L228 (①.2) and "(L340)", all correct; "Only that line changed; no other line is re-wrapped" is the word-diff's finding. The resolver range now reads "L4554-4561": the relatedListTitle block in i18n-resolver.ts is the comment at L4554–4557 plus the if at L4558–4561 — the two-line slip the full review noted is corrected. The Tests line quotes the ratchet output exactly. Gate summary "44 derived, 44 run with exit 0, 0 NOT MEASURED each time" plus pnpm check:changeset-fixed separately: the dev record for this head has 45 lines, all :: exit 0, of which one is check:changeset-fixed — 44 + 1, consistent. The docblock range "L4478-4487" is unchanged from the reviewed head (the full review read it as L4478–4486; one-line, immaterial, not in this delta). Correct.
  7. Commit trailers and head check-runs. check-commit-card-trailers.mjs --range origin/main..HEAD: exit 0, "2 commit message(s) … carry no card relation and no model identifier in the trailer pair". Head check-runs on two REST reads: 44 runs, 28 success, 15 skipped, 1 in progress (Test Core 1/8), 0 failure, 0 other non-success; combined status pending (statuses API, 0 statuses). Success includes the two required floors (Lint & Repo Gates, TypeScript Type Check), PR-body guards (both rows), Check Changeset (both rows), Governed Surface Queue Guard, Check PR Size, Lint · repo & tooling gates, Lint · PM dispatch-gates, Lint · docs & code guards, Build Core, Test Core (2/8), Test UI, Live E2E UI. Nothing red; one pending, the same full-battery shard that was pending on the prior head. Correct.
  8. Review state on this head. The PR thread carries the seat's Contract-review-claim: for 290d1fc (6631340146) and no record; reviews: 0; draft, auto_merge null, mergeable_state blocked, labels documentation, size/s, tooling. Tier H (skills/**) still; this record does not lift the landing.

② Semver level

Unchanged: patch, and the changeset still says patch. The delta is one clause in a published skill and one sentence in the changeset's prose; Clause-②: no, Metadata-protocol: none on both the body and the changeset; no packages/spec/src/** path; Check Changeset success on the head.

③ Boundary flags

  • S1 of 6630998230: resolved at head L340 in the first spelling offered, cross-reference resolving to L352, no re-wrap, ceiling row unmoved (①.2–3).
  • S2 of 6630998230: resolved; the body spells the waiver with a tier phrase and carries no model family word or id (①.5). The claude-projects-attribution HTML comment is the harness's attribution marker, unchanged from the reviewed head, and not a model identifier.
  • Dev open_questions: none in the body. The body's "Per the contract review's S1" paragraph is a correct account of what changed and why.
  • Independence: PR author objectstack-fleet[bot], commit author Claude on both commits; no off-relay author note is owed. No review seat is seated (6631340146); no assignee, requested reviewer, or review on the PR.
  • Tier H: the one in-progress shard (Test Core 1/8) must be read green before any Tier H act; landing is the maintainer's hand or an authorized GOVERNED_APPROVERS approval, not this record.
  • The pre-existing inlineTitle / lookup surface question noted in ③ of the full review is unchanged and not this PR's.

④ Design judgment

Per hits file, for the delta only:

  • skills/objectstack-i18n/SKILL.md L340: the clause sits where a reader meets the two schemas and tells them, in the contract's own words, which methods return them and that those methods are optional, then points at the section that says no shipped code implements them. That is exactly the cross-reference the cut at merge-base L348–351 removed, restored at a quarter of its cost (+111 bytes against −222) and in the section the full review named first. The second spelling (annotating L379–380 instead) would have left the schemas section silent again, so this is the better of the two homes. The line is now long (one wrapped physical line against the file's ~80-column habit), but the ratchet prices tokens, not columns, and re-wrapping the paragraph would have been the re-wrap the lane forbids. Holds.

Must-fix: none. Should-fix: none remaining — S1 and S2 of 6630998230 are both resolved on this head.

Check-runs at record time: 44 check-runs on 290d1fc, 28 success, 15 skipped, 0 failure, 1 in progress (Test Core 1/8) on both reads; combined status pending (0 statuses). mergeable_state blocked, draft, auto_merge null; Tier H (skills/**), landing by the maintainer's hand or an authorized approval, not by this record, and only after Test Core (1/8) is read green.

Implemented-by: claude/project-thread-2cn4ji
Reviewed-by: session_01J8VVAnMUWA9rufXzFaEh4J

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J

维护者速读

席位核对 — ACCEPT · domain:skills#1 · head 290d1fc0aa4c1dbf877a1b3f3885136b5e458a64

  1. 形态: draft → main,Fixes #29990;作者 objectstack-fleet[bot];文件在认领面内,附 @objectstack/skills patch changeset(⛔ 不挂 skip-changeset)。
  2. 前提实测: 复核逐条对过 field.zod.ts、field.form.ts、translation.zod.ts、i18n-resolver.ts 与 i18n-service.ts。
  3. 门禁(钉 head 290d1fc0): check-runs success 28 / skipped 15 / 进行中 1(Test Core 1/8),无失败;落地前检须读到全绿。派生门禁 44 条全过。
  4. 接受的偏差: 开发在低于规定档位的模型上进行,依维护者原话(无额度时豁免)。
  5. 范围外去向: 复核提到 inlineTitle 一项的字段类型说法与 translation.zod.ts L234–235 不一致,是此前就有的 spec 面问题,不是本 PR 的;留在复核记录里,不另立卡。
  6. 落地条款: Tier H。保持 draft,挂 needs-user-decision,同轮请 os-zhuang、hotlong 审批;获批后本席过落地前检、清标、ready、auto-merge;维护者直合亦可。

Generated by Claude Code

@objectstack-fleet objectstack-fleet Bot added the needs-user-decision Blocked on a maintainer decision — do not dispatch; decision cards only, never on a PR label Nov 4, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review November 4, 2026 13:12
@os-zhuang
os-zhuang added this pull request to the merge queue Nov 4, 2026
Merged via the queue into main with commit 0ce44c9 Nov 4, 2026
51 checks passed
@os-zhuang
os-zhuang deleted the claude/project-thread-2cn4ji branch November 4, 2026 13:30
@objectstack-fleet objectstack-fleet Bot removed the needs-user-decision Blocked on a maintainer decision — do not dispatch; decision cards only, never on a PR label Nov 4, 2026
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/s tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

skills/objectstack-i18n: the fields.{field_name} row misses relatedListTitle, the bundle slot #29942 adds

2 participants