mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-22 04:31:02 +03:00
refactor(cfe-patch-method): эргономика вывода по итогам dogfood
По результатам прогона субагентом реального сценария (адаптация метода Бухгалтерии + рефакторинг оригинала → конфликт): - SKILL.md: убрана протёкшая и УСТАРЕВШАЯ реализация — раздел про merge-воркспейс называл файлы merged.bsl/diff.txt, которых больше нет; раздел «Проверка/актуализация пачкой» дублировал рантайм-вывод. Оставлено только решенческое (режимы, область, зона ответственности, зачем проактивно). - conflict.md: к каждой неразмещённой вставке добавлена привязка к якорю (после/перед из local) и подсказка «куда переносить» (якорь вынесен/отрефакторен → ищи в диффе новый вызов, размещай пост-обработкой) + напоминание сохранить BOM. Диагноз дрейфа якоря теперь виден, не нужно грепать вручную. - Согласование числительных в итог-строках (было «1 конфликтов»). Паритет ps1<->py, 16 кейсов зелёные в обоих. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
9aaa3a1c1e
commit
dcce32faed
@@ -80,25 +80,17 @@ allowed-tools:
|
|||||||
|
|
||||||
- `[АКТУАЛЕН]` — оригинал не менялся, изменений нет;
|
- `[АКТУАЛЕН]` — оригинал не менялся, изменений нет;
|
||||||
- `[АКТУАЛИЗИРОВАН]` — тело обновлено по новому оригиналу, правки (`#Вставка`/`#Удаление`) перенесены автоматически (в выводе — сводка перенесённого);
|
- `[АКТУАЛИЗИРОВАН]` — тело обновлено по новому оригиналу, правки (`#Вставка`/`#Удаление`) перенесены автоматически (в выводе — сводка перенесённого);
|
||||||
- `[АКТУАЛИЗИРОВАН-ЧАСТИЧНО]` — часть правок не удалось разместить (окружающий контекст изменился). Они помечены `// [РЕСИНК-КОНФЛИКТ]` и не потеряны; в системный temp выгружается merge-воркспейс (`base.bsl` — предок, `local.bsl` — твоя версия с маркерами, `remote.bsl` — новый оригинал, `merged.bsl` — результат, `diff.txt` — base→remote) — путь печатается в выводе. Проверь конфликтные блоки и размести вручную.
|
- `[АКТУАЛИЗИРОВАН-ЧАСТИЧНО]` — часть правок не удалось разместить (якорь изменился в новом оригинале). Они помечены `// [РЕСИНК-КОНФЛИКТ]` в модуле и не потеряны. Путь к merge-воркспейсу печатается в выводе — начни с `index.md`, дальше по каждому конфликту его `conflict.md` (см. ниже), размести блоки вручную в `.bsl` расширения.
|
||||||
|
|
||||||
Повторный вызов `Before`/`After`/`Instead` для уже перехваченного метода не создаёт дубль (`[ПРОПУЩЕН]`).
|
Повторный вызов `Before`/`After`/`Instead` для уже перехваченного метода не создаёт дубль (`[ПРОПУЩЕН]`).
|
||||||
|
|
||||||
## Проверка и актуализация пачкой (`-Check` / `-Actualize`)
|
## Пакетно: `-Check` / `-Actualize`
|
||||||
|
|
||||||
После обновления конфигурации контролируемые методы (`&ИзменениеИКонтроль`) могут разойтись с
|
По **всем** `&ИзменениеИКонтроль` расширения (сузить: `-ModulePath` — модуль, `+ -MethodName` — один);
|
||||||
исходником — платформа при загрузке об этом молчит, ошибка всплывает лишь в рантайме. Эти режимы
|
затрагивают **только тело** контролируемых методов. `-Check` — отчёт по дрейфу (`exit 1`, если есть),
|
||||||
проходят по **всем** `&ИзменениеИКонтроль` расширения (или сузить: `-ModulePath` — модуль, `+ -MethodName` — один):
|
ничего не пишет; `-Actualize` — авто-перенос правок, конфликты уходят в merge-воркспейс (путь и порядок
|
||||||
|
разбора печатаются в выводе). Полезно после обновления КФ — о рассинхроне контроля платформа при
|
||||||
- **`-Check`** — только отчёт: какие методы дрейфнули (`ДРЕЙФ` / `КОНФЛИКТ` / `МЕТОД-ИСЧЕЗ`); актуальные
|
загрузке молчит.
|
||||||
считаются числом (`100/103 актуальны`). Ничего не пишет. Код возврата **1**, если есть что чинить.
|
|
||||||
- **`-Actualize`** — чинит: авто-переносит правки, для неоднозначных — merge-воркспейс.
|
|
||||||
|
|
||||||
Зона ответственности — **только тело `&ИзменениеИКонтроль`** (не свойства/формы/сигнатуры).
|
|
||||||
|
|
||||||
Merge-воркспейс конфликтов (`-Actualize`) в системном temp: `index.md` (тонкий список конфликтов с
|
|
||||||
путями к `.bsl` расширения для правки) + подпапка на каждый конфликтный метод с `conflict.md`
|
|
||||||
(что перенести + дифф) и `base/local/remote`. Путь печатается в выводе.
|
|
||||||
|
|
||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
|
|||||||
@@ -530,10 +530,20 @@ function Write-ConflictFolder {
|
|||||||
$md += "Метод: $existingName (&ИзменениеИКонтроль(`"$($method.Canonical)`"))"
|
$md += "Метод: $existingName (&ИзменениеИКонтроль(`"$($method.Canonical)`"))"
|
||||||
$md += "Причина: $(Get-ResyncConflictReason $disputed)"
|
$md += "Причина: $(Get-ResyncConflictReason $disputed)"
|
||||||
$md += ""
|
$md += ""
|
||||||
$md += "## Не размещено — перенести в метод вручную"
|
$md += "## Не размещено — перенести вручную"
|
||||||
foreach ($d in $disputed) {
|
foreach ($d in $disputed) {
|
||||||
if ($d.Kind -eq 'insert') { $md += '#Вставка'; foreach ($l in $d.Lines) { $md += $l }; $md += '#КонецВставки' }
|
$md += ""
|
||||||
else { $md += '// не удалось найти для удаления:'; foreach ($l in $d.Lines) { $md += ('// ' + $l.Trim()) } }
|
if ($d.Kind -eq 'insert') {
|
||||||
|
$md += "Вставка. В вашей версии (local) блок стоял по якорю:"
|
||||||
|
if ($d.Before -and $d.Before.Count -gt 0) { $md += " после:"; foreach ($l in $d.Before) { $md += " $l" } } else { $md += " после: (начало метода)" }
|
||||||
|
if ($d.After -and $d.After.Count -gt 0) { $md += " перед:"; foreach ($l in $d.After) { $md += " $l" } } else { $md += " перед: (конец метода)" }
|
||||||
|
$md += "Якорь изменился/исчез в новом оригинале (remote) — потому блок не лёг автоматически (см. дифф base→remote ниже)."
|
||||||
|
$md += "Куда переносить: если якорного кода в новом методе больше нет — он, вероятно, вынесен/отрефакторен (ищите в диффе новый вызов/процедуру). Размести адаптацию по смыслу: например пост-обработкой после нового вызова, либо в заимствованной процедуре, куда переехал код. При правке файла сохрани кодировку (UTF-8 с BOM). Блок:"
|
||||||
|
$md += "#Вставка"; foreach ($l in $d.Lines) { $md += $l }; $md += "#КонецВставки"
|
||||||
|
} else {
|
||||||
|
$md += "Удаление. Строки для удаления не найдены в новом оригинале (изменились/исчезли):"
|
||||||
|
foreach ($l in $d.Lines) { $md += " - $($l.Trim())" }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$md += ""
|
$md += ""
|
||||||
$md += "## Дифф base→remote (что изменилось в оригинале)"
|
$md += "## Дифф base→remote (что изменилось в оригинале)"
|
||||||
@@ -588,7 +598,11 @@ function Invoke-Resync {
|
|||||||
$ae = [Math]::Min($v1norm.Count - 1, $op.After + 3)
|
$ae = [Math]::Min($v1norm.Count - 1, $op.After + 3)
|
||||||
for ($m = $op.After + 1; $m -le $ae; $m++) { $afterLines += $v1norm[$m] }
|
for ($m = $op.After + 1; $m -le $ae; $m++) { $afterLines += $v1norm[$m] }
|
||||||
$k = Resolve-InsertionPoint $v2norm $beforeLines $afterLines
|
$k = Resolve-InsertionPoint $v2norm $beforeLines $afterLines
|
||||||
if ($null -eq $k) { $disputed += @{ Kind = 'insert'; Lines = $op.Lines } }
|
if ($null -eq $k) {
|
||||||
|
$dbefore = @(); if ($op.After -ge 0) { $bz = [Math]::Max(0, $op.After - 2); for ($z = $bz; $z -le $op.After; $z++) { $dbefore += $v1[$z] } }
|
||||||
|
$dafter = @(); $az = [Math]::Min($v1.Count - 1, $op.After + 3); for ($z = $op.After + 1; $z -le $az; $z++) { $dafter += $v1[$z] }
|
||||||
|
$disputed += @{ Kind = 'insert'; Lines = $op.Lines; Before = $dbefore; After = $dafter }
|
||||||
|
}
|
||||||
elseif ($k -lt 0) { $insertTop += ,$op.Lines; $transferred += @{ Kind = 'insert' } }
|
elseif ($k -lt 0) { $insertTop += ,$op.Lines; $transferred += @{ Kind = 'insert' } }
|
||||||
else { if (-not $insertAfter.ContainsKey($k)) { $insertAfter[$k] = @() }; $insertAfter[$k] += ,$op.Lines; $transferred += @{ Kind = 'insert' } }
|
else { if (-not $insertAfter.ContainsKey($k)) { $insertAfter[$k] = @() }; $insertAfter[$k] += ,$op.Lines; $transferred += @{ Kind = 'insert' } }
|
||||||
} else {
|
} else {
|
||||||
@@ -659,7 +673,7 @@ function Write-ResyncIndex {
|
|||||||
$upd = @($results | Where-Object { $_.Status -eq 'АКТУАЛИЗИРОВАН' }).Count
|
$upd = @($results | Where-Object { $_.Status -eq 'АКТУАЛИЗИРОВАН' }).Count
|
||||||
$lines = @()
|
$lines = @()
|
||||||
$lines += "[$verb] $extName -> $configPath"
|
$lines += "[$verb] $extName -> $configPath"
|
||||||
$lines += "Итог: $actual/$total актуальны · $upd актуализировано · $($conflicts.Count) конфликтов"
|
$lines += "Итог: $actual/$total актуальны · актуализировано: $upd · конфликтов: $($conflicts.Count)"
|
||||||
$lines += ""
|
$lines += ""
|
||||||
$lines += "Конфликты — править .bsl расширения:"
|
$lines += "Конфликты — править .bsl расширения:"
|
||||||
foreach ($c in $conflicts) {
|
foreach ($c in $conflicts) {
|
||||||
@@ -759,12 +773,12 @@ if ($Check -or $Actualize) {
|
|||||||
$drift = @($results | Where-Object { $_.Status -eq 'ДРЕЙФ' }).Count
|
$drift = @($results | Where-Object { $_.Status -eq 'ДРЕЙФ' }).Count
|
||||||
$confl = @($results | Where-Object { $_.Status -eq 'КОНФЛИКТ' }).Count
|
$confl = @($results | Where-Object { $_.Status -eq 'КОНФЛИКТ' }).Count
|
||||||
$gone = @($results | Where-Object { $_.Status -in @('МЕТОД-ИСЧЕЗ', 'ИСТОЧНИК-НЕ-НАЙДЕН') }).Count
|
$gone = @($results | Where-Object { $_.Status -in @('МЕТОД-ИСЧЕЗ', 'ИСТОЧНИК-НЕ-НАЙДЕН') }).Count
|
||||||
Write-Host "Итог: $actual/$total актуальны · $drift дрейф · $confl конфликт · $gone требуют внимания"
|
Write-Host "Итог: $actual/$total актуальны · дрейф: $drift · конфликтов: $confl · внимания: $gone"
|
||||||
if ($listed.Count -gt 0) { Write-Host "Починить: /cfe-patch-method -Actualize -ExtensionPath $ExtensionPath -ConfigPath $ConfigPath"; exit 1 } else { exit 0 }
|
if ($listed.Count -gt 0) { Write-Host "Починить: /cfe-patch-method -Actualize -ExtensionPath $ExtensionPath -ConfigPath $ConfigPath"; exit 1 } else { exit 0 }
|
||||||
} else {
|
} else {
|
||||||
$upd = @($results | Where-Object { $_.Status -eq 'АКТУАЛИЗИРОВАН' }).Count
|
$upd = @($results | Where-Object { $_.Status -eq 'АКТУАЛИЗИРОВАН' }).Count
|
||||||
$part = @($results | Where-Object { $_.Status -eq 'ЧАСТИЧНО' }).Count
|
$part = @($results | Where-Object { $_.Status -eq 'ЧАСТИЧНО' }).Count
|
||||||
Write-Host "Итог: $actual/$total актуальны · $upd актуализировано · $part частично"
|
Write-Host "Итог: $actual/$total актуальны · актуализировано: $upd · частично: $part"
|
||||||
$idx = Write-ResyncIndex $runRoot $results $extName $ConfigPath $verb $enc
|
$idx = Write-ResyncIndex $runRoot $results $extName $ConfigPath $verb $enc
|
||||||
if ($idx) { Write-Host "Merge-воркспейс конфликтов (см. index.md): $idx" }
|
if ($idx) { Write-Host "Merge-воркспейс конфликтов (см. index.md): $idx" }
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -597,7 +597,7 @@ def main():
|
|||||||
drift = sum(1 for r in results if r["status"] == "ДРЕЙФ")
|
drift = sum(1 for r in results if r["status"] == "ДРЕЙФ")
|
||||||
confl = sum(1 for r in results if r["status"] == "КОНФЛИКТ")
|
confl = sum(1 for r in results if r["status"] == "КОНФЛИКТ")
|
||||||
gone = sum(1 for r in results if r["status"] in ("МЕТОД-ИСЧЕЗ", "ИСТОЧНИК-НЕ-НАЙДЕН"))
|
gone = sum(1 for r in results if r["status"] in ("МЕТОД-ИСЧЕЗ", "ИСТОЧНИК-НЕ-НАЙДЕН"))
|
||||||
print("Итог: %d/%d актуальны · %d дрейф · %d конфликт · %d требуют внимания"
|
print("Итог: %d/%d актуальны · дрейф: %d · конфликтов: %d · внимания: %d"
|
||||||
% (actual, total, drift, confl, gone))
|
% (actual, total, drift, confl, gone))
|
||||||
if listed:
|
if listed:
|
||||||
print("Починить: /cfe-patch-method -Actualize -ExtensionPath %s -ConfigPath %s" % (extension_path, cp))
|
print("Починить: /cfe-patch-method -Actualize -ExtensionPath %s -ConfigPath %s" % (extension_path, cp))
|
||||||
@@ -606,7 +606,7 @@ def main():
|
|||||||
else:
|
else:
|
||||||
upd = sum(1 for r in results if r["status"] == "АКТУАЛИЗИРОВАН")
|
upd = sum(1 for r in results if r["status"] == "АКТУАЛИЗИРОВАН")
|
||||||
part = sum(1 for r in results if r["status"] == "ЧАСТИЧНО")
|
part = sum(1 for r in results if r["status"] == "ЧАСТИЧНО")
|
||||||
print("Итог: %d/%d актуальны · %d актуализировано · %d частично" % (actual, total, upd, part))
|
print("Итог: %d/%d актуальны · актуализировано: %d · частично: %d" % (actual, total, upd, part))
|
||||||
idx = write_resync_index(run_root, results, ext_name, cp, verb)
|
idx = write_resync_index(run_root, results, ext_name, cp, verb)
|
||||||
if idx:
|
if idx:
|
||||||
print("Merge-воркспейс конфликтов (см. index.md): %s" % idx)
|
print("Merge-воркспейс конфликтов (см. index.md): %s" % idx)
|
||||||
@@ -868,14 +868,30 @@ def write_conflict_folder(folder, method_id, ext_bsl, existing_name, method, v1,
|
|||||||
md.append('Метод: %s (&ИзменениеИКонтроль("%s"))' % (existing_name, method["canonical"]))
|
md.append('Метод: %s (&ИзменениеИКонтроль("%s"))' % (existing_name, method["canonical"]))
|
||||||
md.append("Причина: %s" % conflict_reason(disputed))
|
md.append("Причина: %s" % conflict_reason(disputed))
|
||||||
md.append("")
|
md.append("")
|
||||||
md.append("## Не размещено — перенести в метод вручную")
|
md.append("## Не размещено — перенести вручную")
|
||||||
for d in disputed:
|
for d in disputed:
|
||||||
|
md.append("")
|
||||||
if d["kind"] == "insert":
|
if d["kind"] == "insert":
|
||||||
|
md.append("Вставка. В вашей версии (local) блок стоял по якорю:")
|
||||||
|
if d.get("before"):
|
||||||
|
md.append(" после:")
|
||||||
|
for l in d["before"]:
|
||||||
|
md.append(" " + l)
|
||||||
|
else:
|
||||||
|
md.append(" после: (начало метода)")
|
||||||
|
if d.get("after"):
|
||||||
|
md.append(" перед:")
|
||||||
|
for l in d["after"]:
|
||||||
|
md.append(" " + l)
|
||||||
|
else:
|
||||||
|
md.append(" перед: (конец метода)")
|
||||||
|
md.append("Якорь изменился/исчез в новом оригинале (remote) — потому блок не лёг автоматически (см. дифф base→remote ниже).")
|
||||||
|
md.append("Куда переносить: если якорного кода в новом методе больше нет — он, вероятно, вынесен/отрефакторен (ищите в диффе новый вызов/процедуру). Размести адаптацию по смыслу: например пост-обработкой после нового вызова, либо в заимствованной процедуре, куда переехал код. При правке файла сохрани кодировку (UTF-8 с BOM). Блок:")
|
||||||
md.append("#Вставка"); md.extend(d["lines"]); md.append("#КонецВставки")
|
md.append("#Вставка"); md.extend(d["lines"]); md.append("#КонецВставки")
|
||||||
else:
|
else:
|
||||||
md.append("// не удалось найти для удаления:")
|
md.append("Удаление. Строки для удаления не найдены в новом оригинале (изменились/исчезли):")
|
||||||
for l in d["lines"]:
|
for l in d["lines"]:
|
||||||
md.append("// " + l.strip())
|
md.append(" - " + l.strip())
|
||||||
md.append("")
|
md.append("")
|
||||||
md.append("## Дифф base→remote (что изменилось в оригинале)")
|
md.append("## Дифф base→remote (что изменилось в оригинале)")
|
||||||
for l in v1:
|
for l in v1:
|
||||||
@@ -929,7 +945,9 @@ def resync_one(ext_bsl, ext_lines, dup, method, logical_module, conflict_folder,
|
|||||||
after_lines = v1norm[after + 1:after + 4]
|
after_lines = v1norm[after + 1:after + 4]
|
||||||
k = resolve_insertion_point(v2norm, before_lines, after_lines)
|
k = resolve_insertion_point(v2norm, before_lines, after_lines)
|
||||||
if k is None:
|
if k is None:
|
||||||
disputed.append({"kind": "insert", "lines": op["lines"]})
|
dbefore = v1[max(0, after - 2):after + 1] if after >= 0 else []
|
||||||
|
dafter = v1[after + 1:after + 4]
|
||||||
|
disputed.append({"kind": "insert", "lines": op["lines"], "before": dbefore, "after": dafter})
|
||||||
elif k < 0:
|
elif k < 0:
|
||||||
insert_top.append(op["lines"]); transferred += 1
|
insert_top.append(op["lines"]); transferred += 1
|
||||||
else:
|
else:
|
||||||
@@ -1006,7 +1024,7 @@ def write_resync_index(run_root, results, ext_name, config_path, verb):
|
|||||||
upd = sum(1 for r in results if r["status"] == "АКТУАЛИЗИРОВАН")
|
upd = sum(1 for r in results if r["status"] == "АКТУАЛИЗИРОВАН")
|
||||||
lines = []
|
lines = []
|
||||||
lines.append("[%s] %s -> %s" % (verb, ext_name, config_path))
|
lines.append("[%s] %s -> %s" % (verb, ext_name, config_path))
|
||||||
lines.append("Итог: %d/%d актуальны · %d актуализировано · %d конфликтов" % (actual, total, upd, len(conflicts)))
|
lines.append("Итог: %d/%d актуальны · актуализировано: %d · конфликтов: %d" % (actual, total, upd, len(conflicts)))
|
||||||
lines.append("")
|
lines.append("")
|
||||||
lines.append("Конфликты — править .bsl расширения:")
|
lines.append("Конфликты — править .bsl расширения:")
|
||||||
for c in conflicts:
|
for c in conflicts:
|
||||||
|
|||||||
@@ -29,5 +29,5 @@
|
|||||||
],
|
],
|
||||||
"params": { "extensionPath": "ext" },
|
"params": { "extensionPath": "ext" },
|
||||||
"args_extra": ["-Actualize"],
|
"args_extra": ["-Actualize"],
|
||||||
"expect": { "stdoutContains": "1 актуализировано" }
|
"expect": { "stdoutContains": "актуализировано: 1" }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user