@rowansenne/workflow-run 0.24.0 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +15 -0
- package/bin/lib/core.mjs +5 -2
- package/bin/lib/install.mjs +15 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.24.1] - 2026-10-21
|
|
8
|
+
|
|
9
|
+
### 修复
|
|
10
|
+
- WorkBuddy 改用 `--copy` 重装时,将本工具已有的技能软链接转换为真实目录,保留已填配置,避免写入共享来源或影响其他环境;用户指向其他位置的链接保留并报错。
|
|
11
|
+
- 升级以最近一次显式安装的环境和模式为准,自动退回拷贝的清单不覆盖单一来源的完整技能选择。
|
|
12
|
+
- 补充 Windows WorkBuddy 的管理员终端、独立拷贝安装及技能不可见时的排查说明。
|
|
13
|
+
|
|
7
14
|
## [0.24.0] - 2026-10-21
|
|
8
15
|
|
|
9
16
|
### 变更
|
package/README.md
CHANGED
|
@@ -78,6 +78,21 @@ npx @rowansenne/workflow-run docs-repo git@git.example.com:team/team-docs.git
|
|
|
78
78
|
* Windows:安装与升级(`init` / `upgrade`)**必须在管理员终端执行**(建目录软链接需要该权限);在普通终端运行会直接停下、不做任何改动,并提示改用「以管理员身份运行」的终端。`doctor`、`seed-templates`、`uninstall` 不要求管理员。少数文件系统仍建不了软链接时,该环境自动退回独立拷贝。在 Windows 上 clone 含软链接的仓库需要 `git config core.symlinks true`。
|
|
79
79
|
* 不想用软链接:加 `--copy`,每个环境各装一份完整文件。
|
|
80
80
|
|
|
81
|
+
### 在 Windows 的 WorkBuddy 中使用
|
|
82
|
+
|
|
83
|
+
在**业务项目根目录**打开管理员 PowerShell,运行 npm 包提供的安装命令(仅 `npm install` 下载包不会生成项目技能):
|
|
84
|
+
|
|
85
|
+
```powershell
|
|
86
|
+
npx @rowansenne/workflow-run@latest --envs workbuddy --copy --skip-db --yes
|
|
87
|
+
npx @rowansenne/workflow-run@latest doctor --offline
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
这里用 `--copy` 在 `.codebuddy/skills/<skill>/` 生成真实目录和 `SKILL.md`,便于排除目录软链接的兼容问题。已有指向 `.agents/skills/` 的本工具链接会先转成独立拷贝,保留已填配置,再更新技能文件;共享来源和 Qwen 等其他环境的链接不变。后续 `upgrade` 沿用最近一次显式安装的环境和模式。只选择 WorkBuddy 时,全新安装不会生成 `.qwen/skills/`。
|
|
91
|
+
|
|
92
|
+
安装后,将 **同一个业务项目目录**设为 WorkBuddy 任务的工作目录,重新打开项目并新建会话,再尝试 `/workflow status`、`/dev` 或 `/project-review`。`/workflow profile` 等是技能参数,不是额外的独立技能。
|
|
93
|
+
|
|
94
|
+
如果仍然不可见,先确认业务项目下确实有 `.codebuddy/skills/workflow/SKILL.md`,并保留安装命令、`doctor --offline` 输出与 WorkBuddy 版本以便排查。项目级配置目录见 [WorkBuddy 官方说明](https://www.codebuddy.cn/docs/workbuddy/From-Beginner-to-Expert-Guide/Function-Description/Project)。
|
|
95
|
+
|
|
81
96
|
每个 skill 目录结构(四环境一致):
|
|
82
97
|
|
|
83
98
|
|
package/bin/lib/core.mjs
CHANGED
|
@@ -107,9 +107,12 @@ export function timestamp() {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
export const INSTALL_BASES = [CANON_DIR, ...Object.values(LINK_ENVS)];
|
|
110
|
-
//
|
|
110
|
+
// 以最近一次显式安装为准;自动退回拷贝的清单不覆盖单一来源的模式与 skill 选择。
|
|
111
111
|
export function findManifests(root) {
|
|
112
|
-
|
|
112
|
+
const found = INSTALL_BASES.map((rel) => ({ rel, base: path.join(root, rel), m: readManifest(path.join(root, rel)) })).filter((x) => x.m);
|
|
113
|
+
const primary = found.filter((x) => x.rel === CANON_DIR || x.m.mode === 'copy').reduce((latest, x) =>
|
|
114
|
+
!latest || (Date.parse(x.m.installedAt) || 0) > (Date.parse(latest.m.installedAt) || 0) ? x : latest, null);
|
|
115
|
+
return primary ? [primary, ...found.filter((x) => x !== primary)] : found;
|
|
113
116
|
}
|
|
114
117
|
export function cmpVersion(a, b) {
|
|
115
118
|
const pa = String(a).split(/[.-]/).map((x) => parseInt(x, 10) || 0);
|
package/bin/lib/install.mjs
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import { TPL_DIR, PKG, CANON_DIR, INSTALL_BASES, SKILLS, SKILL_LIST, USER_FILES, MANIFEST, ok, warn, readJson, walk, toPosix, sameFile, writeFile, render, sha256, fileHash, readManifest, removeEmptyDirs, lstat, timestamp, removeLink, HOME } from './core.mjs';
|
|
5
|
+
import { TPL_DIR, PKG, CANON_DIR, INSTALL_BASES, SKILLS, SKILL_LIST, USER_FILES, MANIFEST, ok, warn, fail, readJson, walk, toPosix, sameFile, writeFile, render, sha256, fileHash, readManifest, removeEmptyDirs, lstat, timestamp, removeLink, HOME } from './core.mjs';
|
|
6
6
|
import { writeDbConfig } from './db.mjs';
|
|
7
|
+
import { linkPointsTo } from './uninstall.mjs';
|
|
7
8
|
import { layout, ensureIgnore, homeIsRepo, migrateLayout, IGNORE_LINE, TMP_DIR } from '../../workflow/scripts/requirement.mjs';
|
|
8
9
|
import { detectEnv } from '../../workflow/scripts/resolve.mjs';
|
|
9
10
|
import { rotate as rotateFeedback, ensureUnionMerge } from '../../workflow/scripts/feedback.mjs';
|
|
@@ -66,6 +67,19 @@ export async function installSkills(base, db, ctx) {
|
|
|
66
67
|
for (const skill of selected) {
|
|
67
68
|
const srcDir = path.join(TPL_DIR, skill);
|
|
68
69
|
const dstDir = path.join(base, skill);
|
|
70
|
+
// --copy 重装已有链接时先解除共享关系,避免写穿链接、仍留下无法被部分宿主发现的链接目录。
|
|
71
|
+
if (ctx.mode !== 'symlink' && lstat(dstDir)?.isSymbolicLink()) {
|
|
72
|
+
if (!linkPointsTo(dstDir, path.resolve(ctx.root, CANON_DIR, skill))) fail(`${dstDir} 指向其他位置,不能改为独立拷贝;请先手动处理该链接。`);
|
|
73
|
+
const tmp = fs.mkdtempSync(path.join(base, '.workflow-run-copy-'));
|
|
74
|
+
const copy = path.join(tmp, skill);
|
|
75
|
+
try {
|
|
76
|
+
if (fs.existsSync(dstDir)) fs.cpSync(dstDir, copy, { recursive: true, dereference: true });
|
|
77
|
+
else fs.mkdirSync(copy);
|
|
78
|
+
removeLink(dstDir);
|
|
79
|
+
fs.renameSync(copy, dstDir);
|
|
80
|
+
} finally { fs.rmSync(tmp, { recursive: true, force: true }); }
|
|
81
|
+
ok(`${toPosix(path.relative(ctx.root, dstDir))} 已由软链接改为独立拷贝(已有配置保留)`);
|
|
82
|
+
}
|
|
69
83
|
const prevSkill = prev?.skills?.[skill];
|
|
70
84
|
const entry = { files: {}, userFiles: {} };
|
|
71
85
|
const notes = [];
|
package/package.json
CHANGED