@rt-tools/agent-kit 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +73 -0
  2. package/assets/checks/check-doc-paths.mjs +200 -30
  3. package/assets/checks/check-specs.mjs +42 -7
  4. package/assets/checks/rt-kit-checks.config.mjs +12 -0
  5. package/assets/commands/agent-kit-digest.md +83 -0
  6. package/assets/commands/next-session.md +122 -0
  7. package/assets/commands/skill-curator.md +33 -1
  8. package/assets/defaults/gate-map.sh +23 -1
  9. package/assets/defaults/project.sh +37 -1
  10. package/assets/docs/GLOSSARY.md +77 -0
  11. package/assets/hooks/docs-guard.sh +18 -1
  12. package/assets/hooks/git-guard-delivery.sh +30 -3
  13. package/assets/hooks/git-guard-main.sh +8 -0
  14. package/assets/hooks/git-guard-push-tests.sh +8 -1
  15. package/assets/hooks/grill-gate.sh +38 -16
  16. package/assets/hooks/lint-after-edit.sh +10 -3
  17. package/assets/hooks/observe.sh +90 -0
  18. package/assets/hooks/postmortem-guard.sh +92 -0
  19. package/assets/hooks/profile-check.sh +43 -0
  20. package/assets/hooks/qa-dataid-guard.sh +9 -2
  21. package/assets/hooks/reuse-first-guard.sh +9 -2
  22. package/assets/hooks/skill-gate.sh +15 -0
  23. package/assets/hooks/skill-loaded.sh +7 -0
  24. package/assets/hooks/task-context-load.sh +16 -2
  25. package/assets/hooks/task-flow-guard.sh +9 -2
  26. package/assets/hooks/window-fill-guard.sh +157 -0
  27. package/assets/laws/code-structure.md +10 -0
  28. package/assets/laws/delivery.md +8 -1
  29. package/assets/laws/project-documentation.md +9 -0
  30. package/assets/laws/verifiability.md +9 -0
  31. package/assets/laws/work-conduct.md +47 -0
  32. package/assets/patterns/git-workflow-commit.azure.md +16 -12
  33. package/assets/patterns/git-workflow-commit.github.md +16 -12
  34. package/assets/patterns/git-workflow-commit.gitlab.md +16 -12
  35. package/assets/patterns/spec-driven-domain.md +19 -0
  36. package/assets/patterns/task-flow-close.md +4 -4
  37. package/assets/patterns/task-flow-handoff.md +115 -0
  38. package/assets/patterns/task-flow-resume.md +14 -2
  39. package/assets/patterns/task-flow-start.md +40 -2
  40. package/assets/rules/doc-style.md +39 -1
  41. package/assets/rules/git-workflow.azure.md +39 -0
  42. package/assets/rules/git-workflow.github.md +38 -0
  43. package/assets/rules/git-workflow.gitlab.md +38 -0
  44. package/assets/rules/spec-driven.md +14 -0
  45. package/assets/rules/task-flow.md +70 -3
  46. package/assets/skills/agent-kit.md +32 -0
  47. package/assets/templates/postmortem.md +32 -0
  48. package/assets/templates/proposal.md +39 -0
  49. package/bin/agent-kit.d.ts.map +1 -1
  50. package/bin/agent-kit.js +50 -1
  51. package/bin/agent-kit.js.map +1 -1
  52. package/lib/catalog.d.ts +33 -0
  53. package/lib/catalog.d.ts.map +1 -1
  54. package/lib/catalog.js +55 -1
  55. package/lib/catalog.js.map +1 -1
  56. package/lib/commands.d.ts +41 -0
  57. package/lib/commands.d.ts.map +1 -1
  58. package/lib/commands.js +315 -3
  59. package/lib/commands.js.map +1 -1
  60. package/lib/config.d.ts +11 -1
  61. package/lib/config.d.ts.map +1 -1
  62. package/lib/config.js +6 -0
  63. package/lib/config.js.map +1 -1
  64. package/lib/hooks-map.d.ts +15 -3
  65. package/lib/hooks-map.d.ts.map +1 -1
  66. package/lib/hooks-map.js +47 -11
  67. package/lib/hooks-map.js.map +1 -1
  68. package/lib/observations.d.ts +72 -0
  69. package/lib/observations.d.ts.map +1 -0
  70. package/lib/observations.js +126 -0
  71. package/lib/observations.js.map +1 -0
  72. package/lib/proposals.d.ts +48 -0
  73. package/lib/proposals.d.ts.map +1 -0
  74. package/lib/proposals.js +111 -0
  75. package/lib/proposals.js.map +1 -0
  76. package/lib/submit.d.ts +24 -0
  77. package/lib/submit.d.ts.map +1 -0
  78. package/lib/submit.js +26 -0
  79. package/lib/submit.js.map +1 -0
  80. package/lib/sync.d.ts +9 -1
  81. package/lib/sync.d.ts.map +1 -1
  82. package/lib/sync.js +4 -6
  83. package/lib/sync.js.map +1 -1
  84. package/package.json +1 -1
  85. package/rt-tools-agent-kit-0.5.2.tgz +0 -0
  86. package/rt-tools-agent-kit-0.5.0.tgz +0 -0
package/lib/sync.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/sync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Раскладка ресурсов пакета в дерево проекта.\n *\n * Порядок один и тот же и для записи, и для проверки: собрать тело, решить судьбу файла, и\n * только потом писать. `sync --check` отличается от `sync` ровно последним шагом — иначе гейт\n * пуша проверял бы не то, что кладёт раскладка.\n */\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nimport { collectAssets, IAsset, targetOf } from './assets.js';\nimport { IEntryOfCatalog, IGapOfVariant, readCatalog, variantGaps } from './catalog.js';\nimport { ICompanion, pathOf, planCompanion } from './companion.js';\nimport { IConfig, OVERRIDES_DIR } from './config.js';\nimport { bindingOf, IHookBinding, unboundHooks } from './hooks-map.js';\nimport { IPlanned, isPending, isRefusal, planFile } from './plan.js';\nimport { mergeDocuments, parseDocument, renderDocument } from './sections.js';\nimport { readStamped } from './stamp.js';\nimport { IRenderResult, renderVars } from './vars.js';\nimport { matchesVariant } from './variants.js';\n\nexport interface ISyncResult {\n readonly planned: readonly IPlanned[];\n /** Дырки без значения, по ресурсам. Непустой список — отказ: подставлять нечего. */\n readonly missing: ReadonlyMap<string, readonly string[]>;\n /** Компаньоны разложенных правил: имена этого дерева, которые пишет проект. */\n readonly companions: readonly ICompanion[];\n /**\n * Файлы, лежащие в дереве от ресурсов, от которых проект отказался.\n *\n * Отказ значит «больше не клади», а не «убери»: разложенное коммитится, рядом с правилом\n * лежит написанный проектом компаньон, и стирать это молча пакет не вправе. Но и молчать\n * нельзя — брошенный файл читается как действующее правило, и агент по нему работает.\n */\n readonly abandoned: readonly string[];\n /**\n * Ресурсы, у которых виды есть, а вида под выбор дерева нет.\n *\n * Пропустить такой ресурс молча значит разложить правило и не разложить инструмент, который\n * оно зовёт: дерево получает указание без исполнителя и узнаёт об этом, когда команда из\n * правила не находится. Поэтому непустой список — отказ раскладки наравне с дыркой без\n * значения и с файлом, который правили руками.\n */\n readonly gaps: readonly IGapOfVariant[];\n /**\n * Разложенные гарды, которых нет в настройке агента: файл лежит, а позвать его некому.\n *\n * Раскладку это не отбивает — настройка принадлежит дереву, и пакет в неё не пишет, — но и\n * молчать нельзя: гард, который не зовут, неотличим от гарда, который всё пропускает.\n */\n readonly unbound: readonly IHookBinding[];\n readonly written: readonly string[];\n}\n\n/** Шаблон черновика компаньона — тот же, что пакет кладёт проекту в шаблоны. */\nconst COMPANION_TEMPLATE: string = 'templates/implementation.md';\n\nconst read: (path: string) => string | null = (path: string): string | null => (existsSync(path) ? readFileSync(path, 'utf8') : null);\n\n/**\n * Тело ресурса: текст пакета, поверх него надстройка проекта, и уже потом подстановка значений.\n *\n * Порядок именно такой. Надстройка тоже пишется с дырками — иначе проект, дописавший раздел про\n * свою главную ветку, зашил бы её имя в двух местах: в конфиге и в тексте.\n */\nfunction renderAsset(asset: IAsset, config: IConfig, root: string): IRenderResult {\n const override: string | null = read(join(root, OVERRIDES_DIR, asset.id));\n const merged: string = override ? renderDocument(mergeDocuments(parseDocument(asset.text), parseDocument(override))) : asset.text;\n\n return renderVars(merged, config.vars);\n}\n\n/**\n * Что лежит в дереве от ресурсов, которые проект больше не берёт.\n *\n * Ищется по тем же правилам раскладки, что и всё остальное: путь ресурса вычисляется так, будто\n * его кладут, и проверяется, лежит ли там файл с шапкой пакета. Чужой файл на том же пути\n * брошенным не считается — его пакет не клал.\n */\nfunction abandonedOf(config: IConfig, root: string, assetsDir: string): readonly string[] {\n const taken: ReadonlySet<string> = new Set(collectAssets(config, assetsDir).map((asset: IAsset): string => asset.id));\n\n return readCatalog(assetsDir)\n .filter((entry: IEntryOfCatalog): boolean => !taken.has(entry.id) && matchesVariant(entry.variant, config.variants))\n .map((entry: IEntryOfCatalog): string => targetOf(entry, config.layout))\n .filter((path: string): boolean => {\n const existing: string | null = read(join(root, path));\n\n return existing !== null && readStamped(existing) !== null;\n });\n}\n\n/**\n * Что о себе говорят гарды, которые дерево берёт. Читается у ресурсов, а не у разложенных\n * файлов: карта нужна и до первой раскладки — чтобы было что вставить в настройку.\n */\nfunction bindingsOf(config: IConfig, assetsDir: string): readonly IHookBinding[] {\n const bindings: IHookBinding[] = [];\n for (const asset of collectAssets(config, assetsDir)) {\n if (asset.kind !== 'hooks') {\n continue;\n }\n const binding: IHookBinding | null = bindingOf(asset.text, asset.target);\n if (binding) {\n bindings.push(binding);\n }\n }\n\n return bindings;\n}\n\nexport function planSync(config: IConfig, root: string, version: string, assetsDir: string): ISyncResult {\n const planned: IPlanned[] = [];\n const missing: Map<string, readonly string[]> = new Map();\n const companions: ICompanion[] = [];\n const template: string | null = read(join(assetsDir, COMPANION_TEMPLATE));\n\n for (const asset of collectAssets(config, assetsDir)) {\n const rendered: IRenderResult = renderAsset(asset, config, root);\n if (rendered.missing.length) {\n missing.set(asset.id, rendered.missing);\n continue;\n }\n planned.push(\n planFile({ path: asset.target, asset: asset.id, version, rendered: rendered.text, existing: read(join(root, asset.target)) })\n );\n if (asset.kind === 'rules' && template !== null) {\n companions.push(planCompanion(asset, read(join(root, pathOf(asset))), template));\n }\n }\n\n return {\n planned,\n missing,\n companions,\n abandoned: abandonedOf(config, root, assetsDir),\n gaps: variantGaps(readCatalog(assetsDir), config),\n unbound: unboundHooks(bindingsOf(config, assetsDir), root),\n written: [],\n };\n}\n\n/** Раскладка. Отказ хотя бы по одному файлу не пишет ничего: половина разложенного хуже целого. */\nexport function runSync(config: IConfig, root: string, version: string, assetsDir: string): ISyncResult {\n const result: ISyncResult = planSync(config, root, version, assetsDir);\n if (result.missing.size || result.gaps.length || result.planned.some((entry: IPlanned): boolean => isRefusal(entry.outcome))) {\n return result;\n }\n\n // Право на запуск переносится с файла в пакете. Без него гард отвечает отказом доступа, то\n // есть ненулевым кодом, а ненулевой код у гарда значит «правка отбита»: разложенный набор\n // отбивал бы подряд всё, включая сборку и тесты, и причина при этом нигде не называлась.\n const executable: ReadonlySet<string> = new Set(\n collectAssets(config, assetsDir)\n .filter((asset: IAsset): boolean => asset.executable)\n .map((asset: IAsset): string => asset.id)\n );\n\n const written: string[] = [];\n for (const entry of result.planned) {\n if (entry.content === null) {\n continue;\n }\n const path: string = join(root, entry.path);\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, entry.content, 'utf8');\n if (executable.has(entry.asset)) {\n chmodSync(path, 0o755);\n }\n written.push(entry.path);\n }\n\n // Черновик компаньона кладётся только там, где файла нет вовсе. Он без шапки и без суммы:\n // сверять в нём нечего — с первой правки проекта это его текст, а не текст пакета.\n for (const companion of result.companions) {\n if (companion.content === null) {\n continue;\n }\n const path: string = join(root, companion.path);\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, companion.content, 'utf8');\n written.push(companion.path);\n }\n\n return { ...result, written };\n}\n\nexport const pendingOf: (result: ISyncResult) => readonly IPlanned[] = (result: ISyncResult): readonly IPlanned[] =>\n result.planned.filter((entry: IPlanned): boolean => isPending(entry.outcome));\n"]}
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/sync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Раскладка ресурсов пакета в дерево проекта.\n *\n * Порядок один и тот же и для записи, и для проверки: собрать тело, решить судьбу файла, и\n * только потом писать. `sync --check` отличается от `sync` ровно последним шагом — иначе гейт\n * пуша проверял бы не то, что кладёт раскладка.\n */\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nimport { collectAssets, IAsset, targetOf } from './assets.js';\nimport { brokenLinks, IBrokenLink, IEntryOfCatalog, IGapOfVariant, readCatalog, variantGaps } from './catalog.js';\nimport { ICompanion, pathOf, planCompanion } from './companion.js';\nimport { IConfig, OVERRIDES_DIR } from './config.js';\nimport { bindingsOf as declaredIn, IHookBinding, unboundHooks } from './hooks-map.js';\nimport { IPlanned, isPending, isRefusal, planFile } from './plan.js';\nimport { mergeDocuments, parseDocument, renderDocument } from './sections.js';\nimport { readStamped } from './stamp.js';\nimport { IRenderResult, renderVars } from './vars.js';\nimport { matchesVariant } from './variants.js';\n\nexport interface ISyncResult {\n readonly planned: readonly IPlanned[];\n /** Дырки без значения, по ресурсам. Непустой список — отказ: подставлять нечего. */\n readonly missing: ReadonlyMap<string, readonly string[]>;\n /** Компаньоны разложенных правил: имена этого дерева, которые пишет проект. */\n readonly companions: readonly ICompanion[];\n /**\n * Файлы, лежащие в дереве от ресурсов, от которых проект отказался.\n *\n * Отказ значит «больше не клади», а не «убери»: разложенное коммитится, рядом с правилом\n * лежит написанный проектом компаньон, и стирать это молча пакет не вправе. Но и молчать\n * нельзя — брошенный файл читается как действующее правило, и агент по нему работает.\n */\n readonly abandoned: readonly string[];\n /**\n * Ресурсы, у которых виды есть, а вида под выбор дерева нет.\n *\n * Пропустить такой ресурс молча значит разложить правило и не разложить инструмент, который\n * оно зовёт: дерево получает указание без исполнителя и узнаёт об этом, когда команда из\n * правила не находится. Поэтому непустой список — отказ раскладки наравне с дыркой без\n * значения и с файлом, который правили руками.\n */\n readonly gaps: readonly IGapOfVariant[];\n /**\n * Разложенные гарды, которых нет в настройке агента: файл лежит, а позвать его некому.\n *\n * Раскладку это не отбивает — настройка принадлежит дереву, и пакет в неё не пишет, — но и\n * молчать нельзя: гард, который не зовут, неотличим от гарда, который всё пропускает.\n */\n readonly unbound: readonly IHookBinding[];\n /**\n * Выбранные ресурсы, чьи требования в дерево не поехали.\n *\n * Предупреждение, а не отказ: дерево вправе закрыть требование своим средством, но обязано\n * знать, что закрывает. Молчание же оставляет его исправным на вид — сверка зелена на любом\n * подмножестве, сколько бы связок ни было разорвано.\n */\n readonly broken: readonly IBrokenLink[];\n readonly written: readonly string[];\n}\n\n/** Шаблон черновика компаньона — тот же, что пакет кладёт проекту в шаблоны. */\nconst COMPANION_TEMPLATE: string = 'templates/implementation.md';\n\nconst read: (path: string) => string | null = (path: string): string | null => (existsSync(path) ? readFileSync(path, 'utf8') : null);\n\n/**\n * Тело ресурса: текст пакета, поверх него надстройка проекта, и уже потом подстановка значений.\n *\n * Порядок именно такой. Надстройка тоже пишется с дырками — иначе проект, дописавший раздел про\n * свою главную ветку, зашил бы её имя в двух местах: в конфиге и в тексте.\n */\nfunction renderAsset(asset: IAsset, config: IConfig, root: string): IRenderResult {\n const override: string | null = read(join(root, OVERRIDES_DIR, asset.id));\n const merged: string = override ? renderDocument(mergeDocuments(parseDocument(asset.text), parseDocument(override))) : asset.text;\n\n return renderVars(merged, config.vars);\n}\n\n/**\n * Что лежит в дереве от ресурсов, которые проект больше не берёт.\n *\n * Ищется по тем же правилам раскладки, что и всё остальное: путь ресурса вычисляется так, будто\n * его кладут, и проверяется, лежит ли там файл с шапкой пакета. Чужой файл на том же пути\n * брошенным не считается — его пакет не клал.\n */\nfunction abandonedOf(config: IConfig, root: string, assetsDir: string): readonly string[] {\n const taken: ReadonlySet<string> = new Set(collectAssets(config, assetsDir).map((asset: IAsset): string => asset.id));\n\n return readCatalog(assetsDir)\n .filter((entry: IEntryOfCatalog): boolean => !taken.has(entry.id) && matchesVariant(entry.variant, config.variants))\n .map((entry: IEntryOfCatalog): string => targetOf(entry, config.layout))\n .filter((path: string): boolean => {\n const existing: string | null = read(join(root, path));\n\n return existing !== null && readStamped(existing) !== null;\n });\n}\n\n/**\n * Что о себе говорят гарды, которые дерево берёт. Читается у ресурсов, а не у разложенных\n * файлов: карта нужна и до первой раскладки — чтобы было что вставить в настройку.\n */\nfunction bindingsOf(config: IConfig, assetsDir: string): readonly IHookBinding[] {\n const bindings: IHookBinding[] = [];\n for (const asset of collectAssets(config, assetsDir)) {\n if (asset.kind !== 'hooks') {\n continue;\n }\n bindings.push(...declaredIn(asset.text, asset.target));\n }\n\n return bindings;\n}\n\nexport function planSync(config: IConfig, root: string, version: string, assetsDir: string): ISyncResult {\n const planned: IPlanned[] = [];\n const missing: Map<string, readonly string[]> = new Map();\n const companions: ICompanion[] = [];\n const template: string | null = read(join(assetsDir, COMPANION_TEMPLATE));\n\n for (const asset of collectAssets(config, assetsDir)) {\n const rendered: IRenderResult = renderAsset(asset, config, root);\n if (rendered.missing.length) {\n missing.set(asset.id, rendered.missing);\n continue;\n }\n planned.push(\n planFile({ path: asset.target, asset: asset.id, version, rendered: rendered.text, existing: read(join(root, asset.target)) })\n );\n if (asset.kind === 'rules' && template !== null) {\n companions.push(planCompanion(asset, read(join(root, pathOf(asset))), template));\n }\n }\n\n return {\n planned,\n missing,\n companions,\n abandoned: abandonedOf(config, root, assetsDir),\n gaps: variantGaps(readCatalog(assetsDir), config),\n unbound: unboundHooks(bindingsOf(config, assetsDir), root),\n broken: brokenLinks(readCatalog(assetsDir), config),\n written: [],\n };\n}\n\n/** Раскладка. Отказ хотя бы по одному файлу не пишет ничего: половина разложенного хуже целого. */\nexport function runSync(config: IConfig, root: string, version: string, assetsDir: string): ISyncResult {\n const result: ISyncResult = planSync(config, root, version, assetsDir);\n if (result.missing.size || result.gaps.length || result.planned.some((entry: IPlanned): boolean => isRefusal(entry.outcome))) {\n return result;\n }\n\n // Право на запуск переносится с файла в пакете. Без него гард отвечает отказом доступа, то\n // есть ненулевым кодом, а ненулевой код у гарда значит «правка отбита»: разложенный набор\n // отбивал бы подряд всё, включая сборку и тесты, и причина при этом нигде не называлась.\n const executable: ReadonlySet<string> = new Set(\n collectAssets(config, assetsDir)\n .filter((asset: IAsset): boolean => asset.executable)\n .map((asset: IAsset): string => asset.id)\n );\n\n const written: string[] = [];\n for (const entry of result.planned) {\n if (entry.content === null) {\n continue;\n }\n const path: string = join(root, entry.path);\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, entry.content, 'utf8');\n if (executable.has(entry.asset)) {\n chmodSync(path, 0o755);\n }\n written.push(entry.path);\n }\n\n // Черновик компаньона кладётся только там, где файла нет вовсе. Он без шапки и без суммы:\n // сверять в нём нечего — с первой правки проекта это его текст, а не текст пакета.\n for (const companion of result.companions) {\n if (companion.content === null) {\n continue;\n }\n const path: string = join(root, companion.path);\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, companion.content, 'utf8');\n written.push(companion.path);\n }\n\n return { ...result, written };\n}\n\nexport const pendingOf: (result: ISyncResult) => readonly IPlanned[] = (result: ISyncResult): readonly IPlanned[] =>\n result.planned.filter((entry: IPlanned): boolean => isPending(entry.outcome));\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rt-tools/agent-kit",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Переносимый слой правил для агента: законы, хуки, проверки и агенты, раскладываемые в репозиторий одной командой",
5
5
  "author": "RT Team",
6
6
  "license": "Apache-2.0",
Binary file
Binary file