create-yss-spec 3.1.0 → 3.1.3

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 (139) hide show
  1. package/README.md +117 -91
  2. package/bin/create-yss-spec.js +11 -3
  3. package/package.json +9 -2
  4. package/src/api/_sync-service.js +191 -0
  5. package/src/api/index.js +22 -0
  6. package/src/api/project-diff.js +9 -0
  7. package/src/api/project-doctor.js +10 -0
  8. package/src/api/template-apply.js +10 -0
  9. package/src/api/template-plan.js +9 -0
  10. package/src/cli/args.js +60 -0
  11. package/src/cli/error-output.js +52 -0
  12. package/src/cli/flags.js +9 -0
  13. package/src/cli/help.js +95 -0
  14. package/src/cli/index.js +82 -0
  15. package/src/cli/plan-output.js +61 -0
  16. package/src/cli/prompts.js +91 -0
  17. package/src/cli/router.js +41 -0
  18. package/src/cli.js +5 -2253
  19. package/src/commands/attach.js +280 -0
  20. package/src/commands/diff.js +23 -0
  21. package/src/commands/doctor.js +417 -0
  22. package/src/commands/init.js +193 -0
  23. package/src/commands/sync.js +146 -0
  24. package/src/commands/update.js +14 -0
  25. package/src/contracts/apply-result-v1.json +45 -0
  26. package/src/contracts/customization-policy-v1.json +28 -0
  27. package/src/contracts/doctor-report-v1.json +29 -0
  28. package/src/contracts/error-envelope-v1.json +24 -0
  29. package/src/contracts/generator-policy-v1.json +24 -0
  30. package/src/contracts/ownership-policy-v1.json +40 -0
  31. package/src/contracts/plan-schema-v1.json +115 -0
  32. package/src/family-identity.js +365 -0
  33. package/src/family-runtime.js +23 -0
  34. package/src/filesystem/apply-plan.js +44 -0
  35. package/src/filesystem/copy-path.js +28 -0
  36. package/src/filesystem/path-utils.js +67 -0
  37. package/src/filesystem/transaction-runner.js +41 -0
  38. package/src/filesystem/transaction.js +153 -0
  39. package/src/git/submodule.js +115 -0
  40. package/src/git/worktree.js +69 -0
  41. package/src/template/attach-planner-runtime.js +51 -0
  42. package/src/template/attach-planner.js +160 -0
  43. package/src/template/instance-runtime.js +463 -0
  44. package/src/template/lifecycle-metadata.js +99 -0
  45. package/src/template/lifecycle-policy.js +129 -0
  46. package/src/template/lifecycle-runtime.js +90 -0
  47. package/src/template/migration-planner.js +95 -0
  48. package/src/template/migration-runtime.js +247 -0
  49. package/src/template/ownership-metadata.js +79 -0
  50. package/src/template/ownership-policy.js +149 -0
  51. package/src/template/ownership-runtime.js +109 -0
  52. package/src/template/plan-schema.js +36 -0
  53. package/src/template/sync-planner-runtime.js +57 -0
  54. package/src/template/sync-planner.js +206 -0
  55. package/src/template/verification-runtime.js +154 -0
  56. package/src/validation/identity.js +41 -0
  57. package/src/validation/metadata.js +105 -0
  58. package/src/validation/security.js +67 -0
  59. package/src/validation/snapshot.js +47 -0
  60. package/template/.agents/skills/.strategic-design-skills-manifest.json +1 -1
  61. package/template/.agents/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
  62. package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  63. package/template/.agents/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +6 -0
  64. package/template/.agents/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +2 -0
  65. package/template/.agents/skills/yss-product-lifecycle/SKILL.md +2 -0
  66. package/template/.agents/skills/yss-ui/SKILL.md +2 -0
  67. package/template/.claude/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
  68. package/template/.claude/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  69. package/template/.claude/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +6 -0
  70. package/template/.claude/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +2 -0
  71. package/template/.claude/skills/yss-product-lifecycle/SKILL.md +2 -0
  72. package/template/.claude/skills/yss-ui/SKILL.md +2 -0
  73. package/template/.codex/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
  74. package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  75. package/template/.codex/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +6 -0
  76. package/template/.codex/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +2 -0
  77. package/template/.codex/skills/yss-product-lifecycle/SKILL.md +2 -0
  78. package/template/.codex/skills/yss-ui/SKILL.md +2 -0
  79. package/template/.cursor/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
  80. package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  81. package/template/.cursor/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +6 -0
  82. package/template/.cursor/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +2 -0
  83. package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +2 -0
  84. package/template/.cursor/skills/yss-ui/SKILL.md +2 -0
  85. package/template/.pi/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
  86. package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  87. package/template/.pi/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +6 -0
  88. package/template/.pi/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +2 -0
  89. package/template/.pi/skills/yss-product-lifecycle/SKILL.md +2 -0
  90. package/template/.pi/skills/yss-ui/SKILL.md +2 -0
  91. package/template/.qoder/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
  92. package/template/.qoder/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  93. package/template/.qoder/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +6 -0
  94. package/template/.qoder/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +2 -0
  95. package/template/.qoder/skills/yss-product-lifecycle/SKILL.md +2 -0
  96. package/template/.qoder/skills/yss-ui/SKILL.md +2 -0
  97. package/template/.trae/skills/yss-frontend-scaffold-generator/SKILL.md +2 -0
  98. package/template/.trae/skills/yss-implementation-contract-compiler/SKILL.md +2 -0
  99. package/template/.trae/skills/yss-implementation-contract-compiler/references/compiler-contract.yaml +6 -0
  100. package/template/.trae/skills/yss-implementation-contract-compiler/references/slice-implementation-contract.md +2 -0
  101. package/template/.trae/skills/yss-product-lifecycle/SKILL.md +2 -0
  102. package/template/.trae/skills/yss-ui/SKILL.md +2 -0
  103. package/template/CONTEXT.md +2 -0
  104. package/template/README.md +4 -0
  105. package/template/docs/agents/digital-human-roles.yaml +1 -0
  106. package/template/docs/process/frontend-backend-delivery.md +72 -0
  107. package/template/docs/process/implementation-repo-integration.md +2 -0
  108. package/template/docs/process/lifecycle-artifact-map.md +1 -0
  109. package/template/docs/process/lifecycle-registry-baseline.json +2 -1
  110. package/template/docs/process/lifecycle-registry.yaml +5 -0
  111. package/template/docs/process/schemas/backend-delivery-verification.schema.json +113 -0
  112. package/template/docs/process/schemas/backend-delivery.schema.json +301 -0
  113. package/template/docs/process/schemas/digital-human-task-package.schema.json +8 -0
  114. package/template/docs/process/schemas/frontend-delivery-acceptance.schema.json +200 -0
  115. package/template/docs/process/schemas/frontend-implementation-evidence.schema.json +3 -0
  116. package/template/docs/process/template-verification-profiles.yaml +6 -0
  117. package/template/docs/user-guide//346/210/230/346/234/257/350/256/276/350/256/241/345/255/220/351/241/271/347/233/256/347/224/250/346/210/267/346/211/213/345/206/214.md +20 -206
  118. package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214.md +63 -963
  119. package/template/docs/user-guide//347/224/250/346/210/267/346/211/213/345/206/214/347/264/242/345/274/225.md +11 -14
  120. package/template/docs/user-guide//350/256/276/345/244/207/345/200/237/347/224/250/350/264/257/347/251/277/346/241/210/344/276/213.md +127 -0
  121. package/template/scripts/backend-delivery +14 -0
  122. package/template/scripts/fixtures/backend-delivery/revision-server.mjs +11 -0
  123. package/template/scripts/instantiate-harness +69 -0
  124. package/template/scripts/lib/backend-delivery.mjs +164 -0
  125. package/template/scripts/lib/frontend-delivery-boundary.mjs +49 -0
  126. package/template/scripts/lib/frontend-delivery.mjs +73 -0
  127. package/template/scripts/lib/harness-execution-scope.mjs +52 -0
  128. package/template/scripts/lib/implementation-contract-compiler.mjs +12 -2
  129. package/template/scripts/lib/lifecycle-transition.mjs +7 -0
  130. package/template/scripts/lib/strategic-handoff-consumption.mjs +14 -7
  131. package/template/scripts/lib/strategic-handoff.mjs +1 -1
  132. package/template/scripts/lib/task-package.mjs +7 -0
  133. package/template/scripts/sync-strategic-handoff-tools +3 -1
  134. package/template/scripts/verify-frontend-delivery +9 -0
  135. package/template/scripts/verify-frontend-delivery-scenarios +131 -0
  136. package/template/scripts/verify-frontend-implementation-evidence +2 -0
  137. package/template/skills-lock.json +11 -11
  138. package/template.manifest.json +43 -1
  139. package/template.snapshot.json +5 -5
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+
6
+ const { parseArgs } = require("../cli/args");
7
+ const { promptForMissingOptions } = require("../cli/prompts");
8
+ const { printHelp, printVersion } = require("../cli/help");
9
+ const { pathKind, normalizeRelativePath } = require("../filesystem/path-utils");
10
+ const { applyManagedOperation } = require("../filesystem/apply-plan");
11
+ const { runInTransaction } = require("../filesystem/transaction-runner");
12
+ const { assertBundledFamily, assertTargetFamily } = require("../family-runtime");
13
+ const { assertTargetWorkingTreeWritable } = require("../validation/security");
14
+ const {
15
+ PACKAGE_ROOT,
16
+ PACKAGE_MANIFEST,
17
+ BUNDLED_TEMPLATE_ROOT,
18
+ TEMPLATE_METADATA_FILENAME,
19
+ readTemplateSnapshot,
20
+ buildDesiredManagedOperations,
21
+ buildMetadata,
22
+ writeTemplateMetadata,
23
+ } = require("../template/instance-runtime");
24
+ const {
25
+ applyOwnershipToOperations,
26
+ assertWritableTemplateOperations,
27
+ } = require("../template/ownership-runtime");
28
+ const {
29
+ initializeGitRepository,
30
+ verifyGeneratedInit,
31
+ } = require("../template/verification-runtime");
32
+
33
+ function assertRequiredOptions(options) {
34
+ if (!options.projectName) {
35
+ throw new Error("init 需要 --project-name,项目名称不能为空");
36
+ }
37
+ if (!options.businessDomain) {
38
+ throw new Error("init 需要 --business-domain,业务领域不能为空");
39
+ }
40
+ if (!options.targetDir) {
41
+ throw new Error("init 需要 --target-dir,目标目录不能为空");
42
+ }
43
+ }
44
+
45
+ function normalizeTargetDir(targetDir) {
46
+ return path.resolve(process.cwd(), targetDir);
47
+ }
48
+
49
+ function isInsideTemplateRoot(targetDir) {
50
+ const relativePath = path.relative(BUNDLED_TEMPLATE_ROOT, targetDir);
51
+ return (
52
+ relativePath === "" ||
53
+ (!relativePath.startsWith("..") && !path.isAbsolute(relativePath))
54
+ );
55
+ }
56
+
57
+ function inspectTargetDir(targetDir, force) {
58
+ if (isInsideTemplateRoot(targetDir)) {
59
+ throw new Error("目标目录不能位于模板源仓库内部");
60
+ }
61
+
62
+ assertTargetWorkingTreeWritable(targetDir, {
63
+ force,
64
+ packageRoot: PACKAGE_ROOT,
65
+ });
66
+
67
+ if (!fs.existsSync(targetDir)) {
68
+ return { exists: false, clearEntries: false };
69
+ }
70
+ if (pathKind(targetDir) !== "directory") {
71
+ throw new Error("目标目录必须是目录");
72
+ }
73
+
74
+ const entries = fs.readdirSync(targetDir);
75
+ if (entries.length > 0 && !force) {
76
+ throw new Error("目标目录非空,当前主路径不支持覆盖已有内容");
77
+ }
78
+
79
+ return { exists: true, clearEntries: entries.length > 0 && force };
80
+ }
81
+
82
+ function prepareTargetDir(targetDir, targetState) {
83
+ if (!targetState.exists) {
84
+ fs.mkdirSync(targetDir, { recursive: true });
85
+ return;
86
+ }
87
+ if (!targetState.clearEntries) return;
88
+
89
+ for (const entry of fs.readdirSync(targetDir)) {
90
+ fs.rmSync(path.join(targetDir, entry), { recursive: true, force: true });
91
+ }
92
+ }
93
+
94
+ function parentDirectoryOperations(desiredOperations, targetDir) {
95
+ const directories = new Set();
96
+ for (const operation of desiredOperations) {
97
+ const parts = normalizeRelativePath(operation.relativePath).split("/").filter(Boolean);
98
+ parts.pop();
99
+ let current = "";
100
+ for (const part of parts) {
101
+ current = current ? `${current}/${part}` : part;
102
+ directories.add(current);
103
+ }
104
+ }
105
+
106
+ return [...directories]
107
+ .sort((left, right) => {
108
+ const depth = left.split("/").length - right.split("/").length;
109
+ return depth || left.localeCompare(right);
110
+ })
111
+ .map((relativePath) => ({
112
+ type: "mkdir",
113
+ relativePath,
114
+ targetPath: path.join(targetDir, ...relativePath.split("/")),
115
+ }));
116
+ }
117
+
118
+ async function runInit(argv = []) {
119
+ const options = parseArgs(argv);
120
+ if (options.help) {
121
+ printHelp(PACKAGE_MANIFEST.version);
122
+ return;
123
+ }
124
+ if (options.version) {
125
+ printVersion(PACKAGE_MANIFEST.version);
126
+ return;
127
+ }
128
+
129
+ const promptedOptions = await promptForMissingOptions(options);
130
+ assertRequiredOptions(promptedOptions);
131
+ const snapshot = readTemplateSnapshot();
132
+ assertBundledFamily(snapshot);
133
+
134
+ const targetDir = normalizeTargetDir(promptedOptions.targetDir);
135
+ assertTargetFamily(targetDir);
136
+ const targetState = inspectTargetDir(targetDir, promptedOptions.force);
137
+ const desiredOperations = applyOwnershipToOperations(
138
+ buildDesiredManagedOperations(targetDir, promptedOptions, "init"),
139
+ );
140
+ assertWritableTemplateOperations(desiredOperations);
141
+ const directoryOperations = parentDirectoryOperations(desiredOperations, targetDir);
142
+
143
+ if (promptedOptions.dryRun) {
144
+ console.log("dry-run 预览");
145
+ console.log(`输出目录:${targetDir}`);
146
+ for (const operation of [...directoryOperations, ...desiredOperations]) {
147
+ const ownership = operation.ownership ? ` [${operation.ownership}]` : "";
148
+ console.log(`${operation.type}: ${operation.relativePath}${ownership}`);
149
+ }
150
+ return;
151
+ }
152
+
153
+ prepareTargetDir(targetDir, targetState);
154
+
155
+ runInTransaction({
156
+ targetDir,
157
+ operation: "init",
158
+ affectedPaths: [
159
+ ...desiredOperations.map((operation) => operation.relativePath),
160
+ TEMPLATE_METADATA_FILENAME,
161
+ ],
162
+ execute: (transaction) => {
163
+ for (const operation of desiredOperations) {
164
+ applyManagedOperation(operation, transaction);
165
+ }
166
+ verifyGeneratedInit(targetDir);
167
+ writeTemplateMetadata(
168
+ targetDir,
169
+ buildMetadata(promptedOptions, desiredOperations),
170
+ transaction,
171
+ );
172
+ },
173
+ });
174
+
175
+ if (promptedOptions.gitInit) {
176
+ initializeGitRepository(targetDir);
177
+ }
178
+
179
+ console.log("初始化完成");
180
+ console.log(`输出目录:${targetDir}`);
181
+ console.log("下一步建议:");
182
+ console.log(`1. cd ${targetDir}`);
183
+ console.log(
184
+ promptedOptions.gitInit
185
+ ? "2. 运行 git status 检查初始化结果"
186
+ : "2. 如需版本管理,可执行 git init",
187
+ );
188
+ console.log("3. 检查 AGENTS.md、README 和 docs 目录是否符合预期");
189
+ }
190
+
191
+ module.exports = {
192
+ runInit,
193
+ };
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+
3
+ const { parseArgs } = require("../cli/args");
4
+ const { renderPlanText } = require("../cli/plan-output");
5
+ const { serializePlan } = require("../template/plan-schema");
6
+ const {
7
+ buildSyncContext,
8
+ applySyncContext,
9
+ } = require("../api/_sync-service");
10
+
11
+ function shellQuote(value) {
12
+ return `'${String(value).replaceAll("'", "'\\''")}'`;
13
+ }
14
+
15
+ function printLimitedOperations(operations, formatter, limit = 40) {
16
+ const prioritized = [...operations].sort((left, right) => {
17
+ const leftPath = typeof left === "string" ? left : left.relativePath;
18
+ const rightPath = typeof right === "string" ? right : right.relativePath;
19
+ const leftIsRoot = !leftPath.includes("/");
20
+ const rightIsRoot = !rightPath.includes("/");
21
+ if (leftIsRoot !== rightIsRoot) return leftIsRoot ? -1 : 1;
22
+ return leftPath.localeCompare(rightPath);
23
+ });
24
+
25
+ for (const operation of prioritized.slice(0, limit)) {
26
+ console.log(formatter(operation));
27
+ }
28
+ if (operations.length > limit) {
29
+ console.log(
30
+ `... 其余 ${operations.length - limit} 项省略,可用 manifest / git diff 查看完整清单`,
31
+ );
32
+ }
33
+ }
34
+
35
+ function printMigrationPlan(migrationPlan) {
36
+ for (const item of migrationPlan.legacy || []) {
37
+ const destination = item.to ? ` -> ${item.to}` : "";
38
+ console.log(`legacy: ${item.action} ${item.from}${destination}`);
39
+ }
40
+ for (const item of migrationPlan.unsafe || []) {
41
+ console.log(`unsafe: ${item.path} (${item.reason})`);
42
+ }
43
+ for (const item of migrationPlan.conflicts || []) {
44
+ console.log(`conflict: ${item.from} -> ${item.to} (${item.reason})`);
45
+ }
46
+ }
47
+
48
+ function printSyncDryRun(context) {
49
+ const { targetDir, metadata, syncPlan, migrationPlan, plan } = context;
50
+ console.log("sync dry-run 预览");
51
+ console.log(`目标目录:${targetDir}`);
52
+ console.log(
53
+ `模板版本:${metadata.templateVersion || metadata.cliVersion || "unknown"} -> ${plan.template?.to || "unknown"}`,
54
+ );
55
+ printLimitedOperations(
56
+ syncPlan.updated,
57
+ (operation) => `update: ${operation.relativePath}`,
58
+ );
59
+ printLimitedOperations(
60
+ syncPlan.added,
61
+ (operation) => `add: ${operation.relativePath}`,
62
+ );
63
+ printLimitedOperations(
64
+ syncPlan.skipped,
65
+ (operation) => `conflict: ${operation.relativePath} (${operation.reason})`,
66
+ );
67
+ printLimitedOperations(
68
+ syncPlan.unsafe,
69
+ (operation) => `unsafe: ${operation.relativePath} (${operation.reason})`,
70
+ );
71
+ printLimitedOperations(
72
+ syncPlan.removed,
73
+ (relativePath) => `remove-report: ${relativePath}`,
74
+ );
75
+ console.log(`unchanged: ${syncPlan.unchanged.length}`);
76
+ printMigrationPlan(migrationPlan);
77
+ }
78
+
79
+ function runSync(argv = []) {
80
+ const options = parseArgs(argv);
81
+ const context = buildSyncContext({
82
+ targetDir: options.targetDir || ".",
83
+ force: Boolean(options.force),
84
+ });
85
+
86
+ if (options.json) {
87
+ process.stdout.write(serializePlan(context.plan));
88
+ return context.plan;
89
+ }
90
+
91
+ if (options.plan) {
92
+ process.stdout.write(renderPlanText(context.plan));
93
+ return context.plan;
94
+ }
95
+
96
+ if (context.warning) console.log(context.warning);
97
+
98
+ if (options.dryRun) {
99
+ printSyncDryRun(context);
100
+ return context.plan;
101
+ }
102
+
103
+ if (context.migrationPlan.unsafe.length > 0 || context.syncPlan.unsafe.length > 0) {
104
+ printSyncDryRun(context);
105
+ } else if (context.migrationPlan.conflicts.length > 0) {
106
+ printMigrationPlan(context.migrationPlan);
107
+ }
108
+
109
+ const result = applySyncContext(context, { force: Boolean(options.force) });
110
+
111
+ console.log("同步完成");
112
+ console.log(
113
+ `模板版本:${context.metadata.templateVersion || context.metadata.cliVersion || "unknown"} -> ${context.plan.template?.to || "unknown"}`,
114
+ );
115
+ console.log(`自动更新:${result.stats.updated}`);
116
+ console.log(`新增文件:${result.stats.added}`);
117
+ console.log(`跳过文件:${result.stats.skipped}`);
118
+ console.log(`删除差异:${result.stats.removed}`);
119
+
120
+ if (result.skipped.length > 0) {
121
+ console.log("本地已修改,已跳过:");
122
+ for (const item of result.skipped) {
123
+ console.log(`- ${item.path}: ${item.reason}`);
124
+ }
125
+ }
126
+ if (result.removed.length > 0) {
127
+ console.log("模板已移除但未自动删除:");
128
+ for (const relativePath of result.removed) {
129
+ console.log(`- ${relativePath}`);
130
+ }
131
+ }
132
+ if (result.backupPath) {
133
+ console.log(`备份目录:${result.backupPath}`);
134
+ console.log(`清理命令:rm -rf ${shellQuote(result.backupPath)}`);
135
+ }
136
+
137
+ console.log("下一步建议:");
138
+ console.log("1. 运行 git diff 或 git status 检查同步结果");
139
+ console.log("2. 人工处理被跳过文件和删除差异(如有)");
140
+ console.log("3. 确认无误后提交本次模板同步结果");
141
+ return result;
142
+ }
143
+
144
+ module.exports = {
145
+ runSync,
146
+ };
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+
3
+ const { runUpdate } = require("../self-update");
4
+
5
+ function runUpdateCommand(argv = [], context) {
6
+ return runUpdate(argv, {
7
+ packageRoot: context.packageRoot,
8
+ currentVersion: context.currentVersion,
9
+ });
10
+ }
11
+
12
+ module.exports = {
13
+ runUpdateCommand,
14
+ };
@@ -0,0 +1,45 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/iloveZzz/create-yss-spec/schemas/apply-result-v1.json",
4
+ "title": "create-yss-spec Apply Result v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "operation", "targetDir", "backupPath", "template", "stats", "skipped", "removed"],
8
+ "properties": {
9
+ "schemaVersion": { "const": 1 },
10
+ "operation": { "const": "sync" },
11
+ "targetDir": { "type": "string", "minLength": 1 },
12
+ "backupPath": { "type": ["string", "null"] },
13
+ "template": { "type": ["object", "null"], "additionalProperties": true },
14
+ "stats": {
15
+ "type": "object",
16
+ "additionalProperties": false,
17
+ "required": ["updated", "added", "skipped", "removed", "forceApplied"],
18
+ "properties": {
19
+ "updated": { "type": "integer", "minimum": 0 },
20
+ "added": { "type": "integer", "minimum": 0 },
21
+ "skipped": { "type": "integer", "minimum": 0 },
22
+ "removed": { "type": "integer", "minimum": 0 },
23
+ "forceApplied": { "type": "integer", "minimum": 0 }
24
+ }
25
+ },
26
+ "skipped": {
27
+ "type": "array",
28
+ "items": {
29
+ "type": "object",
30
+ "additionalProperties": false,
31
+ "required": ["path", "reason", "ownership", "mergeStrategy"],
32
+ "properties": {
33
+ "path": { "type": "string", "minLength": 1 },
34
+ "reason": { "type": "string", "minLength": 1 },
35
+ "ownership": { "type": ["string", "null"] },
36
+ "mergeStrategy": { "type": ["string", "null"] }
37
+ }
38
+ }
39
+ },
40
+ "removed": {
41
+ "type": "array",
42
+ "items": { "type": "string", "minLength": 1 }
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/iloveZzz/create-yss-spec/schemas/customization-policy-v1.json",
4
+ "title": "create-yss-spec Customization Policy v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["version", "defaultStrategy", "rules"],
8
+ "properties": {
9
+ "version": { "const": 1 },
10
+ "defaultStrategy": {
11
+ "enum": ["replace-with-force", "manual"]
12
+ },
13
+ "rules": {
14
+ "type": "array",
15
+ "items": {
16
+ "type": "object",
17
+ "additionalProperties": false,
18
+ "required": ["pattern", "strategy"],
19
+ "properties": {
20
+ "pattern": { "type": "string", "minLength": 1 },
21
+ "strategy": {
22
+ "enum": ["replace-with-force", "manual"]
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/iloveZzz/create-yss-spec/schemas/doctor-report-v1.json",
4
+ "title": "create-yss-spec Doctor Report v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "operation", "targetDir", "cliVersion", "ok", "checks"],
8
+ "properties": {
9
+ "schemaVersion": { "const": 1 },
10
+ "operation": { "const": "doctor" },
11
+ "targetDir": { "type": "string", "minLength": 1 },
12
+ "cliVersion": { "type": "string", "minLength": 1 },
13
+ "ok": { "type": "boolean" },
14
+ "checks": {
15
+ "type": "array",
16
+ "items": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "required": ["name", "status", "detail"],
20
+ "properties": {
21
+ "name": { "type": "string", "minLength": 1 },
22
+ "status": { "enum": ["ok", "warning", "error"] },
23
+ "detail": { "type": "string", "minLength": 1 },
24
+ "data": {}
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/iloveZzz/create-yss-spec/schemas/error-envelope-v1.json",
4
+ "title": "create-yss-spec Error Envelope v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "ok", "error"],
8
+ "properties": {
9
+ "schemaVersion": { "const": 1 },
10
+ "ok": { "const": false },
11
+ "error": {
12
+ "type": "object",
13
+ "additionalProperties": false,
14
+ "required": ["code", "message"],
15
+ "properties": {
16
+ "code": {
17
+ "type": "string",
18
+ "pattern": "^YSS_[A-Z0-9_]+$"
19
+ },
20
+ "message": { "type": "string", "minLength": 1 }
21
+ }
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/iloveZzz/create-yss-spec/schemas/generator-policy-v1.json",
4
+ "title": "create-yss-spec Generator Policy v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["version", "rules"],
8
+ "properties": {
9
+ "version": { "const": 1 },
10
+ "rules": {
11
+ "type": "array",
12
+ "items": {
13
+ "type": "object",
14
+ "additionalProperties": false,
15
+ "required": ["pattern", "generatorId", "generatorVersion"],
16
+ "properties": {
17
+ "pattern": { "type": "string", "minLength": 1 },
18
+ "generatorId": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
19
+ "generatorVersion": { "type": "integer", "minimum": 1 }
20
+ }
21
+ }
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/iloveZzz/create-yss-spec/schemas/ownership-policy-v1.json",
4
+ "title": "create-yss-spec Ownership Policy v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["version", "default", "rules"],
8
+ "properties": {
9
+ "version": { "const": 1 },
10
+ "default": {
11
+ "enum": [
12
+ "managed",
13
+ "managed-customizable",
14
+ "generated",
15
+ "user-owned",
16
+ "protected"
17
+ ]
18
+ },
19
+ "rules": {
20
+ "type": "array",
21
+ "items": {
22
+ "type": "object",
23
+ "additionalProperties": false,
24
+ "required": ["pattern", "ownership"],
25
+ "properties": {
26
+ "pattern": { "type": "string", "minLength": 1 },
27
+ "ownership": {
28
+ "enum": [
29
+ "managed",
30
+ "managed-customizable",
31
+ "generated",
32
+ "user-owned",
33
+ "protected"
34
+ ]
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,115 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/iloveZzz/create-yss-spec/schemas/plan-v1.json",
4
+ "title": "create-yss-spec Plan Schema v1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schemaVersion",
9
+ "operation",
10
+ "targetDir",
11
+ "template",
12
+ "changes",
13
+ "conflicts",
14
+ "unsafe",
15
+ "warnings",
16
+ "blocked",
17
+ "stats",
18
+ "migration"
19
+ ],
20
+ "$defs": {
21
+ "ownership": {
22
+ "enum": [
23
+ "managed",
24
+ "managed-customizable",
25
+ "generated",
26
+ "user-owned",
27
+ "protected"
28
+ ]
29
+ },
30
+ "mergeStrategy": {
31
+ "enum": ["replace-with-force", "manual"]
32
+ },
33
+ "generatorId": {
34
+ "type": "string",
35
+ "pattern": "^[a-z][a-z0-9-]*$"
36
+ },
37
+ "generatorVersion": {
38
+ "type": "integer",
39
+ "minimum": 1
40
+ }
41
+ },
42
+ "properties": {
43
+ "schemaVersion": { "const": 1 },
44
+ "operation": { "type": "string", "minLength": 1 },
45
+ "targetDir": { "type": ["string", "null"] },
46
+ "template": {
47
+ "type": ["object", "null"],
48
+ "additionalProperties": true
49
+ },
50
+ "changes": {
51
+ "type": "array",
52
+ "items": {
53
+ "type": "object",
54
+ "required": ["action", "path"],
55
+ "properties": {
56
+ "action": { "type": "string", "minLength": 1 },
57
+ "path": { "type": "string", "minLength": 1 },
58
+ "ownership": { "$ref": "#/$defs/ownership" },
59
+ "mergeStrategy": { "$ref": "#/$defs/mergeStrategy" },
60
+ "generatorId": { "$ref": "#/$defs/generatorId" },
61
+ "generatorVersion": { "$ref": "#/$defs/generatorVersion" }
62
+ },
63
+ "additionalProperties": true
64
+ }
65
+ },
66
+ "conflicts": {
67
+ "type": "array",
68
+ "items": {
69
+ "type": "object",
70
+ "required": ["path", "reason"],
71
+ "properties": {
72
+ "path": { "type": "string", "minLength": 1 },
73
+ "reason": { "type": "string" },
74
+ "forceable": { "type": "boolean" },
75
+ "source": { "type": "string" },
76
+ "ownership": { "$ref": "#/$defs/ownership" },
77
+ "mergeStrategy": { "$ref": "#/$defs/mergeStrategy" },
78
+ "generatorId": { "$ref": "#/$defs/generatorId" },
79
+ "generatorVersion": { "$ref": "#/$defs/generatorVersion" }
80
+ },
81
+ "additionalProperties": true
82
+ }
83
+ },
84
+ "unsafe": {
85
+ "type": "array",
86
+ "items": {
87
+ "type": "object",
88
+ "required": ["path", "reason"],
89
+ "properties": {
90
+ "path": { "type": "string", "minLength": 1 },
91
+ "reason": { "type": "string" },
92
+ "source": { "type": "string" },
93
+ "ownership": { "$ref": "#/$defs/ownership" },
94
+ "mergeStrategy": { "$ref": "#/$defs/mergeStrategy" },
95
+ "generatorId": { "$ref": "#/$defs/generatorId" },
96
+ "generatorVersion": { "$ref": "#/$defs/generatorVersion" }
97
+ },
98
+ "additionalProperties": true
99
+ }
100
+ },
101
+ "warnings": {
102
+ "type": "array",
103
+ "items": { "type": "string" }
104
+ },
105
+ "blocked": { "type": "boolean" },
106
+ "stats": {
107
+ "type": "object",
108
+ "additionalProperties": { "type": "number" }
109
+ },
110
+ "migration": {
111
+ "type": ["object", "null"],
112
+ "additionalProperties": true
113
+ }
114
+ }
115
+ }