@yottameta/yotta-workflow 0.2.5 → 0.3.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.
- package/README.md +36 -44
- package/README.zh-CN.md +37 -43
- package/SKILL.md +9 -3
- package/bin/install.js +168 -86
- package/package.json +5 -2
- package/references/exception-playbook.md +31 -0
- package/references/faq.md +50 -0
- package/references/walkthroughs.md +25 -0
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ It depends on no specific agent or platform: the state is just Markdown files un
|
|
|
50
50
|
| **Self-contained handoff anchor** | fixed template + enforced validation (content must match state files); next session resumes painlessly |
|
|
51
51
|
| **Lightweight zero-dependency** | plain Markdown files, no daemon / database / injection; readable and writable on any platform |
|
|
52
52
|
| **Gradual adoption** | projects with an existing state mechanism keep it, only satisfying the two mandatory points; low migration cost |
|
|
53
|
-
| **Ecosystem distribution** | GitHub + npm dual-source sync release; npx /
|
|
53
|
+
| **Ecosystem distribution** | GitHub + npm dual-source sync release; four install methods (npx / git clone / Download ZIP / install.sh) covering 17+ agent directories |
|
|
54
54
|
|
|
55
55
|
## Protocol details
|
|
56
56
|
|
|
@@ -134,56 +134,42 @@ It is not needed for one-off read-only questions (e.g. "what does this function
|
|
|
134
134
|
|
|
135
135
|
## Installation
|
|
136
136
|
|
|
137
|
-
Pick any of the
|
|
137
|
+
Pick any of the four methods below; the order is the recommended priority. Skill files always come from **npm** (GitHub can be slow without a proxy; npm supports mirrors).
|
|
138
138
|
|
|
139
|
-
### Method 1: npm
|
|
140
|
-
|
|
139
|
+
### Method 1: npm one-liner (recommended)
|
|
140
|
+
|
|
141
|
+
```text
|
|
141
142
|
# Optional China mirror: npm config set registry https://registry.npmmirror.com
|
|
142
|
-
npx -y @yottameta/yotta-workflow -
|
|
143
|
-
npx -y @yottameta/yotta-workflow --dir <your
|
|
143
|
+
npx -y @yottameta/yotta-workflow --agent <agent-name> # install to the agent's default user-level skills dir
|
|
144
|
+
npx -y @yottameta/yotta-workflow --dir <your-skills-dir> # point to the skills dir itself (e.g. ~/.codex/skills)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
- `--agent <name>` installs to that agent's default user-level directory; `--list` shows each agent's default directory.
|
|
148
|
+
- `--dir <path>` installs to the given directory; for agents not in the preset list, point `--dir` at their skills directory.
|
|
149
|
+
- If the mirror has not synced the new package (404): add `--registry=https://registry.npmjs.org/` (a proxy may be needed in China), or wait for the mirror cache.
|
|
150
|
+
|
|
151
|
+
### Method 2: git clone (developers / git available)
|
|
152
|
+
|
|
153
|
+
```text
|
|
154
|
+
git clone https://github.com/YottaMeta/yotta-workflow.git <your-skills-dir>/yotta-workflow
|
|
144
155
|
```
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
bash install.sh --
|
|
156
|
+
|
|
157
|
+
### Method 3: GitHub Download ZIP (manual / no git)
|
|
158
|
+
|
|
159
|
+
On the GitHub repository `YottaMeta/yotta-workflow`, click **Code → Download ZIP**, unzip it and put the `yotta-workflow` folder into the agent's skills directory.
|
|
160
|
+
|
|
161
|
+
### Method 4: install.sh (multi-agent one-liner script)
|
|
162
|
+
|
|
163
|
+
```text
|
|
164
|
+
bash install.sh --agent <name> # install to the agent's default user-level directory
|
|
165
|
+
bash install.sh --dir <path> # install to the given directory
|
|
166
|
+
bash install.sh --list # list agents -> default directories
|
|
154
167
|
```
|
|
155
|
-
> Covers 17 agent families, including Trae / Qwen / Comate / CodeBuddy / Kimi.
|
|
156
|
-
|
|
157
|
-
### Method 3: manual copy
|
|
158
|
-
Copy the whole `yotta-workflow` folder into the target agent's skills directory. Common user-level locations (`%USERPROFILE%` on Windows, `~` on Linux/macOS):
|
|
159
|
-
|
|
160
|
-
| Agent | User-level directory | Project-level directory |
|
|
161
|
-
|---|---|---|
|
|
162
|
-
| Codex | `%USERPROFILE%\.codex\skills\yotta-workflow\` | `.codex\skills\` |
|
|
163
|
-
| Claude Code | `%USERPROFILE%\.claude\skills\yotta-workflow\` | `.claude\skills\` |
|
|
164
|
-
| Cursor | `%USERPROFILE%\.cursor\skills\yotta-workflow\` | `.cursor\skills\` |
|
|
165
|
-
| Windsurf | `%USERPROFILE%\.codeium\windsurf\skills\yotta-workflow\` | `.windsurf\skills\` |
|
|
166
|
-
| opencode | `%USERPROFILE%\.config\opencode\skills\yotta-workflow\` | `.opencode\skills\` |
|
|
167
|
-
| Gemini | `%USERPROFILE%\.gemini\skills\yotta-workflow\` | `.gemini\skills\` |
|
|
168
|
-
| Goose | `%USERPROFILE%\.config\goose\skills\yotta-workflow\` | `.goose\skills\` |
|
|
169
|
-
| Amp | `%USERPROFILE%\.config\agents\skills\yotta-workflow\` | `.agents\skills\` |
|
|
170
|
-
| Kiro | `%USERPROFILE%\.kiro\skills\yotta-workflow\` | `.kiro\skills\` |
|
|
171
|
-
| WorkBuddy | `%USERPROFILE%\.workbuddy\skills\yotta-workflow\` | `.workbuddy\skills\` |
|
|
172
|
-
| Trae Code CLI | `%USERPROFILE%\.traecli\skills\yotta-workflow\` | `.traecli\skills\` |
|
|
173
|
-
| Trae IDE (CN) | `%USERPROFILE%\.trae-cn\skills\yotta-workflow\` | `.trae\skills\` |
|
|
174
|
-
| Qwen Code | `%USERPROFILE%\.qwen\skills\yotta-workflow\` | `.qwen\skills\` |
|
|
175
|
-
| Comate | `%USERPROFILE%\.comate\skills\yotta-workflow\` | `.comate\skills\` |
|
|
176
|
-
| CodeBuddy | `%USERPROFILE%\.codebuddy\skills\yotta-workflow\` | `.codebuddy\skills\` |
|
|
177
|
-
| Kimi | `%USERPROFILE%\.kimi\skills\yotta-workflow\` | `.kimi\skills\` |
|
|
178
|
-
| Generic AGENTS.md | `%USERPROFILE%\.agents\skills\yotta-workflow\` | `.agents\skills\` |
|
|
179
|
-
|
|
180
|
-
> If Codex's `CODEX_HOME` is set, it overrides the default; the same applies to opencode's `XDG_CONFIG_HOME`. `.agents\skills` is not a universal directory — only OpenCode / Cursor / Cline / Amp / Kimi / Gemini CLI / GitHub Copilot etc. read it; **Claude Code and Codex do not read it by default**. When unsure, use `--dir` or let the agent install it.
|
|
181
|
-
|
|
182
|
-
> Project-level: run `npx -y @yottameta/yotta-workflow` or `bash install.sh` inside the project to install into the detected project-level directory.
|
|
183
168
|
|
|
169
|
+
> Method 1 uses the npm registry (npmmirror / npmjs) and does not depend on GitHub; Methods 2/3 use GitHub and may fail without a proxy in China.
|
|
184
170
|
## Upgrade / uninstall
|
|
185
171
|
|
|
186
|
-
- **Upgrade**: reinstall the latest version to overwrite — `npx -y @yottameta/yotta-workflow
|
|
172
|
+
- **Upgrade**: reinstall the latest version to overwrite — rerun the install command you used (e.g. `npx -y @yottameta/yotta-workflow --agent <name>` or `bash install.sh --agent <name>`). Old files in the skill directory are replaced; the project state files (`.workflow\`) are unaffected.
|
|
187
173
|
- **Uninstall**: delete the `yotta-workflow` folder under the target agent's skills directory (see the table above). Uninstalling does not affect state files already written into a project.
|
|
188
174
|
|
|
189
175
|
## FAQ
|
|
@@ -196,6 +182,12 @@ Copy the whole `yotta-workflow` folder into the target agent's skills directory.
|
|
|
196
182
|
|
|
197
183
|
Run inside this project: `python tools/validate-skill.py yotta-workflow`.
|
|
198
184
|
|
|
185
|
+
## References
|
|
186
|
+
|
|
187
|
+
- references/faq.md
|
|
188
|
+
- references/walkthroughs.md
|
|
189
|
+
- references/exception-playbook.md
|
|
190
|
+
|
|
199
191
|
## License
|
|
200
192
|
|
|
201
193
|
MIT © YottaMeta
|
package/README.zh-CN.md
CHANGED
|
@@ -50,7 +50,7 @@ yotta-workflow 把「跨会话协作」沉淀为一套与智能体无关的协
|
|
|
50
50
|
| **自包含交接锚点** | 固定模板 + 强制校验(内容必须与状态文件一致),下个会话无痛接续 |
|
|
51
51
|
| **轻量零依赖** | 纯 Markdown 文件,无 daemon / 无数据库 / 无注入;任何平台可读可写 |
|
|
52
52
|
| **渐进采用** | 已有状态机制的项目可沿用原机制,只需满足两个强制点,迁移成本低 |
|
|
53
|
-
| **生态分发** | GitHub + npm 双源同步发布;npx / install.sh
|
|
53
|
+
| **生态分发** | GitHub + npm 双源同步发布;npx / git clone / Download ZIP / install.sh 四种安装方式,覆盖 17+ 类智能体目录 |
|
|
54
54
|
|
|
55
55
|
## 协议详解
|
|
56
56
|
|
|
@@ -134,54 +134,42 @@ yotta-workflow 把「跨会话协作」沉淀为一套与智能体无关的协
|
|
|
134
134
|
|
|
135
135
|
## 安装
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
以下四种方式任选,顺序即推荐优先级;技能文件一律从 **npm** 获取(GitHub 无代理较慢,npm 支持镜像)。
|
|
138
138
|
|
|
139
|
-
### 方式一:npm
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
npx -y @yottameta/yotta-workflow --
|
|
139
|
+
### 方式一:npm 一行装(推荐)
|
|
140
|
+
|
|
141
|
+
```text
|
|
142
|
+
# 可选国内加速:npm config set registry https://registry.npmmirror.com
|
|
143
|
+
npx -y @yottameta/yotta-workflow --agent <智能体名称> # 装到指定智能体默认用户级技能目录
|
|
144
|
+
npx -y @yottameta/yotta-workflow --dir <智能体的技能目录> # 指到技能目录本身(如 ~/.codex/skills)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
- `--agent <name>` 自动装到该智能体默认用户级目录;`--list` 可查看各智能体默认目录。
|
|
148
|
+
- `--dir <路径>` 装到指定的技能目录;未收录的智能体用 `--dir` 指到它的技能目录。
|
|
149
|
+
- npmmirror 未同步新包(404):加 `--registry=https://registry.npmjs.org/`(国内需代理),或稍等镜像缓存。
|
|
150
|
+
|
|
151
|
+
### 方式二:git clone(开发者 / 有 git 环境)
|
|
152
|
+
|
|
153
|
+
```text
|
|
154
|
+
git clone https://github.com/YottaMeta/yotta-workflow.git <智能体的技能目录>/yotta-workflow
|
|
144
155
|
```
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
bash install.sh --
|
|
156
|
+
|
|
157
|
+
### 方式三:GitHub 下载压缩包(手动 / 无 git 环境)
|
|
158
|
+
|
|
159
|
+
在 GitHub 仓库 `YottaMeta/yotta-workflow` 点 **Code → Download ZIP**,解压后把 `yotta-workflow` 文件夹放进智能体技能目录。
|
|
160
|
+
|
|
161
|
+
### 方式四:install.sh(多智能体一键脚本)
|
|
162
|
+
|
|
163
|
+
```text
|
|
164
|
+
bash install.sh --agent <name> # 装到指定智能体默认用户级目录
|
|
165
|
+
bash install.sh --dir <path> # 装到指定目录
|
|
166
|
+
bash install.sh --list # 列出智能体 -> 默认目录
|
|
154
167
|
```
|
|
155
|
-
> 覆盖 17 类智能体,含国内 Trae / Qwen / Comate / CodeBuddy / Kimi。Windows 用户:装有 Git Bash 即可用;否则用方式三手动复制。
|
|
156
|
-
|
|
157
|
-
### 方式三:手动复制
|
|
158
|
-
把整个 `yotta-workflow` 文件夹复制到目标智能体的 skills 目录。常见位置(用户级;Windows 用 `%USERPROFILE%`,Linux/macOS 用 `~`):
|
|
159
|
-
|
|
160
|
-
| 智能体 | 用户级目录 | 项目级目录 |
|
|
161
|
-
|---|---|---|
|
|
162
|
-
| Codex | `%USERPROFILE%\.codex\skills\yotta-workflow\` | `.codex\skills\` |
|
|
163
|
-
| Claude Code | `%USERPROFILE%\.claude\skills\yotta-workflow\` | `.claude\skills\` |
|
|
164
|
-
| Cursor | `%USERPROFILE%\.cursor\skills\yotta-workflow\` | `.cursor\skills\` |
|
|
165
|
-
| Windsurf | `%USERPROFILE%\.codeium\windsurf\skills\yotta-workflow\` | `.windsurf\skills\` |
|
|
166
|
-
| opencode | `%USERPROFILE%\.config\opencode\skills\yotta-workflow\` | `.opencode\skills\` |
|
|
167
|
-
| Gemini | `%USERPROFILE%\.gemini\skills\yotta-workflow\` | `.gemini\skills\` |
|
|
168
|
-
| Goose | `%USERPROFILE%\.config\goose\skills\yotta-workflow\` | `.goose\skills\` |
|
|
169
|
-
| Amp | `%USERPROFILE%\.config\agents\skills\yotta-workflow\` | `.agents\skills\` |
|
|
170
|
-
| Kiro | `%USERPROFILE%\.kiro\skills\yotta-workflow\` | `.kiro\skills\` |
|
|
171
|
-
| WorkBuddy | `%USERPROFILE%\.workbuddy\skills\yotta-workflow\` | `.workbuddy\skills\` |
|
|
172
|
-
| Trae Code CLI | `%USERPROFILE%\.traecli\skills\yotta-workflow\` | `.traecli\skills\` |
|
|
173
|
-
| Trae IDE (CN) | `%USERPROFILE%\.trae-cn\skills\yotta-workflow\` | `.trae\skills\` |
|
|
174
|
-
| Qwen Code | `%USERPROFILE%\.qwen\skills\yotta-workflow\` | `.qwen\skills\` |
|
|
175
|
-
| Comate | `%USERPROFILE%\.comate\skills\yotta-workflow\` | `.comate\skills\` |
|
|
176
|
-
| CodeBuddy | `%USERPROFILE%\.codebuddy\skills\yotta-workflow\` | `.codebuddy\skills\` |
|
|
177
|
-
| Kimi | `%USERPROFILE%\.kimi\skills\yotta-workflow\` | `.kimi\skills\` |
|
|
178
|
-
| Generic AGENTS.md | `%USERPROFILE%\.agents\skills\yotta-workflow\` | `.agents\skills\` |
|
|
179
|
-
|
|
180
|
-
> 通用约定:`.agents/skills` 并非所有智能体都读取(Claude Code 与 Codex 默认不读),仅为 OpenCode / Cursor / Cline / Amp / Kimi / Gemini CLI 等智能体识别。已修改默认目录的智能体,请用 `--dir` 指定实际路径。
|
|
181
168
|
|
|
169
|
+
> 方式一走 npm 源(npmmirror / npmjs),不依赖 GitHub;方式二 / 三走 GitHub,国内无代理可能失败。
|
|
182
170
|
## 升级 / 卸载
|
|
183
171
|
|
|
184
|
-
-
|
|
172
|
+
- **升级**:重新安装最新版覆盖即可——重跑你用的安装命令(如 `npx -y @yottameta/yotta-workflow --agent <name>` 或 `bash install.sh --agent <name>`)。技能目录内旧文件会被替换;项目里的状态文件(`.workflow\`)不受影响。
|
|
185
173
|
- **卸载**:删除目标智能体 skills 目录下的 `yotta-workflow` 文件夹(各智能体目录见上表)。卸载不影响已写入项目的状态文件。
|
|
186
174
|
|
|
187
175
|
## 常见问题
|
|
@@ -194,6 +182,12 @@ bash install.sh --dir /path/to/skills
|
|
|
194
182
|
|
|
195
183
|
本项目内运行:`python tools/validate-skill.py yotta-workflow`。
|
|
196
184
|
|
|
185
|
+
## 参考文档
|
|
186
|
+
|
|
187
|
+
- references/faq.md
|
|
188
|
+
- references/walkthroughs.md
|
|
189
|
+
- references/exception-playbook.md
|
|
190
|
+
|
|
197
191
|
## 许可证
|
|
198
192
|
|
|
199
193
|
MIT © YottaMeta
|
package/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yotta-workflow
|
|
3
|
-
description: "跨会话/跨项目通用工作流标准:让任何 AI 智能体活过会话——开工必读状态、状态就近存 .workflow
|
|
4
|
-
version: 0.
|
|
3
|
+
description: "跨会话/跨项目通用工作流标准:让任何 AI 智能体活过会话——开工必读状态、状态就近存 .workflow、进行中自动记流水/任务/决策、收工必留交接锚点。触发:开工/接手项目、续测、收工、跨会话恢复、要落盘、多步开发、项目状态变化、跨智能体协作。边界:只记录项目状态(进度/任务/决策/流水),不写 AI 人格、用户偏好、关系或跨项目通用知识;轻量一次性问答不强制初始化。所有 AI 智能体通用。"
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
license: MIT
|
|
6
6
|
agent_created: true
|
|
7
7
|
metadata:
|
|
@@ -189,4 +189,10 @@ metadata:
|
|
|
189
189
|
## 七、与既有项目机制的协调
|
|
190
190
|
|
|
191
191
|
- **项目已有自己的交接/状态机制**:沿用其机制,不必强制迁移到本标准结构,但必须满足两个强制点——开工先读状态再声称了解;收工更新状态并留锚点。
|
|
192
|
-
- **新项目 / 无既有机制**:按「〇、判定规则」初始化状态目录,完整执行本协议。
|
|
192
|
+
- **新项目 / 无既有机制**:按「〇、判定规则」初始化状态目录,完整执行本协议。
|
|
193
|
+
|
|
194
|
+
## 八、参考文档
|
|
195
|
+
|
|
196
|
+
- 常见问题:`references/faq.md`
|
|
197
|
+
- 复杂场景走查:`references/walkthroughs.md`
|
|
198
|
+
- 异常恢复手册:`references/exception-playbook.md`
|
package/bin/install.js
CHANGED
|
@@ -1,51 +1,97 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* yotta-workflow
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* npx -y @yottameta/yotta-workflow --
|
|
7
|
-
* npx -y @yottameta/yotta-workflow
|
|
8
|
-
* npx -y @yottameta/yotta-workflow
|
|
9
|
-
* npx -y @yottameta/yotta-workflow
|
|
3
|
+
* @yottameta/yotta-workflow cross-platform installer.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx -y @yottameta/yotta-workflow --agent <name>
|
|
7
|
+
* npx -y @yottameta/yotta-workflow --dir <path>
|
|
8
|
+
* npx -y @yottameta/yotta-workflow -g
|
|
9
|
+
* npx -y @yottameta/yotta-workflow
|
|
10
|
+
* npx -y @yottameta/yotta-workflow --list
|
|
10
11
|
*/
|
|
11
12
|
'use strict';
|
|
13
|
+
|
|
12
14
|
const fs = require('fs');
|
|
13
15
|
const path = require('path');
|
|
14
16
|
const os = require('os');
|
|
15
17
|
|
|
16
18
|
const SKILL_NAME = 'yotta-workflow';
|
|
17
19
|
const PKG_ROOT = path.join(__dirname, '..');
|
|
20
|
+
const COPY_SKIP = new Set(['package.json', 'bin', 'node_modules', '.git', '.github', 'test']);
|
|
18
21
|
|
|
19
|
-
// 智能体 -> 用户级默认技能目录(dirs 按优先级排列;--agent 装到第一个)
|
|
20
|
-
// 依据官方文档:.agents/skills 并非通用目录,被 OpenCode / Cursor / Cline / Amp /
|
|
21
|
-
// Kimi / Gemini CLI / GitHub Copilot 等读取;Claude Code 与 Codex 默认不读 .agents。
|
|
22
22
|
const AGENT_DIRS = {
|
|
23
23
|
claude: { label: 'Claude Code', dirs: ['.claude/skills'] },
|
|
24
24
|
cursor: { label: 'Cursor', dirs: ['.cursor/skills', '.agents/skills'] },
|
|
25
|
-
codex: { label: 'Codex', dirs: ['.codex/skills'] },
|
|
25
|
+
codex: { label: 'Codex', dirs: ['.codex/skills'] },
|
|
26
26
|
gemini: { label: 'Gemini CLI', dirs: ['.gemini/skills', '.agents/skills'] },
|
|
27
27
|
goose: { label: 'Goose', dirs: ['.config/goose/skills', '.agents/skills'] },
|
|
28
28
|
amp: { label: 'Amp', dirs: ['.config/agents/skills', '.agents/skills'] },
|
|
29
|
-
opencode: { label: 'OpenCode', dirs: ['.config/opencode/skills'] },
|
|
29
|
+
opencode: { label: 'OpenCode', dirs: ['.config/opencode/skills'] },
|
|
30
30
|
windsurf: { label: 'Windsurf', dirs: ['.codeium/windsurf/skills'] },
|
|
31
31
|
workbuddy: { label: 'WorkBuddy', dirs: ['.workbuddy/skills'] },
|
|
32
32
|
kiro: { label: 'Kiro', dirs: ['.kiro/skills'] },
|
|
33
33
|
trae: { label: 'Trae Code CLI', dirs: ['.traecli/skills'] },
|
|
34
|
-
'trae-cn': { label: 'Trae IDE
|
|
34
|
+
'trae-cn': { label: 'Trae IDE', dirs: ['.trae-cn/skills'] },
|
|
35
35
|
qwen: { label: 'Qwen Code', dirs: ['.qwen/skills'] },
|
|
36
|
-
comate: { label: 'Comate
|
|
36
|
+
comate: { label: 'Comate', dirs: ['.comate/skills'] },
|
|
37
37
|
codebuddy: { label: 'CodeBuddy Code', dirs: ['.codebuddy/skills'] },
|
|
38
38
|
kimi: { label: 'Kimi Code CLI', dirs: ['.kimi/skills'] },
|
|
39
|
-
agents: { label: '
|
|
39
|
+
agents: { label: 'Generic AGENTS.md', dirs: ['.agents/skills'] },
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
class UsageError extends Error {}
|
|
43
|
+
class TargetError extends Error {}
|
|
44
|
+
class InstallError extends Error {}
|
|
45
|
+
|
|
46
|
+
function usage() {
|
|
47
|
+
console.log('yotta-workflow installer');
|
|
48
|
+
console.log('');
|
|
49
|
+
console.log('Usage:');
|
|
50
|
+
console.log(' npx -y @yottameta/yotta-workflow --agent <name> Install to an agent default directory');
|
|
51
|
+
console.log(' npx -y @yottameta/yotta-workflow --dir <path> Install to a custom directory');
|
|
52
|
+
console.log(' npx -y @yottameta/yotta-workflow -g Install to all known agent directories');
|
|
53
|
+
console.log(' npx -y @yottameta/yotta-workflow Auto-detect project-level directories');
|
|
54
|
+
console.log(' npx -y @yottameta/yotta-workflow --list List supported agent directories');
|
|
55
|
+
console.log('');
|
|
56
|
+
console.log('Options:');
|
|
57
|
+
console.log(' --agent <name> Agent key, see --list');
|
|
58
|
+
console.log(' --dir <path> Custom skills directory');
|
|
59
|
+
console.log(' -g, --global Install to all known user-level directories');
|
|
60
|
+
console.log(' --list, -l List supported agents');
|
|
61
|
+
console.log(' -h, --help Show this help');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function parseArgs(argv) {
|
|
65
|
+
const opts = { help: false, list: false, global: false, dir: null, agent: null };
|
|
66
|
+
for (let i = 0; i < argv.length; i++) {
|
|
67
|
+
const arg = argv[i];
|
|
68
|
+
if (arg === '--help' || arg === '-h') opts.help = true;
|
|
69
|
+
else if (arg === '--list' || arg === '-l') opts.list = true;
|
|
70
|
+
else if (arg === '--global' || arg === '-g') opts.global = true;
|
|
71
|
+
else if (arg === '--dir') {
|
|
72
|
+
const value = argv[++i];
|
|
73
|
+
if (!value) throw new UsageError('--dir requires a non-empty path');
|
|
74
|
+
opts.dir = value;
|
|
75
|
+
} else if (arg === '--agent') {
|
|
76
|
+
const value = argv[++i];
|
|
77
|
+
if (!value) throw new UsageError('--agent requires a non-empty name');
|
|
78
|
+
opts.agent = value.toLowerCase();
|
|
79
|
+
} else {
|
|
80
|
+
throw new UsageError('Unknown argument: ' + arg);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!opts.help) {
|
|
84
|
+
const selected = [opts.dir, opts.agent, opts.global].filter(Boolean).length;
|
|
85
|
+
if (selected > 1) throw new UsageError('Use only one of --dir, --agent, or -g');
|
|
86
|
+
}
|
|
87
|
+
return opts;
|
|
88
|
+
}
|
|
89
|
+
|
|
43
90
|
function codexUserDir() {
|
|
44
91
|
const base = process.env.CODEX_HOME || path.join(os.homedir(), '.codex');
|
|
45
92
|
return path.join(base, 'skills');
|
|
46
93
|
}
|
|
47
94
|
|
|
48
|
-
// OpenCode 用户级目录特判:优先 $XDG_CONFIG_HOME/opencode/skills,否则 ~/.config/opencode/skills
|
|
49
95
|
function opencodeUserDir() {
|
|
50
96
|
const base = process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config');
|
|
51
97
|
return path.join(base, 'opencode', 'skills');
|
|
@@ -57,82 +103,65 @@ function resolveUserDir(rel) {
|
|
|
57
103
|
return path.join(os.homedir(), rel);
|
|
58
104
|
}
|
|
59
105
|
|
|
60
|
-
function installTo(dest) {
|
|
61
|
-
const target = path.join(dest, SKILL_NAME);
|
|
62
|
-
fs.mkdirSync(target, { recursive: true });
|
|
63
|
-
copyDir(PKG_ROOT, target, new Set(['package.json', 'bin', 'node_modules', '.git']));
|
|
64
|
-
console.log('installed -> ' + target);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function copyDir(src, dst, skip) {
|
|
68
|
-
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
69
|
-
if (skip.has(entry.name)) continue;
|
|
70
|
-
const s = path.join(src, entry.name);
|
|
71
|
-
const d = path.join(dst, entry.name);
|
|
72
|
-
if (entry.isDirectory()) {
|
|
73
|
-
fs.mkdirSync(d, { recursive: true });
|
|
74
|
-
copyDir(s, d, skip);
|
|
75
|
-
} else if (entry.isFile()) {
|
|
76
|
-
fs.copyFileSync(s, d);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
106
|
function displayDir(rel) {
|
|
82
107
|
if (process.platform === 'win32') return '%USERPROFILE%\\' + rel.replace(/\//g, '\\');
|
|
83
108
|
return '~/' + rel;
|
|
84
109
|
}
|
|
85
110
|
|
|
86
|
-
function
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
let explicitDir = null;
|
|
91
|
-
const di = args.indexOf('--dir');
|
|
92
|
-
if (di !== -1 && args[di + 1]) explicitDir = args[di + 1];
|
|
93
|
-
let agent = null;
|
|
94
|
-
const ai = args.indexOf('--agent');
|
|
95
|
-
if (ai !== -1 && args[ai + 1]) agent = String(args[ai + 1]).toLowerCase();
|
|
96
|
-
|
|
97
|
-
if (list) {
|
|
98
|
-
console.log('智能体 -> 默认技能目录(--agent <name> 装到第一个,用户级):');
|
|
99
|
-
for (const [key, v] of Object.entries(AGENT_DIRS)) {
|
|
100
|
-
const resolved = v.dirs.map(displayDir);
|
|
101
|
-
console.log(' ' + key.padEnd(10) + v.label.padEnd(18) + resolved.join('、'));
|
|
102
|
-
}
|
|
103
|
-
console.log('\n说明:Windows 用 %USERPROFILE%,Linux/macOS 用 ~;仅收录有官方默认目录的智能体。');
|
|
104
|
-
console.log('改了目录的请用 --dir <路径>,不要依赖默认位置;若设置了 CODEX_HOME / XDG_CONFIG_HOME,安装自动以该变量为准。');
|
|
105
|
-
return;
|
|
111
|
+
function printList() {
|
|
112
|
+
console.log('Agent -> default skill directory:');
|
|
113
|
+
for (const [key, value] of Object.entries(AGENT_DIRS)) {
|
|
114
|
+
console.log(' ' + key.padEnd(12) + value.label.padEnd(20) + value.dirs.map(displayDir).join(', '));
|
|
106
115
|
}
|
|
116
|
+
console.log('');
|
|
117
|
+
console.log('Use --dir <path> for agents not listed. CODEX_HOME and XDG_CONFIG_HOME are respected.');
|
|
118
|
+
}
|
|
107
119
|
|
|
108
|
-
|
|
120
|
+
function assertSafeTarget(target) {
|
|
121
|
+
const rel = path.relative(PKG_ROOT, target);
|
|
122
|
+
if (rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel))) {
|
|
123
|
+
throw new UsageError('Target directory must be outside the skill source directory');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
109
126
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
127
|
+
function copyDir(src, dst, skip) {
|
|
128
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
129
|
+
if (skip.has(entry.name)) continue;
|
|
130
|
+
const from = path.join(src, entry.name);
|
|
131
|
+
const to = path.join(dst, entry.name);
|
|
132
|
+
try {
|
|
133
|
+
if (entry.isDirectory()) {
|
|
134
|
+
fs.mkdirSync(to, { recursive: true });
|
|
135
|
+
copyDir(from, to, skip);
|
|
136
|
+
} else if (entry.isFile()) {
|
|
137
|
+
fs.copyFileSync(from, to);
|
|
138
|
+
}
|
|
139
|
+
} catch (err) {
|
|
140
|
+
throw new InstallError('Failed to copy ' + from + ' -> ' + to + ': ' + err.message);
|
|
116
141
|
}
|
|
117
|
-
installTo(resolveUserDir(info.dirs[0]));
|
|
118
|
-
console.log('完成。');
|
|
119
|
-
return;
|
|
120
142
|
}
|
|
143
|
+
}
|
|
121
144
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
145
|
+
function installTo(dest) {
|
|
146
|
+
if (!dest || typeof dest !== 'string') throw new UsageError('Destination directory is required');
|
|
147
|
+
const target = path.resolve(dest, SKILL_NAME);
|
|
148
|
+
assertSafeTarget(target);
|
|
149
|
+
try {
|
|
150
|
+
fs.mkdirSync(target, { recursive: true });
|
|
151
|
+
copyDir(PKG_ROOT, target, COPY_SKIP);
|
|
152
|
+
if (!fs.existsSync(path.join(target, 'SKILL.md'))) {
|
|
153
|
+
throw new InstallError('Installed directory is missing SKILL.md');
|
|
130
154
|
}
|
|
131
|
-
|
|
132
|
-
|
|
155
|
+
} catch (err) {
|
|
156
|
+
if (err instanceof UsageError || err instanceof InstallError) throw err;
|
|
157
|
+
throw new InstallError('Cannot install to ' + target + ': ' + err.message);
|
|
133
158
|
}
|
|
159
|
+
console.log('installed -> ' + target);
|
|
160
|
+
return target;
|
|
161
|
+
}
|
|
134
162
|
|
|
135
|
-
|
|
163
|
+
function projectDirs() {
|
|
164
|
+
return [
|
|
136
165
|
'.claude/skills',
|
|
137
166
|
'.cursor/skills',
|
|
138
167
|
'.codex/skills',
|
|
@@ -150,14 +179,67 @@ function main() {
|
|
|
150
179
|
'.codebuddy/skills',
|
|
151
180
|
'.kimi/skills',
|
|
152
181
|
'.agents/skills',
|
|
153
|
-
];
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
182
|
+
].filter((dir) => fs.existsSync(dir));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function run() {
|
|
186
|
+
const opts = parseArgs(process.argv.slice(2));
|
|
187
|
+
if (opts.help) { usage(); return; }
|
|
188
|
+
if (opts.list) { printList(); return; }
|
|
189
|
+
|
|
190
|
+
if (opts.dir) { installTo(opts.dir); return; }
|
|
191
|
+
|
|
192
|
+
if (opts.agent) {
|
|
193
|
+
const info = AGENT_DIRS[opts.agent];
|
|
194
|
+
if (!info) {
|
|
195
|
+
throw new UsageError('Unknown agent: ' + opts.agent + '. Available: ' + Object.keys(AGENT_DIRS).join(', ') + '. Use --dir for a custom directory.');
|
|
196
|
+
}
|
|
197
|
+
installTo(resolveUserDir(info.dirs[0]));
|
|
198
|
+
return;
|
|
157
199
|
}
|
|
158
|
-
|
|
159
|
-
|
|
200
|
+
|
|
201
|
+
if (opts.global) {
|
|
202
|
+
const seen = new Set();
|
|
203
|
+
let count = 0;
|
|
204
|
+
for (const value of Object.values(AGENT_DIRS)) {
|
|
205
|
+
for (const dir of value.dirs) {
|
|
206
|
+
if (seen.has(dir)) continue;
|
|
207
|
+
seen.add(dir);
|
|
208
|
+
installTo(resolveUserDir(dir));
|
|
209
|
+
count++;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
console.log('Installed to ' + count + ' directories.');
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const dirs = projectDirs();
|
|
217
|
+
if (!dirs.length) {
|
|
218
|
+
throw new TargetError('No project-level agent directory detected. Use --agent <name> or --dir <path>.');
|
|
219
|
+
}
|
|
220
|
+
for (const dir of dirs) installTo(dir);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function main() {
|
|
224
|
+
try {
|
|
225
|
+
run();
|
|
226
|
+
} catch (err) {
|
|
227
|
+
if (err instanceof UsageError) {
|
|
228
|
+
console.error('Usage error: ' + err.message);
|
|
229
|
+
usage();
|
|
230
|
+
process.exitCode = 2;
|
|
231
|
+
} else if (err instanceof TargetError) {
|
|
232
|
+
console.error('Target error: ' + err.message);
|
|
233
|
+
process.exitCode = 4;
|
|
234
|
+
} else if (err instanceof InstallError) {
|
|
235
|
+
console.error('Install failed: ' + err.message);
|
|
236
|
+
console.error('Fix: check directory permissions and free space, then retry. Use --dir to choose another directory.');
|
|
237
|
+
process.exitCode = 1;
|
|
238
|
+
} else {
|
|
239
|
+
console.error('Unexpected error: ' + (err && err.message ? err.message : String(err)));
|
|
240
|
+
process.exitCode = 1;
|
|
241
|
+
}
|
|
160
242
|
}
|
|
161
243
|
}
|
|
162
244
|
|
|
163
|
-
main();
|
|
245
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yottameta/yotta-workflow",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Cross-session / cross-project workflow standard for all AI agents: read the state on start, store state nearby in a unified .workflow directory, persist logs/tasks/decisions while working, and leave a self-contained handoff anchor on finish.
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Cross-session / cross-project workflow standard for all AI agents: read the state on start, store state nearby in a unified .workflow directory, persist logs/tasks/decisions while working, and leave a self-contained handoff anchor on finish. Boundaries: records project state only; no AI personality, user preferences, relationships, or cross-project general knowledge.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"agent-skills",
|
|
@@ -31,5 +31,8 @@
|
|
|
31
31
|
},
|
|
32
32
|
"bin": {
|
|
33
33
|
"yotta-workflow": "bin/install.js"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"test": "node --test \"test/*.test.js\""
|
|
34
37
|
}
|
|
35
38
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# 元序异常恢复手册
|
|
2
|
+
|
|
3
|
+
## 1. 状态文件缺失
|
|
4
|
+
|
|
5
|
+
- 信号:项目存在但状态目录不存在。
|
|
6
|
+
- 动作:按项目根初始化标准结构,不覆盖既有机制。
|
|
7
|
+
- 恢复:读取项目文档与用户补充信息,重建最小状态。
|
|
8
|
+
|
|
9
|
+
## 2. 并发写入冲突
|
|
10
|
+
|
|
11
|
+
- 信号:两个会话同时更新同一状态文件。
|
|
12
|
+
- 动作:停止整文件重写,改为读取后合并。
|
|
13
|
+
- 恢复:保留双方有效信息,冲突处标注来源并请用户确认。
|
|
14
|
+
|
|
15
|
+
## 3. 状态文件过大
|
|
16
|
+
|
|
17
|
+
- 信号:单文件明显超过常规阅读量。
|
|
18
|
+
- 动作:拆分历史内容,保留当前快照。
|
|
19
|
+
- 恢复:STATE 只留当前进度,历史写入日志或专项文档。
|
|
20
|
+
|
|
21
|
+
## 4. 既有机制冲突
|
|
22
|
+
|
|
23
|
+
- 信号:项目已有自己的交接文件。
|
|
24
|
+
- 动作:沿用原机制,只补足开工读取与收工锚点。
|
|
25
|
+
- 恢复:把本协议必要字段映射到原机制,不重复建一套状态。
|
|
26
|
+
|
|
27
|
+
## 5. 会话中断
|
|
28
|
+
|
|
29
|
+
- 信号:用户直接开新会话,未走收工流程。
|
|
30
|
+
- 动作:先读状态,再请用户补充缺失点。
|
|
31
|
+
- 恢复:确认后从下一步继续,不假装记得对话内容。
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# 元序常见问题
|
|
2
|
+
|
|
3
|
+
## 速查索引
|
|
4
|
+
|
|
5
|
+
- **适用**:什么任务用 · 一次性问答要不要用
|
|
6
|
+
- **状态**:目录在哪 · 多智能体如何共享 · 文件太大怎么办
|
|
7
|
+
- **协作**:并发写入 · 既有机制兼容 · 轻量会话简化
|
|
8
|
+
- **收尾**:锚点格式 · 中断恢复
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. 什么任务应该使用元序?
|
|
13
|
+
|
|
14
|
+
项目型、跨会话、多步骤、需要落盘状态的任务。一次性问答或纯查资料不需要初始化状态目录。
|
|
15
|
+
|
|
16
|
+
## 2. 状态目录在哪里?
|
|
17
|
+
|
|
18
|
+
按“当前目录 → 项目根 / 工作区根”判定。项目根下使用项目内状态目录;工作区根下按项目名分目录。不要写死绝对路径。
|
|
19
|
+
|
|
20
|
+
## 3. 多个智能体能共享状态吗?
|
|
21
|
+
|
|
22
|
+
可以。同一项目内的智能体读写同一份状态文件,形成单一事实源。若出现不同步,先确认它们的项目根是否一致。
|
|
23
|
+
|
|
24
|
+
## 4. 状态文件太大怎么办?
|
|
25
|
+
|
|
26
|
+
日志按天拆分;STATE 只保留当前进度,历史快照放 ROADMAP / DECISIONS。超过约 500 行时应拆分或归档,避免每次开工读入过多内容。
|
|
27
|
+
|
|
28
|
+
## 5. 多个智能体同时写入怎么办?
|
|
29
|
+
|
|
30
|
+
尽量由一个会话负责写入。若必须并发,先读取再小步追加,不要整文件重写;冲突时以文件内容为准,合并后写入。
|
|
31
|
+
|
|
32
|
+
## 6. 项目已有交接机制怎么办?
|
|
33
|
+
|
|
34
|
+
沿用原机制,但必须满足两点:开工先读状态,收工更新状态并留锚点。
|
|
35
|
+
|
|
36
|
+
## 7. 轻量会话可以简化吗?
|
|
37
|
+
|
|
38
|
+
可以。只做两件事:开工读状态,收工写一条简短锚点。不要为了小任务生成完整状态结构。
|
|
39
|
+
|
|
40
|
+
## 8. 收工锚点必须固定格式吗?
|
|
41
|
+
|
|
42
|
+
必须。固定结构保证下个会话能自动解析:项目、路径、上次结束时间、当前进度、已完成、下一步、关键决定、遗留问题、开工读取路径。
|
|
43
|
+
|
|
44
|
+
## 9. 会话中断后怎么恢复?
|
|
45
|
+
|
|
46
|
+
先读状态文件,再对照用户补充信息确认恢复点;没有状态时明说缺失,请用户给恢复点。
|
|
47
|
+
|
|
48
|
+
## 10. 状态与对话记忆冲突怎么办?
|
|
49
|
+
|
|
50
|
+
以状态文件为准,并在回复中说明冲突来源。
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# 元序复杂场景走查
|
|
2
|
+
|
|
3
|
+
## 走查 1:项目开工
|
|
4
|
+
|
|
5
|
+
1. 读取当前目录,判定项目根。
|
|
6
|
+
2. 读取 STATE / TASKS / ROADMAP / DECISIONS。
|
|
7
|
+
3. 汇总当前进度与下一步。
|
|
8
|
+
4. 执行前先确认本次会话目标与验收。
|
|
9
|
+
|
|
10
|
+
## 走查 2:任务中主动落盘
|
|
11
|
+
|
|
12
|
+
背景:一个功能已改完一半,后续还有测试和文档。
|
|
13
|
+
|
|
14
|
+
1. 立刻更新 STATE 当前进度。
|
|
15
|
+
2. 在 TASKS 勾选已完成项。
|
|
16
|
+
3. 如有新决策,写入 DECISIONS。
|
|
17
|
+
4. 当天日志追加一条简短记录。
|
|
18
|
+
5. 继续执行剩余步骤。
|
|
19
|
+
|
|
20
|
+
## 走查 3:收工锚点
|
|
21
|
+
|
|
22
|
+
1. 更新 STATE / TASKS / ROADMAP。
|
|
23
|
+
2. 追加当天日志。
|
|
24
|
+
3. 输出固定格式锚点,包含项目、路径、时间、进度、已完成、下一步、关键决定、遗留问题、开工读取路径。
|
|
25
|
+
4. 确认锚点与状态文件一致。
|