Files
openswarm/linter/config/config.json
T

298 lines
16 KiB
JSON

{
"enabled": {
"max-file-lines": true,
"max-folder-items": true,
"import-cycles": true,
"no-nested-imports": false,
"vulture": true,
"eslint": false,
"knip": false,
"endpoints": false,
"classes": false,
"no-underscore-names": true,
"p-private": true,
"ruff": true,
"pyright": true
},
"_notes": {
"no-nested-imports": "Off on purpose: this codebase uses function-level/lazy imports to break import cycles (400+ sites). Flagging them all is wrong for us.",
"eslint-knip": "Node tooling deferred to a later pass.",
"classes": "Placeholder check, not wired up. endpoints: orphaned-endpoint triage deferred.",
"max-file-lines-exceptions": "Grandfather list of pre-existing >300-line files (existing debt, not new). Paths updated after the folder-tree restructure moved several of them. The two manager/prompt/* entries are from the agent_manager decomposition: prompt_context.py aggregates the system-prompt context builders and attachments.py is one cohesive 230-line attachment resolver; both are single-responsibility and a few lines over, not splittable without an artificial seam.",
"max-folder-items-exceptions": "Exact-path allow for folders intentionally over the cap. The rule trips at >7 (7 items is fine, the 8th tips it), so only genuinely 8+ folders are listed. backend/ and backend/apps are FastAPI feature-package registries (each child is an app mounted in main.py); agents/ aggregates agent subsystems; agents/manager/ is the agent_manager god-object decomposition (cohesive AgentManager mixins + standalone run helpers + the streaming/permissions/prompt/session subtrees), conventionally flat like agents/ and core/ since its standalone helpers are heterogeneous and don't group cleanly; agents/manager/streaming and agents/manager/session are flat peer collections of one-module-per-concern handlers; core/, tools_lib/, tests/ are conventionally flat. Frontend: app/pages is the page registry, AgentChat/ChatInput/Settings-sections/Onboarding are organizational parents, and shared/state (Redux slices) plus hooks/steps/mcp-cards/Views are flat peer collections. scripts/, electron/, linter/checks/ are flat tool dirs. These replaced blanket .lintignore-max-folder-items sentinels (backend, frontend, scripts, electron, linter/checks) so the rule still catches NEW unplanned bloat everywhere else. Kept as whole-subtree sentinels on purpose: debugger/ (self-contained injected sub-tool with its own Vite GUI), webapp_template (Vite scaffold payload), and vendored mcp-bundles. 2026-07 desktop-shell additions: Dashboard canvas/cards/desktop + hooks/interaction + hooks/lifecycle, AgentChat bubbles/tool-ui, and shared/styles are flat peer collections (one component or hook per concern) that crossed 7 as the redesign surface grew. frontend/src/toolui carries a whole-subtree .lintignore: vendored tool-ui component library (pierre), same treatment as mcp-bundles. openswarm-edge/app is the edge's flat one-module-per-concern set (routing, bundles, inject, ratelimit, sandbox, and the vendored code_safety gate); it crossed 7 when the sandbox's static gate was split out to mirror the desktop file byte for byte.",
"import-cycles": "Flags RUNTIME circular imports only (SCC>1). Skips type-only imports (import type / export type) and dynamic import() since neither runs at module init, which is why the idiomatic Redux store<->hooks type cycle is not flagged. Frontend alias resolution comes from import-cycle-aliases. Zero cycles today; the check keeps it that way.",
"ruff + pyright": "Ported from Haik's linter (haik/feat/ingest). ruff is narrowed to F401/F811/F841 (unused imports/redefs/locals) and intentionally DROPS Haik's ARG001/ARG002 (unused args): our SDK-callback signatures require unused params (can_use_tool/pre_tool_hook take a `context` they don't use) and we ban the `_unused` prefix, so ARG is noise here. pyright runs Haik's existence-only config (typeCheckingMode off) with reportAttributeAccessIssue ENABLED: the AgentManager behavior classes now inherit a typing-only AgentManagerProtocol base (manager/AgentManagerProtocol.py) that declares the composed __init__ state + cross-class methods, so the checker sees self.sessions etc. from inside a mixin. pyright caught real bugs: a dangling `_conns` ref + TWO broken lazy imports (`_load_all`/`_load` from outputs.py, renamed to load_all/load in workspace_io but the import sites weren't updated \u2014 App Builder workspace seeding/name-sync was silently failing in a try/except). The one grandfathered SURFACE file (handle_assistant_message) is the SDK-optional try/except-import boundary (TextBlock=object fallback defeats isinstance narrowing). Both grandfather pre-existing debt by file; the refactor surface is clean. Requires `ruff` + `pyright` on PATH (added to requirements-dev.txt); pyright's config expects the venv at backend/.venv.",
"no-underscore-names + p-private": "Convention checks ported verbatim from Haik's linter (haik/feat/ingest): no-underscore-names bans leading-underscore names (a dead-code-tooling blind spot; use p_ for private), p-private enforces that p_-prefixed names are accessed only inside their owning file/class (cross-file/class use means the name should be public). Backend Python only. The exception lists grandfather pre-existing debt that landed with the workflows/analytics forward-ports (eric's 'don't mass-migrate untouched files' rule); the agent_manager refactor surface is clean. NOTE: Haik's full linter (his branch also adds pyright + ruff and runs a different enabled set) should eventually supersede this; these two were lifted to enforce the p_ conventions on eric/dev now. browser_cookies.py is excepted for `_fields_` only: a ctypes.Structure protocol name required by the ctypes metaclass, not our naming."
},
"rules": {
"max-file-lines": 300,
"max-folder-items": 7,
"import-cycle-aliases": {
"@/": "frontend/src/"
},
"vulture-min-confidence": 1,
"vulture-error-threshold": 1,
"no-nested-imports": true,
"endpoint-ignore-routes": [
"*/callback",
"*/callback/*"
],
"ruff-select": "F401,F811,F841"
},
"include_extensions": [
".py",
".ts",
".tsx",
".js",
".jsx"
],
"exclude": [
"node_modules",
".venv",
"dist",
"build",
"__pycache__",
".git",
".cursor",
".vscode",
".claude",
".pytest_cache",
".mypy_cache",
".ruff_cache",
".account-factory",
".local-stash",
".DS_Store",
"python-env",
"build-staging",
"webapp_template_cache",
"openswarm-cloud",
"uv-bin",
"data",
"public",
"openswarm_debug.egg-info"
],
"exceptions": {
"max-file-lines": [
"backend/apps/agents/show_ui_mcp_server.py",
"backend/apps/agents/agents.py",
"backend/apps/agents/proxy/anthropic_proxy.py",
"backend/apps/agents/proxy/anthropic_to_openai.py",
"backend/apps/agents/browser/browser_agent.py",
"backend/apps/agents/browser_agent_mcp_server.py",
"backend/apps/agents/browser/browser_schema.py",
"backend/apps/agents/core/ws_manager.py",
"backend/apps/agents/manager/prompt/prompt_context.py",
"backend/apps/agents/manager/prompt/attachments.py",
"backend/apps/agents/providers/pricing.py",
"backend/apps/agents/providers/registry.py",
"backend/apps/dashboards/dashboards.py",
"backend/apps/discord_mcp_shim/server.py",
"backend/apps/mcp_registry/mcp_registry.py",
"backend/apps/nine_router/oauth.py",
"backend/apps/nine_router/process.py",
"backend/apps/nine_router/sync_custom.py",
"backend/apps/outputs/outputs.py",
"backend/apps/outputs/runtime.py",
"backend/apps/outputs/view_builder_templates.py",
"backend/apps/outputs/webapp_template/frontend/src/shared/styles/ThemeContext.tsx",
"backend/apps/service/client.py",
"backend/apps/service/service.py",
"backend/apps/settings/settings.py",
"backend/apps/skills/skills.py",
"backend/apps/subscription/router.py",
"backend/apps/tools_lib/tools_lib.py",
"backend/apps/web/web.py",
"backend/main.py",
"backend/tests/test_disconnect_resilience.py",
"backend/tests/test_outputs_runtime_cleanup.py",
"backend/tests/test_service.py",
"backend/tests/test_skill_registry_community.py",
"backend/tests/test_streaming_harness.py",
"backend/tests/test_swarm_bundle.py",
"backend/tests/test_v2_invariants.py",
"backend/tests/test_v2_label_logic.py",
"electron/affiliateTracking.test.js",
"electron/main.js",
"frontend/src/app/Main.tsx",
"frontend/src/app/components/editor/CommandPicker.tsx",
"frontend/src/app/components/editor/DirectoryBrowser.tsx",
"frontend/src/app/components/overlays/DynamicIsland.tsx",
"frontend/src/app/components/overlays/GlobalSearchPalette.tsx",
"frontend/src/app/components/Layout/AppShell.tsx",
"frontend/src/app/components/Onboarding/OnboardingPanel.tsx",
"frontend/src/app/components/Onboarding/ac/AgenticCursor.tsx",
"frontend/src/app/components/Onboarding/ac/acRuntime.ts",
"frontend/src/app/components/overlays/PlanPicker.tsx",
"frontend/src/app/components/editor/RichPromptEditor.tsx",
"frontend/src/app/components/overlays/SignInGate.tsx",
"frontend/src/app/components/editor/useDomElementSelector.ts",
"frontend/src/app/pages/AgentChat/AgentChat.tsx",
"frontend/src/app/pages/AgentChat/shell/ApprovalBar.tsx",
"frontend/src/app/pages/AgentChat/shell/BrowserAgentInlineFeed.tsx",
"frontend/src/app/pages/AgentChat/bubbles/MessageBubble.tsx",
"frontend/src/app/pages/AgentChat/parsing/toolLabels.ts",
"frontend/src/app/pages/Analytics/PixelChart.tsx",
"frontend/src/app/pages/Commands/Commands.tsx",
"frontend/src/app/pages/Dashboard/cards/AgentCard.tsx",
"frontend/src/app/pages/Dashboard/cards/BrowserAgentOverlay.tsx",
"frontend/src/app/pages/Dashboard/cards/BrowserCard.tsx",
"frontend/src/app/pages/Dashboard/canvas/DashboardHeader.tsx",
"frontend/src/app/pages/Dashboard/DashboardToolbar.tsx",
"frontend/src/app/pages/Dashboard/cards/DashboardViewCard.tsx",
"frontend/src/app/pages/Dashboard/cards/NoteCard.tsx",
"frontend/src/app/pages/Dashboard/hooks/interaction/useCanvasControls.ts",
"frontend/src/app/pages/DashboardSelection/DashboardSelection.tsx",
"frontend/src/app/pages/Modes/Modes.tsx",
"frontend/src/app/pages/Skills/SkillBuilderChat.tsx",
"frontend/src/app/pages/Skills/Skills.tsx",
"frontend/src/app/pages/Views/ViewEditor.tsx",
"frontend/src/app/pages/Views/ViewPreview.tsx",
"frontend/src/app/pages/Views/useIframeElementSelector.ts",
"frontend/src/shared/browserCommandHandler.ts",
"frontend/src/shared/state/agentsSlice.ts",
"frontend/src/shared/state/dashboardLayoutSlice.ts",
"frontend/src/shared/ws/WebSocketManager.ts"
],
"max-folder-items": [
"backend",
"backend/apps",
"backend/apps/reddit_mcp_shim",
"backend/apps/x_mcp_shim",
"backend/apps/tiktok_mcp_shim",
"backend/apps/agents",
"backend/apps/agents/core",
"backend/apps/agents/manager",
"backend/apps/agents/manager/session",
"backend/apps/agents/manager/streaming",
"backend/apps/outputs",
"openswarm-edge/app",
"backend/apps/tools_lib",
"backend/apps/service",
"backend/tests",
"frontend/src/shared",
"frontend/src/shared/state",
"frontend/src/shared/hooks",
"frontend/src/app/pages",
"frontend/src/app/pages/AgentChat",
"frontend/src/app/pages/AgentChat/ChatInput",
"frontend/src/app/pages/AgentChat/ChatInput/hooks",
"frontend/src/app/pages/AgentChat/mcp-cards",
"frontend/src/app/pages/AgentChat/bubbles",
"frontend/src/app/pages/AgentChat/tool-ui",
"frontend/src/app/pages/Dashboard/canvas",
"frontend/src/app/pages/Dashboard/cards",
"frontend/src/app/pages/Dashboard/desktop",
"frontend/src/app/pages/Dashboard/hooks/interaction",
"frontend/src/app/pages/Dashboard/hooks/lifecycle",
"frontend/src/shared/styles",
"frontend/src/app/pages/Settings/sections",
"frontend/src/app/pages/Views",
"frontend/src/app/components/Onboarding",
"frontend/src/app/components/Onboarding/steps",
"scripts",
"electron",
"linter/checks"
],
"no-nested-imports": [],
"import-cycles": [],
"vulture": [
"backend/tests/*"
],
"endpoints": [],
"classes": [],
"no-underscore-names": [
"backend/apps/onboarding/usage/browser_cookies.py",
"backend/apps/agents/schedule_mcp_server.py",
"backend/apps/workflows/audit.py",
"backend/apps/workflows/escalation.py",
"backend/apps/workflows/executor.py",
"backend/apps/workflows/models.py",
"backend/apps/workflows/notifier.py",
"backend/apps/workflows/scheduler.py",
"backend/apps/workflows/storage.py",
"backend/apps/workflows/workflows.py",
"backend/tests/conftest.py",
"backend/tests/test_app_edit_bind.py",
"backend/tests/test_executor_pipeline.py",
"backend/tests/test_free_trial.py",
"backend/tests/test_schedule_e2e.py",
"backend/tests/test_schedule_recovery.py",
"backend/tests/test_schedule_recurrence.py",
"backend/tests/test_seed_no_clobber.py",
"backend/tests/test_workflows_api.py",
"backend/tests/test_workflows_semantics.py",
"backend/tests/test_workflows_storage.py"
],
"p-private": [
"backend/apps/workflows/workflows.py",
"backend/tests/test_schedule_recurrence.py",
"backend/tests/test_skill_registry_community.py",
"backend/tests/test_ssrf_guard.py",
"backend/tests/test_workflows_semantics.py",
"backend/tests/test_workflows_storage.py"
],
"ruff": [
"backend/apps/agents/agents.py",
"backend/apps/agents/browser/browser_agent.py",
"backend/apps/agents/providers/registry.py",
"backend/apps/agents/proxy/anthropic_proxy.py",
"backend/apps/agents/proxy/anthropic_to_openai.py",
"backend/apps/agents/tools/web.py",
"backend/apps/dashboards/dashboards.py",
"backend/apps/health/health.py",
"backend/apps/modes/modes.py",
"backend/apps/nine_router/process.py",
"backend/apps/outputs/outputs.py",
"backend/apps/service/buffer.py",
"backend/apps/service/service.py",
"backend/apps/settings/settings.py",
"backend/apps/subscription/router.py",
"backend/apps/swarm/redact.py",
"backend/apps/tools_lib/tools_lib.py",
"backend/apps/web/web.py",
"backend/apps/workflows/models.py",
"backend/apps/workflows/workflows.py",
"backend/auth.py",
"backend/main.py",
"backend/tests/conftest.py",
"backend/tests/test_browser_agent_loop.py",
"backend/tests/test_browser_meta_playbook.py",
"backend/tests/test_browser_orchestrator_routing.py",
"backend/tests/test_bundled_extracted_modules.py",
"backend/tests/test_disconnect_resilience.py",
"backend/tests/test_disk_caches.py",
"backend/tests/test_effective_tools.py",
"backend/tests/test_outputs_runtime_cleanup.py",
"backend/tests/test_phase1_stress.py",
"backend/tests/test_schedule_e2e.py",
"backend/tests/test_schedule_recurrence.py",
"backend/tests/test_service_legacy.py",
"backend/tests/test_settings_meta_guard.py",
"backend/tests/test_skills_folders.py",
"backend/tests/test_swarm_bundle.py",
"backend/tests/test_system_prompt.py",
"backend/tests/test_v2_invariants.py",
"backend/tests/test_v2_label_logic.py",
"backend/tests/test_web_mcp_decision.py",
"backend/tests/test_workflows_semantics.py",
"backend/tests/test_ws_integration.py"
],
"pyright": [
"backend/apps/agents/agents.py",
"backend/apps/agents/browser_agent_mcp_server.py",
"backend/apps/agents/manager/streaming/handle_assistant_message.py",
"backend/apps/google_workspace_mcp_shim/run.py",
"backend/apps/health/health.py",
"backend/apps/settings/settings.py",
"backend/apps/subscription/free_trial.py",
"backend/apps/swarm/closure.py",
"backend/apps/swarm/entities/modes.py",
"backend/apps/web/web.py",
"backend/apps/workflows/executor.py",
"backend/apps/workflows/workflows.py",
"backend/auth.py",
"backend/config/Apps.py"
]
}
}