ci(lint): stop new cli imports from the core package root (#11798)

Importing a value from the @qwen-code/qwen-code-core root evaluates all
of core in every test whose import graph reaches the importing file,
which is where most cli test time goes (#10908). The existing rule stops
at packages/core/src, so cli kept adding root imports: 446 production
files at #10957's merge, 465 eight days later.

Enable @typescript-eslint/no-restricted-imports for cli production files
with type-only imports allowed, reusing the barrel specifier set from
no-core-root-barrel-import. The 372 files that value-import the root
today are listed in eslint.legacy-core-barrel-imports.mjs; the list only
shrinks. The new file is registered wherever eslint.legacy-filenames.mjs
is: the lint-gate freshness list, the autofix sensitive-file classifier,
and the hygiene fix agent's deny list.

ESLint and Prettier (--experimental-cli) were run on the changed files,
and the new block was exercised through ESLint's API against the real
eslint.config.js. The scripts/tests vitest suites were not run locally.

Refs #10908
This commit is contained in:
易良 authored and GitHub committed 2026-09-14 04:49:03 +00:00
1 parent f71a4e797e
commit 351b5fc51a
10 files changed
+495 -4

No files matched your search

@@ -48,6 +48,7 @@ export const GATE_FILES = [
'scripts/lint.js',
'eslint.config.js',
'eslint.legacy-filenames.mjs',
'eslint.legacy-core-barrel-imports.mjs',
'.prettierrc.json',
'.prettierignore',
'.github/workflows/ci.yml',
@@ -50,6 +50,7 @@ test('pins the gate file list', () => {
'scripts/lint.js',
'eslint.config.js',
'eslint.legacy-filenames.mjs',
'eslint.legacy-core-barrel-imports.mjs',
'.prettierrc.json',
'.prettierignore',
'.github/workflows/ci.yml',
@@ -734,12 +734,12 @@ sensitive_class_of() {
package-lock.json | npm-shrinkwrap.json | */package-lock.json | */npm-shrinkwrap.json | patches/*) echo 'supply-chain' ;;
.gitattributes | */.gitattributes) echo 'measurement-config' ;;
*) case "${f##*/}" in
eslint.config.* | eslint.legacy-filenames.mjs | vitest.config.* | tsconfig.json | tsconfig.*.json)
eslint.config.* | eslint.legacy-filenames.mjs | eslint.legacy-core-barrel-imports.mjs | vitest.config.* | tsconfig.json | tsconfig.*.json)
# Workspace-root configs are machinery; a scaffold template deep in
# a src tree is test/fixture data (same exemption manifests get).
if at_workspace_root "${f}"; then
case "${f##*/}" in
eslint.config.* | eslint.legacy-filenames.mjs) echo 'lint-config' ;;
eslint.config.* | eslint.legacy-filenames.mjs | eslint.legacy-core-barrel-imports.mjs) echo 'lint-config' ;;
vitest.config.*) echo 'test-config' ;;
*) echo 'ts-config' ;;
esac
+1
View File
@@ -431,6 +431,7 @@ jobs:
"write_file(**/tsconfig.*.json)",
"write_file(**/eslint.config.*)",
"write_file(**/eslint.legacy-filenames.*)",
"write_file(**/eslint.legacy-core-barrel-imports.*)",
"write_file(**/vitest.config.*)",
"write_file(**/vite.config.*)",
"write_file(**/node_modules/**)"
+1
View File
@@ -166,6 +166,7 @@ npm run preflight # Full check: clean → install → format → lint → build
2-space indent, 80-char width
- **Linting**: No `any` types, consistent type imports, no relative imports
between packages
- **Core imports in cli**: production code in `packages/cli/src` imports core values from the module that defines them (`@qwen-code/qwen-code-core/utils/debugLogger.js`), not the package root, which evaluates all of core in every test that reaches the file. Type-only imports are exempt. Files that predate the rule are allowlisted in `eslint.legacy-core-barrel-imports.mjs`; drop an entry when you move its file off the root, never add one.
- **Tests**: Collocated with source (`file.test.ts` next to `file.ts`),
vitest framework
- **File naming**: `PascalCase.tsx` for React components, `kebab-case.ts` for
+1 -1
View File
@@ -30,7 +30,7 @@ function isCoreProductionFile(filename) {
const CORE_PACKAGE_SPECIFIER = '@qwen-code/qwen-code-core';
// The package exports map ("./*", "./src/*", "./dist/*") also exposes the root
// barrel through these self-reference subpaths.
const CORE_BARREL_SPECIFIERS = new Set([
export const CORE_BARREL_SPECIFIERS = new Set([
CORE_PACKAGE_SPECIFIER,
`${CORE_PACKAGE_SPECIFIER}/index.js`,
`${CORE_PACKAGE_SPECIFIER}/src/index.js`,
+31 -1
View File
@@ -13,10 +13,13 @@ import importPlugin from 'eslint-plugin-import';
import vitest from '@vitest/eslint-plugin';
import globals from 'globals';
import checkFile from 'eslint-plugin-check-file';
import noCoreRootBarrelImport from './eslint-rules/no-core-root-barrel-import.js';
import noCoreRootBarrelImport, {
CORE_BARREL_SPECIFIERS,
} from './eslint-rules/no-core-root-barrel-import.js';
import noUtilsUpwardImport from './eslint-rules/no-utils-upward-import.js';
import noCoreUtilsUpwardImport from './eslint-rules/no-core-utils-upward-import.js';
import { legacyFilenames } from './eslint.legacy-filenames.mjs';
import { legacyCoreBarrelImports } from './eslint.legacy-core-barrel-imports.mjs';
import noConfigObjectCreate from './eslint-rules/no-config-object-create.js';
// General syntax restrictions applied to every TS/TSX source file. Hoisted so
@@ -291,6 +294,33 @@ export default tseslint.config(
'architecture/no-core-utils-upward-import': 'error',
},
},
{
// Importing a value from core's package root evaluates all of core in
// every test whose import graph reaches the importing file, which is
// where most cli test time goes (#10908). Type-only imports are erased
// and stay allowed. Files that predate this rule are listed in
// eslint.legacy-core-barrel-imports.mjs; drop an entry when migrating it.
files: ['packages/cli/src/**/*.{ts,tsx}'],
ignores: [
'**/*.{test,spec}.{ts,tsx}',
'**/__tests__/**',
'**/fixtures/**',
...legacyCoreBarrelImports,
],
rules: {
'@typescript-eslint/no-restricted-imports': [
'error',
{
paths: [...CORE_BARREL_SPECIFIERS].map((name) => ({
name,
allowTypeImports: true,
message:
"Import from the core module that defines the symbol, e.g. '@qwen-code/qwen-code-core/utils/debugLogger.js'. The package root evaluates all of core in every test that reaches this file (#10908).",
})),
},
],
},
},
{
// no-restricted-imports only sees static import/export declarations, so a
// dynamic `await import('../serve/...')` would slip past the #8084 guard
+383
View File
@@ -0,0 +1,383 @@
/**
* cli production files that still import values from the core package root.
*
* Used by eslint.config.js to exempt these files from the rule that sends cli
* imports to the core module defining each symbol. The list only shrinks:
* remove an entry when its file moves off the package root, and never add one.
*
* See: https://github.com/QwenLM/qwen-code/issues/10908
*/
export const legacyCoreBarrelImports = [
'packages/cli/src/acp-integration/acpAgent.ts',
'packages/cli/src/acp-integration/active-work-reporter.ts',
'packages/cli/src/acp-integration/authMethods.ts',
'packages/cli/src/acp-integration/extension-skills.ts',
'packages/cli/src/acp-integration/generation.ts',
'packages/cli/src/acp-integration/live/capture-screen-context.ts',
'packages/cli/src/acp-integration/live/live-speak-to-user.ts',
'packages/cli/src/acp-integration/live/live-task-tools.ts',
'packages/cli/src/acp-integration/model-configuration.ts',
'packages/cli/src/acp-integration/runtimeOutputDirContext.ts',
'packages/cli/src/acp-integration/service/filesystem.ts',
'packages/cli/src/acp-integration/session-model-persistence.ts',
'packages/cli/src/acp-integration/session/Session.ts',
'packages/cli/src/acp-integration/session/SubAgentTracker.ts',
'packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts',
'packages/cli/src/acp-integration/session/emitters/tool-call-emitter.ts',
'packages/cli/src/acp-integration/session/history-replay-page.ts',
'packages/cli/src/acp-integration/session/history-replayer.ts',
'packages/cli/src/acp-integration/session/permissionUtils.ts',
'packages/cli/src/acp-integration/session/recovered-goal-update.ts',
'packages/cli/src/acp-integration/session/repeated-tool-failure-guard.ts',
'packages/cli/src/acp-integration/session/rewrite/LlmRewriter.ts',
'packages/cli/src/acp-integration/session/rewrite/MessageRewriteMiddleware.ts',
'packages/cli/src/acp-integration/session/tasksSnapshot.ts',
'packages/cli/src/acp-integration/session/tool-call-preparation-tracker.ts',
'packages/cli/src/acp-integration/skill-management.ts',
'packages/cli/src/acp-integration/skill-source-download.ts',
'packages/cli/src/commands/channel/config-utils.ts',
'packages/cli/src/commands/channel/daemon-worker.ts',
'packages/cli/src/commands/channel/loop-runtime.ts',
'packages/cli/src/commands/channel/observed-contact-store.ts',
'packages/cli/src/commands/channel/pidfile.ts',
'packages/cli/src/commands/channel/proxy.ts',
'packages/cli/src/commands/channel/runtime.ts',
'packages/cli/src/commands/channel/start.ts',
'packages/cli/src/commands/channel/status.ts',
'packages/cli/src/commands/channel/stop.ts',
'packages/cli/src/commands/extensions/enable.ts',
'packages/cli/src/commands/extensions/install.ts',
'packages/cli/src/commands/extensions/link.ts',
'packages/cli/src/commands/extensions/new.ts',
'packages/cli/src/commands/extensions/settings.ts',
'packages/cli/src/commands/extensions/sources.ts',
'packages/cli/src/commands/extensions/uninstall.ts',
'packages/cli/src/commands/extensions/update.ts',
'packages/cli/src/commands/extensions/utils.ts',
'packages/cli/src/commands/hooks.tsx',
'packages/cli/src/commands/mcp/approve.ts',
'packages/cli/src/commands/mcp/list.ts',
'packages/cli/src/commands/mcp/reconnect.ts',
'packages/cli/src/commands/mcp/remove.ts',
'packages/cli/src/commands/review/agent-prompt.ts',
'packages/cli/src/commands/review/comment-status.ts',
'packages/cli/src/commands/review/cost-ledger.ts',
'packages/cli/src/commands/review/findings.ts',
'packages/cli/src/commands/review/lib/deadline.ts',
'packages/cli/src/commands/review/lib/diff-plan.ts',
'packages/cli/src/commands/review/lib/inline-counts.ts',
'packages/cli/src/commands/review/lib/paths.ts',
'packages/cli/src/commands/review/lib/run-ledger.ts',
'packages/cli/src/commands/review/lib/transcripts.ts',
'packages/cli/src/commands/review/lib/worktree.ts',
'packages/cli/src/commands/review/parse-args.ts',
'packages/cli/src/commands/review/pr-context.ts',
'packages/cli/src/commands/review/recover-findings.ts',
'packages/cli/src/commands/review/repo-context.ts',
'packages/cli/src/commands/review/run.ts',
'packages/cli/src/commands/review/save-artifact.ts',
'packages/cli/src/commands/review/submit.ts',
'packages/cli/src/commands/review/test-plan.ts',
'packages/cli/src/commands/review/workflow-script.ts',
'packages/cli/src/commands/serve.ts',
'packages/cli/src/commands/sessions/common.ts',
'packages/cli/src/commands/sessions/controllers.ts',
'packages/cli/src/commands/sessions/ps.ts',
'packages/cli/src/config/auth.ts',
'packages/cli/src/config/claudeMcpImport.ts',
'packages/cli/src/config/config.ts',
'packages/cli/src/config/daemon-trust-policy-monitor.ts',
'packages/cli/src/config/daemon-trust-policy.ts',
'packages/cli/src/config/environment.ts',
'packages/cli/src/config/extension-runtime-reload.ts',
'packages/cli/src/config/hot-reload.ts',
'packages/cli/src/config/lsp-config-watcher.ts',
'packages/cli/src/config/mcpApprovals.ts',
'packages/cli/src/config/mcpJson.ts',
'packages/cli/src/config/migration/scheduler.ts',
'packages/cli/src/config/permission-settings.ts',
'packages/cli/src/config/sandboxConfig.ts',
'packages/cli/src/config/settings-cache.ts',
'packages/cli/src/config/settings.ts',
'packages/cli/src/config/settingsSchema.ts',
'packages/cli/src/config/settingsWatcher.ts',
'packages/cli/src/config/skill-settings.ts',
'packages/cli/src/config/trustedFolders.ts',
'packages/cli/src/core/auth.ts',
'packages/cli/src/core/initializer.ts',
'packages/cli/src/dualOutput/DualOutputBridge.ts',
'packages/cli/src/external-agents/acp-subagent-executor.ts',
'packages/cli/src/external-agents/codex-subagent-executor.ts',
'packages/cli/src/i18n/index.ts',
'packages/cli/src/i18n/languageUtils.ts',
'packages/cli/src/llm.tsx',
'packages/cli/src/nonInteractive/chat-recording-failure.ts',
'packages/cli/src/nonInteractive/control/controllers/baseController.ts',
'packages/cli/src/nonInteractive/control/controllers/systemController.ts',
'packages/cli/src/nonInteractive/io/BaseJsonOutputAdapter.ts',
'packages/cli/src/nonInteractive/io/StreamJsonOutputAdapter.ts',
'packages/cli/src/nonInteractive/nonInteractiveHelpers.ts',
'packages/cli/src/nonInteractive/tool-result-boundary-diagnostics.ts',
'packages/cli/src/nonInteractiveCli.ts',
'packages/cli/src/nonInteractiveCliCommands.ts',
'packages/cli/src/peerMessaging/peer-messaging.ts',
'packages/cli/src/runtime/channel-delivery.ts',
'packages/cli/src/runtime/scheduled-task-run.ts',
'packages/cli/src/serve/acp-http/client-mcp-ws.ts',
'packages/cli/src/serve/acp-http/dispatch.ts',
'packages/cli/src/serve/acp-http/index.ts',
'packages/cli/src/serve/auth/qwen-device-flow-provider.ts',
'packages/cli/src/serve/conversations/standalone-session-service.ts',
'packages/cli/src/serve/core-runtime.ts',
'packages/cli/src/serve/create-sub-session.ts',
'packages/cli/src/serve/daemon-git-worktree-guard.ts',
'packages/cli/src/serve/daemon-status-provider.ts',
'packages/cli/src/serve/env-snapshot.ts',
'packages/cli/src/serve/fs/paths.ts',
'packages/cli/src/serve/fs/policy.ts',
'packages/cli/src/serve/fs/workspace-file-system.ts',
'packages/cli/src/serve/live/live-session-coordinator.ts',
'packages/cli/src/serve/live/live-task-service.ts',
'packages/cli/src/serve/live/realtime-startup-context.ts',
'packages/cli/src/serve/local-control/service.ts',
'packages/cli/src/serve/model-configuration.ts',
'packages/cli/src/serve/model-providers-edit.ts',
'packages/cli/src/serve/prompt-terminal-ledger.ts',
'packages/cli/src/serve/routes/scheduled-tasks.ts',
'packages/cli/src/serve/routes/session-pr-backfill.ts',
'packages/cli/src/serve/routes/session.ts',
'packages/cli/src/serve/routes/sse-events.ts',
'packages/cli/src/serve/routes/standalone-sessions.ts',
'packages/cli/src/serve/routes/usage-stats.ts',
'packages/cli/src/serve/routes/workspace-auth.ts',
'packages/cli/src/serve/routes/workspace-extensions-controller.ts',
'packages/cli/src/serve/routes/workspace-extensions.ts',
'packages/cli/src/serve/routes/workspace-git-branches.ts',
'packages/cli/src/serve/routes/workspace-git-diff.ts',
'packages/cli/src/serve/routes/workspace-git-log.ts',
'packages/cli/src/serve/routes/workspace-git.ts',
'packages/cli/src/serve/routes/workspace-github-prs.ts',
'packages/cli/src/serve/routes/workspace-management.ts',
'packages/cli/src/serve/routes/workspace-mcp-config.ts',
'packages/cli/src/serve/routes/workspace-models.ts',
'packages/cli/src/serve/routes/workspace-trust.ts',
'packages/cli/src/serve/scheduled-task-keepalive.ts',
'packages/cli/src/serve/scheduled-task-session-lifecycle.ts',
'packages/cli/src/serve/server.ts',
'packages/cli/src/serve/server/aone-mrs.ts',
'packages/cli/src/serve/server/auth-provider-helpers.ts',
'packages/cli/src/serve/server/error-response.ts',
'packages/cli/src/serve/server/git-branch-ops.ts',
'packages/cli/src/serve/server/session-archive.ts',
'packages/cli/src/serve/server/session-export.ts',
'packages/cli/src/serve/server/session-list.ts',
'packages/cli/src/serve/server/session-pr-refresh.ts',
'packages/cli/src/serve/server/telemetry.ts',
'packages/cli/src/serve/server/worktree-orphan-cleanup.ts',
'packages/cli/src/serve/session-attachments-root.ts',
'packages/cli/src/serve/session-id-admission.ts',
'packages/cli/src/serve/session-organization-helpers.ts',
'packages/cli/src/serve/virtual-subagent-sessions.ts',
'packages/cli/src/serve/voice/resolve-voice-config.ts',
'packages/cli/src/serve/voice/voice-ws.ts',
'packages/cli/src/serve/workspace-agents.ts',
'packages/cli/src/serve/workspace-git-state.ts',
'packages/cli/src/serve/workspace-memory.ts',
'packages/cli/src/serve/workspace-providers-status.ts',
'packages/cli/src/serve/workspace-remember.ts',
'packages/cli/src/serve/workspace-runtime-storage.ts',
'packages/cli/src/serve/workspace-skill-management.ts',
'packages/cli/src/serve/workspace-skills-status.ts',
'packages/cli/src/services/BuiltinCommandLoader.ts',
'packages/cli/src/services/BundledSkillLoader.ts',
'packages/cli/src/services/CommandService.ts',
'packages/cli/src/services/FileCommandLoader.ts',
'packages/cli/src/services/McpPromptLoader.ts',
'packages/cli/src/services/SkillCommandLoader.ts',
'packages/cli/src/services/command-factory.ts',
'packages/cli/src/services/commandUtils.ts',
'packages/cli/src/services/housekeeping/scheduler.ts',
'packages/cli/src/services/insight/generators/DataProcessor.ts',
'packages/cli/src/services/insight/generators/StaticInsightGenerator.ts',
'packages/cli/src/services/insight/generators/TemplateRenderer.ts',
'packages/cli/src/services/markdown-command-parser.ts',
'packages/cli/src/services/prompt-processors/argumentProcessor.ts',
'packages/cli/src/services/prompt-processors/atFileProcessor.ts',
'packages/cli/src/services/prompt-processors/shellProcessor.ts',
'packages/cli/src/services/review-worktree-lease.ts',
'packages/cli/src/services/saved-workflow-loader.ts',
'packages/cli/src/services/setup-github.ts',
'packages/cli/src/services/skill-args-file.ts',
'packages/cli/src/services/voice-keyterms.ts',
'packages/cli/src/services/voice-model.ts',
'packages/cli/src/services/voice-service.ts',
'packages/cli/src/services/voice-transcriber.ts',
'packages/cli/src/services/web-shell-brand.ts',
'packages/cli/src/startup/startup-prefetch.ts',
'packages/cli/src/ui/AppContainer.tsx',
'packages/cli/src/ui/auth/ProviderSetupSteps.tsx',
'packages/cli/src/ui/auth/useAuth.ts',
'packages/cli/src/ui/auth/useProviderSetupFlow.ts',
'packages/cli/src/ui/commands/advisor-command.ts',
'packages/cli/src/ui/commands/approvalModeCommand.ts',
'packages/cli/src/ui/commands/arenaCommand.ts',
'packages/cli/src/ui/commands/btwCommand.ts',
'packages/cli/src/ui/commands/bugCommand.ts',
'packages/cli/src/ui/commands/cdCommand.ts',
'packages/cli/src/ui/commands/clearCommand.ts',
'packages/cli/src/ui/commands/compressCommand.ts',
'packages/cli/src/ui/commands/compressFastCommand.ts',
'packages/cli/src/ui/commands/contextCommand.ts',
'packages/cli/src/ui/commands/curator-command.ts',
'packages/cli/src/ui/commands/diffCommand.ts',
'packages/cli/src/ui/commands/directoryCommand.tsx',
'packages/cli/src/ui/commands/docsCommand.ts',
'packages/cli/src/ui/commands/doctorChecks.ts',
'packages/cli/src/ui/commands/doctorCommand.ts',
'packages/cli/src/ui/commands/dreamCommand.ts',
'packages/cli/src/ui/commands/effort-command.ts',
'packages/cli/src/ui/commands/exportCommand.ts',
'packages/cli/src/ui/commands/extensionsCommand.ts',
'packages/cli/src/ui/commands/forkCommand.ts',
'packages/cli/src/ui/commands/goalCommand.ts',
'packages/cli/src/ui/commands/ideCommand.ts',
'packages/cli/src/ui/commands/initCommand.ts',
'packages/cli/src/ui/commands/insightCommand.ts',
'packages/cli/src/ui/commands/languageCommand.ts',
'packages/cli/src/ui/commands/learn-command.ts',
'packages/cli/src/ui/commands/modelCommand.ts',
'packages/cli/src/ui/commands/output-style-command.ts',
'packages/cli/src/ui/commands/output-style-utils.ts',
'packages/cli/src/ui/commands/peers-command.ts',
'packages/cli/src/ui/commands/planCommand.ts',
'packages/cli/src/ui/commands/recapCommand.ts',
'packages/cli/src/ui/commands/rememberCommand.ts',
'packages/cli/src/ui/commands/renameCommand.ts',
'packages/cli/src/ui/commands/skillsCommand.ts',
'packages/cli/src/ui/commands/statsCommand.ts',
'packages/cli/src/ui/commands/summaryCommand.ts',
'packages/cli/src/ui/commands/tasksCommand.ts',
'packages/cli/src/ui/commands/workflowsCommand.ts',
'packages/cli/src/ui/components/AppHeader.tsx',
'packages/cli/src/ui/components/DebugModeNotification.tsx',
'packages/cli/src/ui/components/DialogManager.tsx',
'packages/cli/src/ui/components/ModelDialog.tsx',
'packages/cli/src/ui/components/WorktreeExitDialog.tsx',
'packages/cli/src/ui/components/arena/ArenaStartDialog.tsx',
'packages/cli/src/ui/components/background-view/workflow-save-overlay.tsx',
'packages/cli/src/ui/components/extensions/steps/UninstallConfirmStep.tsx',
'packages/cli/src/ui/components/extensions/tabs/DiscoverTab.tsx',
'packages/cli/src/ui/components/extensions/tabs/InstalledTab.tsx',
'packages/cli/src/ui/components/extensions/tabs/SourcesTab.tsx',
'packages/cli/src/ui/components/extensions/views/ExtensionActionsView.tsx',
'packages/cli/src/ui/components/extensions/views/McpServerActionsView.tsx',
'packages/cli/src/ui/components/extensions/views/PluginDetailView.tsx',
'packages/cli/src/ui/components/hooks/HooksManagementDialog.tsx',
'packages/cli/src/ui/components/hooks/constants.ts',
'packages/cli/src/ui/components/mcp/steps/AuthenticateStep.tsx',
'packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx',
'packages/cli/src/ui/components/messages/CompactToolGroupDisplay.tsx',
'packages/cli/src/ui/components/messages/GoalStatusMessage.tsx',
'packages/cli/src/ui/components/shared/MaxSizedBox.tsx',
'packages/cli/src/ui/components/shared/text-buffer.ts',
'packages/cli/src/ui/components/subagents/create/DescriptionInput.tsx',
'packages/cli/src/ui/context-menu/ContentMouseController.tsx',
'packages/cli/src/ui/contexts/AgentViewContext.tsx',
'packages/cli/src/ui/contexts/KeypressContext.tsx',
'packages/cli/src/ui/contexts/SessionContext.tsx',
'packages/cli/src/ui/handleAutoUpdate.ts',
'packages/cli/src/ui/hooks/atCommandProcessor.ts',
'packages/cli/src/ui/hooks/session-completion.ts',
'packages/cli/src/ui/hooks/session-mention-ref.ts',
'packages/cli/src/ui/hooks/shellCommandProcessor.ts',
'packages/cli/src/ui/hooks/slashCommandProcessor.ts',
'packages/cli/src/ui/hooks/use-llm-stream.ts',
'packages/cli/src/ui/hooks/use-voice-input.ts',
'packages/cli/src/ui/hooks/useAutoAcceptIndicator.ts',
'packages/cli/src/ui/hooks/useAwaySummary.ts',
'packages/cli/src/ui/hooks/useBranchCommand.ts',
'packages/cli/src/ui/hooks/useEditorSettings.ts',
'packages/cli/src/ui/hooks/useFollowupSuggestions.tsx',
'packages/cli/src/ui/hooks/useHistoryManager.ts',
'packages/cli/src/ui/hooks/useIdeTrustListener.ts',
'packages/cli/src/ui/hooks/useMcpApproval.ts',
'packages/cli/src/ui/hooks/usePreferredEditor.ts',
'packages/cli/src/ui/hooks/useProviderUpdates.ts',
'packages/cli/src/ui/hooks/useQwenAuth.ts',
'packages/cli/src/ui/hooks/useReactToolScheduler.ts',
'packages/cli/src/ui/hooks/useResumeCommand.ts',
'packages/cli/src/ui/hooks/useSelectionList.ts',
'packages/cli/src/ui/hooks/useShellHistory.ts',
'packages/cli/src/ui/hooks/useShowMemoryCommand.ts',
'packages/cli/src/ui/hooks/useSlashCompletion.ts',
'packages/cli/src/ui/hooks/useStatusLine.ts',
'packages/cli/src/ui/hooks/useTurnDiffs.ts',
'packages/cli/src/ui/hooks/useWelcomeBack.ts',
'packages/cli/src/ui/models/availableModels.ts',
'packages/cli/src/ui/opentui/client-tool-run.ts',
'packages/cli/src/ui/opentui/commands-dispatch.ts',
'packages/cli/src/ui/opentui/dialog-data.ts',
'packages/cli/src/ui/opentui/dialogs-arena.tsx',
'packages/cli/src/ui/opentui/dialogs-auth.tsx',
'packages/cli/src/ui/opentui/followup-generation.ts',
'packages/cli/src/ui/opentui/input-prompt.tsx',
'packages/cli/src/ui/opentui/item-projection.ts',
'packages/cli/src/ui/opentui/live-session.ts',
'packages/cli/src/ui/opentui/opentui-app-shell.tsx',
'packages/cli/src/ui/opentui/opentui-footer.tsx',
'packages/cli/src/ui/opentui/opentui-header.tsx',
'packages/cli/src/ui/opentui/opentui-runtime.ts',
'packages/cli/src/ui/opentui/shell-mode.ts',
'packages/cli/src/ui/opentui/start-opentui-ui.tsx',
'packages/cli/src/ui/opentui/transcript-view.tsx',
'packages/cli/src/ui/selection/use-text-selection.tsx',
'packages/cli/src/ui/standalone-update.ts',
'packages/cli/src/ui/startInteractiveUI.tsx',
'packages/cli/src/ui/systemInfo.ts',
'packages/cli/src/ui/systemInfoFields.ts',
'packages/cli/src/ui/themes/color-utils.ts',
'packages/cli/src/ui/themes/detect-terminal-theme.ts',
'packages/cli/src/ui/themes/theme-manager.ts',
'packages/cli/src/ui/utils/CodeColorizer.tsx',
'packages/cli/src/ui/utils/InlineMarkdownRenderer.tsx',
'packages/cli/src/ui/utils/approvalModeDisplay.ts',
'packages/cli/src/ui/utils/backgroundWorkUtils.ts',
'packages/cli/src/ui/utils/clipboardUtils.ts',
'packages/cli/src/ui/utils/commandUtils.ts',
'packages/cli/src/ui/utils/compression-text.ts',
'packages/cli/src/ui/utils/export/export-transcript-document.ts',
'packages/cli/src/ui/utils/export/normalize.ts',
'packages/cli/src/ui/utils/formatters.ts',
'packages/cli/src/ui/utils/goal-runtime.ts',
'packages/cli/src/ui/utils/historyMapping.ts',
'packages/cli/src/ui/utils/inline-image-parts.ts',
'packages/cli/src/ui/utils/osc8.ts',
'packages/cli/src/ui/utils/resumeHistoryUtils.ts',
'packages/cli/src/ui/utils/statsDataService.ts',
'packages/cli/src/ui/utils/terminal-image-renderer.ts',
'packages/cli/src/ui/utils/terminalSetup.ts',
'packages/cli/src/ui/utils/updateCheck.ts',
'packages/cli/src/ui/utils/workflow-keyword.ts',
'packages/cli/src/ui/voice/native-audio-recorder.ts',
'packages/cli/src/ui/voice/qwen-asr-realtime-session.ts',
'packages/cli/src/ui/voice/voice-availability.ts',
'packages/cli/src/ui/voice/voice-recorder.ts',
'packages/cli/src/ui/voice/voice-refine.ts',
'packages/cli/src/ui/voice/voice-stream-retry.ts',
'packages/cli/src/ui/voice/voice-stream-session.ts',
'packages/cli/src/utils/acpModelUtils.ts',
'packages/cli/src/utils/apiPreconnect.ts',
'packages/cli/src/utils/deferred-core-runtime.ts',
'packages/cli/src/utils/errors.ts',
'packages/cli/src/utils/extension-mention.ts',
'packages/cli/src/utils/gitUtils.ts',
'packages/cli/src/utils/housekeeping/cleanup.ts',
'packages/cli/src/utils/housekeeping/throttledOnce.ts',
'packages/cli/src/utils/installationInfo.ts',
'packages/cli/src/utils/modelConfigUtils.ts',
'packages/cli/src/utils/osc.ts',
'packages/cli/src/utils/resolvePath.ts',
'packages/cli/src/utils/runBudget.ts',
'packages/cli/src/utils/sessionPaths.ts',
'packages/cli/src/utils/startupWarnings.ts',
];
@@ -1,5 +1,7 @@
import { existsSync } from 'node:fs';
import { describe, expect, it } from 'vitest';
import { ESLint } from 'eslint';
import { legacyCoreBarrelImports } from '../../eslint.legacy-core-barrel-imports.mjs';
describe('core root barrel flat-config integration', () => {
it('reports production self-imports (static, type-only, inline-type, and dynamic), ignores tests', async () => {
@@ -51,4 +53,72 @@ describe('core root barrel flat-config integration', () => {
// test files stay exempt via the rule's own test/fixture exemption
expect(hasViolation(testStatic)).toBe(false);
});
it('reports cli production value imports from the core root, except type-only, tests, and legacy entries', async () => {
const eslint = new ESLint({
cwd: process.cwd(),
overrideConfigFile: 'eslint.config.js',
});
const cliFile = 'packages/cli/src/ui/fixture-boundary.ts';
const [
valueImport,
reExport,
indexSubpath,
typeOnly,
inlineTypeOnly,
ownerModule,
testFile,
legacyFile,
] = await Promise.all([
eslint.lintText("import { Storage } from '@qwen-code/qwen-code-core';", {
filePath: cliFile,
}),
eslint.lintText("export { Storage } from '@qwen-code/qwen-code-core';", {
filePath: cliFile,
}),
eslint.lintText(
"import { Storage } from '@qwen-code/qwen-code-core/index.js';",
{ filePath: cliFile },
),
eslint.lintText(
"import type { Config } from '@qwen-code/qwen-code-core';",
{ filePath: cliFile },
),
eslint.lintText(
"import { type Config } from '@qwen-code/qwen-code-core';",
{ filePath: cliFile },
),
eslint.lintText(
"import { Storage } from '@qwen-code/qwen-code-core/config/storage.js';",
{ filePath: cliFile },
),
eslint.lintText("import { Storage } from '@qwen-code/qwen-code-core';", {
filePath: 'packages/cli/src/ui/fixture-boundary.test.ts',
}),
eslint.lintText("import { Storage } from '@qwen-code/qwen-code-core';", {
filePath: legacyCoreBarrelImports[0],
}),
]);
const hasViolation = (results) =>
results.some((r) =>
r.messages.some(
(m) => m.ruleId === '@typescript-eslint/no-restricted-imports',
),
);
expect(hasViolation(valueImport)).toBe(true);
expect(hasViolation(reExport)).toBe(true);
expect(hasViolation(indexSubpath)).toBe(true);
expect(hasViolation(typeOnly)).toBe(false);
expect(hasViolation(inlineTypeOnly)).toBe(false);
expect(hasViolation(ownerModule)).toBe(false);
expect(hasViolation(testFile)).toBe(false);
expect(hasViolation(legacyFile)).toBe(false);
});
it('lists only cli files that still exist', () => {
const missing = legacyCoreBarrelImports.filter((file) => !existsSync(file));
expect(missing).toEqual([]);
});
});
@@ -13966,6 +13966,7 @@ exit 1
'packages/core/.gitattributes',
'packages/desktop-shell/.npmrc',
'eslint.legacy-filenames.mjs',
'eslint.legacy-core-barrel-imports.mjs',
'.github/workflows/qwen-pr-safety-precheck.yml',
]);
expect(classes).toContain('.github/actions/a/action.yml=ci-workflows');
@@ -13991,6 +13992,9 @@ exit 1
);
expect(classes).toContain('packages/desktop-shell/.npmrc=toolchain-config');
expect(classes).toContain('eslint.legacy-filenames.mjs=lint-config');
expect(classes).toContain(
'eslint.legacy-core-barrel-imports.mjs=lint-config',
);
expect(classes).toContain(
'.github/workflows/qwen-pr-safety-precheck.yml=autofix-loop',
);