Skip to content

lint: add repo-root no-console rule - #4725

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-4029-no-console-rule
Aug 15, 2026
Merged

lint: add repo-root no-console rule#4725
yinlianghui merged 1 commit into
mainfrom
claude/issue-4029-no-console-rule

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#4029

What

Adds no-console: ['error', { allow: ['warn', 'error'] }] to the repo-root
eslint.config.js, so a module- or function-scope console.log/info/
debug fails CI instead of shipping silently the way
console.log('Registering object-map...') did in #7139 — caught only by a
human reading the diff, since pnpm lint had nothing to say about it.

Adjudication trail (both rulings on the claim comment thread)

  1. Original delegated adjudication (claim comment): adopt the card's own
    suggested shape, overrides exempting scripts/**, test files, and
    examples/**; measure first, clean a ≤~20-hit mechanical residue in this
    PR, report a larger one as a fork instead of absorbing it.
  2. Measured result: the literal exemption list left 235 real hits —
    193 (82%) in packages/cli + packages/create-plugin (CLI tools whose
    entire job is stdout), 18 in per-package examples/ dirs the
    root-anchored glob never reached, and 24 more including two files that
    are the repo's actual debug/logger infrastructure. Reported as
    needs_decision per the ruling's own stop condition instead of guessing
    at the scope boundary.
  3. Supplemental ruling (this PR implements it): adopt recommendation A —
    three additive, invariant-preserving carve-outs (below), line-level
    eslint-disable + comment on the two debug/logger-infrastructure files
    (no separate resolution of the debug-channel question, objectui 的 eslint 没开 no-console:模块作用域遗留调试输出没有任何自动化拦网(#7139 靠人工发现) #4029's own Q2,
    which stays deliberately unbundled), individually judge the remaining
    real residue as delete-vs-promote-to-warn/error, land the rule as
    error, full-repo pnpm lint green.

The three additive carve-outs

  • packages/cli/src/** and packages/create-plugin/src/** — CLI tools
    whose entire job is terminal stdout/stderr. Running a bin is not
    "importing a package and getting console noise you didn't ask for" — the
    #7139 bug class this rule exists to net. (@object-ui/cli's index.ts
    does re-export serve/init for programmatic use, but their console
    output is the documented behavior of calling them, not an accidental
    module-scope leak.)
  • **/examples/** widened from the root-anchored examples/** — measured
    18 of the 235 hits in packages/types/examples/*.ts alone, a
    per-package examples directory the original glob never reached despite
    being the same kind of documentation-code surface as root examples/**.

The two debug/logger-infrastructure carve-outs (line-level, commented)

  • packages/core/src/utils/debug.tsdebugLog/debugTime/
    debugTimeEnd, the repo's opt-in debug channel (gated behind
    globalThis.OBJECTUI_DEBUG). This IS the facility objectui 的 eslint 没开 no-console:模块作用域遗留调试输出没有任何自动化拦网(#7139 靠人工发现) #4029's own Q2 asked
    about — a eslint-disable-next-line no-console with a one-line comment
    is the resolution for this card; the design question of whether the repo
    needs a different debug channel stays open and unbundled.
  • packages/data-objectstack/src/index.ts's createQuietHttpLogger — a
    Logger-interface implementation whose methods deliberately forward to the
    matching console.* method (that IS the function's job).

Remaining 17 real residue sites — individually judged

Rule applied consistently: promote to console.warn/console.error
only where the message diagnoses a real anomaly (matches the pre-existing
house convention in plugin-map/src/ObjectMap.tsx and
core/src/registry/Registry.ts); delete pure success/placeholder
narration that explains nothing going wrong.

Promoted (2):

  • packages/app-shell/src/views/ObjectDataPage.tsx:142console.debug
    console.warn. Explains a real anomaly: a saved-view URL filter was
    silently dropped because it has no canonical ViewFilterRule form.
  • packages/plugin-detail/src/DetailView.tsx:690console.log
    console.error inside a .catch(). A real Web Share API failure, not
    debug noise.

Deleted (15) — all confirmed to be happy-path narration with no diagnostic
content:

  • apps/site/app/components/ObjectUIProvider.tsx:25 — removed the whole
    setTimeout block (its only purpose was this log); the now-unused
    ComponentRegistry import is removed too.
  • packages/fields/src/widgets/MasterDetailField.tsx:46handleView
    stub; param renamed _item per the repo's existing
    argsIgnorePattern: '^_' convention.
  • packages/plugin-detail/src/DetailView.tsx:694 — redundant "Link copied
    to clipboard" success log.
  • packages/plugin-gantt/demo/main.tsx:599,601 — demo-only
    onLayoutChange/onTaskClick echo logs (this file is demo/, not
    src/, so it carries no changeset).
  • packages/runner/src/App.tsx:94,99 — loader-selection debug prints
    (emoji-prefixed, informal style inconsistent with the house
    [Component]-prefixed diagnostic convention).
  • packages/runner/src/LayoutRenderer.tsx:309 — an unwired
    // Handle click logic stub's log.
  • packages/runner/src/lib/mockDataSource.ts:23,38,63find/create/
    getObjectSchema per-call narration in the demo mock adapter; unused
    params renamed _resource/_params per the file's own existing
    convention (see findOne/update/delete already using it).
  • packages/sdui-parser/scripts/gen-manifest.ts:26 — build-completion
    message in an unwired, dist-excluded dev script (scripts/ here is a
    per-package dir, not root scripts/**, so no changeset is required —
    the change is outside every published package's src/).
  • packages/sdui-parser/verify.ts:23,74 — a standalone tsx-run
    verification script's per-check "ok" line and final "N checks passed"
    summary; its assert.* calls still throw on a real failure regardless,
    so the tool's actual verification value is unaffected. Same "not under
    src/, no changeset" note as gen-manifest.ts.
  • packages/vscode-extension/src/extension.ts:21 — "extension is now
    active!" activation log.

Changesets

  • .changeset/no-console-lint-rule.md — patch for the five published
    packages with a real behavior change (@object-ui/app-shell,
    @object-ui/fields, @object-ui/plugin-detail, @object-ui/runner,
    object-ui).
  • .changeset/no-console-debug-infra-comments.md — empty frontmatter for
    @object-ui/core and @object-ui/data-objectstack (comment-only,
    zero behavior change).
  • packages/plugin-gantt and @object-ui/sdui-parser carry no changeset:
    every file touched in each (demo/main.tsx; scripts/gen-manifest.ts,
    verify.ts) sits outside that package's src/, which is the guarded
    surface scripts/check-changeset-presence.mjs uses by design (see that
    script's own header on why src/** only).
  • Read back with node scripts/check-changeset-presence.mjs — passes.

Verification

  • Full-repo hit census (both stages) run under the shared
    /tmp/os-heavy-verify.lock; commands and counts are in the linked issue
    comment / dev report.
  • pnpm exec eslint . — 0 errors, 10353 pre-existing warnings unrelated to
    this change (previously 235 no-console hits before this PR's per-site
    cleanup), confirmed green at HEAD ab8d59d08 (this PR's tip).
  • Positive control: added a temporary module-scope console.log(...) to
    packages/core/src/index.ts (not committed), confirmed
    pnpm exec eslint packages/core/src/index.ts goes red with exactly the
    expected no-console message, then reverted (git diff empty
    afterward).
  • pnpm --filter run type-check, package name substituted — green for all nine touched
    packages (app-shell, core, data-objectstack, fields,
    plugin-detail, plugin-gantt, runner, sdui-parser,
    object-ui/vscode-extension).
  • pnpm exec vitest run scoped to the touched packages plus
    packages/plugin-map/src/index.registration.test.tsx (the sibling
    "import must not write console noise" pin from fix(plugin-map): 删掉模块作用域遗留的 console.log('Registering object-map...') (objectstack#7139) #4007/#7139), run in two
    passes: 618 test files / 7628 tests for app-shell + core +
    data-objectstack + fields (1 pre-existing pinned test initially failed
    ObjectDataPage.saveAsViewFilterFold.test.ts asserted the pre-promotion
    console.debug call; fixed to assert console.warn and re-verified
    green), and 86 test files / 806 tests for plugin-detail + runner +
    the plugin-map pin, all green including
    registers its components without printing to the console.
  • node scripts/check-changeset-presence.mjs and
    node scripts/check-changeset-no-major.mjs — both green.

Generated by Claude Code

Adds `no-console: ['error', { allow: ['warn', 'error'] }]` to eslint.config.js
so a module- or function-scope console.log/info/debug fails CI instead of
shipping silently, the way `console.log('Registering object-map...')` did in
#7139 (caught only by hand). A full-repo census found 235 real hits under
the originally-delegated exemption list (root scripts/**, examples/**, test
files) -- far past the ~20-hit threshold for absorbing cleanup into the same
PR -- so the fork was reported and a supplemental ruling adjudicated the
resolution implemented here:
- Three additive carve-outs: packages/cli/src/**, packages/create-plugin/src/**
(CLI tools whose entire job is terminal stdout), and examples/** widened to
any depth (packages/types/examples/*.ts alone carried 18 of the 235 hits).
- Line-level eslint-disable + comment on the two files that ARE the repo's
deliberate debug/logger infrastructure: core/src/utils/debug.ts's
debugLog/debugTime/debugTimeEnd (gated behind globalThis.OBJECTUI_DEBUG)
and data-objectstack/src/index.ts's createQuietHttpLogger (a Logger
interface whose methods deliberately forward to console.*).
- The remaining 17 real residue sites individually judged: promoted to
console.warn/console.error where the message diagnoses a real anomaly
(ObjectDataPage's dropped-filter note, DetailView's Share API failure),
deleted everywhere else (happy-path narration with no diagnostic content).
- Updated the one pinned test that asserted the pre-promotion console.debug
call (ObjectDataPage.saveAsViewFilterFold.test.ts) to assert console.warn.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RnQd8iMMUwXQEV1crFmQiQ
@vercel

vercelBot commented Aug 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectuiIgnoredIgnoredAug 15, 2026 6:00pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)24.7 KB350 KB
Entry fileindex-BO8IKgdg.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.56KB3.59KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)25.13KB5.40KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)38.46KB10.17KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.35KB1.07KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)489.93KB108.68KB
core (index.js)3.79KB1.52KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)157.05KB43.28KB
fields (index.js)230.33KB57.14KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.32KB1.77KB
i18n (index.js)3.35KB1.38KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.12KB7.62KB
i18n (useDisplayLocale.js)2.84KB1.45KB
i18n (useObjectLabel.js)27.59KB6.63KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)38.98KB10.85KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)8.75KB3.06KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)3.67KB1.12KB
permissions (evaluator.js)4.41KB1.44KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.55KB0.71KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.86KB12.91KB
plugin-charts (index.js)64.44KB18.28KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)121.90KB31.76KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)239.81KB59.97KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)114.72KB27.70KB
plugin-gantt (index.js)164.30KB40.02KB
plugin-grid (index.js)192.10KB51.24KB
plugin-kanban (index.js)52.74KB14.53KB
plugin-list (index.js)111.14KB26.92KB
plugin-map (index.js)18.16KB5.81KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)41.38KB11.09KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)83.81KB20.49KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.71KB3.53KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.67KB2.37KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)27.64KB9.44KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.28KB0.68KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)4.09KB1.74KB
sdui-parser (index.js)4.47KB2.03KB
sdui-parser (parse.js)10.04KB2.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)4.69KB1.48KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.05KB1.52KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@yinlianghuiClaude

Copy link
Copy Markdown
CollaboratorAuthor

Review verdict: ACCEPT (reviewer of record, PM session session_01RnQd8iMMUwXQEV1crFmQiQ).

Verified against this PR, not the report: seventeen changed files; Fixes #4029 the only closing keyword. The body carries the complete two-stage adjudication trail — the 235-hit census that triggered the ruling's own stop condition, and the supplemental Option-A ruling this implements — so the scope account is auditable end to end. The seventeen residue sites are individually judged under a stated, convention-anchored rule (promote only where a real anomaly is diagnosed: two promotions, fifteen deletions of pure narration), the pinned-test update follows the falsified-premise pattern correctly (it asserted the pre-promotion console.debug), and the sibling import-silence pin from the defect that motivated this card is explicitly re-run green. Changeset coverage is exact: five behavior-changed published packages patch, two comment-only packages on an empty declaration, and the two no-changeset exemptions grounded in the presence gate's own src/-only design rather than judgement. Positive control red-flips on a planted module-scope console.log. Gates pinned to ab8d59d08, matching this PR's current head.

Will flip ready + enable auto-merge once Lint, Type Check, and Test shards 1–4 conclude success on this head.


Generated by Claude Code

@yinlianghui
yinlianghui marked this pull request as ready for review August 15, 2026 18:18
@yinlianghui
yinlianghui added this pull request to the merge queueAug 15, 2026
Merged via the queue into main with commit 5607092Aug 15, 2026
21 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-4029-no-console-rule branch August 15, 2026 18:18
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

objectui 的 eslint 没开 no-console:模块作用域遗留调试输出没有任何自动化拦网(#7139 靠人工发现)

2 participants

@yinlianghui@claude