diff --git a/README.md b/README.md index cce5564..a1fad90 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ curl -fsSL https://git.codelab.vc/ai/pi-kit/raw/branch/stable/install.sh | bash ``` Скрипт проверит `git` и Node.js (>= 20) — оба обязательны: git нужен для `pi install git:...`, -Node для Pi. Затем поставит Pi (если нет), установит этот пакет, **спросит твой профиль**, поставит -нужные скилы и **интерактивно настроит окружение** (`TRACKER_URL`, `CONFLUENCE_URL`, +Node для Pi. Затем поставит Pi (если нет), установит этот пакет, **спросит один или несколько твоих профилей**, +поставит нужные скилы (их наборы объединяются) и **интерактивно настроит окружение** (`TRACKER_URL`, `CONFLUENCE_URL`, `JIRA_TOKEN`, `CONFLUENCE_TOKEN`, `GITLAB_TOKEN`, ключ LLM-провайдера). Секреты вводятся скрыто и сохраняются в `~/.config/pi-kit/env.sh` (`chmod 600`), который подключается из твоего `~/.zshrc`/`~/.bashrc`. @@ -30,12 +30,16 @@ Pi провайдер-агностичен — модель/провайдера Пропустить интерактивную настройку окружения: `PI_KIT_SETUP_ENV=0`. Значения потом можно поменять прямо в `~/.config/pi-kit/env.sh` или перезапустив `./install.sh`. -Профиль можно задать заранее (для CI/неинтерактивной установки): +Профили можно задать заранее (для CI/неинтерактивной установки) — через запятую: ```bash -PI_KIT_PROFILE=backend curl -fsSL https://git.codelab.vc/ai/pi-kit/raw/branch/stable/install.sh | bash +PI_KIT_PROFILE=backend,qa curl -fsSL https://git.codelab.vc/ai/pi-kit/raw/branch/stable/install.sh | bash ``` +Один профиль тоже подходит: `PI_KIT_PROFILE=backend`. Скилы выбранных профилей +**объединяются** (дубли убираются), а `jira-workflow`/`repo-map`/`docs-map` и общие +публичные скилы ставятся всегда. + ### Профили и скилы Общее для всех: команды `/bugfix /feature /review /rfc /kit-config /kit-doctor /kit-help`, @@ -54,7 +58,8 @@ guardrails, скиллы `jira-workflow`, `confluence`, `repo-map`, `docs-map`, сжатой постановки задачи до структурированной, пригодной для передачи в разработку) без языковых стандартов кода. -Сменить профиль позже: `PI_KIT_PROFILE=frontend ./install.sh` (или перезапусти установку). +Сменить/добавить профиль позже: `PI_KIT_PROFILE=frontend,qa ./install.sh` (или перезапусти установку +и выбери несколько). Уже установленные наборы скилов можно дополнить, указав нужные профили ещё раз. Либо вручную (канал `stable` по умолчанию): @@ -208,17 +213,19 @@ pi-kit/ ### Профили и гейтинг скилов -`install.sh` спрашивает профиль (или берёт `PI_KIT_PROFILE`) и делает две вещи: +`install.sh` спрашивает один или несколько профилей (или берёт `PI_KIT_PROFILE`) и делает две вещи: 1. **Гейтит наши скилы** — переписывает запись пакета в `~/.pi/agent/settings.json` в object-форму `{"source": "...", "skills": ["skills/go-standards", ...]}`, чтобы грузились - только скилы профиля. Prompts и расширения не гейтятся (их ключи опущены → грузятся все). + только скилы выбранных профилей. Prompts и расширения не гейтятся (их ключи опущены → грузятся все). 2. **Ставит публичные скилы** через `npx skills add --skill --global` в `~/.agents/skills/` (Pi читает эту папку). Чужой код в наш репо не вендорится. -Чтобы поменять маппинг профиль→скилы — правь блок `case "$PROFILE"` и `COMMON_PUBLIC_SKILLS` -в `install.sh`. Языковой скилл добавляется как обычный (см. ниже) и подключается к нужному -профилю в этом `case`. Профили: `frontend`, `backend`, `qa`, `mobile`, `pm`. +Наборы скилов нескольких профилей объединяются (путь `frontend+qa` даст и `typescript` +и `python` стандарты). Чтобы поменять маппинг профиль→скилы — правь функцию `profile_skills()` +и `COMMON_PUBLIC_SKILLS` в `install.sh`. Языковой скилл добавляется как обычный (см. ниже) +и подключается к нужному профилю в этой функции. Профили: `frontend`, `backend`, `qa`, +`mobile`, `pm` — любые сочетаются между собой. ### Как добавить шаблон-команду diff --git a/install.sh b/install.sh index 57288ed..315b867 100755 --- a/install.sh +++ b/install.sh @@ -7,9 +7,8 @@ # # or, from a checkout: # ./install.sh # -# Profile selection: -# Interactive by default (prompts via /dev/tty, so it works under curl | bash). -# Non-interactive: set PI_KIT_PROFILE=frontend|backend|qa|mobile before running. +# Profile selection (multiple allowed, merged): +# Non-interactive: set PI_KIT_PROFILE=frontend or PI_KIT_PROFILE=frontend,qa before running. # set -euo pipefail @@ -80,70 +79,132 @@ info "Устанавливаю корпоративный пакет: ${PI_KIT_R pi install "$PI_KIT_REPO" info "Пакет установлен. Обновляться потом: pi update --extensions" -# --- 4. Resolve profile ----------------------------------------------------- -# Precedence: PI_KIT_PROFILE env > interactive prompt > "all" (no gating). -PROFILE="${PI_KIT_PROFILE:-}" -case "$PROFILE" in - frontend | backend | qa | mobile | pm) ;; # valid, keep - "") # ask if we have a terminal, even under `curl | bash` (read from /dev/tty) - if [ -r /dev/tty ]; then - { - printf 'Выбери профиль:\n' - printf ' 1) frontend — TS/UI\n' - printf ' 2) backend — Go/Rust/Python\n' - printf ' 3) qa — тестирование\n' - printf ' 4) mobile — Android/iOS\n' - printf ' 5) pm — постановка задач продакт-менеджера\n' - printf 'Номер или имя [1-5]: ' - } >/dev/tty - read -r ans interactive prompt. +# Env is comma- or space-separated: PI_KIT_PROFILE="backend,qa" (a single +# value like `backend` still works). Empty env + no tty => all profiles. + +profile_name() { # -> canonical profile name, or empty if unknown + case "$1" in + 1 | frontend) echo frontend ;; + 2 | backend) echo backend ;; + 3 | qa) echo qa ;; + 4 | mobile) echo mobile ;; + 5 | pm) echo pm ;; + esac +} + +is_profile() { # — 0 if it's a known profile name/number + [ -n "$(profile_name "$1")" ] +} + +# Parse a comma/space separated selection into the PROFILES array (deduplicated). +# Unknown tokens are dropped with a warning. +profiles_from_text() { # + local raw="$1" arr p name + PROFILES=() + IFS=', ' read -r -a arr <<<"$raw" + for p in "${arr[@]}"; do + [ -z "$p" ] && continue + if is_profile "$p"; then + name="$(profile_name "$p")" + case " ${PROFILES[*]} " in + *" $name "*) ;; # duplicate token/alias — already present + *) PROFILES+=("$name") ;; esac else - PROFILE=all + warn "Неизвестный профиль/номер '${p}' — пропущен." fi - ;; - *) - warn "Неизвестный PI_KIT_PROFILE='${PROFILE}', использую 'all' (без гейтинга скилов)." - PROFILE=all - ;; -esac -info "Профиль: ${PROFILE}" + done +} -# Bundled language skills per profile. Common skills (jira-workflow/repo-map/ -# docs-map) are always enabled. Prompts and guardrail extensions are never gated. -COMMON_BUNDLED="jira-workflow repo-map docs-map" -# Extra bundled skills beyond language standards, added per profile (e.g. product/PM tooling). +all_profiles() { PROFILES=(frontend backend qa mobile pm); } + +PROFILES=() +if [ -n "${PI_KIT_PROFILE:-}" ]; then + profiles_from_text "$PI_KIT_PROFILE" + if [ "${#PROFILES[@]}" -eq 0 ]; then + warn "В PI_KIT_PROFILE нет распознанных профилей — ставлю все." + all_profiles + fi +elif [ -r /dev/tty ]; then + # ask if we have a terminal, even under `curl | bash` (read from /dev/tty) + { + printf 'Выбери один или несколько профилей (через пробел или запятую):\n' + printf ' frontend — TS/UI\n' + printf ' backend — Go/Rust/Python\n' + printf ' qa — тестирование\n' + printf ' mobile — Android/iOS\n' + printf ' pm — постановка задач продакт-менеджера\n' + printf 'Пример: backend qa | frontend,pm: ' + } >/dev/tty + read -r ans + local var="$1" w cur all new + cur="${!var}" + shift + all="$*" + new="" + for w in $all; do + case " $cur " in + *" $w "*) ;; # already present + *) new="$new $w" ;; + esac + done + [ -n "$new" ] && printf -v "$var" '%s%s' "$cur" "$new" +} + +# Accumulate the skill sets of one selected profile. +profile_skills() { # + case "$1" in + frontend) + add_word LANG_BUNDLED "typescript-standards" + PROFILE_PUBLIC+=("anthropics/skills:frontend-design") + ;; + backend) + add_word LANG_BUNDLED "go-standards rust-standards python-standards" + ;; + qa) # TODO: уточнить стек тестировщиков; по умолчанию — Python и TS (автотесты) + add_word LANG_BUNDLED "python-standards typescript-standards" + ;; + mobile) # Android (Kotlin) + iOS (Swift) + add_word LANG_BUNDLED "kotlin-standards swift-standards" + ;; + pm) # Продакт-менеджер: постановка задач, без языковых стандартов кода + add_word EXTRA_BUNDLED "pm-task-spec" + ;; + esac +} + +for p in "${PROFILES[@]}"; do + profile_skills "$p" +done +LANG_BUNDLED="$(printf '%s' "$LANG_BUNDLED" | sed 's/^ *//;s/ *$//')" +info "Профили: ${PROFILES[*]}" # --- 5. Gate bundled skills via settings object-form filter ----------------- # Rewrites the pi-kit package entry in settings.json to {source, skills:[...]} @@ -176,12 +237,8 @@ console.log(patched ? "gated bundled skills -> " + allowed.join(", ") : "pi-kit NODE } -if [ "$PROFILE" = "all" ]; then - info "Профиль 'all' — оставляю все скилы пакета без гейтинга." -else - info "Гейчу скилы пакета под профиль '${PROFILE}'..." - gate_bundled_skills "${COMMON_BUNDLED} ${LANG_BUNDLED} ${EXTRA_BUNDLED}" || warn "не удалось отфильтровать скилы (см. выше)." -fi +info "Гейчу скилы пакета под профили '${PROFILES[*]}'..." +gate_bundled_skills "${COMMON_BUNDLED} ${LANG_BUNDLED} ${EXTRA_BUNDLED}" || warn "не удалось отфильтровать скилы (см. выше)." # --- 6. Install public skills ---------------------------------------------- # Uses the skills.sh CLI (`npx skills add`). Failures are non-fatal. @@ -200,7 +257,7 @@ for entry in "${COMMON_PUBLIC_SKILLS[@]}"; do add_public_skill "${entry%%:*}" "${entry##*:}" done if [ "${#PROFILE_PUBLIC[@]}" -gt 0 ]; then - info "Ставлю публичные скилы профиля '${PROFILE}'..." + info "Ставлю публичные скилы профилей '${PROFILES[*]}'..." for entry in "${PROFILE_PUBLIC[@]}"; do add_public_skill "${entry%%:*}" "${entry##*:}" done @@ -379,13 +436,13 @@ fi cat < /feature <тикет> /review [фокус] /rfc <тема> /kit-config /kit-doctor /kit-help diff --git a/skills/pm-task-spec/SKILL.md b/skills/pm-task-spec/SKILL.md new file mode 100644 index 0000000..c665931 --- /dev/null +++ b/skills/pm-task-spec/SKILL.md @@ -0,0 +1,100 @@ +--- +name: pm-task-spec +description: Используй, когда продакт-менеджер приносит сжатую/неполную постановку задачи и нужно её довести до ясной, непротиворечивой формулировки, пригодной для передачи в разработку. Скилл дополнительно подходит для профиля продукт-менеджера (pm): он опрашивает по ключевым доменам постановки, находит слабые места и выдаёт готовую структурированную постановку задачи. +--- + +# Постановка задачи (для продакт-менеджера) + +Скилл помогает продакт-менеджеру (ПМ) превратить сжатую или неполную постановку задачи в +**готовую структурированную постановку**, в которой нет противоречий и все ключевые моменты +понятны и ясны перед передачей в разработку. + +## Принцип работы + +1. Принимаешь исходный текст постановки от ПМ (он может быть очень коротким). +2. Анализируешь её **адаптивно** — без жёсткого зачитывания фиксированного чек-листа: + определяешь, каких из ключевых доменов не хватает или где есть неоднозначность/противоречие. +3. Задаёшь **точечные уточняющие вопросы** только по найденным слабым местам, простым языком, + объясняя термины (ПМ может быть не техническим). +4. **Не завершаешь опрос, пока каждый ключевой домен постановки не прояснён до однозначного + текста.** Непрояснённые/спорные пункты не замалчиваешь — выносишь в раздел «Открытые вопросы». +5. В конце выдаёшь **готовую постановку** готовым markdown-шаблоном, который ПМ копирует + в нужное место (Jira-тикет, wiki, описание в MR). Никакого автосоздания карточек. + +## Ключевые домены постановки + +Проходишь по ним, но вопрос задаёшь, только если домен пуст, неоднозначен или противоречит +другим уже данным ответам: + +- **Суть / заголовок** — одна фраза, что делаем и зачем. +- **Контекст и бизнес-цель** — какую проблему/метрику закрываем, почему сейчас. +- **Пользователи / аудитория** — для кого, сегменты. +- **Сценарии и шаги** — основной сценарий + ключевые вариации (happy path и отступления). +- **Границы scope** — что входит, что явно НЕ входит. +- **Критерии приёмки** — как понять, что задача сделана и работает. +- **Риски и зависимости** — от чего зависит, что может пойти не так. +- **Открытые вопросы** — то, что осталось неопределённым на момент выдачи. + +## Правила ведения опроса + +- Говори просто и по делу. Если используешь термин, сразу объясни его другим словом. +- Один вопрос за раз, маленькими порциями. Не заваливай ПМ списком из десятка пунктов. +- Если ответ противоречит уже сказанному — укажи на противоречие и попроси подсказать, + какой вариант верный (не решай за ПМ). +- Если ПМ не знает техническую деталь — не додумывай, а отметь это в открытых вопросах + (техрешения по реализации оставь разработчикам — это вне scope скилла). +- Будь настойчивым, но доброжелательным: цель — закрыть пробелы, а не выпустить сырой текст. + +## Шаблон итоговой постановки + +В конце выдай маркдаун-шаблон. Для каждого раздела проставляй значение из ответов ПМ; +если что-то осталось неопределённым — честно помечай `не определено` и добавляй в «Открытые +вопросы» с пояснением, что стоит уточнить. + +```markdown +## Постановка задачи + +### 1. Суть / заголовок +<одна фраза: что делаем и для чего> + +### 2. Контекст и бизнес-цель +- Проблема: <что не так сегодня> +- Цель/метрика: <что должно измениться, на чём меряем успех> +- Почему сейчас: <предпосылки/драйвер> + +### 3. Пользователи / аудитория +<кто, сегменты> + +### 4. Сценарии и шаги +- Основной сценарий: <шаг за шагом> +- Вариации / отступления: <ключевые edge-случаи> + +### 5. Границы scope +- Входит: <...> +- Не входит: <явные исключения> + +### 6. Критерии приёмки +<как понять, что задача решена; желательно проверяемо> + +### 7. Риски и зависимости +<от чего зависит, что может пойти не так> + +### 8. Открытые вопросы +<пункты, которые осталось уточнить; пометь, кому адресован> +``` + +## Non-goals + +Этот скилл — **организатор постановки**, а не техконсультант-исполнитель. Он: + +- **не** консультирует по архитектуре/реализации в Go и других языках; +- **не** оценивает трудозатраты и сроки; +- **не** создаёт/обновляет/таскает Jira-тикеты автоматически; +- **не** заменяет прямое обсуждение ПМ с разработчиками — наоборот, готовит материал + для такого обсуждения. + +## Интеграция + +Контекст — наша компания: трекер **Jira** (см. скилл `jira-workflow`), git-хост +**gitlab.tech.mvideo.ru** (см. `repo-map`), документация **wiki.mvideo.ru** (см. `docs-map`). +Скилл автономен: выдаёт готовый текст постановки, ПМ сам переносит его в нужное место.