mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-20 17:40:59 +03:00
feat(hooks): суфлёр различает чтение/правку + убран триггер на поиск
- Подсказка зависит от действия: Read → info-навык (понять структуру), Edit|Write|MultiEdit → мутатор (meta-edit/form-edit/…). Throttle теперь по (сессия, группа, действие) — отдельно read- и write-подсказка. - Убран триггер на Grep|Glob (группа search): *-info помогают ПОНЯТЬ найденный объект, а не НАЙТИ по содержимому → подсказка вводила в заблуждение. Суфлёр только на файловых инструментах. - cfe-подсказка ведёт и на cf-info (читает свойства/состав расширения), и на cfe-diff (специфика); правка — cfe-borrow/cfe-patch-method. - README обновлён. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ba0880a5c5
commit
4ec2420af6
+5
-4
@@ -6,9 +6,10 @@
|
|||||||
изменить объект типовой конфигурации, который стоит на поддержке поставщика, редактирование
|
изменить объект типовой конфигурации, который стоит на поддержке поставщика, редактирование
|
||||||
**блокируется** — иначе оно молча сломает будущие обновления вендора. В отказе сразу даётся, что делать
|
**блокируется** — иначе оно молча сломает будущие обновления вендора. В отказе сразу даётся, что делать
|
||||||
дальше под конкретный случай (доработать в расширении или явно разрешить редактирование).
|
дальше под конкретный случай (доработать в расширении или явно разрешить редактирование).
|
||||||
- **Подсказка навыков.** Когда модель работает с исходниками 1С «вручную» (читает сырой XML, ищет по
|
- **Подсказка навыков.** Когда модель работает с исходниками 1С «вручную» (читает сырой XML или правит его
|
||||||
метаданным), хук ненавязчиво напоминает, что для этой задачи есть профильный навык (`meta-info`,
|
напрямую), хук ненавязчиво напоминает про профильный навык — и по делу: при **чтении** ведёт на `*-info`
|
||||||
`form-edit`, `mxl-*`, `skd-*` и т.п.). Не блокирует, подсказывает не чаще одного раза за сессию на группу.
|
(понять структуру), при **правке** — на мутатор (`meta-edit`/`form-edit`/`skd-edit`/…). Не блокирует,
|
||||||
|
подсказывает не чаще одного раза за сессию на группу и действие.
|
||||||
|
|
||||||
Это дополнительный слой поверх проверок, которые уже встроены в сами навыки: навыки-мутаторы и так не дадут
|
Это дополнительный слой поверх проверок, которые уже встроены в сами навыки: навыки-мутаторы и так не дадут
|
||||||
испортить объект на поддержке. Хуки добавляют защиту для случаев, когда правят файлы **в обход навыков**.
|
испортить объект на поддержке. Хуки добавляют защиту для случаев, когда правят файлы **в обход навыков**.
|
||||||
@@ -40,7 +41,7 @@
|
|||||||
"command": "node \"${CLAUDE_PROJECT_DIR}/.claude/hooks/support-guard.mjs\"" }] }
|
"command": "node \"${CLAUDE_PROJECT_DIR}/.claude/hooks/support-guard.mjs\"" }] }
|
||||||
],
|
],
|
||||||
"PostToolUse": [
|
"PostToolUse": [
|
||||||
{ "matcher": "Read|Grep|Glob|Edit|Write|MultiEdit",
|
{ "matcher": "Read|Edit|Write|MultiEdit",
|
||||||
"hooks": [{ "type": "command",
|
"hooks": [{ "type": "command",
|
||||||
"command": "node \"${CLAUDE_PROJECT_DIR}/.claude/hooks/skill-suggester.mjs\"" }] }
|
"command": "node \"${CLAUDE_PROJECT_DIR}/.claude/hooks/skill-suggester.mjs\"" }] }
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// object-class.mjs v1.0 — classify a 1C source path → relevant skill group (suggester)
|
// object-class.mjs v1.0 — classify a 1C source path → relevant skill group (suggester)
|
||||||
// Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
// Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
//
|
//
|
||||||
// Conservative path→skill map for the skill-suggester hook. Returns { group, message }
|
// Conservative path→skill map for the skill-suggester hook. Returns { group, read, write }
|
||||||
// or null (stay silent) when the path is not a recognizable 1C artifact. Distinguishes
|
// or null (stay silent) when the path is not a recognizable 1C artifact. Distinguishes
|
||||||
// cf vs cfe (extension) by sniffing <ConfigurationExtensionPurpose> in Configuration.xml,
|
// cf vs cfe (extension) by sniffing <ConfigurationExtensionPurpose> in Configuration.xml,
|
||||||
// and mxl vs skd templates by the root namespace. Never throws.
|
// and mxl vs skd templates by the root namespace. Never throws.
|
||||||
@@ -21,17 +21,45 @@ const META_COLLECTIONS = new Set([
|
|||||||
'Sequences', 'ExternalDataSources', 'IntegrationServices',
|
'Sequences', 'ExternalDataSources', 'IntegrationServices',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Per-group nudges, split by action: `read` → info-skill (понять структуру),
|
||||||
|
// `write` → mutator-skill (безопасно изменить). Подсказка зависит от того, что делает модель.
|
||||||
const MESSAGES = {
|
const MESSAGES = {
|
||||||
meta: 'Структуру объекта 1С быстрее даёт навык `meta-info` (одна сводка вместо сырого XML), а структурные правки — `meta-edit` (реквизиты/ТЧ/измерения/ресурсы).',
|
meta: {
|
||||||
form: 'Для управляемой формы 1С есть `form-info` (анализ элементов/реквизитов/команд) и `form-edit` (точечные правки).',
|
read: 'Структуру объекта 1С быстрее даёт навык `meta-info` (одна сводка вместо сырого XML).',
|
||||||
mxl: 'Это табличный документ 1С: `mxl-info`/`mxl-decompile` дают редактируемое описание, `mxl-compile` собирает обратно.',
|
write: 'Структурные правки объекта (реквизиты/ТЧ/измерения/ресурсы) безопаснее через `meta-edit` — он следит за uuid, порядком и валидностью.',
|
||||||
skd: 'Это схема компоновки данных (СКД): `skd-info` для анализа, `skd-edit` для точечных правок.',
|
},
|
||||||
role: 'Для прав роли 1С есть `role-info` (сводка прав/RLS) и `role-compile` (создание из DSL).',
|
form: {
|
||||||
cf: 'Корень конфигурации 1С: `cf-info` (обзор состава/свойств) и `cf-edit` (правки настроек/состава).',
|
read: 'Управляемую форму 1С удобнее разбирать навыком `form-info` (элементы/реквизиты/команды/события).',
|
||||||
cfe: 'Это расширение конфигурации (CFE): `cfe-diff` для анализа, а доработку безопаснее вести через `cfe-borrow`/`cfe-patch-method`.',
|
write: 'Правки формы (добавить элементы/реквизиты/команды) — через `form-edit`, а не ручной правкой XML.',
|
||||||
subsystem: 'Подсистема 1С: `subsystem-info` (состав/дерево) и `subsystem-edit` (правки состава/свойств).',
|
},
|
||||||
template: 'Это макет объекта 1С: для табличного документа — навыки `mxl-*`, для СКД — `skd-*`.',
|
mxl: {
|
||||||
search: 'Для навигации по метаданным 1С есть структурированные навыки `*-info` (meta-info/cf-info/form-info/…) — обычно быстрее сырого поиска по XML.',
|
read: 'Это табличный документ 1С: `mxl-info` показывает области/параметры, `mxl-decompile` даёт редактируемое описание.',
|
||||||
|
write: 'Табличный документ правят не вручную: `mxl-decompile` → правка JSON → `mxl-compile`.',
|
||||||
|
},
|
||||||
|
skd: {
|
||||||
|
read: 'Это схема компоновки данных (СКД): `skd-info` показывает наборы/поля/параметры.',
|
||||||
|
write: 'Точечные правки СКД — через `skd-edit` (поля/итоги/фильтры/текст запроса).',
|
||||||
|
},
|
||||||
|
role: {
|
||||||
|
read: 'Права роли удобнее смотреть навыком `role-info` (объекты/права/RLS).',
|
||||||
|
write: 'Роль создают и правят из DSL навыком `role-compile`.',
|
||||||
|
},
|
||||||
|
cf: {
|
||||||
|
read: 'Корень конфигурации удобнее смотреть навыком `cf-info` (свойства/состав/счётчики объектов).',
|
||||||
|
write: 'Правки корня (свойства/состав/роли по умолчанию/интерфейс) — через `cf-edit`.',
|
||||||
|
},
|
||||||
|
cfe: {
|
||||||
|
read: 'Это расширение конфигурации (CFE): свойства и состав читает `cf-info`, специфику (заимствования/перехватчики/проверку переноса) — `cfe-diff`.',
|
||||||
|
write: 'Доработку в расширении безопаснее вести навыками `cfe-borrow`/`cfe-patch-method`, а не ручной правкой XML.',
|
||||||
|
},
|
||||||
|
subsystem: {
|
||||||
|
read: 'Подсистему удобнее смотреть навыком `subsystem-info` (состав/дерево/командный интерфейс).',
|
||||||
|
write: 'Правки подсистемы (состав/дочерние/свойства) — через `subsystem-edit`.',
|
||||||
|
},
|
||||||
|
template: {
|
||||||
|
read: 'Это макет объекта 1С: для табличного документа — `mxl-info`, для СКД — `skd-info`.',
|
||||||
|
write: 'Макет правят навыками: табличный документ — `mxl-*`, СКД — `skd-*`.',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function segments(p) {
|
function segments(p) {
|
||||||
@@ -48,7 +76,7 @@ function sniffRoot(path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Classify a concrete file path. Returns { group, message } or null.
|
// Classify a concrete file path. Returns { group, read, write } (action-specific nudges) or null.
|
||||||
export function classifyFile(path) {
|
export function classifyFile(path) {
|
||||||
try {
|
try {
|
||||||
const segs = segments(path);
|
const segs = segments(path);
|
||||||
@@ -90,19 +118,6 @@ export function classifyFile(path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Classify a Grep/Glob search target: if it points inside a 1C config tree (or a known
|
|
||||||
// collection appears in the path/pattern) → suggest the info-skills. Best-effort, lean silent.
|
|
||||||
export function classifySearch(target) {
|
|
||||||
try {
|
|
||||||
if (!target) return null;
|
|
||||||
const segs = segments(target);
|
|
||||||
if (segs.some((s) => META_COLLECTIONS.has(s) || s === 'Roles' || s === 'Subsystems')) return mk('search');
|
|
||||||
return null;
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function mk(group) {
|
function mk(group) {
|
||||||
return { group, message: MESSAGES[group] };
|
return { group, read: MESSAGES[group].read, write: MESSAGES[group].write };
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@
|
|||||||
],
|
],
|
||||||
"PostToolUse": [
|
"PostToolUse": [
|
||||||
{
|
{
|
||||||
"matcher": "Read|Grep|Glob|Edit|Write|MultiEdit",
|
"matcher": "Read|Edit|Write|MultiEdit",
|
||||||
"hooks": [
|
"hooks": [
|
||||||
{
|
{
|
||||||
"type": "command",
|
"type": "command",
|
||||||
|
|||||||
+22
-19
@@ -7,28 +7,24 @@
|
|||||||
// Throttled to 1×/session/skill-group via marker files. Switch: skillSuggester (on|off)
|
// Throttled to 1×/session/skill-group via marker files. Switch: skillSuggester (on|off)
|
||||||
// in .v8-project.json. Never throws.
|
// in .v8-project.json. Never throws.
|
||||||
|
|
||||||
import { classifyFile, classifySearch } from './common/object-class.mjs';
|
import { classifyFile } from './common/object-class.mjs';
|
||||||
import { findConfigRoot } from './common/support-state.mjs';
|
import { findConfigRoot } from './common/support-state.mjs';
|
||||||
import { getSuggesterMode } from './common/project.mjs';
|
import { getSuggesterMode } from './common/project.mjs';
|
||||||
import { resolve, isAbsolute, join } from 'node:path';
|
import { resolve, isAbsolute, join } from 'node:path';
|
||||||
import { existsSync, writeFileSync } from 'node:fs';
|
import { existsSync, writeFileSync } from 'node:fs';
|
||||||
import { tmpdir } from 'node:os';
|
import { tmpdir } from 'node:os';
|
||||||
|
|
||||||
|
// Only file-targeting tools — these are where a skill genuinely substitutes the raw action.
|
||||||
|
// Content search (Grep/Glob) is intentionally NOT nudged: *-info skills help understand a
|
||||||
|
// located object, not find one by content.
|
||||||
function pickTarget(input, cwd) {
|
function pickTarget(input, cwd) {
|
||||||
const ti = input.tool_input || {};
|
const ti = input.tool_input || {};
|
||||||
const tool = input.tool_name;
|
const tool = input.tool_name;
|
||||||
let raw = null, kind = 'file';
|
if (tool !== 'Read' && tool !== 'Edit' && tool !== 'Write' && tool !== 'MultiEdit') return null;
|
||||||
if (tool === 'Read' || tool === 'Edit' || tool === 'Write' || tool === 'MultiEdit') {
|
const raw = typeof ti.file_path === 'string' ? ti.file_path
|
||||||
raw = typeof ti.file_path === 'string' ? ti.file_path
|
: (Array.isArray(ti.file_edits) && ti.file_edits[0]?.file_path) || null;
|
||||||
: (Array.isArray(ti.file_edits) && ti.file_edits[0]?.file_path) || null;
|
|
||||||
} else if (tool === 'Grep') {
|
|
||||||
raw = typeof ti.path === 'string' ? ti.path : null; kind = 'search';
|
|
||||||
} else if (tool === 'Glob') {
|
|
||||||
raw = typeof ti.path === 'string' ? ti.path : (typeof ti.pattern === 'string' ? ti.pattern : null); kind = 'search';
|
|
||||||
}
|
|
||||||
if (!raw) return null;
|
if (!raw) return null;
|
||||||
const path = isAbsolute(raw) ? raw : resolve(cwd, raw);
|
return isAbsolute(raw) ? raw : resolve(cwd, raw);
|
||||||
return { path, kind };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sanitize(s) {
|
function sanitize(s) {
|
||||||
@@ -40,24 +36,31 @@ export function processInput(input, opts = {}) {
|
|||||||
const empty = { stdout: '', stderr: '', exitCode: 0 };
|
const empty = { stdout: '', stderr: '', exitCode: 0 };
|
||||||
try {
|
try {
|
||||||
const cwd = typeof input.cwd === 'string' ? input.cwd : process.cwd();
|
const cwd = typeof input.cwd === 'string' ? input.cwd : process.cwd();
|
||||||
const t = pickTarget(input, cwd);
|
const path = pickTarget(input, cwd);
|
||||||
if (!t) return empty;
|
if (!path) return empty;
|
||||||
|
|
||||||
const hit = t.kind === 'search' ? classifySearch(t.path) : classifyFile(t.path);
|
const hit = classifyFile(path);
|
||||||
if (!hit) return empty;
|
if (!hit) return empty;
|
||||||
|
|
||||||
const { cfgDir } = findConfigRoot(t.path);
|
// Read → info-skill; Edit/Write/MultiEdit → mutator-skill.
|
||||||
|
const action = input.tool_name === 'Read' ? 'read' : 'write';
|
||||||
|
const message = hit[action];
|
||||||
|
if (!message) return empty;
|
||||||
|
|
||||||
|
const { cfgDir } = findConfigRoot(path);
|
||||||
if (getSuggesterMode(cfgDir, cwd) === 'off') return empty;
|
if (getSuggesterMode(cfgDir, cwd) === 'off') return empty;
|
||||||
|
|
||||||
|
// Throttle per (session, group, action): at most one read-nudge and one write-nudge
|
||||||
|
// per skill-group per session.
|
||||||
const dir = opts.throttleDir || tmpdir();
|
const dir = opts.throttleDir || tmpdir();
|
||||||
const marker = join(dir, `cc-1c-suggest-${sanitize(input.session_id)}-${hit.group}`);
|
const marker = join(dir, `cc-1c-suggest-${sanitize(input.session_id)}-${hit.group}-${action}`);
|
||||||
if (existsSync(marker)) return empty; // already nudged this group this session
|
if (existsSync(marker)) return empty;
|
||||||
try { writeFileSync(marker, ''); } catch { /* throttle best-effort */ }
|
try { writeFileSync(marker, ''); } catch { /* throttle best-effort */ }
|
||||||
|
|
||||||
const decision = {
|
const decision = {
|
||||||
hookSpecificOutput: {
|
hookSpecificOutput: {
|
||||||
hookEventName: 'PostToolUse',
|
hookEventName: 'PostToolUse',
|
||||||
additionalContext: `[1c-skills] ${hit.message}`,
|
additionalContext: `[1c-skills] ${message}`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return { stdout: JSON.stringify(decision), stderr: '', exitCode: 0 };
|
return { stdout: JSON.stringify(decision), stderr: '', exitCode: 0 };
|
||||||
|
|||||||
+24
-15
@@ -181,37 +181,46 @@ console.log('=== skill-suggester: PostToolUse nudge ===');
|
|||||||
writeFileSync(join(SYNTH, 'ext', 'Configuration.xml'),
|
writeFileSync(join(SYNTH, 'ext', 'Configuration.xml'),
|
||||||
'<?xml version="1.0"?>\n<MetaDataObject><Configuration uuid="x"><Properties><ConfigurationExtensionPurpose>Customization</ConfigurationExtensionPurpose></Properties></Configuration></MetaDataObject>');
|
'<?xml version="1.0"?>\n<MetaDataObject><Configuration uuid="x"><Properties><ConfigurationExtensionPurpose>Customization</ConfigurationExtensionPurpose></Properties></Configuration></MetaDataObject>');
|
||||||
|
|
||||||
const read = (fp, session = 's1', tool = 'Read') => suggest({ tool_name: tool, session_id: session, cwd: REPO, tool_input: { file_path: fp } }, { throttleDir: THR });
|
const call = (fp, session, tool) => suggest({ tool_name: tool, session_id: session, cwd: REPO, tool_input: { file_path: fp } }, { throttleDir: THR });
|
||||||
|
const read = (fp, session = 's1') => call(fp, session, 'Read');
|
||||||
|
const edit = (fp, session = 's1') => call(fp, session, 'Edit');
|
||||||
const grp = (r) => { try { return JSON.parse(r.stdout)?.hookSpecificOutput?.additionalContext; } catch { return null; } };
|
const grp = (r) => { try { return JSON.parse(r.stdout)?.hookSpecificOutput?.additionalContext; } catch { return null; } };
|
||||||
|
|
||||||
|
// Read → info-skill; Edit → mutator-skill (same group, distinct nudge).
|
||||||
const rMeta = read(join(SYNTH, 'Catalogs', 'Locked.xml'), 'A');
|
const rMeta = read(join(SYNTH, 'Catalogs', 'Locked.xml'), 'A');
|
||||||
check('suggest Catalogs/X.xml → meta nudge', /meta-info/.test(grp(rMeta) || ''), rMeta.stdout);
|
check('Read Catalogs/X.xml → meta-info', /meta-info/.test(grp(rMeta) || ''), rMeta.stdout);
|
||||||
const rMeta2 = read(join(SYNTH, 'Catalogs', 'Editable.xml'), 'A'); // same session+group
|
const rMetaEdit = edit(join(SYNTH, 'Catalogs', 'Editable.xml'), 'A'); // same session+group, write action
|
||||||
check('suggest second meta same session → silent (throttle)', rMeta2.stdout === '', rMeta2.stdout);
|
check('Edit Catalogs/X.xml → meta-edit (not throttled by the read)', /meta-edit/.test(grp(rMetaEdit) || ''), rMetaEdit.stdout);
|
||||||
|
const rMeta2 = read(join(SYNTH, 'Catalogs', 'Editable.xml'), 'A'); // same session+group+action → throttled
|
||||||
|
check('second Read meta same session → silent (throttle)', rMeta2.stdout === '', rMeta2.stdout);
|
||||||
const rForm = read(join(SYNTH, 'Catalogs', 'Obj', 'Forms', 'F', 'Ext', 'Form.xml'), 'A');
|
const rForm = read(join(SYNTH, 'Catalogs', 'Obj', 'Forms', 'F', 'Ext', 'Form.xml'), 'A');
|
||||||
check('suggest Form.xml (diff group, same session) → form nudge', /form-info/.test(grp(rForm) || ''), rForm.stdout);
|
check('Read Form.xml (diff group) → form-info', /form-info/.test(grp(rForm) || ''), rForm.stdout);
|
||||||
|
|
||||||
const rMxl = read(join(SYNTH, 'Catalogs', 'Obj', 'Templates', 'Print', 'Ext', 'Template.xml'), 'B');
|
const rMxl = read(join(SYNTH, 'Catalogs', 'Obj', 'Templates', 'Print', 'Ext', 'Template.xml'), 'B');
|
||||||
check('suggest spreadsheet Template → mxl', /mxl-/.test(grp(rMxl) || ''), rMxl.stdout);
|
check('Read spreadsheet Template → mxl-info', /mxl-info/.test(grp(rMxl) || ''), rMxl.stdout);
|
||||||
const rSkd = read(join(SYNTH, 'Catalogs', 'Obj', 'Templates', 'Scheme', 'Ext', 'Template.xml'), 'B');
|
const rSkd = edit(join(SYNTH, 'Catalogs', 'Obj', 'Templates', 'Scheme', 'Ext', 'Template.xml'), 'B');
|
||||||
check('suggest DCS Template → skd', /skd-/.test(grp(rSkd) || ''), rSkd.stdout);
|
check('Edit DCS Template → skd-edit', /skd-edit/.test(grp(rSkd) || ''), rSkd.stdout);
|
||||||
const rRole = read(join(SYNTH, 'Roles', 'R', 'Ext', 'Rights.xml'), 'B');
|
const rRole = read(join(SYNTH, 'Roles', 'R', 'Ext', 'Rights.xml'), 'B');
|
||||||
check('suggest Rights.xml → role', /role-/.test(grp(rRole) || ''), rRole.stdout);
|
check('Read Rights.xml → role-info', /role-info/.test(grp(rRole) || ''), rRole.stdout);
|
||||||
|
|
||||||
const rCf = read(join(ACC, 'Configuration.xml'), 'C');
|
const rCf = read(join(ACC, 'Configuration.xml'), 'C');
|
||||||
check('suggest base Configuration.xml → cf', /cf-info/.test(grp(rCf) || ''), rCf.stdout);
|
check('Read base Configuration.xml → cf-info', /cf-info/.test(grp(rCf) || ''), rCf.stdout);
|
||||||
const rCfe = read(join(SYNTH, 'ext', 'Configuration.xml'), 'C');
|
const rCfe = read(join(SYNTH, 'ext', 'Configuration.xml'), 'C');
|
||||||
check('suggest extension Configuration.xml → cfe', /cfe-/.test(grp(rCfe) || ''), rCfe.stdout);
|
check('Read extension Configuration.xml → cfe/cf-info', /cfe-diff|cf-info/.test(grp(rCfe) || ''), rCfe.stdout);
|
||||||
|
const rCfeEdit = edit(join(SYNTH, 'ext', 'Configuration.xml'), 'C');
|
||||||
|
check('Edit extension Configuration.xml → cfe-borrow/patch', /cfe-borrow|cfe-patch-method/.test(grp(rCfeEdit) || ''), rCfeEdit.stdout);
|
||||||
|
|
||||||
// blind spots
|
// blind spots
|
||||||
const rBsl = read(join(SYNTH, 'Catalogs', 'Obj', 'Ext', 'ObjectModule.bsl'), 'D');
|
const rBsl = read(join(SYNTH, 'Catalogs', 'Obj', 'Ext', 'ObjectModule.bsl'), 'D');
|
||||||
check('suggest .bsl → silent', rBsl.stdout === '', rBsl.stdout);
|
check('Read .bsl → silent', rBsl.stdout === '', rBsl.stdout);
|
||||||
const rReadme = read(join(REPO, 'README.md'), 'D');
|
const rReadme = read(join(REPO, 'README.md'), 'D');
|
||||||
check('suggest non-1C file → silent', rReadme.stdout === '', rReadme.stdout);
|
check('Read non-1C file → silent', rReadme.stdout === '', rReadme.stdout);
|
||||||
|
|
||||||
// Grep/Glob search
|
// search tools no longer nudge
|
||||||
const rGrep = suggest({ tool_name: 'Grep', session_id: 'E', cwd: REPO, tool_input: { path: join(ACC, 'Catalogs'), pattern: 'foo' } }, { throttleDir: THR });
|
const rGrep = suggest({ tool_name: 'Grep', session_id: 'E', cwd: REPO, tool_input: { path: join(ACC, 'Catalogs'), pattern: 'foo' } }, { throttleDir: THR });
|
||||||
check('suggest Grep under Catalogs → search nudge', /\*-info/.test(grp(rGrep) || ''), rGrep.stdout);
|
check('Grep → silent (search trigger removed)', rGrep.stdout === '', rGrep.stdout);
|
||||||
|
const rGlob = suggest({ tool_name: 'Glob', session_id: 'E', cwd: REPO, tool_input: { pattern: '**/Catalogs/*.xml' } }, { throttleDir: THR });
|
||||||
|
check('Glob → silent (search trigger removed)', rGlob.stdout === '', rGlob.stdout);
|
||||||
|
|
||||||
// skillSuggester off
|
// skillSuggester off
|
||||||
writeFileSync(join(SYNTH, '.v8-project.json'), JSON.stringify({ skillSuggester: 'off' }));
|
writeFileSync(join(SYNTH, '.v8-project.json'), JSON.stringify({ skillSuggester: 'off' }));
|
||||||
|
|||||||
Reference in New Issue
Block a user