fix(l10n): stamp a missing l10nSource when a connected translation is opened #345

Merged
dominik.polakovics merged 1 commit from afk/343 into main 2026-10-23 09:04:03 +02:00

Closes #343

What

Opening a connected translation in the editor (GET /api/page, GET /api/page/elements, via openPage) now stamps, after the existing l10n.Repair:

  • every translated element, nested element and item without l10nSource with its source element's current hash (l10n.StampMissing, built on walkElements, sourceParam, hashOf, setSourceParam);
  • the front matter's page-level l10nSource when missing (l10n.StampMissingPage → pageops.TranslationPageStamp, same pageFormFields as TranslationPageChanged).

The write is persisted with the existing repair translation snapshot. Edge cases:

  • An existing hash, even a stale one, is never overwritten.
  • A free translation is never stamped.
  • An element with no same-uid, same-name source element gets no stamp.
  • The stamp runs under the same condition as the repair: the source's uids must be sound.
  • A present value that is not a string is treated as no hash and is stamped.
  • The tree still does not write, so before the first open it shows translated.

Rule owners

  • "Is this element stamped" stays sourceParam.
  • "Does this front matter carry a page hash" moves into pageSource, which PageChanged and StampMissingPage share.
  • Hashing is only Hash/ItemHash/PageHash.

Docs and skills

  • scaffold/site/AGENTS.md: "Change tracking", "Change tracking of the page's own fields" and "Translations by hand" now say the editor stamps a missing hash on first open.
  • docs/api.md: GET /api/page "Languages" and "Writes", the translations overview and pageChanged.
  • docs/architecture.md: "Multilingual sites".
  • Skills: I re-read edit-content and migrate-site. Neither contradicts the new behaviour, since both point at AGENTS.md, so they are unchanged.

Tests

  • l10n: TestStampMissing and TestStampMissingPage.
  • pageops: TestTranslationPageStamp.
  • server:
    • TestOpenStampsMissingSourceHashes is the regression from the report. It failed before this change and passes now.
    • TestOpenStampTracksParamAndTitleChanges
    • TestOpenStampEdgeCases
    • TestOpenStampSnapshot
  • go vet ./... and go test ./... are green. web/ is untouched.

🤖 Generated with Claude Code

Closes #343 ## What Opening a connected translation in the editor (`GET /api/page`, `GET /api/page/elements`, via `openPage`) now stamps, after the existing `l10n.Repair`: - every translated element, nested element and item without `l10nSource` with its source element's current hash (`l10n.StampMissing`, built on `walkElements`, `sourceParam`, `hashOf`, `setSourceParam`); - the front matter's page-level `l10nSource` when missing (`l10n.StampMissingPage` → `pageops.TranslationPageStamp`, same `pageFormFields` as `TranslationPageChanged`). The write is persisted with the existing `repair translation` snapshot. Edge cases: - An existing hash, even a stale one, is never overwritten. - A free translation is never stamped. - An element with no same-uid, same-name source element gets no stamp. - The stamp runs under the same condition as the repair: the source's uids must be sound. - A present value that is not a string is treated as no hash and is stamped. - The tree still does not write, so before the first open it shows `translated`. ## Rule owners - "Is this element stamped" stays `sourceParam`. - "Does this front matter carry a page hash" moves into `pageSource`, which `PageChanged` and `StampMissingPage` share. - Hashing is only `Hash`/`ItemHash`/`PageHash`. ## Docs and skills - `scaffold/site/AGENTS.md`: "Change tracking", "Change tracking of the page's own fields" and "Translations by hand" now say the editor stamps a missing hash on first open. - `docs/api.md`: GET /api/page "Languages" and "Writes", the translations overview and `pageChanged`. - `docs/architecture.md`: "Multilingual sites". - Skills: I re-read `edit-content` and `migrate-site`. Neither contradicts the new behaviour, since both point at AGENTS.md, so they are unchanged. ## Tests - `l10n`: `TestStampMissing` and `TestStampMissingPage`. - `pageops`: `TestTranslationPageStamp`. - `server`: - `TestOpenStampsMissingSourceHashes` is the regression from the report. It failed before this change and passes now. - `TestOpenStampTracksParamAndTitleChanges` - `TestOpenStampEdgeCases` - `TestOpenStampSnapshot` - `go vet ./...` and `go test ./...` are green. `web/` is untouched. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(l10n): stamp a missing l10nSource when a connected translation is opened
All checks were successful
ci / build-and-test (pull_request) Successful in 3m52s
ci / release (pull_request) Has been skipped
c6bb7c302f
A connected translation written without change-tracking hashes (by hand,
by `harness lang add`, imported) was never marked changed, however much
its source changed. Opening it in the editor (GET /api/page, GET
/api/page/elements) now stamps every translated element, nested element
and item that has no l10nSource with its source element's current hash,
and the front matter with the page-level hash, persisted with the
existing "repair translation" snapshot. An existing hash is never
overwritten; free translations are left alone.

- l10n.StampMissing and l10n.StampMissingPage reuse sourceParam, hashOf,
  PageHash and StampPageChanges; the page-level "carries a hash" rule
  moves into one helper (pageSource) shared with PageChanged.
- pageops.TranslationPageStamp uses the same properties-form fields as
  TranslationPageChanged.
- AGENTS.md "Translations", docs/api.md GET /api/page and
  docs/architecture.md describe the stamp.

Closes #343

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
Owner

[autoland] verdict: pass

PASS — signal: ci / build-and-test success (run 365; release skipped). Title is Conventional Commits, body carries Closes #343. Diff matches the issue: l10n.StampMissing / StampMissingPage (sourceParam stays the one 'is stamped' owner, pageSource shared with PageChanged, hashing only via hashOf/PageHash), pageops.TranslationPageStamp over the same pageFormFields as TranslationPageChanged, wired into openPage (both GET /api/page and GET /api/page/elements) under the existing repair-translation snapshot. Edge cases (stale hash kept, free translation untouched, no same-uid/same-name source skipped) are tested at l10n, pageops and server level, plus the #343 regression. AGENTS.md, docs/api.md and docs/architecture.md updated; skills unaffected (they point at AGENTS.md). Base moved by #344 (supervisor only, disjoint); merge-tree is clean.

[autoland] verdict: pass PASS — signal: ci / build-and-test success (run 365; release skipped). Title is Conventional Commits, body carries Closes #343. Diff matches the issue: l10n.StampMissing / StampMissingPage (sourceParam stays the one 'is stamped' owner, pageSource shared with PageChanged, hashing only via hashOf/PageHash), pageops.TranslationPageStamp over the same pageFormFields as TranslationPageChanged, wired into openPage (both GET /api/page and GET /api/page/elements) under the existing repair-translation snapshot. Edge cases (stale hash kept, free translation untouched, no same-uid/same-name source skipped) are tested at l10n, pageops and server level, plus the #343 regression. AGENTS.md, docs/api.md and docs/architecture.md updated; skills unaffected (they point at AGENTS.md). Base moved by #344 (supervisor only, disjoint); merge-tree is clean.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/deckle!345
No description provided.