Compare commits
22 Commits
973e59b083
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 4964849397 | |||
| c5eee95460 | |||
| 79adaf928d | |||
| b51657bfe4 | |||
| 48fa29e9dc | |||
| 65a2518a5e | |||
| 84e28c5d1c | |||
| 607a475e28 | |||
| 252e22ec80 | |||
| ac0c41feb8 | |||
| 314b15ea25 | |||
| c310ada38d | |||
| 5c726eb5ec | |||
| d2059b42bd | |||
| 2707ba48b5 | |||
| 9c969cefb9 | |||
| 37f617a461 | |||
| ccac87200f | |||
| b1cc0439a7 | |||
| 3f78c54dd2 | |||
| ddcb552601 | |||
| 74fdbe8070 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -90,3 +90,6 @@ coverage/
|
|||||||
# Missing here made `git status` see `?? .tasks/claims/` → poller skipped every
|
# Missing here made `git status` see `?? .tasks/claims/` → poller skipped every
|
||||||
# claim with "working tree dirty". Mirrors .common/.gitignore.
|
# claim with "working tree dirty". Mirrors .common/.gitignore.
|
||||||
.tasks/claims/
|
.tasks/claims/
|
||||||
|
|
||||||
|
# mappa bootstrap cache (генерируется, не в репо)
|
||||||
|
.mappa/share/
|
||||||
|
|||||||
9
.mappa/config.yaml
Normal file
9
.mappa/config.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# mappa project marker — machine-readable identifier of a mappa project folder
|
||||||
|
schema_version: 1 # версия схемы файла (bump при изменении структуры)
|
||||||
|
protocol_version: 1 # версия протокола интерпретации маркера
|
||||||
|
project: skills
|
||||||
|
tenant: vitya
|
||||||
|
url: https://mappa.vds.kzntsv.site
|
||||||
|
git_provider: gitea
|
||||||
|
git: OpeItcLoc03/skills
|
||||||
|
git_host: git.kzntsv.site
|
||||||
19
AGENTS.md
19
AGENTS.md
@@ -8,8 +8,27 @@ check across all projects
|
|||||||
pull remote before work
|
pull remote before work
|
||||||
session handoff: read on start, write on end
|
session handoff: read on start, write on end
|
||||||
inbox monitor: raise on start
|
inbox monitor: raise on start
|
||||||
|
session sync: write to mappa
|
||||||
follow project discipline
|
follow project discipline
|
||||||
follow tdd-criteria
|
follow tdd-criteria
|
||||||
delegate to interns when allowed
|
delegate to interns when allowed
|
||||||
recommend, don't menu
|
recommend, don't menu
|
||||||
we're on Windows
|
we're on Windows
|
||||||
|
mappa sync: run on start
|
||||||
|
|
||||||
|
<!-- mappa:canon-block (auto; do not edit) -->
|
||||||
|
## Mappa canon
|
||||||
|
**Gates (canon/gates — shared):** краткая суть; полный текст — `wiki_get(slug='canon/gates', full=true)`
|
||||||
|
- Г1. Знание и артефакты → mappa, не файлы — durable-знание и артефакты проекта живут в mappa; файловые каналы (`.brainstorm/`, `.tasks/`, `.wiki/`) и «сохранить рядом с проектом» закрыты.
|
||||||
|
- Г2. Контракт каналов — письмо (inbox) — носитель вердиктов/указаний/находок, полным телом; комментарии на тасках — короткий след. Адресация `about`/`to`/`thread` (XOR); lifecycle `ack`/`resolve`/`cancel`.
|
||||||
|
- Г3. Поиск до угадывания — не угадывать slug/роут: сначала `search`/`wiki_search`; `wiki_get` без project = shared; общая память — `search(mode='recall')`.
|
||||||
|
- Г4. Адресация и слаги — рефы полными именами (`[[task:N]]`/`[[wiki:slug]]`); слаги kebab-case, латиница; номера `task:N` выдаёт сервер.
|
||||||
|
- Г5. .mappa-гейт — папка участвует в mappa-операциях только с маркером `.mappa`; нет маркера → сказать человеку, мутации — отказ.
|
||||||
|
- Г6. Секреты — в mappa не пишутся (422); только `secret:<path>`-рефы, значения мимо.
|
||||||
|
- Г7. Degraded-режим — mappa недоступна: читать кэш `.mappa/` (canon/methodology/runbooks), мутации → `.mappa/pending/`; нет кэша → стоп, не импровизировать.
|
||||||
|
- Г8. Перед работой с вики/каноном — первым действием прочитать канон-блок AGENTS.md проекта.
|
||||||
|
- Г9. Живое состояние до заявления — статус заявлять только по свежему чтению mappa, не по памяти/кэшу/ответу create.
|
||||||
|
**Entity → runbook (runbooks/index — shared):** task → [[runbooks/tasks]] · wiki → [[runbooks/wiki]] · inbox → [[runbooks/inbox]] · **thread** → [[runbooks/threads]] · session → [[runbooks/session]] · search → [[runbooks/search]] · issue → [[runbooks/issue]] · **intent** → [[runbooks/intent]] · requirements → [[runbooks/requirements]] · plan → [[runbooks/plan]] · comment → [[runbooks/comment]] · tag → [[runbooks/tag]] · attachment → [[runbooks/attachment]] · release → [[runbooks/release]] · brainstorm → [[runbooks/brainstorm]] · agent → [[runbooks/agent-operator]] · repo → [[runbooks/repo-commit]] · project → [[runbooks/project]] · skill → [[runbooks/skill]] · entity-слой → [[runbooks/entity]] · sched → [[runbooks/sched-telemetry]]
|
||||||
|
**Methodology:** `methodology/kzntsv`
|
||||||
|
**Canon version:** 4
|
||||||
|
<!-- /mappa:canon-block -->
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ an explicit `adapted-from` marker in its frontmatter.
|
|||||||
| `code-review` | `adapted-from: mattpocock/skills @ 84fdeffd` (MIT) — two-axis + Fowler baseline; output: caveman-review format |
|
| `code-review` | `adapted-from: mattpocock/skills @ 84fdeffd` (MIT) — two-axis + Fowler baseline; output: caveman-review format |
|
||||||
| `writing-skills` | `adapted-from: obra/superpowers @ 6.2.0` (MIT) — TDD-for-skills core + ideya 8 self-skill-authoring |
|
| `writing-skills` | `adapted-from: obra/superpowers @ 6.2.0` (MIT) — TDD-for-skills core + ideya 8 self-skill-authoring |
|
||||||
| `web-search` | `author: ours` — search_web tool (pi-extension) + policy: when to search, «без поиска» session-off |
|
| `web-search` | `author: ours` — search_web tool (pi-extension) + policy: when to search, «без поиска» session-off |
|
||||||
|
| `ops-browser` | `author: ours` — свой **скрытый** браузер агента: отдельный профиль + CDP (`eval`/`fetch` из страницы/скриншоты), `handoff` человеку для пароля/капчи; свой замок `ops.lock` |
|
||||||
|
| `browser-operator` | `author: ours` — браузер ОПЕРАТОРА (его Chrome/логины): канал по харнессу (Hermes `browser_exec` / pi тул `browser` / CC `chrome-devtools`), аренда «один водитель за раз», границы «человек vs агент», рецепты тяжёлых страниц. Закрывает провал базового прогона 2026-09-11 («куки из Chrome + curl + ввод пароля» мимо канала); анонимные прогоны — `browser-cdp` |
|
||||||
| `review-subagent` | `author: ours` — review_subagent tool (pi-extension): clean-context review by your own model, optional `model` override |
|
| `review-subagent` | `author: ours` — review_subagent tool (pi-extension): clean-context review by your own model, optional `model` override |
|
||||||
| `report-mappa-issue` | `author: ours` — TEMPORARY stopgap: mappa deviation reporting (mail to `mappa` + `.workshop`) while the service is unstable; retire when stabilized |
|
| `report-mappa-issue` | `author: ours` — TEMPORARY stopgap: mappa deviation reporting (mail to `mappa` + `.workshop`) while the service is unstable; retire when stabilized |
|
||||||
| all other `skills/*` | `author: ours` |
|
| all other `skills/*` | `author: ours` |
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ bash scripts/build.sh caveman # один
|
|||||||
| `code-search` | `author: ours` — rg-first код-поиск (замер: 15 мин → 0 сек; роутинг: rg / git grep / interns repo_read / grep_audit) |
|
| `code-search` | `author: ours` — rg-first код-поиск (замер: 15 мин → 0 сек; роутинг: rg / git grep / interns repo_read / grep_audit) |
|
||||||
| `code-review` | `adapted-from: mattpocock/skills @ 84fdeffd` (MIT) — двухосевость + Fowler-база; формат вывода: caveman-review |
|
| `code-review` | `adapted-from: mattpocock/skills @ 84fdeffd` (MIT) — двухосевость + Fowler-база; формат вывода: caveman-review |
|
||||||
| `writing-skills` | `adapted-from: obra/superpowers @ 6.2.0` (MIT) — TDD-for-skills ядро + идея 8 self-skill-authoring |
|
| `writing-skills` | `adapted-from: obra/superpowers @ 6.2.0` (MIT) — TDD-for-skills ядро + идея 8 self-skill-authoring |
|
||||||
|
| `ops-browser` | `author: ours` — свой скрытый браузер агента (профиль + CDP + `handoff` человеку, замок `ops.lock`) |
|
||||||
|
| `browser-operator` | `author: ours` — браузер ОПЕРАТОРА (его Chrome/логины): канал по харнессу (Hermes `browser_exec` / pi тул `browser` / CC `chrome-devtools`), аренда «один водитель за раз», границы «человек vs агент»; анонимные прогоны — `browser-cdp` |
|
||||||
| остальные `skills/*` | `author: ours` |
|
| остальные `skills/*` | `author: ours` |
|
||||||
|
|
||||||
Политика адаптации: клон переписывается под наши конвенции (доски `.tasks/`,
|
Политика адаптации: клон переписывается под наши конвенции (доски `.tasks/`,
|
||||||
|
|||||||
BIN
dist/browser-cdp.skill
vendored
BIN
dist/browser-cdp.skill
vendored
Binary file not shown.
BIN
dist/browser-operator.skill
vendored
Normal file
BIN
dist/browser-operator.skill
vendored
Normal file
Binary file not shown.
BIN
dist/ops-browser.skill
vendored
Normal file
BIN
dist/ops-browser.skill
vendored
Normal file
Binary file not shown.
BIN
dist/review-kit-pi-method.skill
vendored
BIN
dist/review-kit-pi-method.skill
vendored
Binary file not shown.
BIN
dist/session-health.skill
vendored
BIN
dist/session-health.skill
vendored
Binary file not shown.
BIN
dist/update-skills.skill
vendored
BIN
dist/update-skills.skill
vendored
Binary file not shown.
BIN
dist/using-markitdown.skill
vendored
BIN
dist/using-markitdown.skill
vendored
Binary file not shown.
@@ -55,6 +55,14 @@ skills:
|
|||||||
mode: auto
|
mode: auto
|
||||||
category: software-development
|
category: software-development
|
||||||
|
|
||||||
|
browser-operator:
|
||||||
|
mode: auto
|
||||||
|
category: software-development
|
||||||
|
|
||||||
|
ops-browser:
|
||||||
|
mode: auto
|
||||||
|
category: software-development
|
||||||
|
|
||||||
using-markitdown:
|
using-markitdown:
|
||||||
mode: auto
|
mode: auto
|
||||||
category: productivity
|
category: productivity
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
---
|
---
|
||||||
name: browser-cdp
|
name: browser-cdp
|
||||||
author: ours
|
author: ours
|
||||||
version: 0.1.0
|
version: 0.1.1
|
||||||
description: >
|
description: >
|
||||||
Веб-автоматизация через минимальные CDP CLI-тулы в bash — вместо playwright-mcp
|
Веб-автоматизация через минимальные CDP CLI-тулы в bash — вместо playwright-mcp
|
||||||
/ Chrome-DevTools-MCP (подход «what if you don't need MCP»). Запуск Chrome с remote
|
/ Chrome-DevTools-MCP (подход «what if you don't need MCP»). Запуск Chrome с remote
|
||||||
debugging, навигация, eval JS, скриншоты. Trigger: «браузер», «скрейпинг», «открой
|
debugging, навигация, eval JS, скриншоты. Trigger: «браузер», «скрейпинг», «открой
|
||||||
страницу», «перейди на», «сделай скриншот», «playwright», «веб-автоматизация»,
|
страницу», «перейди на», «сделай скриншот», «playwright», «веб-автоматизация»,
|
||||||
«web scraping», «browser».
|
«web scraping», «browser». Для ЛИЧНЫХ КАБИНЕТОВ оператора (его логины, антибот) —
|
||||||
|
НЕ этот скил, а `browser-operator`.
|
||||||
---
|
---
|
||||||
|
|
||||||
# browser-cdp
|
# browser-cdp
|
||||||
@@ -20,6 +21,9 @@ description: >
|
|||||||
снять скриншот, собрать данные (скрейпинг). Использовать **вместо** playwright-mcp или
|
снять скриншот, собрать данные (скрейпинг). Использовать **вместо** playwright-mcp или
|
||||||
Chrome-DevTools-MCP.
|
Chrome-DevTools-MCP.
|
||||||
|
|
||||||
|
- ⚠️ **Для личных кабинетов оператора этот путь НЕ годится:** здесь свой Chrome и свой
|
||||||
|
профиль (без его логинов). Нужен браузер оператора — скил `browser-operator`.
|
||||||
|
|
||||||
## Процесс
|
## Процесс
|
||||||
|
|
||||||
1. **Прочитай полную справку** (обязательно, первый шаг):
|
1. **Прочитай полную справку** (обязательно, первый шаг):
|
||||||
|
|||||||
128
skills/browser-operator/SKILL.md
Normal file
128
skills/browser-operator/SKILL.md
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
---
|
||||||
|
name: browser-operator
|
||||||
|
author: ours
|
||||||
|
version: 0.1.0
|
||||||
|
description: >
|
||||||
|
Работа в браузере ОПЕРАТОРА — его Chrome, его профиль, его живые логины: личные
|
||||||
|
кабинеты поставщиков (ЧипДип, ДКО, Промэлектроника, ТМ), Avito, порталы под
|
||||||
|
антиботом. Trigger: «зайди в личный кабинет», «открой ЛК», «собери заказы»,
|
||||||
|
«посмотри в браузере», «нужна его сессия», «ЧипДип/Ozon/Avito», «browser».
|
||||||
|
НЕ для публичных страниц (там сначала обычный fetch/curl) и НЕ для анонимных
|
||||||
|
прогонов (там скил browser-cdp).
|
||||||
|
---
|
||||||
|
|
||||||
|
# Browser operator — браузер оператора
|
||||||
|
|
||||||
|
**Браузер оператора — разделяемый ресурс с его живыми сессиями.** Работай через
|
||||||
|
готовый канал своего харнесса и **только под арендой «один водитель за раз»**.
|
||||||
|
Не вытаскивай его куки, не логинься сам, не поднимай свой Chrome.
|
||||||
|
|
||||||
|
## Когда браузер действительно нужен
|
||||||
|
|
||||||
|
Сначала спроси себя, нужен ли браузер вообще:
|
||||||
|
|
||||||
|
- **Нет** — публичная страница, API, доки: обычный fetch/curl/поиск. Браузер тут лишний.
|
||||||
|
- **Да** — страница требует взаимодействия (клик/форма/навигация), JS-рендер,
|
||||||
|
**его логин** (личный кабинет, Avito), либо портал режет не-браузерный трафик.
|
||||||
|
|
||||||
|
## Канал по харнессу (не изобретай свой)
|
||||||
|
|
||||||
|
| Харнесс | Чем работать | Аренда |
|
||||||
|
|---|---|---|
|
||||||
|
| **Hermes** | тул `browser_exec` (демон `browser-use`, тот же профиль оператора) | автоматически: shell-хук `pre_tool_call` берёт аренду и блокирует вызов при чужой |
|
||||||
|
| **pi** | тул `browser`: `open` / `read` / `js` / `click` / `screenshot` / `lease` | автоматически внутри тула; `lease` покажет, кто держит |
|
||||||
|
| **Claude Code** | MCP `chrome-devtools` (`list_pages`, `navigate_page`, `take_snapshot`, `evaluate_script`, `click`, `fill`, `take_screenshot`) | автоматически: обёртка берёт аренду перед стартом сервера |
|
||||||
|
|
||||||
|
**Никогда:** `curl` с куками из его профиля, `browser_cookie3`-выгрузка куки,
|
||||||
|
свой `chrome --remote-debugging-port` с пустым профилем (там нет его логинов),
|
||||||
|
`pip install`-стек ради одного кабинета.
|
||||||
|
|
||||||
|
## Аренда: «один водитель в браузере за раз»
|
||||||
|
|
||||||
|
Браузер один. Если его держит другой харнесс — **не ломиться**, сказать «занято,
|
||||||
|
держит X» и вернуться позже (или попросить оператора освободить).
|
||||||
|
|
||||||
|
Идёшь в браузер **в обход** тула (например, скриптом или `browser-use` из терминала) —
|
||||||
|
бери аренду сам:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
BL="$HOME/.config/browser-harness/bin/browser-lease.sh"
|
||||||
|
HOLD="manual:$$" # метка держателя
|
||||||
|
MYPID="$(cat /proc/$$/winpid 2>/dev/null || echo 0)" # НАСТОЯЩИЙ windows-PID
|
||||||
|
bash "$BL" acquire --holder "$HOLD" --ttl 900 --pid "$MYPID" --tool browser # 0 = взял, 3 = занято, 2 = ошибка
|
||||||
|
# … работа …
|
||||||
|
bash "$BL" release --holder "$HOLD"
|
||||||
|
```
|
||||||
|
|
||||||
|
**PID — только настоящий.** MSYS `$$` это НЕ windows-PID: по нему живость аренды врёт
|
||||||
|
(мёртвый держатель выглядит живым, живой — мёртвым). В bash бери `/proc/$$/winpid`,
|
||||||
|
в pi/Node — `process.pid`; не знаешь — передай `0` («неизвестен», живость решит TTL).
|
||||||
|
|
||||||
|
**`driver.lock` руками не трогай** (в том числе пустой или «битый» — это окно чужой
|
||||||
|
записи): отбор мёртвой аренды делает CLI по `ts`/TTL/мёртвому PID. Чужую аренду не снимай.
|
||||||
|
|
||||||
|
Контракт аренды (формат файла, TTL, кого связывать): вики mappa
|
||||||
|
`concepts/browser-lease-contract`.
|
||||||
|
|
||||||
|
## Как работать в страницах (рецепты)
|
||||||
|
|
||||||
|
- **Первым делом — своя вкладка.** `ensure_real_tab()` / `new_tab(url)`; не полагайся
|
||||||
|
на активную вкладку оператора: тяжёлая или аудио-страница подвешивает демон
|
||||||
|
(все вызовы падают в таймаут, хотя `browser-use --doctor` говорит «alive»).
|
||||||
|
- **Тяжёлые страницы — читать изнутри, а не обходом.** Если у сайта есть внутренний
|
||||||
|
JSON-эндпоинт, зови его `fetch(path, {credentials:'include'})` из уже открытой
|
||||||
|
страницы: это быстрее и надёжнее десятков навигаций.
|
||||||
|
- **По одной штуке за раз, с паузами.** Паузы — в Python/процессе, **не** в JS `await`
|
||||||
|
(иначе `Runtime.evaluate timed out`). Ориентир оператора: 1 запрос, пауза 7–13 с,
|
||||||
|
перекур каждые ~40, стоп после 3 ошибок подряд.
|
||||||
|
- **Клики:** сначала дерево доступности (`Accessibility.getFullAXTree`) или
|
||||||
|
`querySelector` → центр элемента (`getBoundingClientRect`) → `click_at_xy` → **проверь
|
||||||
|
результат** отдельным `js(...)`/`page_info()`. Не кликай «на глаз» по скриншоту.
|
||||||
|
- **Прогресс — сразу на диск** (jsonl/atomic), а не в конце прогона: длинные обходы
|
||||||
|
обрываются.
|
||||||
|
- **Долгие обходы** — в фоновый процесс, а не в цикл интерактивных вызовов.
|
||||||
|
|
||||||
|
## Границы: где человек, а где агент
|
||||||
|
|
||||||
|
- **Пароли и второй фактор — никогда.** Не вводим и не просим в аргументах командной
|
||||||
|
строки. Уже залогиненная сессия оператора — вот твой доступ.
|
||||||
|
- **Попап «Разрешить удалённую отладку?»** — это человеческое подтверждение: агент его
|
||||||
|
не жмёт, а просит оператора нажать «Разрешить» и повторяет попытку.
|
||||||
|
- **Деньги/платежи/отправка форм с персональными данными** — только с явным
|
||||||
|
подтверждением оператора.
|
||||||
|
- **Секреты и содержимое залогиненных страниц** не пишем в логи, файлы репозитория и
|
||||||
|
вики: в mappa — только агрегаты и идентификаторы.
|
||||||
|
|
||||||
|
## Проверенные адреса и факты
|
||||||
|
|
||||||
|
- **ЧипДип, кабинет заказов:** `https://www.chipdip.ru/order/list`
|
||||||
|
(⚠️ `/cabinet` и `/orders` отдают 404 — не перебирай наугад, ссылка есть в шапке).
|
||||||
|
- Залогиненность видна в шапке кабинета (имя оператора); если видишь форму логина —
|
||||||
|
**сессия потеряна: стоп и скажи оператору**, не логинься сам.
|
||||||
|
- `about:blank`-вкладка с титулом-лошадкой в `document.title` = страницу ведёт агент.
|
||||||
|
|
||||||
|
## Так делать НЕ надо
|
||||||
|
|
||||||
|
| Соблазн | Почему нет |
|
||||||
|
|---|---|
|
||||||
|
| «Вытащу куки из Chrome и пойду `curl`'ом» | мимо канала и мимо аренды; пароль/2FA оказываются рядом; ломается при смене защиты |
|
||||||
|
| «Подниму свой Chrome с отладкой» | там **нет** его логинов → выкинет на логин/капчу, плюс это второй водитель |
|
||||||
|
| «Введу логин/пароль через `read -s`» | пароли и 2FA не вводим никогда |
|
||||||
|
| «Проверю ещё пяток URL кабинета» | адрес подтверждай по ссылке в интерфейсе, а не перебором |
|
||||||
|
| «Налью 20 запросов параллельно, быстрее» | антибот + оператор останавливает такие прогоны; один водитель, одна очередь |
|
||||||
|
|
||||||
|
Основание: базовый прогон без скила (2026-09-11) ушёл именно в «куки + curl + пароль»
|
||||||
|
мимо канала; скил закрывает этот путь.
|
||||||
|
|
||||||
|
## Красные флаги (стоп и перечитай)
|
||||||
|
|
||||||
|
- Собираешься вытащить куки / поднять свой браузер / ввести пароль или код.
|
||||||
|
- Работаешь с браузером **без** аренды (или ломишься, когда «занято»).
|
||||||
|
- Полливаешь запросами без паузы или ждёшь паузу в JS.
|
||||||
|
- Пишешь содержимое залогиненных страниц/секреты в файл, лог или вики.
|
||||||
|
|
||||||
|
## Вне скоупа
|
||||||
|
|
||||||
|
- Анонимные/антидетект-прогоны, свой профиль, `mode: fresh` — скил `browser-cdp`.
|
||||||
|
- Облачные браузеры (Browser Use Cloud и прочие) — не берём.
|
||||||
|
- Свой stdio-MCP-сервер поверх общего демона — отдельная тема.
|
||||||
90
skills/ops-browser/SKILL.md
Normal file
90
skills/ops-browser/SKILL.md
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
---
|
||||||
|
name: ops-browser
|
||||||
|
author: ours
|
||||||
|
version: 0.1.0
|
||||||
|
description: >
|
||||||
|
Use when a task needs a real browser — личный кабинет, заказы, чеки, yt-digest,
|
||||||
|
скриншот живого сайта, «дёрни внутренний API». Свой СКРЫТЫЙ браузер агента:
|
||||||
|
отдельный профиль, CDP, `fetch()` ИЗ страницы, хендофф человеку для пароля/капчи.
|
||||||
|
---
|
||||||
|
|
||||||
|
# ops-browser — свой скрытый браузер агента
|
||||||
|
|
||||||
|
**Есть задача, которой нужен браузер? Работай в своём браузере, скрыто, и не подсовывай куки.**
|
||||||
|
Профиль владеет сессией сам (куки продлеваются браузером, а не руками) — это и есть лечение
|
||||||
|
боли «куки протухли».
|
||||||
|
|
||||||
|
## Когда ЭТОТ инструмент, а когда другой
|
||||||
|
|
||||||
|
| Ситуация | Чем работать |
|
||||||
|
|---|---|
|
||||||
|
| Публичная страница без логина | `web_search` / `web_extract` / curl — браузер не нужен |
|
||||||
|
| Личный кабинет, заказы, чеки, внутренний API сайта, антибот | **`ops-browser.sh`** (этот скил) |
|
||||||
|
| Нужны ЕГО логины и ЕГО Chrome (Avito, кабинеты поставщиков) | канал оператора: Hermes `browser_exec` / pi тул `browser` / CC `chrome-devtools` — всё под арендой `driver.lock` |
|
||||||
|
| Посмотреть глазами, кликнуть по живому сайту, показать ему | панель предпросмотра (`desktop_preview` + `drive_preview`) — без JS, только текст/клики |
|
||||||
|
|
||||||
|
`ops-browser` не заменяет канал оператора: там его сессии, здесь — **мой** профиль.
|
||||||
|
И то и другое живёт под правилом «один водитель» (у ops свой замок `ops.lock`).
|
||||||
|
|
||||||
|
## Команды
|
||||||
|
|
||||||
|
```bash
|
||||||
|
OB="$HOME/.config/browser-harness/bin/ops-browser.sh"
|
||||||
|
bash "$OB" start # headless + аренда (окон нет)
|
||||||
|
bash "$OB" open https://site/path # перейти
|
||||||
|
bash "$OB" read 2000 # видимый текст страницы
|
||||||
|
bash "$OB" eval 'fetch("/api/x",{credentials:"include"}).then(r=>r.json()).then(j=>JSON.stringify(j))'
|
||||||
|
bash "$OB" screenshot [path] # PNG, печатает путь
|
||||||
|
bash "$OB" cookies https://site # имена кук (без значений)
|
||||||
|
bash "$OB" status # аренда + CDP + текущая страница
|
||||||
|
bash "$OB" stop # ШТАТНО закрыть и отпустить
|
||||||
|
bash "$OB" handoff <url> # человеку: пароль/2FA/капча (см. ниже)
|
||||||
|
```
|
||||||
|
|
||||||
|
`eval` выполняет JS **в контексте страницы** — значит `fetch()` идёт с её куками и заголовками:
|
||||||
|
так дёргают внутренние эндпоинты приложения (то, что недоступно извне и чего не умеет панель).
|
||||||
|
|
||||||
|
## Хендофф человеку (пароль, 2FA, капча, согласие)
|
||||||
|
|
||||||
|
Останавливаюсь и отдаю экран **сам**, без «скажи готово»:
|
||||||
|
|
||||||
|
1. `bash "$OB" handoff <url>` — закрывает headless (профиль нельзя открыть дважды) и поднимает
|
||||||
|
**видимое** окно ТОГО ЖЕ профиля на нужной странице;
|
||||||
|
2. человек вводит, что нужно (пароль/2FA/капчу вводит только он);
|
||||||
|
3. признак успеха ловлю сам: URL ушёл со страницы логина/auth **или** выросли куки домена;
|
||||||
|
4. штатно закрываю окно и возвращаюсь в headless — логин остался в профиле.
|
||||||
|
|
||||||
|
Скриншот делаю **до** шага (что от человека хотят) и **после** (что получилось); **во время ввода
|
||||||
|
пароля не снимаю**. Если признак успеха не увидел — окно остаётся открытым, а я говорю об этом прямо.
|
||||||
|
|
||||||
|
## Границы (не двигаются)
|
||||||
|
|
||||||
|
- Пароли, 2FA, капчу — **вводит человек**. Я к ним не подхожу.
|
||||||
|
- Деньги, оформление заказов, формы с перс.данными — только с явного согласия оператора.
|
||||||
|
- Куки не выгружаю и не расшифровываю; содержимое залогиненных страниц не уходит в логи/вику.
|
||||||
|
- Антибот-челленджи не обхожу; если сайт невзлюбил `headless` — это повод для `handoff`, а не для трюков.
|
||||||
|
|
||||||
|
## Грабли (стоили времени, проверены живьём)
|
||||||
|
|
||||||
|
- **Закрывать только штатно** (`stop` → `Browser.close`). Жёсткий kill может не сбросить профиль →
|
||||||
|
потеря логина. Сессионные куки (без срока) перезапуск не переживают по дизайну — настоящие логины живут.
|
||||||
|
- **MSYS-пути**: нативным программам нужен вид `C:/...` (`cygpath -m`), а `powershell -File` —
|
||||||
|
только `C:\...` (`cygpath -w`). Иначе «модуль не найден» / «файл .ps1 не найден».
|
||||||
|
- **Экранирование PowerShell внутри bash-строки тихо ломается** (`$_` подменяется) — PS-запросы
|
||||||
|
держим в отдельных `.ps1`.
|
||||||
|
- **Профиль нельзя открыть дважды** — перед видимым окном headless обязан остановиться (это делает `handoff`).
|
||||||
|
- **Профиль**: `~/.config/browser-harness/profiles/ops`; порт CDP: `OPS_CDP_PORT` (9346).
|
||||||
|
|
||||||
|
## Аренда
|
||||||
|
|
||||||
|
```bash
|
||||||
|
BL="$HOME/.config/browser-harness/bin/browser-lease.sh"
|
||||||
|
bash "$BL" --lock ops status # состояние ops-замка (у Chrome оператора — driver.lock)
|
||||||
|
```
|
||||||
|
|
||||||
|
Чужой держатель `ops.lock` → `start` честно отказывает (rc=1). Мёртвый держатель отпускается по PID/TTL.
|
||||||
|
Идёшь в браузер **сам** (в обход `ops-browser.sh`)? Возьми `ops.lock` так же, как любой другой харнесс.
|
||||||
|
|
||||||
|
Контракт: mappa `concepts/ops-browser-contract` (проект `pi-extensions`),
|
||||||
|
требования `requirements:42`, план `plan:35`. Исходники: репо `pi-extensions/scripts/browser/`
|
||||||
|
(установка `just install-browser`).
|
||||||
@@ -39,7 +39,7 @@ Karpathy / `.tasks/` (см. using-wiki/using-tasks, legacy-раздел).
|
|||||||
| `README.md` | minimal stub | Skipped if file exists. |
|
| `README.md` | minimal stub | Skipped if file exists. |
|
||||||
| вики | mappa (`using-wiki`) | сущности `type=wiki` в сервисе; файловый layout — только вне mappa (легаси). |
|
| вики | mappa (`using-wiki`) | сущности `type=wiki` в сервисе; файловый layout — только вне mappa (легаси). |
|
||||||
| таски | mappa (`using-tasks`) | сущности `type=task` в сервисе; файловый `.tasks/` — только вне mappa (легаси). |
|
| таски | mappa (`using-tasks`) | сущности `type=task` в сервисе; файловый `.tasks/` — только вне mappa (легаси). |
|
||||||
| `AGENTS.md` | `assets/AGENTS.md.template` | **Canon** — skill triggers (`use project wiki`, `use task management system`, etc.). On non-Windows hosts, swap the `we're on Windows` line for `we're on Linux` / `we're on macOS`. On upgrade, the template is treated as a canonical set and merged idempotently — only missing trigger lines are appended after user confirm. Re-runs are no-ops. |
|
| `AGENTS.md` | `assets/AGENTS.md.template` | **Canon** — mappa-agnostic generic triggers (caveman, pull remote before work, tdd, interns, recommend, platform). Mappa-специфичные триггеры (`inbox monitor: raise on start`, `session sync: write to mappa`, `use project wiki`, `use task management system`, `check across all projects`) инжектятся через mappa-bootstrap (Step 5.7.2). On non-Windows hosts, swap the `we're on Windows` line for `we're on Linux` / `we're on macOS`. On upgrade, the template is treated as a canonical set and merged idempotently — only missing generic trigger lines are appended after user confirm. Re-runs are no-ops. |
|
||||||
| `CLAUDE.md` | generated pointer | `Canon is AGENTS.md. Read AGENTS.md.` — legacy pointer for tooling that looks for the old name. |
|
| `CLAUDE.md` | generated pointer | `Canon is AGENTS.md. Read AGENTS.md.` — legacy pointer for tooling that looks for the old name. |
|
||||||
| `.wiki/concepts/bootstrap-manifest.md` | generated | Records which skill versions initialized the project, so cross-project layout drift is debuggable. |
|
| `.wiki/concepts/bootstrap-manifest.md` | generated | Records which skill versions initialized the project, so cross-project layout drift is debuggable. |
|
||||||
|
|
||||||
@@ -102,9 +102,9 @@ target with `CLAUDE_SKILLS_DIR=/path bash scripts/install.sh …`.
|
|||||||
|
|
||||||
- [`using-wiki`](../using-wiki/) — runtime policy for the mappa wiki (v2).
|
- [`using-wiki`](../using-wiki/) — runtime policy for the mappa wiki (v2).
|
||||||
- [`using-tasks`](../using-tasks/) — runtime policy for the mappa task board (v2).
|
- [`using-tasks`](../using-tasks/) — runtime policy for the mappa task board (v2).
|
||||||
- vitya-flavored cross-project discipline (activated per-project by
|
- kzntsv-flavored cross-project discipline (activated per-project by
|
||||||
`mappa-bootstrap`, which selects the methodology flavor) — moved to
|
`mappa-bootstrap`, which selects the methodology flavor) — moved to
|
||||||
`victor/mappa-vitya-skills` (mappa-vitya-project-discipline).
|
`victor/mappa-vitya-skills` (легаси, поглощено монорепо) — mappa-kzntsv-project-discipline.
|
||||||
- [`setup-interns`](../setup-interns/), [`using-interns`](../using-interns/) —
|
- [`setup-interns`](../setup-interns/), [`using-interns`](../using-interns/) —
|
||||||
pair behind the `delegate to interns when allowed` trigger; cheap-LLM
|
pair behind the `delegate to interns when allowed` trigger; cheap-LLM
|
||||||
delegation under a per-session permission grant.
|
delegation under a per-session permission grant.
|
||||||
|
|||||||
@@ -389,9 +389,6 @@ Template contents (`assets/AGENTS.md.template` — source of truth):
|
|||||||
# Agent instructions. Each line is a trigger for an installed skill.
|
# Agent instructions. Each line is a trigger for an installed skill.
|
||||||
|
|
||||||
talk like a caveman
|
talk like a caveman
|
||||||
use project wiki
|
|
||||||
use task management system
|
|
||||||
check across all projects
|
|
||||||
pull remote before work
|
pull remote before work
|
||||||
follow tdd-criteria
|
follow tdd-criteria
|
||||||
delegate to interns when allowed
|
delegate to interns when allowed
|
||||||
@@ -399,10 +396,15 @@ recommend, don't menu
|
|||||||
we're on Windows
|
we're on Windows
|
||||||
```
|
```
|
||||||
|
|
||||||
The `check across all projects` trigger activates the **mappa** tooling
|
Mappa-специфичные триггеры (`check across all projects`, `inbox monitor:
|
||||||
(`mcp__mappa__*`) — cross-project boards, shared wiki and the project
|
raise on start`, `use project wiki`, `use task management system`, `session
|
||||||
registry live in mappa. The file-based `projects-meta-mcp` and its skills
|
sync: write to mappa`) **не в шаблоне** — инжектятся через mappa-bootstrap
|
||||||
(`using-projects-meta`, `setup-projects-meta`, `meta-host-routing`, `setup-wiki`,
|
(Step 5.7.2), project-bootstrap mappa-agnostic. `check across all projects`
|
||||||
|
активирует **mappa** tooling (`mcp__mappa__*`) — cross-project boards, shared
|
||||||
|
wiki и реестр проектов живут в mappa.
|
||||||
|
|
||||||
|
The file-based `projects-meta-mcp` and its skills (`using-projects-meta`,
|
||||||
|
`setup-projects-meta`, `meta-host-routing`, `setup-wiki`,
|
||||||
`setup-tasks`) were removed 2026-08-25; the shared `projects-wiki` files are
|
`setup-tasks`) were removed 2026-08-25; the shared `projects-wiki` files are
|
||||||
stubs «не читать, не править» — канон mappa shared-scope.
|
stubs «не читать, не править» — канон mappa shared-scope.
|
||||||
|
|
||||||
@@ -428,7 +430,7 @@ which lets Claude offload predictable bulk I/O and summarization tasks
|
|||||||
local `interns` MCP server (`mcp__interns__bulk_text_read`,
|
local `interns` MCP server (`mcp__interns__bulk_text_read`,
|
||||||
`mcp__interns__transcript_distill`, etc.) — saves Anthropic quota at ~125× the
|
`mcp__interns__transcript_distill`, etc.) — saves Anthropic quota at ~125× the
|
||||||
per-call cost reduction on bulk reads. Per-session permission grant mirrors the
|
per-call cost reduction on bulk reads. Per-session permission grant mirrors the
|
||||||
`mappa-vitya-project-discipline` Rule 4 (skill moved to `victor/mappa-vitya-skills`): ask-mode default, conversational grant / revoke,
|
`mappa-kzntsv-project-discipline` Rule 4 (skill moved from `victor/mappa-vitya-skills`, легаси, поглощено монорепо): ask-mode default, conversational grant / revoke,
|
||||||
always-ask paths for `.env` / secrets / keys / SSH credentials even with an
|
always-ask paths for `.env` / secrets / keys / SSH credentials even with an
|
||||||
active grant, session-end reset. The skill is a no-op until the `interns` MCP
|
active grant, session-end reset. The skill is a no-op until the `interns` MCP
|
||||||
server is registered — install via `setup-interns` on a fresh machine if
|
server is registered — install via `setup-interns` on a fresh machine if
|
||||||
@@ -516,6 +518,7 @@ Mismatch between template and map → silent gaps in the recommendation.
|
|||||||
| `use project wiki` | `mappa-knowledge` | skill | см. mappa-bootstrap (репо mappa) | `cd <mappa-repo> && bash skills/mappa-bootstrap/assets/install.sh` |
|
| `use project wiki` | `mappa-knowledge` | skill | см. mappa-bootstrap (репо mappa) | `cd <mappa-repo> && bash skills/mappa-bootstrap/assets/install.sh` |
|
||||||
| `use task management system` | `mappa-task-work` | skill | см. mappa-bootstrap (репо mappa) | `cd <mappa-repo> && bash skills/mappa-bootstrap/assets/install.sh` |
|
| `use task management system` | `mappa-task-work` | skill | см. mappa-bootstrap (репо mappa) | `cd <mappa-repo> && bash skills/mappa-bootstrap/assets/install.sh` |
|
||||||
| `inbox monitor: raise on start` | `mappa-session-orient` | skill | см. mappa-bootstrap (репо mappa) | `cd <mappa-repo> && bash skills/mappa-bootstrap/assets/install.sh` |
|
| `inbox monitor: raise on start` | `mappa-session-orient` | skill | см. mappa-bootstrap (репо mappa) | `cd <mappa-repo> && bash skills/mappa-bootstrap/assets/install.sh` |
|
||||||
|
| `session sync: write to mappa` | `mappa-session-orient` | skill | см. mappa-bootstrap (репо mappa) | `cd <mappa-repo> && bash skills/mappa-bootstrap/assets/install.sh` |
|
||||||
| `we're on Windows` / `we're on Linux` / `we're on macOS` | `active-platform` | skill | `~/.claude/skills/active-platform/SKILL.md` | `bash scripts/install.sh active-platform` |
|
| `we're on Windows` / `we're on Linux` / `we're on macOS` | `active-platform` | skill | `~/.claude/skills/active-platform/SKILL.md` | `bash scripts/install.sh active-platform` |
|
||||||
|
|
||||||
### Algorithm
|
### Algorithm
|
||||||
@@ -626,14 +629,22 @@ python -c "import json; d=json.load(open('$HOME/.claude.json')); print('mappa' i
|
|||||||
mappa-конвенции в AGENTS.md (5.7.2) можно добавлять и без MCP-регистрации
|
mappa-конвенции в AGENTS.md (5.7.2) можно добавлять и без MCP-регистрации
|
||||||
— триггеры будут ждать установки сервера (как любой absent-скилл).
|
— триггеры будут ждать установки сервера (как любой absent-скилл).
|
||||||
|
|
||||||
### 5.7.2 — mappa-конвенции в AGENTS.md (idempotent merge)
|
### 5.7.2 — mappa-конвенции в AGENTS.md (инъекция через mappa-bootstrap)
|
||||||
|
|
||||||
mappa-специфичные триггеры уже в каноне шаблона (Step 5) — `inbox monitor:
|
`project-bootstrap` — mappa-agnostic: mappa-триггеры **не хардкодятся** в
|
||||||
raise on start`, `use project wiki`, `use task management system`. Это не
|
шаблоне (см. `assets/AGENTS.md.template`). Инъекция канонического набора
|
||||||
отдельный merge: существующая идемпотентная машинерия Step 5 покрывает их.
|
mappa-триггеров (`inbox monitor: raise on start`, `session sync: write to
|
||||||
Модуль только **верифицирует**: после Step 5 убедиться, что строки на месте
|
mappa`, `use project wiki`, `use task management system`, `check across all
|
||||||
(та же substring-проверка что в Step 5 upgrade-merge). Если пользователь
|
projects`) — через скил `mappa-bootstrap` (репо mappa, единый источник):
|
||||||
сознательно убрал их из AGENTS.md — не возвращать (уважать выбор).
|
|
||||||
|
```bash
|
||||||
|
bash <mappa>/skills-core/mappa-bootstrap/assets/install.sh --triggers <project-dir>
|
||||||
|
```
|
||||||
|
|
||||||
|
После инъекции — **верифицировать** наличие строк (substring-проверка, та же
|
||||||
|
машинерия что Step 5 upgrade-merge). Если пользователь сознательно убрал
|
||||||
|
mappa-триггеры из AGENTS.md — не возвращать (уважать выбор). Источник истины
|
||||||
|
набора — mappa-bootstrap, НЕ шаблон project-bootstrap.
|
||||||
|
|
||||||
### 5.7.3 — методика-install (пакет из репо mappa, версия в манифест)
|
### 5.7.3 — методика-install (пакет из репо mappa, версия в манифест)
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
# AGENTS.md
|
# AGENTS.md
|
||||||
# Agent instructions. Each line is a trigger for an installed skill.
|
# Agent instructions. Each line is a trigger for an installed skill.
|
||||||
#
|
#
|
||||||
# Inter-session mail channel is Mappa (mcp__mappa__inbox_send/inbox_monitor),
|
# mappa-специфичные триггеры (inbox monitor: raise on start, session sync:
|
||||||
# NOT files. This line opts the project into inbox delivery at session start:
|
# write to mappa, use project wiki, use task management system, check across
|
||||||
inbox monitor: raise on start
|
# all projects) НЕ хардкодятся здесь — project-bootstrap mappa-agnostic. Они
|
||||||
|
# инжектятся при создании/апгрейде проекта через mappa-bootstrap:
|
||||||
|
# bash <mappa>/skills-core/mappa-bootstrap/assets/install.sh --triggers <dir>
|
||||||
|
# (см. Step 5.7.2 — mappa-конвенции в AGENTS.md, делегирование в mappa-bootstrap)
|
||||||
|
|
||||||
# Search rule
|
# Search rule
|
||||||
|
|
||||||
@@ -16,11 +19,7 @@ result file names, NOT directory traversal — it still walks every node_modules
|
|||||||
entry; `| grep -v node_modules` filters after the walk, doesn't save you.
|
entry; `| grep -v node_modules` filters after the walk, doesn't save you.
|
||||||
|
|
||||||
talk like a caveman
|
talk like a caveman
|
||||||
use project wiki
|
|
||||||
use task management system
|
|
||||||
check across all projects
|
|
||||||
pull remote before work
|
pull remote before work
|
||||||
session handoff: read on start, write on end
|
|
||||||
follow tdd-criteria
|
follow tdd-criteria
|
||||||
delegate to interns when allowed
|
delegate to interns when allowed
|
||||||
recommend, don't menu
|
recommend, don't menu
|
||||||
|
|||||||
@@ -1,130 +0,0 @@
|
|||||||
---
|
|
||||||
name: project-create
|
|
||||||
author: ours
|
|
||||||
version: 0.3.0
|
|
||||||
description: >
|
|
||||||
Mappa-side cycle of creating a new project: ask the operator for the hosting
|
|
||||||
address (platform + user/org) FIRST — never derive it from neighbouring
|
|
||||||
projects — then pre-flight checks (free in mappa AND in gitea), then ASK the
|
|
||||||
operator HOW to create the repo (via .admin task+letter / server flow
|
|
||||||
projects_create_repo / manual) — the path is the operator's call, never
|
|
||||||
assumed — then create the repo and register in mappa (in the right order,
|
|
||||||
see Hard rule 2026-08-29), then ask where on
|
|
||||||
disk the project folder goes and what it's named, create the folder, write
|
|
||||||
the `.mappa` marker (wiki:3340), and hand over to project-bootstrap (general
|
|
||||||
skill). Triggers (bilingual):
|
|
||||||
«создай проект», «заведи проект», «новый проект», «создать проект на
|
|
||||||
гите», "create a project", "start a new project", "set up a project",
|
|
||||||
«куда разместить проект». NOT repo content/bootstrap (→ project-bootstrap),
|
|
||||||
NOT renaming/re-hosting an existing project.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Project Create (mappa-side)
|
|
||||||
|
|
||||||
The cycle of creating a **new project** from the mappa side. Built live on the
|
|
||||||
tg-digest case (2026-08-27, brainstorm:129): the operator ran the pattern
|
|
||||||
through a real creation, the skill records it. Guarantees that the hosting
|
|
||||||
address is the operator's decision (not the agent's guess), that mappa and
|
|
||||||
gitea stay in sync (created together, not one before the other), and that the
|
|
||||||
operator picks the on-disk location.
|
|
||||||
|
|
||||||
## When to use
|
|
||||||
|
|
||||||
Before any `projects_register` / gitea repo creation for a **new** project.
|
|
||||||
|
|
||||||
**Activates:** «создай проект», «заведи проект», «новый проект», «создать проект на гите», "create a project", "start a new project", "set up a project".
|
|
||||||
|
|
||||||
**Not applicable:**
|
|
||||||
- Repo content / bootstrap (git init, README, AGENTS.md, .wiki, .tasks, remote push) → `project-bootstrap` (general skill; project-create hands over to it).
|
|
||||||
- Re-hosting / renaming an existing project → read what's there first, no creation.
|
|
||||||
- A project that already exists in mappa registry or gitea → verify with the operator, don't create a duplicate.
|
|
||||||
|
|
||||||
## Hard rules
|
|
||||||
|
|
||||||
### Hard rule 1 (original lesson)
|
|
||||||
|
|
||||||
**The hosting address (platform + user/org) is the operator's decision. ASK, never derive.** Do not copy the owner from a neighbouring project (the live failure: `victor/tg-digest` was assumed by analogy with `victor/yt-digest` — wrong, the operator had to correct it). Options to offer: platform (Gitea git.kzntsv.site / GitHub), and for Gitea — the known users/orgs from the registry (e.g. `victor` personal apps, `OpeItcLoc03` infra/meta, `cancel_music` music modules). The registry `mcp__mappa__projects_list` shows the existing `qualified` names — use it to propose options, but the choice is the operator's.
|
|
||||||
|
|
||||||
### Hard rule 2 (2026-08-29, live failure agensyn)
|
|
||||||
|
|
||||||
**The repo-creation PATH is the operator's decision — ASK, never assume the default.** Offer: (a) via `.admin` (task + letter — the legacy canon, secrets live there), (b) server flow `mcp__mappa__projects_create_repo` (creates the repo on the provider AND registers in mappa itself, `source=auto`), (c) manual. The operator overrides the default; delegating to `.admin` before they choose is not revocable (the task lands on the board, `.admin` reacts instantly — the agensyn case).
|
|
||||||
|
|
||||||
**NEVER register the project in mappa (`projects_register`) BEFORE the repo exists.** A pre-existing registry entry makes the server flow `projects_create_repo` return 409 `already registered` (resolveStrict), and there is no delete channel for registry entries. Order that works: operator picks the path → repo is created → registration (the server flow registers itself; the `.admin` path registers AFTER the repo exists, with the known qualified).
|
|
||||||
|
|
||||||
## Steps (the pattern)
|
|
||||||
|
|
||||||
1. **Ask the hosting address.** Platform (Gitea/GitHub) + user/org. One question, offer the registry-derived options, wait for the answer. Do NOT register anything yet.
|
|
||||||
2. **Ask the repo-creation path** (Hard rule 2): via `.admin` / server flow `projects_create_repo` / manual. Do NOT delegate or register yet — this is the operator's call.
|
|
||||||
3. **Pre-flight checks** — can we create:
|
|
||||||
- mappa: the project name is not in the registry (`projects_list` / `projects_resolve`) — and do NOT create it here.
|
|
||||||
- gitea: repo name is free, the user/org exists, we have rights (`.admin` path: `.admin` owns the tokens and checks on its side; server flow: the mappa server holds provider creds).
|
|
||||||
4. **Create the repo + register, per the chosen path:**
|
|
||||||
- **server flow** (`projects_create_repo`) — single call creates the repo AND registers (`source=auto`, `qualified` from the provider response). Nothing else to register.
|
|
||||||
- **via `.admin`** — `task_create` in `.admin` (**priority P0** — it blocks the project chain) + covering letter via `inbox_send` (a task on the board doesn't ping a live session). The repo task is an **ops task → NO paired review** (mappa-delegation: skip review for ops). Acceptance: repo created private, answer letter with clone URLs + which token is needed for push. AFTER the repo exists (qualified known) → `projects_register`.
|
|
||||||
- **manual** — the operator creates the repo themselves; register after they confirm.
|
|
||||||
5. **Ask the operator: where on disk the project folder goes and what it's named** (location AND folder name — both are the operator's call) — do not guess the path or the name.
|
|
||||||
6. **Create the folder** on the agent's local filesystem (the operator's workstation, not a remote host).
|
|
||||||
7. **Write the `.mappa` marker** — see Step 5.5 below. Right after the folder exists, the marker values are known from this cycle; no manual generator run.
|
|
||||||
8. **Hand over to bootstrap** — `project-bootstrap` (general skill) does git init, .gitignore, README, AGENTS.md, remote connect, push. Separate step, after the repo exists.
|
|
||||||
|
|
||||||
## Step 5.5 — `.mappa` маркер (контракт wiki:3340)
|
|
||||||
|
|
||||||
Сразу после создания папки — маркер `.mappa/config.yaml` (гейт mappa-скилов:
|
|
||||||
«без маркера папка не участвует в mappa-операциях», task:1546). Значения уже
|
|
||||||
известны из этого цикла — ручной прогон генератора не нужен (task:1583):
|
|
||||||
|
|
||||||
- `project` — канон (имя папки, выбрано оператором в шаге 5);
|
|
||||||
- `tenant` — `MAPPA_TENANT` (по умолчанию `vitya`);
|
|
||||||
- `url` — `MAPPA_CORE_URL` (без trailing slash);
|
|
||||||
- `git_provider` — платформа из шага 1 (gitea/github/…);
|
|
||||||
- `git` — qualified (owner/repo) из ответа `.admin` / `projects_create_repo` (шаг 4, clone URL).
|
|
||||||
|
|
||||||
Запись — детерминированный рендер по контракту. Канон-скрипт — ассет
|
|
||||||
`project-bootstrap` (в репо: `skills/project-bootstrap/assets/dot_mappa_marker.py`;
|
|
||||||
тот же шаг в bootstrap 5.8 — повторный прогон там no-op):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python <skills-repo>/skills/project-bootstrap/assets/dot_mappa_marker.py write \
|
|
||||||
--project "$FOLDER_NAME" --tenant vitya --url "$MAPPA_CORE_URL" \
|
|
||||||
--git-provider gitea --git "$OWNER/$REPO" --dir "$FOLDER_PATH"
|
|
||||||
```
|
|
||||||
|
|
||||||
Верифицировать: `python .../dot_mappa_marker.py check --dir "$FOLDER_PATH"`
|
|
||||||
→ exit 0. Маркер без секретов, коммитится. Если project-bootstrap не
|
|
||||||
установлен — маркер всё равно появится на хэндовере (шаг 8 → bootstrap 5.8).
|
|
||||||
|
|
||||||
## Why the repo usually goes through `.admin` (and when it doesn't)
|
|
||||||
|
|
||||||
Gitea tokens are secrets — they live only with `.admin` (zone rule: secrets stay out of other agents). Precedent: yt-digest (inbox:2305) and tg-digest (inbox:2463) — `.admin` creates the repo via `POST /user/repos` → transfer to the target owner (the admin endpoint refuses without write:admin), then answers with the clone URLs and the push token (`pass show gitea/admin-token` for OpeItcLoc03, or a user token with repo:write for the target owner).
|
|
||||||
|
|
||||||
**The alternative:** `projects_create_repo` (task:1542) — the mappa server holds provider creds and creates the repo itself, registering the project in the same call. The operator chooses which path; do not hard-default to `.admin` (Hard rule 2, agensyn 2026-08-29).
|
|
||||||
|
|
||||||
## Failure modes
|
|
||||||
|
|
||||||
- The operator hasn't chosen the address → abort, don't create. The address is the operator's call.
|
|
||||||
- The operator hasn't chosen the repo-creation path → ask, don't default to `.admin` (Hard rule 2).
|
|
||||||
- mappa name taken → suggest a rename, don't overwrite.
|
|
||||||
- gitea name taken / user missing → report, suggest a rename.
|
|
||||||
- `projects_create_repo` → 409 `already registered` → you registered before the repo (Hard rule 2) — there is no delete channel; report to the operator, don't work around it by hand.
|
|
||||||
- `.admin` repo task failed → report, don't register the project alone (mappa and gitea are created as a pair).
|
|
||||||
- `task_create` in `.admin` → 422 secret-detected on the token scope string (`write:repository` is flagged) → rephrase ("токен с правами на запись в репозиторий"), don't include raw token strings.
|
|
||||||
- The operator answers the on-disk path only after the repo is created → that's the normal order, fine.
|
|
||||||
|
|
||||||
## What NOT to do
|
|
||||||
|
|
||||||
- Don't assume the hosting owner from a neighbouring project — ask (Hard rule 1).
|
|
||||||
- Don't assume the repo-creation path — ask (Hard rule 2); a `.admin` delegation already sent is not revocable.
|
|
||||||
- Don't register the project in mappa before the repo exists (breaks the server flow with 409; no delete channel).
|
|
||||||
- Don't create mappa registration alone without the repo (they're a pair).
|
|
||||||
- Don't create the repo alone without the mappa registration.
|
|
||||||
- Don't create the on-disk folder in a guessed location — ask.
|
|
||||||
- Don't do the bootstrap inside this skill — that's `project-bootstrap`.
|
|
||||||
- Don't create a paired review for the `.admin` repo task (ops task).
|
|
||||||
- Don't skip the covering letter to `.admin` (task + letter, not just task).
|
|
||||||
|
|
||||||
## Reference
|
|
||||||
|
|
||||||
- Mappa registry: `mcp__mappa__projects_list` / `projects_register` / `projects_resolve`.
|
|
||||||
- Repo creation: `.admin` (task + letter, mappa-delegation canon; ops → no review).
|
|
||||||
- Bootstrap: `project-bootstrap` (general skill).
|
|
||||||
- Live case: brainstorm:129 (tg-digest, .workshop) — the whole pattern was built there.
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: review-kit-pi-method
|
name: review-kit-pi-method
|
||||||
author: ours
|
author: ours
|
||||||
version: 0.1.1
|
version: 0.1.2
|
||||||
description: >
|
description: >
|
||||||
Spawn clean-context non-implementer subagents for review, trigger-testing,
|
Spawn clean-context non-implementer subagents for review, trigger-testing,
|
||||||
and spec validation under pi — the pi-native port of the review-kit method.
|
and spec validation under pi — the pi-native port of the review-kit method.
|
||||||
@@ -124,6 +124,26 @@ non-implementer subagents, anti-priming checklist, negative controls — is
|
|||||||
agent-agnostic and transfers to any runtime that can spawn a fresh-context
|
agent-agnostic and transfers to any runtime that can spawn a fresh-context
|
||||||
subprocess (claude `-p`, codex exec, hermes headless).
|
subprocess (claude `-p`, codex exec, hermes headless).
|
||||||
|
|
||||||
|
### CC-спавн (claude-code через deepseek) — live-проверен 2026-09-01 (session:974)
|
||||||
|
|
||||||
|
CC (`claude -p`) умеет субагент-ревью БЕЗ скилов: тот же чистый контекст
|
||||||
|
(флаги изоляции) через обёртку `claude-deepseek`
|
||||||
|
(`.common/scripts/claude-switch.ps1`; env `ANTHROPIC_BASE_URL=
|
||||||
|
https://api.deepseek.com/anthropic` + ключ из `~/.deepseek_api_key`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude -p "<question>" \
|
||||||
|
--output-format stream-json --verbose \
|
||||||
|
--model deepseek-v4-flash-vision-exp \
|
||||||
|
--tools "" --disable-slash-commands --no-session-persistence
|
||||||
|
```
|
||||||
|
|
||||||
|
Флаги изоляции (аналог `-nc -ns -nt` pi): `--tools ""` (нет тулов —
|
||||||
|
не читает файлы, не самопраймится), `--disable-slash-commands` (нет
|
||||||
|
команд-интерпретатора), `--no-session-persistence` (эфемерно, без
|
||||||
|
сессионного блода). Анти-прайминг-чеклист и правила промпта — те же, что
|
||||||
|
выше (ask the behavior, one question per run, negative controls).
|
||||||
|
|
||||||
## Out of scope
|
## Out of scope
|
||||||
|
|
||||||
- Does NOT define the review criteria themselves (skill-specific acceptance —
|
- Does NOT define the review criteria themselves (skill-specific acceptance —
|
||||||
|
|||||||
Reference in New Issue
Block a user