Files
cc-1c-skills/tests/skills/check-enum-drift.mjs
T
Nick ShirokovandClaude Opus 5.5 812ca7d278 fix(meta-*,cf-validate,cf-init): допустимые значения перечислений — по платформе
Списки сверены с XSD платформы, каждое спорное значение проверено загрузкой
и выгрузкой на 8.3.24 и 8.5.1.

- Платформа отвергает, а навыки принимали: FillChecking=ShowWarning (и
  алиас «Предупреждение»), RegisterRecordsWritingOnPost=WriteAll,
  MainClientApplicationWindowMode=Fullscreen. meta-compile при этом вообще
  не проверял fillChecking/indexing реквизита, ТЧ и стандартных реквизитов —
  значение из DSL уходило в XML как есть; теперь через список.
- Платформа принимает, а навыки отвергали: DependenceOnCalculationTypes=
  OnRegistrationPeriod, режимы окна Workplace/FullscreenWorkplace/Kiosk/
  EmbeddedWorkplace, DefaultPresentation=AsNumber — только у задачи
  (список «Вид.Свойство»; у справочника платформа его отвергает).
- meta-validate (PS) сравнивал значения без учёта регистра, py — с учётом;
  платформа читает по точному имени — теперь оба с учётом.
- cf-init отвергает режим совместимости новее платформы своей
  -FormatVersion: платформа старше режима молча понижает его при загрузке.
  Лестница «платформа → формат» сверяется с §7.1 в check-format-versions.
- check-enum-drift: ключи «Вид.Свойство», сверка cf-validate ↔ cfe-validate.
- Документация: убраны ShowWarning/WriteAll/Fullscreen, OnPeriod →
  OnRegistrationPeriod, AsNumber у задачи.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018dc2yLQfw6wppbopM1Y4Ps
2026-09-30 17:56:48 +03:00

68 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
// Анти-дрейф enum-allowlist-ов: сверяет продублированные списки допустимых значений перечислений
// meta-compile (АВТОРИТЕТ) ↔ meta-validate ↔ meta-edit, а также cf-validate (АВТОРИТЕТ) ↔ cfe-validate. Навыки автономны (allowlist-ы копируются
// намеренно), поэтому нужен гард от расхождений значений (напр. HierarchyItemsOnly vs HierarchyOfItems).
// Парсит .ps1 (канонический порт). Выход 1 при дрейфе. Запуск: node tests/skills/check-enum-drift.mjs
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
// Извлечь PS1-хэштейбл по имени переменной, распарсить "Prop" = @("v1","v2", ...)
function parsePs1EnumMap(file, varName) {
const text = readFileSync(join(ROOT, file), 'utf8');
const at = text.indexOf(varName);
if (at < 0) throw new Error(`${varName} not found in ${file}`);
let i = text.indexOf('@{', at) + 2, depth = 1, end = i;
while (i < text.length && depth > 0) {
const c = text[i];
if (c === '{') depth++;
else if (c === '}') { depth--; if (depth === 0) { end = i; break; } }
i++;
}
const block = text.slice(text.indexOf('@{', at) + 2, end);
const map = {};
// Ключ — свойство или уточнение по виду объекта «Вид.Свойство» (Task.DefaultPresentation)
const re = /"([\wА-Яа-яЁё.]+)"\s*=\s*@\(([^)]*)\)/g;
let m;
while ((m = re.exec(block)) !== null) {
map[m[1]] = [...m[2].matchAll(/"([^"]*)"/g)].map(v => v[1]);
}
return map;
}
const compile = parsePs1EnumMap('.claude/skills/meta-compile/scripts/meta-compile.ps1', '$script:validEnumValues');
const validate = parsePs1EnumMap('.claude/skills/meta-validate/scripts/meta-validate.ps1', '$validPropertyValues');
const edit = parsePs1EnumMap('.claude/skills/meta-edit/scripts/meta-edit.ps1', '$script:validEnumValues');
const eq = (a, b) => a.length === b.length && [...a].sort().join('|') === [...b].sort().join('|');
let drift = 0;
for (const [name, map] of [['meta-validate', validate], ['meta-edit', edit]]) {
for (const prop of Object.keys(map)) {
if (compile[prop] && !eq(map[prop], compile[prop])) {
console.log(`DRIFT ${name}.${prop}: [${map[prop].join(', ')}] != meta-compile [${compile[prop].join(', ')}]`);
drift++;
}
}
}
// Информационно: свойства в валидаторе/редакторе, которых НЕТ в авторитете (возможен опечатка-ключ или устаревшее)
for (const [name, map] of [['meta-validate', validate], ['meta-edit', edit]]) {
for (const prop of Object.keys(map)) {
if (!compile[prop]) console.log(`INFO ${name}.${prop} нет в meta-compile.validEnumValues (проверьте ключ)`);
}
}
// Корень конфигурации и корень расширения: общие свойства (режимы совместимости, интерфейс)
// cf-validate и cfe-validate обязаны принимать одинаково — это одни и те же перечисления платформы.
const cfv = parsePs1EnumMap('.claude/skills/cf-validate/scripts/cf-validate.ps1', '$validEnumValues');
const cfev = parsePs1EnumMap('.claude/skills/cfe-validate/scripts/cfe-validate.ps1', '$validEnumValues');
for (const prop of Object.keys(cfev)) {
if (cfv[prop] && !eq(cfev[prop], cfv[prop])) {
console.log(`DRIFT cfe-validate.${prop}: [${cfev[prop].join(', ')}] != cf-validate [${cfv[prop].join(', ')}]`);
drift++;
}
}
console.log(drift === 0 ? 'OK — нет дрейфа значений enum-allowlist (meta-* vs meta-compile, cfe-validate vs cf-validate)' : `\n${drift} DRIFT(s) — свести к эталону.`);
process.exit(drift ? 1 : 0);