[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6MX1CM9Q49BHTGCX3MBZ0MH":3,"skill-same:01M6MX1CM9Q49BHTGCX3MBZ0MH":46},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":28,"repositoryHtmlUrl":29,"repositoryHomepageUrl":6,"ownerHtmlUrl":30,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":31,"install":32,"resources":45},"01M6MX1CM9Q49BHTGCX3MBZ0MH","pgd",null,"PGD — справочник по формату и CLI pgDesigner. Используй при работе с .pgd файлами.","vmkteam\u002Fclaude-plugins","vmkteam","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F55537877?v=4","01M6MWYAFDCD63N1M8MBJA6T0S","01M6MWYAKHK0QCPR0Y7AW5SH0R",7,"MIT","https:\u002F\u002Fgithub.com\u002Fvmkteam\u002Fclaude-plugins\u002Fblob\u002Fmaster\u002Fplugins\u002Fdeveloper\u002Fskills\u002Fpgd\u002FSKILL.md",[],[5,18],"cli","2026-11-10 10:12:30",false,"---\nname: pgd\ndescription: \"PGD — справочник по формату и CLI pgDesigner. Используй при работе с .pgd файлами.\"\npaths: \"**\u002F*.pgd\"\n---\n\n# PGD — pgDesigner формат и CLI\n\n`.pgd` — git-friendly XML-формат [pgDesigner](https:\u002F\u002Fpgdesigner.io) для схем PostgreSQL.\nИсточник правды — спецификация https:\u002F\u002Fpgdesigner.io\u002Fdocs\u002Fpgd-format и XSD `pgd-format.xsd` (в репозитории\npgdesigner — `docs\u002Fpgd-format\u002F`). Скилл сверен с pgdesigner **0.0.6** (`pgdesigner version`); на другой версии\nловушки ниже перепроверь.\n\nCLI: `pgdesigner` (не `pgd`).\n\n## Non-obvious правила редактирования\n\n- **Без числовых ID** — объекты по имени; кросс-схемно через `schema.table`\n- **`\u003Cindex>` — на уровне `\u003Cschema>`, НЕ внутри `\u003Ctable>`** (частая ошибка при конверсии из PDD)\n- **Порядок элементов в `\u003Ctable>`:** column → pk → fk → unique → check → exclude → with → partition-by → partition\n- **Порядок элементов в `\u003Cindex>`:** ключи → `\u003Cinclude>` → `\u003Cwith>` → `\u003Cwhere>`. Ключи — `\u003Ccolumn>` и `\u003Cexpression>` вперемешку, в порядке ключа индекса. Старый порядок (`\u003Cwhere>` перед `\u003Cinclude>`) pgdesigner читает, но XSD 0.0.6 его отвергает\n- **Булевы — строки** `\"true\"`\u002F`\"false\"` (не `\"0\"`\u002F`\"1\"` как в PDD)\n- **Сырой SQL — текстом элемента в CDATA:** `\u003Ccheck>`, `\u003Cexpression>` и `\u003Cwhere>` индекса, `\u003Cbound>` партиции, `\u003Cquery>` представления, `\u003Cbody>` функции, `\u003Cusing>`\u002F`\u003Cwith-check>` политики, `\u003Cconstraint>` домена\n- **Атрибутом, не текстом:** `default=\"…\"` колонки и `\u003Cgenerated expression=\"…\">` — XSD требует атрибут. Текст или CDATA внутри `\u003Cgenerated>` `generate` превращает в `GENERATED ALWAYS AS ()`; `lint` ловит это как E033\n- **`nullable` default `\"true\"`** — для NOT NULL ставь явно `nullable=\"false\"`\n- **`comment=\"…\"`** у `\u003Ctable>` и `\u003Ccolumn>` — это `COMMENT ON`\n- **Действия FK указывай явно:** `restrict`, `cascade`, `set-null`, `set-default`, `no action` (с пробелом, остальные через дефис). Без атрибута `generate` пишет `NO ACTION`, хотя XSD объявляет `restrict`, и `lint` молчит; W015 срабатывает только на явный `no action`, а `lint -fix` меняет его на `restrict`\n- **Тип из не-public схемы — со схемой:** `type=\"app.level\"`, иначе PostgreSQL ищет его по `search_path` (W024)\n- Атрибуты на одной строке — иначе git-diff будет шумный\n\n## Корень\n\n```xml\n\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003Cpgd version=\"1\" pg-version=\"18\" default-schema=\"public\">\n```\n\n## Иерархия\n\nВсе разделы необязательны; порядок — канонический:\n\n```\n\u003Cpgd>\n├── \u003Cproject>\u002F\u003Csettings>     \u003Cnaming>, \u003Cdefaults>, \u003Clint ignore-rules>\n├── \u003Cdatabase>               имя, кодировка, коллация\n├── \u003Croles> \u003Ctablespaces> \u003Cextensions>\n├── \u003Ctypes>                  enum, composite, domain, range\n├── \u003Csequences>\n├── \u003Cschema>\n│   ├── \u003Ctable>\n│   │   └── column, pk, fk, unique, check, exclude, with,\n│   │       partition-by, partition\n│   └── \u003Cindex>              \u003C-- на уровне schema!\n├── \u003Cviews> \u003Cfunctions> \u003Ctriggers> \u003Crules> \u003Cpolicies>\n├── \u003Ccomments> \u003Cgrants>\n└── \u003Clayouts>                позиции, группы и цвета редактора\n```\n\n## Канонические сниппеты\n\nEnum — порядок `\u003Clabel>` = порядок значений в PostgreSQL (см. ловушки `diff`):\n```xml\n\u003Cenum name=\"user_status\" schema=\"public\">\n  \u003Clabel>active\u003C\u002Flabel>\n  \u003Clabel>inactive\u003C\u002Flabel>\n\u003C\u002Fenum>\n```\n\nFK (inline в `\u003Ctable>`, в отличие от PDD):\n```xml\n\u003Cfk name=\"fk_orders_user\" to-table=\"users\" on-delete=\"cascade\" on-update=\"restrict\">\n  \u003Ccolumn name=\"user_id\" references=\"id\">\u003C\u002Fcolumn>\n\u003C\u002Ffk>\n```\n\nИндекс по выражению \u002F covering \u002F partial \u002F opclass:\n```xml\n\u003Cindex name=\"idx_users_lower_email\" table=\"users\" using=\"btree\">\n  \u003Cexpression>\u003C![CDATA[lower(email)]]>\u003C\u002Fexpression>\n  \u003Cinclude>\u003Ccolumn name=\"name\">\u003C\u002Fcolumn>\u003C\u002Finclude>\n  \u003Cwhere>\u003C![CDATA[deleted_at IS NULL]]>\u003C\u002Fwhere>\n\u003C\u002Findex>\n\u003Cindex name=\"idx_users_name_trgm\" table=\"users\" using=\"gin\">\n  \u003Ccolumn name=\"name\" opclass=\"gin_trgm_ops\">\u003C\u002Fcolumn>\n\u003C\u002Findex>\n\u003Cindex name=\"idx_users_full_name_trgm\" table=\"users\" using=\"gin\">\n  \u003Cexpression opclass=\"gin_trgm_ops\">\u003C![CDATA[lower(full_name)]]>\u003C\u002Fexpression>\n\u003C\u002Findex>\n```\n\n`opclass`, `order` и `nulls` у `\u003Cexpression>` — как у `\u003Ccolumn>`. Одно `\u003Cexpression>` — один ключ: несколько ключей через запятую в одном выражении — W023.\n\nIDENTITY и generated (`stored=\"false\"` — VIRTUAL, PG18):\n```xml\n\u003Ccolumn name=\"id\" type=\"bigint\" nullable=\"false\">\n  \u003Cidentity generated=\"always\">\u003C\u002Fidentity>\n\u003C\u002Fcolumn>\n\u003Ccolumn name=\"full_name\" type=\"text\">\n  \u003Cgenerated expression=\"first_name || ' ' || last_name\" stored=\"true\">\u003C\u002Fgenerated>\n\u003C\u002Fcolumn>\n```\n\nПартицирование — границу по `timestamptz` пиши со смещением, иначе она зависит от таймзоны сессии, которая накатывала миграцию (и см. ловушку сверки с базой):\n```xml\n\u003Cpartition-by type=\"range\">\u003Ccolumn name=\"created_at\">\u003C\u002Fcolumn>\u003C\u002Fpartition-by>\n\u003Cpartition name=\"events_2024\">\n  \u003Cbound>FOR VALUES FROM ('2024-01-01 00:00:00+00') TO ('2025-01-01 00:00:00+00')\u003C\u002Fbound>\n\u003C\u002Fpartition>\n```\n\nПолный синтаксис всех тегов и атрибутов: https:\u002F\u002Fpgdesigner.io\u002Fdocs\u002Fpgd-format.\n\n## Ловушки 0.0.6\n\n### `diff` → миграция\n\n`diff` 0.0.6 выдаёт FK и комментарии новых таблиц, смену и снятие generated (`SET EXPRESSION`, `DROP EXPRESSION`),\nпересоздание индекса при смене выражения, `INCLUDE`, `NULLS NOT DISTINCT` и `WITH`, `ADD VALUE … AFTER` для enum,\nпереименование индексов и ограничений. Миграцию всё равно проверяй: накати цепочку на пустую БД и сравни `pg_dump -s`\nс базой из полного `pgdesigner generate`.\n\nРискованные шаги `diff` помечает в stderr и комментарием в SQL:\n\n- **`ENUM_ADD_VALUE`** — новое значение enum нельзя использовать до коммита транзакции. Если миграция тут же пишет это значение (`UPDATE`, `DEFAULT`), вынеси `ADD VALUE` в отдельную миграцию, у `\u002Fpgmigrator` — в предыдущий файл или `-NONTR.sql`.\n- **`TABLE_REWRITE`** — новое выражение stored generated-колонки переписывает таблицу под блокировкой.\n- **`COLUMN_RECREATE`** (dangerous) — обычная колонка становится generated через `DROP COLUMN` + `ADD COLUMN`: данные колонки пересчитываются, зависимые представления и FK блокируют `DROP`.\n- **`TYPE_RECREATE`** (dangerous) — перестановка или удаление значения enum. SQL не выдаётся, только комментарий: PostgreSQL этого не умеет. Пиши руками (новый тип, `ALTER COLUMN … TYPE … USING`, `DROP TYPE` старого) или не меняй порядок.\n\n### Сверка модели с живой базой\n\n- **`convert` из базы без `-full`** читает таблицы и индексы, но не типы, представления, функции и триггеры — `diff` модели с таким файлом предлагает `DROP TYPE` для каждого enum. Для сверки — `convert -full`.\n- **Граница партиции без смещения** (`'2024-01-01'`) база хранит в своей таймзоне (`'2024-01-01 00:00:00+03'`), и `diff` показывает ложный `REATTACH_PARTITION`. С явным смещением в модели ложной разницы нет.\n- `convert \"postgres:\u002F\u002F…\"` пишет `\u003Cdbname>.pgd` и не перезаписывает существующий файл — задай `-o`. Пароль из DSN в сообщениях скрыт.\n\n## SQL → PGD маппинг\n\n| SQL | PGD |\n|---|---|\n| `CREATE TABLE` | `\u003Ctable>` в нужную `\u003Cschema>` |\n| `ALTER TABLE ADD COLUMN` | `\u003Ccolumn>` в `\u003Ctable>` |\n| `CREATE INDEX` | `\u003Cindex>` в `\u003Cschema>` (не в `\u003Ctable>`) |\n| `ADD CONSTRAINT` | `\u003Cpk>`\u002F`\u003Cfk>`\u002F`\u003Cunique>`\u002F`\u003Ccheck>` в `\u003Ctable>` |\n| `CREATE TYPE` | `\u003Cenum>`\u002F`\u003Ccomposite>`\u002F`\u003Cdomain>`\u002F`\u003Crange>` в `\u003Ctypes>` |\n| `CREATE FUNCTION` \u002F `PROCEDURE` \u002F `AGGREGATE` | `\u003Cfunction>` в `\u003Cfunctions>`, `kind=\"procedure\"`\u002F`\"aggregate\"` |\n| `COMMENT ON TABLE\u002FCOLUMN` | атрибут `comment` у `\u003Ctable>`\u002F`\u003Ccolumn>` |\n| `UNLOGGED`, `TABLESPACE`, `USING` таблицы | атрибуты `unlogged`, `tablespace`, `using` у `\u003Ctable>` |\n| `WITH (…)`, `toast.*` | `\u003Cwith>\u003Cparam name=\"toast.autovacuum_enabled\" value=\"false\">\u003C\u002Fparam>\u003C\u002Fwith>` |\n\n## Отличия от PDD (MicroOLAP)\n\n| Аспект | PDD | PGD |\n|---|---|---|\n| Идентификация | числовые ID | имена |\n| Типы | коды (25, 1043) | имена (`text`, `varchar`) |\n| NOT NULL | `NotNull=\"1\"` | `nullable=\"false\"` |\n| Индексы | внутри ENTITY | в `\u003Cschema>` |\n| FK | секция REFERENCES | `\u003Cfk>` inline |\n| Булевы | `\"0\"`\u002F`\"1\"` | `\"true\"`\u002F`\"false\"` |\n\n## CLI `pgdesigner`\n\n```bash\npgdesigner generate  [-o schema.sql] schema.pgd                   # DDL\npgdesigner diff      [-f json] [-o patch.sql] old.pgd new.pgd     # ALTER (используется в \u002Fpgmigrator), см. ловушки\npgdesigner lint      [-fix] [-s error] schema.pgd                 # 69 правил (E\u002FW\u002FI)\npgdesigner convert   [-o project.pgd] schema.pdd|.sql|.dbs|.dm2\npgdesigner convert   [-o project.pgd] [-schema s1,s2] -full \"postgres:\u002F\u002F...\"   # см. сверку с базой\npgdesigner testdata  [-seed 42 -rows 100] schema.pgd\npgdesigner merge     base.pgd overlay.pgd\n```\n","# PGD — pgDesigner формат и CLI\n\n`.pgd` — git-friendly XML-формат [pgDesigner](https:\u002F\u002Fpgdesigner.io) для схем PostgreSQL.\nИсточник правды — спецификация https:\u002F\u002Fpgdesigner.io\u002Fdocs\u002Fpgd-format и XSD `pgd-format.xsd` (в репозитории\npgdesigner — `docs\u002Fpgd-format\u002F`). Скилл сверен с pgdesigner **0.0.6** (`pgdesigner version`); на другой версии\nловушки ниже перепроверь.\n\nCLI: `pgdesigner` (не `pgd`).\n\n## Non-obvious правила редактирования\n\n- **Без числовых ID** — объекты по имени; кросс-схемно через `schema.table`\n- **`\u003Cindex>` — на уровне `\u003Cschema>`, НЕ внутри `\u003Ctable>`** (частая ошибка при конверсии из PDD)\n- **Порядок элементов в `\u003Ctable>`:** column → pk → fk → unique → check → exclude → with → partition-by → partition\n- **Порядок элементов в `\u003Cindex>`:** ключи → `\u003Cinclude>` → `\u003Cwith>` → `\u003Cwhere>`. Ключи — `\u003Ccolumn>` и `\u003Cexpression>` вперемешку, в порядке ключа индекса. Старый порядок (`\u003Cwhere>` перед `\u003Cinclude>`) pgdesigner читает, но XSD 0.0.6 его отвергает\n- **Булевы — строки** `\"true\"`\u002F`\"false\"` (не `\"0\"`\u002F`\"1\"` как в PDD)\n- **Сырой SQL — текстом элемента в CDATA:** `\u003Ccheck>`, `\u003Cexpression>` и `\u003Cwhere>` индекса, `\u003Cbound>` партиции, `\u003Cquery>` представления, `\u003Cbody>` функции, `\u003Cusing>`\u002F`\u003Cwith-check>` политики, `\u003Cconstraint>` домена\n- **Атрибутом, не текстом:** `default=\"…\"` колонки и `\u003Cgenerated expression=\"…\">` — XSD требует атрибут. Текст или CDATA внутри `\u003Cgenerated>` `generate` превращает в `GENERATED ALWAYS AS ()`; `lint` ловит это как E033\n- **`nullable` default `\"true\"`** — для NOT NULL ставь явно `nullable=\"false\"`\n- **`comment=\"…\"`** у `\u003Ctable>` и `\u003Ccolumn>` — это `COMMENT ON`\n- **Действия FK указывай явно:** `restrict`, `cascade`, `set-null`, `set-default`, `no action` (с пробелом, остальные через дефис). Без атрибута `generate` пишет `NO ACTION`, хотя XSD объявляет `restrict`, и `lint` молчит; W015 срабатывает только на явный `no action`, а `lint -fix` меняет его на `restrict`\n- **Тип из не-public схемы — со схемой:** `type=\"app.level\"`, иначе PostgreSQL ищет его по `search_path` (W024)\n- Атрибуты на одной строке — иначе git-diff будет шумный\n\n## Корень\n\n```xml\n\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003Cpgd version=\"1\" pg-version=\"18\" default-schema=\"public\">\n```\n\n## Иерархия\n\nВсе разделы необязательны; порядок — канонический:\n\n```\n\u003Cpgd>\n├── \u003Cproject>\u002F\u003Csettings>     \u003Cnaming>, \u003Cdefaults>, \u003Clint ignore-rules>\n├── \u003Cdatabase>               имя, кодировка, коллация\n├── \u003Croles> \u003Ctablespaces> \u003Cextensions>\n├── \u003Ctypes>                  enum, composite, domain, range\n├── \u003Csequences>\n├── \u003Cschema>\n│   ├── \u003Ctable>\n│   │   └── column, pk, fk, unique, check, exclude, with,\n│   │       partition-by, partition\n│   └── \u003Cindex>              \u003C-- на уровне schema!\n├── \u003Cviews> \u003Cfunctions> \u003Ctriggers> \u003Crules> \u003Cpolicies>\n├── \u003Ccomments> \u003Cgrants>\n└── \u003Clayouts>                позиции, группы и цвета редактора\n```\n\n## Канонические сниппеты\n\nEnum — порядок `\u003Clabel>` = порядок значений в PostgreSQL (см. ловушки `diff`):\n```xml\n\u003Cenum name=\"user_status\" schema=\"public\">\n  \u003Clabel>active\u003C\u002Flabel>\n  \u003Clabel>inactive\u003C\u002Flabel>\n\u003C\u002Fenum>\n```\n\nFK (inline в `\u003Ctable>`, в отличие от PDD):\n```xml\n\u003Cfk name=\"fk_orders_user\" to-table=\"users\" on-delete=\"cascade\" on-update=\"restrict\">\n  \u003Ccolumn name=\"user_id\" references=\"id\">\u003C\u002Fcolumn>\n\u003C\u002Ffk>\n```\n\nИндекс по выражению \u002F covering \u002F partial \u002F opclass:\n```xml\n\u003Cindex name=\"idx_users_lower_email\" table=\"users\" using=\"btree\">\n  \u003Cexpression>\u003C![CDATA[lower(email)]]>\u003C\u002Fexpression>\n  \u003Cinclude>\u003Ccolumn name=\"name\">\u003C\u002Fcolumn>\u003C\u002Finclude>\n  \u003Cwhere>\u003C![CDATA[deleted_at IS NULL]]>\u003C\u002Fwhere>\n\u003C\u002Findex>\n\u003Cindex name=\"idx_users_name_trgm\" table=\"users\" using=\"gin\">\n  \u003Ccolumn name=\"name\" opclass=\"gin_trgm_ops\">\u003C\u002Fcolumn>\n\u003C\u002Findex>\n\u003Cindex name=\"idx_users_full_name_trgm\" table=\"users\" using=\"gin\">\n  \u003Cexpression opclass=\"gin_trgm_ops\">\u003C![CDATA[lower(full_name)]]>\u003C\u002Fexpression>\n\u003C\u002Findex>\n```\n\n`opclass`, `order` и `nulls` у `\u003Cexpression>` — как у `\u003Ccolumn>`. Одно `\u003Cexpression>` — один ключ: несколько ключей через запятую в одном выражении — W023.\n\nIDENTITY и generated (`stored=\"false\"` — VIRTUAL, PG18):\n```xml\n\u003Ccolumn name=\"id\" type=\"bigint\" nullable=\"false\">\n  \u003Cidentity generated=\"always\">\u003C\u002Fidentity>\n\u003C\u002Fcolumn>\n\u003Ccolumn name=\"full_name\" type=\"text\">\n  \u003Cgenerated expression=\"first_name || ' ' || last_name\" stored=\"true\">\u003C\u002Fgenerated>\n\u003C\u002Fcolumn>\n```\n\nПартицирование — границу по `timestamptz` пиши со смещением, иначе она зависит от таймзоны сессии, которая накатывала миграцию (и см. ловушку сверки с базой):\n```xml\n\u003Cpartition-by type=\"range\">\u003Ccolumn name=\"created_at\">\u003C\u002Fcolumn>\u003C\u002Fpartition-by>\n\u003Cpartition name=\"events_2024\">\n  \u003Cbound>FOR VALUES FROM ('2024-01-01 00:00:00+00') TO ('2025-01-01 00:00:00+00')\u003C\u002Fbound>\n\u003C\u002Fpartition>\n```\n\nПолный синтаксис всех тегов и атрибутов: https:\u002F\u002Fpgdesigner.io\u002Fdocs\u002Fpgd-format.\n\n## Ловушки 0.0.6\n\n### `diff` → миграция\n\n`diff` 0.0.6 выдаёт FK и комментарии новых таблиц, смену и снятие generated (`SET EXPRESSION`, `DROP EXPRESSION`),\nпересоздание индекса при смене выражения, `INCLUDE`, `NULLS NOT DISTINCT` и `WITH`, `ADD VALUE … AFTER` для enum,\nпереименование индексов и ограничений. Миграцию всё равно проверяй: накати цепочку на пустую БД и сравни `pg_dump -s`\nс базой из полного `pgdesigner generate`.\n\nРискованные шаги `diff` помечает в stderr и комментарием в SQL:\n\n- **`ENUM_ADD_VALUE`** — новое значение enum нельзя использовать до коммита транзакции. Если миграция тут же пишет это значение (`UPDATE`, `DEFAULT`), вынеси `ADD VALUE` в отдельную миграцию, у `\u002Fpgmigrator` — в предыдущий файл или `-NONTR.sql`.\n- **`TABLE_REWRITE`** — новое выражение stored generated-колонки переписывает таблицу под блокировкой.\n- **`COLUMN_RECREATE`** (dangerous) — обычная колонка становится generated через `DROP COLUMN` + `ADD COLUMN`: данные колонки пересчитываются, зависимые представления и FK блокируют `DROP`.\n- **`TYPE_RECREATE`** (dangerous) — перестановка или удаление значения enum. SQL не выдаётся, только комментарий: PostgreSQL этого не умеет. Пиши руками (новый тип, `ALTER COLUMN … TYPE … USING`, `DROP TYPE` старого) или не меняй порядок.\n\n### Сверка модели с живой базой\n\n- **`convert` из базы без `-full`** читает таблицы и индексы, но не типы, представления, функции и триггеры — `diff` модели с таким файлом предлагает `DROP TYPE` для каждого enum. Для сверки — `convert -full`.\n- **Граница партиции без смещения** (`'2024-01-01'`) база хранит в своей таймзоне (`'2024-01-01 00:00:00+03'`), и `diff` показывает ложный `REATTACH_PARTITION`. С явным смещением в модели ложной разницы нет.\n- `convert \"postgres:\u002F\u002F…\"` пишет `\u003Cdbname>.pgd` и не перезаписывает существующий файл — задай `-o`. Пароль из DSN в сообщениях скрыт.\n\n## SQL → PGD маппинг\n\n| SQL | PGD |\n|---|---|\n| `CREATE TABLE` | `\u003Ctable>` в нужную `\u003Cschema>` |\n| `ALTER TABLE ADD COLUMN` | `\u003Ccolumn>` в `\u003Ctable>` |\n| `CREATE INDEX` | `\u003Cindex>` в `\u003Cschema>` (не в `\u003Ctable>`) |\n| `ADD CONSTRAINT` | `\u003Cpk>`\u002F`\u003Cfk>`\u002F`\u003Cunique>`\u002F`\u003Ccheck>` в `\u003Ctable>` |\n| `CREATE TYPE` | `\u003Cenum>`\u002F`\u003Ccomposite>`\u002F`\u003Cdomain>`\u002F`\u003Crange>` в `\u003Ctypes>` |\n| `CREATE FUNCTION` \u002F `PROCEDURE` \u002F `AGGREGATE` | `\u003Cfunction>` в `\u003Cfunctions>`, `kind=\"procedure\"`\u002F`\"aggregate\"` |\n| `COMMENT ON TABLE\u002FCOLUMN` | атрибут `comment` у `\u003Ctable>`\u002F`\u003Ccolumn>` |\n| `UNLOGGED`, `TABLESPACE`, `USING` таблицы | атрибуты `unlogged`, `tablespace`, `using` у `\u003Ctable>` |\n| `WITH (…)`, `toast.*` | `\u003Cwith>\u003Cparam name=\"toast.autovacuum_enabled\" value=\"false\">\u003C\u002Fparam>\u003C\u002Fwith>` |\n\n## Отличия от PDD (MicroOLAP)\n\n| Аспект | PDD | PGD |\n|---|---|---|\n| Идентификация | числовые ID | имена |\n| Типы | коды (25, 1043) | имена (`text`, `varchar`) |\n| NOT NULL | `NotNull=\"1\"` | `nullable=\"false\"` |\n| Индексы | внутри ENTITY | в `\u003Cschema>` |\n| FK | секция REFERENCES | `\u003Cfk>` inline |\n| Булевы | `\"0\"`\u002F`\"1\"` | `\"true\"`\u002F`\"false\"` |\n\n## CLI `pgdesigner`\n\n```bash\npgdesigner generate  [-o schema.sql] schema.pgd                   # DDL\npgdesigner diff      [-f json] [-o patch.sql] old.pgd new.pgd     # ALTER (используется в \u002Fpgmigrator), см. ловушки\npgdesigner lint      [-fix] [-s error] schema.pgd                 # 69 правил (E\u002FW\u002FI)\npgdesigner convert   [-o project.pgd] schema.pdd|.sql|.dbs|.dm2\npgdesigner convert   [-o project.pgd] [-schema s1,s2] -full \"postgres:\u002F\u002F...\"   # см. сверку с базой\npgdesigner testdata  [-seed 42 -rows 100] schema.pgd\npgdesigner merge     base.pgd overlay.pgd\n```\n",{"name":5,"paths":24,"description":7},"**\u002F*.pgd","master","8f3147ce24a1a470d9aaa02aa775d7797d621d95","plugins\u002Fdeveloper\u002Fskills\u002Fpgd",1,"https:\u002F\u002Fgithub.com\u002Fvmkteam\u002Fclaude-plugins","https:\u002F\u002Fgithub.com\u002Fvmkteam","2026-11-05 00:26:25",{"source":8,"skillName":5,"commands":33,"prompt":43,"zipAvailable":44},[34,37,40],{"tool":35,"command":36},"npx","npx skills add vmkteam\u002Fclaude-plugins --skill pgd",{"tool":38,"command":39},"bunx","bunx skills add vmkteam\u002Fclaude-plugins --skill pgd",{"tool":41,"command":42},"pnpm","pnpm dlx skills add vmkteam\u002Fclaude-plugins --skill pgd","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fvmkteam\u002Fclaude-plugins\u002Fblob\u002Fmaster\u002Fplugins\u002Fdeveloper\u002Fskills\u002Fpgd\u002FSKILL.md",true,[],[47,58,70,86,103,115],{"skillNo":48,"name":49,"nameZh":6,"description":50,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":51,"categories":52,"keywords":53,"publishedAt":19},"01M6MX3A8MZJBTMMK6WMY35FYH","zenrpc","Zenrpc — справочник по JSON-RPC 2.0 серверу для Go. Используй при создании и редактировании RPC-сервисов.","https:\u002F\u002Fgithub.com\u002Fvmkteam\u002Fclaude-plugins\u002Fblob\u002Fmaster\u002Fplugins\u002Fdeveloper\u002Fskills\u002Fzenrpc\u002FSKILL.md",[],[49,54,55,56,57],"go","json-rpc","json","rpc",{"skillNo":59,"name":60,"nameZh":6,"description":61,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":62,"categories":63,"keywords":64,"publishedAt":19},"01M6MX36PEA0NSHCCRF5GGVVTZ","youtrack","YouTrack — задачи через REST API и pcurl. Используй для поиска issues, создания, обновления описаний, смены assignee\u002Fstage\u002Fприоритета, логирования времени и работы с комментариями.","https:\u002F\u002Fgithub.com\u002Fvmkteam\u002Fclaude-plugins\u002Fblob\u002Fmaster\u002Fplugins\u002Fdeveloper\u002Fskills\u002Fyoutrack\u002FSKILL.md",[],[60,65,66,67,68,69],"issues","REST","api","stage","rest api",{"skillNo":71,"name":72,"nameZh":6,"description":73,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":74,"categories":75,"keywords":76,"publishedAt":19},"01M6MX322TD9HQPCYSNTFB4HBA","topsrv","topsrv — метрики, алерты, CVE и HTTP-логи серверов проекта через публичный JSON-RPC API app.topsrv.io. Используй, когда нужна загрузка CPU, памяти или диска хоста, метрики PostgreSQL\u002Fnginx\u002Fangie агента topsrv (`topsrv_*`), какие алерты горят, уязвимые пакеты на серверах или кто (боты, сети, IP) нагружает сайт.","https:\u002F\u002Fgithub.com\u002Fvmkteam\u002Fclaude-plugins\u002Fblob\u002Fmaster\u002Fplugins\u002Fdeveloper\u002Fskills\u002Ftopsrv\u002FSKILL.md",[],[72,77,78,57,79,80,67,81,56,82,83,84,55,85],"CPU","postgresql","cve","nginx","Bash","ip","app","io","http",{"skillNo":87,"name":88,"nameZh":6,"description":89,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":90,"categories":91,"keywords":97,"publishedAt":19},"01M6MX2XFXCHNRPPW6WYZ15BXN","testing","Testing — используй всегда, когда пишешь или правишь Go-тесты (*_test.go), в том числе по сценариям Given\u002FWhen\u002FThen из spec: фреймворк как в соседних файлах, префикс TestDB, фабрики pkg\u002Fdb\u002Ftest, реальная БД без моков. Также при настройке TestMain\u002Ftest-short и когда тесты падают в gate, но проходят локально.","https:\u002F\u002Fgithub.com\u002Fvmkteam\u002Fclaude-plugins\u002Fblob\u002Fmaster\u002Fplugins\u002Fdeveloper\u002Fskills\u002Ftesting\u002FSKILL.md",[92],{"categoryNo":93,"categoryName":94,"taxonomyType":95,"taxonomyTypeDesc":96},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[88,98,99,54,100,101,102],"gate","spec","test","short","db",{"skillNo":104,"name":105,"nameZh":6,"description":106,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":109,"publishedAt":19},"01M6MX2P8RFYPV4EXRMVW6KAN7","solve","Solve — полный цикл решения задачи из YouTrack: preflight → анализ → план → реализация → ревью → коммит. Используй при любой YouTrack-задаче (`\u002Fsolve PLF-819`); флаг `--fast` сокращает HITL для тривиальных багфиксов.","https:\u002F\u002Fgithub.com\u002Fvmkteam\u002Fclaude-plugins\u002Fblob\u002Fmaster\u002Fplugins\u002Fdeveloper\u002Fskills\u002Fsolve\u002FSKILL.md",[],[105,110,111,112,113,114,60],"fast","preflight","task","hitl","id",{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":121,"publishedAt":19},"01M6MX2H6TF2VW75PCPGWR2SKZ","skills-check","Skills Check — smoke-тесты интеграций из project-index.md. Используй для проверки что pcurl-профили и URL всех data-source скиллов ещё живы.","https:\u002F\u002Fgithub.com\u002Fvmkteam\u002Fclaude-plugins\u002Fblob\u002Fmaster\u002Fplugins\u002Fdeveloper\u002Fskills\u002Fskills-check\u002FSKILL.md",[],[122,123,124,81,125,126,127,128,129,130,131,132,133,134],"skills check","check","data","smoke","probe","project","false","URL","data-source","true","source","fork","index"]