611 lines
51 KiB
HTML
611 lines
51 KiB
HTML
<!DOCTYPE html><html lang="ru"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Архитектура Simbiot Harness (Коди)</title><style>
|
||
:root{--paper:#faf8f3;--ink:#15150f;--signal:#FF4F00;--dim:#6b675e;--line:#d8d3c8;--card:#f3f0e8}
|
||
*{box-sizing:border-box}
|
||
body{margin:0;background:var(--paper);color:var(--ink);font:16px/1.62 -apple-system,"Segoe UI",Roboto,Arial,sans-serif;-webkit-font-smoothing:antialiased}
|
||
.wrap{max-width:1000px;margin:0 auto;padding:48px 28px 120px;display:grid;grid-template-columns:220px 1fr;gap:48px}
|
||
nav{position:sticky;top:24px;align-self:start;font-size:13.5px}
|
||
nav .kicker{font-family:ui-monospace,Menlo,monospace;font-size:11px;letter-spacing:.22em;color:var(--signal);font-weight:700;text-transform:uppercase;margin-bottom:12px}
|
||
nav a{display:block;color:var(--dim);text-decoration:none;padding:4px 0;border-left:2px solid transparent;padding-left:10px}
|
||
nav a:hover{color:var(--ink);border-left-color:var(--signal)}
|
||
main{min-width:0}
|
||
h1{font-size:clamp(30px,5vw,46px);line-height:1.05;font-weight:800;letter-spacing:-.02em;margin:0 0 8px}
|
||
h1+p{color:var(--dim);font-size:14px;margin-top:0;border-bottom:3px solid var(--ink);padding-bottom:20px}
|
||
h2{font-size:24px;margin:56px 0 12px;padding-top:12px;border-top:1px solid var(--line);letter-spacing:-.01em}
|
||
h2::before{content:"";display:inline-block;width:10px;height:10px;background:var(--signal);margin-right:12px;vertical-align:middle}
|
||
code{font-family:ui-monospace,"JetBrains Mono",Menlo,monospace;font-size:.88em;background:var(--card);padding:1px 5px;border-radius:4px}
|
||
pre{background:var(--card);padding:14px;border-radius:8px;overflow-x:auto}
|
||
table{border-collapse:collapse;width:100%;margin:16px 0;font-size:14px;display:block;overflow-x:auto}
|
||
th,td{border:1px solid var(--line);padding:7px 10px;text-align:left;vertical-align:top}
|
||
th{background:var(--ink);color:var(--paper);font-weight:600}
|
||
tr:nth-child(even) td{background:#f6f3ec}
|
||
ul,ol{padding-left:22px} li{margin:4px 0}
|
||
strong{font-weight:700}
|
||
.diagram{margin:24px 0;background:#fff;border:1px solid var(--line);border-radius:10px;padding:12px}
|
||
.diagram svg{width:100%;height:auto;display:block}
|
||
figcaption{font-size:13px;color:var(--dim);margin-top:8px}
|
||
@media(max-width:860px){.wrap{grid-template-columns:1fr} nav{position:static}}
|
||
</style></head><body><div class="wrap"><nav><div class="kicker">Simbiot Harness</div><a href="#обзор">Обзор</a><a href="#процессы-и-сервисы">Процессы и сервисы</a><a href="#event-sourcing-и-криптоаудит">Event Sourcing и криптоаудит</a><a href="#тактовая-лестница">Тактовая лестница</a><a href="#llm-воркер">LLM-воркер</a><a href="#telegram-канал">Telegram-канал</a><a href="#decision-модель">Decision-модель</a><a href="#ядро-коди">Ядро Коди</a><a href="#куб-4-4-4-круги-доверия">Куб 4×4×4: круги доверия</a><a href="#динамическая-память-d0-d3">Динамическая память D0–D3</a><a href="#конфигурация-cli-деплой-и-тесты">Конфигурация, CLI, деплой и тесты</a><a href="#известные-ограничения-и-дорожная-карта">Известные ограничения и дорожная карта</a></nav><main><h1 id="архитектура-simbiot-harness-коди">Архитектура Simbiot Harness (Коди)</h1>
|
||
<p>17.10.2026 · HTML: <code>docs/ARCHITECTURE.html</code> (собирается <code>scripts/build-architecture-html.py</code>) · онлайн-версия для комментариев: https://claude.ai/code/artifact/195fd476-44e7-47cc-9093-2d41ea53c8c9</p>
|
||
<h2 id="обзор">Обзор</h2>
|
||
<p>Simbiot Harness — ритмичный агент кооператива: он живёт тактами (секунда, минута, час, день), а в Telegram отвечает как Коди (@juno42bot). Главная метрика — долгосрочный AUM кооператива: каждое решение проверяется вопросом «добавит ли это ≥1% к AUM на горизонте год+».</p>
|
||
<p>Архитектура держится на пяти принципах:</p>
|
||
<ul>
|
||
<li><strong>Всё — события.</strong> Единственный источник правды — append-only стор событий; состояние (read model) — проекция. Каждое событие подписано ed25519 и сцеплено с предыдущим.</li>
|
||
<li><strong>Дешёвое решает раньше дорогого.</strong> Детерминированные правила и локальные/облачные decision-модели отсекают лишнее до запуска LLM: гейт важности, фильтр адресации, выбор глубины памяти.</li>
|
||
<li><strong>LLM — в изоляции.</strong> Каждый LLM-тик — отдельный процесс с бюджетом шагов, таймаутами и стражем прав на каждом вызове инструмента.</li>
|
||
<li><strong>Доверие — по личности, не по тексту.</strong> Права тика определяет самый недоверенный вход его контекста.</li>
|
||
<li><strong>Учится на исходах.</strong> Ядро Коди собирает решения и их последствия, обучает маленьких учеников и допускает их в бой только при честной победе над базовой линией.</li>
|
||
</ul>
|
||
<p>Куб 4×4×4 задаёт поведение одной таблицей политик: 4 круга доверия × 4 тика × 4 глубины памяти. Это не 64 программы, а один код и параметры.</p>
|
||
<figure class="diagram"><svg viewBox="0 0 760 500" role="img" aria-label="Сообщение проходит фильтры до LLM, всё оседает в сторе" font-size="13" font-family="-apple-system,Segoe UI,Roboto,Arial,sans-serif"><defs><marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z" fill="#6b675e"/></marker></defs><text x="24" y="32" font-size="15" font-weight="600" fill="#15150f">Сообщение проходит фильтры до LLM, всё оседает в сторе</text><g fill="none" stroke="#6b675e" stroke-width="1.25"><path d="M208 86.0H264" marker-end="url(#a)"/><path d="M208 158.0H264" marker-end="url(#a)"/><path d="M380.0 112V132" marker-end="url(#a)"/><path d="M380.0 184V204" marker-end="url(#a)"/><path d="M380.0 256V276" marker-end="url(#a)"/><path d="M380.0 328V348" marker-end="url(#a)"/><path d="M380.0 400V428" marker-end="url(#a)"/><path d="M116.0 400V428" marker-end="url(#a)"/><path d="M496 374.0H552" marker-end="url(#a)"/><path d="M552 158.0H496" stroke-dasharray="4 4" marker-end="url(#a)"/><path d="M552 302.0H496" stroke-dasharray="4 4" marker-end="url(#a)"/></g><g><rect x="24" y="60" width="184" height="52" rx="8" fill="#ffffff" stroke="#b9b3a6" stroke-width="1.25"/><text x="116.0" y="82" text-anchor="middle" font-weight="600" fill="#15150f">Telegram</text><text x="116.0" y="100" text-anchor="middle" font-size="11.5" fill="#6b675e">@juno42bot: личка, группы</text></g><g><rect x="24" y="132" width="184" height="52" rx="8" fill="#ffffff" stroke="#b9b3a6" stroke-width="1.25"/><text x="116.0" y="154" text-anchor="middle" font-weight="600" fill="#15150f">Портал и агенты</text><text x="116.0" y="172" text-anchor="middle" font-size="11.5" fill="#6b675e">MCP, канал агент↔агент</text></g><g><rect x="24" y="348" width="184" height="52" rx="8" fill="#ffffff" stroke="#b9b3a6" stroke-width="1.25"/><text x="116.0" y="370" text-anchor="middle" font-weight="600" fill="#15150f">Человек</text><text x="116.0" y="388" text-anchor="middle" font-size="11.5" fill="#6b675e">cli.py, TUI</text></g><g><rect x="264" y="60" width="232" height="52" rx="8" fill="#ffffff" stroke="#b9b3a6" stroke-width="1.25"/><text x="380.0" y="82" text-anchor="middle" font-weight="600" fill="#15150f">TG-поллер</text><text x="380.0" y="100" text-anchor="middle" font-size="11.5" fill="#6b675e">приём, файлы, голос, кнопки</text></g><g><rect x="264" y="132" width="232" height="52" rx="8" fill="#ffffff" stroke="#b9b3a6" stroke-width="1.25"/><text x="380.0" y="154" text-anchor="middle" font-weight="600" fill="#15150f">Адресация</text><text x="380.0" y="172" text-anchor="middle" font-size="11.5" fill="#6b675e">кому сообщение: боту или людям</text></g><g><rect x="264" y="204" width="232" height="52" rx="8" fill="#ffffff" stroke="#b9b3a6" stroke-width="1.25"/><text x="380.0" y="226" text-anchor="middle" font-weight="600" fill="#15150f">Гейт важности</text><text x="380.0" y="244" text-anchor="middle" font-size="11.5" fill="#6b675e">есть ли событие важнее порога</text></g><g><rect x="264" y="276" width="232" height="52" rx="8" fill="#ffffff" stroke="#b9b3a6" stroke-width="1.25"/><text x="380.0" y="298" text-anchor="middle" font-weight="600" fill="#15150f">Круг доверия и память</text><text x="380.0" y="316" text-anchor="middle" font-size="11.5" fill="#6b675e">права тика, глубина D0–D3</text></g><g><rect x="264" y="348" width="232" height="52" rx="8" fill="#ffe9dd" stroke="#FF4F00" stroke-width="2"/><text x="380.0" y="370" text-anchor="middle" font-weight="600" fill="#15150f">LLM-воркер</text><text x="380.0" y="388" text-anchor="middle" font-size="11.5" fill="#6b675e">инструменты под стражем прав</text></g><g><rect x="552" y="132" width="184" height="52" rx="8" fill="#ffffff" stroke="#b9b3a6" stroke-width="1.25"/><text x="644.0" y="154" text-anchor="middle" font-weight="600" fill="#15150f">Decision-модель</text><text x="644.0" y="172" text-anchor="middle" font-size="11.5" fill="#6b675e">clef:27b → nimble</text></g><g><rect x="552" y="276" width="184" height="52" rx="8" fill="#ffffff" stroke="#b9b3a6" stroke-width="1.25"/><text x="644.0" y="298" text-anchor="middle" font-weight="600" fill="#15150f">Память и ядро</text><text x="644.0" y="316" text-anchor="middle" font-size="11.5" fill="#6b675e">индекс nomic, ученики</text></g><g><rect x="552" y="348" width="184" height="52" rx="8" fill="#ffffff" stroke="#b9b3a6" stroke-width="1.25"/><text x="644.0" y="370" text-anchor="middle" font-weight="600" fill="#15150f">9router и портал</text><text x="644.0" y="388" text-anchor="middle" font-size="11.5" fill="#6b675e">LLM-тики, MCP-вызовы</text></g><rect x="24" y="428" width="712" height="52" rx="8" fill="#f3f0e8" stroke="#b9b3a6" stroke-width="1.25"/><text x="380" y="450" text-anchor="middle" font-weight="600" fill="#15150f">Стор событий</text><text x="380" y="468" text-anchor="middle" font-size="11.5" fill="#6b675e">подписи ed25519 · проекции · сжатие с архивом · каждый шаг пишет события</text></svg><figcaption>Слева — входы, по центру — фильтры перед LLM по порядку, справа — помощники (пунктир — консультируют, сплошная — вызывает воркер); стор событий — единственный источник правды.</figcaption></figure>
|
||
|
||
<h2 id="процессы-и-сервисы">Процессы и сервисы</h2>
|
||
<p>Харнес — два долгоживущих процесса на одном сторе событий плюс короткоживущие LLM-воркеры; код — <code>/root/simbiot-harness</code>, данные инстанса — <code>/var/lib/simbiot-harness</code> (<code>SIMBIOT_HOME</code>).</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Процесс</th>
|
||
<th>Запуск</th>
|
||
<th>Что делает</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Лестница</td>
|
||
<td><code>simbiot-harness.service</code> → <code>python -m harness.scheduler</code></td>
|
||
<td>такты sec/min/hour/day в отдельных потоках, демон доставки и сирот, триаж, ночная тренировка ядра</td>
|
||
</tr>
|
||
<tr>
|
||
<td>TG-поллер</td>
|
||
<td><code>simbiot-harness-tg.service</code> → <code>python -m harness.tg_inbox</code></td>
|
||
<td>long polling @juno42bot: входящие, файлы, расшифровка голоса, кнопки</td>
|
||
</tr>
|
||
<tr>
|
||
<td>LLM-воркер</td>
|
||
<td><code>harness/_llm_worker.py</code>, сабпроцесс на каждый LLM-тик</td>
|
||
<td>агент Strands с инструментами, страж прав, бюджет шагов</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Дашборд</td>
|
||
<td><code>simbiot-dashboard.service</code>, HTTP 8765</td>
|
||
<td>доска задач и тиков, только чтение стора</td>
|
||
</tr>
|
||
<tr>
|
||
<td>CLI</td>
|
||
<td><code>cli.py</code> (и обёртка <code>simbiot</code>)</td>
|
||
<td>команды агентов и людей: ответы, задачи, эскалации, ядро, память, доверие</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Каталоги инстанса (<code>/var/lib/simbiot-harness</code>):</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Путь</th>
|
||
<th>Содержимое</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>db/harness.db</code></td>
|
||
<td>стор событий + read model + журнал доставок (SQLite, WAL)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>env/.env</code></td>
|
||
<td>секреты и флаги (600)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>audit/</code></td>
|
||
<td>ключ ed25519 харнеса</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>archive/</code></td>
|
||
<td>сжатые события (jsonl.gz, подписаны)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>core/</code></td>
|
||
<td>чемпионы учеников ядра + кеш эмбеддингов</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>memory/</code></td>
|
||
<td>индекс памяти Коди</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>inbox/</code></td>
|
||
<td>файлы из чатов</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Внешние зависимости:</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Система</th>
|
||
<th>Зачем</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>9router (<code>127.0.0.1:20128</code>)</td>
|
||
<td>LLM для тиков, модель <code>auto</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Ollama Cloud</td>
|
||
<td>decision-модель <code>clef:27b</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Ollama локально (<code>127.0.0.1:11434</code>)</td>
|
||
<td>запасная decision-модель <code>nimble</code>, эмбеддинги <code>nomic-embed-text</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Портал cil.by (MCP)</td>
|
||
<td>звонки, реестры, канал агент↔агент</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Telegram Bot API</td>
|
||
<td>чаты Коди</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Deepgram</td>
|
||
<td>расшифровка голосовых</td>
|
||
</tr>
|
||
<tr>
|
||
<td>RAG <code>/root/rag</code></td>
|
||
<td>поиск по базе знаний кооператива</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2 id="event-sourcing-и-криптоаудит">Event Sourcing и криптоаудит</h2>
|
||
<p>Всё состояние харнеса выводится из подписанной цепочки событий (<code>harness/es.py</code>, <code>harness/audit.py</code>); после сжатия 17.10 стор — 200 MB, полная проверка — около 30 с.</p>
|
||
<p><strong>Стор.</strong> Таблица <code>events</code> (aggregate, aggregate_id, event_type, data, timestamp, version, sig, key_id, prev_sig). Уникальность <code>(aggregate, aggregate_id, version)</code> делает запись идемпотентной: тик <code>level:seq</code> не произойдёт дважды. Клейм задачи — атомарный (<code>claim_task_if_ready</code>, BEGIN IMMEDIATE), поэтому два уровня не возьмут одну задачу.</p>
|
||
<p><strong>Проекции.</strong> <code>run_projections()</code> инкрементально строит read model (задачи, инбокс, эскалации, дайджесты, круги доверия, политика AUM) и сохраняет снапшот в <code>read_model</code>. Перед применением хвост проверяется подписями: подделка останавливает проекции.</p>
|
||
<p><strong>Подписи.</strong> Каждое событие подписано ключом харнеса (ed25519, key_id <code>faf8d19d9aed71fe</code>), <code>prev_sig</code> ссылается на подпись более раннего. События до внедрения подписей помечены <code>genesis:<id></code>, неподписанные — legacy-границы. Защита от чужого ключа: стор, уже подписанный одним ключом, другим не подписывается. Полная проверка — <code>cli.py verify</code>.</p>
|
||
<p><strong>Сжатие с подписью</strong> (<code>harness/compact.py</code>, <code>scripts/compact-store.sh</code>). Шум сек-уровня старше часа уходит в архив:</p>
|
||
<ol>
|
||
<li>Строки целиком, со всеми подписями, пишутся в <code>archive/events-<first>-<last>-<id>.jsonl.gz</code> (600).</li>
|
||
<li>Подписи удалённых строк, на которые ссылаются остающиеся, и маркеры <code>boundary:<id></code> для legacy-границ попадают в мост <code>compaction_bridge</code>.</li>
|
||
<li>Подписанное событие <code>StoreCompacted</code> фиксирует sha256 архива, строк и моста.</li>
|
||
<li>Удаление идёт пачками по 20 000 строк без остановки сервисов; VACUUM — под остановленными писателями (секунды).</li>
|
||
</ol>
|
||
<p><code>verify</code> принимает мост, только если его хеш совпадает с подписанным <code>StoreCompacted</code>; архивы проверяются построчно (<code>cli.py compact --verify-archives</code>). Первое сжатие: 2 886 765 строк в архив (246 MB), 1389 → 200 MB.</p>
|
||
<p>Сек-уровень больше не шумит: <code>CycleTicked</code>/<code>ReflexObserved</code> пишутся heartbeat'ом раз в 60 с и в такты с событием (алерт, команды, каналы).</p>
|
||
<h2 id="тактовая-лестница">Тактовая лестница</h2>
|
||
<p>Четыре уровня тикают независимо, каждый в своём потоке (<code>harness/scheduler.py</code>, <code>harness/levels.py</code>); дорогой LLM-тик запускается, только если есть событие важнее порога уровня.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Уровень</th>
|
||
<th>Интервал</th>
|
||
<th>LLM</th>
|
||
<th>Порог гейта</th>
|
||
<th>Задачи</th>
|
||
<th>Шагов на тик</th>
|
||
<th>Таймаут</th>
|
||
<th>Память по умолчанию</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>sec</td>
|
||
<td>1 с</td>
|
||
<td>нет</td>
|
||
<td>—</td>
|
||
<td>—</td>
|
||
<td>—</td>
|
||
<td>—</td>
|
||
<td>—</td>
|
||
</tr>
|
||
<tr>
|
||
<td>min</td>
|
||
<td>1 мин + по входящему</td>
|
||
<td>effort low, контекст 256k</td>
|
||
<td>critical</td>
|
||
<td>S</td>
|
||
<td>30</td>
|
||
<td>480 с</td>
|
||
<td>D1</td>
|
||
</tr>
|
||
<tr>
|
||
<td>hour</td>
|
||
<td>1 ч</td>
|
||
<td>effort medium, 512k</td>
|
||
<td>warn</td>
|
||
<td>S, M, L</td>
|
||
<td>300</td>
|
||
<td>2880 с</td>
|
||
<td>D2</td>
|
||
</tr>
|
||
<tr>
|
||
<td>day</td>
|
||
<td>1 д</td>
|
||
<td>effort high, 1M</td>
|
||
<td>warn</td>
|
||
<td>S, M, L</td>
|
||
<td>10 000</td>
|
||
<td>таймаут уровня</td>
|
||
<td>D3</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>sec — рефлекс без LLM.</strong> Телеметрия и алерт нагрузки, мгновенные команды бота (<code>/лестница</code>, <code>/статус</code>, <code>/задачи</code>), каналы портала и агент↔агент.</p>
|
||
<p><strong>Гейт важности.</strong> Сигналы: входящее без ответа и готовая задача — critical; эскалации — по их severity; высокая нагрузка — warn. Ниже порога тик закрывается детерминированно (<code>GateSkipped</code> + заглушка-дайджест). Серая зона (только warn/info) спрашивает decision-модель — сейчас в режиме shadow.</p>
|
||
<p><strong>Тик по входящему.</strong> Демон раз в секунду смотрит хвост стора; через 3 с тишины после <code>MessageReceived</code> или <code>MessageTranscribed</code> запускает внеочередной мин-тик в слот следующей минуты. Ответ в Telegram приходит за 10–40 с вместо ~80 с медианы до нуджа.</p>
|
||
<p><strong>Батч задач.</strong> Уровень берёт все ready-задачи своих классов в бюджете контекста: из 9 старейших первой ставится самая ценная для AUM (decision-модель), остальные — FIFO. В один батч попадают задачи одного круга доверия, и уровень берёт только обслуживаемые круги.</p>
|
||
<p><strong>Эскалация недоделанных.</strong> «Бюджет исчерпан» или смерть воркера возвращают задачу в очередь; после 2 захватов на уровне она растёт до размера, которого этот уровень не берёт (S → M, к часу). До этого S-задача могла браться минутным уровнем 33 раза подряд. Задачи про внешние системы (портал, сервер, деплой, UI, git) сразу уходят часу — правило головы <code>task_fit</code>.</p>
|
||
<p>Занятый уровень поглощает тик (<code>TickAbsorbed</code>), запущенная задача не прерывается, наверх идут только дайджесты и эскалации (<code>cli.py escalate</code>). Демон доставки возвращает задачи-сироты после рестартов и доставляет результаты в чат идемпотентно (журнал доставок).</p>
|
||
<h2 id="llm-воркер">LLM-воркер</h2>
|
||
<p>Каждый LLM-тик — отдельный процесс (<code>isolated_runner.py</code> → <code>_llm_worker.py</code>) со свежим asyncio-рантаймом Strands: падение или таймаут не роняют лестницу, а вся группа процессов добивается по таймауту уровня.</p>
|
||
<p><strong>Вход воркера (payload):</strong> мандат уровня, собранный контекст тика, модель и effort, флаг shell, круг доверия тика. Результат возвращается JSON-файлом; трассу (<code>InvocationStarted</code>, <code>ToolCalled</code>, <code>ToolResult</code>, <code>BudgetSpent</code>) воркер пишет в стор сам и инкрементально, чтобы таймаут не съел учёт расходов.</p>
|
||
<p><strong>Инструменты:</strong></p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Инструмент</th>
|
||
<th>Ограничение</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>shell</code>, <code>read</code>, <code>write</code>, <code>edit</code></td>
|
||
<td>только уровни с <code>can_shell</code>; в кругах ≥ 2 — страж прав</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>rag_lookup</code></td>
|
||
<td>1 запрос на тик, k ≤ 5, таймаут 20 с</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>portal_mcp</code></td>
|
||
<td>4 вызова на тик, деньги-тулы запрещены по умолчанию</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>cli.py …</code> через shell</td>
|
||
<td>основной способ действовать: <code>tg-reply</code>, <code>task</code>, <code>complete</code>, <code>escalate</code>, <code>tg-deliver-file</code>, <code>decide</code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Хуки на каждом вызове</strong> (<code>BeforeToolCallEvent</code>, до исполнения):</p>
|
||
<ol>
|
||
<li><strong>Страж прав</strong> — <code>trust.check_tool</code>: запрещённый вызов отменяется (<code>cancel_tool</code>) и пишется <code>TrustDenied</code>.</li>
|
||
<li><strong>Бюджет шагов</strong> — сверх лимита уровня вызовы отменяются, цикл завершается итоговым текстом; задачи без <code>complete</code> возвращаются или эскалируются.</li>
|
||
<li><strong>Трасса</strong> — <code>ToolCalled</code>/<code>ToolResult</code> с trace_id, уровнем и длительностью.</li>
|
||
</ol>
|
||
<p><strong>TTFT-сторож.</strong> Если апстрим 9router принял запрос, но за 45 с не прислал первый токен, стрим закрывается и делается новый вызов (до 3 попыток). Начавший отвечать стрим не трогается.</p>
|
||
<p><strong>Окружение.</strong> <code>SIMBIOT_TICK_CIRCLE</code> наследуют shell и <code>cli.py</code>: задачи из тика штампуются его кругом, а <code>cli.py trust set</code> из тика отказывает.</p>
|
||
<h2 id="telegram-канал">Telegram-канал</h2>
|
||
<p>Коди в Telegram — бот @juno42bot (id 7245454391); поллер пишет входящие в стор, а отвечает минутный (реже часовой) тик через <code>cli.py tg-reply</code>.</p>
|
||
<p><strong>Приём</strong> (<code>harness/tg_inbox.py</code>). Long polling (<code>message</code>, <code>edited_message</code>, <code>callback_query</code>). Отправитель вне <code>SIMBIOT_TG_ALLOWED</code> → <code>MessageIgnored(not_allowed)</code>. Документы и фото сразу сохраняются на диск, голосовые расшифровываются. Сохраняется, на чьё сообщение сделан reply и упомянут ли бот. Правка уже принятого сообщения не становится новым входящим.</p>
|
||
<p><strong>Адресация в группах</strong> (<code>harness/addressing.py</code>) — до гейта, без LLM:</p>
|
||
<ol>
|
||
<li>Личка, портал, агенты — всегда адресовано.</li>
|
||
<li>В группе «да» без модели: <code>@juno42bot</code>, reply на сообщение бота, звательное обращение («Коди, …», «…, Коди», «Коди!»).</li>
|
||
<li>«Нет» без модели: reply на сообщение другого человека.</li>
|
||
<li>Серая зона — decision-модель: «кому адресовано — боту, человеку или группе», P(бот) ≥ 0.5. Разговор О Коди в третьем лице обращением не считается. Модель недоступна — бот молчит.</li>
|
||
</ol>
|
||
<p>Вердикт: <code>MessageTriaged{addressed}</code> + 👀 или <code>MessageIgnored(not_addressed)</code> — тогда ни один уровень его не видит. В тени рядом работает ученик ядра <code>addressing</code>.</p>
|
||
<p><strong>Ответы.</strong> В группе — reply'ем на последнее сообщение батча (<code>allow_sending_without_reply</code>), в личке — без цитаты. Сводный ответ на несколько сообщений — <code>tg-reply m-1,m-2 -c</code>. Правило «сначала ответ, потом работа»: если нужно больше ~30 с, сначала короткий ответ, итог — <code>tg-reply <id> --followup</code> в тот же чат (идемпотентно по тексту).</p>
|
||
<p><strong>Реакции.</strong> 👀 ставится при приёме в личке и триажем в группе — только на адресованное боту. Параметр Bot API — <code>reaction</code> (массив); до 17.10 ошибка в имени параметра делала реакцию невидимой.</p>
|
||
<p><strong>Журнал исходящих.</strong> Каждое сообщение бота → <code>OutboundMessage</code> (chat:message_id → полный текст). Reply на сообщение бота получает <code>reply_to_full</code> (до 4000 символов вместо 300 от Telegram), а тик видит блок «ЭТО ОТВЕТ НА ТВОЁ СООБЩЕНИЕ». Собственные рассылки бота за 48 ч попадают в память тика.</p>
|
||
<p><strong>Кнопки.</strong> <code>core:…</code> — «Это было мне?» для ученика ядра; <code>trust:…</code> — «Разрешить полные права», нажать может только владелец.</p>
|
||
<h2 id="decision-модель">Decision-модель</h2>
|
||
<p>Решения «выбрать один из нескольких» и «да/нет» принимает не LLM, а decision-модель Ollama <code>/v1/systemone</code> (<code>harness/decision.py</code>): облачная <code>clef:27b</code> отвечает за 0.6–0.9 с, запасная локальная <code>nimble</code> (qwen3.5-9B Q8_0, CPU) — за 10–30 с.</p>
|
||
<p><strong>Контракт.</strong> <code>choice</code> — варианты объектом <code>{ключ: описание}</code>, ответ — ключ и распределение вероятностей; <code>noul</code> — P(«да»). Шортлист строго ≤ 9 вариантов: по замерам systemone-bench точность падает со 100% на 6 до 50% на 10. <code>confidence</code> — концентрация распределения, а не вероятность правильности.</p>
|
||
<p><strong>Надёжность.</strong> Бэкенды опрашиваются по порядку, у каждого свой предохранитель: облако — таймаут 30 с, после сбоя пауза 60 с; локальная — 90 с и 5 минут. Ответы детерминированы, поэтому кешируются на час по хешу вопроса и состояния. Каждый реальный вызов → <code>DecisionMade</code> (бэкенд, модель, латентность, применено ли). Модель недоступна — вызывающий берёт свой детерминированный фолбэк.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Потребитель</th>
|
||
<th>Вопрос</th>
|
||
<th>Режим</th>
|
||
<th>Фолбэк</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>адресация в группах</td>
|
||
<td>кому адресовано сообщение</td>
|
||
<td>on</td>
|
||
<td>молчать</td>
|
||
</tr>
|
||
<tr>
|
||
<td>порядок батча задач</td>
|
||
<td>какая из 9 старейших ценнее для AUM</td>
|
||
<td>on</td>
|
||
<td>FIFO</td>
|
||
</tr>
|
||
<tr>
|
||
<td>тема инициативы</td>
|
||
<td>что сейчас полезнее предложить</td>
|
||
<td>on</td>
|
||
<td>по кругу</td>
|
||
</tr>
|
||
<tr>
|
||
<td>серая зона гейта</td>
|
||
<td>нужен ли дорогой LLM-тик</td>
|
||
<td>shadow</td>
|
||
<td>порог</td>
|
||
</tr>
|
||
<tr>
|
||
<td>агент в тике</td>
|
||
<td><code>cli.py decide -q … -o ключ=описание</code></td>
|
||
<td>on</td>
|
||
<td>—</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Режимы: <code>SIMBIOT_DECISION=off|shadow|on</code>, точечно <code>SIMBIOT_DECISION_<ПОТРЕБИТЕЛЬ></code>; ключ облака — <code>SIMBIOT_DECISION_API_KEY</code> в <code>.env</code> инстанса. Статус и статистика — <code>cli.py decide</code>, <code>cli.py decide --stats</code>.</p>
|
||
<h2 id="ядро-коди">Ядро Коди</h2>
|
||
<p>Ядро (<code>harness/kodi_core.py</code>) — цикл самообучения по образцу systemone-bench (engine42/router42): учитель и правила решают, маленький ученик учится на их решениях и реальных исходах и получает право решать сам только после честной проверки. Сейчас у ядра три головы.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Голова</th>
|
||
<th>Решение</th>
|
||
<th>Метки</th>
|
||
<th>Режим</th>
|
||
<th>Состояние на 17.10</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>addressing</code></td>
|
||
<td>отвечать ли в группе</td>
|
||
<td>учитель (вес 1), реакция чата (3), кнопки владельца (5)</td>
|
||
<td>shadow</td>
|
||
<td>чемпион на 262 примерах</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>task_fit</code></td>
|
||
<td>влезет ли S-задача в мин-тик</td>
|
||
<td>исходы задач из истории</td>
|
||
<td>on (правило «внешние системы»)</td>
|
||
<td>ML-чемпион снят: не бил базу; действует правило (точность 0.74)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>depth</code></td>
|
||
<td>нужна ли глубокая память</td>
|
||
<td>решения правил (1), нехватка памяти по трассе (3)</td>
|
||
<td>shadow</td>
|
||
<td>копит данные, нужно 40 примеров</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Ученик.</strong> Признаки — эмбеддинг <code>nomic-embed-text</code> (локально, ~70 мс, с дисковым кешем) плюс флаги головы. Модель — логистическая регрессия на numpy (Adam, L2): на сотнях примеров она устойчивее MLP. kNN-память даёт «новизну»; её пороги калибруются при обучении.</p>
|
||
<p><strong>Роутер.</strong> Знакомая ситуация и |p − 0.5| ≥ 0.4 → решает ученик; незнакомая и учитель сомневается → вопрос владельцу кнопками (≤ 5 в сутки); иначе — учитель. В shadow ученик только пишет <code>CorePrediction</code>.</p>
|
||
<p><strong>Честный допуск</strong> (ночная тренировка в дневной тик, <code>cli.py core train</code>):</p>
|
||
<ol>
|
||
<li>Чемпион помнит <code>trained_upto</code>; с претендентом сравнивается только на свежих данных (≥ 10), которых он не видел.</li>
|
||
<li>Претендент обязан бить базовую линию — константу, равную доле класса.</li>
|
||
<li>Чемпион, который на свежих данных хуже базы, снимается (<code>CoreModelRetired</code>) — ученик молчит.</li>
|
||
<li>Смена чемпиона — подписанное <code>CoreModelPromoted</code> с sha256 файла; подменённый файл не грузится; откат — <code>cli.py core rollback --head <голова></code>.</li>
|
||
</ol>
|
||
<p><strong>Рефлексия.</strong> Раз в сутки: ≥ 3 расхождений адресации с метками человека/чата или ≥ 3 S-задач, не влезших в мин-тик, → задача часу с автодоставкой: разобрать случаи и предложить владельцу правило. Первая рефлексия (17.10) привела к правилу <code>task_fit</code> «внешние системы → сразу к часу».</p>
|
||
<p><strong>Недельный отчёт.</strong> По понедельникам владельцу в личку, без LLM, идемпотентно по неделе (<code>cli.py core report</code>).</p>
|
||
<h2 id="куб-4-4-4-круги-доверия">Куб 4×4×4: круги доверия</h2>
|
||
<p>Поведение задаёт одна таблица <code>POLICY</code> (<code>harness/trust.py</code>): круг доверия определяет инструменты, уровни времени и потолок глубины памяти. Вторая ось — тики (sec/min/hour/day), третья — глубина D0–D3.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Круг</th>
|
||
<th>Кто</th>
|
||
<th>Shell</th>
|
||
<th>Файлы</th>
|
||
<th>Портал MCP</th>
|
||
<th>Уровни</th>
|
||
<th>Память до</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>1 владелец</td>
|
||
<td>Alex, локальный терминал, система (тик без внешних входов)</td>
|
||
<td>полный</td>
|
||
<td>полный доступ</td>
|
||
<td>всё (деньги — по флагу)</td>
|
||
<td>все</td>
|
||
<td>D3</td>
|
||
</tr>
|
||
<tr>
|
||
<td>2 правление</td>
|
||
<td>Vlad, Yura</td>
|
||
<td><code>cli.py</code>: ответы, задачи, эскалации, доставка файлов, обзор доски</td>
|
||
<td>чтение docs/out/sites/artifacts и присланного</td>
|
||
<td>звонки, реестры, фичи; без казны и member_create</td>
|
||
<td>min, hour, day</td>
|
||
<td>D3</td>
|
||
</tr>
|
||
<tr>
|
||
<td>3 свои</td>
|
||
<td>участники портала, MCP-агенты, партнёры</td>
|
||
<td><code>cli.py</code>: ответы, задачи, эскалации</td>
|
||
<td>нет</td>
|
||
<td>запись на звонок, проекты, фичи</td>
|
||
<td>min, hour</td>
|
||
<td>D2</td>
|
||
</tr>
|
||
<tr>
|
||
<td>4 остальные</td>
|
||
<td>прочие Telegram-пользователи</td>
|
||
<td><code>cli.py</code>: только ответ и эскалация</td>
|
||
<td>нет</td>
|
||
<td>нет</td>
|
||
<td>min</td>
|
||
<td>D1</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Как определяется круг.</strong> Только по проверенной личности: Telegram user_id, канал MCP-агента или портала, локальный терминал. Текст сообщения прав не даёт. Меняет круг только человек на сервере (<code>cli.py trust set <субъект> <1-4></code>) — из LLM-тика это запрещено и стражем, и самим CLI.</p>
|
||
<p><strong>Круг тика</strong> = самый недоверенный вход его контекста (входящие + задачи батча). Задачи наследуют круг тика, в котором поданы: просьба правления не исполняется позже часовым уровнем с правами владельца.</p>
|
||
<p><strong>Страж</strong> проверяет каждый вызов инструмента до исполнения. Shell в кругах 2–4 — одна команда <code>cli.py</code> из белого списка круга, без <code>;</code> <code>&&</code> <code>|</code> <code>></code> <code>$()</code> и обратных кавычек; файлы с секретами закрыты всегда. Задача правления упёрлась в права → владельцу приходят кнопки «Разрешить / Нет»; «Разрешить» даёт задаче круг 1.</p>
|
||
<p>Вживую проверено на реальном воркере в круге 2: <code>cat /etc/hostname</code> отменён до исполнения, <code>cli.py decide --stats</code> выполнился.</p>
|
||
<h2 id="динамическая-память-d0-d3">Динамическая память D0–D3</h2>
|
||
<p>Перед каждым LLM-тиком харнес выбирает, сколько собственной истории подгрузить (<code>harness/memory.py</code>, <code>SIMBIOT_MEMORY=on</code>); индекс на 17.10 — 1650 разговоров, 270 итогов задач, 91 дайджест.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Глубина</th>
|
||
<th>Что в контексте</th>
|
||
<th>Когда</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>D0</td>
|
||
<td>только текущие входящие</td>
|
||
<td>все реплики односложные: «ок», «спасибо»</td>
|
||
</tr>
|
||
<tr>
|
||
<td>D1</td>
|
||
<td>+ 12 последних реплик чата + свои сообщения за 48 ч</td>
|
||
<td>минутный тик по умолчанию</td>
|
||
</tr>
|
||
<tr>
|
||
<td>D2</td>
|
||
<td>+ до 8 эпизодов из своей истории по смыслу (≤ 5000 символов)</td>
|
||
<td>час; «помнишь», «вчера», «как договаривались»; задачи в батче; reply на сообщение бота старше 48 ч</td>
|
||
</tr>
|
||
<tr>
|
||
<td>D3</td>
|
||
<td>+ до 15 записей архива (≤ 12 000 символов)</td>
|
||
<td>день; «за месяц», «что ты делал», «итоги», «план на»</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Потолок задаёт круг: «свои» — до D2, «остальные» — до D1.</p>
|
||
<p><strong>Индекс</strong> (<code><home>/memory/index.sqlite</code>) инкрементально догоняет стор перед поиском (~3.5 с, только чтение):</p>
|
||
<ul>
|
||
<li><code>conv</code> — сообщение + ответ Коди (в батче — ответ головы);</li>
|
||
<li><code>out</code> — собственные рассылки бота, не ответы;</li>
|
||
<li><code>task</code> — задача и её итог;</li>
|
||
<li><code>digest</code> — содержательные дайджесты часа и дня (заглушки отсеиваются).</li>
|
||
</ul>
|
||
<p><strong>Приватность.</strong> У каждой записи — круг: сказанное в чате видно всем его участникам, поэтому круг записи = самый недоверенный участник чата (личка владельца — 1, «Правление» — 2); задача — её круг; дайджест — 1. Поиск отдаёт только записи с кругом ≥ круга тика: тик с сообщением правления не поднимет личку владельца. Круги читаются прямо из событий <code>TrustSet</code>, чтобы отставшая проекция не дала записи слишком широкий круг.</p>
|
||
<p><strong>Релевантность.</strong> Эмбеддинги <code>nomic-embed-text</code> (<code>search_document</code> / <code>search_query</code>). Калибровка на прод-индексе: релевантное — 0.78–0.88, посторонний запрос — до 0.75. Порог 0.76 и окно 0.07 от лучшего совпадения; свежий разговор того же чата (уже в D1) не дублируется.</p>
|
||
<p><strong>Обучение выбора.</strong> Решение о глубине → <code>DepthChosen</code> с причинами и признаками нехватки памяти по трассе: агент полез в базу знаний или в свой стор, ответил «не помню». Это сырьё для головы ядра <code>depth</code>.</p>
|
||
<h2 id="конфигурация-cli-деплой-и-тесты">Конфигурация, CLI, деплой и тесты</h2>
|
||
<p>Настройки читаются из env процесса, затем из <code>/var/lib/simbiot-harness/env/.env</code>; новые подсистемы по умолчанию выключены или в shadow, а на проде включаются строкой в <code>.env</code>.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Переменная</th>
|
||
<th>Прод</th>
|
||
<th>Что делает</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>SIMBIOT_DECISION</code></td>
|
||
<td>on</td>
|
||
<td>decision-модель (гейт — shadow)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SIMBIOT_DECISION_API_KEY</code></td>
|
||
<td>задан</td>
|
||
<td>облако <code>clef:27b</code>, запасная — локальная <code>nimble</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SIMBIOT_MEMORY</code></td>
|
||
<td>on</td>
|
||
<td>индекс памяти и блоки D2/D3</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SIMBIOT_CORE_ADDRESSING</code></td>
|
||
<td>shadow</td>
|
||
<td>ученик адресации</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SIMBIOT_CORE_TASK_FIT</code></td>
|
||
<td>on</td>
|
||
<td>сразу к часу задачи про внешние системы</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SIMBIOT_CORE_DEPTH</code></td>
|
||
<td>shadow</td>
|
||
<td>ученик глубины памяти</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SIMBIOT_TG_ALLOWED</code></td>
|
||
<td>Alex, Yura, Vlad</td>
|
||
<td>кто вообще обрабатывается</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SIMBIOT_MIN_NUDGE</code></td>
|
||
<td>on</td>
|
||
<td>тик по входящему</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SIMBIOT_TASK_ATTEMPTS_PER_LEVEL</code></td>
|
||
<td>2</td>
|
||
<td>попыток до эскалации размера</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>SIMBIOT_MAX_TOOL_CALLS_<УРОВЕНЬ></code></td>
|
||
<td>min 30, hour 300</td>
|
||
<td>бюджет шагов тика</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>CLI</strong> (<code>cli.py</code>, для людей и агентов в тике):</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Группа</th>
|
||
<th>Команды</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>чат</td>
|
||
<td><code>tg-reply [--followup]</code>, <code>tg-notify -k</code>, <code>tg-deliver-file</code>, <code>tg-list</code>, <code>tg-seen</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>задачи</td>
|
||
<td><code>task</code>, <code>tasks</code>, <code>complete</code>, <code>block</code>, <code>promote</code>, <code>requeue</code>, <code>close</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>уровни</td>
|
||
<td><code>ladder</code>, <code>status</code>, <code>escalate</code>, <code>escalations</code>, <code>escalation-ack</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>решения</td>
|
||
<td><code>decide</code>, <code>decide --stats</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>ядро</td>
|
||
<td><code>core status / train / backfill / feedback / reflect / report / rollback / retire [--head]</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>память</td>
|
||
<td><code>memory sync [--all] / stats / search "…" --circle N</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>доверие</td>
|
||
<td><code>trust list</code>, <code>trust set <субъект> <1-4></code> (только человек)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>стор</td>
|
||
<td><code>events</code>, <code>verify</code>, <code>compact [--dry-run / --vacuum / --verify-archives]</code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Деплой.</strong> Код — ветка <code>master</code> в <code>git.cil.by/symbiot/simbiot-harness</code>. Перезапуск лестницы — только <code>scripts/safe-restart.sh</code>: он ждёт, пока закончится идущий LLM-воркер, чтобы задача не застряла в running. TG-поллер перезапускается напрямую: Telegram копит апдейты. Сжатие стора — <code>scripts/compact-store.sh</code>.</p>
|
||
<p><strong>Тесты.</strong> <code>tests/test_*.py</code> — скрипты (<code>./venv/bin/python tests/<имя>.py</code>), каждый со своим временным стором (<code>SIMBIOT_DB</code>). Внешние системы подменены: фейковый <code>/v1/systemone</code>, эмбеддинги «мешок слов», заглушки Telegram. Перед каждым коммитом гоняется полный набор и сравнивается с предыдущим прогоном. Несколько старых тестов (<code>test_tg_commands</code>, <code>test_reply_routing</code>, <code>test_portal_mcp</code>, <code>test_tool_budget</code>) падают и на чистом коде — они зависят от живого состояния.</p>
|
||
<h2 id="известные-ограничения-и-дорожная-карта">Известные ограничения и дорожная карта</h2>
|
||
<p>Главное открытое место — косвенные каналы между кругами и автономность часового уровня в круге 1.</p>
|
||
<p><strong>Ограничения:</strong></p>
|
||
<ul>
|
||
<li><strong>Выжимки нижних уровней считаются внутренними.</strong> Пересказ сообщений правления в дайджесте попадает в часовой и дневной тик с кругом 1.</li>
|
||
<li><strong>Часовой уровень в круге 1 может менять код сам.</strong> Рефлексия 17.10 закоммитила правило вопреки «код не меняй».</li>
|
||
<li><strong>Адресация ошибается на коротких репликах без контекста.</strong> «Выбирай любую.», сказанное боту, фильтр пропустит; выход — «Коди, …» или reply.</li>
|
||
<li><strong>Ученики пока слабые.</strong> <code>addressing</code> на свежих данных совпадает с учителем в 71% и уверен в ~10% случаев; ML-версия <code>task_fit</code> не бьёт базу; <code>depth</code> ещё не обучался.</li>
|
||
<li><strong>Расход токенов часового уровня</strong> — в среднем 46k токенов на вызов, до 205 вызовов инструментов на тик. Лимит 300 оставлен по решению владельца.</li>
|
||
<li><strong>Уровни неделя/месяц/квартал/год</strong> пока не работают; куб сознательно сжат до 4 тиков.</li>
|
||
</ul>
|
||
<p><strong>Дальше:</strong></p>
|
||
<ul>
|
||
<li>☐ Рефлексия и другие задачи «только предложить» — в ограниченном круге, внедрение после «да» владельца.</li>
|
||
<li>☐ Круг приватности для дайджестов — закрыть косвенный канал.</li>
|
||
<li>☐ Команда в боте для смены кругов (только владелец), чтобы не ходить на сервер.</li>
|
||
<li>☐ Решение по ученику адресации по цифрам недельного отчёта.</li>
|
||
<li>☐ Режим on для серой зоны гейта — по статистике shadow.</li>
|
||
<li>☐ Уровни неделя и месяц на основе D3 и дайджестов дня.</li>
|
||
</ul></main></div></body></html>
|