Compare commits
8 Commits
314b15ea25
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 79adaf928d | |||
| b51657bfe4 | |||
| 48fa29e9dc | |||
| 65a2518a5e | |||
| 84e28c5d1c | |||
| 607a475e28 | |||
| 252e22ec80 | |||
| ac0c41feb8 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -90,3 +90,6 @@ coverage/
|
||||
# Missing here made `git status` see `?? .tasks/claims/` → poller skipped every
|
||||
# claim with "working tree dirty". Mirrors .common/.gitignore.
|
||||
.tasks/claims/
|
||||
|
||||
# mappa bootstrap cache (генерируется, не в репо)
|
||||
.mappa/share/
|
||||
|
||||
19
AGENTS.md
19
AGENTS.md
@@ -8,10 +8,27 @@ check across all projects
|
||||
pull remote before work
|
||||
session handoff: read on start, write on end
|
||||
inbox monitor: raise on start
|
||||
session sync: write to mappa
|
||||
follow project discipline
|
||||
follow tdd-criteria
|
||||
delegate to interns when allowed
|
||||
recommend, don't menu
|
||||
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,7 @@ an explicit `adapted-from` marker in its frontmatter.
|
||||
| `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 |
|
||||
| `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 |
|
||||
| `report-mappa-issue` | `author: ours` — TEMPORARY stopgap: mappa deviation reporting (mail to `mappa` + `.workshop`) while the service is unstable; retire when stabilized |
|
||||
|
||||
@@ -91,6 +91,7 @@ bash scripts/build.sh caveman # один
|
||||
| `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 |
|
||||
| `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` |
|
||||
|
||||
|
||||
BIN
dist/browser-operator.skill
vendored
BIN
dist/browser-operator.skill
vendored
Binary file not shown.
BIN
dist/ops-browser.skill
vendored
Normal file
BIN
dist/ops-browser.skill
vendored
Normal file
Binary file not shown.
@@ -59,6 +59,10 @@ skills:
|
||||
mode: auto
|
||||
category: software-development
|
||||
|
||||
ops-browser:
|
||||
mode: auto
|
||||
category: software-development
|
||||
|
||||
using-markitdown:
|
||||
mode: auto
|
||||
category: productivity
|
||||
|
||||
@@ -47,11 +47,20 @@ description: >
|
||||
|
||||
```bash
|
||||
BL="$HOME/.config/browser-harness/bin/browser-lease.sh"
|
||||
bash "$BL" acquire --holder "pi:$$" --ttl 900 --pid $$ --tool browser # 0 = взял, 3 = занято, 2 = ошибка
|
||||
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 "pi:$$"
|
||||
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`.
|
||||
|
||||
|
||||
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`).
|
||||
Reference in New Issue
Block a user