You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[finding] The generated-leaf provenance companion is now RECORDED in 9 of 9 bundle sets and READ at serving time in 1 — withSourceFallback was never wired outside platform-objects #12642
Origin: measured while implementing #12559 (the --source-hashes rollout). Filed unassigned and recording-only — this is a boundary the rollout leaves behind, not a defect in it, and the hazard is again what a reader concludes.
The measurement
PR #12557 (#11671, maintainer ruling #12069 Option A) landed the provenance companion as two halves, and its own body says so:
withSourceFallback takes that table as a fourth argument and now judges objects / metadataForms alongside the hand-authored sections, so a leaf whose source moved underneath it serves the current source string instead of a superseded draft.
It does not only record. withSourceFallback reads the records at serving time and substitutes the current source, and findStaleFills reports them.
#12559 rolled out the recording half to the eight uncovered sets. The reading half did not move, and nothing in either PR's file surface would tell a reader that. Measured on the tree at the head of claude/issue-12559-i18n-source-hash-rollout:
Every call site is in @objectstack/platform-objects — src/apps/translations/setup.translation.ts and src/metadata-translations/index.ts. The other eight sets' src/translations/index.ts assemble their TranslationBundle from the raw generated modules and never consult the companion sitting next to them:
So after #12559: provenance recorded 9 of 9, provenance served 1 of 9.
Why it is worth writing down
It is the same inference hazard #12559 was filed about, one layer down. After that PR the repo has --source-hashes documented in all nine extract configs, 24 committed companions, a changeset announcing the rollout, and check:i18n reporting 7 bundles per set where it reported 4. The natural reading of all of that is "a stale generated leaf now serves the current source everywhere". For eight of nine sets it records the drift and still serves the superseded draft.
The gap is not hypothetical, and it was measured on a newly covered set during that PR's ablation. Revising the source label behind objects.sys_share_link.fields.token.label in plugin-sharing (a leaf recorded in es-ES only) and regenerating from one extract run:
observation
result
findStaleFills on the companion
es-ES 1 stale, zh-CN 0, ja-JP 0 — the record identifies it exactly
check:i18n
OK (9 package(s) — all bundles in sync…)
check:i18n-stale-fill
OK (10 bundle set(s) — no new stale fills, 0 baselined) — blind by construction, one locale, no second witness
what es-ES serves
the superseded English draft
On platform-objects that same leaf would have been substituted at serving time. In plugin-sharing the evidence exists on disk and nothing reads it.
What resolving it would look like — not chosen here
Wire the eight — each src/translations/index.ts passes its three companions through withSourceFallback, the shape platform-objects takes. Cheap for seven of the eight, which already depend on @objectstack/platform-objects. @objectstack/plugin-webhooks does not (@objectstack/core, @objectstack/service-messaging, @objectstack/spec), so this route adds a dependency edge there or moves withSourceFallback somewhere both can reach — which is the part that makes this a decision rather than a mechanical follow-up.
Move the seam — have the i18n loader apply provenance centrally, so a bundle set opts in by committing a companion rather than by wiring a call. One place instead of nine, and no new package edges.
Choosing among these is a per-package architecture call, so it is triage's rather than a seat's. Filed unassigned; not claimed.
Dedup
Searched 2026-08-27 across open issues for this vocabulary (withSourceFallback, source-hashes, provenance companion); the positive control fired — the query returns #12559 itself. No existing card covers the serving-side half: #11671 is the mechanism, #12069 its ruling, #12559 the recording rollout, and none of them names the eight sets' index.ts.
Origin: measured while implementing #12559 (the
--source-hashesrollout). Filed unassigned and recording-only — this is a boundary the rollout leaves behind, not a defect in it, and the hazard is again what a reader concludes.The measurement
PR #12557 (#11671, maintainer ruling #12069 Option A) landed the provenance companion as two halves, and its own body says so:
#12559 rolled out the recording half to the eight uncovered sets. The reading half did not move, and nothing in either PR's file surface would tell a reader that. Measured on the tree at the head of
claude/issue-12559-i18n-source-hash-rollout:Every call site is in
@objectstack/platform-objects—src/apps/translations/setup.translation.tsandsrc/metadata-translations/index.ts. The other eight sets'src/translations/index.tsassemble theirTranslationBundlefrom the raw generated modules and never consult the companion sitting next to them:So after #12559: provenance recorded 9 of 9, provenance served 1 of 9.
Why it is worth writing down
It is the same inference hazard #12559 was filed about, one layer down. After that PR the repo has
--source-hashesdocumented in all nine extract configs, 24 committed companions, a changeset announcing the rollout, andcheck:i18nreporting 7 bundles per set where it reported 4. The natural reading of all of that is "a stale generated leaf now serves the current source everywhere". For eight of nine sets it records the drift and still serves the superseded draft.The gap is not hypothetical, and it was measured on a newly covered set during that PR's ablation. Revising the source label behind
objects.sys_share_link.fields.token.labelinplugin-sharing(a leaf recorded in es-ES only) and regenerating from one extract run:findStaleFillson the companioncheck:i18nOK (9 package(s) — all bundles in sync…)check:i18n-stale-fillOK (10 bundle set(s) — no new stale fills, 0 baselined)— blind by construction, one locale, no second witnessOn
platform-objectsthat same leaf would have been substituted at serving time. Inplugin-sharingthe evidence exists on disk and nothing reads it.What resolving it would look like — not chosen here
src/translations/index.tspasses its three companions throughwithSourceFallback, the shapeplatform-objectstakes. Cheap for seven of the eight, which already depend on@objectstack/platform-objects.@objectstack/plugin-webhooksdoes not (@objectstack/core,@objectstack/service-messaging,@objectstack/spec), so this route adds a dependency edge there or moveswithSourceFallbacksomewhere both can reach — which is the part that makes this a decision rather than a mechanical follow-up.check:i18nand carry forward across source revisions), and a future consumer inherits nine sets of history rather than one. But then the boundary needs to be written where a reader looks, exactly as [finding] Generated-leaf staleness detection covers 1 of 9 i18n bundle sets — the other 8 stay legacy-trusted, and nothing says so at the point a reader would look #12559 argued.Choosing among these is a per-package architecture call, so it is triage's rather than a seat's. Filed unassigned; not claimed.
Dedup
Searched 2026-08-27 across open issues for this vocabulary (
withSourceFallback,source-hashes,provenance companion); the positive control fired — the query returns #12559 itself. No existing card covers the serving-side half: #11671 is the mechanism, #12069 its ruling, #12559 the recording rollout, and none of them names the eight sets'index.ts.