@birdie_moblie/open_spec 2.1.7 → 2.2.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 (39) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +1 -1
  4. package/dist/cli/commands/ext.js +140 -21
  5. package/dist/cli/commands/init.js +22 -12
  6. package/dist/config/load.d.ts +4 -0
  7. package/dist/config/load.js +23 -5
  8. package/dist/config/preset-repo-tools.d.ts +36 -0
  9. package/dist/config/preset-repo-tools.js +114 -0
  10. package/dist/config/preset-repo.d.ts +164 -0
  11. package/dist/config/preset-repo.js +180 -0
  12. package/dist/config/preset-use.d.ts +79 -0
  13. package/dist/config/preset-use.js +282 -0
  14. package/dist/config/presets.d.ts +38 -113
  15. package/dist/config/presets.js +159 -84
  16. package/dist/config/schema.d.ts +136 -9
  17. package/dist/config/schema.js +30 -2
  18. package/dist/core/source-operations.js +6 -1
  19. package/dist/index.d.ts +15 -3
  20. package/dist/index.js +22 -28
  21. package/dist/marketplace/registry.d.ts +2 -2
  22. package/dist/marketplace/registry.js +6 -55
  23. package/dist/marketplace/upgrade.js +5 -3
  24. package/dist/shared/fs.d.ts +2 -0
  25. package/dist/shared/fs.js +6 -2
  26. package/dist/shared/git-snapshot.d.ts +18 -0
  27. package/dist/shared/git-snapshot.js +75 -0
  28. package/dist/shared/pkg.js +1 -1
  29. package/docs/getting-started.md +1 -1
  30. package/docs/guides/configuration.md +9 -2
  31. package/docs/guides/plugin-migration.md +5 -5
  32. package/docs/guides/ui-conventions-template.md +2 -2
  33. package/package.json +1 -2
  34. package/plugin.json +1 -1
  35. package/presets/backend-service.yaml +0 -19
  36. package/presets/flutter-mobile/plugin-hooks.json +0 -68
  37. package/presets/flutter-mobile/ui-conventions.md +0 -122
  38. package/presets/flutter-mobile.yaml +0 -205
  39. package/presets/web-product.yaml +0 -23
@@ -0,0 +1,164 @@
1
+ import { z } from 'zod';
2
+ import { type PresetBaseline } from './presets.js';
3
+ import { type PresetReference, type ProjectConfig } from './schema.js';
4
+ /** preset 仓库中每个 preset 占一个目录:`<id>/preset.yaml` 加它引用的模板文件。 */
5
+ export declare const REPO_PRESET_FILE = "preset.yaml";
6
+ export declare const RepoPresetSchema: z.ZodObject<{
7
+ schemaVersion: z.ZodLiteral<"openspec.team-preset.v2">;
8
+ id: z.ZodString;
9
+ title: z.ZodString;
10
+ description: z.ZodOptional<z.ZodString>;
11
+ requires: z.ZodOptional<z.ZodObject<{
12
+ openspec: z.ZodString;
13
+ }, z.core.$strict>>;
14
+ marketplaces: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
15
+ name: z.ZodString;
16
+ repo: z.ZodString;
17
+ ref: z.ZodString;
18
+ }, z.core.$strict>>>>;
19
+ plugins: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
20
+ name: z.ZodString;
21
+ marketplace: z.ZodString;
22
+ minVersion: z.ZodOptional<z.ZodString>;
23
+ }, z.core.$strict>>>>;
24
+ configPatch: z.ZodOptional<z.ZodObject<{
25
+ verify: z.ZodOptional<z.ZodOptional<z.ZodObject<{
26
+ reviewScope: z.ZodOptional<z.ZodObject<{
27
+ includeDirs: z.ZodOptional<z.ZodArray<z.ZodString>>;
28
+ excludeDirs: z.ZodOptional<z.ZodArray<z.ZodString>>;
29
+ }, z.core.$strict>>;
30
+ failurePolicy: z.ZodOptional<z.ZodObject<{
31
+ failOnHookFailure: z.ZodOptional<z.ZodBoolean>;
32
+ failOnRequiredCommandFailure: z.ZodOptional<z.ZodBoolean>;
33
+ }, z.core.$strict>>;
34
+ }, z.core.$strict>>>;
35
+ taskCategories: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodObject<{
36
+ notes: z.ZodOptional<z.ZodString>;
37
+ }, z.core.$strict>>>>>;
38
+ schema: z.ZodOptional<z.ZodLiteral<"spec-product">>;
39
+ hooks: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
40
+ id: z.ZodString;
41
+ stage: z.ZodEnum<{
42
+ collect: "collect";
43
+ parse: "parse";
44
+ tech: "tech";
45
+ plan: "plan";
46
+ execute: "execute";
47
+ verify: "verify";
48
+ }>;
49
+ type: z.ZodOptional<z.ZodEnum<{
50
+ command: "command";
51
+ skill: "skill";
52
+ notes: "notes";
53
+ file: "file";
54
+ check: "check";
55
+ }>>;
56
+ capability: z.ZodOptional<z.ZodEnum<{
57
+ requirements: "requirements";
58
+ interfaces: "interfaces";
59
+ design: "design";
60
+ }>>;
61
+ use: z.ZodOptional<z.ZodString>;
62
+ operation: z.ZodOptional<z.ZodLiteral<"preview">>;
63
+ input: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
64
+ inputFiles: z.ZodOptional<z.ZodArray<z.ZodString>>;
65
+ name: z.ZodOptional<z.ZodString>;
66
+ notes: z.ZodOptional<z.ZodString>;
67
+ taskCategories: z.ZodOptional<z.ZodArray<z.ZodString>>;
68
+ command: z.ZodOptional<z.ZodString>;
69
+ target: z.ZodOptional<z.ZodEnum<{
70
+ project: "project";
71
+ inScopeChangedFiles: "inScopeChangedFiles";
72
+ }>>;
73
+ include: z.ZodOptional<z.ZodArray<z.ZodString>>;
74
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
75
+ allowEmpty: z.ZodOptional<z.ZodBoolean>;
76
+ required: z.ZodOptional<z.ZodBoolean>;
77
+ purpose: z.ZodOptional<z.ZodString>;
78
+ path: z.ZodOptional<z.ZodString>;
79
+ category: z.ZodOptional<z.ZodString>;
80
+ description: z.ZodOptional<z.ZodString>;
81
+ }, z.core.$strict>>>>;
82
+ plugins: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
83
+ name: z.ZodString;
84
+ marketplace: z.ZodString;
85
+ minVersion: z.ZodOptional<z.ZodString>;
86
+ }, z.core.$strict>>>>;
87
+ marketplaces: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodObject<{
88
+ name: z.ZodString;
89
+ repo: z.ZodString;
90
+ ref: z.ZodString;
91
+ }, z.core.$strict>>>>;
92
+ tools: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodEnum<{
93
+ claude: "claude";
94
+ codex: "codex";
95
+ cursor: "cursor";
96
+ }>>>>;
97
+ }, z.core.$strict>>;
98
+ scaffold: z.ZodOptional<z.ZodArray<z.ZodObject<{
99
+ path: z.ZodString;
100
+ template: z.ZodString;
101
+ description: z.ZodOptional<z.ZodString>;
102
+ }, z.core.$strict>>>;
103
+ notes: z.ZodOptional<z.ZodArray<z.ZodString>>;
104
+ warnings: z.ZodOptional<z.ZodArray<z.ZodString>>;
105
+ }, z.core.$strict>;
106
+ export type RepoPreset = z.infer<typeof RepoPresetSchema>;
107
+ declare const PresetLockSchema: z.ZodObject<{
108
+ version: z.ZodLiteral<1>;
109
+ repo: z.ZodString;
110
+ ref: z.ZodString;
111
+ id: z.ZodString;
112
+ resolvedSha: z.ZodString;
113
+ digest: z.ZodString;
114
+ }, z.core.$strict>;
115
+ export type PresetLock = z.infer<typeof PresetLockSchema>;
116
+ export declare function presetCacheRoot(): string;
117
+ /** 缓存按仓库与提交区分;目录名带仓库地址摘要,避免同名仓库互相覆盖。锁里不存本机路径,成员之间可共享。 */
118
+ export declare function presetCacheDir(repo: string, resolvedSha: string): string;
119
+ export declare function presetLockPath(projectRoot: string): string;
120
+ export declare function readPresetLock(projectRoot: string): PresetLock | null;
121
+ export declare function writePresetLock(projectRoot: string, lock: PresetLock): void;
122
+ /** 拉取仓库在不可变 ref 上的快照;所有读取 preset 仓库的命令都经过这里,ref 在此统一校验。 */
123
+ export declare function fetchPresetRepo(repo: string, ref: string): {
124
+ resolvedSha: string;
125
+ cachePath: string;
126
+ digest: string;
127
+ };
128
+ /** 读取快照中的一个 preset,并检查它要求的 OpenSpec 版本。 */
129
+ export declare function readRepoPreset(root: string, id: string): RepoPreset;
130
+ export declare function presetBaseline(preset: RepoPreset): PresetBaseline;
131
+ /**
132
+ * 项目引用的 preset 快照目录:锁必须与配置引用一致,缓存必须存在且摘要与锁相同。
133
+ * 运行时只读缓存、不联网;缺失时提示用 init 补齐。
134
+ */
135
+ export declare function presetRootForProject(projectRoot: string, reference: PresetReference): {
136
+ root: string;
137
+ lock: PresetLock;
138
+ };
139
+ /** loadConfig 使用的基线:未引用 preset 时为 undefined。 */
140
+ export declare function loadPresetBaseline(projectRoot: string, layer: ProjectConfig): PresetBaseline | undefined;
141
+ /**
142
+ * init 用:让缓存与锁对齐。锁与配置一致时,已缓存则不联网、按锁核对摘要(成员离线也能 init),
143
+ * 未缓存则按锁里的 SHA 补拉并核对,保证成员拿到同一份内容;没有锁或锁已过期时按配置 ref 重新解析并写锁。
144
+ */
145
+ export declare function syncPresetCache(projectRoot: string, reference: PresetReference): PresetLock;
146
+ /** doctor 用:不抛错,返回检查结果。 */
147
+ export declare function inspectPreset(projectRoot: string, reference: PresetReference): {
148
+ id: string;
149
+ repo: string;
150
+ ref: string;
151
+ ok: boolean;
152
+ code?: string;
153
+ message?: string;
154
+ resolvedSha?: string;
155
+ digest?: string;
156
+ };
157
+ /** 列出快照中的全部 preset:每个含 preset.yaml 的顶层目录一项,按 id 排序。 */
158
+ export declare function listRepoPresets(root: string): Array<{
159
+ id: string;
160
+ title: string;
161
+ description?: string;
162
+ }>;
163
+ export {};
164
+ //# sourceMappingURL=preset-repo.d.ts.map
@@ -0,0 +1,180 @@
1
+ import path from 'node:path';
2
+ import { parse as parseYaml } from 'yaml';
3
+ import { z } from 'zod';
4
+ import { exists, listDirs, readJson, readText, writeJson } from '../shared/fs.js';
5
+ import { digestDirectory, sha256 } from '../shared/hash.js';
6
+ import { AppError } from '../shared/errors.js';
7
+ import { assertPathToken, resolveInside } from '../shared/paths.js';
8
+ import { compareVersions, VERSION } from '../shared/version.js';
9
+ import { openspecHome } from '../marketplace/adapters.js';
10
+ import { isImmutableRef, snapshotGitRef } from '../shared/git-snapshot.js';
11
+ import { ScaffoldEntrySchema } from './presets.js';
12
+ import { PluginMinVersionSchema, ProjectConfigPatchSchema } from './schema.js';
13
+ /** preset 仓库中每个 preset 占一个目录:`<id>/preset.yaml` 加它引用的模板文件。 */
14
+ export const REPO_PRESET_FILE = 'preset.yaml';
15
+ export const RepoPresetSchema = z.object({
16
+ schemaVersion: z.literal('openspec.team-preset.v2'),
17
+ id: z.string().min(1),
18
+ title: z.string().min(1),
19
+ description: z.string().optional(),
20
+ /** 需要的最低 OpenSpec 版本;版本号本身以仓库 tag 为准,preset 文件不再维护。 */
21
+ requires: z.object({ openspec: PluginMinVersionSchema }).strict().optional(),
22
+ marketplaces: ProjectConfigPatchSchema.shape.marketplaces,
23
+ plugins: ProjectConfigPatchSchema.shape.plugins,
24
+ configPatch: ProjectConfigPatchSchema.optional(),
25
+ scaffold: z.array(ScaffoldEntrySchema).optional(),
26
+ /** 引用时展示给项目维护者的说明与提醒 */
27
+ notes: z.array(z.string()).optional(),
28
+ warnings: z.array(z.string()).optional(),
29
+ }).strict();
30
+ const PresetLockSchema = z.object({
31
+ version: z.literal(1),
32
+ repo: z.string().min(1),
33
+ ref: z.string().min(1),
34
+ id: z.string().min(1),
35
+ resolvedSha: z.string().regex(/^[0-9a-f]{40}$/i),
36
+ digest: z.string().regex(/^[0-9a-f]{64}$/),
37
+ }).strict();
38
+ export function presetCacheRoot() {
39
+ return resolveInside(openspecHome(), 'presets', 'preset_cache_outside_home');
40
+ }
41
+ /** 缓存按仓库与提交区分;目录名带仓库地址摘要,避免同名仓库互相覆盖。锁里不存本机路径,成员之间可共享。 */
42
+ export function presetCacheDir(repo, resolvedSha) {
43
+ const base = (repo.split(/[/:]/).pop() ?? 'preset').replace(/\.git$/, '') || 'preset';
44
+ const key = `${base}-${sha256(repo).slice(0, 12)}`;
45
+ assertPathToken(key, 'preset repo');
46
+ assertPathToken(resolvedSha, 'preset revision');
47
+ return resolveInside(presetCacheRoot(), path.join(key, resolvedSha), 'preset_cache_outside_home');
48
+ }
49
+ export function presetLockPath(projectRoot) {
50
+ return resolveInside(projectRoot, 'openspec/preset-lock.json', 'preset_lock_outside_project');
51
+ }
52
+ export function readPresetLock(projectRoot) {
53
+ const file = presetLockPath(projectRoot);
54
+ if (!exists(file))
55
+ return null;
56
+ const parsed = PresetLockSchema.safeParse(readJson(file));
57
+ if (!parsed.success)
58
+ throw new AppError('invalid_preset_lock', 'preset 锁不合法', parsed.error.issues);
59
+ return parsed.data;
60
+ }
61
+ export function writePresetLock(projectRoot, lock) {
62
+ writeJson(presetLockPath(projectRoot), PresetLockSchema.parse(lock));
63
+ }
64
+ /** 拉取仓库在不可变 ref 上的快照;所有读取 preset 仓库的命令都经过这里,ref 在此统一校验。 */
65
+ export function fetchPresetRepo(repo, ref) {
66
+ if (!isImmutableRef(ref))
67
+ throw new AppError('mutable_preset_ref', `preset ref 必须是完整 Git SHA 或 refs/tags/<tag>: ${ref}`);
68
+ return snapshotGitRef({
69
+ repo, ref, label: 'preset', cacheRoot: presetCacheRoot(), cacheDir: (sha) => presetCacheDir(repo, sha),
70
+ });
71
+ }
72
+ /** 读取快照中的一个 preset,并检查它要求的 OpenSpec 版本。 */
73
+ export function readRepoPreset(root, id) {
74
+ assertPathToken(id, 'preset id');
75
+ const file = resolveInside(root, path.posix.join(id, REPO_PRESET_FILE), 'preset_path_outside_repo');
76
+ if (!exists(file))
77
+ throw new AppError('preset_not_in_repo', `preset 仓库中没有 ${id}(缺少 ${id}/${REPO_PRESET_FILE})`);
78
+ let raw;
79
+ try {
80
+ raw = parseYaml(readText(file));
81
+ }
82
+ catch (error) {
83
+ throw new AppError('invalid_preset', `preset ${id} 无法解析`, error instanceof Error ? error.message : String(error));
84
+ }
85
+ const parsed = RepoPresetSchema.safeParse(raw);
86
+ if (!parsed.success)
87
+ throw new AppError('invalid_preset', `preset ${id} 不合法`, parsed.error.issues);
88
+ if (parsed.data.id !== id)
89
+ throw new AppError('invalid_preset', `preset 目录 ${id} 与声明的 id ${parsed.data.id} 不一致`);
90
+ const required = parsed.data.requires?.openspec;
91
+ if (required && (compareVersions(VERSION, required) ?? -1) < 0) {
92
+ throw new AppError('preset_requires_newer_openspec', `preset ${id} 需要 OpenSpec ${required} 或更高,当前 ${VERSION}`);
93
+ }
94
+ return parsed.data;
95
+ }
96
+ export function presetBaseline(preset) {
97
+ return {
98
+ id: preset.id,
99
+ patch: {
100
+ ...preset.configPatch,
101
+ ...(preset.marketplaces ? { marketplaces: preset.marketplaces } : {}),
102
+ ...(preset.plugins ? { plugins: preset.plugins } : {}),
103
+ },
104
+ };
105
+ }
106
+ /**
107
+ * 项目引用的 preset 快照目录:锁必须与配置引用一致,缓存必须存在且摘要与锁相同。
108
+ * 运行时只读缓存、不联网;缺失时提示用 init 补齐。
109
+ */
110
+ export function presetRootForProject(projectRoot, reference) {
111
+ const lock = readPresetLock(projectRoot);
112
+ if (!lock) {
113
+ throw new AppError('preset_not_locked', `项目引用了 preset ${reference.id} 但没有 preset 锁;运行 openspec preset use ${reference.id} --repo <repo> --ref <ref>`);
114
+ }
115
+ if (lock.repo !== reference.repo || lock.ref !== reference.ref || lock.id !== reference.id) {
116
+ throw new AppError('preset_lock_mismatch', `config 引用的 preset 与 preset 锁不一致(锁为 ${lock.id}@${lock.ref});运行 openspec init 重新锁定`);
117
+ }
118
+ const root = presetCacheDir(lock.repo, lock.resolvedSha);
119
+ if (!exists(root)) {
120
+ throw new AppError('preset_cache_missing', `preset 缓存不存在: ${lock.id}@${lock.resolvedSha.slice(0, 12)};运行 openspec init 拉取`);
121
+ }
122
+ if (digestDirectory(root) !== lock.digest) {
123
+ throw new AppError('preset_digest_mismatch', `preset 缓存内容与锁不一致: ${lock.id}@${lock.resolvedSha.slice(0, 12)};删除该缓存后运行 openspec init 重新拉取`);
124
+ }
125
+ return { root, lock };
126
+ }
127
+ /** loadConfig 使用的基线:未引用 preset 时为 undefined。 */
128
+ export function loadPresetBaseline(projectRoot, layer) {
129
+ if (!layer.preset)
130
+ return undefined;
131
+ const { root } = presetRootForProject(projectRoot, layer.preset);
132
+ return presetBaseline(readRepoPreset(root, layer.preset.id));
133
+ }
134
+ /**
135
+ * init 用:让缓存与锁对齐。锁与配置一致时,已缓存则不联网、按锁核对摘要(成员离线也能 init),
136
+ * 未缓存则按锁里的 SHA 补拉并核对,保证成员拿到同一份内容;没有锁或锁已过期时按配置 ref 重新解析并写锁。
137
+ */
138
+ export function syncPresetCache(projectRoot, reference) {
139
+ const lock = readPresetLock(projectRoot);
140
+ if (lock && lock.repo === reference.repo && lock.ref === reference.ref && lock.id === reference.id) {
141
+ if (!exists(presetCacheDir(lock.repo, lock.resolvedSha))) {
142
+ const snapshot = fetchPresetRepo(lock.repo, lock.resolvedSha);
143
+ if (snapshot.digest !== lock.digest) {
144
+ throw new AppError('preset_digest_mismatch', `拉取到的 preset 内容与锁不一致: ${lock.id}@${lock.resolvedSha.slice(0, 12)}`);
145
+ }
146
+ }
147
+ readRepoPreset(presetRootForProject(projectRoot, reference).root, lock.id);
148
+ return lock;
149
+ }
150
+ const snapshot = fetchPresetRepo(reference.repo, reference.ref);
151
+ readRepoPreset(snapshot.cachePath, reference.id);
152
+ const next = { version: 1, ...reference, resolvedSha: snapshot.resolvedSha, digest: snapshot.digest };
153
+ writePresetLock(projectRoot, next);
154
+ return next;
155
+ }
156
+ /** doctor 用:不抛错,返回检查结果。 */
157
+ export function inspectPreset(projectRoot, reference) {
158
+ const base = { id: reference.id, repo: reference.repo, ref: reference.ref };
159
+ try {
160
+ const { root, lock } = presetRootForProject(projectRoot, reference);
161
+ readRepoPreset(root, reference.id);
162
+ return { ...base, ok: true, resolvedSha: lock.resolvedSha, digest: lock.digest };
163
+ }
164
+ catch (error) {
165
+ if (!(error instanceof AppError))
166
+ throw error;
167
+ return { ...base, ok: false, code: error.code, message: error.message };
168
+ }
169
+ }
170
+ /** 列出快照中的全部 preset:每个含 preset.yaml 的顶层目录一项,按 id 排序。 */
171
+ export function listRepoPresets(root) {
172
+ return listDirs(root)
173
+ .filter((id) => !id.startsWith('.') && exists(path.join(root, id, REPO_PRESET_FILE)))
174
+ .sort()
175
+ .map((id) => {
176
+ const preset = readRepoPreset(root, id);
177
+ return { id, title: preset.title, ...(preset.description ? { description: preset.description } : {}) };
178
+ });
179
+ }
180
+ //# sourceMappingURL=preset-repo.js.map
@@ -0,0 +1,79 @@
1
+ import { diffBaselines, type ScaffoldResult } from './presets.js';
2
+ import { type ProjectConfig } from './schema.js';
3
+ /**
4
+ * 让项目引用 preset 仓库中的一个 preset:拉取并锁定快照,写入引用,确认合成后的生效配置合法,再生成模板文件。
5
+ * 任何一步失败都按原字节还原 config 与锁。
6
+ */
7
+ export declare function usePreset(input: {
8
+ projectRoot: string;
9
+ id: string;
10
+ repo: string;
11
+ ref: string;
12
+ }): {
13
+ id: string;
14
+ repo: string;
15
+ ref: string;
16
+ resolvedSha: string;
17
+ digest: string;
18
+ scaffold: ScaffoldResult[];
19
+ notes: string[];
20
+ warnings: string[];
21
+ };
22
+ /**
23
+ * 把项目引用的 preset 升级到新 ref:列出基线的新增、修改与删除;按升级前后的生效配置,
24
+ * 生效值不变的条目即被项目层遮住(覆盖、禁用或更高的插件最低版本),单独列出。
25
+ * 只改 config 中的 ref 值并更新锁,确认生效配置合法后补齐新模板。任何一步失败都按原字节还原 config 与锁。
26
+ */
27
+ export declare function upgradePreset(input: {
28
+ projectRoot: string;
29
+ ref: string;
30
+ allowActiveChanges?: boolean;
31
+ }): {
32
+ id: string;
33
+ status: 'upgraded' | 'unchanged';
34
+ from: {
35
+ ref: string;
36
+ resolvedSha: string;
37
+ };
38
+ to: {
39
+ ref: string;
40
+ resolvedSha: string;
41
+ };
42
+ changes: ReturnType<typeof diffBaselines>;
43
+ shadowed: Array<{
44
+ section: string;
45
+ id: string;
46
+ }>;
47
+ scaffold: ScaffoldResult[];
48
+ };
49
+ /**
50
+ * 把拷贝式配置迁移为“引用 preset + 项目层”。迁移前后生效配置必须逐项一致(唯一例外:preset 提高的插件最低版本,
51
+ * 在结果中列出),否则中止且不写任何文件;
52
+ * 写入时替换 config(原注释不保留)、写新锁并删除旧的 preset-lock.yaml。dryRun 只返回结果。
53
+ */
54
+ export declare function migratePreset(input: {
55
+ projectRoot: string;
56
+ id: string;
57
+ repo: string;
58
+ ref: string;
59
+ dryRun?: boolean;
60
+ }): {
61
+ id: string;
62
+ ref: string;
63
+ resolvedSha: string;
64
+ written: boolean;
65
+ removedLegacyLock: boolean;
66
+ layer: ProjectConfig;
67
+ inherited: {
68
+ taskCategories: string[];
69
+ hooks: string[];
70
+ plugins: string[];
71
+ marketplaces: string[];
72
+ };
73
+ raisedMinVersions: Array<{
74
+ plugin: string;
75
+ from?: string;
76
+ to: string;
77
+ }>;
78
+ };
79
+ //# sourceMappingURL=preset-use.d.ts.map