create-yss-spec 3.4.10 → 3.5.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.
- package/README.md +2 -2
- package/package.json +1 -1
- package/src/api/_sync-service.js +111 -18
- package/src/cli/args.js +1 -0
- package/src/cli/help.js +10 -1
- package/src/cli/index.js +3 -0
- package/src/cli/prompts.js +5 -1
- package/src/cli/router.js +2 -0
- package/src/commands/attach.js +12 -2
- package/src/commands/init.js +2 -0
- package/src/commands/skills.js +253 -0
- package/src/commands/sync.js +3 -0
- package/src/family-identity.js +1 -1
- package/src/template/asset-runtime.js +220 -0
- package/src/template/distribution-runtime.js +165 -0
- package/src/template/instance-runtime.js +76 -29
- package/src/template/ownership-policy.js +17 -1
- package/src/template/prune-planner.js +6 -1
- package/src/template/sync-planner.js +3 -0
- package/src/template/verification-runtime.js +56 -1
- package/src/validation/metadata.js +24 -1
- package/template/.agents/skills/.strategic-design-skills-manifest.json +1 -1
- package/template/.agents/skills/yss-cache/SKILL.md +6 -5
- package/template/.agents/skills/yss-cache/references/annotations.md +3 -1
- package/template/.agents/skills/yss-cache/references/architecture.md +4 -2
- package/template/.agents/skills/yss-cache/references/configuration.md +6 -3
- package/template/.agents/skills/yss-cache/references/jetcache.md +21 -0
- package/template/.agents/skills/yss-cache/references/redis-fallback.md +5 -3
- package/template/.agents/skills/yss-cache/references/verification.md +10 -4
- package/template/.agents/skills/yss-cache/scripts/verify-cache-component.sh +26 -20
- package/template/.agents/skills/yss-distributed-id/SKILL.md +14 -58
- package/template/.agents/skills/yss-distributed-id/agents/openai.yaml +2 -2
- package/template/.agents/skills/yss-distributed-id/references/README.md +11 -47
- package/template/.agents/skills/yss-mybatis/SKILL.md +14 -2
- package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +5 -4
- package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +8 -8
- package/template/.agents/skills/yss-prototype-stage/SKILL.md +2 -2
- package/template/.agents/skills/yss-repository/SKILL.md +1 -0
- package/template/.codex/skills/yss-cache/SKILL.md +6 -5
- package/template/.codex/skills/yss-cache/references/annotations.md +3 -1
- package/template/.codex/skills/yss-cache/references/architecture.md +4 -2
- package/template/.codex/skills/yss-cache/references/configuration.md +6 -3
- package/template/.codex/skills/yss-cache/references/jetcache.md +21 -0
- package/template/.codex/skills/yss-cache/references/redis-fallback.md +5 -3
- package/template/.codex/skills/yss-cache/references/verification.md +10 -4
- package/template/.codex/skills/yss-cache/scripts/verify-cache-component.sh +26 -20
- package/template/.codex/skills/yss-distributed-id/SKILL.md +14 -58
- package/template/.codex/skills/yss-distributed-id/agents/openai.yaml +2 -2
- package/template/.codex/skills/yss-distributed-id/references/README.md +11 -47
- package/template/.codex/skills/yss-mybatis/SKILL.md +14 -2
- package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +5 -4
- package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +8 -8
- package/template/.codex/skills/yss-prototype-stage/SKILL.md +2 -2
- package/template/.codex/skills/yss-repository/SKILL.md +1 -0
- package/template/.cursor/skills/yss-cache/SKILL.md +6 -5
- package/template/.cursor/skills/yss-cache/references/annotations.md +3 -1
- package/template/.cursor/skills/yss-cache/references/architecture.md +4 -2
- package/template/.cursor/skills/yss-cache/references/configuration.md +6 -3
- package/template/.cursor/skills/yss-cache/references/jetcache.md +21 -0
- package/template/.cursor/skills/yss-cache/references/redis-fallback.md +5 -3
- package/template/.cursor/skills/yss-cache/references/verification.md +10 -4
- package/template/.cursor/skills/yss-cache/scripts/verify-cache-component.sh +26 -20
- package/template/.cursor/skills/yss-distributed-id/SKILL.md +14 -58
- package/template/.cursor/skills/yss-distributed-id/agents/openai.yaml +2 -2
- package/template/.cursor/skills/yss-distributed-id/references/README.md +11 -47
- package/template/.cursor/skills/yss-mybatis/SKILL.md +14 -2
- package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +5 -4
- package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +8 -8
- package/template/.cursor/skills/yss-prototype-stage/SKILL.md +2 -2
- package/template/.cursor/skills/yss-repository/SKILL.md +1 -0
- package/template/.pi/skills/yss-cache/SKILL.md +6 -5
- package/template/.pi/skills/yss-cache/references/annotations.md +3 -1
- package/template/.pi/skills/yss-cache/references/architecture.md +4 -2
- package/template/.pi/skills/yss-cache/references/configuration.md +6 -3
- package/template/.pi/skills/yss-cache/references/jetcache.md +21 -0
- package/template/.pi/skills/yss-cache/references/redis-fallback.md +5 -3
- package/template/.pi/skills/yss-cache/references/verification.md +10 -4
- package/template/.pi/skills/yss-cache/scripts/verify-cache-component.sh +26 -20
- package/template/.pi/skills/yss-distributed-id/SKILL.md +14 -58
- package/template/.pi/skills/yss-distributed-id/agents/openai.yaml +2 -2
- package/template/.pi/skills/yss-distributed-id/references/README.md +11 -47
- package/template/.pi/skills/yss-mybatis/SKILL.md +14 -2
- package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +5 -4
- package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +8 -8
- package/template/.pi/skills/yss-prototype-stage/SKILL.md +2 -2
- package/template/.pi/skills/yss-repository/SKILL.md +1 -0
- package/template/README.md +2 -5
- package/template/docs/agents/skill-migrations.md +4 -0
- package/template/docs/agents/yss-skill-registry.yaml +7 -6
- package/template/docs/design/README.md +0 -1
- package/template/docs/design/design.md +2 -2
- package/template/docs/design/templates/interaction-spec-template.md +1 -1
- package/template/docs/engineering/evidence/aliyun-artifact-resolution.json +446 -0
- package/template/scripts/design-md +2 -0
- package/template/scripts/lib/design-md.mjs +230 -0
- package/template/scripts/lib/skill-registry.mjs +9 -2
- package/template/scripts/lib/skill-supply-chain.mjs +33 -14
- package/template/scripts/verify-project-instance +11 -10
- package/template/skills-lock.json +11 -26
- package/template.manifest.json +18 -3
- package/template.snapshot.json +5 -5
- package/template/.agents/skills/grill-me/SKILL.md +0 -7
- package/template/.agents/skills/grill-me/agents/openai.yaml +0 -5
- package/template/.agents/skills/yss-distributed-id/assets/AutoIdInterceptor.java +0 -246
- package/template/.agents/skills/yss-distributed-id/assets/EnableDistributedId.java +0 -25
- package/template/.agents/skills/yss-distributed-id/assets/LeafConf.java +0 -36
- package/template/.codex/skills/grill-me/SKILL.md +0 -7
- package/template/.codex/skills/grill-me/agents/openai.yaml +0 -5
- package/template/.codex/skills/yss-distributed-id/assets/AutoIdInterceptor.java +0 -246
- package/template/.codex/skills/yss-distributed-id/assets/EnableDistributedId.java +0 -25
- package/template/.codex/skills/yss-distributed-id/assets/LeafConf.java +0 -36
- package/template/.cursor/skills/grill-me/SKILL.md +0 -7
- package/template/.cursor/skills/grill-me/agents/openai.yaml +0 -5
- package/template/.cursor/skills/yss-distributed-id/assets/AutoIdInterceptor.java +0 -246
- package/template/.cursor/skills/yss-distributed-id/assets/EnableDistributedId.java +0 -25
- package/template/.cursor/skills/yss-distributed-id/assets/LeafConf.java +0 -36
- package/template/.pi/skills/grill-me/SKILL.md +0 -7
- package/template/.pi/skills/grill-me/agents/openai.yaml +0 -5
- package/template/.pi/skills/yss-distributed-id/assets/AutoIdInterceptor.java +0 -246
- package/template/.pi/skills/yss-distributed-id/assets/EnableDistributedId.java +0 -25
- package/template/.pi/skills/yss-distributed-id/assets/LeafConf.java +0 -36
- package/template/docs/agents/yss-plugin-dependency-contract.md +0 -45
- package/template/docs/api/.gitkeep +0 -0
- package/template/docs/api/specs/.gitkeep +0 -0
- package/template/docs/architecture/.gitkeep +0 -0
- package/template/docs/design/facts/antdv-next/1.5.2/cli-help.txt +0 -38
- package/template/docs/design/facts/antdv-next/1.5.2/component-list.json +0 -434
- package/template/docs/design/facts/antdv-next/1.5.2/components/Alert/demo-basic.json +0 -7
- package/template/docs/design/facts/antdv-next/1.5.2/components/Alert/info.json +0 -246
- package/template/docs/design/facts/antdv-next/1.5.2/components/Alert/semantic.json +0 -40
- package/template/docs/design/facts/antdv-next/1.5.2/components/Alert/token.json +0 -32
- package/template/docs/design/facts/antdv-next/1.5.2/components/Button/demo-basic.json +0 -7
- package/template/docs/design/facts/antdv-next/1.5.2/components/Button/info.json +0 -190
- package/template/docs/design/facts/antdv-next/1.5.2/components/Button/semantic.json +0 -20
- package/template/docs/design/facts/antdv-next/1.5.2/components/Button/token.json +0 -256
- package/template/docs/design/facts/antdv-next/1.5.2/components/Input/demo-basic.json +0 -7
- package/template/docs/design/facts/antdv-next/1.5.2/components/Input/info.json +0 -460
- package/template/docs/design/facts/antdv-next/1.5.2/components/Input/semantic.json +0 -70
- package/template/docs/design/facts/antdv-next/1.5.2/components/Input/token.json +0 -123
- package/template/docs/design/facts/antdv-next/1.5.2/components/Modal/demo-basic.json +0 -7
- package/template/docs/design/facts/antdv-next/1.5.2/components/Modal/info.json +0 -646
- package/template/docs/design/facts/antdv-next/1.5.2/components/Modal/semantic.json +0 -50
- package/template/docs/design/facts/antdv-next/1.5.2/components/Modal/token.json +0 -130
- package/template/docs/design/facts/antdv-next/1.5.2/components/Select/demo-basic.json +0 -7
- package/template/docs/design/facts/antdv-next/1.5.2/components/Select/info.json +0 -640
- package/template/docs/design/facts/antdv-next/1.5.2/components/Select/semantic.json +0 -70
- package/template/docs/design/facts/antdv-next/1.5.2/components/Select/token.json +0 -172
- package/template/docs/design/facts/antdv-next/1.5.2/components/Table/demo-basic.json +0 -7
- package/template/docs/design/facts/antdv-next/1.5.2/components/Table/info.json +0 -1010
- package/template/docs/design/facts/antdv-next/1.5.2/components/Table/semantic.json +0 -70
- package/template/docs/design/facts/antdv-next/1.5.2/components/Table/token.json +0 -263
- package/template/docs/design/facts/antdv-next/1.5.2/components/Tag/demo-basic.json +0 -7
- package/template/docs/design/facts/antdv-next/1.5.2/components/Tag/info.json +0 -321
- package/template/docs/design/facts/antdv-next/1.5.2/components/Tag/semantic.json +0 -25
- package/template/docs/design/facts/antdv-next/1.5.2/components/Tag/token.json +0 -25
- package/template/docs/design/facts/antdv-next/1.5.2/design-md.json +0 -3
- package/template/docs/design/facts/antdv-next/1.5.2/manifest.json +0 -215
- package/template/docs/design/facts/antdv-next/1.5.2/resolution-probe.json +0 -5
- package/template/docs/design/prototypes/.gitkeep +0 -1
- package/template/docs/implementation/.gitkeep +0 -1
- package/template/docs/plan/IDEATION.md +0 -96
- package/template/docs/process/PDCA-SCRUM.md +0 -10
- package/template/docs/process/harness-executive-blueprint.md +0 -10
- package/template/docs/releases/.gitkeep +0 -1
- package/template/docs/requirements/README.md +0 -85
- package/template/docs/requirements/tickets/.gitkeep +0 -1
- package/template/docs/templates/agent-brief-template.md +0 -46
- package/template/docs/templates/architecture-proposal-template.md +0 -18
- package/template/docs/templates/implementation-plan-template.md +0 -16
- package/template/docs/templates/implementation-routing-template.md +0 -350
- package/template/docs/templates/requirement-freeze-template.md +0 -63
- package/template/docs/templates/risk-register-template.md +0 -11
- package/template/docs/templates/user-story-template.md +0 -20
- package/template/docs/testing/README.md +0 -110
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { createRequire } from "node:module";
|
|
7
|
+
import { parseDocument } from "../vendor/yaml.mjs";
|
|
8
|
+
|
|
9
|
+
const repositoryRoot = path.resolve(new URL("../..", import.meta.url).pathname);
|
|
10
|
+
const designPath = path.join(repositoryRoot, "DESIGN.md");
|
|
11
|
+
const projectionDir = path.join(repositoryRoot, "docs/design/tokens");
|
|
12
|
+
const manifestPath = path.join(projectionDir, ".design-md-projection.json");
|
|
13
|
+
const syncMetadataPath = path.join(repositoryRoot, "docs/design/design-system-sync.yaml");
|
|
14
|
+
const expectedSections = ["Overview", "Colors", "Typography", "Layout", "Elevation & Depth", "Shapes", "Components", "Do's and Don'ts"];
|
|
15
|
+
const requiredFrontmatter = ["version", "name", "description", "colors", "typography", "rounded", "spacing", "components"];
|
|
16
|
+
const componentProperties = new Set(["backgroundColor", "textColor", "typography", "rounded", "padding", "size", "height", "width"]);
|
|
17
|
+
|
|
18
|
+
function sha256(value) { return createHash("sha256").update(value).digest("hex"); }
|
|
19
|
+
function fail(message) { throw new Error(message); }
|
|
20
|
+
function escapeRegExp(value) { return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }
|
|
21
|
+
|
|
22
|
+
function resolveValue(value, frontmatter) {
|
|
23
|
+
const match = typeof value === "string" ? value.match(/^\{(colors|typography|rounded|spacing)\.([\w-]+)\}$/) : null;
|
|
24
|
+
return match ? frontmatter[match[1]]?.[match[2]] : value;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function projectedCssVariables(frontmatter) {
|
|
28
|
+
const components = frontmatter.components;
|
|
29
|
+
return {
|
|
30
|
+
"yss-color-primary-control": resolveValue(components["button-primary"].backgroundColor, frontmatter),
|
|
31
|
+
"yss-color-primary-control-hover": resolveValue(components["button-primary-hover"].backgroundColor, frontmatter),
|
|
32
|
+
"yss-color-on-primary": resolveValue(components["button-primary"].textColor, frontmatter),
|
|
33
|
+
"yss-control-height": resolveValue(components["button-primary"].height, frontmatter),
|
|
34
|
+
"yss-card-padding": resolveValue(components["card-default"].padding, frontmatter),
|
|
35
|
+
"yss-control-height-compact": resolveValue(components["button-compact"].height, frontmatter),
|
|
36
|
+
"yss-card-compact-padding": resolveValue(components["card-compact"].padding, frontmatter)
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function writeCssProjection(frontmatter) {
|
|
41
|
+
const cssPath = path.join(projectionDir, "variables.css");
|
|
42
|
+
let source = readFileSync(cssPath, "utf8");
|
|
43
|
+
for (const [name, value] of Object.entries(projectedCssVariables(frontmatter))) {
|
|
44
|
+
const declaration = ` --${name}: ${value};`;
|
|
45
|
+
const pattern = new RegExp(`^\\s*--${escapeRegExp(name)}:.*;$`, "m");
|
|
46
|
+
source = pattern.test(source) ? source.replace(pattern, declaration) : source.replace(":root {\n", `:root {\n${declaration}\n`);
|
|
47
|
+
}
|
|
48
|
+
writeFileSync(cssPath, source);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function validateCssProjection(frontmatter) {
|
|
52
|
+
const source = readFileSync(path.join(projectionDir, "variables.css"), "utf8");
|
|
53
|
+
for (const [name, value] of Object.entries(projectedCssVariables(frontmatter))) {
|
|
54
|
+
if (!new RegExp(`^\\s*--${escapeRegExp(name)}: ${escapeRegExp(String(value))};$`, "m").test(source)) fail(`variables.css 的 --${name} 与 DESIGN.md 不一致`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function readDesign(file = designPath) {
|
|
59
|
+
const source = readFileSync(file, "utf8");
|
|
60
|
+
if (!source.startsWith("---\n")) fail(`${path.relative(repositoryRoot, file)} 缺少 YAML frontmatter`);
|
|
61
|
+
const end = source.indexOf("\n---", 4);
|
|
62
|
+
if (end < 0) fail(`${path.relative(repositoryRoot, file)} frontmatter 未闭合`);
|
|
63
|
+
const document = parseDocument(source.slice(4, end), { uniqueKeys: true, maxAliasCount: 0 });
|
|
64
|
+
if (document.errors.length) fail(document.errors[0].message);
|
|
65
|
+
const frontmatter = document.toJS({ maxAliasCount: 0 });
|
|
66
|
+
for (const field of requiredFrontmatter) if (!frontmatter?.[field]) fail(`frontmatter 缺少 ${field}`);
|
|
67
|
+
const body = source.slice(end + 4);
|
|
68
|
+
const headings = [...body.matchAll(/^## ([^\n]+)$/gm)].map((match) => match[1].trim());
|
|
69
|
+
const actual = headings.slice(0, expectedSections.length);
|
|
70
|
+
if (JSON.stringify(actual) !== JSON.stringify(expectedSections)) fail(`canonical H2 章节顺序必须为: ${expectedSections.join(" → ")}`);
|
|
71
|
+
for (const section of expectedSections) {
|
|
72
|
+
if (headings.filter((heading) => heading === section).length !== 1) fail(`canonical H2 章节必须且只能出现一次: ${section}`);
|
|
73
|
+
}
|
|
74
|
+
const canonicalH1 = [...body.matchAll(/^# ([^\n]+)$/gm)].map((match) => match[1].trim()).filter((heading) => expectedSections.includes(heading));
|
|
75
|
+
if (canonicalH1.length > 0) fail(`canonical 正文章节必须使用 H2,不能使用 H1: ${canonicalH1.join(", ")}`);
|
|
76
|
+
for (const [name, component] of Object.entries(frontmatter.components)) {
|
|
77
|
+
if (!/^[a-z][a-z0-9-]*$/.test(name)) fail(`组件变体名称非法: ${name}`);
|
|
78
|
+
for (const key of Object.keys(component)) if (!componentProperties.has(key)) fail(`组件 ${name} 使用不支持的属性: ${key}`);
|
|
79
|
+
}
|
|
80
|
+
const references = [...source.matchAll(/\{(colors|typography|rounded|spacing)\.([\w-]+)\}/g)].map((match) => match[0]);
|
|
81
|
+
for (const reference of references) {
|
|
82
|
+
const [, group, token] = reference.match(/^\{([^}]+)\.([^}]+)\}$/);
|
|
83
|
+
if (frontmatter[group]?.[token] === undefined) fail(`悬空 token 引用: ${reference}`);
|
|
84
|
+
}
|
|
85
|
+
if (file === designPath && existsSync(syncMetadataPath)) {
|
|
86
|
+
const syncDocument = parseDocument(readFileSync(syncMetadataPath, "utf8"), { uniqueKeys: true, maxAliasCount: 0 });
|
|
87
|
+
if (syncDocument.errors.length) fail(syncDocument.errors[0].message);
|
|
88
|
+
const sync = syncDocument.toJS({ maxAliasCount: 0 })?.design_system_sync;
|
|
89
|
+
if (!sync?.baseline_sha256 || sync.baseline_sha256 !== sha256(source)) {
|
|
90
|
+
fail("design-system-sync.yaml 的 baseline_sha256 与 DESIGN.md 不一致,请更新跨仓同步摘要");
|
|
91
|
+
}
|
|
92
|
+
if (!Array.isArray(sync.synchronized_sections) || sync.synchronized_sections.length === 0) {
|
|
93
|
+
fail("design-system-sync.yaml 缺少 synchronized_sections");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { source, frontmatter };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function runUpstream(args) {
|
|
100
|
+
const result = spawnSync("npx", ["--yes", "@google/design.md@0.4.0", ...args], { cwd: repositoryRoot, encoding: "utf8" });
|
|
101
|
+
if (result.error || result.status !== 0) fail(result.stderr?.trim() || result.stdout?.trim() || "design.md CLI 执行失败");
|
|
102
|
+
return result.stdout;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function projectionFiles() {
|
|
106
|
+
return ["theme.json", "tokens.default.json", "tokens.dark.json", "tokens.compact.json", "variables.css", "variables.dark.css"].map((file) => path.join(projectionDir, file));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function writeProjectionManifest() {
|
|
110
|
+
const { source } = readDesign();
|
|
111
|
+
const files = Object.fromEntries(projectionFiles().map((file) => [path.relative(repositoryRoot, file), sha256(readFileSync(file))]));
|
|
112
|
+
writeFileSync(manifestPath, `${JSON.stringify({ schema_version: 1, source: "DESIGN.md", source_sha256: sha256(source), files }, null, 2)}\n`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function writeThemeProjection(frontmatter) {
|
|
116
|
+
const themeFile = path.join(projectionDir, "theme.json");
|
|
117
|
+
const theme = { token: {}, algorithm: "default" };
|
|
118
|
+
const token = theme.token || (theme.token = {});
|
|
119
|
+
const colors = frontmatter.colors;
|
|
120
|
+
const typography = frontmatter.typography;
|
|
121
|
+
const rounded = frontmatter.rounded;
|
|
122
|
+
const spacing = frontmatter.spacing;
|
|
123
|
+
Object.assign(token, {
|
|
124
|
+
colorPrimary: colors.primary,
|
|
125
|
+
colorSuccess: colors.success,
|
|
126
|
+
colorWarning: colors.warning,
|
|
127
|
+
colorError: colors.error,
|
|
128
|
+
colorInfo: colors.info ?? colors.primary,
|
|
129
|
+
colorTextBase: "#000000",
|
|
130
|
+
colorBgBase: colors.surface ?? "#ffffff",
|
|
131
|
+
colorBgLayout: colors["canvas-layout"] ?? "#f0f2f5",
|
|
132
|
+
colorText: colors.text,
|
|
133
|
+
colorTextSecondary: colors["text-secondary"],
|
|
134
|
+
colorBorder: colors.border ?? "#d9d9d9",
|
|
135
|
+
fontFamily: typography.body.fontFamily,
|
|
136
|
+
fontSize: Number.parseInt(typography.body.fontSize, 10),
|
|
137
|
+
borderRadius: Number.parseInt(rounded.md, 10),
|
|
138
|
+
sizeUnit: Number.parseInt(spacing.xxs, 10),
|
|
139
|
+
sizeStep: Number.parseInt(spacing.xxs, 10),
|
|
140
|
+
controlHeight: Number.parseInt(frontmatter.components["button-primary"].height, 10),
|
|
141
|
+
controlHeightSM: Number.parseInt(frontmatter.components["button-small"].height, 10),
|
|
142
|
+
controlHeightLG: Number.parseInt(frontmatter.components["button-large"].height, 10),
|
|
143
|
+
fontSizeSM: Number.parseInt(typography.caption.fontSize, 10),
|
|
144
|
+
borderRadiusSM: Number.parseInt(rounded.sm, 10),
|
|
145
|
+
borderRadiusLG: Number.parseInt(rounded.lg, 10),
|
|
146
|
+
padding: Number.parseInt(spacing.md, 10),
|
|
147
|
+
paddingSM: Number.parseInt(spacing.sm, 10),
|
|
148
|
+
paddingXS: Number.parseInt(spacing.xs, 10),
|
|
149
|
+
paddingLG: Number.parseInt(spacing.card, 10)
|
|
150
|
+
});
|
|
151
|
+
theme.components = { Card: { borderRadiusLG: token.borderRadiusLG, paddingLG: token.paddingLG } };
|
|
152
|
+
writeFileSync(themeFile, `${JSON.stringify(theme, null, 2)}\n`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function writeAlgorithmProjections(toolchain) {
|
|
156
|
+
if (!toolchain) fail("export --write 需要 --antd-toolchain <独立作者工具目录>,固定 antd 6.6.4");
|
|
157
|
+
const require = createRequire(path.join(path.resolve(toolchain), "package.json"));
|
|
158
|
+
if (require("antd/package.json").version !== "6.6.4") fail("主题算法需要 antd 6.6.4");
|
|
159
|
+
const { theme } = require("antd");
|
|
160
|
+
const config = JSON.parse(readFileSync(path.join(projectionDir, "theme.json")));
|
|
161
|
+
const kebab = key => key.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`);
|
|
162
|
+
const snapshots = {};
|
|
163
|
+
for (const [mode, algorithm] of Object.entries({ default: theme.defaultAlgorithm, dark: theme.darkAlgorithm, compact: theme.compactAlgorithm })) {
|
|
164
|
+
const token = { ...config.token };
|
|
165
|
+
// Let the dark algorithm derive neutral colors instead of pinning light aliases.
|
|
166
|
+
if (mode === "dark") for (const key of ["colorBgBase", "colorTextBase", "colorBgLayout", "colorText", "colorTextSecondary", "colorBorder"]) delete token[key];
|
|
167
|
+
snapshots[mode] = theme.getDesignToken({ token, algorithm });
|
|
168
|
+
writeFileSync(path.join(projectionDir, `tokens.${mode}.json`), JSON.stringify(snapshots[mode], null, 2) + "\n");
|
|
169
|
+
}
|
|
170
|
+
const rewrite = (css, token) => {
|
|
171
|
+
const values = Object.fromEntries(Object.entries(token).map(([key,value]) => [kebab(key),value]));
|
|
172
|
+
return css.replace(/(--brand-([\w-]+):\s*)([^;]+);/g, (all, prefix, key, old) => {
|
|
173
|
+
const value = values[key];
|
|
174
|
+
if (value === undefined || typeof value === "object") return all;
|
|
175
|
+
const unit = typeof value === "number" ? old.trim().match(/(?:px|ms|s)$/)?.[0] || "" : "";
|
|
176
|
+
return `${prefix}${value}${unit};`;
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
const cssPath = path.join(projectionDir, "variables.css");
|
|
180
|
+
const css = readFileSync(cssPath, "utf8");
|
|
181
|
+
const darkStart = css.indexOf('[data-theme="dark"]');
|
|
182
|
+
writeFileSync(cssPath, darkStart < 0 ? rewrite(css, snapshots.default) : rewrite(css.slice(0, darkStart), snapshots.default) + rewrite(css.slice(darkStart), snapshots.dark));
|
|
183
|
+
const darkPath = path.join(projectionDir, "variables.dark.css");
|
|
184
|
+
writeFileSync(darkPath, rewrite(readFileSync(darkPath, "utf8"), snapshots.dark));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function driftCheck() {
|
|
188
|
+
const { source, frontmatter } = readDesign();
|
|
189
|
+
validateCssProjection(frontmatter);
|
|
190
|
+
if (!existsSync(manifestPath)) fail(`缺少 ${path.relative(repositoryRoot, manifestPath)},请先执行 export --write-manifest`);
|
|
191
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
192
|
+
if (manifest.source_sha256 !== sha256(source)) fail("DESIGN.md 已变化但投影未重新生成(source_sha256 漂移)");
|
|
193
|
+
for (const [relative, digest] of Object.entries(manifest.files || {})) {
|
|
194
|
+
const file = path.join(repositoryRoot, relative);
|
|
195
|
+
if (!existsSync(file) || sha256(readFileSync(file)) !== digest) fail(`派生文件漂移: ${relative}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function main() {
|
|
200
|
+
const [command, ...args] = process.argv.slice(2);
|
|
201
|
+
if (command === "lint") {
|
|
202
|
+
const file = args.find((arg) => !arg.startsWith("-")) || designPath;
|
|
203
|
+
readDesign(path.resolve(repositoryRoot, file));
|
|
204
|
+
process.stdout.write(`${runUpstream(["lint", file, "--format", "json"])}`);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (command === "diff") {
|
|
208
|
+
if (args.length < 2) fail("用法: design-md diff <before> <after>");
|
|
209
|
+
process.stdout.write(runUpstream(["diff", ...args.slice(0, 2), "--format", "json"]));
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (command === "export") {
|
|
213
|
+
const format = args[0] || "dtcg";
|
|
214
|
+
const { frontmatter } = readDesign();
|
|
215
|
+
process.stdout.write(runUpstream(["export", "DESIGN.md", "--format", format]));
|
|
216
|
+
if (args.includes("--write")) {
|
|
217
|
+
const toolchain = args[args.indexOf("--antd-toolchain") + 1];
|
|
218
|
+
if (!args.includes("--antd-toolchain") || !toolchain) fail("缺少 --antd-toolchain");
|
|
219
|
+
writeThemeProjection(frontmatter);
|
|
220
|
+
writeAlgorithmProjections(toolchain);
|
|
221
|
+
writeCssProjection(frontmatter);
|
|
222
|
+
}
|
|
223
|
+
if (args.includes("--write-manifest")) writeProjectionManifest();
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (command === "drift") { driftCheck(); process.stdout.write("DESIGN.md 投影无漂移\n"); return; }
|
|
227
|
+
fail("用法: design-md lint|diff|export|drift");
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
try { main(); } catch (error) { process.stderr.write(`${error.message}\n`); process.exitCode = 1; }
|
|
@@ -65,10 +65,17 @@ export function loadSkillRegistry(filePath = DEFAULT_REGISTRY) {
|
|
|
65
65
|
export function resolveSkillForNewUse(registry, requestedId) {
|
|
66
66
|
requireString(requestedId, "requested skill id");
|
|
67
67
|
if (OBSOLETE.has(requestedId)) {
|
|
68
|
+
const replacementSkill = requestedId === "grill-me" ? "grilling" : null;
|
|
68
69
|
throw new SkillLifecycleError(
|
|
69
70
|
SKILL_LIFECYCLE_FAILURE_CODES.retired,
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
replacementSkill
|
|
72
|
+
? `${requestedId} 已硬退役;请使用 ${replacementSkill}`
|
|
73
|
+
: `${requestedId} 已硬退役;按迁移 tombstone 重新路由`,
|
|
74
|
+
{
|
|
75
|
+
skill: requestedId,
|
|
76
|
+
migration_ref: "docs/agents/skill-migrations.md",
|
|
77
|
+
...(replacementSkill ? { replacement_skill: replacementSkill } : {})
|
|
78
|
+
}
|
|
72
79
|
);
|
|
73
80
|
}
|
|
74
81
|
const aliases = new Map((registry.skills ?? []).flatMap((skill) => (skill.aliases ?? []).map((alias) => [alias, skill.id])));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, readlinkSync, realpathSync, rmSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
@@ -10,7 +10,7 @@ const LOCK_PATH = path.join(ROOT, "skills-lock.json");
|
|
|
10
10
|
const YSS_UI_MANIFEST_PATH = path.join(SOURCE_ROOT, ".yss-skills-manifest.json");
|
|
11
11
|
const STRATEGIC_DESIGN_MANIFEST_PATH = path.join(SOURCE_ROOT, ".strategic-design-skills-manifest.json");
|
|
12
12
|
export const PROJECTION_ROOTS = [".codex/skills", ".cursor/skills", ".pi/skills"];
|
|
13
|
-
export const OBSOLETE = new Set(["yss-antd-design", "yss-antdv-next-design", "to-" + "prd", "to-" + "issues", "design-an-interface", "qa", "request-refactor-plan", "ubiquitous-language", "edit-article", "obsidian-vault", "writing-great-skills", "code-review-process", "yss-domain-modeling", "yss-dir", "yss-duckdb", "yss-file", "yss-filerunner", "yss-db2mybatis", "yss-mail", "yss-mapper-dynamic", "yss-quality", "yss-sql-condition", "yss-sql-tpl", "yss-valuation", "yss-variable", "yss-openapi", "web-design-engineer", "web-video-presentation", "wireframe-prototype", "wizard", "git-guardrails-claude-code", "claude-handoff", "batch-grill-me", "product-design-prototype", "research", "ask-matt", "dispatching-parallel-agents", "loop-me", "migrate-to-shoehorn", "prototype-page-acceptance", "scaffold-exercises", "setup-pre-commit", "setup-ts-deep-modules", "teach", "writing-beats", "writing-fragments", "writing-shape", "yss-microapp-commit", "yss-page-module-development", "yss-dictionary", "yss-jdbc", "yss-log", "yss-taskflow", "yss-backend-scaffold-application", "yss-backend-scaffold-domain", "yss-backend-scaffold-infrastructure", "yss-backend-scaffold-web", "yss-router", "yss-source-index"]);
|
|
13
|
+
export const OBSOLETE = new Set(["yss-antd-design", "yss-antdv-next-design", "to-" + "prd", "to-" + "issues", "design-an-interface", "qa", "request-refactor-plan", "ubiquitous-language", "edit-article", "obsidian-vault", "writing-great-skills", "code-review-process", "yss-domain-modeling", "yss-dir", "yss-duckdb", "yss-file", "yss-filerunner", "yss-db2mybatis", "yss-mail", "yss-mapper-dynamic", "yss-quality", "yss-sql-condition", "yss-sql-tpl", "yss-valuation", "yss-variable", "yss-openapi", "web-design-engineer", "web-video-presentation", "wireframe-prototype", "wizard", "git-guardrails-claude-code", "claude-handoff", "batch-grill-me", "grill-me", "product-design-prototype", "research", "ask-matt", "dispatching-parallel-agents", "loop-me", "migrate-to-shoehorn", "prototype-page-acceptance", "scaffold-exercises", "setup-pre-commit", "setup-ts-deep-modules", "teach", "writing-beats", "writing-fragments", "writing-shape", "yss-microapp-commit", "yss-page-module-development", "yss-dictionary", "yss-jdbc", "yss-log", "yss-taskflow", "yss-backend-scaffold-application", "yss-backend-scaffold-domain", "yss-backend-scaffold-infrastructure", "yss-backend-scaffold-web", "yss-router", "yss-source-index"]);
|
|
14
14
|
for (const id of ["component-selection-imports", "page-form-module", "page-list-module", "page-skeleton", "vue3-best-practices", "yss-use-table-height", "yss-use-tree-height", "yss-components", "yss-mvc-scaffold-generator", "yss-mvc-design", "yss-mvc-data-analysis-project-initializer", "yss-backend-scaffold-parent", "yss-backend-scaffold-adapter", "yss-application-layer-reference", "yss-domain-layer-reference", "yss-infrastructure-layer-reference", "yss-web-layer-reference"]) OBSOLETE.add(id);
|
|
15
15
|
export function obsoleteCanonicalResidues(names, obsolete = OBSOLETE) {
|
|
16
16
|
return names.filter((name) => obsolete.has(name)).sort();
|
|
@@ -49,6 +49,21 @@ export function treeHash(directory) {
|
|
|
49
49
|
return digest.digest("hex");
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
// treeHash is the published, normalized Skill digest. A no-op copy needs the
|
|
53
|
+
// stricter filesystem comparison so modes, links and raw line endings survive.
|
|
54
|
+
function projectionMatchesSource(source, target) {
|
|
55
|
+
const sourceInfo = lstatSafe(source);
|
|
56
|
+
const targetInfo = lstatSafe(target);
|
|
57
|
+
if (!sourceInfo || !targetInfo || (sourceInfo.mode & 0o7777) !== (targetInfo.mode & 0o7777)) return false;
|
|
58
|
+
if (sourceInfo.isSymbolicLink()) return targetInfo.isSymbolicLink() && readlinkSync(source) === readlinkSync(target);
|
|
59
|
+
if (sourceInfo.isFile()) return targetInfo.isFile() && readFileSync(source).equals(readFileSync(target));
|
|
60
|
+
if (!sourceInfo.isDirectory() || !targetInfo.isDirectory()) return false;
|
|
61
|
+
const sourceNames = readdirSync(source).sort();
|
|
62
|
+
const targetNames = readdirSync(target).sort();
|
|
63
|
+
return sourceNames.length === targetNames.length && sourceNames.every((name, index) =>
|
|
64
|
+
name === targetNames[index] && projectionMatchesSource(path.join(source, name), path.join(target, name)));
|
|
65
|
+
}
|
|
66
|
+
|
|
52
67
|
/**
|
|
53
68
|
* 校验并返回 YSS UI 前端 skills 与 MCP 的上游集成合同。
|
|
54
69
|
*
|
|
@@ -156,13 +171,12 @@ export function unlockedCanonicalEntries(names, allowedNames, hasSkillMd = () =>
|
|
|
156
171
|
const allowed = new Set(allowedNames);
|
|
157
172
|
return names.filter((name) => !allowed.has(name) && !OBSOLETE.has(name) && hasSkillMd(name)).sort();
|
|
158
173
|
}
|
|
159
|
-
export function syncSkills({ check = false } = {}) {
|
|
174
|
+
export function syncSkills({ check = false, hashCache = new Map() } = {}) {
|
|
160
175
|
let trackedSet;
|
|
161
176
|
const tracked = ref => (trackedSet ??= trackedPaths()).has(ref);
|
|
162
|
-
const sourceHashes = new Map();
|
|
163
177
|
const sourceHash = source => {
|
|
164
|
-
if (!
|
|
165
|
-
return
|
|
178
|
+
if (!hashCache.has(source)) hashCache.set(source, treeHash(source));
|
|
179
|
+
return hashCache.get(source);
|
|
166
180
|
};
|
|
167
181
|
const lock = parseLock();
|
|
168
182
|
const shared = sharedFromLock(lock);
|
|
@@ -192,10 +206,12 @@ export function syncSkills({ check = false } = {}) {
|
|
|
192
206
|
else if (sourceHash(source) !== treeHash(target)) drift.push(`projection drift: ${relative(target)}`);
|
|
193
207
|
} else if (info?.isSymbolicLink() && existsSync(target) && realpathSync(target) === realpathSync(source)) {
|
|
194
208
|
continue;
|
|
209
|
+
} else if (info?.isDirectory() && tracked(relative(target)) && projectionMatchesSource(source, target)) {
|
|
210
|
+
continue;
|
|
195
211
|
} else {
|
|
196
212
|
rmSync(target, { recursive: true, force: true });
|
|
197
213
|
if (!info || !tracked(relative(target))) symlinkSync(path.relative(projection, source), target, "dir");
|
|
198
|
-
else cpSync(source, target, { recursive: true, preserveTimestamps: true });
|
|
214
|
+
else cpSync(source, target, { recursive: true, preserveTimestamps: true, verbatimSymlinks: true });
|
|
199
215
|
}
|
|
200
216
|
}
|
|
201
217
|
for (const name of OBSOLETE) {
|
|
@@ -230,11 +246,12 @@ function sourceRevisionMap(oldLock, arguments_) {
|
|
|
230
246
|
}
|
|
231
247
|
return sources;
|
|
232
248
|
}
|
|
233
|
-
function metadata(name, skillPath, directory, previous, canonical = false, sources = {}, upstreamRoot = null) {
|
|
249
|
+
function metadata(name, skillPath, directory, previous, canonical = false, sources = {}, upstreamRoot = null, hashCache = new Map()) {
|
|
234
250
|
const old = previous[name] ?? {};
|
|
235
251
|
let recordedPath = old.skillPath ?? skillPath;
|
|
236
252
|
if (canonical && /^\.(codex|cursor|pi)\/skills\//.test(recordedPath)) recordedPath = skillPath;
|
|
237
|
-
|
|
253
|
+
if (!hashCache.has(directory)) hashCache.set(directory, treeHash(directory));
|
|
254
|
+
const result = { source: old.source ?? "project", sourceType: old.sourceType ?? "local", skillPath: recordedPath, effectiveHash: hashCache.get(directory) };
|
|
238
255
|
const sourceInfo = sources[result.source];
|
|
239
256
|
if (sourceInfo?.revision) result.sourceRevision = sourceInfo.revision;
|
|
240
257
|
let upstreamDirectory = null;
|
|
@@ -249,7 +266,7 @@ function metadata(name, skillPath, directory, previous, canonical = false, sourc
|
|
|
249
266
|
}
|
|
250
267
|
return result;
|
|
251
268
|
}
|
|
252
|
-
export function updateSkillLock(arguments_ = process.argv.slice(2)) {
|
|
269
|
+
export function updateSkillLock(arguments_ = process.argv.slice(2), { hashCache = new Map() } = {}) {
|
|
253
270
|
const oldLock = parseLock(); const previous = priorMetadata(oldLock); const sources = sourceRevisionMap(oldLock, arguments_); const upstreamRoot = option(arguments_, "upstream-root");
|
|
254
271
|
const yssUiManifest = loadYssUiSkillManifest();
|
|
255
272
|
sources[yssUiManifest.source] = { ...(sources[yssUiManifest.source] ?? {}), revision: yssUiManifest.source_revision };
|
|
@@ -269,7 +286,7 @@ export function updateSkillLock(arguments_ = process.argv.slice(2)) {
|
|
|
269
286
|
if (unlocked.length) throw new TypeError(`发现未登记到 skills-lock.json 的已跟踪共享 skills: ${unlocked.join(", ")}\n确认新增后运行 scripts/update-skill-lock --add=<skill-name>`);
|
|
270
287
|
const targets = [".agents/skills", ...PROJECTION_ROOTS];
|
|
271
288
|
const shared = Object.fromEntries(sharedNames.map((name) => {
|
|
272
|
-
const item = metadata(name, `.agents/skills/${name}/SKILL.md`, path.join(SOURCE_ROOT, name), previous, true, sources, upstreamRoot);
|
|
289
|
+
const item = metadata(name, `.agents/skills/${name}/SKILL.md`, path.join(SOURCE_ROOT, name), previous, true, sources, upstreamRoot, hashCache);
|
|
273
290
|
const yssUiSkill = yssUiSkills.get(name);
|
|
274
291
|
if (yssUiSkill) {
|
|
275
292
|
item.source = yssUiManifest.source;
|
|
@@ -300,10 +317,12 @@ export function updateSkillLock(arguments_ = process.argv.slice(2)) {
|
|
|
300
317
|
if (!names.length) continue;
|
|
301
318
|
const absentPlatform = names.filter((name) => !lstatSafe(path.join(location, name))?.isDirectory());
|
|
302
319
|
if (absentPlatform.length) throw new TypeError(`锁文件声明的平台 skills 缺少内容 (${root}): ${absentPlatform.join(", ")}`);
|
|
303
|
-
platform[root] = Object.fromEntries(names.map((name) => { const item = metadata(name, `${root}/${name}/SKILL.md`, path.join(location, name), previous, false, sources, upstreamRoot); item.targets = [root]; return [name, item]; }));
|
|
320
|
+
platform[root] = Object.fromEntries(names.map((name) => { const item = metadata(name, `${root}/${name}/SKILL.md`, path.join(location, name), previous, false, sources, upstreamRoot, hashCache); item.targets = [root]; return [name, item]; }));
|
|
304
321
|
}
|
|
305
322
|
const manifest = { version: 3, generatedBy: "scripts/update-skill-lock", canonicalRoot: ".agents/skills", projectionRoots: PROJECTION_ROOTS, sources, skills: { shared, platform } };
|
|
306
323
|
const rendered = `${JSON.stringify(manifest, null, 2)}\n`;
|
|
307
|
-
|
|
308
|
-
|
|
324
|
+
const current = existsSync(LOCK_PATH) ? readFileSync(LOCK_PATH, "utf8") : null;
|
|
325
|
+
if (arguments_.includes("--check")) { if (current !== rendered) throw new TypeError("skills-lock.json is stale; run scripts/update-skill-lock"); return "skills-lock.json matches distributed skills"; }
|
|
326
|
+
if (current !== rendered) writeFileSync(LOCK_PATH, rendered);
|
|
327
|
+
return `updated skills-lock.json with ${sharedNames.length} shared skills and ${Object.values(platform).reduce((sum, group) => sum + Object.keys(group).length, 0)} platform skills`;
|
|
309
328
|
}
|
|
@@ -5,6 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { parseDocument } from "./vendor/yaml.mjs";
|
|
7
7
|
import { loadRegistry, validateRegistry } from "./lib/lifecycle-registry.mjs";
|
|
8
|
+
import { syncSkills, updateSkillLock } from "./lib/skill-supply-chain.mjs";
|
|
8
9
|
|
|
9
10
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
11
|
const identityPath = path.join(root, "yss-project.yaml");
|
|
@@ -16,18 +17,18 @@ if (identity?.schema_version !== 1 || identity?.repository_mode !== "project-ins
|
|
|
16
17
|
throw new TypeError("verify-project-instance 仅适用于合法 project-instance");
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
const commands = [
|
|
20
|
-
|
|
21
|
-
["scripts/update-skill-lock", ["--check"]],
|
|
22
|
-
["scripts/verify-context-contract", ["--root", ".", "--json"]],
|
|
23
|
-
];
|
|
24
|
-
for (const [command, args] of commands) {
|
|
20
|
+
const commands = ["scripts/sync-skills", "scripts/update-skill-lock", "scripts/verify-context-contract"];
|
|
21
|
+
for (const command of commands) {
|
|
25
22
|
const executable = path.join(root, command);
|
|
26
23
|
if (!existsSync(executable)) throw new TypeError(`缺少项目实例校验入口: ${command}`);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
}
|
|
25
|
+
const hashCache = new Map();
|
|
26
|
+
syncSkills({ check: true, hashCache });
|
|
27
|
+
updateSkillLock(["--check"], { hashCache });
|
|
28
|
+
const command = "scripts/verify-context-contract";
|
|
29
|
+
const result = spawnSync(path.join(root, command), ["--root", ".", "--json"], { cwd: root, encoding: "utf8" });
|
|
30
|
+
if (result.status !== 0) {
|
|
31
|
+
throw new TypeError(result.stderr.trim() || result.stdout.trim() || `${command} 校验失败`);
|
|
31
32
|
}
|
|
32
33
|
validateRegistry(loadRegistry());
|
|
33
34
|
process.stdout.write("项目实例校验通过\n");
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"revision": "c4d958f18cc947cb91cbe1bd48783fa4601cc18f"
|
|
19
19
|
},
|
|
20
20
|
"iloveZzz/yss-harness-design-agent": {
|
|
21
|
-
"revision": "
|
|
21
|
+
"revision": "9b579c7b954c153d2347696f53123aebaccde48f"
|
|
22
22
|
},
|
|
23
23
|
"ayghri/i-have-adhd": {
|
|
24
24
|
"revision": "7b9069b39972e269e61bd95c2f66ebb90cac6a02"
|
|
@@ -226,21 +226,6 @@
|
|
|
226
226
|
".pi/skills"
|
|
227
227
|
]
|
|
228
228
|
},
|
|
229
|
-
"grill-me": {
|
|
230
|
-
"source": "mattpocock/skills",
|
|
231
|
-
"sourceType": "github",
|
|
232
|
-
"skillPath": "skills/productivity/grill-me/SKILL.md",
|
|
233
|
-
"effectiveHash": "916cf7ff0d81cf47fe578bd86695e09a53fbe8a4b371586e19dde6573549e88d",
|
|
234
|
-
"sourceRevision": "0ab1b63a410a03d3627979a109c8695de27af954",
|
|
235
|
-
"upstreamHash": "5a13e157f85835632b132390a162d234822658b6a544f31cc2578280062bd044",
|
|
236
|
-
"adaptationRef": "docs/process/MATT-POCOCK-ENGINEERING-SKILLS.md",
|
|
237
|
-
"targets": [
|
|
238
|
-
".agents/skills",
|
|
239
|
-
".codex/skills",
|
|
240
|
-
".cursor/skills",
|
|
241
|
-
".pi/skills"
|
|
242
|
-
]
|
|
243
|
-
},
|
|
244
229
|
"grill-with-docs": {
|
|
245
230
|
"source": "mattpocock/skills",
|
|
246
231
|
"sourceType": "github",
|
|
@@ -425,7 +410,7 @@
|
|
|
425
410
|
"sourceType": "git-submodule",
|
|
426
411
|
"skillPath": ".agents/skills/prototype-review/SKILL.md",
|
|
427
412
|
"effectiveHash": "410ed10f248f6eb396cd50cea905032e45ec9b203aad41dbf78dbd03aba84b55",
|
|
428
|
-
"sourceRevision": "
|
|
413
|
+
"sourceRevision": "9b579c7b954c153d2347696f53123aebaccde48f",
|
|
429
414
|
"upstreamHash": "6df02dd4de236a749a80efd5eba46d18be7979849af2a9af28636906ccfcb2a0",
|
|
430
415
|
"adaptationRef": "docs/agents/strategic-design-skills-integration.md",
|
|
431
416
|
"targets": [
|
|
@@ -682,7 +667,7 @@
|
|
|
682
667
|
"source": "project",
|
|
683
668
|
"sourceType": "local",
|
|
684
669
|
"skillPath": ".agents/skills/yss-cache/SKILL.md",
|
|
685
|
-
"effectiveHash": "
|
|
670
|
+
"effectiveHash": "64a24a5108feae462d5cf53d2892a27e9ae00c552e6a184f8b59c7dcafe9b62d",
|
|
686
671
|
"targets": [
|
|
687
672
|
".agents/skills",
|
|
688
673
|
".codex/skills",
|
|
@@ -707,7 +692,7 @@
|
|
|
707
692
|
"sourceType": "git-submodule",
|
|
708
693
|
"skillPath": ".agents/skills/yss-design-system/SKILL.md",
|
|
709
694
|
"effectiveHash": "b3ddbff30926f6675ac60cbf89182593df7ed272d7a1dc75f657f7640960c1b8",
|
|
710
|
-
"sourceRevision": "
|
|
695
|
+
"sourceRevision": "9b579c7b954c153d2347696f53123aebaccde48f",
|
|
711
696
|
"upstreamHash": "e156229435c35827c48d3699b021e5e171ec565c2bf91cc91cbb033bf7802d7c",
|
|
712
697
|
"adaptationRef": "docs/agents/strategic-design-skills-integration.md",
|
|
713
698
|
"targets": [
|
|
@@ -721,7 +706,7 @@
|
|
|
721
706
|
"source": "project",
|
|
722
707
|
"sourceType": "local",
|
|
723
708
|
"skillPath": ".agents/skills/yss-distributed-id/SKILL.md",
|
|
724
|
-
"effectiveHash": "
|
|
709
|
+
"effectiveHash": "d7e61711f9ccc8a1f5a7c768f4016cd57bbcd3ff9d5fc0375c550ea387a68d31",
|
|
725
710
|
"targets": [
|
|
726
711
|
".agents/skills",
|
|
727
712
|
".codex/skills",
|
|
@@ -856,7 +841,7 @@
|
|
|
856
841
|
"source": "project",
|
|
857
842
|
"sourceType": "local",
|
|
858
843
|
"skillPath": ".agents/skills/yss-mybatis/SKILL.md",
|
|
859
|
-
"effectiveHash": "
|
|
844
|
+
"effectiveHash": "59cc457511213d05c1cd5a035f41f22ca14d77f296be7e7a4ccc9067f0f158b3",
|
|
860
845
|
"targets": [
|
|
861
846
|
".agents/skills",
|
|
862
847
|
".codex/skills",
|
|
@@ -892,7 +877,7 @@
|
|
|
892
877
|
"source": "project",
|
|
893
878
|
"sourceType": "local",
|
|
894
879
|
"skillPath": ".agents/skills/yss-product-lifecycle/SKILL.md",
|
|
895
|
-
"effectiveHash": "
|
|
880
|
+
"effectiveHash": "509c9a2b5bbb8e4c1a0b72bd59e75ef3cde0d70452a0c9d7ffa5864a737814ba",
|
|
896
881
|
"targets": [
|
|
897
882
|
".agents/skills",
|
|
898
883
|
".codex/skills",
|
|
@@ -904,8 +889,8 @@
|
|
|
904
889
|
"source": "iloveZzz/yss-harness-design-agent",
|
|
905
890
|
"sourceType": "git-submodule",
|
|
906
891
|
"skillPath": ".agents/skills/yss-prototype-stage/SKILL.md",
|
|
907
|
-
"effectiveHash": "
|
|
908
|
-
"sourceRevision": "
|
|
892
|
+
"effectiveHash": "ac8390003dd1cf661cf01f9b13fdb37f16463810af0c74fe9a8428cc569a5167",
|
|
893
|
+
"sourceRevision": "9b579c7b954c153d2347696f53123aebaccde48f",
|
|
909
894
|
"upstreamHash": "6e1bcdf107d95c11faee2b988e4e0c36b8e5b76f6b40312a206b83733a96b0fc",
|
|
910
895
|
"adaptationRef": "docs/agents/strategic-design-skills-integration.md",
|
|
911
896
|
"targets": [
|
|
@@ -919,7 +904,7 @@
|
|
|
919
904
|
"source": "project",
|
|
920
905
|
"sourceType": "local",
|
|
921
906
|
"skillPath": ".agents/skills/yss-repository/SKILL.md",
|
|
922
|
-
"effectiveHash": "
|
|
907
|
+
"effectiveHash": "4c67dbfa563761b60668e4622ae7043ded94458f29b2ad0525fd53fa6c98d672",
|
|
923
908
|
"targets": [
|
|
924
909
|
".agents/skills",
|
|
925
910
|
".codex/skills",
|
|
@@ -983,7 +968,7 @@
|
|
|
983
968
|
"sourceType": "git-submodule",
|
|
984
969
|
"skillPath": ".agents/skills/yss-stage-decision/SKILL.md",
|
|
985
970
|
"effectiveHash": "43a83bc02fea3c36105be6791ad019036b7ea1a17e5f0704daf93fb7be29b60b",
|
|
986
|
-
"sourceRevision": "
|
|
971
|
+
"sourceRevision": "9b579c7b954c153d2347696f53123aebaccde48f",
|
|
987
972
|
"upstreamHash": "f7f765e20f4dca6aca667be03e2b9a7f2a8acc3510eefba88306961882d86ed4",
|
|
988
973
|
"adaptationRef": "docs/agents/strategic-design-skills-integration.md",
|
|
989
974
|
"targets": [
|
package/template.manifest.json
CHANGED
|
@@ -101,11 +101,26 @@
|
|
|
101
101
|
".gitignore",
|
|
102
102
|
"AGENTS.md",
|
|
103
103
|
"README.md",
|
|
104
|
+
"skills-lock.json",
|
|
105
|
+
"docs/user-guide/用户手册.md",
|
|
106
|
+
"docs/user-guide/用户手册索引.md",
|
|
107
|
+
"docs/user-guide/阶段接入与产物复用使用手册.md",
|
|
108
|
+
"docs/user-guide/技术设计用户指南.md",
|
|
109
|
+
"docs/design/README.md",
|
|
110
|
+
"docs/engineering/backend-platforms.json",
|
|
111
|
+
"scripts/lib/skill-supply-chain.mjs",
|
|
112
|
+
"docs/agents/backend-architecture-profiles.md",
|
|
113
|
+
".agents/skills/yss-design-system/SKILL.md",
|
|
114
|
+
".agents/skills/yss-design-system/references/data-quality-theme.md",
|
|
115
|
+
".codex/skills/yss-design-system/SKILL.md",
|
|
116
|
+
".codex/skills/yss-design-system/references/data-quality-theme.md",
|
|
117
|
+
".cursor/skills/yss-design-system/SKILL.md",
|
|
118
|
+
".cursor/skills/yss-design-system/references/data-quality-theme.md",
|
|
119
|
+
".pi/skills/yss-design-system/SKILL.md",
|
|
120
|
+
".pi/skills/yss-design-system/references/data-quality-theme.md",
|
|
104
121
|
"yss-project.yaml"
|
|
105
122
|
],
|
|
106
|
-
"exampleDocPaths": [
|
|
107
|
-
"docs/plan/IDEATION.md"
|
|
108
|
-
],
|
|
123
|
+
"exampleDocPaths": [],
|
|
109
124
|
"initExcludeRootEntries": [],
|
|
110
125
|
"initExcludeRootFiles": [
|
|
111
126
|
"yss-public-skills.json"
|
package/template.snapshot.json
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
"templateName": "yss-spec-project-template",
|
|
4
4
|
"templateSource": "github:iloveZzz/yss-spec-project-template",
|
|
5
5
|
"templateRepository": "https://github.com/iloveZzz/yss-spec-project-template.git",
|
|
6
|
-
"requestedRef": "
|
|
7
|
-
"templateCommit": "
|
|
6
|
+
"requestedRef": "085a80540035c6430a2dff1fb3fb7396469152df",
|
|
7
|
+
"templateCommit": "085a80540035c6430a2dff1fb3fb7396469152df",
|
|
8
8
|
"sourceState": "committed",
|
|
9
|
-
"manifestHash": "
|
|
9
|
+
"manifestHash": "d60babd9ea2ec16ee054c0c3f467379ba42915b348e1a0451c2975a60c4496d0",
|
|
10
10
|
"encodedPaths": {
|
|
11
11
|
".agents/skills/yss-frontend-scaffold-generator/assets/data-quality-v1/.gitignore": ".agents/skills/yss-frontend-scaffold-generator/assets/data-quality-v1/__yss_dotfile__.gitignore",
|
|
12
12
|
".codex/skills/data-analytics/.gitignore": ".codex/skills/data-analytics/__yss_dotfile__.gitignore",
|
|
@@ -17,6 +17,6 @@
|
|
|
17
17
|
".gitignore": "__yss_dotfile__.gitignore",
|
|
18
18
|
".pi/skills/yss-frontend-scaffold-generator/assets/data-quality-v1/.gitignore": ".pi/skills/yss-frontend-scaffold-generator/assets/data-quality-v1/__yss_dotfile__.gitignore"
|
|
19
19
|
},
|
|
20
|
-
"snapshotHash": "
|
|
21
|
-
"generatedAt": "2026-09-
|
|
20
|
+
"snapshotHash": "11dfca9873c856b70ec0ae6309e9e391143c4fc102a92553bd118b19640ead16",
|
|
21
|
+
"generatedAt": "2026-09-24T13:20:11.384Z"
|
|
22
22
|
}
|