Skip to content

fix: honor language changes on clean updates - #548

Open
Gautam Sharma (GautamSharma99) wants to merge 1 commit into
langchain-ai:mainfrom
GautamSharma99:fix/language-aware-update-noop
Open

fix: honor language changes on clean updates#548
Gautam Sharma (GautamSharma99) wants to merge 1 commit into
langchain-ai:mainfrom
GautamSharma99:fix/language-aware-update-noop

Conversation

@GautamSharma99

Copy link
Copy Markdown

Summary

Fixes #538.

Clean repository updates now treat an explicit primary-language change as meaningful work. A command such as:

openwiki code --update --language fr --print

will no longer return through the clean-tree no-op path when the persisted wiki language is English. It proceeds through provider setup and reaches the existing whole-wiki translation pass.

This PR also keeps the no-op optimization for equivalent language variants, wires the same decision into the pre-credential startup shortcut, centralizes primary-language comparison, adds regression tests, and includes a patch changeset.

Problem

The update flow checked for a clean-tree no-op before creating run context or resolving the translation plan:

if (command === "update" && shouldCheckUpdateNoop(options)) {
  const noopStatus = await getUpdateNoopStatus(cwd, openWikiIgnore);
  if (noopStatus.shouldSkip) return ...;
}

getUpdateNoopStatus() considered metadata, git HEAD, worktree changes, ignored paths, and interrupted runs, but received no language intent. On a clean tree it returned shouldSkip: true even when options.language requested a full language switch.

The same bug existed one layer earlier in resolveStartupCommand(). A credential-less --print run could use the clean-update shortcut and return successfully without requiring credentials, even though translation needed a model call.

Implementation

Language-aware no-op status

getUpdateNoopStatus() now accepts the requested language and compares it with the persisted .last-update.json language before evaluating git state.

When their primary language subtags differ it returns:

{
  shouldSkip: false,
  reason: "output language changed"
}

An absent persisted language is treated as English, matching the existing translation behavior for metadata written by older OpenWiki versions.

The requested language is validated and canonicalized through resolveLanguage() before comparison. Invalid programmatic values therefore do not create a false language switch; the CLI already drops them with its existing warning.

Same semantics as translation

The translation middleware already intentionally compares primary subtags so region-only changes do not trigger a whole-wiki rewrite—for example, en and en-GB are considered equivalent.

That comparison is now centralized in getPrimaryLanguageSubtag() and shared by:

  • the clean-update no-op decision;
  • resolveTranslationPlan().

This prevents the optimization and translation pass from drifting into different definitions of a language switch.

Both early-return paths updated

The requested language is passed into no-op evaluation from:

  • runOpenWikiAgent(), which owns the actual clean-tree early return;
  • canSkipCleanUpdateBeforeCredentials(), which lets genuine print-mode no-ops exit without configured provider credentials.

A real language change can therefore no longer be skipped at either layer.

Behavior matrix

Persisted language Requested language Clean tree behavior
English or absent none Skip as before
English or absent fr Run translation/update
fr de Run translation/update
en en Skip
en en-GB Skip; same primary language
pt-BR pt-PT Skip; same primary language
any invalid/unrecognized value Existing warning/fallback behavior; no false switch

Tests

No-op regression coverage

test/update-noop.test.ts now verifies that:

  • a clean English wiki requested as French returns output language changed;
  • an equivalent en-GB request remains a no-op.

Startup regression coverage

test/startup.test.ts now verifies that a clean --print update requesting French does not use the credential-free no-op shortcut. With no provider key configured, startup correctly reports the missing credential because model-backed translation must run.

Shared language comparison

test/language.test.ts covers:

  • region variants mapping to the same primary subtag;
  • absent legacy metadata defaulting to English;
  • malformed persisted values remaining a safe mismatch.

Existing translation tests continue to verify full-pass versus region-only behavior through the same shared helper.

Validation

  • corepack pnpm test — 67 files, 797 tests passed
  • corepack pnpm exec vitest run test/update-noop.test.ts test/startup.test.ts test/translation-middleware.test.ts test/language.test.ts — 48 tests passed
  • corepack pnpm run typecheck
  • corepack pnpm run lint:check
  • corepack pnpm run format:check
  • corepack pnpm exec changeset status
  • git diff --check

@changeset-bot

changeset-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 918ec7f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
openwiki Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Clean-update no-op skips explicit --language changes

1 participant