Repository navigation
settings(localization): retire date_format, time_format, number_format and first_day_of_week from the Localization manifest — no renderer honours them; formats follow the locale (ruled on objectui#11675, B) #21958
Description
Activity
objectstack-fleet commented on Oct 6, 2026
Claim: PM loop round 1 · 2026-10-06T07:29Z
Session: session_01WMQprn46CND82KmY8sZWBu
Account: os-warren (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-21958-retire-locale-format-settings
Worktree: objectstack-issue-21958
Domain: domain:services
Seat: domain:services#2 (seat post #21118)
Ruling-ref: objectstack-ai/objectui#11675 comment 6010771237, read in this act: the maintainer's 「同意」 on decision batch 2, item 1, B.
File surface (at origin/main 80f9f7e6ba):
packages/services/service-settings/src/manifests/localization.manifest.ts: the four rowsdate_format,time_format,number_formatandfirst_day_of_weekleave.timezone,locale,default_country,currencyandfiscal_year_startstay.src/translations/{en,es-ES,ja-JP,zh-CN}.ts: their entries leave.- Tests:
localization.manifest.test.ts,translations/settings-translation-coverage.test.ts, andsettings-service.test.tswhere it names the four. - The stored-value handling the dev measures, kept inside
service-settings. - One changeset, graded as
check-changeset-no-major.mjsrequires. - ⛔ No
packages/specedit and noskills/**edit. If a retirement entry belongs in either, the dev stops and reports. Stop on breach; explain in the report.
Container & model:M,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate; default tier, because the stored-value treatment is a judgment, not a mechanical removal)
Clause-②: no (narrowing)
Thread-read: none
Serial constraints cleared: at 2026-10-06T07:29Z, no open PR touchespackages/services/service-settings, and no in-flight claim of any lane declares it. PR fix(services): settings, datasource, webhook and messaging plumbing passes the explicit system opt-in instead of no principal #21940 (security(service-settings, service-messaging, service-datasource, plugin-webhooks): plumbing reads and writes reach the engine with no principal and no system opt-in — the services-lane producers of #21908's closure #21913), the last edit to that package, merged as76fec88b16. The ruled remainder on objectui#11675 (calendar and timeline week start) and objectui#11693 are objectui's, and disjoint.
Clause-②: no (narrowing): four offered settings keys leave the published manifest, and no accepted shape widens. How a stored value of a retired key reads and writes afterwards is measured and stated, and the row is kept, never silently dropped, as the card's "Done when" requires.
Generated by Claude Code
objectstack-fleet commented on Oct 6, 2026
os-dev-report
{
"issue": 21958,
"status": "done",
"branch": "claude/issue-21958-retire-locale-format-settings",
"pr": "#21970",
"session": "session_01WMQprn46CND82KmY8sZWBu (shared, mode:subagent; parent's harness-stamped id)",
"premise_still_valid": true,
"summary": "date_format, time_format, number_format and first_day_of_week leave localizationSettingsManifest together with the now-empty 'formats' group. Their entries and the formats group leave the en, es-ES, ja-JP and zh-CN bundles. The namespace description now reads 'Default timezone, language, country, currency, and fiscal year.' timezone, locale, default_country, currency and fiscal_year_start are unchanged. The manifest version goes from 1 to 2: the spec's SettingsManifestSchema.version describe/TSDoc is the settings contract's only retirement entry ('Increment when keys are renamed/removed.'); no spec edit, and nothing reads version in objectstack or objectui. Stored values, measured through the real REST handlers on origin/main 80f9f7e (simulated retirement over a store holding a date_format row) and on the branch, with identical answers. The row is KEPT and never deleted. GET /api/settings/localization neither serves nor resolves the key. A PUT naming it is refused 400 UNKNOWN_KEY (details.namespace/key), whole-batch. A save of the live keys succeeds over the stale row. The reset action clears only the live keys. In-process get rejects SETTINGS_UNKNOWN_KEY. A rollback re-registration reads the row back unchanged. OS_LOCALIZATION_DATE_FORMAT and the other three are no longer read, silently. No service code changed: this is the existing undeclared-key path, now pinned at the REST surface. Docs: no content/docs page lists the four (searched outside references/ and releases/), so there are no doc edits. The skills/** hits are SQL's date_format() in objectstack-query/rules/aggregation.md:82 and objectstack-ui/rules/dashboards.md:327, not the settings key.",
"files_changed": [
".changeset/21958-retire-locale-format-settings.md",
"packages/services/service-settings/src/manifests/localization.manifest.ts",
"packages/services/service-settings/src/manifests/localization.manifest.test.ts",
"packages/services/service-settings/src/translations/en.ts",
"packages/services/service-settings/src/translations/es-ES.ts",
"packages/services/service-settings/src/translations/ja-JP.ts",
"packages/services/service-settings/src/translations/zh-CN.ts",
"packages/services/service-settings/src/translations/settings-translation-coverage.test.ts",
"packages/services/service-settings/src/settings-service.test.ts",
"packages/services/service-settings/src/settings-routes.test.ts"
],
"tests": "head 397edab, the final commit; gates run after it. Build: dependency closure pnpm --workspace-concurrency=2 --filter '@objectstack/service-settings^...' build, VERDICT command-exit 0; then pnpm --filter @objectstack/service-settings build, exit 0. pnpm --filter @objectstack/service-settings typecheck: exit 0 (tsc --noEmit; --listFiles shows 36 test files compiled, including all 4 edited). pnpm --filter @objectstack/service-settings test: 'Test Files 36 passed (36) / Tests 626 passed (626)', VERDICT command-exit 0. The built dist serves version 2 and keys timezone,locale,default_country,currency,fiscal_year_start through both require('./dist/index.cjs') and import('./dist/index.js'). Gates: dispatch-gates --commands --repo objectstack-ai/objectstack re-derived 63 on the final tree, the dispatch's 49 plus 14: adr-0087-registration x2, empty-changeset x2, release-rehearsal-clone/release-pending-publish self-tests, engine-double-contract, objectql-double-limit, objectui-changeset, pm-changeset-deadline-census, query-options-erasure, type-check-coverage, type-check-debt, where-matcher. Results: 62 exit 0; pnpm check:dual-build-cjs-loads exit 3, PREREQUISITE NOT MET (53 packages outside the closure have no dist/), NOT MEASURED, reason: CI's full build owns it, with the direct CJS load above as the narrowed substitute. --ran reconciliation (exit codes recorded): '63 derived, 62 run, 1 NOT-MEASURED, 0 UNRUN'. check-adr-0087-registration: '1 declared-breaking changeset(s), each carrying an ADR-0087 disposition ... not-required (no-migration-prescription)'. check-changeset-no-major: 'This diff introduces no major bump'. ESLint narrowed: eslint --no-inline-config --format json over the 9 touched .ts files gave 9 files linted, 0 errors, 0 warnings. Population is **/.{ts,...} per eslint.config.mjs, and the config enables no type-aware linting, so untouched files' verdicts cannot move. Ablation via scripts/ablation-replace.mjs, nothing built (the subject is the package's own src, imported relatively; vitest aliases resolve to source). (A) date_format row re-inserted into the manifest: on-disk count 1, blob e8f3039af917 to 38665aa77765. 8 red: 3 new route pins, the 'five keys' and 'offers none of the four' manifest pins, and zh-CN/ja-JP/es-ES coverage. Restored blob == HEAD e8f3039af917 and git diff HEAD empty. A first attempt was a refused no-op, because the replacement contained its anchor; nothing was measured on it. (B) date_format: {label} re-added to en.ts: on-disk count 1. The reverse pin went red: 'en has undeclared settings copy: localization.key:date_format'. Restored blob == HEAD 0b0918e9ece5, git diff HEAD empty. Direction observed: red, as expected. The refusal pin asserts status 400 + error.code UNKNOWN_KEY + error.details.",
"mcp_calls": "0",
"api_writes": "3 REST writes, each through the fleet-write relay as objectstack-fleet[bot] (each is one POST /repos/objectstack-ai/objectstack/dispatches): (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, draft #21970, read back byte-identical (10063 bytes); (2) label-write --assign os-warren, POST /repos//issues/21970/assignees, read back MATCHES; (3) this os-dev-report comment, POST /repos//issues/21958/comments. Plus git push x3 (the empty branch probe and 2 commits), which is not REST. Reads used plain gh api: scripts/pm/with-fleet.sh --read refused with exit 3 because auto resolves to dispatch in this cloud container.",
"deviations": [
"Test surface beyond the three named files. The stored-value pins live in src/settings-routes.test.ts, inside service-settings, because that file already holds the REST harness and the seedGlobalSecret store-level seeding precedent. settings-translation-coverage.test.ts gained the reverse direction (no copy for an undeclared group/key, en included), which measured zero such entries across all ten manifests and closes the class.",
"version 1 to 2 is a judgment. The spec contract text is the only 'retirement entry' the settings contract names, there is no packages/spec edit, and the bump is pinned in localization.manifest.test.ts.",
"Same-docblock accuracy fix: localization.manifest.ts named resolveExecutionContext, which no longer exists. It now names resolveLocalizationContext (@objectstack/core) and says it reads timezone, locale and currency.",
"Mechanism hypothesis 3 partly falsified: settings-routes.ts:25 cites envelope siblings retired from the route module, not a settings key. settings-service.ts ~:920 is retired mail.provider OPTION values. Measured over an unshallowed history (15,821 commits): no settings key ever left a manifest before, and no manifest version was ever above 1.",
"History deepening: git fetch --deepen=20000 origin main in the shared clone, to measure the precedent. This changes the common object store and the shallow file, not any branch or worktree.",
"pnpm check:dual-build-cjs-loads NOT MEASURED (exit 3, PREREQUISITE NOT MET); declared narrowing, CI runs it."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted in PR Acceptance notes, not filed: an OS_LOCALIZATION_ variable naming a retired key (or any undeclared key, e.g. a typo) is silently unread. No namespace audits undeclared OS_ variables. Pre-existing, general, and never read before either.",
"carrier: none · noted, not filed: SettingsManifest.version has no reader in objectstack or objectui (grep manifest.version over the settings code), so the 'increment when keys are renamed/removed' contract is declared but unenforced. No pull.",
"carrier: whoever next edits objectui apps/console/src/pages/settings/tests/SettingsField.valueDomain.test.tsx (objectui#11675 remainder possibly) · noted, not filed: it uses date_format/first_day_of_week as hand-built fixture keys, does not import this manifest, and stays green."
]
}
Generated by Claude Code
objectstack-fleet commented on Oct 6, 2026
Review: PR #21970 at 397edabf04 · seat domain:services#2 (#21118) · session_01WMQprn46CND82KmY8sZWBu · 2026-10-06T08:20Z
ACCEPT (verdict on the dev report 6012265052). Checked against the PR, not the report:
-
Shape: draft, base
main. Line 1 isFixes #21958and line 2Clause-②: no (narrowing). No other closing keyword appears, and the body carries no HTML comment. Not governed (check-governed-merges.mjs --pr 21970), 316 changed lines. -
What moved, read in the diff: the four rows and the emptied
formatsgroup leavelocalizationSettingsManifest. Their copy leavesen,es-ES,ja-JPandzh-CN.timezone,locale,default_country,currencyandfiscal_year_startare untouched.versiongoes from 1 to 2, under the spec's ownSettingsManifest.versioncontract ("increment when keys are renamed/removed"), with nopackages/specedit. The namespace description now names what remains. No service code moved. -
Stored values, the card's judgment, pinned at the REST surface (
settings-routes.test.ts, with rows seeded store-level the wayseedGlobalSecretis):GETneither offers nor resolves the four;- a
PUTnaming one is refused400 UNKNOWN_KEYwithdetails.key, the existing answer for any undeclared key; - the stored rows read back unchanged after read, write and reset;
- a save of the live keys succeeds over them.
This matches the ruling and the card's "kept, never silently dropped".
-
The new reverse coverage pin (
settings-translation-coverage.test.ts: no bundle carries copy for an undeclared group or key) is a test pin inside the existing coverage suite, not a gate. It measured zero across all ten manifests. Accepted. -
Ablations: a re-inserted row turned 8 cases red, and re-added
encopy turned the reverse pin red. Both were restored by blob. -
Changeset sentences checked against the diff: the title; the BREAKING paragraph (four specifiers and the Formats group, four bundles, Setup and
GET, the ruling, the five live keys, version 2); each stored-value bullet (row kept,GETabsent,PUT400 UNKNOWN_KEYwhole-batch, save and reset, in-processSETTINGS_UNKNOWN_KEY,OS_LOCALIZATION_*no longer read); "What to do after upgrading".minorwith the BREAKING banner, ADR-0087not-required. -
Docs: no
content/docs/**page lists the four. The seat's own read at80f9f7e6baagrees: the only hit isreferences/api/export.mdx's unrelatedtransform: 'date_format'. The twoskills/**hits are SQL'sdate_format(), not these keys. -
Writes:
mcp_calls0, and 3 relay writes. -
CI at review: 15 success, 3 skipped and 13 in progress on
397edabf04. The seat lands it once every check is green.
out_of_scope_findings: all three → Acceptance notes:
- an
OS_LOCALIZATION_*variable naming an undeclared key is silently unread; SettingsManifest.versionhas no reader;- objectui's
SettingsField.valueDomainfixture keys.
objectui#11675's remainder (the calendar and timeline week start) stays with objectui.
Generated by Claude Code
objectstack-fleet commented on Oct 6, 2026
Landed · domain:services seat 2 (#21118) · session_01WMQprn46CND82KmY8sZWBu · 2026-10-06T09:25Z
- PR fix(service-settings)!: retire date_format, time_format, number_format and first_day_of_week from the Localization manifest (#21958) #21970 merged through the queue as
0d8ea5e1bb, read onorigin/main. The card closedcompletedbyFixes #21958, andpm:dispatchedis stripped in this act. - Closing-keyword check: only this card closed at the merge. decision: the tenant Localization settings (date format, time format, number format, first day of week) are applied by no renderer — honour them, or stop offering them objectui#11675 (the calendar and timeline week start) stays open with objectui, as ruled.
Generated by Claude Code
Path: ② the capabilities an end user meets in the app — localization | 缺项 | P2
Filed by the triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U, executing the maintainer's ruling on objectstack-ai/objectui#11675. Provenance: the maintainer, in the triage seat's live chat (session_01AavokzJ5DndAwitDXvKy4U), answering decision batch 2 (director format), verbatim: 「同意」, for item 1, which recommended B. ⛔ Not a claim, ⛔ not a dispatch.Triage: lands in
packages/services/service-settings/src/manifests/localization.manifest.ts(the four rows, about:84–:120) and itstranslations/*.ts⇒domain:services; rationale: the settings page offers four controls that nothing reads.Ruled
Dates, times, numbers and the first day of the week follow the locale (language and region), as Salesforce derives formats from the user's Locale. The four separate format settings are retired. ⛔ They are not implemented.
Read before filing (
main)date_format()indriver-sql, an exporttransformenum value, and comments.Done when
timezone,locale,default_country,currencyandfiscal_year_startstay.GET /api/settings/localizationand the Setup → Localization form no longer offer the four keys.bug·priority:p2·pm:queue.Generated by Claude Code