Repository navigation
spec(i18n): the one authority for TranslateFn — the narrowed-t shape — lands in @object-ui/i18n; app-shell and fields re-export it #8261
Description
Activity
- addeddomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seat
on Sep 7, 2026 objectstack-fleet commented
on Sep 25, 2026 ContributorMore actionsClaim: PM loop round 6 —
domain:uiexecution seat 2
Session:session_014mXUNuFomfj24w7s1pZzhN
Branch:claude/issue-8261-translatefn-authority
Worktree:objectui-issue-8261
Domain:domain:ui
Seat:domain:ui#2
File surface:packages/i18n/src/(declare and exportTranslateFnfrom the package's public entry),packages/app-shell/src/providers/writeWarningToast.tsandpackages/fields/src/widgets/file-size-guard.ts(type re-exports of it),scripts/__tests__/one-authority-per-exported-name-6273.test.ts(theKNOWN_COLLISIONSrow forTranslateFnshrinks to zero sites / is removed), tests, one changeset ('@object-ui/i18n': minorfor the newly published name;'@object-ui/app-shell': patch,'@object-ui/fields': patch). Stop on breach and explain it in the report
Container & model:S,mode:subagent,model: opus—dispatch-gates --tier: 「no path-derived mandate … floor sonnet · default opus · ceiling fable」; executes the maintainer's ruling on objectui#8165 (5565867673, decision batch #72, option A), which this card carries
Clause-②: yes —@object-ui/i18npublishes a new name,TranslateFn
Thread-read: none
Serial constraints cleared: open-PR file lists read 2026-09-25T16:05Z: no open PR touchespackages/i18n/src/index.ts,writeWarningToast.ts,file-size-guard.tsor the one-authority gate.check-governed-queue-guard.mjs --test: NOT GOVERNED. objectui#8203 (the other nine names) is NOT in this card; it follows after this lands, as the card says.Clause-②: yes— a shared package publishes the one authority for a type two packages declare locally today; the two local declarations become re-exports of it, and no call site's contract moves (re-measured byte-identical before re-pointing).
Generated by Claude Code
objectstack-fleet commented
on Sep 25, 2026 ContributorMore actionsos-dev-report
{ "issue": 8261, "status": "done", "branch": "claude/issue-8261-translatefn-authority", "pr": "https://github.com/objectstack-ai/objectui/pull/10703", "session": "session_014mXUNuFomfj24w7s1pZzhN — mode:subagent, the dispatching PM's id; identity is the branch named in claim 5835312654", "premise_still_valid": true, "summary": "Option A is executed. packages/i18n/src/translateFn.ts declares TranslateFn once, and the i18n entry (src/index.ts, whose built output is exports['.'].types ./dist/index.d.ts) publishes it with export type. The two remaining declarations, app-shell providers/writeWarningToast.ts and fields widgets/file-size-guard.ts, now import type it and re-export it from @object-ui/i18n. saveAdvisoryToast.ts and metadataReadWarningToast.ts point at @object-ui/i18n directly: their docblocks named writeWarningToast as the owner and had to be rewritten anyway. The local, unexported TranslateFn in preview/usePublishAllDrafts.ts is also re-pointed; it differs only in its parameter NAME (opts), which TypeScript does not compare. The TranslateFn row leaves KNOWN_COLLISIONS. H2 byte identity held on base c659439b4 (sha256 29f2f334..., 86 bytes with the newline, cmp 0), so no call site's contract moves. H3: app-shell and fields already depend on @object-ui/i18n (workspace:*) and i18n depends only on core, which depends only on types, so there is no cycle and no package.json changed. Draft PR #10703 is open with a closing first line naming this card and a Clause-② line copied from the claim. The PR assignee os-elon-musk was set and read back. The card's assignee was never written.", "tests": "All at head 367e586e4. Heavy runs went through os-verify-lock.sh; verdicts are its VERDICT lines and timings are shared-box seconds. (1) Closure build: turbo run build --filter='@object-ui/app-shell^...' --concurrency=2 gave 'Tasks: 28 successful, 28 total', VERDICT command-exit 0. (2) type-check (tsc --noEmit plus tsc -p tsconfig.test.json, script echo confirmed) exited 0 with zero 'error TS' lines for @object-ui/i18n, @object-ui/fields and @object-ui/app-shell; pnpm type-check:scripts also exited 0. (3) Built .d.ts: packages/i18n/dist/index.d.ts has TranslateFn 1 ('export type { TranslateFn } from ./translateFn.js') against control SafeTranslate 2; dist/translateFn.d.ts carries the declaration; packages/fields/dist/index.d.ts has TranslateFn 0 against control FileField 2. (4) vitest run over the gate, packages/i18n/, app-shell providers/ + preview/ + console/home/__tests__/ + MetadataService.saveAdvisories + useMetadataClient.advisorySink, and the 28 fields tests naming a file-size-guard consumer: 'Test Files 149 passed (149), Tests 2616 passed (2616)', VERDICT command-exit 0. (5) Gate before, on a detached base worktree at c659439b4 with 1 TranslateFn row: 'Test Files 1 passed (1), Tests 11 passed (11)'. Gate after, at head with 0 rows: 'Test Files 1 passed (1), Tests 11 passed (11)'. (6) Ablation through objectstack scripts/ablation-replace.mjs in wrap mode, anchors hit x1 to x0 and blobs moved on disk. LEG A put the declaration back in file-size-guard.ts (blob ca873659cf07 to 6e625184bee3): gate exit 1, 'TranslateFn — a NEW colliding name', sites packages/fields/src/widgets/file-size-guard.ts and packages/i18n/src/translateFn.ts, then the SHRINK-ONLY refusal. LEG B put the row back with the re-points kept (blob 600bed9be040 to 38991d28dc31): gate exit 1, 'KNOWN_COLLISIONS lists collisions that no longer exist ... TranslateFn — no longer collides at: writeWarningToast.ts, file-size-guard.ts', which proves the row removal was owed. LEG C was the type reverse-verification: a probe 'export const typeProbe8261: TranslateFn = (key: number) => String(key);' made fields tsc --noEmit exit 1 with exactly one error, TS2322 'Type (key: number) => string is not assignable to type TranslateFn'. Restore was proven by state: disk blob equals HEAD blob for both paths (ca873659cf07, 600bed9be040), git diff HEAD is empty, and afterwards declarations 0, re-exports 1, rows 0. (7) README snippet compiled with tsc --strict against the built i18n dist: exit 0; the negative control t(42) gave exit 2 with TS2345. (8) Gates: check-changeset-presence exit 0 ('7 source file(s) of 3 released package(s) changed ... declares 1 changeset'); changeset-no-major 0; changeset-fixed 0; changeset-overwrite 0 (report-only; lists the 8165 prose correction as case 2, both sides declaring nothing); check:new-line-citations 'VERDICT new-cross-file-line-citations: 0 new citation(s)'; check:control-bytes OK (8784 files); doc-fences 0; check-doc-links 0; check:readme-exports 0 (TranslateFn judged real from @object-ui/i18n; 8 other packages unbuilt and unjudged locally); phantom-deps 0; unused-deps 0; unreferenced-sources 0; pending-changeset-literals 0; i18n-keys 0; esm-specifiers 0; governed-queue-guard --test on the 11 paths reads NOT GOVERNED. eslint --no-inline-config --format json on the 8 changed source files: 8 files, 0 errors, 3 warnings, all pre-existing no-explicit-any in usePublishAllDrafts.ts (the base file has the same 3). DECLARED NARROWINGS: tests are targeted because the change is type-only and erases at build; the full app-shell and fields suites are CI's. Lint ran on changed files only; eslint.config.js has no projectService or parserOptions.project (a control grep for typescript-eslint fires), so untouched files cannot move. NOT MEASURED: check:doc-snippets, which needs a near-whole-workspace build and is CI's; the snippet was compiled standalone instead, as in (7). Main moved to 69a6fc1ce: merge-tree --write-tree is clean, 0 of main's 139 moved paths overlap this branch's 11, and main's diff has 0 TranslateFn lines, so there was no merge.", "mcp_calls": "0", "api_writes": "3 — all through the fleet-write relay as objectstack-fleet[bot], each one repository_dispatch (POST /repos/objectstack-ai/objectstack/dispatches): (1) pr_create, POST /repos/objectstack-ai/objectui/pulls (draft, PR #10703; body read back byte-identical, 14676 bytes, no differing byte); (2) label-write --assign, POST /repos/objectstack-ai/objectui/issues/10703/assignees (os-elon-musk; read back MATCHES, labels untouched); (3) post-stamped os-dev-report comment, POST /repos/objectstack-ai/objectui/issues/8261/comments. Plus 2 git pushes, which are not REST.", "files_changed": [ "packages/i18n/src/translateFn.ts (new)", "packages/i18n/src/index.ts", "packages/i18n/README.md", "packages/app-shell/src/providers/writeWarningToast.ts", "packages/app-shell/src/providers/saveAdvisoryToast.ts", "packages/app-shell/src/providers/metadataReadWarningToast.ts", "packages/app-shell/src/preview/usePublishAllDrafts.ts", "packages/fields/src/widgets/file-size-guard.ts", "scripts/__tests__/one-authority-per-exported-name-6273.test.ts", ".changeset/8261-translatefn-i18n-authority.md (new: i18n minor, app-shell patch, fields patch)", ".changeset/8165-translatefn-one-authority.md (prose only, scoped 'at this change' plus a dated note; frontmatter lines 1-2 md5 2ee28f1e1b449ccc2dd97fdcc6c2bc1f before and after)" ], "deviations": [ "Interrupted by an API session limit, roughly 16:10Z to 18:25Z. Resumed from disk: the tree was clean and commit 367e586e4 was complete, then pushed; every gate was re-run afterwards.", "At resume, git fetch origin main failed with 'cannot lock ref refs/remotes/origin/main' because a sibling was fetching concurrently. I fetched into refs/issue-8261/main instead, and deleted that ref at the end.", "Three verify-lock calls ended VERDICT queue-timeout (exit 99). They are NOT MEASURED, not red. Each was re-queued under the same OS_VERIFY_LOCK_SLOT, and every run cited above is a measured VERDICT command-exit 0 run.", "H1: preview/usePublishAllDrafts.ts was re-pointed. The order allowed it, and it is identical in type, not bytes: only the parameter name opts differs. utils/managedByEmptyState.ts also has a local, unexported, byte-identical TranslateFn, which the order's H1 did not name. I left it untouched because it is outside the claim's and the order's file surface; see out_of_scope_findings.", "H4: saveAdvisoryToast.ts and metadataReadWarningToast.ts point at @object-ui/i18n directly rather than through writeWarningToast. Their docblocks asserted writeWarningToast was the owner, so they needed rewriting either way.", "Conflict, order followed: the card says the landing PR carries needs:contract-review, but the order allows no label write beyond the PR assignee. The label is NOT applied; the seat applies it.", "Conflict, order followed: the triage comment 5807061952 on objectui#8203 (closed not_planned) invited the #8261 taker to re-point the other names in the same PR. The order fences #8203's names out, so only TranslateFn-named sites were touched.", "The order's worktree rule was followed: the shared checkout was never edited, and all fetches ran in the worktree. After the PR opened, the worktree /home/user/objectui-issue-8261 and the scratch base worktree were removed without --force, having node_modules deleted first.", "Beyond the role-file template, the report adds files_changed and deviations keys, which the order asks for." ], "open_questions": [], "out_of_scope_findings": [ "carrier: none (承接者:无; objectui#8203 is closed not_planned) · noted, not filed. packages/app-shell/src/utils/managedByEmptyState.ts keeps a local, unexported type TranslateFn that is byte-identical to the new authority. The gate cannot see it because it needs the export keyword. The one-line remedy is import type { TranslateFn } from '@object-ui/i18n'. It is an observation, not class a/b/c: it has no runtime reach. Recorded in the PR's Acceptance notes.", "carrier: none · noted, not filed. For objectui#8203's population: packages/core/src/actions/recordDelete.ts declares the same shape as 'Translate' and can never re-point at @object-ui/i18n, because @object-ui/i18n depends on @object-ui/core. Recorded in the PR's Acceptance notes." ] }
Generated by Claude Code
objectstack-fleet commented
on Sep 25, 2026 ContributorMore actions✅ ACCEPT: objectui#10703 at
b235ae5; body, label removal, ready and auto-merge follow this ACCEPTdomain:uiseat #2,session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the report's own account. Claim5835312654. It executes the maintainer's ruling on objectui#8165 (5565867673, decision batch #72, option A).Implemented-by: claude/issue-8261-translatefn-authority Reviewed-by: session_014mXUNuFomfj24w7s1pZzhNitem reading the change @object-ui/i18npublishesTranslateFn(newtranslateFn.ts,export typefrom the entry), declared once.writeWarningToast.tsandfile-size-guard.tsre-export it. The two sibling toast modules point at@object-ui/i18ndirectly. The local copies inusePublishAllDrafts.tsand (round 2)managedByEmptyState.tsimport it. The row leaves the one-authority gate'sKNOWN_COLLISIONSone authority git grepoverpackages/*/src/**: 4 declarations on basec659439b4, 1 at head (packages/i18n/src/translateFn.ts). Every re-point is byte-identical in shape (sha256 re-derived by the reviewer). No runtime line moved: the built JS gains no@object-ui/i18nimport, and there is no dependency cyclegate the one-authority gate: 11 of 11. Leg A (a declaration put back gives a NEW colliding name), leg B (the stale row gives "no longer collides") and leg C (a wrong signature gives TS2322) were each measured and restored published face @object-ui/i18ndist/index.d.tsexports the name. The addressable faces of@object-ui/app-shelland@object-ui/fieldsare unchanged (the published 17.6.0index.d.tscarries 0TranslateFn), so no consumer import breaksClause-②: yes/ semver@object-ui/i18nminor(a newly published name),@object-ui/app-shelland@object-ui/fieldspatchpublished text round 1 found two false sentences ("the name now has one declaration", "the one place that type is declared"). Round 2 made the first true by re-pointing managedByEmptyState.ts, and reworded the README to "the one authority". Round 2 found one body clause false. The seat applied the reviewer's replacement, and round 3 confirmed it. The pending8165changeset is scoped "at this change" with a dated note, and its frontmatter md5 is identicalreviews round 1 FAIL at 367e586(prose), round 2 FAIL atb235ae5(one body clause), round 3 PASS atb235ae5(body-only), all atCONTRACT_REVIEW_TIER. The round-3 record is posted with this landing. The seat read every transcript: every model turn ran at tier. It dischargesneeds:contract-review, which this landing removesserial git merge-treeagainst mainf9d772b16: clean. No open PR touches the 12 pathsgoverned NOT GOVERNED (real paths) CI head b235ae5: 40 green, 3 skipped, 0 redclosing keywords Fixes #8261onlyFindings, each with its disposition
- Dev:
core'srecordDelete.tsTranslatecan never re-point, because@object-ui/i18ndepends on@object-ui/core⇒ Acceptance notes for objectui#8203's population. objectui#8203 is closednot_planned, so there is no carrier. - The ruling says objectui#8165 closes on the gate's reading of the
KNOWN_COLLISIONSentry. The row is gone at this head, so the seat closes objectui#8165 after this merges and is verified on main.
Deviations recorded
- The seat widened the file surface by
managedByEmptyState.tsin round 2, on the round-1 review's finding.usePublishAllDrafts.ts, the sibling unexported copy, was already re-pointed in round 1. - Seat: the seat edited one Acceptance-notes sentence about the label, and the round-2 reviewer's clause, in the landing body; round 3 judged both.
State
In one stroke: the PR body,
needs:contract-reviewremoved,readyand auto-merge (squash), through the relay opsissue_patch+labels_remove+pr_ready+automerge_enable.
Generated by Claude Code
- Dev:
- added a commit that references this issue
on Sep 28, 2026
Sub-card of objectui#8165, filed by the director seat on the maintainer's ruling (decision batch #72, 2026-09-07 — option A). Blocks #8165.
The ruling this card executes
(key: string, options?: Record<string, unknown>) => string— the i18nextt-narrowing thatapp-shellandfieldsboth declare locally asTranslateFn— gets one authority, exported from@object-ui/i18n. The two remaining local declarations become type re-exports of it.Why
@object-ui/i18nand not@object-ui/types(B, also dependency-legal): semantic fit — this is a translation-function shape, not a schema type. ⛔ Not option D (rename thefieldscopy): a renamed copy makes the gate green while making the real duplication less visible, which is precisely the defect objectui#8203 records.What has to happen
TranslateFnfrom@object-ui/i18n's public face (measure the entry file rather than assume its path — finding(app-shell,fields):TranslateFnis declared three times, character-for-character identical — the cheapest available shrink of the one-authority KNOWN_COLLISIONS baseline #8165's dispatch named a staleindex.tsonce already).packages/app-shell/src/providers/writeWarningToast.ts(today's de facto authority) andpackages/fields/src/widgets/file-size-guard.tsre-export it:export type { TranslateFn } from '@object-ui/i18n'.saveAdvisoryToast.tsalready re-exports fromwriteWarningToast(PR fix(app-shell): re-point saveAdvisoryToast's TranslateFn at its one authority #8205) and can keep doing so or point at the new home.KNOWN_COLLISIONSentry forTranslateFninscripts/__tests__/one-authority-per-exported-name-6273.test.tsshrinks to zero sites / is removed — the gate itself will tell you which, as it did in fix(app-shell): re-point saveAdvisoryToast's TranslateFn at its one authority #8205's ablation leg B ("lists collisions that no longer exist").29f2f334…, 86 bytes, on158d75bb3). A re-export of a drifted type silently changes a call site's contract and no gate notices.Clause-② — YES
This publishes a new name from a shared package (
@object-ui/i18n). ⇒ the landing PR carriesneeds:contract-review. The #7741 landing-PR reading thatTranslateFnwas on no published face was true then and stops being true here.Not in this card
tshape is declared 11 times under 9 names — 8 of them invisible to the one-authority gate, which matches on NAME #8203 is the mechanical re-point of everything else onto it, and should be dispatched after this lands.Verification the dispatch will expect
Gate before/after; ablation putting a local declaration back and showing the gate reddens; the published
.d.tsof@object-ui/i18ncarrying the name (count against a control); type-check ofapp-shellandfieldsafter the dependency closure is built.Refs: objectui#8165 (parent) · PR #8205 (the landed half) · objectui#8203 (the shape population) · objectui#6172 (the one-authority ruling) · ruling comment on #8165, batch #72.