Skip to content

Correct 17 false behavioral claims in skills/objectstack-i18n — sweep flight ⑧ - #13833

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-13815-skills-sweep-i18n
Aug 31, 2026
Merged

Correct 17 false behavioral claims in skills/objectstack-i18n — sweep flight ⑧#13833
os-zhuang merged 2 commits into
mainfrom
claude/issue-13815-skills-sweep-i18n

Conversation

@huangyiirene

Copy link
Copy Markdown
Collaborator

Fixes #13815
Part of #13658

Flight ⑧ of the published-skills factual sweep: skills/objectstack-i18n/** (3 files, 807 lines at branch point). Every claim was settled against the implementing code plus an executed probe — never against another document. 17 distinct false facts across 20 landing sites; net −8 lines, −2 tokens (SKILL.md 6337/6338, evals/README.md 410/411 — both shrink, no ceiling touched).

references/_index.md is generator-owned and was not hand-edited; check:skill-refs is green against it.

Where the truth was read

Fact class Implementing code
bundle / item / config shapes packages/spec/src/system/translation.zod.ts
service contract packages/spec/src/contracts/i18n-service.ts
shipped adapters packages/services/service-i18n/src/{file-i18n-adapter,i18n-service-plugin}.ts · packages/core/src/fallbacks/memory-i18n.ts
authored-item sync packages/core/src/fallbacks/authored-translation-sync.ts
CLI coverage / extract packages/cli/src/commands/i18n/{check,extract}.ts · packages/cli/src/utils/i18n-{coverage,extract}.ts
orphan-key lint packages/lint/src/validate-translation-references.ts
shipped examples examples/app-crm/src/translations/ · examples/app-todo/src/translations/

Per-item corrections

# 落点 before after
1 SKILL.md · Object-Level table "Object-level text (label is required)" "Object-level text (every key optional)" — label: z.string().optional(), with a schema comment arguing partial translation is the normal state
2 SKILL.md · Object-Level table no _tabs row added _tabs.{tab_name} — a live authorable surface (resolveTabLabel), extracted and coverage-gated
3 SKILL.md · Object-Level table _actions holds label, confirmText, successMessage, params, resultDialog description added — declared on the action translation shape
4 SKILL.md · Object-Level table _sections holds "Form section / tab label" "Form section label" — tabs are their own group, now row 2 above
5 SKILL.md · "Top-level groups alongside objects" apps, messages, globalActions, dashboards, settings, metadataForms, settingsCommon pages and flows added — 10 groups on the shape, not 8
6 SKILL.md · Core Concepts 1 same list minus settingsCommon, and object content omits tabs both lists brought to the shape's real membership
7 SKILL.md · Authoring at Runtime "skipped by the runtime sync — a silent skip … rather than inferred from the item name" the sync falls back to a BCP-47-looking item name, then skips with an [i18n] … — skipped warning naming the row. Not silent
8 SKILL.md · "Retired: the o.* dialect" "rejected at save time with a message naming the group to use instead" "both doors now reject it — files included". 4 of the 10 keys are told they have no home (reports, notifications, errors, namespace), so "naming the group to use instead" was false for them
9 SKILL.md · Pitfall "The Retired o.* Shape" "Files registered in that shape resolve to nothing; runtime items … rejected at save time" both doors reject: defineTranslationBundle throws on a file bundle. The file door was closed at the same time as the item door
10 SKILL.md · os i18n check "reports missing object/field/option/view/action keys" every surface the extractor walks — 14 source kinds live, 5 were named
11 SKILL.md · Extract skeletons "writes {locale}.objects.generated.ts … Other flags: --default-locale, --filter, --dry-run, --json" the {locale}.metadata-forms.generated.ts companion is written by default; four more flags exist (--no-merge, --no-objects-only, --metadata-forms, --source-hashes), so the list now points at --help instead of claiming to be complete
12 SKILL.md · "Use both gates" "Renaming a label, adding an object, or removing a spec key leaves coverage at 100%" adding an object lowers coverage — its keys join the expected set. Dropped from the trio
13 SKILL.md · II18nService methods getLocales() / getDefaultLocale() / setDefaultLocale() setSupportedLocales() added — on the contract and implemented by both shipped adapters
14 SKILL.md · II18nService optional methods "getCoverage, suggestTranslations — no shipped implementation provides" getFieldLabels added — same class exactly: declared optional, probed by both serving surfaces, implemented by no shipped provider
15 SKILL.md · Diff & Coverage Schemas TranslationDiffItem = key, status, locale, sourceHash, AI fields optional objectName added
16 SKILL.md · orphan-key lint "object, field, view, action, param, section, app, nav item, dashboard or widget" flow screens added — the rule walks flows.{name}.screens.{node} too
17 SKILL.md · Authoring Translation Bundles "mirrors the shipped example apps ({en,zh-CN}.ts + index.ts)" that is examples/app-todo alone, and it ships three locales
18 SKILL.md · CRM I18n Blueprint "Bundle entry: src/translations/index.ts … Locale files: {en,zh-CN,ja-JP,es-ES}.ts" examples/app-crm has one file, crm.translation.ts, holding en + zh-CN. No index.ts, no per-locale files, no ja-JP/es-ES
19 SKILL.md · CRM table "per-locale source files by convention" · "imports per-locale files" · objects.account.fields.* the CRM example does none of these; its object is crm_account
20 SKILL.md · Pitfall "Ignoring Coverage Reports" "Stale translations can cause confusion. Always run os i18n check" coverage cannot see staleness — this document's own extract --check section says so. Now points at the gate that can
21 evals/README.md · rubric "runtime objects.* vs secondary o.* format" "retired o.* is rejected" — a grader taught the retired dialect is a live secondary format fails correct answers
22 evals/README.md · rubric "ICU is experimental" "no ICU engine" — the messageFormat knob was removed and nothing evaluates ICU strings

Rows 4, 6, 19 are the second landing sites of facts 2, 5 and 18; 17 distinct facts, 20 sites, plus 2 rubric rows.

Executed evidence

Two probe scripts (temporary, removed before commit — this diff is 2 markdown files). Built first: @objectstack/service-i18n..., @objectstack/lint..., @objectstack/platform-objects... (exit 0 each), so every read is against rebuilt dist, not stale declarations.

Schema/adapter probe, run from packages/services/service-i18n:

=== TranslationDataSchema top-level groups ===
["objects","apps","messages","globalActions","dashboards","pages","flows","settings","metadataForms","settingsCommon"]

=== ObjectTranslationDataSchema sub-keys ===
["label","pluralLabel","description","fields","_views","_actions","_sections","_tabs"]

=== object _actions sub-keys ===
["label","description","confirmText","successMessage","params","resultDialog"]

=== is objects.OBJ.label REQUIRED? ===
parse { objects: { task: { pluralLabel } } } (no label) -> success=true

=== retired o.* dialect ===
  item.o: rejected=true :: `o` is the retired object-first dialect … use 'objects.OBJECT_NAME'
  item.reports: rejected=true :: `reports` … reports have no translation group, omit them
  bundle-door o: rejected=true
  defineTranslationBundle({ en: { o: … } }) -> threw

=== interpolation ===
  double: Welcome, Alice!        single: Hi, {userName}!        icu: messages.icu   (key echoed)

=== contract methods on both shipped adapters ===
  setSupportedLocales  file=true   memory=true
  getFieldLabels       file=false  memory=false
  getCoverage          file=false  memory=false
  suggestTranslations  file=false  memory=false

CLI probe (tsx, packages/cli), driving the real walker and coverage detector:

=== ExpectedEntry.source kinds the walker emits ===
  action 7 · app 1 · dashboard 1 · field 6 · flow 2 · globalAction 4 ·
  metadataFormField 948 · metadataFormSection 150 · metadataType 54 ·
  navigation 1 · object 3 · option 1 · page 1 · view 1 · widget 1

=== _tabs IS harvested ===
  objects.task._tabs.urgent.label   [source=view]
  flows.onboard.screens.welcome.title   [source=flow]

=== os i18n check reported source kinds ===
  action, app, dashboard, field, globalAction, metadataForm, navigation,
  object, option, page, view, widget      (12 kinds from one small fixture)

=== --strict promotes non-default gaps ===
  lax    errors=0   warnings=783
  strict errors=783 warnings=0

The non-vacuity control is satisfied many times over: facts 1, 2, 3, 5, 8, 9, 10, 13, 14 were each decided by a run, not a read.

Gates — all run at 5d16fd477 (the final commit)

Families derived from the real diff with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (exit 0; 14 families, re-derived unchanged on the final commit), plus the skill-specific gates the derivation scores silent because they compute their own population:

gate exit
check-ci-filter-parity · check-cross-package-test-inputs · check-shard-attestation 0 · 0 · 0
check-skills-token-ratchet 0 — SKILL.md 6337/6338 (−1), evals/README.md 410/411 (−1)
check:doc-formula-expressions · check:agent-test-spelling · check:corpus-claim-drift 0 · 0 · 0
check:cross-package-test-inputs · check:doc-authoring · check:pm-governed-merges 0 · 0 · 0
check:role-word · check:skill-compatibility · check:skill-frame-sync 0 · 0 · 0
check:nul-bytes · check:pm-skill-ratchet · check:pm-skill-id-lint · check:skill-frame-freshness 0 · 0 · 0 · 0
@objectstack/spec check:skill-examples 0 — 260 marked blocks across 101 files, population non-empty (this package contributes 4 os:check fences)
@objectstack/spec check:skill-refs · check:skill-docs 0 · 0
pnpm lint (repo-wide eslint . --no-inline-config) 0
check-test-completeness 3 — NOT MEASURED. The gate grades a saved turbo run test log and none exists locally; its own text says exit 3 "is not a red, and there is nothing here to fix"

ESLint was run whole rather than narrowed, and separately measured: both changed files report File ignored because no matching configuration was supplied — markdown is outside the linted population entirely (no files block in eslint.config.mjs names .md).

Pure skills/** diff, nothing published from any package — skip-changeset applies, matching flights ③/④/⑤ which landed the same shape with no changeset.

Governed surface

Published skills/**: this PR stays draft and is for the maintainer to merge. needs:contract-review is attached to this PR and to card #13815 in the same stroke (批 #12 clause ② CONTENT limb) and is never self-cleared.

Generated by Claude Code


Generated by Claude Code

claude added 2 commits August 31, 2026 14:03
…implementation

Flight 8 of the published-skills factual sweep (#13658). Every correction is
settled against the implementing code plus an executed probe; net -1 line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EnE7G31tqbxN1rqpQmzurT
…en ratchet

The corrections in the previous commit were factually right but grew SKILL.md
by 124 tokens against a ceiling that only ever shrinks. Same facts, fewer
bytes: enumerations point at the authority instead of transcribing it, and
duplicated prose around the retired o.* dialect is stated once.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EnE7G31tqbxN1rqpQmzurT

Copy link
Copy Markdown
Collaborator Author

Contract review — PASS at head 5d16fd477

Applicability: clause-② CONTENT limb (批 #12). Both carriers attached at PR creation, delayed read-backs clean; cleared in this stroke.

Reviewer qualification, machine-read this sitting: get_sessionexternal_metadata.last_served_model = claude-fable-5 = CONTRACT_REVIEW_TIER.

Review: report + diff read; anchors independently re-measured on origin/main this hour —

  • _tabs is a live, gated slot: ObjectTranslationDataSchema declares it, packages/cli/src/utils/i18n-extract.ts:590–611 emits objects.<o>._tabs.<tab>.label for every rendered preset tab, and resolveTabLabel consumes it — the missing table row hid shipped capability;
  • pages is harvested by the same extractor (:563) — the top-level group list was under-enumerating;
  • setSupportedLocales is in the contract (packages/spec/src/contracts/i18n-service.ts:97) and implemented on BOTH shipped adapters (file adapter + packages/core/src/fallbacks/memory-i18n.ts) — the method-list omission was false;
  • The dev's parse probe disproving "label is required" ({objects:{task:{pluralLabel}}} parses green) and the LEGACY_OBJECT_FIRST_KEYS double-door rejection are executed evidence in both error directions, with the non-vacuity control satisfied many times over.

Program-significant: 8.5%/10% density — the highest measured in eight flights, and the dev's sharper class naming ("an enumeration that stopped growing when the schema did", 15 of 20 sites) supersedes the table-shape heuristic; recorded on the anchor. Out-of-scope findings verified real: #13835 (lint _tabs orphan leg missing, the accepted #11608 shape one group over) and #13837 (CLI --help under-count — the #13809 spec-twin pattern applied to a CLI surface). Budget: net −8 lines / −2 tokens, both files shrink, no ceiling touched; generator-owned index untouched, check:skill-refs green; whole-repo pnpm lint run un-narrowed, exit 0.

needs:contract-review cleared on BOTH carriers. Governed .md content: PR remains DRAFT for the maintainer's merge (os-zhuang / hotlong requested).


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review August 31, 2026 15:43
@os-zhuang
os-zhuang enabled auto-merge August 31, 2026 15:43
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 31, 2026
Merged via the queue into main with commit 05ef23e Aug 31, 2026
40 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-13815-skills-sweep-i18n branch August 31, 2026 16:02
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 skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

skills-sweep ⑧: objectstack-i18n (807 lines, 3 files) — behavioral-claim verification, content-class execution-first

3 participants