Skip to content
This repository was archived by the owner on Sep 11, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@
"редакторні",
"реджектиться",
"реджектом",
"резолвилась",
"резолвлена",
"резолвленої",
"резолвлену",
Expand Down
19 changes: 10 additions & 9 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions plugins/lang-js/.changes/260720-0729-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
bump: patch
section: Fixed
---
style/lint: stylelint — задекларована залежність плагіна (раніше резолвилась лише транзитивно у цьому монорепо через @nitra/stylelint-config); відсутність тула тепер дає видимий warn-diagnostic замість мовчазного no-op (незалежний консюмер бачив би 'зелений' style-лінт, який насправді нічого не перевіряв)
3 changes: 2 additions & 1 deletion plugins/lang-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"jscpd": "^5.0.11",
"knip": "^6.22.0",
"oxc-parser": "^0.137.0",
"oxlint": "^1.68.0"
"oxlint": "^1.68.0",
"stylelint": "^17.6.0"
},
"peerDependencies": {
"@7n/rules": ">=1.27.0"
Expand Down
4 changes: 2 additions & 2 deletions plugins/lang-js/rules/js-bun-redis/lib/docs/redis-imports.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export function findRedisImportsInText(

### Внутрішні (репозиторій)

Імпорт із `'../../../scripts/utils/ast-scan-utils.mjs'` — спільні утиліти AST-сканера для всіх правил у `npm/rules/*/lib/`:
Імпорт із `'@7n/rules/scripts/utils/ast-scan-utils.mjs'` (ядро) — спільні утиліти AST-сканера, які використовують правила з декількох плагінів:

- `dynamicImportModule(node)` — якщо вузол AST є динамічним `import('mod')`, повертає рядок `'mod'`, інакше `null`/`undefined`.
- `langFromPath(path)` — обчислює `lang` для `oxc-parser` за розширенням шляху.
Expand Down Expand Up @@ -198,7 +198,7 @@ import x from 'my-redis-helpers' // довільний сторонній пак
Контрольний перелік, за яким можна **відтворити** функціонал модуля «з нуля»:

1. Створити файл `redis-imports.mjs`, що імпортує `parseSync` з `oxc-parser`.
2. Імпортувати з `'../../../scripts/utils/ast-scan-utils.mjs'` шість утиліт: `dynamicImportModule`, `langFromPath`, `normalizeSnippet`, `offsetToLine`, `requireCallModule`, `walkAstWithAncestors`.
2. Імпортувати з `'@7n/rules/scripts/utils/ast-scan-utils.mjs'` шість утиліт: `dynamicImportModule`, `langFromPath`, `normalizeSnippet`, `offsetToLine`, `requireCallModule`, `walkAstWithAncestors`.
3. Оголосити константу `SOURCE_FILE_RE = /\.([cm]?[jt]sx?)$/u`.
4. Оголосити константу `FORBIDDEN_MODULE_NAMES` як `Set` із елементами: `'ioredis'`, `'node-redis'`, `'redis'`, `'@redis/client'`, `'@redis/json'`, `'@redis/search'`, `'@redis/time-series'`, `'@redis/bloom'`.
5. Реалізувати приватну функцію `isForbiddenRedisModule(mod)`: повертає `true`, якщо `FORBIDDEN_MODULE_NAMES.has(mod)` **або** `mod.startsWith('ioredis/')` **або** `mod.startsWith('redis/')` **або** `mod.startsWith('@redis/')`.
Expand Down
2 changes: 1 addition & 1 deletion plugins/lang-js/rules/style/admin_table/docs/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ type: JS Module
title: main.mjs
resource: plugins/lang-js/rules/style/admin_table/main.mjs
docgen:
crc: 267496d1
crc: fb8f81a5
---

## Огляд
Expand Down
4 changes: 2 additions & 2 deletions plugins/lang-js/rules/style/admin_table/main.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ const DEFINITION_RE = /\.n-admin-table\b/u
* клас `n-admin-table`, він має бути визначений хоч в одному `.scss`/`.css`/`.vue`
* (guide: `admin_table.mdc`). Для усунення false positives — крос-файлова перевірка,
* тож потребує whole-repo сканування незалежно від `ctx.files`.
* @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd)
* @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
* @param {import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd)
* @returns {Promise<import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
*/
export async function lint(ctx) {
const reporter = createViolationReporter(ctx)
Expand Down
2 changes: 1 addition & 1 deletion plugins/lang-js/rules/style/gap/docs/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ type: JS Module
title: main.mjs
resource: plugins/lang-js/rules/style/gap/main.mjs
docgen:
crc: 23cd7951
crc: 5d9d76e7
---

## Огляд
Expand Down
4 changes: 2 additions & 2 deletions plugins/lang-js/rules/style/gap/main.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ const DEFINITION_RE = /\.n-gap-(xs|sm|md|lg)\b/gu
* використаний у `.vue`, має бути визначений хоч в одному `.scss`/`.css`/`.vue`
* (guide: `gap.mdc`). Крос-файлова перевірка usage↔definition — потребує whole-repo
* сканування незалежно від `ctx.files`.
* @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd)
* @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
* @param {import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd)
* @returns {Promise<import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
*/
export async function lint(ctx) {
const reporter = createViolationReporter(ctx)
Expand Down
2 changes: 1 addition & 1 deletion plugins/lang-js/rules/style/lint/docs/fix-lint.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ type: JS Module
title: fix-lint.mjs
resource: plugins/lang-js/rules/style/lint/fix-lint.mjs
docgen:
crc: a63dc24c
crc: a44c6b01
---

## Огляд
Expand Down
2 changes: 1 addition & 1 deletion plugins/lang-js/rules/style/lint/docs/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ type: JS Module
title: main.mjs
resource: plugins/lang-js/rules/style/lint/main.mjs
docgen:
crc: c9a94f80
crc: 25130f97
model: omlx/gemma-4-e4b-it-OptiQ-4bit
score: 100
issues: judge:inaccurate:0.99
Expand Down
2 changes: 1 addition & 1 deletion plugins/lang-js/rules/style/lint/fix-lint.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async function listStyleFiles(cwd, ctxFiles) {
return (r.stdout ?? '').split('\0').filter(Boolean)
}

/** @type {import('../../../scripts/lib/lint-surface/types.mjs').T0Pattern[]} */
/** @type {import('@7n/rules/scripts/lib/lint-surface/types.mjs').T0Pattern[]} */
export const patterns = [
{
id: 'style-stylelint-fix',
Expand Down
24 changes: 18 additions & 6 deletions plugins/lang-js/rules/style/lint/main.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/**
* lint-поверхня style: read-only detector (stylelint без --fix) для css/scss/vue.
* Per-file (ctx.files) або весь проєкт (ctx.files === undefined). Якщо stylelint
* недоступний — крок пропускається (без npx-автовстановлення).
* Per-file (ctx.files) або весь проєкт (ctx.files === undefined). `stylelint` —
* задекларована залежність плагіна (справжній `npm install` завжди його ставить);
* якщо резолв все ж не вдався (побитий install, hoisting-аномалія) — крок
* пропускається з видимим warn-diagnostic, а не мовчки (без npx-автовстановлення).
*/
import { existsSync } from 'node:fs'
import { join } from 'node:path'
Expand Down Expand Up @@ -33,8 +35,8 @@ export function resolveStylelint(cwd) {

/**
* Detector style/lint (read-only).
* @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd, files)
* @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
* @param {import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd, files)
* @returns {Promise<import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
*/
export async function lint(ctx) {
const reporter = createViolationReporter(ctx)
Expand All @@ -54,8 +56,18 @@ export async function lint(ctx) {

const stylelint = resolveStylelint(cwd)
if (!stylelint) {
// stylelint недоступний → крок пропущено (без автовстановлення)
return reporter.result()
// stylelint — задекларована залежність плагіна, тож відсутність тут аномальна
// (побитий install, hoisting) — крок пропущено з видимим warn, не мовчки.
const result = reporter.result()
result.diagnostics = [
{
level: 'warn',
message:
'lint-style: `stylelint` не резолвиться (ні node_modules/.bin, ні PATH) — CSS/SCSS/Vue-стилі НЕ перевірені ' +
'цим прогоном (style.mdc). `stylelint` — залежність @7n/rules-lang-js; переустанови плагін, якщо бачиш це.'
}
]
return result
}

const r = await spawnAsync(stylelint, targets, { cwd, shell: false })
Expand Down
41 changes: 41 additions & 0 deletions plugins/lang-js/rules/style/lint/tests/main.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Тести detector-а `style/lint` (main.mjs). `resolveCmd` мокається на `null` для
* PATH-незалежного негативного сценарію — у дев-оточенні цього монорепо
* `stylelint` реально стоїть у корені (@nitra/stylelint-config), тож PATH-резолв
* знаходить його навіть у tmp-каталозі; без підміни тест не ізольований від хоста.
*/
import { describe, expect, test, vi } from 'vitest'

import { withTmpDir } from '@7n/rules/scripts/utils/test-helpers.mjs'

vi.mock('@7n/rules/scripts/utils/resolve-cmd.mjs', () => ({ resolveCmd: () => null }))

const { filterStyleFiles, lint, resolveStylelint } = await import('../main.mjs')

describe('filterStyleFiles', () => {
test('лишає лише css/scss/vue', () => {
expect(filterStyleFiles(['a.css', 'b.scss', 'c.vue', 'd.js', 'e.ts'])).toEqual(['a.css', 'b.scss', 'c.vue'])
})
})

describe('resolveStylelint', () => {
test('без node_modules/.bin/stylelint і поза PATH → null', async () => {
await withTmpDir(dir => {
expect(resolveStylelint(dir)).toBeNull()
return Promise.resolve()
})
})
})

describe('lint — stylelint недоступний', () => {
test('дає warn-diagnostic, не мовчазний skip і не violation (регресія: тихий no-op для незалежних консюмерів)', async () => {
await withTmpDir(async dir => {
const result = await lint({ cwd: dir, files: ['a.css'] })
expect(result.violations).toEqual([])
expect(result.diagnostics).toHaveLength(1)
expect(result.diagnostics[0].level).toBe('warn')
expect(result.diagnostics[0].message).toContain('stylelint')
expect(result.diagnostics[0].message).toContain('не резолвиться')
})
})
})
2 changes: 1 addition & 1 deletion plugins/lang-js/rules/style/quasar_fixes/docs/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ type: JS Module
title: main.mjs
resource: plugins/lang-js/rules/style/quasar_fixes/main.mjs
docgen:
crc: 0f9c4631
crc: dec47808
---

## Огляд
Expand Down
4 changes: 2 additions & 2 deletions plugins/lang-js/rules/style/quasar_fixes/main.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ const FIXES = [
* `<q-scroll-area>` або `<q-tooltip>`, у `.scss`/`.css`/`.vue` має бути відповідний
* CSS-фікс (guide: `quasar_fixes.mdc`). Крос-файлова перевірка usage↔definition —
* потребує whole-repo сканування незалежно від `ctx.files`.
* @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd)
* @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
* @param {import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd)
* @returns {Promise<import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
*/
export async function lint(ctx) {
const reporter = createViolationReporter(ctx)
Expand Down
2 changes: 1 addition & 1 deletion plugins/lang-js/rules/style/tooling/docs/fix-tooling.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ type: JS Module
title: fix-tooling.mjs
resource: plugins/lang-js/rules/style/tooling/fix-tooling.mjs
docgen:
crc: a25e47d2
crc: 033af5f9
model: omlx/gemma-4-e4b-it-OptiQ-4bit
score: 100
issues: judge:inaccurate:0.98
Expand Down
2 changes: 1 addition & 1 deletion plugins/lang-js/rules/style/tooling/docs/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ type: JS Module
title: main.mjs
resource: plugins/lang-js/rules/style/tooling/main.mjs
docgen:
crc: c96a4b01
crc: aeb36134
model: omlx/gemma-4-e4b-it-OptiQ-4bit
score: 90
issues: anchor-miss:extensions.json,anchor-miss:settings.json,judge:inaccurate:0.99
Expand Down
2 changes: 1 addition & 1 deletion plugins/lang-js/rules/style/tooling/fix-tooling.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const STYLELINTIGNORE_MISSING_RE = /\.stylelintignore не існує/u
const STYLELINTIGNORE_NO_DIST_RE = /\.stylelintignore не містить рядка dist\//u
const NO_STYLELINT_CONFIG_RE = /Немає конфігу stylelint/u

/** @type {import('../../../scripts/lib/lint-surface/types.mjs').T0Pattern[]} */
/** @type {import('@7n/rules/scripts/lib/lint-surface/types.mjs').T0Pattern[]} */
export const patterns = [
{
id: 'style-stylelintignore-create',
Expand Down
4 changes: 2 additions & 2 deletions plugins/lang-js/rules/style/tooling/main.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ async function checkStylelintConfigPresence(reporter, cwd) {

/**
* Перевіряє відповідність проєкту правилам style.mdc
* @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd тощо)
* @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
* @param {import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd тощо)
* @returns {Promise<import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
*/
export async function lint(ctx) {
const cwd = ctx.cwd
Expand Down
5 changes: 5 additions & 0 deletions plugins/lang-rust/.changes/260720-0729-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
bump: patch
section: Fixed
---
cargo_mutants_config: T0-fix pattern id (test-cargo-mutants-config-create → rust-cargo-mutants-config-create) і JSDoc/доки узгоджені з поточним власником (правило rust, не test) — хвіст після переїзду концерну з ядра
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ type: JS Module
title: fix-cargo_mutants_config.mjs
resource: plugins/lang-rust/rules/rust/cargo_mutants_config/fix-cargo_mutants_config.mjs
docgen:
crc: 00f74615
crc: f1cbd78c
model: omlx/gemma-4-e4b-it-OptiQ-4bit
score: 100
issues: judge:inaccurate:0.99
Expand All @@ -12,7 +12,7 @@ docgen:

## Огляд

Для виконання завдання мені потрібен **код або контекст** файлу `test/cargo_mutants_config`, щоб я міг переписати секцію "Overview" відповідно до наданих "ВІДОМИХ ФАКТІВ" та уникнути помилок із "ЧЕРНЕТКОЮ".
T0-autofix концерну `rust/cargo_mutants_config`: детерміновано створює `<cargoDir>/.cargo/mutants.toml` з canonical neutral baseline у кожному каталозі з Cargo-маніфестом, де конфіга ще немає. Запис виконується лише тут (detector — read-only, звітує `mutants-config-missing`).

## Поведінка

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
---
type: Directory Index
title: npm/rules/test/cargo_mutants_config
title: plugins/lang-rust/rules/rust/cargo_mutants_config
resource: plugins/lang-rust/rules/rust/cargo_mutants_config/
---

# npm/rules/test/cargo_mutants_config

| Файл | Тип |
| ----------------------------------------------------------- | --------- |
| [fix-cargo_mutants_config.mjs](fix-cargo_mutants_config.md) | JS Module |
Expand Down
Loading
Loading