You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maka.apache.org by as...@apache.org on 2026/09/05 06:55:25 UTC
(maka) branch main updated: chore(desktop): stop pricing sanctioned imports in the renderer ratchet (#4823)
This is an automated email from the ASF dual-hosted git repository.
Astro-Han pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/maka.git
The following commit(s) were added to refs/heads/main by this push:
new 21702c85cf chore(desktop): stop pricing sanctioned imports in the renderer ratchet (#4823)
21702c85cf is described below
commit 21702c85cf9f1387dd8792fbdb2a05f56341baf7
Author: NekoPunch <95...@users.noreply.github.com>
AuthorDate: Fri Sep 4 23:55:20 2026 -0700
chore(desktop): stop pricing sanctioned imports in the renderer ratchet (#4823)
The renderer architecture ratchet admitted a legacy file's dependency on a validated copy catalog, a shell module or a public application contract, but still counted the importDeclarations / importSpecifiers of those edges as debt. Replacing eight inlined lines with one import from application/contracts failed with "importSpecifiers debt increased", so the incentive ran backwards: copy the helper rather than import it. Copy catalogs hit the same inconsistency: validateCopyCatalog perm [...]
Import debt is now computed per source and excludes the sources isSanctionedDependencyTarget already exempts for that section; a validated catalog's bare package runtime imports are exempt from closure debt, matching catalog validation. The ledger is regenerated: every changed entry is lower, so the one-way ratchet holds. Two fixture tests pin the sanctioned edge as free and a private application/sessions import as still priced.
No product behavior change. Ledger entries now depend on other files' zones, so a later move into shell/ or a public surface should regenerate the ledger rather than edit counts by hand.
Generated-by: Claude Code
---
apps/desktop/renderer-architecture.json | 60 +++++++++----------
.../scripts/check-renderer-architecture.mjs | 67 ++++++++++++++++------
.../scripts/check-renderer-architecture.test.mjs | 62 +++++++++++++++++++-
3 files changed, 139 insertions(+), 50 deletions(-)
diff --git a/apps/desktop/renderer-architecture.json b/apps/desktop/renderer-architecture.json
index f6cd35fd2c..c4724663db 100644
--- a/apps/desktop/renderer-architecture.json
+++ b/apps/desktop/renderer-architecture.json
@@ -311,7 +311,7 @@
"nonTriviaTokens": 92
},
"src/renderer/app-shell-chat-actions.ts": {
- "importDeclarations": 9,
+ "importDeclarations": 8,
"bridgePaths": {
"window.maka.newTasks.create": 1,
"window.maka.sessions.remove": 1,
@@ -337,11 +337,11 @@
"@maka/core/session-name": 1,
"@maka/ui": 1
},
- "importSpecifiers": 16,
+ "importSpecifiers": 14,
"nonTriviaTokens": 4086
},
"src/renderer/app-shell-chrome-actions.tsx": {
- "importDeclarations": 5,
+ "importDeclarations": 4,
"bridgePaths": {},
"environmentCapabilities": {},
"hookCalls": {
@@ -357,11 +357,11 @@
"@maka/ui": 1,
"@maka/ui/icons": 1
},
- "importSpecifiers": 8,
+ "importSpecifiers": 7,
"nonTriviaTokens": 408
},
"src/renderer/app-shell-command-actions.ts": {
- "importDeclarations": 7,
+ "importDeclarations": 5,
"bridgePaths": {
"window.maka.connections.setDefault": 1,
"window.maka.connections.test": 1,
@@ -388,11 +388,11 @@
"./locales/shell-copy.js": 1,
"react": 1
},
- "importSpecifiers": 11,
+ "importSpecifiers": 9,
"nonTriviaTokens": 2307
},
"src/renderer/app-shell-context-compaction.ts": {
- "importDeclarations": 1,
+ "importDeclarations": 0,
"bridgePaths": {},
"environmentCapabilities": {},
"hookCalls": {},
@@ -402,11 +402,11 @@
"dependencyPaths": {
"./locales/shell-copy.js": 1
},
- "importSpecifiers": 1,
+ "importSpecifiers": 0,
"nonTriviaTokens": 610
},
"src/renderer/app-shell-copy.ts": {
- "importDeclarations": 2,
+ "importDeclarations": 1,
"bridgePaths": {},
"environmentCapabilities": {},
"hookCalls": {},
@@ -417,7 +417,7 @@
"./locales/shell-copy.js": 1,
"@maka/core/redaction": 1
},
- "importSpecifiers": 2,
+ "importSpecifiers": 1,
"nonTriviaTokens": 504
},
"src/renderer/app-shell-detail-panel.tsx": {
@@ -453,7 +453,7 @@
"nonTriviaTokens": 666
},
"src/renderer/app-shell-effects.ts": {
- "importDeclarations": 12,
+ "importDeclarations": 11,
"bridgePaths": {
"window.maka.app.info": 1,
"window.maka.appWindow.subscribeCommand": 1,
@@ -502,11 +502,11 @@
"@maka/core/session-event-health": 1,
"react": 1
},
- "importSpecifiers": 20,
+ "importSpecifiers": 19,
"nonTriviaTokens": 3816
},
"src/renderer/app-shell-overlays.tsx": {
- "importDeclarations": 8,
+ "importDeclarations": 7,
"bridgePaths": {},
"environmentCapabilities": {
"window": 2,
@@ -534,11 +534,11 @@
"@maka/ui": 1,
"react": 1
},
- "importSpecifiers": 12,
+ "importSpecifiers": 11,
"nonTriviaTokens": 977
},
"src/renderer/app-shell-project-actions.ts": {
- "importDeclarations": 5,
+ "importDeclarations": 4,
"bridgePaths": {
"window.maka.app.openPath": 4,
"window.maka.app.resolveProjectGitInfo": 1,
@@ -564,11 +564,11 @@
"./open-path": 1,
"./session-workspace-errors": 1
},
- "importSpecifiers": 9,
+ "importSpecifiers": 7,
"nonTriviaTokens": 2284
},
"src/renderer/app-shell-revision-actions.ts": {
- "importDeclarations": 6,
+ "importDeclarations": 4,
"bridgePaths": {
"window.maka.sessions.abandonSessionCopy": 2,
"window.maka.sessions.reviseBeforeTurn": 1
@@ -588,11 +588,11 @@
"./session-workspace-errors.js": 1,
"@maka/core/session": 1
},
- "importSpecifiers": 10,
+ "importSpecifiers": 8,
"nonTriviaTokens": 2316
},
"src/renderer/app-shell-session-events.ts": {
- "importDeclarations": 3,
+ "importDeclarations": 2,
"bridgePaths": {},
"environmentCapabilities": {
"requestAnimationFrame": 1,
@@ -610,11 +610,11 @@
"./model-connection-errors.js": 1,
"@maka/ui": 1
},
- "importSpecifiers": 12,
+ "importSpecifiers": 11,
"nonTriviaTokens": 2974
},
"src/renderer/app-shell-session-start-actions.ts": {
- "importDeclarations": 3,
+ "importDeclarations": 2,
"bridgePaths": {
"window.maka.newTasks.create": 1,
"window.maka.onboarding.setMilestone": 1
@@ -631,7 +631,7 @@
"./model-connection-errors.js": 1,
"./session-workspace-errors.js": 1
},
- "importSpecifiers": 7,
+ "importSpecifiers": 5,
"nonTriviaTokens": 650
},
"src/renderer/app-shell-session-ui-state.ts": {
@@ -649,7 +649,7 @@
"nonTriviaTokens": 7
},
"src/renderer/app-shell-stop-action.ts": {
- "importDeclarations": 2,
+ "importDeclarations": 0,
"bridgePaths": {
"window.maka.sessions.stop": 1
},
@@ -664,11 +664,11 @@
"./locales/conversation-copy.js": 1,
"./locales/shell-copy.js": 1
},
- "importSpecifiers": 2,
+ "importSpecifiers": 0,
"nonTriviaTokens": 302
},
"src/renderer/app-shell-turn-actions.ts": {
- "importDeclarations": 4,
+ "importDeclarations": 2,
"bridgePaths": {
"window.maka.sessions.branchFromTurn": 1,
"window.maka.sessions.regenerateTurn": 1
@@ -686,7 +686,7 @@
"./session-copy-attempt.js": 1,
"./session-workspace-errors.js": 1
},
- "importSpecifiers": 5,
+ "importSpecifiers": 3,
"nonTriviaTokens": 650
},
"src/renderer/app-shell-turn-view-model.ts": {
@@ -713,7 +713,7 @@
"nonTriviaTokens": 1408
},
"src/renderer/app-shell.tsx": {
- "importDeclarations": 92,
+ "importDeclarations": 81,
"bridgePaths": {
"window.maka.app.installUpdate": 1,
"window.maka.app.retryUpdateDownload": 1,
@@ -895,7 +895,7 @@
"@maka/ui/icons": 1,
"react": 1
},
- "importSpecifiers": 147,
+ "importSpecifiers": 124,
"nonTriviaTokens": 15588
},
"src/renderer/use-app-shell-composer-quotes.ts": {
@@ -916,7 +916,7 @@
"nonTriviaTokens": 360
},
"src/renderer/use-app-shell-session-list.ts": {
- "importDeclarations": 10,
+ "importDeclarations": 8,
"bridgePaths": {
"window.maka.sessions.list": 1
},
@@ -941,7 +941,7 @@
"@maka/ui": 1,
"react": 1
},
- "importSpecifiers": 13,
+ "importSpecifiers": 11,
"nonTriviaTokens": 581
},
"src/renderer/use-app-shell-session-ui-reads.ts": {
diff --git a/apps/desktop/scripts/check-renderer-architecture.mjs b/apps/desktop/scripts/check-renderer-architecture.mjs
index 606952781f..e522c6901c 100644
--- a/apps/desktop/scripts/check-renderer-architecture.mjs
+++ b/apps/desktop/scripts/check-renderer-architecture.mjs
@@ -1249,6 +1249,8 @@ export function analyzeRendererSource(source, file = 'fixture.ts') {
const moduleReexports = [];
let importDeclarations = 0;
let importSpecifiers = 0;
+ const importDeclarationsBySource = {};
+ const importSpecifiersBySource = {};
let unresolvedDependencies = 0;
function recordBridgePath(path) {
@@ -1261,9 +1263,14 @@ export function analyzeRendererSource(source, file = 'fixture.ts') {
function visit(node, parent) {
if (node.type === 'ImportDeclaration' && !typeOnlySourceDependency(node)) {
+ const specifierCount = node.specifiers.filter((specifier) => specifier.importKind !== 'type').length;
importDeclarations += 1;
- importSpecifiers += node.specifiers.filter((specifier) => specifier.importKind !== 'type').length;
+ importSpecifiers += specifierCount;
const source = staticString(node.source);
+ if (source !== undefined) {
+ importDeclarationsBySource[source] = (importDeclarationsBySource[source] ?? 0) + 1;
+ importSpecifiersBySource[source] = (importSpecifiersBySource[source] ?? 0) + specifierCount;
+ }
if (source !== undefined && node.importKind !== 'type') {
for (const specifier of node.specifiers) {
if (specifier.importKind === 'type') continue;
@@ -1544,7 +1551,9 @@ export function analyzeRendererSource(source, file = 'fixture.ts') {
environmentCapabilities: sortedObject(environmentCapabilities),
hookCalls: sortedObject(hookCalls),
importDeclarations,
+ importDeclarationsBySource: sortedObject(importDeclarationsBySource),
importSpecifiers,
+ importSpecifiersBySource: sortedObject(importSpecifiersBySource),
lifecycleMethods: sortedObject(lifecycleMethods),
moduleImports: moduleImports.map((entry, index) => ({
...entry,
@@ -1651,11 +1660,20 @@ function capabilityDebtMetrics(analysis) {
};
}
-function debtMetrics(analysis) {
+// Imports from a sanctioned target (a validated copy catalog, or for AppShell
+// files a shell / public application / public feature module) are the edges
+// the migration wants a legacy file to take on; they cost no import debt, so
+// a legacy file is never pushed to inline a helper it could import.
+function debtMetrics(analysis, isSanctionedSource) {
+ const unsanctioned = (bySource) =>
+ Object.entries(bySource).reduce(
+ (total, [source, count]) => (isSanctionedSource(source) ? total : total + count),
+ 0,
+ );
return {
- importDeclarations: analysis.importDeclarations,
+ importDeclarations: unsanctioned(analysis.importDeclarationsBySource),
...capabilityDebtMetrics(analysis),
- importSpecifiers: analysis.importSpecifiers,
+ importSpecifiers: unsanctioned(analysis.importSpecifiersBySource),
nonTriviaTokens: analysis.nonTriviaTokens,
};
}
@@ -2247,15 +2265,15 @@ function validateMetric(path, metric, actual, expected, violations) {
}
}
-function validateDebtFile(desktopRoot, path, expected, violations, metrics = ROOT_DEBT_METRICS) {
- const absolutePath = resolve(desktopRoot, path);
- if (!existsSync(absolutePath)) {
+function validateDebtFile(desktopRoot, path, expected, violations, section) {
+ if (!existsSync(resolve(desktopRoot, path))) {
violations.push(`${path}: debt ledger entry points to a missing file`);
return;
}
- const analysis = analyzeRendererSource(readFileSync(absolutePath, 'utf8'), path);
- for (const metric of metrics) {
- validateMetric(path, metric, analysis[metric], expected[metric], violations);
+ const rootSection = section === 'legacyAppShell' || section === 'rootDebt';
+ const actual = rootSection ? debtForPath(desktopRoot, path, section) : capabilityDebtForPath(desktopRoot, path);
+ for (const metric of rootSection ? ROOT_DEBT_METRICS : CAPABILITY_DEBT_METRICS) {
+ validateMetric(path, metric, actual[metric], expected[metric], violations);
}
}
@@ -2282,7 +2300,7 @@ function validateLegacyLedger(desktopRoot, config, violations) {
}
for (const [path, expected] of Object.entries(config.legacyAppShell.files)) {
- validateDebtFile(desktopRoot, path, expected, violations);
+ validateDebtFile(desktopRoot, path, expected, violations, 'legacyAppShell');
}
const actualClosure = collectRootDependencyClosure(desktopRoot, expectedFiles, violations, 'AppShell');
const expectedClosure = Object.keys(config.legacyAppShell.closure).sort();
@@ -2299,10 +2317,10 @@ function validateLegacyLedger(desktopRoot, config, violations) {
if (!isRootClosureDebtSource(path) || DECLARATION_FILE.test(path)) {
violations.push(`${path}: AppShell closure debt must point to a non-owner Desktop source`);
}
- validateDebtFile(desktopRoot, path, expected, violations, CAPABILITY_DEBT_METRICS);
+ validateDebtFile(desktopRoot, path, expected, violations, 'legacyAppShellClosure');
}
for (const [path, expected] of Object.entries(config.rootDebt)) {
- validateDebtFile(desktopRoot, path, expected, violations);
+ validateDebtFile(desktopRoot, path, expected, violations, 'rootDebt');
}
const appShellDebtPaths = new Set([...expectedFiles, ...expectedClosure]);
const rootDebtPaths = Object.keys(config.rootDebt).sort();
@@ -2322,7 +2340,7 @@ function validateLegacyLedger(desktopRoot, config, violations) {
if (!isRootClosureDebtSource(path) || DECLARATION_FILE.test(path)) {
violations.push(`${path}: renderer root closure debt must point to a non-owner Desktop source`);
}
- validateDebtFile(desktopRoot, path, expected, violations, CAPABILITY_DEBT_METRICS);
+ validateDebtFile(desktopRoot, path, expected, violations, 'rootDebtClosure');
}
const ownedPaths = new Map();
@@ -2981,7 +2999,7 @@ function validateCopyCatalog(desktopRoot, relativePath) {
if (metricTotal(value) > 0) return `catalog carries ${metric} (${describeMetric(value)})`;
}
const forbidden = inspection.runtimeDependencies.find(
- (dependency) => dependency.startsWith('.') || dependency.startsWith(DESKTOP_SELF_PREFIX),
+ (dependency) => !isBarePackageSpecifier(dependency),
);
if (forbidden !== undefined) {
return `runtime import ${forbidden} is not a bare package specifier`;
@@ -3008,9 +3026,17 @@ function validateCopyCatalogFiles(desktopRoot, violations) {
}
}
+function isBarePackageSpecifier(dependency) {
+ return !dependency.startsWith('.') && !dependency.startsWith(DESKTOP_SELF_PREFIX);
+}
+
function withoutSanctionedDependencies(desktopRoot, section, importerPath, dependencyPaths) {
+ // A validated catalog is already restricted to bare package runtime imports;
+ // pricing them again would push copy helpers back inline into the catalog.
+ const importerIsCatalog = isValidatedCopyCatalog(desktopRoot, importerPath);
const filtered = {};
for (const [dependency, count] of Object.entries(dependencyPaths)) {
+ if (importerIsCatalog && isBarePackageSpecifier(dependency)) continue;
if (isSanctionedDependencyTarget(desktopRoot, section, importerPath, dependency)) continue;
filtered[dependency] = count;
}
@@ -3043,8 +3069,11 @@ function allowsMigrationDependency({ base, current, dependency, desktopRoot, pat
return swapZones.includes(zoneFor(normalizePath(relative(desktopRoot, target))).kind);
}
-function debtForPath(desktopRoot, path) {
- return debtMetrics(analyzeRendererSource(readFileSync(resolve(desktopRoot, path), 'utf8'), path));
+function debtForPath(desktopRoot, path, section) {
+ return debtMetrics(
+ analyzeRendererSource(readFileSync(resolve(desktopRoot, path), 'utf8'), path),
+ (source) => isSanctionedDependencyTarget(desktopRoot, section, path, source),
+ );
}
function capabilityDebtForPath(desktopRoot, path) {
@@ -3091,7 +3120,7 @@ export function generateArchitectureConfig(desktopRoot, config) {
const imports = collectLegacyImportEdges(desktopRoot);
const rootDebt = {};
for (const path of Object.keys(config.rootDebt ?? {}).sort()) {
- if (existsSync(resolve(desktopRoot, path))) rootDebt[path] = debtForPath(desktopRoot, path);
+ if (existsSync(resolve(desktopRoot, path))) rootDebt[path] = debtForPath(desktopRoot, path, 'rootDebt');
}
const appShellDebtPaths = new Set([...appShellFiles, ...closureFiles]);
const rootDebtClosureFiles = collectRootDependencyClosure(
@@ -3111,7 +3140,7 @@ export function generateArchitectureConfig(desktopRoot, config) {
legacyPlatformImports: imports.platform,
controllerOwners: controllerOwnersOf(config),
legacyAppShell: {
- files: Object.fromEntries(appShellFiles.map((path) => [path, debtForPath(desktopRoot, path)])),
+ files: Object.fromEntries(appShellFiles.map((path) => [path, debtForPath(desktopRoot, path, 'legacyAppShell')])),
closure: Object.fromEntries(closureFiles.map((path) => [path, capabilityDebtForPath(desktopRoot, path)])),
},
rootDebt,
diff --git a/apps/desktop/scripts/check-renderer-architecture.test.mjs b/apps/desktop/scripts/check-renderer-architecture.test.mjs
index 46d6e81b7c..db2c11d8cf 100644
--- a/apps/desktop/scripts/check-renderer-architecture.test.mjs
+++ b/apps/desktop/scripts/check-renderer-architecture.test.mjs
@@ -2229,9 +2229,15 @@ describe('renderer architecture checker fixtures', () => {
return <AlphaHost scope={defaultSessionScope} />;
}
`;
- const currentDebt = debtForSource(appShellSource, appShellPath);
+ const currentDebt = {
+ ...debtForSource(appShellSource, appShellPath),
+ importDeclarations: 0,
+ importSpecifiers: 0,
+ };
const baseDebt = {
...currentDebt,
+ importDeclarations: 2,
+ importSpecifiers: 2,
dependencyPaths: {
'./legacy-alpha-owner.js': 1,
'./legacy-session-owner.js': 1,
@@ -2271,6 +2277,37 @@ describe('renderer architecture checker fixtures', () => {
);
});
+ for (const [targetPath, pricing] of [
+ ['src/renderer/application/contracts/fixture-diagnostics.ts', 'free'],
+ ['src/renderer/application/sessions/fixture-service.ts', 'priced'],
+ ]) {
+ it(`${pricing === 'free' ? 'exempts' : 'prices'} AppShell import specifiers from ${targetPath}`, async () => {
+ const specifier = `./${targetPath.slice('src/renderer/'.length).replace(/\.ts$/u, '.js')}`;
+ await withDesktopFixture(
+ {
+ [TRANSITIVE_APP_SHELL_PATH]: `
+ import { reportFixture } from '${specifier}';
+ export const AppShell = reportFixture('shell');
+ `,
+ [targetPath]: `export function reportFixture(scope: string): string { return scope; }`,
+ },
+ (desktopRoot) => {
+ const currentConfig = generateArchitectureConfig(desktopRoot, transitiveAppShellSeedConfig());
+ const baseConfig = structuredClone(currentConfig);
+ Object.assign(baseConfig.legacyAppShell.files[TRANSITIVE_APP_SHELL_PATH], {
+ importDeclarations: 0,
+ importSpecifiers: 0,
+ dependencyPaths: {},
+ });
+ const priced = violationsFor(desktopRoot, currentConfig, baseConfig).some((violation) =>
+ violation.startsWith(`${TRANSITIVE_APP_SHELL_PATH}: importSpecifiers debt increased`),
+ );
+ assert.equal(priced, pricing === 'priced');
+ },
+ );
+ });
+ }
+
it('rejects replacing legacy AppShell debt with a feature private import', async () => {
const appShellPath = 'src/renderer/app-shell.tsx';
const appShellSource = `
@@ -2831,6 +2868,29 @@ describe('validated copy catalog dependencies', () => {
);
});
+ it('does not price a catalog\'s own bare package runtime import', async () => {
+ await withDesktopFixture(
+ transitiveAppShellFiles(
+ `
+ import { FIXTURE_COPY } from './locales/fixture-copy.js';
+ export const legacySessionHelper = FIXTURE_COPY.en.notice;
+ `,
+ {
+ [CATALOG_PATH]: catalogSource(`
+ import { lookupCopy } from '@maka/core/ui-locale';
+ export const noticeFor = (code: string) => lookupCopy(FIXTURE_COPY.en, code);
+ `),
+ },
+ ),
+ (desktopRoot) => {
+ const currentConfig = generateArchitectureConfig(desktopRoot, catalogSeedConfig());
+ const baseConfig = structuredClone(currentConfig);
+ baseConfig.legacyAppShell.closure[CATALOG_PATH].dependencyPaths = {};
+ assert.deepEqual(violationsFor(desktopRoot, currentConfig, baseConfig), []);
+ },
+ );
+ });
+
const INVALID_CATALOGS = [
['a hook call', catalogSource(`
import { useState } from 'react';
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org