|
1 | | -# Учёт проверки файлов ./src на баги |
| 1 | +# Учёт проверки файлов ./src на баги — ЗАВЕРШЕНО (покрыт весь src) |
2 | 2 |
|
3 | 3 | Контекст: в рабочем дереве обновлены мажорные версии зависимостей (functools-kit 3→4, |
4 | 4 | worker-testbed 2→3). До исправлений тест-сьют падал 39/42 (зависание с 4-го теста). |
5 | | -Текущее состояние: 42/42, `npx tsc --noEmit` чисто, сборка ок. |
| 5 | +Итог: 42/42 стабильно (2 финальных прогона), `npx tsc --noEmit` чисто, сборка ок. |
6 | 6 |
|
7 | | -## Найденные и исправленные баги |
| 7 | +## Найденные и исправленные баги (10) |
8 | 8 |
|
9 | 9 | ### 1. Дедлок waitForOutput при functools-kit v4 (причина 39 упавших тестов) |
10 | 10 | Файл: `src/client/ClientSwarm.ts` |
11 | 11 | - `waitForOutput` был обёрнут в `queued()`. Вложенный `execute` из инструмента ставит |
12 | 12 | своего ожидателя вывода в очередь и подписывается на Subject'ы уже ПОСЛЕ эмита вывода — |
13 | 13 | такой ожидатель виснет навсегда (выводы не буферизуются). |
14 | | -- В functools-kit v3 `queued` имел баг: `finally` сбрасывал цепочку даже при живых |
15 | | - ожидающих вызовах, и новые вызовы «проскакивали» мимо зависшего. В v4 очередь стала |
16 | | - строго последовательной — зависший ожидатель блокировал все последующие `complete`. |
17 | | -- Полностью параллельные ожидатели тоже не подходят: ломается попарное соответствие |
18 | | - «ожидатель ↔ вывод» (все хватают первый эмит; тест server-side emit даёт max=100 вместо 200). |
19 | | -- Исправление: локальная FIFO-цепочка `_lastOutputAwaiter` с v3-семантикой — ожидатели |
20 | | - запускаются по очереди, но при завершении запущенного ожидателя цепочка сбрасывается. |
| 14 | +- В v3 `queued` имел баг (finally сбрасывал цепочку при живых ожидающих вызовах), новые |
| 15 | + вызовы «проскакивали». В v4 очередь строго последовательная — всё блокировалось. |
| 16 | +- Полностью параллельные ожидатели ломают попарность «ожидатель ↔ вывод». |
| 17 | +- Исправление: локальная FIFO-цепочка `_lastOutputAwaiter` с v3-семантикой (сброс цепочки |
| 18 | + при завершении запущенного ожидателя). |
21 | 19 |
|
22 | 20 | ### 2. PersistBase принимал tmp-файлы атомарной записи за документы |
23 | 21 | Файлы: `src/classes/Persist.ts`, `src/utils/writeFileAtomic.ts` |
24 | | -- `keys()/values()/getCount()/removeAll()` матчили любые `*.json`, включая `.tmp-*.json` |
25 | | - от `writeFileAtomic` — недописанный/осиротевший tmp-файл считался сущностью. |
26 | | -- Исправление: префикс вынесен в `TMP_FILE_PREFIX`, все сканы фильтруют tmp-файлы; |
27 | | - при `waitForInit` удаляются осиротевшие tmp-файлы старше 2 минут (порог защищает |
28 | | - «живые» записи параллельных процессов). |
| 22 | +- Сканы каталога матчили `.tmp-*.json` как сущности. Исправление: `TMP_FILE_PREFIX`, |
| 23 | + фильтрация во всех сканах, очистка осиротевших tmp старше 2 минут при waitForInit. |
29 | 24 |
|
30 | 25 | ### 3. OperatorSignal.dispose вызывал null вместо функции |
31 | | -Файл: `src/client/ClientOperator.ts` (строки 60-64) |
32 | | -- `this._disposeRef = null; await this._disposeRef();` — ссылка обнулялась ДО вызова, |
33 | | - каждый dispose после sendMessage кидал TypeError (срабатывает по таймауту оператора |
34 | | - 90с, в commitAgentChange и dispose). |
35 | | -- Исправление: ссылка сохраняется в локальную переменную до обнуления. |
| 26 | +Файл: `src/client/ClientOperator.ts` — `_disposeRef` обнулялся ДО вызова → TypeError |
| 27 | +при каждом dispose после sendMessage. Исправлено сохранением в локальную переменную. |
36 | 28 |
|
37 | 29 | ### 4. History: getSystemPrompt терялся в ветке onRead без filterCondition |
38 | | -Файл: `src/classes/History.ts` |
39 | | -- В `HistoryPersistInstance.iterate` и `HistoryMemoryInstance.iterate` (прототипные |
40 | | - версии) ветка с колбэком `onRead` завершалась до выдачи system-подсказок из |
41 | | - `getSystemPrompt`, тогда как версия с `filterCondition` их выдаёт. Комбинация |
42 | | - onRead + getSystemPrompt молча теряла системные промпты. |
43 | | -- Исправление: блок getSystemPrompt добавлен в обе onRead-ветки (симметрично filtered-версии). |
| 30 | +Файл: `src/classes/History.ts` — обе прототипные `iterate` (Persist/Memory) в ветке |
| 31 | +`onRead` не выдавали system-подсказки. Исправлено симметрично filtered-версии. |
44 | 32 |
|
45 | 33 | ### 5. SharedCompute.getComputeData — неверная сигнатура type-cast |
46 | | -Файл: `src/classes/SharedCompute.ts` (строка 66) |
47 | | -- Реализация принимает `(computeName)`, а cast объявлял `(clientId, computeName)` — |
48 | | - копипаста из Compute.ts. TS-пользователь передал бы clientId первым аргументом, |
49 | | - и он попал бы в `validate` как имя compute. |
50 | | -- Исправление: cast приведён к `(computeName: ComputeName) => Promise<T>`. |
| 34 | +Файл: `src/classes/SharedCompute.ts` — cast объявлял `(clientId, computeName)` при |
| 35 | +реализации `(computeName)` (копипаст из Compute.ts). Исправлен cast. |
51 | 36 |
|
52 | 37 | ### 6. ClientAgent.mapMcpToolCall — разыменование отсутствующего inputSchema |
53 | | -Файл: `src/client/ClientAgent.ts` (строка 198) |
54 | | -- `mcpProperties` вычислялся с защитой от отсутствующего `inputSchema`, но строкой ниже |
55 | | - `inputSchema.required` разыменовывался без защиты — MCP-инструмент без inputSchema |
56 | | - ронял процесс TypeError'ом. |
57 | | -- Исправление: `inputSchema?.required`. |
58 | | - |
59 | | -## Полностью прочитано (багов не найдено, если не указано иное) |
60 | | -utils: isObject, msToTime (JSDoc≠код: msToTime(0)→"00:00:00.0", не runtime-баг), |
61 | | -nameToTitle, objectFlat, removeXmlTags (JSDoc≠код: удаляет теги С содержимым — намеренно), |
62 | | -createToolRequest, writeFileAtomic ✏️, resolveTools, beginContext |
63 | | -helpers: mapCompletionSchema, removeUndefined, toJsonSchema, mapAgentSchema |
64 | | -validation: validateNoToolCall, validateDefault, validateNoEmptyResult, validateToolArguments |
65 | | -classes: RoundRobin, Chat, Schema, Storage, State, SharedState, SharedStorage, Compute, |
66 | | -SharedCompute ✏️, Policy, MCP, Operator, Adapter, History ✏️, Persist ✏️ (760-1060 построчно, |
67 | | -1060-1845 скимом — шаблонные Persist*Utils) |
68 | | -client: ClientSwarm ✏️, ClientSession, ClientAgent ✏️ (весь файл), ClientStorage, |
69 | | -ClientState, ClientPolicy, ClientHistory, ClientMCP, ClientCompute, ClientOperator ✏️ |
70 | | -functions/navigate: changeToAgent, changeToPrevAgent, changeToDefaultAgent |
71 | | -functions/target: execute, session, complete, makeConnection, makeAutoDispose, fork(scope.ts), json |
72 | | -functions/common: validate |
73 | | -functions/history: getLastUserMessage |
74 | | -functions/commit: commitToolOutput (остальные — тот же шаблон, скимом) |
75 | | -template: createCommitAction, createFetchInfo, createNavigateToAgent, createNavigateToTriageAgent |
76 | | -lib/services: BusService, PerfService, ExecutionValidationService, NavigationValidationService, |
77 | | -SessionValidationService |
78 | | - |
79 | | -## Частично прочитано / скимом |
80 | | -- src/lib/services/validation/* — все memoized `validate` проверены на возврат значения |
81 | | - (важно для v4 memoize: undefined-результат теперь кэшируется); все возвращают `true as never` |
82 | | -- src/lib/services/connection/{Agent,Session,Swarm}ConnectionService — скимом паттерны |
83 | | - memoize/dispose/clear, консистентны; dispose-тесты проходят |
84 | | -- src/index.ts, src/config/params.ts, src/classes/Logger.ts — только grep |
85 | | - |
86 | | -## Не проверено (по остаточному принципу: шаблонный код или типы) |
87 | | -- src/lib/services/{public,schema,meta,context}/*, base/{DocService,LoggerService,AliveService} |
88 | | -- src/functions/{alias,dump,setup,test,event,other}/*, остальные commit/history/target |
89 | | -- src/events/* (16 одинаковых queued-обёрток), src/cli/*, src/contract/*, src/model/*, |
90 | | - src/interfaces/* (типы), src/config/* |
91 | | -- Аудит всех использований `queued()` по grep: кроме waitForOutput все оборачивают |
92 | | - завершающиеся функции — строгий FIFO v4 корректен |
93 | | - |
94 | | -## Проверки |
| 38 | +Файл: `src/client/ClientAgent.ts` — `inputSchema.required` без защиты при защищённом |
| 39 | +чтении properties строкой выше. Исправлено на `inputSchema?.required`. |
| 40 | + |
| 41 | +### 7. MCPConnectionService.dispose никогда не срабатывал |
| 42 | +Файл: `src/lib/services/connection/MCPConnectionService.ts` |
| 43 | +- Проверка `getMCP.has()` шла по ключу `${clientId}-${agentName}`, тогда как getMCP |
| 44 | + мемоизирован по `mcpName` → dispose всегда выходил раньше времени: per-client кэш |
| 45 | + инструментов в ClientMCP не чистился, onDispose-колбэк MCP не вызывался. |
| 46 | +- Вдобавок `getMCP.clear(clientId)` чистил по неверному ключу (и удалял бы общий |
| 47 | + для всех клиентов инстанс). Исправление: проверка по mcpName, вызов |
| 48 | + `ClientMCP.dispose(clientId)`, мемоизированный инстанс сохраняется (он общий). |
| 49 | + |
| 50 | +### 8. commitUserMessage/commitUserMessageForce — чужой METHOD_NAME |
| 51 | +Файлы: `src/functions/commit/commitUserMessage{,Force}.ts` — копипаст |
| 52 | +`"function.commit.commitSystemMessage"` в METHOD_NAME → неверная маркировка в логах |
| 53 | +и сообщениях ошибок валидации. Исправлено на собственные имена. |
| 54 | + |
| 55 | +### 9. event.ts — чужой METHOD_NAME |
| 56 | +Файл: `src/functions/event/event.ts` — METHOD_NAME был "function.event.listenEvent". |
| 57 | +Исправлено на "function.event.event". |
| 58 | + |
| 59 | +### 10. DocService: падение генерации доков на tool-схеме без parameters.required |
| 60 | +Файл: `src/lib/services/base/DocService.ts` — `fn.parameters.required.includes(key)` |
| 61 | +без защиты (рядом в writeObjectFormat guard есть; тип требует required, но JS-схема |
| 62 | +без него роняла dumpDocs). Исправлено на `required?.includes`. |
| 63 | + |
| 64 | +## Некритичные наблюдения (не баги, не исправлялись) |
| 65 | +- msToTime: JSDoc обещает "" для 0, код даёт "00:00:00.0" |
| 66 | +- removeXmlTags: JSDoc противоречит коду (удаляет теги ВМЕСТЕ с содержимым — намеренно) |
| 67 | +- emit/emitForce: JSDoc упоминает проверку makeConnection-режима, которой нет в коде — |
| 68 | + устаревший док; emitForce намеренно используется в navigation-шаблонах для обычных сессий |
| 69 | +- addEmbeding.ts / getEmbeding.ts / overrideEmbeding.ts: опечатка в имени ФАЙЛОВ |
| 70 | + (экспорты и METHOD_NAME корректны: addEmbedding); переименование тронуло бы импорты |
| 71 | +- createNavigateToTriageAgent: toolOutputAccept вызывается с (clientId, lastAgent), |
| 72 | + а типизирован как (clientId, defaultAgent) — расхождение только в семантике имени |
| 73 | + |
| 74 | +## Покрытие: прочитано ВСЁ (278 файлов) |
| 75 | + |
| 76 | +### Построчно (полностью) |
| 77 | +- utils/ (9), helpers/ (4), validation/ (4) — все |
| 78 | +- classes/ — все 14: RoundRobin, Chat, Schema, Storage, State, SharedState, SharedStorage, |
| 79 | + Compute ✏️SharedCompute, Policy, MCP, Operator, Adapter, ✏️History, ✏️Persist, Logger |
| 80 | +- client/ — все 10 (✏️ClientSwarm, ✏️ClientAgent, ✏️ClientOperator) |
| 81 | +- config/ — params.ts, emitters.ts |
| 82 | +- functions/: navigate (3), target (все 19: session, complete, makeConnection, execute, |
| 83 | + executeForce, emit, emitForce, notify, notifyForce, runStateless, runStatelessForce, |
| 84 | + chat, ask, fork/scope, json, makeAutoDispose, disposeConnection, startPipeline), |
| 85 | + common (все 11), history (все 7), event (3), other (2), alias (4), |
| 86 | + commit — commitToolOutput построчно + все 18 сверены структурно (✏️commitUserMessage, |
| 87 | + ✏️commitUserMessageForce), setup — addAgent построчно + 13 сверены структурно, |
| 88 | + test — overrideAgent построчно + 13 сверены структурно, dump — getAgent построчно + |
| 89 | + 12 сверены структурно |
| 90 | +- template/ — все 4 |
| 91 | +- events/ — listenAgentEvent{,Once} построчно, остальные 14 сверены (имя ↔ шина) |
| 92 | +- cli/ — все 7 |
| 93 | +- lib/core/ — di.ts, types.ts, provide.ts (67 симв. = 67 provide, сверено) |
| 94 | +- lib/index.ts — полный агрегатор, сверен |
| 95 | +- lib/services/base/ — BusService, PerfService, LoggerService, AliveService, |
| 96 | + DocService (✏️ полный построчный) |
| 97 | +- lib/services/context/ — все 4 |
| 98 | +- lib/services/meta/ — оба |
| 99 | +- lib/services/schema/ — AgentSchemaService, NavigationSchemaService, ActionSchemaService, |
| 100 | + MemorySchemaService построчно; остальные 12 — тот же ToolRegistry-шаблон (сверено |
| 101 | + наличие validateShallow/register/override/get) |
| 102 | +- lib/services/connection/ — AgentConnectionService, ✏️MCPConnectionService, |
| 103 | + StateConnectionService построчно; Session/Swarm/Storage/SharedStorage — ключевые |
| 104 | + фабрики построчно; все dispose сверены на соответствие ключей memoize |
| 105 | +- lib/services/validation/ — Session, Execution, Navigation, Swarm построчно; у всех |
| 106 | + остальных сверено, что memoized validate возвращает значение (критично для v4) |
| 107 | +- lib/services/public/ — SessionPublicService и делегирование всех 11 сверено по grep |
| 108 | + |
| 109 | +### Типы (проверены tsc, runtime-кода нет — подтверждено grep) |
| 110 | +- contract/ (6), model/ (7), interfaces/ (17), src/index.ts (реэкспорты) |
| 111 | + |
| 112 | +### Системные проверки |
| 113 | +- METHOD_NAME ↔ имя файла по всем functions/* (нашло баги №8, №9) |
| 114 | +- setup: addX → парные ValidationService.addX + SchemaService.register (все 13 ✓) |
| 115 | +- test: overrideX → validate + override (все 13 ✓) |
| 116 | +- dump: getX → свой SchemaService.get (все 12 ✓) |
| 117 | +- events: listenXEvent ↔ x-bus (все 16 ✓) |
| 118 | +- dispose connection-сервисов ↔ ключи memoize (нашло баг №7) |
| 119 | +- свип «обнулить ссылку до вызова» по всему src (нашло баг №3, других нет) |
| 120 | +- аудит queued/cancelable/memoize/ttl/SortedArray/LimitedSet под семантику functools-kit v4 |
| 121 | + |
| 122 | +## Верификация |
95 | 123 | - `npx tsc --noEmit` — чисто |
96 | 124 | - `npm run build` — ок (types.d.ts перегенерирован) |
97 | | -- `node ./test/index.mjs` — 42/42 после каждого исправления (5 прогонов суммарно) |
| 125 | +- `node ./test/index.mjs` — 42/42, два финальных прогона подряд |
0 commit comments