@yottameta/yotta-workflow 0.2.6 → 0.4.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 +33 -12
- package/README.zh-CN.md +33 -12
- package/SKILL.md +81 -30
- package/bin/install.js +168 -86
- package/package.json +5 -2
- package/references/exception-playbook.md +37 -0
- package/references/faq.md +62 -0
- package/references/path-model.md +52 -0
- package/references/walkthroughs.md +34 -0
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<h1 align="center">yotta-workflow · 元序 (Yuanxu)</h1>
|
|
8
8
|
|
|
9
|
-
<p align="center">A universal workflow standard for all AI agents: <b>the process is set globally,
|
|
9
|
+
<p align="center">A universal workflow standard for all AI agents: <b>the process is set globally, state follows the project root; read the state on start, always leave a handoff anchor on finish</b>. Lets any AI conversation resume painlessly and avoids amnesia from overlong single sessions.</p>
|
|
10
10
|
<p align="center">State directory is unified as <code>.workflow</code> — all agent sessions of the same project read and write the same state (one source of truth); on start, read the state to restore context; while working, actively persist logs / tasks / decisions; on finish, generate a self-contained handoff anchor.</p>
|
|
11
11
|
<p align="center">Pure Markdown text, zero dependencies, no injection, no platform lock; install once, works across 78+ agents such as Claude Code / Codex / Cursor / OpenCode.</p>
|
|
12
12
|
|
|
@@ -29,12 +29,12 @@ yotta-workflow distills "cross-session collaboration" into an agent-agnostic pro
|
|
|
29
29
|
- **When to read, when to write?** — read on start, write actively while working, always leave an anchor on finish.
|
|
30
30
|
- **How to hand off?** — a fixed template generates a self-contained handoff anchor; the next session resumes painlessly from just that anchor.
|
|
31
31
|
|
|
32
|
-
It depends on no specific agent or platform: the state is just Markdown files under the project
|
|
32
|
+
It depends on no specific agent or platform: the state is just Markdown files under the project root, readable and writable by any agent or tool.
|
|
33
33
|
|
|
34
34
|
## Core value
|
|
35
35
|
|
|
36
36
|
- **One source of truth** — all agent sessions of the same project read and write the same `.workflow\` state directory, instead of each building its own and keeping separate records.
|
|
37
|
-
- **State
|
|
37
|
+
- **State follows the project root** — `.workflow` belongs to the project root, not to a source checkout or a workspace container; an existing `.workflow` is always reused in place and never auto-migrated.
|
|
38
38
|
- **Proactive anti-amnesia** — every completed action is written to logs / tasks / decisions while working, not relied on in-conversation memory (context gets auto-compressed).
|
|
39
39
|
- **Self-contained handoff** — on finish, generate a fixed-format handoff anchor; the next session restores full context from the anchor plus state files.
|
|
40
40
|
- **Compatible with existing mechanisms** — if the project already has its own handoff / state mechanism, keep it, only satisfying two mandatory points: read state on start, update state and leave an anchor on finish.
|
|
@@ -45,7 +45,7 @@ It depends on no specific agent or platform: the state is just Markdown files un
|
|
|
45
45
|
|---|---|
|
|
46
46
|
| **Cross-agent unified** | follows the Agent Skills open standard (agentskills.io); install once, 78+ agents share one state protocol |
|
|
47
47
|
| **One source of truth** | unified `.workflow` state directory; any agent of the same project reads/writes the same state, eliminating multiple sources of truth |
|
|
48
|
-
| **Automated path detection** |
|
|
48
|
+
| **Automated path detection** | explicit root → nearest existing `.workflow` → project root / source directory / workspace classification; never hard-code a path |
|
|
49
49
|
| **Proactive persistence** | immediately write logs / tasks / decisions while working, so context compression never loses key state |
|
|
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 |
|
|
@@ -54,16 +54,29 @@ It depends on no specific agent or platform: the state is just Markdown files un
|
|
|
54
54
|
|
|
55
55
|
## Protocol details
|
|
56
56
|
|
|
57
|
-
###
|
|
57
|
+
### Path model and state file location rule
|
|
58
58
|
|
|
59
|
-
**First
|
|
59
|
+
**First distinguish three concepts: the project root owns the whole project state and is the only anchor for `.workflow`; the source directory is normally a code subdirectory under the project root; a workspace root is only a container for multiple project roots.**
|
|
60
60
|
|
|
61
|
-
|
|
|
62
|
-
|
|
63
|
-
|
|
|
64
|
-
|
|
|
61
|
+
| Directory | Definition | Where `.workflow` goes |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| **Project root** | Parent directory that owns the whole project state and normally contains both `.workflow` and the source directory | `<project root>\.workflow\` |
|
|
64
|
+
| **Source directory** | Code directory under the project root; it may have its own `.git` | Not there, unless the user explicitly says it is also the project root |
|
|
65
|
+
| **Workspace root** | Container holding multiple project roots; it owns no project state | Not there; choose the relevant project root first |
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
<project root>\
|
|
69
|
+
├── .workflow\ # state; directly under the project root
|
|
70
|
+
└── <source dir>\ # source directory; under the project root
|
|
71
|
+
```
|
|
65
72
|
|
|
66
|
-
|
|
73
|
+
**Resolution order (two signals only):**
|
|
74
|
+
|
|
75
|
+
1. The user explicitly specifies a project root → use it.
|
|
76
|
+
2. Walk upward from the cwd and use the nearest existing `.workflow\STATE.md`; its parent is the project root. Keep it in place; **never auto-migrate it**.
|
|
77
|
+
3. If neither signal exists, stop and ask: `What is this task's project root directory?` Do not infer it from `.git`, `package.json`, `src`, `README`, the cwd, or directory structure.
|
|
78
|
+
|
|
79
|
+
> This skill defines only the standard layout and state location. How a real project names or layers its source directories is left to the user to adapt.
|
|
67
80
|
|
|
68
81
|
### Project state system (five file types)
|
|
69
82
|
|
|
@@ -174,14 +187,22 @@ bash install.sh --list # list agents -> default directories
|
|
|
174
187
|
|
|
175
188
|
## FAQ
|
|
176
189
|
|
|
177
|
-
- **Where is the state directory?**
|
|
190
|
+
- **Where is the state directory?** Accept an explicitly specified project root first; otherwise walk upward from the cwd to find an existing `.workflow\`. If neither exists, ask. State always lives at `<project root>\.workflow\`, not in a source directory or workspace root.
|
|
178
191
|
- **Multiple agents out of sync?** Confirm they point to the same project directory (the same `.workflow\`). This skill is designed to share one state; if each built its own `.workflow`, the project directory differs.
|
|
192
|
+
- **The source directory has `.git`; should state live there?** Not by that signal alone. State belongs under the project-root `.workflow`; the user decides how source directories are organized.
|
|
179
193
|
- **Project already has its own handoff mechanism?** Keep it, only satisfying the two mandatory points: read state on start, update state and leave an anchor on finish.
|
|
180
194
|
|
|
181
195
|
## Development & checks
|
|
182
196
|
|
|
183
197
|
Run inside this project: `python tools/validate-skill.py yotta-workflow`.
|
|
184
198
|
|
|
199
|
+
## References
|
|
200
|
+
|
|
201
|
+
- references/faq.md
|
|
202
|
+
- references/path-model.md
|
|
203
|
+
- references/walkthroughs.md
|
|
204
|
+
- references/exception-playbook.md
|
|
205
|
+
|
|
185
206
|
## License
|
|
186
207
|
|
|
187
208
|
MIT © YottaMeta
|
package/README.zh-CN.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<h1 align="center">yotta-workflow · 元序</h1>
|
|
8
8
|
|
|
9
|
-
<p align="center">一套面向所有 AI 智能体的通用工作流标准:<b
|
|
9
|
+
<p align="center">一套面向所有 AI 智能体的通用工作流标准:<b>流程全局定、状态跟项目根目录;开工必读状态,收工必留锚点</b>。让任何 AI 会话都能无痛接续,避免单会话拉长而失忆。</p>
|
|
10
10
|
<p align="center">状态目录统一 <code>.workflow</code>——同一项目所有智能体会话读写同一份状态(一个真相源);开工读状态恢复上下文、进行中主动落盘流水 / 任务 / 决策、收工生成自包含交接锚点。</p>
|
|
11
11
|
<p align="center">纯 Markdown 文本,零依赖、不注入、不锁平台;安装一次,Claude Code / Codex / Cursor / OpenCode 等 78+ 智能体通用。</p>
|
|
12
12
|
|
|
@@ -34,7 +34,7 @@ yotta-workflow 把「跨会话协作」沉淀为一套与智能体无关的协
|
|
|
34
34
|
## 核心价值
|
|
35
35
|
|
|
36
36
|
- **一个真相源**:同一项目所有智能体会话读写同一份 `.workflow\` 状态目录,不再各建目录、各记各的。
|
|
37
|
-
-
|
|
37
|
+
- **状态跟着项目根目录走**:`.workflow` 只放项目根目录,不放源码目录,也不放工作区根;已有 `.workflow` 就近沿用、不自动迁移。
|
|
38
38
|
- **主动防失忆**:进行中每完成一件事就落盘流水 / 任务 / 决策,不靠对话记忆(上下文会被自动压缩)。
|
|
39
39
|
- **自包含交接**:收工生成固定格式交接锚点,下个会话只凭锚点 + 状态文件即可恢复全部上下文。
|
|
40
40
|
- **与既有机制兼容**:项目已有自己的交接 / 状态机制时沿用原机制,只需满足两个强制点——开工先读状态、收工更新状态并留锚点。
|
|
@@ -45,7 +45,7 @@ yotta-workflow 把「跨会话协作」沉淀为一套与智能体无关的协
|
|
|
45
45
|
|---|---|
|
|
46
46
|
| **跨智能体统一** | 符合 Agent Skills 开放标准(agentskills.io),安装一次,78+ 智能体共用同一套状态协议 |
|
|
47
47
|
| **一个真相源** | 状态目录统一 `.workflow`,同一项目任何智能体读写同一份状态,杜绝多真相源 |
|
|
48
|
-
|
|
|
48
|
+
| **路径判定无歧义** | 只认用户明确指定或向上找到已有 `.workflow`;两种证据都没有就先问,不靠 `.git` / cwd 猜 |
|
|
49
49
|
| **主动式落盘** | 进行中即时写流水 / 任务 / 决策,上下文压缩也不丢关键状态 |
|
|
50
50
|
| **自包含交接锚点** | 固定模板 + 强制校验(内容必须与状态文件一致),下个会话无痛接续 |
|
|
51
51
|
| **轻量零依赖** | 纯 Markdown 文件,无 daemon / 无数据库 / 无注入;任何平台可读可写 |
|
|
@@ -54,16 +54,29 @@ yotta-workflow 把「跨会话协作」沉淀为一套与智能体无关的协
|
|
|
54
54
|
|
|
55
55
|
## 协议详解
|
|
56
56
|
|
|
57
|
-
###
|
|
57
|
+
### 路径模型与状态文件位置判定
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
**先分清三个概念:项目根目录是拥有整个项目状态的目录,也是 `.workflow` 的唯一锚点;源码目录默认是项目根目录下的代码子目录;工作区根只是并列多个项目根目录的父目录。**
|
|
60
60
|
|
|
61
|
-
|
|
|
62
|
-
|
|
63
|
-
|
|
|
64
|
-
|
|
|
61
|
+
| 目录 | 定义 | `.workflow` 放哪 |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| **项目根目录** | 拥有整个项目状态的父目录;默认承载 `.workflow` 和源码目录 | `<项目根目录>\.workflow\` |
|
|
64
|
+
| **源码目录** | 项目根目录下的代码目录;可以有独立 `.git` | 不放,除非用户明确说明它同时就是项目根目录 |
|
|
65
|
+
| **工作区根目录** | 并列多个项目根目录的容器;不拥有某个项目的状态 | 不放;先选具体项目根目录 |
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
<项目根目录>\
|
|
69
|
+
├── .workflow\ # 工作流;直接放在项目根目录
|
|
70
|
+
└── <源码目录>\ # 源码目录;位于项目根目录之下
|
|
71
|
+
```
|
|
65
72
|
|
|
66
|
-
|
|
73
|
+
**定位顺序(只认两种证据):**
|
|
74
|
+
|
|
75
|
+
1. 用户明确指定项目根目录 → 直接用。
|
|
76
|
+
2. 从 cwd 向上查找已有的 `.workflow\STATE.md` → 找到最近的,其父目录就是项目根目录;**永不自动迁移**。
|
|
77
|
+
3. 两种证据都没有 → 先问“项目根目录是哪一个?”,不得用 `.git`、`package.json`、`src`、`README`、cwd 或目录结构自行猜测。
|
|
78
|
+
|
|
79
|
+
> 本技能只规定标准形态与状态位置;实际项目中源码目录怎么命名、怎么分层,由用户按项目情况调整。
|
|
67
80
|
|
|
68
81
|
### 项目状态体系(五类文件)
|
|
69
82
|
|
|
@@ -174,14 +187,22 @@ bash install.sh --list # 列出智能体 -> 默认目录
|
|
|
174
187
|
|
|
175
188
|
## 常见问题
|
|
176
189
|
|
|
177
|
-
- **状态目录在哪?**
|
|
190
|
+
- **状态目录在哪?** 先认用户明确指定的项目根目录,再从 cwd 向上找已有 `.workflow\`;两者都没有就先问。状态始终放 `<项目根目录>\.workflow\`,不放源码目录或工作区根。
|
|
178
191
|
- **多个智能体状态不同步?** 确认它们指向同一项目目录(同一份 `.workflow\`)。本技能设计为共享一份状态;若各自建了 `.workflow`,说明项目目录不一致。
|
|
192
|
+
- **源码目录里有 `.git`,状态应该放那里吗?** 不应只凭 `.git` 判断;状态只放项目根目录下的 `.workflow`。源码目录的具体组织由用户决定。
|
|
179
193
|
- **项目已有自己的交接机制?** 沿用原机制即可,只需满足两个强制点:开工先读状态、收工更新状态并留锚点。
|
|
180
194
|
|
|
181
195
|
## 开发与校验
|
|
182
196
|
|
|
183
197
|
本项目内运行:`python tools/validate-skill.py yotta-workflow`。
|
|
184
198
|
|
|
199
|
+
## 参考文档
|
|
200
|
+
|
|
201
|
+
- references/faq.md
|
|
202
|
+
- references/path-model.md
|
|
203
|
+
- references/walkthroughs.md
|
|
204
|
+
- references/exception-playbook.md
|
|
205
|
+
|
|
185
206
|
## 许可证
|
|
186
207
|
|
|
187
|
-
MIT © YottaMeta
|
|
208
|
+
MIT © YottaMeta
|
package/SKILL.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yotta-workflow
|
|
3
|
-
description: "跨会话/跨项目通用工作流标准:让任何 AI
|
|
4
|
-
version: 0.
|
|
3
|
+
description: "跨会话/跨项目通用工作流标准:让任何 AI 智能体活过会话——开工必读状态、状态只存项目根目录的 .workflow、进行中自动记流水/任务/决策、收工必留交接锚点。项目根目录是状态锚点,源码目录可嵌套且 .git 不等于项目根目录。触发:开工/接手项目、续测、收工、跨会话恢复、要落盘、多步开发、项目状态变化、跨智能体协作。边界:只记录项目状态(进度/任务/决策/流水),不写 AI 人格、用户偏好、关系或跨项目通用知识;轻量一次性问答不强制初始化。所有 AI 智能体通用。"
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
license: MIT
|
|
6
6
|
agent_created: true
|
|
7
7
|
metadata:
|
|
8
|
-
short-description:
|
|
8
|
+
short-description: 跨会话工作流:状态只认项目根目录,开工读、收工锚点
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# 元序(yotta-workflow)
|
|
12
12
|
|
|
13
13
|
本文件是**全局层标准**:所有项目共享同一套工作流程。状态文件位置按规则判定(见下)。
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
核心原则:**流程全局定,状态跟项目根目录。开工必读状态,收工必留锚点。**
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
@@ -24,8 +24,8 @@ metadata:
|
|
|
24
24
|
| --- | --- |
|
|
25
25
|
| **这是什么** | 跨会话 / 跨项目的工作流协议:开工读状态 → 进行中记流水/任务/决策 → 收工留锚点。状态统一存本项目 `.workflow`。 |
|
|
26
26
|
| **何时触发** | 涉及「项目」「续测」「跨会话」「要落盘」「多步开发」「收工」即触发;一次性只读问答不触发。 |
|
|
27
|
-
| **怎么用(三步)** | ①
|
|
28
|
-
| **是否初始化 `.workflow`** |
|
|
27
|
+
| **怎么用(三步)** | ① 先按「〇」定位项目根目录,再定状态目录 → ② 存在就读 STATE/TASKS/ROADMAP/DECISIONS + 近期 logs;不存在就初始化 → ③ 全程按「二/三/四」执行,收工输出「五」锚点。 |
|
|
28
|
+
| **是否初始化 `.workflow`** | **项目型会话**(能确定项目根目录 / 要落盘 / 多步开发)→ 自动初始化并全程执行;**轻量临时会话**(纯问答 / 一次性)→ 不初始化,只按需提示。 |
|
|
29
29
|
| **AI 该记住什么** | 只记「项目状态类」:进度 / 任务 / 决策 / 流水。**不记**:AI 人格 / 用户偏好 / 关系 / 跨项目通用知识(非项目状态,不写入本技能状态文件)。 |
|
|
30
30
|
---
|
|
31
31
|
|
|
@@ -49,40 +49,84 @@ metadata:
|
|
|
49
49
|
- **不必单独用**:只用单一智能体、自带记忆够用、项目很轻 → 自带记忆即可,本技能是锦上添花。
|
|
50
50
|
---
|
|
51
51
|
|
|
52
|
-
##
|
|
52
|
+
## 〇、路径模型与状态目录判定
|
|
53
53
|
|
|
54
|
-
>
|
|
54
|
+
> 这一节解决一个高频混淆:**项目根目录不等于源码目录,`.git` 也不能单独决定项目根目录。** 状态跟着项目根目录走,不跟着某一个代码仓库走。
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
### 1. 三个概念(一句话分清)
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
| 概念 | 定义 | 是否放 `.workflow` |
|
|
59
|
+
| --- | --- | --- |
|
|
60
|
+
| **项目根目录** | 拥有这个项目全部状态的目录;源码、文档、素材、配置都可以放在它里面。它不要求有 Git。 | **放这里**:`<项目根目录>\.workflow\` |
|
|
61
|
+
| **源码目录** | 存放代码、资源或某个 Git 仓库的目录;它只是项目内部的一个位置。 | 不放;除非用户明确说明“它同时就是项目根目录” |
|
|
62
|
+
| **工作区根目录** | 下面并列放着多个项目根目录的父目录;它不拥有某一个项目的状态。 | 不放;先选具体项目根目录,再放到项目根目录下 |
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
- **已指定 / 已锚定项目目录**(含用户自建的统一工作区根目录)→ `base` = 用户指定的项目根目录 / 工作区根目录。
|
|
62
|
-
- **未指定项目目录**(临时会话 / 无固定工作目录)→ `base` = 会话开始时宿主给的**当前工作目录(cwd)**,AI 启动时读取即可,不要写死。
|
|
64
|
+
一句话:**项目根目录 = 状态锚点;源码目录 = 实现位置;工作区根 = 项目容器。**
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
- `base` **本身就是一个项目根目录**(含项目标识,如 `.git`、项目配置、或用户明确指向的单一项目)→ 状态文件放 `base` 下 `.workflow\`
|
|
66
|
-
```
|
|
67
|
-
<base>\.workflow\
|
|
68
|
-
├── STATE.md
|
|
69
|
-
├── TASKS.md
|
|
70
|
-
├── DECISIONS.md
|
|
71
|
-
├── ROADMAP.md
|
|
72
|
-
└── logs\
|
|
73
|
-
└── YYYY-MM-DD.md
|
|
74
|
-
```
|
|
75
|
-
- `base` 是**工作区根目录**(下面并列多个项目子目录)→ 按项目名建子目录:`<base>\<项目名>\.workflow\`(结构同上)。
|
|
66
|
+
标准形态(默认按这个理解):
|
|
76
67
|
|
|
77
|
-
|
|
68
|
+
```text
|
|
69
|
+
<项目根目录>\
|
|
70
|
+
├── .workflow\ # 工作流;始终直接放在项目根目录
|
|
71
|
+
└── <源码目录>\ # 代码目录;位于项目根目录之下
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
标准只规定两件事:**`.workflow` 必须直接放在项目根目录下;源码目录属于项目根目录内部。** 实际项目里源码目录叫什么、放在哪一层、是否有特殊布局,由用户按项目情况调整,本技能不替用户改造项目结构。
|
|
75
|
+
|
|
76
|
+
### 2. 唯一状态目录
|
|
77
|
+
|
|
78
|
+
状态目录固定为 **项目根目录下的 `.workflow\`**:
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
<项目根目录>\.workflow\
|
|
82
|
+
├── STATE.md
|
|
83
|
+
├── TASKS.md
|
|
84
|
+
├── DECISIONS.md
|
|
85
|
+
├── ROADMAP.md
|
|
86
|
+
└── logs\
|
|
87
|
+
└── YYYY-MM-DD.md
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**对同一项目,任何智能体会话(无论 Codex / Cursor / Hermes / OpenCode…)都读写这一份 `.workflow\`**,不得因为使用的智能体不同而另建一份。
|
|
91
|
+
|
|
92
|
+
以下信号都**不能单独判定项目根目录**:`.git`、`package.json`、`src`、`app`、`README`、当前目录是不是 Git 仓库根。它们只能说明当前目录“像源码”,不能说明它“拥有整个项目”。
|
|
93
|
+
|
|
94
|
+
### 3. 判定顺序(从强到弱)
|
|
95
|
+
|
|
96
|
+
项目根目录只认两种证据,按顺序执行:
|
|
97
|
+
|
|
98
|
+
1. **用户明确指定项目根目录**(直接说项目根目录、给出交接锚点的“路径”,或确认“当前目录就是项目根目录”)→ 这是项目根目录。
|
|
99
|
+
2. **从 cwd 向上查找已有 `.workflow\STATE.md`** → 找到最近的一份;它所在的父目录就是项目根目录。**已有 `.workflow` 永不自动迁移、复制或重建。**
|
|
100
|
+
3. **两种证据都没有** → **停止初始化,先问一个问题**:`这个任务的项目根目录是哪一个?` 不得用 `.git`、`package.json`、`src`、`README`、cwd 或目录结构自行猜测。
|
|
78
101
|
|
|
79
|
-
|
|
102
|
+
如果用户明确说 cwd 就是项目根目录,则使用 cwd;如果用户说项目根目录在上层,则使用上层;如果用户给的是工作区根,则继续问具体项目根目录。判断依据永远来自用户或已有 `.workflow`,不来自目录里有什么文件。
|
|
103
|
+
|
|
104
|
+
定位时只处理项目根目录;源码目录如何组织,不参与 `.workflow` 的位置判定。
|
|
105
|
+
|
|
106
|
+
4. **不要写死任何默认路径。** 不同宿主给未指定项目的会话分配的 cwd 可能不同;不能把某个盘符或目录当通用默认。
|
|
107
|
+
|
|
108
|
+
项目名取项目根目录名;同名冲突时附加路径哈希。
|
|
109
|
+
|
|
110
|
+
> 兼容红线:本次规则只影响首次初始化和解释口径。任何已经存在的 `.workflow\` 保持原位,不因源码仓库嵌套、目录改名或规则升级而迁移。
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 〇·一、快速定位例子
|
|
115
|
+
|
|
116
|
+
| 场景 | 项目根目录 | 状态目录 |
|
|
117
|
+
| --- | --- | --- |
|
|
118
|
+
| 标准形态 | `<项目根目录>` | `<项目根目录>\.workflow\` |
|
|
119
|
+
| 用户明确指定项目根目录 | 用户指定的目录 | `<项目根目录>\.workflow\` |
|
|
120
|
+
| 向上找到已有 `.workflow` | `.workflow` 的父目录 | 已有 `.workflow\`,原地沿用 |
|
|
121
|
+
| 没有用户指定,也没有已有 `.workflow` | 先问 | 不创建 |
|
|
122
|
+
|
|
123
|
+
更完整的路径走查见 `references/path-model.md`。
|
|
80
124
|
|
|
81
125
|
---
|
|
82
126
|
|
|
83
127
|
## 一、项目状态体系
|
|
84
128
|
|
|
85
|
-
|
|
129
|
+
状态文件结构固定一致。**所有状态文件与流水日志都存放在本项目根目录的 `.workflow\` 状态目录下**(位置见「〇」),项目之间互不共享、互不读写:
|
|
86
130
|
|
|
87
131
|
文件首行格式约定:
|
|
88
132
|
- `STATE.md` 首行:`# 项目状态`,下面依次为 `## 当前进度`、`## 最近决定`、`## 遗留问题`、`## 下一步`
|
|
@@ -95,7 +139,7 @@ metadata:
|
|
|
95
139
|
|
|
96
140
|
## 二、开工协议(每次会话开始必做)
|
|
97
141
|
|
|
98
|
-
1.
|
|
142
|
+
1. 按「〇、路径模型与状态目录判定」确定状态目录,检查 `.workflow\STATE.md` 是否存在。
|
|
99
143
|
2. **存在** → 完整读取 `STATE.md`、`TASKS.md`、`ROADMAP.md`、`DECISIONS.md`,最近几天的 `logs/*.md` 首屏,恢复上下文。
|
|
100
144
|
3. **不存在** → 视为新项目,按「一、项目状态体系」初始化全部文件,写入项目背景和首个目标,然后向用户确认定位是否准确。
|
|
101
145
|
4. **一个会话一个里程碑**:根据 `ROADMAP.md` 确定本次只交付一个里程碑/目标,不散开做多件事;做完就收工开新会话,别让单个会话聊太长而失忆。
|
|
@@ -189,4 +233,11 @@ metadata:
|
|
|
189
233
|
## 七、与既有项目机制的协调
|
|
190
234
|
|
|
191
235
|
- **项目已有自己的交接/状态机制**:沿用其机制,不必强制迁移到本标准结构,但必须满足两个强制点——开工先读状态再声称了解;收工更新状态并留锚点。
|
|
192
|
-
- **新项目 / 无既有机制**:按「〇、判定规则」初始化状态目录,完整执行本协议。
|
|
236
|
+
- **新项目 / 无既有机制**:按「〇、判定规则」初始化状态目录,完整执行本协议。
|
|
237
|
+
|
|
238
|
+
## 八、参考文档
|
|
239
|
+
|
|
240
|
+
- 常见问题:`references/faq.md`
|
|
241
|
+
- 路径模型:`references/path-model.md`
|
|
242
|
+
- 复杂场景走查:`references/walkthroughs.md`
|
|
243
|
+
- 异常恢复手册:`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,
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Cross-session / cross-project workflow standard for all AI agents: read the state on start, keep .workflow at the project root, persist logs/tasks/decisions while working, and leave a self-contained handoff anchor on finish. The project root is the state anchor; source directories may be nested and .git alone does not define the project root.",
|
|
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,37 @@
|
|
|
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
|
+
- 恢复:确认后从下一步继续,不假装记得对话内容。
|
|
32
|
+
|
|
33
|
+
## 6. 误把源码目录当项目根目录
|
|
34
|
+
|
|
35
|
+
- 信号:某个子目录有 `.git`,AI 在它下面新建了 `.workflow`,但上层其实已有项目根目录或状态。
|
|
36
|
+
- 动作:立即停止新增写入;先检查上层已有 `.workflow` 和用户指定的项目根目录;不要自动移动或合并文件。
|
|
37
|
+
- 恢复:确认项目根目录后,由用户确认如何处理误建的 `.workflow`;后续状态只写入正确项目根目录,已有正确 `.workflow` 保持原位。
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# 元序常见问题
|
|
2
|
+
|
|
3
|
+
## 速查索引
|
|
4
|
+
|
|
5
|
+
- **适用**:什么任务用 · 一次性问答要不要用
|
|
6
|
+
- **状态**:目录在哪 · 项目根目录与源码目录的区别 · 多智能体如何共享 · 文件太大怎么办
|
|
7
|
+
- **协作**:并发写入 · 既有机制兼容 · 轻量会话简化
|
|
8
|
+
- **收尾**:锚点格式 · 中断恢复
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. 什么任务应该使用元序?
|
|
13
|
+
|
|
14
|
+
项目型、跨会话、多步骤、需要落盘状态的任务。一次性问答或纯查资料不需要初始化状态目录。
|
|
15
|
+
|
|
16
|
+
## 2. 状态目录在哪里?
|
|
17
|
+
|
|
18
|
+
状态目录固定为 `<项目根目录>\.workflow\`。项目根目录只认两种证据:用户明确指定,或从 cwd 向上找到已有 `.workflow`。两种都没有时先问,不用 `.git`、`package.json`、`src`、`README`、cwd 或目录结构自行猜。已有 `.workflow` 永不自动迁移。
|
|
19
|
+
|
|
20
|
+
`.git` 只是版本控制标记,不能单独决定项目根目录。源码目录可以是项目根目录的子目录,也可以有独立 `.git`。
|
|
21
|
+
|
|
22
|
+
## 2.1 项目根目录、源码目录、工作区根有什么区别?
|
|
23
|
+
|
|
24
|
+
| 名称 | 含义 | `.workflow` |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| 项目根目录 | 拥有整个项目状态的目录 | 放这里 |
|
|
27
|
+
| 源码目录 | 代码 / 资源 / 某个仓库所在位置 | 不放,除非用户明确说明它同时就是项目根目录 |
|
|
28
|
+
| 工作区根目录 | 并列多个项目根目录的父目录 | 不放;先选具体项目根目录 |
|
|
29
|
+
|
|
30
|
+
标准形态:项目根目录下直接放 `.workflow`,源码目录属于项目根目录内部。实际项目中源码目录怎么命名、怎么分层,由用户按项目情况调整。
|
|
31
|
+
|
|
32
|
+
## 3. 多个智能体能共享状态吗?
|
|
33
|
+
|
|
34
|
+
可以。同一项目内的智能体读写同一份状态文件,形成单一事实源。若出现不同步,先确认它们的项目根目录是否一致。
|
|
35
|
+
|
|
36
|
+
## 4. 状态文件太大怎么办?
|
|
37
|
+
|
|
38
|
+
日志按天拆分;STATE 只保留当前进度,历史快照放 ROADMAP / DECISIONS。超过约 500 行时应拆分或归档,避免每次开工读入过多内容。
|
|
39
|
+
|
|
40
|
+
## 5. 多个智能体同时写入怎么办?
|
|
41
|
+
|
|
42
|
+
尽量由一个会话负责写入。若必须并发,先读取再小步追加,不要整文件重写;冲突时以文件内容为准,合并后写入。
|
|
43
|
+
|
|
44
|
+
## 6. 项目已有交接机制怎么办?
|
|
45
|
+
|
|
46
|
+
沿用原机制,但必须满足两点:开工先读状态,收工更新状态并留锚点。
|
|
47
|
+
|
|
48
|
+
## 7. 轻量会话可以简化吗?
|
|
49
|
+
|
|
50
|
+
可以。只做两件事:开工读状态,收工写一条简短锚点。不要为了小任务生成完整状态结构。
|
|
51
|
+
|
|
52
|
+
## 8. 收工锚点必须固定格式吗?
|
|
53
|
+
|
|
54
|
+
必须。固定结构保证下个会话能自动解析:项目、路径、上次结束时间、当前进度、已完成、下一步、关键决定、遗留问题、开工读取路径。
|
|
55
|
+
|
|
56
|
+
## 9. 会话中断后怎么恢复?
|
|
57
|
+
|
|
58
|
+
先读状态文件,再对照用户补充信息确认恢复点;没有状态时明说缺失,请用户给恢复点。
|
|
59
|
+
|
|
60
|
+
## 10. 状态与对话记忆冲突怎么办?
|
|
61
|
+
|
|
62
|
+
以状态文件为准,并在回复中说明冲突来源。
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# 元序路径模型
|
|
2
|
+
|
|
3
|
+
本文档只规定元序的标准形态和状态位置,不规定具体项目必须怎样组织源码目录。
|
|
4
|
+
|
|
5
|
+
## 1. 标准形态
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
<项目根目录>\
|
|
9
|
+
├── .workflow\ # 工作流
|
|
10
|
+
└── <源码目录>\ # 源码目录
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
它表达三件事:
|
|
14
|
+
|
|
15
|
+
- **项目根目录**:整个项目的状态锚点。
|
|
16
|
+
- **`.workflow\`**:直接放在项目根目录下,是唯一的工作流状态目录。
|
|
17
|
+
- **源码目录**:位于项目根目录内部;实际叫什么、放在哪一层、是否嵌套多个仓库,由用户按项目情况自行调整。
|
|
18
|
+
|
|
19
|
+
标准不要求项目根目录有 Git,也不要求源码目录一定叫 `src`。这些都属于具体项目的结构,不属于元序的控制范围。
|
|
20
|
+
|
|
21
|
+
## 2. 状态位置
|
|
22
|
+
|
|
23
|
+
状态目录固定为:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
<项目根目录>\.workflow\
|
|
27
|
+
├── STATE.md
|
|
28
|
+
├── TASKS.md
|
|
29
|
+
├── DECISIONS.md
|
|
30
|
+
├── ROADMAP.md
|
|
31
|
+
└── logs\
|
|
32
|
+
└── YYYY-MM-DD.md
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
同一项目的所有智能体会话都读写这一份状态,不另建副本。
|
|
36
|
+
|
|
37
|
+
## 3. 定位项目根目录
|
|
38
|
+
|
|
39
|
+
只认两种证据,按顺序执行:
|
|
40
|
+
|
|
41
|
+
1. **用户明确指定项目根目录**:直接使用用户指定或交接锚点“路径”指向的目录。
|
|
42
|
+
2. **已有状态**:从 cwd 向上查找最近的 `.workflow\STATE.md`;其父目录就是项目根目录,原地沿用。
|
|
43
|
+
3. **两者都没有**:停止初始化,先问:`这个任务的项目根目录是哪一个?`
|
|
44
|
+
|
|
45
|
+
`.git`、`package.json`、`src`、`app`、`README`、cwd 或目录结构都不能单独判定项目根目录。
|
|
46
|
+
|
|
47
|
+
## 4. 技能边界
|
|
48
|
+
|
|
49
|
+
- 元序只规定 `.workflow` 必须位于项目根目录下。
|
|
50
|
+
- 元序不替用户设计或改造源码目录结构。
|
|
51
|
+
- 具体项目如何使用标准形态,由用户根据实际情况调整。
|
|
52
|
+
- 已有 `.workflow` 永不自动迁移、复制或重建。
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# 元序复杂场景走查
|
|
2
|
+
|
|
3
|
+
## 走查 1:项目开工
|
|
4
|
+
|
|
5
|
+
1. 先看用户是否明确指定项目根目录;再看 cwd 向上是否有已有 `.workflow\STATE.md`。
|
|
6
|
+
2. 两者都没有时停止初始化,先问“项目根目录是哪一个?”;不得用 `.git`、`package.json`、`src`、`README` 或 cwd 猜。
|
|
7
|
+
3. 读取项目根目录下 `.workflow\` 的 STATE / TASKS / ROADMAP / DECISIONS。
|
|
8
|
+
4. 汇总当前进度与下一步。
|
|
9
|
+
5. 执行前先确认本次会话目标与验收。
|
|
10
|
+
|
|
11
|
+
## 走查 2:任务中主动落盘
|
|
12
|
+
|
|
13
|
+
背景:一个功能已改完一半,后续还有测试和文档。
|
|
14
|
+
|
|
15
|
+
1. 立刻更新 STATE 当前进度。
|
|
16
|
+
2. 在 TASKS 勾选已完成项。
|
|
17
|
+
3. 如有新决策,写入 DECISIONS。
|
|
18
|
+
4. 当天日志追加一条简短记录。
|
|
19
|
+
5. 继续执行剩余步骤。
|
|
20
|
+
|
|
21
|
+
## 走查 3:收工锚点
|
|
22
|
+
|
|
23
|
+
1. 更新 STATE / TASKS / ROADMAP。
|
|
24
|
+
2. 追加当天日志。
|
|
25
|
+
3. 输出固定格式锚点,包含项目、项目根目录绝对路径、时间、进度、已完成、下一步、关键决定、遗留问题、开工读取路径。
|
|
26
|
+
4. 确认锚点与状态文件一致。
|
|
27
|
+
|
|
28
|
+
## 走查 4:源码目录里有 `.git`,项目状态该放哪?
|
|
29
|
+
|
|
30
|
+
背景:当前 cwd 位于项目根目录的源码子目录,源码目录有 `.git`;用户此前给的项目根目录是上层目录。
|
|
31
|
+
|
|
32
|
+
1. 用户指定的项目根目录优先,不因 cwd 或 `.git` 改变。
|
|
33
|
+
2. 检查项目根目录下的 `.workflow\`;存在则沿用,不存在则在项目根目录初始化。
|
|
34
|
+
3. 源码目录只负责放代码,不在源码目录另建状态。
|