feat(dev): 新增组件样式与表单辅助 Skill

This commit is contained in:
zhiye.sun
2026-08-25 17:16:03 +08:00
parent da5678f260
commit dec3855ce6
27 changed files with 335 additions and 14 deletions
+5 -3
View File
@@ -136,13 +136,14 @@ plan-change
### 项目规范与前端辅助批次
1. `dev/select-component`
2. `dev/design-style`
3. `dev/design-form`
1. `dev/component`(已完成,基于项目证据完成组件选型与契约查证)
2. `dev/style`(已完成,基于项目视觉基线设计样式)
3. `dev/form`(已完成,设计表单结构、响应布局和可访问性)
4. `skill/guidance`(特殊样本已完成)
5. `skill/guidance-edit`
这里只实现读取和维护“当前项目自身规范”的机制,不随 CraftKit 提供任何来源项目规范。
原前端导航能力由上述 Skill 的精确触发描述和 Codex 自动发现替代,不再维护独立路由 Skill。混合任务按 `style` → `component` → `form` → 前端设计或实现的依赖顺序处理。
### 基于公开资料重建批次
@@ -236,3 +237,4 @@ plan-change
- [x] 完成 Git 本地操作批次:`identity`、`export`。
- [x] 完成 Git 高风险隔离集成样本:`integrate`。
- [x] 完成知识管理批次:`trace`、`distill`、`lessons`、`worklog`。
- [x] 完成前端辅助批次:`component`、`style`、`form`,并以精确触发替代独立路由。
+21 -5
View File
@@ -118,7 +118,10 @@
"source-b:f6ec7bd5501e6ea5": {
"sourcePathHash": "f6ec7bd5501e6ea5f6e907a586a8d7cbe5fbbeebd3e5c8efead9b250742a148e",
"sourceSha256": "25905b3b294b0be2e245099acb1a557793215f157b96b9e964e78170838652f0",
"status": "pending"
"status": "migrated",
"target": "plugins/dev/skills/component",
"targetVersion": "0.1.0",
"reviewedAt": "2026-08-25"
},
"source-b:c49d1db42acd7220": {
"sourcePathHash": "c49d1db42acd722071d61420be58ba8ccbc54f5370bdf951abfb5981914271cf",
@@ -128,7 +131,10 @@
"source-b:9a3f3d3c43d9017a": {
"sourcePathHash": "9a3f3d3c43d9017a080a9832df5b975e6ddd3f8c39947ee768aeb973fc23974e",
"sourceSha256": "47c072e792d1cf80ddcc69536236ccb525d21e7d5408ed41cca55483556e8acb",
"status": "pending"
"status": "superseded",
"target": "plugins/dev/skills",
"reason": "前端导航能力已由 component、style、form 的精确触发描述和 Codex 自动发现替代",
"reviewedAt": "2026-08-25"
},
"source-b:eb730c56bc7a4a15": {
"sourcePathHash": "eb730c56bc7a4a158ddec74c7497a10fdea2d0b628783b968e3ee9ee4572b15c",
@@ -141,7 +147,10 @@
"source-b:422174b0c00bbd65": {
"sourcePathHash": "422174b0c00bbd657f4c08415d4a722584556cfa5f3edc997b11e8ab0ef8656a",
"sourceSha256": "017a4ca0b7648ed91003deeb97a3757e8f17acd6963c6019140389a907f1345a",
"status": "pending"
"status": "migrated",
"target": "plugins/dev/skills/style",
"targetVersion": "0.1.0",
"reviewedAt": "2026-08-25"
},
"source-b:742ba3611bee4e34": {
"sourcePathHash": "742ba3611bee4e34dfee6dadbe192dd8be677c4b9f49108e2f04d9e22dc8801f",
@@ -190,7 +199,11 @@
"source-b:ca08ee8839bccc15": {
"sourcePathHash": "ca08ee8839bccc1504c253cdb9bfc09803ddf77f948605f8563d04e0466a2ce7",
"sourceSha256": "0086c8da048d94303e9d5765b91b7eff9a10a798ffa73de9f245be5422cf3255",
"status": "pending"
"status": "superseded",
"target": "plugins/dev/skills/component",
"targetVersion": "0.1.0",
"reason": "组件约定与契约查证能力已合并到 component",
"reviewedAt": "2026-08-25"
},
"source-b:1b4cee54060ef399": {
"sourcePathHash": "1b4cee54060ef3995d6c98e99dee3c3200ab2e90dd62136cef07b9b09e31364d",
@@ -205,7 +218,10 @@
"source-b:5f525e6aeda55dd8": {
"sourcePathHash": "5f525e6aeda55dd81c26d38cf59097cb52abbcfc5b05e35fe7e8101a1a3353b5",
"sourceSha256": "8068a6137951e94a01bc68cf9011db69f3d759304a3167291afa4c238531e34a",
"status": "pending"
"status": "migrated",
"target": "plugins/dev/skills/form",
"targetVersion": "0.1.0",
"reviewedAt": "2026-08-25"
},
"source-b:f2079362cf82e719": {
"sourcePathHash": "f2079362cf82e719e2dde6098c55ce984709a97446a7f66113f8b5f317f1f55b",
+51
View File
@@ -0,0 +1,51 @@
"""前端辅助 Skill 的结构与行为边界测试。"""
from pathlib import Path
import unittest
ROOT = Path(__file__).resolve().parents[2]
DEV_SKILLS = ROOT / "plugins" / "dev" / "skills"
def read_skill(name: str) -> str:
"""读取指定 Skill 的入口及引用文档。"""
folder = DEV_SKILLS / name
files = [folder / "SKILL.md", *sorted((folder / "references").glob("*.md"))]
return "\n".join(path.read_text(encoding="utf-8") for path in files)
class FrontendHelpersTest(unittest.TestCase):
"""验证三个 Skill 能互补协作且不恢复来源专有规则。"""
def test_component_requires_project_evidence(self) -> None:
content = read_skill("component")
self.assertIn(".craftkit/project.json", content)
self.assertIn(".craftkit/standards/frontend/components.md", content)
self.assertIn("不编造结论", content)
self.assertIn("官方文档", content)
self.assertIn("不复制依赖库文档", content)
def test_style_uses_existing_visual_authority(self) -> None:
content = read_skill("style")
self.assertIn("设计令牌", content)
self.assertIn("经用户确认后再修改", content)
self.assertIn("不内置固定矩阵", content)
def test_form_does_not_invent_business_rules(self) -> None:
content = read_skill("form")
self.assertIn("不自行确定字段必填", content)
self.assertIn("不设计接口", content)
self.assertIn("component", content)
def test_precise_skills_replace_router(self) -> None:
self.assertFalse((DEV_SKILLS / "guide").exists())
descriptions = {
name: (DEV_SKILLS / name / "SKILL.md").read_text(encoding="utf-8").split("---", 2)[1]
for name in ("component", "style", "form")
}
self.assertEqual(3, len(set(descriptions.values())))
if __name__ == "__main__":
unittest.main()
+20
View File
@@ -71,6 +71,9 @@ class GuidanceInitTest(unittest.TestCase):
self.assertEqual(1, payload["schemaVersion"])
self.assertIn(payload["initialization"]["mode"], {"existing", "new"})
self.assertEqual([], payload["dependencies"]["internal"])
self.assertEqual([], payload["frontend"]["componentLibraries"])
self.assertEqual([], payload["frontend"]["componentRoots"])
self.assertEqual([], payload["frontend"]["documentation"])
self.assertEqual(
".craftkit/standards/index.md",
payload["guidance"]["standardsIndex"],
@@ -78,6 +81,23 @@ class GuidanceInitTest(unittest.TestCase):
serialized = json.dumps(payload, ensure_ascii=False)
self.assertNotIn(":\\", serialized)
def test_init_collects_frontend_component_metadata(self) -> None:
"""初始化应记录组件库证据和入口,但不能默认选择组件库。"""
content = "\n".join(
path.read_text(encoding="utf-8")
for path in (
INIT / "SKILL.md",
INIT / "references" / "project-config.md",
INIT / "references" / "existing.md",
INIT / "references" / "new.md",
)
)
self.assertIn("componentLibraries", content)
self.assertIn("组件根", content)
self.assertIn("不默认选择流行方案", content)
self.assertTrue((INIT / "assets" / "frontend-components.md").is_file())
def test_local_directories_are_the_only_nested_ignores(self) -> None:
"""初始化模板只排除本地状态和缓存,不得排除共享资料。"""