@dzhechkov/harness-core 0.8.21 → 0.8.23

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.
Files changed (54) hide show
  1. package/.dz-manifest.json +68 -48
  2. package/README.md +163 -0
  3. package/dist/amendment-trace.d.ts.map +1 -1
  4. package/dist/amendment-trace.js +5 -140
  5. package/dist/amendment-trace.js.map +1 -1
  6. package/dist/claude-hooks-assets.d.ts +3 -3
  7. package/dist/claude-hooks-assets.d.ts.map +1 -1
  8. package/dist/claude-hooks-assets.js +24 -11
  9. package/dist/claude-hooks-assets.js.map +1 -1
  10. package/dist/discrimination-gate.d.ts.map +1 -1
  11. package/dist/discrimination-gate.js +2 -1
  12. package/dist/discrimination-gate.js.map +1 -1
  13. package/dist/feature-adr-routing.d.ts +3 -1
  14. package/dist/feature-adr-routing.d.ts.map +1 -1
  15. package/dist/feature-adr-routing.js +17 -10
  16. package/dist/feature-adr-routing.js.map +1 -1
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/loop-blobs.generated.js +2 -2
  22. package/dist/loop-blobs.generated.js.map +1 -1
  23. package/dist/markdown-masker.d.ts +21 -0
  24. package/dist/markdown-masker.d.ts.map +1 -0
  25. package/dist/markdown-masker.js +119 -0
  26. package/dist/markdown-masker.js.map +1 -0
  27. package/dist/mutation-gate.d.ts +16 -7
  28. package/dist/mutation-gate.d.ts.map +1 -1
  29. package/dist/mutation-gate.js +141 -30
  30. package/dist/mutation-gate.js.map +1 -1
  31. package/dist/statusline.d.ts +14 -0
  32. package/dist/statusline.d.ts.map +1 -1
  33. package/dist/statusline.js +24 -1
  34. package/dist/statusline.js.map +1 -1
  35. package/dist/store-counts.d.ts +12 -0
  36. package/dist/store-counts.d.ts.map +1 -1
  37. package/dist/store-counts.js +30 -12
  38. package/dist/store-counts.js.map +1 -1
  39. package/dist/swarm-brief.d.ts.map +1 -1
  40. package/dist/swarm-brief.js +13 -144
  41. package/dist/swarm-brief.js.map +1 -1
  42. package/package.json +6 -6
  43. package/sbom.json +97 -47
  44. package/src/amendment-trace.ts +6 -123
  45. package/src/claude-hooks-assets.ts +24 -11
  46. package/src/discrimination-gate.ts +2 -1
  47. package/src/feature-adr-routing.ts +21 -11
  48. package/src/index.ts +2 -0
  49. package/src/loop-blobs.generated.ts +2 -2
  50. package/src/markdown-masker.ts +109 -0
  51. package/src/mutation-gate.ts +167 -31
  52. package/src/statusline.ts +35 -1
  53. package/src/store-counts.ts +44 -13
  54. package/src/swarm-brief.ts +13 -104
@@ -1,3 +1,5 @@
1
+ import { maskMarkdown } from './markdown-masker.js';
2
+
1
3
  /**
2
4
  * Контракт вывода брифа роя — РАЗБИРАЕМЫЙ, а не прозаический (ADR-001 фичи
3
5
  * swarm-brief-output-contract).
@@ -169,112 +171,19 @@ const LINE_BREAK = /\r\n|\r|\n/;
169
171
  /** Строка-заглушка вместо замаскированной: не пустая, не пункт, не объявление — то есть проза. */
170
172
  const MASK = '\u0000masked\u0000';
171
173
 
172
- /**
173
- * ОБЪЯВЛЕНИЕ ВНУТРИ ЗАБОРА КОДА ИЛИ HTML-КОММЕНТАРИЯ — НЕ ОБЪЯВЛЕНИЕ (находка 2).
174
- *
175
- * Разбор был построчным и о заборах ``` / ~~~ и о `<!-- -->` не знал. Бриф, чьё НАСТОЯЩЕЕ задание —
176
- * «один итоговый отчёт в самом конце, ничего промежуточного на диск», но с примером контракта в
177
- * блоке ```example, получал «годен». Это ровно тот отказ, ради которого фича заведена (инцидент 33):
178
- * проверка удостоверяла ПРИМЕР вместо задания.
179
- *
180
- * НАЗВАННЫЕ ПРЕДЕЛЫ, оба в безопасную сторону:
181
- * - НЕЗАКРЫТЫЙ забор маскирует текст до конца файла. Значит бриф с болтающимся ``` получит отказ
182
- * «не объявлено», а не тихий пропуск. Громко и с понятным лечением.
183
- * - ОТСТУПНЫЙ блок кода в четыре пробела маскируется. Это намеренно задевает объявление внутри
184
- * пункта списка, если оно сдвинуто на четыре пробела: ложный отказ виден и лечится снятием
185
- * отступа, а ложный зелёный вердикт на невидимой инструкции молчалив.
186
- *
187
- * ДЛИНА ЗАБОРА — ЧАСТЬ ЕГО ТОЖДЕСТВА (раунд 2, дефект 1; кросс-семейное ревью). Первая редакция
188
- * запоминала только СИМВОЛ забора и закрывающим считала любой прогон того же символа — даже КОРОЧЕ
189
- * открывающего. По правилам Markdown закрывающий забор обязан быть не короче открывающего, и на
190
- * этом держится обычнейший приём документации: показать пример, содержащий ```, внутри блока на
191
- * ````. ИЗМЕРЕНО: `````example` с ``` внутри давал `{"ok":true,…,"violations":[]}` и код 0 — то есть
192
- * объявления, лежащие ВНУТРИ внешнего забора, засчитывались настоящими. Это инцидент 33 с другого
193
- * конца: проверка удостоверяла ПРИМЕР вместо задания. Правило — «не короче», а не «ровно столько
194
- * же»: закрывающий забор ДЛИННЕЕ открывающего закрывать обязан, иначе пример остался бы замаскирован
195
- * до конца файла и утащил бы за собой настоящие объявления ниже.
196
- *
197
- * ПОПЫТКА ВЛОЖИТЬ КОММЕНТАРИЙ — ОТКАЗ ПО НЕОДНОЗНАЧНОСТИ (раунд 2, дефект 3). `<!--`, внутри
198
- * `<!-- вложенный -->`, ниже объявления, в конце `-->`. По правилам HTML комментарии НЕ вкладываются:
199
- * первый же `-->` закрывает внешний блок, значит объявления ниже — живой текст, который рендер
200
- * ПОКАЗЫВАЕТ. Автор же, открывший блок сверху, читает их как закомментированные. Два прочтения, оба
201
- * защитимые, и выбрать между ними разборщику нечем.
202
- *
203
- * ПОЧЕМУ НЕ «СЧИТАТЬ ДО ПОСЛЕДНЕГО `-->`» (второй вариант, отвергнут): это выбор в пользу авторского
204
- * прочтения, то есть УГАДЫВАНИЕ — и оно съело бы настоящие объявления, стоящие ниже законно
205
- * закрытого комментария, дав отказ «не объявлено» вместо названной причины. Мы не выбираем: спорная
206
- * область читается по HTML (как живой текст) и ОТДЕЛЬНО помечается, а вердикт — громкий отказ,
207
- * называющий вложение. Это то же правило, что и везде в этом файле: неоднозначность разрешается
208
- * отказом, а не выбором.
209
- *
210
- * НАЗВАННЫЙ ПРЕДЕЛ ЭТОГО ОТКАЗА (риск Р1 — «проверка, изобретающая нарушения, хуже отсутствующей»):
211
- * спорной область становится ТОЛЬКО тогда, когда в ней есть что разбирать — объявление контракта
212
- * или пункт списка. Заметка на полях, устроенная так же, но ничего разбираемого за собой не несущая,
213
- * остаётся годной: отказывать по признаку, который ни на что не влияет, значит учить автора обходить
214
- * проверку.
215
- */
174
+ /** Preserve brief-specific EOF, indentation, list-barrier and ambiguity policies. */
216
175
  function maskFencedAndCommented(lines: readonly string[]): { lines: string[]; nestedComment: boolean } {
217
- const out: string[] = [];
218
- let fence: { char: string; len: number } | null = null;
219
- let inComment = false;
220
- /** Внутри текущего комментария встретился второй `<!--`. */
221
- let nestedOpener = false;
222
- /** Мы за внутренним `-->`: по HTML это уже живой текст, по замыслу автора — ещё комментарий. */
223
- let disputed = false;
176
+ const out = lines.slice();
224
177
  let nestedComment = false;
225
- for (const line of lines) {
226
- if (fence !== null) {
227
- out.push(MASK);
228
- // Закрывает только прогон ТОГО ЖЕ символа длиной НЕ МЕНЬШЕ открывающего. Ни ` ни ~ не
229
- // метасимволы регулярного выражения, поэтому подставляются как есть. CommonMark разрешает
230
- // перед закрытием только 0–3 пробела; четыре пробела оставляют строку содержимым блока.
231
- if (new RegExp(`^ {0,3}${fence.char}{${fence.len},}[ \\t]*$`).test(line)) fence = null;
232
- continue;
233
- }
234
-
235
- // У открывающего забора та же CommonMark-граница 0–3 пробела. При четырёх это одна строка
236
- // отступного кода, а не состояние, способное спрятать последующий живой текст.
237
- const opened = /^ {0,3}(`{3,}|~{3,})/.exec(line);
238
- if (!inComment && opened !== null) {
239
- const run = opened[1] ?? '';
240
- fence = { char: run[0] ?? '`', len: run.length };
241
- out.push(MASK);
242
- continue;
243
- }
244
-
245
- // Четыре пробела превращают строку в код до того, как читатели увидят похожий на контракт
246
- // текст. Маркеры комментария внутри отступного кода тоже не меняют HTML-состояние.
247
- if (!inComment && /^ {4,}/.test(line)) {
248
- out.push(MASK);
249
- continue;
250
- }
251
-
252
- // Маркеры обрабатываются СЛЕВА НАПРАВО. Проверки includes по всей строке теряли второй opener
253
- // в `<!-- заметка --> <!-- скрытое` и выпускали скрытый хвост как живой контракт.
254
- let maskLine = inComment;
255
- const wasDisputed = disputed;
256
- const delimiters = line.match(/<!--|-->/g) ?? [];
257
- for (const delimiter of delimiters) {
258
- maskLine = true;
259
- if (delimiter === '<!--') {
260
- if (inComment) nestedOpener = true;
261
- else inComment = true;
262
- continue;
263
- }
264
- if (inComment) {
265
- inComment = false;
266
- if (nestedOpener) { disputed = true; nestedOpener = false; }
267
- } else if (disputed) {
268
- disputed = false;
269
- }
270
- }
271
- if ((wasDisputed || disputed) && isParseable(line)) nestedComment = true;
272
- if (maskLine) {
273
- out.push(MASK);
274
- continue;
275
- }
276
- out.push(line);
277
- }
178
+ maskMarkdown(lines.join('\n'), {
179
+ unclosed: 'mask',
180
+ indentedCode: true,
181
+ inlineComments: true,
182
+ onMasked: (i = 0) => { out[i] = MASK; },
183
+ onDisputed: (i = 0) => {
184
+ if (isParseable(lines[i] ?? '')) nestedComment = true;
185
+ },
186
+ });
278
187
  return { lines: out, nestedComment };
279
188
  }
280
189