Skip to content

chore(desktop): admit validated copy catalogs in the renderer architecture ratchet - #4493

Merged
Astro-Han merged 2 commits into
apache:mainfrom
orangeCatDeveloper:chore/renderer-arch-catalog-class
Sep 2, 2026
Merged

chore(desktop): admit validated copy catalogs in the renderer architecture ratchet#4493
Astro-Han merged 2 commits into
apache:mainfrom
orangeCatDeveloper:chore/renderer-arch-catalog-class

Conversation

@orangeCatDeveloper

@orangeCatDeveloper orangeCatDeveloper commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Part of #2672

Two repository gates deadlock. The locale policy (#2672, enforced by the copy-gate family) forces user-visible copy OUT of business files and INTO src/renderer/locales/*-copy.ts catalogs — which necessarily ADDS an import edge. The renderer architecture ratchet forbids exactly that: legacy files may not grow their dependency count at all, and the AppShell closure rejects any new entry. #4457 fails CI on precisely this collision (12 × new dependency debt, 2 × new legacyAppShellClosure debt entries are forbidden); no placement of the catalog can satisfy both gates today.

This PR admits exactly one dependency class instead of loosening the ratchet generally. A "validated copy catalog" is recognized structurally and re-verified on every checker run — never grandfathered:

  • path src/renderer/locales/*-copy.ts;
  • carries a UiCatalog marker imported from @maka/core/ui-locale (satisfies or type annotation);
  • zero tracked capabilities by the checker's own metrics (hooks, bridge, lifecycle, environment, action factories, unresolved/dynamic imports);
  • imports bare package specifiers only — no relative or @maka/desktop/ imports — so a catalog can never become a tunnel to renderer implementation.

Admitted edges are excluded from the dependency-count ratchets and closure admission, and feature/Desktop-adapter imports of a validated catalog need no legacy budget edge (the ledger drops 26 now-unneeded budget entries). Everything else still ratchets: the importing file's hook/bridge/environment/token rules are untouched, root-entry (app-shell.tsx family) import and token counts stay strict, and a catalog that grows a hook or a relative import instantly loses admission — the adversarial fixtures cover hook smuggling, implementation-import smuggling, a missing marker, dynamic imports (fail closed upstream), and an unrelated dependency added beside a valid catalog.

Boundaries: root-entry files deliberately get no import-count discount — touching app-shell.tsx still requires net-zero there. Documented in src/renderer/README.md.

$ node scripts/check-renderer-architecture.mjs --base <main>   # before, on #4457's tree
- src/renderer/expected-operation-error.ts: new legacyAppShellClosure debt entries are forbidden
- src/renderer/plan-mode-panel.tsx: new dependency debt ./expected-operation-error.js
  (…12 files, 25 violations)

$ node --test scripts/check-renderer-architecture.test.mjs     # after, this branch
# pass 68  fail 0
$ node scripts/check-renderer-architecture.mjs --base 5013f904b
Renderer architecture check passed against 5013f904b.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex implemented the revision propagation and causal overlay retirement, added regression tests, and assisted with review. All affected commits include Generated-by: Codex trailers.

The locale policy forces user-visible copy out of business files and
into locales/ catalogs, which adds import edges the renderer
architecture ratchet forbids in legacy files — the two gates deadlock.
Admit exactly one dependency class: a structurally validated copy
catalog (UiCatalog marker, zero tracked capabilities, bare package
imports only), re-verified on every run so a catalog can never become
a dependency tunnel. Root-entry import and token ratchets stay strict.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified the load-bearing claims on da6662a9: validation re-runs from the working tree on every check (no grandfathering), the bare-specifier rule is equivalent to resolveDependency's two prefixes, root-entry metrics still ratchet, and the stale-budget check forces the ledger deletion. Approving; two things worth settling before this shapes the next PRs.

The catalog predicate is brittle, and the ledger deletion is a one-way door. The predicate reuses environmentCapabilities, which treats any unshadowed identifier in ENVIRONMENT_OBJECTS as a global. I ran analyzeRendererSource from this head against the head catalogs: settings-data-copy.ts reports {history: 3} — that's the copy key history: '输入历史' — and settings-test-result-copy.ts reports {location: 1} from a parameter name. Three more (onboarding-copy, settings-navigation-copy, settings-projects-copy) fail the bare-specifier rule on type-only imports from src/shared/src/preload. None of those five currently carry deleted budget edges, so CI is green — but once a future change gives shell-copy.ts (10 deleted edges) or conversation-copy.ts (8) a key named history or a type-only relative import, the catalog silently drops out, the feature edges come back as unbudgeted, and re-adding them to the ledger hits new feature-to-legacy imports are forbidden. Nothing in the violation text says "this catalog stopped validating". Any of these would close it: exclude object keys/parameters from the catalog check (or use a narrower "no behavior" predicate than environmentCapabilities), allow type-only imports that resolve outside src/renderer, or at minimum emit a dedicated violation when a *-copy.ts under locales/ fails validation.

The #4457 framing doesn't match its log. Run 33500504864 has 25 violations; 13 are expected-operation-error.ts being a new renderer root module (10 dependency-debt edges, closure entry, unclassified file, feature import), which this PR doesn't touch. It clears 2. And #4457's shell-copy.ts imports ../expected-operation-error.js, which fails the new predicate — so on top of this PR, #4457 gains roughly 18 unfixable violations rather than losing 14. Worth rewriting the description to what this PR actually admits, and coordinating with #4457 (move expected-operation-error out of src/renderer/, or reach the work-board-ipc types through a bare specifier).

Minor: README says "never renderer implementation", but the rule rejects src/shared/src/preload type imports too; no fixture for the @maka/desktop/ prefix or the unresolvedDependencies case; the ledger drops 25 edges, not 26.

The catalog predicate inherited analyzer false positives (object keys
and type-space identifiers counted as environment globals) and rejected
type-only relative imports, so a catalog could silently lose admission.
Count only value references, restrict the bare-specifier rule to runtime
imports, and report failed catalogs with a dedicated violation.
@orangeCatDeveloper

Copy link
Copy Markdown
Contributor Author

Verified the load-bearing claims on da6662a9: validation re-runs from the working tree on every check (no grandfathering), the bare-specifier rule is equivalent to resolveDependency's two prefixes, root-entry metrics still ratchet, and the stale-budget check forces the ledger deletion. Approving; two things worth settling before this shapes the next PRs.

The catalog predicate is brittle, and the ledger deletion is a one-way door. The predicate reuses environmentCapabilities, which treats any unshadowed identifier in ENVIRONMENT_OBJECTS as a global. I ran analyzeRendererSource from this head against the head catalogs: settings-data-copy.ts reports {history: 3} — that's the copy key history: '输入历史' — and settings-test-result-copy.ts reports {location: 1} from a parameter name. Three more (onboarding-copy, settings-navigation-copy, settings-projects-copy) fail the bare-specifier rule on type-only imports from src/shared/src/preload. None of those five currently carry deleted budget edges, so CI is green — but once a future change gives shell-copy.ts (10 deleted edges) or conversation-copy.ts (8) a key named history or a type-only relative import, the catalog silently drops out, the feature edges come back as unbudgeted, and re-adding them to the ledger hits new feature-to-legacy imports are forbidden. Nothing in the violation text says "this catalog stopped validating". Any of these would close it: exclude object keys/parameters from the catalog check (or use a narrower "no behavior" predicate than environmentCapabilities), allow type-only imports that resolve outside src/renderer, or at minimum emit a dedicated violation when a *-copy.ts under locales/ fails validation.

The #4457 framing doesn't match its log. Run 33500504864 has 25 violations; 13 are expected-operation-error.ts being a new renderer root module (10 dependency-debt edges, closure entry, unclassified file, feature import), which this PR doesn't touch. It clears 2. And #4457's shell-copy.ts imports ../expected-operation-error.js, which fails the new predicate — so on top of this PR, #4457 gains roughly 18 unfixable violations rather than losing 14. Worth rewriting the description to what this PR actually admits, and coordinating with #4457 (move expected-operation-error out of src/renderer/, or reach the work-board-ipc types through a bare specifier).

Minor: README says "never renderer implementation", but the rule rejects src/shared/src/preload type imports too; no fixture for the @maka/desktop/ prefix or the unresolvedDependencies case; the ledger drops 25 edges, not 26.

Updated in the next revision

@orangeCatDeveloper

Copy link
Copy Markdown
Contributor Author

@Astro-Han CI is all green

@orangeCatDeveloper

Copy link
Copy Markdown
Contributor Author

@Astro-Han Can we merge this? It will unblock my other refactor PRs. Thank you!

@Astro-Han
Astro-Han merged commit ae53d5c into apache:main Sep 2, 2026
1 check passed
@orangeCatDeveloper
orangeCatDeveloper deleted the chore/renderer-arch-catalog-class branch September 2, 2026 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/L Under 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants