cowork-flow 0.0.16 → 0.0.17
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 +34 -20
- package/package.json +1 -1
- package/src/cli.js +18 -2
- package/src/commands/init.js +155 -35
- package/src/lib/copy-template.js +3 -26
- package/template/.agent/skills/before-dev/SKILL.md +31 -0
- package/template/.agent/skills/brainstorming/SKILL.md +17 -156
- package/template/.agent/skills/break-loop/SKILL.md +16 -121
- package/template/.agent/skills/check/SKILL.md +29 -0
- package/template/.agent/skills/continue/SKILL.md +29 -0
- package/template/.agent/skills/entry-boundary/SKILL.md +49 -0
- package/template/.agent/skills/finish-work/SKILL.md +21 -152
- package/template/.agent/skills/meta/SKILL.md +30 -0
- package/template/.agent/skills/python-design/SKILL.md +27 -0
- package/template/.agent/skills/start/SKILL.md +33 -67
- package/template/.agent/skills/update-spec/SKILL.md +24 -320
- package/template/.agent/skills/writing-plans/SKILL.md +37 -127
- package/template/.codex/agents/cowork-check.toml +49 -0
- package/template/.codex/agents/cowork-implement.toml +51 -0
- package/template/.codex/agents/cowork-research.toml +45 -0
- package/template/.codex/config.toml +10 -0
- package/template/.codex/hooks/inject-workflow-state.py +140 -0
- package/template/.codex/hooks.json +15 -0
- package/template/.cowork-flow/.version +1 -1
- package/template/.cowork-flow/config.yaml +14 -26
- package/template/.cowork-flow/scripts/add_session.py +2 -2
- package/template/.cowork-flow/scripts/change.py +8 -1
- package/template/.cowork-flow/scripts/common/__init__.py +0 -6
- package/template/.cowork-flow/scripts/common/active_task.py +167 -0
- package/template/.cowork-flow/scripts/common/config.py +13 -18
- package/template/.cowork-flow/scripts/common/execution_context.py +151 -12
- package/template/.cowork-flow/scripts/common/git_context.py +53 -70
- package/template/.cowork-flow/scripts/common/paths.py +0 -119
- package/template/.cowork-flow/scripts/doctor.py +118 -0
- package/template/.cowork-flow/scripts/resume.py +14 -1
- package/template/.cowork-flow/scripts/run.py +6 -5
- package/template/.cowork-flow/scripts/subagent.py +379 -0
- package/template/.cowork-flow/scripts/task.py +92 -135
- package/template/.cowork-flow/spec/backend/database-guidelines.md +15 -18
- package/template/.cowork-flow/spec/backend/index.md +16 -13
- package/template/.cowork-flow/spec/backend/quality-guidelines.md +14 -13
- package/template/.cowork-flow/spec/frontend/index.md +20 -9
- package/template/.cowork-flow/spec/frontend/quality-guidelines.md +14 -12
- package/template/.cowork-flow/workflow.md +172 -284
- package/template/.cowork-flow/workspace/index.md +12 -5
- package/template/AGENTS.md +9 -16
- package/template/.agent/skills/agent-team-execution/SKILL.md +0 -79
- package/template/.agent/skills/brainstorming/scripts/frame-template.html +0 -214
- package/template/.agent/skills/brainstorming/scripts/helper.js +0 -88
- package/template/.agent/skills/brainstorming/scripts/server.cjs +0 -354
- package/template/.agent/skills/brainstorming/scripts/start-server.sh +0 -148
- package/template/.agent/skills/brainstorming/scripts/stop-server.sh +0 -56
- package/template/.agent/skills/brainstorming/spec-document-reviewer-prompt.md +0 -49
- package/template/.agent/skills/brainstorming/visual-companion.md +0 -287
- package/template/.agent/skills/check-cross-layer/SKILL.md +0 -158
- package/template/.agent/skills/record-session/SKILL.md +0 -78
- package/template/.agent/skills/requesting-code-review/SKILL.md +0 -103
- package/template/.agent/skills/requesting-code-review/code-reviewer.md +0 -168
- package/template/.agent/skills/subagent-driven-development/SKILL.md +0 -279
- package/template/.agent/skills/subagent-driven-development/code-quality-reviewer-prompt.md +0 -25
- package/template/.agent/skills/subagent-driven-development/implementer-prompt.md +0 -113
- package/template/.agent/skills/subagent-driven-development/spec-reviewer-prompt.md +0 -61
- package/template/.agent/skills/writing-plans/plan-document-reviewer-prompt.md +0 -49
- package/template/.cowork-flow/agent-team/adapters.yaml +0 -15
- package/template/.cowork-flow/agent-team/agents.yaml +0 -120
- package/template/.cowork-flow/agent-team/policy.yaml +0 -23
- package/template/.cowork-flow/scripts/agent_team.py +0 -681
- package/template/.cowork-flow/scripts/common/agent_team.py +0 -626
- package/template/.superpowers/dispatching-parallel-agents/SKILL.md +0 -182
- package/template/.superpowers/executing-plans/SKILL.md +0 -72
- package/template/.superpowers/finishing-a-development-branch/SKILL.md +0 -251
- package/template/.superpowers/receiving-code-review/SKILL.md +0 -213
- package/template/.superpowers/systematic-debugging/CREATION-LOG.md +0 -119
- package/template/.superpowers/systematic-debugging/SKILL.md +0 -296
- package/template/.superpowers/systematic-debugging/condition-based-waiting-example.ts +0 -158
- package/template/.superpowers/systematic-debugging/condition-based-waiting.md +0 -115
- package/template/.superpowers/systematic-debugging/defense-in-depth.md +0 -122
- package/template/.superpowers/systematic-debugging/find-polluter.sh +0 -63
- package/template/.superpowers/systematic-debugging/root-cause-tracing.md +0 -169
- package/template/.superpowers/systematic-debugging/test-academic.md +0 -14
- package/template/.superpowers/systematic-debugging/test-pressure-1.md +0 -58
- package/template/.superpowers/systematic-debugging/test-pressure-2.md +0 -68
- package/template/.superpowers/systematic-debugging/test-pressure-3.md +0 -69
- package/template/.superpowers/test-driven-development/SKILL.md +0 -371
- package/template/.superpowers/test-driven-development/testing-anti-patterns.md +0 -299
- package/template/.superpowers/using-git-worktrees/SKILL.md +0 -215
- package/template/.superpowers/using-superpowers/SKILL.md +0 -117
- package/template/.superpowers/using-superpowers/references/codex-tools.md +0 -59
- package/template/.superpowers/using-superpowers/references/copilot-tools.md +0 -42
- package/template/.superpowers/using-superpowers/references/gemini-tools.md +0 -51
- package/template/.superpowers/verification-before-completion/SKILL.md +0 -139
- package/template/.superpowers/writing-skills/SKILL.md +0 -655
- package/template/.superpowers/writing-skills/anthropic-best-practices.md +0 -1150
- package/template/.superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +0 -189
- package/template/.superpowers/writing-skills/graphviz-conventions.dot +0 -172
- package/template/.superpowers/writing-skills/persuasion-principles.md +0 -187
- package/template/.superpowers/writing-skills/render-graphs.js +0 -168
- package/template/.superpowers/writing-skills/testing-skills-with-subagents.md +0 -384
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
cowork-flow 是一个用于新项目初始化协作流程的模板仓库。它把项目说明、任务流转、规格治理、开发计划和会话记录放在一套可复制的目录结构里,帮助团队在项目早期就建立清晰的工作闭环。
|
|
4
4
|
|
|
5
|
-
这个仓库本身不绑定具体技术栈,也不提供业务代码脚手架。它提供的是协作与治理基础设施:你可以把 `template/`
|
|
5
|
+
这个仓库本身不绑定具体技术栈,也不提供业务代码脚手架。它提供的是协作与治理基础设施:你可以把 `template/` 复制到目标项目中,再按目标项目的真实情况补充技术栈、质量门禁、目录规范和提交策略。
|
|
6
6
|
|
|
7
7
|
## 适用场景
|
|
8
8
|
|
|
@@ -23,12 +23,13 @@ cowork-flow 是一个用于新项目初始化协作流程的模板仓库。它
|
|
|
23
23
|
├── README.md
|
|
24
24
|
└── template/
|
|
25
25
|
├── AGENTS.md
|
|
26
|
+
├── .codex/
|
|
27
|
+
│ └── agents/
|
|
26
28
|
├── .agent/
|
|
27
29
|
│ └── skills/
|
|
28
30
|
└── .cowork-flow/
|
|
29
31
|
├── config.yaml
|
|
30
32
|
├── workflow.md
|
|
31
|
-
├── agent-team/
|
|
32
33
|
├── scripts/
|
|
33
34
|
├── spec/
|
|
34
35
|
├── changes/
|
|
@@ -43,10 +44,16 @@ cowork-flow 是一个用于新项目初始化协作流程的模板仓库。它
|
|
|
43
44
|
项目级协作入口,包含编码前思考、简单优先、外科手术式改动、验证优先等基础原则。接入项目后,应把项目名称、技术栈、运行命令、测试命令和提交策略补齐。
|
|
44
45
|
|
|
45
46
|
`template/.agent/skills/`
|
|
46
|
-
|
|
47
|
+
本地技能入口,覆盖 start、before-dev、brainstorming、writing-plans、check、finish-work、continue、meta、python-design、update-spec 和 break-loop 等协作动作。这里的 skill 应保持通用,不承载某个业务项目的一次性细节。
|
|
48
|
+
|
|
49
|
+
`template/.codex/agents/`
|
|
50
|
+
固定角色 agent 定义,包含 `cowork-research`、`cowork-implement` 和 `cowork-check`。主会话负责计划与收口,并用 Codex `spawn_agent` 派发固定 agent;派发必须使用 `fork_turns="none"`,提示词首行使用 `Active task: <task-dir>`。
|
|
51
|
+
|
|
52
|
+
`template/.codex/config.toml`、`template/.codex/hooks.json`、`template/.codex/hooks/`
|
|
53
|
+
Codex 项目级配置与每轮上下文注入入口。hook 会读取当前 session task、`.cowork-flow/workflow.md` 中的 `workflow-state` 片段和 `codex.dispatch_mode`,把流程状态注入到当前轮对话。
|
|
47
54
|
|
|
48
55
|
`template/.cowork-flow/`
|
|
49
|
-
工作流目录,包含流程说明、任务状态、开发者工作区、项目规范、行为变更规格、实现计划和辅助脚本。`.cowork-flow/config.yaml`
|
|
56
|
+
工作流目录,包含流程说明、任务状态、开发者工作区、项目规范、行为变更规格、实现计划和辅助脚本。`.cowork-flow/config.yaml` 只承载真实接线的 session/journal, Codex hint, and task lifecycle hook settings。
|
|
50
57
|
|
|
51
58
|
`template/.cowork-flow/spec/`
|
|
52
59
|
项目规范目录,预置了 backend、frontend 和 guides 三类说明。接入时应按项目事实保留、改写或删除对应规范。
|
|
@@ -57,9 +64,6 @@ cowork-flow 是一个用于新项目初始化协作流程的模板仓库。它
|
|
|
57
64
|
`template/.cowork-flow/plans/`
|
|
58
65
|
保存可执行步骤、验证方式和执行状态。
|
|
59
66
|
|
|
60
|
-
`template/.cowork-flow/agent-team/`
|
|
61
|
-
保存 agent team 的项目级 registry、适配器和策略。默认适配器是 `codex`,由主 agent 调度 Codex 子 agent;没有子 agent 能力时可退回 `manual` 提示词模式。
|
|
62
|
-
|
|
63
67
|
## 快速开始
|
|
64
68
|
|
|
65
69
|
使用 CLI 把模板内容安装到目标项目根目录:
|
|
@@ -68,17 +72,23 @@ cowork-flow 是一个用于新项目初始化协作流程的模板仓库。它
|
|
|
68
72
|
npx cowork-flow init ./my-project
|
|
69
73
|
```
|
|
70
74
|
|
|
75
|
+
`init` 会显式要求开发者身份。交互式终端会提示输入;脚本或 CI 请传入:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npx cowork-flow init ./my-project --developer <your-name>
|
|
79
|
+
```
|
|
80
|
+
|
|
71
81
|
也可以先全局安装:
|
|
72
82
|
|
|
73
83
|
```bash
|
|
74
84
|
npm install -g cowork-flow
|
|
75
|
-
cowork-flow init ./my-project
|
|
85
|
+
cowork-flow init ./my-project --developer <your-name>
|
|
76
86
|
```
|
|
77
87
|
|
|
78
88
|
初始化后优先完成这些配置:
|
|
79
89
|
|
|
80
90
|
1. 更新 `AGENTS.md` 中的项目名称、技术栈、命令和提交策略。
|
|
81
|
-
2.
|
|
91
|
+
2. 按需调整 `.cowork-flow/config.yaml` 中的 session/journal, Codex hint, and task lifecycle hook settings。
|
|
82
92
|
3. 更新 `.cowork-flow/workflow.md` 中与项目流程不一致的门禁、分级和完成定义。
|
|
83
93
|
4. 按项目实际情况调整 `.cowork-flow/spec/`,删除不存在的 frontend、backend 或行为变更场景。
|
|
84
94
|
5. 按团队实践使用 `.cowork-flow/changes/` 管理规格变更,使用 `.cowork-flow/plans/` 管理实现计划和验证状态。
|
|
@@ -97,8 +107,7 @@ npx cowork-flow --help
|
|
|
97
107
|
cowork-flow init ./my-project
|
|
98
108
|
```
|
|
99
109
|
|
|
100
|
-
`init`
|
|
101
|
-
在非交互环境里,这一步会自动跳过询问并默认视为已安装。
|
|
110
|
+
`init` 会直接复制模板中的 `.agent/skills/`、`.codex/` 和 `.cowork-flow/`,并初始化 `.cowork-flow/.developer` 与 `.cowork-flow/workspace/<developer>/`。交互式终端会提示输入开发者名称;非交互式环境必须传入 `--developer <name>`。`init` 不会复制额外技能包。
|
|
102
111
|
|
|
103
112
|
初始化到当前项目:
|
|
104
113
|
|
|
@@ -115,9 +124,11 @@ cowork-flow init ./my-project --dry-run
|
|
|
115
124
|
需要明确覆盖已有文件时使用:
|
|
116
125
|
|
|
117
126
|
```bash
|
|
118
|
-
cowork-flow init ./my-project --force
|
|
127
|
+
cowork-flow init ./my-project --force --developer <your-name>
|
|
119
128
|
```
|
|
120
129
|
|
|
130
|
+
`--force` 不会静默覆盖既有 `.cowork-flow/.developer`;如需重设身份,请先显式处理旧身份文件。
|
|
131
|
+
|
|
121
132
|
升级 CLI 本身:
|
|
122
133
|
|
|
123
134
|
```bash
|
|
@@ -176,18 +187,21 @@ cowork-flow sync . --dry-run
|
|
|
176
187
|
./.cowork-flow/run task start <task-dir>
|
|
177
188
|
```
|
|
178
189
|
|
|
179
|
-
执行 plan
|
|
190
|
+
执行 plan 时使用固定 cowork agents:
|
|
180
191
|
|
|
181
|
-
|
|
192
|
+
主会话负责创建/启动任务、维护计划与收口验证;可并行的实现或检查工作通过 Codex subagent 交给固定角色 agent。
|
|
182
193
|
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
194
|
+
```python
|
|
195
|
+
spawn_agent(
|
|
196
|
+
agent_type="cowork-implement",
|
|
197
|
+
fork_turns="none",
|
|
198
|
+
message="Active task: <task-dir>\n\n<assignment>",
|
|
199
|
+
)
|
|
188
200
|
```
|
|
189
201
|
|
|
190
|
-
`
|
|
202
|
+
默认角色为 `cowork-research`、`cowork-implement`、`cowork-check`,任务上下文由 agent 根据 active task 自行加载。主会话必须用 `wait_agent` 等待结果,验收输出,再用 `list_agents` / `close_agent` 收口。
|
|
203
|
+
|
|
204
|
+
Codex hook 启用后,每轮会自动注入 `<workflow-state>`,其中包含当前任务、状态来源和下一步流程提示。hook 不替代主会话验收;它只负责把 task 状态和 workflow gate 放进上下文。
|
|
191
205
|
|
|
192
206
|
记录 session:
|
|
193
207
|
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { stdin as input, stdout as output } from 'node:process';
|
|
2
|
+
import { createInterface } from 'node:readline/promises';
|
|
3
|
+
|
|
1
4
|
import { runInit } from './commands/init.js';
|
|
2
5
|
import { runSync } from './commands/sync.js';
|
|
3
6
|
import { runUpdate } from './commands/update.js';
|
|
@@ -6,7 +9,7 @@ import { readPackageInfo } from './lib/package-info.js';
|
|
|
6
9
|
const HELP = `cowork-flow
|
|
7
10
|
|
|
8
11
|
Usage:
|
|
9
|
-
cowork-flow init [target] [--dry-run] [--force]
|
|
12
|
+
cowork-flow init [target] [--developer <name>] [--dry-run] [--force]
|
|
10
13
|
cowork-flow update [--global] [--yes]
|
|
11
14
|
cowork-flow sync [target] [--dry-run] [--force]
|
|
12
15
|
cowork-flow --version
|
|
@@ -24,8 +27,21 @@ function defaultIo() {
|
|
|
24
27
|
};
|
|
25
28
|
}
|
|
26
29
|
|
|
30
|
+
async function defaultPrompt(message) {
|
|
31
|
+
if (!input.isTTY || !output.isTTY) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const readline = createInterface({ input, output });
|
|
35
|
+
try {
|
|
36
|
+
return await readline.question(message);
|
|
37
|
+
} finally {
|
|
38
|
+
readline.close();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
27
42
|
export async function main(argv = process.argv.slice(2), options = {}) {
|
|
28
43
|
const io = options.io ?? defaultIo();
|
|
44
|
+
const prompt = Object.hasOwn(options, 'prompt') ? options.prompt : defaultPrompt;
|
|
29
45
|
const [command, ...args] = argv;
|
|
30
46
|
|
|
31
47
|
try {
|
|
@@ -41,7 +57,7 @@ export async function main(argv = process.argv.slice(2), options = {}) {
|
|
|
41
57
|
}
|
|
42
58
|
|
|
43
59
|
if (command === 'init') {
|
|
44
|
-
return await runInit(args, { io, prompt
|
|
60
|
+
return await runInit(args, { io, prompt });
|
|
45
61
|
}
|
|
46
62
|
|
|
47
63
|
if (command === 'sync') {
|
package/src/commands/init.js
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { access, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join, resolve } from 'node:path';
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
applyPlan,
|
|
6
6
|
buildInitPlan,
|
|
7
|
-
buildSuperpowersPlan,
|
|
8
7
|
summarizePlan
|
|
9
8
|
} from '../lib/copy-template.js';
|
|
10
9
|
import { readPackageInfo } from '../lib/package-info.js';
|
|
11
10
|
|
|
12
11
|
function parseInitArgs(args) {
|
|
13
|
-
const options = { dryRun: false, force: false, target: process.cwd() };
|
|
14
|
-
for (
|
|
12
|
+
const options = { developer: null, dryRun: false, force: false, target: process.cwd() };
|
|
13
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
14
|
+
const arg = args[index];
|
|
15
15
|
if (arg === '--dry-run') {
|
|
16
16
|
options.dryRun = true;
|
|
17
17
|
} else if (arg === '--force') {
|
|
18
18
|
options.force = true;
|
|
19
|
+
} else if (arg === '--developer') {
|
|
20
|
+
const value = args[index + 1];
|
|
21
|
+
if (!value || value.startsWith('--')) {
|
|
22
|
+
throw new Error('Missing value for --developer');
|
|
23
|
+
}
|
|
24
|
+
options.developer = value;
|
|
25
|
+
index += 1;
|
|
26
|
+
} else if (arg.startsWith('--developer=')) {
|
|
27
|
+
options.developer = arg.slice('--developer='.length);
|
|
19
28
|
} else if (arg.startsWith('--')) {
|
|
20
29
|
throw new Error(`Unknown init option: ${arg}`);
|
|
21
30
|
} else {
|
|
@@ -25,27 +34,139 @@ function parseInitArgs(args) {
|
|
|
25
34
|
return options;
|
|
26
35
|
}
|
|
27
36
|
|
|
28
|
-
function
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
async function pathExists(path) {
|
|
38
|
+
try {
|
|
39
|
+
await access(path);
|
|
40
|
+
return true;
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (error && error.code === 'ENOENT') {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
31
47
|
}
|
|
32
48
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
49
|
+
function normalizeDeveloperName(value) {
|
|
50
|
+
const name = String(value ?? '').trim();
|
|
51
|
+
if (!name) {
|
|
52
|
+
throw new Error('Developer name required. Run: cowork-flow init <target> --developer <name>');
|
|
53
|
+
}
|
|
54
|
+
if (/[\\/]/.test(name)) {
|
|
55
|
+
throw new Error('Developer name must not contain path separators');
|
|
37
56
|
}
|
|
57
|
+
return name;
|
|
58
|
+
}
|
|
38
59
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
60
|
+
async function readExistingDeveloper(target) {
|
|
61
|
+
const developerFile = join(target, '.cowork-flow', '.developer');
|
|
62
|
+
if (!await pathExists(developerFile)) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const content = await readFile(developerFile, 'utf8');
|
|
66
|
+
const match = content.match(/^name=(.+)$/m);
|
|
67
|
+
return match ? match[1].trim() : null;
|
|
68
|
+
}
|
|
43
69
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
70
|
+
async function resolveDeveloperName(options, prompt) {
|
|
71
|
+
const existing = await readExistingDeveloper(options.target);
|
|
72
|
+
if (existing) {
|
|
73
|
+
return { existing: true, name: existing };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (options.dryRun && !options.developer) {
|
|
77
|
+
return { existing: false, name: null };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let name = options.developer;
|
|
81
|
+
if (!name && typeof prompt === 'function') {
|
|
82
|
+
name = await prompt('Developer name: ');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return { existing: false, name: normalizeDeveloperName(name) };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function todayIsoDate() {
|
|
89
|
+
return new Date().toISOString().slice(0, 10);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function initialJournalContent(name) {
|
|
93
|
+
return `# Development Journal - ${name} (Part 1)
|
|
94
|
+
|
|
95
|
+
> AI development session journal
|
|
96
|
+
> Start date: ${todayIsoDate()}
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function initialIndexContent(name) {
|
|
104
|
+
return `# Workspace Index - ${name}
|
|
105
|
+
|
|
106
|
+
> Tracks AI development session records.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Current Status
|
|
111
|
+
|
|
112
|
+
<!-- @@@auto:current-status -->
|
|
113
|
+
- **Current file**: \`journal-1.md\`
|
|
114
|
+
- **Total Sessions**: 0
|
|
115
|
+
- **Last Active**: -
|
|
116
|
+
<!-- @@@/auto:current-status -->
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Active Documents
|
|
121
|
+
|
|
122
|
+
<!-- @@@auto:active-documents -->
|
|
123
|
+
| File | Lines | Status |
|
|
124
|
+
|------|------|------|
|
|
125
|
+
| \`journal-1.md\` | ~0 | Current |
|
|
126
|
+
<!-- @@@/auto:active-documents -->
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Session History
|
|
131
|
+
|
|
132
|
+
<!-- @@@auto:session-history -->
|
|
133
|
+
| # | Date | Title | Commit |
|
|
134
|
+
|---|------|------|------|
|
|
135
|
+
<!-- @@@/auto:session-history -->
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Notes
|
|
140
|
+
|
|
141
|
+
- Sessions are appended to the journal file
|
|
142
|
+
- A new journal file is created automatically after the current file exceeds 2000 lines
|
|
143
|
+
- Use \`add_session.py\` to record sessions
|
|
144
|
+
- New records use English text; legacy records can remain as they are
|
|
145
|
+
`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async function initializeDeveloper(target, developer) {
|
|
149
|
+
const workflowDir = join(target, '.cowork-flow');
|
|
150
|
+
const developerFile = join(workflowDir, '.developer');
|
|
151
|
+
const workspaceDir = join(workflowDir, 'workspace', developer.name);
|
|
152
|
+
const journalFile = join(workspaceDir, 'journal-1.md');
|
|
153
|
+
const indexFile = join(workspaceDir, 'index.md');
|
|
154
|
+
|
|
155
|
+
await mkdir(workflowDir, { recursive: true });
|
|
156
|
+
if (!developer.existing) {
|
|
157
|
+
await writeFile(
|
|
158
|
+
developerFile,
|
|
159
|
+
`name=${developer.name}\ninitialized_at=${new Date().toISOString()}\n`,
|
|
160
|
+
'utf8'
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
await mkdir(workspaceDir, { recursive: true });
|
|
165
|
+
if (!await pathExists(journalFile)) {
|
|
166
|
+
await writeFile(journalFile, initialJournalContent(developer.name), 'utf8');
|
|
167
|
+
}
|
|
168
|
+
if (!await pathExists(indexFile)) {
|
|
169
|
+
await writeFile(indexFile, initialIndexContent(developer.name), 'utf8');
|
|
49
170
|
}
|
|
50
171
|
}
|
|
51
172
|
|
|
@@ -53,8 +174,9 @@ export async function runInit(args, { io, prompt }) {
|
|
|
53
174
|
return runInitWithOptions(args, { io, prompt });
|
|
54
175
|
}
|
|
55
176
|
|
|
56
|
-
export async function runInitWithOptions(args, { io, prompt
|
|
177
|
+
export async function runInitWithOptions(args, { io, prompt }) {
|
|
57
178
|
const options = parseInitArgs(args);
|
|
179
|
+
const developer = await resolveDeveloperName(options, prompt);
|
|
58
180
|
const packageInfo = await readPackageInfo();
|
|
59
181
|
const plan = await buildInitPlan(options.target, {
|
|
60
182
|
force: options.force,
|
|
@@ -65,24 +187,22 @@ export async function runInitWithOptions(args, { io, prompt = defaultSuperpowers
|
|
|
65
187
|
io.writeOut(summarizePlan(plan, options.dryRun));
|
|
66
188
|
|
|
67
189
|
if (options.dryRun) {
|
|
68
|
-
|
|
190
|
+
if (developer.existing) {
|
|
191
|
+
io.writeOut(`dry-run preserve-existing=.cowork-flow/.developer for developer ${developer.name}\n`);
|
|
192
|
+
} else if (developer.name) {
|
|
193
|
+
io.writeOut(`dry-run would-create=.cowork-flow/.developer for developer ${developer.name}\n`);
|
|
194
|
+
io.writeOut(`dry-run would-create=.cowork-flow/workspace/${developer.name}/\n`);
|
|
195
|
+
}
|
|
69
196
|
io.writeOut('Next: update AGENTS.md and .cowork-flow/config.yaml for this project.\n');
|
|
70
197
|
return 0;
|
|
71
198
|
}
|
|
72
199
|
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
io.writeOut(
|
|
76
|
-
|
|
77
|
-
|
|
200
|
+
await initializeDeveloper(options.target, developer);
|
|
201
|
+
if (developer.existing) {
|
|
202
|
+
io.writeOut(`Developer already initialized: ${developer.name}\n`);
|
|
203
|
+
} else {
|
|
204
|
+
io.writeOut(`Developer initialized: ${developer.name}\n`);
|
|
78
205
|
}
|
|
79
|
-
|
|
80
|
-
const superpowersPlan = await buildSuperpowersPlan(options.target, {
|
|
81
|
-
force: options.force
|
|
82
|
-
});
|
|
83
|
-
await applyPlan(superpowersPlan, { dryRun: false });
|
|
84
|
-
io.writeOut(summarizePlan(superpowersPlan, false));
|
|
85
|
-
io.writeOut('Superpowers skills were bundled into .agent/skills.\n');
|
|
86
206
|
io.writeOut('Next: update AGENTS.md and .cowork-flow/config.yaml for this project.\n');
|
|
87
207
|
return 0;
|
|
88
208
|
}
|
package/src/lib/copy-template.js
CHANGED
|
@@ -36,16 +36,12 @@ function toTemplatePath(relativePath) {
|
|
|
36
36
|
return relativePath.replaceAll('\\', '/');
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
export function isInternalTemplateFile(relativePath) {
|
|
40
|
-
return toTemplatePath(relativePath).startsWith('.superpowers/');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
39
|
export async function buildInitPlan(targetDir, options = {}) {
|
|
44
40
|
const files = await listFiles(templateRoot);
|
|
45
41
|
const actions = [];
|
|
46
42
|
|
|
47
43
|
for (const file of files) {
|
|
48
|
-
if (toTemplatePath(file) === '.cowork-flow/.version'
|
|
44
|
+
if (toTemplatePath(file) === '.cowork-flow/.version') {
|
|
49
45
|
continue;
|
|
50
46
|
}
|
|
51
47
|
|
|
@@ -69,26 +65,6 @@ export async function buildInitPlan(targetDir, options = {}) {
|
|
|
69
65
|
return actions;
|
|
70
66
|
}
|
|
71
67
|
|
|
72
|
-
export async function buildSuperpowersPlan(targetDir, options = {}) {
|
|
73
|
-
const sourceRoot = join(templateRoot, '.superpowers');
|
|
74
|
-
if (!await pathExists(sourceRoot)) {
|
|
75
|
-
return [];
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const files = await listFiles(sourceRoot);
|
|
79
|
-
const actions = [];
|
|
80
|
-
|
|
81
|
-
for (const file of files) {
|
|
82
|
-
const source = join(sourceRoot, file);
|
|
83
|
-
const destination = join(targetDir, '.agent', 'skills', file);
|
|
84
|
-
const exists = await pathExists(destination);
|
|
85
|
-
const action = exists ? (options.force ? 'update' : 'skip') : 'create';
|
|
86
|
-
actions.push({ action, source, destination, relativePath: `.agent/skills/${file}` });
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return actions;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
68
|
const PROTECTED_SYNC_FILES = new Set([
|
|
93
69
|
'.cowork-flow/config.yaml'
|
|
94
70
|
]);
|
|
@@ -102,6 +78,7 @@ const PROTECTED_SYNC_PREFIXES = [
|
|
|
102
78
|
];
|
|
103
79
|
|
|
104
80
|
const SAFE_SYNC_PREFIXES = [
|
|
81
|
+
'.codex/',
|
|
105
82
|
'.agent/skills/',
|
|
106
83
|
'.cowork-flow/'
|
|
107
84
|
];
|
|
@@ -180,7 +157,7 @@ export async function buildSyncPlan(targetDir, options = {}) {
|
|
|
180
157
|
const actions = [];
|
|
181
158
|
|
|
182
159
|
for (const file of files) {
|
|
183
|
-
if (toTemplatePath(file) === '.cowork-flow/.version'
|
|
160
|
+
if (toTemplatePath(file) === '.cowork-flow/.version') {
|
|
184
161
|
continue;
|
|
185
162
|
}
|
|
186
163
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: before-dev
|
|
3
|
+
description: Use before writing code in a cowork-flow project to load project-specific guidelines, active task context, and verification expectations.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Before Dev
|
|
7
|
+
|
|
8
|
+
Use this immediately before code edits.
|
|
9
|
+
|
|
10
|
+
## Read
|
|
11
|
+
|
|
12
|
+
1. `AGENTS.md`
|
|
13
|
+
2. `.cowork-flow/workflow.md`
|
|
14
|
+
3. Active task `prd.md`
|
|
15
|
+
4. Active task `implement.jsonl`
|
|
16
|
+
5. Relevant `.cowork-flow/spec/*/index.md`
|
|
17
|
+
6. Any exact files named by the task, plan, or user
|
|
18
|
+
|
|
19
|
+
Do not bulk-load unrelated tasks, archived sessions, or every spec file.
|
|
20
|
+
|
|
21
|
+
## Confirm
|
|
22
|
+
|
|
23
|
+
State briefly:
|
|
24
|
+
|
|
25
|
+
- Assumptions.
|
|
26
|
+
- Success criteria.
|
|
27
|
+
- Files or modules likely to change.
|
|
28
|
+
- Verification command you expect to run.
|
|
29
|
+
- Whether fixed agents or inline work are appropriate.
|
|
30
|
+
|
|
31
|
+
If the task is a bounded subagent prompt, do not convert it into main-session planning.
|