msdevflow 0.7.4 → 0.7.5
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/README.md +31 -41
- package/lib/bootstrap.js +262 -88
- package/package.json +2 -2
- package/skill/{msdevflow → msd}/README.md +38 -33
- package/skill/{msdevflow → msd}/SKILL.md +26 -35
- package/skill/{msdevflow → msd}/references/ci-and-review.md +1 -1
- package/skill/{msdevflow → msd}/references/create-issue.md +1 -1
- package/skill/{msdevflow → msd}/references/design-and-development.md +1 -1
- package/skill/{msdevflow → msd}/references/pr-and-ci.md +1 -1
- package/skill/{msdevflow → msd}/references/recovery.md +1 -1
- package/skill/{msdevflow → msd}/references/review-and-merge.md +2 -2
- package/skill/{msdevflow → msd}/references/setup-and-issue.md +2 -2
- package/skill/msd-ci/SKILL.md +15 -0
- package/skill/msd-code-review/SKILL.md +15 -0
- package/skill/msd-create-issue/SKILL.md +15 -0
- package/skill/msd-develop/SKILL.md +15 -0
- package/skill/msd-discover/SKILL.md +15 -0
- package/skill/msd-feedback/SKILL.md +15 -0
- package/skill/msd-issue/SKILL.md +15 -0
- package/skill/msd-merge/SKILL.md +15 -0
- package/skill/msd-openlibing-auth/SKILL.md +15 -0
- package/skill/msd-pr/SKILL.md +15 -0
- /package/skill/{msdevflow → msd}/references/code-review.md +0 -0
- /package/skill/{msdevflow → msd}/references/command-capabilities.md +0 -0
- /package/skill/{msdevflow → msd}/references/openlibing-ci.md +0 -0
- /package/skill/{msdevflow → msd}/references/state-and-safety.md +0 -0
- /package/skill/{msdevflow → msd}/scripts/openlibing_ci.py +0 -0
- /package/skill/{msdevflow → msd}/scripts/requirements.txt +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# msdevflow
|
|
2
2
|
|
|
3
|
-
`msdevflow`
|
|
3
|
+
`msdevflow` npm 包提供一套 GitCode Agent Skills:`msd` 核心可以把已授权的 Issue 安全推进到代码实现、普通 PR、CI、检视意见闭环和最终合入,十个 `msd-<action>` 薄路由入口用于在输入阶段发现并运行单项能力。正式支持 Claude Code、Codex 和 OpenCode;Trae 的 Skills 安装与兼容机制尚未完成可靠验证,因此当前不宣称支持。
|
|
4
4
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
@@ -29,7 +29,7 @@ npx msdevflow@latest setup
|
|
|
29
29
|
|
|
30
30
|
`setup` 默认检测 PATH 中的 Claude Code、Codex 和 OpenCode,展示完整计划并在确认后:
|
|
31
31
|
|
|
32
|
-
1.
|
|
32
|
+
1. 把一个 `msd` 核心和十个 `msd-<action>` 路由器作为整套事务原子安装或更新到所需目标;
|
|
33
33
|
2. 安装或升级官方 `@gitcode-cli/cli@latest`;
|
|
34
34
|
3. 安装受审的 Python Playwright 依赖;
|
|
35
35
|
4. 验收 Issue、PR、结构化评论、行内评论、JSON、显式仓库和正文文件等 CLI 能力;
|
|
@@ -47,15 +47,17 @@ npx msdevflow setup --dry-run --targets all
|
|
|
47
47
|
安装目录映射:
|
|
48
48
|
|
|
49
49
|
```text
|
|
50
|
-
Claude Code -> ~/.claude/skills/
|
|
51
|
-
Codex -> ~/.agents/skills/
|
|
52
|
-
仅 OpenCode -> ~/.agents/skills/
|
|
53
|
-
OpenCode + Claude Code -> 复用
|
|
54
|
-
OpenCode + Codex -> 复用
|
|
55
|
-
Claude Code + Codex ->
|
|
56
|
-
三者同时安装 ->
|
|
50
|
+
Claude Code -> ~/.claude/skills/{msd,msd-*}
|
|
51
|
+
Codex -> ~/.agents/skills/{msd,msd-*}
|
|
52
|
+
仅 OpenCode -> ~/.agents/skills/{msd,msd-*}
|
|
53
|
+
OpenCode + Claude Code -> 复用 Claude 目标
|
|
54
|
+
OpenCode + Codex -> 复用 Agent Skills 目标
|
|
55
|
+
Claude Code + Codex -> 两套受管副本
|
|
56
|
+
三者同时安装 -> 两套受管副本,并提示 OpenCode 双路径发现
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
每个物理目标都包含完整套件,薄路由器不复制核心业务规则。已有 entry 只有在 manifest 精确匹配自身名称时才允许更新;由旧版包管理的 `msdevflow` 目录会在新套件全部验证后安全迁移,来源不明的目录、文件或符号链接会阻断安装。
|
|
60
|
+
|
|
59
61
|
自定义目录:
|
|
60
62
|
|
|
61
63
|
```bash
|
|
@@ -65,29 +67,15 @@ npx msdevflow setup --agents-skills-dir "<shared-agent-skills-directory>"
|
|
|
65
67
|
|
|
66
68
|
`--skills-dir` 未配合 `--targets` 使用时保留旧语义,只安装 Claude Code 目标。没有检测到客户端时,交互运行会要求选择目标;非交互运行必须提供 `--targets`。安装完成后重启或重新加载对应客户端。如果机器已有 Python 版本的 `gitcode`,setup 会保留它,并为 npm CLI 创建 `gitcode-npm` 命令;否则使用 `gitcode`。
|
|
67
69
|
|
|
68
|
-
## 运行与 action
|
|
69
|
-
|
|
70
|
-
从目标仓库目录启动客户端并提交 `msdevflow`:
|
|
71
|
-
|
|
72
|
-
- Claude Code:输入并提交 `/msdevflow`;
|
|
73
|
-
- Codex:使用 `$msdevflow` 或从 `/skills` 选择后提交;
|
|
74
|
-
- OpenCode:打开 `/skills`,选择 `msdevflow`,再提交插入的 `/msdevflow`。`@` 用于文件、reference 或 agent,不用于选择 Skill。
|
|
70
|
+
## 运行与 action 补全
|
|
75
71
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
```text
|
|
79
|
-
选择运行方式
|
|
80
|
-
├─ 完整端到端流程
|
|
81
|
-
├─ 作者工作流
|
|
82
|
-
│ ├─ Issue 管理 -> discover | create-issue | issue
|
|
83
|
-
│ ├─ 开发与交付 -> develop | pr | ci
|
|
84
|
-
│ └─ PR 后续 -> feedback | merge
|
|
85
|
-
└─ 独立工具 -> openlibing-auth | code-review
|
|
86
|
-
```
|
|
72
|
+
从目标仓库目录启动客户端。直接调用核心 `msd` 会运行完整作者 E2E:
|
|
87
73
|
|
|
88
|
-
Claude Code
|
|
74
|
+
- Claude Code:输入并提交 `/msd`;
|
|
75
|
+
- Codex:使用 `$msd` 或从 `/skills` 选择;
|
|
76
|
+
- OpenCode:打开 `/skills`,选择 `msd`,再提交插入的 `/msd`。`@` 用于文件、reference 或 agent,不用于选择 Skill。
|
|
89
77
|
|
|
90
|
-
|
|
78
|
+
核心流程为:
|
|
91
79
|
|
|
92
80
|
```text
|
|
93
81
|
Issue 发现/核验
|
|
@@ -102,9 +90,9 @@ Issue 发现/核验
|
|
|
102
90
|
-> 远端回读 PR 已 merged
|
|
103
91
|
```
|
|
104
92
|
|
|
105
|
-
|
|
93
|
+
调用正文可提供 Issue/PR URL、仓库路径、canonical、source 和模式。核心 `msd` 不显示运行时 Question 菜单。
|
|
106
94
|
|
|
107
|
-
这是可暂停、可恢复的流程。外部检视或审批有新进展后,可再次提交 `/
|
|
95
|
+
这是可暂停、可恢复的流程。外部检视或审批有新进展后,可再次提交 `/msd` 和 PR 信息:
|
|
108
96
|
|
|
109
97
|
```text
|
|
110
98
|
恢复 https://gitcode.com/<canonical-owner>/<repo>/pulls/<number> 的完整作者 E2E。
|
|
@@ -116,7 +104,7 @@ source:<your-account>/<repo>
|
|
|
116
104
|
|
|
117
105
|
## 独立 action
|
|
118
106
|
|
|
119
|
-
|
|
107
|
+
Claude Code/OpenCode 输入 `/msd-`、Codex 输入 `$msd-` 即可筛选十个独立入口。每个入口只运行对应 action,完成后立即停止;前置条件不足时不会隐式补跑上游流程。`/msd action=<name>` 和 `$msd action=<name>` 仍是兼容调用,但参数本身不提供跨客户端枚举补全。
|
|
120
108
|
|
|
121
109
|
| action | 用途 | 完成状态或结果 |
|
|
122
110
|
|---|---|---|
|
|
@@ -134,19 +122,19 @@ source:<your-account>/<repo>
|
|
|
134
122
|
示例:
|
|
135
123
|
|
|
136
124
|
```text
|
|
137
|
-
/
|
|
125
|
+
/msd-create-issue
|
|
138
126
|
在 Ascend/example 提一个 bug:升级后首次启动失败……
|
|
139
127
|
使用 guided 模式,确认完整预览后再创建。
|
|
140
128
|
```
|
|
141
129
|
|
|
142
130
|
```text
|
|
143
|
-
/
|
|
131
|
+
/msd-ci
|
|
144
132
|
PR:https://gitcode.com/Ascend/example/pulls/456
|
|
145
133
|
本地仓库:D:\work\example
|
|
146
134
|
```
|
|
147
135
|
|
|
148
136
|
```text
|
|
149
|
-
/
|
|
137
|
+
/msd-code-review
|
|
150
138
|
PR:https://gitcode.com/Ascend/example/pulls/789
|
|
151
139
|
```
|
|
152
140
|
|
|
@@ -188,17 +176,19 @@ Agent 写入的 PR/Issue 正文、评论和 discussion 回复末尾会附加:
|
|
|
188
176
|
|
|
189
177
|
## 常见阻塞
|
|
190
178
|
|
|
191
|
-
### 客户端找不到 `
|
|
179
|
+
### 客户端找不到 `msd` 或 `msd-<action>`
|
|
192
180
|
|
|
193
|
-
|
|
181
|
+
按目标确认核心和相应路由器的 manifest 都存在,然后重启或重新加载客户端:
|
|
194
182
|
|
|
195
183
|
```text
|
|
196
|
-
Claude Code: ~/.claude/skills/
|
|
197
|
-
|
|
184
|
+
Claude Code: ~/.claude/skills/msd/SKILL.md
|
|
185
|
+
~/.claude/skills/msd-<action>/SKILL.md
|
|
186
|
+
Codex: ~/.agents/skills/msd/SKILL.md
|
|
187
|
+
~/.agents/skills/msd-<action>/SKILL.md
|
|
198
188
|
OpenCode: 上述任一路径(按 setup 计划)
|
|
199
189
|
```
|
|
200
190
|
|
|
201
|
-
|
|
191
|
+
Claude Code/OpenCode 可输入 `/msd-` 筛选 action;Codex 使用 `$msd-`。可运行 `npx msdevflow setup --dry-run --targets <clients>` 检查目标映射。
|
|
202
192
|
|
|
203
193
|
### `blocked: bootstrap-required`
|
|
204
194
|
|
|
@@ -229,4 +219,4 @@ npx msdevflow setup
|
|
|
229
219
|
|
|
230
220
|
## 详细文档
|
|
231
221
|
|
|
232
|
-
完整 action、恢复、模板、CI、review、UTF-8 和安全契约见 [`skill/
|
|
222
|
+
完整 action、恢复、模板、CI、review、UTF-8 和安全契约见 [`skill/msd/README.md`](skill/msd/README.md)。
|
package/lib/bootstrap.js
CHANGED
|
@@ -24,7 +24,25 @@ import { fileURLToPath } from "node:url";
|
|
|
24
24
|
const REGISTRY = "https://registry.npmjs.org";
|
|
25
25
|
const GITCODE_PACKAGE = "@gitcode-cli/cli@latest";
|
|
26
26
|
const PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
27
|
-
const
|
|
27
|
+
const BUNDLED_SKILLS_DIR = path.join(PACKAGE_ROOT, "skill");
|
|
28
|
+
const CORE_SKILL_NAME = "msd";
|
|
29
|
+
const LEGACY_SKILL_NAME = "msdevflow";
|
|
30
|
+
export const ACTIONS = [
|
|
31
|
+
"discover",
|
|
32
|
+
"create-issue",
|
|
33
|
+
"issue",
|
|
34
|
+
"develop",
|
|
35
|
+
"pr",
|
|
36
|
+
"ci",
|
|
37
|
+
"openlibing-auth",
|
|
38
|
+
"feedback",
|
|
39
|
+
"code-review",
|
|
40
|
+
"merge",
|
|
41
|
+
];
|
|
42
|
+
export const MANAGED_SKILL_NAMES = [
|
|
43
|
+
CORE_SKILL_NAME,
|
|
44
|
+
...ACTIONS.map((action) => `${CORE_SKILL_NAME}-${action}`),
|
|
45
|
+
];
|
|
28
46
|
const SUPPORTED_CLIENTS = ["claude", "codex", "opencode"];
|
|
29
47
|
const REQUIRED_SCHEMAS = {
|
|
30
48
|
"auth login": ["web"],
|
|
@@ -70,8 +88,8 @@ client is detected, interactive setup asks which clients to install; non-interac
|
|
|
70
88
|
setup requires --targets. OpenCode reuses a Claude or shared Agent Skills target
|
|
71
89
|
instead of creating a third copy.
|
|
72
90
|
|
|
73
|
-
The setup installs or updates the bundled
|
|
74
|
-
the official GitCode npm CLI, and installs all reviewed Python runtime
|
|
91
|
+
The setup installs or updates the bundled msd core and msd-<action> skills,
|
|
92
|
+
installs or upgrades the official GitCode npm CLI, and installs all reviewed Python runtime
|
|
75
93
|
dependencies. It never downloads or launches Chromium. If GitCode is not
|
|
76
94
|
authenticated, it starts the CLI's official browser login; setup never reads or
|
|
77
95
|
prints a token.`;
|
|
@@ -167,29 +185,33 @@ function defaultAgentsSkillsDir(options, environment, platform) {
|
|
|
167
185
|
|| path.join(environmentHome(environment, platform), ".agents", "skills");
|
|
168
186
|
}
|
|
169
187
|
|
|
170
|
-
function createSkillLayout(kind, clients, skillsDir,
|
|
188
|
+
function createSkillLayout(kind, clients, skillsDir, bundledSkillsDir) {
|
|
171
189
|
const resolvedSkillsDir = path.resolve(skillsDir);
|
|
172
|
-
const
|
|
173
|
-
const
|
|
190
|
+
const resolvedBundledSkillsDir = path.resolve(bundledSkillsDir);
|
|
191
|
+
const coreDir = path.join(resolvedSkillsDir, CORE_SKILL_NAME);
|
|
192
|
+
const bundledCoreDir = path.join(resolvedBundledSkillsDir, CORE_SKILL_NAME);
|
|
174
193
|
return {
|
|
175
194
|
kind,
|
|
176
195
|
clients,
|
|
177
196
|
skillsDir: resolvedSkillsDir,
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
pythonRequirements: path.join(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
197
|
+
coreDir,
|
|
198
|
+
coreManifest: path.join(coreDir, "SKILL.md"),
|
|
199
|
+
pythonRequirements: path.join(coreDir, "scripts", "requirements.txt"),
|
|
200
|
+
legacyDir: path.join(resolvedSkillsDir, LEGACY_SKILL_NAME),
|
|
201
|
+
legacyManifest: path.join(resolvedSkillsDir, LEGACY_SKILL_NAME, "SKILL.md"),
|
|
202
|
+
bundledSkillsDir: resolvedBundledSkillsDir,
|
|
203
|
+
bundledCoreDir,
|
|
204
|
+
bundledCoreManifest: path.join(bundledCoreDir, "SKILL.md"),
|
|
205
|
+
bundledPythonRequirements: path.join(bundledCoreDir, "scripts", "requirements.txt"),
|
|
184
206
|
};
|
|
185
207
|
}
|
|
186
208
|
|
|
187
|
-
export function resolveLayout(options, environment = process.env,
|
|
209
|
+
export function resolveLayout(options, environment = process.env, bundledSkillsDir = BUNDLED_SKILLS_DIR) {
|
|
188
210
|
return createSkillLayout(
|
|
189
211
|
"claude",
|
|
190
212
|
["claude"],
|
|
191
213
|
defaultClaudeSkillsDir(options, environment, process.platform),
|
|
192
|
-
|
|
214
|
+
bundledSkillsDir,
|
|
193
215
|
);
|
|
194
216
|
}
|
|
195
217
|
|
|
@@ -197,7 +219,7 @@ export function resolveLayouts(
|
|
|
197
219
|
options,
|
|
198
220
|
clients,
|
|
199
221
|
environment = process.env,
|
|
200
|
-
|
|
222
|
+
bundledSkillsDir = BUNDLED_SKILLS_DIR,
|
|
201
223
|
platform = process.platform,
|
|
202
224
|
) {
|
|
203
225
|
const layouts = [];
|
|
@@ -207,7 +229,7 @@ export function resolveLayouts(
|
|
|
207
229
|
"claude",
|
|
208
230
|
openCodeUsesClaude ? ["claude", "opencode"] : ["claude"],
|
|
209
231
|
defaultClaudeSkillsDir(options, environment, platform),
|
|
210
|
-
|
|
232
|
+
bundledSkillsDir,
|
|
211
233
|
));
|
|
212
234
|
}
|
|
213
235
|
if (clients.includes("codex") || (clients.includes("opencode") && !openCodeUsesClaude)) {
|
|
@@ -219,12 +241,12 @@ export function resolveLayouts(
|
|
|
219
241
|
"agents",
|
|
220
242
|
sharedClients,
|
|
221
243
|
defaultAgentsSkillsDir(options, environment, platform),
|
|
222
|
-
|
|
244
|
+
bundledSkillsDir,
|
|
223
245
|
));
|
|
224
246
|
}
|
|
225
247
|
const unique = new Map();
|
|
226
248
|
for (const layout of layouts) {
|
|
227
|
-
const key = normalizedPath(layout.
|
|
249
|
+
const key = normalizedPath(layout.skillsDir, platform);
|
|
228
250
|
const existing = unique.get(key);
|
|
229
251
|
if (existing) {
|
|
230
252
|
existing.clients = [...new Set([...existing.clients, ...layout.clients])];
|
|
@@ -440,7 +462,7 @@ function requireFile(file, description) {
|
|
|
440
462
|
verifyFile(file, `${description} not found: ${file}. Reinstall the msdevflow npm package.`);
|
|
441
463
|
}
|
|
442
464
|
|
|
443
|
-
function skillManifestIsOwned(file) {
|
|
465
|
+
function skillManifestIsOwned(file, expectedName) {
|
|
444
466
|
try {
|
|
445
467
|
const metadata = lstatSync(file);
|
|
446
468
|
if (metadata.isSymbolicLink() || !metadata.isFile()) {
|
|
@@ -451,7 +473,7 @@ function skillManifestIsOwned(file) {
|
|
|
451
473
|
return false;
|
|
452
474
|
}
|
|
453
475
|
const names = [...frontmatter[1].matchAll(/^name:\s*([^\s#]+)\s*$/gm)];
|
|
454
|
-
return names.length === 1 && names[0][1] ===
|
|
476
|
+
return names.length === 1 && names[0][1] === expectedName;
|
|
455
477
|
} catch (error) {
|
|
456
478
|
if (error?.code === "ENOENT") {
|
|
457
479
|
return false;
|
|
@@ -491,26 +513,25 @@ function skillDigest(root) {
|
|
|
491
513
|
return digest.digest("hex");
|
|
492
514
|
}
|
|
493
515
|
|
|
494
|
-
function
|
|
495
|
-
|
|
496
|
-
requireFile(
|
|
497
|
-
if (!skillManifestIsOwned(
|
|
498
|
-
throw new BootstrapError(
|
|
516
|
+
function installedSkillDetails(source, target, name) {
|
|
517
|
+
const sourceManifest = path.join(source, "SKILL.md");
|
|
518
|
+
requireFile(sourceManifest, `bundled ${name} skill manifest`);
|
|
519
|
+
if (!skillManifestIsOwned(sourceManifest, name)) {
|
|
520
|
+
throw new BootstrapError(`Bundled skill manifest does not identify ${name}.`, 3);
|
|
499
521
|
}
|
|
500
|
-
|
|
501
|
-
const bundledDigest = skillDigest(layout.bundledSkillDir);
|
|
522
|
+
const bundledDigest = skillDigest(source);
|
|
502
523
|
let status = "absent";
|
|
503
524
|
let existingDigest = null;
|
|
504
525
|
try {
|
|
505
|
-
const metadata = lstatSync(
|
|
526
|
+
const metadata = lstatSync(target);
|
|
506
527
|
if (metadata.isSymbolicLink() || !metadata.isDirectory()
|
|
507
|
-
|| !skillManifestIsOwned(
|
|
528
|
+
|| !skillManifestIsOwned(path.join(target, "SKILL.md"), name)) {
|
|
508
529
|
throw new BootstrapError(
|
|
509
|
-
`Refusing to overwrite a skills entry not owned by
|
|
530
|
+
`Refusing to overwrite a skills entry not owned by ${name}: ${target}`,
|
|
510
531
|
3,
|
|
511
532
|
);
|
|
512
533
|
}
|
|
513
|
-
existingDigest = skillDigest(
|
|
534
|
+
existingDigest = skillDigest(target);
|
|
514
535
|
status = existingDigest === bundledDigest ? "current" : "update";
|
|
515
536
|
} catch (error) {
|
|
516
537
|
if (error?.code !== "ENOENT") {
|
|
@@ -518,70 +539,211 @@ function skillInstallDetails(layout) {
|
|
|
518
539
|
}
|
|
519
540
|
}
|
|
520
541
|
return {
|
|
521
|
-
|
|
522
|
-
|
|
542
|
+
name,
|
|
543
|
+
source,
|
|
544
|
+
target,
|
|
523
545
|
status,
|
|
524
546
|
bundledDigest,
|
|
525
547
|
existingDigest,
|
|
526
548
|
};
|
|
527
549
|
}
|
|
528
550
|
|
|
529
|
-
function
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
551
|
+
function legacySkillDetails(layout) {
|
|
552
|
+
try {
|
|
553
|
+
const metadata = lstatSync(layout.legacyDir);
|
|
554
|
+
if (metadata.isSymbolicLink() || !metadata.isDirectory()
|
|
555
|
+
|| !skillManifestIsOwned(layout.legacyManifest, LEGACY_SKILL_NAME)) {
|
|
556
|
+
throw new BootstrapError(
|
|
557
|
+
`Refusing to migrate a legacy skills entry not owned by ${LEGACY_SKILL_NAME}: ${layout.legacyDir}`,
|
|
558
|
+
3,
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
return {
|
|
562
|
+
target: layout.legacyDir,
|
|
563
|
+
status: "migrate",
|
|
564
|
+
existingDigest: skillDigest(layout.legacyDir),
|
|
565
|
+
};
|
|
566
|
+
} catch (error) {
|
|
567
|
+
if (error?.code === "ENOENT") {
|
|
568
|
+
return {
|
|
569
|
+
target: layout.legacyDir,
|
|
570
|
+
status: "absent",
|
|
571
|
+
existingDigest: null,
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
throw error;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function skillInstallDetails(layout) {
|
|
579
|
+
requireFile(layout.bundledPythonRequirements, "bundled workflow Python requirements file");
|
|
580
|
+
validatePythonRequirements(layout.bundledPythonRequirements);
|
|
581
|
+
const entries = MANAGED_SKILL_NAMES.map((name) => installedSkillDetails(
|
|
582
|
+
path.join(layout.bundledSkillsDir, name),
|
|
583
|
+
path.join(layout.skillsDir, name),
|
|
584
|
+
name,
|
|
585
|
+
));
|
|
586
|
+
return {
|
|
587
|
+
source: layout.bundledSkillsDir,
|
|
588
|
+
target: layout.skillsDir,
|
|
589
|
+
entries,
|
|
590
|
+
legacy: legacySkillDetails(layout),
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
function assertSkillInstallUnchanged(details) {
|
|
595
|
+
const layout = {
|
|
596
|
+
skillsDir: details.target,
|
|
597
|
+
bundledSkillsDir: details.source,
|
|
598
|
+
bundledPythonRequirements: path.join(
|
|
599
|
+
details.source,
|
|
600
|
+
CORE_SKILL_NAME,
|
|
601
|
+
"scripts",
|
|
602
|
+
"requirements.txt",
|
|
603
|
+
),
|
|
604
|
+
legacyDir: path.join(details.target, LEGACY_SKILL_NAME),
|
|
605
|
+
legacyManifest: path.join(details.target, LEGACY_SKILL_NAME, "SKILL.md"),
|
|
606
|
+
};
|
|
607
|
+
const current = skillInstallDetails(layout);
|
|
608
|
+
for (let index = 0; index < details.entries.length; index += 1) {
|
|
609
|
+
const expected = details.entries[index];
|
|
610
|
+
const actual = current.entries[index];
|
|
611
|
+
if (actual.name !== expected.name || actual.status !== expected.status
|
|
612
|
+
|| actual.existingDigest !== expected.existingDigest
|
|
613
|
+
|| actual.bundledDigest !== expected.bundledDigest) {
|
|
614
|
+
throw new BootstrapError(
|
|
615
|
+
`Skill target changed after confirmation; refusing to overwrite it: ${expected.target}`,
|
|
616
|
+
3,
|
|
617
|
+
);
|
|
618
|
+
}
|
|
541
619
|
}
|
|
542
|
-
if (current.status
|
|
543
|
-
|
|
620
|
+
if (current.legacy.status !== details.legacy.status
|
|
621
|
+
|| current.legacy.existingDigest !== details.legacy.existingDigest) {
|
|
622
|
+
throw new BootstrapError(
|
|
623
|
+
`Legacy skill target changed after confirmation; refusing to migrate it: ${details.legacy.target}`,
|
|
624
|
+
3,
|
|
625
|
+
);
|
|
544
626
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
function installedSuiteResult(details) {
|
|
630
|
+
const entries = details.entries.map((entry) => ({
|
|
631
|
+
name: entry.name,
|
|
632
|
+
status: entry.status === "current"
|
|
633
|
+
? "current"
|
|
634
|
+
: entry.status === "absent" ? "installed" : "updated",
|
|
635
|
+
target: entry.target,
|
|
636
|
+
}));
|
|
637
|
+
let status = "current";
|
|
638
|
+
if (details.legacy.status === "migrate") {
|
|
639
|
+
status = "migrated";
|
|
640
|
+
} else if (entries.some((entry) => entry.status === "updated")) {
|
|
641
|
+
status = "updated";
|
|
642
|
+
} else if (entries.some((entry) => entry.status === "installed")) {
|
|
643
|
+
status = "installed";
|
|
644
|
+
}
|
|
645
|
+
return { status, entries, legacy: details.legacy.status };
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
function suiteTransactionPath(details, name, extension) {
|
|
649
|
+
const skillsRootName = path.basename(details.target) || "skills";
|
|
650
|
+
return path.join(
|
|
651
|
+
path.dirname(details.target),
|
|
652
|
+
`.${skillsRootName}-msdevflow-${name}-${randomUUID()}.${extension}`,
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
function installBundledSkillSuites(suites) {
|
|
657
|
+
for (const details of suites) {
|
|
658
|
+
mkdirSync(details.target, { recursive: true });
|
|
659
|
+
assertSkillInstallUnchanged(details);
|
|
660
|
+
}
|
|
661
|
+
const staged = [];
|
|
662
|
+
const switched = [];
|
|
663
|
+
const migrated = [];
|
|
548
664
|
try {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
665
|
+
for (const details of suites) {
|
|
666
|
+
for (const entry of details.entries.filter((item) => item.status !== "current")) {
|
|
667
|
+
const staging = suiteTransactionPath(details, entry.name, "tmp");
|
|
668
|
+
cpSync(entry.source, staging, { recursive: true, errorOnExist: true });
|
|
669
|
+
if (skillDigest(staging) !== entry.bundledDigest) {
|
|
670
|
+
throw new BootstrapError(`Bundled ${entry.name} verification failed after staging.`, 3);
|
|
671
|
+
}
|
|
672
|
+
staged.push({ details, entry, staging });
|
|
673
|
+
}
|
|
552
674
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
movedExisting = true;
|
|
675
|
+
for (const details of suites) {
|
|
676
|
+
assertSkillInstallUnchanged(details);
|
|
556
677
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
renameSync(backup, details.target);
|
|
562
|
-
movedExisting = false;
|
|
678
|
+
for (const item of staged) {
|
|
679
|
+
const backup = suiteTransactionPath(item.details, item.entry.name, "backup");
|
|
680
|
+
if (item.entry.status === "update") {
|
|
681
|
+
renameSync(item.entry.target, backup);
|
|
563
682
|
}
|
|
564
|
-
|
|
683
|
+
try {
|
|
684
|
+
renameSync(item.staging, item.entry.target);
|
|
685
|
+
} catch (error) {
|
|
686
|
+
if (item.entry.status === "update") {
|
|
687
|
+
renameSync(backup, item.entry.target);
|
|
688
|
+
}
|
|
689
|
+
throw error;
|
|
690
|
+
}
|
|
691
|
+
switched.push({ ...item, backup: item.entry.status === "update" ? backup : null });
|
|
565
692
|
}
|
|
566
|
-
|
|
567
|
-
|
|
693
|
+
for (const details of suites.filter((item) => item.legacy.status === "migrate")) {
|
|
694
|
+
const backup = suiteTransactionPath(details, LEGACY_SKILL_NAME, "backup");
|
|
695
|
+
renameSync(details.legacy.target, backup);
|
|
696
|
+
migrated.push({ details, backup });
|
|
697
|
+
}
|
|
698
|
+
} catch (error) {
|
|
699
|
+
const rollbackFailures = [];
|
|
700
|
+
for (const item of migrated.reverse()) {
|
|
568
701
|
try {
|
|
569
|
-
|
|
570
|
-
} catch {
|
|
571
|
-
|
|
702
|
+
renameSync(item.backup, item.details.legacy.target);
|
|
703
|
+
} catch (rollbackError) {
|
|
704
|
+
rollbackFailures.push(rollbackError);
|
|
572
705
|
}
|
|
573
706
|
}
|
|
574
|
-
|
|
707
|
+
for (const item of switched.reverse()) {
|
|
708
|
+
try {
|
|
709
|
+
rmSync(item.entry.target, { recursive: true, force: true });
|
|
710
|
+
if (item.backup !== null) {
|
|
711
|
+
renameSync(item.backup, item.entry.target);
|
|
712
|
+
}
|
|
713
|
+
} catch (rollbackError) {
|
|
714
|
+
rollbackFailures.push(rollbackError);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
if (rollbackFailures.length) {
|
|
718
|
+
throw new BootstrapError(
|
|
719
|
+
`Skill suite installation failed and rollback was incomplete: ${error.message}; rollback: ${rollbackFailures.map((failure) => failure.message).join("; ")}`,
|
|
720
|
+
3,
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
throw error;
|
|
575
724
|
} finally {
|
|
576
|
-
|
|
577
|
-
|
|
725
|
+
for (const item of staged) {
|
|
726
|
+
rmSync(item.staging, { recursive: true, force: true });
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
for (const item of switched) {
|
|
731
|
+
if (item.backup !== null) {
|
|
578
732
|
try {
|
|
579
|
-
|
|
733
|
+
rmSync(item.backup, { recursive: true, force: true });
|
|
580
734
|
} catch {
|
|
581
|
-
|
|
735
|
+
// The verified replacement is live; stale backup cleanup can be retried manually.
|
|
582
736
|
}
|
|
583
737
|
}
|
|
584
738
|
}
|
|
739
|
+
for (const item of migrated) {
|
|
740
|
+
try {
|
|
741
|
+
rmSync(item.backup, { recursive: true, force: true });
|
|
742
|
+
} catch {
|
|
743
|
+
// The legacy entry is no longer discoverable; stale backup cleanup is non-blocking.
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
return suites.map(installedSuiteResult);
|
|
585
747
|
}
|
|
586
748
|
|
|
587
749
|
function validatePythonRequirements(file) {
|
|
@@ -628,7 +790,7 @@ async function selectClientTargets(input, output, promptOutput = output) {
|
|
|
628
790
|
promptOutput.write("No supported agent client was detected. Available targets: claude, codex, opencode, all.\n");
|
|
629
791
|
const terminal = createInterface({ input, output: promptOutput });
|
|
630
792
|
try {
|
|
631
|
-
const answer = await terminal.question("Install
|
|
793
|
+
const answer = await terminal.question("Install the msd skill suite for: ");
|
|
632
794
|
return parseTargets(answer);
|
|
633
795
|
} finally {
|
|
634
796
|
terminal.close();
|
|
@@ -653,7 +815,7 @@ async function resolveClientTargets(options, run, platform, selectClients) {
|
|
|
653
815
|
function clientTargetWarnings(clients, layouts) {
|
|
654
816
|
if (clients.includes("opencode") && layouts.length > 1) {
|
|
655
817
|
return [
|
|
656
|
-
"OpenCode can discover
|
|
818
|
+
"OpenCode can discover the msd skill suite from both installed paths; keep both copies managed by this setup to prevent version drift.",
|
|
657
819
|
];
|
|
658
820
|
}
|
|
659
821
|
return [];
|
|
@@ -951,11 +1113,16 @@ function safeAuthStatus(output) {
|
|
|
951
1113
|
function printPlan(plan, write) {
|
|
952
1114
|
write("Setup plan (no changes made yet):");
|
|
953
1115
|
write(` Client targets: ${plan.clientTargets.clients.join(", ")} (${plan.clientTargets.source})`);
|
|
954
|
-
write(` Bundled skill: ${plan.skillInstalls[0].details.source}`);
|
|
1116
|
+
write(` Bundled skill suite: ${plan.skillInstalls[0].details.source}`);
|
|
955
1117
|
for (const { layout, details } of plan.skillInstalls) {
|
|
956
|
-
write(` Skill
|
|
1118
|
+
write(` Skill root: ${details.target}`);
|
|
957
1119
|
write(` Clients: ${layout.clients.join(", ")}`);
|
|
958
|
-
|
|
1120
|
+
for (const entry of details.entries) {
|
|
1121
|
+
write(` ${entry.name}: ${entry.status}`);
|
|
1122
|
+
}
|
|
1123
|
+
if (details.legacy.status === "migrate") {
|
|
1124
|
+
write(` ${LEGACY_SKILL_NAME}: migrate after suite verification`);
|
|
1125
|
+
}
|
|
959
1126
|
}
|
|
960
1127
|
for (const warning of plan.clientTargets.warnings) {
|
|
961
1128
|
write(` Warning: ${warning}`);
|
|
@@ -1079,7 +1246,8 @@ function textResult(result, write) {
|
|
|
1079
1246
|
write("Setup completed:");
|
|
1080
1247
|
write(` Client targets: ${result.clients.join(", ")}`);
|
|
1081
1248
|
for (const skill of result.skills) {
|
|
1082
|
-
write(` Skill: ${skill.status} at ${skill.target} (${skill.clients.join(", ")})`);
|
|
1249
|
+
write(` Skill suite: ${skill.status} at ${skill.target} (${skill.clients.join(", ")})`);
|
|
1250
|
+
write(` Entries: ${skill.entries.map((entry) => entry.name).join(", ")}`);
|
|
1083
1251
|
}
|
|
1084
1252
|
for (const warning of result.warnings) {
|
|
1085
1253
|
write(` Warning: ${warning}`);
|
|
@@ -1124,7 +1292,10 @@ export async function runSetup(options, dependencies = {}) {
|
|
|
1124
1292
|
options,
|
|
1125
1293
|
targetSelection.clients,
|
|
1126
1294
|
environment,
|
|
1127
|
-
dependencies.
|
|
1295
|
+
dependencies.bundledSkillsDir
|
|
1296
|
+
|| (dependencies.bundledSkillDir
|
|
1297
|
+
? path.dirname(dependencies.bundledSkillDir)
|
|
1298
|
+
: BUNDLED_SKILLS_DIR),
|
|
1128
1299
|
platform,
|
|
1129
1300
|
);
|
|
1130
1301
|
const skillInstalls = layouts.map((layout) => ({
|
|
@@ -1220,14 +1391,17 @@ export async function runSetup(options, dependencies = {}) {
|
|
|
1220
1391
|
progress,
|
|
1221
1392
|
options.json,
|
|
1222
1393
|
);
|
|
1223
|
-
const skills = await progress.run("Installing
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1394
|
+
const skills = await progress.run("Installing msd skill suites", async () => {
|
|
1395
|
+
const installedSuites = installBundledSkillSuites(
|
|
1396
|
+
skillInstalls.map(({ details }) => details),
|
|
1397
|
+
);
|
|
1398
|
+
return installedSuites.map((installedSuite, index) => ({
|
|
1399
|
+
kind: skillInstalls[index].layout.kind,
|
|
1400
|
+
clients: skillInstalls[index].layout.clients,
|
|
1401
|
+
target: skillInstalls[index].layout.skillsDir,
|
|
1402
|
+
...installedSuite,
|
|
1403
|
+
}));
|
|
1404
|
+
});
|
|
1231
1405
|
const result = {
|
|
1232
1406
|
state: "ready",
|
|
1233
1407
|
git: gitVersion,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "msdevflow",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "Install the msdevflow GitCode skill and its runtime dependencies",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"bin/",
|
|
11
11
|
"lib/",
|
|
12
12
|
"skill/",
|
|
13
|
-
"!skill
|
|
13
|
+
"!skill/**/scripts/test_openlibing_ci.py",
|
|
14
14
|
"!skill/**/__pycache__/**",
|
|
15
15
|
"!skill/**/*.pyc"
|
|
16
16
|
],
|
|
@@ -1,22 +1,25 @@
|
|
|
1
|
-
#
|
|
1
|
+
# msd
|
|
2
2
|
|
|
3
|
-
通用 GitCode Issue 到 PR 合入 workflow
|
|
3
|
+
通用 GitCode Issue 到 PR 合入 workflow Skill 套件。业务规则只存在于核心 `msd`;十个 `msd-<action>` 薄路由 Skill 让 Claude Code、Codex 和 OpenCode 在输入阶段展示并补全可用 action。
|
|
4
4
|
|
|
5
5
|
## 1. Action 模型
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
输入 `/msd-`(Claude Code/OpenCode)或 `$msd-`(Codex)即可筛选:
|
|
8
8
|
|
|
9
9
|
```text
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
msd-discover
|
|
11
|
+
msd-create-issue
|
|
12
|
+
msd-issue
|
|
13
|
+
msd-develop
|
|
14
|
+
msd-pr
|
|
15
|
+
msd-ci
|
|
16
|
+
msd-openlibing-auth
|
|
17
|
+
msd-feedback
|
|
18
|
+
msd-code-review
|
|
19
|
+
msd-merge
|
|
17
20
|
```
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
每个薄路由只固定唯一 action、保留调用正文,并从相对路径 `../msd/SKILL.md` 加载同一 skills 根目录中的核心,不复制业务规则;核心 references 继续以 `../msd/` 为基准。直接调用核心 `msd` 会运行完整作者 E2E,不会在提交后弹出 Question 菜单;`/msd action=<name>`、`$msd action=<name>` 仍作为兼容调用,但参数本身没有跨客户端枚举下拉。
|
|
20
23
|
|
|
21
24
|
支持:
|
|
22
25
|
|
|
@@ -42,7 +45,7 @@ Claude Code 使用 `AskUserQuestion`,Codex 使用 `request_user_input`,OpenC
|
|
|
42
45
|
|
|
43
46
|
## 2. 完整作者 E2E
|
|
44
47
|
|
|
45
|
-
|
|
48
|
+
直接调用核心 `msd` 且不提供 `action=` 时,从环境、CLI 能力和仓库画像开始运行完整流程:
|
|
46
49
|
|
|
47
50
|
```text
|
|
48
51
|
discover -> issue -> develop -> pr -> ci
|
|
@@ -69,12 +72,12 @@ discover -> issue -> develop -> pr -> ci
|
|
|
69
72
|
|
|
70
73
|
## 4. 调用示例
|
|
71
74
|
|
|
72
|
-
以下示例使用 Claude Code 的 `/
|
|
75
|
+
以下示例使用 Claude Code 的 `/msd` 形式。Codex 使用 `$msd`,OpenCode 可从 `/skills` 选择 `msd`;OpenCode 的 `@` 不用于 Skill。单项能力优先使用各客户端输入补全中的 `msd-<action>`,正文中的任务参数保持不变。
|
|
73
76
|
|
|
74
|
-
###
|
|
77
|
+
### 运行完整 E2E
|
|
75
78
|
|
|
76
79
|
```text
|
|
77
|
-
/
|
|
80
|
+
/msd
|
|
78
81
|
处理 https://gitcode.com/Ascend/example/issues/123。
|
|
79
82
|
本地仓库:D:\work\example
|
|
80
83
|
canonical:Ascend/example
|
|
@@ -85,7 +88,7 @@ Fork:myname/example
|
|
|
85
88
|
### 只发现候选 Issue
|
|
86
89
|
|
|
87
90
|
```text
|
|
88
|
-
/
|
|
91
|
+
/msd-discover
|
|
89
92
|
查询 Ascend/example 中分配给当前账号的开放 Issue,列出仍需处理的候选。
|
|
90
93
|
```
|
|
91
94
|
|
|
@@ -94,7 +97,7 @@ Fork:myname/example
|
|
|
94
97
|
### 只创建 Issue
|
|
95
98
|
|
|
96
99
|
```text
|
|
97
|
-
/
|
|
100
|
+
/msd-create-issue
|
|
98
101
|
在 Ascend/example 提一个 bug:升级后首次启动失败,错误信息和环境如下……
|
|
99
102
|
使用 guided 模式,先给我完整预览,确认后再创建。
|
|
100
103
|
```
|
|
@@ -106,7 +109,7 @@ Fork:myname/example
|
|
|
106
109
|
### 只接取和核验 Issue
|
|
107
110
|
|
|
108
111
|
```text
|
|
109
|
-
/
|
|
112
|
+
/msd-issue
|
|
110
113
|
处理 https://gitcode.com/Ascend/example/issues/123。
|
|
111
114
|
本地仓库:D:\work\example
|
|
112
115
|
```
|
|
@@ -116,7 +119,7 @@ Fork:myname/example
|
|
|
116
119
|
### 只开发和本地验证
|
|
117
120
|
|
|
118
121
|
```text
|
|
119
|
-
/
|
|
122
|
+
/msd-develop
|
|
120
123
|
Issue:https://gitcode.com/Ascend/example/issues/123
|
|
121
124
|
本地仓库:D:\work\example
|
|
122
125
|
```
|
|
@@ -126,7 +129,7 @@ Issue:https://gitcode.com/Ascend/example/issues/123
|
|
|
126
129
|
### 只创建 PR
|
|
127
130
|
|
|
128
131
|
```text
|
|
129
|
-
/
|
|
132
|
+
/msd-pr
|
|
130
133
|
Issue:https://gitcode.com/Ascend/example/issues/123
|
|
131
134
|
本地仓库:D:\work\example
|
|
132
135
|
canonical:Ascend/example
|
|
@@ -138,7 +141,7 @@ source:myname/example
|
|
|
138
141
|
### 只处理 CI
|
|
139
142
|
|
|
140
143
|
```text
|
|
141
|
-
/
|
|
144
|
+
/msd-ci
|
|
142
145
|
PR:https://gitcode.com/Ascend/example/pulls/456
|
|
143
146
|
本地仓库:D:\work\example
|
|
144
147
|
```
|
|
@@ -148,7 +151,7 @@ CI 通过后立即停止,不处理 feedback 或 merge。识别为 openLiBing
|
|
|
148
151
|
### 只验证 openLiBing OAuth
|
|
149
152
|
|
|
150
153
|
```text
|
|
151
|
-
/
|
|
154
|
+
/msd-openlibing-auth
|
|
152
155
|
本地仓库:D:\work\example
|
|
153
156
|
```
|
|
154
157
|
|
|
@@ -159,7 +162,7 @@ CI 通过后立即停止,不处理 feedback 或 merge。识别为 openLiBing
|
|
|
159
162
|
### 只处理自己 PR 的意见
|
|
160
163
|
|
|
161
164
|
```text
|
|
162
|
-
/
|
|
165
|
+
/msd-feedback
|
|
163
166
|
PR:https://gitcode.com/Ascend/example/pulls/456
|
|
164
167
|
本地仓库:D:\work\example
|
|
165
168
|
```
|
|
@@ -169,7 +172,7 @@ PR:https://gitcode.com/Ascend/example/pulls/456
|
|
|
169
172
|
### 检视他人的 PR
|
|
170
173
|
|
|
171
174
|
```text
|
|
172
|
-
/
|
|
175
|
+
/msd-code-review
|
|
173
176
|
PR:https://gitcode.com/Ascend/example/pulls/789
|
|
174
177
|
```
|
|
175
178
|
|
|
@@ -180,7 +183,7 @@ PR:https://gitcode.com/Ascend/example/pulls/789
|
|
|
180
183
|
### 只核验并合入
|
|
181
184
|
|
|
182
185
|
```text
|
|
183
|
-
/
|
|
186
|
+
/msd-merge
|
|
184
187
|
PR:https://gitcode.com/Ascend/example/pulls/456
|
|
185
188
|
```
|
|
186
189
|
|
|
@@ -224,7 +227,7 @@ GitCode CLI 会打开官方页面让用户创建 Token,再在 CLI 自己的终
|
|
|
224
227
|
|
|
225
228
|
## 6. 安装
|
|
226
229
|
|
|
227
|
-
npm
|
|
230
|
+
npm 包 `msdevflow` 同时携带 `msd` Skill 套件和 setup 程序。首次安装:
|
|
228
231
|
|
|
229
232
|
```bash
|
|
230
233
|
npx msdevflow setup
|
|
@@ -240,7 +243,7 @@ npx msdevflow@latest setup
|
|
|
240
243
|
|
|
241
244
|
`setup` 默认检测 PATH 中的 Claude Code、Codex 和 OpenCode,先展示客户端、物理 skill 目标、安装或更新状态、GitCode CLI 归属、registry、安装模式、Python 依赖命令和认证方式;用户确认后,在同一次运行中:
|
|
242
245
|
|
|
243
|
-
1. 从 npm
|
|
246
|
+
1. 从 npm 包内的 `skill/msd` 核心和十个 `skill/msd-<action>` 路由器原子安装或更新整套入口;
|
|
244
247
|
2. 安装或升级官方 GitCode npm CLI;
|
|
245
248
|
3. 安装内置 `scripts/requirements.txt` 中的 Python Playwright 包;
|
|
246
249
|
4. 验收 workflow 所需 schema/API;
|
|
@@ -249,15 +252,17 @@ npx msdevflow@latest setup
|
|
|
249
252
|
客户端到物理目录的映射:
|
|
250
253
|
|
|
251
254
|
```text
|
|
252
|
-
Claude Code -> ~/.claude/skills/
|
|
253
|
-
Codex -> ~/.agents/skills/
|
|
254
|
-
仅 OpenCode -> ~/.agents/skills/
|
|
255
|
+
Claude Code -> ~/.claude/skills/{msd,msd-*}
|
|
256
|
+
Codex -> ~/.agents/skills/{msd,msd-*}
|
|
257
|
+
仅 OpenCode -> ~/.agents/skills/{msd,msd-*}
|
|
255
258
|
OpenCode + Claude Code -> 复用 Claude 目标
|
|
256
259
|
OpenCode + Codex -> 复用 Agent Skills 目标
|
|
257
|
-
Claude Code + Codex ->
|
|
258
|
-
三者同时安装 ->
|
|
260
|
+
Claude Code + Codex -> 两套受管副本
|
|
261
|
+
三者同时安装 -> 两套受管副本,并提示 OpenCode 双路径发现
|
|
259
262
|
```
|
|
260
263
|
|
|
264
|
+
每个物理目标都包含一个 `msd` 核心和十个 `msd-<action>` 路由器;业务规则仍只有一份。
|
|
265
|
+
|
|
261
266
|
显式选择客户端、只读预检或自定义目录:
|
|
262
267
|
|
|
263
268
|
```bash
|
|
@@ -277,7 +282,7 @@ npm 包尚未发布时,可从当前源码/发布目录运行等价入口:
|
|
|
277
282
|
node ./msdevflow/bin/msdevflow.js setup
|
|
278
283
|
```
|
|
279
284
|
|
|
280
|
-
`setup` 不下载或启动 Chromium。GitCode Token 只由 GitCode CLI 自己的终端提示接收并验证;setup 父进程不读取、输出或转存 Token,也不要求用户把 Token 传给 Agent。每个已有
|
|
285
|
+
`setup` 不下载或启动 Chromium。GitCode Token 只由 GitCode CLI 自己的终端提示接收并验证;setup 父进程不读取、输出或转存 Token,也不要求用户把 Token 传给 Agent。每个已有 `msd` 或 `msd-<action>` entry 的 manifest 都必须精确匹配自身名称才允许更新;来源不明的目录、文件或符号链接会阻断整套安装。旧 `msdevflow` 目录只有在 manifest 精确证明由本包管理时,才会在新套件全部切换并验证后安全迁移;失败时回滚整套变更。安装后重启或重新加载对应客户端。
|
|
281
286
|
|
|
282
287
|
## 7. 仓库画像和 PR 模板
|
|
283
288
|
|
|
@@ -1,52 +1,43 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: msd
|
|
3
3
|
description: >
|
|
4
|
-
通用 GitCode Issue 到 PR
|
|
4
|
+
通用 GitCode Issue 到 PR 合入工作流核心。直接调用 msd 时运行完整作者端到端流程;也接受 action=discover、create-issue、issue、develop、pr、ci、openlibing-auth、feedback、code-review 或 merge 兼容参数。推荐通过独立的 msd-<action> Skill 在输入时发现并选择单项能力。适用于发现、新建或接取 GitCode Issue、开发并创建 PR、处理 CI、验证 openLiBing OAuth、处理自己 PR 的检视意见、检视他人 PR,以及在独立审批和显式确认后合入。仅适用于已授权的 GitCode 仓库。
|
|
5
5
|
compatibility: Requires Git, Node.js >=18, Python >=3.10, GitCode access, and the setup-installed GitCode CLI. Supports Claude Code, Codex, and OpenCode.
|
|
6
6
|
metadata:
|
|
7
|
-
version:
|
|
7
|
+
version: 3.0.0
|
|
8
8
|
source: msdevflow
|
|
9
|
+
role: core
|
|
9
10
|
---
|
|
10
11
|
|
|
11
|
-
#
|
|
12
|
+
# msd:GitCode Issue 到 PR 合入
|
|
12
13
|
|
|
13
|
-
把 GitCode
|
|
14
|
+
把 GitCode 工作拆成可独立发现和调用的 action,不硬编码组织、默认分支、CI、分支命名、合并方式或机器人协议。安装套件同时提供核心 `msd` 和十个薄路由 Skill:Claude Code 与 OpenCode 输入 `/msd-`、Codex 输入 `$msd-`,即可在客户端的 Skill 补全中查看 action。
|
|
14
15
|
|
|
15
16
|
## Action 路由
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
推荐入口为 `msd-<action>`。薄路由 Skill 只固定一个 action、保留调用正文并加载本核心,不复制业务规则。核心也兼容字面量参数 `action=<name>`;显式 action 直接路由,未知 action 停止并列出有效值,不做远端写入。
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
直接调用核心 `msd` 且没有 `action=` 时,运行完整作者 E2E,不显示运行时 Question 菜单,也不根据自然语言改成某个独立 action。完整 E2E 内部按权威证据定位当前阶段并渐进加载规则。
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
若薄路由 Skill 固定的 action 与调用正文中的 `action=` 冲突,停止为 `blocked: action-conflict`,不得猜测或执行远端写入。
|
|
23
|
+
|
|
24
|
+
可发现入口:
|
|
22
25
|
|
|
23
26
|
```text
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
│ └─ PR 后续
|
|
36
|
-
│ ├─ feedback
|
|
37
|
-
│ └─ merge
|
|
38
|
-
└─ 独立工具
|
|
39
|
-
├─ openlibing-auth
|
|
40
|
-
└─ code-review
|
|
27
|
+
msd
|
|
28
|
+
msd-discover
|
|
29
|
+
msd-create-issue
|
|
30
|
+
msd-issue
|
|
31
|
+
msd-develop
|
|
32
|
+
msd-pr
|
|
33
|
+
msd-ci
|
|
34
|
+
msd-openlibing-auth
|
|
35
|
+
msd-feedback
|
|
36
|
+
msd-code-review
|
|
37
|
+
msd-merge
|
|
41
38
|
```
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
1. 顶层“完整端到端流程”不是 action;选中后按“完整作者 E2E”执行,并在内部将本次路由记为 `full-e2e`。
|
|
46
|
-
2. 每级原生菜单都把推荐项放在首位,并按宿主约定标明推荐:顶层推荐“完整端到端流程”;作者工作流分类推荐“Issue 管理”;各叶子层分别推荐 `discover`、`develop`、`feedback` 和 `openlibing-auth`。不得为了改变推荐项而提前探测仓库或远端。
|
|
47
|
-
3. 选中叶子 action 后,等同于用户显式提供了对应 `action=<name>`,严格遵守显式 action 契约;保留调用正文中已经给出的 URL、路径、仓库和模式等参数。
|
|
48
|
-
4. 宿主没有可用选择工具、选择工具在当前模式被禁用,或处于非交互运行时,只输出当前层的编号文本选项并停止等待用户回复;不得自行选择默认项,也不得把多层菜单一次性展开。
|
|
49
|
-
5. 只要调用中没有字面量 `action=<name>`,即使自然语言看似指向某个流程,也必须从顶层菜单开始;不得根据意图猜测跳过菜单。菜单选择属于当前 skill 调用,选定后立即继续,不要求用户重新输入 `/msdevflow`。
|
|
40
|
+
薄路由选定后,等同于向本核心显式提供对应 `action=<name>`,并严格遵守显式 action 契约。
|
|
50
41
|
|
|
51
42
|
| action | 目标 | 主要输入 | 完成后立即停止于 | 必读文件 |
|
|
52
43
|
|---|---|---|---|---|
|
|
@@ -61,7 +52,7 @@ metadata:
|
|
|
61
52
|
| `code-review` | 检视他人的 PR,发布 finding 或 `/lgtm` | 他人 PR | `review-findings`、`review-passed`、`review-incomplete`、`waiting` 或 `blocked` | [references/code-review.md](references/code-review.md) |
|
|
62
53
|
| `merge` | 核验门禁并在最终确认后合入 | canonical PR | `merged`、`waiting` 或 `blocked` | [references/review-and-merge.md](references/review-and-merge.md) |
|
|
63
54
|
|
|
64
|
-
`code-review`
|
|
55
|
+
`code-review` 只能通过 `msd-code-review` 或兼容参数 `action=code-review` 独立调用,永不进入作者 E2E,不得检视或批准当前账号自己的 PR。它固定当前 head,完整检视权威 diff、必要上下文和既有 discussions:有高置信度问题时发布经确认且逐字回读的 finding,不发送 `/lgtm`;没有问题、没有有效未解决意见且覆盖完整时,在针对当前 PR/head 明确确认后先发布带尾签摘要,再原样发送 `/lgtm`。它不发送 `/approve`、`/merge`,不修改作者代码。
|
|
65
56
|
|
|
66
57
|
## 显式 action 契约
|
|
67
58
|
|
|
@@ -75,7 +66,7 @@ metadata:
|
|
|
75
66
|
|
|
76
67
|
## 完整作者 E2E
|
|
77
68
|
|
|
78
|
-
|
|
69
|
+
直接调用核心 `msd` 且未提供 `action=` 时,从 Phase 0 环境、CLI 能力和仓库画像开始运行完整流程;调用正文可以提供完整 E2E 所需的 URL、路径、仓库和模式。“从头开始”只表示重新读取事实,不表示重复创建资源或重复评论。按证据幂等跳过已完成步骤:
|
|
79
70
|
|
|
80
71
|
```text
|
|
81
72
|
discover -> issue -> develop -> pr -> ci
|
|
@@ -97,7 +88,7 @@ discover -> issue -> develop -> pr -> ci
|
|
|
97
88
|
1. 固定 `gitcode_command`:无 Python 同名工具时为 `gitcode`;有 Python `gitcode` 时保留它并使用 `gitcode-npm`。来源不明时停止,不覆盖。
|
|
98
89
|
2. 检查当前目录;若不是 Git 仓库,自动探测直接子目录中的 Git 仓库及 remotes。
|
|
99
90
|
3. 确认 canonical repository、source repository、operation target、当前账号和授权范围。
|
|
100
|
-
4. 除纯只读 `discover` 外,显式 action 先从 [references/setup-and-issue.md](references/setup-and-issue.md) 只读取公共环境、仓库上下文和最小充分仓库画像,不执行其中的 Issue 接取业务;随后只加载该 action 对应 reference 及实际触发的深层规则。`create-issue` 的模板选择和写入只按 [references/create-issue.md](references/create-issue.md),不执行候选发现或既有 Issue 核验。`code-review` 只使用公共只读画像和 [references/code-review.md](references/code-review.md),不加载作者 feedback/merge
|
|
91
|
+
4. 除纯只读 `discover` 外,显式 action 先从 [references/setup-and-issue.md](references/setup-and-issue.md) 只读取公共环境、仓库上下文和最小充分仓库画像,不执行其中的 Issue 接取业务;随后只加载该 action 对应 reference 及实际触发的深层规则。`create-issue` 的模板选择和写入只按 [references/create-issue.md](references/create-issue.md),不执行候选发现或既有 Issue 核验。`code-review` 只使用公共只读画像和 [references/code-review.md](references/code-review.md),不加载作者 feedback/merge 规则。完整作者 E2E 也只按当前位置渐进加载。
|
|
101
92
|
5. CLI 缺失、命令不兼容或版本不足时读 [references/command-capabilities.md](references/command-capabilities.md),停止当前 action 并提示用户运行独立 setup;setup 成功后恢复原 action。
|
|
102
93
|
6. 进入 autonomous、远端写、危险动作或恢复时读 [references/state-and-safety.md](references/state-and-safety.md)。
|
|
103
94
|
7. 中断恢复、写结果不确定或最终报告时读 [references/recovery.md](references/recovery.md)。
|
|
@@ -107,7 +107,7 @@ commit/head SHA
|
|
|
107
107
|
- 不采纳:spec/代码/测试依据;
|
|
108
108
|
6. 统一换行为 `\n` 后逐字比较完整远端回复与预期正文,并验证末尾恰好存在一次尾签;发现 `?`、乱码、截断、尾签缺失、重复或其他不一致时先原地修复,未修复前不得 resolve;
|
|
109
109
|
7. 正文回读通过后,仓库规则允许且权限具备时 resolve,再回读确认 `resolved=true`;
|
|
110
|
-
8. 产生新 head 时,显式 `action=feedback` 停止并建议 `action=ci
|
|
110
|
+
8. 产生新 head 时,显式 `action=feedback` 停止并建议 `action=ci`;核心 `msd` 启动的完整作者 E2E 由编排器随后路由到 `ci`。
|
|
111
111
|
|
|
112
112
|
不要只发一条总体总结替代逐条回复。汇总应在逐条闭环后发布。
|
|
113
113
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Action `create-issue`
|
|
2
2
|
|
|
3
|
-
显式 `action=create-issue` 用于在一个已授权的 canonical repository 中创建一个 GitCode Issue。它是独立 action:创建并回读确认后立即停止,不执行 `discover`、`issue`、接取、查重、代码核验、开发或 PR
|
|
3
|
+
显式 `action=create-issue` 用于在一个已授权的 canonical repository 中创建一个 GitCode Issue。它是独立 action:创建并回读确认后立即停止,不执行 `discover`、`issue`、接取、查重、代码核验、开发或 PR 流程,也不进入核心 `msd` 启动的完整作者 E2E。
|
|
4
4
|
|
|
5
5
|
## 输入和边界
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Action `develop`:分析、设计与开发
|
|
2
2
|
|
|
3
|
-
只在显式 `action=develop
|
|
3
|
+
只在显式 `action=develop`,或核心 `msd` 启动的完整作者 E2E 已达到 `verified` 时读取。显式 action 启动时先只读确认 Issue 已核验且没有重复实现;前置不足时返回 `blocked` 并建议 `action=issue`,不得自动接取或补跑核验。
|
|
4
4
|
|
|
5
5
|
## Phase 3:需求分析与设计决策树
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Action `pr` 与 `ci`
|
|
2
2
|
|
|
3
|
-
只在显式 `action=pr`、`action=ci
|
|
3
|
+
只在显式 `action=pr`、`action=ci`,或核心 `msd` 启动的完整作者 E2E 路由到对应位置时读取。任何远端写前同时读取 [state-and-safety.md](state-and-safety.md)。CI 触发或失败时再读取 [ci-and-review.md](ci-and-review.md),不要提前加载。
|
|
4
4
|
|
|
5
5
|
## Action `pr`:Commit、Push、普通 PR
|
|
6
6
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
4. 根据 action 完成条件识别最后一个有证据的状态;不能只信先前摘要或旧 run 产物。
|
|
15
15
|
5. 验证本地分支与远端 source head 是否一致。
|
|
16
16
|
6. 显式 action 只判断自身前置和完成条件:前置缺失时 `blocked`,不得运行上游;已完成时报告证据并立即停止。
|
|
17
|
-
7.
|
|
17
|
+
7. 核心 `msd` 启动的完整作者 E2E 从 Phase 0 重建仓库画像,再路由到下一未完成作者 action;不重复已完成的写操作。
|
|
18
18
|
8. `create-issue` 不执行产品查重;仅在本次创建结果不确定时按目标仓库、当前账号、启动时间、标题和完整正文做有界恢复,无法唯一证明时停止。`openlibing-auth` 的历史 profile 或旧认证摘要不证明当前授权有效;必须用本次固定 run 做真实只读请求。
|
|
19
19
|
9. `code-review` 不参与作者 E2E,也不从作者 feedback 状态恢复。恢复时重新确认 reviewer、author、PR 状态和当前 head;旧 `review_head_sha` 的分析、摘要、finding 或 `/lgtm` 不证明当前 head 已检视。
|
|
20
20
|
10. 当前 head 等于旧 `review_head_sha` 时,回读结构化 comments/discussions,并按 reviewer、head、path/position 和完整正文恢复已发布 finding;检视通过必须同时回读到绑定当前 head 的带尾签摘要和同一 reviewer 的精确 `/lgtm`。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Action `feedback` 与 `merge`
|
|
2
2
|
|
|
3
|
-
只在显式 `action=feedback`、`action=merge
|
|
3
|
+
只在显式 `action=feedback`、`action=merge`,或核心 `msd` 启动的完整作者 E2E 路由到对应位置时读取。开始时同时读取 [state-and-safety.md](state-and-safety.md);处理结构化 discussion 或 CI 时按需读取 [ci-and-review.md](ci-and-review.md)。本文件不定义 `action=code-review`。
|
|
4
4
|
|
|
5
5
|
## Action `feedback`:处理自己 PR 的检视意见
|
|
6
6
|
|
|
@@ -31,7 +31,7 @@ PR 不存在时返回 `blocked` 并建议 `action=pr`;source branch 不可写
|
|
|
31
31
|
6. 创建新 commit 并 push,不 amend、不 force push;
|
|
32
32
|
7. 每条 discussion 在线程内回复:已修复引用 commit;部分采纳、不采纳或延期说明依据;每条回复按 [state-and-safety.md](state-and-safety.md) 使用 UTF-8 安全通道并附加唯一尾签,逐字回读完整正文;
|
|
33
33
|
8. 只有回复正文和尾签回读一致后,仓库规则和权限允许时才 resolve;乱码、`?`、截断或不一致时先原地修复;
|
|
34
|
-
9. 产生新 head 时记录旧 CI 结果已失效,停止后建议 `action=ci`;不得在显式 `feedback` 内触发或监控远端 CI
|
|
34
|
+
9. 产生新 head 时记录旧 CI 结果已失效,停止后建议 `action=ci`;不得在显式 `feedback` 内触发或监控远端 CI。核心 `msd` 启动的完整作者 E2E 由编排器随后路由到 `ci`。
|
|
35
35
|
|
|
36
36
|
不要以一条总体评论替代逐条回复。处理完成后不请求重新检视、不触发检视机器人;外部 reviewer 是否重新检视由仓库和人员流程决定。
|
|
37
37
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Action `discover` 与 `issue`
|
|
2
2
|
|
|
3
|
-
在显式 `action=discover`、`action=issue
|
|
3
|
+
在显式 `action=discover`、`action=issue`,或核心 `msd` 启动的完整作者 E2E 启动时读取;显式 `action=create-issue` 只读取本文件的公共环境、仓库上下文和最小充分画像,模板和写入业务转到 [create-issue.md](create-issue.md),不得执行本文件的发现、接取或重复实现核验。`discover` 全程只读并在候选报告后立即停止;`issue` 只接取和核验指定 Issue,达到 `verified` 后立即停止,不进入开发。
|
|
4
4
|
|
|
5
5
|
显式 `action=issue` 必须提供 Issue URL 或编号。缺少目标时只做确认输入缺失所需的只读核验,随后返回 `blocked` 并建议先运行 `action=discover`;不得在本 action 内查询候选、让用户选择 Issue 或执行 `discover` 的业务。
|
|
6
6
|
|
|
@@ -98,7 +98,7 @@ pr_number(如已有)
|
|
|
98
98
|
|
|
99
99
|
## Phase 1:发现与接取
|
|
100
100
|
|
|
101
|
-
显式 `action=issue` 直接读取输入中的 Issue URL/编号;缺少目标时按本文件入口规则返回 `blocked`。显式 `action=discover`
|
|
101
|
+
显式 `action=issue` 直接读取输入中的 Issue URL/编号;缺少目标时按本文件入口规则返回 `blocked`。显式 `action=discover` 或核心 `msd` 启动的完整作者 E2E 尚无目标时,才对“无目标发现”确认出的每个 canonical 查询当前用户负责的开放 Issue:
|
|
102
102
|
|
|
103
103
|
```bash
|
|
104
104
|
<gitcode-command> issue list -R <canonical> --state open --assignee <username> --json
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: msd-ci
|
|
3
|
+
description: 监控、诊断并修复当前 GitCode PR 的 CI,结果严格绑定当前 head SHA。
|
|
4
|
+
compatibility: Requires the sibling msd core skill.
|
|
5
|
+
metadata:
|
|
6
|
+
source: msdevflow
|
|
7
|
+
role: action-router
|
|
8
|
+
action: ci
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# msd ci router
|
|
12
|
+
|
|
13
|
+
先读取并完整遵循相对路径 `../msd/SKILL.md`(同一 skills 根目录中的 `msd` 核心),以固定参数 `action=ci` 执行;核心引用的相对路径均以 `../msd/` 为基准。原样保留本次调用正文中的 URL、路径、仓库、模式和其他参数;若正文包含不同的 `action=`,按核心规则停止为 `blocked: action-conflict`。无法读取核心时停止为 `blocked: core-skill-unavailable`。
|
|
14
|
+
|
|
15
|
+
本路由只固定 action,不实现或复制业务规则。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: msd-code-review
|
|
3
|
+
description: 独立检视他人的 GitCode PR,发布高置信度 finding,或确认后评论精确的 /lgtm。
|
|
4
|
+
compatibility: Requires the sibling msd core skill.
|
|
5
|
+
metadata:
|
|
6
|
+
source: msdevflow
|
|
7
|
+
role: action-router
|
|
8
|
+
action: code-review
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# msd code-review router
|
|
12
|
+
|
|
13
|
+
先读取并完整遵循相对路径 `../msd/SKILL.md`(同一 skills 根目录中的 `msd` 核心),以固定参数 `action=code-review` 执行;核心引用的相对路径均以 `../msd/` 为基准。原样保留本次调用正文中的 URL、路径、仓库、模式和其他参数;若正文包含不同的 `action=`,按核心规则停止为 `blocked: action-conflict`。无法读取核心时停止为 `blocked: core-skill-unavailable`。
|
|
14
|
+
|
|
15
|
+
本路由只固定 action,不实现或复制业务规则。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: msd-create-issue
|
|
3
|
+
description: 按目标仓库或 Ascend community 的同类型模板创建一个 GitCode Issue,并回读验证。
|
|
4
|
+
compatibility: Requires the sibling msd core skill.
|
|
5
|
+
metadata:
|
|
6
|
+
source: msdevflow
|
|
7
|
+
role: action-router
|
|
8
|
+
action: create-issue
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# msd create-issue router
|
|
12
|
+
|
|
13
|
+
先读取并完整遵循相对路径 `../msd/SKILL.md`(同一 skills 根目录中的 `msd` 核心),以固定参数 `action=create-issue` 执行;核心引用的相对路径均以 `../msd/` 为基准。原样保留本次调用正文中的 URL、路径、仓库、模式和其他参数;若正文包含不同的 `action=`,按核心规则停止为 `blocked: action-conflict`。无法读取核心时停止为 `blocked: core-skill-unavailable`。
|
|
14
|
+
|
|
15
|
+
本路由只固定 action,不实现或复制业务规则。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: msd-develop
|
|
3
|
+
description: 分析并实现已核验的 GitCode Issue,从最新 canonical 基线建分支并完成本地验证。
|
|
4
|
+
compatibility: Requires the sibling msd core skill.
|
|
5
|
+
metadata:
|
|
6
|
+
source: msdevflow
|
|
7
|
+
role: action-router
|
|
8
|
+
action: develop
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# msd develop router
|
|
12
|
+
|
|
13
|
+
先读取并完整遵循相对路径 `../msd/SKILL.md`(同一 skills 根目录中的 `msd` 核心),以固定参数 `action=develop` 执行;核心引用的相对路径均以 `../msd/` 为基准。原样保留本次调用正文中的 URL、路径、仓库、模式和其他参数;若正文包含不同的 `action=`,按核心规则停止为 `blocked: action-conflict`。无法读取核心时停止为 `blocked: core-skill-unavailable`。
|
|
14
|
+
|
|
15
|
+
本路由只固定 action,不实现或复制业务规则。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: msd-discover
|
|
3
|
+
description: 只读发现当前 GitCode 账号负责且仍需处理的候选 Issue,并列出候选与排除证据。
|
|
4
|
+
compatibility: Requires the sibling msd core skill.
|
|
5
|
+
metadata:
|
|
6
|
+
source: msdevflow
|
|
7
|
+
role: action-router
|
|
8
|
+
action: discover
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# msd discover router
|
|
12
|
+
|
|
13
|
+
先读取并完整遵循相对路径 `../msd/SKILL.md`(同一 skills 根目录中的 `msd` 核心),以固定参数 `action=discover` 执行;核心引用的相对路径均以 `../msd/` 为基准。原样保留本次调用正文中的 URL、路径、仓库、模式和其他参数;若正文包含不同的 `action=`,按核心规则停止为 `blocked: action-conflict`。无法读取核心时停止为 `blocked: core-skill-unavailable`。
|
|
14
|
+
|
|
15
|
+
本路由只固定 action,不实现或复制业务规则。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: msd-feedback
|
|
3
|
+
description: 处理当前账号自己 GitCode PR 的检视意见,验证并推送修改,逐条回复 discussion。
|
|
4
|
+
compatibility: Requires the sibling msd core skill.
|
|
5
|
+
metadata:
|
|
6
|
+
source: msdevflow
|
|
7
|
+
role: action-router
|
|
8
|
+
action: feedback
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# msd feedback router
|
|
12
|
+
|
|
13
|
+
先读取并完整遵循相对路径 `../msd/SKILL.md`(同一 skills 根目录中的 `msd` 核心),以固定参数 `action=feedback` 执行;核心引用的相对路径均以 `../msd/` 为基准。原样保留本次调用正文中的 URL、路径、仓库、模式和其他参数;若正文包含不同的 `action=`,按核心规则停止为 `blocked: action-conflict`。无法读取核心时停止为 `blocked: core-skill-unavailable`。
|
|
14
|
+
|
|
15
|
+
本路由只固定 action,不实现或复制业务规则。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: msd-issue
|
|
3
|
+
description: 接取并核验指定 GitCode Issue,检查关联 PR、默认分支和重复实现证据。
|
|
4
|
+
compatibility: Requires the sibling msd core skill.
|
|
5
|
+
metadata:
|
|
6
|
+
source: msdevflow
|
|
7
|
+
role: action-router
|
|
8
|
+
action: issue
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# msd issue router
|
|
12
|
+
|
|
13
|
+
先读取并完整遵循相对路径 `../msd/SKILL.md`(同一 skills 根目录中的 `msd` 核心),以固定参数 `action=issue` 执行;核心引用的相对路径均以 `../msd/` 为基准。原样保留本次调用正文中的 URL、路径、仓库、模式和其他参数;若正文包含不同的 `action=`,按核心规则停止为 `blocked: action-conflict`。无法读取核心时停止为 `blocked: core-skill-unavailable`。
|
|
14
|
+
|
|
15
|
+
本路由只固定 action,不实现或复制业务规则。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: msd-merge
|
|
3
|
+
description: 核验当前 GitCode PR 的 CI、discussion 和独立审批门禁,并在最终确认后合入。
|
|
4
|
+
compatibility: Requires the sibling msd core skill.
|
|
5
|
+
metadata:
|
|
6
|
+
source: msdevflow
|
|
7
|
+
role: action-router
|
|
8
|
+
action: merge
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# msd merge router
|
|
12
|
+
|
|
13
|
+
先读取并完整遵循相对路径 `../msd/SKILL.md`(同一 skills 根目录中的 `msd` 核心),以固定参数 `action=merge` 执行;核心引用的相对路径均以 `../msd/` 为基准。原样保留本次调用正文中的 URL、路径、仓库、模式和其他参数;若正文包含不同的 `action=`,按核心规则停止为 `blocked: action-conflict`。无法读取核心时停止为 `blocked: core-skill-unavailable`。
|
|
14
|
+
|
|
15
|
+
本路由只固定 action,不实现或复制业务规则。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: msd-openlibing-auth
|
|
3
|
+
description: 在当前 canonical 仓库内固定一个 openLiBing run,并安全验证 GitCode OAuth 只读访问。
|
|
4
|
+
compatibility: Requires the sibling msd core skill.
|
|
5
|
+
metadata:
|
|
6
|
+
source: msdevflow
|
|
7
|
+
role: action-router
|
|
8
|
+
action: openlibing-auth
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# msd openlibing-auth router
|
|
12
|
+
|
|
13
|
+
先读取并完整遵循相对路径 `../msd/SKILL.md`(同一 skills 根目录中的 `msd` 核心),以固定参数 `action=openlibing-auth` 执行;核心引用的相对路径均以 `../msd/` 为基准。原样保留本次调用正文中的 URL、路径、仓库、模式和其他参数;若正文包含不同的 `action=`,按核心规则停止为 `blocked: action-conflict`。无法读取核心时停止为 `blocked: core-skill-unavailable`。
|
|
14
|
+
|
|
15
|
+
本路由只固定 action,不实现或复制业务规则。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: msd-pr
|
|
3
|
+
description: 复验本地实现后 commit、push,并创建和回读验证普通 GitCode PR。
|
|
4
|
+
compatibility: Requires the sibling msd core skill.
|
|
5
|
+
metadata:
|
|
6
|
+
source: msdevflow
|
|
7
|
+
role: action-router
|
|
8
|
+
action: pr
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# msd pr router
|
|
12
|
+
|
|
13
|
+
先读取并完整遵循相对路径 `../msd/SKILL.md`(同一 skills 根目录中的 `msd` 核心),以固定参数 `action=pr` 执行;核心引用的相对路径均以 `../msd/` 为基准。原样保留本次调用正文中的 URL、路径、仓库、模式和其他参数;若正文包含不同的 `action=`,按核心规则停止为 `blocked: action-conflict`。无法读取核心时停止为 `blocked: core-skill-unavailable`。
|
|
14
|
+
|
|
15
|
+
本路由只固定 action,不实现或复制业务规则。
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|