flower-trellis 0.4.9 → 0.4.10

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "syncedAt": "2026-07-08T02:50:48.728Z",
2
+ "syncedAt": "2026-07-08T03:53:14.101Z",
3
3
  "syncedFrom": "vendor/skill-garden",
4
4
  "sourceCommit": "6ecfb1b46320d82aeb3e83442235f271d92aa398",
5
5
  "common": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flower-trellis",
3
- "version": "0.4.9",
3
+ "version": "0.4.10",
4
4
  "description": "一键安装/升级 Trellis 并自动融合 skill-garden 强化包(默认 Claude + agents)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -58,9 +58,9 @@
58
58
  "commit-and-tag-version": "^12.7.3"
59
59
  },
60
60
  "flowerReleaseNotes": {
61
- "version": "0.4.9",
61
+ "version": "0.4.10",
62
62
  "source": "CHANGELOG.md",
63
- "body": "### 🐛 修复 Bug Fixes\n\n* **flower:** 强化项目知识发现门禁 ([d21b17e](https://github.com/SilentFlower/flower-trellis/commit/d21b17e860d3b91bb5c69c3921620d60b49608d5))\n* **flower:** 恢复 in_progress 完成门禁 ([304f5fa](https://github.com/SilentFlower/flower-trellis/commit/304f5fadfab139638cfa9658f168448a1f26f9e6))",
63
+ "body": "### 🐛 修复 Bug Fixes\n\n* **flower:** 项目侧待更新提示会显示对应版本更新摘要 ([cc98c02](https://github.com/SilentFlower/flower-trellis/commit/cc98c021eb0536f693f50651854093a4795d9e93))",
64
64
  "truncated": false
65
65
  }
66
66
  }
@@ -119,6 +119,46 @@ function releaseNotesFromMetadata(metadata, range) {
119
119
  return buildReleaseNotesSummary(metadata?.releaseNotesByVersion, range);
120
120
  }
121
121
 
122
+ /**
123
+ * 安全执行 npm metadata 拉取。
124
+ *
125
+ * 默认 fetcher 已经吞掉网络错误;这里再兜底测试注入的 fetcher,确保 release notes
126
+ * 补拉失败不会破坏 self-check 主流程。
127
+ *
128
+ * @param {() => Promise<object|null>} fetchMetadata npm metadata 拉取函数
129
+ * @returns {Promise<object|null>} registry metadata,失败时为 null
130
+ */
131
+ async function safeFetchPackageUpdateMetadata(fetchMetadata) {
132
+ try {
133
+ return await fetchMetadata();
134
+ } catch {
135
+ return null;
136
+ }
137
+ }
138
+
139
+ /**
140
+ * 缓存命中但缺少摘要时,主动补拉 release notes。
141
+ *
142
+ * 这个补拉只服务当前 actionable 提示的摘要展示,不能把失败写成新的远程版本证据;
143
+ * 成功时也只写回 lastReleaseNotes,保持 lastRemote 仍只记录 dist-tags。
144
+ *
145
+ * @param {string} target 目标项目根
146
+ * @param {object|null} manifest 目标项目 manifest
147
+ * @param {boolean} writeCache 是否允许写缓存
148
+ * @param {object|null} range release notes 范围
149
+ * @param {() => Promise<object|null>} fetchMetadata npm metadata 拉取函数
150
+ * @returns {Promise<object|null>} release notes 摘要;范围有效但不可用时返回 unavailable 摘要
151
+ */
152
+ async function fetchMissingReleaseNotes(target, manifest, writeCache, range, fetchMetadata) {
153
+ if (!range) return null;
154
+ const metadata = await safeFetchPackageUpdateMetadata(fetchMetadata);
155
+ const releaseNotes = releaseNotesFromMetadata(metadata, range);
156
+ if (releaseNotes && !releaseNotes.unavailable && writeCache && manifest) {
157
+ writeUpdateCheck(target, { lastReleaseNotes: releaseNotes });
158
+ }
159
+ return releaseNotes;
160
+ }
161
+
122
162
  /** 检查目标目录 git 工作区是否 clean。 */
123
163
  function gitSafety(target) {
124
164
  const common = {
@@ -312,12 +352,15 @@ export function safetyState(target, status, command) {
312
352
  * 构建启动自更新检查结果。
313
353
  *
314
354
  * @param {string} target 目标项目根
315
- * @param {{writeCache?: boolean, forceRemote?: boolean}} options 检查选项
355
+ * @param {{writeCache?: boolean, forceRemote?: boolean, fetchMetadata?: () => Promise<object|null>}} options 检查选项
316
356
  * @returns {Promise<object>} 结构化检查结果
317
357
  */
318
358
  export async function buildSelfCheck(target, options = {}) {
319
359
  const writeCache = options.writeCache !== false;
320
360
  const forceRemote = options.forceRemote === true;
361
+ const fetchMetadata = typeof options.fetchMetadata === "function"
362
+ ? options.fetchMetadata
363
+ : fetchPackageUpdateMetadata;
321
364
  const now = new Date();
322
365
  const absoluteTarget = path.resolve(target);
323
366
  const trellisDir = path.join(absoluteTarget, ".trellis");
@@ -404,11 +447,19 @@ export async function buildSelfCheck(target, options = {}) {
404
447
  }
405
448
  if (projectOutOfSync) {
406
449
  const releaseNotesRange = projectReleaseNotesRange(projectFlower, currentFlower);
450
+ const releaseNotes = cachedReleaseNotes(updateCheck, releaseNotesRange) ||
451
+ await fetchMissingReleaseNotes(
452
+ absoluteTarget,
453
+ manifest,
454
+ writeCache,
455
+ releaseNotesRange,
456
+ fetchMetadata,
457
+ );
407
458
  return projectOutOfSyncResult(base, absoluteTarget, {
408
459
  tags,
409
460
  fromCache: true,
410
461
  skipped: true,
411
- }, cachedReleaseNotes(updateCheck, releaseNotesRange));
462
+ }, releaseNotes);
412
463
  }
413
464
  return {
414
465
  ...base,
@@ -418,7 +469,7 @@ export async function buildSelfCheck(target, options = {}) {
418
469
  };
419
470
  }
420
471
 
421
- const metadata = await fetchPackageUpdateMetadata();
472
+ const metadata = await safeFetchPackageUpdateMetadata(fetchMetadata);
422
473
  if (!metadata) {
423
474
  if (writeCache && manifest) {
424
475
  writeUpdateCheck(absoluteTarget, {