cardbuddy 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/preview-editor/assets/index-BkbBxDTT.css +1 -0
  2. package/dist/preview-editor/assets/{index-CIIfMlwI.js → index-Bro07DTa.js} +91 -88
  3. package/dist/preview-editor/index.html +2 -2
  4. package/dist/vendored/card-editor/runtime/adapter.js +2 -2
  5. package/dist/vendored/mcp/client.mjs +1 -1
  6. package/dist/vendored/server/core/ai-chat.js +251 -80
  7. package/dist/vendored/server/core/cardValidate.js +16 -5
  8. package/dist/vendored/skills/card-skill-trainer/SKILL.md +61 -6
  9. package/dist/vendored/skills/card-skill-trainer/scripts/diagnose_case.mjs +14 -82
  10. package/dist/vendored/skills/card-skill-trainer/scripts/lib/diagnosis.mjs +207 -0
  11. package/dist/vendored/skills/card-skill-trainer/scripts/lib/layout-correction-sim.mjs +62 -0
  12. package/dist/vendored/skills/card-skill-trainer/scripts/lib/paradigm-router.mjs +76 -0
  13. package/dist/vendored/skills/card-skill-trainer/scripts/lib/pixel-worker-runner.mjs +31 -0
  14. package/dist/vendored/skills/card-skill-trainer/scripts/lib/pixel-worker.mjs +138 -0
  15. package/dist/vendored/skills/card-skill-trainer/scripts/lib/scoring.mjs +24 -20
  16. package/dist/vendored/skills/card-skill-trainer/scripts/lib/telemetry.mjs +46 -0
  17. package/dist/vendored/skills/card-skill-trainer/scripts/plan_next_round.mjs +4 -1
  18. package/dist/vendored/skills/card-skill-trainer/scripts/run_round.mjs +279 -90
  19. package/dist/vendored/skills/card-skill-trainer/scripts/score_round.mjs +74 -2
  20. package/dist/vendored/skills/card-skill-trainer/scripts/sink_rules.mjs +127 -0
  21. package/dist/vendored/skills/dsl-card-generator/SKILL.md +93 -27
  22. package/dist/vendored/skills/dsl-card-generator/references/dsl_structure.md +1 -15
  23. package/dist/vendored/skills/dsl-card-generator/references/expression_engine.md +11 -20
  24. package/dist/vendored/skills/dsl-card-generator/references/generation_pitfalls.md +169 -44
  25. package/dist/vendored/skills/dsl-card-generator/references/ir-format.md +87 -3
  26. package/dist/vendored/skills/dsl-card-generator/references/iteration_protocol.md +35 -6
  27. package/dist/vendored/skills/dsl-card-generator/references/quickref.md +28 -27
  28. package/dist/vendored/skills/dsl-card-generator/references/recipes.md +30 -8
  29. package/dist/vendored/skills/dsl-card-generator/references/rules.md +3 -2
  30. package/dist/vendored/skills/dsl-card-generator/references/scripts_reference.md +5 -2
  31. package/dist/vendored/skills/dsl-card-generator/references/slices_convention.md +2 -3
  32. package/dist/vendored/skills/dsl-card-generator/references/spec_to_schema_patterns.md +1 -4
  33. package/dist/vendored/skills/dsl-card-generator/scripts/add_component.mjs +5 -14
  34. package/dist/vendored/skills/dsl-card-generator/scripts/autofix_schema.py +88 -0
  35. package/dist/vendored/skills/dsl-card-generator/scripts/check_fidelity.mjs +143 -42
  36. package/dist/vendored/skills/dsl-card-generator/scripts/check_topology.py +0 -35
  37. package/dist/vendored/skills/dsl-card-generator/scripts/expand_ir.mjs +99 -53
  38. package/dist/vendored/skills/dsl-card-generator/scripts/gate.mjs +5 -2
  39. package/dist/vendored/skills/dsl-card-generator/scripts/iterate.mjs +388 -29
  40. package/dist/vendored/skills/dsl-card-generator/scripts/lib/component_contract.mjs +315 -0
  41. package/dist/vendored/skills/dsl-card-generator/scripts/lib/layout-tokens.mjs +1 -1
  42. package/dist/vendored/skills/dsl-card-generator/scripts/lib/paths.mjs +23 -0
  43. package/dist/vendored/skills/dsl-card-generator/scripts/lib/paths.py +0 -37
  44. package/dist/vendored/skills/dsl-card-generator/scripts/lib/python.mjs +99 -0
  45. package/dist/vendored/skills/dsl-card-generator/scripts/lib/rules/adaptive-width.mjs +105 -0
  46. package/dist/vendored/skills/dsl-card-generator/scripts/lib/rules/bindings.mjs +260 -0
  47. package/dist/vendored/skills/dsl-card-generator/scripts/lib/rules/expr.mjs +52 -0
  48. package/dist/vendored/skills/dsl-card-generator/scripts/lib/rules/image.mjs +96 -0
  49. package/dist/vendored/skills/dsl-card-generator/scripts/lib/rules/registry.mjs +166 -0
  50. package/dist/vendored/skills/dsl-card-generator/scripts/lib/rules/structure.mjs +127 -0
  51. package/dist/vendored/skills/dsl-card-generator/scripts/lib/rules/walk.mjs +61 -0
  52. package/dist/vendored/skills/dsl-card-generator/scripts/lib/scope_alias.mjs +125 -0
  53. package/dist/vendored/skills/dsl-card-generator/scripts/lib/v3_assemble.mjs +325 -41
  54. package/dist/vendored/skills/dsl-card-generator/scripts/lib/v3_extract.mjs +112 -6
  55. package/dist/vendored/skills/dsl-card-generator/scripts/lib/v3_shared.mjs +0 -6
  56. package/dist/vendored/skills/dsl-card-generator/scripts/lint_card.mjs +119 -78
  57. package/dist/vendored/skills/dsl-card-generator/scripts/preflight.mjs +48 -50
  58. package/dist/vendored/skills/dsl-card-generator/scripts/readiness.mjs +634 -0
  59. package/dist/vendored/skills/dsl-card-generator/scripts/register_card_template.mjs +5 -8
  60. package/dist/vendored/skills/dsl-card-generator/scripts/route_input.mjs +5 -10
  61. package/dist/vendored/skills/dsl-card-generator/scripts/spec_audit.mjs +122 -8
  62. package/dist/vendored/skills/dsl-card-generator/scripts/v3_regression.mjs +3 -1
  63. package/dist/vendored/skills/dsl-card-generator/scripts/validate_schema.py +23 -15
  64. package/dist/vendored/skills/shared/exit-codes.md +79 -0
  65. package/dist/vendored/skills/shared/spec-contract.md +118 -0
  66. package/dist/vendored/skills/sketch-spec-to-card/SKILL.md +26 -9
  67. package/dist/vendored/skills/sketch-spec-to-card/references/spec-schema.md +3 -3
  68. package/dist/vendored/skills/sketch-spec-to-card/scripts/build_prompt.py +0 -8
  69. package/dist/vendored/skills/sketch-spec-to-card/scripts/cluster_states.py +14 -25
  70. package/dist/vendored/skills/sketch-spec-to-card/scripts/parse_meaxure.py +91 -47
  71. package/dist/vendored/skills/sketch-spec-to-card/scripts/png_utils.py +0 -5
  72. package/dist/vendored/skills/sketch-spec-to-card/scripts/test_text_only_artboard.py +75 -15
  73. package/dist/vendored/skills/sketch-spec-to-card/scripts/vision.py +40 -34
  74. package/package.json +1 -1
  75. package/dist/preview-editor/assets/index-DQn0zQBP.css +0 -1
  76. package/dist/vendored/skills/card-skill-trainer/scripts/test_missing_slice.py +0 -122
  77. package/dist/vendored/skills/dsl-card-generator/scripts/analyze_component_usage.mjs +0 -153
@@ -1,153 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * analyze_component_usage.mjs — 组件/范式使用分析,用真实卡片数据反哺 recipes。
4
- *
5
- * 回答三个问题:
6
- * 1. 哪些组件/范式最高频?(className 频率 + recipe 探测命中卡数)
7
- * 2. 哪些结构组合最常见?(父→子组件共现对,供新 recipe 候选判断)
8
- * 3. 现有 recipe 片段健康度如何?(recipe_snippets/*.json 各被多少卡使用;
9
- * 0 使用 = 候选复核,高频无片段 = 候选补充)
10
- *
11
- * 数据源:直接扫宿主项目卡片 schema(唯一真源),复用 build_card_index.mjs 的
12
- * RECIPE_PROBES / collectComponents(同一份探测定义,不复制)。
13
- *
14
- * 用法:
15
- * node skills/dsl-card-generator/scripts/analyze_component_usage.mjs [--json] [--out <path>]
16
- * (在宿主项目根目录跑;卡片目录由 lib/paths.mjs 解析)
17
- *
18
- * 退出码:0 = 正常(报告制工具,永不拦截)。
19
- */
20
- import fs from 'node:fs'
21
- import path from 'node:path'
22
- import { fileURLToPath } from 'node:url'
23
- import { cardsDir, skillRoot } from './lib/paths.mjs'
24
- import { RECIPE_PROBES, collectComponents } from './build_card_index.mjs'
25
-
26
- const SNIPPETS_DIR = path.join(skillRoot, 'references', 'recipe_snippets')
27
-
28
- /** snippet 文件名 → recipe 探测 key(无对应探测的记 null = unprobed,如实报告不硬凑) */
29
- const SNIPPET_PROBE = {
30
- 'alertCard-pair': 'alertCard',
31
- 'canvas-title-head': 'canvas-head',
32
- 'list-expand-collapse': 'list-expand',
33
- globalSet: 'globalSet',
34
- 'money-format': 'money-format',
35
- tabBillMode: 'tab-billMode',
36
- 'tab-billMode': 'tab-billMode',
37
- }
38
-
39
- /** 遍历全部节点(双通道),回调 (node, parentClassName) */
40
- function walk(node, parent, cb) {
41
- if (!node || typeof node !== 'object') return
42
- const cls = node.className || '?'
43
- cb(node, parent)
44
- for (const c of node.components || []) walk(c, cls, cb)
45
- for (const s of node.slots || []) for (const c of s.components || []) walk(c, cls, cb)
46
- }
47
-
48
- function main() {
49
- const argv = process.argv.slice(2)
50
- const asJson = argv.includes('--json')
51
- const outIdx = argv.indexOf('--out')
52
- const outPath = outIdx >= 0 ? argv[outIdx + 1] : null
53
-
54
- const ids = fs.readdirSync(cardsDir).filter((id) => {
55
- const d = path.join(cardsDir, id)
56
- return fs.statSync(d).isDirectory() && fs.existsSync(path.join(d, 'schema.json'))
57
- })
58
-
59
- const compCards = new Map() // className -> Set<cardId>(多少卡用过)
60
- const compTotal = new Map() // className -> 实例总数
61
- const pairs = new Map() // 'Parent>Child' -> 次数
62
- const recipeCards = new Map(RECIPE_PROBES.map((p) => [p.key, new Set()]))
63
- let parseFail = 0
64
-
65
- for (const id of ids) {
66
- let schema
67
- try {
68
- schema = JSON.parse(fs.readFileSync(path.join(cardsDir, id, 'schema.json'), 'utf8'))
69
- } catch {
70
- parseFail++
71
- continue
72
- }
73
- const text = JSON.stringify(schema)
74
- for (const p of RECIPE_PROBES) if (p.test(text)) recipeCards.get(p.key).add(id)
75
-
76
- const inCard = new Set()
77
- walk(schema.view, null, (node, parent) => {
78
- const cls = node.className || '?'
79
- inCard.add(cls)
80
- compTotal.set(cls, (compTotal.get(cls) || 0) + 1)
81
- if (parent) {
82
- const key = `${parent}>${cls}`
83
- pairs.set(key, (pairs.get(key) || 0) + 1)
84
- }
85
- })
86
- for (const cls of inCard) {
87
- if (!compCards.has(cls)) compCards.set(cls, new Set())
88
- compCards.get(cls).add(id)
89
- }
90
- }
91
-
92
- // snippet 健康度:每个片段对应探测的命中卡数;无探测记 null
93
- const snippetFiles = fs.existsSync(SNIPPETS_DIR)
94
- ? fs.readdirSync(SNIPPETS_DIR).filter((f) => f.endsWith('.json')).sort()
95
- : []
96
- const snippets = snippetFiles.map((f) => {
97
- const key = f.replace(/\.json$/, '')
98
- const probe = Object.prototype.hasOwnProperty.call(SNIPPET_PROBE, key) ? SNIPPET_PROBE[key] : null
99
- return {
100
- snippet: key,
101
- probe,
102
- usedByCards: probe ? recipeCards.get(probe).size : null,
103
- }
104
- })
105
-
106
- const sorted = (m, val) => [...m.entries()].sort((a, b) => val(b) - val(a))
107
- const report = {
108
- generatedAt: new Date().toISOString(),
109
- cardCount: ids.length,
110
- parseFail,
111
- components: sorted(compCards, (e) => e[1].size).map(([className, cards]) => ({
112
- className,
113
- cards: cards.size,
114
- instances: compTotal.get(className) || 0,
115
- })),
116
- recipes: RECIPE_PROBES.map((p) => ({ recipe: p.key, cards: recipeCards.get(p.key).size })).sort(
117
- (a, b) => b.cards - a.cards,
118
- ),
119
- topPairs: sorted(pairs, (e) => e[1])
120
- .slice(0, 20)
121
- .map(([pair, count]) => ({ pair, count })),
122
- snippetHealth: snippets.sort((a, b) => (b.usedByCards ?? -1) - (a.usedByCards ?? -1)),
123
- }
124
-
125
- if (asJson) {
126
- console.log(JSON.stringify(report, null, 2))
127
- } else {
128
- console.log(`\n📊 组件使用分析(${report.cardCount} 张卡${parseFail ? `,${parseFail} 张解析失败` : ''})`)
129
- console.log('\n组件频率(使用卡数 / 实例数):')
130
- for (const c of report.components) console.log(` ${c.className.padEnd(16)} ${String(c.cards).padStart(3)} 卡 / ${c.instances} 实例`)
131
- console.log('\n范式命中(卡数):')
132
- for (const r of report.recipes) console.log(` ${r.recipe.padEnd(16)} ${r.cards} 卡`)
133
- console.log('\nTop 结构组合(父>子 共现):')
134
- for (const p of report.topPairs.slice(0, 10)) console.log(` ${p.pair.padEnd(28)} ${p.count}`)
135
- console.log('\nrecipe 片段健康度:')
136
- for (const s of report.snippetHealth) {
137
- const usage = s.usedByCards == null ? 'unprobed(无对应探测,需人工判断)' : `${s.usedByCards} 卡使用`
138
- const flag = s.usedByCards === 0 ? ' ⚠️ 0 使用,候选复核' : ''
139
- console.log(` ${s.snippet.padEnd(24)} ${usage}${flag}`)
140
- }
141
- }
142
-
143
- if (outPath) {
144
- const abs = path.resolve(outPath)
145
- fs.mkdirSync(path.dirname(abs), { recursive: true })
146
- fs.writeFileSync(abs, JSON.stringify(report, null, 2) + '\n')
147
- console.log(`\n报告已落盘: ${abs}`)
148
- }
149
- }
150
-
151
- const _thisScript = fs.realpathSync(fileURLToPath(import.meta.url))
152
- const _calledAs = process.argv[1] ? fs.realpathSync(path.resolve(process.argv[1])) : ''
153
- if (_thisScript === _calledAs) main()