diff --git a/.skills-sync-state.json b/.skills-sync-state.json index 8bd87ac5..33dfe428 100644 --- a/.skills-sync-state.json +++ b/.skills-sync-state.json @@ -15,22 +15,22 @@ "status": "synced" }, "framework/rules/agent-context-protocol/SKILL.md": { - "ru_hash": "sha256:29c0707c3c85e29dd657942382b38d9e5feb3236ca48f1398b08d55c8fc1cf49", + "ru_hash": "sha256:c1e3d444e5065a67863d1c17b08f2c51e512fabe115c46f5b9c6896839cae30c", "en_hash": "sha256:bb5cdc9693cb633a50ee2e02ed622b06149c715331694e04d029f01dac0b8dc3", "synced_at": "2026-06-22T22:05:43Z", - "status": "synced" + "status": "dirty" }, "framework/rules/sdd-policy/SKILL.md": { - "ru_hash": "sha256:195efb80c45e971ff795d52f1a46985d1863774f0a3fa4330eada88e3f0fbefd", + "ru_hash": "sha256:76178e1fc7f256f4332802780acc84fe6dabf52704ea81e0a6dadecc773fe0f0", "en_hash": "sha256:b194753a2d453bcb801bbf6a59beae4a2b41f40209bde4e8dff67c410e1d91fc", "synced_at": "2026-06-22T19:10:38Z", - "status": "synced" + "status": "dirty" }, "framework/rules/tdd-policy/SKILL.md": { - "ru_hash": "sha256:344b4c601b9afbe523fd5817c08d6ca59f72b770484a0394ff0e72e13e5edfd7", + "ru_hash": "sha256:e4b9ebfc76769a19b73ad80748eea8d3587904a5aba02c57eee53d1b509f1830", "en_hash": "sha256:530ef8fafaeb328383078061022025fd27a143524ac86a5e82975a1ca3379957", "synced_at": "2026-06-22T20:45:12Z", - "status": "synced" + "status": "dirty" }, "framework/skills/_template-skill.md": { "ru_hash": "sha256:72b88d1f50eb242a340a807d06baf5139542372d6b03b0acad22093fd04da4c7", @@ -39,46 +39,46 @@ "status": "synced" }, "framework/skills/bsl-practices/coding-standards/SKILL.md": { - "ru_hash": "sha256:f0cf2cac4a70f4b5115a101e6caad12d9f131304ec5b6199f4a21ce65076b66a", + "ru_hash": "sha256:8bd94971c7121044e28b21b9b999086f3724d11f9ea90a34d1eaa3fc41a338cd", "en_hash": "sha256:3e309cf654c1955f8fb051dfca3697372ff040a3a1300102a9bc476de8574d94", "synced_at": "2026-06-04T15:52:50Z", - "status": "synced" + "status": "dirty" }, "framework/skills/bsl-practices/error-handling/SKILL.md": { - "ru_hash": "sha256:62bc001d00d95ac55c0e6b02b27243ecea0b95c1896a672e047b3dfd4ef0059c", + "ru_hash": "sha256:3815f02241c86f1c4fd173007783a8037ff2d56c5601969695ae028522a7d455", "en_hash": "sha256:8f30246482fe673e93d4a35cadb054fc5604fe72d7ee4c44a0e0ecf938a92d1b", "synced_at": "2026-06-04T15:54:08Z", - "status": "synced" + "status": "dirty" }, "framework/skills/bsl-practices/form-patterns/SKILL.md": { - "ru_hash": "sha256:27d7fef41cdee991191d9b8a3b72c0ae38c248930c601dfeadfa48d24cd781ad", + "ru_hash": "sha256:6297c272af7e06bd778c2ed895e5b8fc4a8db301a70ef88a367396c879063ca0", "en_hash": "sha256:e41273b69bf4248d70a634ae143c2c303dff369b9a1c6d47f73f36f88f2f076f", "synced_at": "2026-06-04T15:54:05Z", - "status": "synced" + "status": "dirty" }, "framework/skills/bsl-practices/form-visual-requirements/SKILL.md": { - "ru_hash": "sha256:60c874ecdd0326cbdfc1d079036bff13bf47f86ab243d8b9f7af603c0ee345a6", - "en_hash": "sha256:eba6bd9f09c37307e14ed9c0b4f081163f92f57cd0d16807dcc5da28a7fc12c9", - "synced_at": "2026-06-04T15:52:53Z", + "ru_hash": "sha256:97300f914bde35d3726e6a1150548da45f33701893e86e4287a6fbacc395f6d4", + "en_hash": "sha256:90a918c9e3d2a8260083aa4028add4d6309c80f9840381c8818468e560324e82", + "synced_at": "2026-06-27T05:49:11Z", "status": "synced" }, "framework/skills/bsl-practices/query-patterns/SKILL.md": { - "ru_hash": "sha256:0b16f5dc19923d63c07822db76505edd6f83f27c0a7fbabd8ef383b8efb21440", + "ru_hash": "sha256:3713aebe10ffa589d0ab88180c2f6510a4e6a3bb8dc88c88d6471ab57ffd00eb", "en_hash": "sha256:c690c67401c66a4f0162d95c31c43f07ccdd7fd5d272c20accf3dd9dbf52014d", "synced_at": "2026-06-04T15:54:06Z", - "status": "synced" + "status": "dirty" }, "framework/skills/bsl-practices/ssl-patterns/SKILL.md": { - "ru_hash": "sha256:637bf0da617b9e2aa7c2d2decfba3f3128b9e2d2d82287bcaa49b07a4a10ed6b", + "ru_hash": "sha256:8e3b67efe335971a399f6c8f83dd3e3786a7c0d07efef74d7cad4586faea0f8d", "en_hash": "sha256:cc8851de346d429f69243c5610e72a1aee24fe27d100747173d855f191518a43", "synced_at": "2026-06-10T23:33:20Z", - "status": "synced" + "status": "dirty" }, "framework/skills/bsl-practices/test-writing/SKILL.md": { - "ru_hash": "sha256:68c99cf3679b4ee4c06a66e556e01634dddc1a85161ac20685188da9c581a287", + "ru_hash": "sha256:f833aafa268c760e7b12be3e63f442be39c5ff69c31a0cb8d7c948d59940527e", "en_hash": "sha256:1e7754fe2af18cf35fec4ee46422cee93a2372e039419c810d9afb22b9ebb53e", "synced_at": "2026-06-22T10:55:00Z", - "status": "synced" + "status": "dirty" }, "framework/skills/bsl-practices/test-writing/references/yaxunit-cheatsheet.md": { "ru_hash": "sha256:dfb05a33170c5cbf66066eabf65bb44e484af2c012d3b575669380221e8a1382", @@ -153,10 +153,10 @@ "status": "synced" }, "framework/skills/other/find-skills/SKILL.md": { - "ru_hash": "sha256:8705dd3c8b791b82b9f1b0368abb61a390b3edf89da672d6c5afedad2748e225", + "ru_hash": "sha256:3c1b7c0e966cb90d78532ec3869b7783a5edf4023b8c828435a0daa400c797be", "en_hash": "sha256:02d6f9aa0ca0d5168c3fbffb44b2ca9f5a2ccdd5c84670b0e8f36b76bcf9ad0a", "synced_at": "2026-06-04T15:54:06Z", - "status": "synced" + "status": "dirty" }, "framework/skills/other/find-skills/domains.json": { "ru_hash": "sha256:4727a1588547785e43bd7de4ecde9d6bc691bfa5bee971bdd4dc564d756b9906", @@ -165,16 +165,16 @@ "status": "synced" }, "framework/skills/spec-writing/spec-standard/SKILL.md": { - "ru_hash": "sha256:d080776b5221d7e6adeb86cb5fd7e186f01f2243c5f39f779ffbb233908f31fc", - "en_hash": "sha256:6fd62df18721819e9701673c4d105003ba78b049685dc29bd7307fba696bc23f", - "synced_at": "2026-06-12T08:11:57Z", + "ru_hash": "sha256:d0408615ea204a61d416e02f401892546b075223b31fa255ad267e2b76f1cca6", + "en_hash": "sha256:7b49625e208477dbf956f0828fdda6572d3efc08efa279232347bcb9af34da1b", + "synced_at": "2026-06-27T07:13:57Z", "status": "synced" }, "framework/skills/spec-writing/technical-design-standard/SKILL.md": { - "ru_hash": "sha256:d4e21e2fedf6c41f52c3b270a6a2c665636bb02c52ef6b4879aa135461fc7ed1", + "ru_hash": "sha256:6bcbe6b03f95737860ade23d0a4e4011f3246b6205069a05b13d842a5f28b2aa", "en_hash": "sha256:42f31e1370ba1d8005470df6686ec9d4da9abc8a7d1adf5b50ee55d8e8febb4c", "synced_at": "2026-06-04T15:55:17Z", - "status": "synced" + "status": "dirty" }, "framework/subagents/_template-agent.md": { "ru_hash": "sha256:4e0fd4f11a6ccfa2400262c7cb66549eefaf6c10d64d99775250370072cd05c2", @@ -183,10 +183,10 @@ "status": "synced" }, "framework/subagents/analyst.md": { - "ru_hash": "sha256:8b821bd66e58d4824875cd15d7678ff6080e70f4eb45532a831fdbb7646b7135", + "ru_hash": "sha256:b1a520df8b95fbe299bfc05e43a0c20150303d4954f62872954a1239d04272da", "en_hash": "sha256:9e027878b10e21da4c65c147e46d53a02906394382b81bcd21aa75acf591ba0d", "synced_at": "2026-06-22T21:23:54Z", - "status": "synced" + "status": "dirty" }, "framework/subagents/architect.md": { "ru_hash": "sha256:5516d49a1c0a8ad140810f15caf7af16cbc726ff6ad99cdcebab0be53b074f83", @@ -219,28 +219,28 @@ "status": "synced" }, "framework/subagents/tester.md": { - "ru_hash": "sha256:9cd052f02f2d23e78254e6ad58f2b0b472127b6ef6bba6a46af9bcd749de1f45", - "en_hash": "sha256:e2df5d80be1ea9efc2cfbf62ad2bda798a02c1da75d9eb35e39f833204ba5dd3", - "synced_at": "2026-06-22T21:16:54Z", + "ru_hash": "sha256:976e4ff54f698fdb27049052acab5df449475bed6cf948956a8c0cf4c4e80e0c", + "en_hash": "sha256:31c719ffb0402f4601e8d9b52f36312b98b94df561c9e3b2ff3eb2899a4f5c46", + "synced_at": "2026-06-27T06:23:01Z", "status": "synced" }, "framework/workflows/full-cycle/SKILL.md": { - "ru_hash": "sha256:0bf1133da7e1a1541ff2d89feb5af6694e8c79399259664371ea238b60f27b44", - "en_hash": "sha256:32350e6c226e926ab89437d3d28674a40d9fd31c36f5caf943470b9645988058", - "synced_at": "2026-06-26T10:38:17Z", + "ru_hash": "sha256:c1656f5c29bd08b23dcd8663ef028355d8e1f2cd4af957f44b621612f11a2446", + "en_hash": "sha256:8002a17ae26e2d03bf898dd79b87edcc3eb69363b5fc7cbb7259f153022cb68f", + "synced_at": "2026-06-27T05:50:19Z", "status": "synced" }, "framework/workflows/orchestrator/SKILL.md": { - "ru_hash": "sha256:8bf74217703778a69a91ecad5ab54c1bf912611df28175a417b998710c93d9ce", + "ru_hash": "sha256:27f48e14a6b7cd7b4e1066d487683fcc92868618b713c140226e29bbd139de64", "en_hash": "sha256:433e35acd32e2d0488ce66f5f0f3687cc2e21981b5128e13d2b626eefdad9dbc", "synced_at": "2026-06-22T22:04:14Z", - "status": "synced" + "status": "dirty" }, "framework/workflows/quick-fix/SKILL.md": { - "ru_hash": "sha256:a294be3228606d46e55c3fbf82a062c8bc75434626509c3f47e86997093809a8", + "ru_hash": "sha256:6c7b3ad275c69560f1e916ed3108729491270dca409eb7c3aa52cd838e8ae758", "en_hash": "sha256:679ee7fb787424c7cf7166553e8931353cd8ada3ca7e50d96203b83cc7bfdd15", "synced_at": "2026-06-22T22:04:14Z", - "status": "synced" + "status": "dirty" }, "framework/skills/framework-meta/skills-i18n-sync/SKILL.md": { "ru_hash": "sha256:c3fd0693f697379f2ff88d7e6f97ef71743c328c451ada59cf6fad927fa9fd0f", @@ -249,9 +249,9 @@ "status": "synced" }, "framework/skills/tool-usage/browser-ui/gui-control/SKILL.md": { - "ru_hash": "sha256:9f07c013bf8ca76957894453dd7e35d7d1f65d7ad092183e06b8096432720f7d", - "en_hash": "sha256:0a33f6bfa2d7030a1a61305ed7f2c139190cdcd826b3c550745675753fb36de3", - "synced_at": "2026-06-04T15:54:38Z", + "ru_hash": "sha256:69dd702e1eb65054fff05ba57589d6c1c4faeb1d4d3a035891dccc096845af9c", + "en_hash": "sha256:b467d4ec3b140f4671a625299ec40a2c5e423885db8bd63ac5cee4157f1ff75e", + "synced_at": "2026-06-27T05:57:23Z", "status": "synced" }, "framework/skills/tool-usage/browser-ui/playwright/LICENSE.txt": { @@ -267,9 +267,9 @@ "status": "synced" }, "framework/skills/tool-usage/browser-ui/playwright/SKILL.md": { - "ru_hash": "sha256:aa0f7d3f1bb6358bd30a8b8f6c174b48e3635922c67b4c2dd87b5b3112a9631b", - "en_hash": "sha256:a574f031ce62b46c87debe5d9d5846ed45cc702e8befce52d52efb8869b10fe8", - "synced_at": "2026-06-04T15:54:17Z", + "ru_hash": "sha256:2c34999fdb3f6f284d1e6742ea0d9f87dcfa9f1c410187b7ab26c6ca78aa4968", + "en_hash": "sha256:58e6342391fe1a54afa6571f622df44d3cdaf4ed2a99868123b3c9aec48c5a46", + "synced_at": "2026-06-27T05:58:03Z", "status": "synced" }, "framework/skills/tool-usage/browser-ui/playwright/agents/openai.yaml": { @@ -321,9 +321,9 @@ "status": "synced" }, "framework/skills/tool-usage/browser-ui/playwright-interactive/SKILL.md": { - "ru_hash": "sha256:705ae095127673a3d86421eb6ad3c0e53707960f3039bdd14971d03702d8166d", - "en_hash": "sha256:dfd1812cba03dd6a46621bf77089ec0f4a97267df1acbcaf1e887651639fe018", - "synced_at": "2026-06-04T15:54:33Z", + "ru_hash": "sha256:9eb889c2cb34bf791cf6483312994c5ca5f12a39581609a17a0b5c9ca529e6b7", + "en_hash": "sha256:70f66acb44e1c3531f7580be3011f2de3b483c2c65b6cd1906fdee57f8dd98f5", + "synced_at": "2026-06-27T05:59:25Z", "status": "synced" }, "framework/skills/tool-usage/browser-ui/playwright-interactive/agents/openai.yaml": { @@ -351,9 +351,9 @@ "status": "synced" }, "framework/skills/tool-usage/browser-ui/screenshot/SKILL.md": { - "ru_hash": "sha256:1d9b3f78106fe2687a5eb3d805c87acab8c409e446c7186a514c17d4daec2176", - "en_hash": "sha256:7c102961cc98d0dea878f2c3791ad0d6d83779297c9b889b1b2ae69ca0a01ac9", - "synced_at": "2026-06-04T15:54:27Z", + "ru_hash": "sha256:ee4eb6622f8b947bb385af463f7ac62b3c81dc718f79528fecb2cc376159edde", + "en_hash": "sha256:2f432c90fca5420b1bbaf2b88791b0ca4a70e59e59a2afa5308b9f9c909e4390", + "synced_at": "2026-06-27T06:00:25Z", "status": "synced" }, "framework/skills/tool-usage/browser-ui/screenshot/agents/openai.yaml": { @@ -411,99 +411,99 @@ "status": "synced" }, "framework/skills/tool-usage/browser-ui/visual-check/SKILL.md": { - "ru_hash": "sha256:c1825059edd9fcd0b56ebb6508a30556e606c0f3dca18b3fbb95f16c027992a5", - "en_hash": "sha256:b0ba892afaa713eea879daf34920b7cecf3b12f4ba6c3048df476fbf80f3ac83", - "synced_at": "2026-06-04T15:54:59Z", + "ru_hash": "sha256:ecd263c70ee76998c9875f92906d84488a74f07cce3ac041d42bf23f5252f83f", + "en_hash": "sha256:c9fcf845cba6bfe77f7af9e2e3ab74a9dfda57082a8232b0a4e2ee1b65c0c962", + "synced_at": "2026-06-27T05:46:53Z", "status": "synced" }, "framework/skills/tool-usage/code-analysis/code-navigation/SKILL.md": { - "ru_hash": "sha256:b5f2b87337bcd2c7f9e62f6021a429dd8d6ea4dd9d97f6d93e010555fecc8f7c", + "ru_hash": "sha256:d5ec652ae9a742cd837cc14c1213b46e734f1fb234492e4ec6b6a584292efe78", "en_hash": "sha256:5b78c2d702fac74405ecd0e06605ac94d5474532e9b66174850a0bd5f2ad7405", "synced_at": "2026-06-12T08:07:39Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/code-analysis/search-before-write/SKILL.md": { - "ru_hash": "sha256:4f541ed0fd6f26e791f4fc396177cfbe32dccdbe2ae84464810d2f1d344168af", + "ru_hash": "sha256:58716e10c74b52a57866f2de9c57f5e2033d1626f75bdd0b037816a37bed7f6e", "en_hash": "sha256:67292c7c8aa3233fb89336eea93c5eaaa605563eb849ff52d891b9c1a3e4e088", "synced_at": "2026-06-04T15:54:57Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/code-analysis/syntax-checking/SKILL.md": { - "ru_hash": "sha256:9248646b24a603da3bc0ee06d0ceebb98f22b9b35605e9a163545e2521af4e0a", + "ru_hash": "sha256:ab7c9f6b9d5b2f729f07b3599e4eb2c69be8a394a63f240b8db74e17384c1956", "en_hash": "sha256:f3090b5b8c542eaf22f61f282eb09d13a1c2106ce7edb300de2a4165eabbf689", "synced_at": "2026-06-10T23:34:51Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md": { - "ru_hash": "sha256:7591b14972eb084c9e6bf5d30036fb4b5691748fc6549bec0e6c8bd896b376c1", + "ru_hash": "sha256:b244d99dea87d713845e216c5e17a4f920d2849da9f7d87e514b72c8e3ccfd34", "en_hash": "sha256:110090e09ee3a369ada3cf838563f4c4395cdca7b55554d15cd218e6a2d9fac4", "synced_at": "2026-06-04T15:55:06Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/diagnostics/tech-log-analysis/SKILL.md": { - "ru_hash": "sha256:9b1746536ff6a44747d37bde3672953a4184805068de8dfccdb4ac5769ea9332", + "ru_hash": "sha256:1adce318962cc1c53dc03bbd66057795badbe8af7c61c2253817e18a6874973f", "en_hash": "sha256:66844ebce1b7b187a57033c299aa4daa0fe55e7da5400a87dd50227a80b801b1", "synced_at": "2026-06-04T15:55:22Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/form-dsl/SKILL.md": { - "ru_hash": "sha256:eae7f9a1e7432105cb1ddeda4e62087f10f534ba7f7795e004012ba557ccc18f", + "ru_hash": "sha256:e32d9b8e276c4d1ce884c0e1188b217273e65e70365a51d30fbe6991fb6126ee", "en_hash": "sha256:2841a3161a7781f9e1e3efc19231aaa52183b6ddcc587c86d1a4bc72b56d353d", "synced_at": "2026-06-22T11:54:01Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/mxl-dsl/SKILL.md": { - "ru_hash": "sha256:69bd0c2609442b783070bf87c465a1b33ed7ef3f6054ed64f15bb2da52646a75", + "ru_hash": "sha256:b5c4f0f7e0a845d39dbdf0d10ad7cbc982edf7a360f5b5afee50e6720def1467", "en_hash": "sha256:218eb09a4e95f87dc23be9ba46a1efa4fee30b044152d7eacae0e81af19d260e", "synced_at": "2026-06-04T15:56:07Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/role-dsl/SKILL.md": { - "ru_hash": "sha256:75fd8a431c0a67e50884c9ec64da5f99ba1a6130e6951c0763ddb5900938b68a", + "ru_hash": "sha256:35dc466ec08f280a15942a362feb163a1cdd3d626c11e3203bc5de3469d3668a", "en_hash": "sha256:6e064f1898edcd078473cfdfcaa540084ee0412b1d6a8621481d222e547da8c6", "synced_at": "2026-06-04T15:55:39Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/skd-dsl/SKILL.md": { - "ru_hash": "sha256:6ad3f69ca6f76b46954a84561a4d082463251e589cc4205631c0cf2110f00522", + "ru_hash": "sha256:92e76e69dd2245fb92a0b7911d46f5082aea194780b096fcb110dbdbcab50286", "en_hash": "sha256:290d779b7ad62f852cc11867982effbe45e76ca69b064a78cacb4ea334b258f6", "synced_at": "2026-06-22T11:24:59Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md": { - "ru_hash": "sha256:6dbe76771ff092ea46b928a7595d78767bd1e4364bf472c67bb4fc9c149d6ab7", - "en_hash": "sha256:092f1f46e8aefd713341ad2f5a870e4392a1b0f0d161e21090e208ce7dfd14f4", - "synced_at": "2026-06-26T10:38:17Z", + "ru_hash": "sha256:469447dc2e2a4834b5a2d139cd67ccc1302ef814bcb3a40e70eede95c9bb6726", + "en_hash": "sha256:6a444cf5950cc54dc228d1b77bae5d2afc1b1f2560ce7ccb7ded8ec00ba3c9fd", + "synced_at": "2026-06-27T13:27:15Z", "status": "synced" }, "framework/skills/tool-usage/vanessa/vanessa-diagnostics/SKILL.md": { - "ru_hash": "sha256:3e3cfa14d2e715dc8da5bc6675c1cb16365354991fbc78ec3dd7d94146f53319", - "en_hash": "sha256:6b2774c20e7d5a7012751d7593445a5b14eb991db7e9675e44d948a7860c26f8", - "synced_at": "2026-06-22T19:04:53Z", - "status": "synced" + "ru_hash": "sha256:d982c3d75574f9e82412dc8b78c1481bd1dd057ea32144ba3493769284f23488", + "en_hash": "sha256:c765e2cb37d6bcfc733a1726da36cfdf5206b49ab20fcefb0ed0ca7b30781d8f", + "synced_at": "2026-06-26T23:33:49Z", + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/config-operations/SKILL.md": { - "ru_hash": "sha256:e527136011e8d33e80e18cf51c501a171c4fc4836bbd502f420a53b749d42580", + "ru_hash": "sha256:7f4ec6009353b8a2b2372abfb54ee64d9690055617e8e26025f9d0a52611cc6c", "en_hash": "sha256:883ae5f809c17179e78bec136c8d4524103a9426d4ff899a91328089f50e80ff", "synced_at": "2026-06-04T15:55:44Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/meta-operations/SKILL.md": { - "ru_hash": "sha256:3a5e6e24fc24ae9f51439b5ab0803748a420386902a11d53ca58caca11b4bd0f", + "ru_hash": "sha256:6f4736bd46b774229490bc4141875e2981242366fea17531b5d2e412c5364c8e", "en_hash": "sha256:00a59f674184d7a127cb215cadc4c08f46cdf1401688ba1e387c7fa33a6cac39", "synced_at": "2026-06-08T22:26:10Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/extension-operations/SKILL.md": { - "ru_hash": "sha256:485cd376fd22737f95b08c39d3ef30a4d3cc2d1216ab555df4957152be802274", + "ru_hash": "sha256:6fa6d2b42870afb34db1589541bbaca6a11090fd0227086ac1f6a2d944bf4649", "en_hash": "sha256:1889f216e43f293fe5dc851c9596c686f6680d10d5cbec826b6788d7fd257cd3", "synced_at": "2026-06-04T15:56:18Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/browser-ui/web-test-1c/SKILL.md": { - "ru_hash": "sha256:ff1d65a8150f5db4e0bfe050caa324307cfd9eebe0e1b0112fd715e50c0a538b", - "en_hash": "sha256:78a2ae9c9c3c9a129ebfd0a035bc46206c238e03dfd2ff8c836afa34eed8222f", - "synced_at": "2026-06-22T11:37:26Z", + "ru_hash": "sha256:bf649eb534abce5b8328b694b5f08284082014bb6be7f3b1868bf3bc1d5756dc", + "en_hash": "sha256:cacecab415b698726e0b5b31c232d200cf892218498d2b4d58bacf15627d8e13", + "synced_at": "2026-06-27T06:02:51Z", "status": "synced" }, "framework/subagents/scenario-author.md": { @@ -513,10 +513,10 @@ "status": "synced" }, "framework/skills/framework-meta/skill-editing-from-project/SKILL.md": { - "ru_hash": "sha256:faf202775a674abc4dfb8b49f1173ccf8610b34e828df6da68471f9b4e425a96", + "ru_hash": "sha256:a3c3674c5dff0eccaf005ddb4230fffb6fca11d000f3e1f4f1d7710a4ec7d227", "en_hash": "sha256:a996b7d47399d7ff60c04d8c657e7d7d0763ff0f3d80d8a301ba1ad47f71c20a", "synced_at": "2026-06-22T10:46:04Z", - "status": "synced" + "status": "dirty" }, "framework/skills/framework-meta/skill-drying/SKILL.md": { "ru_hash": "sha256:f388bfe0b05fa9fea516fc65b1dfb698792ea5bebf1d7ccb96cddd56248d959c", @@ -549,94 +549,94 @@ "status": "synced" }, "framework/skills/tool-usage/platform-admin/rac-use/SKILL.md": { - "ru_hash": "sha256:4a85383bc799436f6f7abf8fd480c5bb85119bf7b976917d033194567cbafc24", + "ru_hash": "sha256:f76478fc943dcbf360a3c9e4179047255bd9d5c420a84039f9a89327530561d8", "en_hash": "sha256:783bf84af08a89af7a6bbe5a7aba44c97e62a25a5dee3450dc34308fcfd5d240", "synced_at": "2026-06-04T15:56:33Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/vanessa/vanessa-authoring/references/learned-patterns.md": { - "ru_hash": "sha256:90082064d49d72c0a2437eca549b070bcb9f73a247a8fb83d62006bba9d4b2ed", - "en_hash": "sha256:1067b4b88e2faf1d829926b1a63733f68154a219a58aabc2afe7b54b450a0ee9", - "synced_at": "2026-03-25T09:25:45Z", + "ru_hash": "sha256:465a515112302b673a7a97375001305b6fa6fc590f195ab027c1cca111cc1ec4", + "en_hash": "sha256:cdc267e1c40ac55ae9b367de9e4b40a7f4172c651f3a349ad839e7a58c0a0876", + "synced_at": "2026-06-27T06:20:52Z", "status": "synced" }, "framework/skills/tool-usage/diagnostics/agent-debug/SKILL.md": { - "ru_hash": "sha256:cf05e264ab535bc285f3b07f84d32919c3f085e86238924f1e7e12f29ea381ca", + "ru_hash": "sha256:6dba7b001ab2e61dce644591c46f361855873c076f8ad0c8611779186f55b599", "en_hash": "sha256:22b28d6b84f47d023dad0ceb3b0c0af68c522bbbc6c8407e9b5adb65d13b2b10", "synced_at": "2026-06-04T15:58:06Z", - "status": "synced" + "status": "dirty" }, "framework/workflows/source-of-truth-policy/SKILL.md": { - "ru_hash": "sha256:c2ac6932419fa5558bc5c15b5a7e74ffc1454b603415f6dfe13ee129ae865db7", + "ru_hash": "sha256:5d7b7fe705593308ac0672264a9daf24e9f3ec49fe9a2967a8eab2aba991c4dc", "en_hash": "sha256:3eec5070131e351fceff0c6eaa8fa8e28bcfb62c93dfc821e94326a0c80d8207", "synced_at": "2026-06-22T22:05:43Z", - "status": "synced" + "status": "dirty" }, "framework/rules/capability-resolution/SKILL.md": { - "ru_hash": "sha256:53856199484d0c48977c09e8c15bed326febac225c25ba017bdc814719892408", + "ru_hash": "sha256:0b152b94266f351df19f22b7a18fb03ae11b94a0a1cae5d0f9e977c936a0cd7d", "en_hash": "sha256:78395d0bb32749e22a9915bcd362b6e0acdc412a5d4798f19c12cd478c4db89d", "synced_at": "2026-06-04T15:56:43Z", - "status": "synced" + "status": "dirty" }, "framework/rules/framework-bootstrap/SKILL.md": { - "ru_hash": "sha256:5231ae968f7a41cf326f83db18e550bbfc107e44dc6760ea97f7988ad2527fb4", + "ru_hash": "sha256:a2a46723c29430e1a5f970210ac930049cb657bf349e5f238423fbd71cdeb05c", "en_hash": "sha256:b6b6d222629094c7692cfe679545f5a5c96b09dd7d16363372fc50d48363a1b3", "synced_at": "2026-06-22T22:04:14Z", - "status": "synced" + "status": "dirty" }, "framework/rules/protected-paths/SKILL.md": { - "ru_hash": "sha256:69e64fa5daba6cb170c4a44305d240b63ab23128983370603bf8c3ce4b7e41c0", + "ru_hash": "sha256:c84359970fad06d9c532efd92020a1d4e9aa57e84541b3ea5ca25f81b83a77ca", "en_hash": "sha256:5b25f9796775c55cf3f90b9c31a564f1e8b2387c59a9844a8663802eeeef47cc", "synced_at": "2026-06-12T08:06:31Z", - "status": "synced" + "status": "dirty" }, "framework/rules/skill-learning-policy/SKILL.md": { - "ru_hash": "sha256:66818310a6dfafc7567dabe30aa25d738609ab507029c70d5cc345813b3117ef", + "ru_hash": "sha256:4de8835f98a0878c958262f3d9a56d33521202b5be3025adf5b0ebf39041d9cc", "en_hash": "sha256:587d82720ece15d0efb6dc922799bbcdce0f145d2ccd25189b35283724d1a8bd", "synced_at": "2026-06-22T22:05:43Z", - "status": "synced" + "status": "dirty" }, "framework/rules/vanessa-diagnostics-policy/SKILL.md": { - "ru_hash": "sha256:ea072fb44f37bb9ecffb9db478a4bb9056c598e288f0ec8c65be7427446ad9a5", - "en_hash": "sha256:77e734d0b6a270fb45a0cd237fac823a4208fbc28fcdfe516b9e7c0d8654bf96", - "synced_at": "2026-06-04T12:04:12Z", + "ru_hash": "sha256:d07ef511e54f1c1cc25a343f83056bbccd78d02124f89e5fe4f81f0e0ada27cd", + "en_hash": "sha256:daed1afd5f53a5e5a8a145dbfb9779afd60c4064dc053ea7088ab783344a9f25", + "synced_at": "2026-06-27T05:53:52Z", "status": "synced" }, "framework/rules/vanessa-run-loop/SKILL.md": { - "ru_hash": "sha256:6f155ca8c334dce934a46dc8f782217d32bcf1e58397a5fb0bfaa299ff5f08fe", + "ru_hash": "sha256:8375c477ff56c7bb9d31d24effe708a32c9aeb0b73b21a2e63b4b9c6573f210e", "en_hash": "sha256:722e8d7e4618e1ca29aac8e92b8044e62aaf01da2e5b00e75577c95219df48ba", "synced_at": "2026-06-04T12:04:29Z", - "status": "synced" + "status": "dirty" }, "framework/rules/vanessa-scenario-policy/SKILL.md": { - "ru_hash": "sha256:67f2ec246cf59844aa645968bc5531c8ab3e1e687f8db27c493100f2e0bfeae5", - "en_hash": "sha256:a9749cb695c1d2d1f52fa44a2d3952816343247ae3a3c96a377bd8175d4cfe9a", - "synced_at": "2026-06-22T19:17:32Z", + "ru_hash": "sha256:d2ba83ff9a5167d8d5a530a9213f661cb26d2ab7de0481a8f6a75d4d72a81410", + "en_hash": "sha256:c99ea26e26f49e8301c91226dd9919a110f24cf915ce0e8c7a722ba347ea315d", + "synced_at": "2026-06-27T05:55:54Z", "status": "synced" }, "framework/rules/vanessa-security-warning/SKILL.md": { - "ru_hash": "sha256:71cb91411830e331198f70df2704bb073937c0ba2d59b2fc015bb685f8ba6088", - "en_hash": "sha256:4d901d72f1c8b2e5b2594dff0d513ad9eb8647777fed284f43ac0e0a1a4cd821", - "synced_at": "2026-06-04T12:04:20Z", + "ru_hash": "sha256:379a2a447d045bcb2c029123f529089fe7e7628ecd1ecbcfb1f42843ec5da689", + "en_hash": "sha256:996382858288ee2a73147f5008d8c305b37a07e73551ec814039add172e29737", + "synced_at": "2026-06-27T05:54:39Z", "status": "synced" }, "framework/rules/vanessa-test-isolation-policy/SKILL.md": { - "ru_hash": "sha256:944c26856f309848c2770e7ca0491c57a9c79e75eb21875cd4a70fc27ca0f995", + "ru_hash": "sha256:796cf451e762cd32cf8eef37f799b4d30f4d6295c5f1ba3c688ad721f27147c9", "en_hash": "sha256:026bcee2eb08801e6995bd4dcbfecca79dae21f7fead708d910535f4b980f1d2", "synced_at": "2026-06-22T19:05:18Z", - "status": "synced" + "status": "dirty" }, "framework/rules/vanessa-tests-location/SKILL.md": { - "ru_hash": "sha256:e4e76962d742e70bf4d92f3429388e7a4a464034a99625ea471adc95260b0e5b", + "ru_hash": "sha256:edca965a98371d83ce30c424a234f5ccb0b093cd65eca50adfe140cbc2993d93", "en_hash": "sha256:8baff8f591726b9e7fd7dee24f068c1e30fd08e0a8e28fba226b4230c8f5fc7a", "synced_at": "2026-06-04T12:05:13Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/code-analysis/buddy-prompting/SKILL.md": { - "ru_hash": "sha256:469a05c5cefa500196cc69085f5aaa9341cb6e0c76f006d40a6bb470234ec981", + "ru_hash": "sha256:62bc852b4a3d773c101058179bafd9f4c7221e089f8a1e208f778597f3384026", "en_hash": "sha256:3050caf3acde92838acecb1e7b9272a365a60cda82f4214e1dfbb211607d27f1", "synced_at": "2026-06-04T15:57:09Z", - "status": "synced" + "status": "dirty" }, "framework/skills/bsl-practices/test-writing/references/learned-patterns.md": { "ru_hash": "sha256:1198d9a4d835959b46028b66c296eecd49b9364af8fc2333d0cb650a6946e76a", @@ -645,28 +645,28 @@ "status": "synced" }, "framework/rules/no-direct-db-access/SKILL.md": { - "ru_hash": "sha256:40259f0f48e7528d161a749166e8ca283f44f4d48b3eb7e1eb1204ed1ba81e60", + "ru_hash": "sha256:818c7b303e78314d42eee5e7c0eab337aa66c2bb7b164123a716490af0a8ac50", "en_hash": "sha256:945c10095255b8291fa385c01b0ac33509a7bf35411d320f2c1af8bf8b1deba0", "synced_at": "2026-03-26T05:56:14Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-admin/subsystem-update/SKILL.md": { - "ru_hash": "sha256:4382d3a4a20543c6084afd247e0da4c9b3ba72005934fab32e0260dad9cbd7d7", + "ru_hash": "sha256:0e713e447f8b7ed9c83901211f38d6c9f7bc465bccb4780bf96c076a77d73fcc", "en_hash": "sha256:af9970f3f4707ab7a0f817d805d0858c47afaf86274cdba2c5ee7cfb1248433c", "synced_at": "2026-06-04T15:58:19Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/code-analysis/code-verification/SKILL.md": { - "ru_hash": "sha256:3248c395cc7047eb481e3e3037c111fcbb36c1e4ddf3a35ca711262c228d3e55", + "ru_hash": "sha256:0a5426fd472db4ae55393497d303a5ea182c1688edf432ae54922dc0b89e260b", "en_hash": "sha256:c6fa21eaa243bc7ab9a7554eff54bed44100074bc428683b7303e57a327f7a99", "synced_at": "2026-06-10T23:34:51Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/review/cross-provider-review/SKILL.md": { - "ru_hash": "sha256:cab9ccc14cba6697cbf4da107609bfdebb61e5c68337585c9450056dc53036ff", + "ru_hash": "sha256:9beb3f9b2c1daa06315407ffe7b8bf8bb4ba978499a8f82774c1b233ad9028e7", "en_hash": "sha256:27a8c96c3786f23802769444846b48be168912f1b63e9f0b3ba559846c3513e1", "synced_at": "2026-06-04T15:58:18Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/review/cross-provider-review/references/review-prompt.md": { "ru_hash": "sha256:0918df5fe78eb8208cc2e242cf14233f702b4f98762efe779f3300eca0236c27", @@ -693,10 +693,10 @@ "status": "synced" }, "framework/rules/no-manual-xml-edit/SKILL.md": { - "ru_hash": "sha256:17faf911f342a54df101c25380f3a4e1da38af7a3b2b55f60efedf8e59b3505e", + "ru_hash": "sha256:3cf01c43ece75e74b3dceb030b24696792fb8ef0ed61337818f150b20bb5dfbf", "en_hash": "sha256:0af8ac1c78f951bdf8a7022d4773aa966c4e541c2f9f51f2810536aaf65b756c", "synced_at": "2026-06-22T19:06:00Z", - "status": "synced" + "status": "dirty" }, "framework/subagents/scenario-coder.md": { "ru_hash": "sha256:9d059731590cd69f2d00fda649a146012725dcae68cf7095532ef5af1bde6766", @@ -705,16 +705,16 @@ "status": "synced" }, "framework/skills/tool-usage/diagnostics/bug-reporting/SKILL.md": { - "ru_hash": "sha256:cd9517a06c7a38e42254fa224274de9b4ae035d4581b7659e509a1b1a72c1fb0", + "ru_hash": "sha256:133dc3bbd75c01df25e5a6d5774cbbd4e85d0ca75a093c7a1a78a84bd935be7a", "en_hash": "sha256:24f26159ce049183133c420a37a43e1973e426b37999937c09d482fc27c6d08e", "synced_at": "2026-06-22T21:19:26Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/diagnostics/runtime-investigation/SKILL.md": { - "ru_hash": "sha256:4f2d476de31d746f52b50f8bbe1135dc6b783a08ed4567b55b4bdaf2fcefb882", + "ru_hash": "sha256:9ba84f503b8f6a1f677dcb8ff6a8cda16576aec5298cb20b88bc739f00f63986", "en_hash": "sha256:6663146b238ffca1257376a6a81f09982ce52440ebf51973ae5f6b09727e92dd", "synced_at": "2026-06-22T21:16:06Z", - "status": "synced" + "status": "dirty" }, "framework/subagents/debugger.md": { "ru_hash": "sha256:83292c200793c3a2eb9551f783ffbdd68e539808e40930a33c6687a6a2b20f6b", @@ -723,10 +723,10 @@ "status": "synced" }, "framework/skills/tool-usage/content-generation/codex-image-gen/SKILL.md": { - "ru_hash": "sha256:91dcbf0959b96ab653e1b330f7dc316536d4b925cfb0594db85357c36f1430e2", + "ru_hash": "sha256:4026b91987805afce90c6b2a4027868c41babebfddcbdf4e512019d8d07d1572", "en_hash": "sha256:238db9fc33f7a805bb66494ae212592e9ee13bb6a2a01d3cf817c584e8fc4069", "synced_at": "2026-06-04T15:59:33Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/content-generation/codex-image-gen/references/prompt-guide.md": { "ru_hash": "sha256:51b4933512b0674f27a3e6297d83a30b1b698285b6aacb8e900e099549e25b8d", @@ -741,15 +741,15 @@ "status": "synced" }, "framework/rules/escalation-format/SKILL.md": { - "ru_hash": "sha256:ff8e2c631e4aa01b193dcf6d445c1ab053cabbcc63ac82214100992e81e10401", + "ru_hash": "sha256:41d2300ad431abde44f10cc4f4b190808aacd068a8ec8a1a863a171a74ad81d3", "en_hash": "sha256:558d7d82487e3c7419ca7bbd031454d782b18499d05745870fbdce7f355a6fb0", "synced_at": "2026-06-22T22:05:43Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/v8-runner/SKILL.md": { - "ru_hash": "sha256:4c75024011414b2cefc602da1152052349acbbd1c2676f22b03d897784f6dcbc", - "en_hash": "sha256:6debff5f12e65ac8d7295f41acdaa7068379f97806efa4462a4fb69a80cb4d30", - "synced_at": "2026-06-26T10:38:17Z", + "ru_hash": "sha256:8a500c987fc3f551d85a3790d27c2b8613dbe697764c1df26142476071c44a44", + "en_hash": "sha256:2c8c5087192773b2e166ede7718fa2a3572693cfaf56ca2b933dad4e4ca4beef", + "synced_at": "2026-06-27T13:51:33Z", "status": "synced" }, "framework/skills/tool-usage/v8-runner/agents/openai.yaml": { @@ -765,16 +765,16 @@ "status": "synced" }, "framework/skills/tool-usage/v8-runner/references/command-selection.md": { - "ru_hash": "sha256:0b7279af22babcba5b8d1fad7a934b0817a8d5258243e9135d55dfc1f6897659", - "en_hash": "sha256:0172528cd9260bc4debf65b3094076ad0a9656c0a716278a264de77a395092d7", - "synced_at": "2026-05-09T08:33:35Z", + "ru_hash": "sha256:e1a27f7e63daa7676297c3e68b8121e6fdfa7d973d0dcb6dca127bb2a830c076", + "en_hash": "sha256:bce863415b6a8b906f60c2975372052ba9d8c859ab2c23050a86ce21031e86b5", + "synced_at": "2026-06-27T13:22:40Z", "status": "synced" }, "framework/skills/tool-usage/v8-runner/references/config-and-backends.md": { - "ru_hash": "sha256:ae80062e21fde77c505e8a2a211dba088d0e40110277b6e0e0ff5f1cfb39410b", - "en_hash": "sha256:eed09f943d05273f943391da4daed7a313185087ba4873fc9f4ad70eb7f4cc70", - "synced_at": "2026-05-09T08:34:09Z", - "status": "synced" + "ru_hash": "sha256:8faa81130d30a01cd7f98b247afed6717c9114f24cd984ef5d3851841483db1f", + "en_hash": "sha256:acdad9dcbb87489d04c4ab81e08dbc7899b47e60a1aae637b9cc167fb692d2b5", + "synced_at": "2026-06-26T23:33:49Z", + "status": "dirty" }, "framework/skills/tool-usage/v8-runner/references/file-and-artifact-workflows.md": { "ru_hash": "sha256:b530c45cba8174e6f67b91294bee79e7809e9c5f1a6229408d60b061af684746", @@ -783,15 +783,15 @@ "status": "synced" }, "framework/skills/tool-usage/v8-runner/references/project-workflows.md": { - "ru_hash": "sha256:9e9e3e79a88415b48c7795374ceb2a8707d0dc46c27591bb9f793fc178bcbcb7", - "en_hash": "sha256:dd65bb818366251cdca00749d925441ca3d03cd4f705cac279d6816bfe5d6412", - "synced_at": "2026-05-21T21:39:37Z", + "ru_hash": "sha256:db30f19a5e173c649099dcd7df0a86b073888bcdc3d29aa4daeacfb4c16cee58", + "en_hash": "sha256:00382e7139cbea7c08c3a3db72d380374e4f4e11011e633029704e5d4f73e6b1", + "synced_at": "2026-06-27T13:23:57Z", "status": "synced" }, "framework/skills/tool-usage/v8-runner/references/testing.md": { - "ru_hash": "sha256:1d3e3c8f7b940262337b24f368f9d2c135ca54548ca54c36f15d0ca0f1a28ca7", - "en_hash": "sha256:9ae91fcccd62202e4c8a7f9d7ba3968b9ba17716e68fa97fe3283906a8c2fbed", - "synced_at": "2026-06-04T12:07:44Z", + "ru_hash": "sha256:e0da00f3f72bfa75f0e4c8db171dd05dd50abc0ec5dabf95a9c3ce78b556541a", + "en_hash": "sha256:53e045c17360651987facb71868c4e60767afb64433c5bd0b22429cd575b67bb", + "synced_at": "2026-06-27T13:23:37Z", "status": "synced" }, "framework/skills/tool-usage/v8-runner/references/troubleshooting.md": { @@ -801,9 +801,9 @@ "status": "synced" }, "framework/skills/tool-usage/v8-session-manager/SKILL.md": { - "ru_hash": "sha256:7fa0b051f5c7575db489617eaae23ccc1667470eca98701bc3f4396b24841b1c", - "en_hash": "sha256:a265fac8c7f3c60cbc75cb217113de5c39e92cccc07bc6659575bf462d6ede53", - "synced_at": "2026-06-04T15:59:15Z", + "ru_hash": "sha256:6bd3e8039d2bd04d935e01886c4cdee1218e1ed078d673eda83010623fb72c8a", + "en_hash": "sha256:1cf3104d6fb203f7ebe5c4d7181341aa9f343aa22dad3027cda595d614eb2e15", + "synced_at": "2026-06-27T06:17:11Z", "status": "synced" }, "framework/skills/tool-usage/v8-session-manager/references/architecture.md": { @@ -837,16 +837,16 @@ "status": "synced" }, "framework/rules/rlm-workflow/SKILL.md": { - "ru_hash": "sha256:d571784d0fde97b8deb48143b07d2109741f07b4744dfa6216e696a1cd7fc104", + "ru_hash": "sha256:5c3475527e87446e7ae80451a9bda19902d7c0113752ec7a1987ab2a0c6e9351", "en_hash": "sha256:85ab101d3966f578650e8bc9f8f43c65b458d7972dd1f016483a4375c0b10459", "synced_at": "2026-06-22T19:07:41Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/content-generation/docx-convert/SKILL.md": { - "ru_hash": "sha256:43a0a376e3b40d63fc6ec81b2063bb2d721072287dd4043e60e0e62e02292bda", + "ru_hash": "sha256:72d2fae9be50932e79398ab5ae217abcc829dc60b8ff51ce16df9906dc237338", "en_hash": "sha256:0c53ae8347499c3ece7f24065e98f87e5f0f4af5a5078aa4503e43d8771e9850", "synced_at": "2026-06-04T15:58:30Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/content-generation/docx-convert/docx2md.sh": { "ru_hash": "sha256:5a01d87c27537cab6f2ee4ae62b97229cbf00e674b7dc6be07a4fd4b76a5ebfc", @@ -885,9 +885,21 @@ "status": "synced" }, "framework/rules/git-workflow/SKILL.md": { - "ru_hash": "sha256:7266ab6e84347abf41b521e50920ec26e6066efd5c80d0688d124a1100a15537", + "ru_hash": "sha256:114d08e302d91e1855743c3efc59e1ac15fc110177ff51774fe38d0631a46d2e", "en_hash": "sha256:53e0bba9d2ad9c595f09b68bfb2378bf90c76c0d409600fdadee79330780da49", "synced_at": "2026-06-22T22:05:43Z", + "status": "dirty" + }, + "framework/skills/other/infostart-kb/SKILL.md": { + "ru_hash": "sha256:216a772f9cac492560b6328e9e893c390b1661f8809b4d611628388fc4414174", + "en_hash": "sha256:2f98f245a17338c45ee9224f3ef2b1059993904729d5166213990ae639017ec1", + "synced_at": "2026-06-04T15:59:40Z", + "status": "dirty" + }, + "framework/skills/other/infostart-kb/references/how-to-discover-environment.md": { + "ru_hash": "sha256:3abceef413dc21dbe2d6f70a4181789f84739d34bd0401babf5414fe9eeaeb83", + "en_hash": "sha256:b03e3931a89f0c7e059ee9ef1eb9929a8e0a468c5142a8534578ebd188db66c1", + "synced_at": "2026-05-21T21:40:08Z", "status": "synced" }, "framework/skills/tool-usage/v8-runner/references/auth-guard.md": { @@ -897,28 +909,28 @@ "status": "synced" }, "framework/skills/bsl-practices/api-design/SKILL.md": { - "ru_hash": "sha256:0ea5f87666595804ffb419b36dc9816b930252c2bed16c29574a549f59866544", + "ru_hash": "sha256:369412b9693ba5209c7a252d4b5a1d72f92fd76f552d510a91b19eac3c096d48", "en_hash": "sha256:3e4286ec7dd845f63f2a87b8b0e1526dbb2d4c2595faf2b7a1612d206a8cfb3a", "synced_at": "2026-06-04T16:00:20Z", - "status": "synced" + "status": "dirty" }, "framework/skills/bsl-practices/background-jobs/SKILL.md": { - "ru_hash": "sha256:39846b190133cf12e51ef8163989ba599d94437290c1a5047db6280ba9424465", + "ru_hash": "sha256:d007d64189bd158c044e99719dafe7e6fdd5b8fc41af896730f407a740ae75c4", "en_hash": "sha256:7041cae1ef11d7a6b543ca8d217b3b5341c08b16898d577ab742fe1c2be57c58", "synced_at": "2026-06-04T16:01:10Z", - "status": "synced" + "status": "dirty" }, "framework/skills/bsl-practices/data-exchange/SKILL.md": { - "ru_hash": "sha256:90509009a04580657da53aa146caf75f8489dbe3c70a93a1ca78992668106ca2", + "ru_hash": "sha256:9b4e25f27efae890c0e1930932ac1e28840a81c03cf018cb0f8d586d5be98b2e", "en_hash": "sha256:150176c50b5863eecb450829961f5dc0b70f4fbf3aa58cc593e86de9e359aedb", "synced_at": "2026-06-04T16:00:36Z", - "status": "synced" + "status": "dirty" }, "framework/skills/bsl-practices/integration-patterns/SKILL.md": { - "ru_hash": "sha256:7c7bfd0bcf4147a6542ced1ea5cf3c8c293dceafbee98491c82da1df52e3c596", + "ru_hash": "sha256:f412d853b1e53ae954b3c39b7352e5c00fb8e11e601a4aa07d4130a80d8719bd", "en_hash": "sha256:11326d74f499fbdb98f4062ecc27d3771db261a542c2bfd923d3c1b99f7357dd", "synced_at": "2026-06-04T16:00:15Z", - "status": "synced" + "status": "dirty" }, "framework/skills/bsl-practices/integration-patterns/references/auth-schemes.md": { "ru_hash": "sha256:3542a5b085b490e77269145616a377de96e2101d0c497065b405ada948dcc1e9", @@ -927,10 +939,10 @@ "status": "synced" }, "framework/skills/tool-usage/diagnostics/db-performance/SKILL.md": { - "ru_hash": "sha256:5b306edf830b9e90d84d7566cfbdbef7eb9e58496e58dcc47f650289ed92eaf6", + "ru_hash": "sha256:500007376399b84aa15f3ae19f8b0208f97a41c8d969e41aec882cc634956b89", "en_hash": "sha256:090a24a6d0faeb8db184bebb793331153a197b2dffe4c127f1eaa854d800ceec", "synced_at": "2026-06-04T16:00:18Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/mxl-dsl/references/dsl-spec.md": { "ru_hash": "sha256:893cb7f3c21c69a9288d4d39e8a81150801a3a627b044bc9d1d500eff29ad1cb", @@ -939,10 +951,10 @@ "status": "synced" }, "framework/skills/tool-usage/platform-data/xml-generation/skd-edit/SKILL.md": { - "ru_hash": "sha256:d3e45be6cbd793a9a5520fe05b3b23cce611f02bdc0743045453d8aec4e6ff09", + "ru_hash": "sha256:96b815a66742898321cb9affd54b2131d5c7389c4bbf43efbb3a89fa8aca5a9d", "en_hash": "sha256:5fe4e03bc7b2cc395ec24948b9746f1e7a69d1e45b7f2f1feebb737e683beb52", "synced_at": "2026-06-22T11:24:59Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/skd-edit/references/fields.md": { "ru_hash": "sha256:393d28689cdb0aa453fe8faffaee58c28bcfa2c960f9c37045ecc9d0acf29944", @@ -951,16 +963,16 @@ "status": "synced" }, "framework/skills/bsl-practices/query-optimize/SKILL.md": { - "ru_hash": "sha256:fe6ab21deaa9753d239182f98bd0de03e862f99484a4ca45f357a13d88aca93c", + "ru_hash": "sha256:b9f2291aad11d0b9fa0accb90836dd13a2610170e4535bf7292031ab91c42cf4", "en_hash": "sha256:a65f0db30675202e1e29a90bf73f8f0b72ce647c7fad1be169fbd101c61e50d0", "synced_at": "2026-06-04T16:01:04Z", - "status": "synced" + "status": "dirty" }, "framework/skills/bsl-practices/security/SKILL.md": { - "ru_hash": "sha256:6192f01d9c677d660bcace1481b61a372dac548580360b3da50dd19f4cff6e89", + "ru_hash": "sha256:a389d6573e84f433a4956ae63e94fe67ad8ade85c7d1f2f0da38573f5df2eb8e", "en_hash": "sha256:65f1ea7315fb49cd96f564807bddd581a96744d17dcb71d75c1007edbb5092ef", "synced_at": "2026-06-04T16:02:26Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/diagnostics/tech-log-analysis/references/scenarios.md": { "ru_hash": "sha256:2d1359b9e5f86e4288ed1b1c2917de741165dac0d3083555b3bf5600c8b1ba82", @@ -1023,22 +1035,22 @@ "status": "synced" }, "framework/skills/tool-usage/browser-ui/img-grid/SKILL.md": { - "ru_hash": "sha256:4e0f4eb3d22e2ff63a99f22587d78969776d3b35bdea6d35166ed5c58234be3d", + "ru_hash": "sha256:a5f62d5d971002772cfa79dbcbf88c1de2cab796e8a94d342fd8f4798c3d9138", "en_hash": "sha256:89682b10742bb24573cb8294452738c8434863b29cc17fac2e501ffa569b0614", "synced_at": "2026-06-04T16:01:24Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/browser-ui/web-test-1c/recording.md": { - "ru_hash": "sha256:8a95975f04b3bd23d8c98d195b93f89fb042559558506d115b72c11041f1288c", - "en_hash": "sha256:bbad249d74b1006b3ef9e7df28cafab1856eae2308751f841cc164106a0fb064", - "synced_at": "2026-05-21T21:31:29Z", + "ru_hash": "sha256:529cf26aa92f9e65d115a684d5cdc5bcd3610d480358755c7d9d7fc72403f02e", + "en_hash": "sha256:6163663f17a72a716c7d147c1fd47c2985788150352bfb3149a7ec74671ce2ea", + "synced_at": "2026-06-27T06:04:24Z", "status": "synced" }, "framework/skills/tool-usage/browser-ui/web-test-1c/regress.md": { - "ru_hash": "sha256:e09f7f4d2aca646510f260a105b009d6ee6da13abe28c81875c1148f8ed92d3f", - "en_hash": "sha256:c809f419288b11e457d64414b84326fe666eaf6a713bf66e65857ae1d90e5b02", - "synced_at": "2026-06-22T11:37:26Z", - "status": "synced" + "ru_hash": "sha256:f12c8c2b18a62a328a9d5669d3b4aa152344a41f52726ade3696c4f8e132852d", + "en_hash": "sha256:815977ae701a105b51e6e67eb357714f21dbc4d84b4a8decf68d2c3b49b79480", + "synced_at": "2026-06-26T23:33:49Z", + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/meta-operations/references/batch-patch.md": { "ru_hash": "sha256:100778ce06840faefece941401e9f42d5a002b1c5dc8853dac2f79c62be9f81e", @@ -1065,16 +1077,16 @@ "status": "synced" }, "framework/skills/spec-writing/task-breakdown/SKILL.md": { - "ru_hash": "sha256:73acbda4db9b87170a9f1e3b5ce753d44cc2f1f434992b5e0cbffac1a8cb83e0", + "ru_hash": "sha256:2ab3268dd67abc633ad27ebd21c985ffab59fc7a9c4e1ada82207b48b7e30edf", "en_hash": "sha256:41af7bfaa08b9ee3f28bde3aad899d4ccfab33a9a32a4ffc59851ba11f2af846", "synced_at": "2026-06-04T16:01:00Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/platform-data-core/SKILL.md": { - "ru_hash": "sha256:3bc1f7628b5f3c27e9d3b1b913bdbc42e24b07240789e23b366738d6ef8d792c", + "ru_hash": "sha256:9d2300a72124d04b47d77b2f2f460292e826b08d1737cf9992e2188329ddcd99", "en_hash": "sha256:2c008adc2af3b5a65d7eb2e8f18c3c8820afb70cb0c8994a2f58c9ee9a2f55ae", "synced_at": "2026-06-04T16:02:12Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/platform-data-core/references/query-syntax-cheatsheet.md": { "ru_hash": "sha256:abeda4b87b727ae53483942eef990a6d90d62008584d20bce2b41d6e5f1abb23", @@ -1083,16 +1095,16 @@ "status": "synced" }, "framework/skills/tool-usage/platform-data/xml-generation/SKILL.md": { - "ru_hash": "sha256:8c607a148cf8190a4e43b04597df307ab1ed20fc19525ed338c042f90ab182a0", + "ru_hash": "sha256:74aa183481a6394bce9f4b6767957870b9ef892b56e3e7fd205c9b15b7ea4d85", "en_hash": "sha256:145b051b77d97b1dc5fbfa5a5bd44b79f262811a3689be980db178372ef31d2f", "synced_at": "2026-06-22T11:54:01Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/epf-full/SKILL.md": { - "ru_hash": "sha256:139a2c5aade474f6fc35846716854c0abcef7c40643c97a9e41eb5e0baa1555b", + "ru_hash": "sha256:acb9a3a244487f09de19891836a0cbff289ec80298642dca438db8718bfcc2ee", "en_hash": "sha256:9255eedb03c1295dec503332729c42541f4a2c42b193138a90cfa499b7a0e34b", "synced_at": "2026-06-04T16:01:32Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/epf-full/references/epf-base.md": { "ru_hash": "sha256:af239741291126dfdf0f807591580193ec674a1df4fb126ec20f3022b2eb1bd0", @@ -1113,10 +1125,10 @@ "status": "synced" }, "framework/skills/tool-usage/platform-data/xml-generation/forms-toolkit/SKILL.md": { - "ru_hash": "sha256:1a3caa569a4453731c86240543e1665bc409659f66364e738f5045e7af0f7c59", + "ru_hash": "sha256:920d92eaa7a68bb5aa212d39da317a26f6eec2700ce0d4bf5fe4cf653ba5428d", "en_hash": "sha256:99f9a61edef1196d16ef950216ab350643819e048b5b96c59e400eb3a0dd379d", "synced_at": "2026-06-22T11:54:01Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/forms-toolkit/references/edit.md": { "ru_hash": "sha256:7422d7b1f27e5e59290cf265106b922a62d596e03a39d89911cea0cd8696b574", @@ -1143,10 +1155,10 @@ "status": "synced" }, "framework/skills/tool-usage/platform-data/xml-generation/subsystem-interface/SKILL.md": { - "ru_hash": "sha256:780a276de659bfe2d7caec34b018e15641ff8a7275577fb244b8725904562f55", + "ru_hash": "sha256:d008817a57c630c333598fb2b8c02e681fe38f58251efd2f40b446ff333e06e2", "en_hash": "sha256:3c60279e8e4690d7fb5d2023fa9dd06675457dc518ac54e5cbe68133f501145a", "synced_at": "2026-06-04T16:02:03Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/references/universal-commands.md": { "ru_hash": "sha256:afc57393695f231d07f8fa136ed8dff3ea36dc4ce820caa9ab68d19612ec31bf", @@ -1155,94 +1167,94 @@ "status": "synced" }, "framework/rules/agent-debug/SKILL.md": { - "ru_hash": "sha256:5d5f9694a8e971077412b1ac82ad3a6750a1a3b709cf8cbf22102685e62c6592", + "ru_hash": "sha256:01eb5b10f2d815a5f92b386abd02b5162a89e9ece4c0f4e1f5dcf0886a2d0e7f", "en_hash": "sha256:29ef07b73f0307270b8cba4f5a16cf6e5d90a4db0811585324d40c30ce1470eb", "synced_at": "2026-06-04T16:01:26Z", - "status": "synced" + "status": "dirty" }, "framework/rules/buddy-prompting/SKILL.md": { - "ru_hash": "sha256:c146683d42ee4137ba95854f138459a53895f2189d44dd61a0c8999ea093a06d", + "ru_hash": "sha256:aac16df494438c439973e3c97afaaf5d099421594f9b6d476e0bd3abb623cdbf", "en_hash": "sha256:a60684f2e8dabe47e37393de0bfef05d82d43f788945aeb4b6db693d9f1e71ea", "synced_at": "2026-06-04T16:01:59Z", - "status": "synced" + "status": "dirty" }, "framework/rules/bug-reporting/SKILL.md": { - "ru_hash": "sha256:b02880f46f3d4fc51234e99f56674081ef3849b5a3af0c07e06cd598c3368f14", + "ru_hash": "sha256:d9eb1e75cc283e8b7bcdfbac0bcb86b2c47fce04417deb92cd36462a8d19a795", "en_hash": "sha256:c5f709acc5f3f0b48183c5145892221608b8aa1217b6ec6f77f877e85eb8c6b6", "synced_at": "2026-06-04T12:06:49Z", - "status": "synced" + "status": "dirty" }, "framework/rules/code-verification/SKILL.md": { - "ru_hash": "sha256:96e966401bf9d3b05898b816bae835229d20a7ded49681d51dca357ef256da71", + "ru_hash": "sha256:697aff2273a5421f3560c0668fd676bec02630fbd5897bd85675038d064119a2", "en_hash": "sha256:669985d509f6ea03c8817105cd425bb78386fea9fea3b8eed93902debcc08176", "synced_at": "2026-06-04T16:01:48Z", - "status": "synced" + "status": "dirty" }, "framework/rules/coding-standards/SKILL.md": { - "ru_hash": "sha256:0d08c07c38dc1fada4549255d00a3a8dfb0550a5840cac77a017395298630486", + "ru_hash": "sha256:bf3c429d751f5c7091960e0f5cb1c2b2eeb76843cc6c3e3914253a997d30dbad", "en_hash": "sha256:e243df974b5546b04e553353650b78d4f8e493b92e4f21d2a8b37e7741e2fe89", "synced_at": "2026-06-04T16:01:50Z", - "status": "synced" + "status": "dirty" }, "framework/rules/error-handling/SKILL.md": { - "ru_hash": "sha256:681e49292b1c43504e019293c9c1dc71d54354b54d432b1fa3f14170de7a0abd", + "ru_hash": "sha256:a34cf4c7ffa8ad82aac1c9af476b7ee3a2441deee237827818dab21eda93fe65", "en_hash": "sha256:6ca60716f79b4a5b2e6080ac16a1d80a7381df40d39f04e79ba1a7083a44655b", "synced_at": "2026-06-04T16:02:07Z", - "status": "synced" + "status": "dirty" }, "framework/rules/form-patterns/SKILL.md": { - "ru_hash": "sha256:66522adee1c0860d72e82acd1cc69b3a92bb17ceabc172c5e6ac3767c1ca0b35", + "ru_hash": "sha256:6ba36d0029b06687c37c33b3221f313635a0cdf033ceb2d96618338cf016e240", "en_hash": "sha256:e221a0073f6b81427ace7fab429db1928b79eaedad30ec6ca2e2195955bdc3fd", "synced_at": "2026-06-04T16:02:21Z", - "status": "synced" + "status": "dirty" }, "framework/rules/form-visual-check/SKILL.md": { - "ru_hash": "sha256:762c6d5751f13f302e484e09504eb66b0175d9ac5d9fd372d0ac7f5a9e374522", - "en_hash": "sha256:a108dc7f17f190adbaab54b7d364996f42bf1f68f31988e0f166ce82e045a1b0", - "synced_at": "2026-06-04T16:02:08Z", + "ru_hash": "sha256:2d28324427abe1a1b2cfd759508b3b3b22c71a8b79c5678aa1884214468400e3", + "en_hash": "sha256:ab899aab4d4c748b7a78ce4e93bcc903247e8726fd47cd95056291a8399173a6", + "synced_at": "2026-06-27T05:47:40Z", "status": "synced" }, "framework/rules/infostart-kb/SKILL.md": { - "ru_hash": "sha256:9a543472e42ad33d9afe57274929b580d416a7c950f021b3b30ea3684989ffe2", + "ru_hash": "sha256:14fd508f40caaf013492a9fee963f6650ff0ac4063ba546b7076b63c14abe535", "en_hash": "sha256:4a6180976748b47efa1785af69f26a42d8c5629b22051129bce9bda46468af3d", "synced_at": "2026-06-04T16:02:15Z", - "status": "synced" + "status": "dirty" }, "framework/rules/query-optimize/SKILL.md": { - "ru_hash": "sha256:82b1fbff8bd6faf808d0e6c41d71df5d951495f074e25e3d3f64de30e899ae8b", + "ru_hash": "sha256:f5809ad2eba22a1a05a4e5be8572ef416880d45b144a138c876f3116173d0c8e", "en_hash": "sha256:7fa6290edec898f23fa1fe34d38a791ced3cb41c8ccbd8c45f8e30ca7073d0ae", "synced_at": "2026-06-04T16:02:23Z", - "status": "synced" + "status": "dirty" }, "framework/rules/query-patterns/SKILL.md": { - "ru_hash": "sha256:d20287cad8d4f95787587fd5eaaca7c901453c7848037c3928a5e0f229acf1b0", + "ru_hash": "sha256:12f5fbab4e0f324f13f1fe55679793a9b4f36f2f591a4f73fd20f56a627d45e5", "en_hash": "sha256:cbe21b306c86968ef6d286b966f265747839d2bfd57ea36e332ac48d307c5478", "synced_at": "2026-06-04T16:02:26Z", - "status": "synced" + "status": "dirty" }, "framework/rules/search-before-write/SKILL.md": { - "ru_hash": "sha256:36ecd9af83f7a8f73cb70805780e52cc85374c6583ff63dbb2606a9365c21d3d", + "ru_hash": "sha256:4af5e3c57b70f7b6f9d1623c91bed6be369bf6977dff9df45e52dcc17b666444", "en_hash": "sha256:b78951d705ebe59738e927e8bd1b384a07f4fe22787019f6e6ec16398c0613d5", "synced_at": "2026-06-04T16:02:24Z", - "status": "synced" + "status": "dirty" }, "framework/rules/security/SKILL.md": { - "ru_hash": "sha256:8242a611dc2effa6195e638a3fb017bbadb48d746fbce732cd42de24d797194c", + "ru_hash": "sha256:c4ae8bef63a61b9afee62c5952775edfbe754d36d6507d4266ef9f49ed50d867", "en_hash": "sha256:a95b4bfb72bd770d8fc87b318acfa7db20d14f9aeb0ce850242dc7c046472460", "synced_at": "2026-06-04T16:02:35Z", - "status": "synced" + "status": "dirty" }, "framework/rules/source-of-truth/SKILL.md": { - "ru_hash": "sha256:8723d52058246bd32131f0ead883fa77df12a6e67a2f5629fcea0360e2b71b74", + "ru_hash": "sha256:62c19ed2b3054987260729244979a30b6a789810ad477e62250d3e79506cc59b", "en_hash": "sha256:60317b659654c38ade5d234298daeb30dd4ece6862a422d00073928d199edb65", "synced_at": "2026-06-22T22:05:43Z", - "status": "synced" + "status": "dirty" }, "framework/rules/ssl-patterns/SKILL.md": { - "ru_hash": "sha256:edbe712ae6386ff132d8f2e6a84e9376185bf9754fb4557a85ac1adf71df42d7", + "ru_hash": "sha256:d04fab236a0902a0fb80eef20dcc928dd269a7c46aa19d8daa9fe402429f5a88", "en_hash": "sha256:535685345b8df8dcfbd786cbdfa7187d54950bf45c27a6d0006bbe5bb948ebd3", "synced_at": "2026-06-04T16:02:57Z", - "status": "synced" + "status": "dirty" }, "framework/skills/framework-meta/rlm-workflow/SKILL.md": { "ru_hash": "sha256:175ce2fb432b66fa1040d1cc0da7b04b053ed639db0efbc13d8ae8259ba2e950", @@ -1257,16 +1269,16 @@ "status": "synced" }, "framework/rules/yaxunit-isolation/SKILL.md": { - "ru_hash": "sha256:61558eeeaf0b5066902d00d6c0ef67a39ef33c3e138fb100049c1b7579082abe", + "ru_hash": "sha256:512e1e6f3b03c1df760f008703009ace4a69a00a047d6ef95e29da3879877f40", "en_hash": "sha256:764750a7dff2d6780801e67dc1c12c414839617acaa3c3d15bfed7f112411856", "synced_at": "2026-06-05T08:13:48Z", - "status": "synced" + "status": "dirty" }, "framework/rules/test-zero-residue/SKILL.md": { - "ru_hash": "sha256:eb0db713e6faa38dae07a1f78f574a30c37dd7e868d336e32ac0381891256d3b", + "ru_hash": "sha256:a9ba48b71a640df39541891e71b031c4a5e6d1e1d823ad08f4abb2ac4ab25207", "en_hash": "sha256:10d51532bd55c65905af1b177041e4d0941c0268d38d42795d4f26c9b1aa7008", "synced_at": "2026-06-22T19:09:19Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/platform-data/xml-generation/references/behavioral-oracles.md": { "ru_hash": "sha256:151e86537c8da74b5c50e7b8f22e146cecd9a001560023ce23ce865a49e81075", @@ -1293,16 +1305,16 @@ "status": "synced" }, "framework/rules/dap-bsl-debugger/SKILL.md": { - "ru_hash": "sha256:08cc1ee3764538962adc983d3d00de330d80935b1f2087a3c9ca4703f9b76f93", + "ru_hash": "sha256:94f94fbf4ed94075e19ab4952bb586f37520bc983d0f8549d665c5adb65dc1f9", "en_hash": "sha256:66ee2c50d5ea30a52a52cbd79ac839827bf54fb870a1764cc962276d3120b958", "synced_at": "2026-06-22T20:18:30Z", - "status": "synced" + "status": "dirty" }, "framework/skills/tool-usage/diagnostics/dap-bsl-code-debug-procedure/SKILL.md": { - "ru_hash": "sha256:1a7a057eeb00477eb83d22e26374a26caa19cfa64d6bf061b59e70d3d49c57dd", + "ru_hash": "sha256:f37c184effa4e4a6248042ee1692080be3f5a629b7bb70306d40b58b2ec27a42", "en_hash": "sha256:2f111dd50ff8235b1e9232b0a59f34fd2430ca1b3a33a2c38027790fe5d7cbad", "synced_at": "2026-06-22T20:22:05Z", - "status": "synced" + "status": "dirty" }, "framework/skills/agent-process/agent-context/SKILL.md": { "ru_hash": "sha256:912a9609acf9179182ed78297b6f5e00fd255dfc00197969971c94bd9515db96", @@ -1323,10 +1335,10 @@ "status": "synced" }, "framework/skills/agent-process/quick-fix/SKILL.md": { - "ru_hash": "sha256:9cb3d864175e4acc9215b6017d730e5bcf0222df9991b3293dca2bd9ccddafd7", + "ru_hash": "sha256:1a76c5aeca38878edf1c077ecc405d38930841075aa82544ae0193dd403a1d76", "en_hash": "sha256:67d0102717912dbcfb526daef405cf6650551e8c6da75184107e75f748cc5d1a", "synced_at": "2026-06-22T22:04:14Z", - "status": "synced" + "status": "dirty" }, "framework/skills/agent-process/skill-learning/SKILL.md": { "ru_hash": "sha256:ba351f974a69752c22af466117b251b7a5f456616dac4b92953bde82470c7263", @@ -1339,6 +1351,36 @@ "en_hash": "sha256:484484067d3eeecccae3c42a4bbab45e5785668b5e3221c42d09ef919a0449ff", "synced_at": "2026-06-22T22:04:14Z", "status": "synced" + }, + "framework/rules/predefined-elements/SKILL.md": { + "ru_hash": "sha256:a7d3d27ac0b7e7cb267c62e2d4db22ca1afaa302208854c042da05537b9ac06c", + "en_hash": null, + "synced_at": null, + "status": "pending" + }, + "framework/rules/report-discovered-issues/SKILL.md": { + "ru_hash": "sha256:f2d848b0b5b7b78d2fde8ba355f12d6f8b22259e42ade62bb9c26e5f645d3143", + "en_hash": null, + "synced_at": null, + "status": "pending" + }, + "framework/rules/semantic-code-comments/SKILL.md": { + "ru_hash": "sha256:70a0c7bfb3cec9aa1f8bd6f642ff0fd1a9976375e47a27e8f1f1fae50db80b27", + "en_hash": null, + "synced_at": null, + "status": "pending" + }, + "framework/skills/tool-usage/v8-runner/references/learned-patterns.md": { + "ru_hash": "sha256:5e6b2d1708601d4e4171b3e6134eeadaba8de2c06d51528a584dfbca9fff786c", + "en_hash": "sha256:fd8daa3142713962fb95e39bcd5514df998f5aeec79e2b4ad30d389bdb9240ef", + "synced_at": "2026-06-27T13:23:17Z", + "status": "synced" + }, + "framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md": { + "ru_hash": "sha256:e71cca3de96537f44be5b38d71a47ba2a28d43343362031f0fb54b0bc6e61ccd", + "en_hash": "sha256:70515f787e2a3c33714915c5c4c0cfc67f46a68afc6003de40136048f0cab90d", + "synced_at": "2026-06-27T13:15:56Z", + "status": "synced" } } } diff --git a/framework/rules/agent-context-protocol/SKILL.md b/framework/rules/agent-context-protocol/SKILL.md index 6d2d69ea..4032c9cf 100644 --- a/framework/rules/agent-context-protocol/SKILL.md +++ b/framework/rules/agent-context-protocol/SKILL.md @@ -1,6 +1,6 @@ --- name: agent-context-protocol -description: Старт агента → прочитай {role}-context.md; выход → запиши его. Процедура и структура — в навыке agent-context. +description: "На старте/выходе агента читать и писать role context" alwaysApply: true --- # Протокол контекста агента diff --git a/framework/rules/agent-debug/SKILL.md b/framework/rules/agent-debug/SKILL.md index 068a481c..88ce9490 100644 --- a/framework/rules/agent-debug/SKILL.md +++ b/framework/rules/agent-debug/SKILL.md @@ -1,6 +1,6 @@ --- name: agent-debug -description: "Стандартная диагностика (ЖР/скриншоты) не раскрыла реальное поведение → применить навык agent-debug (критичный триггер)" +description: "Если ЖР/скриншоты не помогли, добавить agent-debug" alwaysApply: true --- # Отладочные сообщения (Agent Debug) diff --git a/framework/rules/buddy-prompting/SKILL.md b/framework/rules/buddy-prompting/SKILL.md index 48d4034c..1a028690 100644 --- a/framework/rules/buddy-prompting/SKILL.md +++ b/framework/rules/buddy-prompting/SKILL.md @@ -1,6 +1,6 @@ --- name: buddy-prompting -description: "Перед обращением к 1С Напарнику → применить навык buddy-prompting" +description: "Перед запросом к 1C Buddy подготовить prompt" alwaysApply: true --- # Промпты к 1С Напарнику diff --git a/framework/rules/bug-reporting/SKILL.md b/framework/rules/bug-reporting/SKILL.md index 5dd0d0e7..1c3f0828 100644 --- a/framework/rules/bug-reporting/SKILL.md +++ b/framework/rules/bug-reporting/SKILL.md @@ -1,6 +1,6 @@ --- name: bug-reporting -description: "Лимит самофикса исчерпан / причина не в своём коде → применить навык bug-reporting" +description: "Когда self-fix исчерпан, оформить bug-report" alwaysApply: true --- # Оформление bug-report diff --git a/framework/rules/capability-resolution/SKILL.md b/framework/rules/capability-resolution/SKILL.md index 9f77cc4b..0aebb252 100644 --- a/framework/rules/capability-resolution/SKILL.md +++ b/framework/rules/capability-resolution/SKILL.md @@ -1,6 +1,6 @@ --- name: capability-resolution -description: Резолв capability → реализация (MCP tool или CLI). Агент использует registry.yaml для вызова. +description: "При выборе инструмента сначала сопоставить capability" alwaysApply: true --- diff --git a/framework/rules/code-verification/SKILL.md b/framework/rules/code-verification/SKILL.md index 776417e0..28588193 100644 --- a/framework/rules/code-verification/SKILL.md +++ b/framework/rules/code-verification/SKILL.md @@ -1,6 +1,6 @@ --- name: code-verification -description: "После правки BSL → применить навыки code-verification + syntax-checking" +description: "После правок BSL выполнить verification и syntax checks" alwaysApply: true --- # Верификация BSL после правок diff --git a/framework/rules/coding-standards/SKILL.md b/framework/rules/coding-standards/SKILL.md index 8d41c2aa..4dbd936c 100644 --- a/framework/rules/coding-standards/SKILL.md +++ b/framework/rules/coding-standards/SKILL.md @@ -1,6 +1,6 @@ --- name: coding-standards -description: "При написании или ревью BSL-кода → применить навык coding-standards" +description: "При написании/ревью BSL применять coding standards" alwaysApply: true --- # Стандарты кодирования BSL diff --git a/framework/rules/dap-bsl-debugger/SKILL.md b/framework/rules/dap-bsl-debugger/SKILL.md index 89c1a3cf..9b3dc23e 100644 --- a/framework/rules/dap-bsl-debugger/SKILL.md +++ b/framework/rules/dap-bsl-debugger/SKILL.md @@ -1,6 +1,6 @@ --- name: dap-bsl-debugger -description: "Интерактивная BSL-отладка нужна для воспроизводимого runtime-сценария, когда статический анализ, ЖР/скриншоты и agent-debug не раскрыли путь исполнения или значения переменных → применить навык dap-bsl-code-debug-procedure." +description: "Когда runtime-путь неясен, включить DAP-отладку BSL" alwaysApply: true --- # DAP BSL Debugger diff --git a/framework/rules/error-handling/SKILL.md b/framework/rules/error-handling/SKILL.md index 67bc7207..bf68d7c1 100644 --- a/framework/rules/error-handling/SKILL.md +++ b/framework/rules/error-handling/SKILL.md @@ -1,6 +1,6 @@ --- name: error-handling -description: "BSL-код с транзакциями/Попытка/блокировками → применить навык error-handling" +description: "Для Try, транзакций или блокировок применять error-handling" alwaysApply: true --- # Обработка ошибок и транзакции diff --git a/framework/rules/escalation-format/SKILL.md b/framework/rules/escalation-format/SKILL.md index b4dc01c2..9788f167 100644 --- a/framework/rules/escalation-format/SKILL.md +++ b/framework/rules/escalation-format/SKILL.md @@ -1,6 +1,6 @@ --- name: escalation-format -description: Эскалация решения пользователю → применить навык escalation-format (структура Что→Почему→Варианты→Оценка→Рекомендация). +description: "При эскалации решения дать options и recommendation" alwaysApply: true --- # Формат эскалации пользователю diff --git a/framework/rules/form-patterns/SKILL.md b/framework/rules/form-patterns/SKILL.md index d61f04ff..e85426db 100644 --- a/framework/rules/form-patterns/SKILL.md +++ b/framework/rules/form-patterns/SKILL.md @@ -1,6 +1,6 @@ --- name: form-patterns -description: "Перед написанием модуля управляемой формы → применить навык form-patterns" +description: "Перед модулем управляемой формы применить form-patterns" alwaysApply: true --- # Паттерны модуля управляемой формы diff --git a/framework/rules/form-visual-check/SKILL.md b/framework/rules/form-visual-check/SKILL.md index 0eb12240..6b39d1be 100644 --- a/framework/rules/form-visual-check/SKILL.md +++ b/framework/rules/form-visual-check/SKILL.md @@ -1,16 +1,18 @@ --- name: form-visual-check -description: "После правок или скриншота формы выполнить visual-check" +description: "После правок или скриншота формы выполнить визуальную проверку" alwaysApply: true --- # Визуальная проверка форм -> **Триггер:** после изменения управляемой формы, при исследовании/проверке клиентской формы через TestClient/VA/web-клиент, ИЛИ после получения скриншота формы на ревью. При срабатывании — применить навыки `visual-check` (`framework/skills/tool-usage/browser-ui/visual-check/SKILL.md`) и `form-visual-requirements` (`framework/skills/bsl-practices/form-visual-requirements/SKILL.md`). +> **Триггер:** после изменения управляемой формы, при исследовании/проверке клиентской формы через VA/TestClient, ИЛИ после получения скриншота формы на ревью. При срабатывании — применить навыки `va-visual-check` (`framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md`) и `form-visual-requirements` (`framework/skills/bsl-practices/form-visual-requirements/SKILL.md`). -Маршрут по умолчанию для форм 1С — Vanessa/TestClient или платформенный TestClient MCP. Визуальный скриншот обязателен: сначала пробуй проверенный VA MCP screenshot, если он реально работает в текущем окружении; иначе снимай внешний OS/noVNC screenshot видимого окна 1С. Web-клиент в `visual-check` выбирается только для browser-specific дефектов: DOM/CSS/HTML, JS console/network, web-auth/publication, viewport/pixel rendering, browser extension или browser-only file/clipboard. +Предпочтительный маршрут для форм 1С — Vanessa/TestClient и VA MCP: `connect_test_client` → реальный PID тест-клиента → `get_window_list_os` → `get_window_screenshot_os`. Детали маршрута, Linux headless X11/Xvfb рецепт для чёрных скриншотов и browser fallback описаны в `va-visual-check`. + +Платформенный TestClient MCP можно использовать для структурного управления формой, если это часть VA/TestClient-сценария. Если используется browser/web-client fallback, причину, выполненные VA-шаги и остаточный риск нужно явно записать в контекст. --- depends_on: - - visual-check + - framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md - form-visual-requirements --- diff --git a/framework/rules/framework-bootstrap/SKILL.md b/framework/rules/framework-bootstrap/SKILL.md index 32f5e974..81bfcc8d 100644 --- a/framework/rules/framework-bootstrap/SKILL.md +++ b/framework/rules/framework-bootstrap/SKILL.md @@ -1,6 +1,6 @@ --- name: framework-bootstrap -description: 1C BSL Agent Development Framework — портативный само-промотирующий стаб главного потока +description: "На старте или компакте загрузить профиль оркестратора" alwaysApply: true --- # 1C BSL Agent Development Framework diff --git a/framework/rules/git-workflow/SKILL.md b/framework/rules/git-workflow/SKILL.md index 6cbd3ece..778450bb 100644 --- a/framework/rules/git-workflow/SKILL.md +++ b/framework/rules/git-workflow/SKILL.md @@ -1,6 +1,6 @@ --- name: git-workflow -description: Гард git для агентского цикла — субагенты не коммитят; запрет удаления/git rm без явного разрешения пользователя; коммит и merge только оркестратор/пользователь. Процедура → навык git-workflow. +description: "Перед commit/delete применять git workflow guardrails" alwaysApply: true --- # Политика работы с Git diff --git a/framework/rules/infostart-kb/SKILL.md b/framework/rules/infostart-kb/SKILL.md index c7e2b41e..e0f076b4 100644 --- a/framework/rules/infostart-kb/SKILL.md +++ b/framework/rules/infostart-kb/SKILL.md @@ -1,6 +1,6 @@ --- name: infostart-kb -description: "Перед написанием/отладкой/проектированием 1С-кода → обратиться к навыку infostart-kb" +description: "Перед 1C дизайном/кодом/отладкой проверить Infostart" alwaysApply: true --- # База знаний Infostart (перед разработкой 1С) diff --git a/framework/rules/no-direct-db-access/SKILL.md b/framework/rules/no-direct-db-access/SKILL.md index 78989fbd..f7aa38e8 100644 --- a/framework/rules/no-direct-db-access/SKILL.md +++ b/framework/rules/no-direct-db-access/SKILL.md @@ -1,6 +1,6 @@ --- name: no-direct-db-access -description: Глобальный запрет прямого обращения к СУБД. Агенты работают с данными только через платформу 1С:Предприятие. Прямые запросы к СУБД допустимы только для анализа производительности и только на чтение. +description: "Данные читать/писать через платформу 1С, не СУБД" alwaysApply: true --- diff --git a/framework/rules/no-manual-xml-edit/SKILL.md b/framework/rules/no-manual-xml-edit/SKILL.md index 66fc3555..4a8f8a76 100644 --- a/framework/rules/no-manual-xml-edit/SKILL.md +++ b/framework/rules/no-manual-xml-edit/SKILL.md @@ -1,6 +1,6 @@ --- name: no-manual-xml-edit -description: Правишь 1С XML/MXL → применить навык xml-generation. Ручная правка запрещена; для агентов без PreToolUse-хука обязателен self-check через block-direct-xml-edit.py. +description: "При правке XML/MXL 1С использовать xml-generation" alwaysApply: true --- diff --git a/framework/rules/predefined-elements/SKILL.md b/framework/rules/predefined-elements/SKILL.md new file mode 100644 index 00000000..192bc6cb --- /dev/null +++ b/framework/rules/predefined-elements/SKILL.md @@ -0,0 +1,46 @@ +--- +name: predefined-elements +description: "Перед новой настройкой искать предопределённое значение" +alwaysApply: true +--- + +# Reuse-first для настроек и предопределенных значений + +> **Триггер:** задаче нужна настройка, именованное предопределенное значение, порог, флаг, код, ссылка на объект или другой параметр, который должен жить централизованно. + +## Принцип + +Настройки, размноженные по копиям или зашитые литералами в код, расходятся между установками и молча ломают логику. Если в проекте уже есть централизованное хранилище настроек или именованных предопределенных значений, агент обязан сначала искать значение там и использовать штатный слой доступа к нему. + +## MUST + +| Требование | Описание | +|-----------|----------| +| Сначала поиск | Перед созданием новой настройки или хардкодом значения найти существующее значение по бизнес-ключу через штатный механизм проекта. Нашел - переиспользовать, не плодить дубль | +| Чтение через обертки | Если в проекте есть сервисный модуль, API или БСП-обертка доступа к настройкам, использовать ее, а не прямой запрос к хранилищу | +| Запрет хардкода | Не зашивать коды, ссылки, пороги и флаги, которые должны быть управляемыми настройками. Значение должно читаться по осмысленному бизнес-ключу | +| Новый ключ только при отсутствии | Создавать новую настройку только после проверки отсутствия существующего ключа и коллизий по назначению | +| Ключ в одном месте | Строковый бизнес-ключ объявлять один раз: константа, экспортная функция или единая точка доступа. Не дублировать литерал по коду | +| Документировать назначение | Для новой настройки фиксировать назначение, формат значения, владельца логики и допустимое значение по умолчанию в артефактах задачи или проектной документации | + +## SHOULD + +- Если настройка нужна нескольким местам, все они читают ее через один и тот же ключ и один слой доступа. +- Если проект не имеет централизованного хранилища настроек, сначала проверить типовые или библиотечные механизмы, а не создавать локальный справочник/регистр без архитектурного решения. +- Для миграции старого хардкода сначала найти все места использования литерала и определить единый ключ, затем заменить обращения через общий API. + +## Что НЕ покрывается этим правилом + +- Настройки, являющиеся полноценной предметной моделью со сложной идентификацией и жизненным циклом. Для них нужен отдельный дизайн, а не key-value запись. +- Типовые механизмы хранения настроек платформы или библиотек. Их нужно переиспользовать по правилам `ssl-patterns`, если они подходят задаче. + +## Связанные правила + +- `search-before-write` - reuse-first для кода и готовых механизмов. +- `ssl-patterns` - переиспользование типовых и библиотечных механизмов. + +--- +depends_on: + - search-before-write + - ssl-patterns +--- diff --git a/framework/rules/protected-paths/SKILL.md b/framework/rules/protected-paths/SKILL.md index ba1c9916..3f7b4489 100644 --- a/framework/rules/protected-paths/SKILL.md +++ b/framework/rules/protected-paths/SKILL.md @@ -1,6 +1,6 @@ --- name: protected-paths -description: Глобальная защита путей. Категорически запрещает модификацию защищённых директорий для любых агентов и сабагентов. +description: "Перед записью или удалением проверить protected paths" alwaysApply: true --- diff --git a/framework/rules/query-optimize/SKILL.md b/framework/rules/query-optimize/SKILL.md index 8a76f51c..90b00531 100644 --- a/framework/rules/query-optimize/SKILL.md +++ b/framework/rules/query-optimize/SKILL.md @@ -1,6 +1,6 @@ --- name: query-optimize -description: "После выявления медленного запроса → применить навык query-optimize" +description: "После обнаружения медленного запроса применить optimize" alwaysApply: true --- # Оптимизация запросов (после выявления проблемы) diff --git a/framework/rules/query-patterns/SKILL.md b/framework/rules/query-patterns/SKILL.md index 32ea258e..b07567fb 100644 --- a/framework/rules/query-patterns/SKILL.md +++ b/framework/rules/query-patterns/SKILL.md @@ -1,6 +1,6 @@ --- name: query-patterns -description: "Перед написанием нового запроса → применить навык query-patterns" +description: "Перед новым запросом 1С применить query-patterns" alwaysApply: true --- # Паттерны запросов (перед написанием) diff --git a/framework/rules/report-discovered-issues/SKILL.md b/framework/rules/report-discovered-issues/SKILL.md new file mode 100644 index 00000000..16821078 --- /dev/null +++ b/framework/rules/report-discovered-issues/SKILL.md @@ -0,0 +1,70 @@ +--- +name: report-discovered-issues +description: "Найденные вне scope дефекты сообщать после задачи" +alwaysApply: true +--- + +# Доклад о найденных проблемах + +> Агент часто видит больше, чем нужно для текущей задачи. Молчаливо проигнорированная находка остается неисправленным риском, поэтому ее нужно явно донести до пользователя. + +## Принцип + +Решая одну задачу, агент может найти регрессии, ошибки в смежных модулях, техдолг, антипаттерны, расхождения кода со спецификацией, проблемы производительности или безопасности. Эти находки не нужно чинить внутри текущей задачи без разрешения пользователя, но их нельзя скрывать. + +## MUST + +| Требование | Описание | +|-----------|----------| +| Фиксировать находки | По мере обнаружения записывать проблему в рабочий контекст, заметки задачи или раздел финального отчета | +| Не расширять scope молча | Не исправлять найденные проблемы внутри текущей задачи без явного разрешения пользователя | +| Доложить после завершения | В финальном ответе или отчете перечислить найденные проблемы, которые не относятся к выполненному scope | +| Давать конкретику | Для каждой находки указать место, суть, риск, серьезность и примерный размер исправления | +| Предложить путь | Предложить дальнейшее действие: отдельная задача, quick-fix, отложить, задокументировать или проверить дополнительно | + +## Формат доклада + +```markdown +## Найдено по пути + +### 1. [Краткое название] +- **Где:** `path/to/file:line` +- **Что:** конкретное описание проблемы +- **Почему проблема:** последствия или риск +- **Серьезность:** критично / средне / низко +- **Усилие:** простой фикс / отдельная задача / большая работа +- **Предложение:** что сделать дальше +``` + +## Что докладывать обязательно + +- Баги, которые могут привести к потере данных, денег, безопасности или доступности. +- Регрессии и расхождения с источником истины. +- Проблемы целостности данных. +- Краши или исключения, возможные в рабочем сценарии. +- Ошибки в тестах или инфраструктуре, которые маскируют реальный результат. + +## Что можно не докладывать + +- Чисто стилистические мелочи без влияния на сопровождение. +- Опечатки в комментариях. +- Абстрактные пожелания по рефакторингу без конкретного риска. + +## Что НЕ делать + +- Не превращать текущую задачу в уборку всего найденного. +- Не откладывать доклад "на потом". +- Не объединять разные проблемы в одну расплывчатую фразу. +- Не драматизировать и не преуменьшать: описание должно быть проверяемым. + +## Связанные правила + +- `agent-context-protocol` - где фиксировать рабочий контекст и найденные проблемы. +- `quick-fix` / `full-cycle` - как превращать находки в дальнейшую работу. +- `source-of-truth` - как проверять расхождения между артефактами. + +--- +depends_on: + - agent-context-protocol + - source-of-truth +--- diff --git a/framework/rules/rlm-workflow/SKILL.md b/framework/rules/rlm-workflow/SKILL.md index 30807cfa..feeb373e 100644 --- a/framework/rules/rlm-workflow/SKILL.md +++ b/framework/rules/rlm-workflow/SKILL.md @@ -1,6 +1,6 @@ --- name: rlm-workflow -description: Универсальные переиспользуемые знания (паттерны, арх-решения, домен-факты) → RLM, НЕ в контекст. Перед нетривиальной задачей/решением в домене — pull из RLM. Native-память — только тощее always-on ядро. +description: "Перед нетривиальной доменной работой читать RLM" alwaysApply: true --- # Раскладка памяти и работа с RLM diff --git a/framework/rules/sdd-policy/SKILL.md b/framework/rules/sdd-policy/SKILL.md index 5fc31a76..22b64f66 100644 --- a/framework/rules/sdd-policy/SKILL.md +++ b/framework/rules/sdd-policy/SKILL.md @@ -1,6 +1,6 @@ --- name: sdd-policy -description: Новая фича / архитектурное изменение / сложный баг → спека до кода. Применить навык spec-standard. +description: "Для features, архитектуры и сложных багов сначала spec" alwaysApply: true --- diff --git a/framework/rules/search-before-write/SKILL.md b/framework/rules/search-before-write/SKILL.md index 34a2b504..05fe07da 100644 --- a/framework/rules/search-before-write/SKILL.md +++ b/framework/rules/search-before-write/SKILL.md @@ -1,6 +1,6 @@ --- name: search-before-write -description: "Перед созданием новой функции/запроса/обработки → применить навык search-before-write" +description: "Перед новым кодом или запросом искать существующее" alwaysApply: true --- # Поиск перед написанием diff --git a/framework/rules/security/SKILL.md b/framework/rules/security/SKILL.md index c66049ab..5f4bb687 100644 --- a/framework/rules/security/SKILL.md +++ b/framework/rules/security/SKILL.md @@ -1,6 +1,6 @@ --- name: security -description: "Работа с паролями/токенами/крипто/привилегиями → применить навык security" +description: "Для секретов, токенов, crypto, privileges применять security" alwaysApply: true --- # Безопасность 1С diff --git a/framework/rules/semantic-code-comments/SKILL.md b/framework/rules/semantic-code-comments/SKILL.md new file mode 100644 index 00000000..cc39faa3 --- /dev/null +++ b/framework/rules/semantic-code-comments/SKILL.md @@ -0,0 +1,109 @@ +--- +name: semantic-code-comments +description: "В комментариях объяснять зачем, не пересказывать код" +alwaysApply: true +--- + +# Семантические комментарии в коде + +> Хороший комментарий объясняет **почему**, а не **что**. Имена, структура и выражения уже показывают действие кода; комментарий нужен для бизнес-смысла, ограничений, компромиссов и скрытых инвариантов. + +## Принцип + +Код пишется один раз, а читается много раз. Если будущий читатель будет спрашивать "почему так?", "что сломается, если убрать?", "какое бизнес-правило здесь защищено?" - нужен семантический комментарий. + +Цель не в плотности комментариев, а в снятии догадок при чтении сложного или неочевидного кода. + +## Что комментировать + +### Неочевидные бизнес-правила + +```bsl +// Скидку применяем только после подтверждения лимита, потому что договор +// может запрещать ретроспективное изменение цены. +Если ЛимитПодтвержден И ДоговорРазрешаетИзменениеЦены Тогда +``` + +### Защиту от внешних сбоев и краевых случаев + +```bsl +// Внешний сервис иногда возвращает пустую сумму для закрытого периода. +// Считаем ее нулем, чтобы отчет остался построимым, а не падал на преобразовании. +Сумма = ?(ЗначениеЗаполнено(Ответ.Сумма), Ответ.Сумма, 0); +``` + +### Workaround и компромиссы + +```bsl +// Не используем пакетную запись: обработчик записи должен отработать для каждого +// объекта отдельно, иначе не обновятся зависимые агрегаты. +Для Каждого Объект Из Объекты Цикл +``` + +### Скрытые инварианты и порядок вызовов + +```bsl +// Важно выполнить до расчета итогов: эта процедура заполняет временную таблицу, +// из которой следующий запрос берет границы периода. +ПодготовитьГраницыПериода(Параметры); +``` + +### Причины отказа от очевидного решения + +```bsl +// Не используем левое соединение: downstream-логика требует обязательную ссылку +// и не имеет безопасной ветки для пустого значения. +ВНУТРЕННЕЕ СОЕДИНЕНИЕ +``` + +### Магические числа и константы + +```bsl +МаксимумПопыток = 3; // Больше трех повторов задерживает пользователя сильнее, чем помогает при временном сбое. +``` + +## Что НЕ комментировать + +### Пересказ кода + +```bsl +// Плохо: складываем A и B. +Сумма = A + B; +``` + +### Очевидные операции + +```bsl +// Плохо: увеличиваем счетчик. +Счетчик = Счетчик + 1; +``` + +### Комментарии, противоречащие коду + +Если правишь код, проверь комментарии рядом. Устаревший комментарий хуже отсутствующего, потому что создает ложную уверенность. + +## SHOULD + +- Перед нетривиальным блоком сложной логики дать краткое объяснение назначения блока. +- В начале процедуры добавить комментарий назначения, если оно не следует из имени. +- Ссылаться на спецификацию, ADR или задачу, когда без внешнего контекста причина решения непонятна. +- Объяснять ограничения внешних систем, платформы, библиотек и данных. +- Комментировать намеренно странный код: почему он выглядит необычно и что сломается при "упрощении". + +## Как формулировать + +| Хорошо | Плохо | +|--------|-------| +| "Не используем X, потому что Y" | "Здесь X" | +| "Защита от пустого ответа внешнего сервиса" | "Проверяем значение" | +| "Если убрать, нарушится инвариант периода" | "Не трогать" | +| "Сначала заполняем кэш, потому что следующий запрос читает его" | "Заполняем кэш" | + +## Связь с разметкой изменений + +`agent-code-marking` показывает, кто и когда изменил код. `semantic-code-comments` объясняет, почему код устроен именно так. Эти правила дополняют друг друга: маркеры дают аудит, комментарии дают смысл. + +--- +depends_on: + - agent-code-marking +--- diff --git a/framework/rules/skill-learning-policy/SKILL.md b/framework/rules/skill-learning-policy/SKILL.md index 7c996557..c09afd2d 100644 --- a/framework/rules/skill-learning-policy/SKILL.md +++ b/framework/rules/skill-learning-policy/SKILL.md @@ -1,6 +1,6 @@ --- name: skill-learning-policy -description: Накопление знаний, два триггера. ЗАПИСЬ — после цикла с ≥2 итерациями провести ретроспективу. ЧТЕНИЕ — перед работой с навыком прочитать его references/learned-patterns.md. Процедура и формат записи → навык skill-learning. +description: "До skill use и после итераций обновлять learned patterns" alwaysApply: true --- # Политика накопления знаний (Skill Learning) diff --git a/framework/rules/source-of-truth/SKILL.md b/framework/rules/source-of-truth/SKILL.md index d63b6249..443cfd07 100644 --- a/framework/rules/source-of-truth/SKILL.md +++ b/framework/rules/source-of-truth/SKILL.md @@ -1,6 +1,6 @@ --- name: source-of-truth -description: Конфликт / падение теста / спор артефактов → проверь цепочку источников правды сверху вниз (L1→L6). Метод — в навыке source-of-truth. +description: "При конфликтах и падениях следовать source-of-truth" alwaysApply: true --- # Политика источников правды (Source of Truth) diff --git a/framework/rules/ssl-patterns/SKILL.md b/framework/rules/ssl-patterns/SKILL.md index 870eeb94..05c9bb9d 100644 --- a/framework/rules/ssl-patterns/SKILL.md +++ b/framework/rules/ssl-patterns/SKILL.md @@ -1,6 +1,6 @@ --- name: ssl-patterns -description: "Перед реализацией логики — проверить наличие готового в БСП → навык ssl-patterns" +description: "Перед кастомной логикой проверить механизмы БСП" alwaysApply: true --- # БСП-паттерны (перед реализацией) diff --git a/framework/rules/tdd-policy/SKILL.md b/framework/rules/tdd-policy/SKILL.md index 06b248e6..e5ef5391 100644 --- a/framework/rules/tdd-policy/SKILL.md +++ b/framework/rules/tdd-policy/SKILL.md @@ -1,6 +1,6 @@ --- name: tdd-policy -description: Пишешь тесты или код → тесты до реализации (Red→Green). Применить навык test-writing. +description: "При коде или тестах идти Red -> Green" alwaysApply: true --- diff --git a/framework/rules/test-zero-residue/SKILL.md b/framework/rules/test-zero-residue/SKILL.md index 9b101bd5..404200a0 100644 --- a/framework/rules/test-zero-residue/SKILL.md +++ b/framework/rules/test-zero-residue/SKILL.md @@ -1,6 +1,6 @@ --- name: test-zero-residue -description: Любой тест, пишущий в БД, не оставляет следов прогона — все созданные объекты физически зачищены, дельта по справочникам/регистрам/документам до и после прогона = 0. Применить навык test-writing. +description: "Для DB-writing тестов обязателен zero-residue cleanup" alwaysApply: true --- diff --git a/framework/rules/vanessa-diagnostics-policy/SKILL.md b/framework/rules/vanessa-diagnostics-policy/SKILL.md index 8c5bc008..54ed1fbb 100644 --- a/framework/rules/vanessa-diagnostics-policy/SKILL.md +++ b/framework/rules/vanessa-diagnostics-policy/SKILL.md @@ -1,6 +1,6 @@ --- name: vanessa-diagnostics-policy -description: Прогон Vanessa не прошёл → диагностировать в порядке ЖР → визуал → техжурнал. Применить навык vanessa-diagnostics. +description: "При падении Vanessa: ЖР -> visual -> tech log" alwaysApply: true --- @@ -13,7 +13,7 @@ alwaysApply: true | Приоритет | Источник | Условие | |-----------|----------|---------| | 1-й | Журнал регистрации (`event-log`) | Основной источник ошибок — смотреть первым | -| 2-й | Визуальная диагностика (noVNC / скриншот) | При подозрении на GUI-блокировку или `Предупреждение безопасности` | +| 2-й | Визуальная диагностика | Для состояния формы тест-клиента, GUI-блокировки, modal/manager window и `Предупреждение безопасности` — визуальный артефакт по `va-visual-check`: сначала VA MCP-скриншот, при необходимости fallback с фиксацией причины | | 3-й | Технологический журнал | Только если `event-log` и визуал не дали ответа | - Не полагаться слепо на локальные временные окна: ClickHouse и локальное время могут расходиться (timezone drift). diff --git a/framework/rules/vanessa-run-loop/SKILL.md b/framework/rules/vanessa-run-loop/SKILL.md index ee840bde..fd9ce556 100644 --- a/framework/rules/vanessa-run-loop/SKILL.md +++ b/framework/rules/vanessa-run-loop/SKILL.md @@ -1,6 +1,6 @@ --- name: vanessa-run-loop -description: Изменил .feature / конфиг tests.va / MCP-расширение → обязателен прогон v8-runner test va. Применить навыки v8-runner и vanessa-diagnostics. +description: "После правок feature/tests.va/MCP запускать VA tests" alwaysApply: true --- diff --git a/framework/rules/vanessa-scenario-policy/SKILL.md b/framework/rules/vanessa-scenario-policy/SKILL.md index 5f2a4abd..66a71e9a 100644 --- a/framework/rules/vanessa-scenario-policy/SKILL.md +++ b/framework/rules/vanessa-scenario-policy/SKILL.md @@ -1,6 +1,6 @@ --- name: vanessa-scenario-policy -description: Пишешь / обновляешь Vanessa feature-файл → применить навык vanessa-authoring. +description: "При написании Vanessa features применять authoring rules" alwaysApply: true --- @@ -32,8 +32,8 @@ alwaysApply: true - **Тег задачи обязателен.** Каждый `.feature`-файл MUST содержать тег `@task-` (например `@task-103`) на уровне `Функциональность:`. - **Комментарий-источник.** В шапке файла (перед тегами) MUST быть комментарий: `# Задача: — <название>`. - Не гадай логику — читай код (делегируй Explorer / `code-navigation`). Расхождение кода и теста — это найденное несоответствие, фиксируй как результат. -- **Не гадай интерфейс** — имена и заголовки элементов, поля, кнопки, закладки, доступность и состояние элементов берутся из **реального отрендеренного интерфейса**, исследованного через веб-клиент (`gui-control` / `screenshot` / `chrome-devtools`-snapshot), а не из догадок по коду или памяти. Помни о разнице идентификаторов: шаги «содержит строки» / «перехожу к строке» ждут **заголовок (Title)**, «запоминаю значение поля» ждёт **имя (name)** — точное значение узнаётся осмотром формы, не угадывается. Расхождение сценария и реального UI — найденное несоответствие, фиксируй как результат. -- **Ручное заполнение перед сценарием.** Новый сценарий по документу пишется ПОСЛЕ ручного заполнения формы в веб-клиенте со сверкой состава формы **на каждом шаге** (значение поля влияет на видимость/обязательность других полей); ключевые поля шапки и обязательные ТЧ (≥ нескольких строк) заполнены; Подсказка/справочные данные документа изучены; учтены полосы прокрутки, скрывающие поля. При необходимости по смыслу теста — документ **записан и проведён**, всплывающие ошибки внизу экрана разобраны и заполнение скорректировано. Сценарии заполнения — переиспользуемые «кубики» (`@exportscenarios`), один документ может иметь несколько. Детали — `vanessa-authoring`. +- **Не гадай интерфейс** — имена и заголовки элементов, поля, кнопки, закладки, доступность и состояние элементов берутся из **реального отрендеренного интерфейса**, исследованного через Vanessa/TestClient или через fallback по `va-visual-check`, а не из догадок по коду или памяти. Помни о разнице идентификаторов: шаги «содержит строки» / «перехожу к строке» ждут **заголовок (Title)**, «запоминаю значение поля» ждёт **имя (name)** — точное значение узнаётся осмотром формы, не угадывается. Расхождение сценария и реального UI — найденное несоответствие, фиксируй как результат. +- **Ручное заполнение перед сценарием.** Новый сценарий по документу пишется ПОСЛЕ ручного заполнения формы через Vanessa/TestClient со сверкой состава формы **на каждом шаге** (значение поля влияет на видимость/обязательность других полей); ключевые поля шапки и обязательные ТЧ (≥ нескольких строк) заполнены; Подсказка/справочные данные документа изучены; учтены полосы прокрутки, скрывающие поля. При необходимости по смыслу теста — документ **записан и проведён**, всплывающие ошибки внизу экрана разобраны и заполнение скорректировано. Сценарии заполнения — переиспользуемые «кубики» (`@exportscenarios`), один документ может иметь несколько. Детали — `vanessa-authoring`. --- depends_on: diff --git a/framework/rules/vanessa-security-warning/SKILL.md b/framework/rules/vanessa-security-warning/SKILL.md index def2dbe2..0ee27fcd 100644 --- a/framework/rules/vanessa-security-warning/SKILL.md +++ b/framework/rules/vanessa-security-warning/SKILL.md @@ -1,6 +1,6 @@ --- name: vanessa-security-warning -description: В ЖР есть запись о «Предупреждение безопасности» → обязательная визуальная проверка. Применить навыки gui-control / screenshot. +description: "Security Warning в ЖР требует visual verification" alwaysApply: true --- @@ -13,13 +13,14 @@ alwaysApply: true | Требование | Описание | |------------|----------| | ЖР как триггер | Запись о `Предупреждение безопасности` в ЖР → обязательная визуальная проверка | -| Визуальная проверка обязательна | MUST использовать реальный экран: noVNC или скриншот | -| Не полагаться на X11-эвристику | Нельзя делать вывод только по `wmctrl`/`xwininfo`/заголовкам окон | +| Визуальная проверка обязательна | MUST использовать VA MCP-скриншот реального окна тест-клиента | +| Не полагаться на X11-эвристику | Нельзя делать вывод только по `wmctrl`/`xwininfo`/заголовкам окон; визуальный артефакт получать по `va-visual-check` | +| Скриншот валидируется | Проверить, что PNG не пустой/чёрный; Linux/Xvfb и fallback-случаи выполнять по `va-visual-check` | | Trust-flow только для первого запуска | Первый запуск после изменения EPF не считается валидным тестовым прогоном | --- depends_on: - framework/skills/tool-usage/browser-ui/gui-control/SKILL.md - - framework/skills/tool-usage/browser-ui/screenshot/SKILL.md + - framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md - framework/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md --- diff --git a/framework/rules/vanessa-test-isolation-policy/SKILL.md b/framework/rules/vanessa-test-isolation-policy/SKILL.md index 3eb53e36..0c7a0446 100644 --- a/framework/rules/vanessa-test-isolation-policy/SKILL.md +++ b/framework/rules/vanessa-test-isolation-policy/SKILL.md @@ -1,6 +1,6 @@ --- name: vanessa-test-isolation-policy -description: Пишешь Vanessa-сценарий с записью данных → полная изоляция (тест создаёт свои объекты). Применить навык vanessa-authoring. +description: "Для data-writing Vanessa tests изолировать данные" alwaysApply: true --- diff --git a/framework/rules/vanessa-tests-location/SKILL.md b/framework/rules/vanessa-tests-location/SKILL.md index 78282082..e1856057 100644 --- a/framework/rules/vanessa-tests-location/SKILL.md +++ b/framework/rules/vanessa-tests-location/SKILL.md @@ -1,6 +1,6 @@ --- name: vanessa-tests-location -description: Создаёшь / обновляешь Vanessa feature-файл → соблюдать конвенцию расположения. Применить навык vanessa-authoring для деталей. +description: "При добавлении Vanessa features соблюдать location rules" alwaysApply: true --- diff --git a/framework/rules/yaxunit-isolation/SKILL.md b/framework/rules/yaxunit-isolation/SKILL.md index f81c4d94..aa2990af 100644 --- a/framework/rules/yaxunit-isolation/SKILL.md +++ b/framework/rules/yaxunit-isolation/SKILL.md @@ -1,6 +1,6 @@ --- name: yaxunit-isolation -description: Пишешь серверный YaxUnit-тест, который пишет в БД → обязательная транзакционная изоляция через .ВТранзакции(). Применить навык test-writing. +description: "Для DB-writing YaxUnit tests использовать transaction" alwaysApply: false --- diff --git a/framework/skills/agent-process/quick-fix/SKILL.md b/framework/skills/agent-process/quick-fix/SKILL.md index 834637dc..4b6daf6d 100644 --- a/framework/skills/agent-process/quick-fix/SKILL.md +++ b/framework/skills/agent-process/quick-fix/SKILL.md @@ -42,6 +42,10 @@ guard ниже. 1. `get_diagnostics` — быстрая проверка изменённого файла 2. `run_tests` — если есть тесты для модуля 3. `check_syntax` — финальная проверка перед коммитом +4. Покрытие по runtime-слою изменения: + - если изменена серверная логика/серверный метод/запрос — актуализировать и запустить YaxUnit-тест; если теста нет, добавить минимальный YaxUnit-тест или эскалировать в full-cycle; + - если изменён UI или клиентский контекст (форма, команда, кнопка, клиентский обработчик, `ОткрытьФорму`, видимость/доступность) — выполнить сценарную проверку пользовательского действия в живой ИБ/тестовом клиенте: открыть entrypoint, выполнить действие, убедиться что оно запускается/завершается без ошибки; + - если проверка технически невозможна — явно зафиксировать это в ответе как непокрытый риск; молчаливый пропуск запрещён. ## Эскалация на full-цикл diff --git a/framework/skills/bsl-practices/api-design/SKILL.md b/framework/skills/bsl-practices/api-design/SKILL.md index 8543e726..4cd8489d 100644 --- a/framework/skills/bsl-practices/api-design/SKILL.md +++ b/framework/skills/bsl-practices/api-design/SKILL.md @@ -1,6 +1,6 @@ --- name: api-design -description: "Use for проектирования и ревью публичного API подсистем 1С. Helps классифицировать экспортные методы по 5 категориям, проверить обратную совместимость и спроектировать версионирование с deprecated-обёртками." +description: "Для проектирования и ревью публичного API подсистем 1С" --- # API Design — проектирование и ревью интерфейсов подсистем 1С diff --git a/framework/skills/bsl-practices/background-jobs/SKILL.md b/framework/skills/bsl-practices/background-jobs/SKILL.md index 3360ba39..56d4ed02 100644 --- a/framework/skills/bsl-practices/background-jobs/SKILL.md +++ b/framework/skills/bsl-practices/background-jobs/SKILL.md @@ -1,6 +1,6 @@ --- name: background-jobs -description: "Use for проектирования, диагностики и исправления фоновых и регламентных заданий 1С. Helps обеспечить идемпотентность, retry-политику, checkpointing, mutex и разделение retryable/permanent ошибок." +description: "Для проектирования и отладки фоновых заданий 1С" skills: - architect - developer-code diff --git a/framework/skills/bsl-practices/coding-standards/SKILL.md b/framework/skills/bsl-practices/coding-standards/SKILL.md index 86e60374..029464d2 100644 --- a/framework/skills/bsl-practices/coding-standards/SKILL.md +++ b/framework/skills/bsl-practices/coding-standards/SKILL.md @@ -1,6 +1,6 @@ --- name: coding-standards -description: "MUST use WHEN пишешь или ревьюишь BSL-код. Provides стандарты именования, структуру модулей, типовые антипаттерны и рекомендации ИТС для платформы 1С:Предприятие." +description: "При написании или ревью BSL применять стандарты 1С" alwaysApply: false --- diff --git a/framework/skills/bsl-practices/data-exchange/SKILL.md b/framework/skills/bsl-practices/data-exchange/SKILL.md index 6ee54205..0d7a0a07 100644 --- a/framework/skills/bsl-practices/data-exchange/SKILL.md +++ b/framework/skills/bsl-practices/data-exchange/SKILL.md @@ -1,6 +1,6 @@ --- name: data-exchange -description: "Use for реализации и диагностики обмена данными 1С (РИБ, КД 2.0/3.0, EnterpriseData, БСП). Helps выбрать модель обмена, обеспечить идемпотентность пакетов и явное разрешение конфликтов." +description: "Для обменов 1С: РИБ, КД, EnterpriseData, БСП" --- # Обмен данными 1С diff --git a/framework/skills/bsl-practices/error-handling/SKILL.md b/framework/skills/bsl-practices/error-handling/SKILL.md index edbb8ef8..41af2d55 100644 --- a/framework/skills/bsl-practices/error-handling/SKILL.md +++ b/framework/skills/bsl-practices/error-handling/SKILL.md @@ -1,6 +1,6 @@ --- name: error-handling -description: "MUST use WHEN обрабатываешь исключения или управляешь транзакциями в BSL. Provides каноническую схему Попытка/Исключение, правила отката транзакций и управления блокировками данных." +description: "Для BSL-исключений, транзакций, откатов и блокировок" alwaysApply: false --- diff --git a/framework/skills/bsl-practices/form-patterns/SKILL.md b/framework/skills/bsl-practices/form-patterns/SKILL.md index 79633f66..e9020ce8 100644 --- a/framework/skills/bsl-practices/form-patterns/SKILL.md +++ b/framework/skills/bsl-practices/form-patterns/SKILL.md @@ -1,6 +1,6 @@ --- name: form-patterns -description: "MUST use WHEN пишешь код модуля управляемой формы 1С. Provides правила выбора директив контекста (&НаСервереБезКонтекста и др.) и минимизации серверных round-trip." +description: "При коде управляемых форм и серверных вызовах" alwaysApply: false --- diff --git a/framework/skills/bsl-practices/form-visual-requirements/SKILL.md b/framework/skills/bsl-practices/form-visual-requirements/SKILL.md index 89d59c26..20e114ce 100644 --- a/framework/skills/bsl-practices/form-visual-requirements/SKILL.md +++ b/framework/skills/bsl-practices/form-visual-requirements/SKILL.md @@ -1,6 +1,6 @@ --- name: form-visual-requirements -description: "MUST use WHEN проверяешь визуальное оформление формы 1С (скриншот или результат visual-check). Provides чек-лист компоновки, выравнивания, подписей и UX-критериев." +description: "При визуальной проверке форм 1С: layout, labels, UX" alwaysApply: false --- @@ -8,6 +8,8 @@ alwaysApply: false Используй этот чек-лист для проверки форм 1С. +Перед оценкой изображения проверь, что PNG не пустой и не одноцветный/чёрный. Как получать скриншот формы, как действовать в Xvfb и когда допустим browser fallback — см. профильный навык `va-visual-check`. + ## 1. Разметка и выравнивание - [ ] **Выравнивание**: элементы выровнены по сетке, без эффекта «лесенки». diff --git a/framework/skills/bsl-practices/integration-patterns/SKILL.md b/framework/skills/bsl-practices/integration-patterns/SKILL.md index 850eacb9..c19c78a0 100644 --- a/framework/skills/bsl-practices/integration-patterns/SKILL.md +++ b/framework/skills/bsl-practices/integration-patterns/SKILL.md @@ -1,6 +1,6 @@ --- name: integration-patterns -description: "Use for проектирования HTTP-сервисов и интеграций 1С (REST/SOAP/webhook). Helps зафиксировать контракт до кода, реализовать аутентификацию (Basic/OAuth/CertificateAuth), retry и безопасное хранение секретов." +description: "Для 1C HTTP/REST/SOAP, auth, retry, webhooks" --- # Паттерны интеграции 1С diff --git a/framework/skills/bsl-practices/query-optimize/SKILL.md b/framework/skills/bsl-practices/query-optimize/SKILL.md index e9663826..1552b0e8 100644 --- a/framework/skills/bsl-practices/query-optimize/SKILL.md +++ b/framework/skills/bsl-practices/query-optimize/SKILL.md @@ -1,6 +1,6 @@ --- name: query-optimize -description: "MUST use WHEN нужно ускорить существующий запрос или переписать СКД dataset. Provides правила устранения query-in-loop, dot-dereference, виртуальных таблиц без параметров и излишних итогов." +description: "Для оптимизации медленных запросов 1С и наборов СКД" target_agents: - developer-code - architect diff --git a/framework/skills/bsl-practices/query-patterns/SKILL.md b/framework/skills/bsl-practices/query-patterns/SKILL.md index d9dd2e1d..3851dbdd 100644 --- a/framework/skills/bsl-practices/query-patterns/SKILL.md +++ b/framework/skills/bsl-practices/query-patterns/SKILL.md @@ -1,6 +1,6 @@ --- name: query-patterns -description: "MUST use WHEN пишешь новый запрос на языке запросов 1С:Предприятие. Provides базовые паттерны параметризации, обработки NULL, пакетных выборок и запретов запросов в цикле." +description: "При написании новых запросов 1С и параметров" alwaysApply: false --- diff --git a/framework/skills/bsl-practices/security/SKILL.md b/framework/skills/bsl-practices/security/SKILL.md index 58d09f2f..14fccc9d 100644 --- a/framework/skills/bsl-practices/security/SKILL.md +++ b/framework/skills/bsl-practices/security/SKILL.md @@ -1,6 +1,6 @@ --- name: security -description: "MUST use WHEN работаешь с паролями, токенами, ЭЦП, TLS или привилегированным режимом в коде 1С. Provides правила хранения секретов в БезопасноеХранилище, криптографии (ГОСТ/МенеджерКриптографии) и аутентификации." +description: "Для секретов, токенов, TLS, подписей и привилегий 1С" alwaysApply: false --- diff --git a/framework/skills/bsl-practices/ssl-patterns/SKILL.md b/framework/skills/bsl-practices/ssl-patterns/SKILL.md index a8260e55..4f9dab45 100644 --- a/framework/skills/bsl-practices/ssl-patterns/SKILL.md +++ b/framework/skills/bsl-practices/ssl-patterns/SKILL.md @@ -1,6 +1,6 @@ --- name: ssl-patterns -description: "MUST use WHEN используешь или расширяешь функциональность БСП (Библиотека стандартных подсистем). Provides каталог готовых функций ОбщегоНазначения и правила вызова подсистем без дублирования." +description: "Перед логикой на БСП проверить готовые механизмы" uses_capabilities: - get_signature_help alwaysApply: false diff --git a/framework/skills/bsl-practices/test-writing/SKILL.md b/framework/skills/bsl-practices/test-writing/SKILL.md index 9b09d1bb..e1ddce30 100644 --- a/framework/skills/bsl-practices/test-writing/SKILL.md +++ b/framework/skills/bsl-practices/test-writing/SKILL.md @@ -1,6 +1,6 @@ --- name: test-writing -description: "Use for написания тестовых модулей YaxUnit (BSL). Covers регистрация тестов, утверждения, мокирование и подготовку тестовых данных." +description: "Для YaxUnit-тестов BSL, моков и assertions" --- # Написание тестов YaxUnit (BSL) @@ -59,6 +59,47 @@ description: "Use for написания тестовых модулей YaxUnit --- +## Одноразовые операционные YaxUnit-модули + +Иногда YaxUnit используют не как регрессионный тест, а как одноразовый серверный канал для ручной production-операции: исправить данные, перепровести точечный набор документов, выполнить контролируемую миграцию. Такой модуль НЕ является обычным тестом и не должен случайно попасть в режим «запустить все тесты». + +### Обязательная маркировка + +| Что маркировать | Конвенция | +|-----------------|-----------| +| Имя модуля | `Опер_<Описание>[_Номер]` или проектный префикс + явный фрагмент `_Операция_`; не маскировать под обычный `_Тест` | +| Заголовок модуля | Комментарий первой строкой: `// ONE_OFF_YAXUNIT_OPERATION: НЕ ЗАПУСКАТЬ В ОБЩЕМ ПРОГОНЕ. <назначение>` | +| Имя набора | Префикс `[ONE_OFF_OPERATION] <краткое назначение>` | +| Теги YaxUnit | `.Тег("one-off-operation")` на наборе и, если тесты регистрируются отдельно, на каждом операционном тесте | +| Контекст запуска | Комментарий рядом с регистрацией: кто разрешил операцию, на какой базе/контуре можно запускать, как проверить результат и как вывести модуль из общего прогона после выполнения | + +### Барьер от общего прогона + +Маркер и тег — это навигация, а не защита. Операционный модуль MUST иметь технический барьер, из-за которого обычный all-tests не регистрирует и не выполняет операцию: + +1. Предпочтительно — не держать такой модуль зарегистрированным в общем тестовом расширении после выполнения операции: перенести в артефакты задачи, удалить регистрацию или отключить модуль отдельной задачей сопровождения. +2. Если модуль временно остаётся в тестовом расширении, `ИсполняемыеСценарии()` MUST возвращаться без `ДобавитьТестовыйНабор()` без явного opt-in. Opt-in задаётся отдельным параметром запуска/настройкой/обёрткой и документируется в комментарии у регистрации. Обычный «запустить все тесты» этот opt-in не устанавливает. +3. Точечный запуск операционного модуля допускается только явным фильтром по модулю/методу и тегу `one-off-operation`, после отдельного подтверждения оператора. Запуск без фильтра модулей/методов запрещён. +4. После успешной операции агент MUST зафиксировать, как модуль выведен из общего прогона. Оставить исполняемый production-operation модуль в общем all-tests без opt-in барьера запрещено. + +```bsl +// ONE_OFF_YAXUNIT_OPERATION: НЕ ЗАПУСКАТЬ В ОБЩЕМ ПРОГОНЕ. Разовая корректировка данных. +Процедура ИсполняемыеСценарии() Экспорт + + Если НЕ РазовыйОперационныйПрогонРазрешён() Тогда + Возврат; + КонецЕсли; + + ЮТТесты + .ДобавитьТестовыйНабор("[ONE_OFF_OPERATION] Корректировка данных") + .Тег("one-off-operation") + .ДобавитьСерверныйТест("ВыполнитьКорректировку"); + +КонецПроцедуры +``` + +--- + ## Структура тестового модуля Обязательно: экспортная процедура `ИсполняемыеСценарии`. Только регистрация тестов — никаких данных, никакой логики. @@ -84,6 +125,28 @@ description: "Use for написания тестовых модулей YaxUnit --- +## Обязательность YaxUnit для серверных изменений + +Любое изменение серверной логики или серверного контекста ОБЯЗАНО иметь YaxUnit-проверку на том же +runtime-слое. Это относится к общим модулям, модулям менеджеров/объектов, серверным методам форм, +запросам, записи регистров/документов, фоновым и регламентным обработчикам, если проверяемый эффект +доступен из серверного теста. + +Правило выбора: + +| Ситуация | Действие | +|----------|----------| +| Изменён существующий серверный метод, и тест уже есть | Актуализировать тест под новое поведение и перепрогнать его. | +| Изменён существующий серверный метод, теста нет | Добавить минимальный YaxUnit-тест на изменённый контракт. | +| Добавлен новый серверный метод/API | Добавить YaxUnit-тест вместе с методом. | +| Изменение серверной логики проявляется только через процесс | Написать серверный integration-тест на наблюдаемый эффект процесса или явно зафиксировать, почему нужен более высокий сценарный уровень. | + +Синтаксис, LSP и успешная сборка НЕ заменяют YaxUnit для серверной логики: они подтверждают, что код +может быть загружен, но не подтверждают контракт метода. Если тест технически невозможен, это +фиксируется как blocker/остаточный риск с причиной; молчаливый пропуск запрещён. + +--- + ## Реализация теста Один тест проверяет одно утверждение. Паттерн Arrange-Act-Assert: diff --git a/framework/skills/framework-meta/skill-editing-from-project/SKILL.md b/framework/skills/framework-meta/skill-editing-from-project/SKILL.md index 3d68be00..abe968ba 100644 --- a/framework/skills/framework-meta/skill-editing-from-project/SKILL.md +++ b/framework/skills/framework-meta/skill-editing-from-project/SKILL.md @@ -1,7 +1,7 @@ --- name: skill-editing-from-project installable: true -description: Use for редактирования навыков фреймворка, находясь в каталоге проекта 1С (не в репозитории фреймворка). Helps найти RU-источник через симлинки и .install-session.json без переключения репозитория. +description: "Правка framework skills из проекта через install-session" --- # Редактирование навыков фреймворка из проекта diff --git a/framework/skills/other/find-skills/SKILL.md b/framework/skills/other/find-skills/SKILL.md index 316f7c3f..faad2f67 100644 --- a/framework/skills/other/find-skills/SKILL.md +++ b/framework/skills/other/find-skills/SKILL.md @@ -1,6 +1,6 @@ --- name: find-skills -description: "Use for поиска и установки навыков агента когда пользователь спрашивает «есть ли навык для X» или хочет расширить возможности. Helps найти подходящий skill через npx skills find и установить его." +description: "Когда нужен поиск или установка агентского навыка" capabilities: skills-management --- diff --git a/framework/skills/spec-writing/spec-standard/SKILL.md b/framework/skills/spec-writing/spec-standard/SKILL.md index aa478ff9..23d56c3e 100644 --- a/framework/skills/spec-writing/spec-standard/SKILL.md +++ b/framework/skills/spec-writing/spec-standard/SKILL.md @@ -1,6 +1,6 @@ --- name: spec-standard -description: "Use for написания спецификации задачи (SDD). Defines структуру документа, RFC 2119 уровни требований и quality checklist для Phase 1 full-cycle." +description: "Для SDD-спецификаций с RFC 2119 и чеклистом" --- # Навык написания спецификаций (SDD) @@ -108,6 +108,26 @@ BDD поверх полного unit-покрытия одного и того --- +## 4b. Покрытие по затронутому runtime-слою (MUST) + +План тестирования ОБЯЗАН выбирать уровень теста по тому runtime-слою, который меняется. Нельзя +закрывать клиентское изменение только синтаксисом/юнитом, а серверное изменение — только кликом в UI. + +| Что затронуто | Обязательное покрытие | +|---------------|------------------------| +| Серверная логика, общий модуль, модуль менеджера/объекта, серверный метод формы, запрос, запись регистров/документов | YaxUnit unit/integration. Если тест уже есть — актуализировать и перепрогнать; если теста нет — добавить. | +| UI или клиентский контекст: форма, команда, кнопка, командный интерфейс, клиентский обработчик, `ОткрытьФорму`, оповещение, видимость/доступность, права на открытие UI | Сценарный тест через Vanessa/TestClient: открыть пользовательский entrypoint, выполнить действие и проверить наблюдаемый результат без ошибки. Для UI/UX-приёмки формы планировать PNG-скриншот через VA MCP (`connect_test_client -> get_window_list_os -> get_window_screenshot_os`) с проверкой, что снимок не пустой/чёрный. Web-клиент планировать только для browser-specific слоя (DOM/CSS/JS console/network/web-auth/viewport/browser extension), явно указав, какой функции принципиально нет в VA MCP. Для точечной команды минимальный сценарий кликает команду и подтверждает успешный запуск/завершение. | +| Связанный пользовательский процесс, проходящий через несколько форм/объектов | End-to-end сценарий процесса. Сначала переиспользовать существующий сценарий и актуализировать его под изменение; новый сценарий писать только если существующего покрытия нет. | +| Интеграционная граница, HTTP/API, фоновое или регламентное выполнение | Integration/YaxUnit или сценарный тест с проверяемым внешним/регистровым эффектом; для фоновых заданий — проверка идемпотентности и повторного запуска, если это относится к изменению. | + +Каждый MUST в спеке должен иметь в «Плане тестирования» явную строку трассировки: +`требование → затронутый слой → тип теста → существующий тест актуализируется или создаётся новый`. + +Если обязательный UI/VA-тест технически невозможен в текущем окружении, спека НЕ должна молча снижать +покрытие: применить fallback-правила `va-visual-check` и зафиксировать выполненные VA-шаги, причину fallback и остаточный риск. Если fallback не даёт достаточного сигнала для требования — зафиксировать blocker. Reviewer проверяет не только наличие тестов, но и соответствие уровня теста затронутому runtime-слою. + +--- + ## 5. Правила RFC 2119 | Ключевое слово | Значение | Правило использования | @@ -138,6 +158,8 @@ BDD поверх полного unit-покрытия одного и того - [ ] «Контекст» описывает кто имеет проблему и что не работает. - [ ] Каждый MUST покрыт пунктом в «Плане тестирования». +- [ ] Для каждого MUST указан затронутый runtime-слой и выбран соответствующий тип теста: + server → YaxUnit, UI/client → сценарный UI/BDD, процесс → end-to-end, integration/background → integration/job. - [ ] «Границы» явно разделяют «Входит в scope» и «Не входит в scope». - [ ] «Рассмотренные варианты» содержит минимум 2 альтернативы. - [ ] «Выбранное решение» содержит обоснование и последствия. @@ -146,6 +168,8 @@ BDD поверх полного unit-покрытия одного и того - [ ] Требования сформулированы через RFC 2119 (MUST/SHOULD/MAY/MUST NOT). - [ ] Есть ссылка/выжимка по отдельному Task Breakdown JSON. - [ ] «Приёмочные сценарии» содержат Gherkin-сценарии бизнес-уровня (Дано/Когда/Тогда) для MUST-требований. +- [ ] Если изменение затрагивает UI/client context, есть сценарий, который открывает пользовательский entrypoint и выполняет изменённое действие. +- [ ] Если изменение затрагивает серверный метод/логику, есть YaxUnit-покрытие: актуализирован существующий тест или создан новый. - [ ] Документ написан на русском языке (кроме идентификаторов кода). --- diff --git a/framework/skills/spec-writing/task-breakdown/SKILL.md b/framework/skills/spec-writing/task-breakdown/SKILL.md index 2ce46cf5..0e59b38b 100644 --- a/framework/skills/spec-writing/task-breakdown/SKILL.md +++ b/framework/skills/spec-writing/task-breakdown/SKILL.md @@ -1,6 +1,6 @@ --- name: task-breakdown -description: "Use for декомпозиции спецификации в Task Breakdown JSON. Covers два режима: linear (self-check, single-agent) и subagent (cross-review + BLOCK-итерации)." +description: "Для декомпозиции спецификации в Task Breakdown JSON" depends_on: - framework/skills/spec-writing/spec-standard/SKILL.md metadata: diff --git a/framework/skills/spec-writing/technical-design-standard/SKILL.md b/framework/skills/spec-writing/technical-design-standard/SKILL.md index 6543b066..dc5af788 100644 --- a/framework/skills/spec-writing/technical-design-standard/SKILL.md +++ b/framework/skills/spec-writing/technical-design-standard/SKILL.md @@ -1,6 +1,6 @@ --- name: technical-design-standard -description: "Use for написания технического дизайна (Phase 2). Defines структуру technical-design.md, правила заполнения секций (MUST/SHOULD/MAY) и чеклист качества для архитектора и ревьюера (scope=arch)." +description: "Для technical-design.md 1C с MUST/SHOULD/MAY" --- # Стандарт технического дизайна (Technical Design) diff --git a/framework/skills/tool-usage/README.md b/framework/skills/tool-usage/README.md index b6728180..dd6fc06c 100644 --- a/framework/skills/tool-usage/README.md +++ b/framework/skills/tool-usage/README.md @@ -44,7 +44,7 @@ │ контекст │ │ │ │ │ │ │ │ проверка │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ (вне агента) spec-writing bsl-practices bsl-practices test-execution - platform-data-core code-navigation tool-usage/core visual-check + platform-data-core code-navigation tool-usage/core va-visual-check search-before-w. review-* xml-gen syntax-checking code-navigation event-log-analysis review-* event-log-analysis tech-log-analysis spec-writing tech-log-analysis @@ -184,7 +184,7 @@ | tool-usage | `search-before-write` | Поиск перед написанием кода | `navigate_symbol`, `list_metadata_objects`, `get_metadata_structure`, `search_syntax_reference`, `get_type_info`, `search_ssl_functions`, `ask_ai_assistant` | | tool-usage | `syntax-checking` | Проверка синтаксиса BSL | `check_syntax`, `get_diagnostics` | | tool-usage | `test-execution` | TDD: сборка, запуск тестов, анализ | `run_tests`, `build_project`, `navigate_symbol`, `check_syntax` | -| tool-usage | `visual-check` | Визуальная проверка форм в браузере | `browser_navigate`, `browser_snapshot`, `browser_fill`, `browser_click`, `browser_take_screenshot`, `browser_console_messages`, `browser_wait_for` | +| tool-usage | `va-visual-check` | Визуальная проверка форм 1С через Vanessa/VA MCP; browser fallback по правилам навыка | VA MCP, `web-test-1c`/Playwright как fallback | | **tool-usage / xml-gen** | | | | | tool-usage | `xml-generation` | Обзор генерации XML-метаданных + CLI (validate, edit, replace-text) | — (CLI) | | tool-usage | `epf-full` | Создание EPF/ERF, макеты объектов, BSP-регистрация | — (CLI) | @@ -212,7 +212,7 @@ | framework-meta | `agent-development` | Разработка субагентов | — | | framework-meta | `agent-development-ext` | Разработка субагентов (1С) | — | -**Пример рабочего сценария:** Программист реализует справочник «ПромоКоды» с формой. Агент: (1) через `search-before-write` ищет аналоги в конфигурации, (2) через `epf-full` / `form-dsl` генерирует XML-метаданные справочника и формы, (3) пишет BSL-код модуля по `coding-standards`, (4) через `syntax-checking` проверяет синтаксис, (5) через `test-execution` запускает YaxUnit-тесты, (6) через `visual-check` проверяет отображение формы в браузере, (7) через `cross-provider-review` получает второе мнение от opposite-family модели. +**Пример рабочего сценария:** Программист реализует справочник «ПромоКоды» с формой. Агент: (1) через `search-before-write` ищет аналоги в конфигурации, (2) через `epf-full` / `form-dsl` генерирует XML-метаданные справочника и формы, (3) пишет BSL-код модуля по `coding-standards`, (4) через `syntax-checking` проверяет синтаксис, (5) через `test-execution` запускает YaxUnit-тесты, (6) через `va-visual-check` проверяет отображение формы, (7) через `cross-provider-review` получает второе мнение от opposite-family модели. **Незакрытые зоны:** - Работа с жизненным циклом ТЖ — покрыто навыком `tech-log-analysis` @@ -235,7 +235,7 @@ | Категория | Навык | Назначение | MCP Tools | |-----------|-------|------------|-----------| | tool-usage | `test-execution` | Сборка проекта и запуск YaxUnit-тестов | `run_tests`, `build_project`, `navigate_symbol`, `check_syntax` | -| tool-usage | `visual-check` | Визуальная проверка форм через браузер | `browser_navigate`, `browser_snapshot`, `browser_fill`, `browser_click`, `browser_take_screenshot`, `browser_console_messages`, `browser_wait_for` | +| tool-usage | `va-visual-check` | Визуальная проверка форм через Vanessa/VA MCP; browser fallback по правилам навыка | VA MCP, `web-test-1c`/Playwright как fallback | | tool-usage | `syntax-checking` | Проверка синтаксиса BSL | `check_syntax`, `get_diagnostics` | | tool-usage | `event-log-analysis` | Анализ ЖР на ошибки | `search_event_log`, `navigate_symbol` | | tool-usage | `tech-log-analysis` | Анализ ТЖ на блокировки и исключения | `search_tech_log`, `navigate_symbol` | @@ -244,7 +244,7 @@ | tool-usage | `cross-provider-review` | Cross-family ревью кода (Claude↔Codex) | CLI-адаптеры | | tool-usage | `gemini-review` | Ревью кода через Gemini | — (внешний CLI) | -**Пример рабочего сценария:** QA проверяет реализацию промокодов. Агент: (1) через `test-execution` запускает YaxUnit-тесты модуля, (2) через `visual-check` открывает форму справочника в браузере и проверяет элементы по чеклисту `form-visual-requirements`, (3) через `event-log-analysis` ищет ошибки в ЖР, через `tech-log-analysis` — блокировки и исключения в ТЖ, (4) через `cross-provider-review` инициирует финальное ревью. +**Пример рабочего сценария:** QA проверяет реализацию промокодов. Агент: (1) через `test-execution` запускает YaxUnit-тесты модуля, (2) через `va-visual-check` открывает форму и проверяет элементы по чеклисту `form-visual-requirements`, (3) через `event-log-analysis` ищет ошибки в ЖР, через `tech-log-analysis` — блокировки и исключения в ТЖ, (4) через `cross-provider-review` инициирует финальное ревью. **Незакрытые зоны:** - Визуальная регрессия (сравнение скриншотов) — нет инструмента @@ -266,7 +266,7 @@ | 7 | `search-before-write` | tool-usage | | ● | ● | ● | | | 8 | `syntax-checking` | tool-usage | | | ● | ● | ● | | 9 | `test-execution` | tool-usage | | | | ● | ● | -| 10 | `visual-check` | tool-usage | | | | ● | ● | +| 10 | `va-visual-check` | tool-usage | | | | ● | ● | | 11 | `xml-generation` | tool-usage | | | | ● | | | 12 | `epf-full` | tool-usage | | | | ● | | | 14 | `form-dsl` | tool-usage | | | | ● | | @@ -310,7 +310,7 @@ | MCP-инструмент | Провайдер | Описание | Затронутые роли | Статус | |----------------|-----------|----------|-----------------|--------| | **Не требуют навыка** | | | | | -| `launch_app` | mcp-onec-test-runner | Запуск клиентов 1С | — | ⚪ YaxUnit запускает клиент автоматически через `run_tests`; интерактивная работа с толстым/тонким клиентом агенту недоступна; веб-клиент покрыт `visual-check` | +| `launch_app` | mcp-onec-test-runner | Запуск клиентов 1С | — | ⚪ YaxUnit запускает клиент автоматически через `run_tests`; интерактивная работа с толстым/тонким клиентом идёт через Vanessa/TestClient и профильные навыки | | `explain_1c_syntax` | spring-mcp-1c-copilot | Объяснение конструкций BSL | — | ⚪ Современный агент справляется без инструмента | | `check_1c_code` | spring-mcp-1c-copilot | AI-проверка кода через copilot (старая модель) | — | ⚪ Слабее `cross-provider-review`; ревью закрыто review-навыками | | `range` | mcp-bsl-lsp-bridge | Анализ диапазона кода | Программист | 🟡 Инструмент доступен; навык не нужен — низкоуровневой LSP-операции достаточно | @@ -352,13 +352,13 @@ | `logc_disable_techlog` | 1c-log-checker | Отключение ТЖ | Программист, QA | 🟢 `tech-log-analysis` | | `logc_get_techlog_config` | 1c-log-checker | Чтение конфигурации ТЖ | Программист, QA | 🟢 `tech-log-analysis` | | `logc_get_actual_log_timestamp` | 1c-log-checker | Актуальная метка времени журнала | Программист, QA | 🟢 `tech-log-analysis` | -| `browser_navigate` | chrome-devtools | Навигация в браузере (= `navigate_page`) | Программист, QA | 🟢 `visual-check` | -| `browser_snapshot` | chrome-devtools | Снимок страницы (= `take_snapshot`) | Программист, QA | 🟢 `visual-check` | -| `browser_fill` | chrome-devtools | Заполнение полей (= `fill`) | Программист, QA | 🟢 `visual-check` | -| `browser_click` | chrome-devtools | Клик по элементу (= `click`) | Программист, QA | 🟢 `visual-check` | -| `browser_take_screenshot` | chrome-devtools | Скриншот (= `take_screenshot`) | Программист, QA | 🟢 `visual-check` | -| `browser_console_messages` | chrome-devtools | Сообщения консоли (= `list_console_messages`) | Программист, QA | 🟢 `visual-check` | -| `browser_wait_for` | chrome-devtools | Ожидание элемента (= `wait_for`) | Программист, QA | 🟢 `visual-check` | +| `browser_navigate` | chrome-devtools | Навигация в браузере (= `navigate_page`) | Программист, QA | 🟢 `web-test-1c` / `playwright`; для 1C UI только browser-layer или fallback по `va-visual-check` | +| `browser_snapshot` | chrome-devtools | Снимок страницы (= `take_snapshot`) | Программист, QA | 🟢 `web-test-1c` / `playwright`; для 1C UI только browser-layer или fallback по `va-visual-check` | +| `browser_fill` | chrome-devtools | Заполнение полей (= `fill`) | Программист, QA | 🟢 `web-test-1c` / `playwright`; для 1C UI только browser-layer или fallback по `va-visual-check` | +| `browser_click` | chrome-devtools | Клик по элементу (= `click`) | Программист, QA | 🟢 `web-test-1c` / `playwright`; для 1C UI только browser-layer или fallback по `va-visual-check` | +| `browser_take_screenshot` | chrome-devtools | Скриншот (= `take_screenshot`) | Программист, QA | 🟢 `web-test-1c` / `playwright`; для 1C UI только browser-layer или fallback по `va-visual-check` | +| `browser_console_messages` | chrome-devtools | Сообщения консоли (= `list_console_messages`) | Программист, QA | 🟢 `web-test-1c` / `playwright`; для 1C UI только browser-layer или fallback по `va-visual-check` | +| `browser_wait_for` | chrome-devtools | Ожидание элемента (= `wait_for`) | Программист, QA | 🟢 `web-test-1c` / `playwright`; для 1C UI только browser-layer или fallback по `va-visual-check` | > **Альтернативные MCP-провайдеры.** Помимо основных серверов, зарегистрированных в `registry.yaml`, существуют альтернативные провайдеры: **1c-batch** (сборка/выгрузка конфигурации — альтернатива `test-runner` для `build_project`/`dump_config`), **1c-mcp-tools** (метаданные/запросы — альтернатива `1c-mcp`), **1c_mcp** (прозрачный прокси с динамическими инструментами на стороне 1С — потенциальный путь для закрытия пробелов без создания новых MCP-серверов). Фреймворк выбрал конкретные провайдеры; альтернативы подключаются через `registry.yaml` при необходимости. @@ -371,7 +371,7 @@ | Интеграция с трекерами | Нет MCP-сервера для Jira/YouTrack — ФА забирает задачу вручную | ФА | 🟢 Низкий приоритет, удобство а не необходимость | | Моделирование процессов | Нет генератора BPMN/EPC-диаграмм | БА | 🔴 Нет инструмента | | Визуализация архитектуры | Нет генератора C4/компонентных/ER-диаграмм | ФА, СА | 🔴 Нет инструмента | -| Визуальная регрессия | Нет сравнения скриншотов (pixel diff) | QA | 🟡 Можно реализовать поверх `visual-check` | +| Визуальная регрессия | Нет сравнения скриншотов (pixel diff) | QA | 🟡 Можно реализовать поверх `va-visual-check` | | Нагрузочное тестирование | Нет профилировщика и генератора нагрузки | СА, QA | 🔴 Нет инструмента | | E2E-тестирование | Нет оркестратора сквозных сценариев | QA | 🔴 Нет инструмента | @@ -381,9 +381,9 @@ | # | Имя навыка | Категория | Приоритет | Описание | MCP Tools | |---|------------|-----------|-----------|----------|-----------| -| 1 | `visual-regression` | tool-usage | 🟢 Низкий | Сравнение скриншотов форм (pixel diff) для регрессионного тестирования UI | `browser_take_screenshot` + внешний diff | +| 1 | `visual-regression` | tool-usage | 🟢 Низкий | Сравнение скриншотов форм (pixel diff) для регрессионного тестирования UI | VA/browser screenshot + внешний diff | -**Рекомендуемый порядок реализации:** `visual-regression` — зависит от `visual-check`, требует внешнего инструмента сравнения скриншотов. +**Рекомендуемый порядок реализации:** `visual-regression` — зависит от `va-visual-check`, требует внешнего инструмента сравнения скриншотов. --- @@ -417,8 +417,9 @@ framework/skills/tool-usage/ ├── test-execution/ │ └── SKILL.md # TDD: сборка + тесты YaxUnit │ -├── visual-check/ -│ └── SKILL.md # Визуальная проверка форм в браузере +├── vanessa/ +│ └── va-visual-check/ +│ └── SKILL.md # Визуальная проверка форм 1С через VA MCP │ ├── xml-generation/ │ ├── xml-generation/ diff --git a/framework/skills/tool-usage/browser-ui/gui-control/SKILL.md b/framework/skills/tool-usage/browser-ui/gui-control/SKILL.md index 4b115a3e..1067caf5 100644 --- a/framework/skills/tool-usage/browser-ui/gui-control/SKILL.md +++ b/framework/skills/tool-usage/browser-ui/gui-control/SKILL.md @@ -1,21 +1,23 @@ --- name: gui-control -description: "MUST use WHEN GUI-диалог блокирует завершение базы или тест завис без событий в ЖР. Provides X11-детектирование окон 1С, скриншот и симуляцию клавиш для разблокировки без участия человека." +description: "Разблокировка зависших окон 1С, диалогов и тестов" --- # Управление GUI 1С через X11 X11-управление — action, не диагностика. Использовать только когда детектирован GUI-диалог, блокирующий нормальное завершение базы. Диагностику причин — через ЖР (`event-log-analysis`). -Для `Предупреждение безопасности` метаданные X11-окон могут быть неполными. Ориентируйся на связку: ЖР → скриншот → действия с клавиатурой. +Для UI/UX-приёмки обычных 1C-форм не используй `gui-control` как основной маршрут. Сначала применяй `va-visual-check`; X11-клавиши и прямое GUI-управление допустимы как fallback/action только с фиксацией причины и остаточного риска. + +Для `Предупреждение безопасности` метаданные X11-окон могут быть неполными. Ориентируйся на связку: ЖР → визуальный артефакт по `va-visual-check` → действие с клавиатурой при необходимости. ## Когда применять | Триггер | Действие | |---------|----------| | В ЖР нет событий после `test_start_time` | Проверить — не завис ли GUI-диалог | -| Заголовок окна: «Ошибка» / «Предупреждение» | Скриншот → закрыть диалог → анализ ЖР | -| База не завершается после тестов | Закрыть через Escape + Enter | +| Заголовок окна: «Ошибка» / «Предупреждение» | VA MCP-скриншот → закрыть диалог только если VA MCP принципиально не умеет нужное действие → анализ ЖР | +| База не завершается после тестов | Закрыть через Escape + Enter только если VA MCP принципиально не умеет закрыть блокирующее окно | | В ЖР `Предупреждение безопасности` на EPF | Визуальная проверка, не действовать вслепую по заголовкам | ## Настройка окружения @@ -54,7 +56,7 @@ print(error_windows) ### 2. Закрыть диалог и завершить базу -Последовательность: Enter (закрыть диалог) → Escape (закрытие) → Enter (подтвердить). После — ждать 2–3 сек и проверить через шаг 1. +Сначала проверь, есть ли в VA MCP инструмент для закрытия/подтверждения нужного окна. Если используешь X11-клавиши как fallback/action, зафиксируй причину. Последовательность: Enter (закрыть диалог) → Escape (закрытие) → Enter (подтвердить). После — ждать 2–3 сек и проверить через шаг 1. ```python import os, time @@ -81,26 +83,12 @@ time.sleep(1) send_key(d, ENTER) ``` -### 3. Скриншот для лога (опционально, перед шагом 2) - -```python -import os -os.environ['DISPLAY'] = ':99' -from PIL import ImageGrab -from Xlib import display +### 3. Скриншот для лога (обязательно через VA MCP, перед шагом 2) -d = display.Display() -root = d.screen().root +Скриншот для 1C UI получай по `va-visual-check`: VA MCP PNG, Linux/Xvfb рецепт и fallback-правила. -for win in root.query_tree().children: - name = win.get_wm_name() - wm_class = win.get_wm_class() - if wm_class and '1cv8' in wm_class: - geom = win.get_geometry() - img = ImageGrab.grab(bbox=(geom.x, geom.y, geom.x + geom.width, geom.y + geom.height)) - path = f'/tmp/onec_{win.id}.png' - img.save(path) - print(f'Скриншот сохранён: {path}') +```json +{"name":"get_window_screenshot_os","arguments":{"window_title":"","file_name":".png","color_mode":"color"}} ``` ## Пайплайн: тесты завершились, база не закрылась @@ -108,9 +96,9 @@ for win in root.query_tree().children: ``` search_event_log(from=test_start_time, limit=20) ├── есть события, нет Error → ждать - ├── есть Error → скриншот → закрыть → анализ ЖР + ├── есть Error → VA MCP-скриншот → закрыть при отсутствующей VA capability → анализ ЖР └── нет событий → детектировать окна - ├── окно с ошибкой → скриншот → закрыть + ├── окно с ошибкой → VA MCP-скриншот → закрыть при отсутствующей VA capability └── нет окон → база не запустилась ``` @@ -118,7 +106,7 @@ search_event_log(from=test_start_time, limit=20) - **Только Xvfb** — не применять на продуктивных серверах с реальным дисплеем - **Только навигационные клавиши** (Enter/Escape) — не вводить данные в поля -- **Скриншоты — в /tmp/** — могут содержать персональные данные +- **VA MCP-скриншоты — в /tmp/** — могут содержать персональные данные ## Типичные ошибки @@ -126,8 +114,8 @@ search_event_log(from=test_start_time, limit=20) |--------|---------------| | `DISPLAY` не установлен | `os.environ['DISPLAY'] = ':99'` до импортов | | `python-xlib` не установлен | `pip install python-xlib` | -| `PIL.ImageGrab` не работает | `pip install Pillow` | | Окна не найдены, но процесс есть | GUI ещё не отрисован — ждать 2–3 сек | +| VA MCP-скриншот Xvfb чёрный/одноцветный | Действовать по `va-visual-check`: Linux/Xvfb-рецепт, повтор VA-снимка, затем fallback при необходимости | | XTEST недоступна | Xvfb с флагом `-extensions XTEST` | ## Capabilities @@ -135,7 +123,7 @@ search_event_log(from=test_start_time, limit=20) | Capability | Назначение | |------------|------------| | `python-xlib` | Чтение метаданных окон, симуляция ввода | -| `PIL ImageGrab` | Скриншот фреймбуфера или окна | +| `get_window_screenshot_os` | VA MCP-скриншот окна тест-клиента | --- depends_on: [] diff --git a/framework/skills/tool-usage/browser-ui/img-grid/SKILL.md b/framework/skills/tool-usage/browser-ui/img-grid/SKILL.md index 81e431b5..dc011052 100644 --- a/framework/skills/tool-usage/browser-ui/img-grid/SKILL.md +++ b/framework/skills/tool-usage/browser-ui/img-grid/SKILL.md @@ -1,6 +1,6 @@ --- name: "img-grid" -description: "Use for измерения пропорций и span-ов колонок на скриншоте печатной формы (MXL). Helps точно определить границы ячеек перед генерацией макета табличного документа." +description: "Замер сетки и колонок по скриншоту печатной формы MXL" argument-hint: " [--cell-size 50] [--cols N] [-o OUTPUT]" allowed-tools: - Bash diff --git a/framework/skills/tool-usage/browser-ui/playwright-interactive/SKILL.md b/framework/skills/tool-usage/browser-ui/playwright-interactive/SKILL.md index c67881f8..23081363 100644 --- a/framework/skills/tool-usage/browser-ui/playwright-interactive/SKILL.md +++ b/framework/skills/tool-usage/browser-ui/playwright-interactive/SKILL.md @@ -1,12 +1,16 @@ --- name: "playwright-interactive" -description: "Use for итеративной отладки UI веб-приложений и Electron через персистентную `js_repl`-сессию Playwright. Helps сохранять браузерные хендлы живыми между шагами без перезапуска." +description: "Интерактивная Playwright-отладка в постоянной сессии" --- # Playwright Interactive Skill Persistent `js_repl` Playwright session for iterative UI debugging of web and Electron apps. Keep the same handles alive across iterations. +## 1C Boundary + +For 1C:Enterprise UI, interactive Playwright is not the preferred path for ordinary forms. First use `va-visual-check`: Vanessa Automation/TestClient and VA MCP for opening forms, clicking commands, filling fields, checking table rows, validating client-side behavior, and taking UI/UX screenshots. Use interactive Playwright for 1C only when the target is browser-specific or as fallback under `va-visual-check`: DOM/CSS/HTML, browser console/network, cookies/storage, web publication/auth, web-client viewport/pixel rendering, Chrome/Edge-only behavior, browser extension behavior, or browser-only file/clipboard flows. If used for 1C, record the VA steps already attempted, why browser evidence is sufficient, and the residual risk. + ## Preconditions - `js_repl` must be enabled (`~/.codex/config.toml`: `[features] js_repl = true`, or `--enable js_repl`). diff --git a/framework/skills/tool-usage/browser-ui/playwright/SKILL.md b/framework/skills/tool-usage/browser-ui/playwright/SKILL.md index b84e93b4..965f36a5 100644 --- a/framework/skills/tool-usage/browser-ui/playwright/SKILL.md +++ b/framework/skills/tool-usage/browser-ui/playwright/SKILL.md @@ -1,12 +1,16 @@ --- name: "playwright" -description: "Use for автоматизации браузера из терминала (навигация, заполнение форм, снимки, скриншоты, извлечение данных, отладка UI-потоков) через `playwright-cli`. Helps запустить сценарий без интерактивного IDE." +description: "Browser UI automation: сценарии, формы, скриншоты" --- # Playwright CLI Skill CLI-first browser automation. Do not pivot to `@playwright/test` unless explicitly asked. +## 1C Boundary + +For 1C:Enterprise UI, Playwright is not the preferred test or screenshot path for ordinary forms. First use the `va-visual-check` policy for Vanessa Automation/TestClient and VA MCP. Use Playwright/browser screenshots for 1C only as browser-layer work or as fallback under `va-visual-check`, recording the VA steps already attempted, why browser evidence is sufficient, and the residual risk. + ## Prerequisite check ```bash diff --git a/framework/skills/tool-usage/browser-ui/screenshot/SKILL.md b/framework/skills/tool-usage/browser-ui/screenshot/SKILL.md index 11b2d8ac..36949773 100644 --- a/framework/skills/tool-usage/browser-ui/screenshot/SKILL.md +++ b/framework/skills/tool-usage/browser-ui/screenshot/SKILL.md @@ -1,16 +1,18 @@ --- name: "screenshot" -description: "Use for захвата скриншота рабочего стола или окна на уровне ОС (полный экран, конкретное приложение/окно, пиксельная область). Helps получить снимок когда инструментно-специфичный захват (Playwright, Figma MCP) недоступен." +description: "OS-скриншоты рабочего стола, окна или области экрана" --- -# Screenshot Capture +# Снятие скриншотов -Save-location rules: -1. User specifies path → save there. -2. User asks without path → OS default location. -3. Codex self-inspection → temp directory. +Правила сохранения: +1. Пользователь указал путь → сохранить туда. +2. Пользователь попросил без пути → использовать стандартное расположение ОС. +3. Самопроверка Codex → временный каталог. -Prefer tool-specific captures (Figma MCP, Playwright, agent-browser) when available. Use this skill for explicit requests, whole-system desktop captures, or when tool-specific capture cannot get what you need. +Предпочитай специализированные инструменты снятия изображения (Figma MCP, Playwright, agent-browser, VA MCP), когда у целевого домена есть такой инструмент. Этот навык используй для явных запросов на снимок рабочего стола/окна, снимков всего экрана или доменов, где специализированного инструмента нет. + +Для UI/форм 1С:Предприятия сначала применяй профильный навык `va-visual-check`. Этот OS-screenshot навык можно использовать для 1С только как fallback по правилам `va-visual-check`, с фиксацией выполненных VA-шагов, причины fallback и остаточного риска. ## macOS permission preflight @@ -53,6 +55,8 @@ Display dimensions: `DISPLAY=:99 xdpyinfo | grep dimensions` `--app`, `--window-name`, `--list-windows` are macOS-only. On Linux use `--active-window` or `--window-id`. +Для 1C-скриншотов в Xvfb см. `va-visual-check`: там описаны VA-маршрут, экспонирование окна перед VA-снимком и fallback-условия. + ## PowerShell helper (Windows) ```powershell @@ -68,7 +72,7 @@ powershell -ExecutionPolicy Bypass -File /scripts/take_screenshot | `-ActiveWindow` | Ask user to focus first | | `-WindowHandle ` | Specific window | -## Direct OS fallbacks +## Прямые OS-снимки ### macOS @@ -93,4 +97,5 @@ ffmpeg -y -f x11grab -video_size 800x600 -i :99+100,200 -frames:v 1 output/regio - macOS sandbox errors ("screen capture blocked", `ModuleCache`) → rerun with escalated permissions - macOS no matches → `--list-windows --app "Name"` → retry with `--window-id` - Linux tool missing → `command -v scrot`, `command -v import` +- 1C VA PNG чёрный/одноцветный → действуй по `va-visual-check` - Always report saved file path diff --git a/framework/skills/tool-usage/browser-ui/visual-check/SKILL.md b/framework/skills/tool-usage/browser-ui/visual-check/SKILL.md index 5ec054cd..da4f24cd 100644 --- a/framework/skills/tool-usage/browser-ui/visual-check/SKILL.md +++ b/framework/skills/tool-usage/browser-ui/visual-check/SKILL.md @@ -1,76 +1,21 @@ --- name: visual-check -description: "UI-приёмка формы 1С: скриншот, консоль, чеклист" +description: "Deprecated: визуальная проверка форм 1С перенесена в va-visual-check" alwaysApply: false --- -# Визуальная проверка форм (Visual Check) +# Deprecated: visual-check -По умолчанию визуальная проверка управляемых форм 1С выполняется через Vanessa/TestClient или платформенный тест-клиент MCP: открыть форму, выполнить пользовательское действие, получить структурные данные формы (`get_form_analysis`, `get_window_list_testclient`, `get_value`, `get_table_rows`) и сверить с `form-visual-requirements`. +Этот навык оставлен как совместимый указатель для старых ссылок. Для визуальной проверки 1С-форм используй профильный навык `va-visual-check`: -Для любой работы с клиентской формой, где важны компоновка, видимость, доступность или пользовательское восприятие, визуальный скриншот обязателен. Путь получения скриншота выбирается так: +- основной маршрут Vanessa/TestClient + VA MCP; +- Linux headless X11/Xvfb рецепт для чёрных VA-скриншотов; +- browser fallback и правила фиксации остаточного риска. -1. Если в текущем VA MCP окружении короткая smoke-проверка `connect_test_client` -> `get_window_list_os` -> `get_window_screenshot_os` реально прошла, используй VA MCP screenshot. -2. Если VA MCP screenshot не прошёл или падает на `PID=0` / `Не вышло получить PID процесса клиента тестирования`, используй внешний OS/noVNC screenshot видимого окна 1С. -3. Web-клиент используй для screenshot только как browser-specific исключение ниже. - -Веб-клиент использовать только когда проверяется браузерный слой, недоступный TestClient: DOM/CSS/HTML, JS console/network, viewport/responsive, web-публикация и web-auth, cookies/storage, браузерные расширения, browser-only upload/download/clipboard или дефект, воспроизводимый только в Chrome/Edge web-client. - -Требуется для web-исключения: URL веб-клиента 1С (опубликованная база), учётные данные и короткая причина, почему TestClient/VA недостаточны. - -## Процесс проверки - -### 1. Навигация к форме - -Если цель не браузерная, остановись и перейди в TestClient/VA-путь (`vanessa-authoring`, `v8-runner`). Дальнейшие шаги применяются только для web-исключения. - -Предпочитай Deep Linking — быстрее навигации через интерфейс. - -- Список: `/e1cib/list/<ТипМетаданных>.<Имя>` -- Новый объект: `/e1cib/data/<ТипМетаданных>.<Имя>?ref=00000000-0000-0000-0000-000000000000` -- Существующий объект: `/e1cib/data/<ТипМетаданных>.<Имя>?ref=` - -### 2. Авторизация (если перенаправил на вход) - -`browser_snapshot` → `browser_fill` (логин/пароль по ref) → `browser_click` (Войти). - -### 3. Снимок и консоль - -После загрузки (дождаться исчезновения индикатора): -1. `browser_take_screenshot` -2. `browser_console_messages` — искать «Error», «Exception», «Uncaught» - -### 4. Анализ по чеклисту `form-visual-requirements` - -- Расположение и выравнивание (группировка, отступы, ширина) -- Элементы управления и подписи (метки, обрезка, заголовки, командная панель) -- Удобство (порядок обхода, ключевые поля, таблицы, горизонтальная прокрутка) -- Специфика типа объекта (справочники, документы, обработки) - -**Отчёт:** результат анализа скриншота + наличие/отсутствие JS-ошибок. - -## Capabilities - -| Capability | Назначение | -|------------|------------| -| `browser_navigate` | Открытие URL формы | -| `browser_snapshot` | Структура страницы и ref-ы элементов | -| `browser_fill` | Заполнение полей | -| `browser_click` | Клик по элементам | -| `browser_take_screenshot` | Снимок формы | -| `browser_console_messages` | Проверка JS-ошибок | -| `browser_wait_for` | Ожидание загрузки | - -## Типичные ошибки - -| Ошибка | Обходной путь | -|--------|---------------| -| Скриншот пустой | `browser_wait_for` перед скриншотом | -| Deep Link не работает для нового | Список → «Создать» через `browser_click` | -| `browser_fill` не находит поле | `browser_snapshot` для актуальных ref-ов | -| JS-ошибки при нормальной форме | Зафиксировать — проявятся при сохранении | +Оценку качества формы выполняй по `form-visual-requirements`. --- depends_on: + - framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md - framework/skills/bsl-practices/form-visual-requirements/SKILL.md --- diff --git a/framework/skills/tool-usage/browser-ui/web-test-1c/SKILL.md b/framework/skills/tool-usage/browser-ui/web-test-1c/SKILL.md index 18383bc3..a59fe9aa 100644 --- a/framework/skills/tool-usage/browser-ui/web-test-1c/SKILL.md +++ b/framework/skills/tool-usage/browser-ui/web-test-1c/SKILL.md @@ -1,12 +1,26 @@ --- name: web-test-1c -description: "Use for автоматизации действий в 1С через браузер (навигация по разделам, заполнение форм, чтение таблиц и отчётов, фильтрация списков). Helps писать browser-тесты 1С на семантическом слое без знания DOM-деталей платформы." +description: "Browser UI tests for 1C: формы, таблицы, отчёты" --- # web-test-1c — Автоматизация 1С веб-клиента Семантический слой поверх Playwright для DOM 1С:Предприятие веб-клиента. +## Граница применения + +`web-test-1c` НЕ является маршрутом по умолчанию для проверки 1С UI. Если задача — открыть форму/список, нажать команду, заполнить поля, проверить видимость/доступность, реакцию клиентских обработчиков, строки табличной части, пользовательский бизнес-поток или визуально принять форму, сначала применяй профильный навык `va-visual-check`. + +Веб-клиент допустим как browser-layer инструмент или как fallback по правилам `va-visual-check`, когда VA-маршрут уже проверен и причина fallback зафиксирована. Типовые browser-layer случаи: + +- DOM/HTML/CSS: структура разметки, нестандартный виджет, CSS-обрезка/перекрытие, точный браузерный selector. +- Browser diagnostics: console errors, network trace, cookies/localStorage/sessionStorage, web-auth/login/logout, публикация базы на web-сервере. +- Browser rendering: viewport/responsive-поведение веб-клиента, pixel-level screenshot именно браузерного слоя, Chrome/Edge-only дефект, поведение 1C browser extension. +- Browser-only I/O: file chooser/download/clipboard/drag-and-drop, если это зависит от браузера, а не от формы 1С. +- Fallback после VA MCP, когда browser/web-client даёт достаточный сигнал для текущей задачи. + +Если web-клиент выбран, явно зафиксируй причину, выполненные VA-шаги и остаточный риск отличий web-client от тонкого/толстого клиента. + ## Установка ```bash @@ -134,7 +148,7 @@ node $RUN stop # logout + закрытие (освоб **1. Vanessa Automation (рекомендуется)** — если сценарий описан в `.feature`-файле. Vanessa пишет видео прогона и генерирует субтитры из шагов Gherkin из коробки. Настраивается через профиль (`ЗаписыватьВидео`, `ГенерироватьСубтитры`, `ПутьКВидеозаписям`). Использовать для демо-видео команде, документирования бизнес-процессов. -**2. Playwright fallback** — когда Vanessa недоступна, нужен headless или сценарий написан на JS. API: `startRecording` / `stopRecording` / `showCaption` / `addNarration` (TTS через node-edge-tts, OpenAI или ElevenLabs). Требует ffmpeg. +**2. Playwright для browser/fallback записи** — когда сценарий находится в браузерном слое, написан на JS или выбран как fallback по правилам `va-visual-check`. API: `startRecording` / `stopRecording` / `showCaption` / `addNarration` (TTS через node-edge-tts, OpenAI или ElevenLabs). Требует ffmpeg. Подробнее: [recording.md](recording.md) — сравнительная таблица, параметры профиля Vanessa, полный API Playwright-записи, примеры, устранение неполадок. diff --git a/framework/skills/tool-usage/browser-ui/web-test-1c/recording.md b/framework/skills/tool-usage/browser-ui/web-test-1c/recording.md index ffda0a1c..c829c52a 100644 --- a/framework/skills/tool-usage/browser-ui/web-test-1c/recording.md +++ b/framework/skills/tool-usage/browser-ui/web-test-1c/recording.md @@ -1,10 +1,10 @@ # Запись видео + субтитры -## Два пути: Vanessa (приоритет) и Playwright (fallback) +## Два пути: Vanessa и Playwright для browser-only задач | | Vanessa Automation | Playwright (`web-test-1c`) | |---|---|---| -| **Когда использовать** | Сценарий описан в `.feature`-файле; нужно демо-видео для команды с автоматическими субтитрами из шагов Gherkin | Vanessa недоступна; нужен headless-режим или сценарий написан на JS; требуется точный контроль над оверлеями | +| **Когда использовать** | Сценарий описан в `.feature`-файле; нужно демо-видео для команды с автоматическими субтитрами из шагов Gherkin | Сценарий browser-only, нужен JS/DOM-контроль, точный контроль браузерных оверлеев или fallback по правилам `va-visual-check` | | **Формат сценария** | Gherkin / feature-файл | JS / `.test.mjs` или inline `exec` | | **Заголовки/субтитры** | Генерируются из текстов шагов автоматически | Вручную через `showCaption()` + `addNarration()` | | **UI 1С** | Полный стандартный клиент | Браузер, запущенный Playwright | @@ -57,9 +57,9 @@ v8-runner test va --params '{"ЗаписыватьВидео":true,"ПутьКВ --- -## Путь 2: Запись через Playwright (fallback) +## Путь 2: Запись через Playwright для browser-only задач -Используй когда Vanessa недоступна, нужен headless или сценарий написан на JS в `web-test-1c`. +Используй, когда сценарий относится к браузерному слою, написан на JS в `web-test-1c` или выбран как fallback по правилам `va-visual-check`. Для обычного 1C UI-сценария перед Playwright зафиксируй выполненные VA-шаги, причину fallback, почему browser/web-client даёт достаточный сигнал, и остаточный риск отличий клиента. ### Предварительные требования diff --git a/framework/skills/tool-usage/browser-ui/web-test-1c/regress.md b/framework/skills/tool-usage/browser-ui/web-test-1c/regress.md index 85ca6165..bfba4ad6 100644 --- a/framework/skills/tool-usage/browser-ui/web-test-1c/regress.md +++ b/framework/skills/tool-usage/browser-ui/web-test-1c/regress.md @@ -2,6 +2,8 @@ Используй этот документ когда нужно покрыть 1С-решение автоматизированными регрессионными тестами: запускать несколько .feature / JSON-сценариев подряд, агрегировать результаты, получать отчёт fail/pass, настраивать retry на flaky-тесты, сохранять скриншоты на падения. Для разовой автоматизации (один сценарий) оставайся в режимах `run`/`exec` из SKILL.md. +Для 1С UI это не default-регресс. Если тест проверяет форму, команду, поле, ТЧ, клиентский обработчик или бизнес-поток без браузерной специфики — сначала пиши/запускай Vanessa `.feature` через TestClient. Playwright-регресс через `web-test-1c` выбирай для web-client/browser-слоя или как fallback по `va-visual-check`: DOM/CSS/HTML, console/network, web-auth/publication, viewport/pixel rendering, browser extension или browser-only I/O. В тесте или отчёте фиксируй VA-шаги, причину выбора browser/fallback и остаточный риск. + Раннер — тот же `run.mjs`. Режим — `test`: ```bash @@ -16,7 +18,8 @@ node $RUN test [--url=] [флаги] | Цель | Режим | |------|-------| -| Исследовать форму, прototипировать один шаг, отладить селектор | `exec` (интерактивная сессия) | +| Исследовать форму/прототипировать шаг без browser-specific причины | Vanessa/TestClient или платформенный TestClient MCP | +| Отладить DOM/CSS selector или browser-only поведение | `exec` (интерактивная web-сессия) | | Воспроизвести баг как падающий тест перед фиксом | `test` | | Покрыть фичу тестами на будущее | `test` | | Запустить регресс проекта на новой сборке | `test` | diff --git a/framework/skills/tool-usage/code-analysis/buddy-prompting/SKILL.md b/framework/skills/tool-usage/code-analysis/buddy-prompting/SKILL.md index 3ac049d3..f83fb624 100644 --- a/framework/skills/tool-usage/code-analysis/buddy-prompting/SKILL.md +++ b/framework/skills/tool-usage/code-analysis/buddy-prompting/SKILL.md @@ -1,6 +1,6 @@ --- name: buddy-prompting -description: "MUST use WHEN нужно запросить у 1С Напарника (ask_ai_assistant) API платформы, стандарты ИТС, diff версий или валидацию BSL. Provides жёсткие шаблоны (SEARCH_DOCS / SEARCH_ITS / FETCH_ITS / DIFF_VERSIONS / VALIDATE_BSL), совпадающие с внутренними инструкциями Напарника." +description: "Перед вопросом 1C Buddy: API, ИТС, версии, BSL" uses_capabilities: - ask_ai_assistant alwaysApply: false diff --git a/framework/skills/tool-usage/code-analysis/code-navigation/SKILL.md b/framework/skills/tool-usage/code-analysis/code-navigation/SKILL.md index 1659f8b2..1ff6f483 100644 --- a/framework/skills/tool-usage/code-analysis/code-navigation/SKILL.md +++ b/framework/skills/tool-usage/code-analysis/code-navigation/SKILL.md @@ -1,6 +1,6 @@ --- name: code-navigation -description: "Use for навигации по BSL-коду через LSP (поиск определений, ссылок, граф вызовов, переименование). Helps точно находить символы по индексу проекта без угадывания расположения." +description: "LSP-навигация BSL: definitions, refs, call graph" uses_capabilities: - navigate_symbol - get_call_graph diff --git a/framework/skills/tool-usage/code-analysis/code-verification/SKILL.md b/framework/skills/tool-usage/code-analysis/code-verification/SKILL.md index 34a29665..ea27fba0 100644 --- a/framework/skills/tool-usage/code-analysis/code-verification/SKILL.md +++ b/framework/skills/tool-usage/code-analysis/code-verification/SKILL.md @@ -1,6 +1,6 @@ --- name: code-verification -description: "MUST use WHEN BSL-код изменён перед коммитом или передачей на ревью. Provides трёхслойную проверку: LSP-диагностику, VALIDATE_BSL через Напарника и верификацию платформенного API через bsl-platform-context." +description: "После правок BSL: LSP, Buddy/API, syntax checks" uses_capabilities: - get_diagnostics - ask_ai_assistant diff --git a/framework/skills/tool-usage/code-analysis/search-before-write/SKILL.md b/framework/skills/tool-usage/code-analysis/search-before-write/SKILL.md index 4a7f10cb..c306c67f 100644 --- a/framework/skills/tool-usage/code-analysis/search-before-write/SKILL.md +++ b/framework/skills/tool-usage/code-analysis/search-before-write/SKILL.md @@ -1,6 +1,6 @@ --- name: search-before-write -description: "MUST use BEFORE написанием нового BSL-кода или функции. Defines каскад поиска (LSP → метаданные → платформа → БСП) как доказательство того, что готовый аналог отсутствует." +description: "Перед новым BSL-кодом найти существующий аналог" alwaysApply: false --- diff --git a/framework/skills/tool-usage/code-analysis/syntax-checking/SKILL.md b/framework/skills/tool-usage/code-analysis/syntax-checking/SKILL.md index bcf4e845..bae1ff9d 100644 --- a/framework/skills/tool-usage/code-analysis/syntax-checking/SKILL.md +++ b/framework/skills/tool-usage/code-analysis/syntax-checking/SKILL.md @@ -1,6 +1,6 @@ --- name: syntax-checking -description: "MUST use BEFORE коммитом или передачей BSL-кода на ревью. Defines двухуровневый процесс (LSP get_diagnostics → полная проверка Конфигуратором) как доказательство отсутствия синтаксических ошибок." +description: "Перед handoff BSL: LSP и полная проверка синтаксиса" uses_capabilities: - get_diagnostics - get_quality_diagnostics diff --git a/framework/skills/tool-usage/content-generation/codex-image-gen/SKILL.md b/framework/skills/tool-usage/content-generation/codex-image-gen/SKILL.md index f9e79455..9a0e4a21 100644 --- a/framework/skills/tool-usage/content-generation/codex-image-gen/SKILL.md +++ b/framework/skills/tool-usage/content-generation/codex-image-gen/SKILL.md @@ -1,6 +1,6 @@ --- name: codex-image-gen -description: "Use for генерации и редактирования растровых изображений (UI mockup, wireframe, иллюстрация, диаграмма, иконка, тестовая фикстура). Helps делегировать создание картинок Codex/GPT через `codex exec image_generation`, складывая результат в `tasks//assets/`." +description: "Для генерации и редактирования изображений и макетов" capabilities: content-generation,image-generation,cross-provider,delegation --- diff --git a/framework/skills/tool-usage/content-generation/docx-convert/SKILL.md b/framework/skills/tool-usage/content-generation/docx-convert/SKILL.md index eeae9c3b..2fa09e83 100644 --- a/framework/skills/tool-usage/content-generation/docx-convert/SKILL.md +++ b/framework/skills/tool-usage/content-generation/docx-convert/SKILL.md @@ -1,6 +1,6 @@ --- name: docx-convert -description: "Use for конвертации Word-документа (.docx) в Markdown с извлечением изображений (ТЗ, спека, инструкция, документация поставщика). Helps получить GFM-текст через pandoc с постобработкой HTML-таблиц и путей к картинкам." +description: "Для конвертации DOCX в Markdown с изображениями" capabilities: content-generation,document-conversion --- diff --git a/framework/skills/tool-usage/diagnostics/agent-debug/SKILL.md b/framework/skills/tool-usage/diagnostics/agent-debug/SKILL.md index fe9017c2..34cdcbc3 100644 --- a/framework/skills/tool-usage/diagnostics/agent-debug/SKILL.md +++ b/framework/skills/tool-usage/diagnostics/agent-debug/SKILL.md @@ -1,6 +1,6 @@ --- name: agent-debug -description: "MUST use WHEN стандартная диагностика (event-log, скриншоты) не раскрывает фактическое поведение системы — нужно вставить временные точки логирования в код, запустить тест и проанализировать записи ЖР. Provides паттерн debug-блоков с маркерами AGENTDEBUG и чистка после." +description: "Трассировка BSL, если ЖР/скриншоты не объяснили сбой" alwaysApply: false --- diff --git a/framework/skills/tool-usage/diagnostics/bug-reporting/SKILL.md b/framework/skills/tool-usage/diagnostics/bug-reporting/SKILL.md index d58ef0a4..6fb00b5d 100644 --- a/framework/skills/tool-usage/diagnostics/bug-reporting/SKILL.md +++ b/framework/skills/tool-usage/diagnostics/bug-reporting/SKILL.md @@ -1,6 +1,6 @@ --- name: bug-reporting -description: "MUST use WHEN сабагент исчерпал лимит самовосстановления и должен передать проблему оркестратору на расследование. Provides стандарт формы bug-report.json и критерии «это баг для дебаггера»." +description: "Эскалация бага после лимита самовосстановления агента" alwaysApply: false --- diff --git a/framework/skills/tool-usage/diagnostics/dap-bsl-code-debug-procedure/SKILL.md b/framework/skills/tool-usage/diagnostics/dap-bsl-code-debug-procedure/SKILL.md index cc266699..e4b53db9 100644 --- a/framework/skills/tool-usage/diagnostics/dap-bsl-code-debug-procedure/SKILL.md +++ b/framework/skills/tool-usage/diagnostics/dap-bsl-code-debug-procedure/SKILL.md @@ -1,6 +1,6 @@ --- name: dap-bsl-code-debug-procedure -description: "Use when нужно интерактивно отладить отдельно взятую BSL-процедуру через DAP/MCP: подключиться к debug server 1С, поставить/снять breakpoint, дождаться остановки, смотреть переменные, выполнить step_in/step_out/continue и корректно очистить отладочную сессию." +description: "Интерактивная DAP-отладка одной BSL-процедуры" uses_capabilities: - debug_bsl_code --- diff --git a/framework/skills/tool-usage/diagnostics/db-performance/SKILL.md b/framework/skills/tool-usage/diagnostics/db-performance/SKILL.md index 6a2fcdd4..cf107d76 100644 --- a/framework/skills/tool-usage/diagnostics/db-performance/SKILL.md +++ b/framework/skills/tool-usage/diagnostics/db-performance/SKILL.md @@ -1,6 +1,6 @@ --- name: db-performance -description: "Use for диагностики производительности БД и запросов 1С. Helps выявить slow query, план СУБД, блокировки, deadlock, TEMPDB/WAL, размеры таблиц и СКД на больших данных." +description: "Диагностика медленных запросов, блокировок и планов СУБД" target_agents: - debugger - developer-code diff --git a/framework/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md b/framework/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md index 1e8a1c3b..a1645e3e 100644 --- a/framework/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md +++ b/framework/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md @@ -1,6 +1,6 @@ --- name: event-log-analysis -description: "Use for поиска ошибок, событий и действий пользователей в журнале регистрации (ЖР) через ClickHouse. Helps локализовать время и контекст сбоя по event-log до обращения к техжурналу." +description: "Диагностика ошибок и действий в журнале регистрации" uses_capabilities: - search_event_log - logc_get_actual_log_timestamp diff --git a/framework/skills/tool-usage/diagnostics/runtime-investigation/SKILL.md b/framework/skills/tool-usage/diagnostics/runtime-investigation/SKILL.md index 658e1065..8c396a5b 100644 --- a/framework/skills/tool-usage/diagnostics/runtime-investigation/SKILL.md +++ b/framework/skills/tool-usage/diagnostics/runtime-investigation/SKILL.md @@ -1,6 +1,6 @@ --- name: runtime-investigation -description: "Use for расследования багов по bug-report: граф вызовов + ключевые переменные → DAP/agent-debug трасса → цикл гипотез." +description: "Runtime-диагностика бага: call graph, DAP, трассировка" --- # Runtime Investigation — расследование багов в рантайме diff --git a/framework/skills/tool-usage/diagnostics/tech-log-analysis/SKILL.md b/framework/skills/tool-usage/diagnostics/tech-log-analysis/SKILL.md index 99aecadd..df16f9ba 100644 --- a/framework/skills/tool-usage/diagnostics/tech-log-analysis/SKILL.md +++ b/framework/skills/tool-usage/diagnostics/tech-log-analysis/SKILL.md @@ -1,6 +1,6 @@ --- name: tech-log-analysis -description: "Use for управления жизненным циклом технологического журнала 1С (ТЖ): настройка, включение, сбор, анализ, восстановление. Helps диагностировать медленные запросы, блокировки и исключения платформы, недоступные в ЖР." +description: "Диагностика техжурнала 1С: EXCP, SQL, блокировки" uses_capabilities: - search_tech_log - configure_tech_log diff --git a/framework/skills/tool-usage/platform-admin/rac-use/SKILL.md b/framework/skills/tool-usage/platform-admin/rac-use/SKILL.md index 436f0821..516d7502 100644 --- a/framework/skills/tool-usage/platform-admin/rac-use/SKILL.md +++ b/framework/skills/tool-usage/platform-admin/rac-use/SKILL.md @@ -1,6 +1,6 @@ --- name: rac-use -description: "Use for администрирования кластера серверов 1С через RAC: просмотр/завершение сеансов, блокировки, соединения, информационные базы." +description: "Администрирование RAC: сессии, блокировки, инфобазы 1С" --- # RAC — утилита администрирования кластера 1С diff --git a/framework/skills/tool-usage/platform-admin/subsystem-update/SKILL.md b/framework/skills/tool-usage/platform-admin/subsystem-update/SKILL.md index 0498c601..3dd4dab6 100644 --- a/framework/skills/tool-usage/platform-admin/subsystem-update/SKILL.md +++ b/framework/skills/tool-usage/platform-admin/subsystem-update/SKILL.md @@ -1,6 +1,6 @@ --- name: subsystem-update -description: "Use for инициализации обновления подсистемы БСП: блокировка сеансов, запуск обработчиков обновления, проверка через ЖР и регистр ВерсииПодсистем." +description: "Обновления подсистем БСП: запуск, контроль, журнал" --- # Обновление подсистемы БСП diff --git a/framework/skills/tool-usage/platform-data/platform-data-core/SKILL.md b/framework/skills/tool-usage/platform-data/platform-data-core/SKILL.md index 20afdff5..8d12670e 100644 --- a/framework/skills/tool-usage/platform-data/platform-data-core/SKILL.md +++ b/framework/skills/tool-usage/platform-data/platform-data-core/SKILL.md @@ -1,6 +1,6 @@ --- name: platform-data-core -description: "Use for исследования метаданных конфигурации, выполнения запросов к базе и разбора навигационных ссылок. Helps получить структуру объектов, сформировать запрос и построить nav link в едином рабочем цикле." +description: "Platform data: metadata, nav links, safe queries" uses_capabilities: - list_metadata_objects - get_metadata_structure diff --git a/framework/skills/tool-usage/platform-data/xml-generation/SKILL.md b/framework/skills/tool-usage/platform-data/xml-generation/SKILL.md index 7c172490..e0c738db 100644 --- a/framework/skills/tool-usage/platform-data/xml-generation/SKILL.md +++ b/framework/skills/tool-usage/platform-data/xml-generation/SKILL.md @@ -1,6 +1,6 @@ --- name: xml-generation -description: "MUST use WHEN нужно создать, изменить или валидировать любой XML метаданных 1С (формы, роли, объекты, MXL, СКД, EPF, расширения, конфигурация). Provides безопасную генерацию и точечную модификацию через CLI xml-gen, соблюдая правило no-manual-xml-edit." +description: "Для любого XML метаданных 1С через xml-gen CLI" argument-hint: [] allowed-tools: - Bash diff --git a/framework/skills/tool-usage/platform-data/xml-generation/config-operations/SKILL.md b/framework/skills/tool-usage/platform-data/xml-generation/config-operations/SKILL.md index 93fe6ef6..45c13e81 100644 --- a/framework/skills/tool-usage/platform-data/xml-generation/config-operations/SKILL.md +++ b/framework/skills/tool-usage/platform-data/xml-generation/config-operations/SKILL.md @@ -1,6 +1,6 @@ --- name: config-operations -description: "Use for создания конфигурации, анализа и изменения её свойств и ChildObjects, валидации Configuration.xml. Helps управлять составом и параметрами Configuration.xml через xml-gen config." +description: "xml-gen Configuration.xml: свойства и ChildObjects" --- # Config Operations diff --git a/framework/skills/tool-usage/platform-data/xml-generation/epf-full/SKILL.md b/framework/skills/tool-usage/platform-data/xml-generation/epf-full/SKILL.md index a71f30f8..82805485 100644 --- a/framework/skills/tool-usage/platform-data/xml-generation/epf-full/SKILL.md +++ b/framework/skills/tool-usage/platform-data/xml-generation/epf-full/SKILL.md @@ -1,6 +1,6 @@ --- name: epf-full -description: "Use for создания внешних обработок и отчётов (EPF/ERF), добавления форм, макетов и справки, подключения к подсистеме «Дополнительные отчёты и обработки» БСП. Helps пройти полный цикл init→add-form→template→BSP-регистрация через xml-gen." +description: "xml-gen EPF/ERF: внешние отчёты и обработки" targets: - developer-code - architect diff --git a/framework/skills/tool-usage/platform-data/xml-generation/extension-operations/SKILL.md b/framework/skills/tool-usage/platform-data/xml-generation/extension-operations/SKILL.md index e84e36d9..76c3b81f 100644 --- a/framework/skills/tool-usage/platform-data/xml-generation/extension-operations/SKILL.md +++ b/framework/skills/tool-usage/platform-data/xml-generation/extension-operations/SKILL.md @@ -1,6 +1,6 @@ --- name: extension-operations -description: "Use for создания расширений конфигурации (CFE), заимствования объектов, генерации перехватчиков методов и анализа состава расширения. Helps управлять CFE через xml-gen extension init/borrow/diff/validate." +description: "xml-gen CFE: init, borrow, interceptors, validate" --- # Extension Operations (CFE) diff --git a/framework/skills/tool-usage/platform-data/xml-generation/form-dsl/SKILL.md b/framework/skills/tool-usage/platform-data/xml-generation/form-dsl/SKILL.md index 3790172e..cde22950 100644 --- a/framework/skills/tool-usage/platform-data/xml-generation/form-dsl/SKILL.md +++ b/framework/skills/tool-usage/platform-data/xml-generation/form-dsl/SKILL.md @@ -1,6 +1,6 @@ --- name: form-dsl -description: "Use for генерации управляемых форм 1С с UI-элементами, реквизитами и командами через JSON DSL. Helps описать структуру и статические свойства формы для xml-gen form compile/edit." +description: "xml-gen managed form DSL: compile/edit" --- # Form DSL diff --git a/framework/skills/tool-usage/platform-data/xml-generation/forms-toolkit/SKILL.md b/framework/skills/tool-usage/platform-data/xml-generation/forms-toolkit/SKILL.md index e51c7554..60de4f37 100644 --- a/framework/skills/tool-usage/platform-data/xml-generation/forms-toolkit/SKILL.md +++ b/framework/skills/tool-usage/platform-data/xml-generation/forms-toolkit/SKILL.md @@ -1,6 +1,6 @@ --- name: forms-toolkit -description: "Use for анализа структуры форм, добавления элементов, валидации и маппинга Title→Name для Vanessa-сценариев. Helps работать с Form.xml и EPF/ERF через xml-gen form-info/form-edit/form-validate/form-element-mapping/epf-validate." +description: "xml-gen forms: info, edit, validate, mapping" argument-hint: [] allowed-tools: - Bash diff --git a/framework/skills/tool-usage/platform-data/xml-generation/meta-operations/SKILL.md b/framework/skills/tool-usage/platform-data/xml-generation/meta-operations/SKILL.md index b7f187fc..d983d962 100644 --- a/framework/skills/tool-usage/platform-data/xml-generation/meta-operations/SKILL.md +++ b/framework/skills/tool-usage/platform-data/xml-generation/meta-operations/SKILL.md @@ -1,6 +1,6 @@ --- name: meta-operations -description: "Use for создания и редактирования объектов метаданных 1С (23 типа: справочники, документы, регистры, перечисления и др.) через xml-gen meta. Helps добавлять реквизиты, ТЧ, измерения и валидировать объекты конфигурации." +description: "xml-gen metadata: объекты, реквизиты, табличные части" --- # Meta Operations diff --git a/framework/skills/tool-usage/platform-data/xml-generation/mxl-dsl/SKILL.md b/framework/skills/tool-usage/platform-data/xml-generation/mxl-dsl/SKILL.md index 07c142c3..bad087c2 100644 --- a/framework/skills/tool-usage/platform-data/xml-generation/mxl-dsl/SKILL.md +++ b/framework/skills/tool-usage/platform-data/xml-generation/mxl-dsl/SKILL.md @@ -1,6 +1,6 @@ --- name: mxl-dsl -description: "Use for генерации и доработки печатных форм 1С (MXL) через JSON DSL. Helps описать области, ячейки и статические стили для xml-gen mxl compile/decompile/info/validate." +description: "xml-gen MXL print forms: compile/edit/info" --- # MXL DSL diff --git a/framework/skills/tool-usage/platform-data/xml-generation/role-dsl/SKILL.md b/framework/skills/tool-usage/platform-data/xml-generation/role-dsl/SKILL.md index 5830c34e..e9b6665b 100644 --- a/framework/skills/tool-usage/platform-data/xml-generation/role-dsl/SKILL.md +++ b/framework/skills/tool-usage/platform-data/xml-generation/role-dsl/SKILL.md @@ -1,6 +1,6 @@ --- name: role-dsl -description: "Use for генерации ролей 1С с правами доступа через JSON DSL и точечного редактирования Rights.xml. Helps создать роль с нуля и управлять отдельными правами через xml-gen role compile/add-object/add-right." +description: "xml-gen roles DSL и Rights.xml editing" --- # Role DSL diff --git a/framework/skills/tool-usage/platform-data/xml-generation/skd-dsl/SKILL.md b/framework/skills/tool-usage/platform-data/xml-generation/skd-dsl/SKILL.md index c9d58fcd..9e6dcf4d 100644 --- a/framework/skills/tool-usage/platform-data/xml-generation/skd-dsl/SKILL.md +++ b/framework/skills/tool-usage/platform-data/xml-generation/skd-dsl/SKILL.md @@ -1,6 +1,6 @@ --- name: skd-dsl -description: "Use for генерации схем компоновки данных 1С (СКД) с нуля через JSON DSL: наборы данных, вычисляемые поля, шаблоны вывода, варианты, условное оформление. Helps собрать Schema.xml через xml-gen skd compile/info/validate." +description: "xml-gen SKD schemas from JSON DSL" --- # SKD DSL diff --git a/framework/skills/tool-usage/platform-data/xml-generation/skd-edit/SKILL.md b/framework/skills/tool-usage/platform-data/xml-generation/skd-edit/SKILL.md index 19c7cd8f..8007f306 100644 --- a/framework/skills/tool-usage/platform-data/xml-generation/skd-edit/SKILL.md +++ b/framework/skills/tool-usage/platform-data/xml-generation/skd-edit/SKILL.md @@ -1,6 +1,6 @@ --- name: skd-edit -description: "Use for атомарного изменения существующей Schema.xml СКД: добавить/удалить поля, итоги, параметры, переписать запрос набора данных, изменить структуру варианта. Helps точечно дорабатывать СКД без полной перекомпиляции через xml-gen skd edit." +description: "xml-gen atomic edits of existing SKD Schema.xml" --- # SKD Edit — точечное редактирование Schema.xml diff --git a/framework/skills/tool-usage/platform-data/xml-generation/subsystem-interface/SKILL.md b/framework/skills/tool-usage/platform-data/xml-generation/subsystem-interface/SKILL.md index d1be9b95..57fb9107 100644 --- a/framework/skills/tool-usage/platform-data/xml-generation/subsystem-interface/SKILL.md +++ b/framework/skills/tool-usage/platform-data/xml-generation/subsystem-interface/SKILL.md @@ -1,6 +1,6 @@ --- name: subsystem-interface -description: "Use for создания подсистем, управления их составом и настройки CommandInterface.xml (видимость, порядок команд, размещение в группах). Helps поддерживать навигацию конфигурации через xml-gen subsystem/interface compile/edit/validate." +description: "xml-gen subsystems and CommandInterface.xml" --- # Subsystem + Interface Operations diff --git a/framework/skills/tool-usage/review/cross-provider-review/SKILL.md b/framework/skills/tool-usage/review/cross-provider-review/SKILL.md index 1983ab53..dea3ada5 100644 --- a/framework/skills/tool-usage/review/cross-provider-review/SKILL.md +++ b/framework/skills/tool-usage/review/cross-provider-review/SKILL.md @@ -1,6 +1,6 @@ --- name: cross-provider-review -description: "Use for advisory second-opinion review между model families. Маршрутизирует GPT/Codex primary agents в Claude/Opus review и наоборот; поддерживает sandbox-сессии, follow-up, debate, sync, status, log, stats, show, close lifecycle." +description: "Для второго ревью другой моделью и debate-сессий" capabilities: review,agent-governance,cross-provider --- diff --git a/framework/skills/tool-usage/v8-runner/SKILL.md b/framework/skills/tool-usage/v8-runner/SKILL.md index b9fcdb8a..3e12a994 100644 --- a/framework/skills/tool-usage/v8-runner/SKILL.md +++ b/framework/skills/tool-usage/v8-runner/SKILL.md @@ -1,6 +1,6 @@ --- name: v8-runner -description: "Use for управления v8-runner на локальных 1С-проектах: настройка v8project.yaml, сборка, синтаксические проверки, тесты, выгрузка/загрузка ИБ, конвертация форматов, запуск клиентов 1С." +description: "v8-runner: базы, сборка, проверки, тесты, клиенты 1С" provides_capabilities: - build_project - full_rebuild_project @@ -64,6 +64,19 @@ v8-runner --json-message build - `--log-level ` — для диагностики. - `--no-color` — простой текстовый вывод. +## Жизненный цикл запущенных клиентов 1С + +Интерактивные клиенты 1С и MCP/VA-сессии, которые должны оставаться доступными после возврата команды агенту, запускай как самостоятельные процессы с явным управлением жизненным циклом. Не используй `sleep`, `tail -f`, бесконечный shell-loop или похожую wrapper-команду как способ «удержать» клиент 1С живым: при завершении wrapper'а терминал/PTY или окружение агента может закрыть дочерний процесс 1С, а `session-manager` увидит это как обрыв WS без нормального закрытия. + +Правильный порядок: + +1. Запусти клиент через штатную команду `v8-runner launch ...`. +2. Если среда выполнения прибирает дочерние процессы после завершения shell-команды, запускай команду detached-средствами окружения (`nohup`, `setsid`, service/job runner или эквивалент проекта), сохрани PID и лог запуска. +3. Готовность проверяй внешним наблюдаемым состоянием: `session_list`, появление нужных MCP-tools, окно 1С, файл-протокол или запись в ЖР. +4. Завершай клиент явным действием: штатным инструментом session-manager/VA, командой закрытия клиента или точечным `kill ` только для своего сохранённого PID. + +`sleep` допустим только как короткое ожидание между проверками готовности внутри скрипта/poll-loop. Он не должен быть владельцем жизненного цикла 1С-процесса. + ## Первый проход 1. Проверь, существует ли `v8project.yaml` в корне 1С-проекта. @@ -116,7 +129,7 @@ WS-сопряжение с [v8-client-session-manager](https://github.com/SteelM ### CLI-флаги -- `--mcp-transport={ws|legacy|auto}` — `auto` (по умолчанию) делает TCP-пробу `manager_url` ~200 ms; `ws` — строго WS, падает при недоступности; `legacy` — старый HTTP-режим без probe. +- `--mcp-transport={mcp|ws|auto}` — `auto` (по умолчанию) делает TCP-пробу `manager_url` ~200 ms; `ws` — строго WS, падает при недоступности; `mcp` — локальный HTTP MCP-режим без probe. - `--manager-url ` — переопределить `tools.client_mcp.manager_url` (дефолт `ws://127.0.0.1:4000/sessions`). - `--client-uid ` — переопределить автогенерированный UUID v4. - `--corr-id ` — переопределить `vr-<первые 8 символов client_uid>`. @@ -128,7 +141,7 @@ WS-сопряжение с [v8-client-session-manager](https://github.com/SteelM ```yaml tools: client_mcp: - transport: auto # ws | legacy | auto + transport: auto # mcp | ws | auto manager_url: ws://127.0.0.1:4000/sessions log_level: info ws_timeout_ms: 1000 @@ -146,6 +159,17 @@ tools: | `test yaxunit ...` | `yaxunit_runner` | | `test va ...` | `vanessa_test_client` | +### Режимы запуска клиентов и тестов + +| Режим | Назначение | MCP/VA поведение | +|---|---|---| +| `launch designer` | Открыть Конфигуратор. | Не запускает клиентские MCP-tools и не применяет enterprise additional keys. | +| `launch thin`, `launch thick`, `launch ordinary` | Открыть обычный UI-клиент 1С. | При WS-сопряжении регистрирует базовый клиентский MCP-набор без `kind`; сам по себе не даёт VA-tools. | +| `launch mcp` | Запустить onec-client-mcp-devkit внутри 1С без Vanessa. | `kind=v8_runner_client` для WS; локальный HTTP MCP при `--mcp-transport=mcp` или fallback из `auto`. | +| `launch mcp va` | Запустить менеджер тестирования Vanessa для исследования, авторинга и клиентских MCP-tools VA. | `kind=vanessa_test_client`; runner добавляет `/TESTMANAGER`, `/DisableUnsafeActionProtection`, `/Execute `, runtime `VAParams`, отключает автозапуск/автозакрытие сценариев и не использует `StartFeaturePlayer`. | +| `test yaxunit ...` | Выполнить YAxUnit тесты. | `kind=yaxunit_runner` в WS-режиме; это тестовый runner, а не интерактивная UI-сессия. | +| `test va` | Выполнить Vanessa feature-сценарии. | `kind=vanessa_test_client`, но payload — `StartFeaturePlayer;VAParams=...`; это прогон сценариев, не режим исследования менеджера. | + ### Что v8-runner подставляет в `/C` в WS-ветке ```text @@ -187,21 +211,78 @@ v8-runner launch mcp va \ /N <пользователь> /P <пароль> /Execute <путь>/vanessa-automation.epf - /C"mcpMode=ws;manager_url=ws://127.0.0.1:4000/sessions;client_uid=;kind=vanessa_test_client;corr_id=;mcp_log_level=debug;mcp_ws_timeout_ms=5000" + /C"mcpMode=ws;manager_url=ws://127.0.0.1:4000/sessions;client_uid=;kind=vanessa_test_client;corr_id=;mcp_log_level=debug;mcp_ws_timeout_ms=5000;VAParams=" ``` +Обязательный смысл этой строки запуска: MCP-сессия должна жить на стороне процесса тест-менеджера с открытой внешней обработкой Vanessa Automation. Не запускай тестируемое приложение с формой `MCPVA`: `MCPVA` — внутренняя форма/модуль внешней обработки VA, и именно VA в процессе `/TESTMANAGER` должна выполнить `MCPVA.ЗарегистрироватьИнструментыMCP()`. + Критерий готовности VA MCP-сессии: в `session_list` появилась live-сессия `kind=vanessa_test_client`, и в её tools есть VA-инструменты (`get_VanessaAutomation_state`, `connect_test_client`, `get_window_list_os`, `get_window_screenshot_os`, `get_form_analysis`, `manage_command_interface`) или число tools стало больше базового набора `client_mcp`. Первичная регистрация с базовыми tools ещё не означает, что `MCPVA.ЗарегистрироватьИнструментыMCP()` уже отработал. -Тестируемое приложение в VA-контуре запускает сам тест-менеджер: вызови `connect_test_client` с именем профиля клиента тестирования (`profileName`, например `Codex thin AgentAI`). VA поднимет отдельный процесс `/TESTCLIENT -TPort ` из профиля и подключит к нему `ТестируемоеПриложение`. Не запускай этот `/TESTCLIENT` вручную для VA-пути, если только не отлаживаешь сам механизм профилей. +Сразу после `v8-runner launch mcp va` ответ `session_list=[]` или отсутствие VA-tools **не является ошибкой**: запуск тест-менеджера и регистрация инструментов штатно могут занимать 10-90 секунд. Обязательный readiness-loop: + +1. Опроси `session_list` каждые 5-10 секунд. +2. Жди суммарно до 120 секунд с момента запуска: 10-90 секунд — нормальный диапазон, 90-120 секунд — диагностический запас. +3. Продолжай только при live-сессии `kind=vanessa_test_client`, `state=active`, `disconnected_secs_ago=null`, `inflight=0`, и наличии нужных VA-tools для текущей задачи. +4. Имена tools из кеша MCP/showcase без live-сессии не доказывают готовность. +5. Если условие не выполнено за 120 секунд — стоп и доклад `VA MCP readiness blocker`. + +После готовности WS-сессии тестируемое приложение в VA-контуре запускает сам тест-менеджер: вызови MCP-tool `connect_test_client` с аргументом `profileName` (имя профиля клиента тестирования, например `Codex thin AgentAI`). VA поднимет отдельный процесс `/TESTCLIENT -TPort ` из профиля и подключит к нему `ТестируемоеПриложение`; после этого становятся доступны клиентские MCP-методы VA (`get_form_analysis`, `manage_command_interface`, `manage_form_elements`, screenshot/data tools и т.п.). Не запускай этот `/TESTCLIENT` вручную для VA-пути, если только не отлаживаешь сам механизм профилей. + +После исследования, прогона ручных действий или ошибки обязательно вызови MCP-tool `close_test_client`. Передавай тот же `profileName`, если работал с конкретным профилем; без `profileName` tool закрывает текущий подключенный профиль. Это освобождает test-client процесс и не оставляет лишние 1С-сессии перед следующим запуском. + +Скриншотные MCP-инструменты VA (`get_window_list_os`, `get_window_screenshot_os`) считай готовыми только после короткой smoke-проверки на текущем окружении: live-сессия должна оставаться активной, `inflight=0`, а PNG должен быть не пустым и не чёрным. Детальный порядок визуальной проверки и fallback-условия описаны в навыке `va-visual-check`. + +Секцию `tools.va` / `tests.va` в `v8project.yaml` и профиль TestClient в VAParams настраивай по `references/config-and-backends.md` (раздел «Vanessa Automation в `v8project.yaml`»). Точную командную цепочку запуска manager → `connect_test_client` → close см. в `references/testing.md` (раздел «Точная цепочка VA manager → TestClient»). Полный payload, JSON-форму вывода (`--json-message`), правила probe и поведение при недоступности менеджера — в `references/project-workflows.md` (раздел «WS-режим к session-manager»). Подъём самого менеджера в v8-runner **не входит** — см. навык `v8-session-manager`. + +### UI MCP через платформенный тест-клиент + +Если задача — пройти интерфейс 1С через клиентские MCP-tools (`open_form`, `click`, `input`, `get_value`, `get_table_rows`, `test_client_start`), этот контур допустим только для структурного управления, когда нужная функция принципиально отсутствует в VA MCP или когда он используется как часть VA/TestClient-сценария. + +Рабочая цепочка: + +1. Подними session-manager и проверь HTTP endpoint: `tools/call session_list` должен отвечать, даже если `sessions=[]`. +2. Запусти управляющий MCP-клиент detached, обязательно с `/TESTMANAGER`: + +```bash +uid=$(cat /proc/sys/kernel/random/uuid) +setsid nohup v8-runner --no-color --log-level debug launch thin \ + --mcp-transport ws \ + --manager-url ws://127.0.0.1:4000/sessions \ + --client-uid "$uid" \ + --corr-id "ui-$uid" \ + --mcp-log-level debug \ + --mcp-ws-timeout-ms 5000 \ + --raw-key /TESTMANAGER \ + > "/tmp/ui-mcp-$uid.log" 2>&1 & +``` + +3. Дождись в `session_list` live-сессии `kind=1c-client`, `state=active`, `inflight=0`, `infobase_name=<нужная ИБ>`. Базовая проверка перед UI-вызовами: `infobase_info` должен быстро вернуть ответ. +4. Запусти тестируемое приложение отдельным процессом с `/TESTCLIENT -TPort <порт>` и теми же параметрами подключения, пользователем и паролем, что в проектном запуске. Это предпочтительный путь: агент сам поднимает тестируемое приложение detached и сохраняет PID/лог, а `test_client_start` на следующем шаге используется как подключение управляющего `/TESTMANAGER` к уже слушающему порту. Если в проекте есть готовый launcher, он тоже должен передавать `/N`, `/P`, `/UC` и тот же connection string; иначе используй прямую форму платформы: + +```bash +setsid nohup /opt/1cv8/x86_64//1cv8c ENTERPRISE \ + /DisableStartupDialogs \ + /IBConnectionString 'Srvr="";Ref="";' \ + /N /P /UC \ + /TESTCLIENT -TPort 1538 \ + > /tmp/test-client-1538.log 2>&1 & +``` + +5. Подключи тестируемое приложение через управляющую MCP-сессию: + +```json +{"name":"test_client_start","arguments":{"session_id":"<1c-client session_id>","port":1538}} +``` -Скриншотные MCP-инструменты VA (`get_window_list_os`, `get_window_screenshot_os`) считай условными, а не гарантированными. Они появляются в MCP tools после `MCPVA.ЗарегистрироватьИнструментыMCP()`, но фактически работают только если VA заполнила PID/дескриптор окна тест-клиента. Проверенная на 26.06.2026 связка 1C 8.3.27.2074 + Vanessa Automation 1.2.043.28 + Linux/X11: +Успешный критерий: `{"ok": true, "data": {"connected": true}}`. -- при штатном проектном `VAParams` (`ИспользоватьКомпонентуVanessaExt=Ложь`, `ИспользоватьВнешнююКомпонентуДляСкриншотов=Ложь`) `connect_test_client` успешен, `get_window_list_testclient` видит окна, но `get_window_list_os` падает с `ACTION_FAILED: Не вышло получить PID процесса клиента тестирования`; -- при временном включении `ИспользоватьКомпонентуVanessaExt=Истина` и `ИспользоватьВнешнююКомпонентуДляСкриншотов=Истина` первый запуск блокируется диалогом установки внешней компоненты, повторный запуск регистрирует VA MCP tools, но профиль всё равно остаётся с `PID=0`, и `get_window_screenshot_os` падает той же ошибкой. +6. После этого выполняй UI MCP-tools только через `session_id` управляющей сессии: `open_form` → `click/input/select` → `get_value/get_table_rows`. Для элементов формы можно строить URI напрямую как `control:///`, если `find` нестабилен. -Поэтому default для визуального контроля формы: управляй формой через VA/TestClient MCP, а визуальный скриншот снимай внешним OS/noVNC/browser screenshot-инструментом, если `get_window_screenshot_os` не прошёл короткую smoke-проверку на текущем окружении. Наличие tool в `tools/list` или `session_list.tools` не является доказательством работоспособности скриншота. +Не делай так: -Полный payload, JSON-форму вывода (`--json-message`), правила probe и поведение при недоступности менеджера — в `references/project-workflows.md` (раздел «WS-режим к session-manager»). Подъём самого менеджера в v8-runner **не входит** — см. навык `v8-session-manager`. +- Не запускай управляющий клиент без `/TESTMANAGER`: при первом `test_client_start` платформа может упасть с `Тип не определен (ТестируемоеПриложение)`. +- Не полагайся на `test_client_start` как на единственный способ запуска `/TESTCLIENT`, если он стартует клиента без `/N` и `/P`: такой процесс может остаться на входе в базу, а подключение вернёт `Отсутствует подходящий клиент тестирования`. +- Не считай `tools/list` доказательством готовности: proxied tools могут быть только из кеша session-manager. Готовность подтверждает live-сессия в `session_list` и успешный простой вызов (`infobase_info`). ### Resolved: WS-сессии в `test yaxunit` (DRIVE 2026-05-11) diff --git a/framework/skills/tool-usage/v8-runner/references/command-selection.md b/framework/skills/tool-usage/v8-runner/references/command-selection.md index eb828780..c6983acd 100644 --- a/framework/skills/tool-usage/v8-runner/references/command-selection.md +++ b/framework/skills/tool-usage/v8-runner/references/command-selection.md @@ -166,8 +166,8 @@ v8-runner launch mcp --mcp-config ```bash v8-runner launch mcp --mcp-transport=ws --manager-url ws://127.0.0.1:4000/sessions -v8-runner launch mcp --mcp-transport=legacy # принудительно legacy без probe +v8-runner launch mcp --mcp-transport=mcp # принудительно локальный HTTP MCP без probe v8-runner launch mcp --mcp-log-level=debug --client-uid --corr-id ``` -`--mcp-transport=auto` (по умолчанию) выполняет TCP-пробу `manager_url` на 200 ms и выбирает `ws` при успехе и `legacy` при отказе. Те же WS-флаги работают на `test yaxunit ...` и `test va ...`. Смотри полный раздел WS-режима в `project-workflows.md`, внутренний mapping `kind` и форму вывода `--json-message`. +`--mcp-transport=auto` (по умолчанию) выполняет TCP-пробу `manager_url` на 200 ms и выбирает `ws` при успехе и `mcp` при отказе. Те же WS-флаги работают на `test yaxunit ...` и `test va ...`. Смотри полный раздел WS-режима в `project-workflows.md`, внутренний mapping `kind` и форму вывода `--json-message`. diff --git a/framework/skills/tool-usage/v8-runner/references/config-and-backends.md b/framework/skills/tool-usage/v8-runner/references/config-and-backends.md index e37be1ea..b9f6d91d 100644 --- a/framework/skills/tool-usage/v8-runner/references/config-and-backends.md +++ b/framework/skills/tool-usage/v8-runner/references/config-and-backends.md @@ -53,3 +53,80 @@ `v8project.local.yaml` — это только автоматический локальный overlay. Он может переопределять только `workPath`, `infobase.*`, `tools.*`, `tests.*` и `mcp.*`; он не должен задавать `source-set`, `format` или `builder`, и его нельзя использовать как `--config`. `--workdir` имеет приоритет над обоими конфиг-файлами. + +## Vanessa Automation в `v8project.yaml` + +Конфигурация VA разделена на два уровня: + +1. `v8project.yaml` / `v8project.local.yaml` указывает, какую внешнюю обработку VA запускать, какой JSON-шаблон параметров взять и какой профиль фич активен. +2. JSON из `tests.va.params_path` — это шаблон `VAParams`. В нём лежат настройки самой Vanessa Automation, включая таблицу профилей TestClient. `v8-runner` читает этот шаблон, создаёт runtime-копию в `workPath/temp/.../va-params.json`, накладывает выбранный профиль фич/теги/логи и передаёт runtime-копию в `/C` как `VAParams=`. Не редактируй runtime-копию как источник правды. + +Минимальный универсальный блок в `v8project.yaml`: + +```yaml +tools: + va: + epf_path: '' + +tests: + va: + params_path: '' + profile: '' + fail_fast: false + profiles: + : + feature_path: '' + # опционально: + # features_to_run: ['feature-name.feature'] + # filter_tags: ['tag-without-or-with-leading-at'] + # ignore_tags: ['wip'] + # scenario_filter: ['scenario name fragment'] +``` + +Смысл полей: + +- `tools.va.epf_path` — путь к внешней обработке Vanessa Automation. Legacy-поле `tests.va.epf_path` не поддерживается. +- `tests.va.params_path` — путь к JSON-шаблону VAParams. Это не generated-файл, а стабильный шаблон проекта или локального окружения. +- `tests.va.profile` — имя активного профиля фич; должно существовать в `tests.va.profiles`. +- `tests.va.profiles..feature_path` — файл или каталог `.feature`, который будет записан в runtime VAParams как `КаталогФич`. +- `filter_tags` и `ignore_tags` можно писать с `@` или без него; runner удалит один ведущий `@` перед записью в `СписокТеговОтбор` / `СписокТеговИсключение`. + +`v8project.local.yaml` используй для машинно-локальных путей и секретов: например, если `epf_path`, `params_path`, пользователь/пароль TestClient или путь к локальной ИБ отличаются на машине агента. Не храни реальные секреты в общем `v8project.yaml`; лучше вынеси их в локальный VAParams-шаблон и укажи его через `tests.va.params_path` в `v8project.local.yaml`. + +### Профиль TestClient внутри VAParams + +Для `launch mcp va` и UI/UX-проверки через VA MCP профиль тест-клиента задаётся не отдельным полем `v8project.yaml`, а таблицей `ДанныеКлиентовТестирования` в JSON-шаблоне VAParams. Именно имя этой строки потом передаётся в MCP-вызов `connect_test_client {"profileName":"<имя-профиля>"}`. + +Минимальная структура: + +```json +{ + "ИспользоватьКомпонентуVanessaExt": "Истина", + "ИспользоватьВнешнююКомпонентуДляСкриншотов": "Истина", + "ДиапазонПортовTestclient": "-", + "ОпределятьРеальныйПортНаКоторомЗапустилсяКлиентТестирования": "Истина", + "ДанныеКлиентовТестирования": [ + { + "Имя": "", + "Синоним": "", + "ПутьКИнфобазе": "", + "ПортЗапускаТестКлиента": , + "ДопПараметры": "/N /P /DisableStartupDialogs /DisableUnsafeActionProtection", + "ТипКлиента": "Тонкий", + "ИмяКомпьютера": "localhost" + } + ] +} +``` + +Почему поля именно такие: + +- `Имя` — стабильный ключ профиля, который агент передаёт в `connect_test_client`; имя должно быть независимым от конкретной задачи. +- `Синоним` — человекочитаемый алиас; если отдельный алиас не нужен, держи равным `Имя`, чтобы не плодить неоднозначность. +- `ПутьКИнфобазе` — строка подключения тестируемого приложения. VA manager запускается отдельно и должен знать, какую ИБ открыть как `/TESTCLIENT`. +- `ПортЗапускаТестКлиента` и `ДиапазонПортовTestclient` — фиксируют порт, чтобы агент мог гарантированно подключиться к ожидаемому клиенту и не зависеть от старых открытых TestClient-процессов. Перед запуском закрывай старые test-client'ы или выбирай свободный зарезервированный порт. +- `ДопПараметры` — всё, что не должно останавливать запуск на диалогах: пользователь/пароль или другой способ авторизации, `/DisableStartupDialogs`, `/DisableUnsafeActionProtection`, при необходимости `/UC <код>`. Если строка содержит секреты, шаблон должен быть локальным. +- `ТипКлиента` — тип клиента, который VA должна запустить. Для автоматизации обычно выбирают тонкий клиент, если проект не требует толстый или обычный. +- `ИмяКомпьютера` — машина, где VA ищет/запускает TestClient. Для локального manager + test-client это `localhost`. +- `ИспользоватьКомпонентуVanessaExt` и `ИспользоватьВнешнююКомпонентуДляСкриншотов` включай, когда профиль VA должен работать с OS-окнами и реальным PID тест-клиента. +- `ОпределятьРеальныйПортНаКоторомЗапустилсяКлиентТестирования` оставляй включённым: VA должна сверить фактический процесс/порт, а не считать запуск успешным по одному профилю. diff --git a/framework/skills/tool-usage/v8-runner/references/learned-patterns.md b/framework/skills/tool-usage/v8-runner/references/learned-patterns.md new file mode 100644 index 00000000..7652adcc --- /dev/null +++ b/framework/skills/tool-usage/v8-runner/references/learned-patterns.md @@ -0,0 +1,25 @@ +# Learned Patterns — v8-runner + +## UI MCP через платформенный тест-клиент требует двух клиентских ролей + +``` +status: candidate +класс: Смешение управляющего MCP-клиента и тестируемого приложения при UI-автоматизации 1С +приём: Для клиентских MCP-tools запускать управляющий 1С-клиент с WS-сопряжением и /TESTMANAGER, отдельно запускать тестируемое приложение с /TESTCLIENT -TPort и теми же /N /P, затем подключать его через test_client_start и проверять connected=true +антиприём: Не запускать управляющий клиент без /TESTMANAGER и не считать процесс /TESTCLIENT подходящим, если он стартовал без учётных данных или завис на входе в ИБ +почему: Без /TESTMANAGER недоступны платформенные типы тестирования, а /TESTCLIENT без корректного входа в ИБ не считается подходящим клиентом; proxied MCP-вызовы зависают или возвращают ошибки подключения +шаги: session_list -> live kind=1c-client -> infobase_info -> запуск /TESTCLIENT с /N /P -> test_client_start(port) -> open_form/click/get_value с session_id +источник: UI MCP-прогон формы 1С через session-manager: сначала ошибки режима клиента и подключения /TESTCLIENT, затем успешная цепочка /TESTMANAGER + /TESTCLIENT с учётными данными +``` + +## Общие launch-helper-ы требуют матрицы entry-point тестов + +``` +status: candidate +класс: Изменение общего launch-helper-а без закрепления всех команд-потребителей +приём: При расширении helper-а, который формирует ключи или payload запуска для нескольких команд, сразу находить все call-site-ы и добавлять/обновлять тесты для каждого entry-point-а +антиприём: Не покрывать только команду, ради которой начато изменение, если фактический helper используется другими режимами запуска +почему: Новый ключ или overlay становится частью контракта всех потребителей helper-а; без тестов регрессия или неожиданное изменение поведения другой команды останется незамеченным +шаги: rg по helper/import -> список команд-потребителей -> отдельные CLI/unit проверки на новый контракт и отсутствие дублей для каждого потребителя +источник: Доработка `launch mcp va`: `/DisableUnsafeActionProtection` добавлялся через общий `vanessa_enterprise_launch_keys`, после ревью пришлось дополнительно закрепить контракт `test va` +``` diff --git a/framework/skills/tool-usage/v8-runner/references/project-workflows.md b/framework/skills/tool-usage/v8-runner/references/project-workflows.md index 6cbad9a0..119ab5bd 100644 --- a/framework/skills/tool-usage/v8-runner/references/project-workflows.md +++ b/framework/skills/tool-usage/v8-runner/references/project-workflows.md @@ -148,17 +148,17 @@ v8-runner launch mcp --mcp-config > - v8-runner: upstream [`alkoleft/v8-runner-rust`](https://github.com/alkoleft/v8-runner-rust) → используемый форк [`SteelMorgan/v8-runner-rust`](https://github.com/SteelMorgan/v8-runner-rust) > - onec-client-mcp-devkit: используемый форк [`SteelMorgan/onec-client-mcp-devkit`](https://github.com/SteelMorgan/onec-client-mcp-devkit) -Когда рядом с проектом запущен [`v8-client-session-manager`](https://github.com/SteelMorgan/v8-client-session-manager), 1С-клиент может подключаться к нему по WebSocket вместо локального HTTP MCP-сервера (legacy `runMcp`-режим). v8-runner делает выбор автоматически. +Когда рядом с проектом запущен [`v8-client-session-manager`](https://github.com/SteelMorgan/v8-client-session-manager), 1С-клиент может подключаться к нему по WebSocket вместо локального HTTP MCP-сервера (`runMcp`-режим). v8-runner делает выбор автоматически. ### Транспорт и автоопределение `tools.client_mcp.transport`: -- `auto` (по умолчанию) — короткий TCP-probe (200 ms) на хост:порт из `manager_url`. Слышим listener → WS, нет → legacy. +- `auto` (по умолчанию) — короткий TCP-probe (200 ms) на хост:порт из `manager_url`. Слышим listener → WS, нет → `mcp`. - `ws` — строго WS, при недоступности менеджера запуск падает с `session-manager unreachable at `. -- `legacy` — старый HTTP-режим без probe. +- `mcp` — локальный HTTP MCP-режим без probe. -Override через `--mcp-transport={ws|legacy|auto}`. CLI приоритет конфига. +Override через `--mcp-transport={ws|mcp|auto}`. CLI приоритет конфига. ### Что v8-runner подставляет в `/C` в WS-ветке @@ -200,13 +200,13 @@ WS-ветка: ```json { "transport": "ws", "client_uid": "...", "kind": "...", "manager_url": "...", "corr_id": "..." } ``` -Legacy-ветка: +MCP-ветка: ```json -{ "transport": "legacy", "mcp_port": 9874 } +{ "transport": "mcp", "mcp_port": 9874 } ``` Внешний оркестратор (CI, AI-агент) использует `client_uid` для поиска сессии в `session_list` менеджера. Структура записи сессии и `session_list` описаны в навыке `v8-session-manager`. ### Менеджер не запускается из v8-runner -v8-runner только подключается к запущенному менеджеру. Подъём менеджера — отдельный шаг (`cargo run --release` в репо `v8-client-session-manager`, либо systemd-юнит `systemd/v8-session-manager.service`, либо Docker-compose). Если менеджер не нужен — `--mcp-transport=legacy` форсирует старый flow. +v8-runner только подключается к запущенному менеджеру. Подъём менеджера — отдельный шаг (`cargo run --release` в репо `v8-client-session-manager`, либо systemd-юнит `systemd/v8-session-manager.service`, либо Docker-compose). Если менеджер не нужен — `--mcp-transport=mcp` форсирует локальный HTTP MCP flow. diff --git a/framework/skills/tool-usage/v8-runner/references/testing.md b/framework/skills/tool-usage/v8-runner/references/testing.md index 3422dfa8..2bf32851 100644 --- a/framework/skills/tool-usage/v8-runner/references/testing.md +++ b/framework/skills/tool-usage/v8-runner/references/testing.md @@ -25,7 +25,7 @@ v8-runner test yaxunit --mcp-transport=ws all # ❌ ```yaml tools: client_mcp: - transport: auto # ws | legacy | auto + transport: auto # mcp | ws | auto manager_url: ws://127.0.0.1:4000/sessions log_level: info ws_timeout_ms: 1000 @@ -40,7 +40,7 @@ tools: Если yaxunit_runner / vanessa_test_client не появляется в `session_list` менеджера: 1. **Лог менеджера** — `/tmp/v8sm/logs/mcp/actions.log` (путь зависит от `workPath` менеджера). Искать `WS connection accepted (handshake completed)` в окне прогона. Запустить менеджер с `--log-level debug`, если он стоит на `info`. -2. **`/C`-payload** — поднять v8-runner с `--log-level=trace` (на уровне глобальных опций) и смотреть, дописался ли `mcpMode=ws;manager_url=...` к `RunUnitTests=...`. Если нет — `decide_mcp_transport` вернул `Legacy`. +2. **`/C`-payload** — поднять v8-runner с `--log-level=trace` (на уровне глобальных опций) и смотреть, дописался ли `mcpMode=ws;manager_url=...` к `RunUnitTests=...`. Если нет — выбор транспорта ушёл в `mcp`. 3. **Лог Enterprise-1С** — `/temp/yaxunit/runs//enterprise.out.log` и `runner.log`. Искать `[MCP INFO ...] Logging params applied` и `Регистрация провайдера ...` — это диагностика MCP-инициализации со стороны BSL devkit. 4. **Stdout v8-runner** — диагностический блок `[MCP INFO ...]` появляется в `diagnostic`-секции `test`-output (только при удачной MCP-инициализации клиента). @@ -68,6 +68,8 @@ v8-runner test yaxunit --full module ## Vanessa Automation +Конфиг запуска VA описан в `references/config-and-backends.md`, раздел «Vanessa Automation в `v8project.yaml`»: `tools.va.epf_path`, `tests.va.params_path`, `tests.va.profile`, `tests.va.profiles.*` и профиль TestClient внутри VAParams. Перед изменением команд сначала проверь именно эти секции. + Запусти настроенный профиль Vanessa Automation: ```bash @@ -89,12 +91,61 @@ v8-runner test va ```bash v8-runner launch mcp va v8-runner launch mcp va --mode thin -v8-runner launch mcp va --mcp-port -v8-runner launch mcp va --mcp-config +v8-runner launch mcp va --mcp-transport ws --manager-url ws://127.0.0.1:4000/sessions ``` Это запускает клиентский MCP-сервер в 1С и загружает Vanessa Automation из `tools.va`. Предпочитай его для разведочной работы с VA; для настроенного автоматического прогона тестов используй `test va`. +Перед запуском проверь конфиг: + +1. `tools.va.epf_path` указывает на существующую `vanessa-automation.epf`. +2. `tests.va.params_path` указывает на JSON-шаблон VAParams. +3. `tests.va.profile` существует в `tests.va.profiles`. +4. В VAParams есть профиль TestClient в `ДанныеКлиентовТестирования`; его `Имя` — это будущий `profileName` для `connect_test_client`. + +### Точная цепочка VA manager → TestClient + +1. Убедись, что session-manager отвечает на `session_list`. Если менеджер не запущен, подними его по навыку `v8-session-manager`. + +2. Запусти VA test-manager через `v8-runner launch mcp va` в detached-режиме, если клиент должен жить после возврата shell-команды: + +```bash +uid=$(cat /proc/sys/kernel/random/uuid) +setsid nohup v8-runner --no-color --log-level debug launch mcp va \ + --mcp-transport ws \ + --manager-url ws://127.0.0.1:4000/sessions \ + --client-uid "$uid" \ + --corr-id "va-$uid" \ + --mcp-log-level debug \ + --mcp-ws-timeout-ms 5000 \ + > "/tmp/va-mcp-$uid.log" 2>&1 & +echo $! +``` + +3. Дождись live-сессии VA manager: + +```json +{"name":"session_list","arguments":{}} +``` + +Критерий готовности: `kind=vanessa_test_client`, `state=active`, `disconnected_secs_ago=null`, `inflight=0`, появились VA-инструменты (`connect_test_client`, `get_form_analysis`). Наличие имени tool только в кешированном `tools/list` не считается готовностью. Нормальное появление сессии и VA-tools после старта занимает 10-90 секунд; опрашивай `session_list` каждые 5-10 секунд и держи диагностический предел 120 секунд. + +4. Подключи тестируемое приложение. Его запускает VA manager по профилю из VAParams; агент не должен отдельно запускать `/TESTCLIENT` для этого VA-пути. `connect_test_client` принимает обязательный аргумент `profileName`: + +```json +{"name":"connect_test_client","arguments":{"profileName":""}} +``` + +Если live-сессий несколько, передавай `session_id` VA manager-сессии в каждый MCP-вызов. Успешный запуск должен дать реальный PID тест-клиента в профиле/логе VA, не `0`. После этого доступны клиентские MCP-методы VA: анализ формы, управление командным интерфейсом и элементами формы, чтение данных, скриншоты и выполнение VA-действий. + +5. После исследования закрой тест-клиент. `close_test_client` можно вызвать с тем же `profileName`; без него tool закрывает текущий подключенный профиль: + +```json +{"name":"close_test_client","arguments":{"profileName":""}} +``` + +Если VA manager запускался только для исследования, останови и его штатным завершением клиента или точечным завершением сохранённого PID. Не оставляй открытые TestClient-процессы перед следующим запуском с тем же фиксированным портом. + ## Опции launch во время тестов Тестовые команды принимают launch-связанные опции, такие как `--client-mode`, `--c`, `--execute`, `--use-privileged-mode` и повторяемый `--raw-key`. @@ -127,7 +178,7 @@ v8-runner syntax edt |------------|----------| | Мониторинг stdout v8-runner | Агент MUST читать stdout v8-runner каждые **20 секунд** пока тест выполняется. Стандартный вывод содержит маркеры успеха и падения сразу (`[diagnostic]`, `[artifact]`, `ERROR: runtime error: test run reported failures` и т.п.) — это надёжнее ЖР. | | Прерывание при ошибке | Если в stdout появилась строка `ERROR:` (например `ERROR: runtime error: test run reported failures`) — агент MUST прервать ожидание, прочитать `runner.log` + `junit/junit.xml` в каталоге прогона и перейти к диагностике. ЖР смотреть дополнительно, если первичных артефактов недостаточно. | -| Детект зависания | Если в stdout v8-runner нет новых строк >60 сек И процесс `1cv8c.*vanessa-automation` ещё жив — агент MUST снять скриншоты (noVNC/X11) и оценить, жив ли тест. | +| Детект зависания | Если в stdout v8-runner нет новых строк >60 сек И процесс `1cv8c.*vanessa-automation` ещё жив — агент MUST проверить процессы manager/test-client и первичные логи запуска, затем перейти к диагностике Vanessa. | | Корректное условие завершения | Условие выхода из ожидания: появился `va-status.log` (создаётся И при success, И при failure) ИЛИ исчез процесс `1cv8c.*vanessa-automation` ИЛИ в stdout появился `ERROR:`. **Не использовать только `va-status.json`** — он создаётся только при штатном завершении сценария; при ранних падениях (ошибка шага, краш клиента) его не будет, и блокирующее ожидание зависнет. | | Обязательный анализ артефактов | После прогона агент MUST проверить `va-status.json` и `vanessa-execution.log` под `workPath/temp//runs//`. | | Обязательный анализ ЖР | После прогона агент MUST проверить `event-log`, если сценарий не прошёл или запуск выглядит подозрительно. | diff --git a/framework/skills/tool-usage/v8-session-manager/SKILL.md b/framework/skills/tool-usage/v8-session-manager/SKILL.md index d068f3ea..904d937a 100644 --- a/framework/skills/tool-usage/v8-session-manager/SKILL.md +++ b/framework/skills/tool-usage/v8-session-manager/SKILL.md @@ -1,6 +1,6 @@ --- name: v8-session-manager -description: "Use for работы с менеджером сессий 1С: запуск, конфигурация, подключение клиентов, чтение session_list, вызов проксированных MCP-tools расширений 1С. Helps при ошибках «no active sessions» / «session_id required» и подключении клиента через mcpMode=ws." +description: "Session manager 1C: запуск, клиенты, session_list, MCP" provides_capabilities: # Встроенные tools менеджера — доступны всегда, пока поднят. - session_list @@ -61,6 +61,38 @@ provides_capabilities: Подробности — `references/sessions-and-tools.md` § «Persistent кеш и `tools_cache_reset`». +## Диагностика UI MCP-сессий + +Для клиентских UI-tools (`open_form`, `click`, `input`, `get_value`, `get_table_rows`, `test_client_start`) сначала докажи, что есть живой 1С-клиент, а не только запись в кешированной витрине. + +Минимальный порядок: + +1. Вызови `session_list`. +2. Найди live-сессию нужной ИБ: `state=active`, `disconnected_secs_ago=null`, `infobase_name=<нужная ИБ>`. +3. Для обычного UI MCP через платформенный тест-клиент нужна управляющая сессия `kind=1c-client`; для Vanessa нужны `kind=vanessa_test_client` и VA-tools сверх базового набора. +4. Если live-сессий несколько, всегда передавай `session_id` в каждый proxied tool call. +5. Перед длинным UI-сценарием проверь простой вызов (`infobase_info`) и `inflight=0`. + +Для UI/UX-приёмки 1C-форм основной визуальный путь описан в `va-visual-check`. Базовая цепочка через Vanessa/TestClient: + +1. Убедись по `session_list`, что VA manager живой: `kind=vanessa_test_client`, `state=active`, `tools` содержит VA-инструменты, `inflight=0`. +2. Запусти или подключи тест-клиент через VA tool `connect_test_client` с нужным профилем. +3. Проверь, что VA вернула реальный PID тест-клиента, а не `0`/пусто. +4. Получи окна через `get_window_list_os`. +5. Сними PNG через `get_window_screenshot_os`; Linux/Xvfb-рецепт для чёрного PNG и fallback-условия см. в `va-visual-check`. +6. Проверь, что PNG не пустой и не одноцветный/чёрный. + +`tools/list` не доказывает готовность этой цепочки: список может быть из persistent cache. Доказательство — live-сессия + успешный smoke `connect_test_client -> get_window_list_os -> get_window_screenshot_os`. + +Если proxied вызов зависает или `inflight` остаётся больше нуля: + +- для формы тест-клиента сначала применяй `va-visual-check`; если нужен fallback, фиксируй выполненные VA-шаги, причину и остаточный риск; +- проверь `/tmp/mcp-client.log` или проектный лог client_mcp: пришёл ли `MCP_TOOL_CALL`, зарегистрировалась ли WS-сессия, нет ли ошибки платформенного типа; +- не сбрасывай `tools_cache_reset` как первое действие: кеш не блокирует live-вызовы и не лечит зависший клиент; +- если клиент запущен неправильным режимом, заверши только свой сохранённый PID и перезапусти его правильной командой через `v8-runner`. + +Для цепочки запуска `1c-client` + `/TESTMANAGER` + отдельный `/TESTCLIENT` см. навык `v8-runner`, раздел «UI MCP через платформенный тест-клиент». + ## Границы Менеджер **не**: diff --git a/framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md b/framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md new file mode 100644 index 00000000..530567cf --- /dev/null +++ b/framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md @@ -0,0 +1,102 @@ +--- +name: va-visual-check +description: "Vanessa/VA MCP: визуальная проверка форм 1С и скриншоты" +--- + +# VA Visual Check + +Используй этот навык для визуальной проверки 1С-форм через Vanessa Automation / TestClient и VA MCP. Это профильный маршрут для UI/UX-скриншотов управляемых форм 1С. + +## Основной маршрут + +1. Если VA MCP manager-сессия ещё не поднята, подними её строго по навыку `v8-runner`; здесь проверяй только live-сессию `kind=vanessa_test_client` в `session_list`. +2. Подключи тест-клиент через `connect_test_client` с профилем из настроек VA, не угадывай имя профиля. +3. Убедись, что подключён реальный test-client: профиль/лог/состояние VA содержит PID, не `0`. +4. Открой нужную форму через VA/TestClient tools. +5. Получи структурное состояние формы (`get_form_analysis`, `get_window_list_testclient`, чтение элементов/таблиц). +6. Получи список OS-окон через `get_window_list_os`. +7. Критично: операции снятия скриншотов через VA MCP выполняй строго синхронно. Не запускай несколько `get_window_screenshot_os` параллельно и не используй для них `multi_tool_use.parallel`: отправь один запрос, дождись полного ответа и убедись через `session_list`, что сессия жива и `inflight=0`; только после этого отправляй следующий запрос. +8. Сними PNG через `get_window_screenshot_os`: + +```text +get_window_screenshot_os { + "window_title": "<точный заголовок окна формы>", + "file_name": "<путь>.png", + "color_mode": "color" +} +``` + +9. Проверь PNG: файл создан, размер ожидаемый, изображение не пустое, не одноцветное и не чёрное. + +## Linux headless X11/Xvfb без window-manager + +Этот рецепт применим только для Linux на виртуальном X11/Xvfb-дисплее без графического окружения/window-manager. Он нужен, когда `get_window_list_os` видит окно формы, но `get_window_screenshot_os` возвращает чёрный или почти пустой PNG. + +X11-команды используются только для экспонирования уже открытого окна. Приоритетный скриншот после этого всё равно делается через VA MCP. + +1. Найди X11 id окна формы: + +```bash +xwininfo -root -tree | sed -n '1,220p' +``` + +Если `wmctrl -l` или другие EWMH-инструменты отвечают `Cannot get client list properties` / `_NET_CLIENT_LIST or _WIN_CLIENT_LIST`, это ожидаемо для Xvfb без window-manager. Используй дерево `xwininfo`, а не список клиента window-manager. + +2. Проверь, что найденное окно принадлежит test-client, а не VA manager: + +```bash +xprop -id _NET_WM_PID WM_NAME WM_CLASS +``` + +`_NET_WM_PID` должен совпадать с PID подключённого test-client. Если PID ещё не зафиксирован, получи его из VA-профиля/состояния подключения; заголовок окна используй только как дополнительный фильтр. + +3. Перемести, увеличь и подними окно: + +```bash +xdotool windowmove 0 0 || true +xdotool windowsize 1200 800 || true +xdotool windowraise || true +xdotool windowactivate --sync || true +xwininfo -id | sed -n '1,60p' +``` + +В среде без window-manager `windowactivate` может упасть с сообщением про `_NET_ACTIVE_WINDOW`; это не blocker, если `xwininfo` показывает `Map State: IsViewable`. + +4. Повтори штатный VA-снимок через `get_window_screenshot_os`. + +5. Повтори проверку PNG. Если снимок всё ещё чёрный/одноцветный, переходи к fallback-решению ниже и явно зафиксируй причину. + +## Browser fallback + +VA MCP — предпочтительный маршрут для обычных форм 1С, потому что он работает с реальным TestClient и даёт одновременно структуру формы и визуальный PNG. + +Web/browser fallback допустим, когда: + +- VA MCP недоступен или не проходит readiness; +- `connect_test_client` не даёт реальный PID; +- `get_window_list_os` не видит нужное окно; +- `get_window_screenshot_os` остаётся чёрным/одноцветным после Linux/Xvfb-рецепта; +- проверяемое поведение относится к браузерному слою: DOM/CSS/HTML, console/network, web-auth/publication, viewport/pixel rendering, browser extension, browser-only upload/download/clipboard. + +Перед fallback зафиксируй: + +- какая VA capability не сработала; +- какие шаги VA-маршрута уже выполнены; +- почему browser/web-client даст достаточный сигнал для текущей задачи; +- остаточный риск: web-client может отличаться от тонкого/толстого клиента 1С. + +Для browser fallback используй профильные browser-навыки (`web-test-1c`, `playwright`, `screenshot`) по их назначению. Не смешивай результат: если артефакт получен через web/browser fallback, так и называй его в отчёте. + +## Что не делать + +- Не заменяй VA MCP скриншот прямым X11/noVNC/OS-снимком без явной fallback-записи. +- Не выбирай окно только по заголовку в Xvfb: VA manager и test-client могут иметь одинаковые заголовки. +- Не считай `get_window_list_testclient` визуальным подтверждением: это структура внутренних окон, не PNG. +- Не продолжай по cached `tools/list`: нужна live-сессия нужного `kind`. + +--- +depends_on: + - framework/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md + - framework/skills/tool-usage/v8-session-manager/SKILL.md + - framework/skills/bsl-practices/form-visual-requirements/SKILL.md +--- diff --git a/framework/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md b/framework/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md index c21fc33f..9da21b82 100644 --- a/framework/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md +++ b/framework/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md @@ -1,6 +1,6 @@ --- name: vanessa-authoring -description: "Use for создания и доработки feature-сценариев Vanessa Automation по реальным требованиям проекта." +description: "Vanessa: написание и уточнение feature-сценариев" uses_capabilities: - run_vanessa - build_project @@ -13,7 +13,7 @@ uses_capabilities: 1. Определи источник требования — спецификация или бизнес-кейс (`vanessa-scenario-policy`). 2. Определи **под каким пользователем** выполняется сценарий (см. «Пользовательский контекст»). 3. Найди подходящие шаги: сначала в библиотеке Vanessa, затем в сценариях проекта. -4. **Исследуй интерфейс и заполни форму вручную**. Предпочтительный путь — MCP-инструменты Vanessa Automation через `v8-client-session-manager` (см. «MCP-исследование через Vanessa Automation»). Если они недоступны, используй веб-клиент (`gui-control` / `screenshot` / `chrome-devtools`-snapshot). В обоих случаях зафиксируй точные имена и заголовки элементов, поля, кнопки, закладки **до** ссылок на них в шагах; не угадывай идентификаторы (заголовок Title vs имя name — см. `vanessa-scenario-policy`). +4. **Исследуй интерфейс и заполни форму вручную**. Предпочтительный путь — MCP-инструменты Vanessa Automation через `v8-client-session-manager` (см. «MCP-исследование через Vanessa Automation»). Для UI/UX-контроля формы применяй `va-visual-check`: VA MCP screenshot route, Linux/Xvfb рецепт и browser fallback с фиксацией причины. В любом варианте зафиксируй точные имена и заголовки элементов, поля, кнопки, закладки **до** ссылок на них в шагах; не угадывай идентификаторы (заголовок Title vs имя name — см. `vanessa-scenario-policy`). 5. Напиши один smoke-сценарий: открыть → одно действие → одно наблюдаемое следствие. 6. Если шага нет — пометь `# unknown_step_candidate`, не изобретай BSL-шаг. 7. Передай сценарий на прогон через `v8-runner` (`v8-runner test va`). @@ -28,21 +28,23 @@ uses_capabilities: ### Проверка версии и готовности -1. Запусти VA manager-сессию через `v8-runner launch mcp va --mcp-transport ws ...` (детальная строка — в навыке `v8-runner`, раздел «Vanessa Automation MCP через session-manager»). +1. Если VA manager-сессия ещё не поднята, запусти её строго по навыку `v8-runner` (раздел «Vanessa Automation MCP через session-manager»); не собирай строку запуска в этом навыке. 2. Через `session_list` дождись live-сессии `kind=vanessa_test_client`, где появились VA-tools: например `get_VanessaAutomation_state`, `connect_test_client`, `get_form_analysis`, `manage_command_interface`. 3. Вызови `get_environment_data` или ближайший доступный VA-инструмент окружения и зафиксируй версию Vanessa Automation в контексте задачи. 4. Если нужны служебные data-tools (`get_table_data`, `get_object_attributes`), проверь, что служебное расширение VA загружено в тестируемую ИБ. Наличие свежих файлов расширения в source недостаточно: runtime-инструменты ищут формы в подключенной базе. ### Обязательная последовательность работы -1. **Подключить тест-клиент.** Перед любыми инструментами, которые читают/управляют интерфейсом тестируемого приложения, вызови `connect_test_client` с профилем тест-клиента. Профиль выбирай из настроек VA/таблицы профилей, не угадывай имя. +1. **Подключить тест-клиент.** Перед любыми инструментами, которые читают/управляют интерфейсом тестируемого приложения, вызови `connect_test_client` с профилем тест-клиента. Профиль выбирай из настроек VA/таблицы профилей `ДанныеКлиентовТестирования` в VAParams, не угадывай имя. Как формировать `tools.va` / `tests.va` в `v8project.yaml` и профиль TestClient внутри VAParams — см. `v8-runner`, `references/config-and-backends.md`. 2. **Исследовать форму через VA-tools.** Используй live-схемы tools и их описания из `session_list` / `tools/list`, потому что набор инструментов расширяется между версиями VA. Не фиксируй закрытый список как полный. На момент VA `1.2.043.28` основные классы инструментов: командный интерфейс, список окон, данные активного окна, анализ формы, действия с элементами формы, чтение реквизитов объекта, чтение таблиц/данных, скриншоты, запись действий пользователя, выполнение шагов `.feature`. -3. **Не записывать данные без цели теста.** Для исследования заполнения формы можно открыть форму создания, читать реквизиты и пробовать навигацию; запись/проведение выполняй только если это нужно для проверки заполнения или сценария, и соблюдай правила изоляции тестовых данных. -4. **Закрыть тест-клиент.** После исследования, прогона или ошибки обязательно вызови `close_test_client` для подключенного профиля. Если VA manager-сессия запускалась вручную для исследования, после завершения работы останови и её. +3. **Снять визуальный контрольный скриншот.** Для любой UI/UX-проверки после открытия нужной формы применяй `va-visual-check`: сначала VA MCP PNG, затем при необходимости Linux/Xvfb рецепт или browser fallback с фиксацией причины. +4. **Не записывать данные без цели теста.** Для исследования заполнения формы можно открыть форму создания, читать реквизиты и пробовать навигацию; запись/проведение выполняй только если это нужно для проверки заполнения или сценария, и соблюдай правила изоляции тестовых данных. +5. **Закрыть тест-клиент.** После исследования, прогона или ошибки обязательно вызови `close_test_client` для подключенного профиля. Если VA manager-сессия запускалась вручную для исследования, после завершения работы останови и её. Антипаттерны: - вызывать `get_form_analysis`, `manage_command_interface`, `manage_form_elements`, `get_object_attributes`, screenshot/recording-инструменты до `connect_test_client`; +- считать внутренний список окон `get_window_list_testclient` визуальным скриншотом: он нужен для структуры и навигации, а UI/UX-приёмка требует PNG по правилам `va-visual-check`; - считать наличие имени tool в кешированном `tools/list` доказательством доступности — проверяй live-сессию нужного `kind`; - держать тест-клиент открытым после завершения операции; - править vendor-код VA/VAExtension, когда проблема в версии, загрузке расширения или настройке запуска. @@ -53,18 +55,19 @@ uses_capabilities: 1. Открой раздел/команду через `manage_command_interface` или прямую навигацию. 2. Получи `get_active_window_data` и `get_form_analysis`. -3. Для формы объекта получи `get_object_attributes` в режимах реквизитов шапки и табличных частей. -4. При необходимости получи справочные данные через `get_table_data`, чтобы выбирать существующие валидные значения. -5. По результатам зафиксируй точные команды, имена элементов, обязательные поля, условную видимость/доступность и порядок заполнения в контексте сценария. -6. Только после этого пиши Gherkin-шаги и подсценарии. +3. Сделай визуальный PNG формы по `va-visual-check` и проверь его по `form-visual-requirements`. +4. Для формы объекта получи `get_object_attributes` в режимах реквизитов шапки и табличных частей. +5. При необходимости получи справочные данные через `get_table_data`, чтобы выбирать существующие валидные значения. +6. По результатам зафиксируй точные команды, имена элементов, обязательные поля, условную видимость/доступность, визуальные замечания и порядок заполнения в контексте сценария. +7. Только после этого пиши Gherkin-шаги и подсценарии. ## Ручное заполнение формы перед сценарием (MUST) -> Перед написанием НОВОГО сценария по документу агент сначала заполняет форму **вручную в веб-клиенте**, сверяясь с реальным составом формы на каждом шаге. `.feature` пишется только ПОСЛЕ успешного ручного заполнения. +> Перед написанием НОВОГО сценария по документу агент сначала заполняет форму **через Vanessa/TestClient**, сверяясь с реальным составом формы на каждом шаге. Платформенный TestClient MCP допустим только для действия, которого VA MCP принципиально не предоставляет, с записью причины в контекст. `.feature` пишется только ПОСЛЕ успешного заполнения через VA/TestClient. Web-клиент допустим только для браузерных функций, которых VA MCP принципиально не поддерживает. | Требование | Описание | |-----------|----------| -| Снимок после каждого поля | После изменения **каждого** поля заново снимать состав формы (`take_snapshot` / `screenshot`): значение поля меняет видимость, доступность и **обязательность** других полей (обработчики `ПриИзменении`). Полный набор обязательных полей выясняется **итеративно**, не угадывается заранее | +| Снимок после каждого поля | После изменения **каждого** поля заново снимать состав формы (`get_form_analysis`, `get_active_window_data`, чтение элемента/таблицы): значение поля меняет видимость, доступность и **обязательность** других полей (обработчики `ПриИзменении`). Визуальный PNG делай по `va-visual-check` на ключевых состояниях формы и обязательно для итоговой UI/UX-приёмки. Полный набор обязательных полей выясняется **итеративно**, не угадывается заранее | | Изучить Подсказку и справочные данные | До заполнения прочитать Help/подсказку документа и справочные данные — понять сценарии работы и порядок заполнения. Могут быть пусты, но у типовых объектов часто заполнены | | Все ключевые поля шапки | Заполнять по смысловой оценке назначения документа (Организация, Контрагент, Соглашение, Склад и т.п. — то, что требует смысл документа) | | Обязательные табличные части | Заполнять обязательные ТЧ (обычно товары / по смыслу документа) **хотя бы несколькими строками**; проверять, что все поля строк заполнены | diff --git a/framework/skills/tool-usage/vanessa/vanessa-authoring/references/learned-patterns.md b/framework/skills/tool-usage/vanessa/vanessa-authoring/references/learned-patterns.md index e3c57690..0f84f4c0 100644 --- a/framework/skills/tool-usage/vanessa/vanessa-authoring/references/learned-patterns.md +++ b/framework/skills/tool-usage/vanessa/vanessa-authoring/references/learned-patterns.md @@ -15,7 +15,7 @@ status: confirmed шаги: | 1. Открыть форму документа 2. Визуально определить обязательные поля (красная пунктирная линия под полем) - или использовать screenshot + visual-check + или использовать `va-visual-check` 3. Заполнить ВСЕ обязательные поля 4. Только после этого выполнять «Записать» / «Провести» источник: универсальное поведение платформы 1С:Предприятие @@ -76,7 +76,7 @@ status: confirmed (запись/проведение); ложная тревога на информационное сообщение — трата времени шаги: | 1. После действия на форме (заполнение, запись, проведение) — проверить область - сообщений в нижней части экрана (screenshot / visual-check) + сообщений в нижней части экрана по `va-visual-check` 2. Если сообщение похоже на ошибку, но смысл неясен — искать текст в коде: a) Модуль формы документа b) Модуль объекта @@ -120,7 +120,8 @@ status: confirmed область: RadioButtonField с RadioButtonType=Tumbler приём: Tumbler в DOM =
, НЕ кнопка. Стандартные шаги Vanessa НЕ работают. Обходные пути: (1) если значение по умолчанию подходит — пропустить шаг; - (2) если нужно переключить — написать кастомный шаг или кликнуть через Playwright по + (2) если нужно переключить — сделать DOM-анализ через web-test как исключение и затем написать кастомный Vanessa/TestClient-шаг; + прямой клик Playwright допустим только для одноразовой диагностики, не как основной сценарий антиприём: НЕ использовать: "я меняю значение переключателя" (ВыбратьВариант error), "из выпадающего списка" (ОткрытьВыпадающийСписок error), "я ввожу текст" (ВвестиТекст error), @@ -131,7 +132,7 @@ status: confirmed шаги: | 1. Проверить, не установлено ли нужное значение по умолчанию (Form.xml или Module.bsl) 2. Проверить, не устанавливается ли значение автоматически другим полем (напр. портфелем) - 3. Если нужно переключить — DOM-анализ через web-test, затем кастомный шаг + 3. Если нужно переключить — DOM-анализ через web-test как браузерное исключение, затем кастомный Vanessa/TestClient-шаг источник: task-103 GBIG PAM, 12 итераций Vanessa-сценариев (2026-03-24) ``` diff --git a/framework/skills/tool-usage/vanessa/vanessa-diagnostics/SKILL.md b/framework/skills/tool-usage/vanessa/vanessa-diagnostics/SKILL.md index b1bbc46b..9f896e73 100644 --- a/framework/skills/tool-usage/vanessa/vanessa-diagnostics/SKILL.md +++ b/framework/skills/tool-usage/vanessa/vanessa-diagnostics/SKILL.md @@ -1,6 +1,6 @@ --- name: vanessa-diagnostics -description: "MUST use WHEN feature-сценарий не прошёл, артефакты не создались или нужно классифицировать сбой после запуска. Provides алгоритм разбора артефактов прогона и классификации типа ошибки." +description: "Vanessa diagnostics: падения, артефакты и причины" --- # Диагностика Vanessa Automation @@ -39,7 +39,7 @@ description: "MUST use WHEN feature-сценарий не прошёл, арте | `va-status.json` не создан | Считать запуск аварийным, идти в диагностику | | `va-status.json != 0` | Читать артефакты и классифицировать падение | | `vanessa-execution.log` содержит ошибку | Определить класс ошибки | -| Подозрение на блокировку GUI | Визуальная диагностика | +| Подозрение на блокировку GUI | Визуальная диагностика по `va-visual-check`: сначала VA MCP-скриншот, при необходимости fallback с фиксацией причины | | Прогон «зелёный», но 0 шагов выполнено / шаги `undefined`/`skipped` | Ложный успех — классифицировать как `step_resolution_error`/`scenario_error` | --- @@ -49,14 +49,15 @@ description: "MUST use WHEN feature-сценарий не прошёл, арте 1. Проверить `va-status.json`. 2. Проверить `vanessa-execution.log`. 3. Проверить `event-log`: сначала последние `Error`; если пусто — без фильтра уровня. -4. Если сигнал на модальное окно / security warning — `gui-control` / `screenshot`. -5. Только если недостаточно — `tech-log-analysis`. +4. Если нужно увидеть состояние формы тест-клиента — применяй `va-visual-check`: VA MCP-скриншот, проверка PNG, затем fallback при необходимости. +5. Если сигнал на модальное окно / security warning / manager window, визуальный артефакт также получай по `va-visual-check`. +6. Только если недостаточно — `tech-log-analysis`. ### Special-case: `Предупреждение безопасности` Если в `event-log` запись о `Предупреждение безопасности` для `bddRunner.epf` или плагинов: 1. Считать триггером на визуальную проверку. -2. Открыть реальный экран через noVNC или снять скриншот (не полагаться на заголовки X11-окон). +2. Снять реальный экран по `va-visual-check`, не полагаясь только на заголовки X11-окон. 3. Только после визуального подтверждения трактовать повторный запуск. --- diff --git a/framework/subagents/analyst.md b/framework/subagents/analyst.md index 4d2afeea..330047c9 100644 --- a/framework/subagents/analyst.md +++ b/framework/subagents/analyst.md @@ -34,9 +34,14 @@ skills: 4. **Identify blockers** — ВСЕ вопросы одним списком, НЕ по одному 5. **Save context** → если blockers: `clarification_needed`, НЕ писать частичную спеку 6. **Write specification** — context, decision, assumptions, acceptance criteria, test plan -7. **Write Acceptance Scenarios** — Gherkin бизнес-уровня для MUST; НЕ шаги Vanessa -8. **Self-review** по чек-листу `spec-standard` -9. **Update context** → `completed` +7. **Coverage by runtime layer** — для каждого MUST явно указать затронутый runtime-слой и тип проверки: + - серверная логика/серверный контекст → YaxUnit; если тест уже есть — актуализировать и перепрогнать, если нет — создать; + - UI/клиентский контекст → сценарный UI/BDD-тест, открывающий пользовательский entrypoint и выполняющий изменённое действие; + - связанный пользовательский процесс → end-to-end сценарий процесса с переиспользованием/актуализацией существующего сценария; + - интеграция/фоновые задания → integration/job-проверка с наблюдаемым эффектом. +8. **Write Acceptance Scenarios** — Gherkin бизнес-уровня для MUST; НЕ шаги Vanessa +9. **Self-review** по чек-листу `spec-standard` +10. **Update context** → `completed` **Когда спрашивать:** diff --git a/framework/subagents/tester.md b/framework/subagents/tester.md index 2cbc7592..4f1dfb63 100644 --- a/framework/subagents/tester.md +++ b/framework/subagents/tester.md @@ -10,7 +10,7 @@ skills: - test-writing - coding-standards - error-handling - - visual-check + - va-visual-check - event-log-analysis - gui-control - screenshot @@ -43,11 +43,13 @@ skills: **Протокол:** 1. **Check context** — прочитай `tester-context.md`; добавь `Planned Skills & Rules` 2. **Read test plan** — сценарии и критерии -3. **Analyze existing tests** — что покрыли Phase 3b и Phase 3a -4. **Write missing tests** — edge-cases, негативы, интеграция, регрессия -5. **Syntax check** → **Build** (если кодовая база менялась) → **Run all tests** -6. **If unclear status** (hang/interactive error): `event-log-analysis` от `test_start_time` → `gui-control` → повторная проверка -7. **Протокол отладки при падении теста:** +3. **Check coverage matrix** — для каждого MUST сверить затронутый runtime-слой и обязательный тип теста: + server/server-context → YaxUnit; UI/client-context → сценарный UI/BDD; связанный процесс → end-to-end; integration/background → integration/job. +4. **Analyze existing tests** — что покрыли Phase 3b и Phase 3a, какие существующие тесты должны быть актуализированы и перепрогнаны +5. **Write missing tests** — edge-cases, негативы, интеграция, регрессия; если серверная логика изменена и YaxUnit-теста нет — создать; если UI/client изменён и сценария нет — указать на недостающий сценарий или создать его в рамках полномочий +6. **Syntax check** → **Build** (если кодовая база менялась) → **Run all tests** +7. **If unclear status** (hang/interactive error): `event-log-analysis` от `test_start_time` → `gui-control` → повторная проверка +8. **Протокол отладки при падении теста:** **7a. BDD-сценарий (Vanessa) не прошёл:** 1. Проверить: сценарий соответствует спецификации и бизнес-задаче? @@ -79,11 +81,12 @@ skills: **При СТОП по неочевидному runtime-дефекту** — завести `bug-report.json` через навык `bug-reporting` в `task_dir/.context/bugs/.json`. Tester видит сценарий end-to-end и обязан заполнить максимум — особенно полную секцию `scenario_context` (action, user, input_data с реквизитами документа/обработки, system_state) и `debug_trigger` (как Debugger должен запустить unit/Vanessa/UI-действие после установки breakpoint или trace). Текущая классификация (`test_error` / `implementation_error` / `spec_mismatch`) перекладывается в `hypotheses[].layer` с обоснованием в `reasoning`. Все 3 попытки фиксируются в `self_fix_attempts`. -8. **Save context** → `completed` + сводка; **Save test-report** +9. **Save context** → `completed` + сводка; **Save test-report** **Exit criteria (status `completed`):** - Все unit-тесты задачи Green (`run_all_tests` exit 0, никаких failed). - Все task scenarios `v8-runner test va` Green: `va-status.json = 0`, нет skipped/missing шагов, количество выполненных шагов > 0 (см. `vanessa-run-loop` правило). +- Матрица покрытия Test Plan закрыта по runtime-слоям: server/server-context требования покрыты YaxUnit, UI/client-context требования покрыты сценарным UI/BDD, связанные процессы покрыты end-to-end сценариями. Непокрытый слой = `implementation_error`/`spec_mismatch` или blocker, но не `completed`. - Если scenarios красные из-за production-кода → `implementation_error` → STOP, return Developer-Code (orchestrator routes). - Если scenarios красные из-за нерезолвящихся шагов (`unknown_step_candidate`) → STOP с указанием на Phase 3c (Scenario-Coder). - Если scenarios красные из-за тестовых данных (несуществующие пользователи / отсутствующие предусловия) → STOP с указанием на data-prep (или эскалация пользователю). @@ -123,7 +126,7 @@ depends_on: - framework/skills/bsl-practices/error-handling/SKILL.md - framework/skills/bsl-practices/test-writing/SKILL.md - framework/skills/tool-usage/v8-runner/SKILL.md - - framework/skills/tool-usage/browser-ui/visual-check/SKILL.md + - framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md - framework/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md - framework/skills/tool-usage/browser-ui/gui-control/SKILL.md - framework/skills/tool-usage/browser-ui/screenshot/SKILL.md diff --git a/framework/workflows/full-cycle/SKILL.md b/framework/workflows/full-cycle/SKILL.md index c7c7d5b9..1d1a43ea 100644 --- a/framework/workflows/full-cycle/SKILL.md +++ b/framework/workflows/full-cycle/SKILL.md @@ -1,6 +1,6 @@ --- name: full-cycle -description: Полный цикл разработки с обязательным кросс-ревью на каждой фазе. +description: "Для средних и сложных задач вести полный цикл с ревью" --- # Воркфлоу: Полный цикл разработки (Full Cycle) @@ -25,6 +25,12 @@ Explorer исследует кодовую базу → модули, графы Вход: задача + `explorer-context.md`. Analyst создаёт спеку MADR 4.0 + RFC 2119. Ревью Reviewer (Premium). Макс. 3 итерации BLOCK. Ревью + cross-provider-review + **STOP: ждём ОК пользователя**. +В Test Plan Analyst ОБЯЗАН разнести требования по runtime-слоям и назначить обязательный тип +проверки: серверная логика/серверный контекст → YaxUnit; UI/клиентский контекст → сценарный +UI/BDD-тест; связанный пользовательский процесс → end-to-end сценарий процесса; интеграция/фоновые +задания → integration/job-проверка. Для существующего покрытия план должен явно сказать, какой тест +актуализируется и перепрогоняется; если покрытия нет — какой тест создаётся. + Approval gate Phase 1 нужен, потому что спецификация фиксирует бизнес-решения (уровни RFC 2119, границы scope, выбор между альтернативами), которые пользователь ОБЯЗАН подтвердить ДО того, как Architect потратит ресурс на дизайн, опирающийся на возможно неверный контракт. Пропуск этого gate исторически приводил к множественным итерациям: cross-provider-review или Architect находили противоречия в спеке, которые можно было устранить одним уточнением у пользователя на этой стадии. ### Phase 2: Архитектура (Architect → High/Premium) @@ -36,17 +42,20 @@ Approval gate Phase 1 нужен, потому что спецификация Фазы 3a–3d идут строго последовательно. Каждая следующая начинается только после ревью предыдущей (и cross-provider-review в advisory). - **3a (Scenario-Author → Mid):** перед написанием новых UI/форменных сценариев проводит исследование формы через Vanessa MCP workflow (`vanessa-authoring`: запуск VA manager → `connect_test_client` → VA-tools → `close_test_client`) и фиксирует точные команды/элементы/обязательные поля в своём контексте. Затем intent-сценарии спеки → `.feature` Vanessa с пометкой `# unknown_step_candidate` для не найденных шагов. Ревью (scope=bdd). -- **3b (Developer-Tests → Mid/High):** MUST-сценарии Test Plan → unit/интеграционные тесты (Red). Ревью (scope=tests). +- **3b (Developer-Tests → Mid/High):** MUST-сценарии Test Plan, относящиеся к серверной логике/серверному контексту, → YaxUnit unit/интеграционные тесты (Red). Если серверный метод изменён и тест уже есть — актуализирует и перепрогоняет его; если теста нет — создаёт. Ревью (scope=tests). - **3c (Scenario-Coder → Mid):** делает `.feature` 3a исполняемыми — подбирает/реализует шаги Vanessa (`@exportscenarios` или, как escape hatch, BSL-шаги в `vanessa-tests/support/`), заменяет `unknown_step_candidate`. Если шаг зависит от реального UI-состояния, проверяет его через Vanessa MCP workflow и закрывает тест-клиент после проверки. Red-гейт: `v8-runner test va` на сценариях задачи показывает падение на отсутствующей прод-логике, не на неизвестных шагах. Ревью (scope=bdd-steps). - **3d (Developer-Code → High):** вход — всё из Phase 2 + тесты 3b + Red-executable `.feature` 3a/3c. Пишет код (Green для unit-тестов Phase 3b И сценариев 3a). При `test_failure` + `suspected_test_error` → Reviewer-арбитраж → маршрутизация (в 3b если юнит-тест, в 3c если шаг, иначе в 3d). **Зачем разделены 3a и 3c.** Scenario-Author отвечает за **что** должно произойти (бизнес-намерение, читаемый Gherkin). Scenario-Coder отвечает за **как** это выражено в шагах Vanessa (техническая реализация step-library, переиспользование). Раньше эту работу никто явно не делал — шаги либо висели `TODO`, либо доделывались Developer-Code с размытием Green-гейта. Разделение ролей даёт: (а) чистый Red-гейт на уровне сценариев до написания прод-кода, (б) ответственного за качество и переиспользование step-library, (в) возможность параметризовать шаги по функциональности предметной области, а не по задаче. -**Место vendor workflow Vanessa MCP.** Исследовательский MCP workflow не заменяет Red/Green-гейты и не является отдельной фазой full-cycle. Он является обязательной техникой внутри 3a/3c для UI/форменных сценариев: сначала получить runtime-карту формы и справочных данных через live VA-tools, затем писать или чинить Gherkin. Если `v8-client-session-manager` или VA MCP недоступны, это фиксируется как диагностический blocker/escape hatch, после чего допускается ручное исследование через веб-клиент с теми же артефактами в контексте. +**Место vendor workflow Vanessa MCP.** Исследовательский MCP workflow не заменяет Red/Green-гейты и не является отдельной фазой full-cycle. Он является обязательной техникой внутри 3a/3c для UI/форменных сценариев: сначала получить runtime-карту формы и справочных данных через live VA-tools, затем писать или чинить Gherkin. Для визуальных артефактов применяется `va-visual-check`: VA MCP — предпочтительный маршрут, browser/web fallback допустим после фиксации выполненных VA-шагов, причины и остаточного риска. ### Phase 4: Покрытие и регрессия (Tester → Mid/High) -Tester запускает все тесты, дописывает edge-cases, интеграционные, регрессионные. Ревью (High). Phase 4 НЕ дублирует Phase 3. +Tester запускает все тесты, дописывает edge-cases, интеграционные, регрессионные. Перед закрытием +Phase 4 он проверяет матрицу покрытия из Test Plan: каждый server/server-context MUST закрыт +YaxUnit, каждый UI/client-context MUST закрыт сценарным UI/BDD-тестом, каждый связанный процесс — +end-to-end сценарием. Ревью (High). Phase 4 НЕ дублирует Phase 3. --- @@ -79,7 +88,7 @@ Tester запускает все тесты, дописывает edge-cases, и | Сценарий Phase 3c зелёный до прод-кода | Признак мока в шаге → Scenario-Coder удаляет мок, перезапускает Red-гейт | | `test_failure` в Phase 4 | Tester: свой тест → исправить; баг в коде → `implementation_error` → Developer | | `check_syntax` падение | Developer исправляет до ревью | -| MCP недоступен | Escape hatch → эскалация | +| MCP/VA недоступен для UI-задачи | Применить fallback-правила `va-visual-check`; если fallback не даёт достаточного сигнала — blocker → эскалация | --- depends_on: diff --git a/framework/workflows/orchestrator/SKILL.md b/framework/workflows/orchestrator/SKILL.md index a5327ae2..ac312ff2 100644 --- a/framework/workflows/orchestrator/SKILL.md +++ b/framework/workflows/orchestrator/SKILL.md @@ -1,10 +1,6 @@ --- name: orchestrator -description: > - Указатель на манинг оркестрации. После ретиринга (манифест §6, §7.2) операционный манинг - оркестратора (Слой 1 — Lead/диспетчер, Слой 2 — дисциплина) переехал в ПРОФИЛЬ главного потока - framework/subagents/orchestrator.md. Детальная фазовая механика (Слой 3) — framework/workflows/full-cycle/SKILL.md. - Этот файл сохранён как стабильная точка входа и носитель ссылок depends_on; он НЕ дублирует тело манинга. +description: "Оркестратор: маршрутизация работы и фаз агентов" --- # Оркестратор: мета-воркфлоу (указатель) diff --git a/framework/workflows/quick-fix/SKILL.md b/framework/workflows/quick-fix/SKILL.md index 0eb3ee35..d8a56334 100644 --- a/framework/workflows/quick-fix/SKILL.md +++ b/framework/workflows/quick-fix/SKILL.md @@ -1,8 +1,6 @@ --- name: quick-fix -description: > - Редирект. quick-fix перенесён в навык — используй Skill-тул или читай напрямую: - framework/skills/agent-process/quick-fix/SKILL.md +description: "Для малых безопасных правок применять quick-fix" alwaysApply: false --- diff --git a/framework/workflows/source-of-truth-policy/SKILL.md b/framework/workflows/source-of-truth-policy/SKILL.md index d79ba92d..1c1784ce 100644 --- a/framework/workflows/source-of-truth-policy/SKILL.md +++ b/framework/workflows/source-of-truth-policy/SKILL.md @@ -1,6 +1,6 @@ --- name: source-of-truth-policy -description: Указатель-редирект. Always-on триггер переехал в framework/rules/source-of-truth/SKILL.md, метод — в навык source-of-truth. +description: "Redirect: использовать source-of-truth rule и skill" alwaysApply: false --- # Политика источников правды — указатель diff --git a/framework_eng/rules/agent-context-protocol/SKILL.md b/framework_eng/rules/agent-context-protocol/SKILL.md index ef260dae..afecbfb4 100644 --- a/framework_eng/rules/agent-context-protocol/SKILL.md +++ b/framework_eng/rules/agent-context-protocol/SKILL.md @@ -1,18 +1,18 @@ --- name: agent-context-protocol -description: Agent startup -> read {role}-context.md; exit -> write it. Procedure and structure are in the agent-context skill. +description: "On agent start/exit, read and write role context" alwaysApply: true --- # Agent Context Protocol -> **Trigger:** start of any agent (orchestrator or subagent) and any of its terminations (`completed`, `clarification_needed`, `implementation_error`). When triggered, apply the `agent-context` skill (`framework/skills/agent-process/agent-context/SKILL.md`): location of `.context/`, file structure, role name table, resume mechanism, saving context through delegation. +> **Trigger:** the start of any agent (orchestrator or subagent) and any of its termination states (`completed`, `clarification_needed`, `implementation_error`). When triggered, apply the `agent-context` skill (`framework/skills/agent-process/agent-context/SKILL.md`): `.context/` location, file structure, role-name table, resume mechanism, and context savings through delegation. ## Invariant (always) -- Every agent - **both the orchestrator and the subagents** - MUST as the **first step** read `task_dir/.context/{role}-context.md` (if present) and continue without repeating completed steps. +- Every agent - **both orchestrator and subagents** - MUST as the **first step** read `task_dir/.context/{role}-context.md` (if present) and continue without repeating completed steps. - Every agent MUST write `task_dir/.context/{role}-context.md` **before any termination**. No write = agent error. -- File by role: orchestrator - `orchestrator-context.md`, subagent - `{role}-context.md`; stored in `task_dir/.context/`. -- All task artifacts (contexts, spec, design, reports, comments `.feature`) are in **Russian**; code identifiers stay as-is. +- Role files: orchestrator - `orchestrator-context.md`, subagent - `{role}-context.md`; stored in `task_dir/.context/`. +- All task artifacts (contexts, spec, design, reports, `.feature` comments) are in **Russian**; code identifiers remain as-is. --- depends_on: diff --git a/framework_eng/rules/agent-debug/SKILL.md b/framework_eng/rules/agent-debug/SKILL.md index 2e8f37a5..5666db15 100644 --- a/framework_eng/rules/agent-debug/SKILL.md +++ b/framework_eng/rules/agent-debug/SKILL.md @@ -1,6 +1,6 @@ --- name: agent-debug -description: "Standard diagnostics (registration log/screenshots) did not reveal the actual behavior -> apply the `agent-debug` skill (critical trigger)" +description: "If logs/screenshots fail, add agent-debug tracing" alwaysApply: true --- # Debug Messages (Agent Debug) diff --git a/framework_eng/rules/buddy-prompting/SKILL.md b/framework_eng/rules/buddy-prompting/SKILL.md index 740339ba..70cf05b1 100644 --- a/framework_eng/rules/buddy-prompting/SKILL.md +++ b/framework_eng/rules/buddy-prompting/SKILL.md @@ -1,6 +1,6 @@ --- name: buddy-prompting -description: "Before contacting 1C Buddy -> apply the buddy-prompting skill" +description: "Before asking 1C Buddy, shape the prompt" alwaysApply: true --- # Prompts for 1C Buddy diff --git a/framework_eng/rules/bug-reporting/SKILL.md b/framework_eng/rules/bug-reporting/SKILL.md index 601ac83c..83f8f99c 100644 --- a/framework_eng/rules/bug-reporting/SKILL.md +++ b/framework_eng/rules/bug-reporting/SKILL.md @@ -1,6 +1,6 @@ --- name: bug-reporting -description: "Self-fix limit exhausted / cause is not in own code -> apply the bug-reporting skill" +description: "When self-fix is exhausted, file bug-report" alwaysApply: true --- # Bug Report Formatting diff --git a/framework_eng/rules/capability-resolution/SKILL.md b/framework_eng/rules/capability-resolution/SKILL.md index a15ae9e8..a4d5c0e0 100644 --- a/framework_eng/rules/capability-resolution/SKILL.md +++ b/framework_eng/rules/capability-resolution/SKILL.md @@ -1,6 +1,6 @@ --- name: capability-resolution -description: Resolve capability → implementation (MCP tool or CLI). The agent uses registry.yaml for invocation. +description: "Before choosing a tool, resolve capability first" alwaysApply: true --- @@ -8,7 +8,7 @@ alwaysApply: true ## Model -- Capability is a stable contract through which skills reference a capability ("what needs to be done"). +- Capability is a stable contract through which skills refer to a capability ("what needs to be done"). - The capability implementation is fixed in `framework/capabilities/registry.yaml`: - `kind: mcp` — MCP server + tool; - `kind: cli` — CLI command. @@ -26,9 +26,9 @@ alwaysApply: true 4. If the capability is missing from the registry — inform the user and do not substitute a "similar" tool. 5. If the MCP server is unavailable (not in the tool list) or the CLI binary is not found — inform the user; do not attempt workarounds. -## v8-session-manager: runtime storefront +## v8-session-manager: runtime showcase -Some of the tools in v8-session-manager (`session_list`) are built-in and always available as long as the manager is running. The remaining tools are proxied from connected 1С clients and appear on the storefront only when a client with the required extension is connected to the manager via WS. If a capability with `server: v8-session-manager` is not available in `tools/list`, that means the corresponding client is not connected. Bringing up the client is the task of `v8-runner` (see SKILL.md in `framework/skills/tool-usage/v8-runner/`). +Some of the tools in v8-session-manager (`session_list`) are built-in and always available as long as the manager is running. The remaining tools are proxied from connected 1С clients and appear on the showcase only when a client with the required extension is connected to the manager via WS. If a capability with `server: v8-session-manager` is not available in `tools/list`, that means the corresponding client is not connected. Bringing up the client is the task of `v8-runner` (see SKILL.md in `framework/skills/tool-usage/v8-runner/`). > Replacing a capability implementation (via `tools/capability-registry.py` or direct editing of `registry.yaml`) is a procedural how-to; see the documentation for `tools/capability-registry.py`. diff --git a/framework_eng/rules/code-verification/SKILL.md b/framework_eng/rules/code-verification/SKILL.md index 96fbaf2c..4c76fe04 100644 --- a/framework_eng/rules/code-verification/SKILL.md +++ b/framework_eng/rules/code-verification/SKILL.md @@ -1,13 +1,13 @@ --- name: code-verification -description: "After modifying BSL → apply code-verification + syntax-checking skills" +description: "After BSL changes, run verification and syntax checks" alwaysApply: true --- # BSL Verification After Changes -> **Trigger:** after any BSL code change. When triggered, apply the `code-verification` (`framework/skills/tool-usage/code-analysis/code-verification/SKILL.md`) and `syntax-checking` (`framework/skills/tool-usage/code-analysis/syntax-checking/SKILL.md`) skills. +> **Trigger:** after any BSL code change. When triggered, apply the `code-verification` skill (`framework/skills/tool-usage/code-analysis/code-verification/SKILL.md`) and `syntax-checking` (`framework/skills/tool-usage/code-analysis/syntax-checking/SKILL.md`). -**GUARD:** zero LSP errors are mandatory before commit. +**GUARD:** zero LSP errors are mandatory before committing. --- depends_on: diff --git a/framework_eng/rules/coding-standards/SKILL.md b/framework_eng/rules/coding-standards/SKILL.md index 37758859..c9b67662 100644 --- a/framework_eng/rules/coding-standards/SKILL.md +++ b/framework_eng/rules/coding-standards/SKILL.md @@ -1,6 +1,6 @@ --- name: coding-standards -description: "When writing or reviewing BSL code → apply the coding-standards skill" +description: "When writing/reviewing BSL, apply coding standards" alwaysApply: true --- # BSL Coding Standards diff --git a/framework_eng/rules/dap-bsl-debugger/SKILL.md b/framework_eng/rules/dap-bsl-debugger/SKILL.md index b1e576b1..eec27e58 100644 --- a/framework_eng/rules/dap-bsl-debugger/SKILL.md +++ b/framework_eng/rules/dap-bsl-debugger/SKILL.md @@ -1,6 +1,6 @@ --- name: dap-bsl-debugger -description: "Interactive BSL debugging is needed for a reproducible runtime scenario when static analysis, ЖР/screenshots, and agent-debug do not reveal the execution path or variable values → apply the `dap-bsl-code-debug-procedure` skill." +description: "When runtime path is unclear, use BSL DAP debugging" alwaysApply: true --- # DAP BSL Debugger diff --git a/framework_eng/rules/error-handling/SKILL.md b/framework_eng/rules/error-handling/SKILL.md index 43d27939..61666c81 100644 --- a/framework_eng/rules/error-handling/SKILL.md +++ b/framework_eng/rules/error-handling/SKILL.md @@ -1,6 +1,6 @@ --- name: error-handling -description: "BSL code with transactions/Try/blocking → apply the `error-handling` skill" +description: "For Try, transactions, or locks, apply error-handling" alwaysApply: true --- # Error Handling and Transactions @@ -9,10 +9,6 @@ alwaysApply: true **GUARD:** an unclosed transaction is a critical error; acceptance is blocked. ---- -depends_on: - - error-handling - --- depends_on: - error-handling diff --git a/framework_eng/rules/escalation-format/SKILL.md b/framework_eng/rules/escalation-format/SKILL.md index 7cd4c216..211e0de5 100644 --- a/framework_eng/rules/escalation-format/SKILL.md +++ b/framework_eng/rules/escalation-format/SKILL.md @@ -1,6 +1,6 @@ --- name: escalation-format -description: Escalating a decision to the user -> apply the escalation-format skill (the What->Why->Options->Assessment->Recommendation structure). +description: "When escalating decisions, give options and recommendation" alwaysApply: true --- # User Escalation Format diff --git a/framework_eng/rules/form-patterns/SKILL.md b/framework_eng/rules/form-patterns/SKILL.md index acbb1a07..4cdce137 100644 --- a/framework_eng/rules/form-patterns/SKILL.md +++ b/framework_eng/rules/form-patterns/SKILL.md @@ -1,11 +1,11 @@ --- name: form-patterns -description: "Before writing a managed form module → apply the form-patterns skill" +description: "Before managed form modules, apply form-patterns" alwaysApply: true --- # Managed Form Module Patterns -> **Trigger:** before writing or making significant changes to a managed form module in 1С. When triggered, apply the `form-patterns` skill (`framework/skills/bsl-practices/form-patterns/SKILL.md`). +> **Trigger:** before writing or making a significant change to a 1C managed form module. When triggered, apply the `form-patterns` skill (`framework/skills/bsl-practices/form-patterns/SKILL.md`). --- depends_on: diff --git a/framework_eng/rules/form-visual-check/SKILL.md b/framework_eng/rules/form-visual-check/SKILL.md index e5aee5f2..743daecc 100644 --- a/framework_eng/rules/form-visual-check/SKILL.md +++ b/framework_eng/rules/form-visual-check/SKILL.md @@ -1,16 +1,18 @@ --- name: form-visual-check -description: "After changes or a form screenshot, run visual-check" +description: "After changes or a form screenshot, perform a visual check" alwaysApply: true --- # Form Visual Check -> **Trigger:** after changing a managed form, when investigating/checking a client form through TestClient/VA/web client, OR after receiving a form screenshot in review. When triggered, apply the `visual-check` skill (`framework/skills/tool-usage/browser-ui/visual-check/SKILL.md`) and `form-visual-requirements` (`framework/skills/bsl-practices/form-visual-requirements/SKILL.md`). +> **Trigger:** after changing a managed form, when investigating/checking a client form through VA/TestClient, OR after receiving a form screenshot in review. When triggered, apply the `va-visual-check` skill (`framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md`) and `form-visual-requirements` (`framework/skills/bsl-practices/form-visual-requirements/SKILL.md`). -The default route for 1C forms is Vanessa/TestClient or the platform TestClient MCP. A visual screenshot is mandatory: first try the proven VA MCP screenshot if it actually works in the current environment; otherwise take an external OS/noVNC screenshot of the visible 1C window. The web client in `visual-check` is chosen only for browser-specific defects: DOM/CSS/HTML, JS console/network, web-auth/publication, viewport/pixel rendering, browser extension, or browser-only file/clipboard. +The preferred route for 1С forms is Vanessa/TestClient and VA MCP: `connect_test_client` → the real test-client PID → `get_window_list_os` → `get_window_screenshot_os`. The route details, the Linux headless X11/Xvfb recipe for black screenshots, and the browser fallback are described in `va-visual-check`. + +The platform TestClient MCP can be used for structural form control if that is part of a VA/TestClient scenario. If browser/web-client fallback is used, the reason, the completed VA steps, and the residual risk must be explicitly recorded in the context. --- depends_on: - - visual-check + - framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md - form-visual-requirements --- diff --git a/framework_eng/rules/framework-bootstrap/SKILL.md b/framework_eng/rules/framework-bootstrap/SKILL.md index f238a92c..05bd9ce8 100644 --- a/framework_eng/rules/framework-bootstrap/SKILL.md +++ b/framework_eng/rules/framework-bootstrap/SKILL.md @@ -1,19 +1,19 @@ --- name: framework-bootstrap -description: 1C BSL Agent Development Framework — portable self-promoting main-thread stub +description: "On start or compaction, load the orchestrator profile" alwaysApply: true --- # 1C BSL Agent Development Framework -This is an agent development framework for 1C BSL. A minimal always-on anchor + a portable -cross-harness bridge that raises the Lead/orchestrator role in the main thread. Detailed routing and +This is an agent development framework for 1C BSL. A minimal always-on reference point + a portable +cross-harness bridge that elevates the Lead/orchestrator role in the main thread. Detailed routing and orchestration management live in the **orchestrator profile** (`framework/subagents/orchestrator.md`), not here. ## Self-Promoting Stub (main thread) -> The goal is to guarantee that the main thread HAS orchestration instructions, on any harness and after -> any context loss. The condition is keyed on the **actual presence of the orchestrator instruction body in +> The goal is to ensure that the main thread HAS orchestration instructions on any harness and after +> any context loss. The condition keys off the **actual presence of the orchestrator instruction body in > the current context**, NOT on the belief “I am the orchestrator”: after compaction, the task state (“I > believe I am the orchestrator”) survives in the summary, while the instruction body is evicted. Keying on > belief would create a false read skip. @@ -33,14 +33,14 @@ not here. как Lead. Это и есть портативная эмуляция профиля на харнесах без --agent/--append. ``` -**Re-trigger points:** session start · **after compaction** · resuming from +**Trigger points:** session start · **after compaction** · resuming from `task_dir/.context/orchestrator-context.md`. In each of them, re-check the middle/third branch: if the management body is not in context, reread the profile before the first management action. ## Delivery on Different Harnesses (one portable carrier) - **Harness WITH profile** (Claude CLI, launched with `--append-system-prompt` or `--agent orchestrator`, - see `framework/subagents/orchestrator.md` § «Способ запуска» and the manifest §6.1) → management + see `framework/subagents/orchestrator.md` § "Launch Method" and the manifest §6.1) → management is preloaded into the system prompt → the second branch of the stub is true → stub **no-op**. - **Harness WITHOUT profile** (Codex / Cursor, etc.) → the third branch triggers: the main thread reads the profile itself. Durability is via re-trigger (this stub is always-on, survives compaction; the diff --git a/framework_eng/rules/git-workflow/SKILL.md b/framework_eng/rules/git-workflow/SKILL.md index 429089de..3c9b4779 100644 --- a/framework_eng/rules/git-workflow/SKILL.md +++ b/framework_eng/rules/git-workflow/SKILL.md @@ -1,11 +1,11 @@ --- name: git-workflow -description: Git guardrail for the agentic cycle - subagents do not commit; deletion/git rm is forbidden without explicit user permission; commit and merge are only for the orchestrator/user. Procedure -> `git-workflow` skill. +description: "Before commit/delete, apply git workflow guardrails" alwaysApply: true --- # Git Workflow Policy -> **Trigger:** working with git (commits, branches, task merge, rollback). When triggered, apply the `git-workflow` skill (`framework/skills/agent-process/git-workflow/SKILL.md`): branch strategy, phase-based commit format, squash-merge, rollback. +> **Trigger:** working with git (commits, branches, merge tasks, rollback). When triggered, apply the `git-workflow` skill (`framework/skills/agent-process/git-workflow/SKILL.md`): branch strategy, phase-based commit format, squash-merge, rollback. The guardrail below must always be visible, regardless of whether the skill is loaded or not. @@ -15,8 +15,8 @@ The guardrail below must always be visible, regardless of whether the skill is l |---|---| | **Subagents do NOT commit** | The `git commit` right belongs ONLY to the orchestrator (within the task and the final merge) and to the user. A subagent does not see the full phase scope and may commit junk. | | **Commit and merge are only for the orchestrator / user** | No subagent initiates a commit or merge on its own. | -| **Deletion of files from git is forbidden without explicit user permission** | `git rm`, `git rm --cached`, physical deletion of a file under git with inclusion in the commit, `git reset --hard` with loss of someone else's changes - are FORBIDDEN without an explicit "yes, delete it" in the current dialogue. Permissions from memory / CLAUDE.md do NOT count. Instead of deleting - comment out via `//--agent`, overwrite with a new version, escalate. The `tasks//` folder must never be deleted. | -| **No force-pushes and no destructive operations in the parent branch** | Inside the local task branch, rebase/amend are allowed; in the parent branch - no. | +| **Deletion of files from git is forbidden without explicit user permission** | `git rm`, `git rm --cached`, physical deletion of a file under git with inclusion in the commit, `git reset --hard` with loss of someone else's changes are FORBIDDEN without an explicit "yes, delete it" in the current dialogue. Permissions from memory / CLAUDE.md do NOT count. Instead of deleting, comment out via `//--agent`, overwrite with a new version, escalate. The `tasks//` folder must never be deleted. | +| **No force-pushes and no destructive operations in the parent branch** | Inside the local task branch, rebase/amend are allowed; in the parent branch, no. | | **Suspicion of deletion -> stop** | `D ` or `R -> ` in `git status`, not explicitly initiated by the current phase -> DO NOT commit, record `SUSPECTED_DELETION: ` in `orchestrator-context.md`, escalate to the user. | Details of the "how" (creating the task branch, what to commit, message format, squash-merge conditions and command, rollback scenarios, exceptions for deletion) are in the `git-workflow` skill. diff --git a/framework_eng/rules/infostart-kb/SKILL.md b/framework_eng/rules/infostart-kb/SKILL.md index fc4d32bc..b25a23a7 100644 --- a/framework_eng/rules/infostart-kb/SKILL.md +++ b/framework_eng/rules/infostart-kb/SKILL.md @@ -1,13 +1,13 @@ --- name: infostart-kb -description: "Before writing/debugging/designing 1С code → refer to the infostart-kb skill" +description: "Before 1C design/code/debug, check Infostart" alwaysApply: true --- -# Infostart Knowledge Base (before 1С development) +# Infostart Knowledge Base (before 1C development) -> **Trigger:** before writing, debugging, or designing 1С:Предприятие code (documents, registers, БСП, managed forms, extensions, queries, exchange, etc.). When triggered, apply the `infostart-kb` skill (`framework/skills/other/infostart-kb/SKILL.md`). +> **Trigger:** before writing, debugging, or designing 1C:Enterprise code (documents, registers, БСП, managed forms, extensions, queries, exchange, etc.). When triggered, apply the `infostart-kb` skill (`framework/skills/other/infostart-kb/SKILL.md`). -The knowledge base contains hundreds of thousands of real solutions and known community issues - using it for 1С tasks is mandatory. +The knowledge base contains hundreds of thousands of real solutions and known community issues - using it for 1C tasks is mandatory. --- depends_on: diff --git a/framework_eng/rules/no-direct-db-access/SKILL.md b/framework_eng/rules/no-direct-db-access/SKILL.md index 985200a3..0dff6103 100644 --- a/framework_eng/rules/no-direct-db-access/SKILL.md +++ b/framework_eng/rules/no-direct-db-access/SKILL.md @@ -1,33 +1,35 @@ --- name: no-direct-db-access -description: Global prohibition on direct access to the DBMS. Agents work with data only through the 1C:Enterprise platform. Direct queries to the DBMS are allowed only for performance analysis and only in read-only mode. +description: "Read/write data through 1C platform, not DBMS" alwaysApply: true --- -# Ban on Direct DBMS Access +# Ban on Direct Access to the DBMS -A global rule for all agents and subagents. +Global rule for all agents and subagents. ## Context -The 1C:Enterprise platform is the sole legitimate data access layer. Direct access to the DBMS (PostgreSQL, MS SQL, etc.) bypasses business logic, compromises data integrity, and creates security risks. +The 1C:Enterprise platform is the only legitimate data access layer. +Direct access to the DBMS (PostgreSQL, MS SQL, etc.) bypasses business logic, +breaks data integrity, and creates security risks. ## Rules ### PROHIBITED (without exceptions) -- Modifying data in the DBMS directly: `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`, DDL operations -- Generating or suggesting SQL scripts to alter data +- Direct modification of data in the DBMS: `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`, DDL operations +- Generating or suggesting SQL scripts to change data - Bypassing platform mechanisms (RLS, locks, subscriptions) through direct access ### PROHIBITED (without user approval) -- Reading data from the DBMS directly (`SELECT`) — only via 1С platform queries +- Reading data from the DBMS directly (`SELECT`) — only through 1C platform queries - Connecting to the DBMS by any means (psql, sqlcmd, ODBC, etc.) ### ALLOWED (performance tasks only) -With **explicit** approval from the user **or** if the task is classified as a performance task: +With **explicit** user approval **or** if the task is classified as a performance task: - `SELECT` queries to the DBMS for execution plan analysis (`EXPLAIN ANALYZE`) - Reading DBMS system views (`pg_stat_*`, `sys.dm_exec_*`) diff --git a/framework_eng/rules/no-manual-xml-edit/SKILL.md b/framework_eng/rules/no-manual-xml-edit/SKILL.md index 13567715..d5733c8b 100644 --- a/framework_eng/rules/no-manual-xml-edit/SKILL.md +++ b/framework_eng/rules/no-manual-xml-edit/SKILL.md @@ -1,6 +1,6 @@ --- name: no-manual-xml-edit -description: You are editing 1C XML/MXL -> apply the xml-generation skill. Manual editing is forbidden; for agents without a PreToolUse hook, a self-check through block-direct-xml-edit.py is mandatory. +description: "When editing 1C XML/MXL, use xml-generation" alwaysApply: true --- diff --git a/framework_eng/rules/predefined-elements/SKILL.md b/framework_eng/rules/predefined-elements/SKILL.md new file mode 100644 index 00000000..6971984f --- /dev/null +++ b/framework_eng/rules/predefined-elements/SKILL.md @@ -0,0 +1,46 @@ +--- +name: predefined-elements +description: "Before new settings, search predefined values" +alwaysApply: true +--- + +# Reuse-first for settings and predefined values + +> **Trigger:** the task needs a setting, a named predefined value, a threshold, a flag, a code, a reference to an object, or another parameter that should live centrally. + +## Principle + +Settings replicated across copies or hardcoded as literals in code diverge between installations and silently break logic. If the project already has a centralized storage for settings or named predefined values, the agent must first look for the value there and use the standard access layer for it. + +## MUST + +| Requirement | Description | +|-----------|----------| +| Search first | Before creating a new setting or hardcoding a value, find the existing value by business key through the project's standard mechanism. If found, reuse it and do not create a duplicate | +| Read through wrappers | If the project has a service module, API, or БСП access wrapper for settings, use it instead of a direct query to storage | +| No hardcoding | Do not hardcode codes, references, thresholds, and flags that should be manageable settings. The value must be read by a meaningful business key | +| New key only when absent | Create a new setting only after checking that no existing key and no collisions by purpose exist | +| One key in one place | Declare the string business key only once: a constant, an exported function, or a single access point. Do not duplicate the literal across the code | +| Document the purpose | For a new setting, record the purpose, value format, logic owner, and acceptable default value in task artifacts or project documentation | + +## SHOULD + +- If a setting is needed in multiple places, all of them read it through the same key and the same access layer. +- If the project does not have a centralized settings storage, first check standard or library mechanisms instead of creating a local catalog/register without an architectural decision. +- For migrating old hardcoded values, first find all usages of the literal and define a single key, then replace accesses through a shared API. + +## What this rule does NOT cover + +- Settings that are a full-fledged domain model with complex identification and lifecycle. They require a separate design, not a key-value entry. +- Standard platform or library mechanisms for storing settings. They should be reused according to `ssl-patterns` if they fit the task. + +## Related rules + +- `search-before-write` - reuse-first for code and ready-made mechanisms. +- `ssl-patterns` - reuse of standard and library mechanisms. + +--- +depends_on: + - search-before-write + - ssl-patterns +--- diff --git a/framework_eng/rules/protected-paths/SKILL.md b/framework_eng/rules/protected-paths/SKILL.md index 263feac1..6ebf80f6 100644 --- a/framework_eng/rules/protected-paths/SKILL.md +++ b/framework_eng/rules/protected-paths/SKILL.md @@ -1,6 +1,6 @@ --- name: protected-paths -description: Global protection of paths. Categorically forbids modification of protected directories for any agents and subagents. +description: "Before writes or deletes, check protected paths" alwaysApply: true --- @@ -16,14 +16,14 @@ Any match = prohibition on creation/modification/deletion. ## Behavior when blocked -If a fix requires protected path: +If a fix requires a protected path: -1. Do NOT make changes to protected path +1. Do NOT make changes to the protected path 2. Record statuses: `test_failure` + `suspected_test_error` + `blocked_by_protected_path` 3. Provide justification and the prohibited path(s) 4. Stop and hand off the task to the orchestrator/user -**developer-code:** fixes only bugs in its own code for the current session; all other cases (test failure, infrastructure, protected path) — block per the protocol above. +**developer-code:** fixes only bugs in its own code for the current session; all other cases (test failure, infrastructure, protected path) - block per the protocol above. --- depends_on: [] diff --git a/framework_eng/rules/query-optimize/SKILL.md b/framework_eng/rules/query-optimize/SKILL.md index b2dfcf2e..fb401d51 100644 --- a/framework_eng/rules/query-optimize/SKILL.md +++ b/framework_eng/rules/query-optimize/SKILL.md @@ -1,9 +1,9 @@ --- name: query-optimize -description: "After identifying a slow query → apply the query-optimize skill" +description: "After finding a slow query, apply query optimize" alwaysApply: true --- -# Query Optimization (after identifying the problem) +# Query Optimization (after the issue is identified) > **Trigger:** after identifying a slow query or receiving a complaint about query/Data Composition System performance. When triggered, apply the `query-optimize` skill (`framework/skills/bsl-practices/query-optimize/SKILL.md`). diff --git a/framework_eng/rules/query-patterns/SKILL.md b/framework_eng/rules/query-patterns/SKILL.md index f35dad0d..37cdb769 100644 --- a/framework_eng/rules/query-patterns/SKILL.md +++ b/framework_eng/rules/query-patterns/SKILL.md @@ -1,9 +1,9 @@ --- name: query-patterns -description: "Before writing a new query → apply the query-patterns skill" +description: "Before new 1C queries, apply query-patterns" alwaysApply: true --- -# Query Patterns (before writing) +# Query Patterns (Before Writing) > **Trigger:** before writing a new query in the 1C query language. When triggered — apply the `query-patterns` skill (`framework/skills/bsl-practices/query-patterns/SKILL.md`). diff --git a/framework_eng/rules/report-discovered-issues/SKILL.md b/framework_eng/rules/report-discovered-issues/SKILL.md new file mode 100644 index 00000000..27a5a4fb --- /dev/null +++ b/framework_eng/rules/report-discovered-issues/SKILL.md @@ -0,0 +1,70 @@ +--- +name: report-discovered-issues +description: "Report out-of-scope defects after the task" +alwaysApply: true +--- + +# Report of Discovered Issues + +> The agent often sees more than is needed for the current task. A silently ignored finding remains an unresolved risk, so it must be explicitly communicated to the user. + +## Principle + +While solving one task, the agent may discover regressions, bugs in adjacent modules, technical debt, antipatterns, mismatches between code and specification, performance issues, or security issues. These findings do not need to be fixed within the current task without the user's permission, but they cannot be hidden. + +## MUST + +| Requirement | Description | +|-----------|----------| +| Record findings | As they are discovered, record the issue in the working context, task notes, or the final report section | +| Do not silently expand scope | Do not fix discovered issues within the current task without explicit user permission | +| Report after completion | In the final response or report, list the discovered issues that are outside the completed scope | +| Provide specifics | For each finding, specify the location, essence, risk, severity, and approximate size of the fix | +| Suggest a path | Propose a next step: separate task, quick-fix, defer, document, or investigate further | + +## Report Format + +```markdown +## Найдено по пути + +### 1. [Краткое название] +- **Где:** `path/to/file:line` +- **Что:** конкретное описание проблемы +- **Почему проблема:** последствия или риск +- **Серьезность:** критично / средне / низко +- **Усилие:** простой фикс / отдельная задача / большая работа +- **Предложение:** что сделать дальше +``` + +## What Must Be Reported + +- Bugs that can lead to data loss, financial loss, security issues, or availability issues. +- Regressions and divergences from the source of truth. +- Data integrity issues. +- Crashes or exceptions possible in a production scenario. +- Errors in tests or infrastructure that mask the real result. + +## What Can Be Omitted + +- Purely stylistic details without maintainability impact. +- Typos in comments. +- Abstract refactoring wishes without a concrete risk. + +## What Not to Do + +- Do not turn the current task into cleaning up everything found. +- Do not postpone the report until later. +- Do not combine different problems into one vague phrase. +- Do not dramatize or understate it: the description must be verifiable. + +## Related Rules + +- `agent-context-protocol` - where to record working context and discovered issues. +- `quick-fix` / `full-cycle` - how to turn findings into follow-up work. +- `source-of-truth` - how to check discrepancies between artifacts. + +--- +depends_on: + - agent-context-protocol + - source-of-truth +--- diff --git a/framework_eng/rules/rlm-workflow/SKILL.md b/framework_eng/rules/rlm-workflow/SKILL.md index aa580818..a2aa15e3 100644 --- a/framework_eng/rules/rlm-workflow/SKILL.md +++ b/framework_eng/rules/rlm-workflow/SKILL.md @@ -1,6 +1,6 @@ --- name: rlm-workflow -description: Universal reusable knowledge (patterns, architecture decisions, domain facts) → RLM, NOT into context. Before a non-trivial task/decision in a domain, pull from RLM. Native memory is only a thin always-on core. +description: "Before non-trivial domain work, read RLM knowledge" alwaysApply: true --- # Memory Layout and Working with RLM diff --git a/framework_eng/rules/sdd-policy/SKILL.md b/framework_eng/rules/sdd-policy/SKILL.md index de543827..38a45993 100644 --- a/framework_eng/rules/sdd-policy/SKILL.md +++ b/framework_eng/rules/sdd-policy/SKILL.md @@ -1,6 +1,6 @@ --- name: sdd-policy -description: New feature / architectural change / complex bug -> spec before code. Apply spec-standard skill. +description: "For features, architecture, complex bugs, write spec first" alwaysApply: true --- diff --git a/framework_eng/rules/search-before-write/SKILL.md b/framework_eng/rules/search-before-write/SKILL.md index 1e25123f..a45510a6 100644 --- a/framework_eng/rules/search-before-write/SKILL.md +++ b/framework_eng/rules/search-before-write/SKILL.md @@ -1,6 +1,6 @@ --- name: search-before-write -description: "Before creating a new function/query/processing -> apply the `search-before-write` skill" +description: "Before new code or query, search existing code" alwaysApply: true --- # Search Before Writing diff --git a/framework_eng/rules/security/SKILL.md b/framework_eng/rules/security/SKILL.md index 596fbd65..d8bf25f5 100644 --- a/framework_eng/rules/security/SKILL.md +++ b/framework_eng/rules/security/SKILL.md @@ -1,6 +1,6 @@ --- name: security -description: "Working with passwords/tokens/crypto/privileges → apply the security skill" +description: "For secrets, tokens, crypto, privileges, use security" alwaysApply: true --- # 1C Security diff --git a/framework_eng/rules/semantic-code-comments/SKILL.md b/framework_eng/rules/semantic-code-comments/SKILL.md new file mode 100644 index 00000000..18fa7de8 --- /dev/null +++ b/framework_eng/rules/semantic-code-comments/SKILL.md @@ -0,0 +1,109 @@ +--- +name: semantic-code-comments +description: "In comments, explain why, not what the code does" +alwaysApply: true +--- + +# Semantic Comments in Code + +> A good comment explains **why**, not **what**. Names, structure, and expressions already show what the code does; a comment is needed for business meaning, constraints, tradeoffs, and hidden invariants. + +## Principle + +Code is written once and read many times. If a future reader will ask "why is it like this?", "what breaks if I remove it?", "which business rule is protected here?" - you need a semantic comment. + +The goal is not comment density, but reducing guesswork when reading complex or non-obvious code. + +## What to Comment + +### Non-obvious Business Rules + +```bsl +// Скидку применяем только после подтверждения лимита, потому что договор +// может запрещать ретроспективное изменение цены. +Если ЛимитПодтвержден И ДоговорРазрешаетИзменениеЦены Тогда +``` + +### Protection Against External Failures and Edge Cases + +```bsl +// Внешний сервис иногда возвращает пустую сумму для закрытого периода. +// Считаем ее нулем, чтобы отчет остался построимым, а не падал на преобразовании. +Сумма = ?(ЗначениеЗаполнено(Ответ.Сумма), Ответ.Сумма, 0); +``` + +### Workarounds and Tradeoffs + +```bsl +// Не используем пакетную запись: обработчик записи должен отработать для каждого +// объекта отдельно, иначе не обновятся зависимые агрегаты. +Для Каждого Объект Из Объекты Цикл +``` + +### Hidden Invariants and Call Order + +```bsl +// Важно выполнить до расчета итогов: эта процедура заполняет временную таблицу, +// из которой следующий запрос берет границы периода. +ПодготовитьГраницыПериода(Параметры); +``` + +### Reasons for Rejecting the Obvious Solution + +```bsl +// Не используем левое соединение: downstream-логика требует обязательную ссылку +// и не имеет безопасной ветки для пустого значения. +ВНУТРЕННЕЕ СОЕДИНЕНИЕ +``` + +### Magic Numbers and Constants + +```bsl +МаксимумПопыток = 3; // Больше трех повторов задерживает пользователя сильнее, чем помогает при временном сбое. +``` + +## What Not to Comment + +### Code Recap + +```bsl +// Плохо: складываем A и B. +Сумма = A + B; +``` + +### Obvious Operations + +```bsl +// Плохо: увеличиваем счетчик. +Счетчик = Счетчик + 1; +``` + +### Comments That Contradict the Code + +If you change the code, check the nearby comments. An outdated comment is worse than no comment because it creates false confidence. + +## SHOULD + +- Before a non-trivial block of complex logic, give a short explanation of the block's purpose. +- At the start of a procedure, add a purpose comment if it does not follow from the name. +- Refer to the specification, ADR, or task when the reason for the decision is not clear without external context. +- Explain the limitations of external systems, the platform, libraries, and data. +- Comment intentionally strange code: why it looks unusual and what will break if it is "simplified". + +## How to Phrase It + +| Good | Bad | +|--------|-------| +| "Do not use X because Y" | "Here X" | +| "Protection against an empty response from an external service" | "Check the value" | +| "If removed, the period invariant will be broken" | "Do not touch" | +| "First fill the cache because the next query reads it" | "Fill the cache" | + +## Relationship to Change Markup + +`agent-code-marking` shows who changed the code and when. `semantic-code-comments` explains why the code is structured this way. These rules complement each other: markers provide auditability, comments provide meaning. + +--- +depends_on: + - agent-code-marking +--- diff --git a/framework_eng/rules/skill-learning-policy/SKILL.md b/framework_eng/rules/skill-learning-policy/SKILL.md index 0d23ca55..117cc46a 100644 --- a/framework_eng/rules/skill-learning-policy/SKILL.md +++ b/framework_eng/rules/skill-learning-policy/SKILL.md @@ -1,36 +1,36 @@ --- name: skill-learning-policy -description: Knowledge accumulation, two triggers. WRITE — after a cycle with ≥2 iterations, perform a retrospective. READ — before working with a skill, read its references/learned-patterns.md. Procedure and write format → skill-learning. +description: "Before skill use and after iterations, update learned patterns" alwaysApply: true --- # Knowledge Accumulation Policy (Skill Learning) -## TRIGGER — WRITE a lesson (MUST, strict) +## TRIGGER — RECORD a lesson (MUST, strict) -> A work cycle with **≥2 iterations** has completed (wrote → error → found the correct path → success) → a retrospective is **MANDATORY**. Apply the `skill-learning` skill (`framework/skills/agent-process/skill-learning/SKILL.md`) and perform it. +> Completed a work cycle with **≥2 iterations** (wrote → error → found the correct path → success) → a retrospective is **MANDATORY**. Apply the `skill-learning` skill (`framework/skills/agent-process/skill-learning/SKILL.md`) and conduct it. > -> The task was solved on the first attempt → a retrospective is NOT needed, the trigger does not fire. +> Task solved on the first attempt → retrospective is NOT needed, trigger does not fire. > -> **Trigger acceptance:** in full-cycle, skipping the retrospective is recorded by the orchestrator during phase acceptance. In quick-fix/FREE there is no orchestrator acceptance → the agent confirms completion itself with a line in `{role}-context.md` / report: `SKILL_LEARNING: matched|refined|new|skipped()`. +> **Trigger acceptance:** in a full-cycle, skipping the retrospective is recorded by the orchestrator during phase acceptance. In quick-fix/FREE there is no orchestrator acceptance → the agent confirms completion itself with a line in `{role}-context.md` / report: `SKILL_LEARNING: matched|refined|new|skipped()`. ## TRIGGER — READ lessons (before working with a skill) -> Before starting work with any skill, read the accumulated lessons of the owning skill, BEFORE design/implementation: +> Before starting work with any skill — read the accumulated lessons of the skill owner, BEFORE design/implementation: > - `/references/learned-patterns.md` — universal techniques; > - `{project}/.context/learned-patterns.md` — project techniques. > -> Apply `confirmed` as additional rules, `candidate` as hints. If the file does not exist → skip it. The trigger is phase-based: when entering work on a skill, not on every turn. +> Apply `confirmed` as additional rules, `candidate` as hints. File missing → skip. Phase trigger: on entering work with a skill, not on every turn. ## MUST (invariant, always) -- **Abstraction level above the incident.** A lesson describes a named CLASS of error + an anti-recipe (a generalized prohibition/check), NOT a specific incident. Specific `file:line` / symbol names from that incident go as a "source example", NOT as the body of the rule. -- **Abstraction test (record acceptance).** The anti-recipe must apply to at least ≥1 OTHER hypothetical situation besides the one that created it. If it does not apply, it is an instance: rephrase it higher or reject it. -- **Update check before writing.** Compare the incident with existing recipes (`references/learned-patterns.md` of the owning skill + `{project}/.context/learned-patterns.md`). If it falls under an existing class, update it (candidate→confirmed, expand the boundaries of the anti-recipe, add the source), do NOT create a duplicate. If it does not fit, create a new class. The outcome is recorded explicitly: `matched | refined | new`. -- Entries are written ONLY to `references/learned-patterns.md` of the owning skill (universal) or `{project}/.context/learned-patterns.md` (project) — NOT into the body of `SKILL.md`. -- **The target directory for the universal lesson is the RU source of the framework** (the owning skill directory in `framework/`, NOT the installed ENG symlink `framework_eng/`: otherwise the lesson is lost during synchronization). Search for the directory and synchronize to ENG via the `skill-editing-from-project` skill. A project lesson (`{project}/.context/learned-patterns.md`) is in Russian, without mapping or synchronization. +- **Abstraction level above the incident.** The lesson describes a named CLASS of error + anti-recipe (generalized prohibition/check), NOT a specific incident. The specific `file:line` / symbol names of that incident are given as a "source example", NOT as the body of the rule. +- **Abstraction test (record acceptance).** The anti-recipe applies to at least ≥1 OTHER hypothetical situation besides the one that produced it. Not applicable → this is an instance: reformulate higher or reject it. +- **Verification/update before recording.** Compare the incident against existing recipes (`references/learned-patterns.md` of the skill owner + `{project}/.context/learned-patterns.md`). If it falls under an existing class → update it (candidate→confirmed, expand the anti-recipe boundaries, add a source), do NOT create a duplicate. If it does not fit → new class. The outcome is recorded explicitly: `matched | refined | new`. +- Entries are written ONLY to `references/learned-patterns.md` of the skill owner (universal) or `{project}/.context/learned-patterns.md` (project-specific) — NOT in the body of `SKILL.md`. +- **Target directory for a universal lesson is the RU source of the framework** (the skill owner's directory in `framework/`, NOT the installed ENG symlink `framework_eng/`: otherwise the lesson is lost during synchronization). Search for the directory and synchronize to ENG with the `skill-editing-from-project` skill. The project lesson (`{project}/.context/learned-patterns.md`) is in Russian, without mapping or synchronization. - Acceptance and anti-acceptance are one entry; the first case = `candidate`, repetition = `confirmed`. -The retrospective procedure (reconstructing the chain of iterations, abstracting to a class, abstraction test, check-cascade, choosing the level and owning skill, searching the RU directory) is in the `skill-learning` skill. +Retrospective procedure (reconstructing the iteration chain, abstracting to a class, abstraction test, cascade verification, choosing the level and skill owner, searching the RU directory) is in the `skill-learning` skill. --- depends_on: diff --git a/framework_eng/rules/source-of-truth/SKILL.md b/framework_eng/rules/source-of-truth/SKILL.md index c2314232..ddd3698a 100644 --- a/framework_eng/rules/source-of-truth/SKILL.md +++ b/framework_eng/rules/source-of-truth/SKILL.md @@ -1,11 +1,11 @@ --- name: source-of-truth -description: Conflict / test failure / artifact dispute → check the source-of-truth chain top-down (L1→L6). Method — in the source-of-truth skill. +description: "On conflicts and failures, follow source-of-truth" alwaysApply: true --- -# Source of Truth Policy (Source of Truth) +# Source of Truth Policy -> **Trigger:** any conflict, test failure, behavioral discrepancy, or dispute between artifacts. When triggered, apply the `source-of-truth` skill (`framework/skills/agent-process/source-of-truth/SKILL.md`): full L1→L6 hierarchy, end-to-end verification method, classification of the first broken link, implications for roles, and typical applications. +> **Trigger:** any conflict, test failure, behavior mismatch, or dispute between artifacts. When triggered, apply the `source-of-truth` skill (`framework/skills/agent-process/source-of-truth/SKILL.md`): full L1→L6 hierarchy, end-to-end verification method, classification of the first broken link, implications for roles, typical applications. --- depends_on: diff --git a/framework_eng/rules/ssl-patterns/SKILL.md b/framework_eng/rules/ssl-patterns/SKILL.md index 9ca6fcf9..67c298b1 100644 --- a/framework_eng/rules/ssl-patterns/SKILL.md +++ b/framework_eng/rules/ssl-patterns/SKILL.md @@ -1,13 +1,13 @@ --- name: ssl-patterns -description: "Before implementing logic — check for a ready-made mechanism in БСП → ssl-patterns skill" +description: "Before custom logic, check BSP mechanisms" alwaysApply: true --- # БСП Patterns (before implementation) -> **Trigger:** before implementing any business logic in 1С code. When triggered — apply the `ssl-patterns` skill (`framework/skills/bsl-practices/ssl-patterns/SKILL.md`). +> **Trigger:** before implementing any business logic in 1C code. When triggered, apply the `ssl-patterns` skill (`framework/skills/bsl-practices/ssl-patterns/SKILL.md`). -**GUARD:** duplicating ready-made mechanisms in БСП blocks review. +**GUARD:** duplicating built-in БСП mechanisms blocks review. --- depends_on: diff --git a/framework_eng/rules/tdd-policy/SKILL.md b/framework_eng/rules/tdd-policy/SKILL.md index 7b970dca..2d3a06ad 100644 --- a/framework_eng/rules/tdd-policy/SKILL.md +++ b/framework_eng/rules/tdd-policy/SKILL.md @@ -1,21 +1,21 @@ --- name: tdd-policy -description: You write tests or code → tests before implementation (Red→Green). Apply the test-writing skill. +description: "When writing code or tests, go Red -> Green" alwaysApply: true --- # TDD Policy (Test-Driven Development) -> **Trigger:** test-writing phase (Phase 3b) or implementation phase (Phase 3c/3d). When triggered, apply the skill `test-writing` (`framework/skills/bsl-practices/test-writing/SKILL.md`). +> **Trigger:** test-writing phase (Phase 3b) or implementation phase (Phase 3c/3d). When triggered, apply the `test-writing` skill (`framework/skills/bsl-practices/test-writing/SKILL.md`). ## Layer Responsibilities (MUST) -- **Server/business logic is verified by unit tests (YaxUnit)**: checking filling, posting, calculations, queries, registers, routines. **Client/UI behavior** (opening a form, `ПриСозданииНаСервере`/`ПриОткрытии`, visibility/availability/requiredness of elements, reaction to input, form commands) is the domain of **scenario (Vanessa) tests through UI**, see `vanessa-scenario-policy`. Do not substitute the layer: if you bypass the UI with a server call, all client logic (client handlers, form events, conditional formatting, visibility/availability, reaction to input) remains completely untested - it is not covered by either such a "scenario" or a unit test. +- **Server/business logic is verified by unit tests (YaxUnit)**: filling, posting, calculations, queries, registers, routines. **Client/UI behavior** (opening a form, `ПриСозданииНаСервере`/`ПриОткрытии`, visibility/availability/requiredness of elements, reaction to input, form commands) is the domain of **scenario (Vanessa) tests through UI**, see `vanessa-scenario-policy`. Do not substitute the layer: if you bypass the UI with a server call, all client logic (client handlers, form events, conditional formatting, visibility/availability, reaction to input) remains completely untested - it is not covered by either such a "scenario" or a unit test. ## MUST - The test plan is described in the specification **BEFORE** code. -- YaxUnit tests for MUST scenarios are written BEFORE implementation (Red → Green → Refactor). +- YaxUnit tests for MUST scenarios are written BEFORE implementation (Red -> Green -> Refactor). - Tests are reviewed for coverage against the spec. - After fixing remarks, rerun ALL affected tests. - **User/Role context in Test Plan:** if code uses `SetPrivilegedMode`, role checks (`AccessRight`, `RoleAvailable`) or the result depends on the current user - the specification MUST explicitly specify for each test in the "Test Plan" section: user name/role set, required mode (privileged or not), expected result (success/failure). Without this, a test under a full-rights runner (for example `AgentAI`) will produce a false positive. If this is technically impossible for unit, record an ADR in the spec with a transfer to integration scope (Phase 4). diff --git a/framework_eng/rules/test-zero-residue/SKILL.md b/framework_eng/rules/test-zero-residue/SKILL.md index c8aea6ea..c9cbd09f 100644 --- a/framework_eng/rules/test-zero-residue/SKILL.md +++ b/framework_eng/rules/test-zero-residue/SKILL.md @@ -1,38 +1,38 @@ --- name: test-zero-residue -description: Any test that writes to the DB leaves no run residue - all created objects are physically cleaned up, delta across catalogs/registers/documents before and after the run = 0. Apply the `test-writing` skill. +description: "For DB-writing tests, require zero-residue cleanup" alwaysApply: true --- # Tests Leave No Traces (zero-residue) -> **Trigger:** design, writing, or review of ANY test (YaxUnit unit, server-side YaxUnit helper "Vanessa interception", Vanessa `.feature`, integration, end-to-end) that creates/modifies/writes objects in the DB. Applies to ALL test types. When triggered, apply the `test-writing` skill (`framework/skills/bsl-practices/test-writing/SKILL.md`) and the corresponding isolation mechanism: `yaxunit-isolation` for YaxUnit, `vanessa-test-isolation-policy` for Vanessa. +> **Trigger:** designing, writing, or reviewing ANY test (YaxUnit unit, server-side YaxUnit helper "Vanessa interceptor", Vanessa `.feature`, integration, end-to-end) that creates/modifies/writes objects in the DB. Applies to ALL test types. When triggered, apply the `test-writing` skill (`framework/skills/bsl-practices/test-writing/SKILL.md`) and the corresponding isolation mechanism: `yaxunit-isolation` for YaxUnit, `vanessa-test-isolation-policy` for Vanessa. -**GUARD:** a test that leaves data behind in the production database after the run is NOT accepted (Reviewer BLOCK) - even if it is "green". +**GUARD:** a test that leaves data behind in the production database after execution is NOT accepted (Reviewer BLOCK) — even if it is "green". ## Principle -A test that accumulates leftovers pollutes real data, breaks other tests (scheduled jobs pick test objects -> timeouts; idempotency sees other runs as duplicates) and masks database degradation. Post-fact cleanup is a symptom; the root cause is the absence of teardown in the test ARCHITECTURE. This is built into the architecture of every test, not done as a one-off cleanup. +A test that accumulates residue pollutes real data, breaks other tests (scheduled jobs select test objects → timeouts; idempotency sees other runs as duplicates) and masks database degradation. Post-factum cleanup is a symptom; the root cause is the absence of teardown in the test ARCHITECTURE. This is built into the architecture of each test, not done as a one-time cleanup. ## MUST (invariant, always) | Requirement | Description | |-----------|----------| | Zero residue | Delta in count for EACH affected catalog / register / document / record set before and after the run = **0** | -| Isolation mechanism is mandatory | YaxUnit - `.ВТранзакции()` (rollback) OR explicit teardown `.После()` when a permitted exception applies (see `yaxunit-isolation`) | +| Isolation mechanism is mandatory | YaxUnit — `.ВТранзакции()` (rollback) OR explicit teardown `.После()` when a permitted exception applies (see `yaxunit-isolation`). Vanessa and server-side helpers outside a transaction require physical cleanup of everything created, resilient to Act/Assert failures | | Objects are trackable | Create catalogs via `ЮТест.Данные()` (auto-tracking + auto-deletion via `.УдалениеТестовыхДанных()`), not via `Справочники.X.СоздатьЭлемент()` outside tracking | -| Physical deletion of untracked objects | What is not cleaned by transaction/auto-tracking (documents via `Документы.X.СоздатьДокумент()`, objects from helpers, objects from `КонструкторОбъекта().Записать()`) must be deleted physically: `ОбменДанными.Загрузка = Истина` + `Удалить()`, in dependent -> owner order; not marked for deletion | -| **Collector is mandatory** | A test that generates data MUST register EVERY created object in the test object collector AT THE MOMENT of creation; teardown (`.После()` / final scenario step / `ПослеВсехТестов`) walks the collector and physically deletes everything that survived transaction rollback. Works EVEN if Act/Assert failed. Mechanism detail - the `test-writing` skill ("Test Object Collector") | -| **Silent swallowing of delete errors is forbidden** | Collector drain/teardown is NOT allowed to silently swallow a `Удалить()` error. Deletion can legitimately fail on a version conflict (optimistic-lock: the object was concurrently rewritten by a subscription/background job between read and delete) -> it MUST retry with a fresh `ПолучитьОбъект()` (limited number of attempts), retrying ONLY on a version conflict. If after retries the object is still not deleted OR the error is non-conflict, write an Error-level record to the registration log (NOT Warning) with the type + reference of the residue that could not be deleted and continue draining the remaining references (do not abort the drain with an exception - otherwise the rest will be orphaned). A deletion error swallowed in `Попытке` without a visible Error-level trace is an invisible leak that delta-0 acceptance in the registration log will not catch | -| End-to-end test - cleanup step | If data must live during the run (end-to-end) - this is the only exception, and the test MUST end with an explicit step that deletes everything created (via the collector) | -| Acceptance = delta-0 | Verification of the delta of key objects before/after is part of the phase acceptance criterion; non-zero delta = test not accepted | -| Band-aid forbidden | Hiding created objects from queries/scheduled jobs (object exclusion flag, special prefix filter) does NOT count as cleanup - the object must be physically deleted | -| Fragile selectors forbidden | Cleanup by scanning the database by NAME/prefix/regex ("delete everything `LIKE \"Test%\"`", mixed alphabets) is NOT the primary teardown mechanism: a false-wide selection risks deleting production data, a false-narrow one leaves residue. It is allowed ONLY as a one-off sweep of already accumulated historical garbage, not as the standard test teardown. Standard teardown - the collector (exact references) | +| Physical deletion of untracked objects | What is not cleaned by transaction/auto-tracking (documents via `Документы.X.СоздатьДокумент()`, objects from helpers, objects from `КонструкторОбъекта().Записать()`) must be deleted physically: `ОбменДанными.Загрузка = Истина` + `Удалить()`, in dependent → owner order; not marked for deletion | +| **Collector is mandatory** | A test that generates data MUST register EVERY created object in the test object collector AT THE MOMENT of creation; teardown (`.После()` / final scenario step / `ПослеВсехТестов`) walks the collector and physically deletes everything that survived transaction rollback. Works EVEN if Act/Assert failed. Mechanism detail - the `test-writing` skill ("Test object collector") | +| **Silent swallowing of delete errors is forbidden** | Collector drain/teardown is NOT allowed to silently swallow a `Удалить()` error. Deletion can legitimately fail on a version conflict (optimistic-lock: the object was concurrently rewritten by a subscription/background job between read and delete) → it MUST retry with a fresh `ПолучитьОбъект()` (limited number of attempts), retrying ONLY on a version conflict. If after retries the object is still not deleted OR the error is non-conflict, write an Error-level record to the registration log (NOT Warning) with the type+reference of the undeleted residue and continue draining the remaining references (do not abort the drain with an exception — otherwise it will orphan the rest). A deletion error swallowed in `Попытке` without a visible Error-level trace is an invisible leak that delta-0 acceptance in the registration log will not catch | +| End-to-end test — cleanup step | If data must live during the run (end-to-end) — this is the only exception, and the test MUST end with an explicit step that deletes everything created (via the collector) | +| Acceptance = delta-0 | Checking the delta of key objects before/after is part of the phase acceptance criterion; non-zero delta = test not accepted | +| Band-aid forbidden | Hiding created objects from queries/scheduled jobs (object exclusion flag, special prefix filter) does NOT count as cleanup — the object must be physically deleted | +| Fragile selectors forbidden | Cleanup by scanning the database by NAME/prefix/regexp ("delete everything `ПОДОБНО "Test%"`", mixing alphabets) is NOT the primary teardown mechanism: a false-wide selection risks deleting production data, a false-narrow one leaves residue. It is allowed ONLY as a one-off sweep of already accumulated historical garbage, not as the standard test teardown. Standard teardown — the collector (exact references) | ## Relation to mechanisms -- `yaxunit-isolation` - HOW to isolate a server-side YaxUnit test (`.ВТранзакции()`, allowed exceptions, teardown `.После()`). This rule defines the INVARIANT (delta-0), that rule defines the mechanism. -- `vanessa-test-isolation-policy` - isolation of Vanessa scenarios (creation of their own objects). Reinforced by the requirement for physical cleanup down to zero. +- `yaxunit-isolation` — HOW to isolate a server-side YaxUnit test (`.ВТранзакции()`, permitted exceptions, teardown `.После()`). This rule defines the INVARIANT (delta-0), that rule — the mechanism. +- `vanessa-test-isolation-policy` — isolation of Vanessa scenarios (creating their own objects). Reinforced by the requirement for physical cleanup down to zero. --- depends_on: diff --git a/framework_eng/rules/vanessa-diagnostics-policy/SKILL.md b/framework_eng/rules/vanessa-diagnostics-policy/SKILL.md index e7eab59d..2f79a69c 100644 --- a/framework_eng/rules/vanessa-diagnostics-policy/SKILL.md +++ b/framework_eng/rules/vanessa-diagnostics-policy/SKILL.md @@ -1,22 +1,22 @@ --- name: vanessa-diagnostics-policy -description: Vanessa run failed -> diagnose in the order event log -> visual -> tech log. Apply the `vanessa-diagnostics` skill. +description: "When Vanessa fails: event log -> visual -> tech log" alwaysApply: true --- -# Vanessa Diagnostics Policy +# Vanessa Automation Diagnostics Policy -> **Trigger:** an unsuccessful or suspicious scenario run. When triggered, apply the `vanessa-diagnostics` skill (`framework/skills/tool-usage/vanessa/vanessa-diagnostics/SKILL.md`). +> **Trigger:** unsuccessful or suspicious scenario run. When triggered, apply the `vanessa-diagnostics` skill (`framework/skills/tool-usage/vanessa/vanessa-diagnostics/SKILL.md`). ## MUST (source priority) | Priority | Source | Condition | -|-----------|--------|----------| -| 1st | Registration log (`event-log`) | Main source of errors - check first | -| 2nd | Visual diagnostics (noVNC / screenshot) | If a GUI blockage or `Security Warning` is suspected | -| 3rd | Tech log | Only if `event-log` and visual diagnostics did not provide an answer | +|-----------|----------|---------| +| 1st | Registration log (`event-log`) | Primary source of errors — check first | +| 2nd | Visual diagnostics | For test client form state, GUI blocking, modal/manager window, and `Security warning` — visual artifact via `va-visual-check`: first VA MCP screenshot, with fallback if necessary and the reason recorded | +| 3rd | Technology log | Only if `event-log` and visual diagnostics did not provide an answer | -- Do not rely blindly on local time windows: ClickHouse and local time may diverge (timezone drift). +- Do not rely blindly on local time windows: ClickHouse and local time may differ (timezone drift). --- depends_on: diff --git a/framework_eng/rules/vanessa-run-loop/SKILL.md b/framework_eng/rules/vanessa-run-loop/SKILL.md index 731fb679..d4428fcd 100644 --- a/framework_eng/rules/vanessa-run-loop/SKILL.md +++ b/framework_eng/rules/vanessa-run-loop/SKILL.md @@ -1,6 +1,6 @@ --- name: vanessa-run-loop -description: Changed `.feature` / `tests.va` config / MCP extension -> `v8-runner test va` run is mandatory. Apply the `v8-runner` and `vanessa-diagnostics` skills. +description: "After feature/tests.va/MCP changes, run VA tests" alwaysApply: true --- diff --git a/framework_eng/rules/vanessa-scenario-policy/SKILL.md b/framework_eng/rules/vanessa-scenario-policy/SKILL.md index b629c20d..e2f8f9cf 100644 --- a/framework_eng/rules/vanessa-scenario-policy/SKILL.md +++ b/framework_eng/rules/vanessa-scenario-policy/SKILL.md @@ -1,6 +1,6 @@ --- name: vanessa-scenario-policy -description: You are writing / updating a Vanessa feature file -> apply the vanessa-authoring skill. +description: "When writing Vanessa features, apply authoring rules" alwaysApply: true --- @@ -8,32 +8,32 @@ alwaysApply: true > **Trigger:** creating or modifying a `.feature` file. When triggered, apply the `vanessa-authoring` skill (`framework/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md`). -## Test Layer Purpose (MUST - fundamental) +## Purpose of Testing Layers (MUST - fundamental) -> A scenario (Vanessa) test exists to verify **client-side behavior through the UI, simulating user actions**. This is its direct purpose. Server-side business logic belongs to **unit tests** (YaxUnit). Do not mix layers: a server test wrapped in Vanessa does not verify what scenario tests are meant for. +> A scenario (Vanessa) test exists to verify **client behavior through the UI, imitating user actions**. That is its direct purpose. Server-side business logic is the domain of **unit tests** (YaxUnit). Do not mix the layers: a server test wrapped in Vanessa does not verify what scenario tests are meant to verify. | What we verify | Which test | |---------------|--------------| -| Server/business logic: fill validation (`ОбработкаПроверкиЗаполнения`), posting, calculations, queries, registers, regulations | **Unit (YaxUnit)** | -| Client/UI behavior: opening a form, `ПриСозданииНаСервере`/`ПриОткрытии`, visibility/availability/requiredness of elements, reaction to input (`ПриИзменении`), form commands, navigation, input based on another object | **Scenario (Vanessa) through the UI** | +| Server-side/business logic: fill validation (`ОбработкаПроверкиЗаполнения`), posting, calculations, queries, registers, scheduled jobs | **Unit (YaxUnit)** | +| Client/UI behavior: opening a form, `ПриСозданииНаСервере`/`ПриОткрытии`, visibility/accessibility/required state of elements, reaction to input (`ПриИзменении`), form commands, navigation, input based on | **Scenario (Vanessa) through UI** | -- **Verified behavior goes ONLY through the UI.** The scenario opens the form and simulates the user with real UI steps (`window opens`, `in the field named ... I enter`, `I click the ... button`, `I see the element`, `element ... is available`). It is **FORBIDDEN** to replace the user action path with a server call (`CheckFill()`, `WriteObject()`, direct call to a common module) - such a "scenario" is a unit test in a Vanessa costume and misses form-layer defects. -- **Server-side BSL in Vanessa is allowed ONLY for data preparation/cleanup** (fixtures, setup, teardown - see the two-session split below), NOT as a substitute for the verified user scenario. Boundary: code "sets the stage" - server-side is allowed; code "verifies behavior" - only through the UI. -- **Why this rule exists.** If a scenario calls server logic instead of opening the form, **all client logic remains completely untested** - it is not covered by the scenario (it bypassed the UI), nor by a unit test (that is not its layer). The following go unverified: client handlers (`&НаКлиенте`, `ПриОткрытии`, `ПриИзменении`, command handlers), form client-server calls (`ПриСозданииНаСервере` and others), conditional formatting, visibility/availability/requiredness of elements, reaction to input and navigation, the structure of the form itself. Result - server validation is green, but the form crashes at runtime (broken form structure, unhandled event, incorrect visibility - for example "Object field not found"), and this only surfaces for the user. Only a scenario that really opens the form and simulates the user checks client logic (`create -> window opens -> I see the element ... / enter / click`). +- **Verified behavior goes ONLY through the UI.** The scenario opens the form and imitates the user with real UI steps (`window opened`, `in the field named ... I enter`, `I click the ... button`, `I see the element`, `element ... is available`). It is **FORBIDDEN** to replace the user action path with a server call (`ПроверитьЗаполнение()`, `ЗаписатьОбъект()`, direct call of a common module) - such a "scenario" is a unit test in Vanessa clothing and misses form-layer defects. +- **Server-side BSL in Vanessa is allowed ONLY for data preparation/cleanup** (fixtures, setup, teardown - see the two-session split below), NOT as a replacement for the checked user scenario. Boundary: code "prepares the stage" - server-side is allowed; code "checks behavior" - only through the UI. +- **Why this rule exists.** If a scenario calls server-side logic instead of opening the form, **all client logic remains completely untested** - it is covered by neither the scenario (it bypassed the UI) nor the unit test (this is not its layer). The following remain unverified: client handlers (`&НаКлиенте`, `ПриОткрытии`, `ПриИзменении`, command handlers), client-server form calls (`ПриСозданииНаСервере` and others), conditional formatting, visibility/accessibility/required state of elements, reaction to input and navigation, and the structure of the form itself. The result is that server-side validation is green, but the form fails at runtime (broken form structure, unhandled event, incorrect visibility - for example "Object field not found"), and this surfaces only for the user. Client logic is verified ONLY by a scenario that actually opens the form and imitates the user (`create -> window opened -> I see element ... / enter / click`). ## MUST -- The scenario is based on the task specification or an existing business case - no invented cases. +- The scenario is based on the task specification or an existing business case - no fictional cases. - One scenario = one observable behavior. -- Before a new step, look for an existing one in the Vanessa library and project scenarios. +- Before adding a new step, look for an existing one in the Vanessa library and the project scenarios. - The first scenario for a new case is a short smoke test. -- The scenario runs under a specific **business user**, not under admin/AgentAI - the only exception is if the function being checked is available exclusively to an administrator; the user is determined from the task description, and if absent - **ask a person**. -- **Two-session split:** infrastructure data preparation (creating objects, VAExtension steps, BSL fixtures) - under the technical user (AgentAI); business flow (behavior verification) - under the specific business user. Switch via `And I close TestClient` + new `Given I connect TestClient`. You cannot assign technical roles to a business user just to pass infrastructure steps. -- **Task tag is mandatory.** Each `.feature` file MUST contain the `@task-` tag (for example `@task-103`) at the `Feature:` level. -- **Source comment.** At the top of the file (before the tags) MUST be a comment: `# Task: - `. -- Do not guess logic - read the code (delegate to Explorer / `code-navigation`). A discrepancy between code and test is a discovered mismatch; record it as a result. -- **Do not guess the interface** - names and titles of elements, fields, buttons, tabs, availability and state of elements are taken from the **real rendered interface**, examined through the web client (`gui-control` / `screenshot` / `chrome-devtools` snapshot), not guessed from code or memory. Remember the difference in identifiers: the steps "contains strings" / "go to line" expect the **title**, while "remember the field value" expects the **name** - the exact value is learned by inspecting the form, not guessed. A discrepancy between the scenario and the real UI is a discovered mismatch; record it as a result. -- **Manual fill-in before the scenario.** A new document scenario is written AFTER manually filling the form in the web client and checking the form composition **at every step** (the field value affects visibility/requiredness of other fields); the key header fields and required tabular sections (≥ several rows) are filled; the document's hint/reference data have been studied; scrollbars hiding fields have been taken into account. If needed by the test meaning, the document is **saved and posted**, and pop-up errors at the bottom of the screen are analyzed and the filling corrected. Fill-in scenarios are reusable "building blocks" (`@exportscenarios`), and one document can have several. Details - `vanessa-authoring`. +- The scenario is executed under a specific **business user**, not under admin/AgentAI - the only exception is if the function being checked is available exclusively to an administrator; the user is determined from the task description, and if it is missing, **ask a human**. +- **Two-session split:** infrastructure data preparation (creating objects, VAExtension steps, BSL fixtures) is done under the technical user (AgentAI); the business flow (behavior verification) is done under a specific business user. Switch via `And I close TestClient` + a new `Given I connect TestClient`. You cannot assign technical roles to the business user just to pass infrastructure steps. +- **Task tag is mandatory.** Every `.feature` file MUST contain the tag `@task-<ID>` (for example `@task-103`) at the `Feature:` level. +- **Source comment.** The file header (before the tags) MUST contain the comment: `# Task: <ID> - <title>`. +- Do not guess the logic - read the code (delegate to Explorer / `code-navigation`). A discrepancy between code and test is a discovered mismatch; record it as a result. +- **Do not guess the interface** - names and titles of elements, fields, buttons, tabs, availability and state of elements are taken from the **real rendered interface**, examined through Vanessa/TestClient or through the fallback via `va-visual-check`, not from guesses based on code or memory. Remember the difference between identifiers: the steps "contains strings" / "go to line" expect the **title (Title)**, while "remember the field value" expects the **name (name)** - the exact value is learned by inspecting the form, not guessed. A discrepancy between the scenario and the real UI is a discovered mismatch; record it as a result. +- **Manual fill-in before the scenario.** A new document scenario is written AFTER filling the form manually through Vanessa/TestClient with verification of the form composition **at every step** (the field value affects visibility/requiredness of other fields); the key header fields and required tabular sections (>= several rows) are filled; the document hint/reference data have been studied; scrollbars hiding fields have been taken into account. If needed by the test meaning, the document is **saved and posted**, pop-up errors at the bottom of the screen are analyzed and the filling corrected. Fill-in scenarios are reusable "building blocks" (`@exportscenarios`), and one document can have several. Details - `vanessa-authoring`. --- depends_on: diff --git a/framework_eng/rules/vanessa-security-warning/SKILL.md b/framework_eng/rules/vanessa-security-warning/SKILL.md index 34f2aee3..49fe6d19 100644 --- a/framework_eng/rules/vanessa-security-warning/SKILL.md +++ b/framework_eng/rules/vanessa-security-warning/SKILL.md @@ -1,25 +1,26 @@ --- name: vanessa-security-warning -description: An entry about `Security Warning` in the event log means mandatory visual verification. Apply the `gui-control` / `screenshot` skills. +description: "Security Warning in the event log requires visual verification" alwaysApply: true --- -# Vanessa Security Warning Alerts +# Vanessa Security Warnings -> **Trigger:** an entry about `Security Warning` in the event log. When it occurs, apply the `gui-control` skills (`framework/skills/tool-usage/browser-ui/gui-control/SKILL.md`) and `screenshot` (`framework/skills/tool-usage/browser-ui/screenshot/SKILL.md`). +> **Trigger:** a `Security Warning` entry in the event log. When it fires, apply the `gui-control` skill (`framework/skills/tool-usage/browser-ui/gui-control/SKILL.md`) and `screenshot` (`framework/skills/tool-usage/browser-ui/screenshot/SKILL.md`). ## MUST | Requirement | Description | |------------|----------| -| Event log as a trigger | An entry about `Security Warning` in the event log -> mandatory visual verification | -| Visual verification is mandatory | MUST use a real screen: noVNC or a screenshot | -| Do not rely on X11 heuristics | You cannot draw conclusions based only on `wmctrl`/`xwininfo`/window titles | +| Event log as trigger | An entry for `Security Warning` in the event log → mandatory visual verification | +| Visual verification is mandatory | MUST use a VA MCP screenshot of the real test client window | +| Do not rely on X11 heuristics | Do not draw conclusions only from `wmctrl`/`xwininfo`/window titles; obtain the visual artifact via `va-visual-check` | +| Screenshot is validated | Check that the PNG is not empty/black; handle Linux/Xvfb and fallback cases via `va-visual-check` | | Trust-flow only for the first run | The first run after changing the EPF does not count as a valid test run | --- depends_on: - framework/skills/tool-usage/browser-ui/gui-control/SKILL.md - - framework/skills/tool-usage/browser-ui/screenshot/SKILL.md + - framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md - framework/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md --- diff --git a/framework_eng/rules/vanessa-test-isolation-policy/SKILL.md b/framework_eng/rules/vanessa-test-isolation-policy/SKILL.md index b7812e4f..5b19ca42 100644 --- a/framework_eng/rules/vanessa-test-isolation-policy/SKILL.md +++ b/framework_eng/rules/vanessa-test-isolation-policy/SKILL.md @@ -1,12 +1,12 @@ --- name: vanessa-test-isolation-policy -description: You are writing a Vanessa scenario with data writes → full isolation (the test creates its own objects). Apply the vanessa-authoring skill. +description: "For data-writing Vanessa tests, isolate test data" alwaysApply: true --- # Vanessa Test Data Isolation Policy -> **Trigger:** writing a scenario that creates, modifies, or writes objects to the DB. When triggered, apply the `vanessa-authoring` skill (`framework/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md`). +> **Trigger:** writing a scenario that creates, modifies, or writes objects to the database. When triggered, apply the `vanessa-authoring` skill (`framework/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md`). ## Isolation Criterion (MUST) @@ -15,7 +15,7 @@ alwaysApply: true | Yes | **Full** | The test creates its own objects | | No | Relaxed | Existing stable objects | -The main question: **can the test pass again** without intervention? If not, increase the isolation. +The main question: **can the test pass again** without intervention? If not, increase isolation. ## MUST for Full Isolation @@ -23,7 +23,7 @@ The main question: **can the test pass again** without intervention? If not, inc - Identifiers are passed between steps through Vanessa variables (`$VarName$`). - When switching TestClient, the document is saved and closed **before** switching. - Do not post test documents unless necessary - movements affect other tests. -- Business-critical dependencies (counterparties with contracts, limit settings) must be recorded in the scenario comment with the specific object indicated. +- Business-critical dependencies (counterparties with contracts, limit settings) should be fixed in the scenario comment, with the specific object indicated. --- depends_on: diff --git a/framework_eng/rules/vanessa-tests-location/SKILL.md b/framework_eng/rules/vanessa-tests-location/SKILL.md index 82d08fcf..592c055b 100644 --- a/framework_eng/rules/vanessa-tests-location/SKILL.md +++ b/framework_eng/rules/vanessa-tests-location/SKILL.md @@ -1,6 +1,6 @@ --- name: vanessa-tests-location -description: You create / update a Vanessa feature file → follow the location convention. Apply the `vanessa-authoring` skill for details. +description: "When adding Vanessa features, follow location rules" alwaysApply: true --- diff --git a/framework_eng/rules/yaxunit-isolation/SKILL.md b/framework_eng/rules/yaxunit-isolation/SKILL.md index 78fa1edc..4adab66a 100644 --- a/framework_eng/rules/yaxunit-isolation/SKILL.md +++ b/framework_eng/rules/yaxunit-isolation/SKILL.md @@ -1,36 +1,36 @@ --- name: yaxunit-isolation -description: You are writing a server-side YaxUnit test that writes to the DB -> mandatory transactional isolation via .ВТранзакции(). Apply the test-writing skill. +description: "For DB-writing YaxUnit tests, use transaction" alwaysApply: false --- -# YaxUnit test isolation (transaction rollback) +# YaxUnit Test Isolation (transaction rollback) -> **Trigger:** a server test (`ДобавитьСерверныйТест`) writes to the DB - creates, posts, modifies, or deletes objects. When this happens, apply the `test-writing` skill (`framework/skills/bsl-practices/test-writing/SKILL.md`), section "Isolating test data". +> **Trigger:** a server test (`ДобавитьСерверныйТест`) writes to the DB - it creates, posts, modifies, and deletes objects. When this happens, apply the `test-writing` skill (`framework/skills/bsl-practices/test-writing/SKILL.md`), section "Isolating test data". ## Principle -A test that writes to the DB **must roll back its changes** - otherwise every run leaves garbage in the database, tests become non-idempotent, and the database gradually degrades. YaxUnit solves this with the built-in `.ВТранзакции()` mechanism: a transaction opens before each test and rolls back after the test. +A test that writes to the DB **must roll back its changes** - otherwise each run leaves garbage in the database, tests become non-idempotent, and the database gradually degrades. YaxUnit solves this with the built-in `.ВТранзакции()` mechanism: before each test, a transaction is opened; after the test, it is rolled back. ## MUST | Requirement | Description | |---|---| | `.ВТранзакции()` by default | Any set of server tests that write to the DB is registered with `.ВТранзакции()` immediately after `ДобавитьТестовыйНабор()` | -| Catalogs - via `ЮТест.Данные()` | Create catalog items only through `ЮТест.Данные().СоздатьЭлемент(...)` or `КонструкторОбъекта(...).Записать()` - then they are tracked and deleted automatically | -| Exception -> explicit justification | A set without `.ВТранзакции()` MUST contain a comment before `ДобавитьТестовыйНабор()` stating the reason for the exception (one of the three below) + teardown via `.После("ИмяПроцедурыОчистки")` | -| Documents without `.ВТранзакции()` -> teardown | Documents created through `Документы.X.СоздатьДокумент()` (not through `ЮТест.Данные()`) are NOT tracked by auto-cleanup - they require explicit teardown in `.После()` | +| Catalogs via `ЮТест.Данные()` | Create catalog items only through `ЮТест.Данные().СоздатьЭлемент(...)` or `КонструкторОбъекта(...).Записать()` - then they are tracked and removed automatically | +| Exception -> explicit rationale | A set without `.ВТранзакции()` MUST contain a comment before `ДобавитьТестовыйНабор()` stating the reason for the exception (one of the three below) + teardown via `.После("ИмяПроцедурыОчистки")` | +| Documents without `.ВТранзакции()` -> teardown | Documents created via `Документы.X.СоздатьДокумент()` (not via `ЮТест.Данные()`) are NOT tracked by auto-cleanup - they require explicit teardown in `.После()` | | Client tests - without `.ВТранзакции()` | `ДобавитьКлиентскийТест` runs in the client context, where transactional rollback is unavailable | -## Permitted exceptions to `.ВТранзакции()` +## Allowed Exceptions from `.ВТранзакции()` -### (a) Negative posting tests (expected Denial) +### (a) Negative posting tests (expected Refusal) -The test verifies that document posting is **forbidden** (`Отказ = Истина` is set in the handler). A nested write transaction that ends in an error **poisons** the outer one: subsequent reads return "Errors have already occurred in this transaction!". The solution is not to wrap such sets in `.ВТранзакции()`, to create objects through `ЮТест.Данные()` (they will be removed by `.УдалениеТестовыхДанных()`), and to additionally clean up the document in teardown. +The test checks that posting a document is **forbidden** (`Отказ = Истина` is set in the handler). A nested write transaction with an error **poisons** the outer one: subsequent reads return "Errors have already occurred in this transaction!". The solution is not to wrap such sets in `.ВТранзакции()`, to create objects via `ЮТест.Данные()` (they will be removed by `.УдалениеТестовыхДанных()`), and to additionally clean up the document in teardown. ```bsl -// Exception (a): negative posting test - the expected Denial poisons the outer transaction. -// Isolation via ЮТест.Данные() + .УдалениеТестовыхДанных() + teardown in .После(). +// Исключение (а): негативный тест проведения — ожидаемый Отказ отравляет внешнюю транзакцию. +// Изоляция через ЮТест.Данные() + .УдалениеТестовыхДанных() + teardown в .После(). ЮТТесты .ДобавитьТестовыйНабор("Запрет проведения без договора") .УдалениеТестовыхДанных() @@ -43,8 +43,8 @@ The test verifies that document posting is **forbidden** (`Отказ = Исти Some production procedures explicitly check for the absence of an active transaction (two-phase commits, real external API calls, writes to information registers with a unique key). Running such code inside `.ВТранзакции()` causes an error or unexpected behavior in the production code itself. ```bsl -// Exception (b): production code contains a ТранзакцияАктивна() guard - it cannot run in a transaction. -// Teardown performs manual cleanup via ЮТест.Данные().УстановитьЗначениеРеквизита(). +// Исключение (б): прод-код содержит гвард ТранзакцияАктивна() — нельзя запускать в транзакции. +// Teardown выполняет ручную очистку через ЮТест.Данные().УстановитьЗначениеРеквизита(). ЮТТесты .ДобавитьТестовыйНабор("Двухфазная фиксация позиции") .После("ОчиститьДанныеДвухфазнойФиксации") @@ -53,11 +53,11 @@ Some production procedures explicitly check for the absence of an active transac ### (c) Client context -`ДобавитьКлиентскийТест` - transactional rollback on the client is unavailable by platform architecture. Test data under client tests is created and cleaned up through `Перед`/`После` handlers in the server context. +`ДобавитьКлиентскийТест` - transactional rollback on the client is unavailable by platform architecture. Test data under client tests is created and cleaned through `Перед`/`После` handlers in the server context. -## Object re-read pattern when reposting +## Object Re-reading Pattern for Reposting -A test that changes a document's write mode (posting -> unposting -> reposting) **must re-read the object** between transitions via `ДокОбъект = Ссылка.ПолучитьОбъект()` - this models form behavior: +A test that changes the document write mode (posting -> unposting -> reposting) **must reread the object** between mode changes via `ДокОбъект = Ссылка.ПолучитьОбъект()` - this mirrors form behavior: ```bsl // Провести @@ -73,9 +73,9 @@ A test that changes a document's write mode (posting -> unposting -> reposting) ДокОбъект.Записать(РежимЗаписиДокумента.Проведение); ``` -**Important (platform 8.3.27):** programmatic reposting in a server session can trigger the platform error `[ОшибкаХранимыхДанных]` (a stack with no application frames). Neither re-reading nor `.ВТранзакции()` fixes it - this is a platform limitation. In that case, reposting idempotence is verified at the **scenario layer** (Vanessa, the path through the form), and the unit test is written with `ЮТест.Пропустить()` and an explicit justification. +**Important (platform 8.3.27):** programmatic reposting in a server session can trigger a platform error `[ОшибкаХранимыхДанных]` (stack without application frames). Neither rereading nor `.ВТранзакции()` fixes it - this is a platform limitation. In this case, reposting idempotence is checked at the **scenario layer** (Vanessa, path through the form), and the unit test is written with `ЮТест.Пропустить()` and an explicit rationale. -## Example of correct registration with `.ВТранзакции()` +## Example of Correct Registration with `.ВТранзакции()` ```bsl Процедура ИсполняемыеСценарии() Экспорт diff --git a/framework_eng/skills/agent-process/quick-fix/SKILL.md b/framework_eng/skills/agent-process/quick-fix/SKILL.md index 8706586b..f60dc27b 100644 --- a/framework_eng/skills/agent-process/quick-fix/SKILL.md +++ b/framework_eng/skills/agent-process/quick-fix/SKILL.md @@ -1,6 +1,6 @@ --- name: quick-fix -description: MUST use WHEN task is classified as simple (< 20 lines, 1 file, no new metadata objects, no architectural decisions). Provides a short cycle of 3 steps with a guard on self-path and mandatory verify. +description: MUST use WHEN the task is classified as simple (< 20 lines, 1 file, no new metadata objects, no architectural decisions). Provides a 3-step short cycle with a guard on the self path and mandatory verify. installable: true alwaysApply: false --- @@ -12,48 +12,52 @@ alwaysApply: false ## When it applies -Lead (main flow) classified the task as **simple** (see orchestrator profile, Layer 1) and -chose the short cycle. In the short cycle, Lead may execute it himself or delegate one subagent — under -the guard below. +Lead (main flow) classified the task as **simple** (see the orchestrator profile, Layer 1) and +selected the short cycle. In the short cycle, Lead may execute it directly or delegate one subagent +under the guard below. -## Guard on self-path (MUST, otherwise slippery slope) +## Guard on the self path (MUST, otherwise slippery slope) > self-execution is the only mode where the main flow has no cross-review. Therefore the boundaries are strict -> and are checked BEFORE any change is made. +> and are checked BEFORE the edit begins. -- self is allowed ONLY within the boundaries: `< 20 lines, 1 file, no new metadata objects, no +- self is allowed ONLY within these boundaries: `< 20 lines, 1 file, no new metadata objects, no architectural decisions`; -- **exceeding any criterion -> forced transition to full cycle (delegation), self is forbidden**; -- **the verify step (step 3) is mandatory EVEN for self** — the only compensation for the absence of cross-review. +- **exceeding any criterion -> forced transition to the full cycle (delegation), self is forbidden**; +- **the verify step (step 3) is mandatory EVEN for self** - the only compensation for the lack of cross-review. ## Steps ### 1. Find (Explorer → Economy) `navigate_symbol` + `get_call_graph` → path to the module, dependencies, make sure the change is localized -(confirmation of guard boundaries: one file, no architectural links). +(guard boundary confirmation: one file, no architectural links). ### 2. Fix (Developer → Mid) -The minimum necessary change according to `coding-standards`. No "improvements" beyond the scope of the task. +The minimum necessary change according to `coding-standards`. No "improvements" beyond the task. ### 3. Verify (Developer → Mid) — MANDATORY, including for self 1. `get_diagnostics` — quick check of the changed file 2. `run_tests` — if there are tests for the module 3. `check_syntax` — final check before commit +4. Coverage for the runtime layer of the change: + - if server logic/server method/query was changed - update and run a YaxUnit test; if there is no test, add a minimal YaxUnit test or escalate to the full cycle; + - if the UI or client context was changed (form, command, button, client handler, `ОткрытьФорму`, visibility/accessibility) - perform a scenario check of the user action in the live infobase/test client: open the entrypoint, perform the action, make sure it starts/completes without an error; + - if verification is technically impossible - explicitly record it in the response as an uncovered risk; silent omission is forbidden. -## Escalation to full cycle +## Escalation to the full cycle | Situation | Action | |----------|----------| | Tests fail after the change | Fix or escalate to full | | Multiple modules / architecture / review / > 20 lines / new metadata object | full cycle | -**Escalation protocol:** record the state → **the orchestrator, in its own context, raises phase management**. -The orchestration discipline and phase form are already durable in its profile (`framework/subagents/orchestrator.md`, +**Escalation protocol:** record the state → **the orchestrator raises phase management in place**. +Orchestration discipline and the phase form are already durable in its profile (`framework/subagents/orchestrator.md`, Layer 2); it reads the detailed phase mechanics from `framework/workflows/full-cycle/SKILL.md` when entering the phase. -This is NOT "passing to an external document" and NOT starting another session — Lead simply puts on the hat +This is NOT "handing off to an external document" and NOT launching another session - Lead simply puts on the hat of the full-cycle orchestrator and proceeds with Phase 1 (or Phase 3, if the spec already exists). --- diff --git a/framework_eng/skills/bsl-practices/api-design/SKILL.md b/framework_eng/skills/bsl-practices/api-design/SKILL.md index 15826a11..741416d0 100644 --- a/framework_eng/skills/bsl-practices/api-design/SKILL.md +++ b/framework_eng/skills/bsl-practices/api-design/SKILL.md @@ -1,6 +1,6 @@ --- name: api-design -description: "Use for designing and reviewing the public API of 1C subsystems. Helps classify export methods into 5 categories, verify backward compatibility, and design versioning with deprecated wrappers." +description: "Design or review public APIs of 1C subsystems" --- # API Design — design and review of 1C subsystem interfaces diff --git a/framework_eng/skills/bsl-practices/background-jobs/SKILL.md b/framework_eng/skills/bsl-practices/background-jobs/SKILL.md index 3ed848ce..a58f6ed4 100644 --- a/framework_eng/skills/bsl-practices/background-jobs/SKILL.md +++ b/framework_eng/skills/bsl-practices/background-jobs/SKILL.md @@ -1,6 +1,6 @@ --- name: background-jobs -description: "Use for designing, diagnosing, and fixing 1C background and scheduled jobs. Helps ensure idempotency, retry policy, checkpointing, mutexes, and separation of retryable/permanent errors." +description: "Design or debug 1C background and scheduled jobs" skills: - architect - developer-code @@ -297,7 +297,7 @@ v8 run --ib <путь_к_ИБ> --event-log --filter "ФоновоеЗадани **Checking active background jobs in the event log:** -Look for events named `background job`. A stuck job is a `Start` event without a paired `Finish` and without `Error` - this is a candidate for a stale lock. +Look for events named `Background job`. A stuck job is a `Start` event without a paired `Finish` and without `Error` - this is a candidate for a stale lock. --- diff --git a/framework_eng/skills/bsl-practices/coding-standards/SKILL.md b/framework_eng/skills/bsl-practices/coding-standards/SKILL.md index 2030b2a7..e564e464 100644 --- a/framework_eng/skills/bsl-practices/coding-standards/SKILL.md +++ b/framework_eng/skills/bsl-practices/coding-standards/SKILL.md @@ -1,6 +1,6 @@ --- name: coding-standards -description: "BSL coding standards (1C). This skill teaches the agent to write code in the built-in 1C language (BSL) in accordance with the standards of the 1C:Enterprise platform and ITS recommendations." +description: "Apply 1C coding standards when writing or reviewing BSL" alwaysApply: false --- @@ -8,15 +8,15 @@ alwaysApply: false ## Rule 1: Variable naming - CamelCase in Russian -ITS standard: "Module texts" - names in Russian, CamelCase. +ITS standard: "Module Texts" - names in Russian, CamelCase. | Element | Format | Example | |---------|--------|--------| -| Variable | NounOrPhrase | `КоличествоСтрок`, `ДатаНачалаПериода` | -| Procedure | VerbPhrase | `ЗаполнитьТабличнуюЧасть`, `УстановитьОтбор` | -| Function | NounOrQuestion | `ПолучитьСписокДокументов`, `ЭтоНовый` | -| Boolean variable | Affirmative form | `ЭтоНовый`, `РазрешеноРедактирование`, `ЕстьОшибки` | -| Parameter | LikeVariable | `ДокументСсылка`, `РежимОткрытия` | +| Variable | СуществительноеИлиФраза | `КоличествоСтрок`, `ДатаНачалаПериода` | +| Procedure | ГлагольнаяФраза | `ЗаполнитьТабличнуюЧасть`, `УстановитьОтбор` | +| Function | СуществительноеИлиВопрос | `ПолучитьСписокДокументов`, `ЭтоНовый` | +| Boolean variable | Утвердительная форма | `ЭтоНовый`, `РазрешеноРедактирование`, `ЕстьОшибки` | +| Parameter | КакПеременная | `ДокументСсылка`, `РежимОткрытия` | ```bsl Процедура ЗаполнитьТабличнуюЧастьТовары(ДокументОбъект, ДанныеЗаполнения) @@ -37,14 +37,14 @@ ITS standard: "Module texts" - names in Russian, CamelCase. ## Rule 2: Module structure - interface and implementation sections -ITS standard: "Module structure" - regions (#Область) in a specific order. +ITS standard: "Module Structure" - regions (#Область) in a defined order. -### Section order for a common module +### Order of sections in a common module ```bsl #Область ПрограммныйИнтерфейс -// Экспортные процедуры и функции — публичный API модуля. +// Exported procedures and functions — public API of the module. Функция ПолучитьКурсВалюты(Валюта, ДатаКурса) Экспорт // ... @@ -54,7 +54,7 @@ ITS standard: "Module structure" - regions (#Область) in a specific order #Область СлужебныйПрограммныйИнтерфейс -// Экспортные процедуры для вызова только из других модулей данной подсистемы. +// Exported procedures for calls only from other modules of this subsystem. Функция ПересчитатьКурсВнутренний(ПараметрыПересчета) Экспорт // ... @@ -64,7 +64,7 @@ ITS standard: "Module structure" - regions (#Область) in a specific order #Область СлужебныеПроцедурыИФункции -// Внутренняя реализация. Не экспортные. +// Internal implementation. Not exported. Функция СформироватьЗапросКурса(Валюта, Дата) // ... @@ -73,7 +73,7 @@ ITS standard: "Module structure" - regions (#Область) in a specific order #КонецОбласти ``` -### Section order for an object module +### Order of sections in an object module ```bsl #Область ОписаниеПеременных @@ -108,14 +108,14 @@ ITS standard: "Module structure" - regions (#Область) in a specific order ## Rule 3: Compilation directives - &НаКлиенте, &НаСервере, &НаСервереБезКонтекста -When `&НаСервере` is called, the platform serializes **the entire form context** back and forth. `&НаСервереБезКонтекста` passes only parameters - drastically less traffic. +When calling `&НаСервере`, the platform serializes **the entire form context** back and forth. `&НаСервереБезКонтекста` passes only parameters - drastically less traffic. | Directive | Where it runs | Access to form data | When to use | |-----------|----------------|----------------------|-------------------| | `&НаКлиенте` | Client (thin/web) | Yes (client copy) | Interactive logic: dialogs, navigation | -| `&НаСервере` | Server | Yes (full form context) | Need access to form attributes + database | -| `&НаСервереБезКонтекста` | Server | No | Database queries, calculations without form data | -| `&НаКлиентеНаСервереБезКонтекста` | Both client and server | No | Pure calculations, validation without database | +| `&НаСервере` | Server | Yes (full form context) | Need access to form attributes + DB | +| `&НаСервереБезКонтекста` | Server | No | Queries to DB, calculations without form data | +| `&НаКлиентеНаСервереБезКонтекста` | Both client and server | No | Pure calculations, validation without DB | ```bsl &НаКлиенте @@ -139,7 +139,7 @@ When `&НаСервере` is called, the platform serializes **the entire form ## Rule 6: Do not shadow the global context -A local variable with the name of a global collection hides the manager - later references to it in the code will fail. +A local variable with the name of a global collection hides the manager, and later references to it in code will fail. ```bsl // Правильно — конкретное имя @@ -153,21 +153,21 @@ A local variable with the name of a global collection hides the manager - later --- -## Rule 7: String concatenation - do not use `+` in loops +## Rule 7: String concatenation - do not use "+" in loops -In BSL, strings are immutable. `Строка1 + Строка2` in a loop with N iterations gives O(N^2) in memory and time - each iteration copies everything before it. +In BSL, strings are immutable. `Строка1 + Строка2` in a loop of N iterations gives O(N^2) in memory and time - each iteration copies everything before it. ITS standard: "Efficient string handling". ```bsl -// O(N) — массив + СтрСоединить() +// O(N) — array + СтрСоединить() ЧастиСтроки = Новый Массив; Для Каждого Элемент Из КоллекцияДанных Цикл ЧастиСтроки.Добавить(Элемент.Наименование); КонецЦикла; РезультатСтрока = СтрСоединить(ЧастиСтроки, ", "); -// Для фиксированного числа подстановок — СтрШаблон() (до 10 параметров) +// For a fixed number of substitutions — СтрШаблон() (up to 10 parameters) ТекстСообщения = СтрШаблон( НСтр("ru = 'Документ %1 от %2 на сумму %3 руб.'"), НомерДокумента, @@ -177,9 +177,9 @@ ITS standard: "Efficient string handling". --- -## Rule 8: Regions (#Область) for organizing code +## Rule 8: Regions (#Область) for code organization -ITS standard: "Module structure" - mandatory standard regions. +ITS standard: "Module Structure" - mandatory standard regions. ### Standard regions for a form module @@ -228,7 +228,7 @@ ITS standard: "Description of procedures and functions" - exported procedures MU Функция ПолучитьКурсВалюты(Валюта, ДатаКурса = Неопределено) Экспорт ``` -### Comment "why" +### Comment that explains "why" ```bsl // Сумму округляем до копеек, потому что бухгалтерский учёт не допускает дробных копеек, @@ -238,16 +238,16 @@ ITS standard: "Description of procedures and functions" - exported procedures MU --- -## Rule 10: Use НСтр() for string literals +## Rule 10: Use `НСтр()` for string literals All strings shown to the user are wrapped in `НСтр()` for localization. -ITS standard: "Using the НСтр() function". +ITS standard: "Using the `НСтр()` function". ```bsl ТекстПредупреждения = НСтр("ru = 'Документ не может быть проведён. Не заполнена дата.'"); -// С параметрами — НСтр() + СтрШаблон() +// With parameters — НСтр() + СтрШаблон() ТекстСообщения = СтрШаблон( НСтр("ru = 'Остаток товара ""%1"" на складе: %2 %3'"), Номенклатура, @@ -259,7 +259,7 @@ ITS standard: "Using the НСтр() function". ## Rule 11: One procedure - one responsibility -A procedure longer than 100 lines is a signal to decompose it. Splitting into small functions with descriptive names makes the code self-documenting. +A procedure longer than 100 lines is a signal to decompose. Splitting into small functions with speaking names makes the code self-documenting. ```bsl Процедура ОбработкаПроведения(Отказ, РежимПроведения) @@ -276,12 +276,12 @@ A procedure longer than 100 lines is a signal to decompose it. Splitting into sm --- -## Rule 12: Explicitly type parameters in comments +## Rule 12: Explicit type annotations for parameters in comments BSL is dynamically typed. Describing types in the comment for an exported function is the only way to document the contract. ```bsl -// Создаёт новый элемент справочника «Номенклатура» с заполнением по умолчанию. +// Creates a new "Номенклатура" catalog item with default filling. // // Параметры: // ДанныеЗаполнения - Структура - содержит поля: @@ -301,7 +301,7 @@ BSL is dynamically typed. Describing types in the comment for an exported functi ## Rule 13: Do not use `Выполнить()` and `Вычислить()` unless absolutely necessary -Security risk (an eval-like equivalent), invisible to static analysis, difficult to debug. +A security threat (eval-like), invisible to static analysis, hard to debug. ```bsl // Правильно — прямой вызов через метаданные @@ -312,7 +312,7 @@ Security risk (an eval-like equivalent), invisible to static analysis, difficult ## Rule 14: Magic numbers and strings - move them into parameters -Hard-coded values are unclear, duplicated, and not configurable. +Hardcoded values are unclear, duplicated, and not configurable. ```bsl // Правильно — перечисление, значение самодокументировано @@ -320,15 +320,15 @@ Hard-coded values are unclear, duplicated, and not configurable. // ... КонецЕсли; -// Или константа для настраиваемых значений +// Or a constant for configurable values МаксимальноеКоличествоПопыток = Константы.МаксимальноеКоличествоПопытокОтправки.Получить(); ``` --- -## Rule 15: Explicit JOINs instead of dot notation through references +## Rule 15: Explicit JOINs instead of dotted notation through references -Reference chains create implicit JOINs. For compound types, the platform makes a JOIN to **all** possible tables. +Reference chains create implicit JOINs. For composite types, the platform makes a JOIN to **all** possible tables. ```bsl // Правильно — один запрос с явными JOIN @@ -344,7 +344,7 @@ Reference chains create implicit JOINs. For compound types, the platform makes a | Товары.Ссылка = &ДокументСсылка"; ``` -### Incorrect - dot access in a loop (N+1) +### Incorrect - access through a dot in a loop (N+1) ```bsl Для Каждого СтрокаТоваров Из Документ.Товары Цикл @@ -355,9 +355,9 @@ Reference chains create implicit JOINs. For compound types, the platform makes a --- -## Rule 16: Open forms through ОткрытьФорму() +## Rule 16: Open forms through `ОткрытьФорму()` -`ПолучитьФорму()` is for the classic application and does not work in the managed interface. +`ПолучитьФорму()` is for a regular application; it does not work in the managed interface. ```bsl ПараметрыФормы = Новый Структура; @@ -374,9 +374,9 @@ Reference chains create implicit JOINs. For compound types, the platform makes a --- -## Rule 17: Business logic should not live in the form module +## Rule 17: Business logic should not live in a form module -Put write and validation logic in the object module - for testability and reuse. +Place write and validation logic in the object module for testability and reuse. ```bsl // Модуль объекта документа @@ -401,10 +401,10 @@ See `form-patterns`. --- -## Verification via Partner +## Verification via Buddy -- **Code check against standards and БСП equivalents:** `ask_ai_assistant` (VALIDATE_BSL template from `buddy-prompting`). Provide a code fragment - get standards violations and recommendations for replacing them with БСП/platform methods. -- **Check the standard against the primary source:** `ask_ai_assistant` (SEARCH_ITS template from `buddy-prompting`). If the skill differs from ITS, ITS takes priority. +- **Code standards and BСП analog check:** `ask_ai_assistant` (VALIDATE_BSL template from `buddy-prompting`). Give a code snippet - get standard violations and recommendations for replacement with BСП/platform methods. +- **Check the standard at the source:** `ask_ai_assistant` (SEARCH_ITS template from `buddy-prompting`). If the skill conflicts with ITS, ITS has priority. --- depends_on: [] diff --git a/framework_eng/skills/bsl-practices/data-exchange/SKILL.md b/framework_eng/skills/bsl-practices/data-exchange/SKILL.md index c570ab08..8d319aaf 100644 --- a/framework_eng/skills/bsl-practices/data-exchange/SKILL.md +++ b/framework_eng/skills/bsl-practices/data-exchange/SKILL.md @@ -1,6 +1,6 @@ --- name: data-exchange -description: "Use for implementing and diagnosing 1C data exchange (РИБ, КД 2.0/3.0, EnterpriseData, БСП). Helps choose the exchange model, ensure packet idempotency, and explicit conflict resolution." +description: "Use for 1C exchanges: RIB, KD, EnterpriseData, BSP" --- # 1C Data Exchange @@ -15,7 +15,7 @@ Before implementation, you must determine the exchange model. The choice affects | Model | When to use | Mechanism | |--------|-------------------|----------| -| РИБ (distributed information base) | Full copy of the configuration at the nodes; all data is transferred | `ПланыОбмена`, XML serialization, `ОбменДаннымиXML` | +| РИБ (distributed infobase) | Full copy of the configuration at the nodes; all data is transferred | `ПланыОбмена`, XML serialization, `ОбменДаннымиXML` | | Selective exchange (БСП) | Rule-based exchange, object filtering, different configurations | БСП "Data exchange" subsystem, EnterpriseData format | | КД 2.0 | Complex conversion rules between different configurations | "Data Conversion" processing, XML rules | | КД 3.0 / EDT | Modern projects, rules in BSL, EnterpriseData support | Configuration "Data Conversion 3" | @@ -281,9 +281,9 @@ A conflict occurs when the same object is changed in two nodes at the same time. --- -## Rule 6: Exchange through the БСП "Data exchange" subsystem +## Rule 6: Exchange through the БСП subsystem "Обмен данными" -БСП provides ready-made infrastructure: node settings, exchange rules, transport (file, FTP, e-mail, WS), message queue, and conflict register. +БСП provides ready-made infrastructure: node settings, exchange rules, transport (file, FTP, e-mail, WS), a message queue, and a conflict register. ### Key subsystem objects @@ -339,9 +339,9 @@ EnterpriseData is a standardized XML format for exchange between 1C configuratio ## Rule 7: КД 2.0 - conversion rules -КД 2.0 is used for exchange between different configurations using a conversion rules file (XML). +КД 2.0 is used for exchange between different configurations with a conversion rule file (XML). -### Loading pattern through КД 2.0 +### Load pattern via КД 2.0 ```bsl // Загрузка данных с использованием обработки «Конвертация данных» @@ -373,7 +373,7 @@ EnterpriseData is a standardized XML format for exchange between 1C configuratio | Rules | XML file | BSL modules in the КД 3 configuration | | EDT support | No | Yes | | Format | Proprietary XML | EnterpriseData (optional) | -| Handlers | In the rules (code strings) | Full BSL, debugging | +| Handlers | In rules (code strings) | Full BSL, debugging | | Recommendation | Existing projects | New projects | --- @@ -384,8 +384,8 @@ EnterpriseData is a standardized XML format for exchange between 1C configuratio When diagnosing exchange, look for events: -| Registration log event | What it means | -|------------------------|---------------| +| Event in the registration log | Meaning | +|-----------|-------------| | `ОбменДанными` | General events of the БСП subsystem | | `ОбменДанными.Выгрузка` | Packet formation | | `ОбменДанными.Загрузка` | Packet reception and processing | @@ -447,24 +447,24 @@ When diagnosing exchange, look for events: --- -## Typical mistakes +## Typical errors | Error | Consequence | How to avoid | -|-------|-------------|--------------| -| No `ОбменДанными.Загрузка` check | Business logic runs during load, data is corrupted or the exchange loops | In every `ПриЗаписи` handler, at the first lines | -| Fixing `НомерОтправленного` before delivery confirmation | Changes are marked as sent but never reach the node; they will not be exported in the next session | Fix the number only after recipient confirmation | +|--------|------------|--------------| +| No `ОбменДанными.Загрузка` check | Business logic runs during loading, data gets corrupted or the exchange loops | In every `ПриЗаписи` handler, in the first lines | +| Fixing `НомерОтправленного` before delivery confirmation | Changes are marked as sent, but never reach the node; they will not be exported in the next session | Fix the number only after receiver confirmation | | Loading without idempotency check | Duplicate documents, double register movements | Check `НомерСообщения <= НомерПринятого` before loading | -| Conflict without logging | Data is silently overwritten, user changes are lost | Always write to the registration log on conflict with Warning level | -| Registering changes inside a load handler | Infinite exchange: A->B->A->B | The `Загрузка = Истина` flag disables registration | -| Long transaction when loading a large packet | Locks, timeouts, rollback of the entire packet | Load object by object with separate transactions or batches | -| Not deleting change register entries after export | Accumulation of millions of records, performance degradation | `ПланыОбмена.УдалитьРегистрациюИзменений` after confirmation | +| Conflict without logging | Data is silently overwritten, user edits are lost | Always write to the registration log with Warning level on conflict | +| Registering changes inside a load handler | Infinite exchange: A→B→A→B | The `Загрузка = Истина` flag disables registration | +| Long transaction during large packet loading | Locks, timeouts, rollback of the entire packet | Load object by object with separate transactions or batches | +| Not deleting change-register entries after export | Accumulation of millions of records, performance degradation | `ПланыОбмена.УдалитьРегистрациюИзменений` after confirmation | --- ## Related resources -- [error-handling](../error-handling/SKILL.md) - canonical transaction pattern, required during loading/export -- [background-jobs](../background-jobs/SKILL.md) - data exchange is often performed in background jobs +- [error-handling](../error-handling/SKILL.md) - canonical transaction pattern, mandatory during load/export +- [background-jobs](../background-jobs/SKILL.md) - data exchange often runs in background jobs --- depends_on: diff --git a/framework_eng/skills/bsl-practices/error-handling/SKILL.md b/framework_eng/skills/bsl-practices/error-handling/SKILL.md index ab51f3d1..1bb11de1 100644 --- a/framework_eng/skills/bsl-practices/error-handling/SKILL.md +++ b/framework_eng/skills/bsl-practices/error-handling/SKILL.md @@ -1,6 +1,6 @@ --- name: error-handling -description: "MUST be used WHEN handling exceptions or controlling transactions in BSL. Provides the canonical Try/Except pattern, transaction rollback rules, and data locking management." +description: "Use for BSL exceptions, transactions, rollback, locks" alwaysApply: false --- @@ -45,7 +45,7 @@ ITS standard: "In an exception handler, error information must be recorded in th ### Example: different handling levels ```bsl -// Нижний уровень — логирование + проброс +// Lower level - logging + rethrow Функция ЗаписатьДокумент(ДокументОбъект) Попытка ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение); @@ -61,7 +61,7 @@ ITS standard: "In an exception handler, error information must be recorded in th КонецПопытки; КонецФункции -// Верхний уровень (форма) — показ пользователю +// Upper level (form) - show to the user &НаКлиенте Процедура ЗаписатьДокумент(Команда) Попытка @@ -87,27 +87,27 @@ ITS standard: "Transactions: usage rules" - `НачатьТранзакцию()` НачатьТранзакцию(); Попытка - // 1. Блокировка данных (если нужно — см. правило 5) + // 1. Data locking (if needed - see rule 5) Блокировка = Новый БлокировкаДанных; ЭлементБлокировки = Блокировка.Добавить("Документ.РеализацияТоваровУслуг"); ЭлементБлокировки.УстановитьЗначение("Ссылка", ДокументСсылка); Блокировка.Заблокировать(); - // 2. Чтение и модификация данных + // 2. Read and modify data ДокументОбъект = ДокументСсылка.ПолучитьОбъект(); ДокументОбъект.Статус = Перечисления.СтатусыДокументов.Согласован; - // 3. Запись + // 3. Write ДокументОбъект.Записать(); - // === Фиксация — ПОСЛЕДНЯЯ операция перед Исключение === + // === Commit is the LAST operation before Исключение === ЗафиксироватьТранзакцию(); Исключение - // === Откат — ПЕРВАЯ операция в блоке Исключение === + // === Rollback is the FIRST operation in the Исключение block === ОтменитьТранзакцию(); - // Логирование ПОСЛЕ отката (запись в ЖР внутри отменённой транзакции будет потеряна!) + // Logging AFTER rollback (an entry in the registration log inside a rolled-back transaction will be lost!) ЗаписьЖурналаРегистрации( НСтр("ru = 'Согласование документа'"), УровеньЖурналаРегистрации.Ошибка, @@ -131,24 +131,24 @@ ITS standard: "Transactions: usage rules" - `НачатьТранзакцию()` ### Wrong variants (platform traps) ```bsl -// ПЛОХО: код между НачатьТранзакцию и Попытка +// BAD: code between НачатьТранзакцию and Попытка НачатьТранзакцию(); -ПодготовитьДанные(); // Если здесь ошибка — транзакция зависнет! +ПодготовитьДанные(); // If there is an error here, the transaction will hang! Попытка // ... КонецПопытки; -// ПЛОХО: ЗаписьЖурнала ДО ОтменитьТранзакцию +// BAD: registration log entry BEFORE ОтменитьТранзакцию Исключение - ЗаписьЖурналаРегистрации(...); // Может быть потеряна при откате! + ЗаписьЖурналаРегистрации(...); // Can be lost during rollback! ОтменитьТранзакцию(); КонецПопытки; -// ПЛОХО: код после ЗафиксироватьТранзакцию, но до конца Попытка +// BAD: code after ЗафиксироватьТранзакцию, but before the end of Попытка ЗафиксироватьТранзакцию(); - ОтправитьОповещение(); // Ошибка здесь — транзакция уже зафиксирована, но Исключение выполнится! + ОтправитьОповещение(); // Error here - the transaction is already committed, but Исключение will run! Исключение - ОтменитьТранзакцию(); // Ошибка! Транзакция уже зафиксирована! + ОтменитьТранзакцию(); // Error! The transaction is already committed! КонецПопытки; ``` @@ -173,7 +173,7 @@ In 1C, a nested `НачатьТранзакцию()` does not create a new trans НСтр("ru = 'Запись данных'"), УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); - ВызватьИсключение; // ОБЯЗАТЕЛЬНО пробрасываем — внешний код должен знать + ВызватьИсключение; // MUST rethrow - the outer code must know КонецПопытки; КонецПроцедуры @@ -182,7 +182,7 @@ In 1C, a nested `НачатьТранзакцию()` does not create a new trans ### Rule: DO NOT use `ТранзакцияАктивна()` as a substitute for the correct pattern ```bsl -// ПЛОХО: ТранзакцияАктивна() маскирует ошибку в структуре кода +// BAD: ТранзакцияАктивна() masks an error in the code structure Попытка НачатьТранзакцию(); // ... @@ -193,7 +193,7 @@ In 1C, a nested `НачатьТранзакцию()` does not create a new trans КонецЕсли; КонецПопытки; -// ПРАВИЛЬНО: корректная структура делает проверку ненужной +// CORRECT: the proper structure makes the check unnecessary НачатьТранзакцию(); Попытка // ... @@ -211,11 +211,11 @@ In 1C, a nested `НачатьТранзакцию()` does not create a new trans While a transaction is open, modified data is locked in the DBMS. A long transaction = cascading locks = users cannot work. ```bsl -// Подготовка данных — ВНЕ транзакции +// Data preparation - OUTSIDE the transaction МассивДанных = ПодготовитьДанные(); ПроверитьКорректность(МассивДанных); -// Транзакция — только быстрые операции записи +// Transaction - only fast write operations НачатьТранзакцию(); Попытка Для Каждого ДанныеСтроки Из МассивДанных Цикл @@ -246,7 +246,7 @@ ITS standard: "Managed locks". НачатьТранзакцию(); Попытка - // 1. СНАЧАЛА блокируем + // 1. FIRST lock Блокировка = Новый БлокировкаДанных; ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ТоварыНаСкладах"); ЭлементБлокировки.УстановитьЗначение("Номенклатура", НоменклатураСсылка); @@ -254,7 +254,7 @@ ITS standard: "Managed locks". ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный; Блокировка.Заблокировать(); - // 2. Читаем — гарантированно актуальные данные + // 2. Read - guaranteed up-to-date data Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ @@ -273,15 +273,15 @@ ITS standard: "Managed locks". Выборка = Результат.Выбрать(); Выборка.Следующий(); - // 3. Проверяем + // 3. Check Если Выборка.Остаток < ТребуемоеКоличество Тогда ВызватьИсключение СтрШаблон( НСтр("ru = 'Недостаточно остатков. На складе: %1, требуется: %2.'"), Выборка.Остаток, ТребуемоеКоличество); КонецЕсли; - // 4. Записываем - // ... запись движений ... + // 4. Write + // ... movement posting ... ЗафиксироватьТранзакцию(); Исключение @@ -294,14 +294,14 @@ ITS standard: "Managed locks". ### Why lock BEFORE reading ``` -Без блокировки (race condition): - Сеанс A: Читает остаток = 10 | Сеанс B: Читает остаток = 10 - Сеанс A: 10 >= 8? Да, списываем 8 | Сеанс B: 10 >= 7? Да, списываем 7 - Итого: списано 15 единиц при остатке 10 → отрицательный остаток! - -С блокировкой: - Сеанс A: Блокирует → Читает 10 → Списывает 8 → Фиксирует → Разблокирует - Сеанс B: Ждёт блокировку → Читает 2 → 2 < 7 → Ошибка (корректная!) +Without locking (race condition): + Session A: Reads balance = 10 | Session B: Reads balance = 10 + Session A: 10 >= 8? Yes, write off 8 | Session B: 10 >= 7? Yes, write off 7 + Total: 15 units written off with a balance of 10 -> negative balance! + +With locking: + Session A: Locks -> Reads 10 -> Writes off 8 -> Commits -> Unlocks + Session B: Waits for lock -> Reads 2 -> 2 < 7 -> Error (correct!) ``` --- @@ -349,11 +349,11 @@ Prevents lost update: the second user will get the error "Object locked by user ```bsl ЗаписьЖурналаРегистрации( - ИмяСобытия, // Строка — иерархическое имя (через точку) - УровеньСобытия, // УровеньЖурналаРегистрации — Ошибка/Предупреждение/Информация/Примечание - МетаданныеОбъекта, // Объект метаданных — для фильтрации по типу - Данные, // Ссылка на объект — для навигации из ЖР - Комментарий); // Строка — подробное описание (до 1024 символов) + ИмяСобытия, // String - hierarchical name (with dots) + УровеньСобытия, // УровеньЖурналаРегистрации - Ошибка/Предупреждение/Информация/Примечание + МетаданныеОбъекта, // Metadata object - for filtering by type + Данные, // Object reference - for navigation from the registration log + Комментарий); // String - detailed description (up to 1024 characters) ``` ### Levels @@ -426,17 +426,17 @@ For the user - **what happened** and **what to do**. In the registration log - t | `ВызватьИсключение "Text";` | At the user boundary (form) | Replaces the technical stack with a clear message | ```bsl -// Промежуточный слой — пробрасываем оригинал +// Intermediate layer - rethrow the original Процедура ОбработатьДанные(Данные) Попытка ЗаписатьДанные(Данные); Исключение ЗаписьЖурналаРегистрации(...); - ВызватьИсключение; // Оригинальный стек сохранён + ВызватьИсключение; // Original stack preserved КонецПопытки; КонецПроцедуры -// Граница с пользователем +// User boundary &НаСервере Процедура ОбработатьНаСервере() Попытка @@ -503,7 +503,7 @@ An error in one document must not stop the processing of the others. Each transa When two sessions lock data in different orders - deadlock. The DBMS rolls back one of the transactions. ```bsl -// Всегда блокируйте ресурсы в фиксированном порядке (по ссылке) +// Always lock resources in a fixed order (by reference) МассивСсылок = ОбщегоНазначенияКлиентСервер.СвернутьМассив(МассивДокументов); МассивСсылок.СортироватьПоЗначению(); @@ -548,7 +548,7 @@ When two sessions lock data in different orders - deadlock. The DBMS rolls back ## Rule 12: Try/Except for external calls -External system calls are unreliable. **Always** wrap them in `Try/Except`. +Calls to external systems are unreliable. **Always** wrap them in `Try/Except`. ### Pattern: HTTP call with retries diff --git a/framework_eng/skills/bsl-practices/form-patterns/SKILL.md b/framework_eng/skills/bsl-practices/form-patterns/SKILL.md index a16edf47..0511b355 100644 --- a/framework_eng/skills/bsl-practices/form-patterns/SKILL.md +++ b/framework_eng/skills/bsl-practices/form-patterns/SKILL.md @@ -1,6 +1,6 @@ --- name: form-patterns -description: "Form module patterns. MUST use WHEN writing 1C managed form module code. Provides rules for choosing context directives (&НаСервереБезКонтекста and others) and minimizing server round-trips." +description: "Use for managed form module code and server calls" alwaysApply: false --- diff --git a/framework_eng/skills/bsl-practices/form-visual-requirements/SKILL.md b/framework_eng/skills/bsl-practices/form-visual-requirements/SKILL.md index 4414cb28..f17c5975 100644 --- a/framework_eng/skills/bsl-practices/form-visual-requirements/SKILL.md +++ b/framework_eng/skills/bsl-practices/form-visual-requirements/SKILL.md @@ -1,47 +1,49 @@ --- name: form-visual-requirements -description: "MUST use WHEN checking the visual appearance of 1C forms (screenshot or visual-check result). Provides a checklist for layout, alignment, labels, and UX criteria." +description: "For visual checks of 1C forms: layout, labels, UX" alwaysApply: false --- -# Visual requirements for forms +# Visual Requirements for Forms Use this checklist to review 1C forms. -## 1. Layout and alignment +Before evaluating the image, check that the PNG is not empty and not single-color/black. How to capture a form screenshot, how to work in Xvfb, and when browser fallback is allowed — see the dedicated skill `va-visual-check`. -- [ ] **Alignment**: elements are aligned to the grid, without a staircase effect. +## 1. Layout and Alignment + +- [ ] **Alignment**: elements are aligned to the grid, without a stair-step effect. - [ ] **Grouping**: logically related fields are grouped together (frame, page). -- [ ] **Empty spaces**: there are no large empty areas (>150px) unless this is intentional. +- [ ] **Empty spaces**: there are no large empty areas (>150px) unless intended. - [ ] **Field widths**: - `Code`, `Number`, `Date` — narrow. - - `Description`, `Comment`, `Address` — wide (expanded). - - Table section columns — "Auto width" or an explicit width to fill the available space. + - `Description`, `Comment`, `Address` — wide (stretched). + - Columns of tabular sections — "Auto width" or an explicit width to fill the space. -## 2. Elements and labels +## 2. Elements and Labels -- [ ] **Labels**: all fields have labels (or `TitleLocation=None` is explicitly set). -- [ ] **Truncation**: labels and values should not be truncated with an ellipsis ("...") when there is available space. +- [ ] **Labels**: all fields have labels (or `TitleLocation=None` is explicitly specified). +- [ ] **Truncation**: labels and values must not be truncated with an ellipsis ("…") when there is space available. - [ ] **Checkbox labels**: the checkbox label should be clear (for example, "Active", not just a checkbox). -- [ ] **Command bar**: the "More" menu should not hide the main actions. +- [ ] **Command bar**: the "More" menu must not hide primary actions. ## 3. Usability -- [ ] **Tab order**: focus moves from left to right and from top to bottom. +- [ ] **Tab order**: focus moves left to right and top to bottom. - [ ] **Key fields**: important identifiers (Name, Code, Date) are in the upper-left corner. -- [ ] **Table sections**: a reasonable height (at least 5–10 visible rows). -- [ ] **Horizontal scrolling**: strictly forbidden for the main form area (vertical scrolling is allowed). +- [ ] **Tabular sections**: reasonable height (at least 5-10 visible rows). +- [ ] **Horizontal scrolling**: strictly forbidden for the main form area (vertical is allowed). -## 4. Object type specifics +## 4. Specifics by Object Type ### Справочники - Code/Name are usually at the top. -- The parent field (when hierarchical) should be prominent. +- The parent field (for hierarchies) should be prominent. ### Документы - Date/Number are at the top. - Status/Organization/Warehouse are in the header. -- Table sections are in the body of the form. +- Tabular sections are in the form body. - Totals/Comment/Author are at the bottom. ### Обработки diff --git a/framework_eng/skills/bsl-practices/integration-patterns/SKILL.md b/framework_eng/skills/bsl-practices/integration-patterns/SKILL.md index c28da607..f2727d7d 100644 --- a/framework_eng/skills/bsl-practices/integration-patterns/SKILL.md +++ b/framework_eng/skills/bsl-practices/integration-patterns/SKILL.md @@ -1,6 +1,6 @@ --- name: integration-patterns -description: "1C integration patterns: HTTP/REST/SOAP services, authentication (Basic/Token/OAuth/CertificateAuth), idempotency, retry, secure secret storage, versioning. Use when you need to create an HTTP service, a REST/SOAP client, implement a webhook, define a contract, configure authentication, or handle errors from external interactions." +description: "Use for 1C HTTP/REST/SOAP, auth, retry, webhooks" --- # 1C Integration Patterns @@ -147,7 +147,7 @@ For details on each scheme, see [references/auth-schemes.md](references/auth-sch ## Rule 4: HTTP client - retry and timeout -External calls are unreliable. Always wrap them in `Попытка/Исключение`. For mutating operations, use an idempotency key and protection against repeated execution. +External calls are unreliable. Always wrap them in `try/except`. For mutating operations, use an idempotency key and protection against repeated execution. ```bsl Функция ВызватьВнешнийAPIСПовтором(URLПуть, ТелоЗапросаJSON, КлючИдемпотентности = "") diff --git a/framework_eng/skills/bsl-practices/query-optimize/SKILL.md b/framework_eng/skills/bsl-practices/query-optimize/SKILL.md index dd187376..8ed0713f 100644 --- a/framework_eng/skills/bsl-practices/query-optimize/SKILL.md +++ b/framework_eng/skills/bsl-practices/query-optimize/SKILL.md @@ -1,24 +1,24 @@ --- name: query-optimize -description: "MUST use WHEN you need to speed up an existing query or rewrite a DCS dataset. Provides rules for eliminating query-in-loop, dot-dereference, virtual tables without parameters, and excessive totals." +description: "Optimize slow 1C queries and DCS datasets" target_agents: - developer-code - architect alwaysApply: false --- -# Query Optimize — optimization of queries and СКД +# Query Optimize — query and SKD optimization -A skill for optimizing **existing** queries and data composition schemas. For writing queries from scratch - `query-patterns`. For DB diagnostics (plan, locks, evidence) - `db-performance`. +Skill for optimizing **existing** queries and data composition schemas. For writing queries from scratch — `query-patterns`. For DBMS diagnostics (plan, locks, evidence) — `db-performance`. --- ## Relationship with other skills ``` -db-performance ← lower evidentiary layer (DB evidence, plan, locks) +db-performance ← lower evidence layer (DBMS-evidence, plan, locks) ↓ passes query + reason -query-optimize ← rewrite (this skill) +query-optimize ← rewriting (this skill) ↓ uses writing rules query-patterns ← basic patterns (parameterization, NULL, loops) ``` @@ -32,13 +32,13 @@ Without `db-performance` evidence, optimization is a guess. If the cause is unkn ### 1. Extract the query and execution context - Find the query text: `rg "Запрос.Текст\s*=" --type-add "bsl:*.bsl" -t bsl` -- For DCS - find the `.xml` schema through `code-navigation`, determine the dataset +- For SKD — find the `.xml` schemas via `code-navigation`, determine the dataset - Record: - - Module / DCS dataset + - Module / SKD dataset - Virtual table parameters (passed / not passed) - - Temp table chain + - Temporary table chain - Calling loop (yes / no) - - Expected row count / actual + - Expected number of rows / actual ### 2. Check metadata @@ -55,36 +55,36 @@ Choose from the categories (one per iteration): | Cause | Sign | |---------|---------| -| Broad virtual table read | `Остатки()` / `Обороты()` without period or dimension parameters | -| Query-in-loop | Query inside `Для Каждого` / `Пока` / recursion | -| Dot-dereference without ВЫРАЗИТЬ | `Движения.Регистратор.Контрагент` when the type is composite | -| Excessive temp tables | Intermediate tables with a full field set instead of a minimal one | -| Extra totals | `ИТОГИ` in the query when a flat result set is needed | -| Filtering after join | `ГДЕ` conditions on fields of a large table instead of virtual table parameters | +| Broad virtual table read | balance/turnover virtual table without period or dimension parameters | +| Query-in-loop | Query inside a `for each` / `while` loop / recursion | +| Dot-dereference without explicit casting | `Движения.Регистратор.Контрагент` when the type is composite | +| Excessive temporary tables | Intermediate tables with the full field set instead of the minimum | +| Unnecessary totals | totals in a query when a flat result set is needed | +| Filtering after join | `WHERE` conditions on fields of a large table instead of virtual table parameters | | Implicit row multiplication through JOIN | LEFT JOIN without aggregation duplicates rows | -| DISTINCT masks the problem | `ВЫБРАТЬ РАЗЛИЧНЫЕ` hides an unnecessary JOIN instead of fixing it | +| `DISTINCT` masks the problem | `ВЫБРАТЬ РАЗЛИЧНЫЕ` hides an unnecessary JOIN instead of fixing it | ### 4. Apply the optimization rule -For each cause, use the specific rule (see the "Rules" section below). +For each cause — a specific rule (see the "Rules" section below). ### 5. Check syntax and semantics - Syntax: `v8-runner` after any change -- Semantics: do not silently remove `РАЗРЕШЕННЫЕ` filters; preserve safety rules -- For join changes: make sure the row count has not changed unexpectedly +- Semantics: do not silently remove permission filters; security rules must remain intact +- For join changes: make sure the row count did not change unexpectedly -### 6. Request DB verification if the effect is non-obvious +### 6. Request DBMS verification if the effect is not obvious -If the change affects the DB plan (index, virtual table parameters, join type), ask the user for `EXPLAIN` / trace logs before and after. Without measurement, record it as "expected effect, requires verification." +If the change affects the DBMS plan (index, virtual table parameters, join type), ask the user for `EXPLAIN` / log before and after. Without measurement, record it as an "expected effect, requires verification." --- ## Optimization Rules -### Virtual tables: parameters inside +### Virtual tables: pass parameters inside -**Problem:** The DB computes all data first, then filters in `ГДЕ`. +**Problem:** The DBMS calculates all data first, then filters in `WHERE`. ```bsl // ПЛОХО — фильтр в WHERE, СУБД читает всё @@ -98,9 +98,9 @@ If the change affects the DB plan (index, virtual table parameters, join type), | ) КАК Ост" ``` -Rule: the virtual table always receives period and dimension parameters. The only exception is an explicit justification (a report for all warehouses without a filter). +Rule: a virtual table always receives period and dimension parameters. The only exception is when there is an explicit justification (a report across all warehouses without a filter). -### Query-in-loop: one query + Correspondence +### Query-in-loop: one query + a map **Problem:** N iterations × (latency + query time). @@ -125,9 +125,9 @@ Rule: the virtual table always receives period and dimension parameters. The onl КонецЦикла; ``` -### Dot-dereference: ВЫРАЗИТЬ for a composite type +### Dot-dereference: explicit casting for a composite type -**Problem:** `Движения.Регистратор.Контрагент` when the type is composite - the DB performs a LEFT JOIN to all tables of the composite type. +**Problem:** `Движения.Регистратор.Контрагент` for a composite type means the DBMS makes a LEFT JOIN to all tables of the composite type. ```bsl // ПЛОХО — N LEFT JOIN по составному типу @@ -140,7 +140,7 @@ Rule: the virtual table always receives period and dimension parameters. The onl |ГДЕ Движения.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг" ``` -### Temporary tables: minimal fields and ИНДЕКСИРОВАТЬ +### Temporary tables: minimal fields and indexes ```bsl // Только поля, нужные следующим этапам @@ -152,30 +152,30 @@ Rule: the virtual table always receives period and dimension parameters. The onl |ИНДЕКСИРОВАТЬ ПО Контрагент" // только поле соединения ``` -Rule: use `ИНДЕКСИРОВАТЬ ПО` for fields that will be used in a JOIN in the next query of the package. Do not add an index on every field. +Rule: add indexes for fields that will be JOINed in the next query of the package. Do not add an index on every field. -### Extra totals: replace ИТОГИ with GROUP BY +### Unnecessary totals: replace totals with `GROUP BY` -`ИТОГИ` generates extra total rows. If a flat result set is needed, use `СГРУППИРОВАТЬ ПО`. +Totals generate extra summary rows. If a flat result set is needed, use `GROUP BY`. ```bsl -// ИТОГИ нужны только при иерархическом обходе Выбрать(ПоГруппировкам) -// Для плоской выборки — только СГРУППИРОВАТЬ ПО +// Totals are needed only for hierarchical traversal +// For a flat selection — only GROUP BY "ВЫБРАТЬ Контрагент, СУММА(Сумма) КАК Итог |ИЗ ... |СГРУППИРОВАТЬ ПО Контрагент" ``` -### Filter on a composite type: IN instead of JOIN + DISTINCT +### Filter on a composite type: `IN` instead of JOIN + `DISTINCT` ```bsl -// ПЛОХО — JOIN умножает строки, РАЗЛИЧНЫЕ скрывает +// BAD — JOIN multiplies rows, DISTINCT hides it "ВЫБРАТЬ РАЗЛИЧНЫЕ Контрагенты.Ссылка |ИЗ Справочник.Контрагенты КАК Контрагенты | ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Реализация КАК Реал | ПО Контрагенты.Ссылка = Реал.Контрагент" -// ХОРОШО — подзапрос +// GOOD — subquery "ВЫБРАТЬ Контрагенты.Ссылка |ИЗ Справочник.Контрагенты КАК Контрагенты |ГДЕ Контрагенты.Ссылка В @@ -185,49 +185,50 @@ Rule: use `ИНДЕКСИРОВАТЬ ПО` for fields that will be used in a JO --- -## DCS: optimization specifics +## SKD: optimization specifics ### Dataset parameters -- DCS parameters passed into dataset virtual tables work the same as query parameters: pass them inside, do not filter through selection afterward -- For register period conditions - always parameterize them in the dataset query text +- SKD parameters passed into dataset virtual tables work the same way as query parameters: pass them inside, do not filter through a selection after the fact +- For register period conditions — always parameterize them in the dataset query text ### Resources and calculated fields -- DCS calculated fields that access other datasets through relations are a potential query-in-loop at the platform level -- Dataset relations (`СВЯЗЬ`) with conditions and no index on the detail side - check metadata +- SKD calculated fields that access other datasets through links are a potential query-in-loop at the platform level +- Dataset links with conditions and no index on the dependent side — check metadata -### DCS filters +### SKD selections -- Filters applied by the user through settings may not reach virtual table parameters - this is an architectural limitation; document it -- For critical filters (period, organization) - pass them as dataset query parameters, do not rely only on DCS filters +- Selections applied by the user through settings may not reach virtual table parameters — this is an architectural limitation; document it +- For critical filters (period, organization) — pass them as dataset query parameters, do not rely only on SKD selections --- -## Query review checklist +## Query Review Checklist -- [ ] Virtual tables receive period and dimension parameters (not filtering in `ГДЕ`) -- [ ] Temp tables contain only the fields needed for later stages -- [ ] Join fields in temp tables are indexed (`ИНДЕКСИРОВАТЬ ПО`) -- [ ] No repeated subqueries or query-in-loop +- [ ] Virtual tables receive period and dimension parameters (not filtering in `WHERE`) +- [ ] Temporary tables contain only fields needed by later stages +- [ ] Join fields in temporary tables are indexed +- [ ] There are no repeated subqueries or query-in-loop patterns - [ ] JOIN does not multiply rows; totals and groupings match the business meaning - [ ] Date and organization filters are applied as early as possible -- [ ] Composite types are expanded through `ВЫРАЗИТЬ` before dot-dereference -- [ ] `ЛЕВОЕ СОЕДИНЕНИЕ` does not turn into `ВНУТРЕННЕЕ` because of a condition in `ГДЕ` -- [ ] `РАЗЛИЧНЫЕ` does not mask an unnecessary JOIN -- [ ] `РАЗРЕШЕННЫЕ` and other rights filters are preserved +- [ ] Composite types are expanded before dot-dereference +- [ ] LEFT JOIN does not turn into INNER JOIN because of a WHERE condition +- [ ] DISTINCT does not hide an unnecessary JOIN +- [ ] Permission filters and other access filters are preserved --- -## Stop rules +## Stop Rules -1. **Do not remove `РАЗРЕШЕННЫЕ`** without explicit security approval. -2. **Do not recommend an index without** a concrete predicate + write-cost assessment - that is a `db-performance` task. -3. **Do not rewrite multiple causes in one step** - it is impossible to measure each contribution. -4. **Do not replace LEFT JOIN with INNER JOIN** without checking the business requirement: are all rows needed, or only matching ones. -5. **Do not transfer an optimization based on one DBMS's data behavior** to another without verification: PostgreSQL and MS SQL Server have different planner models. +1. **Do not remove permission filters** without explicit security approval. +2. **Do not recommend an index without** a specific predicate + write-cost assessment — that is a `db-performance` task. +3. **Do not rewrite multiple causes in one step** — you cannot measure each contribution. +4. **Do not replace LEFT JOIN with INNER JOIN** without checking the business requirement: do all rows need to be kept, or only matching ones. +5. **Do not transfer an optimization based on one DBMS** to another without verification: PostgreSQL and MS SQL Server have different planner models. --- + depends_on: - framework/skills/bsl-practices/query-patterns/SKILL.md - framework/skills/tool-usage/diagnostics/db-performance/SKILL.md diff --git a/framework_eng/skills/bsl-practices/query-patterns/SKILL.md b/framework_eng/skills/bsl-practices/query-patterns/SKILL.md index 0f7f2993..4a335136 100644 --- a/framework_eng/skills/bsl-practices/query-patterns/SKILL.md +++ b/framework_eng/skills/bsl-practices/query-patterns/SKILL.md @@ -1,20 +1,20 @@ --- name: query-patterns -description: "MUST use WHEN writing a new query in the 1C:Enterprise query language. Provides basic patterns for parameterization, NULL handling, batch selection, and prohibiting queries in loops." +description: "Use when writing new 1C queries and parameters" alwaysApply: false --- -# 1C Query Patterns +# 1С Query Patterns -**Key principle:** Every query to the database is a network round-trip. Minimizing the number of queries and the amount of returned data is the priority. +**Key principle:** Every database query is a network round-trip. Minimizing the number of queries and the volume of returned data is the priority. --- ## Rule 1: NEVER run queries in a loop -For N iterations — N * (network latency + execution time). 1000 elements * 5 ms = 5 seconds just waiting for the network. +For N iterations, it is N * (network latency + execution time). 1000 items * 5 ms = 5 seconds just waiting on the network. -ITS standard: "Database queries - restriction on using queries in a loop". +ITS standard: “Database queries — restriction on using queries in a loop”. ### Correct — one query + Соответствие for processing @@ -54,7 +54,7 @@ ITS standard: "Database queries - restriction on using queries in a loop". ## Rule 2: Temporary tables for complex queries -Breaking into stages: readability, step-by-step debugging, indexing of intermediate results. +Breaking it into stages: readability, step-by-step debugging, indexing intermediate results. ```bsl Запрос = Новый Запрос; @@ -99,16 +99,16 @@ Breaking into stages: readability, step-by-step debugging, indexing of intermedi | ОбщаяСумма УБЫВ"; ``` -Rules: `вт` prefix (standard); `ИНДЕКСИРОВАТЬ ПО` for join fields; use `МенеджерВременныхТаблиц` to manage the lifecycle. +Rules: prefix `вт` (standard); `ИНДЕКСИРОВАТЬ ПО` for join fields; use `МенеджерВременныхТаблиц` to manage the lifecycle. --- -## Rule 3: Query parameterization — do not interpolate values into the text +## Rule 3: Query parameterization — do not substitute values into the text -Interpolating values into the text: vulnerability, inability to cache the DBMS plan, formatting errors. +Substituting values into the text: vulnerability, inability to cache the DBMS plan, formatting errors. ```bsl -// Правильно — через параметры +// Correct — through parameters Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ Товары.Наименование @@ -122,7 +122,7 @@ Interpolating values into the text: vulnerability, inability to cache the DBMS p --- -## Rule 4: `ЕСТЬNULL()` with LEFT JOIN +## Rule 4: ЕСТЬNULL() with LEFT JOIN `NULL + 100 = NULL`, `NULL > 0 = FALSE`. An unhandled NULL leads to incorrect calculations and lost rows in conditions. @@ -140,7 +140,7 @@ Interpolating values into the text: vulnerability, inability to cache the DBMS p | ЕСТЬNULL(ОстаткиТоваров.КоличествоОстаток, 0) > 0"; ``` -### Pitfall — filter without ЕСТЬNULL +### Trap — filter without ЕСТЬNULL ```bsl // ПЛОХО: ГДЕ ОстаткиТоваров.КоличествоОстаток > 0 @@ -149,14 +149,14 @@ Interpolating values into the text: vulnerability, inability to cache the DBMS p --- -## Rule 5: Register virtual tables — parameters inside +## Rule 5: Register virtual tables — put parameters inside -Virtual tables (`Остатки`, `Обороты`, `СрезПоследних`) are parameterized DBMS functions. Parameters inside mean the optimal plan. Parameters in WHERE mean the DBMS first computes **all** data, then filters. The difference is thousands of times. +Virtual tables (`Остатки`, `Обороты`, `СрезПоследних`) are parameterized DBMS functions. Parameters inside mean the optimal plan. Parameters in WHERE mean the DBMS will first compute **all** data, then filter it. The difference is thousands of times. -ITS standard: "Using virtual tables". +ITS standard: “Using virtual tables”. ```bsl -// Правильно — параметры внутри виртуальной таблицы +// Correct — parameters inside the virtual table Запрос.Текст = "ВЫБРАТЬ | Остатки.Номенклатура КАК Номенклатура, @@ -170,7 +170,7 @@ ITS standard: "Using virtual tables". | ) КАК Остатки"; ``` -### Incorrect — filtering through WHERE +### Wrong — filtering through WHERE ```bsl // ПЛОХО: СУБД вычислит остатки по ВСЕЙ номенклатуре на ВСЕХ складах, потом отфильтрует @@ -180,9 +180,9 @@ ITS standard: "Using virtual tables". --- -## Rule 6: Batch operations — `ТаблицаЗначений` as a query parameter +## Rule 6: Batch operations — use ТаблицаЗначений as a query parameter -Passing an array of data into a temporary table through `Запрос.УстановитьПараметр("ВТ", ТаблицаЗначений)` — one query instead of a loop. +Passing an array of data into a temporary table through `Запрос.УстановитьПараметр("ВТ", ТаблицаЗначений)` means one query instead of a loop. ```bsl ТаблицаДанных = Новый ТаблицаЗначений; @@ -219,7 +219,7 @@ Passing an array of data into a temporary table through `Запрос.Устан --- -## Rule 7: Result handling — Selection vs Export +## Rule 7: Result processing — Выборка vs Выгрузка | Method | When to use | |--------|-------------------| @@ -243,7 +243,7 @@ Passing an array of data into a temporary table through `Запрос.Устан ## Rule 8: Indexing — help the optimizer -Index: fields in WHERE conditions, fields in join conditions (ON), sorting fields. +Index: fields in WHERE conditions, fields in join conditions (ОН/ON), ordering fields. ### Temporary tables — index join fields @@ -272,16 +272,16 @@ Index: fields in WHERE conditions, fields in join conditions (ON), sorting field | ПО втЗаказы.Номенклатура = Остатки.Номенклатура"; ``` -In the configurator/EDT: Attribute -> Properties -> "Indexing". +In Configurator/EDT: Attribute -> Properties -> «Index». --- -## Rule 9: Only the needed fields (not SELECT *) +## Rule 9: Only the needed fields (not ВЫБРАТЬ *) -Extra fields: extra traffic, inability to use a covering index, fragility when adding attributes. +Extra fields mean extra traffic, no covering index, and brittleness when adding attributes. ```bsl -// Правильно — явный список полей +// Correct — explicit field list "ВЫБРАТЬ | Контрагенты.Ссылка, | Контрагенты.Наименование, @@ -291,9 +291,9 @@ Extra fields: extra traffic, inability to use a covering index, fragility when a --- -## Rule 10: FIRST N to limit the result +## Rule 10: ПЕРВЫЕ N to limit the result -An unrestricted query can return millions of rows and exhaust memory. +A query without a limit can return millions of rows and exhaust memory. ```bsl "ВЫБРАТЬ ПЕРВЫЕ 100 @@ -307,12 +307,12 @@ For displaying lists, use dynamic lists — they implement pagination automatica --- -## Rule 11: Do not mask duplicates with DISTINCT +## Rule 11: Do not mask duplicates with РАЗЛИЧНЫЕ -`DISTINCT` requires sorting/hashing all rows. If duplicates come from an unnecessary JOIN, fix the query. +`РАЗЛИЧНЫЕ` requires sorting/hashing all rows. If duplicates come from an extra JOIN, fix the query. ```bsl -// Правильно — подзапрос вместо JOIN + РАЗЛИЧНЫЕ +// Correct — subquery instead of JOIN + РАЗЛИЧНЫЕ "ВЫБРАТЬ Контрагенты.Ссылка, Контрагенты.Наименование |ИЗ Справочник.Контрагенты КАК Контрагенты |ГДЕ Контрагенты.Ссылка В @@ -323,14 +323,14 @@ For displaying lists, use dynamic lists — they implement pagination automatica --- -## Rule 12: `ВЫРАЗИТЬ` for composite types +## Rule 12: ВЫРАЗИТЬ for composite types -If a field has a composite type (e.g. "Регистратор"), the DBMS makes a LEFT JOIN to **all** tables of the composite type. `ВЫРАЗИТЬ(Поле КАК Тип)` limits the JOIN to one table. +If a field has a composite type (e.g. “Регистратор”), the DBMS performs a LEFT JOIN to **all** tables of the composite type. `ВЫРАЗИТЬ(Поле КАК Тип)` limits the JOIN to a single table. -ITS standard: "Using the ВЫРАЗИТЬ construct in queries". +ITS standard: “Using the ВЫРАЗИТЬ construct in queries”. ```bsl -// Правильно — JOIN только с одной таблицей +// Correct — JOIN with only one table "ВЫБРАТЬ | Движения.Период, | ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.РеализацияТоваровУслуг).Контрагент КАК Контрагент, @@ -339,7 +339,7 @@ ITS standard: "Using the ВЫРАЗИТЬ construct in queries". |ГДЕ Движения.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг" ``` -### Pitfall — referencing through a composite type without `ВЫРАЗИТЬ` +### Trap — accessing a composite type without ВЫРАЗИТЬ ```bsl // ПЛОХО: Движения.Регистратор.Контрагент без ВЫРАЗИТЬ @@ -350,11 +350,11 @@ ITS standard: "Using the ВЫРАЗИТЬ construct in queries". ## Rule 13: ON vs WHERE in LEFT JOIN -- Condition in `ПО` filters the right table **BEFORE** the join — rows from the left table without a match remain with NULL -- Condition in `ГДЕ` filters **AFTER** — rows with NULL are discarded, turning LEFT JOIN into INNER JOIN +- The condition in `ПО` filters the right table **BEFORE** the join — left rows without a match remain with NULL +- The condition in `ГДЕ` filters **AFTER** — rows with NULL are dropped, turning LEFT JOIN into INNER JOIN ```bsl -// Правильно — фильтр правой таблицы в параметрах виртуальной таблицы / в ON +// Correct — filter the right table in the virtual table parameters / in ON "ВЫБРАТЬ | Номенклатура.Наименование, | ЕСТЬNULL(Цены.Цена, 0) КАК Цена @@ -362,10 +362,10 @@ ITS standard: "Using the ВЫРАЗИТЬ construct in queries". | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаЦен, | ВидЦены = &ВидЦены) КАК Цены | ПО Номенклатура.Ссылка = Цены.Номенклатура" -// Все товары в результате, даже без цены +// All items are in the result, even without a price ``` -### Pitfall — filter of the right table in WHERE +### Trap — filtering the right table in WHERE ```bsl // ПЛОХО: ГДЕ Цены.ВидЦены = &ВидЦены diff --git a/framework_eng/skills/bsl-practices/security/SKILL.md b/framework_eng/skills/bsl-practices/security/SKILL.md index 6f84d730..55c07688 100644 --- a/framework_eng/skills/bsl-practices/security/SKILL.md +++ b/framework_eng/skills/bsl-practices/security/SKILL.md @@ -1,6 +1,6 @@ --- name: security -description: "MUST use WHEN working with passwords, tokens, electronic signatures, TLS, or privileged mode in 1C code. Provides rules for storing secrets in `БезопасноеХранилище`, cryptography (GOST/`МенеджерКриптографии`) and authentication." +description: "Use for 1C secrets, tokens, TLS, signatures, privileges" alwaysApply: false --- diff --git a/framework_eng/skills/bsl-practices/ssl-patterns/SKILL.md b/framework_eng/skills/bsl-practices/ssl-patterns/SKILL.md index 5a96956a..b365b83e 100644 --- a/framework_eng/skills/bsl-practices/ssl-patterns/SKILL.md +++ b/framework_eng/skills/bsl-practices/ssl-patterns/SKILL.md @@ -1,45 +1,45 @@ --- name: ssl-patterns -description: "MUST use WHEN you use or extend functionality of БСП (Standard Subsystems Library). Provides a catalog of ready-made ОбщегоНазначения functions and rules for calling subsystems without duplication." +description: "Check ready BSP/SSL mechanisms before custom logic" uses_capabilities: - get_signature_help alwaysApply: false --- -# Patterns for working with БСП (Standard Subsystems Library) +# Patterns for Working with BСП (Standard Subsystems Library) -БСП code is tested on millions of installations, updated centrally, and familiar to other developers. Duplicating БСП is an anti-pattern. +BСП code is battle-tested on millions of installations, updated centrally, and familiar to other developers. Duplicating BСП is an antipattern. -> **БСП function signatures — via `get_signature_help`.** `ОбщегоНазначения` and other БСП module -> functions have many parameters and overloads; do not guess the order or set of arguments. At the -> call site, `get_signature_help(uri, line, character)` shows the parameters and overloads of the -> called method right there — without opening the БСП module definition. Use it when calling any -> function from the catalog below if you are unsure of the signature. +> **BСП function signatures are available through `get_signature_help`.** Functions from `ОбщегоНазначения` and +> other BСП modules have many parameters and overloads; do not guess the order or set of arguments. +> At the call site, `get_signature_help(uri, line, character)` shows the parameters and overloads +> of the invoked method right in place - without opening the BСП module definition. Use it when calling +> any function from the catalog below if you are unsure about the signature. --- -## Rule 1: The ОбщегоНазначения module is the main "Swiss Army knife" +## Rule 1: The `ОбщегоНазначения` module is the main "Swiss army knife" -Before writing your own implementation, check whether БСП already has a ready-made function. +Before writing your own implementation, check whether BСП already has a ready-made function. | Function | When to use | -|---------|-------------------| +|---------|---| | `ЗначениеРеквизитаОбъекта()` | Instead of `Ссылка.Реквизит` (avoid dot notation) | | `ЗначенияРеквизитовОбъекта()` | Several attributes in one call | -| `СообщитьПользователю()` | Message tied to a field (instead of `Сообщить()`) | +| `СообщитьПользователю()` | Message bound to a field (instead of `Сообщить()`) | | `МенеджерОбъектаПоСсылке()` | Instead of `Выполнить("Справочники." + Имя)` | -| `ПодсистемаСуществует()` | Conditional module invocation | -| `ОбщийМодуль()` | Dynamic call to a БСП module | +| `ПодсистемаСуществует()` | Conditional invocation of modules | +| `ОбщийМодуль()` | Dynamic invocation of a BСП module | | `ЭтоСсылка()` | Parameter validation | -| `СсылкаСуществует()` | Check before access | +| `СсылкаСуществует()` | Check before accessing | ```bsl -// ПЛОХО: three database accesses through dot notation +// ПЛОХО: три обращения к БД через точку Наименование = КонтрагентСсылка.Наименование; ИНН = КонтрагентСсылка.ИНН; Ответственный = КонтрагентСсылка.ОсновнойМенеджер; -// ПРАВИЛЬНО: one access through БСП +// ПРАВИЛЬНО: одно обращение через БСП РеквизитыКонтрагента = ОбщегоНазначения.ЗначенияРеквизитовОбъекта( КонтрагентСсылка, "Наименование, ИНН, ОсновнойМенеджер"); @@ -47,20 +47,20 @@ Before writing your own implementation, check whether БСП already has a ready --- -## Rule 2: СтроковыеФункцииКлиентСервер is for string handling +## Rule 2: `СтроковыеФункцииКлиентСервер` - working with strings -The module contains optimized functions that handle edge cases correctly. +The module contains optimized functions that correctly handle edge cases. | Function | When to use | -|---------|-------------------| -| `ПодставитьПараметрыВСтроку()` | An equivalent of `СтрШаблон()`, with additional checks | +|---------|---| +| `ПодставитьПараметрыВСтроку()` | Equivalent of `СтрШаблон()`, with additional checks | | `СтрокаСЧисломПредметов()` | Declension: "5 documents", "1 document" | | `ЕстьНедопустимыеСимволы()` | Input validation | | `ТолькоЦифрыВСтроке()` | Validation of INN, KPP | | `РазложитьСтрокуВМассивПодстрок()` | Parsing by delimiter | ```bsl -// Declension: "1 document", "2 documents", "5 documents" +// Склонение: «1 документ», «2 документа», «5 документов» ТекстОповещения = СтроковыеФункцииКлиентСервер.СтрокаСЧисломПредметов( КоличествоДокументов, НСтр("ru = 'документ, документа, документов'")); @@ -68,53 +68,53 @@ The module contains optimized functions that handle edge cases correctly. --- -## Rule 3: ОбщегоНазначенияКлиентСервер are utilities for both environments +## Rule 3: `ОбщегоНазначенияКлиентСервер` - utilities for both environments -The directive `&НаКлиентеНаСервереБезКонтекста` is available on both client and server. +The directive `&НаКлиентеНаСервереБезКонтекста` means it is available on both the client and the server. | Function | Description | -|---------|----------| +|---------|---| | `ДополнитьМассив()` | Merge two arrays | | `ДополнитьСтруктуру()` | Merge two structures | -| `СвойствоСтруктуры()` | Safe property read (default value if absent) | +| `СвойствоСтруктуры()` | Safe property read (default value if missing) | | `ПроверитьПараметр()` | Type validation with an informative error | ```bsl -// Safe access with a default value +// Безопасный доступ с значением по умолчанию ДатаНачала = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры( ПараметрыОтчёта, "ДатаНачала", НачалоГода(ТекущаяДатаСеанса())); ``` --- -## Rule 4: Strategy for finding БСП functions +## Rule 4: BСП function search strategy ### Algorithm: LSP -> grep -> AI 1. **LSP** (if available): `navigate_symbol("ЗначенияРеквизитовОбъекта")` 2. **Text search**: `grep -r "Функция.*КурсВалюты" src/CommonModules/` -3. **AI assistant**: "Is there a БСП function for getting the exchange rate on a date?" +3. **AI assistant**: "Is there a BСП function for getting the exchange rate on a date?" -### When to write your own vs use БСП +### When to write your own vs use BСП | Situation | Decision | -|----------|---------| -| БСП has a suitable function | **Use БСП** | -| БСП has a similar function, but with extra functionality | **Use БСП** - extra functionality does not hurt | -| The needed function is not in БСП | Write your own in the БСП style | -| Configuration without БСП | Write your own | +|---|---| +| BСП has a suitable function | **Use BСП** | +| BСП has a similar function, but with extra functionality | **Use BСП** - the extra does not hurt | +| The needed function does not exist in BСП | Write your own in BСП style | +| Configuration without BСП | Write your own | --- -## Rule 5: Working with the registration log through БСП +## Rule 5: Working with the registration log through BСП See `error-handling`, rule 7. --- -## Rule 6: РаботаСФайлами instead of direct ФайловаяСистема +## Rule 6: `РаботаСФайлами` - instead of direct `ФайловаяСистема` -Direct file handling does not account for access rights, temporary files, or cross-platform compatibility. +Direct file handling does not account for: access rights, temporary files, cross-platform compatibility. ```bsl ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx"); @@ -131,9 +131,9 @@ Direct file handling does not account for access rights, temporary files, or cro --- -## Rule 7: Typical БСП patterns +## Rule 7: Typical BСП patterns -### Fill validation (ОбработкаПроверкиЗаполнения) +### Fill check (`ОбработкаПроверкиЗаполнения`) ```bsl Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты) @@ -174,41 +174,41 @@ Direct file handling does not account for access rights, temporary files, or cro --- -## Rule 8: Do not duplicate БСП functionality +## Rule 8: Do not duplicate BСП functionality -| What people often write themselves | What is in БСП | -|----------------------|----------------| +| What people often write themselves | What exists in BСП | +|---|---| | Get an attribute by reference | `ОбщегоНазначения.ЗначениеРеквизитаОбъекта()` | | String substitution | `СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку()` | | Word declension | `СтроковыеФункцииКлиентСервер.СтрокаСЧисломПредметов()` | | Sending mail | `РаботаСПочтовымиСообщениями` | | Exchange rate | `РаботаСКурсамиВалют.ПолучитьКурсВалюты()` | -| Long-running operation in the background | `ДлительныеОперации.ВыполнитьФункцию()` | -| Secret / password storage | `БезопасноеХранилище.ПрочитатьДанные()` | -| Access right profiles | `ГруппыДоступаПользователей` / `ПрофилиГруппДоступа` | -| Registering an external processor | `СведенияОВнешнейОбработке()` | +| Long-running background operation | `ДлительныеОперации.ВыполнитьФункцию()` | +| Storing secrets / passwords | `БезопасноеХранилище.ПрочитатьДанные()` | +| Access rights profiles | `ГруппыДоступаПользователей` / `ПрофилиГруппДоступа` | +| Registering an external processing object | `СведенияОВнешнейОбработке()` | --- -## Rule 9: "КлиентСервер" modules - responsibility split +## Rule 9: "ClientServer" modules - separation of responsibilities | Module suffix | Environment | Example | -|----------------|-------|--------| +|---|---|---| | (no suffix) | Server | `ОбщегоНазначения` | | `Клиент` | Client | `ОбщегоНазначенияКлиент` | | `КлиентСервер` | Both environments | `ОбщегоНазначенияКлиентСервер` | | `ПовтИсп` | Server, with caching | `ОбщегоНазначенияПовтИсп` | -For client-side form code, first look in `*КлиентСервер`, then in `*Клиент`. For server-side code, look primarily in the main module (without suffix). `*ПовтИсп` is for frequently requested reference data. +For client-side form code, search first in `*КлиентСервер`, then in `*Клиент`. For server-side code, use the main module (without suffix). `*ПовтИсп` is for frequently requested reference data. --- -## Rule 10: Long-running operations (ДлительныеОперации) +## Rule 10: Long-running operations (`ДлительныеОперации`) -Use the `ДлительныеОперации` subsystem for any server work that takes longer than about 3 seconds. Do not block the UI with a homemade wait loop. +Use the `ДлительныеОперации` subsystem for any server-side work longer than ~3 seconds. Do not block the UI with a hand-rolled wait loop. ```bsl -// Launch a background task +// Запуск фоновой задачи &НаСервере Функция ЗапуститьОперацию(Параметры) ПараметрыФона = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор); @@ -217,7 +217,7 @@ Use the `ДлительныеОперации` subsystem for any server work tha ПараметрыФона, Параметры); КонецФункции -// Connect waiting on the client +// Подключение ожидания на клиенте &НаКлиенте Процедура ЗапуститьОперациюНаКлиенте() Операция = ЗапуститьОперацию(ПараметрыРасчёта); @@ -227,35 +227,35 @@ Use the `ДлительныеОперации` subsystem for any server work tha Новый ОписаниеОповещения("ОперацияЗавершена", ЭтотОбъект), ПараметрыОжидания); КонецПроцедуры -// Handle the result +// Обработка результата &НаКлиенте Процедура ОперацияЗавершена(Операция, ДополнительныеПараметры) Экспорт Если Операция = Неопределено Тогда - Возврат; // Canceled by the user + Возврат; // Отменена пользователем КонецЕсли; Если Операция.Статус = "Ошибка" Тогда СтандартныеПодсистемыКлиент.ОбработатьОшибкуФоновогоЗадания(Операция); Возврат; КонецЕсли; - // Get result + // Получить результат РезультатОперации = ПолучитьРезультатСервер(Операция.АдресРезультата); КонецПроцедуры ``` **Key rules:** - Pass progress through `ДлительныеОперации.СообщитьПрогресс()` inside the background procedure. -- Do not store state between steps in global variables - use job parameters. -- Implement idempotent restart: a repeated call with the same parameters must produce the same result. +- Do not store state between steps in global variables - use task parameters. +- Implement idempotent restart: a repeated call with the same parameters should produce the same result. --- -## Rule 11: Secure storage (БезопасноеХранилище) +## Rule 11: Secure storage (`БезопасноеХранилище`) Never store passwords, tokens, or secrets in: - metadata object attributes - configuration constants - the registration log -- version control systems (configs, xml) +- version control system (configs, xml) ```bsl // Запись секрета @@ -271,16 +271,16 @@ Never store passwords, tokens, or secrets in: БезопасноеХранилище.Удалить(ЭтотОбъект); ``` -In the object's `ПередУдалением` handler, always call `БезопасноеХранилище.Удалить()` - otherwise "orphaned" records accumulate in the storage. +In an object `ПередУдалением` handler, always call `БезопасноеХранилище.Удалить()` - otherwise "orphaned" records accumulate in storage. --- -## Rule 12: Access group profiles (ПрофилиГруппДоступа) +## Rule 12: Access group profiles (`ПрофилиГруппДоступа`) -When developing subsystems with role-based access, use the БСП profile mechanism instead of assigning roles directly. +When developing subsystems with role-based access, use the BСП profile mechanism instead of assigning roles directly. ```bsl -// Example of a profile description in ОписаниеПрофилейГруппДоступа() +// Пример описания профиля в ОписаниеПрофилейГруппДоступа() Профиль = УправлениеДоступом.ОписаниеПрофиля(); Профиль.Идентификатор = "ИдентификаторПрофиля_UUID"; Профиль.Наименование = НСтр("ru = 'Менеджер по продажам'"); @@ -290,14 +290,14 @@ When developing subsystems with role-based access, use the БСП profile mechan **Key rules:** - The profile identifier is a fixed UUID and does not change when renamed. -- For elevated privileges, use `ПривилегированныйРежим()` strictly locally, and disable it immediately after the operation. -- Perform permission checks through `УправлениеДоступом.ПроверитьДопустимостьДействия()`, not directly through `РольДоступна()` - the latter does not take RLS into account. +- For elevated privileges, use `ПривилегированныйРежим()` strictly locally, and turn it off immediately after the operation. +- Check permissions through `УправлениеДоступом.ПроверитьДопустимостьДействия()`, not directly through `РольДоступна()` - the latter does not account for RLS. --- -## Rule 13: External processors and extensions (СведенияОВнешнейОбработке) +## Rule 13: External processing objects and extensions (`СведенияОВнешнейОбработке`) -Registering an external processor in a БСП-based configuration requires the `СведенияОВнешнейОбработке()` function in the processor's main module. +Registering an external processing object in a BСП-based configuration requires the `СведенияОВнешнейОбработке()` function in the main module of the processing object. ```bsl // В модуле обработки @@ -329,9 +329,9 @@ Registering an external processor in a БСП-based configuration requires the ` --- -## Searching for analogs via Buddy +## Searching for analogs through Buddy -If `search_ssl_functions` did not return a result, use `ask_ai_assistant` (VALIDATE_BSL template from `buddy-prompting`): pass a code fragment and get recommendations for replacing it with БСП methods. Also use `SEARCH_DOCS` for documentation on a specific БСП method. +If `search_ssl_functions` did not return a result, use `ask_ai_assistant` (VALIDATE_BSL template from `buddy-prompting`): pass a code fragment and get recommendations for replacing it with BСП methods. Also use `SEARCH_DOCS` for documentation on a specific BСП method. --- depends_on: [] diff --git a/framework_eng/skills/bsl-practices/test-writing/SKILL.md b/framework_eng/skills/bsl-practices/test-writing/SKILL.md index 5b3dc1d1..29923183 100644 --- a/framework_eng/skills/bsl-practices/test-writing/SKILL.md +++ b/framework_eng/skills/bsl-practices/test-writing/SKILL.md @@ -1,6 +1,6 @@ --- name: test-writing -description: "Use for writing YaxUnit (BSL) test modules. Covers test registration, assertions, mocking, and test data preparation." +description: "Use for YaxUnit BSL tests, mocks, and assertions" --- # Writing YaxUnit Tests (BSL) @@ -19,8 +19,8 @@ Tests are stored in a **separate configuration extension**: `<project root>/exts | Format | Module code | Metadata file | |--------|------------|-----------------| -| EDT | `exts/TESTS/src/CommonModules/<ModuleName>/Module.bsl` | `.../<ModuleName>.mdo` | -| DESIGNER | `exts/TESTS/src/CommonModules/<ModuleName>/Ext/Module.bsl` | `.../<ModuleName>.xml` | +| EDT | `exts/TESTS/src/CommonModules/<ИмяМодуля>/Module.bsl` | `.../<ИмяМодуля>.mdo` | +| DESIGNER | `exts/TESTS/src/CommonModules/<ИмяМодуля>/Ext/Module.bsl` | `.../<ИмяМодуля>.xml` | If the format is not obvious, check `application-*.yml` / `yaxunit-*.yml` at the project root. @@ -43,11 +43,11 @@ Template: `<Prefix>_<ObjectName>[_<Suffix>]` | Object type | Prefix | Example | |-------------|---------|--------| | Common module | `ОМ_` | `ОМ_ОбщегоНазначения` | -| Document | `Док_` | `Док_ПоступлениеТоваров` | -| Catalog | `Спр_` | `Спр_Контрагенты` | -| Accumulation register | `РН_` | `РН_ОстаткиТоваров` | -| Information register | `РС_` | `РС_КурсыВалют` | -| Data processor | `Обр_` | `Обр_ЗакрытиеМесяца` | +| Документ | `Док_` | `Док_ПоступлениеТоваров` | +| Справочник | `Спр_` | `Спр_Контрагенты` | +| Регистр накопления | `РН_` | `РН_ОстаткиТоваров` | +| Регистр сведений | `РС_` | `РС_КурсыВалют` | +| Обработка | `Обр_` | `Обр_ЗакрытиеМесяца` | ### Suffixes by module type @@ -59,6 +59,47 @@ Template: `<Prefix>_<ObjectName>[_<Suffix>]` --- +## One-off operational YaxUnit modules + +Sometimes YaxUnit is used not as a regression test, but as a one-off server-side channel for a manual production operation: fix data, repost a targeted set of documents, perform a controlled migration. Such a module is NOT an ordinary test and must not accidentally end up in the "run all tests" mode. + +### Required marking + +| What to mark | Convention | +|-----------------|-----------| +| Module name | `Опер_<Description>[_Number]` or project prefix + explicit `_Операция_` fragment; do not disguise it as an ordinary `_Тест` | +| Module header | First-line comment: `// ONE_OFF_YAXUNIT_OPERATION: НЕ ЗАПУСКАТЬ В ОБЩЕМ ПРОГОНЕ. <назначение>` | +| Set name | Prefix `[ONE_OFF_OPERATION] <short purpose>` | +| YaxUnit tags | `.Тег("one-off-operation")` on the set and, if tests are registered separately, on each operational test | +| Run context | Comment next to registration: who approved the operation, on which base/environment it may run, how to verify the result, and how to remove the module from the general run after completion | + +### Barrier against the general run + +The marker and tag are navigation, not protection. The operational module MUST have a technical barrier that prevents the ordinary all-tests run from registering and executing the operation: + +1. Preferably, do not keep such a module registered in the general test extension after the operation is complete: move it to task artifacts, remove the registration, or disable the module through a separate maintenance task. +2. If the module temporarily remains in the test extension, `ИсполняемыеСценарии()` MUST return without `ДобавитьТестовыйНабор()` unless there is explicit opt-in. Opt-in is provided by a separate run parameter / setting / wrapper and is documented in the registration comment. The ordinary "run all tests" does not set this opt-in. +3. A targeted run of the operational module is allowed only with an explicit filter by module/method and the `one-off-operation` tag, after separate operator confirmation. Running without a module/method filter is forbidden. +4. After a successful operation, the agent MUST record how the module was removed from the general run. Leaving an executable production-operation module in the general all-tests run without an opt-in barrier is forbidden. + +```bsl +// ONE_OFF_YAXUNIT_OPERATION: НЕ ЗАПУСКАТЬ В ОБЩЕМ ПРОГОНЕ. Разовая корректировка данных. +Процедура ИсполняемыеСценарии() Экспорт + + Если НЕ РазовыйОперационныйПрогонРазрешён() Тогда + Возврат; + КонецЕсли; + + ЮТТесты + .ДобавитьТестовыйНабор("[ONE_OFF_OPERATION] Корректировка данных") + .Тег("one-off-operation") + .ДобавитьСерверныйТест("ВыполнитьКорректировку"); + +КонецПроцедуры +``` + +--- + ## Test module structure Mandatory: export procedure `ИсполняемыеСценарии`. Registration only - no data, no logic. @@ -159,12 +200,12 @@ A test object must be valid just like a production one. An incomplete test objec | Requirement | Rule | |---|---| -| **Owner for subordinate catalogs** | A catalog subordinate to an owner (metadata sets `Подчинение`/`Владельцы`) must ALWAYS fill `Владелец` in test data. A subordinate item without an owner is semantically invalid; code uniqueness is checked **within the owner scope** (hence `Код не уникально` collisions); queries and cleanup by owner break on such an item. | -| **All mandatory fields** | Fill ALL fields whose metadata has `Проверка заполнения = Выдавать ошибку` (`FillChecking = ShowError`), plus mandatory standard fields. | -| **Mandatory standard fields** | Catalog: `Наименование`/`Код` if they are marked by fill checking; subordinate - `Владелец`. Document: `Дата` (and `Номер` if there is no auto-numbering). Information register record set (`РС`): ALL dimensions. | -| **Source of truth - metadata, NOT a neighboring test** | Before creating a test object, check the metadata description (`get_metadata_structure` / Configurator): which fields are `ShowError`, whether there is subordination. Copying a field set from a neighboring test without checking is forbidden - the object may have acquired a new mandatory field. | +| **Owner for subordinate Справочник** | A `Справочник` subordinate to an owner (metadata has `Подчинение`/`Владельцы`) must ALWAYS fill `Владелец` in test data. A subordinate item without an owner is semantically invalid; code uniqueness is checked **within the owner scope** (hence the `Код не уникально` collisions); queries and cleanup by owner break on such an item. | +| **All mandatory requisites** | Fill ALL requisites whose metadata has `Проверка заполнения = Выдавать ошибку` (`FillChecking = ShowError`), plus mandatory standard requisites. | +| **Mandatory standard requisites** | `Справочник`: `Наименование`/`Код` if they are marked by fill checking; subordinate - `Владелец`. `Документ`: `Дата` (and `Номер` if there is no auto-numbering). `Набор записей РС`: ALL dimensions. | +| **Source of truth - metadata, NOT a neighboring test** | Before creating a test object, check the metadata description (`get_metadata_structure` / Configurator): which requisites are `ShowError`, whether there is subordination. Copying a field set from a neighboring test without checking is forbidden - the object may have acquired a new mandatory requisite. | -**Why by metadata, not by example:** field mandatory-ness is an object property (`Проверка заполнения`), and it changes when the configuration is updated. A test that fills fields "like the neighbor" silently stops covering a new mandatory field - and then either fails on posting or writes incomplete data. Checking against the metadata description makes the field set self-updating. +**Why by metadata, not by example:** field mandatory-ness is an object property (`Проверка заполнения`), and it changes when the configuration is updated. A test that fills fields "like the neighbor" silently stops covering a new mandatory requisite - and then either fails on posting or writes incomplete data. Checking against the metadata description makes the field set self-updating. ```bsl // Подчинённый справочник: Владелец ОБЯЗАТЕЛЕН (Договор подчинён Контрагенту) @@ -184,7 +225,7 @@ A test object must be valid just like a production one. An incomplete test objec --- -## Mocking (Mokito) +## Mocking (Мокито) Pattern: Training -> Run -> Verify. @@ -271,11 +312,11 @@ Pattern: Training -> Run -> Verify. ## Test data isolation (MUST) -A test that writes to the DB must roll back its changes. Without isolation, every run leaves garbage in the database and the tests lose idempotency. +A test that writes to the database must roll back its changes. Without isolation, every run leaves garbage in the database and the tests lose idempotence. ### Transactional isolation via `.ВТранзакции()` -The fluent method `.ВТранзакции()` is called immediately after `ДобавитьТестовыйНабор()` - the setting applies at the **set** level (runtime resolves it by hierarchy: Test -> Set -> Module). Before each test in the set, YaxUnit opens a transaction, and after the test it rolls it back. +The fluent method `.ВТранзакции()` is called immediately after `ДобавитьТестовыйНабор()` - the setting is applied at the **set** level (the runtime searches by hierarchy: Test -> Set -> Module). Before each test in the set, YaxUnit opens a transaction, and after the test it rolls it back. ```bsl Процедура ИсполняемыеСценарии() Экспорт @@ -291,79 +332,80 @@ The fluent method `.ВТранзакции()` is called immediately after `До ### Test object collector (mandatory teardown mechanism) -The `test-zero-residue` rule requires every test that generates data to register EVERY created object in the collector at creation time. Teardown walks the collector and physically deletes everything that survived transaction rollback. This is the standard cleanup mechanism, not a database scan by names or prefixes. +> The `test-zero-residue` rule requires: a test that generates data must register EVERY created object in the collector **at the moment of creation**; teardown iterates through the collector and physically deletes everything that survived the transaction rollback. This is the main standard cleanup mechanism - NOT a database sweep by names/prefixes. -**Why a collector, not YaxUnit auto-tracking:** `ЮТест.Данные()` auto-deletion works ONLY when the set calls `.УдалениеТестовыхДанных()`. Objects created through `КонструкторОбъекта(...).Записать()`, `Документы.X.СоздатьДокумент()`, `Справочники.X.СоздатьЭлемент()` or helpers are not tracked at all. The collector covers all creation paths uniformly by exact references. +**Why a collector, not `ЮТест.Данные()` auto-tracking:** auto-deletion of `ЮТест.Данные()` works ONLY if `.УдалениеТестовыхДанных()` is called on the set. Objects created through `КонструкторОбъекта(...).Записать()`, `Документы.X.СоздатьДокумент()`, `Справочники.X.СоздатьЭлемент()` or from helpers are **NOT tracked at all**. The collector covers ALL creation paths uniformly - by exact references, without guessing. -**Collector module contract** (common server module, for example `биг_ТестовыйКоллектор`): -- `Зарегистрировать(Ссылка) Экспорт` - call immediately after EACH object creation. -- `ОчиститьВсё() Экспорт` - call in teardown (`.После()` / final scenario step / `ПослеВсехТестов()`): walk in LIFO order, dependent objects before owners; read `Объект = Ссылка.ПолучитьОбъект()`; skip `Неопределено`; otherwise set `Объект.ОбменДанными.Загрузка = Истина` and delete under `Попытка` with logging. Clear the accumulator at the end. -- **Accumulator storage trap:** a module-level `Перем` in a common server module does not survive separate `НаСервереБезКонтекста` calls used by YaxUnit to run tests. Store the accumulator in `ХранилищеОбщихНастроек` or an equivalent cross-call storage, not in `Перем`. -- **Reverse walk trap (LIFO):** a 1C `Для` loop only counts upward. `Для Сч = Накопитель.ВГраница() По 0 Цикл` executes zero iterations for a non-empty accumulator. Use `Пока` with manual decrement before any `Продолжить`. +**Collector module contract (a common server module, for example `биг_ТестовыйКоллектор`):** +- `Зарегистрировать(Ссылка) Экспорт` - called immediately after EACH creation (catalog, document, subaccount, owner set, etc.). +- `ОчиститьВсё() Экспорт` - in teardown (`.После()` / final scenario step / `ПослеВсехТестов()`): LIFO traversal (dependents -> owners); `Объект = Ссылка.ПолучитьОбъект()`; if `Неопределено` (survived `.ВТранзакции()` rollback or was removed cascade) -> skip; otherwise `Объект.ОбменДанными.Загрузка = Истина; Объект.Удалить();` under `Попытка` + log. At the end - reset the accumulator. +- **Accumulator storage trap:** a module `Перем` at the session level in a common server module does NOT survive between separate `НаСервереБезКонтекста` calls, which YaxUnit uses to run each test. Store the accumulator in `ХранилищеОбщихНастроек` (or an equivalent that survives calls), not in `Перем`. +- **Reverse traversal trap (LIFO):** the `Для` loop in 1C counts ONLY upward - there is no downward step. `Для Сч = Накопитель.ВГраница() По 0 Цикл` does NOT execute the body AT ALL (the condition `ВГраница() <= 0` is false immediately for a non-empty accumulator) - this is a SILENT no-op: the test is green, the log is clean, and residue keeps accumulating (GBIG PAM precedent: `удалено=0` with 40 in the accumulator). Reverse traversal must be done ONLY with `Пока` and manual decrement BEFORE any `Продолжить`. ```bsl -// creation - register immediately +// creation — register immediately Портфель = ЮТест.Данные().СоздатьЭлемент("Справочник.биг_Портфели").Установить(...).Объект().Ссылка; биг_ТестовыйКоллектор.Зарегистрировать(Портфель); ... -// teardown - one call for the whole accumulator +// teardown — one call for the whole accumulator Процедура ПослеВсехТестов() Экспорт биг_ТестовыйКоллектор.ОчиститьВсё(); КонецПроцедуры ``` -**Canonical reverse walk in `ОчиститьВсё()` (LIFO: dependents before owners):** +**Canonical reverse traversal in `ОчиститьВсё()` (LIFO: dependents before owners):** ```bsl Процедура ОчиститьВсё() Экспорт Накопитель = ПрочитатьНакопитель(); + // ВАЖНО: `Пока` with decrement, NOT `Для ... По 0` (that one will not execute - see the trap above). Сч = Накопитель.ВГраница(); Пока Сч >= 0 Цикл Ссылка = Накопитель[Сч]; - Сч = Сч - 1; // decrement BEFORE `Продолжить` + Сч = Сч - 1; // decrement BEFORE `Продолжить`, otherwise infinite loop Если НЕ ЗначениеЗаполнено(Ссылка) Тогда Продолжить; КонецЕсли; Попытка Объект = Ссылка.ПолучитьОбъект(); - Если Объект <> Неопределено Тогда - Объект.ОбменДанными.Загрузка = Истина; + Если Объект <> Неопределено Тогда // Неопределено = survived rollback / removed cascade -> normal + Объект.ОбменДанными.Загрузка = Истина; // bypass FillChecking/posting during physical delete Объект.Удалить(); КонецЕсли; Исключение ЗаписьЖурналаРегистрации("ТестовыйКоллектор", УровеньЖурналаРегистрации.Предупреждение, - , Ссылка, ОписаниеОшибки()); + , Ссылка, ОписаниеОшибки()); // the leak is visible in the log, but teardown does not fail КонецПопытки; КонецЦикла; - Сбросить(); + Сбросить(); // reset the accumulator -> the next module starts empty КонецПроцедуры ``` -**Collector acceptance:** not "the test is green", but DELTA-0: counters for affected catalogs/documents/registers before and after the run are equal. Verify the delta with `КОЛИЧЕСТВО(*)` queries before/after, and load BSL changes through a full rebuild; dynamic build is a no-op for BSL. +**Collector acceptance:** not "the test is green", but DELTA-0 - the counters of affected catalogs/documents/registers before and after the run are equal. A green test with a broken teardown is a typical disguise (loop no-op above). Check the delta with `КОЛИЧЕСТВО(*)` before/after, and load BSL changes through a full rebuild (dynamic build - no-op for BSL, residue from the previous run creates a false picture). -### Catalogs - create as tracked and register in collector +### Справочники - create trackably + register in the collector -Create catalog items through `ЮТест.Данные().СоздатьЭлемент(...)` or `КонструкторОбъекта(...).Записать()` and register them in the collector immediately. `КонструкторОбъекта(...).Записать()` and direct `Справочники.X.СоздатьЭлемент()` are not tracked by YaxUnit, and even `ЮТест.Данные()` does not auto-delete without `.УдалениеТестовыхДанных()`. A direct catalog creation outside the collector is an antipattern. +Create catalog elements through `ЮТест.Данные().СоздатьЭлемент(...)` or `КонструкторОбъекта(...).Записать()` and **register them in the collector immediately**. Important: `КонструкторОбъекта(...).Записать()` and direct `Справочники.X.СоздатьЭлемент()` are NOT tracked by YaxUnit (they remain in the database) - for them the collector is mandatory; even `ЮТест.Данные()` without `.УдалениеТестовыхДанных()` is not self-deleting. Direct `Справочники.X.СоздатьЭлемент()` outside the collector is an anti-pattern. -### Documents via `СоздатьДокумент()` - mandatory teardown +### Documents through `СоздатьДокумент()` - mandatory teardown -`ЮТест.Данные().СоздатьДокумент(...)` is tracked and deleted automatically. But if a document is created directly through `Документы.X.СоздатьДокумент()`, it is NOT tracked, and an explicit teardown in `.После("ИмяПроцедурыОчистки")` is required. +`ЮТест.Данные().СоздатьДокумент(...)` is tracked and deleted automatically. But if a document is created directly through `Документы.X.СоздатьДокумент()` - it is NOT tracked, and you need an explicit teardown in `.После("ИмяПроцедурыОчистки")`. ### Exceptions from `.ВТранзакции()` -There are three situations where `.ВТранзакции()` MUST NOT be used - in each case, a justification comment is required on the set and teardown through `.После()`: +Three situations when `.ВТранзакции()` MUST NOT be used - for each of them, a comment with the reason is mandatory next to the set and teardown through `.После()`: | Situation | Reason for exclusion | Isolation method | |---|---|---| -| **(a) Negative posting test** (expected `Отказ`) | A failed nested transaction poisons the outer one: "Errors have already occurred in this transaction!" on subsequent reads | `.УдалениеТестовыхДанных()` + `.После("Очистка")` | -| **(b) Prod code with `ТранзакцияАктивна()` guard** | Two-phase commits, real API calls, registers with a unique key - fail or behave unpredictably inside a transaction | `.После("Очистка")` with manual cleanup | -| **(c) Client context** | `ДобавитьКлиентскийТест` - transactional rollback on the client is unavailable due to platform architecture | `Перед`/`После` handlers with server context | +| **(a) Negative posting test** (expected `Отказ`) | A failed nested transaction poisons the outer one: "В данной транзакции уже происходили ошибки!" on subsequent reads | `.УдалениеТестовыхДанных()` + `.После("Очистка")` | +| **(b) Production code with `ТранзакцияАктивна()` guard** | Two-phase commits, real API calls, registers with a unique key - fail or behave unpredictably inside a transaction | `.После("Очистка")` with manual cleanup | +| **(c) Client context** | `ДобавитьКлиентскийТест` - transactional rollback is not available on the client by platform architecture | `Перед`/`После` handlers with server context | ```bsl -// Exception (a): negative test - the expected Отказ poisons the outer transaction. -// Isolation: ЮТест.Данные() + .УдалениеТестовыхДанных() + teardown in .После(). +// Исключение (а): негативный тест — ожидаемый Отказ отравляет внешнюю транзакцию. +// Изоляция: ЮТест.Данные() + .УдалениеТестовыхДанных() + teardown в .После(). ЮТТесты .ДобавитьТестовыйНабор("Запрет проведения") .УдалениеТестовыхДанных() @@ -371,9 +413,9 @@ There are three situations where `.ВТранзакции()` MUST NOT be used - .ДобавитьСерверныйТест("ТестЗапретБезДоговора"); ``` -### Object reread pattern when reposting +### Pattern for rereading an object during reposting -A test that changes a document's write mode **must reread the object** between mode changes - this models form behavior: +A test that changes the document write mode **must reread the object** between changes - this models form behavior: ```bsl // Провести @@ -385,46 +427,48 @@ A test that changes a document's write mode **must reread the object** between m ДокОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения); ``` -**Platform 8.3.27 limitation:** programmatic reposting in a server session sometimes produces `[ОшибкаХранимыхДанных]` - a stack without application frames, and neither rereading nor `.ВТранзакции()` helps. In that case, reposting idempotency is verified at the scenario layer (Vanessa), and the unit test is recorded via `ЮТест.Пропустить()` with an explicit justification. +**Platform limitation 8.3.27:** programmatic reposting in a server session sometimes gives `[ОшибкаХранимыхДанных]` - a stack without application frames, and neither rereading nor `.ВТранзакции()` helps. In that case, reposting idempotence is checked at the scenario layer (Vanessa), and the unit test is оформляется through `ЮТест.Пропустить()` with an explicit explanation. ### Self-cleanup checklist - verification by queries (MUST after writing/editing write tests) -Isolation is declared in code (`.ВТранзакции()`, teardown), but it is **proven by facts** - counters in the DB before/after the run. A green run does NOT prove cleanliness: a test may pass and still leave garbage behind. +Isolation is declared in code (`.ВТранзакции()`, teardown), but **proved by fact** - by database counters before/after the run. A green run does NOT prove cleanliness: the test may pass and still leave garbage behind. -1. **Table map.** Make a list of the tables the module tests may write to: everything created by `Перед` handlers and test bodies (catalogs, documents, registers), including context helper objects (`СоздатьКонтекстТеста` and so on). -2. **Counters BEFORE.** For each table - `ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ Справочник.X` (platform query: MCP `execute_query` / query console). For information registers, count by the test marker dimension, not the whole table. -3. **Run + counters AFTER.** Run the whole module, collect the same counters. The delta for each table = 0. -4. **Second run.** Repeat: GREEN + delta 0 again. The first run may have "eaten" someone else's accumulated garbage and masked your own - repeatability is mandatory. -5. **Delta != 0 -> culprit.** Find the remaining objects by names/markers (`ВЫБРАТЬ Наименование ... ГДЕ Наименование ПОДОБНО "...%"`), identify the creating handler/test, add teardown, repeat the checklist from step 2. +1. **Table map.** Make a list of the tables that the module tests may write to: everything created by `Перед` handlers and test bodies (catalogs, documents, registers), including context-helper objects (`СоздатьКонтекстТеста` and the like). +2. **Counters BEFORE.** For each table - `ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ Справочник.X` (platform query: MCP `execute_query` / query console). For information registers - a counter by the test marker dimension, not by the whole table. +3. **Run + counters AFTER.** Run the whole module, collect the same counters. Delta for each table = 0. +4. **Second run.** Repeat: GREEN + delta 0 again. The first run may have "eaten" someone else's accumulated garbage and masked its own - repeatability is mandatory. +5. **Delta != 0 -> culprit.** Find the remaining objects by names/markers (`ВЫБРАТЬ Наименование ... ГДЕ Наименование ПОДОБНО "...%"`), identify the creating handler/test, add teardown, and repeat the checklist from step 2. -**Pitfalls (precedent TASK-173 / TASK-165.7):** +**Traps (TASK-173 / TASK-165.7 precedent):** -| Pitfall | Essence | +| Trap | Essence | |---|---| -| YaxUnit auto-delete fails on `.Записать(Ложь, Истина)` | `УстановитьПометкуУдаления` revalidates required fields and refuses - the object remains. Teardown is physical deletion: `Объект.ОбменДанными.Загрузка = Истина; Объект.Удалить();` | -| Partial teardown | The `После` handler cleans only part of what was created (for example, the semaphore register but not the account catalog) - it looks like teardown, but still leaves garbage | -| "GREEN = clean" | 41/41 tests are green, while one module still left +15 objects per run - detected only by counters | +| YaxUnit auto-deletion fails on `.Записать(Ложь, Истина)` | `УстановитьПометкуУдаления` re-validates mandatory requisites and refuses - the object remains. Teardown is physical deletion: `Объект.ОбменДанными.Загрузка = Истина; Объект.Удалить();` | +| Partial teardown | The `После` handler cleans only part of what was created (for example a semaphore register, but not the account catalog) - it looks like teardown, but it still leaves garbage | +| "GREEN = clean" | 41/41 tests are green, while one module left +15 objects per run - detected only by counters | --- -## Antipatterns +## Anti-patterns -| Antipattern | Correct | +| Anti-pattern | Correct | |-------------|-----------| | Data in `ИсполняемыеСценарии` | Data in the test body or `Перед` handler | | One test checks 10 conditions | One test - one assertion | | Test depends on execution order | Each test is isolated | -| Hardcoded references to infobase objects | Create through `ЮТест.Данные()` | +| Hardcoded links to database objects | Create through `ЮТест.Данные()` | | Testing private logic | Test through the public interface | | Mocking the module under test | Mock only *dependencies* | -| Writable set without `.ВТранзакции()` | `.ВТранзакции()` by default; exceptions - with a comment + teardown | -| `Справочники.X.СоздатьЭлемент()` in a test | `ЮТест.Данные().СоздатьЭлемент()` - tracked and deleted automatically | +| Writing set without `.ВТранзакции()` | `.ВТранзакции()` by default; exceptions - with a comment + teardown | +| `Справочники.X.СоздатьЭлемент()` in a test | `ЮТест.Данные().СоздатьЭлемент()` + registration in the collector | | `.ВТранзакции()` on a negative posting test | Exception (a) - poisons the transaction; use `.УдалениеТестовыхДанных()` + `.После()` | +| Created an object, did not register it in the collector | Every creation -> `Коллектор.Зарегистрировать(Ссылка)` immediately; teardown -> `Коллектор.ОчиститьВсё()` | +| Teardown by scanning the database by name/prefix/regex (`ПОДОБНО "Тест%"`) | Fragile (too broad deletes production data, too narrow leaves residue). Only a one-time sweeper for historical garbage; standard teardown is the collector (exact references) | | "GREEN = clean" acceptance without counters | Self-cleanup checklist: counters before/after by queries, two runs, delta 0 | --- -## TDD layers and phases, role boundaries +## Layers and phases of TDD, role boundaries Tests and implementation are written by **different agents** in **different phases**. The test author does not know the implementation, and the code author does not modify tests. @@ -439,18 +483,18 @@ Phase 4: Tester → edge cases, regression, BDD + unit | Layer | Phase | Agent | Covers | |------|------|-------|-----------| -| BDD (acceptance) | 3a | Scenario-Author | Behavior through the UI | +| BDD (acceptance) | 3a | Scenario-Author | Behavior through UI | | TDD (unit) | 3b | Developer-Tests | Public methods, MUST scenarios, basic negatives | | TDD (green) | 3c | Developer-Code | Implementation that passes unit tests | | Coverage | 4 | Tester | Edge cases, integration, regression | -Phase 3a and 3b run **in parallel**. Phase 3c starts after both are complete. +Phase 3a and 3b are **parallel**. Phase 3c starts after both are complete. ### Agent boundaries -- **Scenario-Author:** does NOT write unit tests, does NOT run scenarios, does NOT go beyond the specification +- **Scenario-Author:** does NOT write unit tests, does NOT run scenarios, does NOT extend beyond the specification - **Developer-Tests:** MUST scenarios + basic negatives; does NOT cover combinatorial edge cases and integration -- **Tester:** extends coverage; does NOT duplicate Developer tests; does NOT edit BSL code +- **Tester:** extends coverage; does NOT duplicate Developer tests; does NOT modify BSL code ### Rule when a Tester test fails @@ -461,7 +505,7 @@ Phase 3a and 3b run **in parallel**. Phase 3c starts after both are complete. Оркестратор возвращает задачу Developer. ``` -**User/Role context in Test Plan:** if the code uses `SetPrivilegedMode`, role checks (`AccessRight`, `RoleAvailable`), or the result depends on the current user, the specification MUST explicitly state for each test in the "Test Plan" section: user name / role set, required mode (privileged or not), expected result (success / refusal). Without this, a test under a full-rights runner (for example `AgentAI`) will produce a false positive: it will pass "by coincidence" through the privileged branch without checking role-dependent behavior. If this is technically impossible for unit tests, it is recorded in the spec as a separate ADR with a move to integration scope (Phase 4). +**User/Role context in Test Plan:** if the code uses `SetPrivilegedMode`, role checks (`AccessRight`, `RoleAvailable`) or the result depends on the current user, the specification MUST explicitly list for each test in the "Test Plan" section: user name / role set, required mode (privileged or not), expected result (success / отказ). Without this, the test under a full-rights runner (for example `AgentAI`) will produce a false positive: it will pass "by coincidence" through the privileged branch without checking role-dependent behavior. If this is technically impossible for unit tests, it is recorded in the spec as a separate ADR with a move to integration scope (Phase 4). --- depends_on: [] diff --git a/framework_eng/skills/framework-meta/skill-editing-from-project/SKILL.md b/framework_eng/skills/framework-meta/skill-editing-from-project/SKILL.md index c4f0afa5..4cf2a019 100644 --- a/framework_eng/skills/framework-meta/skill-editing-from-project/SKILL.md +++ b/framework_eng/skills/framework-meta/skill-editing-from-project/SKILL.md @@ -1,7 +1,7 @@ --- name: skill-editing-from-project installable: true -description: Use when editing framework skills while in a 1C project directory (not in the framework repository). Helps locate the RU source through symlinks and `.install-session.json` without switching repositories. +description: "Edit framework skills from a project via install-session" --- # Editing Framework Skills from a Project diff --git a/framework_eng/skills/other/find-skills/SKILL.md b/framework_eng/skills/other/find-skills/SKILL.md index 27a9d373..13199337 100644 --- a/framework_eng/skills/other/find-skills/SKILL.md +++ b/framework_eng/skills/other/find-skills/SKILL.md @@ -1,6 +1,6 @@ --- name: find-skills -description: "Use for discovering and installing agent skills when the user asks whether there is a skill for X or wants to extend capabilities. Helps find a suitable skill through `npx skills find` and install it." +description: "Find or install agent skills on user request" capabilities: skills-management --- diff --git a/framework_eng/skills/spec-writing/spec-standard/SKILL.md b/framework_eng/skills/spec-writing/spec-standard/SKILL.md index 315d2a53..8b05ea29 100644 --- a/framework_eng/skills/spec-writing/spec-standard/SKILL.md +++ b/framework_eng/skills/spec-writing/spec-standard/SKILL.md @@ -1,6 +1,6 @@ --- name: spec-standard -description: "Use for writing task specifications (SDD). Defines the document structure, RFC 2119 requirement levels, and a quality checklist for Phase 1 full-cycle." +description: "For SDD specifications with RFC 2119 and a checklist" --- # Specification Writing Skill (SDD) @@ -9,22 +9,22 @@ The skill **does not choose the execution mode** (subagent/linear) - only the st --- -## 2. When a specification is needed +## 2. When a Specification Is Needed -| Task type | Specification required | Rationale | +| Task type | Spec needed | Rationale | |------------|-------------|-------------| -| New functionality | MUST | Captures scope, requirements, alternatives, and the chosen solution. | +| New functionality | MUST | Fixes scope, requirements, alternatives, and the chosen solution. | | Bug fix with architectural impact | MUST | The change in structure/behavior must be justified. | | Simple local bug fix | MAY | A short description without a full spec is acceptable if the change is isolated. | -| Large refactoring | SHOULD | Transparency about boundaries and the consequences of changes is needed. | +| Large refactoring | SHOULD | Transparency is needed around the boundaries and consequences of the changes. | --- -## 3. Specification language +## 3. Specification Language -The specification MUST be written in **Russian** - section headings, descriptions, requirements, and scenarios. The exception is code and metadata identifiers (module names, attributes, variables), which remain as-is. +The specification MUST be written in **Russian** - section headings, descriptions, requirements, and scenarios. Exception: code and metadata identifiers (module names, attributes, variables) remain as-is. -## 4. Required specification structure +## 4. Required Specification Structure ```markdown # SPEC-NNN: [Краткое название] @@ -56,109 +56,129 @@ The specification MUST be written in **Russian** - section headings, description ### Тестовые пользователи (Test Users) -Если тесты (unit / BDD / integration) зависят от ролей, прав или контекста пользователя, спека ОБЯЗАНА содержать секцию «Test Users» (или эквивалент) со следующими правилами: +If tests (unit / BDD / integration) depend on user roles, permissions, or context, the spec MUST contain a "Test Users" section (or equivalent) with the following rules: -- Перечислять **только реально существующих** в целевой базе пользователей (логин + состав ролей + ссылка на источник: предзагруженный профиль, fixture, final-report связанной задачи и т.п.). -- **Запрещены placeholder-имена** («User1», «TestUser», «Manager_NoRole»), а также вымышленные ФИО без подтверждённого соответствия реальному аккаунту в базе («Сидоров», «Иванов» — если такого пользователя в базе нет). -- Для каждого test user указать минимум: логин, состав ролей, источник, тестовый сценарий-применение. -- Если подходящий пользователь **неизвестен** или **не существует** — Analyst задаёт `clarification_needed` пользователю в clarification round, а не выдумывает имя. Допустимо предложить пользователю кандидатов на создание (с указанием ролей), но имя должно быть подтверждено. -- Если test user должен быть **создан администратором** перед запуском (manual data prep) — это явно фиксируется отдельным пунктом в `manual-test-scenario.md` или эквивалентном артефакте, с описанием шагов создания. +- List **only actual users** that exist in the target database (login + role set + source link: preloaded profile, fixture, final-report of the linked task, etc.). +- **Placeholder names are forbidden** ("User1", "TestUser", "Manager_NoRole"), as are invented full names without confirmed correspondence to a real account in the database ("Sidorov", "Ivanov" - if such a user does not exist in the database). +- For each test user, specify at minimum: login, role set, source, and the test scenario/application. +- If a suitable user is **unknown** or **does not exist** - the Analyst asks the user for `clarification_needed` during the clarification round instead of inventing a name. It is acceptable to propose candidates for creation to the user (with roles specified), but the name must be confirmed. +- If a test user must be **created by an administrator** before execution (manual data prep), this is explicitly recorded in a separate item in `manual-test-scenario.md` or an equivalent artifact, with the creation steps described. -**Почему:** placeholder-имена в спеке приводят к Vanessa-сценариям типа «Не смог подключить TestClient <Сидоров>» и проваливают весь Vanessa-уровень. Tester / Scenario-Coder не могут «угадать» реального пользователя и теряют часы на диагностику. +**Why:** placeholder names in a spec lead to Vanessa scenarios like "Could not connect TestClient <Sidorov>" and cause the entire Vanessa level to fail. The Tester / Scenario-Coder cannot "guess" a real user and lose hours to diagnostics. -## Приёмочные сценарии (BDD) +## Acceptance Scenarios (BDD) -## Открытые вопросы +## Open Questions -## Журнал решений (ADR) +## Decision Log (ADR) ``` --- -## 4a. No duplication of test levels (MUST) +## 4a. No Duplication Across Test Levels (MUST) -Every test in the "Test Plan" MUST add coverage that does not already exist. It is forbidden to +Each test in the "Test Plan" MUST add coverage that does not already exist. It is forbidden to plan a test (especially BDD/Vanessa or integration) that checks the same logic with the same -inputs and the same observable result as an already covered unit test - that is, 1-to-1. - -**1-to-1 duplicate criterion (DO NOT plan):** the second test goes through the same code path, with -the same Arrange and the same asserts as the first, and does not involve any new layer (UI/client, -posting in a real database, integration boundary, rights/roles, multi-session operation, -concurrency). BDD on top of full unit coverage of the same server-side calculation is a typical -duplicate. - -**When a second test is justified (plan it):** it EXTENDS coverage - it adds a layer or dimension -that the first test cannot cover: -- client/UI form behavior (visibility, availability, notifications, operator input); -- end-to-end posting through a real database write (while unit mocked the engine); +inputs and the same observable result as an already covered unit test - that is, a 1:1 duplicate. + +**1:1 duplicate criterion (DO NOT plan):** the second test follows the same code path, with the same +Arrange and the same assertions as the first, and does not use any new layer (UI/client, posting +to a real database, integration boundary, permissions/roles, multi-session behavior, concurrency). +BDD on top of full unit coverage of the same server-side calculation is a typical duplicate. + +**When a second test is justified (plan it):** it EXPANDS coverage - it adds a layer or dimension +unavailable to the first: +- form client/UI behavior (visibility, availability, notifications, operator input); +- end-to-end posting through a real database write (while the unit test mocked the engine); - integration boundary (external API, exchange, HTTP service); -- user rights/roles/context (if the mode is NOT unconditionally privileged - see - [[test-writing]] on the privileged-mode test anti-pattern); -- concurrency, restart idempotence, multi-session operation. +- permissions/roles/user context (if the mode is NOT unconditionally privileged - see + [[test-writing]] about the privileged-mode test antipattern); +- concurrency, restart idempotence, multi-session behavior. -**Why:** a 1-to-1 duplicate wastes resources and time (writing + execution + maintenance + false -failure diagnostics) without adding a single line of new coverage. A "green" duplicate creates the -illusion of greater confidence, which does not exist. The cost of BDD-level work (Phase 3a/3c: +**Why:** a 1:1 duplicate wastes resources and time (authoring + execution + maintenance + debugging +false failures) without adding a single line of new coverage. A "green" duplicate creates the +illusion of greater verification, which does not exist. The cost of the BDD level (Phase 3a/3c: executable steps, run profile, iterations to GREEN, zero-residue teardown) is especially high - it -must be justified by a new layer, not by repeating server logic. +must be justified by a new layer, not by repeating server-side logic. **Analyst action:** for each BDD/integration scenario in the spec, explicitly state WHICH layer it -covers beyond the unit plan (one line "extends: <layer>"). If there is no extension and the -scenario is 1-to-1 with unit, do NOT include it in the plan; record the decision in the ADR as -"BDD not needed: covered by unit, duplicate avoided". The Reviewer checks this as part of test -plan acceptance. +covers beyond the unit plan (one line: "expands: <layer>"). If there is no expansion and the +scenario is 1:1 with the unit test, DO NOT include it in the plan; record the ADR decision "BDD is +not needed: covered by unit, duplicate avoided". Reviewer checks this as part of test plan +acceptance. + +--- + +## 4b. Coverage by the Affected Runtime Layer (MUST) + +The test plan MUST choose the test level based on the runtime layer that changes. You cannot cover +a client-side change only with syntax/unit tests, or a server-side change only with a UI click. + +| What is affected | Required coverage | +|---------------|------------------------| +| Server-side logic, common module, manager/object module, form server method, query, register/document posting | YaxUnit unit/integration. If the test already exists, update and rerun it; if there is no test, add one. | +| UI or client context: form, command, button, command interface, client handler, `ОткрытьФорму`, notification, visibility/availability, permissions to open the UI | Scenario test through Vanessa/TestClient: open the user entrypoint, perform the action, and verify the observable result without error. For UI/UX acceptance of a form, plan a PNG screenshot through VA MCP (`connect_test_client -> get_window_list_os -> get_window_screenshot_os`) with a check that the screenshot is not empty/black. Plan the web client only for a browser-specific layer (DOM/CSS/JS console/network/web-auth/viewport/browser extension), explicitly stating which function is missing from VA MCP in principle. For a targeted command, the minimal scenario clicks the command and confirms successful start/completion. | +| A related user process spanning multiple forms/objects | End-to-end process scenario. First reuse the existing scenario and adapt it to the change; write a new scenario only if no existing coverage exists. | +| Integration boundary, HTTP/API, background or scheduled execution | Integration/YaxUnit or a scenario test with a verifiable external/register effect; for background jobs, verify idempotence and rerun behavior if it is relevant to the change. | + +Each MUST in the spec must have an explicit trace line in the "Test Plan": +`requirement → affected layer → test type → existing test is updated or a new one is created`. + +If a required UI/VA test is technically impossible in the current environment, the spec MUST NOT silently +reduce coverage: apply the `va-visual-check` fallback rules and record the completed VA steps, the fallback reason, and the residual risk. If the fallback does not provide a sufficient signal for the requirement, record a blocker. Reviewer checks not only that tests exist, but also that the test level matches the affected runtime layer. --- -## 5. RFC 2119 rules +## 5. RFC 2119 Rules | Keyword | Meaning | Usage rule | |----------------|----------|------------------------| -| MUST | Required | Without it, the requirement is considered unmet. | +| MUST | Required | Without this, the requirement is considered unmet. | | SHOULD | Strongly recommended | Deviation is allowed only with explicit justification. | | MAY | Optional | An improvement that does not block acceptance. | -| MUST NOT | Forbidden | An explicit restriction, violation is unacceptable. | +| MUST NOT | Forbidden | An explicit restriction; violation is not allowed. | Requirements must be: -- atomic (one requirement - one verifiable idea); -- verifiable (can be confirmed by a test/scenario); -- non-contradictory between sections. +- atomic (one requirement - one verifiable thought); +- testable (can be confirmed by a test/scenario); +- consistent across sections. --- -## 6. Task decomposition +## 6. Task Decomposition -For tasks with a specification, decomposition is **mandatory** (a separate Task Breakdown JSON -file). In the specification - include a link to the JSON and/or a short summary. +For tasks with a specification, decomposition is **mandatory** (a separate JSON file, Task Breakdown). The spec must include a link to the JSON and/or a short summary. -The quality control process is outside this skill: `task-breakdown` (§3 Linear - self-check, §4 -Subagent - cross-review). +The quality control process is outside this skill: `task-breakdown` (§3 Linear — self-check, §4 Subagent — cross-review). --- -## 7. Specification quality criteria +## 7. Specification Quality Criteria Review checklist: - [ ] "Context" describes who has the problem and what is not working. - [ ] Every MUST is covered by an item in the "Test Plan". -- [ ] "Scope" clearly separates "In scope" and "Out of scope". +- [ ] For each MUST, the affected runtime layer is specified and the appropriate test type is selected: + server → YaxUnit, UI/client → scenario UI/BDD, process → end-to-end, integration/background → integration/job. +- [ ] "Boundaries" clearly separate "In scope" and "Out of scope". - [ ] "Considered options" contains at least 2 alternatives. -- [ ] "Chosen solution" contains rationale and consequences. +- [ ] "Chosen solution" includes justification and consequences. - [ ] "Technical design" separates user tasks (metadata) and agent tasks (code). - [ ] There are no contradictions between sections. -- [ ] Requirements are formulated using RFC 2119 (MUST/SHOULD/MAY/MUST NOT). +- [ ] Requirements are expressed with RFC 2119 (MUST/SHOULD/MAY/MUST NOT). - [ ] There is a link/summary for a separate Task Breakdown JSON. -- [ ] "Acceptance scenarios" contain business-level Gherkin scenarios (Given/When/Then) for MUST - requirements. +- [ ] "Acceptance scenarios" contain business-level Gherkin scenarios (Given/When/Then) for MUST requirements. +- [ ] If the change affects the UI/client context, there is a scenario that opens the user entrypoint and performs the changed action. +- [ ] If the change affects a server method/logic, there is YaxUnit coverage: an existing test is updated or a new one is created. - [ ] The document is written in Russian (except code identifiers). --- -## 8. Common mistakes +## 8. Common Mistakes | Error | Consequence | -|--------|------------| +|--------|-------------| | Mixing the problem and solution in Context | It is unclear what needs to be fixed | | Vague requirements without RFC 2119 | The work cannot be accepted unambiguously | | Empty Out of scope | Scope creep | diff --git a/framework_eng/skills/spec-writing/task-breakdown/SKILL.md b/framework_eng/skills/spec-writing/task-breakdown/SKILL.md index acfe7df5..b481ebb5 100644 --- a/framework_eng/skills/spec-writing/task-breakdown/SKILL.md +++ b/framework_eng/skills/spec-writing/task-breakdown/SKILL.md @@ -1,6 +1,6 @@ --- name: task-breakdown -description: "Use for spec decomposition into Task Breakdown JSON. Covers two modes: linear (self-check, single-agent) and subagent (cross-review + BLOCK iterations)." +description: "Decompose a spec into Task Breakdown JSON" depends_on: - framework/skills/spec-writing/spec-standard/SKILL.md metadata: @@ -14,18 +14,18 @@ metadata: ## §1 When to use | Trigger | Mode | -|---------|------| +|---------|-------| | FREE/linear execution without Reviewer-agent | **Linear** — self-check | | Full-cycle process with Architect/Reviewer roles | **Subagent** — cross-review + BLOCK iterations | -| A breakdown is needed before implementation | Any mode — use template + example | -| Execution is handled by one agent step by step | **Linear** | -| Reviewer returned BLOCK | **Subagent** — start the correction loop | +| Breakdown of a spec is needed before implementation | Any mode — use template + example | +| Execution is performed by one agent step by step | **Linear** | +| Reviewer returned BLOCK | **Subagent** — run the correction loop | If the orchestration context is unknown, use **Linear** by default. --- -## §2 Task breakdown JSON format +## §2 JSON format for task breakdown ### Required artifact @@ -34,13 +34,13 @@ The breakdown is prepared as a **separate JSON file** (next to the specification Format requirements: - use **template + example**; - **do not use JSON Schema**; -- keep the following fields consistent: +- keep the same fields: - `task_id` - `task_type` - `depends_on` - `spec_refs` -The specification itself should contain: +The specification itself must include: - a link to this JSON file, and/or - a short summary of stages and dependencies. @@ -53,11 +53,11 @@ The specification itself should contain: { "task_id": "T1", "task_type": "analysis", - "title": "Краткое название задачи", - "description": "Что должно быть сделано", + "title": "Short task title", + "description": "What must be done", "depends_on": [], "spec_refs": ["Requirements.MUST-1"], - "deliverables": ["Список ожидаемых артефактов"] + "deliverables": ["List of expected artifacts"] } ] } @@ -80,29 +80,29 @@ The specification itself should contain: { "task_id": "T1", "task_type": "analysis", - "title": "Проверка соответствия MUST-требованиям", - "description": "Сопоставить MUST из спецификации с задачами реализации", + "title": "Validation against MUST requirements", + "description": "Map MUST items from the specification to implementation tasks", "depends_on": [], "spec_refs": ["Requirements.MUST-1", "Requirements.MUST-2"], - "deliverables": ["Матрица покрытия MUST", "Список пробелов"] + "deliverables": ["MUST coverage matrix", "List of gaps"] }, { "task_id": "T2", "task_type": "implementation", - "title": "Реализация основной логики", - "description": "Выполнить реализацию в соответствии с Technical Design", + "title": "Implement core logic", + "description": "Perform the implementation according to Technical Design", "depends_on": ["T1"], "spec_refs": ["Technical Design.Modules", "Requirements.MUST-3"], - "deliverables": ["Изменения кода", "Локальные проверки"] + "deliverables": ["Code changes", "Local checks"] }, { "task_id": "T3", "task_type": "test", - "title": "Проверка тест-плана", - "description": "Проверить, что MUST покрыты тестами из Test Plan", + "title": "Validate the test plan", + "description": "Verify that MUST items are covered by tests from the Test Plan", "depends_on": ["T2"], "spec_refs": ["Test Plan (TDD)"], - "deliverables": ["Результаты тестов", "Список отклонений"] + "deliverables": ["Test results", "List of deviations"] } ] } @@ -116,29 +116,29 @@ The specification itself should contain: - `depends_on` forms a valid sequence; - `spec_refs` point to specific sections/items. 3. Record assumptions if the specification contains ambiguities: - - explicitly list assumptions; + - list assumptions explicitly; - indicate how assumptions affect task order. 4. Execute tasks linearly in dependency order (single-agent execution). -5. Before finishing, repeat the self-check for actual requirement coverage. +5. Before finishing, repeat the self-check against the actual requirement coverage. ### Self-check checklist - [ ] Each task has a unique `task_id`. -- [ ] `task_type` matches the actual work stage. +- [ ] `task_type` matches the real work stage. - [ ] `depends_on` defines an executable linear order without cycles. - [ ] `spec_refs` are present and linked to the specification. - [ ] All MUST requirements have implementation/verification tasks. -- [ ] Assumptions are explicitly recorded and do not contradict Scope. -- [ ] The specification includes a link/summary for the separate JSON. +- [ ] Assumptions are explicitly recorded and do not conflict with Scope. +- [ ] The specification includes a link/summary to the separate JSON. ### Typical mistakes (Linear) -| Error | Consequence | -|-------|-------------| -| No self-check before execution | Execution follows a defective plan | -| Unrecorded assumptions | Hidden mismatch with expectations | +| Mistake | Consequence | +|--------|------------| +| No self-check before execution | Execution based on a defective plan | +| Unrecorded assumptions | Hidden mismatches with expectations | | Incomplete `spec_refs` | Loss of traceability | -| `depends_on` order violation | Rework at later stages | +| Violation of `depends_on` order | Rework in later stages | --- @@ -153,20 +153,20 @@ The specification itself should contain: { "task_id": "T1", "task_type": "analysis", - "title": "Проверка metadata-объектов", - "description": "Сверить состав объектов с разделом Technical Design", + "title": "Check metadata objects", + "description": "Compare the object set with the Technical Design section", "depends_on": [], "spec_refs": ["Technical Design.Metadata Objects", "Requirements.MUST-1"], - "deliverables": ["Список проверенных объектов", "Перечень расхождений"] + "deliverables": ["List of verified objects", "List of discrepancies"] }, { "task_id": "T2", "task_type": "implementation", - "title": "Реализация проведения документа", - "description": "Реализовать движения и проверки остатков", + "title": "Implement document posting", + "description": "Implement movements and balance checks", "depends_on": ["T1"], "spec_refs": ["Requirements.MUST-2", "Requirements.MUST-3"], - "deliverables": ["Код модуля объекта", "Тесты по MUST-требованиям"] + "deliverables": ["Object module code", "Tests for MUST requirements"] } ] } @@ -178,39 +178,39 @@ The specification itself should contain: 2. The agent prepares a separate Task Breakdown JSON (template + example, without JSON Schema). 3. The Reviewer performs a cross-review of the JSON against the specification and dependencies. 4. If the verdict is **BLOCK**: - - return for revision; + - return for rework; - maximum **3 return iterations**. -5. If after 3 returns the remarks remain critical: +5. If after 3 returns the comments remain critical: - set status **BLOCK > 3**; - - perform **escalation** (the architect/user decides whether to rebuild the breakdown or refine the spec). + - perform **escalation** (the architect/user decides whether to rebuild the breakdown or clarify the spec). ### JSON quality checklist (review mode) - [ ] Each task has a unique `task_id`. - [ ] `task_type` reflects the actual stage (analysis/design/implementation/test, etc.). - [ ] `depends_on` does not contain cyclic dependencies. -- [ ] Each task has `spec_refs` that point to specific sections/requirements of the specification. +- [ ] `spec_refs` are present for every task and point to specific sections/requirements of the spec. - [ ] All critical MUST requirements of the specification are covered. -- [ ] The task order is executable with dependencies taken into account. -- [ ] The specification includes a link/summary for the separate JSON. +- [ ] The task order is executable considering the dependencies. +- [ ] The specification includes a link/summary to the separate JSON. ### Typical mistakes (Subagent) -| Error | Consequence | -|-------|-------------| -| `spec_refs` are missing | Loss of traceability | +| Mistake | Consequence | +|--------|------------| +| `spec_refs` omitted | Loss of traceability | | Inconsistent `depends_on` | Invalid execution order | -| Format changes between iterations | Increased review defects | -| Ignoring the BLOCK limit | Endless iterations -> escalation does not happen | +| Format changes between iterations | Increase in review defects | +| Ignoring the BLOCK limit | Endless iterations → escalation does not happen | --- ## §5 When to choose each mode | Criterion | Linear | Subagent | -|-----------|--------|----------| -| Presence of a Reviewer-agent | No | Yes | -| Presence of the Architect role | Optional | Yes | +|----------|--------|---------| +| Reviewer-agent present | No | Yes | +| Architect role present | Optional | Yes | | Quality control method | Self-check | Cross-review | | Iterations on errors | No (fix independently) | Up to 3 BLOCK returns, then escalation | | Typical context | Simple tasks, one-shot execution | Complex specs, full-cycle pipeline | diff --git a/framework_eng/skills/spec-writing/technical-design-standard/SKILL.md b/framework_eng/skills/spec-writing/technical-design-standard/SKILL.md index 7565bc82..85532f47 100644 --- a/framework_eng/skills/spec-writing/technical-design-standard/SKILL.md +++ b/framework_eng/skills/spec-writing/technical-design-standard/SKILL.md @@ -1,11 +1,11 @@ --- name: technical-design-standard -description: "The technical design standard for 1С development tasks. Defines the structure of technical-design.md, the rules for filling sections (MUST/SHOULD/MAY), the quality checklist, and guidance on the level of detail. Used by the architect (Phase 2) and the reviewer (scope=arch)." +description: "Write 1C technical-design.md with MUST/SHOULD/MAY" --- # Technical Design Standard (Technical Design) -Technical design (`technical-design.md`) is the bridge between the specification (WHAT) and the decomposition of tasks (HOW). It records architectural decisions, the modular structure, contracts, and cross-cutting concepts. It extends the high-level Technical Design section from the specification. +Technical design (`technical-design.md`) is the bridge between the specification (WHAT) and task decomposition (HOW). It captures architectural decisions, the module structure, contracts, and cross-cutting concepts. It extends the high-level Technical Design section from the specification. Foundation: Google Design Docs, arc42, MADR 4.0, Stripe RFC (Drawbacks), C4 Model. @@ -13,7 +13,7 @@ Foundation: Google Design Docs, arc42, MADR 4.0, Stripe RFC (Drawbacks), C4 Mode ## 2. Document language -Technical design MUST be written in **Russian** — section headings, descriptions, justifications, tables. Exceptions: code and metadata identifiers (module names, attributes, variables, BSL signatures) and well-established terms (ADR, RFC 2119, C4, MUST/SHOULD/MAY). +Technical design MUST be written in **Russian** — section headings, descriptions, justifications, tables. Exception: code and metadata identifiers (module names, attributes, variables, BSL signatures), as well as established terms (ADR, RFC 2119, C4, MUST/SHOULD/MAY). --- @@ -182,8 +182,8 @@ Cross-cutting solutions that span all modules. **SHOULD** document the decision | Aspect | Decision | Justification | |--------|---------|-------------| -| **Error handling** | Попытка/Исключение с ЗаписьЖурналаРегистрации | coding-standards rule 18 | -| **Logging** | ЖР through БСП (ЗаписьЖурналаРегистрации) | ssl-patterns: standard mechanism | +| **Error handling** | Try/Except with ЗаписьЖурналаРегистрации | coding-standards rule 18 | +| **Logging** | Registration log through БСП (ЗаписьЖурналаРегистрации) | ssl-patterns: standard mechanism | | **Access rights** | Role via xml-gen, RLS is not required | Data does not contain organization-level segregation | | **Transactions** | НачатьТранзакцию/Попытка for writing to registers | coding-standards rule 18 | | **Client/Server** | &НаСервереБезКонтекста for business logic | coding-standards rule 3 | @@ -257,29 +257,29 @@ What becomes worse, more complex, or more expensive. If the drawbacks section is ### § 8. Assumptions and open questions -**Assumptions** — assumptions accepted in the face of uncertainty. They do not block the design but may influence implementation: +**Assumptions** — assumptions accepted in the face of uncertainty. They do not block the architecture, but may influence implementation: ```markdown - Предполагаем, что максимальное кол-во контрагентов < 500K - БСП версии 3.1+ (иначе нужен fallback для ДлительныеОперации) ``` -**Open questions** — unanswered items. They do not block the architecture but require clarification before or during implementation. +**Open questions** — those left unanswered. They do not block the architecture, but require clarification before or during implementation. --- ### § 9. Migration and rollback (conditional) -**Condition:** this section MUST if existing metadata objects are changed or data migration is required. Otherwise — `N/A: new objects, no migration required`. +**Condition:** this section MUST be present if existing metadata objects are changed or data migration is required. Otherwise — `N/A: new objects, migration not required`. #### 9.1 Migration plan - Update order (configuration → data → rights) -- Fill / data conversion processes -- Phasing (if the rollout is staged) +- Fill / convert data processing +- Phasing (if phased rollout is used) #### 9.2 Rollback strategy -- Whether the changes can be rolled back -- What will happen to the data during rollback +- Can the changes be rolled back +- What happens to the data during rollback - Point of no return (if any) --- @@ -296,13 +296,13 @@ Traceability matrix: requirement from the specification → design section → t | SHOULD-1: Отчёт по истории | §4.1 Metadata (SKD) | T-005 | ``` -**Rule:** every MUST from the specification MUST be covered by at least one design section and one task. SHOULD — SHOULD be covered. +**Rule:** each MUST from the specification MUST be covered by at least one design section and one task. SHOULD — SHOULD be covered. --- ## 6. Quality criteria for technical-design.md -Checklist for the reviewer (scope=arch): +Reviewer checklist (scope=arch): ### Structure and completeness - [ ] All MUST sections are filled in (or N/A with a reason) @@ -310,34 +310,34 @@ Checklist for the reviewer (scope=arch): - [ ] Status is correct (Draft when created) ### Overview (§1) -- [ ] Goals describe technical goals and do not repeat specification requirements -- [ ] Non-goals include at least 1 conscious exclusion -- [ ] Background is based on explorer-context.md and does not duplicate it -- [ ] Constraints account for: development mode (extension/configuration), platform/БСП version +- [ ] Goals describe technical goals, not a restatement of the specification requirements +- [ ] Non-goals contain at least 1 conscious exclusion +- [ ] Background relies on explorer-context.md and does not duplicate it +- [ ] Constraints account for the development mode (extension/configuration), platform/БСП version ### Solution strategy (§2) - [ ] The strategy answers each Goal from §1.1 - [ ] The description is at the approach level, not the code level ### Structural blocks (§3) -- [ ] The module map covers all modules from the specification scope +- [ ] The module map covers all modules in the specification scope - [ ] Interfaces and contracts contain signatures with parameters, return values, and compilation directives - [ ] There are no implicit dependencies between modules ### Data and metadata (§4) - [ ] All metadata objects are listed with types and changes -- [ ] Complex objects (forms, SKD, roles) have a link to the JSON DSL file -- [ ] Data flow covers the key scenarios from the test plan +- [ ] Complex objects (forms, SKD, roles) have a link to a JSON DSL file +- [ ] The data flow covers the key scenarios from the test plan ### Cross-cutting concepts (§5) - [ ] Decisions for error handling, transactions, rights, and the client/server boundary -- [ ] The use of or refusal to use БСП mechanisms is justified (ssl-patterns) +- [ ] Use or rejection of БСП mechanisms is justified (ssl-patterns) - [ ] Platform limitations with workarounds (if any) ### Key decisions (§6) -- [ ] Each non-obvious decision (≥2 alternatives) has justification -- [ ] ADR files contain consequences and confirmation -- [ ] There are no decisions that contradict the specification +- [ ] Each non-obvious decision (≥2 alternatives) has a justification +- [ ] ADR files include consequences and confirmation +- [ ] There are no decisions that conflict with the specification ### Risks and drawbacks (§7) - [ ] Drawbacks are not empty — every decision has a cost @@ -345,36 +345,36 @@ Checklist for the reviewer (scope=arch): - [ ] Trade-offs are described honestly (pros + cons) ### Traceability (§10) -- [ ] Every MUST from the specification is covered by a design section and a task +- [ ] Each MUST from the specification is covered by a design section and a task - [ ] There are no requirements without a design link - [ ] Task IDs match task-breakdown.json ### Task decomposition (JSON) - [ ] All tasks have unique `task_id` -- [ ] `depends_on` values are valid and do not contain cycles +- [ ] `depends_on` is valid and contains no cycles - [ ] `spec_refs` point to existing specification sections - [ ] `task_type` is correct (code/test/migration/docs/analysis/architecture) - [ ] `done_criteria` are verifiable and specific -- [ ] JSON is stored in a separate file, with only a link in the design +- [ ] JSON is stored in a separate file; the design contains only a link -### Alignment with the framework +### Consistency with the framework - [ ] The document is written in Russian (except code identifiers and established terms) - [ ] Compatibility with the existing configuration (coding-standards) - [ ] The design is implementable within the specification scope -- [ ] The design does not contradict the decisions in the specification Decision Log +- [ ] The design does not conflict with the decisions from the specification's Decision Log --- -## 7. Typical mistakes +## 7. Common mistakes | Error | Consequence | |--------|------------| | Non-goals are empty | Scope creep | -| Drawbacks are empty | Reviewer cannot assess trade-offs | -| JSON DSL is fully inline | The document becomes bloated, the overview is lost → DSL in artifacts/ | -| Duplication of the specification | Violation of single source of truth | -| Traceability is missing | Impossible to verify requirement coverage | -| All sections are filled for a simple task | Formal overhead → use N/A | +| Drawbacks are empty | The reviewer cannot assess trade-offs | +| JSON DSL is fully inlined | The document becomes bloated, the overview is lost → DSL in artifacts/ | +| Repetition of the specification | Violation of single source of truth | +| Traceability is absent | Requirements coverage cannot be verified | +| All sections are filled in for a simple task | Formal overhead → use N/A | | Constraints are not specified | Incompatible approach (EDT vs Designer, БСП version) | --- diff --git a/framework_eng/skills/tool-usage/browser-ui/gui-control/SKILL.md b/framework_eng/skills/tool-usage/browser-ui/gui-control/SKILL.md index f6b2b5cf..9a912cf2 100644 --- a/framework_eng/skills/tool-usage/browser-ui/gui-control/SKILL.md +++ b/framework_eng/skills/tool-usage/browser-ui/gui-control/SKILL.md @@ -1,31 +1,33 @@ --- name: gui-control -description: "MUST use WHEN the GUI dialog blocks database shutdown or a test hangs with no events in the event log. Provides X11 detection of 1C windows, screenshot capture, and keyboard simulation to unblock without human involvement." +description: "Unlocking frozen 1С windows, dialogs, and tests" --- -# 1C GUI Control via X11 +# Controlling 1С GUI through X11 -X11 control is an action, not diagnostics. Use only when a GUI dialog is detected that blocks the normal shutdown of the database. Diagnose the cause through the event log (`event-log-analysis`). +X11 control is an action, not diagnosis. Use only when a GUI dialog has been detected that blocks normal database shutdown. Diagnose the causes through the event log (`event-log-analysis`). -For `Security Warning`, X11 window metadata may be incomplete. Rely on the sequence: event log → screenshot → keyboard actions. +For UI/UX acceptance of ordinary 1C forms, do not use `gui-control` as the primary route. First apply `va-visual-check`; X11 keys and direct GUI control are allowed only as a fallback/action, with the reason and residual risk recorded. -## When to use +For `Security warning`, X11 window metadata may be incomplete. Rely on the chain: event log → visual artifact via `va-visual-check` → keyboard action if needed. + +## When to apply | Trigger | Action | |---------|----------| -| No events in the event log after `test_start_time` | Check whether a GUI dialog is hanging | -| Window title: "Error" / "Warning" | Screenshot → close the dialog → analyze the event log | -| The database does not shut down after tests | Close with Escape + Enter | -| The event log shows `Security Warning` on EPF | Visually verify; do not act blindly based on titles | +| The event log has no events after `test_start_time` | Check whether a GUI dialog is frozen | +| Window title: «Error» / «Warning» | VA MCP screenshot → close the dialog only if VA MCP fundamentally cannot perform the required action → event log analysis | +| The database does not terminate after tests | Close it via Escape + Enter only if VA MCP fundamentally cannot close the blocking window | +| The event log contains `Security warning` for EPF | Visual inspection, do not act blindly based on titles | ## Environment setup ```python import os -os.environ['DISPLAY'] = ':99' # before importing Xlib and PIL +os.environ['DISPLAY'] = ':99' # до импортов Xlib и PIL ``` -## Workflow +## Working algorithm ### 1. Detect the error dialog @@ -48,13 +50,13 @@ for win in root.query_tree().children: print(error_windows) ``` -- Empty + there are 1C windows → the database is operating normally -- Empty + no windows → the database has shut down -- Not empty → error dialog → step 2 +- Empty + 1С windows present → the database is working normally +- Empty + no windows → the database terminated +- Non-empty → error dialog → step 2 -### 2. Close the dialog and shut down the database +### 2. Close the dialog and terminate the database -Sequence: Enter (close the dialog) → Escape (close) → Enter (confirm). After that, wait 2-3 seconds and check again using step 1. +First check whether there is a VA MCP tool to close/confirm the required window. If you use X11 keys as a fallback/action, record the reason. Sequence: Enter (close dialog) → Escape (close) → Enter (confirm). After that, wait 2–3 sec and check via step 1. ```python import os, time @@ -81,26 +83,12 @@ time.sleep(1) send_key(d, ENTER) ``` -### 3. Screenshot for the log (optional, before step 2) - -```python -import os -os.environ['DISPLAY'] = ':99' -from PIL import ImageGrab -from Xlib import display +### 3. Screenshot for the log (required via VA MCP, before step 2) -d = display.Display() -root = d.screen().root +Take the screenshot for the 1C UI via `va-visual-check`: VA MCP PNG, Linux/Xvfb recipe, and fallback rules. -for win in root.query_tree().children: - name = win.get_wm_name() - wm_class = win.get_wm_class() - if wm_class and '1cv8' in wm_class: - geom = win.get_geometry() - img = ImageGrab.grab(bbox=(geom.x, geom.y, geom.x + geom.width, geom.y + geom.height)) - path = f'/tmp/onec_{win.id}.png' - img.save(path) - print(f'Screenshot saved: {path}') +```json +{"name":"get_window_screenshot_os","arguments":{"window_title":"<title-from-get_window_list_os>","file_name":"<path>.png","color_mode":"color"}} ``` ## Pipeline: tests finished, the database did not close @@ -108,34 +96,34 @@ for win in root.query_tree().children: ``` search_event_log(from=test_start_time, limit=20) ├── there are events, no Error → wait - ├── there is Error → screenshot → close → analyze the event log + ├── there is Error → VA MCP screenshot → close only if the required VA capability is unavailable → event log analysis └── no events → detect windows - ├── window with an error → screenshot → close + ├── error window → VA MCP screenshot → close only if the required VA capability is unavailable └── no windows → the database did not start ``` ## Safety -- **Xvfb only** — do not use on production servers with a real display -- **Navigation keys only** (Enter/Escape) — do not enter data into fields -- **Screenshots go to /tmp/** — they may contain personal data +- **Only Xvfb** — do not use on production servers with a real display +- **Only navigation keys** (Enter/Escape) — do not enter data into fields +- **VA MCP screenshots are in /tmp/** — may contain personal data -## Common mistakes +## Typical errors | Error | Workaround | |--------|---------------| -| `DISPLAY` is not set | `os.environ['DISPLAY'] = ':99'` before imports | -| `python-xlib` is not installed | `pip install python-xlib` | -| `PIL.ImageGrab` does not work | `pip install Pillow` | -| Windows are not found, but the process exists | The GUI has not been rendered yet - wait 2-3 seconds | -| XTEST is unavailable | Xvfb with the `-extensions XTEST` flag | +| `DISPLAY` not set | `os.environ['DISPLAY'] = ':99'` before imports | +| `python-xlib` not installed | `pip install python-xlib` | +| Windows not found, but process exists | GUI has not been rendered yet — wait 2–3 sec | +| VA MCP screenshot of Xvfb is black/single-color | Act according to `va-visual-check`: Linux/Xvfb recipe, repeat the VA capture, then fallback if necessary | +| XTEST unavailable | Xvfb with `-extensions XTEST` flag | ## Capabilities | Capability | Purpose | |------------|------------| | `python-xlib` | Reading window metadata, simulating input | -| `PIL ImageGrab` | Screenshot of the framebuffer or a window | +| `get_window_screenshot_os` | VA MCP screenshot of the test-client window | --- depends_on: [] diff --git a/framework_eng/skills/tool-usage/browser-ui/img-grid/SKILL.md b/framework_eng/skills/tool-usage/browser-ui/img-grid/SKILL.md index 5bfe5821..30cd82cc 100644 --- a/framework_eng/skills/tool-usage/browser-ui/img-grid/SKILL.md +++ b/framework_eng/skills/tool-usage/browser-ui/img-grid/SKILL.md @@ -1,18 +1,18 @@ --- name: "img-grid" -description: "Use for measuring column proportions and spans in a screenshot of a printed form (MXL). Helps precisely determine cell boundaries before generating a table document layout." +description: "Measure MXL print-form grid/columns from a screenshot" argument-hint: "<ImagePath> [--cell-size 50] [--cols N] [-o OUTPUT]" allowed-tools: - Bash - Read --- -# img-grid — Grid for Layout Analysis +# img-grid — Grid for layout analysis -Overlays a numbered grid on an image of a printed form. -Allows you to accurately determine column boundaries, their proportions, and spans for generating an MXL document layout. +Overlays a numbered grid on a print form image. +Allows you to precisely determine column boundaries, their proportions, and spans for generating an MXL document layout. -The numbers are drawn in separate margins outside the image (top and left margins), so they never overlap the form content. +The numbers are drawn in separate fields outside the image (top and left margins), so they never cover the form content. ## Usage @@ -36,23 +36,23 @@ python3 tools/img-grid/grid.py <ImagePath> [--cell-size 50] [--cols N] [--rows N pip install Pillow ``` -## What the Script Does +## What the script does -1. Adds margins (20 px top, 24 px left) for labels so the content is not overlapped. +1. Adds margins (20 px top, 24 px left) for labels so the content is not covered. 2. Draws vertical lines (red) and horizontal lines (blue) on the grid. 3. Every 5th line is brighter, every 10th line is the brightest (easy to count). 4. Numbers the lines in the margins (top for column numbers, left for row numbers). 5. Saves the result as an RGB PNG. -## How to Use the Result +## How to use the result -### 1. Determine Column Boundaries +### 1. Determine column boundaries -Look at the image with the grid and note the numbers of the vertical lines at the boundaries of each table column. +Look at the gridded image and note the numbers of the vertical lines at the boundaries of each table column. -### 2. Find the Base Grid +### 2. Find the base grid -If the form contains multiple tables with different layouts (header + main table), combine all boundary points. Each segment between adjacent boundaries is one base MXL column. +If the form has several tables with different layouts (header + main table), combine all boundary points. Each segment between adjacent boundaries is one base MXL column. Example for form M-11 (`--cols 48`): - Header: boundaries `0, 2, 4, 9, 14, 21, 28, 34, 40, 48` @@ -60,7 +60,7 @@ Example for form M-11 (`--cols 48`): - Union: `0, 2, 4, 9, 11, 14, 16, 19, 21, 23, 28, 32, 34, 36, 40, 42, 48` - Result: **16 base columns** with proportions `2, 2, 5, 2, 3, 2, 3, 2, 2, 5, 4, 2, 2, 4, 2, 6` -### 3. Record the Proportions +### 3. Record the proportions ```json { @@ -74,20 +74,20 @@ Example for form M-11 (`--cols 48`): } ``` -## Typical Workflow (reverse-engineering MXL) +## Typical workflow (reverse-engineering MXL) ```bash -# 1. Сделать скриншот формы -# 2. Наложить сетку с шагом ~50px +# 1. Take a screenshot of the form +# 2. Overlay a grid with a step of about 50px python3 tools/img-grid/grid.py form-screenshot.png --cell-size 50 -o form-grid.png -# 3. Изучить форму, поэкспериментировать с количеством делений +# 3. Inspect the form, experiment with the number of divisions python3 tools/img-grid/grid.py form-screenshot.png --cols 48 -o form-grid-48.png -# 4. Передать агенту на анализ: назвать границы колонок по номерам +# 4. Hand off for analysis: name the column boundaries by number ``` -## Target Agents +## Target agents - **developer-code** — when working with an MXL form from a screenshot -- **explorer / debugger** — when reverse-engineering unknown printed forms +- **explorer / debugger** — when reverse-engineering unknown print forms diff --git a/framework_eng/skills/tool-usage/browser-ui/playwright-interactive/SKILL.md b/framework_eng/skills/tool-usage/browser-ui/playwright-interactive/SKILL.md index d8740777..ba1651d7 100644 --- a/framework_eng/skills/tool-usage/browser-ui/playwright-interactive/SKILL.md +++ b/framework_eng/skills/tool-usage/browser-ui/playwright-interactive/SKILL.md @@ -1,12 +1,16 @@ --- name: "playwright-interactive" -description: "Use for iterative UI debugging of web applications and Electron through a persistent `js_repl` Playwright session. Helps keep browser handles alive between steps without restarting." +description: "Interactive Playwright debugging in a persistent session" --- # Playwright Interactive Skill Persistent `js_repl` Playwright session for iterative UI debugging of web and Electron apps. Keep the same handles alive across iterations. +## 1C Boundary + +For 1C:Enterprise UI, interactive Playwright is not the preferred path for ordinary forms. First use `va-visual-check`: Vanessa Automation/TestClient and VA MCP for opening forms, clicking commands, filling fields, checking table rows, validating client-side behavior, and taking UI/UX screenshots. Use interactive Playwright for 1C only when the target is browser-specific or as fallback under `va-visual-check`: DOM/CSS/HTML, browser console/network, cookies/storage, web publication/auth, web-client viewport/pixel rendering, Chrome/Edge-only behavior, browser extension behavior, or browser-only file/clipboard flows. If used for 1C, record the VA steps already attempted, why browser evidence is sufficient, and the residual risk. + ## Preconditions - `js_repl` must be enabled (`~/.codex/config.toml`: `[features] js_repl = true`, or `--enable js_repl`). diff --git a/framework_eng/skills/tool-usage/browser-ui/playwright/SKILL.md b/framework_eng/skills/tool-usage/browser-ui/playwright/SKILL.md index ebd6eac4..c91a8cc4 100644 --- a/framework_eng/skills/tool-usage/browser-ui/playwright/SKILL.md +++ b/framework_eng/skills/tool-usage/browser-ui/playwright/SKILL.md @@ -1,12 +1,16 @@ --- name: "playwright" -description: "Use for browser automation from the terminal (navigation, form filling, snapshots, screenshots, data extraction, UI-flow debugging) via `playwright-cli`. Helps run a scenario without an interactive IDE." +description: "Browser UI automation: scenarios, forms, screenshots" --- # Playwright CLI Skill CLI-first browser automation. Do not pivot to `@playwright/test` unless explicitly asked. +## 1C Boundary + +For 1C:Enterprise UI, Playwright is not the preferred test or screenshot path for ordinary forms. First use the `va-visual-check` policy for Vanessa Automation/TestClient and VA MCP. Use Playwright/browser screenshots for 1C only as browser-layer work or as fallback under `va-visual-check`, recording the VA steps already attempted, why browser evidence is sufficient, and the residual risk. + ## Prerequisite check ```bash diff --git a/framework_eng/skills/tool-usage/browser-ui/screenshot/SKILL.md b/framework_eng/skills/tool-usage/browser-ui/screenshot/SKILL.md index ded150f9..9c9729c2 100644 --- a/framework_eng/skills/tool-usage/browser-ui/screenshot/SKILL.md +++ b/framework_eng/skills/tool-usage/browser-ui/screenshot/SKILL.md @@ -1,16 +1,18 @@ --- name: "screenshot" -description: "Use for capturing a desktop or window screenshot at the OS level (full screen, a specific app/window, or a pixel region). Helps get a shot when tool-specific capture (Playwright, Figma MCP) is unavailable." +description: "OS screenshots of the desktop, a window, or a screen region" --- -# Screenshot Capture +# Taking Screenshots -Save-location rules: -1. User specifies path → save there. -2. User asks without path → OS default location. -3. Codex self-inspection → temp directory. +Save rules: +1. User specified a path → save there. +2. User asked without a path → use the OS default location. +3. Codex self-check → temporary directory. -Prefer tool-specific captures (Figma MCP, Playwright, agent-browser) when available. Use this skill for explicit requests, whole-system desktop captures, or when tool-specific capture cannot get what you need. +Prefer specialized image-capture tools (Figma MCP, Playwright, agent-browser, VA MCP) when the target domain has such a tool. Use this skill for explicit requests to capture the desktop/window, full-screen captures, or domains where no specialized tool exists. + +For 1C:Enterprise UI/forms, first use the specialized `va-visual-check` skill. Use this OS-screenshot skill for 1C only as a fallback according to the `va-visual-check` rules, recording the completed VA steps, the reason for the fallback, and the residual risk. ## macOS permission preflight @@ -53,6 +55,8 @@ Display dimensions: `DISPLAY=:99 xdpyinfo | grep dimensions` `--app`, `--window-name`, `--list-windows` are macOS-only. On Linux use `--active-window` or `--window-id`. +For 1C screenshots in Xvfb, see `va-visual-check`: it describes the VA flow, exposing the window before the VA capture, and the fallback conditions. + ## PowerShell helper (Windows) ```powershell @@ -68,7 +72,7 @@ powershell -ExecutionPolicy Bypass -File <path-to-skill>/scripts/take_screenshot | `-ActiveWindow` | Ask user to focus first | | `-WindowHandle <id>` | Specific window | -## Direct OS fallbacks +## Direct OS screenshots ### macOS @@ -93,4 +97,5 @@ ffmpeg -y -f x11grab -video_size 800x600 -i :99+100,200 -frames:v 1 output/regio - macOS sandbox errors ("screen capture blocked", `ModuleCache`) → rerun with escalated permissions - macOS no matches → `--list-windows --app "Name"` → retry with `--window-id` - Linux tool missing → `command -v scrot`, `command -v import` +- 1C VA PNG is black/solid-color → follow `va-visual-check` - Always report saved file path diff --git a/framework_eng/skills/tool-usage/browser-ui/visual-check/SKILL.md b/framework_eng/skills/tool-usage/browser-ui/visual-check/SKILL.md index 59b9b2f3..7dee2efd 100644 --- a/framework_eng/skills/tool-usage/browser-ui/visual-check/SKILL.md +++ b/framework_eng/skills/tool-usage/browser-ui/visual-check/SKILL.md @@ -1,76 +1,21 @@ --- name: visual-check -description: "1C form UI acceptance: screenshot, console, checklist" +description: "Deprecated: visual checking of 1C forms has been moved to va-visual-check" alwaysApply: false --- -# Visual Check of Forms (Visual Check) +# Deprecated: visual-check -By default, visual verification of 1C managed forms is performed through Vanessa/TestClient or the platform test client MCP: open the form, perform a user action, obtain the structured form data (`get_form_analysis`, `get_window_list_testclient`, `get_value`, `get_table_rows`) and compare it with `form-visual-requirements`. +This skill is retained as a compatibility pointer for old links. For visual checking of 1C forms, use the dedicated skill `va-visual-check`: -For any work with a client form where layout, visibility, accessibility, or user perception matter, a visual screenshot is mandatory. The screenshot path is chosen as follows: +- the main Vanessa/TestClient + VA MCP path; +- the Linux headless X11/Xvfb recipe for black VA screenshots; +- browser fallback and residual-risk capture rules. -1. If the short smoke check `connect_test_client` -> `get_window_list_os` -> `get_window_screenshot_os` has actually passed in the current VA MCP environment, use the VA MCP screenshot. -2. If the VA MCP screenshot did not pass or fails on `PID=0` / `Failed to obtain the PID of the testing client process`, use an external OS/noVNC screenshot of the visible 1C window. -3. Use the web client for screenshot only as the browser-specific exception below. - -Use the web client only when checking the browser layer that is unavailable to TestClient: DOM/CSS/HTML, JS console/network, viewport/responsive, web publishing and web auth, cookies/storage, browser extensions, browser-only upload/download/clipboard, or a defect reproducible only in the Chrome/Edge web client. - -Required for the web exception: the 1C web client URL (published database), credentials, and a short reason why TestClient/VA are insufficient. - -## Verification Process - -### 1. Navigate to the form - -If the target is not browser-based, stop and switch to the TestClient/VA path (`vanessa-authoring`, `v8-runner`). The following steps apply only to the web exception. - -Prefer Deep Linking - it is faster than navigating through the interface. - -- List: `<base_url>/e1cib/list/<MetadataType>.<Name>` -- New object: `<base_url>/e1cib/data/<MetadataType>.<Name>?ref=00000000-0000-0000-0000-000000000000` -- Existing object: `<base_url>/e1cib/data/<MetadataType>.<Name>?ref=<UUID>` - -### 2. Authentication (if redirected to sign-in) - -`browser_snapshot` → `browser_fill` (login/password from ref) → `browser_click` (Log in). - -### 3. Screenshot and Console - -After loading (wait for the indicator to disappear): -1. `browser_take_screenshot` -2. `browser_console_messages` — look for "Error", "Exception", "Uncaught" - -### 4. Analysis against `form-visual-requirements` - -- Layout and alignment (grouping, padding, width) -- Controls and labels (labels, truncation, headings, command bar) -- Usability (tab order, key fields, tables, horizontal scrolling) -- Object-type specifics (directories, documents, data processors) - -**Report:** screenshot analysis result + presence/absence of JS errors. - -## Capabilities - -| Capability | Purpose | -|------------|---------| -| `browser_navigate` | Open the form URL | -| `browser_snapshot` | Page structure and element refs | -| `browser_fill` | Fill in fields | -| `browser_click` | Click elements | -| `browser_take_screenshot` | Capture the form | -| `browser_console_messages` | Check for JS errors | -| `browser_wait_for` | Wait for loading | - -## Typical Issues - -| Error | Workaround | -|--------|------------| -| Blank screenshot | `browser_wait_for` before the screenshot | -| Deep Link does not work for a new object | List → "Create" via `browser_click` | -| `browser_fill` cannot find the field | `browser_snapshot` for current refs | -| JS errors on a normal form | Record it - they will surface on save | +Evaluate form quality according to `form-visual-requirements`. --- depends_on: + - framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md - framework/skills/bsl-practices/form-visual-requirements/SKILL.md --- diff --git a/framework_eng/skills/tool-usage/browser-ui/web-test-1c/SKILL.md b/framework_eng/skills/tool-usage/browser-ui/web-test-1c/SKILL.md index dc3a0202..c3e36103 100644 --- a/framework_eng/skills/tool-usage/browser-ui/web-test-1c/SKILL.md +++ b/framework_eng/skills/tool-usage/browser-ui/web-test-1c/SKILL.md @@ -1,11 +1,25 @@ --- name: web-test-1c -description: "Use for browser automation in 1С (navigation across sections, filling forms, reading tables and reports, filtering lists). Helps write browser tests for 1С on a semantic layer without knowing DOM details of the platform." +description: "Browser UI tests for 1C: forms, tables, reports" --- -# web-test-1c — 1С Web Client Automation +# web-test-1c — 1C web client automation -Semantic layer on top of Playwright for the DOM of the 1С:Предприятие web client. +A semantic layer on top of Playwright for the 1C:Enterprise web client DOM. + +## Scope + +`web-test-1c` is NOT the default route for checking 1C UI. If the task is to open a form/list, press a command, fill in fields, check visibility/accessibility, client handler reactions, table section rows, a user business flow, or visually approve a form, first apply the dedicated skill `va-visual-check`. + +The web client is allowed as a browser-layer tool or as a fallback under `va-visual-check` rules, when the VA route has already been checked and the fallback reason is recorded. Typical browser-layer cases: + +- DOM/HTML/CSS: markup structure, custom widget, CSS clipping/overlap, exact browser selector. +- Browser diagnostics: console errors, network trace, cookies/localStorage/sessionStorage, web-auth/login/logout, publishing the database on a web server. +- Browser rendering: viewport/responsive behavior of the web client, pixel-level screenshot of the browser layer itself, Chrome/Edge-only defect, behavior of the 1C browser extension. +- Browser-only I/O: file chooser/download/clipboard/drag-and-drop, if it depends on the browser and not on the 1C form. +- Fallback after VA MCP, when the browser/web client gives enough signal for the current task. + +If the web client is chosen, explicitly record the reason, the VA steps that were performed, and the residual risk of differences between the web client and the thin/thick client. ## Installation @@ -13,7 +27,7 @@ Semantic layer on top of Playwright for the DOM of the 1С:Предприяти cd tools/web-test && npm install ``` -Node.js 18+. `npm install` will download Playwright and Chromium. +Node.js 18+. `npm install` downloads Playwright and Chromium. ## Quick start @@ -29,15 +43,15 @@ await clickElement('Провести и закрыть'); SCRIPT ``` -The URL comes from `.v8-project.json` (the `webUrl` field) or is set explicitly. +URL from `.v8-project.json` (`webUrl` field) or set explicitly. -## Operating modes +## Operation modes ```bash -node $RUN run <url> script.js # autonomous — runs and exits -node $RUN start <url> # interactive — starts a session +node $RUN run <url> script.js # autonomous — executes and exits +node $RUN start <url> # interactive — session start node $RUN test tests/<app>/ --url=<url> # regression suite *.test.mjs -cat <<'SCRIPT' | node $RUN exec - # run a script in the session +cat <<'SCRIPT' | node $RUN exec - # execute a script in the session const form = await getFormState(); SCRIPT node $RUN shot result.png # screenshot @@ -49,19 +63,19 @@ node $RUN stop # logout + close (releases the license) | Function | Description | |---------|----------| | `navigateSection(name)` | Go to a section (fuzzy match), returns `{ navigated, sections, commands }` | -| `openCommand(name)` | Open a command from the function panel → form state | -| `navigateLink(url)` | Go to an object by metadata (Shift+F11), Russian names are supported | +| `openCommand(name)` | Open a command from the functions panel -> form state | +| `navigateLink(url)` | Navigate by metadata (Shift+F11), supports Russian names | | `openFile(path)` | Open EPF/ERF, handles the security dialog | ## API — Reading | Function | Description | |---------|----------| -| `getFormState()` | All fields, buttons, tabs, tables, and errors in a single call | +| `getFormState()` | All fields, buttons, tabs, tables, errors in one call | | `readTable({ maxRows?, offset?, table? })` | Table with pagination: `{ columns, rows, total }`. `table` selects the grid by name | -| `readSpreadsheet()` | Report (SpreadsheetDocument) after “Generate”. Supports text-only and reports with numeric headers | +| `readSpreadsheet()` | Report (SpreadsheetDocument) after "Generate". Supports text-only and reports with numeric headers | -`getFormState()` returns: **fields** (name, value, actions, required), **table** (back-compat: first grid), **tables[]** (all visible grids: `{name, columns, rowCount, label}`), **openForms[]**, **formCount**, **modal**, **openTabs[]**, **navigation** (form navigation panel), **reportSettings** (human-readable СКД settings), **errors.stateText** (info-bar SpreadsheetDocument), **errorModal**, **confirmation**. +`getFormState()` returns: **fields** (name, value, actions, required), **table** (back-compat: first grid), **tables[]** (all visible grids: `{name, columns, rowCount, label}`), **openForms[]**, **formCount**, **modal**, **openTabs[]**, **navigation** (form navigation panel), **reportSettings** (human-readable SKD settings), **errors.stateText** (info-bar SpreadsheetDocument), **errorModal**, **confirmation**. Tree rows are marked `_kind: 'group'|'parent'`, `_tree: 'expanded'|'collapsed'`, `_level`, `_selected`. @@ -69,72 +83,72 @@ Tree rows are marked `_kind: 'group'|'parent'`, `_tree: 'expanded'|'collapsed'`, | Function | Description | |---------|----------| -| `fillFields({ name: value })` | Fill fields (fuzzy match, auto-type: catalog/checkbox/radio) | -| `fillField(name, value)` | Single-field version of `fillFields` | -| `selectValue(field, search, opts?)` | Choose from a catalog (dropdown / selection form) | -| `clickElement(text, opts?)` | Click a button/link/row. `opts`: `dblclick`, `table` (scope the command panel to a specific grid), `toggle`/`expand` (tree), `modifier: 'ctrl'\|'shift'` (multi-select), `timeout` | -| `clickElement(target, opts?)` with `{row, column}` | Drill down in SpreadsheetDocument: `{row: 0, column: 'К6'}`, `{row: {'К1': 'Материалы'}, column: 'К6'}`, `{row: 'totals', column: 'К6'}` | -| `fillTableRow(fields, opts)` | Fill a tabular-section row (`{ tab, add, row, table }`) | -| `deleteTableRow(row, { tab?, table? })` | Delete a row | -| `filterList(text, opts?)` / `unfilterList()` | Filter lists (simple / `{ field }`) | +| `fillFields({ name: value })` | Field filling (fuzzy match, auto-type: lookup list/checkbox/radio) | +| `fillField(name, value)` | Single-field equivalent of `fillFields` | +| `selectValue(field, search, opts?)` | Select from a lookup list (drop-down / selection form) | +| `clickElement(text, opts?)` | Click a button/link/row. `opts`: `dblclick`, `table` (scope of the command panel for a specific grid), `toggle`/`expand` (tree), `modifier: 'ctrl'\|'shift'` (multi-select), `timeout` | +| `clickElement(target, opts?)` with `{row, column}` | Drill-down in SpreadsheetDocument: `{row: 0, column: 'К6'}`, `{row: {'К1': 'Материалы'}, column: 'К6'}`, `{row: 'totals', column: 'К6'}` | +| `fillTableRow(fields, opts)` | Table row filling (`{ tab, add, row, table }`) | +| `deleteTableRow(row, { tab?, table? })` | Delete row | +| `filterList(text, opts?)` / `unfilterList()` | List filtering (simple / `{ field }`) | | `closeForm({ save? })` | Close with confirmation handling | | `switchTab(name)` | Switch the form tab or an open tab (tab bar) | -| `navigateLink(url)` | Open an object by metadata (Shift+F11), Russian names are supported | -| `openFile(path)` | Open EPF/ERF through File→Open with security dialog handling | +| `navigateLink(url)` | Open an object by metadata (Shift+F11), supports Russian names | +| `openFile(path)` | Open EPF/ERF via File→Open with security dialog handling | ## API — Utilities and recording | Function | Description | |---------|----------| | `screenshot()` | PNG screenshot | -| `wait(seconds)` | Wait + form state | +| `wait(seconds)` | Pause + form state | | `getPage()` | Playwright Page (non-standard scenarios) | | `startRecording(path, opts?)` / `stopRecording()` | Video recording (can be disabled at the CLI level with `--no-record`) | | `addNarration(videoPath, opts?)` | Overlay TTS narration (node-edge-tts) | -| `showCaption(text, opts?)` / `hideCaption()` | Caption over the video | +| `showCaption(text, opts?)` / `hideCaption()` | Caption over video | | `showTitleSlide(text)` / `hideTitleSlide()` | Title slide | | `showImage(path, opts?)` / `hideImage()` | Image overlay | | `highlight(text, opts?)` / `unhighlight()` / `setHighlight(on)` | Highlight elements | -| `fetchErrorStack(formNum, hasReport)` | Extract the call stack from the 1C error modal | -| `getSections()` / `getCommands()` | Section panel | +| `fetchErrorStack(formNum, hasReport)` | Retrieve the call stack from a 1C error modal | +| `getSections()` / `getCommands()` | Sections panel | -## Important features +## Important details - **Headed mode** — 1C requires a visible browser, no headless - **Ctrl+V** instead of `page.fill()` — 1C reacts only to trusted events -- **Fuzzy matching** — exact > startsWith > includes; `ё` is normalized to `е` and `\u00a0` to a space automatically +- **Fuzzy matching** — exact > startsWith > includes; yo→e and \u00a0→space automatically - **Graceful logout** — `stop` → POST `/e1cib/logout` (releases the license) -- **Auto error detection** — modals, balloons, confirmations are included in the response; when a modal error occurs, the stack (`fetchErrorStack`) and screenshot are pulled automatically -- **Multi-table** — if a form has multiple grids, `tables[]` lists them all; pass `{ table: 'Outgoing' }` to `readTable`/`clickElement`/`fillTableRow`/`deleteTableRow` to select the right one -- **Tree nodes** — by default, clicking selects; `{expand: true}` expands/collapses +- **Automatic error detection** — modals, balloon messages, confirmations are included in the response; on a modal error, the stack (`fetchErrorStack`) and screenshot are attached automatically +- **Multi-table** — if there are multiple grids on the form, `tables[]` lists all of them; pass `{ table: 'Outgoing' }` in `readTable`/`clickElement`/`fillTableRow`/`deleteTableRow` to specify the needed one +- **Tree nodes** — by default, click selects; `{expand: true}` expands/collapses - **Multi-select** — `clickElement(..., { modifier: 'ctrl' })` or `'shift'` -- **1C browser extension** — if installed in Chrome/Edge, it is picked up automatically; you can override it via `extensionPath` in `.v8-project.json` -- **Max. 2 attempts** — after two failures, tell the user +- **1C browser extension** — if installed in Chrome/Edge, it is picked up automatically; it can be overridden through `extensionPath` in `.v8-project.json` +- **Max. 2 attempts** — after two failures, report to the user ## 1C hotkeys | Key | Context | Action | |---------|----------|----------| -| `F8` | Reference field | Create a new element | +| `F8` | Reference field | Create a new item | | `Shift+F4` | Reference field | Clear the value | | `F4` | Reference field | Open the selection form | | `Alt+F` | List/table | Advanced search | ## Regression engine -When you need to cover a 1C solution with a series of automated tests — running multiple `.test.mjs` scenarios in sequence, aggregating results, retrying flaky cases, screenshots on failures, Allure/JUnit reports — switch to `test` mode. More details: [regress.md](regress.md). +When you need to cover a 1C solution with a series of automated tests — running several `.test.mjs` scenarios in a row, aggregating results, retrying flaky cases, screenshots on failures, Allure/JUnit reports — switch to `test` mode. More details: [regress.md](regress.md). -By default, use `run`/`exec` for one-off automation — `test` is a specialized mode for project-wide coverage. +By default, use `run`/`exec` for one-off automation — `test` is a specialized mode for project coverage. -Current runtime limitation: `test` supports one browser context; multi-user scenarios from `regress.md` remain the target contract until the modular engine is ported. +Current runtime limitation: `test` supports one browser context; multi-user scenarios from `regress.md` remain the target contract until the modular engine is migrated. ## Video recording and subtitles Two paths in priority order: -**1. Vanessa Automation (recommended)** — if the scenario is described in a `.feature` file. Vanessa records the run video and generates subtitles from Gherkin steps out of the box. Configured via a profile (`ЗаписыватьВидео`, `ГенерироватьСубтитры`, `ПутьКВидеозаписям`). Use for demo videos for the team and for documenting business processes. +**1. Vanessa Automation (recommended)** — if the scenario is described in a `.feature` file. Vanessa records the run video and generates subtitles from Gherkin steps out of the box. Configure it through the profile (`ЗаписыватьВидео`, `ГенерироватьСубтитры`, `ПутьКВидеозаписям`). Use it for demo videos to the team and for documenting business processes. -**2. Playwright fallback** — when Vanessa is unavailable, headless is needed, or the scenario is written in JS. API: `startRecording` / `stopRecording` / `showCaption` / `addNarration` (TTS via node-edge-tts, OpenAI, or ElevenLabs). Requires ffmpeg. +**2. Playwright for browser/fallback recording** — when the scenario is in the browser layer, written in JS, or selected as fallback under `va-visual-check` rules. API: `startRecording` / `stopRecording` / `showCaption` / `addNarration` (TTS via node-edge-tts, OpenAI or ElevenLabs). Requires ffmpeg. More details: [recording.md](recording.md) — comparison table, Vanessa profile parameters, full Playwright recording API, examples, troubleshooting. diff --git a/framework_eng/skills/tool-usage/browser-ui/web-test-1c/recording.md b/framework_eng/skills/tool-usage/browser-ui/web-test-1c/recording.md index 1d8813cb..22aaacb6 100644 --- a/framework_eng/skills/tool-usage/browser-ui/web-test-1c/recording.md +++ b/framework_eng/skills/tool-usage/browser-ui/web-test-1c/recording.md @@ -1,22 +1,22 @@ -# Video Recording + Subtitles +# Video recording + captions -## Two Paths: Vanessa (Preferred) and Playwright (Fallback) +## Two paths: Vanessa and Playwright for browser-only tasks | | Vanessa Automation | Playwright (`web-test-1c`) | |---|---|---| -| **When to use** | The scenario is described in a `.feature` file; you need a demo video for the team with automatic subtitles from Gherkin steps | Vanessa is unavailable; you need headless mode or the scenario is written in JS; precise control over overlays is required | +| **When to use** | The scenario is described in a `.feature` file; you need a demo video for the team with automatic captions generated from Gherkin steps | The scenario is browser-only, you need JS/DOM control, precise control over browser overlays, or a fallback according to the `va-visual-check` rules | | **Scenario format** | Gherkin / feature file | JS / `.test.mjs` or inline `exec` | -| **Titles/subtitles** | Generated automatically from step texts | Manually via `showCaption()` + `addNarration()` | +| **Titles/captions** | Generated automatically from step texts | Manually via `showCaption()` + `addNarration()` | | **1C UI** | Full standard client | Browser launched by Playwright | -| **Dependencies** | Vanessa Automation, v8-runner | Node.js, ffmpeg, optional node-edge-tts | +| **Dependencies** | Vanessa Automation, v8-runner | Node.js, ffmpeg, optionally node-edge-tts | --- -## Path 1: Recording via Vanessa Automation (recommended) +## Path 1: Recording through Vanessa Automation (recommended) -Vanessa Automation can record scenario runs and generate subtitles from Gherkin steps out of the box, without extra code. +Vanessa Automation can record a scenario run video and generate captions from Gherkin steps out of the box, without any additional code. -### Vanessa profile parameters (va-params / tests.va): +### Vanessa profile parameters (va-params / tests.va) ```json { @@ -30,13 +30,13 @@ Vanessa Automation can record scenario runs and generate subtitles from Gherkin Recording is enabled through the profile - no separate code is needed in the feature file. -### Launch with video recording +### Run with video recording ```bash v8-runner test va --profile tests.va ``` -Or through command-line parameters: +Or via command-line parameters: ```bash v8-runner test va --params '{"ЗаписыватьВидео":true,"ПутьКВидеозаписям":"./reports/video"}' @@ -45,33 +45,33 @@ v8-runner test va --params '{"ЗаписыватьВидео":true,"ПутьКВ ### Result - Video: `<ПутьКВидеозаписям>/<ИмяСценария>.mp4` (one file per scenario) -- Subtitles: `.srt` or `.vtt` next to the video, text is taken from Gherkin step names +- Captions: `.srt` or `.vtt` next to the video, text is taken from Gherkin step names - With `ДелатьСнимкиЭкрана: true` - PNG screenshots for each step in `reports/screenshots/` ### Diagnostics If the video was not created, check: 1. `va-status.json` / `vanessa-execution.log` for errors (see the `vanessa-diagnostics` skill) -2. Write permissions in the `ПутьКВидеозаписям` directory -3. Presence of a codec / ffmpeg in the environment (Vanessa may use it for encoding) +2. Write permissions for the `ПутьКВидеозаписям` directory +3. The presence of a codec / ffmpeg in the environment (Vanessa may use it for encoding) --- -## Path 2: Recording via Playwright (fallback) +## Path 2: Recording through Playwright for browser-only tasks -Use this when Vanessa is unavailable, headless mode is needed, or the scenario is written in JS in `web-test-1c`. +Use this when the scenario belongs to the browser layer, is written in JS in `web-test-1c`, or is chosen as a fallback according to the `va-visual-check` rules. For a regular 1C UI scenario, before Playwright, record the completed VA steps, the reason for the fallback, why the browser/web client provides a sufficient signal, and the residual risk of client differences. ### Prerequisites **ffmpeg** - required. Installation options: -- Local in the project: `tools/ffmpeg/bin/ffmpeg` (detected automatically) -- Global in PATH +- Locally in the project: `tools/ffmpeg/bin/ffmpeg` (detected automatically) +- Globally in PATH - Through `.v8-project.json`: `{ "ffmpegPath": "/opt/ffmpeg/bin/ffmpeg" }` Search order: `opts.ffmpegPath` → `FFMPEG_PATH` → PATH → `tools/ffmpeg/bin/ffmpeg[.exe]` -**node-edge-tts** (optional, for TTS subtitles): +**node-edge-tts** (optional, for TTS captions): ```bash npm install --prefix tools/tts node-edge-tts @@ -82,12 +82,12 @@ npm install --prefix tools/tts node-edge-tts #### `startRecording(outputPath, opts?)` | Parameter | Type | Default | Description | -|----------|-----|---------|----------| -| `outputPath` | string | required | Path to the output `.mp4` | +|----------|-----|-----------|----------| +| `outputPath` | string | required | Path to the output .mp4 | | `opts.fps` | number | 25 | Frame rate | | `opts.quality` | number | 80 | JPEG quality (1-100) | | `opts.ffmpegPath` | string | auto | Explicit path to ffmpeg | -| `opts.speechRate` | number | 70 | Ms/character for smart TTS waiting | +| `opts.speechRate` | number | 70 | ms/char for smart TTS waiting | #### `stopRecording()` → `{ file, duration, size, captions }` @@ -95,17 +95,17 @@ Stops recording and finalizes the MP4. Saves `.captions.json` next to the video. #### `showCaption(text, opts?)` -Displays a text overlay on top of the page (visible in the recording). +Displays a text overlay over the page (visible in the recording). | Parameter | Type | Default | Description | -|----------|-----|---------|----------| -| `text` | string | required | Subtitle text | +|----------|-----|-----------|----------| +| `text` | string | required | Caption text | | `opts.position` | `'top'`\|`'bottom'` | `'bottom'` | Vertical position | | `opts.fontSize` | number | 24 | Font size (px) | | `opts.speech` | string\|false | — | Text for TTS (empty = displayed text, false = no narration) | -| `opts.voice` | string | — | Voice for this subtitle (overrides global) | +| `opts.voice` | string | — | Voice for this caption (global override) | -**Smart TTS wait**: `showCaption` automatically pauses for the estimated speaking time of the text (~70 ms/character, min 2 sec). The subsequent `wait()` accounts for this credit. +**Smart TTS wait**: `showCaption` automatically pauses for the estimated speaking time of the text (~70 ms/char, min 2 sec). The following `wait()` takes this credit into account. #### `addNarration(videoPath, opts?)` → `{ file, duration, size, captions }` @@ -123,15 +123,15 @@ Generates TTS and overlays audio onto the video. Called after `stopRecording()`. | Function | Description | |---------|----------| -| `hideCaption()` | Remove the subtitle | +| `hideCaption()` | Hide the caption | | `showTitleSlide(text, opts?)` | Full-screen title slide (intro/outro) | -| `hideTitleSlide()` | Remove the title | +| `hideTitleSlide()` | Hide the title | | `showImage(path, opts?)` | Full-screen image overlay (styles: `blur`\|`dark`\|`light`\|`full`) | -| `hideImage()` | Remove the image | +| `hideImage()` | Hide the image | | `setHighlight(on)` | Auto-highlight elements before each action (for video) | | `highlight(text)` / `unhighlight()` | Manual element highlighting | -| `isRecording()` | Check whether recording is in progress | -| `getCaptions()` | Get subtitles from the last recording | +| `isRecording()` | Check whether recording is active | +| `getCaptions()` | Get captions from the last recording | ### TTS configuration in `.v8-project.json` @@ -145,12 +145,12 @@ Generates TTS and overlays audio onto the video. Called after `stopRecording()`. } ``` -Edge TTS is free, with no API key required (internet needed). For OpenAI: +Edge TTS is free, with no API key required (internet access is needed). For OpenAI: ```json { "tts": { "provider": "openai", "apiKey": "sk-...", "voice": "alloy" } } ``` -### Example: recording a workflow with subtitles and auto-highlighting +### Example: recording a workflow with captions and auto-highlight ```js await startRecording('recordings/create-order.mp4'); @@ -162,7 +162,7 @@ await showTitleSlide('Создание заказа клиента', { await wait(1); await hideTitleSlide(); -setHighlight(true); // авто-подсветка перед каждым действием +setHighlight(true); // auto-highlight before each action await showCaption('Шаг 1. Переходим в раздел «Продажи»'); await wait(1.5); @@ -191,11 +191,11 @@ const narrated = await addNarration(video.file, { voice: 'ru-RU-DmitryNeural' }) console.log(`С озвучкой: ${narrated.file}`); ``` -**Order: subtitle → pause → action.** `showCaption` handles the TTS pause on its own; add `wait()` only if you need to wait for the form to load. +**Order: caption → pause → action.** `showCaption` handles the TTS pause itself; add `wait()` only if you need to wait for the form to load. ### Re-narration without re-recording -After `stopRecording()`, a `.captions.json` file is saved next to the video. You can narrate it with a different voice without re-shooting: +After `stopRecording()`, a `.captions.json` file is saved next to the video. You can narrate it again with a different voice without re-shooting: ```js const result = await addNarration('recordings/demo.mp4', { voice: 'ru-RU-SvetlanaNeural' }); @@ -208,7 +208,7 @@ In `webtest.config.mjs`, you can enable recording for the entire suite: ```js export default { url: '...', - record: true, // запись каждого теста + record: true, // record every test screenshot: 'on-failure', }; ``` @@ -221,7 +221,7 @@ Or for individual tests via `export const tags = ['recording']` + severity mappi |---------|---------| | "ffmpeg not found" | Install ffmpeg, check the path (see above) | | 0-byte file | Check write permissions in the directory; ffmpeg may have crashed | -| Stuttering video | Add `wait()` between steps; reduce `quality` | +| Video stutter | Add `wait()` between steps; reduce `quality` | | "Already recording" | Call `stopRecording()` before starting a new recording | -| No subtitles | Was `showCaption()` used during recording? Or pass `opts.captions` to `addNarration` | -| TTS timeout | Edge TTS requires internet; check the connection | +| No captions | Was `showCaption()` used during recording? Or pass `opts.captions` to `addNarration` | +| TTS timeout | Edge TTS requires internet access; check the connection | diff --git a/framework_eng/skills/tool-usage/browser-ui/web-test-1c/regress.md b/framework_eng/skills/tool-usage/browser-ui/web-test-1c/regress.md index adf32028..53d68cae 100644 --- a/framework_eng/skills/tool-usage/browser-ui/web-test-1c/regress.md +++ b/framework_eng/skills/tool-usage/browser-ui/web-test-1c/regress.md @@ -1,14 +1,16 @@ # Playwright Regression Engine -Use this document when you need to cover a 1C solution with automated regression tests: run several .feature / JSON scenarios in sequence, aggregate results, get fail/pass reports, configure retry for flaky tests, and save screenshots on failures. For one-off automation (a single scenario), stay in the `run`/`exec` modes from SKILL.md. +Use this document when you need to cover a 1C solution with automated regression tests: run several `.feature` / JSON scenarios in sequence, aggregate results, get a fail/pass report, configure retry on flaky tests, and save screenshots on failures. For one-off automation (one scenario), stay in the `run`/`exec` modes from `SKILL.md`. -The runner is the same `run.mjs`. The mode is `test`: +For 1C UI this is not the default regression path. If a test checks a form, command, field, tabular section, client handler, or business flow without browser-specific behavior, first write/run a Vanessa `.feature` through TestClient. Choose Playwright regression through `web-test-1c` for the web-client/browser layer or as fallback under `va-visual-check`: DOM/CSS/HTML, console/network, web-auth/publication, viewport/pixel rendering, browser extension, or browser-only I/O. In the test or report, record the VA steps, the reason for choosing browser/fallback, and the residual risk. + +The runner is the same `run.mjs`. Mode: `test`: ```bash -node $RUN test <dir|file> [--url=<url>] [flags] +node $RUN test <dir|file> [--url=<url>] [флаги] ``` -The current implementation in this repository is a single-context runner: `url`, discovery, hooks, `step`, `assert`, `--tags`, `--grep`, `--retry`, JSON/JUnit/Allure-smoke reports, and failure screenshots are supported. Multi-user `contexts` below describe the target contract, but are not enabled yet in the `tools/web-test` runtime. +The current implementation in this repository is a single-context runner: `url`, discovery, hooks, `step`, `assert`, `--tags`, `--grep`, `--retry`, JSON/JUnit/Allure-smoke reports, and screenshots on failure are supported. The multi-user `contexts` below describes the target contract, but it is not yet enabled in the `tools/web-test` runtime. Tests live next to the project they cover, not inside the skill. Convention: `tests/` at the project root, `_hooks.mjs` and `webtest.config.mjs` at the suite root. @@ -16,25 +18,26 @@ Tests live next to the project they cover, not inside the skill. Convention: `te | Goal | Mode | |------|-------| -| Explore a form, prototype one step, debug a selector | `exec` (interactive session) | +| Explore a form / prototype a step without a browser-specific reason | Vanessa/TestClient or platform TestClient MCP | +| Debug a DOM/CSS selector or browser-only behavior | `exec` (interactive web session) | | Reproduce a bug as a failing test before the fix | `test` | | Cover a feature with tests for the future | `test` | | Run a project regression on a new build | `test` | -| Create a screencast workflow | `exec` with `startRecording` | +| Make a screencast workflow | `exec` with `startRecording` | -Do not write `.test.mjs` for a one-off request. Do not run a regression suite through a chain of `exec` calls. +Do not write a `.test.mjs` for a one-off request. Do not drive a regression suite through a chain of `exec` calls. ## Reconnaissance before writing tests Two levels, in order. -**1. Static reconnaissance - metadata.** Never invent identifiers. For each metadata object, run the corresponding skill: `/meta-info` (attributes/Tables), `/form-info` (form layout), `/skd-info` (SKD), `/role-info` (permissions). If you cannot find it, ask. +**1. Static reconnaissance - metadata.** Never invent identifiers. For each metadata object, run the corresponding skill: `/meta-info` (attributes/tabular sections), `/form-info` (form layout), `/skd-info` (SKD), `/role-info` (permissions). If you cannot find it, ask. -**2. Live reconnaissance - interactive run.** For a non-trivial scenario, walk through it in `exec` mode before writing the test. Metadata tells you what exists; a live run tells you what actually happens. Capture from `getFormState()`: exact button names, table section names, required fields, and where real waits occur. Then move the working sequence into `*.test.mjs`, wrapping logical blocks in `step('...', async () => { ... })`. +**2. Live reconnaissance - interactive run.** For a non-trivial scenario, go through it in `exec` mode before writing the test. Metadata tells you what exists; a live run tells you what actually happens. Capture from `getFormState()`: exact button names, table section names, required fields, places where real waiting happens. Then transfer the working sequence into `*.test.mjs`, wrapping logical blocks in `step('...', async () => { ... })`. ## Suite Structure -**Each application has its own subfolder in `tests/`.** One repository can contain several isolated suites side by side - they must not share `_hooks.mjs` or `webtest.config.mjs`, because each restores a different DB and publishes to a different URL. +**Each application has its own subfolder in `tests/`.** One repository can contain several isolated suites side by side - they must not share `_hooks.mjs` or `webtest.config.mjs`, because each restores a different database and publishes to a different URL. ``` tests/ @@ -49,9 +52,9 @@ tests/ <another-app>/ # second solution, fully isolated ``` -Inside the application subfolder, organize by **feature**, not by metadata type. Numeric prefixes in folders and files define the execution order. Entries starting with `_` or `.` are excluded from discovery (so `_hooks.mjs`, `_allure/` do not become tests). +Inside the application subfolder, organize by **feature**, not by metadata type. Numeric prefixes in folders and files define execution order. Entries starting with `_` or `.` are excluded from discovery (so `_hooks.mjs`, `_allure/` do not become tests). -## Test File Anatomy +## Anatomy of a test file ```js export const name = 'Создание контрагента'; // обязательно @@ -94,42 +97,42 @@ export default async function(ctx) { } ``` -**Step names should be in Russian and descriptive.** Step labels appear in the console output, JSON/JUnit, and Allure steps. Use a full action phrase (`'Create a new counterparty'`), not a tag (`'create'`). +**Step names should be in Russian and descriptive.** Step labels appear in console output, JSON/JUnit, and Allure steps. Use a full action phrase (`'Create a new counterparty'`), not a tag (`'create'`). -## `ctx` Contract +## ctx Contract -The runner injects all `browser.mjs` exports into `ctx` (all 1C API functions), plus testing utilities: +The runner injects into `ctx` all exports from `browser.mjs` (all 1C API functions), plus testing utilities: ```js step(name, fn) // async wrapper. Records start/stop. Supports nesting. -log(...args) // adds a line to ctx.testInfo output (goes to JSON/Allure attachment) +log(...args) // adds a line to ctx.testInfo output (goes into JSON/Allure attachment) assert.* // see "Assertions" below ``` -### `ctx.testInfo` (always set, read-only) +### ctx.testInfo (always set, read-only) ```js { - name, // 'Navigation by sections' (with parameters substituted) + name, // 'Навигация по разделам' (with parameters substituted) file, // '01-navigation.test.mjs' (basename) tags, // ['nav', 'smoke'] timeout, // ms attempt, // 1..maxAttempts maxAttempts, // 1 + retry param, // { ... } | undefined (only when export const params is set) - // planned after the modular engine is ported: - // contexts: { clerk: { url, ... }, manager: { ... } }, + // planned after modular engine migration: + // contexts: { clerk: { url, ... }, manager: { url, ... } }, // primaryContext: 'clerk' } ``` -### `ctx.testResult` (only in afterEach) +### ctx.testResult (only in afterEach) ```js { status, // 'passed' | 'failed' duration, // ms - attempts, // actually executed attempts + attempts, // attempts actually performed error, // { message, step?, screenshot? } | null steps // array of step results } @@ -137,7 +140,7 @@ assert.* // see "Assertions" below ## Assertions -All of them are on `ctx.assert`. They throw `AssertionError` with `.message`, `.actual`, `.expected`. +Everything is on `ctx.assert`. They throw `AssertionError` with `.message`, `.actual`, `.expected`. ```js // generic @@ -149,7 +152,7 @@ assert.includes(haystack, needle, msg?) assert.match(string, regex, msg?) await assert.throws(asyncFn, msg?) -// 1C-specific - work with getFormState() / readTable() +// 1C specifics - work with getFormState() / readTable() assert.formHasField(state, 'Контрагент', msg?) assert.formTitle(state, expected, msg?) assert.tableHasRow(table, predicate, msg?) // predicate: object (partial) or fn(row) => bool @@ -157,7 +160,7 @@ assert.tableRowCount(table, expected, msg?) assert.noErrors(state, msg?) ``` -## `webtest.config.mjs` +## webtest.config.mjs ```js export default { @@ -172,7 +175,7 @@ export default { // defaultContext: 'clerk', timeout: 30000, - retries: 0, // retry for flaky tests + retries: 0, // retry on flaky tests screenshot: 'on-failure', // 'every-step' | 'off' | 'on-failure' record: false, @@ -184,18 +187,18 @@ export default { }; ``` -CLI flags override the config. Use Latin context IDs + Russian `displayName` values for ergonomics. +CLI flags override the config. Use Latin context IDs plus Russian `displayName` for ergonomics. -## `_hooks.mjs` +## _hooks.mjs ```js -// Infrastructure hooks - run without a browser +// Infrastructure hooks - work without a browser export async function prepare({ hookArgs, log, config }) { - // Restore DB, publish, build EPF. Make it idempotent. + // Restore the database, publish, build EPF. Make it idempotent. } export async function cleanup({ log, config }) { /* optional */ } -// Test-level hooks - run with browser ctx +// Test level - work with browser ctx export async function beforeAll(ctx) { } export async function afterAll(ctx) { } export async function beforeEach(ctx) { } @@ -212,7 +215,7 @@ Pass hook arguments after `--`: node $RUN test tests/<app-name>/ --bail -- --rebuild-stand --data=demo ``` -## Run +## Running ```bash node $RUN test tests/<app-name>/ # entire application suite @@ -229,15 +232,15 @@ The `--retry=1` flag gives one retry for a flaky test - especially useful for un ### Screenshots on failures -`screenshot: 'on-failure'` in `webtest.config.mjs` (or `--screenshot=on-failure`) automatically captures a PNG for every failed test. The screenshot path is placed in `ctx.testResult.error.screenshot` and in the report. With `'every-step'`, a screenshot is taken after each `step()`. +`screenshot: 'on-failure'` in `webtest.config.mjs` (or `--screenshot=on-failure`) automatically captures a PNG on every failed test. The screenshot path is included in `ctx.testResult.error.screenshot` and in the report. With `'every-step'`, a shot is taken after every `step()`. ## Ready-made Patterns -### SKD Report +### SKD report ```js await openCommand('Остатки товаров'); -// Сбрасываем пользовательские настройки (1С их сохраняет между сессиями) +// Reset user settings (1С stores them between sessions) await clickElement('Ещё'); await clickElement('Установить стандартные настройки'); await selectValue('Номенклатура', 'Товар 02'); @@ -249,7 +252,7 @@ assert.ok(r.data.length >= 1); assert.ok(r.totals?.['Сумма']); ``` -### Multi-user Process +### Multi-user process ```js export const contexts = ['clerk', 'manager']; @@ -277,7 +280,7 @@ export default async function({ clerk, manager, step, assert }) { } ``` -### Parameterized Test +### Parameterized test ```js export const name = 'Заполнение поля {type}'; @@ -293,7 +296,7 @@ export default async function({ fillFields, getFormState, assert }, { field, val } ``` -### Bug Reproduction (Failing Test) +### Bug reproduction (failing test) ```js export const name = 'Bug #123: накладная без контрагента не должна проводиться'; @@ -309,38 +312,38 @@ export default async function({ openCommand, clickElement, getFormState, assert, } ``` -Start red, deliver it to the user, fix it, rerun it green. +Write it failing first, hand it to the user, fix it, rerun it green. -## Test Severity +## Test Severity (severity) -| Test type | Recommendation | +| Type of test | Recommendation | |-----------|--------------| | Login + navigation, basic CRUD for covered entities | `critical` (+ tag `smoke`) | -| Document posting, report generation, end-to-end processes | `critical` | +| Posting documents, report generation, end-to-end processes | `critical` | | Edge cases for fields, formatting, optional flows | `normal` | | Video recording / non-functional | `minor` | -Do not mark everything as `critical` - that destroys the signal in the Allure dashboard. +Do not mark everything `critical` - that erodes the signal in the Allure dashboard. -## Anti-patterns +## Antipatterns -- **sleep instead of waiting for state.** `wait(5)` after `openCommand` is fine; `wait(30)` because it flickers is a bug. -- **Retry instead of understanding.** "Not found" twice means the data is missing or the name is wrong. -- **Binding to a row position** (`rows[0]`) when the DB has shared data. Filter by a unique marker. -- **Resetting state manually in `afterEach`.** The runner already closes forms and hides errors. -- **Dependence on test order.** Every test must start from the desktop and prepare its own data. +- **Sleep instead of waiting for state.** `wait(5)` after `openCommand` is fine; `wait(30)` because it is flaky is a bug. +- **Retry instead of understanding.** “Not found” twice means the data is missing or the name is wrong. +- **Binding to row position** (`rows[0]`) when the database has shared data. Filter by a unique marker. +- **Manual state reset in `afterEach`.** The runner already closes forms and hides errors. +- **Dependence on test order.** Every test should start from the desktop and prepare its own data. - **`tags: ['smoke']` on a 90-second test.** Smoke means fast. -## Failure Analysis +## Failure Triage 1. Check the JSON or Allure summary for `failed`. 2. For each failure: `error.message` + `error.step` + screenshot. -3. If `error.onecError.stack` exists, it is a 1C exception; inspect the platform stack trace. +3. If there is `error.onecError.stack` - that is a 1C exception, inspect the platform traceback. 4. Classify: - **Test bug** - wrong selector, wrong expectation, race condition -> fix the test. - - **Application bug** -> report it to the user with the name of the failing step and the stack trace. - - **Environment instability** - Apache timeout, no license -> fix hook idempotence. -5. After the fixes, rerun only the failed files, then the full suite. + - **Application bug** -> report to the user with the name of the failing step and the stack. + - **Environment instability** - Apache timeout, no license -> fix hook idempotency. +5. After fixes, rerun only the failed files, then the full suite. ## Reference diff --git a/framework_eng/skills/tool-usage/code-analysis/buddy-prompting/SKILL.md b/framework_eng/skills/tool-usage/code-analysis/buddy-prompting/SKILL.md index cd00cfb3..223328ea 100644 --- a/framework_eng/skills/tool-usage/code-analysis/buddy-prompting/SKILL.md +++ b/framework_eng/skills/tool-usage/code-analysis/buddy-prompting/SKILL.md @@ -1,6 +1,6 @@ --- name: buddy-prompting -description: "MUST use WHEN you need to query 1С Buddy (ask_ai_assistant) for platform API, ITS standards, version diffs, or BSL validation. Provides strict templates (SEARCH_DOCS / SEARCH_ITS / FETCH_ITS / DIFF_VERSIONS / VALIDATE_BSL) that match Buddy's internal instructions." +description: "Before asking 1C Buddy: API, ITS, versions, BSL" uses_capabilities: - ask_ai_assistant alwaysApply: false diff --git a/framework_eng/skills/tool-usage/code-analysis/code-navigation/SKILL.md b/framework_eng/skills/tool-usage/code-analysis/code-navigation/SKILL.md index 8df86be9..211c1edc 100644 --- a/framework_eng/skills/tool-usage/code-analysis/code-navigation/SKILL.md +++ b/framework_eng/skills/tool-usage/code-analysis/code-navigation/SKILL.md @@ -1,6 +1,6 @@ --- name: code-navigation -description: "Use for navigating BSL code through LSP (finding definitions, references, call graphs, renaming). Helps precisely locate symbols from the project index without guessing their location." +description: "BSL LSP navigation: definitions, refs, call graph" uses_capabilities: - navigate_symbol - get_call_graph @@ -13,7 +13,7 @@ uses_capabilities: # Code Navigation -Do not guess where code is located - use LSP. Accurate results from the project index. +Do not guess code location - use LSP. Exact results from the project index. ## When to use @@ -21,16 +21,16 @@ Do not guess where code is located - use LSP. Accurate results from the project |---------|----------| | Search for procedure/function definitions | `navigate_symbol` operation `definition` | | All calls to function X | `navigate_symbol` `search` or `get_call_graph` `incoming` | -| Who a function calls | `get_call_graph` `outgoing` | +| What a function calls | `get_call_graph` `outgoing` | | Rename across the project | `rename_symbol` (first `preview: true`) | | Quick Fixes | `get_code_actions` | | File diagnostics | `get_diagnostics` | | Investigating unknown code | `navigate_symbol` → `get_call_graph` → hover | -| Error «method not found» on a platform type | `getMembers` / `getMember` / `getConstructors` | -| Object structure / tabular sections / attributes, enum values, predefined items | `get_completion` after a dot (see «Metadata discovery») | +| Error "method not found" on a platform type | `getMembers` / `getMember` / `getConstructors` | +| Object structure / tabular sections / attributes, enum values, predefined items | `get_completion` after a dot (see "Metadata discovery") | | Where a metadata object is used in code | `search_ssl_functions` references on `Документы.X` + grep (see below) | -| Estimate who a procedure/function change affects | `get_symbol_impact` (callers + references + classification) | -| Parameter hints while writing a call | `signature_help` — cursor INSIDE the call parentheses (see «Parameter hints») | +| Estimate who a procedure/function change affects | `get_symbol_impact` (incoming + references + classification) | +| Parameter hints while writing a call | `signature_help` — cursor INSIDE the call parentheses (see "Parameter hints") | ## Algorithms @@ -53,7 +53,7 @@ Do not guess where code is located - use LSP. Accurate results from the project ### Verify the platform API after an error -**Trigger:** error «Object method not found» / «Incorrect number of parameters» on a platform type. Do not guess again - verify. +**Trigger:** error "Object method not found" / "Incorrect number of parameters" on a platform type. Do not guess again - verify. 1. `search_syntax_reference(query: "ТипОбъекта")` → confirm the name, get `id` 2. `getMembers(typeId)` → exact list of methods/properties @@ -73,16 +73,16 @@ BSL LS Type System v2 exposes configuration metadata through completion. One too | Predefined items | after `Справочники.Имя.` / `ПланыСчетов.Имя.` | predefined items + manager methods | | Composition of a DefinedType | cursor on an attribute of type ОпределяемыйТип | `get_completion` + `get_hover_info` reveal the composing types | -**Inverse signal:** if `get_completion` after `перем.` returns nothing or does not include the expected member, the variable type was inferred incorrectly/unknown. No completion here = a type error indicator (a common 1C bug), not «no data». +**Inverse signal:** if `get_completion` after `перем.` returns nothing or does not include the expected member, the variable type was inferred incorrectly/unknown. No completion here = a type error indicator (a common 1C bug), not "no data". ### Find where a metadata object is used in code The picture is hybrid (how the object is used in BSL itself): -1. `search_ssl_functions` (references mode) on the manager symbol `Документы.ИмяОбъекта` → **semantically precise** manager-access locations. References exclude matches in comments/strings/query text. -2. **Complement with grep** for what is not a symbol and therefore is not visible to references: string type literals (`"ДокументСсылка.ИмяОбъекта"`, `Тип("ДокументСсылка.…")`) and metadata paths inside query text (`ИЗ Документ.ИмяОбъекта`). +1. `search_ssl_functions` (references mode) on the manager symbol `Документы.ИмяОбъекта` → **semantically exact** manager-access locations. References exclude matches in comments/strings/query text. +2. **Supplement with grep** for what is not a symbol and therefore is not visible to references: string literals of the type (`"ДокументСсылка.ИмяОбъекта"`, `Тип("ДокументСсылка.…")`) and metadata paths inside query text (`ИЗ Документ.ИмяОбъекта`). -> For “where used”, prefer references over a bare grep by name: grep produces false positives in comments and strings. Use grep only to pick up string/query usages. +> For "where used", prefer references over a bare grep by name: grep produces false positives in comments and strings. Use grep only to pick up string/query usages. ### Change-impact analysis: `get_symbol_impact` @@ -102,15 +102,15 @@ Returns the list of parameters for the called method and which argument the curs **You MUST pass `line`/`character` as 0-based, with the cursor INSIDE the call parentheses** — between `(` and `)`, NOT on the method name and NOT before `(`. The provider finds the enclosing call (`doCall`), resolves the called method, and only then returns signatures. ``` -// Line (1-based 8): Аккаунт = ПолучитьАккаунт(ДокументОперации, ПараметрыОперации); -signature_help(uri, line=7, character=29) // immediately after "(" → param 0 +// Строка (1-based 8): Аккаунт = ПолучитьАккаунт(ДокументОперации, ПараметрыОперации); +signature_help(uri, line=7, character=29) // сразу после "(" → param 0 // → ПолучитьАккаунт(ДокументОперации?, ПараметрыОперации?), Active parameter: 0 signature_help(uri, line=7, character=47) // after comma → Active parameter: 1 ``` **Empty result ≠ tool is broken.** `signature_help` returns signatures only when the called method resolves to a method with a known parameter list. It works reliably for **methods in the same module** (resolution from parsed source). It returns empty for: - cursor NOT inside the parentheses (on the name / before `(`) — the most common mistake; -- cross-module call (`Модуль.Метод(`) — requires the configuration type index, and works only when BSL LS is pointed at a single configuration root (see “Common mistakes”: cross-module resolution); +- cross-module call (`Модуль.Метод(`) — requires the configuration type index, and works only when BSL LS is pointed at a single configuration root (see "Common mistakes": cross-module resolution); - global platform methods (`СтрШаблон(`, `ЗначениеЗаполнено(`) and platform object methods (`Запрос.УстановитьПараметр(`) — requires a loaded **1C platform context** (`.hbk` syntax helper). The mcp-lsp container is lightweight — the platform is NOT baked into the image, it is provisioned at runtime. The `bsl-ls` run script generates a global config and passes it through `-Dapp.globalConfiguration.path`: when `BSL_PLATFORM_BIN` is set (compose `docker-compose.platform.yml` mounts the `.hbk` directory read-only) — the explicit `v8platform.binPath` takes priority; when it is not set — BSL LS auto-detects the installed platform (including Windows). Without either, the startup log shows `Failed to load platform contexts: No 1C platform installations found`, and platform hover/completion/signatures are empty. With a loaded context (`Loaded N platform contexts from 1C syntax helper`) — they resolve with full parameter docs (in Russian when `language:ru`). For a confirmed parameter list regardless of call site - `getMember(typeId, member)` (platform types) or `navigate_symbol`→hover (the method's own declaration). diff --git a/framework_eng/skills/tool-usage/code-analysis/code-verification/SKILL.md b/framework_eng/skills/tool-usage/code-analysis/code-verification/SKILL.md index 1c27baa9..f18290a0 100644 --- a/framework_eng/skills/tool-usage/code-analysis/code-verification/SKILL.md +++ b/framework_eng/skills/tool-usage/code-analysis/code-verification/SKILL.md @@ -1,6 +1,6 @@ --- name: code-verification -description: "MUST use WHEN BSL code is changed before commit or handoff for review. Provides a three-layer check: LSP diagnostics, VALIDATE_BSL through Buddy, and platform API verification via bsl-platform-context." +description: "After BSL changes: LSP, Buddy/API, syntax checks" uses_capabilities: - get_diagnostics - ask_ai_assistant @@ -14,33 +14,33 @@ alwaysApply: false # Code Verification -The skill describes **the sequence for verifying BSL code after changes are made**. -Three layers of checks, each catching its own class of errors. +This skill describes **the sequence for verifying BSL code after changes**. +Three verification layers, each catching its own class of errors. -## When to apply +## When to Use | Trigger | Action | |---------|----------| -| After changing BSL code | Full cycle (all 3 layers) | +| After modifying BSL code | Full cycle (all 3 layers) | | Reviewing someone else's code | Layer 2 + Layer 3 | | User asks "check syntax" | Full cycle | -## Check Layers +## Verification Layers -### Layer 1 — LSP diagnostics (fast) +### Layer 1 - LSP diagnostics (fast) Goal: immediate feedback on the changed file. 1. `get_diagnostics(uri)` — get errors/warnings from the BSL Language Server. -2. If there is an `error`-level issue — fix it before moving to layer 2. -3. If LSP is unavailable — move to layer 2, noting that the LSP check was skipped. +2. If there is an `error`-level issue, fix it before moving to layer 2. +3. If LSP is unavailable, move to layer 2 and note that the LSP check was skipped. -### Layer 2 — Buddy (VALIDATE_BSL) +### Layer 2 - Buddy (VALIDATE_BSL) Goal: syntax validation, standards check, search for analogs in БСП. -**What to pass:** entire procedures/functions in which changes were made. -Not fragments, not individual lines — full method bodies. +**What to pass:** the complete procedures/functions that were modified. +Not fragments, not individual lines - full method bodies. **Call:** `ask_ai_assistant` with the VALIDATE_BSL template from buddy-prompting. @@ -48,20 +48,20 @@ Not fragments, not individual lines — full method bodies. | Situation | Action | |----------|----------| -| Buddy found errors | Analyze each one. Filter out false "undeclared variable" reports for global methods. Fix the rest or justify them. | -| Buddy found no errors | **DO NOT treat this as proof of correctness.** Buddy has limited context — it cannot see the project. Move to layer 3. | +| Buddy found errors | Analyze each one. Filter false "undeclared variable" reports for global methods. Fix or justify the rest. | +| Buddy found no errors | **DO NOT treat this as proof of correctness.** Buddy has limited context - it cannot see the project. Move to layer 3. | | Buddy recommends replacing with a БСП function | Verify via `search_ssl_functions` that the recommended function exists. | -### Layer 3 — Platform API verification +### Layer 3 - Platform API verification Goal: confirm that every platform object, method, property, and constructor used in the code **really exists** on the specified type. **Algorithm:** 1. Extract all platform API references from the changed code: - - `New <Type>(...)` — object creation - - `<Object>.<Method>(...)` — method calls - - `<Object>.<Property>` — property reads/writes + - `New <Type>(...)` - object creation + - `<Object>.<Method>(...)` - method calls + - `<Object>.<Property>` - property reads/writes - References to managers, enumerations, predefined values 2. Verify each reference: @@ -75,9 +75,9 @@ Goal: confirm that every platform object, method, property, and constructor used | Type is unclear | Search by name | `search_syntax_reference` → `getMembers` | | Variable/expression type is unknown | Get the type of the value under the cursor | `get_hover_info` | -3. **Special attention to collection types.** The APIs of `Структура`, `Соответствие`, `ТаблицаЗначений`, `Массив` differ. Do not assume the same methods — verify on the specific type. +3. **Special attention to collection types.** The APIs of `Структура`, `Соответствие`, `ТаблицаЗначений`, `Массив` differ. Do not assume the same methods - verify on the specific type. -4. **Determining a variable type.** When it is unclear which type a variable has (and therefore which API is allowed on it), `get_hover_info(uri, line, character)` on the variable name returns the inferred BSL LS value type (Type System v2). This is the type inference for the **specific value** at this point, not help for all platform types. Then verify members of the resulting type through `getMember`/`getMembers`. If `get_hover_info` is unavailable — determine the type from the declaration/assignment site via `navigate_symbol`. +4. **Determining a variable type.** When it is unclear which type a variable has (and therefore which API is allowed on it), `get_hover_info(uri, line, character)` on the variable name returns the inferred BSL LS value type (Type System v2). This is the type inference for the **specific value** at this point, not help for all platform types. Then verify members of the resulting type through `getMember`/`getMembers`. If `get_hover_info` is unavailable, determine the type from the declaration/assignment site via `navigate_symbol`. ## Trust Hierarchy @@ -105,7 +105,7 @@ As a result of the check, provide a structured output: |----------|------------| | LSP unavailable | Skip layer 1, move to layer 2. Note it in the report. | | Buddy unavailable | Skip layer 2. Strengthen layer 3. | -| `bsl-platform-context` does not know the type | Type from the project (not a platform type) — verify via `navigate_symbol`. | +| `bsl-platform-context` does not know the type | Type from the project (not a platform type) - verify via `navigate_symbol`. | | False "undeclared variable" from Buddy | Normal for global methods — filter it out. | | `search_syntax_reference` is empty | Clarify the type name (Russian/English spelling), check the version. | | Buddy recommends a non-existent БСП function | Verify via `search_ssl_functions`. | diff --git a/framework_eng/skills/tool-usage/code-analysis/search-before-write/SKILL.md b/framework_eng/skills/tool-usage/code-analysis/search-before-write/SKILL.md index 415156d6..95a1bda5 100644 --- a/framework_eng/skills/tool-usage/code-analysis/search-before-write/SKILL.md +++ b/framework_eng/skills/tool-usage/code-analysis/search-before-write/SKILL.md @@ -1,16 +1,16 @@ --- name: search-before-write -description: "MUST use BEFORE writing new BSL code or a function. Defines the search cascade (LSP → metadata → platform → БСП) as proof that no ready-made equivalent exists." +description: "Before new BSL code, find an existing analogue" alwaysApply: false --- # Search Before Write -Any coding task is first and foremost a search task. Search first, then write. +Any coding task is first and foremost a search task. First search, then write. ## Search Cascade -Each next step is only taken if the previous one produced no result: +Each next step is only if the previous one did not produce a result: | Step | Tool | What we search for | |-----|------------|----------| @@ -30,9 +30,9 @@ Each next step is only taken if the previous one produced no result: |--------|-----------------------| | New function/procedure | 1 — search for analogs by name | | Business logic | 2 — search for metadata objects | -| Using the platform API | 3 — syntax reference; fallback 5a (documentation) | +| Platform API usage | 3 — syntax reference; fallback 5a (documentation) | | Print form | 2 → 4 (metadata + БСП API) | -| Development standards and rules | 5b — search in ИТС | +| Standards and development rules | 5b — search in ИТС | | Migration between versions | 5a (DIFF_VERSIONS template) | | Query | 1 — existing queries in the project | @@ -40,23 +40,23 @@ Each next step is only taken if the previous one produced no result: | Capability | Purpose | |------------|------------| -| `navigate_symbol` | Search for symbols, definitions, usages | +| `navigate_symbol` | Search symbols, definition, usages | | `list_metadata_objects` | Metadata objects by type and mask | -| `get_metadata_structure` | Object structure (requisites, dimensions, resources) | +| `get_metadata_structure` | Object structure (attributes, dimensions, resources) | | `search_syntax_reference` | Platform syntax reference | | `get_type_info` | Platform type details | | `search_ssl_functions` | БСП functions | | `ask_ai_assistant` | Best practices, templates | -## Common mistakes +## Typical Errors -| Mistake | Workaround | +| Error | Workaround | |--------|---------------| -| Skipping the search | Hard rule: code creation → first step = search | -| `list_metadata_objects` returns nothing | Is the configuration loaded? `v8-runner build` (or `v8-runner dump --mode incremental` if ИБ is the source of truth); check metaType/nameMask | -| `navigate_symbol` returns nothing | Clarify the name (Rus/Lat, case); `ask_ai_assistant` (SEARCH_DOCS template) | -| `ask_ai_assistant` returns an empty result | Reformulate the query; see the rules in `buddy-prompting` | -| `search_ssl_functions` unavailable | Without БСП — `search_syntax_reference` + `navigate_symbol` through common modules | +| Skipping search | Hard rule: code creation → first step = search | +| `list_metadata_objects` empty | Configuration loaded? `v8-runner build` (or `v8-runner dump --mode incremental` if the ИБ is the source of truth); check metaType/nameMask | +| `navigate_symbol` empty | Clarify the name (Russian/Latin, case); `ask_ai_assistant` (SEARCH_DOCS template) | +| `ask_ai_assistant` empty result | Rephrase query; see rules in `buddy-prompting` | +| `search_ssl_functions` unavailable | Without БСП — `search_syntax_reference` + `navigate_symbol` for common modules | --- depends_on: [] diff --git a/framework_eng/skills/tool-usage/code-analysis/syntax-checking/SKILL.md b/framework_eng/skills/tool-usage/code-analysis/syntax-checking/SKILL.md index 9007cc24..de56fdbe 100644 --- a/framework_eng/skills/tool-usage/code-analysis/syntax-checking/SKILL.md +++ b/framework_eng/skills/tool-usage/code-analysis/syntax-checking/SKILL.md @@ -1,6 +1,6 @@ --- name: syntax-checking -description: "MUST use BEFORE committing or handing BSL code off for review. Defines a two-level process (LSP get_diagnostics → full Configurator check) as proof that there are no syntax errors." +description: "Before BSL handoff: LSP and full syntax check" uses_capabilities: - get_diagnostics - get_quality_diagnostics @@ -14,65 +14,65 @@ alwaysApply: false # Syntax Checking -Any BSL code change → immediate verification. Without verification, the agent can "successfully" complete a task with non-working code. +Any change to BSL code requires immediate validation. Without checking, the agent can "successfully" complete the task with broken code. -**Two levels of verification — different cost:** +**Two levels of checking — different cost:** | Tool | Speed | When to use | |------------|----------|-------------------| | `get_diagnostics` (LSP) | Fast (seconds) | After every change, intermediate checks | -| `v8-runner syntax …` | Slow (tens of seconds — minutes) | Final check: before commit, before PR, after a major refactor | +| `v8-runner syntax …` | Slow (dozens of seconds to minutes) | Final check: before commit, before PR, after major refactoring | -Server-side verification is now done **only through the `v8-runner` CLI** — the separate MCP tools `check_syntax`/`build_project`/`dump_config` have been removed. Details of the commands and selection rules are in the `v8-runner` skill (`framework/skills/tool-usage/v8-runner/`). +Server-side checking is now done **only through the `v8-runner` CLI** — separate MCP tools `check_syntax`/`build_project`/`dump_config` have been deprecated. Details of the commands and selection rules are in the `v8-runner` skill (`framework/skills/tool-usage/v8-runner/`). -## When to apply +## When to use | Trigger | Action | |---------|----------| | After changing BSL code | `get_diagnostics` — fast check | -| Iterative edit cycle (edit → check) | `get_diagnostics` | -| After refactoring / `rename_symbol` | `get_diagnostics` for affected files | +| Iterative editing (edit → check loop) | `get_diagnostics` | +| After refactoring / `rename_symbol` | `get_diagnostics` for the affected files | | Compilation error | `get_diagnostics` for localization | | **Before commit / before PR** | **`v8-runner syntax …`** — final check | | **Task completion** | **`v8-runner syntax …`** — final verdict | -## Quality self-check (beyond syntax) +## Quality self-checking (besides syntax) -Syntax is the necessary minimum, but "it compiles" ≠ "it's good". Once `get_diagnostics`/`v8-runner syntax` -confirm there are no errors, run a self-check over the changed files — it is cheap (LSP, seconds) and -catches what syntax misses: +Syntax is the minimum required, but "compiles" does not mean "high quality". After +`get_diagnostics`/`v8-runner syntax` confirm there are no errors, run a self-check +on the modified files — it is cheap (LSP, seconds) and catches what syntax misses: -| Capability | What it shows | When to apply | -|------------|----------------|-----------------| -| `get_diagnostics` | All BSL LS diagnostics for the file (more precise than workspace checks) | After edits — full list of findings for the file | -| `get_quality_diagnostics` | Only security / performance / sql (query in a loop, disabling safe mode, missing aliases, etc.) | Before commit — targeted self-check by the coder for risks | -| `get_method_complexity` | Cyclomatic + cognitive complexity per method, flags threshold overruns | After writing/editing a method — a "time to refactor" signal (cyclomatic > 20 / cognitive > 15) | -| `get_module_health` | Combo: complexity + security/perf/sql merged per method and ranked "what to refactor first" | Triaging a whole module in one call — instead of separate complexity + quality_diagnostics + manual merge | +| Capability | What it shows | When to use | +|------------|----------------|----------------| +| `get_diagnostics` | All BSL LS diagnostics for the file (more precise than workspace checks) | After edits - the full list of findings for the file | +| `get_quality_diagnostics` | Only security / performance / sql (query in a loop, disabling safe mode, missing aliases, etc.) | Before commit - targeted coder self-check for risks | +| `get_method_complexity` | Cyclomatic + cognitive complexity by method, flags threshold breaches | After writing/editing a method - a signal that it is time to refactor (cyclomatic > 20 / cognitive > 15) | +| `get_module_health` | Combo: complexity + security/perf/sql, aggregated by method and ranked by "what to refactor first" | Triage of the whole module in one call - instead of separate complexity + quality_diagnostics + manual aggregation | -> This is a **coder's self-check**, not a replacement for review. `get_quality_diagnostics`, -> `get_method_complexity` and `get_module_health` rely on BSL LS; complexity metrics require the -> complexity CodeLens to be enabled in the BSL LS config. For a single method's metrics use -> `get_method_complexity`; for one risk category use `get_quality_diagnostics`; for whole-module -> triage use `get_module_health` (the standalone ones are not superseded). +> This is **coder self-checking**, not a replacement for review. `get_quality_diagnostics`, +> `get_method_complexity` and `get_module_health` rely on BSL LS; complexity metrics +> require the complexity CodeLens to be enabled in the BSL LS config. For metrics of one method, +> use `get_method_complexity`; for one risk category, use `get_quality_diagnostics`; for +> triage of the entire module, use `get_module_health` (the individual ones do not cancel each other out). -## Verification algorithm +## Checking algorithm -### Intermediate check (after every change) +### Intermediate check (after each change) 1. `get_diagnostics(uri)` — LSP diagnostics for the changed file. -2. If there is an `error` level — fix it and repeat. +2. If there is an `error`-level issue, fix it and repeat. 3. `warning` — assess criticality. ### Final check (before commit) -The command choice depends on `format`/`builder` in `v8project.yaml` (see `v8-runner/references/config-and-backends.md`): +The choice of command depends on `format`/`builder` in `v8project.yaml` (see `v8-runner/references/config-and-backends.md`): ```bash -# Designer-модули (требует Designer + Designer-формат) +# Designer modules (requires Designer + Designer format) v8-runner build v8-runner syntax designer-modules --server --thin-client -# Designer-конфигурация +# Designer configuration v8-runner build v8-runner syntax designer-config @@ -83,9 +83,9 @@ v8-runner syntax edt Tests (`v8-runner test yaxunit …`, `test va`) run `build` themselves — a separate `build` before them is not needed. -If `get_diagnostics` and `v8-runner syntax` disagree, rely on `v8-runner` as the final verdict. +If LSP and `v8-runner syntax` disagree, rely on v8-runner as the final verdict. -## Result interpretation +## Interpreting results | Field | Action | |------|----------| @@ -98,26 +98,26 @@ Severity: `error` (blocks compilation) > `warning` > `information` / `hint`. ## Suppression markers as evidence -Suppression comment is a clue, not decorative noise. Extract concrete codes from it and assess whether the suppression is justified. +A suppression comment is **evidence**, not decorative noise. From it, extract concrete codes and check whether disabling is justified. ### Marker syntax | Tool | Syntax | |------------|-----------| -| **АПК** | `//{ АПК:142 - comment` … `//}` | +| **APK** | `//{ APK:142 - comment` … `//}` | | **BSL Language Server** | `// BSLLS:LineLength-off` … `// BSLLS:LineLength-on` | | **EDT** | `// @suppress-warning("module-empty-method")` or `//@skip-check` | ### Interpretation method -1. **Extract the literal codes** from the comment: a numeric or mnemonic identifier (АПК:142, LineLength, EDT rule name). -2. **Resolve through the standards reference**: for АПК codes — `ask_1c_ai` ("decode the АПК:142 diagnostic"); for BSL LS — ITS documentation by rule name; for EDT — EDT rules documentation. -3. **Consider it justified** only with **triple corroboration**: literal code + suppression range + link to the standard. If at least one element is missing, mark it as "suppression not justified". -4. **Action priority**: first fix the code → then narrow the suppression range → leave suppression only as a last resort with an explicit link to the standard or platform limitation. +1. **Extract literal codes** from the comment: a numeric or mnemonic identifier (APK:142, LineLength, the EDT rule name). +2. **Resolve through the standards reference**: for APK codes — `ask_1c_ai` ("decode diagnostic APK:142"); for BSL LS — ITS documentation for the rule name; for EDT — EDT rules documentation. +3. **Mark as justified** only with **triple support**: literal code + suppression range + reference to the standard. If at least one element is missing, mark it as "suppression not justified". +4. **Action priority**: first fix the code -> then narrow the suppression range -> keep suppression only as a last resort with an explicit reference to the standard or a platform limitation. ### Sign of "suppression not justified" -The comment contains neither a diagnostic code nor a link to the standard — it must be flagged for review. +The comment contains neither the diagnostic code nor a reference to the standard — it must be flagged for review. ```bsl // Плохо — нет кода, нет обоснования: @@ -134,31 +134,31 @@ The comment contains neither a diagnostic code nor a link to the standard — it ## Capabilities and tools | Capability / CLI | Purpose | Cost | -|------------------|-----------|-----------| -| `get_diagnostics` (MCP `lsp-bsl-bridge`) | LSP diagnostics for a file | Fast — primary tool | -| `v8-runner syntax designer-modules` | Check Designer modules through the platform | Slow — final check only | +|------------------|------------|-----------| +| `get_diagnostics` (MCP `lsp-bsl-bridge`) | LSP diagnostics for a file | Fast - the main tool | +| `v8-runner syntax designer-modules` | Check Designer modules through the platform | Slow - final check only | | `v8-runner syntax designer-config` | Check Designer configuration | Slow | | `v8-runner syntax edt` | Check an EDT project | Slow | -## Monitoring the Final Check +## Final check result monitoring -`v8-runner syntax …` can take tens of seconds to minutes. For long runs use the Monitor tool: +`v8-runner syntax …` can take dozens of seconds to minutes. For long runs, use the Monitor tool: -1. Launch in the background (`Bash run_in_background: true`) and redirect stdout to a log file. -2. Subscribe via **Monitor** with the filter `ERROR:|error:|Errors:|success` — a notification arrives on the first match. -3. Stop waiting when the process exits OR stdout contains `error:` / `Errors: 0` / `success`. -4. After completion, read the result from stdout: if errors are present, note the file, line, and text. +1. Start it in the background (`Bash run_in_background: true`), redirect stdout to a log file. +2. Subscribe through **Monitor** with the filter `ERROR:|error:|Errors:|success` - you will get a notification on the first match. +3. End the wait when the process finishes OR `error:` / `Errors: 0` / `success` appears in stdout. +4. After completion, read the final result from stdout: if there are errors - file, line, text. -For short runs (`--source-set <NAME>`) Monitor is not required — synchronous execution is enough. +For short runs (`--source-set <NAME>`), Monitor is not required - a synchronous run is enough. -## Typical mistakes +## Typical errors | Error | Workaround | |--------|---------------| | LSP is not running | `v8-runner syntax …` as a fallback | | The `syntax …` command is not supported for the current `format`/`builder` | See `v8-runner/references/config-and-backends.md`; do not invent raw `1cv8`/`ibcmd` flags | -| Timeout on a full check | Narrow it with `--source-set <NAME>`; use LSP for specific modules | -| EDT project not found | Check `format`/`builder` and `source-set` in `v8project.yaml` | +| Timeout on the full check | Narrow it with `--source-set <NAME>`; LSP for specific modules | +| The EDT project is not found | Check `format`/`builder` and `source-set` in `v8project.yaml` | | Unclear `errors` | `navigate_symbol` to the error location; `ask_ai_assistant` | --- diff --git a/framework_eng/skills/tool-usage/content-generation/codex-image-gen/SKILL.md b/framework_eng/skills/tool-usage/content-generation/codex-image-gen/SKILL.md index 1fb2c98a..1d5666ec 100644 --- a/framework_eng/skills/tool-usage/content-generation/codex-image-gen/SKILL.md +++ b/framework_eng/skills/tool-usage/content-generation/codex-image-gen/SKILL.md @@ -1,6 +1,6 @@ --- name: codex-image-gen -description: "Use for generating and editing raster images (UI mockup, wireframe, illustration, diagram, icon, test fixture). Helps delegate image creation to Codex/GPT through `codex exec image_generation`, placing the result in `tasks/<id>/assets/`." +description: "Generate or edit images, mockups, diagrams, fixtures" capabilities: content-generation,image-generation,cross-provider,delegation --- diff --git a/framework_eng/skills/tool-usage/content-generation/docx-convert/SKILL.md b/framework_eng/skills/tool-usage/content-generation/docx-convert/SKILL.md index fe78d01c..be13ebc7 100644 --- a/framework_eng/skills/tool-usage/content-generation/docx-convert/SKILL.md +++ b/framework_eng/skills/tool-usage/content-generation/docx-convert/SKILL.md @@ -1,27 +1,27 @@ --- name: docx-convert -description: "Use for converting Word documents (.docx) to Markdown with extracted images (requirements, spec, instructions, vendor documentation). Helps obtain GFM text via pandoc with post-processing of HTML tables and image paths." +description: "Convert DOCX to Markdown with extracted images" capabilities: content-generation,document-conversion --- # Word → Markdown Conversion -A thin wrapper around `pandoc` for converting `.docx` to GitHub-Flavored Markdown with extraction of embedded images. It also post-processes the result: fixes image paths and turns HTML tables (which pandoc leaves as-is in complex cases) into Markdown pipe tables. +A thin wrapper around `pandoc` for converting `.docx` to GitHub-Flavored Markdown with extraction of embedded images. It also post-processes the result: fixes image paths and turns HTML tables (which pandoc leaves in their original form for complex cases) into pipe Markdown tables. ## When to use | Situation | Action | |----------|----------| -| The client sent requirements in `.docx`, and you need to put them in the repository as md | `docx2md.sh input.docx` | +| The client sent a spec in `.docx`, and you need to put it in the repository as md | `docx2md.sh input.docx` | | Vendor documentation is in Word, and you need to feed it to the agent | `docx2md.sh input.docx output_dir` | | The document has complex tables and styles — pandoc skips them | mammoth (see below) | -| You only need the text content without images | `pandoc input.docx --to=gfm -o out.md` directly | +| You only need the text part without images | `pandoc input.docx --to=gfm -o out.md` directly | ## When NOT to use -- You need HTML — use `pandoc --to=html`, the script is not needed. -- You need PDF — use `pandoc --to=pdf` (requires LaTeX), the script is not needed. -- The document was created with WordArt/SmartArt/shapes — these are lost during conversion, this is a limitation of pandoc. +- You need HTML — `pandoc --to=html`, the script is not required. +- You need PDF — `pandoc --to=pdf` (LaTeX is required), the script is not required. +- The document was created using WordArt/SmartArt/shapes — they are lost during conversion, this is a limitation of pandoc. ## Dependencies diff --git a/framework_eng/skills/tool-usage/diagnostics/agent-debug/SKILL.md b/framework_eng/skills/tool-usage/diagnostics/agent-debug/SKILL.md index 9c789f74..361b0b41 100644 --- a/framework_eng/skills/tool-usage/diagnostics/agent-debug/SKILL.md +++ b/framework_eng/skills/tool-usage/diagnostics/agent-debug/SKILL.md @@ -1,24 +1,24 @@ --- name: agent-debug -description: "MUST use WHEN standard diagnostics (event-log, screenshots) do not reveal the actual system behavior - you need to insert temporary logging points into code, run a test, and analyze the registration log entries. Provides a debug-block pattern with AGENTDEBUG markers and cleanup afterward." +description: "Trace BSL when event logs/screenshots do not explain failure" alwaysApply: false --- -# Debug messages (Agent Debug) +# Debug Messages (Agent Debug) -## When to use +## When to Use | Trigger | Action | -|---------|--------| -| Standard diagnostics do not reveal the behavior | Insert debug points | -| A hypothesis about the root cause needs confirmation/refutation | Log key values | -| It is unclear which branch of code is being executed | Place markers across branches | +|---------|----------| +| Standard diagnostics do not explain the behavior | Insert debug points | +| Hypothesis about the cause of the error needs confirmation/refutation | Log key values | +| It is unclear which code branch is executing | Place markers on branches | -**Do not use** if the answer can be obtained by reading the code, event-log, or a screenshot. +**DO NOT** use if the answer can be obtained by reading the code, event log, or a screenshot. --- -## Debug block format +## Debug Block Format ```bsl //[AGENTDEBUG-001] @@ -30,90 +30,90 @@ alwaysApply: false ///[AGENTDEBUG-001] ``` -### Marker rules +### Marker Rules - Opening: `//[AGENTDEBUG-NNN]` - Closing: `///[AGENTDEBUG-NNN]` (three slashes) -- NNN is the sequential point number (001, 002, ...) -- Between markers - **ONLY** debug code. No production code inside the block -- Nested blocks are forbidden +- NNN is the ordinal number of the point (001, 002, ...) +- Between markers there must be **ONLY** debugging code. No production code inside the block +- Nested blocks are prohibited ### Parameters for ЗаписьЖурналаРегистрации | Parameter | Value | Why | -|-----------|-------|-----| -| ИмяСобытия | `"AgentDebug"` | Filtering: all debug entries with one query | -| Уровень | `Информация` | Persisted reliably in the registration log (note may not be saved) | -| МетаданныеОбъекта | `Неопределено` or a specific object | If obvious, specify it for additional filtering | -| Данные | Reference to an object or `Неопределено` | For correlation with a specific document/element | +|----------|----------|-------| +| ИмяСобытия | `"AgentDebug"` | Filtering: all debug records with one query | +| Уровень | `Информация` | Reliably saved in the event log (Note may not be saved) | +| МетаданныеОбъекта | `Неопределено` or a specific object | If obvious, specify for additional filtering | +| Данные | Object reference or `Неопределено` | For correlation with a specific document/item | | Комментарий | `STEP=NNN PROC=... MSG=... \| key=value` | Structured format, easy to parse | -### Comment format +### Comment Format ``` -STEP=001 PROC=ОбработкаПроведения MSG=Brief description of the hypothesis | Key1=Value1 | Key2=Value2 +STEP=001 PROC=ОбработкаПроведения MSG=Краткое описание гипотезы | Ключ1=Значение1 | Ключ2=Значение2 ``` -- `STEP` is the point number (matches the marker) -- `PROC` is the name of the procedure/function -- `MSG` is what is being verified (the hypothesis) -- After `|` - key values in `key=value` format +- `STEP` — point number (matches the marker) +- `PROC` — procedure/function name +- `MSG` — what is being checked (hypothesis) +- After `|` — key values in `key=value` format - Do not log: large structures, value tables, binary data, passwords --- ## Procedure -1. **Formulate the hypothesis** - what exactly is being verified and why -2. **Identify points** - where in the code to insert logging (1-3 per hypothesis, max 5) +1. **Formulate the hypothesis** — what exactly we are checking and why +2. **Determine the points** — where to insert logging in the code (1-3 per hypothesis, max 5) 3. **Insert debug blocks** with markers `//[AGENTDEBUG-NNN]` ... `///[AGENTDEBUG-NNN]` -4. **Run the test** - unit test or Vanessa scenario -5. **Read the registration log** - filter by `ИмяСобытия = "AgentDebug"`, sort by time -6. **Draw the conclusion** - hypothesis confirmed or refuted +4. **Run the test** — unit test or Vanessa scenario +5. **Read the event log** — filter by `ИмяСобытия = "AgentDebug"`, sort by time +6. **Draw a conclusion** — hypothesis confirmed/refuted 7. **Remove ALL debug blocks** (see cleanup checklist) -If one iteration is not enough - adjust the points and repeat (steps 2-6). -If 10+ points are needed - the hypothesis is too broad; split it into several. +If one iteration is not enough, adjust the points and repeat (steps 2-6). +If you need 10+ points, the hypothesis is too broad; split it into several. --- -## Where to insert +## Where to Insert -Search order for a suitable place: +Order of finding a suitable place: -1. **Form module** - event handlers, ПриИзменении, ПередЗаписью -2. **Object module** - ОбработкаПроведения, ПередЗаписью, ПриЗаписи -3. **Manager module** - if the logic is in a manager -4. **Common modules** - if the call goes into a common module +1. **Form module** — event handlers, ПриИзменении, ПередЗаписью +2. **Object module** — ОбработкаПроведения, ПередЗаписью, ПриЗаписи +3. **Manager module** — if the logic is in the manager +4. **Common modules** — if the call goes into a common module -It is preferable to delegate code inspection to a subagent (Explorer / `code-navigation`). +It is preferable to delegate code inspection to a sub-agent (Explorer / `code-navigation`). --- -## Cleanup checklist +## Cleanup Checklist -**MUST** before finishing the task: +**MUST** before completing the task: -1. Search the code for `AGENTDEBUG` - no occurrences should remain -2. Check that only the lines between the markers were removed, and production code was not touched +1. Search in code: `AGENTDEBUG` — no occurrences should remain +2. Check that only the lines between markers were removed, production code was not affected 3. Check module syntax after removal -4. Make sure the marker comments are also removed (opening and closing) +4. Make sure marker comments are also removed (opening and closing) -**Line-by-line removal:** +**Remove line by line:** - Find the line with `//[AGENTDEBUG-NNN]` -- Delete all lines up to and including the matching `///[AGENTDEBUG-NNN]` -- If the matching marker is not found - **STOP**, report the error +- Remove all lines up to the matching `///[AGENTDEBUG-NNN]` inclusive +- If the matching marker is not found — **STOP**, report an error --- -## Anti-patterns +## Anti-Patterns | Anti-pattern | Consequence | -|--------------|-------------| -| Production code inside the debug block | Removing the block breaks business logic | -| Debug blocks left in the final code | Registration log pollution, data leakage | -| 10+ points for one hypothesis | The hypothesis is too broad; the result is unclear | -| Logging value tables / large structures | Registration log overflow, slowdown | +|-------------|-------------| +| Production code inside a debug block | Removing the block will break business logic | +| Debug blocks left in the final code | Event log clutter, data leakage | +| 10+ points for one hypothesis | Overly broad hypothesis, unclear result | +| Logging value tables / large structures | Event log overflow, slowdown | | Free text instead of key=value | Hard to parse during analysis | --- diff --git a/framework_eng/skills/tool-usage/diagnostics/bug-reporting/SKILL.md b/framework_eng/skills/tool-usage/diagnostics/bug-reporting/SKILL.md index c618b898..6db26a23 100644 --- a/framework_eng/skills/tool-usage/diagnostics/bug-reporting/SKILL.md +++ b/framework_eng/skills/tool-usage/diagnostics/bug-reporting/SKILL.md @@ -1,6 +1,6 @@ --- name: bug-reporting -description: "MUST use WHEN the subagent has exhausted its self-recovery limit and must hand the problem to the orchestrator for investigation. Provides the standard bug-report.json form and the criteria for \"this is a bug for the debugger\"." +description: "Escalate bugs after an agent self-recovery limit" alwaysApply: false --- diff --git a/framework_eng/skills/tool-usage/diagnostics/dap-bsl-code-debug-procedure/SKILL.md b/framework_eng/skills/tool-usage/diagnostics/dap-bsl-code-debug-procedure/SKILL.md index 928d2e52..7b6d5b28 100644 --- a/framework_eng/skills/tool-usage/diagnostics/dap-bsl-code-debug-procedure/SKILL.md +++ b/framework_eng/skills/tool-usage/diagnostics/dap-bsl-code-debug-procedure/SKILL.md @@ -1,6 +1,6 @@ --- name: dap-bsl-code-debug-procedure -description: "Use when you need to interactively debug a single BSL procedure through DAP/MCP: connect to the 1С debug server, set or remove a breakpoint, wait for the stop, inspect variables, execute step_in/step_out/continue, and cleanly tear down the debugging session." +description: "Interactively debug one BSL procedure through DAP" uses_capabilities: - debug_bsl_code --- diff --git a/framework_eng/skills/tool-usage/diagnostics/db-performance/SKILL.md b/framework_eng/skills/tool-usage/diagnostics/db-performance/SKILL.md index 555c5a26..2116b3c9 100644 --- a/framework_eng/skills/tool-usage/diagnostics/db-performance/SKILL.md +++ b/framework_eng/skills/tool-usage/diagnostics/db-performance/SKILL.md @@ -1,6 +1,6 @@ --- name: db-performance -description: "1С database and query performance diagnostics. Use when you need to diagnose a slow scenario, slow query, DBMS plan, locks, deadlock, TEMPDB/WAL, table sizes, or SCD on large data." +description: "Diagnose slow queries, locks, and DBMS plans" target_agents: - debugger - developer-code diff --git a/framework_eng/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md b/framework_eng/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md index dae29c09..b48e1d04 100644 --- a/framework_eng/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md +++ b/framework_eng/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md @@ -1,6 +1,6 @@ --- name: event-log-analysis -description: "Use for finding errors, events, and user actions in the registration log (RJ) via ClickHouse. Helps localize the time and context of a failure from the event log before turning to the tech log." +description: "Diagnose errors and user actions in the event log" uses_capabilities: - search_event_log - logc_get_actual_log_timestamp diff --git a/framework_eng/skills/tool-usage/diagnostics/runtime-investigation/SKILL.md b/framework_eng/skills/tool-usage/diagnostics/runtime-investigation/SKILL.md index 2a3cf68a..c2251bac 100644 --- a/framework_eng/skills/tool-usage/diagnostics/runtime-investigation/SKILL.md +++ b/framework_eng/skills/tool-usage/diagnostics/runtime-investigation/SKILL.md @@ -1,6 +1,6 @@ --- name: runtime-investigation -description: "Use for investigating bugs from bug-report: call graph + key variables -> DAP/agent-debug trace -> hypothesis cycle." +description: "Runtime bug diagnostics: call graph, DAP, tracing" --- # Runtime Investigation — runtime bug investigation @@ -325,6 +325,7 @@ Saved to `task_dir/.context/debug/<bug-id>/debug-report.md`. | Skipping verification after a local fix | False "fixed", while adjacent behavior actually broke | --- + depends_on: - framework/skills/tool-usage/diagnostics/bug-reporting/SKILL.md - framework/skills/tool-usage/diagnostics/dap-bsl-code-debug-procedure/SKILL.md diff --git a/framework_eng/skills/tool-usage/diagnostics/tech-log-analysis/SKILL.md b/framework_eng/skills/tool-usage/diagnostics/tech-log-analysis/SKILL.md index 4e3a69bf..6a2013c8 100644 --- a/framework_eng/skills/tool-usage/diagnostics/tech-log-analysis/SKILL.md +++ b/framework_eng/skills/tool-usage/diagnostics/tech-log-analysis/SKILL.md @@ -1,6 +1,6 @@ --- name: tech-log-analysis -description: "Use for managing the lifecycle of the 1C technological log (Tech Log): configuration, enablement, collection, analysis, restoration. Helps diagnose slow queries, locks, and platform exceptions not available in the Event Log." +description: "Analyze 1C tech log: EXCP, SQL, locks, collection" uses_capabilities: - search_tech_log - configure_tech_log diff --git a/framework_eng/skills/tool-usage/platform-admin/rac-use/SKILL.md b/framework_eng/skills/tool-usage/platform-admin/rac-use/SKILL.md index c081f9be..560d50a6 100644 --- a/framework_eng/skills/tool-usage/platform-admin/rac-use/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-admin/rac-use/SKILL.md @@ -1,9 +1,9 @@ --- name: rac-use -description: "1С server cluster administration through the RAC utility — viewing/terminating sessions, managing locks, connections, infobases, and other cluster objects." +description: "Admin RAC: sessions, locks, connections, infobases" --- -# RAC — 1С cluster administration utility +# RAC — cluster administration utility for 1C ## When to use @@ -11,10 +11,10 @@ description: "1С server cluster administration through the RAC utility — view |---------|----------| | Need to check/kill sessions in a database | `session list` / `session terminate` | | Need to disconnect connections | `connection list` / `connection disconnect` | -| Need to block login to the database | `infobase update --sessions-deny=on` | -| Need to prohibit scheduled jobs | `infobase update --scheduled-jobs-deny=on` | +| Need to block access to a database | `infobase update --sessions-deny=on` | +| Need to disable scheduled jobs | `infobase update --scheduled-jobs-deny=on` | | Need to view locks | `lock list` | -| Need information about the cluster/databases | `cluster list` / `infobase summary list` | +| Need cluster/database information | `cluster list` / `infobase summary list` | --- @@ -22,13 +22,13 @@ description: "1С server cluster administration through the RAC utility — view **Binary:** `/opt/1cv8/current/rac` (always the current version). -**Connection data:** `<project_root>/configs/yaxunit-runner.yml`, section `app.connection` — server, database, login, password. +**Connection data:** `<project_root>/configs/yaxunit-runner.yml`, `app.connection` section - server, database, login, password. -**Cluster agent address:** by default `localhost:1545`. If the server differs — specify explicitly as the last argument: `rac <command> <host>:<port>`. +**Cluster agent address:** by default `localhost:1545`. If the server differs, specify it explicitly as the last argument: `rac <command> <host>:<port>`. --- -## First step — get the cluster UUID +## First step - get the cluster UUID All commands require `--cluster=<uuid>`. Get it first: @@ -36,31 +36,31 @@ All commands require `--cluster=<uuid>`. Get it first: /opt/1cv8/current/rac cluster list ``` -The output contains `cluster : <uuid>` — save it and use it later. +The output contains `cluster : <uuid>` - remember it and use it later. --- ## Main scenarios -### Viewing database sessions +### View database sessions ```bash # Find the database UUID /opt/1cv8/current/rac infobase --cluster=<cluster_uuid> summary list -# List the database sessions +# List database sessions /opt/1cv8/current/rac session --cluster=<cluster_uuid> list --infobase=<infobase_uuid> ``` -### Forcefully terminate a session +### Force terminate a session ```bash /opt/1cv8/current/rac session --cluster=<cluster_uuid> terminate \ --session=<session_uuid> \ - --error-message="The session was terminated by the agent to complete the task" + --error-message="Сеанс завершён агентом для выполнения задачи" ``` -### Blocking login to the database +### Block access to a database ```bash # Enable blocking @@ -68,39 +68,39 @@ The output contains `cluster : <uuid>` — save it and use it later. --infobase=<infobase_uuid> \ --infobase-user=<user> --infobase-pwd=<pwd> \ --sessions-deny=on \ - --denied-message="The database is blocked for maintenance" \ + --denied-message="База заблокирована для обслуживания" \ --permission-code="secret123" -# Remove blocking +# Remove the block /opt/1cv8/current/rac infobase --cluster=<cluster_uuid> update \ --infobase=<infobase_uuid> \ --infobase-user=<user> --infobase-pwd=<pwd> \ --sessions-deny=off ``` -### Managing scheduled jobs +### Manage scheduled jobs ```bash -# Prohibit +# Disable /opt/1cv8/current/rac infobase --cluster=<cluster_uuid> update \ --infobase=<infobase_uuid> \ --infobase-user=<user> --infobase-pwd=<pwd> \ --scheduled-jobs-deny=on -# Allow +# Enable /opt/1cv8/current/rac infobase --cluster=<cluster_uuid> update \ --infobase=<infobase_uuid> \ --infobase-user=<user> --infobase-pwd=<pwd> \ --scheduled-jobs-deny=off ``` -### Viewing locks +### View locks ```bash /opt/1cv8/current/rac lock --cluster=<cluster_uuid> list --infobase=<infobase_uuid> ``` -### Viewing and disconnecting connections +### View and disconnect connections ```bash # List database connections @@ -118,8 +118,8 @@ The output contains `cluster : <uuid>` — save it and use it later. | Mode | Purpose | |-------|-----------| | `cluster` | Clusters: list, create, delete, administrators | -| `infobase` | Infobases: create, update, delete, session/scheduled job blocking | -| `session` | Sessions: list, information, forceful termination | +| `infobase` | Infobases: create, update, delete, session/scheduled-job blocking | +| `session` | Sessions: list, information, forced termination | | `connection` | Connections: list, disconnect | | `lock` | Locks: view | | `process` | Worker processes | @@ -136,14 +136,14 @@ Help for any mode: `rac help <mode>`. --- -## Typical errors +## Common errors | Error | Cause | Solution | |--------|---------|---------| -| `Cluster agent unavailable` | `ragent` is not running or the address is incorrect | Check `localhost:1545` or specify the correct address | -| `Invalid cluster identifier` | The UUID was copied incorrectly | Repeat `cluster list` | -| `Insufficient permissions` | Cluster administrator credentials are required | Add `--cluster-user` / `--cluster-pwd` | -| `Infobase not found` | Incorrect database UUID | Check via `infobase summary list` | +| `Агент кластера недоступен` | `ragent` is not running or the address is incorrect | Check `localhost:1545` or specify the correct address | +| `Неверный идентификатор кластера` | The UUID was copied incorrectly | Run `cluster list` again | +| `Недостаточно прав` | Cluster administrator credentials are required | Add `--cluster-user` / `--cluster-pwd` | +| `Информационная база не найдена` | Incorrect database UUID | Verify it via `infobase summary list` | --- depends_on: [] diff --git a/framework_eng/skills/tool-usage/platform-admin/subsystem-update/SKILL.md b/framework_eng/skills/tool-usage/platform-admin/subsystem-update/SKILL.md index 7b946a99..4e70e9dd 100644 --- a/framework_eng/skills/tool-usage/platform-admin/subsystem-update/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-admin/subsystem-update/SKILL.md @@ -1,6 +1,6 @@ --- name: subsystem-update -description: "Use for initializing БСП subsystem updates: session locking, launching update handlers, checking via the event log and the ВерсииПодсистем register." +description: "Run and verify BSP subsystem updates" --- # Updating the БСП Subsystem @@ -15,11 +15,11 @@ description: "Use for initializing БСП subsystem updates: session locking, la --- -## Preconditions +## Prerequisites 1. The handler is registered in the subsystem update module (for example `ОбновлениеИнформационнойБазыXXX`) 2. The subsystem module is registered in `ИнтеграцияПодсистемБСП.ПриДобавленииПодсистем` -3. The project is built (`v8-runner build`) - code changes are loaded into the infobase +3. The project is built (`v8-runner build`) - changes in code are loaded into the infobase --- @@ -33,7 +33,7 @@ description: "Use for initializing БСП subsystem updates: session locking, la ГДЕ ИмяПодсистемы = "ИМЯ_ПОДСИСТЕМЫ" ``` -БСП will run the handler only if the version in the register is **<** the handler version. +БСП will execute the handler only if the version in the register is **<** the handler version. ### Step 2. Lock the Infobase diff --git a/framework_eng/skills/tool-usage/platform-data/platform-data-core/SKILL.md b/framework_eng/skills/tool-usage/platform-data/platform-data-core/SKILL.md index 722f34dd..325cb7b1 100644 --- a/framework_eng/skills/tool-usage/platform-data/platform-data-core/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/platform-data-core/SKILL.md @@ -1,6 +1,6 @@ --- name: platform-data-core -description: "Working with 1C platform data (Platform Data Core). The skill combines three operations: searching and analyzing configuration metadata, parsing navigation links, and executing database queries." +description: "Platform data: metadata, nav links, safe queries" uses_capabilities: - list_metadata_objects - get_metadata_structure diff --git a/framework_eng/skills/tool-usage/platform-data/xml-generation/SKILL.md b/framework_eng/skills/tool-usage/platform-data/xml-generation/SKILL.md index 07b1b181..a19df68c 100644 --- a/framework_eng/skills/tool-usage/platform-data/xml-generation/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/xml-generation/SKILL.md @@ -1,6 +1,6 @@ --- name: xml-generation -description: "MUST use WHEN you need to create, modify, or validate any 1C metadata XML (forms, roles, objects, MXL, SKD, EPF, extensions, configuration). Provides safe generation and targeted modification through the xml-gen CLI, following the no-manual-xml-edit rule." +description: "Use for any 1C metadata XML through xml-gen CLI" argument-hint: <domain> <operation> [<args>] allowed-tools: - Bash diff --git a/framework_eng/skills/tool-usage/platform-data/xml-generation/config-operations/SKILL.md b/framework_eng/skills/tool-usage/platform-data/xml-generation/config-operations/SKILL.md index e9c84c27..eb53e846 100644 --- a/framework_eng/skills/tool-usage/platform-data/xml-generation/config-operations/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/xml-generation/config-operations/SKILL.md @@ -1,6 +1,6 @@ --- name: config-operations -description: "Use for creating a configuration, analyzing and changing its properties and ChildObjects, and validating Configuration.xml. Helps manage the composition and parameters of Configuration.xml through xml-gen config." +description: "xml-gen Configuration.xml: properties and ChildObjects" --- # Config Operations diff --git a/framework_eng/skills/tool-usage/platform-data/xml-generation/epf-full/SKILL.md b/framework_eng/skills/tool-usage/platform-data/xml-generation/epf-full/SKILL.md index 6c77e82e..397cdcca 100644 --- a/framework_eng/skills/tool-usage/platform-data/xml-generation/epf-full/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/xml-generation/epf-full/SKILL.md @@ -1,6 +1,6 @@ --- name: epf-full -description: "Use for creating external processors and reports (EPF/ERF), adding forms, templates, and help, and connecting to the BSP subsystem «Additional Reports and Processors». Helps go through the full init→add-form→template→BSP registration cycle via xml-gen." +description: "xml-gen EPF/ERF external reports and processors" targets: - developer-code - architect diff --git a/framework_eng/skills/tool-usage/platform-data/xml-generation/extension-operations/SKILL.md b/framework_eng/skills/tool-usage/platform-data/xml-generation/extension-operations/SKILL.md index 743972f0..3cba64f4 100644 --- a/framework_eng/skills/tool-usage/platform-data/xml-generation/extension-operations/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/xml-generation/extension-operations/SKILL.md @@ -1,6 +1,6 @@ --- name: extension-operations -description: "Operations with 1C configuration extensions (CFE) - init, borrowing objects, generating method interceptors, and analyzing extension composition. Helps manage CFE via xml-gen extension init/borrow/diff/validate." +description: "xml-gen CFE: init, borrow, interceptors, validate" --- # Extension Operations (CFE) diff --git a/framework_eng/skills/tool-usage/platform-data/xml-generation/form-dsl/SKILL.md b/framework_eng/skills/tool-usage/platform-data/xml-generation/form-dsl/SKILL.md index eff22f8d..937c4512 100644 --- a/framework_eng/skills/tool-usage/platform-data/xml-generation/form-dsl/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/xml-generation/form-dsl/SKILL.md @@ -1,6 +1,6 @@ --- name: form-dsl -description: "Use for generating 1C managed forms with UI elements, attributes, and commands through a JSON DSL. Helps describe the form structure and static properties for xml-gen form compile/edit." +description: "xml-gen managed form DSL: compile/edit" --- # Form DSL diff --git a/framework_eng/skills/tool-usage/platform-data/xml-generation/forms-toolkit/SKILL.md b/framework_eng/skills/tool-usage/platform-data/xml-generation/forms-toolkit/SKILL.md index bdce015c..0d8fcdbb 100644 --- a/framework_eng/skills/tool-usage/platform-data/xml-generation/forms-toolkit/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/xml-generation/forms-toolkit/SKILL.md @@ -1,6 +1,6 @@ --- name: forms-toolkit -description: "Use for analyzing form structure, adding elements, validating, and mapping Title→Name for Vanessa scenarios. Helps work with Form.xml and EPF/ERF through xml-gen form-info/form-edit/form-validate/form-element-mapping/epf-validate." +description: "xml-gen forms: info, edit, validate, mapping" argument-hint: <operation> <FormPath> [<JsonPath>] allowed-tools: - Bash @@ -15,13 +15,13 @@ depends_on: # forms-toolkit — Working with forms and EPF/ERF -## §1 Form workflow lifecycle +## §1 Form lifecycle ``` form-info → form-edit → form-validate → form-info -form-decompile → form-compile — only to scaffold a new form from a sample -epf-validate — for EPF/ERF -form-element-mapping — Title→Name mapping for Vanessa scenarios +form-decompile → form-compile — только для scaffold новой формы по образцу +epf-validate — для EPF/ERF +form-element-mapping — маппинг Title→Name для Vanessa-сценариев ``` ## §2 When to use @@ -29,13 +29,13 @@ form-element-mapping — Title→Name mapping for Vanessa scenarios | Trigger | Operation | Reference | |---------|----------|-----------| | Understand form structure | `form-info` | [references/info.md](references/info.md) | -| Get a draft JSON for a new form from a sample | `form-decompile` | draft, not lossless | +| Get a JSON draft of a new form by example | `form-decompile` | draft, not lossless | | Add a field / attribute / command | `form-edit` | [references/edit.md](references/edit.md) | -| Check Form.xml after changes | `form-validate` | [references/validate.md](references/validate.md) | +| Validate Form.xml after changes | `form-validate` | [references/validate.md](references/validate.md) | | Writing Vanessa steps (Title→Name) | `form-element-mapping` | [references/element-mapping.md](references/element-mapping.md) | -| Validate EPF / ERF | `epf-validate` | [references/validate.md](references/validate.md) (EPF section) | +| EPF / ERF validation | `epf-validate` | [references/validate.md](references/validate.md) (EPF section) | -## §3 Short operation index +## §3 Quick operation index | Operation | Command | Key parameters | |----------|---------|-------------------| @@ -49,22 +49,22 @@ form-element-mapping — Title→Name mapping for Vanessa scenarios ## §4 Quick example ```bash -# 1. Examine the structure +# 1. Изучить структуру xml-gen form info "src/Catalogs/Контрагенты/Forms/ФормаЭлемента/Ext/Form.xml" -# 2. Apply changes (spec.json with elements/attributes) +# 2. Применить изменения (spec.json с elements/attributes) xml-gen form edit "src/.../Form.xml" --json "spec.json" -# 3. Verify the result +# 3. Проверить результат xml-gen validate --type form "src/.../Form.xml" -# Scaffold a new form from a sample +# Scaffold новой формы по образцу xml-gen form decompile "src/.../Form.xml" draft-form.json -# EPF validation +# Валидация EPF xml-gen validate --type epf "src/МояОбработка/" -# Find the programmatic name by the title (for Vanessa) +# Найти программное имя по заголовку (для Vanessa) grep -B5 "Контрагент" path/to/Form.xml | grep "<Name>" ``` @@ -72,6 +72,6 @@ grep -B5 "Контрагент" path/to/Form.xml | grep "<Name>" Details for each operation: - [references/info.md](references/info.md) — detailed form-info output, pagination, type abbreviations -- [references/edit.md](references/edit.md) — JSON format, element types, attribute type system, events -- [references/validate.md](references/validate.md) — checklist for form-validate and epf-validate, error codes, DataPath resolution +- [references/edit.md](references/edit.md) — JSON format, element types, requisite type system, events +- [references/validate.md](references/validate.md) — checklist of form-validate and epf-validate checks, error codes, DataPath resolution - [references/element-mapping.md](references/element-mapping.md) — Title→Name algorithm (4 steps), pitfalls, value format diff --git a/framework_eng/skills/tool-usage/platform-data/xml-generation/meta-operations/SKILL.md b/framework_eng/skills/tool-usage/platform-data/xml-generation/meta-operations/SKILL.md index 5df75be2..a6e61e5d 100644 --- a/framework_eng/skills/tool-usage/platform-data/xml-generation/meta-operations/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/xml-generation/meta-operations/SKILL.md @@ -1,6 +1,6 @@ --- name: meta-operations -description: "Use for creating and editing 1С metadata objects (23 types: catalogs, documents, registers, enumerations, etc.) via xml-gen meta. Helps add attributes, tabular sections, dimensions, and validate configuration objects." +description: "xml-gen metadata: objects, attributes, tabular parts" --- # Meta Operations @@ -54,7 +54,7 @@ xml-gen meta compile <meta.json> <output_dir> **Full Catalog properties:** `hierarchical`, `hierarchyType` (HierarchyFoldersAndItems|HierarchyItemsOnly), `limitLevelCount`, `levelCount`, `foldersOnTop`, `codeLength`, `codeType` (String|Number), `codeAllowedLength` (Variable|Fixed), `codeSeries` (WholeCatalog|WithinOwnerSubordination|WithinSubordination), `descriptionLength`, `autonumbering`, `checkUnique`, `defaultPresentation` (AsDescription|AsCode), `subordinationUse` (ToItems|ToFolders|ToFoldersAndItems), `quickChoice`, `choiceMode` (BothWays|FromChoiceForm|QuickChoice), `editType` (InDialog|InList|BothWays), `owners` (array of strings, e.g. `["Catalog.Counterparties"]`). -**Attribute flag `multiLine`** - makes a string field multiline (`<MultiLine>true</MultiLine>`). In shorthand: `"Описание: String(500) | multiline"`. +**Attribute flag `multiLine`** - makes a string field multiline (`<MultiLine>true</MultiLine>`). In shorthand: `"Description: String(500) | multiline"`. ### meta info @@ -137,7 +137,7 @@ xml-gen meta edit <objectPath> --batch patch.json xml-gen meta edit --batch multi-patch.json ``` -Use this when: multiple operations of different types need to be applied to one object in a single call, the agent is generating patches, reproducible schema migrations. +Use when: several operations of different types need to be applied to a single object in one call, the agent is generating patches, or schema migrations need to be reproducible. **Inline batch via `;;`:** ```bash diff --git a/framework_eng/skills/tool-usage/platform-data/xml-generation/mxl-dsl/SKILL.md b/framework_eng/skills/tool-usage/platform-data/xml-generation/mxl-dsl/SKILL.md index befee5b0..ffacaa97 100644 --- a/framework_eng/skills/tool-usage/platform-data/xml-generation/mxl-dsl/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/xml-generation/mxl-dsl/SKILL.md @@ -1,11 +1,11 @@ --- name: mxl-dsl -description: "Use for generating and refining 1С print forms (MXL) through JSON DSL. Helps describe areas, cells, and static styles for xml-gen mxl compile/decompile/info/validate." +description: "xml-gen MXL print forms: compile/edit/info" --- # MXL DSL -Compact JSON format for describing 1С tabular documents (SpreadsheetDocument). Claude describes **what** (areas, cells, styles, parameters), while the CLI guarantees XML **correctness** (palettes, indices, merges, namespace). +Compact JSON format for describing 1C tabular documents (SpreadsheetDocument). Claude describes **what** (areas, cells, styles, parameters), while the CLI ensures XML **correctness** (palettes, indices, merges, namespace). The canon is taken from Shirokov's specification (cc-1c-skills) and extended with the `--format designer|edt` flag for two output formats. @@ -15,14 +15,13 @@ The canon is taken from Shirokov's specification (cc-1c-skills) and extended wit |---------|----------| | Create a print form from scratch | `mxl compile` + JSON DSL → `references/dsl-spec.md` | | Refine an existing layout | `mxl decompile` → edit JSON → `mxl compile` | -| Validate MXL tool behavior against canon XML | `xml-gen oracle mxl --mode dsl|cli|both` | | Understand the structure of someone else's layout (areas, parameters, drill-downs) | `mxl info` → `references/info-modes.md` | | Check the correctness of the assembled Template.xml | `xml-gen validate --type mxl` → `references/validate-classes.md` | -| Reverse-engineer print output from a sample (screenshot/scan) | `mxl decompile` or build from scratch on a grid — define `page` + `"Nx"` widths | +| Reverse-engineer print output from a sample (screenshot/scan) | `mxl decompile` or build from scratch on a grid — set `page` + `"Nx"` widths | -## Intentionally outside the DSL - do it in code +## Intentionally outside the DSL — do it in code -The DSL covers **static** cell formatting — `font/align/valign/border/wrap/format` through the `styles` map. It intentionally does NOT generate **runtime-conditional** formatting: cell coloring/styling based on the displayed value. This is done programmatically when filling the tabular document — `Область.ТекстЦвет = …`, `Область.ЦветФона = …` on the populated area. The absence is a **design choice**, not a tool defect; see rule `no-manual-xml-edit.md` § "What is done in code, and NOT through xml-gen". +The DSL covers **static** cell formatting — `font/align/valign/border/wrap/format` through the map of `styles`. It intentionally does NOT generate **runtime-conditional** formatting: cell coloring/styling depending on the displayed value. This is done programmatically when filling the tabular document — `Область.ТекстЦвет = …`, `Область.ЦветФона = …` on the populated area. The absence is a **design choice**, not a tool defect; see rule `no-manual-xml-edit.md` § "What is done in code, and NOT through xml-gen". ## Commands @@ -38,9 +37,6 @@ xml-gen mxl info <Template.xml> [--with-text] [--limit N] [--offset N] [--format # Валидация xml-gen validate --type mxl <Template.xml> [--detailed] [--max-errors N] - -# Поведенческий оракул по реальному канону -xml-gen oracle mxl --source <Template.xml|src/xml> --out build/oracle --mode dsl|cli|both [--include-all] ``` **`output.xml`** for compile is the path to the layout in EPF/ERF: `.../Templates/<Name>/Ext/Template.xml`. @@ -116,17 +112,6 @@ For **intersections** (Rows area + Columns area, for example labels/price tags), - If all empty cells in a row have the same style, it is collapsed into `rowStyle`, and the empty cells are removed from the output. - Template parameters (`[Name]` in text) are extracted into separate `template` cells. -## Oracle modes - -`xml-gen oracle mxl` validates two independent modes: - -- `--mode dsl` decompiles canon `Template.xml` to JSON DSL, compiles a new sandbox `Template.xml`, and compares it with the canon. The canon file is never overwritten. -- `--mode cli` decompiles canon into a `CommandPlan` of public commands: `epf init`, `epf add-template --type SpreadsheetDocument`, `mxl compile`, `validate`. The result inside the temporary EPF sandbox is compared with the canon separately from DSL mode. -- `--mode both` runs both and reports separate `dsl` and `cli` summaries. -- With a `src/xml` source, the default corpus is the `_Демо` pilot. Use `--include-all` only for a broad audit of all MXL `Template.xml` files. - -Use oracle for regression detection and coverage reports. Use normal `mxl compile/decompile/info/validate` for day-to-day generation and editing. - ## Workflow (typical) 1. (optional) If the layout is created from an image - overlay a grid, determine column proportions → set `page: "A4-landscape"` + `"Nx"` widths. @@ -135,7 +120,6 @@ Use oracle for regression detection and coverage reports. Use normal `mxl compil 4. `xml-gen validate --type mxl` → if there are errors, see `references/validate-classes.md`. 5. `mxl info` → inspect the structure of areas and parameters with the agent's eyes. 6. (for refining someone else's layout) `mxl decompile` → edit → compile. -7. (for validating tool behavior) `xml-gen oracle mxl --source src/xml --out build/oracle --mode both`. ## Correct / Incorrect diff --git a/framework_eng/skills/tool-usage/platform-data/xml-generation/role-dsl/SKILL.md b/framework_eng/skills/tool-usage/platform-data/xml-generation/role-dsl/SKILL.md index 239ef812..47c532fa 100644 --- a/framework_eng/skills/tool-usage/platform-data/xml-generation/role-dsl/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/xml-generation/role-dsl/SKILL.md @@ -1,6 +1,6 @@ --- name: role-dsl -description: "JSON DSL for generating 1С roles with access rights to metadata objects. Use it for role compile and when editing Rights.xml through xml-generation (edit commands)." +description: "xml-gen roles DSL and Rights.xml editing" --- # Role DSL diff --git a/framework_eng/skills/tool-usage/platform-data/xml-generation/skd-dsl/SKILL.md b/framework_eng/skills/tool-usage/platform-data/xml-generation/skd-dsl/SKILL.md index 34770530..3ae9a264 100644 --- a/framework_eng/skills/tool-usage/platform-data/xml-generation/skd-dsl/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/xml-generation/skd-dsl/SKILL.md @@ -1,6 +1,6 @@ --- name: skd-dsl -description: "Use for generating 1C data composition schemas (SKD) from scratch via JSON DSL: datasets, calculated fields, output templates, variants, conditional formatting. Helps build Schema.xml through xml-gen skd compile/info/validate." +description: "xml-gen SKD schemas from JSON DSL" --- # SKD DSL @@ -261,6 +261,17 @@ Workflow: `overview` → `trace --name <field>` → `query --name <dataset>` → `"filter": ["Amount greater than 0"]` - **incorrect**: the parser accepts operators strictly from the fixed set (`=`, `<>`, `>`, `>=`, `<`, `<=`, `in`, `notIn`, `contains`, `filled`, `notFilled`, `InHierarchy`). `greater` is not recognized. +Fields in `selection`/`order`/`filter`/`structure` must exist in `dataSets` or `calculatedFields` - otherwise the SKD will not compile. + +**Verification after compile:** `xml-gen validate --type skd <output.xml>` → `xml-gen skd info <output.xml>` → if needed `skd info --mode trace --name <field>`. + +## See also + +- [references/templates-dsl.md](references/templates-dsl.md) - templates, drilldown, styles. +- [references/info-modes.md](references/info-modes.md) - 11 `skd info` modes with output examples. +- [xml-generation](../SKILL.md) - `skd add-parameter`, `skd add-field`, replace-text. +- [mxl-dsl](../mxl-dsl/) - print forms. + --- depends_on: [] metadata: diff --git a/framework_eng/skills/tool-usage/platform-data/xml-generation/skd-edit/SKILL.md b/framework_eng/skills/tool-usage/platform-data/xml-generation/skd-edit/SKILL.md index 4ef43eb3..35e5f6a8 100644 --- a/framework_eng/skills/tool-usage/platform-data/xml-generation/skd-edit/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/xml-generation/skd-edit/SKILL.md @@ -1,9 +1,9 @@ --- name: skd-edit -description: "Use for atomic editing of an existing Schema.xml SKD: add/remove fields, totals, parameters, rewrite a data set query, or change the variant structure. Helps fine-tune SKD without full recompilation via xml-gen skd edit." +description: "xml-gen atomic edits of existing SKD Schema.xml" --- -# SKD Edit - targeted editing of Schema.xml +# SKD Edit — targeted editing of Schema.xml ## When to use diff --git a/framework_eng/skills/tool-usage/platform-data/xml-generation/subsystem-interface/SKILL.md b/framework_eng/skills/tool-usage/platform-data/xml-generation/subsystem-interface/SKILL.md index 35d9d471..41e205dc 100644 --- a/framework_eng/skills/tool-usage/platform-data/xml-generation/subsystem-interface/SKILL.md +++ b/framework_eng/skills/tool-usage/platform-data/xml-generation/subsystem-interface/SKILL.md @@ -1,6 +1,6 @@ --- name: subsystem-interface -description: "Use for creating subsystems, managing their composition, and configuring CommandInterface.xml (visibility, command order, placement in groups). Helps maintain configuration navigation through xml-gen subsystem/interface compile/edit/validate." +description: "xml-gen subsystems and CommandInterface.xml" --- # Subsystem + Interface Operations @@ -9,11 +9,11 @@ description: "Use for creating subsystems, managing their composition, and confi | Trigger | Action | |---------|----------| -| Need to create a subsystem | `subsystem compile subsystem.json <output_dir>` | -| Need to view subsystem contents | `subsystem info <subsystemPath>` | -| Need to add an object to a subsystem | `subsystem edit <path> --op add-content --value "Catalog.Товары"` | -| Need to validate a subsystem | `subsystem validate <subsystemPath>` | -| Need to view the subsystem tree | `subsystem info --mode tree <subsystemPath>` | +| Create a subsystem from JSON | `subsystem compile subsystem.json <output_dir>` | +| View subsystem contents | `subsystem info <subsystemPath>` | +| Add an object to a subsystem | `subsystem edit <path> --op add-content --value "Catalog.Товары"` | +| Validate a subsystem | `subsystem validate <subsystemPath>` | +| View the subsystem tree | `subsystem info --mode tree <subsystemPath>` | | Hide/show a command | `xml-gen interface edit … --op hide/show` | | Place a command in a group | `xml-gen interface edit … --op place` | | Set the order of commands/subsystems/groups | `xml-gen interface edit … --op set-order/set-subsystem-order/set-group-order` | diff --git a/framework_eng/skills/tool-usage/review/cross-provider-review/SKILL.md b/framework_eng/skills/tool-usage/review/cross-provider-review/SKILL.md index 5a470638..ddf43aca 100644 --- a/framework_eng/skills/tool-usage/review/cross-provider-review/SKILL.md +++ b/framework_eng/skills/tool-usage/review/cross-provider-review/SKILL.md @@ -1,6 +1,6 @@ --- name: cross-provider-review -description: "Use for advisory second-opinion review between model families. Routes GPT/Codex primary agents to Claude/Opus review and vice versa; supports sandbox sessions, follow-up, debate, sync, status, log, stats, show, and close lifecycle." +description: "Second-opinion model review and debate sessions" capabilities: review,agent-governance,cross-provider --- @@ -9,9 +9,9 @@ capabilities: review,agent-governance,cross-provider A single skill for cross-family second opinion. The reviewer is an advisory layer, not the final authority, and must not edit the real project. -AI governance classification: `advice-only`. Owner: orchestrator/primary agent. HITL is required where workflow, -product, or architectural approval gates require it. Quality signal: evidence-backed findings, a clear primary-agent -position, review trace, and observable lifecycle/cleanup. +AI governance classification: `advice-only`. Owner: orchestrator/primary agent. HITL is required where workflow, product, +or architectural approval gates require it. Quality signal: evidence-backed findings, a clear primary-agent position, +review trace, and observable lifecycle/cleanup. ## Routing @@ -25,21 +25,31 @@ position, review trace, and observable lifecycle/cleanup. The skill works in two modes with different verdict semantics: -- **advisory** (default) - per-artifact review within a phase. The final word belongs to the primary agent/orchestrator; the reviewer provides a second opinion that is handled as regular feedback. All per-artifact workflow runs are advisory. -- **gate** - final review before task closure. The reviewer verdict is blocking: `verdict: PASS` is a mandatory condition for completion. This mode is used by the orchestrator exactly once at the end of the task, instead of an advisory final. +- **advisory** (default) - per-artifact review within a phase. The final word belongs to the primary agent/orchestrator; + the reviewer provides a second opinion that is handled as regular feedback. All per-artifact workflow runs are + advisory. +- **gate** - final review before task closure. The reviewer verdict is blocking: `verdict: PASS` is a mandatory + condition for completion. This mode is used by the orchestrator exactly once at the end of the task, instead of an + advisory final. -The mode is fixed in the introductory prompt (via `--constraints` / `--review-ask`) - the reviewer must explicitly know whether the verdict is blocking or advisory. +The mode is fixed in the introductory prompt (via `--constraints` / `--review-ask`) - the reviewer must explicitly know +whether the verdict is blocking or advisory. ## Prompts -- `references/review-prompt.md` - default shape for advisory review (task artifacts and acceptance-bound reviews). Can be used in a simplified form for free-form opinion review / idea critique, as long as the read-only and evidence boundaries are explicit. -- `references/finalization-prompt.md` - template for **gate** mode (task finalization). Includes a strict structure: bidirectional rule compliance check, goal verification with a traceability table, anti-deception checklist, and an iterative protocol with escalation to the user after 3 rounds. +- `references/review-prompt.md` - default shape for advisory review (task artifacts and acceptance-bound reviews). Can + be used in a simplified form for free-form opinion review / idea critique, as long as the read-only and evidence + boundaries are explicit. +- `references/finalization-prompt.md` - template for **gate** mode (task finalization). Includes a strict structure: + bidirectional rule compliance check, goal verification with a traceability table, anti-deception checklist, and an + iterative protocol with escalation to the user after 3 rounds. ## Session Lifecycle Both adapters support the same lifecycle: -- `start`: creates `.review-sandboxes/<review_id>/workspace`, materializes focused paths or full context (by default via hardlink - almost instant and with no disk usage) and launches the reviewer. +- `start`: creates `.review-sandboxes/<review_id>/workspace`, materializes focused paths or full context (by default via + hardlink - almost instant and with no disk usage) and launches the reviewer. - `ask`: continues a saved session. - `debate`: discusses one specific finding. - `sync`: updates the sandbox from the real source paths. @@ -138,8 +148,8 @@ Focused/free-form: ## Common Session Commands -After `start`, use the same lifecycle for both adapters. In the examples below, `<adapter-script>` means the script selected -by routing: +After `start`, use the same lifecycle for both adapters. In the examples below, `<adapter-script>` means the script +selected by routing: - `.agents/skills/cross-provider-review/scripts/claude_opus_review.py` - `.agents/skills/cross-provider-review/scripts/codex_review.py` @@ -177,7 +187,8 @@ review from a process where only the heartbeat changes. - `--review-id`: set a stable ID for task traceability. - `--timeout-sec`: change the timeout of a single reviewer invocation. -- `--copy-mode {hardlink,copy}`: sandbox materialization mode. `hardlink` (default) - almost instant, ~0 bytes on disk; `copy` - full byte copy. Hardlink automatically falls back to copy on cross-device or unsupported FS. +- `--copy-mode {hardlink,copy}`: sandbox materialization mode. `hardlink` (default) - almost instant, ~0 bytes on disk; + `copy` - full byte copy. Hardlink automatically falls back to copy on cross-device or unsupported FS. - `--keep-sandbox`: preserve review files on `close` only for forensic/debug. - Codex only: `--artifact-type`, `--skills`, `--reasoning-effort`. - Claude only: `--model`. @@ -195,25 +206,37 @@ For per-artifact acceptance-bound review (advisory mode): 7. Use `ask` for follow-up/delta review and `debate` only for specific disputed finding IDs. 8. Use `log`, `stats`, or `show` when trace/debug evidence is needed. 9. Stop at consensus, unchanged stalemate for two rounds, or the maximum round count. -10. Close the review when it is no longer needed. +10. **🔴 MUST — `close` REVIEW_ID as soon as the review is no longer needed** (see the section "CRITICAL: mandatory + sandbox cleanup"). This is not "when convenient" but a required closing step: without it, the sandbox remains on disk + forever. `close` is called even if the review ended in refusal/error. 11. Record the final report: unified findings, disagreements with both positions, iteration count, recommendation, - review id, cleanup status, and relevant status/log evidence. + review id, **cleanup status (`closed` for each `review_id`)** and relevant status/log evidence. Before closing the + task, run the CHECKPOINT from the "CRITICAL" section: `.review-sandboxes/` must be empty. ## Finalization Gate Protocol (blocking) Used by the orchestrator once at the end of the task. Unlike the advisory protocol, the reviewer has the final word here. -**Prerequisite:** the orchestrator must assemble a complete evidence pack (see `references/finalization-prompt.md` section "Input data"). If any item is missing, the reviewer responds `verdict: FAIL` on the first round. +**Prerequisite:** the orchestrator must assemble a complete evidence pack (see `references/finalization-prompt.md` +section "Input data"). If any item is missing, the reviewer responds `verdict: FAIL` on the first round. **Steps:** -1. Launch the opposite-family adapter with the prompt from `references/finalization-prompt.md`. In `--constraints`, specify: "Finalization gate mode. Verdict is blocking, not advisory. Use bidirectional rule compliance check." +1. Launch the opposite-family adapter with the prompt from `references/finalization-prompt.md`. In `--constraints`, + specify: "Finalization gate mode. Verdict is blocking, not advisory. Use bidirectional rule compliance check." 2. Pass the complete evidence pack (file paths + git diff + test stdout). 3. Receive the response: findings + `verdict: PASS | FAIL` + `iteration: N of 3`. -4. If `verdict: PASS` - the task may be closed. Record the review_id in `final-report.md` in the `cross_provider_review` block. -5. If `verdict: FAIL` - address the findings with evidence-based fixes (diff, new stdout, clarified log). Use `ask` for the next round. -6. If `iteration: 3` and the verdict is not `PASS` - the reviewer issues `escalate_to_user: true` with `dispute_summary`. The orchestrator must escalate to the user, passing the dispute_summary verbatim. The user's decision is final. -7. Close the review (`close`) only after a documented PASS verdict or user override. +4. If `verdict: PASS` - the task may be closed. Record the review_id in `final-report.md` in the `cross_provider_review` + block. +5. If `verdict: FAIL` - address the findings with evidence-based fixes (diff, new stdout, clarified log). Use `ask` for + the next round. +6. If `iteration: 3` and the verdict is not `PASS` - the reviewer issues `escalate_to_user: true` with + `dispute_summary`. The orchestrator must escalate to the user, passing the dispute_summary verbatim. The user's + decision is final. +7. **🔴 MUST — `close` review after a documented PASS verdict or user override** (see the section "CRITICAL: mandatory + sandbox cleanup"). Closing the gate review is mandatory in ALL outcomes, including escalation after 3 rounds: after + recording the verdict/override in `final-report.md`, the sandbox must be removed via `close`. Then run the + CHECKPOINT: `.review-sandboxes/` is empty. **Forbidden:** @@ -223,9 +246,17 @@ Used by the orchestrator once at the end of the task. Unlike the advisory protoc ## Safety -- Reviewers work in an isolated sandbox workspace, not in the real project. By default, the sandbox is a hardlink mirror of the source: writes from the primary agent to real files create a new inode, and the reviewer continues to see the frozen snapshot until an explicit `sync`. The reviewers themselves are strictly read-only (see below), so hardlinks are safe: writing through them is impossible. -- Full-context materialization excludes `.git`, `.venv`, `.review-sandboxes`, `node_modules`, `__pycache__`, common build outputs, and `.claude`, `.codex`, `.cursor`, `.windsurf`, `.idea` so the reviewer does not pick up hooks/permissions/MCP configs from the real project. +- Reviewers work in an isolated sandbox workspace, not in the real project. By default, the sandbox is a hardlink mirror + of the source: writes from the primary agent to real files create a new inode, and the reviewer continues to see the + frozen snapshot until an explicit `sync`. The reviewers themselves are strictly read-only (see below), so hardlinks are + safe: writing through them is impossible. +- Full-context materialization excludes `.git`, `.venv`, `.review-sandboxes`, `node_modules`, `__pycache__`, common + build outputs, and `.claude`, `.codex`, `.cursor`, `.windsurf`, `.idea` so the reviewer does not pick up + hooks/permissions/MCP configs from the real project. - Reviewer prompts and adapter prompts include read-only instructions. -- **Codex** runs with `--sandbox read-only` - the kernel-level sandbox blocks any writes regardless of what the model wants. -- **Claude** runs with `--tools=Read,Grep,Glob,LS`, `--permission-mode plan` (plan-only mode without write/edit) and `--strict-mcp-config` (without `--mcp-config` this means "no MCP servers at all"). This is a three-layer permission-level guarantee. +- **Codex** runs with `--sandbox read-only` - the kernel-level sandbox blocks any writes regardless of what the model + wants. +- **Claude** runs with `--tools=Read,Grep,Glob,LS`, `--permission-mode plan` (plan-only mode without write/edit) and + `--strict-mcp-config` (without `--mcp-config` this means "no MCP servers at all"). This is a three-layer + permission-level guarantee. - The primary agent remains responsible for acceptance, rework, and final synthesis. diff --git a/framework_eng/skills/tool-usage/v8-runner/SKILL.md b/framework_eng/skills/tool-usage/v8-runner/SKILL.md index 78e9658f..29ff77aa 100644 --- a/framework_eng/skills/tool-usage/v8-runner/SKILL.md +++ b/framework_eng/skills/tool-usage/v8-runner/SKILL.md @@ -1,6 +1,6 @@ --- name: v8-runner -description: "Use when Codex needs to manage v8-runner on local 1C projects through the CLI: configure v8project.yaml, initialize infobases or EDT workspaces, build sources from Designer or EDT, run syntax checks and tests, dump infobase changes, convert source formats, load or export artifacts, launch 1C clients, or choose safe 1C automation command sequences." +description: "v8-runner: infobases, build, checks, tests, 1C clients" provides_capabilities: - build_project - full_rebuild_project @@ -26,26 +26,26 @@ provides_capabilities: Use this skill to manage `v8-runner` as an automation layer for local 1C development projects. -Keep this file as the entry point for decisions. Load only the reference file that matches the task: +Treat this file as the entry point for decisions. Load only the reference file that matches the task: - `references/command-selection.md` — for choosing the correct command sequence. - `references/bootstrap.md` — for generating `v8project.yaml` from an existing repository: what to determine yourself and what to ask the user (decision tree for `format`, `builder`, `connection`). - `references/config-and-backends.md` — about `v8project.yaml`, source sets, formats, builders, and backend limitations. -- `references/project-workflows.md` — typical build, syntax, dump, launch, and source synchronization scenarios for Designer- and EDT-based projects. +- `references/project-workflows.md` — typical build, syntax, dump, launch, and source synchronization scenarios for Designer and EDT projects. - `references/file-and-artifact-workflows.md` — about dump, convert, load, make/artifacts, and staged publication. - `references/testing.md` — about YaXUnit, Vanessa Automation, syntax checks, and artifacts. -- `references/troubleshooting.md` — about configuration failures, stale state, and environment diagnostics. -- `references/auth-guard.md` — hard stop on license patterns, the rule of two candidates, auth/path error classification, storing credentials in `v8project.local.yaml`. +- `references/troubleshooting.md` — about setup failures, stale state, and environment diagnostics. +- `references/auth-guard.md` — hard stop on license patterns, the two-candidate rule, classification of auth/path errors, storing credentials in `v8project.local.yaml`. ## Command Form -The canonical binary path is `tools/external/v8-runner/v8-runner` (in the project this works through the `tools/` symlink to the framework). The framework installer pulls the latest release from [`alkoleft/v8-runner-rust`](https://github.com/alkoleft/v8-runner-rust) (upstream) on every launch; manual reinstall is `python tools/install.py --install-external-tools`. If the binary is missing at this path and also not in `PATH`, ask the user for the path or use the project wrapper script. +The canonical binary path is `tools/external/v8-runner/v8-runner` (in the project this works through the `tools/` symlink to the framework). The framework installer pulls the Latest release from [`alkoleft/v8-runner-rust`](https://github.com/alkoleft/v8-runner-rust) (upstream) on every run; manual reinstall is `python tools/install.py --install-external-tools`. If the binary is missing at this path and is not in `PATH` either, ask the user for the path or use the project wrapper script. -> **WS transport: the SteelMorgan fork is used.** For WS pairing with the session manager, the fork [`SteelMorgan/v8-runner-rust`](https://github.com/SteelMorgan/v8-runner-rust) is used instead of upstream `alkoleft/v8-runner-rust`, because PRs with WS support are not accepted upstream. The framework installer targets releases from this fork. Likewise, `onec-client-mcp-devkit` (the `mcp_client`, `test_client`, and other extensions) is taken from the fork [`SteelMorgan/onec-client-mcp-devkit`](https://github.com/SteelMorgan/onec-client-mcp-devkit). +> **WS transport: the SteelMorgan fork is used.** For WS integration with the session manager, the fork [`SteelMorgan/v8-runner-rust`](https://github.com/SteelMorgan/v8-runner-rust) is used instead of upstream `alkoleft/v8-runner-rust`, because PRs with WS support are not accepted upstream. The framework installer targets releases from this fork. Similarly, `onec-client-mcp-devkit` (extensions `mcp_client`, `test_client`, etc.) is taken from the fork [`SteelMorgan/onec-client-mcp-devkit`](https://github.com/SteelMorgan/onec-client-mcp-devkit). -`v8project.yaml` is the default project config name. A neighboring `v8project.local.yaml` is loaded automatically for machine-local paths, credentials, tools, tests, and MCP settings. Do not pass `--config v8project.yaml` unless the user explicitly asks for a non-standard command form or the active config path differs from the default; never pass `v8project.local.yaml` through `--config`. +`v8project.yaml` is the default project config name. The adjacent `v8project.local.yaml` is loaded automatically for machine-local paths, credentials, tools, tests, and MCP settings. Do not pass `--config v8project.yaml` unless the user explicitly asks for a nonstandard command form or the active config path differs from the default; never pass `v8project.local.yaml` through `--config`. -Generated `v8project.yaml` files contain a `yaml-language-server` modeline that points to the versioned JSON Schema for the current `v8-runner` release. For `v8project.local.yaml`, use the corresponding raw URL `docs/schemas/v8project.local.schema.json` from the GitHub tag in editor settings when schema-assisted editing matters. +Generated `v8project.yaml` files contain a `yaml-language-server` modeline that points to a versioned JSON Schema for the current `v8-runner` release. For `v8project.local.yaml`, use the corresponding raw URL `docs/schemas/v8project.local.schema.json` from the GitHub tag in editor settings when schema-aware editing matters. Use JSON output only when another tool, script, or the final answer needs structured results: @@ -58,19 +58,32 @@ For direct human diagnostics, use text output. Useful global flags: - `--config <CONFIG>` — when the active config is not `./v8project.yaml`. -- `--json-message` — for machine-readable CLI wrappers. +- `--json-message` — for machine-readable CLI envelopes. - `--workdir <WORKDIR>` — overrides `workPath`; takes precedence over `v8project.local.yaml`. - `--clean-before-execution` — clear logs before execution. - `--log-level <error|warn|info|debug|trace>` — for diagnostics. - `--no-color` — plain text output. +## 1C Client Lifecycle + +Run interactive 1C clients and MCP/VA sessions that must remain available after the command returns to the agent as standalone processes with explicit lifecycle management. Do not use `sleep`, `tail -f`, an infinite shell loop, or a similar wrapper command to "keep" a 1C client alive: when the wrapper exits, the terminal/PTY or the agent environment may close the child 1C process, and `session-manager` will see this as a WS break without a normal close. + +The correct order is: + +1. Start the client with the standard `v8-runner launch ...` command. +2. If the runtime cleans up child processes after the shell command exits, run the command using detached environment facilities (`nohup`, `setsid`, a service/job runner, or the project equivalent), and save the PID and launch log. +3. Check readiness through externally observable state: `session_list`, appearance of the required MCP tools, the 1C window, a file protocol, or an entry in the registration log. +4. Stop the client with an explicit action: the standard session-manager/VA tool, a client shutdown command, or a targeted `kill <PID>` only for your saved PID. + +`sleep` is allowed only as a short wait between readiness checks inside a script/poll loop. It must not own the lifecycle of the 1C process. + ## First Pass 1. Check whether `v8project.yaml` exists at the root of the 1C project. -2. If it does not, run the narrowest possible `v8-runner config init ...` command that fits the project form. +2. If it does not, run the narrowest possible `v8-runner config init ...` command appropriate for the project shape. 3. Inspect the generated config before running any mutating commands. -4. Run `v8-runner init` only when you need to create a file-based infobase or an EDT workspace. -5. Run the narrowest validation command that answers the user's goal. +4. Run `v8-runner init` only when you need to create a file infobase or an EDT workspace. +5. Run the narrowest validation command that matches the user's goal. Useful initialization commands: @@ -82,89 +95,100 @@ v8-runner config init --builder IBCMD v8-runner init ``` -## Routing Typical Scenarios +## Typical Scenario Routing -- If sources changed, the infobase may be stale: run `v8-runner build`. -- If only one source set changed: use commands that accept `--source-set <NAME>` instead of a full rebuild or materializing everything. -- Branch switch, rebase, large object moves, stale source-based tool extension state, or suspicious incremental state: run `v8-runner build --full-rebuild`. -- Syntax check: inspect `format` and `builder`, then choose `syntax designer-modules`, `syntax designer-config`, or `syntax edt`. +- Sources changed, the infobase may be stale: run `v8-runner build`. +- Only one source set changed: use commands that accept `--source-set <NAME>` instead of a full rebuild or full materialization. +- Branch switch, rebase, large object moves, stale source-based tool-extension state, or suspicious incremental state: run `v8-runner build --full-rebuild`. +- Syntax checking: look at `format` and `builder`, then choose `syntax designer-modules`, `syntax designer-config`, or `syntax edt`. - Behavior validation: run the appropriate `v8-runner test ...` command; tests build first. -- Debugging Vanessa Automation, researching forms, or writing scenarios through MCP: use `v8-runner launch mcp va ...` to start a VA test manager session with MCP tools. After startup, check readiness through `session_list`: you need `kind=vanessa_test_client` and VA tools, not only the initial WS registration. -- Need extension property synchronization: use `v8-runner extensions` or `extensions --name <SOURCE_SET>`. +- Debugging Vanessa Automation, exploring forms, and writing scenarios through MCP: use `v8-runner launch mcp va ...` to start a VA test-manager session with MCP tools. After startup, verify readiness via `session_list`: you need `kind=vanessa_test_client` and the appearance of VA tools, not just the initial WS registration. +- Extension property synchronization is needed: use `v8-runner extensions` or `extensions --name <SOURCE_SET>`. - Infobase changes must become Git-visible files: check `git status`, then run the appropriate `v8-runner dump ...` command. -- Need to convert sources between Designer and EDT: use `v8-runner convert`; this is CLI-only and does not use the infobase. +- Need to convert sources between Designer and EDT: use `v8-runner convert`; this is CLI only and does not use the infobase. - Existing `.cf` or `.cfe` artifacts need to be applied to the infobase: use `v8-runner load ...`. - Need to export release artifacts or publish external artifacts: use `v8-runner make ...` or the `artifacts` alias. - Need a 1C UI session: use `v8-runner launch designer`, `launch thin`, `launch thick`, or `launch ordinary`. -- Need to start onec-client-mcp-devkit inside 1C without authoring VA: use `v8-runner launch mcp ...`. -- Pair a running 1C client with a running [v8-client-session-manager](https://github.com/SteelMorgan/v8-client-session-manager) over WebSocket: see the separate "WS pairing parameters" section below. WS flags (`--mcp-transport`, `--manager-url`, `--client-uid`, `--corr-id`, `--mcp-log-level`, `--mcp-ws-timeout-ms`) are available on `launch ...` and `test ...` commands in the same way. Subtle clap detail: on `test`, the flags are placed **before** the `yaxunit/va` subcommand (for example, `v8-runner test --mcp-transport=ws yaxunit module <NAME>`), not after. +- Need to run onec-client-mcp-devkit inside 1C without authoring VA: use `v8-runner launch mcp ...`. +- Couple a running 1C client with an active [v8-client-session-manager](https://github.com/SteelMorgan/v8-client-session-manager) over WebSocket: see the separate "WS coupling parameters" section below. WS flags (`--mcp-transport`, `--manager-url`, `--client-uid`, `--corr-id`, `--mcp-log-level`, `--mcp-ws-timeout-ms`) are available on `launch ...` and `test ...` commands in the same way. The subtle clap-structure point: on `test`, the flags are placed **before** the `yaxunit/va` subcommand (for example `v8-runner test --mcp-transport=ws yaxunit module <NAME>`), not after it. -## WS Pairing Parameters with session-manager +## WS Coupling Parameters with session-manager -WS pairing with [v8-client-session-manager](https://github.com/SteelMorgan/v8-client-session-manager) is a mode in which the 1C client MCP server connects to the manager over WebSocket instead of local HTTP MCP. It is controlled by the same set of CLI flags or by `tools.client_mcp.*` in `v8project.yaml`. +WS coupling with [v8-client-session-manager](https://github.com/SteelMorgan/v8-client-session-manager) is a mode in which the 1C client MCP server connects to the manager over WebSocket instead of local HTTP MCP. It is controlled by the same set of CLI flags or by `tools.client_mcp.*` in `v8project.yaml`. ### Applicable Entry Points -The same set of flags works for: +The same flag set works for: - `v8-runner launch designer | thin | thick | ordinary` — flags are placed after `launch`. - `v8-runner launch mcp` / `launch mcp va` — flags are placed after `launch mcp [va]`. - `v8-runner test yaxunit all` / `test yaxunit module <NAME>` — flags are placed **at the `test` level**, BEFORE the `yaxunit` subcommand. - `v8-runner test va` — flags are placed **at the `test` level**, BEFORE the `va` subcommand. -Example (test): `v8-runner test --mcp-transport=ws --mcp-log-level=debug yaxunit module mcp_МспПровайдер_Тесты`. If you place the WS flags after `yaxunit` or `module <NAME>`, clap returns `error: unexpected argument` because these subcommands do not declare their own `McpClientWsArgs`. +Example (test): `v8-runner test --mcp-transport=ws --mcp-log-level=debug yaxunit module mcp_МспПровайдер_Тесты`. If you place WS flags after `yaxunit` or `module <NAME>`, clap responds with `error: unexpected argument`, because those subcommands do not declare their own `McpClientWsArgs`. ### CLI Flags -- `--mcp-transport={ws|legacy|auto}` — `auto` (default) performs a TCP probe of `manager_url` for about 200 ms; `ws` is strict WS and fails if unavailable; `legacy` is the old HTTP mode without probe. -- `--manager-url <URL>` — override `tools.client_mcp.manager_url` (default `ws://127.0.0.1:4000/sessions`). -- `--client-uid <UUID>` — override the auto-generated v4 UUID. -- `--corr-id <STR>` — override `vr-<first 8 characters of client_uid>`. -- `--mcp-log-level={off|error|warn|info|debug|trace}` — log level inside the client. +- `--mcp-transport={mcp|ws|auto}` — `auto` (default) performs a TCP probe of `manager_url` for about 200 ms; `ws` is strict WS, and fails if unavailable; `mcp` is the local HTTP MCP mode without probing. +- `--manager-url <URL>` — overrides `tools.client_mcp.manager_url` (default `ws://127.0.0.1:4000/sessions`). +- `--client-uid <UUID>` — overrides the auto-generated v4 UUID. +- `--corr-id <STR>` — overrides `vr-<first 8 characters of client_uid>`. +- `--mcp-log-level={off|error|warn|info|debug|trace}` — logging level inside the client. - `--mcp-ws-timeout-ms <N>` — WS handshake timeout (default 1000 ms; relevant for `auto` fallback). -Alternative: all of this can be configured in `tools.client_mcp.*` in `v8project.yaml` / `v8project.local.yaml` — priority order: CLI → yaml → internal defaults. +Alternative: all of this can be set in `tools.client_mcp.*` in `v8project.yaml` / `v8project.local.yaml` — priority order: CLI → yaml → internal defaults. ```yaml tools: client_mcp: - transport: auto # ws | legacy | auto + transport: auto # mcp | ws | auto manager_url: ws://127.0.0.1:4000/sessions log_level: info ws_timeout_ms: 1000 ``` -For specialized entry points, `kind` is fixed by the entry point and cannot be overridden from the CLI. For regular UI clients (`launch thin/thick/ordinary`), `kind` is not passed in `/C`: the `client_mcp` extension announces its client kind itself during `session.register`. +For specialized entry points, `kind` is fixed by the entry point and cannot be overridden from the CLI. For ordinary UI clients (`launch thin/thick/ordinary`), `kind` is not passed in `/C`: the `client_mcp` extension declares its own client kind when `session.register` runs. ### Internal `kind` Mapping | Command | `kind` | |---|---| -| `launch thin/thick/ordinary` | not passed; the client side announces the default kind | +| `launch thin/thick/ordinary` | not passed; the client side declares the default kind | | `launch mcp` | `v8_runner_client` | | `launch mcp va` | `vanessa_test_client` | | `test yaxunit ...` | `yaxunit_runner` | | `test va ...` | `vanessa_test_client` | -### What v8-runner Injects into `/C` in the WS Branch +### Client and Test Launch Modes + +| Mode | Purpose | MCP/VA behavior | +|---|---|---| +| `launch designer` | Open Designer. | Does not start client MCP tools and does not apply enterprise additional keys. | +| `launch thin`, `launch thick`, `launch ordinary` | Open a regular 1C UI client. | With WS coupling, registers the base client MCP tool set without `kind`; by itself it does not publish VA tools. | +| `launch mcp` | Start onec-client-mcp-devkit inside 1C without Vanessa. | `kind=v8_runner_client` for WS; local HTTP MCP with `--mcp-transport=mcp` or `auto` fallback. | +| `launch mcp va` | Start the Vanessa test manager for research, authoring, and VA client MCP tools. | `kind=vanessa_test_client`; the runner adds `/TESTMANAGER`, `/DisableUnsafeActionProtection`, `/Execute <vanessa-automation.epf>`, runtime `VAParams`, disables automatic scenario start/close, and does not use `StartFeaturePlayer`. | +| `test yaxunit ...` | Run YAxUnit tests. | `kind=yaxunit_runner` in WS mode; this is a test runner, not an interactive UI session. | +| `test va` | Run Vanessa feature scenarios. | `kind=vanessa_test_client`, but the payload is `StartFeaturePlayer;VAParams=...`; this is scenario execution, not the manager research mode. | + +### What v8-runner injects into `/C` in the WS branch ```text /C"mcpMode=ws;manager_url=<URL>;client_uid=<UUID>;kind=<KIND>;corr_id=<CORR>;mcp_log_level=<LVL>;mcp_ws_timeout_ms=<MS>" ``` -For `launch mcp` / `launch mcp va`, this is the entire `/C`. For `launch thin/thick/ordinary`, the same WS fragment is used **without** `kind=<KIND>` and is appended with `;` to an existing `/C` value if one is already set. For test commands, the WS fragment is appended with `;` to the existing `RunUnitTests=…` / Vanessa player (if `transport=ws` is selected through the yaml config). +For `launch mcp` / `launch mcp va`, this is the entire `/C`. For `launch thin/thick/ordinary`, the same WS fragment is used, but **without** `kind=<KIND>`, and it is appended via `;` to an existing `/C` if one is already set. For test commands, the WS fragment is appended via `;` to an existing `RunUnitTests=…` / Vanessa player (if `transport=ws` is selected through the yaml config). -Regular thin client in WS mode: +Ordinary thin client in WS mode: ```text /C"mcpMode=ws;manager_url=<URL>;client_uid=<UUID>;corr_id=<CORR>;mcp_log_level=<LVL>;mcp_ws_timeout_ms=<MS>" ``` -Important: do not add `kind` for regular `launch thin/thick/ordinary`. Such a client registers the base `client_mcp` tools, but does not publish Vanessa Automation MCP tools by itself. +Important: do not add `kind` in ordinary `launch thin/thick/ordinary`. Such a client registers the base `client_mcp` tools, but it does not publish Vanessa Automation MCP tools on its own. ### Vanessa Automation MCP through session-manager -For the Vanessa Research/Scenario workflow through our `v8-client-session-manager`, start not a plain thin client but a test manager session with the Vanessa Automation processing opened: +For a Vanessa Research/Scenario workflow through our `v8-client-session-manager`, a plain thin client is not started, but a test-manager session with the Vanessa Automation external processing open: ```bash v8-runner launch mcp va \ @@ -176,7 +200,7 @@ v8-runner launch mcp va \ --mcp-ws-timeout-ms 5000 ``` -Expected 1C launch shape assembled by the runner: +Expected 1C launch form that the runner must assemble: ```text 1cv8c ENTERPRISE @@ -187,27 +211,84 @@ Expected 1C launch shape assembled by the runner: /N <user> /P <password> /Execute <path>/vanessa-automation.epf - /C"mcpMode=ws;manager_url=ws://127.0.0.1:4000/sessions;client_uid=<uid>;kind=vanessa_test_client;corr_id=<uid>;mcp_log_level=debug;mcp_ws_timeout_ms=5000" + /C"mcpMode=ws;manager_url=ws://127.0.0.1:4000/sessions;client_uid=<uid>;kind=vanessa_test_client;corr_id=<uid>;mcp_log_level=debug;mcp_ws_timeout_ms=5000;VAParams=<runtime va-params.json>" +``` + +The required meaning of this launch string is: the MCP session must live on the test-manager process side with the Vanessa Automation external processing open. Do not start the tested application with the `MCPVA` form: `MCPVA` is the internal form/module of the VA external processing, and it is VA running inside `/TESTMANAGER` that must call `MCPVA.ЗарегистрироватьИнструментыMCP()`. + +The readiness criterion for the VA MCP session is: a live `kind=vanessa_test_client` session appeared in `session_list`, and its tools contain VA tools (`get_VanessaAutomation_state`, `connect_test_client`, `get_window_list_os`, `get_window_screenshot_os`, `get_form_analysis`, `manage_command_interface`) or the number of tools became larger than the base `client_mcp` set. The initial registration with the base tools does not yet mean that `MCPVA.ЗарегистрироватьИнструментыMCP()` has already run. + +Immediately after `v8-runner launch mcp va`, the response `session_list=[]` or the absence of VA tools is **not an error**: starting the test manager and registering tools normally takes 10-90 seconds. Mandatory readiness loop: + +1. Poll `session_list` every 5-10 seconds. +2. Wait up to 120 seconds from the start: 10-90 seconds is normal, 90-120 seconds is diagnostic headroom. +3. Continue only when there is a live `kind=vanessa_test_client`, `state=active`, `disconnected_secs_ago=null`, `inflight=0` session, and the required VA tools for the current task are present. +4. Tool names from the MCP/showcase cache without a live session do not prove readiness. +5. If the condition is not satisfied within 120 seconds, stop and report `VA MCP readiness blocker`. + +After the WS session is ready, the tested application in the VA context is started by the test manager itself: call the MCP tool `connect_test_client` with the `profileName` argument (the testing client profile name, for example `Codex thin AgentAI`). VA will start a separate `/TESTCLIENT -TPort <auto>` process from the profile and connect `ТестируемоеПриложение` to it; after that, the VA client MCP methods become available (`get_form_analysis`, `manage_command_interface`, `manage_form_elements`, screenshot/data tools, etc.). Do not start this `/TESTCLIENT` manually for the VA path unless you are debugging the profile mechanism itself. + +After investigation, manual actions, or an error, always call the MCP tool `close_test_client`. Pass the same `profileName` when you worked with a specific profile; without `profileName`, the tool closes the currently connected profile. This releases the test-client process and avoids keeping extra 1C sessions before the next launch. + +Treat VA screenshot MCP tools (`get_window_list_os`, `get_window_screenshot_os`) as ready only after a short smoke check in the current environment: the live session must remain active, `inflight=0`, and the PNG must be non-empty and non-black. The detailed visual-check order and fallback conditions are described in the `va-visual-check` skill. + +Configure the `tools.va` / `tests.va` section in `v8project.yaml` and the TestClient profile in VAParams according to `references/config-and-backends.md` (section "Vanessa Automation in `v8project.yaml`"). The exact command chain for manager → `connect_test_client` → close is in `references/testing.md` (section "Exact VA manager → TestClient chain"). The full payload, the JSON output form (`--json-message`), probe rules, and behavior when the manager is unavailable are in `references/project-workflows.md` (section "WS mode to session-manager"). Starting the manager itself is **not** part of v8-runner — see the `v8-session-manager` skill. + +### UI MCP through the platform test client + +If the task is to drive the 1C UI through client MCP tools (`open_form`, `click`, `input`, `get_value`, `get_table_rows`, `test_client_start`), this contour is allowed only for structural control when the needed function is fundamentally absent in VA MCP or when it is used as part of a VA/TestClient scenario. + +The working chain is: + +1. Start session-manager and verify the HTTP endpoint: `tools/call session_list` must respond, even if `sessions=[]`. +2. Start the control MCP client detached, explicitly with `/TESTMANAGER`: + +```bash +uid=$(cat /proc/sys/kernel/random/uuid) +setsid nohup v8-runner --no-color --log-level debug launch thin \ + --mcp-transport ws \ + --manager-url ws://127.0.0.1:4000/sessions \ + --client-uid "$uid" \ + --corr-id "ui-$uid" \ + --mcp-log-level debug \ + --mcp-ws-timeout-ms 5000 \ + --raw-key /TESTMANAGER \ + > "/tmp/ui-mcp-$uid.log" 2>&1 & ``` -VA MCP session readiness criterion: `session_list` contains a live `kind=vanessa_test_client` session, and its tools include VA tools (`get_VanessaAutomation_state`, `connect_test_client`, `get_window_list_os`, `get_window_screenshot_os`, `get_form_analysis`, `manage_command_interface`) or the tool count is greater than the base `client_mcp` set. The initial registration with base tools does not yet mean that `MCPVA.ЗарегистрироватьИнструментыMCP()` has run. +3. Wait in `session_list` for a live session `kind=1c-client`, `state=active`, `inflight=0`, `infobase_name=<required infobase>`. The baseline check before UI calls is: `infobase_info` must return quickly. +4. Start the tested application as a separate process with `/TESTCLIENT -TPort <port>` and the same connection parameters, user, and password as in the project launch. This is the preferred path: the agent starts the tested application detached and saves the PID/log, while `test_client_start` on the next step is used as a connection from the control `/TESTMANAGER` to the already listening port. If the project has a ready-made launcher, it must also pass `/N`, `/P`, `/UC` and the same connection string; otherwise use the direct platform form: -The tested application in the VA contour is started by the test manager itself: call `connect_test_client` with the test-client profile name (`profileName`, for example `Codex thin AgentAI`). VA starts a separate `/TESTCLIENT -TPort <auto>` process from the profile and connects `ТестируемоеПриложение` to it. Do not start this `/TESTCLIENT` manually for the VA path unless you are debugging the profile mechanism itself. +```bash +setsid nohup /opt/1cv8/x86_64/<version>/1cv8c ENTERPRISE \ + /DisableStartupDialogs \ + /IBConnectionString 'Srvr="<server>";Ref="<infobase>";' \ + /N <user> /P <password> /UC <unlock_code> \ + /TESTCLIENT -TPort 1538 \ + > /tmp/test-client-1538.log 2>&1 & +``` + +5. Connect the tested application through the control MCP session: + +```json +{"name":"test_client_start","arguments":{"session_id":"<1c-client session_id>","port":1538}} +``` -Treat the VA screenshot MCP tools (`get_window_list_os`, `get_window_screenshot_os`) as conditional, not guaranteed. They appear in MCP tools after `MCPVA.ЗарегистрироватьИнструментыMCP()`, but they actually work only if VA has filled the test client's PID/window handle. Verified on 2026-06-26 with 1C 8.3.27.2074 + Vanessa Automation 1.2.043.28 + Linux/X11: +Successful criterion: `{"ok": true, "data": {"connected": true}}`. -- with the project’s standard `VAParams` (`ИспользоватьКомпонентуVanessaExt=Ложь`, `ИспользоватьВнешнююКомпонентуДляСкриншотов=Ложь`), `connect_test_client` succeeds and `get_window_list_testclient` sees the windows, but `get_window_list_os` fails with `ACTION_FAILED: Не вышло получить PID процесса клиента тестирования`; -- with temporary `ИспользоватьКомпонентуVanessaExt=Истина` and `ИспользоватьВнешнююКомпонентуДляСкриншотов=Истина`, the first launch is blocked by the external-component installation dialog; the second launch registers VA MCP tools, but the profile still remains with `PID=0`, and `get_window_screenshot_os` fails with the same error. +6. After that, perform UI MCP tools only through the control session's `session_id`: `open_form` → `click/input/select` → `get_value/get_table_rows`. For form elements, you can build the URI directly as `control://<urlencoded form name>/<urlencoded element name>` if `find` is unstable. -Therefore the default for visual form control is: drive the form through VA/TestClient MCP, and take the visual screenshot with an external OS/noVNC/browser screenshot tool if `get_window_screenshot_os` has not passed a short smoke check in the current environment. The presence of the tool in `tools/list` or `session_list.tools` is not proof that screenshots work. +Do not do this: -The full payload, the JSON output form (`--json-message`), probe rules, and behavior when the manager is unavailable are in `references/project-workflows.md` (section "WS Mode with session-manager"). Bringing up the manager itself is **not** part of v8-runner — see the `v8-session-manager` skill. +- Do not start the control client without `/TESTMANAGER`: on the first `test_client_start` the platform may fail with `Type not defined (ТестируемоеПриложение)`. +- Do not rely on `test_client_start` as the only way to start `/TESTCLIENT` if it starts the client without `/N` and `/P`: such a process may stay at the infobase login screen, and the connection will return `No suitable test client found`. +- Do not treat `tools/list` as proof of readiness: proxied tools may come only from the session-manager cache. Readiness is confirmed by a live session in `session_list` and a successful simple call (`infobase_info`). ### Resolved: WS Sessions in `test yaxunit` (DRIVE 2026-05-11) -Symptom: `yaxunit_runner` is NOT registered in the manager's `session_list`, although v8-runner correctly injects the WS payload into `/C` (`RunUnitTests=...;mcpMode=ws;...;kind=yaxunit_runner;...`). +Symptom: yaxunit_runner is NOT registered in the manager's `session_list`, although v8-runner correctly injects the WS payload into `/C` (`RunUnitTests=...;mcpMode=ws;...;kind=yaxunit_runner;...`). -The root cause is a race condition in BSL `client_mcp` (`ManagedApplicationModule.bsl`): the idle handler `Мсп_ОтложенныйСтарт_Тик` was set with a **1 second** interval, while YAXUNIT with `closeAfterTests: true` closed the application about 1 second after startup (the tests run in about 200 ms), so the idle handler did not have time to tick. +The root cause is a race condition in BSL `client_mcp` (`ManagedApplicationModule.bsl`): the idle handler `Мсп_ОтложенныйСтарт_Тик` was set with a **1 second** interval, and YAXUNIT with `closeAfterTests: true` closed the application about 1 second after startup (tests finish in about 200 ms), so the idle handler did not get a chance to tick. Fix: reduce the idle-handler interval from `1` to `0.1`: ```bsl @@ -215,61 +296,61 @@ Fix: reduce the idle-handler interval from `1` to `0.1`: ПодключитьОбработчикОжидания("Мсп_ОтложенныйСтарт_Тик", 0.1, Истина); ``` -After the fix, yaxunit-Enterprise registers as `kind=yaxunit_runner` in the manager's `session_list` (confirmed in v8-runner stdout: `[MCP INFO ...] WS session registered: uid=... kind=yaxunit_runner ... tools=24`). +After the fix, yaxunit-Enterprise registers as `kind=yaxunit_runner` in the manager's `session_list` (confirmation in v8-runner stdout: `[MCP INFO ...] WS session registered: uid=... kind=yaxunit_runner ... tools=24`). -## Headless Launch of an External Processing Object (.epf) with a Server Method Call +## Headless Launch of External Processing (.epf) with a Server Method Call -Launching an external processing object in batch (headless) mode with automatic execution of its logic is done through `v8-runner launch <thin|thick|ordinary> --execute "<path to .epf>"` (this is `1cv8 ENTERPRISE /Execute<epf>`). The key nuance, without which the approach does not work: +Launching an external processing in batch (headless) mode with automatic execution of its logic is done through `v8-runner launch <thin|thick|ordinary> --execute "<path to .epf>"` (this is `1cv8 ENTERPRISE /Execute<epf>`). The key nuance without which the approach does not work: -- **`/Execute<epf>` OPENS the processing form** (it emulates "Open processing"). By itself it does **NOT** call the object module's export method. Therefore, a **processing object without a form** (only an object module with an export procedure) will **not execute** its logic through `/Execute` - the entry point will never be called. -- The canonical headless approach: the processing object **has a managed form**, and in its module there is a `&OnClient Procedure OnOpen(Cancel)` handler that recognizes batch mode by the **launch parameter**, calls an `&OnServer` method (which performs the work / invokes the object module's export procedure), and then cleanly terminates the session through `EndSystemWork(False)`. +- **`/Execute<epf>` OPENS the processing form** (it emulates "Open processing"). By itself it does **NOT** call the object module's export method. Therefore, a **processing without a form** (only an object module with an export procedure) will **not execute** its logic through `/Execute` — the entry point is never called. +- The canonical headless approach: the processing **has a managed form**, and in its module there is an `&НаКлиенте Процедура ПриОткрытии(Отказ)` handler that recognizes batch mode by the **startup parameter**, calls an `&НаСервере` method (which does the work / invokes the object module's export procedure), and then cleanly ends the session via `ЗавершитьРаботуСистемы(Ложь)`. ### Passing the Parameter and Suppressing the Security Warning -- The launch parameter is passed with the `--c "<string>"` key (this is `/C"<string>"`) and read in BSL through `LaunchParameter()`. Use a sentinel string so that the form can distinguish headless launch from interactive opening and does not auto-execute when opened manually. -- The **first launch** of an external processing object raises a security warning dialog (protection against dangerous actions) - in headless mode it will hang the process. It is suppressed with the `--raw-key /DisableUnsafeActionProtection` key. An alternative is to clear the user's "Protection against dangerous actions" flag or configure a security profile (but the CLI key is preferable for one-off runs). +- The startup parameter is passed with the `--c "<string>"` key (this is `/C"<string>"`) and is read in BSL through `ПараметрЗапуска()`. Use a sentinel string so the form distinguishes headless startup from interactive opening and does not auto-execute when opened manually. +- The **first launch** of the external processing opens a security warning dialog (protection against dangerous actions) - in headless mode it will hang the process. Suppress it with the `--raw-key /DisableUnsafeActionProtection` key. An alternative is to remove the user's "Protection against dangerous actions" flag or configure a security profile (but the CLI key is preferable for one-off runs). ### Minimal Processing Skeleton ```bsl -// Processing form module -&OnClient -Procedure OnOpen(Cancel) - If LaunchParameter() = "BATCH_START" Then // sentinel from --c - Log = PerformOperationOnServer(); // server work - // write Log to a known file for external verification - EndSystemWork(False); // clean exit without dialogs - EndIf; -EndProcedure - -&OnServer -Function PerformOperationOnServer() - // resolve all parameters on the SERVER side (not from form attributes - nobody filled them in headless), - // perform business logic, return the log text -EndFunction +// Модуль формы обработки +&НаКлиенте +Процедура ПриОткрытии(Отказ) + Если ПараметрЗапуска() = "ЗАПУСК_ПАКЕТНО" Тогда // sentinel из --c + Протокол = ВыполнитьОперациюНаСервере(); // серверная работа + // записать Протокол в известный файл для верификации снаружи + ЗавершитьРаботуСистемы(Ложь); // корректный выход без диалогов + КонецЕсли; +КонецПроцедуры + +&НаСервере +Функция ВыполнитьОперациюНаСервере() + // разрешить все параметры СЕРВЕРНО (не из реквизитов формы — в headless их никто не заполнил), + // выполнить бизнес-логику, вернуть текст протокола +КонецФункции ``` ### Command and Verification ```bash -v8-runner launch thin --execute "<abs. path to .epf>" --c "BATCH_START" --raw-key /DisableUnsafeActionProtection +v8-runner launch thin --execute "<абс. путь к .epf>" --c "ЗАПУСК_ПАКЕТНО" --raw-key /DisableUnsafeActionProtection ``` -- The connection to the infobase is taken from `v8project.yaml` - no separate `/S`/`/F` is needed. -- **Completion condition:** wait for the 1cv8 process to exit OR for the log file written by the processing object to appear. The process exit code alone is a weak signal. -- **Verify the result by behavior, not by the fact of launch:** data delta (before/after query), log file contents, registration record in the event log. "The process ran without error" does not mean "the logic executed". +- The connection to the infobase is taken from `v8project.yaml` — there is no need to specify a separate `/S`/`/F`. +- **Completion condition:** wait for the 1cv8 process to exit OR for the protocol file written by the processing itself to appear. A process exit code alone is a weak signal. +- **Verify the result by behavior, not by the fact of launch:** data delta (query before/after), protocol file content, an entry in the registration log. "The process ran without error" does not mean "the logic executed." -> Alternative without `/Execute`: from an **already connected** server session - `ExternalProcessing.Create(<path>, False)` + call its export method (or BSP `LongOperations.ExecuteProcessingObjectModuleProcedure`). This requires a "run code on the server" channel (session manager / test runner), while `/Execute` is self-sufficient from the command line. +> Alternative without `/Execute`: from an **already connected** server session - `ВнешниеОбработки.Создать(<path>, Ложь)` plus a call to its export method (or БСП `ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки`). This requires a "run code on server" channel (session manager / test runner), while `/Execute` is self-contained from the command line. -## Protective Rules +## Guard Rules -- Before any v8-runner operation that accesses an infobase, apply auth-guard: check credentials and classify possible errors (license / auth / path) — see `references/auth-guard.md`. -- Do not delete or recreate an infobase, workspace, temp directory, or generated state unless the user explicitly asked for it or the command itself is documented as a recovery path. +- Before any v8-runner operation that accesses the infobase, apply the auth guard: check credentials and classify possible errors (license / auth / path) — see `references/auth-guard.md`. +- Do not delete or recreate the infobase, workspace, temp directory, or generated state unless the user explicitly asked for it or the command itself is documented as a recovery path. - Do not invent raw `1cv8`, `ibcmd`, or `1cedtcli` flags; prefer the `v8-runner` command surface. -- Before `dump`, check `git status` if the result may overwrite or mix with already applied source edits. -- Keep failed test artifacts in `workPath/temp/<runner-id>/runs/<run-id>/` for diagnostics; do not clean them immediately. -- Report missing local 1C utilities as environment/install problems, not project source errors. -- Keep final responses concrete: executed command, result, path to the relevant artifact, and any follow-up command. +- Before `dump`, check `git status` if the result may overwrite or mix with already made source changes. +- Keep failed test artifacts in `workPath/temp/<runner-id>/runs/<run-id>/` for diagnostics; do not clean them up immediately. +- Report missing local 1C utilities as environment/installation problems, not as project source errors. +- Keep final answers specific: the command run, the result, the path to the relevant artifact, and any follow-up command. ## Output Discipline @@ -277,5 +358,5 @@ When reporting results, separate: - project source failures; - v8-runner command/config failures; -- failures locating the local 1C platform, EDT, IBCMD, or tools; -- test failures and their artifact paths. +- failures to find the local 1C platform, EDT, IBCMD, or tools; +- test failures and the paths to their artifacts. diff --git a/framework_eng/skills/tool-usage/v8-runner/references/command-selection.md b/framework_eng/skills/tool-usage/v8-runner/references/command-selection.md index 8968b7c5..a8b80ddb 100644 --- a/framework_eng/skills/tool-usage/v8-runner/references/command-selection.md +++ b/framework_eng/skills/tool-usage/v8-runner/references/command-selection.md @@ -1,10 +1,10 @@ # Command Selection -Choose commands by user intent, not by listing every CLI surface. +Choose commands by user intent, not by enumerating the entire CLI surface. -## Bootstrap +## Initialization -Use these when a project is missing `v8project.yaml` or generated runtime state: +Use when the project does not have `v8project.yaml` or generated runtime state: ```bash v8-runner config init @@ -14,9 +14,9 @@ v8-runner config init --builder IBCMD v8-runner init ``` -Inspect `v8project.yaml` after `config init` and before commands that create or mutate infobases, workspaces, or source files. +Study `v8project.yaml` after `config init` and before commands that create or modify the infobase, workspaces, or source files. -## Build And Recovery +## Build and Restore Apply Git-visible source changes to the configured infobase: @@ -24,19 +24,19 @@ Apply Git-visible source changes to the configured infobase: v8-runner build ``` -Limit build to one configured source-set: +Restrict the build to one configured source-set: ```bash v8-runner build --source-set <NAME> ``` -Recover after branch switches, rebases, large object moves, or suspicious incremental state: +Recover after branch switches, rebase, large object moves, or suspicious incremental state: ```bash v8-runner build --full-rebuild ``` -Use `test` directly when behavior matters; test commands perform `build` first. +Use `test` directly when behavior matters; test commands run `build` first. ## Syntax @@ -89,7 +89,7 @@ v8-runner launch mcp va ## Extensions -Update all configured extension properties: +Update the properties of all configured extensions: ```bash v8-runner extensions @@ -101,9 +101,9 @@ Update selected extension source-sets: v8-runner extensions --name <SOURCE_SET> ``` -## Dump, Convert, Load, And Artifacts +## Dump, Convert, Load, and Artifacts -Bring infobase changes back into Git-visible files: +Return infobase changes to Git-visible files: ```bash git status --short @@ -111,7 +111,7 @@ v8-runner dump --mode incremental git diff ``` -Dump specific objects when the backend supports it: +Export individual objects when the backend supports it: ```bash v8-runner dump --mode partial --object <TYPE:NAME> @@ -145,7 +145,7 @@ v8-runner make --output <TARGET> --extension <NAME> ## Launch -Launch 1C clients through the runner: +Start 1C clients through the runner: ```bash v8-runner launch designer @@ -154,7 +154,7 @@ v8-runner launch thick v8-runner launch ordinary ``` -Launch onec-client-mcp-devkit inside 1C without VA: +Start `onec-client-mcp-devkit` inside 1C without VA: ```bash v8-runner launch mcp @@ -162,12 +162,12 @@ v8-runner launch mcp --mode thin --mcp-port <PORT> v8-runner launch mcp --mcp-config <FILE> ``` -WS-mode flags (when v8-client-session-manager is reachable): +WS mode flags (when `v8-client-session-manager` is available): ```bash v8-runner launch mcp --mcp-transport=ws --manager-url ws://127.0.0.1:4000/sessions -v8-runner launch mcp --mcp-transport=legacy # force legacy without probe +v8-runner launch mcp --mcp-transport=mcp # force local HTTP MCP without probe v8-runner launch mcp --mcp-log-level=debug --client-uid <UUID> --corr-id <STR> ``` -`--mcp-transport=auto` (default) probes `manager_url` for 200 ms and chooses `ws` on success, `legacy` on failure. The same WS-flags work on `test yaxunit ...` and `test va ...`. See `project-workflows.md` for the full WS mode section, internal `kind` mapping, and `--json-message` output shape. +`--mcp-transport=auto` (default) performs a TCP probe of `manager_url` for 200 ms and selects `ws` on success and `mcp` on failure. The same WS flags also work for `test yaxunit ...` and `test va ...`. See the full WS mode section in `project-workflows.md`, the internal `kind` mapping, and the `--json-message` output format. diff --git a/framework_eng/skills/tool-usage/v8-runner/references/config-and-backends.md b/framework_eng/skills/tool-usage/v8-runner/references/config-and-backends.md index 1dc32445..0db8669a 100644 --- a/framework_eng/skills/tool-usage/v8-runner/references/config-and-backends.md +++ b/framework_eng/skills/tool-usage/v8-runner/references/config-and-backends.md @@ -53,3 +53,80 @@ Prefer `--source-set <NAME>` for narrow build, dump, convert, and artifact scena `v8project.local.yaml` is only an automatic local overlay. It can override only `workPath`, `infobase.*`, `tools.*`, `tests.*` and `mcp.*`; it must not set `source-set`, `format`, or `builder`, and it cannot be used as `--config`. `--workdir` takes precedence over both config files. + +## Vanessa Automation in `v8project.yaml` + +VA configuration is split into two levels: + +1. `v8project.yaml` / `v8project.local.yaml` specifies which external VA processing to launch, which JSON parameter template to use, and which feature profile is active. +2. The JSON from `tests.va.params_path` is a `VAParams` template. It contains Vanessa Automation settings themselves, including the TestClient profile table. `v8-runner` reads this template, creates a runtime copy in `workPath/temp/.../va-params.json`, applies the selected feature/tag/log profile, and passes the runtime copy to `/C` as `VAParams=<path>`. Do not edit the runtime copy as the source of truth. + +Minimal universal block in `v8project.yaml`: + +```yaml +tools: + va: + epf_path: '<path-to-vanessa-automation.epf>' + +tests: + va: + params_path: '<path-to-va-params-template.json>' + profile: '<default-feature-profile>' + fail_fast: false + profiles: + <default-feature-profile>: + feature_path: '<feature-file-or-directory>' + # optional: + # features_to_run: ['feature-name.feature'] + # filter_tags: ['tag-without-or-with-leading-at'] + # ignore_tags: ['wip'] + # scenario_filter: ['scenario name fragment'] +``` + +Meaning of the fields: + +- `tools.va.epf_path` — path to the external Vanessa Automation processing. The legacy `tests.va.epf_path` field is not supported. +- `tests.va.params_path` — path to the VAParams JSON template. This is not a generated file, but a stable project or local-environment template. +- `tests.va.profile` — name of the active feature profile; it must exist in `tests.va.profiles`. +- `tests.va.profiles.<name>.feature_path` — file or `.feature` directory that will be written into runtime VAParams as `КаталогФич`. +- `filter_tags` and `ignore_tags` can be written with or without `@`; the runner removes one leading `@` before writing to `СписокТеговОтбор` / `СписокТеговИсключение`. + +Use `v8project.local.yaml` for machine-local paths and secrets: for example, if `epf_path`, `params_path`, the TestClient user/password, or the path to a local infobase differ on the agent machine. Do not store real secrets in the shared `v8project.yaml`; it is better to move them into a local VAParams template and point to it through `tests.va.params_path` in `v8project.local.yaml`. + +### TestClient profile inside VAParams + +For `launch mcp va` and UI/UX verification through VA MCP, the test-client profile is not set by a separate `v8project.yaml` field, but by the `ДанныеКлиентовТестирования` table in the VAParams JSON template. It is the name of this row that is later passed to the MCP call `connect_test_client {"profileName":"<profile-name>"}`. + +Minimal structure: + +```json +{ + "ИспользоватьКомпонентуVanessaExt": "Истина", + "ИспользоватьВнешнююКомпонентуДляСкриншотов": "Истина", + "ДиапазонПортовTestclient": "<fixed-port>-<fixed-port>", + "ОпределятьРеальныйПортНаКоторомЗапустилсяКлиентТестирования": "Истина", + "ДанныеКлиентовТестирования": [ + { + "Имя": "<stable-profile-name>", + "Синоним": "<stable-profile-name>", + "ПутьКИнфобазе": "<same-infobase-connection-as-tested-app>", + "ПортЗапускаТестКлиента": <fixed-port>, + "ДопПараметры": "/N<user> /P<password> /DisableStartupDialogs /DisableUnsafeActionProtection", + "ТипКлиента": "Тонкий", + "ИмяКомпьютера": "localhost" + } + ] +} +``` + +Why these fields are named this way: + +- `Имя` — stable profile key that the agent passes to `connect_test_client`; the name must be independent of the specific task. +- `Синоним` — human-readable alias; if a separate alias is not needed, keep it equal to `Имя` so you do not create ambiguity. +- `ПутьКИнфобазе` — connection string of the application under test. The VA manager runs separately and must know which infobase to open as `/TESTCLIENT`. +- `ПортЗапускаТестКлиента` and `ДиапазонПортовTestclient` — fix the port so the agent can reliably connect to the expected client and not depend on old open TestClient processes. Before running, close old test-client processes or choose a free reserved port. +- `ДопПараметры` — everything that should not stop startup on dialogs: user/password or another authentication method, `/DisableStartupDialogs`, `/DisableUnsafeActionProtection`, and `/UC <code>` if needed. If the string contains secrets, the template must be local. +- `ТипКлиента` — the client type that VA should launch. For automation, thin client is usually chosen unless the project requires thick or ordinary client. +- `ИмяКомпьютера` — the machine where VA looks for/starts TestClient. For a local manager + test-client, this is `localhost`. +- Enable `ИспользоватьКомпонентуVanessaExt` and `ИспользоватьВнешнююКомпонентуДляСкриншотов` when the VA profile must work with OS windows and the real test-client PID. +- `ОпределятьРеальныйПортНаКоторомЗапустилсяКлиентТестирования` should stay enabled: VA should verify the actual process/port, not consider the launch successful based on a single profile. diff --git a/framework_eng/skills/tool-usage/v8-runner/references/learned-patterns.md b/framework_eng/skills/tool-usage/v8-runner/references/learned-patterns.md new file mode 100644 index 00000000..231fc2db --- /dev/null +++ b/framework_eng/skills/tool-usage/v8-runner/references/learned-patterns.md @@ -0,0 +1,25 @@ +# Learned Patterns — v8-runner + +## UI MCP via the platform test client requires two client roles + +``` +status: candidate +класс: Mixing the controlling MCP client and the test application during 1С UI automation +приём: For client MCP-tools, start the controlling 1С client with WS binding and /TESTMANAGER, separately start the test application with /TESTCLIENT -TPort and the same /N /P, then connect to it through test_client_start and verify connected=true +антиприём: Do not start the controlling client without /TESTMANAGER and do not treat a /TESTCLIENT process as suitable if it started without credentials or got stuck at the infobase login +почему: Without /TESTMANAGER the platform testing types are unavailable, and /TESTCLIENT without a correct infobase login is not considered a suitable client; proxied MCP calls hang or return connection errors +шаги: session_list -> live kind=1c-client -> infobase_info -> запуск /TESTCLIENT с /N /P -> test_client_start(port) -> open_form/click/get_value с session_id +источник: UI MCP run of a 1С form through session-manager: first errors in client mode and /TESTCLIENT connection, then a successful /TESTMANAGER + /TESTCLIENT chain with credentials +``` + +## Common launch helpers require a matrix of entry-point tests + +``` +status: candidate +класс: Changing a shared launch-helper without locking down all consuming commands +приём: When extending a helper that builds launch keys or payloads for multiple commands, immediately find all call sites and add or update tests for each entry point +антиприём: Do not cover only the command that prompted the change if the actual helper is used by other launch modes +почему: A new key or overlay becomes part of the contract for all helper consumers; without tests, a regression or unexpected change in behavior of another command will go unnoticed +шаги: rg over helper/import -> list of consuming commands -> separate CLI/unit checks for the new contract and the absence of duplicates for each consumer +источник: Refinement of `launch mcp va`: `/DisableUnsafeActionProtection` was added through the shared `vanessa_enterprise_launch_keys`, and after review the `test va` contract also had to be locked down +``` diff --git a/framework_eng/skills/tool-usage/v8-runner/references/project-workflows.md b/framework_eng/skills/tool-usage/v8-runner/references/project-workflows.md index 1599c60f..d0553d6f 100644 --- a/framework_eng/skills/tool-usage/v8-runner/references/project-workflows.md +++ b/framework_eng/skills/tool-usage/v8-runner/references/project-workflows.md @@ -1,6 +1,6 @@ # Project workflows -Use these flows based on the user's intent. Do not split the workflow just because the sources are Designer or EDT; many commands share the same lifecycle and differ only in `format`, `builder`, or tool availability. +Use these flows according to the user's intent. Do not split workflows just because the sources are Designer or EDT; many commands share the same lifecycle and differ only in `format`, `builder`, or tool availability. Read the exact support rules in `config-and-backends.md` together with this file. @@ -50,7 +50,7 @@ If `tools.client_mcp.extension` is configured, `build` also prepares this tool e 1. Launch in the background (`Bash run_in_background: true`) and redirect stdout to a file. 2. Subscribe via **Monitor** with the filter `ERROR:|Failed|error:` — a notification arrives on the first match. -3. Terminate the wait when the process exits OR stdout contains `ERROR:` / `Failed` / an explicit success marker. +3. Stop waiting when the process exits OR stdout contains `ERROR:` / `Failed` / an explicit success marker. 4. After completion: exit code 0 = success; otherwise read stdout for the error. ## Syntax @@ -148,17 +148,17 @@ Read `testing.md` for `launch mcp va`; it is part of the workflow for debugging > - v8-runner: upstream [`alkoleft/v8-runner-rust`](https://github.com/alkoleft/v8-runner-rust) → used fork [`SteelMorgan/v8-runner-rust`](https://github.com/SteelMorgan/v8-runner-rust) > - onec-client-mcp-devkit: used fork [`SteelMorgan/onec-client-mcp-devkit`](https://github.com/SteelMorgan/onec-client-mcp-devkit) -When [`v8-client-session-manager`](https://github.com/SteelMorgan/v8-client-session-manager) is running alongside the project, the 1С client can connect to it over WebSocket instead of the local HTTP MCP server (legacy `runMcp` mode). v8-runner makes the choice automatically. +When [`v8-client-session-manager`](https://github.com/SteelMorgan/v8-client-session-manager) is running alongside the project, the 1С client can connect to it over WebSocket instead of the local HTTP MCP server (`runMcp` mode). v8-runner makes the choice automatically. ### Transport and autodetection `tools.client_mcp.transport`: -- `auto` (default) — a short TCP probe (200 ms) to the host:port from `manager_url`. Listener detected → WS, otherwise → legacy. +- `auto` (default) — a short TCP probe (200 ms) to the host:port from `manager_url`. Listener detected → WS, otherwise → `mcp`. - `ws` — strict WS; if the manager is unavailable, launch fails with `session-manager unreachable at <url>`. -- `legacy` — the old HTTP mode without a probe. +- `mcp` — local HTTP MCP mode without a probe. -Override via `--mcp-transport={ws|legacy|auto}`. CLI takes priority over config. +Override via `--mcp-transport={ws|mcp|auto}`. CLI takes priority over config. ### What v8-runner injects into `/C` in the WS branch @@ -200,13 +200,13 @@ WS branch: ```json { "transport": "ws", "client_uid": "...", "kind": "...", "manager_url": "...", "corr_id": "..." } ``` -Legacy branch: +MCP branch: ```json -{ "transport": "legacy", "mcp_port": 9874 } +{ "transport": "mcp", "mcp_port": 9874 } ``` An external orchestrator (CI, AI agent) uses `client_uid` to find the session in the manager's `session_list`. The structure of the session entry and `session_list` is described in the `v8-session-manager` skill. ### The manager is not started from v8-runner -v8-runner only connects to a running manager. Starting the manager is a separate step (`cargo run --release` in the `v8-client-session-manager` repo, or the `systemd/v8-session-manager.service` unit, or Docker Compose). If the manager is not needed, `--mcp-transport=legacy` forces the old flow. +v8-runner only connects to a running manager. Starting the manager is a separate step (`cargo run --release` in the `v8-client-session-manager` repo, or the `systemd/v8-session-manager.service` unit, or Docker Compose). If the manager is not needed, `--mcp-transport=mcp` forces the local HTTP MCP flow. diff --git a/framework_eng/skills/tool-usage/v8-runner/references/testing.md b/framework_eng/skills/tool-usage/v8-runner/references/testing.md index 94d621ba..d03a7926 100644 --- a/framework_eng/skills/tool-usage/v8-runner/references/testing.md +++ b/framework_eng/skills/tool-usage/v8-runner/references/testing.md @@ -25,7 +25,7 @@ CLI alternative — `tools.client_mcp.*` in `v8project.yaml`: ```yaml tools: client_mcp: - transport: auto # ws | legacy | auto + transport: auto # mcp | ws | auto manager_url: ws://127.0.0.1:4000/sessions log_level: info ws_timeout_ms: 1000 @@ -40,8 +40,8 @@ Priority: CLI flag → yaml → internal defaults. If `yaxunit_runner` / `vanessa_test_client` does not appear in the manager's `session_list`: 1. **Manager log** — `/tmp/v8sm/logs/mcp/actions.log` (path depends on the manager's `workPath`). Look for `WS connection accepted (handshake completed)` in the run window. Start the manager with `--log-level debug` if it is set to `info`. -2. **`/C` payload** — start v8-runner with `--log-level=trace` (at the global options level) and check whether `mcpMode=ws;manager_url=...` was appended to `RunUnitTests=...`. If not, `decide_mcp_transport` returned `Legacy`. -3. **1С Enterprise log** — `<workPath>/temp/yaxunit/runs/<run-id>/enterprise.out.log` and `runner.log`. Look for `[MCP INFO ...] Logging params applied` and `provider registration ...` — this is MCP initialization diagnostics from the BSL devkit side. +2. **`/C` payload** — start v8-runner with `--log-level=trace` (at the global options level) and check whether `mcpMode=ws;manager_url=...` was appended to `RunUnitTests=...`. If not, transport selection fell back to `mcp`. +3. **1C Enterprise log** — `<workPath>/temp/yaxunit/runs/<run-id>/enterprise.out.log` and `runner.log`. Look for `[MCP INFO ...] Logging params applied` and `provider registration ...` — this is MCP initialization diagnostics from the BSL devkit side. 4. **v8-runner stdout** — the diagnostic block `[MCP INFO ...]` appears in the `diagnostic` section of the `test` output (only when MCP client initialization succeeds). Resolved (DRIVE 2026-05-11): `yaxunit_runner` was not registered in the manager's `session_list`, although v8-runner was correctly inserting the WS payload into `/C`. The trace log showed a race condition in BSL: the idle handler `Мсп_ОтложенныйСтарт_Тик` in `client_mcp` was scheduled with a 1 second interval, and YAXUNIT with `closeAfterTests: true` closed the application in about 1 second (tests ~200ms). The idle handler did not have time to tick. Fix: reduce the interval `1` → `0.1` in `exts/client_mcp/Ext/ManagedApplicationModule.bsl` (call `ПодключитьОбработчикОжидания("Мсп_ОтложенныйСтарт_Тик", 0.1, Истина)`). After the fix, yaxunit-Enterprise registers a WS session (`kind=yaxunit_runner`, tools=24). @@ -68,6 +68,8 @@ Use module runs for narrow code changes. Use full test runs before pushing or fo ## Vanessa Automation +The VA startup config is described in `references/config-and-backends.md`, section "Vanessa Automation in `v8project.yaml`": `tools.va.epf_path`, `tests.va.params_path`, `tests.va.profile`, `tests.va.profiles.*`, and the TestClient profile inside VAParams. Before changing commands, check exactly these sections first. + Run the configured Vanessa Automation profile: ```bash @@ -89,12 +91,61 @@ Use `launch mcp va` when the goal is interactive debugging of Vanessa Automation ```bash v8-runner launch mcp va v8-runner launch mcp va --mode thin -v8-runner launch mcp va --mcp-port <PORT> -v8-runner launch mcp va --mcp-config <FILE> +v8-runner launch mcp va --mcp-transport ws --manager-url ws://127.0.0.1:4000/sessions ``` This launches the client MCP server in 1С and loads Vanessa Automation from `tools.va`. Prefer it for exploratory VA work; use `test va` for the configured automated test run. +Before starting, check the config: + +1. `tools.va.epf_path` points to an existing `vanessa-automation.epf`. +2. `tests.va.params_path` points to the VAParams JSON template. +3. `tests.va.profile` exists in `tests.va.profiles`. +4. The VAParams contains a TestClient profile in `ДанныеКлиентовТестирования`; its `Имя` is the future `profileName` for `connect_test_client`. + +### Exact VA manager → TestClient chain + +1. Make sure the session-manager responds to `session_list`. If the manager is not running, start it using the `v8-session-manager` skill. + +2. Start the VA test-manager via `v8-runner launch mcp va` in detached mode if the client must remain alive after the shell command returns: + +```bash +uid=$(cat /proc/sys/kernel/random/uuid) +setsid nohup v8-runner --no-color --log-level debug launch mcp va \ + --mcp-transport ws \ + --manager-url ws://127.0.0.1:4000/sessions \ + --client-uid "$uid" \ + --corr-id "va-$uid" \ + --mcp-log-level debug \ + --mcp-ws-timeout-ms 5000 \ + > "/tmp/va-mcp-$uid.log" 2>&1 & +echo $! +``` + +3. Wait for the VA manager live session: + +```json +{"name":"session_list","arguments":{}} +``` + +Readiness criterion: `kind=vanessa_test_client`, `state=active`, `disconnected_secs_ago=null`, `inflight=0`, and VA tools have appeared (`connect_test_client`, `get_form_analysis`). Having the tool name only in cached `tools/list` does not count as readiness. Normal session and VA tool appearance after startup takes 10-90 seconds; poll `session_list` every 5-10 seconds and use 120 seconds as the diagnostic limit. + +4. Connect the application under test. The VA manager starts it according to the profile from VAParams; the agent must not separately launch `/TESTCLIENT` for this VA path. `connect_test_client` takes the required `profileName` argument: + +```json +{"name":"connect_test_client","arguments":{"profileName":"<test-client-profile-name>"}} +``` + +If there are multiple live sessions, pass the `session_id` of the VA manager session in every MCP call. A successful launch must yield the real test-client PID in the VA profile/log, not `0`. After that, VA client MCP methods are available: form analysis, command interface and form element control, data reading, screenshots, and VA action execution. + +5. After the investigation, close the test client. `close_test_client` can be called with the same `profileName`; without it, the tool closes the currently connected profile: + +```json +{"name":"close_test_client","arguments":{"profileName":"<test-client-profile-name>"}} +``` + +If the VA manager was launched only for investigation, stop it as well by normal client termination or by targeted termination of the saved PID. Do not leave open TestClient processes before the next launch on the same fixed port. + ## Launch Options During Tests Test commands accept launch-related options such as `--client-mode`, `--c`, `--execute`, `--use-privileged-mode`, and repeatable `--raw-key`. @@ -127,7 +178,7 @@ v8-runner syntax edt |------------|----------| | Monitoring v8-runner stdout | The agent MUST read v8-runner stdout every **20 seconds** while the test is running. Standard output contains success and failure markers immediately (`[diagnostic]`, `[artifact]`, `ERROR: runtime error: test run reported failures`, etc.) - this is more reliable than the event log. | | Abort on error | If the string `ERROR:` appears in stdout (for example, `ERROR: runtime error: test run reported failures`) - the agent MUST stop waiting, read `runner.log` + `junit/junit.xml` in the run directory, and switch to diagnostics. Check the event log additionally if the primary artifacts are insufficient. | -| Hang detection | If there are no new lines in v8-runner stdout for more than 60 seconds and the `1cv8c.*vanessa-automation` process is still alive - the agent MUST take screenshots (noVNC/X11) and assess whether the test is still alive. | +| Hang detection | If there are no new lines in v8-runner stdout for more than 60 seconds and the `1cv8c.*vanessa-automation` process is still alive - the agent MUST check the manager/test-client processes and primary startup logs, then switch to Vanessa diagnostics. | | Correct termination condition | Exit the wait when `va-status.log` appears (created on both success and failure) OR the `1cv8c.*vanessa-automation` process disappears OR `ERROR:` appears in stdout. **Do not use only `va-status.json`** - it is created only when the scenario finishes normally; on early failures (step error, client crash) it will not be there, and the blocking wait will hang. | | Required artifact analysis | After the run the agent MUST check `va-status.json` and `vanessa-execution.log` under `workPath/temp/<runner-id>/runs/<run-id>/`. | | Required event-log analysis | After the run the agent MUST check `event-log` if the scenario failed or the run looks suspicious. | @@ -140,7 +191,7 @@ v8-runner syntax edt Before starting `v8-runner test va`, the runner agent performs this procedure: -1. Read `v8project.yaml` -> the `tests.va` section, active profile (`tests.va.profile` or the one passed via `--profile`). +1. Read `v8project.yaml` → the `tests.va` section, active profile (`tests.va.profile` or the one passed via `--profile`). 2. Compare the feature path in the profile with the expected `vanessa-tests/features/tasks/<taskID>/`. 3. If it does not match, add a task-specific `tests.va.profiles.<taskID>` profile (either in `v8project.yaml` or through `v8project.local.yaml`) and run with it. 4. When working with tags, remember: `filter_tags` / `ignore_tags` are written **without a leading `@`** in `СписокТеговОтбор` / `СписокТеговИсключение`. diff --git a/framework_eng/skills/tool-usage/v8-session-manager/SKILL.md b/framework_eng/skills/tool-usage/v8-session-manager/SKILL.md index f193db0f..366683c9 100644 --- a/framework_eng/skills/tool-usage/v8-session-manager/SKILL.md +++ b/framework_eng/skills/tool-usage/v8-session-manager/SKILL.md @@ -1,15 +1,15 @@ --- name: v8-session-manager -description: "Use for working with the 1С session manager: launching, configuration, connecting clients, reading session_list, calling proxied MCP tools from 1С extensions. Helps with errors «no active sessions» / «session_id required» and connecting a client via `mcpMode=ws`." +description: "1C session manager: startup, clients, session_list, MCP" provides_capabilities: - # Built-in manager tools — always available while it is running. + # Built-in manager tools — always available while the manager is running. - session_list - tools_cache_reset - # Tools that the manager proxies from connected 1С clients. + # Tools proxied by the manager from connected 1C clients. # WARNING: their names in tools/list are read from the persistent tools-cache - # (ADR-0035) — having a name does NOT guarantee that the call is available. - # Without a live session of the required kind the call will return an MCP - # tool error `isError:true, _meta.error_code="no_live_session"`. + # (ADR-0035) — the presence of a name does NOT guarantee that the call is available. + # Without a live session of the required kind, the call returns MCP tool error + # `isError:true, _meta.error_code="no_live_session"`. # client_mcp / system: - infobase_info - system_spawn_1c_client @@ -34,55 +34,87 @@ provides_capabilities: # v8-session-manager -A thin MCP aggregator: accepts WS connections from 1С clients and publishes their MCP tools on a single HTTP endpoint for the AI agent. +A thin MCP aggregator: accepts WS connections from 1C clients and publishes their MCP tools on a single HTTP endpoint for the AI agent. -## What the manager provides itself +## What the manager itself provides | Capability | Source | |---|---| -| Built-in tool — `session_list` (read-only registry snapshot) | manager | +| Built-in tool — `session_list` (read-only snapshot of the registry) | manager | | Built-in tool — `tools_cache_reset` (full reset or by `config_id`) | manager (ADR-0035) | -| Showcase of proxied tools from connected clients | 1С extensions | +| Showcase of proxied tools from connected clients | 1C extensions | | Persistent showcase cache (`workPath/tools_cache.json`, TTL 5d) | manager (ADR-0035) | -| Routing a call to the correct session by `session_id` | manager | +| Routing a call to the right session by `session_id` | manager | | Soft reconnect of a client by `client_uid` | manager | -| FIFO order of calls into one session | manager | +| FIFO order of calls to one session | manager | -Everything else (domain tools — form descriptions, test runs, navigation, etc.) is added by **1С extensions**, not by the manager. There is a separate skill for each extension. +Everything else (domain tools - form descriptions, test launch, navigation, etc.) is added **by 1C extensions**, not by the manager. Separate skill for each extension. -## Proxied tools cache (ADR-0035) — key point +## Proxied tools cache (ADR-0035) - the key point -The manager's `tools/list` is read from a **persistent cache on disk**, not only from live WS sessions. Implications for the agent: +`tools/list` of the manager is read from a **persistent cache on disk**, not only from live WS sessions. Consequences for the agent: -- **A tool name in `tools/list` ≠ a successful call.** The cache survives client disconnect and manager restart — the name stays on the showcase, but a call without a live session returns an MCP tool error `isError:true, _meta.error_code="no_live_session"`. This is not a bug, it is the contract. -- **Why it is done this way:** some MCP harnesses (in particular Claude Code) respond unreliably to `notifications/tools/list_changed`. The persistent cache removes the dependency on stable notification handling. -- **When `tools_cache_reset` is needed:** when a tool has been intentionally removed from the extension and will not come back (or the configuration has been removed completely). Otherwise it will linger until the TTL expires (by default 5 days from the last `session.register`). Full reset — without arguments; targeted — `{"config_id": "<id>"}` (taken from `session_list[*].config_id`). -- **What the cache does NOT do:** it does not start 1С, does not reproduce the tool response, does not replace a live session. It only stores names and `inputSchema`. +- **A tool name in `tools/list` does not equal call availability.** The cache survives client disconnect and manager restart - the name remains on the showcase, but a call without a live session will return MCP tool error `isError:true, _meta.error_code="no_live_session"`. This is not a bug, it is the contract. +- **Why this is done:** some MCP harnesses (in particular Claude Code) react unreliably to `notifications/tools/list_changed`. The persistent cache removes dependence on stable notification handling. +- **When `tools_cache_reset` is needed:** when a tool has been intentionally removed from the extension and will not return anymore (or the configuration has been removed completely). Otherwise it will remain until the TTL expires (by default 5 days from the last `session.register`). Full reset is without arguments; targeted reset is `{"config_id": "<id>"}` (taken from `session_list[*].config_id`). +- **What the cache does NOT do:** it does not start 1C, does not reproduce a tool response, and does not replace the live session. It only stores names and `inputSchema`. -Details — `references/sessions-and-tools.md` § «Persistent cache and `tools_cache_reset`». +Details - `references/sessions-and-tools.md` § "Persistent cache and `tools_cache_reset`". + +## UI MCP session diagnostics + +For client UI tools (`open_form`, `click`, `input`, `get_value`, `get_table_rows`, `test_client_start`), first prove that there is a live 1C client, not just a record in the cached showcase. + +Minimum order: + +1. Call `session_list`. +2. Find a live session of the required infobase: `state=active`, `disconnected_secs_ago=null`, `infobase_name=<required infobase>`. +3. For ordinary UI MCP through the platform test client, you need a control session `kind=1c-client`; for Vanessa, you need `kind=vanessa_test_client` and VA tools beyond the base set. +4. If there are multiple live sessions, always pass `session_id` to every proxied tool call. +5. Before a long UI scenario, check a simple call (`infobase_info`) and `inflight=0`. + +For UI/UX acceptance of 1C forms, the main visual path is described in `va-visual-check`. The basic chain through Vanessa/TestClient: + +1. Verify through `session_list` that the VA manager is alive: `kind=vanessa_test_client`, `state=active`, `tools` contains VA tools, `inflight=0`. +2. Start or connect the test client through the VA tool `connect_test_client` with the required profile. +3. Check that VA returned a real PID of the test client, not `0`/empty. +4. Get windows through `get_window_list_os`. +5. Take a PNG through `get_window_screenshot_os`; see `va-visual-check` for the Linux/Xvfb recipe for black PNGs and the fallback conditions. +6. Check that the PNG is not empty and not monochrome/black. + +`tools/list` does not prove that this chain is ready: the list can come from the persistent cache. Proof is a live session + successful smoke `connect_test_client -> get_window_list_os -> get_window_screenshot_os`. + +If a proxied call hangs or `inflight` stays above zero: + +- for the test-client form, first apply `va-visual-check`; if a fallback is needed, record the completed VA steps, the reason, and the residual risk; +- check `/tmp/mcp-client.log` or the project log of client_mcp: did `MCP_TOOL_CALL` arrive, was the WS session registered, is there no platform-type error; +- do not reset `tools_cache_reset` as the first action: the cache does not block live calls and does not fix a hung client; +- if the client was started in the wrong mode, terminate only your saved PID and restart it with the correct command through `v8-runner`. + +For the startup chain `1c-client` + `/TESTMANAGER` + separate `/TESTCLIENT`, see the `v8-runner` skill, section "UI MCP through the platform test client". ## Boundaries The manager does **not**: -- launch 1С clients (that is the job of an external orchestrator, typically `v8-runner`); -- store state across restarts (the registry is in-memory); -- contain business logic (transport + routing only); -- manage the infobase. +- start 1C clients (that is the job of an external orchestrator, typically `v8-runner`); +- store state across restarts (registry is in-memory); +- contain business logic (only transport + routing); +- manage an infobase. -## Task Routing +## Task routing | Task | Reference | |---|---| | What each layer of the stack does (addin → devkit → BSL → manager → AI) | `references/architecture.md` | -| Bring up the manager, connect a 1С client | `references/bootstrap.md` | +| Start the manager, connect a 1C client | `references/bootstrap.md` | | Read `session_list`, call a tool, understand why it is missing | `references/sessions-and-tools.md` | -| Add a new tool to a 1С extension | `references/extending-tools.md` | -| Manager does not start / client is not visible / tool is hidden / call fails | `references/troubleshooting.md` | +| Add a new tool to a 1C extension | `references/extending-tools.md` | +| The manager does not start / the client is not visible / the tool is hidden / the call fails | `references/troubleshooting.md` | ## Guardrails (hard) -1. **Do not edit the manager source code** (`src/`, `Cargo.toml`, `systemd/`, `etc/`, `spec/`, ADR in `docs/decisions/`) — this is the upstream repository. All manager-level changes are coordinated in a separate task. -2. **Do not create or modify MCP tools without the user's direct permission.** Tools live in 1С extensions (`exts/<extension>/`); editing/adding them means changing the public contract. -3. **Do not pull business logic into the manager.** If a task requires "the manager should do X", that is a signal that X belongs either in the extension or in the launch orchestrator. -4. **Do not try to start a 1С client through the manager.** The manager only accepts an incoming WS connection. Starting 1С is the responsibility of `v8-runner`. +1. **Do not edit the manager sources** (`src/`, `Cargo.toml`, `systemd/`, `etc/`, `spec/`, ADR in `docs/decisions/`) — this is the upstream repository. All manager-level changes are agreed as a separate task. +2. **Do not create or change MCP tools without explicit user permission.** Tools live in 1C extensions (`exts/<extension>/`); editing/adding them means changing the public contract. +3. **Do not pull business logic into the manager.** If a task requires "the manager should do X", that is a signal that X belongs either to an extension or to the launch orchestrator. +4. **Do not try to start a 1C client through the manager.** The manager only accepts an incoming WS connection. Starting 1C is the `v8-runner` task. 5. **Ask the user before building/restarting the client.** Any operation that changes project state (build, restart) requires confirmation. diff --git a/framework_eng/skills/tool-usage/vanessa/va-visual-check/SKILL.md b/framework_eng/skills/tool-usage/vanessa/va-visual-check/SKILL.md new file mode 100644 index 00000000..118e3890 --- /dev/null +++ b/framework_eng/skills/tool-usage/vanessa/va-visual-check/SKILL.md @@ -0,0 +1,102 @@ +--- +name: va-visual-check +description: "Vanessa/VA MCP: visual checking of 1C forms and screenshots" +--- + +# VA Visual Check + +Use this skill for visual validation of 1C forms through Vanessa Automation / TestClient and VA MCP. This is the dedicated route for UI/UX screenshots of managed 1C forms. + +## Main Route + +1. If the VA MCP manager session is not up yet, start it strictly according to the `v8-runner` skill; here check only the live session `kind=vanessa_test_client` in `session_list`. +2. Connect the test client through `connect_test_client` with the profile from the VA settings; do not guess the profile name. +3. Make sure a real test-client is connected: the profile/log/state of VA contains a PID, not `0`. +4. Open the required form through VA/TestClient tools. +5. Get the structured state of the form (`get_form_analysis`, `get_window_list_testclient`, reading elements/tables). +6. Get the list of OS windows through `get_window_list_os`. +7. Critical: perform screenshot operations through VA MCP strictly synchronously. Do not launch several `get_window_screenshot_os` in parallel and do not use `multi_tool_use.parallel` for them: send one request, wait for the full response, and make sure through `session_list` that the session is alive and `inflight=0`; only then send the next request. +8. Take a PNG through `get_window_screenshot_os`: + +```text +get_window_screenshot_os { + "window_title": "<точный заголовок окна формы>", + "file_name": "<путь>.png", + "color_mode": "color" +} +``` + +9. Check the PNG: the file is created, the size is as expected, the image is not empty, not single-color, and not black. + +## Linux headless X11/Xvfb without a window manager + +This recipe applies only to Linux on a virtual X11/Xvfb display without a graphical environment/window manager. It is needed when `get_window_list_os` sees the form window, but `get_window_screenshot_os` returns a black or nearly empty PNG. + +X11 commands are used only to expose an already opened window. The preferred screenshot after that is still taken through VA MCP. + +1. Find the X11 id of the form window: + +```bash +xwininfo -root -tree | sed -n '1,220p' +``` + +If `wmctrl -l` or other EWMH tools respond with `Cannot get client list properties` / `_NET_CLIENT_LIST or _WIN_CLIENT_LIST`, this is expected for Xvfb without a window manager. Use the `xwininfo` tree, not the window-manager client list. + +2. Verify that the found window belongs to the test-client, not the VA manager: + +```bash +xprop -id <window_id> _NET_WM_PID WM_NAME WM_CLASS +``` + +`_NET_WM_PID` must match the PID of the connected test-client. If the PID is not yet fixed, get it from the VA profile/connection state; use the window title only as an additional filter. + +3. Move, resize, and raise the window: + +```bash +xdotool windowmove <window_id> 0 0 || true +xdotool windowsize <window_id> 1200 800 || true +xdotool windowraise <window_id> || true +xdotool windowactivate --sync <window_id> || true +xwininfo -id <window_id> | sed -n '1,60p' +``` + +In an environment without a window manager, `windowactivate` may fail with a message about `_NET_ACTIVE_WINDOW`; this is not a blocker if `xwininfo` shows `Map State: IsViewable`. + +4. Repeat the standard VA screenshot through `get_window_screenshot_os`. + +5. Repeat the PNG check. If the screenshot is still black/monochrome, move to the fallback solution below and explicitly record the reason. + +## Browser fallback + +VA MCP is the preferred route for ordinary 1C forms because it works with the real TestClient and gives both the form structure and a visual PNG. + +Web/browser fallback is allowed when: + +- VA MCP is unavailable or does not pass readiness; +- `connect_test_client` does not provide a real PID; +- `get_window_list_os` does not see the required window; +- `get_window_screenshot_os` remains black/monochrome after the Linux/Xvfb recipe; +- the behavior being checked relates to the browser layer: DOM/CSS/HTML, console/network, web-auth/publication, viewport/pixel rendering, browser extension, browser-only upload/download/clipboard. + +Before fallback, record: + +- which VA capability failed; +- which VA-route steps have already been completed; +- why the browser/web-client will provide enough signal for the current task; +- residual risk: the web-client may differ from the thin/thick 1C client. + +For browser fallback, use the relevant browser skills (`web-test-1c`, `playwright`, `screenshot`) for their intended purpose. Do not mix the result: if the artifact was obtained through web/browser fallback, call it that in the report. + +## What Not To Do + +- Do not replace the VA MCP screenshot with a direct X11/noVNC/OS screenshot without an explicit fallback note. +- Do not choose the window only by title in Xvfb: the VA manager and the test-client can have identical titles. +- Do not treat `get_window_list_testclient` as visual confirmation: it is the structure of internal windows, not a PNG. +- Do not continue based on cached `tools/list`: you need a live session of the required `kind`. + +--- +depends_on: + - framework/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md + - framework/skills/tool-usage/v8-session-manager/SKILL.md + - framework/skills/bsl-practices/form-visual-requirements/SKILL.md +--- diff --git a/framework_eng/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md b/framework_eng/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md index 0151b30c..b6a5616a 100644 --- a/framework_eng/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md +++ b/framework_eng/skills/tool-usage/vanessa/vanessa-authoring/SKILL.md @@ -1,82 +1,85 @@ --- name: vanessa-authoring -description: "Use for authoring and refining Vanessa Automation feature scenarios from real project requirements." +description: "Vanessa: authoring and refining feature scenarios" uses_capabilities: - run_vanessa - build_project --- -# Vanessa Automation Scenario Authoring +# Vanessa Automation scenario authoring -## Writing Algorithm +## Writing algorithm -1. Identify the requirement source: a specification or a business case (`vanessa-scenario-policy`). -2. Determine **which user** runs the scenario (see "User Context"). -3. Find suitable steps: first in the Vanessa library, then in the project's scenarios. -4. **Inspect the interface and fill out the form manually**. The preferred path is Vanessa Automation MCP tools through `v8-client-session-manager` (see "MCP Research through Vanessa Automation"). If they are unavailable, use the web client (`gui-control` / `screenshot` / `chrome-devtools` snapshot). In both cases, record the exact names and titles of elements, fields, buttons, and tabs **before** referencing them in steps; do not guess identifiers (Title vs name - see `vanessa-scenario-policy`). -5. Write one smoke scenario: open -> one action -> one observable outcome. -6. If a step does not exist, mark `# unknown_step_candidate`; do not invent a BSL step. -7. Submit the scenario for execution through `v8-runner` (`v8-runner test va`). +1. Determine the source of the requirement - specification or business case (`vanessa-scenario-policy`). +2. Determine **under which user** the scenario is executed (see "User Context"). +3. Find suitable steps: first in the Vanessa library, then in the project scenarios. +4. **Inspect the interface and fill out the form manually**. The preferred path is the Vanessa Automation MCP tools through `v8-client-session-manager` (see "MCP Investigation through Vanessa Automation"). For UI/UX form checks, use `va-visual-check`: VA MCP screenshot route, Linux/Xvfb recipe, and browser fallback with reason logging. In any case, record the exact names and captions of elements, fields, buttons, and tabs **before** referencing them in steps; do not guess identifiers (Title vs name - see `vanessa-scenario-policy`). +5. Write one smoke scenario: open → one action → one observable outcome. +6. If a step does not exist - mark `# unknown_step_candidate`, do not invent a BSL step. +7. Pass the scenario for execution through `v8-runner` (`v8-runner test va`). --- -## MCP Research through Vanessa Automation +## MCP Investigation through Vanessa Automation -This section captures the universal workflow verified on Vanessa Automation `1.2.043.28`. For another version, first reconcile behavior with the official VA instruction and live tool schemas. +This section captures the universal workflow validated on Vanessa Automation `1.2.043.28`. For another version, first verify the behavior against the official VA instructions and live tool schemas. -Official Vanessa Automation source: <https://github.com/Pr-Mex/vanessa-automation>. AI/MCP instructions are in `docs/AI/`. Take VA updates from the official repository/releases, not by editing vendor code in the project. WS startup uses our `v8-runner` fork <https://github.com/SteelMorgan/v8-runner-rust> and `v8-client-session-manager` <https://github.com/SteelMorgan/v8-client-session-manager>. +Official Vanessa Automation source: <https://github.com/Pr-Mex/vanessa-automation>. AI/MCP instructions are in `docs/AI/`. Take VA updates from the official repository/releases, not by modifying vendor code in the project. For WS launch, we use our fork `v8-runner` <https://github.com/SteelMorgan/v8-runner-rust> and `v8-client-session-manager` <https://github.com/SteelMorgan/v8-client-session-manager>. -### Version and readiness checks +### Version and readiness check -1. Start a VA manager session through `v8-runner launch mcp va --mcp-transport ws ...` (the detailed launch shape is in the `v8-runner` skill, section "Vanessa Automation MCP through session-manager"). -2. Through `session_list`, wait for a live `kind=vanessa_test_client` session where VA tools appeared: for example `get_VanessaAutomation_state`, `connect_test_client`, `get_form_analysis`, `manage_command_interface`. +1. If the VA manager session is not already running, start it strictly through the `v8-runner` skill (section "Vanessa Automation MCP via session-manager"); do not assemble the launch string in this skill. +2. Through `session_list`, wait for a live session of `kind=vanessa_test_client`, where VA tools appear: for example `get_VanessaAutomation_state`, `connect_test_client`, `get_form_analysis`, `manage_command_interface`. 3. Call `get_environment_data` or the nearest available VA environment tool and record the Vanessa Automation version in the task context. -4. If service data tools are needed (`get_table_data`, `get_object_attributes`), verify that the VA service extension is loaded into the tested infobase. Having fresh extension files in source is not enough: runtime tools look for forms in the connected database. +4. If service data tools are needed (`get_table_data`, `get_object_attributes`), verify that the VA service extension is loaded into the test database. The presence of fresh extension files in source is not enough: runtime tools look for forms in the connected database. -### Mandatory operation sequence +### Required workflow sequence -1. **Connect the test client.** Before any tools that read or control the tested application's UI, call `connect_test_client` with the test-client profile. Choose the profile from VA settings/profile table; do not guess the name. -2. **Research the form through VA tools.** Use live tool schemas and descriptions from `session_list` / `tools/list`, because the tool set expands between VA versions. Do not freeze a closed list as complete. As of VA `1.2.043.28`, the main tool classes are: command interface, window list, active window data, form analysis, form element actions, object attribute reading, table/data reading, screenshots, user action recording, and `.feature` step execution. -3. **Do not write data without a test purpose.** For filling research you may open a creation form, read attributes, and try navigation; save/post only when needed for validating filling or the scenario, and follow test-data isolation rules. -4. **Close the test client.** After research, execution, or an error, always call `close_test_client` for the connected profile. If the VA manager session was started manually for research, stop it too after the work is done. +1. **Connect the test client.** Before any tools that read or control the interface of the tested application, call `connect_test_client` with the test client profile. Choose the profile from VA settings/the `ДанныеКлиентовТестирования` profile table in VAParams; do not guess the name. How to form `tools.va` / `tests.va` in `v8project.yaml` and the TestClient profile inside VAParams is described in `v8-runner`, `references/config-and-backends.md`. +2. **Inspect the form through VA tools.** Use the live tool schemas and their descriptions from `session_list` / `tools/list`, because the tool set expands between VA versions. Do not treat a closed list as complete. As of VA `1.2.043.28`, the main tool classes are: command interface, window list, active window data, form analysis, form element actions, object attribute reading, table/data reading, screenshots, user action recording, execution of `.feature` steps. +3. **Take a visual control screenshot.** For any UI/UX check, after opening the required form, use `va-visual-check`: first VA MCP PNG, then if needed the Linux/Xvfb recipe or browser fallback with reason logging. +4. **Do not write data without a test purpose.** For form fill-in research, you can open the creation form, read attributes, and try navigation; write/post only if it is required to verify fill-in or the scenario, and follow test data isolation rules. +5. **Close the test client.** After the investigation, execution, or an error, call `close_test_client` for the connected profile. If the VA manager session was launched manually for investigation, stop it after you finish. -Antipatterns: +Anti-patterns: -- calling `get_form_analysis`, `manage_command_interface`, `manage_form_elements`, `get_object_attributes`, screenshot/recording tools before `connect_test_client`; -- treating a tool name in cached `tools/list` as proof of availability - check the live session of the required `kind`; -- leaving the test client open after the operation; -- editing vendor VA/VAExtension code when the issue is version, extension loading, or launch configuration. +- call `get_form_analysis`, `manage_command_interface`, `manage_form_elements`, `get_object_attributes`, screenshot/recording tools before `connect_test_client`; +- treat the internal `get_window_list_testclient` window list as a visual screenshot: it is needed for structure and navigation, while UI/UX acceptance requires PNG according to `va-visual-check` rules; +- treat the presence of a tool name in cached `tools/list` as proof of availability - check the live session of the required `kind`; +- keep the test client open after the operation is complete; +- modify VA/VAExtension vendor code when the problem is the version, extension loading, or launch configuration. -### Embedding into scenario authoring +### Integration into scenario authoring -Before writing a `.feature` for a new form, first perform MCP research: +Before writing a `.feature` for a new form, first perform MCP investigation: 1. Open the section/command through `manage_command_interface` or direct navigation. 2. Get `get_active_window_data` and `get_form_analysis`. -3. For an object form, get `get_object_attributes` in header-attributes and tabular-sections modes. -4. If needed, get reference data through `get_table_data` to choose existing valid values. -5. Based on the result, record exact commands, element names, required fields, conditional visibility/availability, and filling order in the scenario context. -6. Only after that write Gherkin steps and subscenarios. +3. Create a visual PNG of the form using `va-visual-check` and verify it against `form-visual-requirements`. +4. For the object form, get `get_object_attributes` in header attribute mode and tabular section mode. +5. If needed, get reference data through `get_table_data` to choose existing valid values. +6. Based on the results, record the exact commands, element names, required fields, conditional visibility/availability, visual notes, and fill order in the scenario context. +7. Only after that write the Gherkin steps and subscenarios. -## Manual Form Filling Before the Scenario (MUST) +## Manual form fill-in before the scenario (MUST) -> Before writing a NEW scenario for a document, the agent first fills out the form **manually in the web client**, checking the real form structure at each step. The `.feature` file is written only AFTER successful manual filling. +> Before writing a NEW scenario for a document, the agent first fills out the form **through Vanessa/TestClient**, checking the real form composition at each step. The platform TestClient MCP is allowed only for an action that VA MCP fundamentally does not provide, with the reason recorded in the context. The `.feature` is written only AFTER successful fill-in through VA/TestClient. Web client is allowed only for browser functions that VA MCP fundamentally does not support. | Requirement | Description | |-----------|----------| -| Snapshot after each field | After changing **each** field, take the form structure snapshot again (`take_snapshot` / `screenshot`): changing a field affects the visibility, availability, and **requiredness** of other fields (`ПриИзменении` handlers). The full set of required fields is discovered **iteratively**, not guessed in advance | -| Study Help and reference data | Before filling out the form, read the document Help/tooltip and reference data to understand the usage scenarios and filling order. They may be empty, but typical objects often have them populated | -| All key header fields | Fill out fields according to the document's intended purpose (Organization, Counterparty, Agreement, Warehouse, etc. - whatever the document semantics require) | -| Required tabular sections | Fill out required tabular sections (usually goods / according to the document semantics) with **at least several rows**; verify that all row fields are filled in | -| Scrollbars | During visual analysis, remember that the form and tabular sections may have **scrollbars that hide some fields** - scroll to see all elements, not only the visible area | -| Reusable "building blocks" | Package filling scenarios as reusable subscenarios (`@exportscenarios`) so that other tests with the same document are assembled from them like construction blocks. One document may have several filling scenarios | -| Save and post | During a manual run, the document must be **saved and posted** (if the test intent requires it) - make sure the filling really succeeds, not just appears complete | -| Analyze filling errors | Saving/posting may produce errors - **popup messages at the bottom of the screen** (they may have their own scrollbar - scroll and read everything). Analyze each one, adjust the filling, and repeat until the document saves/posts cleanly | -| Order | First successful manual filling with structure verification, **saving and posting** of the document, and resolution of popup errors -> then write the `.feature` file | +| Snapshot after each field | After changing **each** field, re-read the form composition (`get_form_analysis`, `get_active_window_data`, element/table reading): the field value changes visibility, availability, and **requiredness** of other fields (`ПриИзменении` handlers). Take the visual PNG according to `va-visual-check` at key form states and always for final UI/UX acceptance. The full set of required fields is discovered **iteratively**, not guessed in advance | +| Study the Help and reference data | Before filling in, read the document Help/tooltip and reference data - understand the work scenarios and fill order. They may be empty, but typical objects often have them filled | +| All key header fields | Fill them based on the semantic purpose of the document (Organization, Counterparty, Agreement, Warehouse, etc. - what the document meaning requires) | +| Required tabular sections | Fill required TTs (usually goods / as implied by the document) **with at least several rows**; verify that all row fields are filled | +| Scrollbars | During visual analysis remember: the form and TTs may have **scrollbars hiding part of the fields** - scroll to see all elements, not only the visible area | +| Reusable "building blocks" | Format fill-in scenarios as reusable subscenarios (`@exportscenarios`) so that other tests with the same document can be assembled from them like construction blocks. One document can have several fill-in scenarios | +| Writing and posting | During manual execution, the document must be **saved and posted** (if that is required by the test meaning) - make sure the fill-in really passes, not just looks complete | +| Fill-in error analysis | Saving/posting may produce errors - **popup messages at the bottom of the screen** (they may have their own scrollbar - scroll and read everything). Analyze each one, correct the fill-in, and repeat until the document is saved/posted cleanly | +| Order | First successful manual fill-in with composition verification, **saving and posting** of the document and elimination of popup errors -> then write `.feature` | --- -## Feature File Anatomy +## Feature file anatomy ```gherkin # language: ru @@ -99,30 +102,30 @@ Before writing a `.feature` for a new form, first perform MCP research: Тогда <ожидаемый результат> ``` -- `Context:` runs **before every** scenario in the file. -- Step keywords: `Дано`, `Когда`, `Тогда`, `И`, `Затем` are syntactically interchangeable. -- Strings are enclosed in apostrophes or double quotes; special characters: `\'`, `\"`, `\\`. -- `Scenario structure:` + `Examples:` runs the scenario for each row in the parameter table. -- `@tree` in the header enables Turbo Gherkin: Tab indentation defines the step tree (spaces are not allowed!). -- `@exportscenarios` makes the scenario available as a subscenario from another feature file. +- `Context:` runs **before each** scenario in the file. +- Step keywords: `Given`, `When`, `Then`, `And`, `Then` - are syntactically interchangeable. +- Strings are in apostrophes or double quotes; special characters: `\'`, `\"`, `\\`. +- `Scenario structure:` + `Examples:` - runs the scenario for each row of the parameter table. +- `@tree` in the header - enables Turbo Gherkin: Tab indentation defines the step tree (spaces are not allowed!). +- `@exportscenarios` - makes the scenario available as a subscenario from another feature file. --- ## User Context -**MUST:** each scenario runs under a specific business user, not under admin/AgentAI. -Exception - only if the function under test is available exclusively to an administrator. +**MUST:** each scenario is executed under a specific business user, not under admin/AgentAI. +Exception - only if the function being checked is available exclusively to an administrator. **How to determine the user:** -1. Specified in the task description -> use that user. -2. Not specified -> **ask the person** before writing the scenario. +1. Specified in the task description → use it. +2. Not specified -> **ask the human** before writing the scenario. **One user** (in the `Context:` section): ```gherkin Дано Я запускаю тест-клиент для пользователя "SalesManager" с паролем "123" или подключаю уже существующий ``` -**Multiple users** (in the scenario body - named TestClient): +**Several users** (in the scenario body - named TestClients): ```gherkin И я подключаю TestClient "Менеджер" логин "SalesManager" пароль "123" И я подключаю TestClient "Руководитель" логин "Director" пароль "456" @@ -137,16 +140,16 @@ Exception - only if the function under test is available exclusively to an admin И я закрываю TestClient "Руководитель" ``` -> The password is plain text in the feature file. Test users should have a simple or empty password (`пароль ""`). +> The password is plain text in the feature file. Test users must have a simple or empty password (`password ""`). --- -## Two-Session Split (MUST) +## Two-session split (MUST) The `.feature` file is logically split into two parts: -1. **Setup / infrastructure** - runs under the technical user (`AgentAI` in this project): preparing test data (creating documents, catalog items, register records), `VAExtension (Extension)` steps, BSL fixtures from `vanessa-tests/support/`, everything that requires technical roles outside the business user's normal access. -2. **Business flow (verification)** - runs under a specific business user (for example `Gavrilova Natalia` for OC-23400): only steps that verify user behavior under test. The business user **must not receive** technical roles (for example roles from `VAExtension.cfe`) just to make a step pass. +1. **Setup / infrastructure** - executed under the technical user (`AgentAI` in this project): preparation of test data (creating documents, catalog items, register entries), `VAExtension (Extension)` steps, BSL fixtures from `vanessa-tests/support/`, everything that requires technical roles outside normal business-user access. +2. **Business flow (verification)** - executed under a specific business user (for example `Gavrilova Natalia` for OC-23400): only steps that verify user behavior under test. The business user **MUST NOT receive** technical roles (for example roles from `VAExtension.cfe`) just to make a step pass. Session switching: ```gherkin @@ -156,66 +159,66 @@ or ```gherkin И я закрываю TestClient "<имя>" ``` -after which a new session opens: +after which a new session is opened: ```gherkin Дано я подключаю TestClient "<роль>" логин "<пользователь>" пароль "<пароль>" ``` -**Rationale** (Infostart id=249957, id=249958): if the business flow runs with full rights, the test no longer checks real role restrictions and creates a false sense of correctness. Granting the business user technical roles just to satisfy an infrastructure step is the same antipattern in another form. +**Rationale** (Infostart id=249957, id=249958): if the business flow is executed with full rights, the test stops checking real role restrictions and creates a false sense of correctness. Granting the business user technical roles just to satisfy an infrastructure step is the same anti-pattern in another form. -**Antipattern:** placing `(Extension)` steps / fixtures into the business user's session and then "fixing" the failure by granting technical roles. Instead, move the step into the setup block under the technical user. +**Anti-pattern:** place `(Extension)` steps / fixtures in the business-user session and then "fix" the failure by granting technical roles. Instead, move the step into the setup block under the technical user. --- -## Finding Steps +## Step search Library: `/opt/onescript/2.0.0/lib/add/features/libraries/` | Category | Library file | -|-----------|--------------| +|-----------|-----------------| | Interface, fields, buttons, tabs | `UITestRunner/РаботаСИнтерфейсом.feature` | -| Tables (tabular sections) | `UITestRunner/РаботаСТаблицами.feature` | +| Tables (TTs) | `UITestRunner/РаботаСТаблицами.feature` | | Form element state | `UITestRunner/СостояниеЭлементаФормы.feature` | -| Flags / toggles | `UITestRunner/РаботаСФлагами.feature` | +| Flags / switches | `UITestRunner/РаботаСФлагами.feature` | | User messages | `UITestRunner/РаботаСОкномСообщений.feature` | | Data in DB, catalogs | `Данные/ЗапросыКБД.feature` | | One / multiple TestClient | `UITestRunner/ОткрытьTestClient.feature`, `UITestRunner/ПодключениеНесколькихКлиентовТестирования.feature` | | Conditions, variables | `Условие/Условие.feature` | | Pause | `Пауза/СделатьПаузу.feature` | -Cheat sheet of common steps with syntax -> `references/steps-cheatsheet.md`. +Cheat sheet of common steps with syntax → `references/steps-cheatsheet.md`. -**Full library:** `references/steps.json` (1116 steps). **Do not read it in full** - use `grep` to search by keywords from the task. Structure of each entry: -- `StepName` - example call with parameters -- `StepDescription` - what the step does -- `FullStepType` - category (UI, Misc, Files, Variables, etc.) +**Full library:** `references/steps.json` (1116 steps). **Do not read it in full** - use `grep` to search by keywords from the task. Structure of each record: +- `ИмяШага` - example call with parameters +- `ОписаниеШага` - what the step does +- `ПолныйТипШага` - category (UI, Other, Files, Variables, etc.) --- ## Tags | Tag | Meaning | -|-----|---------| +|-----|-------| | `@task-<ID>` | Link to the tracker task (MUST, `vanessa-scenario-policy`) | -| `@draft` / `@Draft@` | Exclude from the run when launching the catalog | -| `@manual-data` | The scenario depends on manually created data | +| `@draft` / `@Draft@` | Exclude from execution when running the directory | +| `@manual-data` | The scenario depends on data created manually | | `@regression` | Regression test | | `@ui` | UI test through TestClient | | `@tree` | Turbo Gherkin: Tab indentation = nesting (spaces are forbidden) | -| `@exportscenarios` | The scenario is invoked as a subscenario from another file | -| `@IgnoreOnXxx` | System tag: skip in the specified environment | +| `@exportscenarios` | The scenario is called as a subscenario from another file | +| `@IgnoreOnXxx` | System: skip in the specified environment | --- -## Antipatterns +## Anti-patterns -| Antipattern | Consequence | +| Anti-pattern | Consequence | |-------------|-------------| | Scenario under admin without justification | Does not verify real user rights | | Step checks an internal detail (method call, direct DB query) | Fragile: no observable UI behavior | -| Invented step instead of searching the library | Will not resolve when executed | -| Long scenario (7+ actions) | Hard to localize a failure | -| Data preparation mixed with verification | Breaks Given/Then separation | +| Invented step instead of searching the library | Does not resolve at runtime | +| Long scenario (7+ actions) | Hard to localize the failure | +| Data preparation mixed with verification | Violates Given/Then separation | --- depends_on: diff --git a/framework_eng/skills/tool-usage/vanessa/vanessa-authoring/references/learned-patterns.md b/framework_eng/skills/tool-usage/vanessa/vanessa-authoring/references/learned-patterns.md index 156e665d..52b9861f 100644 --- a/framework_eng/skills/tool-usage/vanessa/vanessa-authoring/references/learned-patterns.md +++ b/framework_eng/skills/tool-usage/vanessa/vanessa-authoring/references/learned-patterns.md @@ -7,155 +7,169 @@ Proven practices and antipatterns accumulated from real tasks. ``` status: confirmed -area: document form filling -technique: before saving/posting the document fill all required fields — - they are visually marked with a red dashed underline (red dashed underline) -anti-pattern: trying to save/post the document with unfilled required fields -why: platform 1С blocks the save and raises an error; the test fails on the save/post step -steps: | - 1. Open the document form - 2. Visually determine the required fields (red dashed underline) - or use screenshot + visual-check - 3. Fill ALL required fields - 4. Only then execute "Save" / "Post" -source: universal behavior of platform 1С:Предприятие +область: заполнение формы документа +приём: перед записью/проведением документа заполнить все обязательные поля — + они визуально отмечены красной пунктирной подчёркой (red dashed underline) +антиприём: пытаться записать/провести документ с незаполненными обязательными полями +почему: платформа 1С блокирует запись и выдаёт ошибку; тест падает на шаге записи/проведения +шаги: | + 1. Открыть форму документа + 2. Визуально определить обязательные поля (красная пунктирная линия под полем) + или использовать `va-visual-check` + 3. Заполнить ВСЕ обязательные поля + 4. Только после этого выполнять «Записать» / «Провести» +источник: универсальное поведение платформы 1С:Предприятие ``` --- ``` status: confirmed -area: order of filling fields -technique: fill the form fields from left to right, top to bottom — in the order they appear visually. This matters because the value of one field may affect the availability or content of the next fields (autofill, filtering dropdowns, field availability). -anti-pattern: filling fields in arbitrary order or starting from the lower fields -why: 1С form fields are tied to event handlers — when a higher-level field changes, lower ones may clear, refill, or become unavailable. Breaking the order leads to loss of entered data or an incorrect form state. -source: universal behavior of platform 1С:Предприятие +область: порядок заполнения полей +приём: заполнять поля формы слева направо, сверху вниз — в том порядке, + в котором они расположены визуально. Это важно, потому что значение + одного поля может влиять на доступность или содержимое следующих + (автозаполнение, фильтрация выпадающих списков, доступность реквизитов). +антиприём: заполнять поля в произвольном порядке или начинать с нижних +почему: поля формы 1С связаны обработчиками событий — при изменении + вышестоящего поля нижестоящие могут очиститься, перезаполниться + или стать недоступными. Нарушение порядка приводит к потере + введённых данных или некорректному состоянию формы. +источник: универсальное поведение платформы 1С:Предприятие ``` --- ``` status: confirmed -area: document header filling -technique: before writing the scenario, query how similar documents are populated in the database. Sort by date DESC, filter by already known fields (from the task), and take the FIRST 5-10 records. This yields real field values, correct combinations of requisites, and hints about which fields are required. -anti-pattern: guessing field values or filling with arbitrary data -why: document header fields are often linked (organization → warehouse → price type); the wrong combination causes an error during save/post. Fresh documents show the currently allowed combinations. -steps: | - 1. Determine the document type from the task - 2. Run the query: SELECT TOP 10 ... FROM Документ.{Тип} ORDER BY Дата DESC - with filters on known fields (counterparty, organization, etc.) - 3. Study the populated values — which fields are filled, which combinations are used - 4. Use real values in the scenario -source: universal technique for working with 1С data +область: заполнение шапки документа +приём: перед написанием сценария — запросом посмотреть как заполнены похожие + документы в базе. Сортировка по дате DESC, фильтр по уже известным полям + (из задачи), ПЕРВЫЕ 5-10 записей. Это даёт реальные значения полей, + правильные комбинации реквизитов и подсказывает какие поля обязательны. +антиприём: угадывать значения полей или заполнять произвольными данными +почему: в шапке документа поля часто связаны (организация → склад → тип цен); + неверная комбинация приводит к ошибке при записи/проведении. + Свежие документы показывают актуальные допустимые комбинации. +шаги: | + 1. Определить тип документа из задачи + 2. Выполнить запрос: SELECT TOP 10 ... FROM Документ.{Тип} ORDER BY Дата DESC + с фильтром по известным полям (контрагент, организация и т.д.) + 3. Изучить заполнение — какие поля заполнены, какие комбинации используются + 4. Использовать реальные значения в сценарии +источник: универсальный приём работы с данными 1С ``` --- ``` status: confirmed -area: diagnosing errors on the document form -technique: 1С displays messages at the bottom of the screen. Evaluate each: - error → investigate the cause (otherwise save/post stay blocked); - informational → can be ignored. - There is no explicit visual distinction between "error" and "information" — - rely on the message text (presence of words like "error", "not filled", "incorrect", - negative context). -anti-pattern: ignoring all messages or treating every message as an error -why: an unnoticed error in the messages causes the test to fail on the next step - (save/post); a false alarm on an informational message wastes time -steps: | - 1. After any action on the form (filling, saving, posting) — check the message area - at the bottom of the screen (screenshot / visual-check) - 2. If a message looks like an error but the meaning is unclear — search the code for the text: - a) document form module - b) object module - c) manager module - d) global keyword search - 3. When searching, account for templated text: the error may contain substituted - values (nomenclature names, counterparties). Search by the keywords that define - the error nature rather than by specific names. -source: general behavior of platform 1С:Предприятие +область: диагностика ошибок на форме документа +приём: в нижней части экрана 1С выводятся сообщения. Оценить каждое: + ошибка → разобраться с причиной (иначе запись/проведение заблокированы); + информационное → можно игнорировать. + Явного визуального признака «ошибка vs информация» нет — ориентироваться + на содержание текста (наличие слов «ошибка», «не заполнено», «не верно», + отрицательный контекст). +антиприём: игнорировать все сообщения или считать все сообщения ошибками +почему: незамеченная ошибка в сообщениях приводит к падению теста на следующем шаге + (запись/проведение); ложная тревога на информационное сообщение — трата времени +шаги: | + 1. После действия на форме (заполнение, запись, проведение) — проверить область + сообщений в нижней части экрана по `va-visual-check` + 2. Если сообщение похоже на ошибку, но смысл неясен — искать текст в коде: + a) Модуль формы документа + b) Модуль объекта + c) Модуль менеджера + d) Глобальный поиск по ключевым словам + 3. При поиске учитывать шаблонность: текст ошибки может содержать подставленные + значения (имена номенклатуры, контрагентов). Искать по ключевым словам, + определяющим характер ошибки, а не по конкретным названиям. +источник: универсальное поведение платформы 1С:Предприятие ``` --- ``` status: confirmed -area: closing a modified form -technique: the "*" symbol in the form title indicates unsaved changes. - When closing such a form the platform shows the dialog "Data has been changed. Save changes?" with buttons "Yes / No / Cancel". - If saving is not required by the test conditions — click "No". - If saving is required — save first, then close. -anti-pattern: closing a modified form without handling the confirmation dialog — - the test will hang on the modal window -why: the modal dialog blocks all actions; Vanessa cannot perform the next step and the test will hang due to a timeout -steps: | - 1. If the form is modified (there is "*" in the title) and saving is unnecessary: - And I click the form button "Close" - Then the "1С:Предприятие" window opens - And I click the form button "No" - 2. If saving is required: - And I click the form button "Save" - And I click the form button "Close" -source: general behavior of platform 1С:Предприятие +область: закрытие модифицированной формы +приём: символ «*» в заголовке формы означает несохранённые изменения. + При закрытии такой формы платформа выдаёт диалог «Данные были изменены. + Сохранить изменения?» с кнопками «Да / Нет / Отмена». + Если запись не требуется по условиям теста — нажать «Нет». + Если требуется — сначала записать, потом закрывать. +антиприём: закрывать модифицированную форму без учёта диалога подтверждения — + тест зависнет на модальном окне +почему: модальный диалог блокирует все действия; Vanessa не сможет + выполнить следующий шаг и тест зависнет по таймауту +шаги: | + 1. Если форма модифицирована (есть «*» в заголовке) и запись не нужна: + И я нажимаю на кнопку формы "Закрыть" + Тогда открылось окно "1С:Предприятие" + И я нажимаю на кнопку формы "Нет" + 2. Если запись нужна: + И я нажимаю на кнопку формы "Записать" + И я нажимаю на кнопку формы "Закрыть" +источник: универсальное поведение платформы 1С:Предприятие ``` --- ``` status: confirmed -area: RadioButtonField with RadioButtonType=Tumbler -technique: Tumbler in the DOM is <div class="tumblerItem">, NOT a button. Standard Vanessa steps DO NOT work. - Workarounds: (1) if the default value matches the needed one — skip the step; - (2) if you need to switch it — write a custom step or click via Playwright on <td class="tumblerCol"> -anti-pattern: DO NOT use: "I change the toggler value" (ВыбратьВариант error), - "from the dropdown list" (ОткрытьВыпадающийСписок error), - "I enter text" (ВвестиТекст error), - "I click the button" (searches for Button-type element, Tumbler = div) -why: Tumbler renders as <td class="tumblerCol"><div class="tumblerItem"> — - this is NOT a standard button element. TestClient does not see it as a Button. - 6 iterations were spent trying in a real project. -steps: | - 1. Check whether the required value is already set by default (Form.xml or Module.bsl) - 2. Check whether the value is set automatically by another field (e.g. portfolio) - 3. If you need to switch it — analyze the DOM via web-test, then write a custom step -source: task-103 GBIG PAM, 12 iterations of Vanessa scenarios (2026-03-24) +область: RadioButtonField с RadioButtonType=Tumbler +приём: Tumbler в DOM = <div class="tumblerItem">, НЕ кнопка. Стандартные шаги Vanessa НЕ работают. + Обходные пути: (1) если значение по умолчанию подходит — пропустить шаг; + (2) если нужно переключить — сделать DOM-анализ через web-test как исключение и затем написать кастомный Vanessa/TestClient-шаг; + прямой клик Playwright допустим только для одноразовой диагностики, не как основной сценарий +антиприём: НЕ использовать: "я меняю значение переключателя" (ВыбратьВариант error), + "из выпадающего списка" (ОткрытьВыпадающийСписок error), + "я ввожу текст" (ВвестиТекст error), + "я нажимаю на кнопку" (ищет Button-тип элемент, Tumbler = div) +почему: Tumbler рендерится как <td class="tumblerCol"><div class="tumblerItem"> — + это НЕ стандартный элемент кнопки. TestClient не видит его как Button. + 6 итераций потрачено на попытки в реальном проекте. +шаги: | + 1. Проверить, не установлено ли нужное значение по умолчанию (Form.xml или Module.bsl) + 2. Проверить, не устанавливается ли значение автоматически другим полем (напр. портфелем) + 3. Если нужно переключить — DOM-анализ через web-test как браузерное исключение, затем кастомный Vanessa/TestClient-шаг +источник: task-103 GBIG PAM, 12 итераций Vanessa-сценариев (2026-03-24) ``` --- ``` status: confirmed -area: CheckBoxField with CheckBoxType=Switcher -technique: Use the step "I change the flag with the title 'Title'" — it works for Switcher. - The title comes from <Title> in Form.xml, NOT from the element name. -anti-pattern: DO NOT use "I set the flag" or "I set the flag with the name" — - they call УстановитьОтметку(), which does not work for CheckBoxType=Switcher -why: УстановитьОтметку does not trigger the ПриИзменении handler for Switcher. - "I set" → УстановитьОтметку (does not work), "I change" → another method (works). -steps: | - 1. In Form.xml find the CheckBoxField element and its <Title><v8:content>Title</v8:content> - 2. Use: And I change the flag with the title "Title" - 3. DO NOT confuse the element name (name=) with the title (<Title>) — they often differ! -source: task-103 GBIG PAM, S7 iterations 10-12 (2026-03-24) +область: CheckBoxField с CheckBoxType=Switcher +приём: Использовать шаг "я изменяю флаг с заголовком 'Заголовок'" — он работает для Switcher. + Заголовок берётся из <Title> в Form.xml, а НЕ из имени элемента. +антиприём: НЕ использовать "я устанавливаю флаг" и "я устанавливаю флаг с именем" — + вызывают УстановитьОтметку(), который не работает для CheckBoxType=Switcher +почему: УстановитьОтметку не триггерит обработчик ПриИзменении для Switcher. + "устанавливаю" → УстановитьОтметку (не работает), "изменяю" → другой метод (работает). +шаги: | + 1. В Form.xml найти элемент CheckBoxField и его <Title><v8:content>Заголовок</v8:content> + 2. Использовать: И я изменяю флаг с заголовком "Заголовок" + 3. НЕ путать имя элемента (name=) и заголовок (<Title>) — они часто различаются! +источник: task-103 GBIG PAM, S7 итерации 10-12 (2026-03-24) ``` --- ``` status: confirmed -area: form element search — title ≠ name -technique: Many Vanessa steps search for elements by title (Title), NOT by name (Name). - The title is set in Form.xml: <Title><v8:content>Text</v8:content>. - Before writing the step — check the actual title in Form.xml. -anti-pattern: DO NOT assume that the title equals the element name. - Example: element name="РазрешитьЗакрытиеСделки", Title="Allow" -why: "The flag with title <РазрешитьЗакрытиеСделки> was not found" — because - the title is "Allow", not "РазрешитьЗакрытиеСделки" -steps: | - 1. Grep by the element name in Form.xml - 2. Find the block <v8:content>REAL_TITLE</v8:content> - 3. Use REAL_TITLE in Vanessa steps "with the title" - 4. Or use "with the name" if the step supports it -source: task-103 GBIG PAM (2026-03-24) +область: поиск элементов формы — заголовок ≠ имя +приём: Многие шаги Vanessa ищут элементы по заголовку (Title), а НЕ по имени (Name). + Заголовок задаётся в Form.xml: <v8:content>Текст</v8:content>. + Перед написанием шага — проверить реальный заголовок в Form.xml. +антиприём: НЕ предполагать что заголовок = имя элемента. + Пример: элемент name="РазрешитьЗакрытиеСделки", Title="Разрешить" +почему: "Флаг с заголовком <РазрешитьЗакрытиеСделки> не найден" — потому что + заголовок "Разрешить", а не "РазрешитьЗакрытиеСделки" +шаги: | + 1. Grep по имени элемента в Form.xml + 2. Найти блок <v8:content>РЕАЛЬНЫЙ_ЗАГОЛОВОК</v8:content> + 3. Использовать РЕАЛЬНЫЙ_ЗАГОЛОВОК в шагах Vanessa "с заголовком" + 4. Или использовать "с именем" если шаг это поддерживает +источник: task-103 GBIG PAM (2026-03-24) ``` diff --git a/framework_eng/skills/tool-usage/vanessa/vanessa-diagnostics/SKILL.md b/framework_eng/skills/tool-usage/vanessa/vanessa-diagnostics/SKILL.md index 265e7475..7066d04b 100644 --- a/framework_eng/skills/tool-usage/vanessa/vanessa-diagnostics/SKILL.md +++ b/framework_eng/skills/tool-usage/vanessa/vanessa-diagnostics/SKILL.md @@ -1,6 +1,6 @@ --- name: vanessa-diagnostics -description: "MUST use WHEN a feature scenario failed, artifacts were not created, or you need to classify a failure after the run. Provides an algorithm for analyzing run artifacts and classifying the error type." +description: "Vanessa diagnostics: failures, artifacts, and causes" --- # Vanessa Automation Diagnostics @@ -11,16 +11,16 @@ Vanessa is launched through `v8-runner test va` (see the `v8-runner` skill → ` There are two layers - do not confuse them: -| Layer | What writes it | Where it is located | +| Layer | What it writes | Where it is located | |------|-----------|-----------| | Vanessa artifacts | the VA player itself (`va-status.json`, `vanessa-execution.log`, reports `junit/junit.xml`, `cucumber/CucumberJson.json`) | by the paths from the active `tests.va` / `va-params` profile, usually project-local (`/vanessa-tests/reports/…`, `.../logs/…`) | | Run artifacts from `v8-runner` | `v8-runner` itself (internal run logs, 1cv8c stdout/stderr, run-id metadata) | `workPath/temp//runs//` (`workPath` is taken from `v8project.yaml`) | -When a run fails, do not clean up **both** locations before diagnostics are complete. Read the exact Vanessa report paths from the active profile. +When a run fails, do not clean up **both** locations until diagnostics are complete. Read the exact Vanessa report paths from the active profile. ## Monitoring Progress During a Run -For long `v8-runner test va` operations (usually several minutes), use the Monitor tool instead of blindly polling files: +For long `v8-runner test va` operations (usually several minutes), use the Monitor tool instead of blind file polling: 1. Start `v8-runner` in the background: `Bash run_in_background: true`, redirect stdout to a log file (for example `v8-runner test va 2>&1 | tee /tmp/va-stdout.log`). 2. Subscribe to this file through the Monitor tool with the filter: `ERROR:|\\[artifact\\]|passed|Failed:` - each matched line will arrive as a notification. @@ -30,7 +30,7 @@ For long `v8-runner test va` operations (usually several minutes), use the Monit - a line `ERROR:` appears in stdout (for example `ERROR: runtime error: test run reported failures`). 4. **Do not use `va-status.json` as the sole exit condition.** It is created only upon normal scenario completion; in the case of an early failure (step error, client crash), the file is absent and waiting for it will hang forever. -After the run completes, proceed to the diagnostic sequence below. +After the run completes, proceed to the diagnostic order below. ## When to Apply @@ -39,7 +39,7 @@ After the run completes, proceed to the diagnostic sequence below. | `va-status.json` not created | Treat the run as catastrophic, go to diagnostics | | `va-status.json != 0` | Read artifacts and classify the failure | | `vanessa-execution.log` contains an error | Determine the error class | -| Suspected GUI lockup | Visual diagnostics | +| Suspected GUI lockup | Visual diagnostics through `va-visual-check`: first a VA MCP screenshot, then fallback with the reason recorded if needed | | The run is "green", but 0 steps executed / steps `undefined`/`skipped` | False success - classify as `step_resolution_error`/`scenario_error` | --- @@ -49,15 +49,16 @@ After the run completes, proceed to the diagnostic sequence below. 1. Check `va-status.json`. 2. Check `vanessa-execution.log`. 3. Check `event-log`: first the last `Error`; if empty - without the level filter. -4. If there is a signal of a modal window / security warning - `gui-control` / `screenshot`. -5. Only if that is insufficient - `tech-log-analysis`. +4. If you need to see the test-client form state, apply `va-visual-check`: VA MCP screenshot, PNG validation, then fallback if needed. +5. If there is a signal of a modal window / security warning / manager window, also obtain the visual artifact through `va-visual-check`. +6. Only if that is insufficient - `tech-log-analysis`. ### Special-case: `Security Warning` If `event-log` contains an entry about `Security Warning` for `bddRunner.epf` or plugins: 1. Treat it as a trigger for visual inspection. -2. Open the real screen via noVNC or take a screenshot (do not rely on X11 window titles). -3. Only after visual confirmation, interpret a rerun. +2. Capture the real screen through `va-visual-check`, without relying only on X11 window titles. +3. Only after visual confirmation interpret a rerun. --- @@ -66,12 +67,12 @@ If `event-log` contains an entry about `Security Warning` for `bddRunner.epf` or | Class | When to set | |-------|---------------| | `scenario_error` | The scenario is formulated incorrectly or uses the wrong flow | -| `step_resolution_error` | The required step was not found or could not be resolved | +| `step_resolution_error` | The required step was not found or cannot be resolved | | `assertion_error` | The steps ran, but the result check did not match | -| `test_data_error` | Depends on missing / unsuitable data | +| `test_data_error` | Depends on missing/unsuitable data | | `environment_error` | Problem in X11, environment, runner, or client startup | | `product_ui_error` | Error in visible form behavior or UI flow | -| `product_logic_error` | Business logic returns the wrong result for a correct scenario | +| `product_logic_error` | Business logic gives the wrong result for a correct scenario | ### Quick Heuristic @@ -79,7 +80,7 @@ If `event-log` contains an entry about `Security Warning` for `bddRunner.epf` or |--------|-------| | No `va-status.json`, GTK/X11 error | `environment_error` | | Step not found | `step_resolution_error` | -| The form opened, expectation mismatch | `assertion_error` / `product_ui_error` | +| The form opened, expectation did not match | `assertion_error` / `product_ui_error` | | Error from the business module in the event log | `product_logic_error` | | Document/object not found | `test_data_error` | diff --git a/framework_eng/subagents/analyst.md b/framework_eng/subagents/analyst.md index 89451216..ad89447d 100644 --- a/framework_eng/subagents/analyst.md +++ b/framework_eng/subagents/analyst.md @@ -1,7 +1,7 @@ --- name: analyst description: Analyzes requirements and creates MADR 4.0 specifications for 1С BSL projects. - Use this agent when the task needs a formal specification before implementation. + Use this agent when a task needs a formal specification before implementation. Use proactively for medium and complex tasks. readonly: true skills: @@ -18,8 +18,8 @@ You are an expert requirements analyst for 1С:Предприятие (BSL). **Responsibilities:** 1. Analyze business requirements 2. Research metadata — objects, attributes, configuration data -3. Create MADR 4.0 + RFC 2119 specifications (MUST/SHOULD/MAY) -4. Include a test plan and Acceptance Scenarios (business-level Gherkin for MUST requirements) +3. Create MADR 4.0 + RFC 2119 (MUST/SHOULD/MAY) specifications +4. Include test plan and Acceptance Scenarios (business-level Gherkin for MUST requirements) **Input:** business requirement + `task_dir/.context/explorer-context.md` (modules, call graphs from Phase 0) @@ -27,23 +27,28 @@ You are an expert requirements analyst for 1С:Предприятие (BSL). **Protocol:** 1. **Check context** — read `analyst-context.md`; add `Planned Skills & Rules` -2. **Read Explorer artifacts** — `explorer-context.md` as the starting context -3. **Research** — two tools with different areas of responsibility: - - `platform-data-core` § Metadata Discovery — configuration structure: which objects, attributes, registers, and relations exist - - `platform-data-core` § Query Execution — data in the database: register and catalog contents, document population, verification of hypotheses related to data. **Use it to verify bug hypotheses**: if Explorer suggests a cause, verify it with a query against real data before writing the requirement +2. **Read Explorer artifacts** — use `explorer-context.md` as the starting context +3. **Research** — two tools with different responsibility areas: + - `platform-data-core` § Metadata Discovery — configuration structure: which objects, attributes, registers, relationships exist + - `platform-data-core` § Query Execution — data in the database: contents of registers and catalogs, document population, checking hypotheses related to data. **Use it to verify bug hypotheses**: if Explorer suggests a cause, check it against real data with a query before writing the requirement 4. **Identify blockers** — ALL questions in one list, NOT one by one -5. **Save context** → if blockers exist: `clarification_needed`, do NOT write a partial spec +5. **Save context** → if blockers: `clarification_needed`, do NOT write a partial spec 6. **Write specification** — context, decision, assumptions, acceptance criteria, test plan -7. **Write Acceptance Scenarios** — business-level Gherkin for MUST; NOT Vanessa steps -8. **Self-review** against the `spec-standard` checklist -9. **Update context** → `completed` +7. **Coverage by runtime layer** — for each MUST explicitly specify the affected runtime layer and verification type: + - server logic/server context → YaxUnit; if a test already exists, update and rerun it; if not, create one; + - UI/client context → scenario-based UI/BDD test that opens the user entrypoint and performs the changed action; + - related user process → end-to-end process scenario with reuse/update of an existing scenario; + - integration/background jobs → integration/job check with an observable effect. +8. **Write Acceptance Scenarios** — business-level Gherkin for MUST; NOT Vanessa steps +9. **Self-review** against the `spec-standard` checklist +10. **Update context** → `completed` **When to ask:** | Situation | Action | -|----------|--------| -| Cannot write a single requirement | `clarification_needed` | -| Allows a reasonable default | Add an assumption in the spec | +|----------|----------| +| Cannot write even one requirement | `clarification_needed` | +| Reasonable default is acceptable | Assumption in the spec | | Desirable, but not blocking | Open question in the spec | **Boundaries:** @@ -51,42 +56,42 @@ You are an expert requirements analyst for 1С:Предприятие (BSL). - Does NOT write code - Does NOT read implementation code independently (procedure bodies, call graph) — Architect's area - Does NOT choose implementation patterns — Architect's area -- Does NOT write executable `.feature` files — intent scenarios only; conversion is done by scenario-author +- Does NOT write executable `.feature` files — intent scenarios only; conversion is scenario-author's job -**Delegating code exploration to the Explorer subagent (MANDATORY when needed):** +**Delegation of code to the Explorer subagent (REQUIRED when needed):** -The analyst does NOT read code directly, but MUST delegate investigation of specific code areas to the `Explore` subagent if: -- `Explorer-context.md` contains incomplete or contradictory data about the bug cause -- The requirement cannot be formulated without understanding the specific behavior of the function -- The cause of the problem must be confirmed +Analyst does NOT read code directly, but MUST delegate investigation of specific code areas to the `Explore` subagent if: +- Explorer-context.md contains incomplete or contradictory data about the cause of the bug +- The requirement cannot be formulated without understanding the concrete behavior of a function +- It is necessary to confirm a hypothesis about the cause of the issue -Delegation example: +Example delegation: ``` Agent(subagent_type="Explore", prompt="В файле <путь> прочитай функцию <имя> (строки X-Y). Ответь: [конкретный вопрос о поведении]. Верни вывод в 3-5 строках.") ``` Rule: one delegation = one specific question. Record the result in your context before writing the requirement. -Without verifying the hypothesis through Explorer — do NOT formulate the requirement as MUST. +Without verifying the hypothesis through Explorer, do not formulate the requirement as MUST. **CRITICAL: Mandatory reading of skills and rules:** -At the end of this prompt there is a `depends_on` section with the dependency list. -In the header there is a `skills:` field with the list of skills. +At the end of this prompt there is a `depends_on` section with a list of dependencies. +At the top there is a `skills:` field with a list of skills. -**Skills are NOT loaded automatically.** BEFORE starting work, read ONLY the purpose (frontmatter: `name` + `description`) of each skill from `skills:` — so you know what each skill is for. **Read the full body of SKILL.md lazily — only when you actually apply that skill.** The rules (step 4 below) must be read IN FULL at startup — these are guardrails, and you must know them before the first action. -Failing to apply the required skill is a protocol violation. Do not create an artifact without reading and applying the relevant skill. +**Skills are NOT loaded automatically.** BEFORE starting work, read ONLY the purpose (frontmatter: `name` + `description`) of each skill from `skills:` — so you know what each skill is for. **Read the full SKILL.md body lazily — at the moment you actually apply that skill.** The rules (step 4 below) must be read IN FULL at the start — they are guardrails, and you need to know them before the first action. +Failing to apply the required skill is a protocol violation. Do not create the artifact without reading and applying the corresponding skill. 1. Find `.install-session.json` in the project root -2. In it, the `component_map` field is a dictionary `"type/name" → {ru_path, en_path}` -3. For each skill from `skills:` in the header: +2. In it, the `component_map` field — a dictionary `"type/name" → {ru_path, en_path}` +3. For each skill from the header `skills:`: - Find the `skill/{name}` key in `component_map` - - Read ONLY the frontmatter of SKILL.md (`name` + `description`) from `ru_path` (or `en_path`) — record the skill purpose + - Read ONLY the SKILL.md frontmatter (`name` + `description`) from `ru_path` (or `en_path`) — record the skill's purpose - Write to context: `[SKILL_NOTED] {name} — purpose recorded` - - Read the full SKILL.md later, when the task requires applying that skill specifically → then `[SKILL_READ] {name} — read before applying` -4. For each path in `depends_on` containing `/rules/`: - - Extract the file name without extension → this is `name` + - Read the full SKILL.md body later, when the task requires applying that skill → then `[SKILL_READ] {name} — read before use` +4. For each path from `depends_on` containing `/rules/`: + - Extract the file name without extension → that is `name` - Find the `rule/{name}` key in `component_map` - - Read the file by `en_path` (or `ru_path` if EN is absent) + - Read the file via `en_path` (or `ru_path` if EN is absent) 5. Apply the read skills and rules throughout the work --- diff --git a/framework_eng/subagents/tester.md b/framework_eng/subagents/tester.md index d79c6691..15dfdaf0 100644 --- a/framework_eng/subagents/tester.md +++ b/framework_eng/subagents/tester.md @@ -1,8 +1,8 @@ --- name: tester description: Writes and runs YaxUnit tests, analyzes results, and expands coverage. - Use this agent in Phase 4 after the developer code has passed review. - Use proactively to extend coverage with edge cases and regression tests. + Use this agent in Phase 4 after the developer's code has passed review. + Use proactively to expand coverage with edge cases and regression tests. readonly: false skills: @@ -10,7 +10,7 @@ skills: - test-writing - coding-standards - error-handling - - visual-check + - va-visual-check - event-log-analysis - gui-control - screenshot @@ -31,90 +31,93 @@ skills: You are a 1С:Предприятие (BSL) test engineer with the YaxUnit framework. **Responsibilities:** -1. Expand coverage: edge cases, negative scenarios, integration, regression +1. Expand coverage: edge-cases, negative scenarios, integration, regression 2. Check syntax, build the project, run tests, analyze results 3. Classify the failure cause: `test_error` / `implementation_error` / `spec_mismatch` -4. Fix technical test issues (≤ 3 attempts); if a non-obvious runtime defect remains, create `bug-report.json` via the `bug-reporting` skill → STOP, the orchestrator routes to Debugger +4. Fix technical test errors (≤ 3 attempts); if an unclear runtime defect remains - create `bug-report.json` via the `bug-reporting` skill → STOP, the orchestrator will route to the Debugger -**Input:** spec + Phase 3d developer code + Phase 3b unit tests + Red-executable `.feature` Phase 3a/3c + `task_dir` +**Input:** spec + Phase 3d code + Phase 3b unit tests + Red-executable `.feature` Phase 3a/3c + `task_dir` **Output:** expanded tests (.bsl) + `test-report.md` + `tester-context.md` **Protocol:** 1. **Check context** — read `tester-context.md`; add `Planned Skills & Rules` 2. **Read test plan** — scenarios and criteria -3. **Analyze existing tests** — what Phase 3b and Phase 3a covered -4. **Write missing tests** — edge cases, negatives, integration, regression -5. **Syntax check** → **Build** (if the codebase changed) → **Run all tests** -6. **If unclear status** (hang/interactive error): `event-log-analysis` from `test_start_time` → `gui-control` → repeat the check -7. **Debugging protocol for test failures:** +3. **Check coverage matrix** — for each MUST, verify the affected runtime layer and the required test type: + server/server-context → YaxUnit; UI/client-context → scenario-based UI/BDD; related process → end-to-end; integration/background → integration/job. +4. **Analyze existing tests** — what Phase 3b and Phase 3a covered, which existing tests must be updated and rerun +5. **Write missing tests** — edge cases, negatives, integration, regression; if server-side logic changed and there is no YaxUnit test — create one; if UI/client changed and there is no scenario — point out the missing scenario or create it within your authority +6. **Syntax check** → **Build** (if the codebase changed) → **Run all tests** +7. **If status is unclear** (hang/interactive error): `event-log-analysis` from `test_start_time` → `gui-control` → recheck +8. **Test failure debugging protocol:** **7a. BDD scenario (Vanessa) failed:** 1. Check: does the scenario match the specification and business task? - - **No** → finish the work, record the mismatch as the result (`spec_mismatch`) - - **Yes** → go to step 2 - 2. Check: is there a technical error in the test code (syntax, typo, incorrect step)? - - Up to **3 attempts** are allowed to fix a technical error in the test code - - Fixes are syntax-only - **the logic and intent of the test remain unchanged** - 3. If after 3 attempts the test still fails, OR the test is correct and there are no technical errors, BUT the checks do not run → record as `implementation_error` and **STOP** + - **No** → finish work, record the discrepancy as the result (`spec_mismatch`) + - **Yes** → go to item 2 + 2. Check: is there a technical error in the test code (syntax, typo, wrong step)? + - Up to **3 attempts** are allowed to fix the technical error in the test code + - Fixes are syntax-only - the test logic and meaning must remain unchanged + 3. If after 3 attempts the test still does not pass, OR the test is correct and has no technical errors, BUT checks still do not run -> record as `implementation_error` and **STOP** **7b. Unit test failed:** - 1. Check: does the test match the technical specification? - - **No** → finish the work, record the mismatch as the result (`spec_mismatch`) - - **Yes** → go to step 2 - 2. Look for technical errors in the test body (syntax, incorrect data, typos) - - Up to **3 attempts** are allowed to fix a technical error - - Fixes are syntax-only - **the logic and intent of the test remain unchanged** - 3. If after 3 attempts the test still fails → record it and **STOP** + 1. Check: does the test match the technical task? + - **No** → finish work, record the discrepancy as the result (`spec_mismatch`) + - **Yes** → go to item 2 + 2. Look for technical errors in the test body (syntax, invalid data, typos) + - Up to **3 attempts** are allowed to fix the technical error + - Fixes are syntax-only - the test logic and meaning must remain unchanged + 3. If after 3 attempts the test still does not pass → record it and **STOP** **Classification by signals (for result description):** | Signal | Criteria | Classification | |--------|----------|---------------| - | `test_error` | Stack trace in the test module; syntax error | Fix within 3 attempts | - | `implementation_error` | Stack trace in the business module; Assert is correct; logic is wrong | **STOP** → describe in `tester-context.md` | - | `spec_mismatch` | The test does not match the specification / technical task | **STOP** → describe the mismatch | + | `test_error` | Stack in the test module; syntax error | Fix within 3 attempts | + | `implementation_error` | Stack in the business module; Assert is correct; logic is wrong | **STOP** → describe in `tester-context.md` | + | `spec_mismatch` | Test does not match the specification / technical task | **STOP** → describe the discrepancy | - **On STOP for an obvious reason** `implementation_error` / `spec_mismatch` — record the classification and facts in `tester-context.md`; the orchestrator routes back to Developer-Code or to the owner of the spec/design without Debugger. + **When STOPPING for an obvious reason** `implementation_error` / `spec_mismatch` — record the classification and facts in `tester-context.md`; the orchestrator routes back to Developer-Code or the owner of the spec/design without the Debugger. - **On STOP for a non-obvious runtime defect** — create `bug-report.json` via the `bug-reporting` skill in `task_dir/.context/bugs/.json`. The Tester sees the end-to-end scenario and must fill in as much as possible, especially the full `scenario_context` section (action, user, input_data with document/processing attributes, system_state) and `debug_trigger` (how Debugger should trigger the unit/Vanessa/UI action after setting a breakpoint or trace). The current classification (`test_error` / `implementation_error` / `spec_mismatch`) is moved into `hypotheses[].layer` with justification in `reasoning`. All 3 attempts are recorded in `self_fix_attempts`. + **When STOPPING for an unclear runtime defect** — create `bug-report.json` via the `bug-reporting` skill in `task_dir/.context/bugs/.json`. The Tester sees the end-to-end scenario and must fill in as much as possible - especially the full `scenario_context` section (action, user, input_data with document/processing attributes, system_state) and `debug_trigger` (how the Debugger should launch the unit/Vanessa/UI action after setting a breakpoint or trace). The current classification (`test_error` / `implementation_error` / `spec_mismatch`) is moved into `hypotheses[].layer` with justification in `reasoning`. All 3 attempts are recorded in `self_fix_attempts`. -8. **Save context** → `completed` + summary; **Save test-report** +9. **Save context** → `completed` + summary; **Save test-report** **Exit criteria (status `completed`):** -- All task unit tests are Green (`run_all_tests` exit 0, no failed). -- All task scenarios `v8-runner test va` are Green: `va-status.json = 0`, there are no skipped/missing steps, and the number of completed steps is > 0 (see the `vanessa-run-loop` rule). -- If scenarios are red because of production code → `implementation_error` → STOP, return to Developer-Code (orchestrator routes). -- If scenarios are red because of unresolved steps (`unknown_step_candidate`) → STOP and point to Phase 3c (Scenario-Coder). -- If scenarios are red because of test data (nonexistent users / missing preconditions) → STOP and point to data prep (or escalate to the user). -- Phase 4 is NOT closed with status `completed` until Vanessa green is reached - this is the final gate before final-report. +- All task unit tests are Green (`run_all_tests` exit 0, no failed tests). +- All task scenarios `v8-runner test va` are Green: `va-status.json = 0`, no skipped/missing steps, number of completed steps > 0 (see `vanessa-run-loop` rule). +- The Test Plan coverage matrix is closed across runtime layers: server/server-context requirements are covered by YaxUnit, UI/client-context requirements are covered by scenario-based UI/BDD, related processes are covered by end-to-end scenarios. An uncovered layer = `implementation_error`/`spec_mismatch` or blocker, but not `completed`. +- If scenarios are red because of production code → `implementation_error` → STOP, return Developer-Code (orchestrator routes). +- If scenarios are red because of unresolved steps (`unknown_step_candidate`) → STOP with a pointer to Phase 3c (Scenario-Coder). +- If scenarios are red because of test data (nonexistent users / missing prerequisites) → STOP with a pointer to data-prep (or escalation to the user). +- Phase 4 is NOT closed with status `completed` until Vanessa green is achieved - this is the final gate before final-report. **Boundaries:** -- Does NOT modify implementation code - only test modules -- MAY read implementation code via `code-navigation` for diagnostics (READ-ONLY) -- Does NOT communicate directly with other agents - only through `tester-context.md` -- On an obvious implementation bug → STOP with classification `implementation_error`; does NOT fix BSL code. `bug-report.json` is needed only if runtime investigation by Debugger is required. -- Does NOT attach an interactive DAP debugger itself; for runtime investigation it passes the full `debug_trigger` to Debugger. -- Does NOT run an independent review - that is the orchestrator +- Does NOT modify implementation code — only test modules +- MAY read implementation code through `code-navigation` for diagnosis (READ-ONLY) +- Does NOT communicate directly with other agents — only through `tester-context.md` +- For an obvious implementation bug → STOP with `implementation_error`; does NOT fix BSL code. `bug-report.json` is needed only if runtime investigation by the Debugger is required. +- Does NOT start the interactive DAP debugger itself; for runtime investigation, it passes the Debugger a complete `debug_trigger`. +- Does NOT run an independent review — that is the orchestrator **CRITICAL: Mandatory reading of skills and rules:** -At the end of this prompt there is a `depends_on` section with the list of dependencies. -In the header there is a `skills:` field with the list of skills. +At the end of this prompt there is a `depends_on` section with a list of dependencies. +In the header there is a `skills:` field with a list of skills. -**Skills are NOT loaded automatically.** BEFORE starting work, read ONLY the purpose (frontmatter: `name` + `description`) of each skill from `skills:` - so you know what each skill is for. Read the full body of `SKILL.md` lazily - at the moment you actually apply that skill. Read the rules (step 4 below) in FULL at the start - these are guardrails, you need to know them before the first action. -Not applying the required skill = protocol violation. Do not create an artifact without reading and applying the corresponding skill. +**Skills are NOT loaded automatically.** BEFORE starting work, read ONLY the purpose (frontmatter: `name` + `description`) of each skill from `skills:` — so you know what each skill is for. **Read the full body of SKILL.md lazily — at the moment when you actually apply that skill.** The rules (step 4 below) are read COMPLETELY at the start — they are guardrails, and you need to know them before the first action. +Failing to apply a needed skill is a protocol violation. Do not create an artifact without first reading and applying the relevant skill. 1. Find `.install-session.json` in the project root 2. In it, the `component_map` field is a dictionary `"type/name" → {ru_path, en_path}` -3. For each skill in `skills:` in the header: +3. For each skill from the `skills:` list in the header: - Find the `skill/{name}` key in `component_map` - - Read ONLY the SKILL.md frontmatter (`name` + `description`) at `ru_path` (or `en_path`) — record the skill's purpose - - Write to context: `[SKILL_NOTED] {name} — purpose recorded` - - Read the full body of SKILL.md later, when the task actually requires applying this skill → then `[SKILL_READ] {name} — read before application` -4. For each path in `depends_on` that contains `/rules/`: - - Extract the filename without extension → this is `name` + - Read ONLY the SKILL.md frontmatter (`name` + `description`) at `ru_path` (or `en_path`) — record the skill purpose + - Write to context: `[SKILL_NOTED] {name} — purpose noted` + - Read the full SKILL.md body later, when the task requires applying that specific skill → then `[SKILL_READ] {name} — read before applying` +4. For each path from `depends_on` containing `/rules/`: + - Extract the filename without extension → that is `name` - Find the `rule/{name}` key in `component_map` - - Read the file at `en_path` (or `ru_path` if EN is missing) + - Read the file at `en_path` (or `ru_path` if EN is unavailable) 5. Apply the read skills and rules throughout the work --- @@ -123,7 +126,7 @@ depends_on: - framework/skills/bsl-practices/error-handling/SKILL.md - framework/skills/bsl-practices/test-writing/SKILL.md - framework/skills/tool-usage/v8-runner/SKILL.md - - framework/skills/tool-usage/browser-ui/visual-check/SKILL.md + - framework/skills/tool-usage/vanessa/va-visual-check/SKILL.md - framework/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md - framework/skills/tool-usage/browser-ui/gui-control/SKILL.md - framework/skills/tool-usage/browser-ui/screenshot/SKILL.md diff --git a/framework_eng/workflows/full-cycle/SKILL.md b/framework_eng/workflows/full-cycle/SKILL.md index 003a1d4b..f8917dfa 100644 --- a/framework_eng/workflows/full-cycle/SKILL.md +++ b/framework_eng/workflows/full-cycle/SKILL.md @@ -1,85 +1,94 @@ --- name: full-cycle -description: Full development cycle with mandatory cross-review at every phase. +description: "For medium and complex tasks, run the full cycle with review" --- # Workflow: Full Development Cycle (Full Cycle) -> Deterministic workflow with cross-review at every phase. For medium and high complexity tasks. +> A deterministic workflow with cross-review at every phase. For medium and high complexity tasks. -> **Place in the hierarchy (Layer 3, read-on-choice).** This is detailed phase mechanics. The orchestration discipline -> and the phase form are already durable in the **orchestrator profile** (`framework/subagents/orchestrator.md`, -> Layer 2). The orchestrator does NOT "load this document as a rule" - it raises the phase mechanics -> from here **when entering a phase**, from its own profile. Launching the full cycle is a Lead-layer -> decision (the "medium/high" classification), not loading an external document into an arbitrary session. +> **Placement in the inheritance tree (Layer 3, read-on-choice).** This is detailed phase mechanics. The discipline +> of orchestration and the phase form are already durable in the **orchestrator profile** (`framework/subagents/orchestrator.md`, +> Layer 2). The orchestrator does NOT "load this document as a rule" - it brings up the phase mechanics +> from here **upon entering the phase**, from its profile. Starting the full cycle is a Lead-layer decision +> (classification "medium/complex"), not loading an external document into an arbitrary session. ## Phases -### Phase 0: Classification (Explorer -> Economy) +### Phase 0: Classification (Explorer → Economy) -Explorer investigates the codebase -> modules, call graphs, dependencies. The orchestrator classifies (Lead-layer of the profile): Simple -> short cycle (skill `quick-fix`); Medium/Complex -> Phase 1. +Explorer studies the codebase → modules, call graphs, dependencies. The orchestrator classifies (Lead layer of the profile): Simple → short cycle (skill `quick-fix`); Medium/Complex → Phase 1. -Explorer artifacts are passed into Phase 1 and Phase 2 as context. +Explorer artifacts are passed to Phase 1 and Phase 2 as context. -### Phase 1: Analysis (Analyst -> Mid/High) +### Phase 1: Analysis (Analyst → Mid/High) Input: task + `explorer-context.md`. Analyst creates a MADR 4.0 + RFC 2119 spec. Reviewer review (Premium). Max. 3 BLOCK iterations. Review + cross-provider-review + **STOP: wait for user OK**. -Approval gate Phase 1 is needed because the specification fixes business decisions (RFC 2119 levels, scope boundaries, choice between alternatives), which the user MUST confirm BEFORE Architect spends resources on a design based on a possibly incorrect contract. Skipping this gate has historically led to multiple iterations: cross-provider-review or Architect found contradictions in the spec that could have been eliminated by one clarification from the user at this stage. +In the Test Plan, Analyst MUST break requirements down by runtime layers and assign a mandatory check +type: server logic/server context → YaxUnit; UI/client context → scenario +UI/BDD test; linked user process → end-to-end process scenario; integration/background +jobs → integration/job check. For existing coverage, the plan must explicitly say which test +is updated and rerun; if there is no coverage, which test is created. -### Phase 2: Architecture (Architect -> High/Premium) +The Phase 1 approval gate is needed because the specification fixes business decisions (RFC 2119 levels, scope boundaries, choice between alternatives) that the user MUST confirm BEFORE the Architect spends resources on a design based on a possibly incorrect contract. Skipping this gate has historically led to multiple iterations: cross-provider-review or the Architect found contradictions in the spec that could be resolved with a single clarification from the user at this stage. -Input: approved spec + `explorer-context.md`. Architect -> `technical-design.md` + `task-breakdown.json`. Review + **STOP: wait for user OK**. +### Phase 2: Architecture (Architect → High/Premium) -### Phase 3: SEQUENTIALLY (3a -> 3b -> 3c -> 3d) +Input: approved spec + `explorer-context.md`. Architect → `technical-design.md` + `task-breakdown.json`. Review + **STOP: wait for user OK**. -Phases 3a-3d proceed strictly sequentially. Each next phase starts only after review of the previous one (and cross-provider-review in advisory). +### Phase 3: SEQUENTIALLY (3a → 3b → 3c → 3d) -- **3a (Scenario-Author -> Mid):** before writing new UI/form scenarios, researches the form through the Vanessa MCP workflow (`vanessa-authoring`: start VA manager -> `connect_test_client` -> VA tools -> `close_test_client`) and records exact commands/elements/required fields in their context. Then spec intent scenarios -> `.feature` Vanessa with `# unknown_step_candidate` for steps not found. Review (scope=bdd). -- **3b (Developer-Tests -> Mid/High):** MUST scenarios from the Test Plan -> unit/integration tests (Red). Review (scope=tests). -- **3c (Scenario-Coder -> Mid):** makes the `.feature` from 3a executable - selects/implements Vanessa steps (`@exportscenarios` or, as an escape hatch, BSL steps in `vanessa-tests/support/`), replaces `unknown_step_candidate`. If a step depends on real UI state, checks it through the Vanessa MCP workflow and closes the test client after the check. Red gate: `v8-runner test va` on the task scenarios shows failure on missing production logic, not on unknown steps. Review (scope=bdd-steps). -- **3d (Developer-Code -> High):** input - everything from Phase 2 + tests from 3b + Red-executable `.feature` from 3a/3c. Writes code (Green for Phase 3b unit tests AND 3a scenarios). On `test_failure` + `suspected_test_error` -> Reviewer arbitration -> routing (to 3b if unit test, to 3c if step, otherwise to 3d). +Phases 3a-3d run strictly sequentially. Each next one starts only after review of the previous one (and cross-provider-review in advisory mode). -**Why 3a and 3c are separated.** Scenario-Author is responsible for **what** should happen (business intent, readable Gherkin). Scenario-Coder is responsible for **how** this is expressed in Vanessa steps (technical implementation of the step library, reuse). Previously no one explicitly did this - steps either stayed `TODO`, or were finished by Developer-Code, blurring the Green gate. The role split gives: (a) a clean Red gate at the scenario level before any production code is written, (b) an owner for step-library quality and reuse, (c) the ability to parameterize steps by domain functionality, not by task. +- **3a (Scenario-Author → Mid):** before writing new UI/form scenarios, researches the form through the Vanessa MCP workflow (`vanessa-authoring`: run VA manager -> `connect_test_client` -> VA-tools -> `close_test_client`) and records exact commands/elements/required fields in their context. Then spec intent scenarios -> `.feature` Vanessa with `# unknown_step_candidate` markers for steps that were not found. Review (scope=bdd). +- **3b (Developer-Tests → Mid/High):** MUST scenarios from the Test Plan that relate to server logic/server context → YaxUnit unit/integration tests (Red). If a server method was changed and a test already exists, update and rerun it; if there is no test, create one. Review (scope=tests). +- **3c (Scenario-Coder → Mid):** makes the `.feature` from 3a executable - selects/implements Vanessa steps (`@exportscenarios` or, as an escape hatch, BSL steps in `vanessa-tests/support/`), replaces `unknown_step_candidate`. If a step depends on real UI state, checks it through the Vanessa MCP workflow and closes the test client after the check. Red gate: `v8-runner test va` on the task scenarios shows failure due to missing production logic, not unknown steps. Review (scope=bdd-steps). +- **3d (Developer-Code → High):** input - everything from Phase 2 + tests from 3b + Red-executable `.feature` from 3a/3c. Writes code (Green for unit tests from Phase 3b AND scenarios from 3a). With `test_failure` + `suspected_test_error` → Reviewer arbitration → routing (to 3b if it's a unit test, to 3c if it's a step, otherwise to 3d). -**Place of the vendor Vanessa MCP workflow.** The research MCP workflow does not replace Red/Green gates and is not a separate full-cycle phase. It is a mandatory technique inside 3a/3c for UI/form scenarios: first get the runtime map of the form and reference data through live VA tools, then write or fix Gherkin. If `v8-client-session-manager` or VA MCP is unavailable, record this as a diagnostic blocker/escape hatch; manual research through the web client is then allowed with the same artifacts in context. +**Why 3a and 3c are separated.** Scenario-Author is responsible for **what** should happen (business intent, readable Gherkin). Scenario-Coder is responsible for **how** this is expressed in Vanessa steps (technical implementation of the step library, reuse). Previously nobody did this explicitly - steps either stayed `TODO`, or were finished by Developer-Code with a blurred Green gate. The separation of roles provides: (a) a clean Red gate at the scenario level before writing production code, (b) ownership of quality and reuse in the step library, (c) the ability to parameterize steps by domain functionality rather than by task. -### Phase 4: Coverage and Regression (Tester -> Mid/High) +**Place of the vendor Vanessa MCP workflow.** The exploratory MCP workflow does not replace Red/Green gates and is not a separate phase of full-cycle. It is a mandatory technique inside 3a/3c for UI/form scenarios: first obtain a runtime map of the form and reference data through live VA-tools, then write or fix Gherkin. For visual artifacts, `va-visual-check` is applied: VA MCP is the preferred route, browser/web fallback is allowed only after recording the completed VA steps, the reasons, and the residual risk. -Tester runs all tests, adds edge cases, integration tests, and regression tests. Review (High). Phase 4 does NOT duplicate Phase 3. +### Phase 4: Coverage and Regression (Tester → Mid/High) + +Tester runs all tests, adds edge cases, integration, and regression tests. Before closing +Phase 4, it checks the coverage matrix from the Test Plan: each server/server-context MUST be covered +by YaxUnit, each UI/client-context MUST be covered by a scenario UI/BDD test, and each linked user process +must be covered by an end-to-end scenario. Review (High). Phase 4 does NOT duplicate Phase 3. --- -## Artifact Transfer +## Artifact Handover -| From -> To | Artifact | +| From → To | Artifact | |--------|----------| -| 0 -> 1, 2 | `explorer-context.md` | -| 1 -> 2 | `spec.md` | -| 2 -> 3a, 3b | spec + technical-design + task-breakdown.json | -| 3a -> 3c | `.feature` (intent) with `unknown_step_candidate` | -| 3b -> 3d | test modules (.bsl) | -| 3c -> 3d | `.feature` with implemented steps + new `@exportscenarios` / BSL steps in `vanessa-tests/support/` | -| 3d -> 4 | BSL + `.feature` + green unit and scenario tests | +| 0 → 1, 2 | `explorer-context.md` | +| 1 → 2 | `spec.md` | +| 2 → 3a, 3b | spec + technical-design + task-breakdown.json | +| 3a → 3c | `.feature` (intent) with `unknown_step_candidate` | +| 3b → 3d | test modules (.bsl) | +| 3c → 3d | `.feature` with implemented steps + new `@exportscenarios` / BSL steps in `vanessa-tests/support/` | +| 3d → 4 | BSL + `.feature` + green unit and scenario tests | -**Required fields:** Specification - Context, Requirements, Scope, Test Plan. Technical Design - components, interfaces. Task Breakdown JSON - task_id, task_type, depends_on, spec_refs, completion criteria. Code - coding standards. Tests - linkage with MUST scenarios. +**Required fields:** Specification - Context, Requirements, Scope, Test Plan. Technical Design - components, interfaces. Task Breakdown JSON - task_id, task_type, depends_on, spec_refs, completion criteria. Code - coding standards. Tests - link to MUST scenarios. --- ## Error Handling | Situation | Action | -|----------|--------| -| BLOCK, <= 3 iterations | Return to author | -| BLOCK, > 3 | Escalate to user | +|----------|----------| +| BLOCK, <= 3 iterations | Return to the author | +| BLOCK, > 3 | Escalate to the user | | User rejected Phase 1 | Analyst revises | | User rejected Phase 2 | Architect revises | -| `test_failure` in Phase 3d | Developer-Code: if own code -> fix it; if unit test -> `suspected_test_error` -> Reviewer arbitration -> 3b; if Vanessa step -> `suspected_step_error` -> Reviewer arbitration -> 3c | -| A step in Phase 3c requires an API outside `technical-design.md` | Scenario-Coder: `clarification_needed` -> Architect (Phase 2) defines the contract further | -| Phase 3c scenario turns green before production code | Sign of a mock in the step -> Scenario-Coder removes the mock, restarts the Red gate | -| `test_failure` in Phase 4 | Tester: if it is their own test -> fix it; if it is a code bug -> `implementation_error` -> Developer | -| `check_syntax` fails | Developer fixes it before review | -| MCP unavailable | Escape hatch -> escalation | +| `test_failure` in Phase 3d | Developer-Code: if own code → fix; if unit test → `suspected_test_error` → Reviewer arbitration → 3b; if Vanessa step → `suspected_step_error` → Reviewer arbitration → 3c | +| A step in Phase 3c requires an API outside `technical-design.md` | Scenario-Coder: `clarification_needed` → Architect (Phase 2) further defines the contract | +| Phase 3c scenario is green before production code | Sign of a mock in the step → Scenario-Coder removes the mock, restarts the Red gate | +| `test_failure` in Phase 4 | Tester: if it's their own test → fix; if it's a code bug → `implementation_error` → Developer | +| `check_syntax` failure | Developer fixes before review | +| MCP/VA unavailable for a UI task | Apply fallback rules `va-visual-check`; if the fallback does not provide sufficient signal, blocker → escalation | --- depends_on: diff --git a/framework_eng/workflows/orchestrator/SKILL.md b/framework_eng/workflows/orchestrator/SKILL.md index eebe4ee8..75a03f78 100644 --- a/framework_eng/workflows/orchestrator/SKILL.md +++ b/framework_eng/workflows/orchestrator/SKILL.md @@ -1,11 +1,6 @@ --- name: orchestrator -description: > - Pointer to the orchestration prompting. After retiering (manifest §6, §7.2), the orchestrator's - operational prompting (Layer 1 — Lead/dispatcher, Layer 2 — discipline) moved into the MAIN THREAD - PROFILE framework/subagents/orchestrator.md. Detailed phase mechanics (Layer 3) — - framework/workflows/full-cycle/SKILL.md. This file is preserved as a stable entry point and a - carrier of depends_on links; it does NOT duplicate the body of the prompting. +description: "Orchestrator routing for work and agent phases" --- # Orchestrator: meta-workflow (pointer) diff --git a/framework_eng/workflows/quick-fix/SKILL.md b/framework_eng/workflows/quick-fix/SKILL.md index a928860a..56a00b91 100644 --- a/framework_eng/workflows/quick-fix/SKILL.md +++ b/framework_eng/workflows/quick-fix/SKILL.md @@ -1,8 +1,6 @@ --- name: quick-fix -description: > - Redirect. quick-fix has been moved into a skill — use the Skill tool or read it directly: - framework/skills/agent-process/quick-fix/SKILL.md +description: "Use quick-fix for small safe changes" alwaysApply: false --- @@ -11,7 +9,7 @@ alwaysApply: false > This file is a fallback redirect. The current body of the quick-fix skill (steps, guard, escalation) > lives in `framework/skills/agent-process/quick-fix/SKILL.md`. -Use the **Skill tool** (`quick-fix`) or read it directly: +Use the **Skill tool** (`quick-fix`) or read directly: ``` framework/skills/agent-process/quick-fix/SKILL.md diff --git a/framework_eng/workflows/source-of-truth-policy/SKILL.md b/framework_eng/workflows/source-of-truth-policy/SKILL.md index 590fb3e8..a25741d4 100644 --- a/framework_eng/workflows/source-of-truth-policy/SKILL.md +++ b/framework_eng/workflows/source-of-truth-policy/SKILL.md @@ -1,16 +1,16 @@ --- name: source-of-truth-policy -description: Pointer redirect. The always-on trigger has moved to framework/rules/source-of-truth/SKILL.md, and the method is in the source-of-truth skill. +description: "Redirect: use source-of-truth rule and skill" alwaysApply: false --- -# Source of Truth Policy - Pointer +# Source of Truth Policy — pointer -> This file is preserved as a stable entry point for existing `depends_on` links. The content is split into two parts: +> This file is kept as a stable entry point for existing `depends_on` links. The content has been split into two parts: > -> - **Always-on trigger + invariant** (L1→L6 hierarchy, “verify the chain from top to bottom”, prohibition of the binary conclusion “the test/code is to blame”) — `framework/rules/source-of-truth/SKILL.md`. -> - **Full method** (end-to-end verification, classification of the first broken link, implications for roles, typical uses) — the `source-of-truth` skill (`framework/skills/agent-process/source-of-truth/SKILL.md`). +> - **Always-on trigger + invariant** (L1→L6 hierarchy, "check the chain from top to bottom", ban on the binary conclusion "the test/code is at fault") — `framework/rules/source-of-truth/SKILL.md`. +> - **Full method** (end-to-end verification, classification of the first broken link, consequences for roles, typical applications) — the `source-of-truth` skill (`framework/skills/agent-process/source-of-truth/SKILL.md`). > -> The heavy always-on rule must live in `framework/rules/` (the installer routes always-on by the root folder — see `tools/install.py`), so the trigger moved there. This file is only a redirect. +> The heavy always-on rule must live in `framework/rules/` (the installer routes always-on rules by the root folder — see `tools/install.py`), so the trigger moved there. Here — only a redirect. --- depends_on: diff --git a/tools/install.py b/tools/install.py index 0594ae24..01859c13 100644 --- a/tools/install.py +++ b/tools/install.py @@ -472,7 +472,7 @@ def _scan(self): # alwaysApply: true → правило-guardrail/триггер. # Без флага → on-demand правило. - # Навыки (skill) флаг не используют — они всегда в skills_dir, не в rules_dir. + # Флаг не влияет на физическую установку компонента. always_apply = str(fm.get("alwaysApply", "")).strip().lower() == "true" if comp_type == "template": @@ -549,9 +549,9 @@ def get_installable_for_user(self) -> List[Component]: def is_always_on_rule(self, comp_id: str) -> bool: """Возвращает True, если правило помечено alwaysApply: true. - Только правила (type=rule) из always-on каталога IDE становятся guardrail/триггерами. - Workflow-файлы и всё без флага — только component_map (on-demand). - Навыки (skill) этот метод не касается — они всегда в skills_dir. + Только правила (type=rule) с alwaysApply становятся guardrail/триггерами. + Workflow-файлы и всё без флага остаются on-demand для оценки контекста, + но всё равно физически устанавливаются. """ comp = self.components.get(comp_id) if not comp: @@ -697,8 +697,8 @@ def print_tree(graph: FrameworkGraph, selected: Optional[Set[str]] = None): - always-on правила (alwaysApply: true) выводятся со связанным навыком-парой (→ имя навыка), если такая пара существует по _build_trigger_skill_pairs. - on-demand правила (без alwaysApply или alwaysApply: false) выводятся в - отдельной подгруппе «on-demand (component_map)» с явной пометкой — чтобы - пользователь видел, что они НЕ попадут в always-on канал IDE. + отдельной подгруппе с явной пометкой — они устанавливаются, но не попадают + в always-on канал IDE/оценки контекста. """ installable = graph.get_installable_for_user() fw_dir = graph.framework_dir @@ -727,9 +727,9 @@ def print_tree(graph: FrameworkGraph, selected: Optional[Set[str]] = None): always_on = [c for c in comps if c.always_apply] on_demand = [c for c in comps if not c.always_apply] - # Подгруппа: always-on правила (попадают в rules_dir IDE) + # Подгруппа: always-on правила (автозагрузка/контекст IDE) if always_on: - print(f"\n {dim('always-on (в rules-каталог IDE)')}") + print(f"\n {dim('always-on (автозагрузка/контекст IDE)')}") for c in sorted(always_on, key=lambda x: x.id): marker = green(" ✓") if selected and c.id in selected else "" linked = graph.get_linked_components(c.id) @@ -741,9 +741,9 @@ def print_tree(graph: FrameworkGraph, selected: Optional[Set[str]] = None): idx_map[idx] = c.id idx += 1 - # Подгруппа: on-demand правила (только component_map, НЕ в always-on канал) + # Подгруппа: on-demand правила (устанавливаются, но НЕ в always-on канал) if on_demand: - print(f"\n {dim('on-demand (только component_map, НЕ в always-on канал IDE)')}") + print(f"\n {dim('on-demand (устанавливаются, НЕ в always-on канал IDE)')}") for c in sorted(on_demand, key=lambda x: x.id): marker = green(" ✓") if selected and c.id in selected else "" linked = graph.get_linked_components(c.id) @@ -891,8 +891,8 @@ def _build_checklist_items(graph: FrameworkGraph) -> List: Для секции «Правила»: - always-on правила выводятся в подгруппе «always-on», со связанным навыком в описании (переиспользует _build_trigger_skill_pairs, не дублирует логику). - - on-demand правила выводятся в подгруппе «on-demand (component_map)» с явной пометкой - в описании — чтобы пользователь видел, что в always-on канал IDE они не попадут. + - on-demand правила выводятся в отдельной подгруппе с явной пометкой + в описании — они устанавливаются, но в always-on канал IDE не попадают. """ items = [] # (id, label, description, is_header) installable = graph.get_installable_for_user() @@ -918,9 +918,9 @@ def _build_checklist_items(graph: FrameworkGraph) -> List: always_on = [c for c in comps if c.always_apply] on_demand = [c for c in comps if not c.always_apply] - # Подгруппа: always-on (попадают в rules_dir IDE) + # Подгруппа: always-on (автозагрузка/контекст IDE) if always_on: - items.append(("", " always-on (в rules-каталог IDE)", "", True)) + items.append(("", " always-on (автозагрузка/контекст IDE)", "", True)) for c in sorted(always_on, key=lambda x: x.id): paired_skill = pairs_map.get(c.id) desc = c.short_description() @@ -928,9 +928,9 @@ def _build_checklist_items(graph: FrameworkGraph) -> List: desc = f"{desc} → навык: {paired_skill.split('/')[-1]}" items.append((c.id, c.id, desc, False)) - # Подгруппа: on-demand (только component_map, НЕ в always-on канал) + # Подгруппа: on-demand (устанавливаются, но НЕ в always-on канал) if on_demand: - items.append(("", " on-demand (component_map, не в always-on канал IDE)", "", True)) + items.append(("", " on-demand (устанавливаются, не в always-on канал IDE)", "", True)) for c in sorted(on_demand, key=lambda x: x.id): desc = f"[on-demand] {c.short_description()}" items.append((c.id, c.id, desc, False)) @@ -1811,8 +1811,14 @@ def _mirror_of(ru_path: Path) -> Optional[Path]: # agent → профиль: .codex/agents/.toml (конвертация из *.md) def _rule_workflow_file_skill_mode(comp: Component, ide_key: str) -> bool: - """Для не-Codex платформ rule/workflow устанавливаются как file-style skills.""" - return ide_key != "codex" and comp.type in ("rule", "workflow") and "skills_dir" in IDE_CONFIGS[ide_key] + """True, если IDE явно требует rule/workflow в каталоге skills как file-style skill. + + По умолчанию rule/workflow идут в rules/workflows-каталоги IDE. Это важно + для Claude Code: правила оформлены в framework как skill-каталоги с SKILL.md, + но устанавливаются как файловые ссылки .claude/rules/.md. + """ + ide_cfg = IDE_CONFIGS[ide_key] + return bool(ide_cfg.get("rule_workflow_file_skill_mode")) and comp.type in ("rule", "workflow") def _codex_mode(comp: Component, ide_key: str) -> Optional[str]: """Режим codex-специфичной установки для компонента или None. @@ -2064,6 +2070,23 @@ def _legacy_rule_workflow_rules_target_file( return project_dir / ide_cfg[dir_key] / f"{short_name}{ext}" +def _legacy_rule_workflow_file_skill_target_file( + comp: Component, + ide_key: str, + project_dir: Path, +) -> Optional[Path]: + """Ошибочный старый путь rule/workflow как .claude/.cursor skills/.md.""" + if comp.type not in ("rule", "workflow"): + return None + if _rule_workflow_file_skill_mode(comp, ide_key): + return None + ide_cfg = IDE_CONFIGS[ide_key] + if "skills_dir" not in ide_cfg: + return None + _, _, short_name = _component_source_paths(comp) + return project_dir / ide_cfg["skills_dir"] / f"{short_name}.md" + + def _norm_path(path: Path) -> str: """Нормализует путь для безопасного сравнения.""" return str(path.resolve(strict=False)) @@ -2085,6 +2108,8 @@ def _component_expected_symlink_source( return source_path if _rule_workflow_file_skill_mode(comp, ide_key): return source_file + if comp.type in ("rule", "workflow"): + return source_file return source_file if not use_symlinks_target else source_path @@ -2238,7 +2263,7 @@ def install_components( # Показываем пары «триггер + навык» для наглядности print_trigger_skill_pairs(graph, all_ids) - # Подсчёт правил: сколько always-on, сколько only component_map + # Подсчёт правил: сколько always-on, сколько on-demand. always_on_rules = [cid for cid in all_ids if graph.components.get(cid) and graph.components[cid].type == "rule" and graph.components[cid].always_apply] @@ -2298,20 +2323,16 @@ def install_components( skipped += 1 continue - # Фильтр alwaysApply применим только к старому rules-каталогу IDE. - # Когда rule/workflow устанавливается как skill, физически размещаем все правила. - if ( - comp.type == "rule" - and not comp.always_apply - and ide_key != "codex" - and not _rule_workflow_file_skill_mode(comp, ide_key) - ): - # Правило не-always-on: пропускаем физическое размещение, но включаем в component_map. - # Вывод только в dry-run для наглядности. + # Удаляем хвосты прежнего ошибочного размещения rule/workflow как + # skills/.md до штатной установки в rules/workflows-каталоги. + legacy_skill_target = _legacy_rule_workflow_file_skill_target_file( + comp, ide_key, project_dir + ) + if legacy_skill_target and (legacy_skill_target.exists() or legacy_skill_target.is_symlink()): if dry_run: - print(f" → (component_map only, alwaysApply missing) {comp_id}") - skipped += 1 - continue + print(f" ← remove legacy {legacy_skill_target}") + else: + legacy_skill_target.unlink() source_file, source_path, _ = _component_source_paths(comp, graph.framework_dir, graph.mirror_dir) target_file = _component_target_file(comp, ide_key, project_dir, use_symlinks=use_symlinks, graph=graph) @@ -2412,10 +2433,12 @@ def install_components( elif use_symlinks: try: try: - rel_path = os.path.relpath(source_path, target_file.parent) + link_source = source_file if comp.type in ("rule", "workflow") else source_path + rel_path = os.path.relpath(link_source, target_file.parent) target_file.symlink_to(rel_path) except ValueError: - target_file.symlink_to(source_path) + link_source = source_file if comp.type in ("rule", "workflow") else source_path + target_file.symlink_to(link_source) installed += 1 except OSError as e: print(red(f" ✗ Ошибка симлинка {comp.id}: {e}")) @@ -2427,6 +2450,8 @@ def install_components( ) if comp.type == "skill" or _rule_workflow_file_skill_mode(comp, ide_key): shutil.copy2(source_file, copy_target) + elif comp.type in ("rule", "workflow"): + shutil.copy2(source_file, copy_target) else: shutil.copy2(source_path, copy_target) print(yellow(f" → скопирован как fallback")) @@ -2435,6 +2460,8 @@ def install_components( # При копировании: для навыков копируем SKILL.md, для остальных — сам файл if comp.type == "skill" or _rule_workflow_file_skill_mode(comp, ide_key): shutil.copy2(source_file, target_file) + elif comp.type in ("rule", "workflow"): + shutil.copy2(source_file, target_file) else: shutil.copy2(source_path, target_file) installed += 1 diff --git a/tools/test_install_always_apply.py b/tools/test_install_always_apply.py index f2ca57e3..f17f7a88 100644 --- a/tools/test_install_always_apply.py +++ b/tools/test_install_always_apply.py @@ -1,10 +1,11 @@ #!/usr/bin/env python3 """ -Тесты фильтра alwaysApply для установщика фреймворка. +Тесты обработки alwaysApply для установщика фреймворка. Проверяет: - 1. Правила и workflow устанавливаются как skills в форме, нужной IDE. - 2. alwaysApply сохраняется в component_map и влияет на оценку контекста. + 1. Правила и workflow устанавливаются в форме, нужной IDE. + 2. alwaysApply сохраняется в component_map и влияет на оценку контекста, но + не фильтрует физическую установку. 3. Навыки всегда в skills_dir, флаг не влияет. 4. estimate_context_usage: правило без флага в on-demand, а не в always. @@ -193,12 +194,20 @@ def _run_install( return installed, skipped -def test_install_claude_code_rules_as_file_skills(): - """Claude Code: все правила и workflow копируются как file-style skills.""" +def test_install_claude_code_rules_as_rule_files(): + """Claude Code: все правила и workflow ставятся файловыми ссылками. + + alwaysApply не фильтрует состав установки: он используется только как + метаданное/подсказка загрузки для IDE и оценки контекста. + """ with tempfile.TemporaryDirectory() as tmp: fw, base = _make_fw(Path(tmp)) project_dir = base / "project" project_dir.mkdir() + legacy_skills_dir = project_dir / ".claude" / "skills" + legacy_skills_dir.mkdir(parents=True) + for name in ("rule-always", "rule-lazy", "rule-explicit-false", "my-workflow"): + (legacy_skills_dir / f"{name}.md").write_text("legacy", encoding="utf-8") _run_install(fw, "claude-code", project_dir) @@ -206,12 +215,12 @@ def test_install_claude_code_rules_as_file_skills(): skills_dir = project_dir / ".claude" / "skills" for name in ("rule-always", "rule-lazy", "rule-explicit-false", "my-workflow"): - skill_file = skills_dir / f"{name}.md" - assert skill_file.exists(), ( - f"{name}.md ожидается как file-style skill в {skills_dir}" + rule_file = rules_dir / f"{name}.md" + assert rule_file.exists(), ( + f"{name}.md ожидается как файловая ссылка в {rules_dir}" ) - assert not (rules_dir / f"{name}.md").exists(), ( - f"{name}.md НЕ ожидается в {rules_dir}" + assert not (skills_dir / f"{name}.md").exists(), ( + f"{name}.md НЕ ожидается в {skills_dir}" ) # Навык должен быть в skills_dir @@ -220,14 +229,14 @@ def test_install_claude_code_rules_as_file_skills(): f"Навык my-skill/SKILL.md ожидается в {skills_dir}" ) - print(" OK test_install_claude_code_rules_as_file_skills") + print(" OK test_install_claude_code_rules_as_rule_files") def test_install_codex_rules_as_skills(): """Codex: правила разворачиваются как навыки в .codex/skills//SKILL.md. - В отличие от claude-code, фильтр alwaysApply НЕ применяется — берутся ВСЕ - правила (и always-on, и lazy), т.к. Codex читает их как навыки по требованию. + Как и для claude-code, фильтр alwaysApply НЕ применяется — берутся ВСЕ + правила (и always-on, и lazy). Codex дополнительно читает их как навыки по требованию. Каталог .codex/rules/ не используется. """ with tempfile.TemporaryDirectory() as tmp: @@ -622,7 +631,7 @@ def main(): tests = [ test_always_apply_parsed, test_is_always_on_rule, - test_install_claude_code_rules_as_file_skills, + test_install_claude_code_rules_as_rule_files, test_install_codex_rules_as_skills, test_install_codex_rules_as_directory_symlinks, test_install_codex_workflows_as_skills, @@ -635,7 +644,7 @@ def main(): ] print(f"\n{'─' * 60}") - print(f" Тесты фильтра alwaysApply (install.py)") + print(f" Тесты обработки alwaysApply (install.py)") print(f"{'─' * 60}\n") passed = 0