@7n/rules 1.17.0 → 1.17.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.17.2] - 2026-07-18
4
+
5
+ ### Fixed
6
+
7
+ - run-fix.mjs: rollback перед перекиданням DetectorError з canonical re-detect — раніше worker/LLM-пошкоджений файл (напр. невалідний YAML) лишався на диску, бо виняток абортував прогін до звичайного snapshot.rollback()
8
+
9
+ ## [1.17.1] - 2026-07-18
10
+
11
+ ### Fixed
12
+
13
+ - lint: `--base <ref>` тепер діє і в чистому delta-режимі (без `--path`) — раніше явна база застосовувалась лише до перетину path ∩ дельта
14
+
3
15
  ## [1.17.0] - 2026-07-18
4
16
 
5
17
  ### Changed
package/bin/n-rules.js CHANGED
@@ -1802,7 +1802,8 @@ try {
1802
1802
  verbose: args.includes('--verbose'),
1803
1803
  files: pathFiles,
1804
1804
  pathMode,
1805
- repoWide
1805
+ repoWide,
1806
+ baseRef
1806
1807
  }
1807
1808
  const noFix = args.includes('--no-fix')
1808
1809
  // Глобальна черга full-прогонів (spec 2026-07-03): одночасно виконується один
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7n/rules",
3
- "version": "1.17.0",
3
+ "version": "1.17.2",
4
4
  "description": "CLI еталонних правил і skills (префікс n-): синк у репозиторій, дельта-lint, конформність",
5
5
  "keywords": [
6
6
  "cli",
@@ -3,7 +3,7 @@ type: JS Module
3
3
  title: run-detectors.mjs
4
4
  resource: npm/scripts/lib/lint-surface/run-detectors.mjs
5
5
  docgen:
6
- crc: 37567fc8
6
+ crc: 128fe3b7
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 100
9
9
  issues: judge:inaccurate:0.98
@@ -3,7 +3,7 @@ type: JS Module
3
3
  title: run-fix.mjs
4
4
  resource: npm/scripts/lib/lint-surface/run-fix.mjs
5
5
  docgen:
6
- crc: 0a7a2c75
6
+ crc: c4235855
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  ---
9
9
 
@@ -22,6 +22,7 @@ Evidence-гейт рунга (Фаза A1 run-harness, спека 2026-07-11):
22
22
  Durable-write-и (issue nitra/cursor#16): worker отримує у `FixContext` поруч із `recordWrite` опційний `recordDurableWrite` — для записів, кожен з яких є самодостатнім кінцевим станом (doc-files: дока зі свіжим CRC). Такі файли переживають rollback провального rung-а і не входять у collateral-veto: частковий прогрес великого батчу не стирається, canonical re-detect наступного rung-а/прогону рахує лише те, що реально лишилось.
23
23
  MT-tail (Фаза B, спека 2026-07-11): коли лишився невиправлений хвіст (worst=1), `renderRemaining` повертає зібрані порушення, і вони матеріалізуються у вузли MT-графа через `materializeTail` (mt-tail.mjs). Єдиний гейт — onboarded-репо (наявність `.mt.json`); fail-open: MT недоступний або будь-яка помилка → лог, lint не падає.
24
24
  Distillation-телеметрія (Фаза C, §13 pi-migration): успішний agentic-рунг (canonical clean, без veto, з реальними правками у worker telemetry) пише запис `oldText→newText` у глобальний стор (`recordFixTelemetry`, `~/.n-rules/telemetry/<rule>/open/`) — корпус для маховика дистиляції T0. Best-effort; T0/ручні фікси не пишуться.
25
+ Rollback на провалі re-detect-а: якщо canonical re-detect усередині rung-а сам кидає виняток (worker/LLM лишив файл синтаксично невалідним — детектор/conftest не може його розпарсити), `runRung` спершу відкочує `snapshot` до S1, і лише потім перекидає виняток далі — без цього зіпсований проміжний стан worker-а лишався б на диску назавжди (виняток абортує весь прогін до звичайного rollback-коду).
25
26
 
26
27
  ## Публічний API
27
28
 
@@ -197,6 +197,7 @@ export async function buildDetectPlan(opts) {
197
197
  explicitFiles: Array.isArray(opts.files) ? opts.files : null,
198
198
  pathMode: opts.pathMode === true,
199
199
  repoWide: opts.repoWide === true,
200
+ baseRef: typeof opts.baseRef === 'string' ? opts.baseRef : null,
200
201
  cwd: opts.cwd
201
202
  })
202
203
  }
@@ -375,10 +376,20 @@ export function computeActiveDomains(byRule, enabledSet, changed) {
375
376
  * @param {string[]|null} args.explicitFiles явний перелік файлів або null.
376
377
  * @param {boolean} [args.pathMode] `--path`-дельта: лише per-file concerns.
377
378
  * @param {boolean} [args.repoWide] `--repo-wide`: лише full-scope concerns, whole-repo.
379
+ * @param {string|null} [args.baseRef] явна база дельти (`--base <ref>`) замість каскаду main→origin/main.
378
380
  * @param {string} args.cwd робоча директорія прогону.
379
381
  * @returns {Promise<PlanItem[]>} впорядкований план прогону.
380
382
  */
381
- async function buildPlan({ byRule, full, rules, explicitFiles, pathMode = false, repoWide = false, cwd }) {
383
+ async function buildPlan({
384
+ byRule,
385
+ full,
386
+ rules,
387
+ explicitFiles,
388
+ pathMode = false,
389
+ repoWide = false,
390
+ baseRef = null,
391
+ cwd
392
+ }) {
382
393
  // scoped + --path: per-file concerns названих правил × перетин path ∩ дельта
383
394
  if (rules.length > 0 && explicitFiles !== null) return buildScopedDeltaPlan(byRule, rules, explicitFiles)
384
395
  // scoped: усі lint-concerns названих правил, whole-repo
@@ -394,7 +405,7 @@ async function buildPlan({ byRule, full, rules, explicitFiles, pathMode = false,
394
405
  if (full && explicitFiles === null) return buildFullPlan(byRule, enabledSet)
395
406
 
396
407
  // delta / explicit-files; path-режим виключає full-scope concerns
397
- const changed = explicitFiles ?? (await collectChangedFilesSince(await resolveChangedBase(cwd), cwd))
408
+ const changed = explicitFiles ?? (await collectChangedFilesSince(await resolveChangedBase(cwd, baseRef), cwd))
398
409
  return buildDeltaPlan(byRule, enabledSet, changed, { perFileOnly: pathMode })
399
410
  }
400
411
 
@@ -554,6 +565,7 @@ export async function detectAll(opts) {
554
565
  explicitFiles,
555
566
  pathMode: opts.pathMode === true,
556
567
  repoWide: opts.repoWide === true,
568
+ baseRef: typeof opts.baseRef === 'string' ? opts.baseRef : null,
557
569
  cwd
558
570
  })
559
571
 
@@ -238,12 +238,17 @@ async function runRung(rung, worker, violations, feedback, rungDeps) {
238
238
  error = workerError.message
239
239
  }
240
240
 
241
- // Canonical re-detect = джерело правди.
241
+ // Canonical re-detect = джерело правди. Якщо він сам кидає (напр. worker лишив файл
242
+ // синтаксично невалідним — LLM зламав YAML-структуру, детектор/conftest не може його
243
+ // розпарсити) — rollback МАЄ спрацювати перед перекиданням винятку далі. Без цього
244
+ // зіпсований проміжний стан worker-а лишався б на диску назавжди: виняток з re-detect
245
+ // абортує весь прогін, і код нижче (snapshot.rollback() для звичайного «не чисто»)
246
+ // ніколи не виконується.
242
247
  let after
243
248
  try {
244
249
  after = await reDetect(item, cwd, progress, verbose)
245
250
  } catch (detectError) {
246
- if (detectError instanceof DetectorError) throw detectError
251
+ snapshot.rollback()
247
252
  throw detectError
248
253
  }
249
254