# Плагин `kompas`, канал поставки и CI

Перенесено из `CLAUDE.md`: нужно при выпуске релиза и правке CI, а не в каждой сессии.
Файл лежит в навыке (`.claude/skills/kompas-mcp-dev/`), а **не** в `plugin/CLAUDE.md`, потому что
`plugin/` распространяется пользователям — внутренняя кухня релиза туда попадать не должна.

## Claude Code plugin (`plugin/`)

The server and both published skills ship as the plugin **`kompas`** — `plugin/` is a self-contained tree,
distributed independently of the rest of the repo.

- `plugin/.claude-plugin/plugin.json` — manifest: `name: "kompas"`, `version` (currently `0.0.0`).
  Version is Claude Code's cache key — `/plugin update` and auto-update skip a plugin whose version
  matches what's installed, so **every release must bump it**.
- `plugin/server.lock.json` — pins exactly one server version: `{version, sourceSha, url, sha256}`.
  `0.0.0` with empty fields = no release published yet.
- `plugin/skills/{kompas-3d,kompas-fdm-design}/` — the source of truth for both published skills.
- `plugin/commands/doctor.md` — `/kompas:doctor`: compares the expected version (from the lock) against
  the `KOMPAS_MCP_EXE` override / `install.json` marker / `kompas-mcp.exe --version`, checks whether
  КОМПАС is installed and running, then `kompas_connect` → `kompas_status`.
- `plugin/.mcp.json` — declares the `kompas` MCP server as
  `powershell -File ${CLAUDE_PLUGIN_ROOT}/scripts/launch-kompas-mcp.ps1`.
- `plugin/scripts/KompasMcpBootstrap.psm1` — delivery: `Read-KompasMcpLock` / `Test-KompasMcpInstall` /
  `Install-KompasMcpServer` / `Resolve-KompasMcpExecutable`. Downloads the release asset, verifies SHA256,
  unpacks under `%LOCALAPPDATA%\kompas-mcp\.tmp` and atomically moves it to
  `%LOCALAPPDATA%\kompas-mcp\<version>`, writes an `install.json` marker. An install is trusted only when
  the marker's `version`/`sha256` match the lock.
- `plugin/scripts/launch-kompas-mcp.ps1` — entry point: the `KOMPAS_MCP_EXE` env var wins (dev mode),
  otherwise deliver per the lock; runs the server and forwards its exit code. Invariant: **not a single
  byte reaches stdout before the server starts** (stdout is the JSON-RPC channel) — all diagnostics go to
  stderr prefixed `kompas-mcp launcher:`.
- `plugin/README.md` — prerequisites and install; `plugin/adapters/{codex,opencode}/` — config snippets
  (not separate distributions) wiring the same launcher into Codex and opencode.
- CLI flag `--version` (`Core/Startup/CliArguments.IsVersionRequest`, early-exit in `Program.cs` before
  the host and any КОМПАС contact) — prints the 3-part assembly version; `/kompas:doctor` uses it to
  cross-check the installed binary against the lock.

**Gotchas:**
- **Plugin PowerShell files must be UTF-8 *with BOM*.** The launcher runs under `powershell` (Windows
  PowerShell 5.1), which reads BOM-less files in the system ANSI codepage — Cyrillic string literals then
  corrupt parsing of the whole script. `pwsh` 7 doesn't reproduce this (BOM auto-detected either way).
- Switching branch/commit across a `plugin/skills` boundary can dangle the skill junctions mid-checkout —
  same failure mode and fix as in `CLAUDE.md` §«Skills and their layout».

## Distribution channel — the `dist` branch, not `main`

Releases (`.gitea/workflows/release.yml`, tag `vX.Y.Z`): `dotnet publish -r win-x64 --self-contained` →
zip → idempotent upsert of a Gitea release + asset via the Gitea API → re-verify the downloaded asset's
SHA256 → commit updated `server.lock.json`/`plugin.json` to branch **`dist`**, on top of the tagged commit.
A private plugin marketplace (`home-repo-cc`) will reference the plugin via a `git-subdir` source pinned to
`ref: dist` — **not added yet**, and there is **no release yet**. Rationale: a release is built from the
tagged commit; if the marketplace pointed at `main`, a user could get a newer `plugin/` tree under a
version whose binary was built from an older commit.

`.gitea/workflows/ci.yml` runs on push/PR to `main`: `plugin.json`↔`server.lock.json` consistency check
(jq), build, then unit tests filtered `Category=Unit&Requires!=Windows` (245 of the 250). Runner:
`gitea-runner` (docker executor, label `ubuntu-latest`).

CI gotchas:
- **SDK 8 doesn't understand the `.slnx` solution format** (`MSBUILD : error MSB1003`) — CI builds and
  tests explicit project paths (`src/Kompas.Mcp.Host/Kompas.Mcp.Host.csproj`,
  `tests/Kompas.Mcp.Tests/Kompas.Mcp.Tests.csproj`) instead of the solution. Not reproducible locally with SDK 9+.
- **`net8.0-windows` builds and runs unit tests fine on the Linux runner** with
  `-p:EnableWindowsTargeting=true`. ASCON interop DLLs link as ordinary references; `ole32`/`oleaut32` are
  only needed at COM runtime, not build time. The 5 `DispatcherTests` are tagged
  `[Trait("Requires", "Windows")]` and excluded — `Thread.SetApartmentState(STA)` throws
  `PlatformNotSupportedException` on Linux.
- **`.gitignore`'s `.mcp.json` rule is anchored to the repo root** (`/.mcp.json`) — without the leading
  slash the glob also matched the tracked, portable `plugin/.mcp.json`.
- Integration tests never run in CI (they need a running КОМПАС with GUI and a license) — a hard boundary,
  not a future task.

## Обновление RAG-базы справки SDK

Когда выходит новая версия КОМПАС — в репозитории `kompas-sdk-docs`, на машине с установленным КОМПАС:
`pwsh tools/update_sdk_docs.ps1 -SdkVersion 25` перегенерирует `sdk/` из `SDK\Help\KOMPAS_SDK_ru-RU.zip`;
просмотри диф (**удалённые статьи = сломался парсер**, а не усохший API), закоммить, поставь тег `sdk-vNN`,
запушь — Gitea Actions на `rag-node` перевалидирует и переключит алиас `kompas_sdk`. Индексация
инкрементальная, по контрольным суммам.
