Skip to content

feat(lint): enforce kebab-case filenames with ESLint#4797

Open
ZijianZhang989 wants to merge 1 commit into
QwenLM:mainfrom
ZijianZhang989:feat/kebab-case-file-naming
Open

feat(lint): enforce kebab-case filenames with ESLint#4797
ZijianZhang989 wants to merge 1 commit into
QwenLM:mainfrom
ZijianZhang989:feat/kebab-case-file-naming

Conversation

@ZijianZhang989

Copy link
Copy Markdown
Collaborator

What this PR does

Adds an ESLint rule (check-file/filename-naming-convention) to enforce kebab-case for all .ts files in packages/core/src and packages/cli/src. Existing non-kebab-case files are excluded via eslint.legacy-filenames.mjs for gradual migration. Updates AGENTS.md to reflect the new convention.

Why it's needed

File naming in the codebase is split between camelCase and kebab-case with no enforcement. Newer modules already converged to kebab-case, but there's nothing preventing new camelCase files from being added. This formalizes the trend and prevents backsliding via a CI hard gate.

Reviewer Test Plan

How to verify

  1. Create a new camelCase file: echo "// test" > packages/core/src/testFoo.ts
  2. Run npx eslint packages/core/src/testFoo.ts — should report an error
  3. Create a new kebab-case file: echo "// test" > packages/core/src/test-foo.ts
  4. Run npx eslint packages/core/src/test-foo.ts — should pass
  5. Run npm run lint — should pass with zero new errors
  6. Clean up: rm packages/core/src/testFoo.ts packages/core/src/test-foo.ts

Evidence (Before & After)

N/A — lint rule enforcement, no UI changes.

Tested on

OS Status
🍏 macOS
🪟 Windows ⚠️
🐧 Linux ⚠️

Environment (optional)

N/A — unit-level ESLint check only.

Risk & Scope

Linked Issues

Closes #4419 (infrastructure part — ESLint rule and allowlist; batch renaming will follow in separate PRs)

中文说明

这个 PR 做了什么

packages/core/srcpackages/cli/src 下的所有 .ts 文件添加 ESLint 规则(check-file/filename-naming-convention),强制使用 kebab-case 命名。现有的非 kebab-case 文件通过 eslint.legacy-filenames.mjs 排除,支持渐进式迁移。同时更新了 AGENTS.md 中的文件命名约定。

为什么需要

代码库中文件命名混用 camelCase 和 kebab-case,且没有强制机制。较新的模块已经收敛到 kebab-case,但没有任何措施阻止新增 camelCase 文件。此 PR 通过 CI 硬卡将这一趋势正式化,防止倒退。

Reviewer Test Plan

How to verify

  1. 创建一个 camelCase 文件:echo "// test" > packages/core/src/testFoo.ts
  2. 运行 npx eslint packages/core/src/testFoo.ts——应报错
  3. 创建一个 kebab-case 文件:echo "// test" > packages/core/src/test-foo.ts
  4. 运行 npx eslint packages/core/src/test-foo.ts——应通过
  5. 运行 npm run lint——应无新增错误
  6. 清理:rm packages/core/src/testFoo.ts packages/core/src/test-foo.ts

Evidence (Before & After)

N/A——lint 规则强制,无 UI 变更。

Risk & Scope

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

📋 Review Summary

This PR adds an ESLint rule to enforce kebab-case filenames for TypeScript files in packages/core/src and packages/cli/src, with a comprehensive allowlist for existing non-compliant files. The implementation is clean, well-documented, and follows the principle of gradual migration. The PR successfully formalizes the existing convention and prevents regression through CI enforcement.

🔍 General Feedback

  • Clear scope definition: The PR correctly limits scope to packages/core/src and packages/cli/src, explicitly acknowledging that other packages (vscode-ide-companion, sdk-typescript) are out of scope per issue Standardize file naming to kebab-case with ESLint enforcement and AGENTS.md documentation #4419.
  • Gradual migration approach: The allowlist strategy is pragmatic—it prevents breaking existing workflows while establishing a clear path forward for incremental renaming.
  • Good documentation: The eslint.legacy-filenames.mjs file includes helpful JSDoc explaining its purpose and maintenance requirements.
  • Minimal changes: The implementation touches only 4 files with focused, purposeful changes—no speculative features or over-engineering.
  • Bilingual documentation: The PR description includes both English and Chinese explanations, improving accessibility for the contributor base.

🎯 Specific Feedback

🔵 Low

  • eslint.config.js:170 - The ignoreMiddleExtensions option is used but not documented. Consider adding a brief comment explaining what this handles (e.g., files like file.session.integ.ts where .session or .integ are middle extensions). This would help future maintainers understand why this flag is necessary.

  • eslint.legacy-filenames.mjs:5 - The comment mentions "Remove entries as files are renamed in migration PRs" but doesn't specify a process for tracking this. Consider adding a note about whether there's a tracking issue or checklist for the migration progress, or if this is purely manual/opportunistic.

  • AGENTS.md:122 - The updated wording "all .ts files (enforced by ESLint)" could be slightly more precise by specifying the scope: "all .ts files in packages/core/src and packages/cli/src (enforced by ESLint)". This matches the actual rule scope in eslint.config.js.

✅ Highlights

  • Excellent test plan: The reviewer test plan is clear, actionable, and covers both positive and negative cases (camelCase should fail, kebab-case should pass).
  • Transparent about tradeoffs: The PR description openly acknowledges the maintenance burden of the ~517-entry allowlist and explicitly states what's out of scope.
  • Clean implementation: The ESLint configuration follows the existing pattern in eslint.config.js, using the same structure as other rules.
  • Proper issue linkage: Correctly links to and closes issue Standardize file naming to kebab-case with ESLint enforcement and AGENTS.md documentation #4419, making the work traceable.
  • No breaking changes: The allowlist approach ensures existing developers aren't blocked by sudden lint failures, reducing friction during adoption.

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

@/tmp/stage-1.md

wenshao
wenshao previously requested changes Jun 5, 2026
Comment thread AGENTS.md Outdated
vitest framework
- **File naming**: `PascalCase.tsx` for React components, `kebab-case.ts` for
new non-component files. Leave existing `camelCase` files alone — renaming breaks `git blame` and imports.
all `.ts` files (enforced by ESLint). Existing camelCase files are allowlisted in `eslint.legacy-filenames.mjs`; rename opportunistically when touching them.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] Test

— qwen3.7-max via Qwen Code /review

@wenshao wenshao dismissed their stale review June 5, 2026 07:23

Dismissing: review was based on local diff including already-merged commits. Re-submitting with correct scope.

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

⚠️ Downgraded from Approve to Comment: CI failing: Test (ubuntu-latest, Node 22.x), Test (windows-latest, Node 22.x), Test (macos-latest, Node 22.x), Lint, triage.

Note: the PR branch contains commit a93314e (--list-extensions flag handler) which is already merged into main via PR #4673. Consider rebasing onto the latest main to remove the already-merged commit and get clean CI.

— qwen3.7-max via Qwen Code /review

Comment thread AGENTS.md Outdated
vitest framework
- **File naming**: `PascalCase.tsx` for React components, `kebab-case.ts` for
new non-component files. Leave existing `camelCase` files alone — renaming breaks `git blame` and imports.
all `.ts` files (enforced by ESLint). Existing camelCase files are allowlisted in `eslint.legacy-filenames.mjs`; rename opportunistically when touching them.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] This states "kebab-case.ts for all .ts files (enforced by ESLint)" but the rule only covers packages/core/src/**/*.ts and packages/cli/src/**/*.ts. Other packages (acp-bridge, channels, daemon, sdk-typescript, etc.) are not covered.

Suggested change
all `.ts` files (enforced by ESLint). Existing camelCase files are allowlisted in `eslint.legacy-filenames.mjs`; rename opportunistically when touching them.
- **File naming**: `PascalCase.tsx` for React components, `kebab-case.ts` for
`.ts` files in `packages/core` and `packages/cli` (enforced by ESLint). Existing camelCase files are allowlisted in `eslint.legacy-filenames.mjs`; rename opportunistically when touching them.

— qwen3.7-max via Qwen Code /review

@ZijianZhang989 ZijianZhang989 force-pushed the feat/kebab-case-file-naming branch 5 times, most recently from 465ad14 to 010f52d Compare June 5, 2026 08:38

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] No automated allowlist drift detection

There is no test or CI check that verifies legacyFilenames entries still correspond to actual files on disk. As files are renamed to kebab-case, stale entries will accumulate silently — ESLint does not warn about unused ignore patterns. Consider adding a lightweight validation script (e.g., a node script that globs packages/{core,cli}/src/**/*.ts and asserts every allowlist entry matches at least one file) to lint:ci or as a pre-commit hook.

— qwen3.7-max via Qwen Code /review

Comment thread eslint.legacy-filenames.mjs Outdated
'responseParsingOptions',
'restoreCommand',
'restoreGoal',
'retryContext',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] Allowlist sort order errors

retryContext (here) should come after resumeHistoryUtils, not before resumeCommand. Alphabetically: restore* < resume* < retry*.

Similarly, userPromptExpansionHook (line 511) should come before useWelcomeBackuserP... < useW... in case-insensitive sort.

— qwen3.7-max via Qwen Code /review

'abortController',
'aboutCommand',
'acpAgent',
'acpAgent.worktree',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] 13 redundant sub-entries covered by parent prefix

Since the ignore pattern is **/${name}* (prefix match), sub-entries whose parent already exists are redundant. For example, acpAgent.worktree is already covered by acpAgent because **/acpAgent* matches acpAgent.worktree.ts.

Redundant entries (13 total): acpAgent.worktree, arenaCommand.agentComplete, chatRecordingService.autoTitle, chatRecordingService.customTitle, forkedAgent.agent, forkedAgent.cache, gitWorktreeService.hooks.integ, gitWorktreeService.symlinks.integ, runtimeStatus.config, sessionService.corruption, sessionService.rename, Session.worktree, StreamJsonOutputAdapter.dualOutput.

These can be removed to slim down the allowlist.

— qwen3.7-max via Qwen Code /review

Comment thread eslint.legacy-filenames.mjs Outdated
'editHelper',
'editorCommand',
'editorSettingsManager',
'enter-worktree.session.integ',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] 5 entries are already kebab-case and don't need allowlisting

With ignoreMiddleExtensions: true, the rule only checks the first segment (before the first dot) against KEBAB_CASE. These entries already pass:

  • enter-worktree.session.integ (line 110) — enter-worktree is kebab-case ✓
  • exit-worktree.session.integ (line 120) — exit-worktree
  • integration.test.circular (line 193) — integration
  • loggers.test.circular (line 210) — loggers
  • pipeline.concurrent (line 273) — pipeline

These can be removed from the allowlist.

— qwen3.7-max via Qwen Code /review

Comment thread eslint.config.js Outdated
{
// Enforce kebab-case filenames
files: ['packages/core/src/**/*.ts', 'packages/cli/src/**/*.ts'],
ignores: legacyFilenames.map((name) => `**/${name}*`), // Exclude pre-existing camelCase files

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The ignores glob uses **/${name}* — the trailing * creates a prefix match that silently exempts any new file whose basename starts with a legacy allowlist entry. For example, sessionServiceV2.ts or useAuthHelper.ts would both bypass the kebab-case rule because **/sessionService* and **/useAuth* match them.

Consider using exact patterns that cover source files and their test/integ variants without over-matching:

Suggested change
ignores: legacyFilenames.map((name) => `**/${name}*`), // Exclude pre-existing camelCase files
ignores: legacyFilenames.flatMap((name) => [
`**/${name}.ts`,
`**/${name}.*.ts`,
]),

**/${name}.*.ts matches fooBar.test.ts and fooBar.integ.ts but does NOT match fooBarV2.ts or fooBarHelper.ts.

— qwen3.7-max via Qwen Code /review

*
* See: https://github.com/QwenLM/qwen-code/issues/4419
*/
export const legacyFilenames = [

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] ~15 entries are redundant sub-entries already covered by a parent entry. Because the ignores use a * suffix, dotted/suffixed variants like chatRecordingService.autoTitle are already matched by **/chatRecordingService* (from the chatRecordingService entry).

Redundant entries include: acpAgent.worktree, arenaCommand.agentComplete, chatRecordingService.autoTitle, chatRecordingService.customTitle, FileCommandLoader-extension, FileCommandLoader-markdown, forkedAgent.agent, forkedAgent.cache, gitWorktreeService.hooks.integ, gitWorktreeService.symlinks.integ, memoryDiagnosticsDumper, nonInteractiveCliCommands, runtimeStatus.config, Session.worktree, sessionService.corruption, sessionService.rename, StreamJsonOutputAdapter.dualOutput, systemInfoFields, terminalSetupCommand, useInputHistoryStore.

Removing them would shrink the allowlist from 519 to ~499 entries. Note: this cleanup depends on the * suffix remaining — if you switch to exact matching (see other comment), these dotted entries would need different handling.

— qwen3.7-max via Qwen Code /review

xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
@ZijianZhang989 ZijianZhang989 force-pushed the feat/kebab-case-file-naming branch from 010f52d to ae8f951 Compare June 8, 2026 02:21
@wenshao

wenshao commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Local Verification Report

Branch: feat/kebab-case-file-namingmain
Environment: macOS Darwin 25.4.0, Node.js local

TypeScript Compilation (tsc --noEmit)

Package PR Branch main Status
packages/core 0 errors 0 errors ✅ Clean

ESLint check-file/filename-naming-convention Rule Verification

Check Result
Existing kebab-case files pass ✅ No violations
Legacy camelCase/PascalCase files pass (allowlisted) ✅ No violations
packages/core/src/**/*.ts full scan ✅ 0 filename violations
packages/cli/src/**/*.ts full scan ✅ 0 filename violations
New non-kebab file correctly rejected BadFileName.ts → error filename-naming-convention

Tested by creating a temporary packages/core/src/BadFileName.ts — the rule correctly reported:

error  The filename "BadFileName.ts" does not match the "KEBAB_CASE" pattern  check-file/filename-naming-convention

Allowlist Completeness

All existing non-kebab-case .ts files in packages/core/src and packages/cli/src are covered by eslint.legacy-filenames.mjs (~515 entries). No false positives found during full-scope lint scan.

Code Review

eslint.config.js:

  • New config block targets packages/core/src/**/*.ts and packages/cli/src/**/*.ts
  • Uses legacyFilenames.flatMap() to generate ignores in the pattern **/${name}.ts and **/${name}.*.ts (covers both source and test files)
  • eslint-plugin-check-file with KEBAB_CASE pattern and ignoreMiddleExtensions: true (so foo.test.ts checks foo, not foo.test)

eslint.legacy-filenames.mjs:

  • 525 lines, ~515 basename entries (no extensions)
  • Covers all existing camelCase/PascalCase files in scope
  • Clean format: one name per line, alphabetically sorted

AGENTS.md:

  • Updated file naming guidance to reference the ESLint enforcement and allowlist file

package.json:

  • Added eslint-plugin-check-file@^3.3.1 as devDependency

Verdict

Ready to merge — Rule correctly enforces kebab-case on new files, allowlist covers all existing files (zero false positives), TSC clean. No behavior changes to runtime code.

Comment thread eslint.legacy-filenames.mjs Outdated
'useToolScheduler',
'useTrustModify',
'useTurnDiffs',
'userPromptExpansionHook',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] userPromptExpansionHook is out of alphabetical order. It currently sits between useTurnDiffs (line 504) and useWelcomeBack (line 506), but should be placed between useResumeCommand (line 483) and userStartupWarnings (line 484). In ASCII order: useR… < user… < useS….

Suggested change
'userPromptExpansionHook',
'useResumeCommand',
'userPromptExpansionHook',
'userStartupWarnings',

— qwen3.7-max via Qwen Code /review

Comment thread AGENTS.md Outdated
vitest framework
- **File naming**: `PascalCase.tsx` for React components, `kebab-case.ts` for
new non-component files. Leave existing `camelCase` files alone — renaming breaks `git blame` and imports.
`.ts` files in `packages/core` and `packages/cli` (enforced by ESLint). Existing camelCase files are allowlisted in `eslint.legacy-filenames.mjs`; rename opportunistically when touching them.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The new text drops the explicit warning about git blame history loss and import breakage that the original had ("renaming breaks git blame and imports"). The replacement ("rename opportunistically") is ambiguous — it could encourage drive-by file renames in unrelated feature PRs without signaling the cost.

Suggested change
`.ts` files in `packages/core` and `packages/cli` (enforced by ESLint). Existing camelCase files are allowlisted in `eslint.legacy-filenames.mjs`; rename opportunistically when touching them.
`.ts` files in `packages/core` and `packages/cli` (enforced by ESLint). Existing camelCase files are allowlisted in `eslint.legacy-filenames.mjs`; rename opportunistically when touching them, updating all imports in the same commit (note: renames lose `git blame` history).

— qwen3.7-max via Qwen Code /review

@ZijianZhang989 ZijianZhang989 force-pushed the feat/kebab-case-file-naming branch from ae8f951 to 4258651 Compare June 8, 2026 03:21
Comment thread eslint.config.js
// For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format
import storybook from 'eslint-plugin-storybook';
import checkFile from 'eslint-plugin-check-file';
import { legacyFilenames } from './eslint.legacy-filenames.mjs';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] No automated test coverage for this rule or the allowlist.

No vitest test validates that:

  1. The check-file/filename-naming-convention rule correctly accepts kebab-case and rejects camelCase filenames
  2. Every legacyFilenames entry maps to an actual file on disk

A plugin upgrade or allowlist typo could silently break enforcement. Consider adding a test using ESLint's RuleTester API plus a filesystem cross-reference check.

— qwen3.7-max via Qwen Code /review

@tanzhenxin

Copy link
Copy Markdown
Collaborator

Assigning this to @pomelo-nwu to own. The implementation here is solid — verified the allowlist is complete (full ESLint run over all 1554 in-scope .ts files passes with zero violations) and the rule fires correctly.

The open question is the convention decision itself, which belongs with the RFC in #4419: that issue is still needs-triage, and adopting a CI hard-gate is the most binding way to lock in kebab-case across a codebase that's currently majority camelCase. Since you authored the RFC, you're best placed to ratify the direction (and the migration commitment) before this enforcement lands. Over to you.

@DragonnZhang DragonnZhang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Review Summary

This PR adds an ESLint rule (check-file/filename-naming-convention) to enforce kebab-case filenames in packages/core/src and packages/cli/src, with a legacy allowlist for ~517 existing non-compliant files.

CI status: All 11 checks passing (Lint, Tests on all 3 platforms, CodeQL).

Deterministic analysis: 0 findings from tsc and eslint on the changed files.

Code review: The implementation is structurally sound. The ESLint flat-config integration is correct, the ignoreMiddleExtensions: true option properly handles .test.ts files, and .tsx files are correctly excluded from the rule (preserving PascalCase for React components).

The 10 existing inline comments from @wenshao provide comprehensive coverage of the open design questions: allowlist maintenance (redundant entries, sort-order issues, already-compliant entries), the prefix-match risk in the ignores glob, the wording precision in AGENTS.md, and the gap in automated test coverage for the rule/allowlist itself. I concur with these observations and have no additional findings to add.

— qwen-code via Qwen Code /review

@yiliang114

Copy link
Copy Markdown
Collaborator

The rule and allowlist look correct, and the prefix-match issue from the earlier round is fixed — ignores now uses **/${name}.ts + **/${name}.*.ts, so sessionServiceV2.ts no longer slips through. CI is green on all three platforms.

The real gate here isn't the code — it's that this is a CI hard-gate locking kebab-case onto a codebase that's currently majority camelCase. That direction, and the migration commitment behind it, should be ratified in #4419 before the enforcement lands; otherwise the 515-entry allowlist just becomes permanent debt. That's already been routed to the RFC author.

Non-blocking, but worth tightening before merge:

  • No test for the rule or the allowlist. A plugin bump or an allowlist typo would silently disable enforcement. Worth a RuleTester case (kebab passes / camel fails) plus a script that globs packages/{core,cli}/src/**/*.ts and asserts every allowlist entry still maps to a real file — that doubles as drift detection so the list can only shrink.
  • One gap the exact-match glob doesn't close: a new dotted sibling of an allowlisted file still passes. sessionService is allowlisted, so a brand-new sessionService.v2.ts is matched by **/sessionService.*.ts and slips through as fresh camelCase.
  • AGENTS.md says "all .ts files" but the rule only covers core/src and cli/src — worth scoping the wording to match.

One design note for the #4419 discussion, not this PR: the rule only catches uppercase in the first segment of a .ts basename. It doesn't constrain directory names, .tsx, or word-splitting (base-llm-client and basellmclient both pass), so "kebab-case enforced" is narrower than it reads. Worth being explicit about how far this gate is meant to go before committing to it.

中文

规则和 allowlist 本身没问题,上一轮的 prefix-match 也修了——ignores 现在是 **/${name}.ts + **/${name}.*.tssessionServiceV2.ts 不会再漏过;三个平台 CI 全绿。

真正的关卡不在代码,而在于这是一道 CI 硬卡,把 kebab-case 锁死在一个当前以 camelCase 为主的代码库上。这个方向以及背后的迁移承诺,应该先在 #4419 里拍板再落地,否则这份 515 条的 allowlist 就会变成永久技术债。该决策已经转给 RFC 作者。

非阻塞,但合并前值得收紧:

  • 规则和 allowlist 都没有测试。插件升级或 allowlist 写错会静默关掉 enforcement。建议加一个 RuleTester 用例(kebab 通过 / camel 报错),再加一个脚本 glob packages/{core,cli}/src/**/*.ts 校验每条 allowlist 仍对应磁盘真实文件——顺带做漂移检测,让名单只减不增。
  • 精确 glob 没堵住的一个口子:allowlisted 文件的带点新兄弟文件仍会通过。sessionService 在名单里,新建的 sessionService.v2.ts 会被 **/sessionService.*.ts 匹配,作为新的 camelCase 漏过。
  • AGENTS.md 写的是「all .ts files」,但规则只覆盖 core/srccli/src,文案范围应对齐。

一个留给 #4419 讨论、不针对本 PR 的设计提醒:规则只检查 .ts 文件名首段是否有大写,不约束目录名、.tsx,也不约束切词(base-llm-clientbasellmclient 都通过),所以「强制 kebab-case」比字面看起来要窄。值得在正式采纳前讲清这道 gate 到底要覆盖到哪。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Standardize file naming to kebab-case with ESLint enforcement and AGENTS.md documentation

7 participants