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.
Files changed (174) hide show
  1. package/README.md +2 -2
  2. package/package.json +1 -1
  3. package/src/api/_sync-service.js +111 -18
  4. package/src/cli/args.js +1 -0
  5. package/src/cli/help.js +10 -1
  6. package/src/cli/index.js +3 -0
  7. package/src/cli/prompts.js +5 -1
  8. package/src/cli/router.js +2 -0
  9. package/src/commands/attach.js +12 -2
  10. package/src/commands/init.js +2 -0
  11. package/src/commands/skills.js +253 -0
  12. package/src/commands/sync.js +3 -0
  13. package/src/family-identity.js +1 -1
  14. package/src/template/asset-runtime.js +220 -0
  15. package/src/template/distribution-runtime.js +165 -0
  16. package/src/template/instance-runtime.js +76 -29
  17. package/src/template/ownership-policy.js +17 -1
  18. package/src/template/prune-planner.js +6 -1
  19. package/src/template/sync-planner.js +3 -0
  20. package/src/template/verification-runtime.js +56 -1
  21. package/src/validation/metadata.js +24 -1
  22. package/template/.agents/skills/.strategic-design-skills-manifest.json +1 -1
  23. package/template/.agents/skills/yss-cache/SKILL.md +6 -5
  24. package/template/.agents/skills/yss-cache/references/annotations.md +3 -1
  25. package/template/.agents/skills/yss-cache/references/architecture.md +4 -2
  26. package/template/.agents/skills/yss-cache/references/configuration.md +6 -3
  27. package/template/.agents/skills/yss-cache/references/jetcache.md +21 -0
  28. package/template/.agents/skills/yss-cache/references/redis-fallback.md +5 -3
  29. package/template/.agents/skills/yss-cache/references/verification.md +10 -4
  30. package/template/.agents/skills/yss-cache/scripts/verify-cache-component.sh +26 -20
  31. package/template/.agents/skills/yss-distributed-id/SKILL.md +14 -58
  32. package/template/.agents/skills/yss-distributed-id/agents/openai.yaml +2 -2
  33. package/template/.agents/skills/yss-distributed-id/references/README.md +11 -47
  34. package/template/.agents/skills/yss-mybatis/SKILL.md +14 -2
  35. package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +5 -4
  36. package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +8 -8
  37. package/template/.agents/skills/yss-prototype-stage/SKILL.md +2 -2
  38. package/template/.agents/skills/yss-repository/SKILL.md +1 -0
  39. package/template/.codex/skills/yss-cache/SKILL.md +6 -5
  40. package/template/.codex/skills/yss-cache/references/annotations.md +3 -1
  41. package/template/.codex/skills/yss-cache/references/architecture.md +4 -2
  42. package/template/.codex/skills/yss-cache/references/configuration.md +6 -3
  43. package/template/.codex/skills/yss-cache/references/jetcache.md +21 -0
  44. package/template/.codex/skills/yss-cache/references/redis-fallback.md +5 -3
  45. package/template/.codex/skills/yss-cache/references/verification.md +10 -4
  46. package/template/.codex/skills/yss-cache/scripts/verify-cache-component.sh +26 -20
  47. package/template/.codex/skills/yss-distributed-id/SKILL.md +14 -58
  48. package/template/.codex/skills/yss-distributed-id/agents/openai.yaml +2 -2
  49. package/template/.codex/skills/yss-distributed-id/references/README.md +11 -47
  50. package/template/.codex/skills/yss-mybatis/SKILL.md +14 -2
  51. package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +5 -4
  52. package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +8 -8
  53. package/template/.codex/skills/yss-prototype-stage/SKILL.md +2 -2
  54. package/template/.codex/skills/yss-repository/SKILL.md +1 -0
  55. package/template/.cursor/skills/yss-cache/SKILL.md +6 -5
  56. package/template/.cursor/skills/yss-cache/references/annotations.md +3 -1
  57. package/template/.cursor/skills/yss-cache/references/architecture.md +4 -2
  58. package/template/.cursor/skills/yss-cache/references/configuration.md +6 -3
  59. package/template/.cursor/skills/yss-cache/references/jetcache.md +21 -0
  60. package/template/.cursor/skills/yss-cache/references/redis-fallback.md +5 -3
  61. package/template/.cursor/skills/yss-cache/references/verification.md +10 -4
  62. package/template/.cursor/skills/yss-cache/scripts/verify-cache-component.sh +26 -20
  63. package/template/.cursor/skills/yss-distributed-id/SKILL.md +14 -58
  64. package/template/.cursor/skills/yss-distributed-id/agents/openai.yaml +2 -2
  65. package/template/.cursor/skills/yss-distributed-id/references/README.md +11 -47
  66. package/template/.cursor/skills/yss-mybatis/SKILL.md +14 -2
  67. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +5 -4
  68. package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +8 -8
  69. package/template/.cursor/skills/yss-prototype-stage/SKILL.md +2 -2
  70. package/template/.cursor/skills/yss-repository/SKILL.md +1 -0
  71. package/template/.pi/skills/yss-cache/SKILL.md +6 -5
  72. package/template/.pi/skills/yss-cache/references/annotations.md +3 -1
  73. package/template/.pi/skills/yss-cache/references/architecture.md +4 -2
  74. package/template/.pi/skills/yss-cache/references/configuration.md +6 -3
  75. package/template/.pi/skills/yss-cache/references/jetcache.md +21 -0
  76. package/template/.pi/skills/yss-cache/references/redis-fallback.md +5 -3
  77. package/template/.pi/skills/yss-cache/references/verification.md +10 -4
  78. package/template/.pi/skills/yss-cache/scripts/verify-cache-component.sh +26 -20
  79. package/template/.pi/skills/yss-distributed-id/SKILL.md +14 -58
  80. package/template/.pi/skills/yss-distributed-id/agents/openai.yaml +2 -2
  81. package/template/.pi/skills/yss-distributed-id/references/README.md +11 -47
  82. package/template/.pi/skills/yss-mybatis/SKILL.md +14 -2
  83. package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +5 -4
  84. package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +8 -8
  85. package/template/.pi/skills/yss-prototype-stage/SKILL.md +2 -2
  86. package/template/.pi/skills/yss-repository/SKILL.md +1 -0
  87. package/template/README.md +2 -5
  88. package/template/docs/agents/skill-migrations.md +4 -0
  89. package/template/docs/agents/yss-skill-registry.yaml +7 -6
  90. package/template/docs/design/README.md +0 -1
  91. package/template/docs/design/design.md +2 -2
  92. package/template/docs/design/templates/interaction-spec-template.md +1 -1
  93. package/template/docs/engineering/evidence/aliyun-artifact-resolution.json +446 -0
  94. package/template/scripts/design-md +2 -0
  95. package/template/scripts/lib/design-md.mjs +230 -0
  96. package/template/scripts/lib/skill-registry.mjs +9 -2
  97. package/template/scripts/lib/skill-supply-chain.mjs +33 -14
  98. package/template/scripts/verify-project-instance +11 -10
  99. package/template/skills-lock.json +11 -26
  100. package/template.manifest.json +18 -3
  101. package/template.snapshot.json +5 -5
  102. package/template/.agents/skills/grill-me/SKILL.md +0 -7
  103. package/template/.agents/skills/grill-me/agents/openai.yaml +0 -5
  104. package/template/.agents/skills/yss-distributed-id/assets/AutoIdInterceptor.java +0 -246
  105. package/template/.agents/skills/yss-distributed-id/assets/EnableDistributedId.java +0 -25
  106. package/template/.agents/skills/yss-distributed-id/assets/LeafConf.java +0 -36
  107. package/template/.codex/skills/grill-me/SKILL.md +0 -7
  108. package/template/.codex/skills/grill-me/agents/openai.yaml +0 -5
  109. package/template/.codex/skills/yss-distributed-id/assets/AutoIdInterceptor.java +0 -246
  110. package/template/.codex/skills/yss-distributed-id/assets/EnableDistributedId.java +0 -25
  111. package/template/.codex/skills/yss-distributed-id/assets/LeafConf.java +0 -36
  112. package/template/.cursor/skills/grill-me/SKILL.md +0 -7
  113. package/template/.cursor/skills/grill-me/agents/openai.yaml +0 -5
  114. package/template/.cursor/skills/yss-distributed-id/assets/AutoIdInterceptor.java +0 -246
  115. package/template/.cursor/skills/yss-distributed-id/assets/EnableDistributedId.java +0 -25
  116. package/template/.cursor/skills/yss-distributed-id/assets/LeafConf.java +0 -36
  117. package/template/.pi/skills/grill-me/SKILL.md +0 -7
  118. package/template/.pi/skills/grill-me/agents/openai.yaml +0 -5
  119. package/template/.pi/skills/yss-distributed-id/assets/AutoIdInterceptor.java +0 -246
  120. package/template/.pi/skills/yss-distributed-id/assets/EnableDistributedId.java +0 -25
  121. package/template/.pi/skills/yss-distributed-id/assets/LeafConf.java +0 -36
  122. package/template/docs/agents/yss-plugin-dependency-contract.md +0 -45
  123. package/template/docs/api/.gitkeep +0 -0
  124. package/template/docs/api/specs/.gitkeep +0 -0
  125. package/template/docs/architecture/.gitkeep +0 -0
  126. package/template/docs/design/facts/antdv-next/1.5.2/cli-help.txt +0 -38
  127. package/template/docs/design/facts/antdv-next/1.5.2/component-list.json +0 -434
  128. package/template/docs/design/facts/antdv-next/1.5.2/components/Alert/demo-basic.json +0 -7
  129. package/template/docs/design/facts/antdv-next/1.5.2/components/Alert/info.json +0 -246
  130. package/template/docs/design/facts/antdv-next/1.5.2/components/Alert/semantic.json +0 -40
  131. package/template/docs/design/facts/antdv-next/1.5.2/components/Alert/token.json +0 -32
  132. package/template/docs/design/facts/antdv-next/1.5.2/components/Button/demo-basic.json +0 -7
  133. package/template/docs/design/facts/antdv-next/1.5.2/components/Button/info.json +0 -190
  134. package/template/docs/design/facts/antdv-next/1.5.2/components/Button/semantic.json +0 -20
  135. package/template/docs/design/facts/antdv-next/1.5.2/components/Button/token.json +0 -256
  136. package/template/docs/design/facts/antdv-next/1.5.2/components/Input/demo-basic.json +0 -7
  137. package/template/docs/design/facts/antdv-next/1.5.2/components/Input/info.json +0 -460
  138. package/template/docs/design/facts/antdv-next/1.5.2/components/Input/semantic.json +0 -70
  139. package/template/docs/design/facts/antdv-next/1.5.2/components/Input/token.json +0 -123
  140. package/template/docs/design/facts/antdv-next/1.5.2/components/Modal/demo-basic.json +0 -7
  141. package/template/docs/design/facts/antdv-next/1.5.2/components/Modal/info.json +0 -646
  142. package/template/docs/design/facts/antdv-next/1.5.2/components/Modal/semantic.json +0 -50
  143. package/template/docs/design/facts/antdv-next/1.5.2/components/Modal/token.json +0 -130
  144. package/template/docs/design/facts/antdv-next/1.5.2/components/Select/demo-basic.json +0 -7
  145. package/template/docs/design/facts/antdv-next/1.5.2/components/Select/info.json +0 -640
  146. package/template/docs/design/facts/antdv-next/1.5.2/components/Select/semantic.json +0 -70
  147. package/template/docs/design/facts/antdv-next/1.5.2/components/Select/token.json +0 -172
  148. package/template/docs/design/facts/antdv-next/1.5.2/components/Table/demo-basic.json +0 -7
  149. package/template/docs/design/facts/antdv-next/1.5.2/components/Table/info.json +0 -1010
  150. package/template/docs/design/facts/antdv-next/1.5.2/components/Table/semantic.json +0 -70
  151. package/template/docs/design/facts/antdv-next/1.5.2/components/Table/token.json +0 -263
  152. package/template/docs/design/facts/antdv-next/1.5.2/components/Tag/demo-basic.json +0 -7
  153. package/template/docs/design/facts/antdv-next/1.5.2/components/Tag/info.json +0 -321
  154. package/template/docs/design/facts/antdv-next/1.5.2/components/Tag/semantic.json +0 -25
  155. package/template/docs/design/facts/antdv-next/1.5.2/components/Tag/token.json +0 -25
  156. package/template/docs/design/facts/antdv-next/1.5.2/design-md.json +0 -3
  157. package/template/docs/design/facts/antdv-next/1.5.2/manifest.json +0 -215
  158. package/template/docs/design/facts/antdv-next/1.5.2/resolution-probe.json +0 -5
  159. package/template/docs/design/prototypes/.gitkeep +0 -1
  160. package/template/docs/implementation/.gitkeep +0 -1
  161. package/template/docs/plan/IDEATION.md +0 -96
  162. package/template/docs/process/PDCA-SCRUM.md +0 -10
  163. package/template/docs/process/harness-executive-blueprint.md +0 -10
  164. package/template/docs/releases/.gitkeep +0 -1
  165. package/template/docs/requirements/README.md +0 -85
  166. package/template/docs/requirements/tickets/.gitkeep +0 -1
  167. package/template/docs/templates/agent-brief-template.md +0 -46
  168. package/template/docs/templates/architecture-proposal-template.md +0 -18
  169. package/template/docs/templates/implementation-plan-template.md +0 -16
  170. package/template/docs/templates/implementation-routing-template.md +0 -350
  171. package/template/docs/templates/requirement-freeze-template.md +0 -63
  172. package/template/docs/templates/risk-register-template.md +0 -11
  173. package/template/docs/templates/user-story-template.md +0 -20
  174. 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
- `${requestedId} 已硬退役;按迁移 tombstone 重新路由`,
71
- { skill: requestedId, migration_ref: "docs/agents/skill-migrations.md" }
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 (!sourceHashes.has(source)) sourceHashes.set(source, treeHash(source));
165
- return sourceHashes.get(source);
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
- const result = { source: old.source ?? "project", sourceType: old.sourceType ?? "local", skillPath: recordedPath, effectiveHash: treeHash(directory) };
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
- if (arguments_.includes("--check")) { if (!existsSync(LOCK_PATH) || readFileSync(LOCK_PATH, "utf8") !== rendered) throw new TypeError("skills-lock.json is stale; run scripts/update-skill-lock"); return "skills-lock.json matches distributed skills"; }
308
- writeFileSync(LOCK_PATH, rendered); 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`;
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
- ["scripts/sync-skills", ["--check"]],
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
- const result = spawnSync(executable, args, { cwd: root, encoding: "utf8" });
28
- if (result.status !== 0) {
29
- throw new TypeError(result.stderr.trim() || result.stdout.trim() || `${command} 校验失败`);
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": "9e17922a0a718e5bd1845ddab11850a2f43becad"
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": "9e17922a0a718e5bd1845ddab11850a2f43becad",
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": "aa18e0996bdc49f0d7ee4a75f49f8ab765259ec3b60d6e9bfe871c3c2f6a8346",
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": "9e17922a0a718e5bd1845ddab11850a2f43becad",
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": "07f3915e94a37c47178f23e97720be9c293fa7019d48e7dbf1e5d2d8856029a5",
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": "c844472c366438f0c84d22246a82eca645753cf562a909c8857d4a621bf5ad7c",
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": "0904753ec31459a719530aae71864e5a8f2d8acef66f64065c7e2848a362c23e",
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": "4cc7d388f89feddf50d208b2d5db3a4ffa41974afb364328270c097970fc39c0",
908
- "sourceRevision": "9e17922a0a718e5bd1845ddab11850a2f43becad",
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": "b70b05ba98192eaf3f463d5409e43ed221d53ed097c00bf740364c786954de96",
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": "9e17922a0a718e5bd1845ddab11850a2f43becad",
971
+ "sourceRevision": "9b579c7b954c153d2347696f53123aebaccde48f",
987
972
  "upstreamHash": "f7f765e20f4dca6aca667be03e2b9a7f2a8acc3510eefba88306961882d86ed4",
988
973
  "adaptationRef": "docs/agents/strategic-design-skills-integration.md",
989
974
  "targets": [
@@ -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"
@@ -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": "445172278b7a107ac42ec00ee1dd936bdd244933",
7
- "templateCommit": "445172278b7a107ac42ec00ee1dd936bdd244933",
6
+ "requestedRef": "085a80540035c6430a2dff1fb3fb7396469152df",
7
+ "templateCommit": "085a80540035c6430a2dff1fb3fb7396469152df",
8
8
  "sourceState": "committed",
9
- "manifestHash": "7c2fe5e36a464fd32b4ec6466e18e8c762a59bda9cb5b598950aba7dd6358891",
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": "7a8f13451bd03f54c57a0b4fa3f713fcf0e43601212590a3fb6e8e5db34f5b37",
21
- "generatedAt": "2026-09-22T11:13:45.412Z"
20
+ "snapshotHash": "11dfca9873c856b70ec0ae6309e9e391143c4fc102a92553bd118b19640ead16",
21
+ "generatedAt": "2026-09-24T13:20:11.384Z"
22
22
  }
@@ -1,7 +0,0 @@
1
- ---
2
- name: grill-me
3
- description: A relentless interview to sharpen a plan or design.
4
- disable-model-invocation: true
5
- ---
6
-
7
- Call the Skill tool with `grilling`.
@@ -1,5 +0,0 @@
1
- interface:
2
- display_name: "Grill Me"
3
- short_description: "Sharpen a plan through interview"
4
- policy:
5
- allow_implicit_invocation: false