@qilitt-mickey/vue3-temp-skill 1.1.76 → 1.2.1
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.
- package/README.md +85 -84
- package/SKILL.md +55 -27
- package/bin/cli.js +5 -6
- package/mapping/admin.json +60 -0
- package/package.json +4 -13
- package/references/adapters/_new-adapter.md +88 -0
- package/references/adapters/vue-antdv.md +70 -0
- package/references/adapters/vue-element-plus.md +90 -0
- package/references/design-apply.md +238 -122
- package/scripts/modules.json +2 -2
- package/dist/mapping-type.d.ts +0 -33
- package/dist/theme-vars.js +0 -62
- package/dist/theme-vars.ts +0 -113
- package/dist/theme.css +0 -73
- package/mapping/basic/color.json +0 -35
- package/mapping/basic/radius.json +0 -17
- package/mapping/basic/semantic-values.json +0 -72
- package/mapping/basic/spacing.json +0 -21
- package/mapping/basic/typography.json +0 -21
- package/mapping/component/button.json +0 -90
- package/mapping/component/card.json +0 -31
- package/mapping/component/input.json +0 -42
- package/mapping/component/overlay.json +0 -79
- package/mapping/component/pagination.json +0 -34
- package/mapping/component/table.json +0 -42
- package/mapping/component/tag.json +0 -48
- package/mapping/layout/breakpoint.json +0 -20
- package/mapping/layout/shell-geometry.json +0 -26
- package/mapping/scenes/admin/content.json +0 -497
- package/mapping/scenes/admin/layout.json +0 -577
- package/parser/fixtures/changeset-fullpage-restore.json +0 -259
- package/parser/fixtures/changeset-gap-block.json +0 -24
- package/parser/fixtures/changeset-legacy.json +0 -11
- package/parser/fixtures/changeset-neg1.json +0 -8
- package/parser/fixtures/changeset-neg2.json +0 -10
- package/parser/fixtures/changeset-neg3.json +0 -22
- package/parser/fixtures/changeset-neg4-g8.json +0 -15
- package/parser/fixtures/changeset-neg5-g8-stub.json +0 -26
- package/parser/fixtures/changeset-neg6-g9-identity.json +0 -39
- package/parser/fixtures/changeset-neg7-g10-dims.json +0 -57
- package/parser/fixtures/changeset-neg8-g11-oracle.json +0 -57
- package/parser/fixtures/changeset-neg9-g6-token-chain.json +0 -34
- package/parser/fixtures/changeset-pos-g6-token-chain.json +0 -35
- package/parser/fixtures/changeset-pos-theme-neutral.json +0 -264
- package/parser/fixtures/changeset-pos-theme-nometa.json +0 -260
- package/parser/fixtures/changeset-pos.json +0 -50
- package/parser/fixtures/changeset-registry-gap.json +0 -29
- package/parser/fixtures/changeset-v32-fields.json +0 -71
- package/parser/fixtures/fake-project/src/styles/app.scss +0 -5
- package/parser/fixtures/fake-project/src/views/list.vue +0 -13
- package/parser/fixtures/registry-bad.json +0 -11
- package/parser/fixtures/registry-g6-token-chain.json +0 -10
- package/parser/fixtures/registry-sample.json +0 -15
- package/parser/fixtures/verify/actual-clean.json +0 -35
- package/parser/fixtures/verify/actual.json +0 -33
- package/parser/fixtures/verify/mockup-baseline-admin-list.html +0 -27
- package/parser/fixtures/verify/mockup-g6-content.html +0 -12
- package/parser/fixtures/verify/mockup-neutral.html +0 -26
- package/parser/fixtures/verify/mockup-nometa.html +0 -26
- package/parser/fixtures/verify/oracle.json +0 -37
- package/parser/fixtures/verify/snapshot-latest.json +0 -103
- package/parser/generator.js +0 -178
- package/parser/index.js +0 -2706
- package/parser/loader.js +0 -66
- package/parser/override.js +0 -119
- package/parser/regression.js +0 -301
- package/parser/validator.js +0 -206
- package/parser/watch.js +0 -103
- package/references/steps/maintenance.md +0 -31
- package/references/steps/regression.md +0 -49
- package/references/steps/step0-preflight.md +0 -58
- package/references/steps/step1-match.md +0 -67
- package/references/steps/step1b-audit.md +0 -23
- package/references/steps/step1c-registry.md +0 -29
- package/references/steps/step2-structure.md +0 -73
- package/references/steps/step3-style.md +0 -38
- package/references/steps/step3b-shell.md +0 -63
- package/references/steps/step3c-priority.md +0 -26
- package/references/steps/step4-l3.md +0 -14
- package/references/steps/step5-gates.md +0 -65
- package/references/steps/step6-verify.md +0 -77
- package/scripts/apply-final-gate.mjs +0 -170
- package/scripts/check.mjs +0 -207
- package/scripts/design-audit.mjs +0 -1707
- package/scripts/validate.mjs +0 -106
package/parser/validator.js
DELETED
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* validator.js — 映射规则校验器
|
|
3
|
-
*
|
|
4
|
-
* 对 mapping/ 目录合并后的映射数据集做全量校验:
|
|
5
|
-
* 1. 字段完整性(必须字段存在且类型正确)
|
|
6
|
-
* 2. 枚举合法性(type/forms 值域)
|
|
7
|
-
* 3. 层级一致性(children 引用的 ID 必须存在于同级或同场景映射集)
|
|
8
|
-
* 4. 三字段结构:anchors(kind/layer 枚举 + target 必填)、
|
|
9
|
-
* preconditions(非空字符串数组)、priority(strategy 枚举)
|
|
10
|
-
*
|
|
11
|
-
* 说明:selector / anchors.target 的「挂载点存在性」需要在**目标项目源码**里查证,
|
|
12
|
-
* 本文件只做映射数据的自洽校验;存在性检查由 index.js 的 audit 子命令完成。
|
|
13
|
-
*
|
|
14
|
-
* 校验不通过:抛出带文件定位的错误并 exit 1(阻断构建)。
|
|
15
|
-
*
|
|
16
|
-
* 用法(由 index.js 调用,也可独立执行):
|
|
17
|
-
* node parser/validator.js # 校验 mapping/ 全目录
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import { buildMappingDataset } from "./loader.js";
|
|
21
|
-
|
|
22
|
-
/** 映射条目允许的 type 枚举 */
|
|
23
|
-
const TYPE_ENUM = ["module", "component", "element", "global_component", "global_token"];
|
|
24
|
-
|
|
25
|
-
/** 必须字段及其类型 */
|
|
26
|
-
const REQUIRED_FIELDS = {
|
|
27
|
-
type: "string",
|
|
28
|
-
style_scope: "string",
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/** 语义 ID 格式:小写字母数字 + 下划线 + 点分层级,最多 4 段 */
|
|
32
|
-
const ID_PATTERN = /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*){1,3}$/;
|
|
33
|
-
|
|
34
|
-
/** anchors 承载通道类型枚举(class = 选择器锚点 / css_var = CSS 变量锚点 / attr = 属性锚点) */
|
|
35
|
-
const ANCHOR_KINDS = ["class", "css_var", "attr"];
|
|
36
|
-
|
|
37
|
-
/** 落点层级枚举:host = 宿主盒;inner = 内层文本盒(专治「值对了、位置不对」) */
|
|
38
|
-
const LAYER_ENUM = ["host", "inner"];
|
|
39
|
-
|
|
40
|
-
/** 覆写优先级策略枚举(design-apply 提权依据) */
|
|
41
|
-
const PRIORITY_ENUM = ["scope_qualified", "self_plus_important", "deep_qualified"];
|
|
42
|
-
|
|
43
|
-
export function validateMappingDataset(dataset) {
|
|
44
|
-
const errors = [];
|
|
45
|
-
const warnings = [];
|
|
46
|
-
|
|
47
|
-
for (const [file, data] of Object.entries(dataset.files)) {
|
|
48
|
-
// meta 校验
|
|
49
|
-
if (!data.meta) {
|
|
50
|
-
errors.push(`[${file}] 缺少 meta 节点`);
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
for (const key of ["layer", "version", "tech_stack"]) {
|
|
54
|
-
if (!data.meta[key])
|
|
55
|
-
errors.push(`[${file}] meta 缺少 ${key}`);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// tokens 型文件(basic/layout 域):token 值必须是非空对象
|
|
59
|
-
if (data.tokens) {
|
|
60
|
-
for (const [field, def] of Object.entries(data.tokens)) {
|
|
61
|
-
if (field.startsWith("$"))
|
|
62
|
-
continue;
|
|
63
|
-
if (typeof def !== "object" || def === null)
|
|
64
|
-
errors.push(`[${file}] tokens.${field} 必须为对象`);
|
|
65
|
-
else if (!def.token && !def.value && !def.hook)
|
|
66
|
-
errors.push(`[${file}] tokens.${field} 缺少 token/value 定义`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// mappings 型文件(component/scenes 域):条目字段校验
|
|
71
|
-
if (data.mappings) {
|
|
72
|
-
for (const [id, entry] of Object.entries(data.mappings)) {
|
|
73
|
-
if (id.startsWith("$"))
|
|
74
|
-
continue;
|
|
75
|
-
|
|
76
|
-
// ID 命名规范
|
|
77
|
-
if (!ID_PATTERN.test(id))
|
|
78
|
-
errors.push(`[${file}] 语义 ID「${id}」不符合命名规范(小写下划线、2~4 段点分层级)`);
|
|
79
|
-
|
|
80
|
-
// 必须字段
|
|
81
|
-
for (const [field, kind] of Object.entries(REQUIRED_FIELDS)) {
|
|
82
|
-
if (typeof entry[field] !== kind)
|
|
83
|
-
errors.push(`[${file}] ${id} 缺少 ${field} 或类型非 ${kind}`);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// type 枚举
|
|
87
|
-
if (entry.type && !TYPE_ENUM.includes(entry.type))
|
|
88
|
-
errors.push(`[${file}] ${id}.type「${entry.type}」不在枚举 ${TYPE_ENUM.join("/")} 内`);
|
|
89
|
-
|
|
90
|
-
// css_vars / custom_style_map 必须为对象(可空对象)
|
|
91
|
-
for (const field of ["css_vars", "custom_style_map"]) {
|
|
92
|
-
if (entry[field] !== undefined && typeof entry[field] !== "object")
|
|
93
|
-
errors.push(`[${file}] ${id}.${field} 必须为对象`);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// css_vars 值必须以 -- 开头(EP/项目 CSS 变量约定)
|
|
97
|
-
if (entry.css_vars) {
|
|
98
|
-
for (const [k, v] of Object.entries(entry.css_vars)) {
|
|
99
|
-
if (typeof v === "string" && !v.trim().startsWith("--"))
|
|
100
|
-
errors.push(`[${file}] ${id}.css_vars.${k} 值「${v}」应为 CSS 变量名(-- 开头)`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// anchors( §3.2):条目可承载的全部通道,含落点层级 layer
|
|
105
|
-
if (entry.anchors !== undefined) {
|
|
106
|
-
if (!Array.isArray(entry.anchors)) {
|
|
107
|
-
errors.push(`[${file}] ${id}.anchors 必须为数组`);
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
let hasClassAnchor = false;
|
|
111
|
-
for (const [i, a] of entry.anchors.entries()) {
|
|
112
|
-
const at = `${id}.anchors[${i}]`;
|
|
113
|
-
if (!a || typeof a !== "object") {
|
|
114
|
-
errors.push(`[${file}] ${at} 必须为对象`);
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
if (!ANCHOR_KINDS.includes(a.kind))
|
|
118
|
-
errors.push(`[${file}] ${at}.kind「${a.kind}」不在枚举 ${ANCHOR_KINDS.join("/")} 内`);
|
|
119
|
-
if (a.kind === "class")
|
|
120
|
-
hasClassAnchor = true;
|
|
121
|
-
if (a.layer !== undefined && !LAYER_ENUM.includes(a.layer))
|
|
122
|
-
errors.push(`[${file}] ${at}.layer「${a.layer}」不在枚举 ${LAYER_ENUM.join("/")} 内`);
|
|
123
|
-
if (typeof a.target !== "string" || a.target.trim() === "")
|
|
124
|
-
errors.push(`[${file}] ${at}.target 必填且为非空字符串`);
|
|
125
|
-
else if (a.kind === "css_var" && !a.target.trim().startsWith("--"))
|
|
126
|
-
errors.push(`[${file}] ${at}.target「${a.target}」为 css_var 锚点时应为 CSS 变量名(-- 开头)`);
|
|
127
|
-
}
|
|
128
|
-
if (entry.anchors.length > 0 && !hasClassAnchor)
|
|
129
|
-
warnings.push(`[${file}] ${id}.anchors 无 class 锚点,样式类字段可能找不到落点选择器`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// preconditions( §3.2):几何 / 取值成立的宿主前提,非空字符串数组
|
|
134
|
-
if (entry.preconditions !== undefined) {
|
|
135
|
-
if (!Array.isArray(entry.preconditions) || entry.preconditions.length === 0) {
|
|
136
|
-
errors.push(`[${file}] ${id}.preconditions 必须为非空字符串数组`);
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
for (const [i, p] of entry.preconditions.entries()) {
|
|
140
|
-
if (typeof p !== "string" || p.trim() === "")
|
|
141
|
-
errors.push(`[${file}] ${id}.preconditions[${i}] 必须为非空字符串`);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// priority( §4.6.4):覆写优先级策略
|
|
147
|
-
if (entry.priority !== undefined) {
|
|
148
|
-
if (typeof entry.priority !== "object" || entry.priority === null) {
|
|
149
|
-
errors.push(`[${file}] ${id}.priority 必须为对象`);
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
if (!PRIORITY_ENUM.includes(entry.priority.strategy))
|
|
153
|
-
errors.push(`[${file}] ${id}.priority.strategy「${entry.priority.strategy}」不在枚举 ${PRIORITY_ENUM.join("/")} 内`);
|
|
154
|
-
if (entry.priority.reason !== undefined && typeof entry.priority.reason !== "string")
|
|
155
|
-
errors.push(`[${file}] ${id}.priority.reason 必须为字符串`);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// 跨文件一致性:children 引用必须可解析(同场景合并字典内查找)
|
|
163
|
-
const mergedIndex = buildMergedIndex(dataset);
|
|
164
|
-
for (const [file, data] of Object.entries(dataset.files)) {
|
|
165
|
-
if (!data.mappings)
|
|
166
|
-
continue;
|
|
167
|
-
for (const [id, entry] of Object.entries(data.mappings)) {
|
|
168
|
-
if (id.startsWith("$") || !Array.isArray(entry.children))
|
|
169
|
-
continue;
|
|
170
|
-
for (const childId of entry.children) {
|
|
171
|
-
if (!mergedIndex[childId])
|
|
172
|
-
warnings.push(`[${file}] ${id}.children 引用的「${childId}」未在当前映射集中定义(可能是待补点位)`);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return { errors, warnings };
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/** 合并全部 mappings 形成扁平索引(跨文件) */
|
|
181
|
-
export function buildMergedIndex(dataset) {
|
|
182
|
-
const index = {};
|
|
183
|
-
for (const data of Object.values(dataset.files)) {
|
|
184
|
-
if (!data.mappings)
|
|
185
|
-
continue;
|
|
186
|
-
// 同 ID 后加载覆盖先加载(scenes 覆盖 component 全局定义,属预期扩展机制)
|
|
187
|
-
Object.assign(index, data.mappings);
|
|
188
|
-
}
|
|
189
|
-
return index;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// ---- CLI 独立执行 ----
|
|
193
|
-
if (process.argv[1] && process.argv[1].endsWith("validator.js")) {
|
|
194
|
-
const dataset = buildMappingDataset();
|
|
195
|
-
const { errors, warnings } = validateMappingDataset(dataset);
|
|
196
|
-
for (const w of warnings)
|
|
197
|
-
console.warn(` ⚠ ${w}`);
|
|
198
|
-
if (errors.length > 0) {
|
|
199
|
-
console.error(`\n✖ 映射表校验失败(${errors.length} 项):`);
|
|
200
|
-
for (const e of errors)
|
|
201
|
-
console.error(` ✘ ${e}`);
|
|
202
|
-
process.exit(1);
|
|
203
|
-
}
|
|
204
|
-
const count = Object.keys(buildMergedIndex(dataset)).length;
|
|
205
|
-
console.log(`✔ 映射表校验通过:${dataset.fileCount} 个文件,${count} 条语义映射,${warnings.length} 条警告`);
|
|
206
|
-
}
|
package/parser/watch.js
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* watch.js — mapping/ 目录监听模式(开发调试)
|
|
5
|
-
*
|
|
6
|
-
* 监听 mapping/ 下所有 *.json 变更,自动执行「校验 + 编译」刷新 dist/。
|
|
7
|
-
* 实现方式:fs.watch 递归监听(Windows/macOS 原生支持 recursive;Linux 上
|
|
8
|
-
* Node ≥ 20 已支持 recursive watch,若不可用则退化为按目录轮询注册)。
|
|
9
|
-
*
|
|
10
|
-
* 用法:
|
|
11
|
-
* node parser/watch.js # 前台监听(Ctrl+C 退出)
|
|
12
|
-
* node parser/watch.js --once # 首次启动即编译一次(默认行为:是)
|
|
13
|
-
*
|
|
14
|
-
* 设计要点:
|
|
15
|
-
* 1. 校验失败不退出进程——打印错误并等待下一次修正(watch 是开发态工具,
|
|
16
|
-
* 方案 §3.4.2「校验不通过时阻断构建」指阻断产物生成,而非杀掉 watcher)。
|
|
17
|
-
* 2. 300ms 防抖:编辑器保存常触发多次事件,合并为一次编译。
|
|
18
|
-
* 3. 仅监听 mapping/ 目录,产物目录 dist/ 不在监听范围,无自触发循环。
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
import { watch, readdirSync, statSync } from "node:fs";
|
|
22
|
-
import path from "node:path";
|
|
23
|
-
import { fileURLToPath } from "node:url";
|
|
24
|
-
import { buildMappingDataset } from "./loader.js";
|
|
25
|
-
import { validateMappingDataset } from "./validator.js";
|
|
26
|
-
import { generateAll } from "./generator.js";
|
|
27
|
-
|
|
28
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
29
|
-
const ROOT = path.resolve(__dirname, "..");
|
|
30
|
-
const MAPPING_DIR = path.join(ROOT, "mapping");
|
|
31
|
-
const DIST_DIR = path.join(ROOT, "dist");
|
|
32
|
-
|
|
33
|
-
let timer = null;
|
|
34
|
-
const DEBOUNCE_MS = 300;
|
|
35
|
-
|
|
36
|
-
function compile(reason) {
|
|
37
|
-
const stamp = new Date().toLocaleTimeString();
|
|
38
|
-
console.log(`\n[${stamp}] 检测到变更(${reason}),重新校验 + 编译 ...`);
|
|
39
|
-
try {
|
|
40
|
-
const dataset = buildMappingDataset();
|
|
41
|
-
const { errors, warnings } = validateMappingDataset(dataset);
|
|
42
|
-
for (const w of warnings)
|
|
43
|
-
console.warn(` ⚠ ${w}`);
|
|
44
|
-
if (errors.length > 0) {
|
|
45
|
-
console.error(` ✖ 校验失败(${errors.length} 项),本次不刷新 dist/:`);
|
|
46
|
-
for (const e of errors)
|
|
47
|
-
console.error(` ✘ ${e}`);
|
|
48
|
-
console.error(` 修正 mapping/ 后将自动重试;Ctrl+C 退出。`);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
const { written, tokenCount } = generateAll(DIST_DIR, false);
|
|
52
|
-
console.log(` ✔ 校验通过(token ${tokenCount} 项)→ 已刷新 dist/:${written.join("、")}`);
|
|
53
|
-
}
|
|
54
|
-
catch (e) {
|
|
55
|
-
console.error(` ✖ 编译异常:${e.message}`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function onEvent(reason) {
|
|
60
|
-
if (timer)
|
|
61
|
-
clearTimeout(timer);
|
|
62
|
-
timer = setTimeout(() => compile(reason), DEBOUNCE_MS);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// 首次启动编译一次
|
|
66
|
-
compile("启动");
|
|
67
|
-
|
|
68
|
-
let watcher;
|
|
69
|
-
try {
|
|
70
|
-
watcher = watch(MAPPING_DIR, { recursive: true }, (event, filename) => {
|
|
71
|
-
const f = String(filename ?? "");
|
|
72
|
-
if (f && !f.endsWith(".json"))
|
|
73
|
-
return; // 只关心 JSON 源文件
|
|
74
|
-
onEvent(f || "mapping/ 目录");
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
// recursive watch 不可用(老版本 Linux Node)→ 降级:非递归监听各子目录
|
|
79
|
-
console.warn("⚠ recursive watch 不可用,降级为逐目录监听");
|
|
80
|
-
const dirs = [MAPPING_DIR];
|
|
81
|
-
for (const name of readdirSync(MAPPING_DIR)) {
|
|
82
|
-
const full = path.join(MAPPING_DIR, name);
|
|
83
|
-
if (statSync(full).isDirectory())
|
|
84
|
-
dirs.push(full);
|
|
85
|
-
}
|
|
86
|
-
for (const d of dirs) {
|
|
87
|
-
watch(d, (event, filename) => {
|
|
88
|
-
const f = String(filename ?? "");
|
|
89
|
-
if (f && !f.endsWith(".json"))
|
|
90
|
-
return;
|
|
91
|
-
onEvent(`${path.relative(MAPPING_DIR, d)}/${f}`);
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
console.log(`\n👁 监听中:${MAPPING_DIR}(Ctrl+C 退出)`);
|
|
97
|
-
|
|
98
|
-
// Ctrl-C / 终止时清理
|
|
99
|
-
process.on("SIGINT", () => {
|
|
100
|
-
console.log("\n👋 退出 watch");
|
|
101
|
-
watcher?.close();
|
|
102
|
-
process.exit(0);
|
|
103
|
-
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# design-apply · 词典维护纪律与出厂状态漂移
|
|
2
|
-
|
|
3
|
-
> **主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:改 mapping / 出厂状态存疑 / 排查词典假前提时。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 词典维护纪律
|
|
8
|
-
|
|
9
|
-
### 出厂状态漂移(词典假前提 = 风险源,落地前必查)
|
|
10
|
-
|
|
11
|
-
**项目可能随时被还原到出厂**(design-shell 回空壳、`.changeset/*` 消失、本体系此前补的通道全部消失)。因此词典里凡「出厂已具备 X」类表述必须满足:① X 是**真出厂能力**(对照出厂源码可验证);② 由本体系补建的通道一律写成**条件式**——「若缺失,按 structure_ops / 补通道流程补建并申报」,不写「已存在」。**落地前必须跑 `node parser/index.js audit --project <dir>`**:锚点/选择器/变量消费者存在性静态校验,会当场暴露词典假前提(例:词典写「出厂已渲染分割线 / 工具栏行已挂语义类」,项目还原后全部失真 → 规则落空)。
|
|
12
|
-
|
|
13
|
-
- mapping/ 是唯一事实源:施工前 `parser query <id>` 精读条目,**不凭记忆施工**。
|
|
14
|
-
- **禁止编造的是「既有条目的映射」**(改既有 selector / css_vars / 变量指向 = 静默篡改,绝对禁止)。**词典缺 ID / 缺字段枚举不属编造**——那是新点位,按 L3 当场落地并写**新增的**临时映射条目,交付说明申报,等人工评审转正。
|
|
15
|
-
- 「宁可不做,不做错」只适用于**设计侧未给值 / 值非法**的意图缺口;用它搁置能力缺口 = 交付失败。
|
|
16
|
-
- 临时映射转正须人工评审;禁止静默修改既有映射条目的 selector/css_vars。
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 布局类问题的「实测复现」手段(无 dev server 时)
|
|
21
|
-
|
|
22
|
-
布局畸形(文字被压成两行 / 字符重叠 / 元素被裁)**不能只靠读 CSS 推理**——同一条规则在不同宽高链里结果完全不同,复现一次比推演十次可靠。当环境里起不了 dev server(如沙箱拦下构建期依赖清理、端口不可用)时,用**编译产物 + headless 浏览器**做等价复现:
|
|
23
|
-
|
|
24
|
-
1. **取编译后的 CSS**:`dist/static/css/` 下的主样式包(含 Element Plus 覆盖、设计层规则、组件 scoped)。确认目标规则真在里面(grep 选择器片段),scoped 规则的 `[data-v-xxxx]` 后缀也在这里读到,复现时必须原样带上该属性。
|
|
25
|
-
2. **写最小 DOM**:只保留目标元素的**祖先盒链**(列宽由 `<colgroup><col width>` 决定就写 col;`.cell` 是内层文本盒就写 `.cell`),其余删掉。
|
|
26
|
-
3. **跑 headless 取数**:`msedge --headless=new --disable-gpu --user-data-dir=<临时目录> --virtual-time-budget=5000 --dump-dom file:///<复现.html>`。
|
|
27
|
-
- **`--user-data-dir` 必给**,否则报 `Missing headless user data directory` 直接不输出。
|
|
28
|
-
- 页面内用 script 把 `getBoundingClientRect()` / `getComputedStyle()` 结果写进 `<title>`,再从 dump 里 grep 取回,比截图量像素精确。
|
|
29
|
-
4. **读什么**:沿祖先链逐层打印 `box 宽高 / width / min-width / flex / display / white-space`,找出**哪一层先装不下**。典型结论:「外盒 144 − 左右内边距 32 = 112 < 内容需求 120」这类确定性差额,比「看起来有点挤」可行动得多。
|
|
30
|
-
|
|
31
|
-
**判据来源优先级**:实测(headless 取数)> 静态审计闸断言 > 源码推理 > 肉眼看截图。截图放大时**先把标注线(红框等)像素抹掉再测量**——标注线会被误读成渲染元素,典型失效模式:横排文字被误判成竖排。
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# design-apply · 端到端回归与配套工具(作者/维护侧)
|
|
2
|
-
|
|
3
|
-
> **主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:改 parser/mapping 后必跑;日常落地不需要加载。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 端到端回归(改 parser/mapping 后必跑)
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
node parser/regression.js # 一键跑完 A-X 二十四步(自动断言退出码与关键输出,任一失败 exit 1 并回显详情)
|
|
11
|
-
npm run regression # 等价写法
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
分步展开(等价于 regression.js 内部步骤,排障时可单跑某一步):
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
node parser/validator.js # A. 映射词典全量校验(含 semantic-values.json)
|
|
18
|
-
node parser/index.js list --scene admin --verbose # B. 头部应输出映射集版本;ID/字段/形态清单
|
|
19
|
-
node parser/index.js match parser/fixtures/changeset-pos.json # C. 正例:exit 0;钴蓝-5→#245BFF 译表解析;pending 功能描述输出
|
|
20
|
-
node parser/index.js match parser/fixtures/changeset-neg1.json # D. 负例1:exit 1(缺 schema)
|
|
21
|
-
node parser/index.js match parser/fixtures/changeset-neg2.json # E. 负例2:exit 1(mapping_version 不匹配)
|
|
22
|
-
node parser/index.js match parser/fixtures/changeset-neg3.json # F. 负例3:exit 1(禁词/非法 ID/位置违规,逐条列出)
|
|
23
|
-
node parser/index.js match parser/fixtures/changeset-legacy.json # G. 旧协议:exit 0 + layout 键/schema 历史值两条告警
|
|
24
|
-
node parser/index.js match parser/fixtures/changeset-fullpage-restore.json # H. 整页场景还原样例:exit 0;壳层+内容区全模块 L1 命中;数值字面量(40px 等)透传无 ⚠
|
|
25
|
-
node parser/index.js build --dry # I. 产物链自检
|
|
26
|
-
node parser/index.js match parser/fixtures/changeset-v32-fields.json # J. 声明字段:exit 0;输出「结构施工 structure_ops」与 layer / apply_via
|
|
27
|
-
node parser/index.js audit --project parser/fixtures/fake-project parser/fixtures/changeset-v32-fields.json # K. 静态审计:夹具项目存在挂载点缺失/死通道 → exit 1
|
|
28
|
-
node parser/index.js verify --oracle parser/fixtures/verify/oracle.json --actual parser/fixtures/verify/actual.json # L. 渲染态验收:夹具含三类故意缺口 → exit 1;归因计数 选择器落空1/权重被压1/语境错位2
|
|
29
|
-
node parser/index.js match --registry parser/fixtures/registry-sample.json parser/fixtures/changeset-registry-gap.json # M. 登记表覆盖率细闸:夹具欠声明 2 条恒存在子项 → exit 1
|
|
30
|
-
node parser/index.js registry parser/fixtures/registry-sample.json # N. 登记表通道核验:点位全部命中 → exit 0;输出含「登记表通道核验」
|
|
31
|
-
node parser/index.js registry parser/fixtures/registry-bad.json # O. 登记表硬缺口:引用不存在且未标 pending 的点位 → exit 1
|
|
32
|
-
node parser/index.js match parser/fixtures/changeset-neg4-g8.json # P. G8 模式闸负例:mode=restore 缺 oracle/coverage(伪还原变更集)→ exit 1
|
|
33
|
-
node parser/index.js match parser/fixtures/changeset-neg5-g8-stub.json # Q. G8 强化负例:mode=restore 但 mockup/registry 空壳(有壳无芯伪基线)→ exit 1
|
|
34
|
-
node parser/index.js match parser/fixtures/changeset-neg6-g9-identity.json # R. G9 身份闸负例:scheme=tangerine 却引 default 方案登记表(分母偷换)→ exit 1
|
|
35
|
-
node parser/index.js match parser/fixtures/changeset-neg7-g10-dims.json # S. G10 dims 闸负例:header_cell 缺 text_align/nowrap(点位在细节丢)→ exit 1
|
|
36
|
-
node parser/index.js match parser/fixtures/changeset-neg8-g11-oracle.json # T. G11 oracle 闸负例:橘橙主色配钴蓝效果图且无 theme_mapping(主题错配)→ exit 1
|
|
37
|
-
node parser/index.js verify --oracle parser/fixtures/verify/oracle.json --actual parser/fixtures/verify/actual-clean.json # U. 残差豁免 + G12 收口正例:申报点位不计缺口、absent 已收口 → exit 0
|
|
38
|
-
# V. 快照回归(两段式,regression.js 内部自动展开):clean 夹具导快照 → 缺口夹具比对 → 基线漂移 → exit 1
|
|
39
|
-
node parser/index.js match parser/fixtures/changeset-pos-theme-neutral.json # W. 主题↔基线图解耦正例:中性文件名 + 图内 data-mockup-theme=钴蓝,本次主题=橘橙 + theme_mapping → 色值归一、exit 0
|
|
40
|
-
node parser/index.js match parser/fixtures/changeset-pos-theme-nometa.json # X. 基线图缺身份元数据不阻断:中性名 + 无 data-mockup-theme,已声明 changeset.theme → 仅提示、exit 0
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
通过标准:regression.js 输出 `A✔ B✔ … X✔` 且 exit 0;分步跑时各步符合注释预期。夹具含义见各文件 `$comment`。
|
|
44
|
-
|
|
45
|
-
## 配套工具(作者/维护侧)
|
|
46
|
-
|
|
47
|
-
- **watch 模式**:`node parser/watch.js` 或 `npm run mapping:watch`——监听 mapping/ 下 JSON 变更,自动「校验 + 重编 dist/」;校验失败不杀进程,修正后自动重试。
|
|
48
|
-
- **业务级覆写 API**:`import { themeVars, overrideMapping } from '<skill>/dist/theme-vars.js'`——仅覆写指定字段,不改动基础映射;strict 模式下覆写词典外字段直接报错(防拼错静默失效)。当前 vue3-web-temp 不引入,服务于未来空白项目。
|
|
49
|
-
- **mapping 版本流程**:所有 mapping/*.json 的 `meta.version` 恒为 `1.0.0`(由 SKILL.md 体系版本统一管理);`release.js` 发版前自动执行 `parser build` 刷新 dist/,产物随 NPM 包发布。
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# design-apply · 第 0 步 · 版本与场景检查 · 对接匹配(适配前置)· 运行时清场
|
|
2
|
-
|
|
3
|
-
> **主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:每次落地开工前(版本/场景/对接匹配/运行时清场三件套)。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
### 第 0 步 · 版本与场景检查 · 对接匹配(适配前置)· 运行时清场
|
|
8
|
-
|
|
9
|
-
**0.1 版本与场景检查**
|
|
10
|
-
|
|
11
|
-
- 变更集 `schema` 版本不在支持范围 → 停止,向上游(用户/设计侧)报告版本不匹配,不降级猜测。
|
|
12
|
-
- `scene` 在 `parser list` 场景清单中无对应域 → 报告并列出支持的场景,等待确认。
|
|
13
|
-
|
|
14
|
-
**0.0 页面绑定检查(G13 页面绑定闸 · 先于一切施工)**
|
|
15
|
-
|
|
16
|
-
- **默认口径(红线)**:效果图页面**默认映射到项目已有页面**——效果图页面(如「运单管理」)是设计侧为承载设计语言虚构的演示标题与角色坐标系(sid 标的是角色不是业务),**不是页面增量**。落地动作恒为「在已有页面上同步结构与样式」;**禁止因效果图新增页面 / 路由 / 菜单项**。
|
|
17
|
-
- 变更集 `page_bindings` 显式声明 `target:"new"` 且 `notes` 申报的条目,才可在申报范围内走新增页面路径(L3 生成页面 + 路由 + 菜单);未声明或申报与动作不符 → 阻断并报告(不猜测、不默认放行)。
|
|
18
|
-
- 对接动作:把效果图页面与项目已有页面的映射关系(mockup → target)写入交付说明;目标页面对不上、找不到合理已有页面承载时,先向用户确认映射,**不得以「图上有这个页面」为由新建**。
|
|
19
|
-
- 判据一句话:换一张效果图不需要改项目的页面/路由/菜单清单 ⇒ 正确;效果图标题 ≠ 项目业务名,验收只比「结构与样式」不比「页面标题文字」。
|
|
20
|
-
|
|
21
|
-
**0.2 对接匹配(适配前置)——把散落的匹配收拢为一个前置阶段**
|
|
22
|
-
|
|
23
|
-
在施工前,把「设计意图 ⇄ 模板能力」整体对一遍,输出匹配结论,供**生成前**决策(而不是落地时才发现对不上)。三步判定:
|
|
24
|
-
|
|
25
|
-
| 级 | 判定 | 依据 |
|
|
26
|
-
|---|---|---|
|
|
27
|
-
| **布局级** | `layout_type` 命中标准枚举? | 命中 → 切布局模板池(§5.2);未命中 → 变体派生 / 定制生成骨架(§5.3 / §5.4) |
|
|
28
|
-
| **点位级** | 逐 id 三级匹配 | 一级完整命中 / 二级父级命中 / 三级未命中(§4.1) |
|
|
29
|
-
| **形态级** | `form` 在条目 `forms` 枚举内?`structure_ops` 所需 DOM 钩子是否存在? | 词典 `forms` / 模板源码 / `audit` |
|
|
30
|
-
|
|
31
|
-
**输出三类结论,处置全在项目侧**:
|
|
32
|
-
|
|
33
|
-
| 结论 | 判据 | 处置 |
|
|
34
|
-
|---|---|---|
|
|
35
|
-
| 完全匹配 | L1 ∧ form 在枚举 ∧ 无需结构 | 直接施工 |
|
|
36
|
-
| 可派生 | L2 / 变体布局 / form 可映射 | 派生骨架或继承父级后施工 |
|
|
37
|
-
| 需适配 | L3 / 定制布局 / 缺通道 / 需新 DOM | **先补通道 / 结构增量 / 生成骨架,再生成**;交付说明单列申报 |
|
|
38
|
-
|
|
39
|
-
> **总原则(红线):设计为主,项目侧适配。** 设计效果是目标态,模板是待适配的一方。"设计 ↔ 模板对不上"的出口**永远在项目侧**——**不回流设计侧改设计**。只有「设计侧未给值 / 值非法」(**意图缺口**)才回流设计侧。严禁以「模板不支持」为由要求设计改图。
|
|
40
|
-
|
|
41
|
-
**0.3 运行时主题清场(T 通道先于 D/S/C)**
|
|
42
|
-
|
|
43
|
-
主色 / 主题走的是**运行时通道**:`setEpThemeColor()` 把 `--el-color-primary` 写成 `documentElement` 的**内联样式**并持久化到 localStorage(读取优先级 = 浏览器持久化 ?? `platform-config.json`)。**内联样式 + 运行时持久化 ⇒ 设计层 CSS 与词典 selector 都赢不了。**
|
|
44
|
-
|
|
45
|
-
- 落地前先读 localStorage(键 `responsive-layout`)的 `theme` / `epThemeColor`,与本变更集主题**不一致时清 key 或显式重设**;
|
|
46
|
-
- 清场动作与结果写入交付说明(可回溯);
|
|
47
|
-
- **不清场则颜色类差异全部失真**——归因前必须先确认起点已对齐,否则会把「环境残留」误判成「落地失败」。
|
|
48
|
-
- **机检对账(G4)**:`parser audit` 会自动比对 `global.brand_primary` ↔ `platform-config.EpThemeColor`、页签 form ↔ `ShowModel`、`visible:false` ↔ 显隐开关,不一致即 `exit 1`——人工清场 + 机检对账双保险。
|
|
49
|
-
|
|
50
|
-
**0.3b T 通道持久化三件套(页签形态 / 主题类字段施工必做)**
|
|
51
|
-
|
|
52
|
-
运行时配置读 localStorage,而 localStorage 只在 `platform-config.Version` 变化时经 `responsive.ts invalidateStorageIfConfigVersionChanged` 重灌。凡施工涉及 `ShowModel` / `Theme` / `EpThemeColor` 等 T 通道字段,**三件套缺一不可**:
|
|
53
|
-
|
|
54
|
-
1. 改 `platform-config.json` 实值(如 `ShowModel: "card"`);
|
|
55
|
-
2. **`Version` 自增一位**(如 0.0.6 → 0.0.7)——漏此步 = 代码对但运行时仍旧形态;
|
|
56
|
-
3. **渲染取证**:断言新形态类实际挂载(如 `.scroll-item.card-item` 出现在 DOM)——不许只看代码改没改。
|
|
57
|
-
|
|
58
|
-
词典 `admin.layout.tabs.preconditions` 有同款硬闸描述;本三件套对任意 T 通道字段通用。
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
# design-apply · 第 1 步 · parser 确定性匹配(含词典硬闸 G8-G11/G1/G5/G6)
|
|
2
|
-
|
|
3
|
-
> **主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:match 执行与闸门判读。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
### 第 1 步 · parser 确定性匹配
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
# 单份变更集
|
|
11
|
-
node parser/index.js match <changeset.json>
|
|
12
|
-
# 项目级批量(设计侧项目级模式产出:全局变更集 + 各页面变更集目录)
|
|
13
|
-
node parser/index.js match --batch <changesets-dir>
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
读取输出的**转换计划**,它包含:
|
|
17
|
-
|
|
18
|
-
| 分级 | 含义 | 处理 |
|
|
19
|
-
|------|------|------|
|
|
20
|
-
| **L1 完整命中** | ID 在词典中直接命中 | 按条目施工坐标直接落地(预期 100% 还原) |
|
|
21
|
-
| **L2 父级命中** | ID 的父模块命中 | 继承父模块样式约定,按子级定位施工(85-90% 还原) |
|
|
22
|
-
| **L3 未命中** | 词典无此 ID(新增点位) | **当场按第 4 步定制布局落地**并写入 mapping 临时映射;只有设计侧未给完整意图(无值 / 值非法)才进缺口清单。**例外**:`global` 为设计侧伪点位(对应变更集顶层 global 节点的基座令牌,不入词典),按 T 通道对账,不按 L3 处理 |
|
|
23
|
-
| **字段级未命中** | ID 命中但 `style` 某字段两层映射都查不到 | 值合法且选择器可定位 → **当场生成作用域内自定义规则落设计层文件并申报**;只有「值非法 / 无法定位」才进缺口清单 |
|
|
24
|
-
|
|
25
|
-
**零缺口交付(禁止中途停顿)**:落地一次跑完,**不得因「词典没建这个 ID / 这个字段没枚举 / 这个值要不要确认」而停下来问用户**。缺口只有两类,去向各不相同:
|
|
26
|
-
|
|
27
|
-
| 缺口类型 | 判据 | 处理 |
|
|
28
|
-
|---|---|---|
|
|
29
|
-
| **能力缺口**(词典缺 ID / 缺字段枚举 / 缺 form) | 设计侧意图完整、值合法 | **项目侧当场落地**:按 L3 定制布局施工并写 mapping 临时映射;出厂文件仅在「补通道」时可动,交付说明单列申报。**进清单 = 把可落地项搁置 = 交付失败** |
|
|
30
|
-
| **意图缺口**(设计侧没给值 / 值非法) | 变更集里本就没有这个值 | 才可进「缺口清单」,交付说明写明「回流设计侧补齐」——**不是问用户要不要做** |
|
|
31
|
-
|
|
32
|
-
> **闸门红 = 硬停(交付缺陷,性质与上表相反)**:`parser match` **退出码非 0**(G8 模式闸 / G9 登记表身份闸 / G10 dims 闸 / G11 oracle 基线闸 / 覆盖率细闸,任一不通过)时 **禁止开工落地**。合法出路只有一条:回设计侧补齐(基线 / 登记项 / 点位)后重跑——**`mode` 唯一合法值是 `restore`**,不存在「经用户同意降级」的出口;范围确需缩小时,停下向用户多轮询问确认真实意图,按确认结论调整变更集范围后重算。
|
|
33
|
-
>
|
|
34
|
-
> **禁止「挑拣完整的那部分先落地」**:最典型的错误是闸门报错后只落全局主题令牌(改 `platform-config.json` 的 `EpThemeColor` + 设计层覆盖 `--brand-primary`)再宣称完成——用户看到的是「只换了主题色,布局样式全不对」,且重建设计层时会把上一轮成果一并覆盖。上表「禁止中途停顿」**只适用于能力缺口**(词典没建 ID / 字段没枚举),**不适用于闸门红**。
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
`缺口清单` 只承载第二类,且必须给出点位 ID + 缺失字段名。
|
|
38
|
-
|
|
39
|
-
**转换计划四类输出**:每条 L1/L2 点位除样式指令外,还会输出——
|
|
40
|
-
|
|
41
|
-
| 输出 | 含义 | 施工含义 |
|
|
42
|
-
|---|---|---|
|
|
43
|
-
| `▸ 承载通道 anchors` | 该点位可落地的宿主盒 / 内层文本盒 / CSS 变量锚点 | 落点以这里为准,不要自己猜选择器 |
|
|
44
|
-
| `▸ 承载通道来源 apply_via` | 本声明引用的锚点来源条目 | 落到该条目的锚点上(而非 change.id 自身的) |
|
|
45
|
-
| `▸ 结构施工 structure_ops` | 需要改数据 / 模板结构的事项 | **必须改动数据或模板分支**,禁止只写 CSS |
|
|
46
|
-
| `▸ 前置条件 preconditions` | 值成立依赖的宿主前提 | 施工前必须满足,否则「值对了也不生效」 |
|
|
47
|
-
| `▸ 覆写优先级 priority` | 该点位的提权策略 | 按策略取胜,禁止逐点硬堆 `!important` |
|
|
48
|
-
|
|
49
|
-
**词典硬闸(match 期机检,违规 = 拒绝执行)**:
|
|
50
|
-
|
|
51
|
-
| 闸 | 触发条件 | 判据来源 | 违规输出 |
|
|
52
|
-
|---|---|---|---|
|
|
53
|
-
| **G8 模式闸** | 变更集顶层 `mode: "restore"`(场景还原)但基线不全:缺 `scheme` / `oracle` / `coverage`,**或 `oracle.mockup` / `coverage.registry` 为空**(有壳无芯的伪基线)——伪还原变更集(只换主题色却以还原之名交付)拒绝执行;`mode` 非法值同样阻断 | 变更集顶层 `scheme` / `mode` / `oracle.mockup` / `coverage.registry` | `G8 模式闸:mode=restore 但缺少 … → 拒绝执行` |
|
|
54
|
-
| **G9 登记表身份闸** | `mode=restore` 但登记表**身份对不上**:`coverage.registry` 实物解析失败,或登记表 `design_scheme`/`scene` 与变更集 `scheme`/`scene` 不一致(或缺身份字段)——凡身份对不上的表视同没有表,防止覆盖率分母被偷换(面包屑/顶栏图标/表头 nowrap 等点位从分母消失,欠声明不可数) | 登记表顶层 `design_scheme` / `scene` ↔ 变更集顶层 `scheme` / `scene` | `G9 登记表身份闸:登记表 … 属于 scheme="…"/scene="…",与变更集 … 不一致 → 拒绝执行` |
|
|
55
|
-
| **G10 dims 兑现闸** | `mode=restore` 下登记项的 ID 已在 `changes[]` 声明,但登记 `dims` 维度未全部给全(`form` 看 `change.form`,其余看 `style ∪ layer` 的键;`source:none`、global 伪点位、`visible:false` 豁免)——「点位在、细节丢」(表头竖排 = nowrap 丢失)正是样式细节不还原的机制成因,dims 缺口与欠声明同级阻断 | 登记表条目 `dims` ↔ 变更集条目 `form` / `style` / `layer` | `dims 兑现缺口(G10 · … 条 → exit 1):… 缺 dims=[…]` |
|
|
56
|
-
| **G11 oracle 基线闸** | `mode=restore` 下 oracle 校验发现问题(主题与基线图色板不一致且未声明归一 / `oracle.sids` 欠声明或无基线 / 实物缺口):restore 下从「⚠ 软提示继续」升格为「拒绝执行」——基线断了仍绿灯交付,verify 无从做 1:1 证明。**基线图是「场景基线」、与主题无关**:换主题的正确动作是**继续读同一张基线图**并声明 `theme_mapping: { from: <基线图色板>, to: <本次主题> }`(只做色值归一,不减读取与声明);**不是「该主题没有效果图」**——把它读成后者就会跳过读图、只改主题色 | 本次主题(`changeset.theme` → 回退 `global.brand_primary`)↔ 基线图色板(图内 `data-mockup-theme` → 回退文件名主题词);`oracle.sids` ↔ `changes[].id` 双向 | `oracle 基线问题(G11 · … 类 → 拒绝执行):主题与基线图色板不一致 …` |
|
|
57
|
-
| **G13 页面绑定闸** | 落地动作涉及**新增页面 / 路由 / 菜单项**,但变更集 `page_bindings` 未把该效果图页面对应声明为 `target:"new"`(或整字段缺省)——效果图页面默认是设计角色坐标系(演示标题),不是项目页面增量;「图上有这个页面」不构成新增依据 | 变更集顶层 `page_bindings[].target` ↔ 本次 diff 是否出现新路由/菜单/页面文件 | `G13 页面绑定闸:效果图页面 … 未声明 target:"new",禁止新增页面/路由/菜单 → 映射已有页面落地` |
|
|
58
|
-
| **G1 suppress 收口** | 条目声明某 `form`,词典 `suppress_rules[form]`(或 forms 描述「suppress 必含 x」内联标记)要求收口的出厂互斥通道未全部出现在该条目 `suppress[]` | 词典条目 `suppress_rules` | `suppress 缺口:…必须收口出厂互斥通道 [x],缺 [x]` |
|
|
59
|
-
| **G5 几何语境** | 词典 preconditions 含「几何语境随值迁移」标记 ∧ `style` 含 padding/margin 族几何字段落宿主 ∧ 未声明 `suppress_inner` | 词典条目 preconditions 标记句 | `suppress_inner 缺口:…两层之和 ≠ 设计值` |
|
|
60
|
-
| **G6 层间令牌链对账** | 词典 preconditions 含「层间令牌链对账」标记 ∧ `style` 含 padding/margin 族几何字段 ∧ 未声明 `suppress_inner`——父子两层盒共享同一条间距令牌链(如 `.app-main` 与 `.main-content` 同链 `--layout-content-padding → --vts-margin`),同一间距只允许一个权威来源 | 词典条目 preconditions 标记句 | `suppress_inner 缺口:…父层设计值 + 子层同链令牌值物理叠加(24px + 8px = 32px/侧)` |
|
|
61
|
-
|
|
62
|
-
> 施工侧配套:设计审计(design-audit)另有 **E18 激活态消费者成对落地** 断言——声明 `indicator_*` 形态时,「竖条消费者存在 + `--vts-theme-menu-active-before` 非透明 + 与出厂胶囊伪元素对决权重足够」三者缺一即报(详见 step5-gates.md 审计清单)。声明指示条形态时,交付说明须同时写明这两项施工约定。
|
|
63
|
-
|
|
64
|
-
三闸与禁词校验同级阻断(`exit 1`)——「新旧形态叠加」「两层 padding 相加」「同链令牌双层叠加」「伪还原只换主题」都会导致实质错误(双竖条、28px 列挤压、内容区边距 32px/侧、「还原后布局细节零变化」),不允许靠观感兜底。G8 判据一句话:**「把系统 / 页面改成 X」默认是还原(restore),必须带齐 `scheme` + `oracle.mockup` + `coverage.registry`;只有「显式声明只改主题色、其它不动」才用 `design`**(还原项目若用无登记表、无基线的轻量变更集,会一路绿灯、落地后「只变了主题、布局细节零变化」;故须堵住 `oracle`/`coverage` 只给空壳、无 `mockup`/`registry` 芯的写法)。**降级不许静默发生**:变更集 `notes` 与交付说明都须显式写出本次 `mode` 与范围。restore 模式下 G9/G10/G11 同时生效(登记表身份、dims 维度兑现、oracle 基线三道复闸),三者判据细节见上表与「登记表覆盖率」小节。
|
|
65
|
-
|
|
66
|
-
**验收基线输出**:转换计划末尾另打印 `=== 验收基线 oracle ===`(效果图路径 + 待比对点位)与 `=== 覆盖率 coverage ===`(登记项 R / 适用 A / 已兑现 C)。有 `oracle` → 落地后必须跑第 6 步 `verify`;缺 `oracle` / `coverage` → 输出提示,把「补基线 / 补登记覆盖率」回流设计侧(场景还原应给)。
|
|
67
|
-
**覆盖率校验**:`coverage.covered` 必须等于 `coverage.applicable`、`gaps` 为空,否则打印缺口清单——`C < A` 即**欠声明**(有规范子项未落进 `changes[]`/`visible`/`pending`),属设计侧交付不完整,必须回流,不得在项目侧"猜着补"。
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# design-apply · 第 1 步附加 · 挂载点审计(audit · 静态查三类隐性缺口)
|
|
2
|
-
|
|
3
|
-
> **主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:match 通过后、施工前。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
### 第 1 步附加 · 挂载点审计(静态查三类隐性缺口)
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
node parser/index.js audit --project <目标项目根目录> [<changeset.json…>]
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
不开浏览器即可查出的三类高发缺口:
|
|
14
|
-
|
|
15
|
-
| 检查 | 抓什么 | 对应风险 |
|
|
16
|
-
|---|---|---|
|
|
17
|
-
| **挂载点缺失 / 可疑** | `selector` / `anchors.target` 里的类名在项目里**只在样式文件出现、模板没挂**,或**完全找不到** | 列未绑 `class-name` → 金额列右对齐 / 缩略图尺寸永不生效;操作栏规则有定义无引用 |
|
|
18
|
-
| **死通道** | `anchors` 里的 CSS 变量在项目中**无 `var()` 消费者**(两类豁免:`--el-*` 组件库变量由 EP 运行时消费;设计层已显式接管定义的变量属故意 suppress) | 变量有定义无引用,翻译再准也不生效 |
|
|
19
|
-
| **词典无此条目** | 变更集引用了词典未建的 ID | L3 新增点位须当场落地并回写临时映射。**例外**:`global` 为设计侧伪点位(对应变更集顶层 global 节点的基座令牌),与 match 路径同口径不入词典、不做词典点检 |
|
|
20
|
-
| **G2 structure_ops 施工证据** | 变更集声明 `structure_ops` 的点位,按词典 anchors/selector 语义类名 + `op.node` 提取探针,在**非设计层结构源码**中查证施工痕迹;零命中 = 纯 CSS 冒充结构施工 | 操作列分割线 `add_node` 声明了却从未施工 |
|
|
21
|
-
| **G4 T 通道对账** | `global.brand_primary`(语义值解析 hex)↔ `platform-config.EpThemeColor`;页签 `form` ↔ `ShowModel`;`visible:false` 点位的 `visible_prop` 开关 ↔ platform-config 实值 | 变更集主题与 platform-config 残留旧主题不一致;flat 页签叠加 chrome 结构 |
|
|
22
|
-
|
|
23
|
-
挂载点疑似但**设计层文件已承载该类名** → 降级不阻断(C 通道由 design-shell 兜底是合法落点)。G2 / G4 违规与挂载点问题同置 `exitCode 1`。审计报错 = **能力缺口**:当场按 `structure_ops` 补挂载 / 补消费者,交付说明单列申报;不得以「词典没建」为由跳过。审计通过 ≠ 还原达标——**静态审计查不出「值对了、位置不对」**,那要靠第 6 步渲染态验收。
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# design-apply · 第 1 步附加(之二)· 登记表覆盖率(子项级细闸)
|
|
2
|
-
|
|
3
|
-
> **主入口与执行顺序见 [../design-apply.md](../design-apply.md)**;加载时机:变更集带 coverage.registry / --registry 时。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
### 第 1 步附加(之二)· 登记表覆盖率(子项级细闸)
|
|
8
|
-
|
|
9
|
-
组级台账(`restore-checklist`)只能防「整组忘光」;**组内子项**是否被静默丢失,用登记表计数。
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
node parser/index.js match <cs.json> --registry <restore-registry.json> # 匹配 + 覆盖率当场重算
|
|
13
|
-
node parser/index.js registry <restore-registry.json> [--verbose] # 只核验登记表对词典的通道就绪度
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
| 量 | 定义 | 谁重算 |
|
|
17
|
-
|---|---|---|
|
|
18
|
-
| **R 登记项** | 登记表条数(= 规范里带样式结论的子项数) | 读表 |
|
|
19
|
-
| **A 适用** | `always:true` 的子项 ∪ 效果图已标注同名 `data-sid` 的子项 | parser 当场算 |
|
|
20
|
-
| **C 兑现** | A 中在 `changes[]` / `visible:false` / `pending[].proposed_id` 出现者 | parser 当场算 |
|
|
21
|
-
| **缺口** | `A − C`,逐条列出 `rule + sid + dims`(同组超过 6 条需加 `--verbose` 展开) | parser 当场算 |
|
|
22
|
-
|
|
23
|
-
**关键口径**:A/C **由 parser 以登记表为权威当场重算,设计侧自报的 `coverage` 数字不参与**——所以「把 applicable 写小」蒙混不过去。有缺口 → `exit 1`,属**交付不完整**,回流设计侧补齐后重跑。
|
|
24
|
-
|
|
25
|
-
另有一项**效果图标注缺口**告警:`always:true` 的子项若在效果图里找不到同名 `data-sid`,基线根本抽不出来(效果图标注粒度必须与登记表同分辨率,否则第 6 步的 oracle 必然残缺)。
|
|
26
|
-
|
|
27
|
-
`registry` 子命令单独回答「这张登记表里有多少必登项在项目侧真有承载字段」:
|
|
28
|
-
- **硬缺口**(引用了词典不存在的点位且未标 `pending`)→ `exit 1`;
|
|
29
|
-
- **通道缺口**(设计侧维度在词典无对应字段)→ 列出,属**项目侧补词典**事项,补齐后还原度才可达 100%。
|