cowork-flow 0.0.2 → 0.0.4
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/LICENSE +21 -0
- package/README.md +23 -11
- package/package.json +2 -2
- package/src/lib/copy-template.js +56 -2
- package/template/.agent/skills/record-session/SKILL.md +8 -8
- package/template/.agent/skills/start/SKILL.md +75 -38
- package/template/.cowork-flow/.version +1 -1
- package/template/.cowork-flow/run +162 -0
- package/template/.cowork-flow/run.cmd +191 -0
- package/template/.cowork-flow/scripts/add_session.py +2 -2
- package/template/.cowork-flow/scripts/change.py +5 -11
- package/template/.cowork-flow/scripts/common/developer.py +1 -1
- package/template/.cowork-flow/scripts/common/git_context.py +142 -5
- package/template/.cowork-flow/scripts/get_context.py +2 -2
- package/template/.cowork-flow/scripts/init_developer.py +1 -1
- package/template/.cowork-flow/scripts/resume.py +21 -0
- package/template/.cowork-flow/scripts/task.py +116 -42
- package/template/.cowork-flow/spec/guides/pre-implementation-checklist.md +1 -1
- package/template/.cowork-flow/workflow.md +43 -19
- package/template/.cowork-flow/workspace/index.md +3 -3
- package/template/.superpowers/brainstorming/SKILL.md +5 -2
- package/template/.superpowers/brainstorming/spec-document-reviewer-prompt.md +1 -1
- package/template/.superpowers/requesting-code-review/SKILL.md +1 -1
- package/template/.superpowers/subagent-driven-development/SKILL.md +1 -1
- package/template/.superpowers/writing-plans/SKILL.md +2 -2
- package/template/AGENTS.md +13 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 fisklikewater
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -128,43 +128,55 @@ cowork-flow sync .
|
|
|
128
128
|
cowork-flow sync . --dry-run
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
`sync`
|
|
131
|
+
`sync` 默认刷新 `.agent/skills/`、`.cowork-flow/scripts/` 和 `AGENTS.md` 中的 `<!-- COWORK-FLOW:START --> ... <!-- COWORK-FLOW:END -->` 托管块,保留 `AGENTS.md` 托管块之外的项目自定义内容。`.cowork-flow/config.yaml`、`.cowork-flow/workflow.md`、`.cowork-flow/spec/`、任务、计划、变更和 workspace 记录默认受保护。只有明确传入 `--force` 时才整文件覆盖保护文件。
|
|
132
132
|
|
|
133
133
|
## 常用入口
|
|
134
134
|
|
|
135
|
+
模板内置统一入口来运行 Python 工作流脚本:
|
|
136
|
+
|
|
137
|
+
- macOS / Linux / Git Bash / WSL:`./.cowork-flow/run`
|
|
138
|
+
- Windows cmd / PowerShell:`.\.cowork-flow\run.cmd`
|
|
139
|
+
|
|
140
|
+
入口会按 `COWORK_FLOW_PYTHON`、`PYTHON`、`python3`、`python`、`py -3`
|
|
141
|
+
的顺序查找 Python 3.8+ 解释器,避免不同环境中 `python` / `python3`
|
|
142
|
+
命令不一致的问题。
|
|
143
|
+
|
|
144
|
+
下面示例使用 macOS / Linux 写法;Windows 原生命令行中把
|
|
145
|
+
`./.cowork-flow/run` 替换为 `.\.cowork-flow\run.cmd`。
|
|
146
|
+
|
|
135
147
|
初始化或查看开发者身份:
|
|
136
148
|
|
|
137
149
|
```bash
|
|
138
|
-
|
|
139
|
-
|
|
150
|
+
./.cowork-flow/run get-developer
|
|
151
|
+
./.cowork-flow/run init-developer <developer-name>
|
|
140
152
|
```
|
|
141
153
|
|
|
142
154
|
查看当前上下文:
|
|
143
155
|
|
|
144
156
|
```bash
|
|
145
|
-
|
|
146
|
-
|
|
157
|
+
./.cowork-flow/run get-context
|
|
158
|
+
./.cowork-flow/run task list
|
|
147
159
|
```
|
|
148
160
|
|
|
149
161
|
创建并验证行为变更:
|
|
150
162
|
|
|
151
163
|
```bash
|
|
152
|
-
|
|
153
|
-
|
|
164
|
+
./.cowork-flow/run change create <slug>
|
|
165
|
+
./.cowork-flow/run change validate <slug>
|
|
154
166
|
```
|
|
155
167
|
|
|
156
168
|
创建并启动任务:
|
|
157
169
|
|
|
158
170
|
```bash
|
|
159
|
-
|
|
160
|
-
|
|
171
|
+
./.cowork-flow/run task create "<title>" --slug <task-name>
|
|
172
|
+
./.cowork-flow/run task start <task-dir>
|
|
161
173
|
```
|
|
162
174
|
|
|
163
175
|
记录 session:
|
|
164
176
|
|
|
165
177
|
```bash
|
|
166
|
-
|
|
167
|
-
|
|
178
|
+
./.cowork-flow/run get-context --mode record
|
|
179
|
+
./.cowork-flow/run add-session \
|
|
168
180
|
--title "<session-title>" \
|
|
169
181
|
--commit "<commit-or-handoff-ref>" \
|
|
170
182
|
--summary "<summary>"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cowork-flow",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "CLI for installing and maintaining cowork-flow collaboration templates.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
],
|
|
15
15
|
"scripts": {
|
|
16
16
|
"test": "node --test",
|
|
17
|
-
"test:template": "
|
|
17
|
+
"test:template": "./template/.cowork-flow/run python -m unittest discover tests -v",
|
|
18
18
|
"pack:check": "npm_config_cache=/tmp/cowork-flow-npm-cache npm pack --dry-run --json",
|
|
19
19
|
"test:all": "npm test && npm run test:template && npm run pack:check"
|
|
20
20
|
},
|
package/src/lib/copy-template.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { constants } from 'node:fs';
|
|
2
|
-
import { access, copyFile, mkdir, readdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { access, chmod, copyFile, mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { dirname, join, relative } from 'node:path';
|
|
4
4
|
|
|
5
5
|
import { templateRoot } from './paths.js';
|
|
@@ -110,9 +110,14 @@ const SAFE_SYNC_PREFIXES = [
|
|
|
110
110
|
|
|
111
111
|
const SAFE_SYNC_FILES = new Set([
|
|
112
112
|
'.cowork-flow/.gitignore',
|
|
113
|
-
'.cowork-flow/.version'
|
|
113
|
+
'.cowork-flow/.version',
|
|
114
|
+
'.cowork-flow/run',
|
|
115
|
+
'.cowork-flow/run.cmd'
|
|
114
116
|
]);
|
|
115
117
|
|
|
118
|
+
const COWORK_FLOW_START = '<!-- COWORK-FLOW:START -->';
|
|
119
|
+
const COWORK_FLOW_END = '<!-- COWORK-FLOW:END -->';
|
|
120
|
+
|
|
116
121
|
function isProtectedSyncFile(relativePath) {
|
|
117
122
|
return PROTECTED_SYNC_FILES.has(relativePath)
|
|
118
123
|
|| PROTECTED_SYNC_PREFIXES.some((prefix) => relativePath.startsWith(prefix));
|
|
@@ -124,6 +129,48 @@ function isSafeSyncFile(relativePath) {
|
|
|
124
129
|
|| relativePath.endsWith('/.gitkeep');
|
|
125
130
|
}
|
|
126
131
|
|
|
132
|
+
function replaceManagedBlock(targetContent, templateContent) {
|
|
133
|
+
const targetStart = targetContent.indexOf(COWORK_FLOW_START);
|
|
134
|
+
const targetEnd = targetContent.indexOf(COWORK_FLOW_END, targetStart + COWORK_FLOW_START.length);
|
|
135
|
+
const templateStart = templateContent.indexOf(COWORK_FLOW_START);
|
|
136
|
+
const templateEnd = templateContent.indexOf(COWORK_FLOW_END, templateStart + COWORK_FLOW_START.length);
|
|
137
|
+
|
|
138
|
+
if (targetStart === -1 || targetEnd === -1 || templateStart === -1 || templateEnd === -1) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const targetBlockEnd = targetEnd + COWORK_FLOW_END.length;
|
|
143
|
+
const templateBlockEnd = templateEnd + COWORK_FLOW_END.length;
|
|
144
|
+
return [
|
|
145
|
+
targetContent.slice(0, targetStart),
|
|
146
|
+
templateContent.slice(templateStart, templateBlockEnd),
|
|
147
|
+
targetContent.slice(targetBlockEnd)
|
|
148
|
+
].join('');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function buildAgentsSyncAction({ source, destination, exists, options }) {
|
|
152
|
+
if (!exists || options.force) {
|
|
153
|
+
return {
|
|
154
|
+
action: exists ? 'update' : 'create',
|
|
155
|
+
source,
|
|
156
|
+
destination,
|
|
157
|
+
relativePath: 'AGENTS.md'
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const [templateContent, targetContent] = await Promise.all([
|
|
162
|
+
readFile(source, 'utf8'),
|
|
163
|
+
readFile(destination, 'utf8')
|
|
164
|
+
]);
|
|
165
|
+
const content = replaceManagedBlock(targetContent, templateContent);
|
|
166
|
+
|
|
167
|
+
if (content === null) {
|
|
168
|
+
return { action: 'protected', source, destination, relativePath: 'AGENTS.md' };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return { action: 'update', source, destination, relativePath: 'AGENTS.md', content };
|
|
172
|
+
}
|
|
173
|
+
|
|
127
174
|
export async function buildSyncPlan(targetDir, options = {}) {
|
|
128
175
|
if (!await pathExists(join(targetDir, '.cowork-flow'))) {
|
|
129
176
|
throw new Error(`Target is not initialized: ${targetDir}`);
|
|
@@ -140,6 +187,11 @@ export async function buildSyncPlan(targetDir, options = {}) {
|
|
|
140
187
|
const source = join(templateRoot, file);
|
|
141
188
|
const destination = join(targetDir, file);
|
|
142
189
|
const exists = await pathExists(destination);
|
|
190
|
+
if (file === 'AGENTS.md') {
|
|
191
|
+
actions.push(await buildAgentsSyncAction({ source, destination, exists, options }));
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
|
|
143
195
|
const protectedFile = isProtectedSyncFile(file) && !options.force && exists;
|
|
144
196
|
const safeFile = isSafeSyncFile(file);
|
|
145
197
|
|
|
@@ -192,6 +244,8 @@ export async function applyPlan(actions, options = {}) {
|
|
|
192
244
|
await writeFile(item.destination, item.content, 'utf8');
|
|
193
245
|
} else {
|
|
194
246
|
await copyFile(item.source, item.destination);
|
|
247
|
+
const sourceStats = await stat(item.source);
|
|
248
|
+
await chmod(item.destination, sourceStats.mode & 0o777);
|
|
195
249
|
}
|
|
196
250
|
}
|
|
197
251
|
}
|
|
@@ -24,7 +24,7 @@ Do not archive a task while the plan file still shows stale progress.
|
|
|
24
24
|
### Step 1: Get Context & Check Tasks
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
|
|
27
|
+
./.cowork-flow/run get-context --mode record
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
[!] Archive tasks whose work is **actually done** — judge by work status, not the `status` field in task.json:
|
|
@@ -33,20 +33,20 @@ python3 ./.cowork-flow/scripts/get_context.py --mode record
|
|
|
33
33
|
- Don't skip archiving just because `status` still says `planning` or `in_progress`
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
|
|
36
|
+
./.cowork-flow/run task archive <task-name>
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
### Step 2: One-Click Add Session
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
42
|
# Method 1: Simple parameters
|
|
43
|
-
|
|
43
|
+
./.cowork-flow/run add-session \
|
|
44
44
|
--title "Session Title" \
|
|
45
45
|
--commit "hash1,hash2" \
|
|
46
46
|
--summary "Brief summary of what was done"
|
|
47
47
|
|
|
48
48
|
# Method 2: Pass detailed content via stdin
|
|
49
|
-
cat << 'EOF' |
|
|
49
|
+
cat << 'EOF' | ./.cowork-flow/run add-session --title "Title" --commit "hash"
|
|
50
50
|
| Feature | Description |
|
|
51
51
|
|---------|-------------|
|
|
52
52
|
| Change | Description |
|
|
@@ -72,7 +72,7 @@ EOF
|
|
|
72
72
|
|
|
73
73
|
| Command | Purpose |
|
|
74
74
|
|---------|---------|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
75
|
+
| `./.cowork-flow/run get-context --mode record` | Get context for record-session |
|
|
76
|
+
| `./.cowork-flow/run add-session --title "..." --commit "..."` | **One-click add session (recommended)** |
|
|
77
|
+
| `./.cowork-flow/run task archive <name>` | Archive completed task (auto-commits) |
|
|
78
|
+
| `./.cowork-flow/run task list` | List active tasks |
|
|
@@ -7,6 +7,14 @@ description: Use when beginning a development session in a project that uses the
|
|
|
7
7
|
|
|
8
8
|
Initialize your AI development session and begin working on tasks.
|
|
9
9
|
|
|
10
|
+
<HARD-GATE>
|
|
11
|
+
Any request that changes repository files MUST go through this skill's task workflow.
|
|
12
|
+
Questions may be answered directly, but file edits are at least `L0` and require a task,
|
|
13
|
+
PRD, context initialization, task activation, verification, and session recording.
|
|
14
|
+
Do not use a direct-edit shortcut unless the user explicitly tells you not to use
|
|
15
|
+
cowork-flow for this task.
|
|
16
|
+
</HARD-GATE>
|
|
17
|
+
|
|
10
18
|
---
|
|
11
19
|
|
|
12
20
|
## Operation Types
|
|
@@ -36,16 +44,21 @@ cat AGENTS.md
|
|
|
36
44
|
- Best practices
|
|
37
45
|
- Project-specific collaboration and documentation rules
|
|
38
46
|
|
|
47
|
+
Command examples use macOS / Linux / Git Bash / WSL syntax. In native Windows
|
|
48
|
+
cmd or PowerShell, replace `./.cowork-flow/run <command>` with
|
|
49
|
+
`.\.cowork-flow\run.cmd <command>`.
|
|
50
|
+
|
|
39
51
|
> **Important**:
|
|
40
52
|
> Reusable skills are already part of the template. During project onboarding, put project-specific facts in `AGENTS.md`, `.cowork-flow/workflow.md`, `.cowork-flow/config.yaml`, and `.cowork-flow/spec/` rather than editing `SKILL.md`.
|
|
41
53
|
|
|
42
54
|
### Step 2: Get Current Context
|
|
43
55
|
|
|
44
56
|
```bash
|
|
45
|
-
|
|
57
|
+
./.cowork-flow/run resume
|
|
46
58
|
```
|
|
47
59
|
|
|
48
|
-
This shows: developer identity, git status, current task (if any), active tasks
|
|
60
|
+
This shows: developer identity, git status, current task (if any), active tasks, and
|
|
61
|
+
the minimal `RESUME CHECKLIST` for loading task details on demand.
|
|
49
62
|
|
|
50
63
|
### Step 3: Read Guidelines Index
|
|
51
64
|
|
|
@@ -71,13 +84,19 @@ When user describes a task, classify it:
|
|
|
71
84
|
|
|
72
85
|
| Type | Criteria | Workflow |
|
|
73
86
|
|------|----------|----------|
|
|
74
|
-
| **Question** | User asks about code, architecture, or how something works | Answer directly |
|
|
75
|
-
| **
|
|
76
|
-
| **
|
|
77
|
-
| **
|
|
87
|
+
| **Question** | User asks about code, architecture, or how something works, and no repository files need to change | Answer directly after session context is loaded |
|
|
88
|
+
| **L0 Change** | Docs, tests, comments, config, small refactors, or any file change without external behavior change | Task Workflow, no Behavior Change Gate |
|
|
89
|
+
| **L1 Change** | Bounded behavior change in one module or one interface | Behavior Change Gate → Task Workflow |
|
|
90
|
+
| **L2 Change** | Cross-layer, architectural, migration, permission, compatibility, release, or security-impacting change | Behavior Change Gate + `design.md` → Task Workflow |
|
|
91
|
+
| **Unclear / Complex** | Vague goal, multiple possible interpretations, or architectural decisions | **Brainstorm → classify L0/L1/L2 → gated workflow** |
|
|
78
92
|
|
|
79
93
|
### Decision Rule
|
|
80
94
|
|
|
95
|
+
> **Any file change must enter L0 / L1 / L2 workflow.**
|
|
96
|
+
>
|
|
97
|
+
> A typo, comment, one-line fix, or "quick" change is still a repository change.
|
|
98
|
+
> Do not treat small size as permission to skip PRD, context, verification, or session recording.
|
|
99
|
+
>
|
|
81
100
|
> **If in doubt, use Brainstorm + Task Workflow.**
|
|
82
101
|
>
|
|
83
102
|
> Task Workflow ensures code-specs are injected to the right context, resulting in higher quality code.
|
|
@@ -93,9 +112,9 @@ Before entering Task Workflow, classify the change as `L0` / `L1` / `L2` using `
|
|
|
93
112
|
|
|
94
113
|
- `L0`: No external behavior change. Continue with the existing Task Workflow.
|
|
95
114
|
- `L1`: Behavior change in a bounded module. Do **not** go straight to PRD/Research. First run:
|
|
96
|
-
1.
|
|
115
|
+
1. `./.cowork-flow/run change create <slug>`
|
|
97
116
|
2. `superpowers:brainstorming` to create or complete `proposal/spec`
|
|
98
|
-
3.
|
|
117
|
+
3. `./.cowork-flow/run change validate <slug>`
|
|
99
118
|
4. `superpowers:writing-plans` to produce the implementation plan
|
|
100
119
|
- `L2`: Same as `L1`, plus required `design.md`. Multi-perspective review happens after implementation in the review gate.
|
|
101
120
|
|
|
@@ -114,24 +133,24 @@ Before Phase 2, always complete this task handoff:
|
|
|
114
133
|
|
|
115
134
|
---
|
|
116
135
|
|
|
117
|
-
## Question
|
|
136
|
+
## Question Only
|
|
118
137
|
|
|
119
|
-
For questions
|
|
138
|
+
For questions that do not modify repository files, work directly:
|
|
120
139
|
|
|
121
|
-
1. Answer
|
|
122
|
-
2. If
|
|
140
|
+
1. Answer the question.
|
|
141
|
+
2. If the answer reveals that files should change, stop and re-enter Task Classification.
|
|
142
|
+
3. Do not modify files from this section.
|
|
123
143
|
|
|
124
144
|
---
|
|
125
145
|
|
|
126
|
-
## Simple Task
|
|
146
|
+
## L0 / Simple Task
|
|
127
147
|
|
|
128
|
-
For simple, well-defined tasks:
|
|
148
|
+
For simple, well-defined tasks that modify files without external behavior change:
|
|
129
149
|
|
|
130
|
-
1.
|
|
131
|
-
2.
|
|
132
|
-
3.
|
|
133
|
-
4. **If it is `
|
|
134
|
-
5. **If it is `L0`, execute ALL steps below without stopping. Do NOT ask for additional confirmation between steps.**
|
|
150
|
+
1. Clarify only if the goal, scope, or verification method is unclear.
|
|
151
|
+
2. Determine whether the task is `L0`, `L1`, or `L2`.
|
|
152
|
+
3. **If it is `L1/L2`, complete the Behavior Change Gate first. After that, execute Path B Step 2 and Step 3, complete the task handoff, then continue with Phase 2.**
|
|
153
|
+
4. **If it is `L0`, execute ALL steps below without stopping. Do NOT ask for additional confirmation between steps. Do NOT switch to ad hoc direct editing.**
|
|
135
154
|
- Create task directory (Phase 1 Path B, Step 2)
|
|
136
155
|
- Write PRD (Step 3)
|
|
137
156
|
- Research codebase (Phase 2, Step 5)
|
|
@@ -202,7 +221,7 @@ If unclear, ask clarifying questions.
|
|
|
202
221
|
**Step 2: Create Task Directory** `[AI]`
|
|
203
222
|
|
|
204
223
|
```bash
|
|
205
|
-
TASK_DIR=$(
|
|
224
|
+
TASK_DIR=$(./.cowork-flow/run task create "<title>" --slug <name>)
|
|
206
225
|
```
|
|
207
226
|
|
|
208
227
|
**Step 3: Write PRD** `[AI]`
|
|
@@ -275,7 +294,7 @@ Use this output format:
|
|
|
275
294
|
Initialize default context:
|
|
276
295
|
|
|
277
296
|
```bash
|
|
278
|
-
|
|
297
|
+
./.cowork-flow/run task init-context "$TASK_DIR" <type>
|
|
279
298
|
# type: backend | frontend | fullstack
|
|
280
299
|
```
|
|
281
300
|
|
|
@@ -283,25 +302,25 @@ Add specs found in your research pass:
|
|
|
283
302
|
|
|
284
303
|
```bash
|
|
285
304
|
# For each relevant spec and code pattern:
|
|
286
|
-
|
|
287
|
-
|
|
305
|
+
./.cowork-flow/run task add-context "$TASK_DIR" implement "<path>" "<reason>"
|
|
306
|
+
./.cowork-flow/run task add-context "$TASK_DIR" check "<path>" "<reason>"
|
|
288
307
|
```
|
|
289
308
|
|
|
290
309
|
If this task came through the Behavior Change Gate, add the approved artifacts before coding:
|
|
291
310
|
|
|
292
311
|
```bash
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
312
|
+
./.cowork-flow/run task add-context "$TASK_DIR" implement ".cowork-flow/changes/<slug>/proposal.md" "Approved change proposal"
|
|
313
|
+
./.cowork-flow/run task add-context "$TASK_DIR" implement ".cowork-flow/changes/<slug>/spec.md" "Approved behavior spec"
|
|
314
|
+
./.cowork-flow/run task add-context "$TASK_DIR" implement ".cowork-flow/changes/<slug>/design.md" "Approved design for L2 changes"
|
|
315
|
+
./.cowork-flow/run task add-context "$TASK_DIR" implement ".cowork-flow/plans/YYYY-MM-DD-<slug>.md" "Approved implementation plan"
|
|
316
|
+
./.cowork-flow/run task add-context "$TASK_DIR" check ".cowork-flow/changes/<slug>/spec.md" "Check implementation against approved spec"
|
|
317
|
+
./.cowork-flow/run task add-context "$TASK_DIR" check ".cowork-flow/plans/YYYY-MM-DD-<slug>.md" "Check implementation against approved plan"
|
|
299
318
|
```
|
|
300
319
|
|
|
301
320
|
**Step 7: Activate Task** `[AI]`
|
|
302
321
|
|
|
303
322
|
```bash
|
|
304
|
-
|
|
323
|
+
./.cowork-flow/run task start "$TASK_DIR"
|
|
305
324
|
```
|
|
306
325
|
|
|
307
326
|
This sets `.current-task` so hooks can inject context.
|
|
@@ -339,7 +358,7 @@ Run a quality pass against check context:
|
|
|
339
358
|
|
|
340
359
|
## Continuing Existing Task
|
|
341
360
|
|
|
342
|
-
If `
|
|
361
|
+
If `resume.py` shows a current task:
|
|
343
362
|
|
|
344
363
|
1. Read the task's `prd.md` to understand the goal
|
|
345
364
|
2. Check `task.json` for current status
|
|
@@ -349,6 +368,23 @@ If yes, resume from the appropriate step (usually Step 7 or 8).
|
|
|
349
368
|
|
|
350
369
|
---
|
|
351
370
|
|
|
371
|
+
## Resume / Context Compression
|
|
372
|
+
|
|
373
|
+
When a conversation has many rounds, a task runs for a long time, or context was
|
|
374
|
+
compressed, resume with the smallest useful context:
|
|
375
|
+
|
|
376
|
+
1. Run `./.cowork-flow/run resume`.
|
|
377
|
+
2. Follow the `RESUME CHECKLIST` section.
|
|
378
|
+
3. Read the current task `prd.md`.
|
|
379
|
+
4. Run `./.cowork-flow/run task list-context <task-dir>` and read only the jsonl references needed for the current phase.
|
|
380
|
+
5. If a plan is listed, read its current execution status before continuing implementation.
|
|
381
|
+
|
|
382
|
+
Do not bulk-read `.cowork-flow/spec/`, all plans, all tasks, or workspace journals
|
|
383
|
+
just because context was compressed. Use the checklist as the minimal recovery
|
|
384
|
+
anchor, then load details on demand.
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
352
388
|
## Skills Reference
|
|
353
389
|
|
|
354
390
|
### User Skills `[USER]`
|
|
@@ -363,13 +399,14 @@ If yes, resume from the appropriate step (usually Step 7 or 8).
|
|
|
363
399
|
|
|
364
400
|
| Script | Purpose |
|
|
365
401
|
|--------|---------|
|
|
366
|
-
|
|
|
367
|
-
|
|
|
368
|
-
|
|
|
369
|
-
|
|
|
370
|
-
|
|
|
371
|
-
|
|
|
372
|
-
|
|
|
402
|
+
| `./.cowork-flow/run resume` | Resume session with minimal context checklist |
|
|
403
|
+
| `./.cowork-flow/run get-context` | Get session context |
|
|
404
|
+
| `./.cowork-flow/run task create` | Create task directory |
|
|
405
|
+
| `./.cowork-flow/run task init-context` | Initialize jsonl files |
|
|
406
|
+
| `./.cowork-flow/run task add-context` | Add spec to jsonl |
|
|
407
|
+
| `./.cowork-flow/run task start` | Set current task |
|
|
408
|
+
| `./.cowork-flow/run task finish` | Clear current task |
|
|
409
|
+
| `./.cowork-flow/run task archive` | Archive completed task |
|
|
373
410
|
|
|
374
411
|
### Workflow Phases `[AI]`
|
|
375
412
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0.0.
|
|
1
|
+
0.0.4
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -u
|
|
3
|
+
|
|
4
|
+
MIN_PYTHON_LABEL="Python 3.8+"
|
|
5
|
+
VERSION_CHECK='import sys; raise SystemExit(0 if sys.version_info >= (3, 8) else 1)'
|
|
6
|
+
|
|
7
|
+
WORKFLOW_DIR=$(CDPATH= cd "$(dirname "$0")" && pwd) || exit 1
|
|
8
|
+
SCRIPTS_DIR="$WORKFLOW_DIR/scripts"
|
|
9
|
+
|
|
10
|
+
print_usage() {
|
|
11
|
+
cat <<'EOF'
|
|
12
|
+
用法:
|
|
13
|
+
./.cowork-flow/run <command> [args...]
|
|
14
|
+
./.cowork-flow/run python [python-args...]
|
|
15
|
+
|
|
16
|
+
常用 command:
|
|
17
|
+
resume
|
|
18
|
+
task
|
|
19
|
+
change
|
|
20
|
+
get-context
|
|
21
|
+
get-developer
|
|
22
|
+
init-developer
|
|
23
|
+
add-session
|
|
24
|
+
|
|
25
|
+
解释器选择顺序:
|
|
26
|
+
COWORK_FLOW_PYTHON -> PYTHON -> python3 -> python -> py -3
|
|
27
|
+
EOF
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
candidate_is_valid() {
|
|
31
|
+
candidate_cmd=$1
|
|
32
|
+
candidate_arg=${2:-}
|
|
33
|
+
|
|
34
|
+
command -v "$candidate_cmd" >/dev/null 2>&1 || return 1
|
|
35
|
+
|
|
36
|
+
if [ -n "$candidate_arg" ]; then
|
|
37
|
+
"$candidate_cmd" "$candidate_arg" -c "$VERSION_CHECK" >/dev/null 2>&1
|
|
38
|
+
else
|
|
39
|
+
"$candidate_cmd" -c "$VERSION_CHECK" >/dev/null 2>&1
|
|
40
|
+
fi
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
select_explicit_python() {
|
|
44
|
+
env_name=$1
|
|
45
|
+
env_value=$2
|
|
46
|
+
|
|
47
|
+
if candidate_is_valid "$env_value"; then
|
|
48
|
+
SELECTED_PYTHON=$env_value
|
|
49
|
+
SELECTED_PYTHON_ARG=
|
|
50
|
+
return 0
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
echo "错误:$env_name 指向的解释器不可用或版本低于 ${MIN_PYTHON_LABEL}:$env_value" >&2
|
|
54
|
+
echo "请设置 $env_name 为可执行的 Python 3.8+ 解释器路径。" >&2
|
|
55
|
+
exit 127
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
select_python() {
|
|
59
|
+
SELECTED_PYTHON=
|
|
60
|
+
SELECTED_PYTHON_ARG=
|
|
61
|
+
|
|
62
|
+
if [ -n "${COWORK_FLOW_PYTHON:-}" ]; then
|
|
63
|
+
select_explicit_python "COWORK_FLOW_PYTHON" "$COWORK_FLOW_PYTHON"
|
|
64
|
+
return 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
if [ -n "${PYTHON:-}" ]; then
|
|
68
|
+
select_explicit_python "PYTHON" "$PYTHON"
|
|
69
|
+
return 0
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
if candidate_is_valid "python3"; then
|
|
73
|
+
SELECTED_PYTHON=python3
|
|
74
|
+
return 0
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
if candidate_is_valid "python"; then
|
|
78
|
+
SELECTED_PYTHON=python
|
|
79
|
+
return 0
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
if candidate_is_valid "py" "-3"; then
|
|
83
|
+
SELECTED_PYTHON=py
|
|
84
|
+
SELECTED_PYTHON_ARG=-3
|
|
85
|
+
return 0
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
echo "错误:需要 ${MIN_PYTHON_LABEL},但未找到可用解释器。" >&2
|
|
89
|
+
echo "已尝试:COWORK_FLOW_PYTHON、PYTHON、python3、python、py -3。" >&2
|
|
90
|
+
echo "可设置 COWORK_FLOW_PYTHON=/path/to/python3 后重试。" >&2
|
|
91
|
+
exit 127
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
exec_python() {
|
|
95
|
+
select_python
|
|
96
|
+
|
|
97
|
+
if [ -n "$SELECTED_PYTHON_ARG" ]; then
|
|
98
|
+
exec "$SELECTED_PYTHON" "$SELECTED_PYTHON_ARG" "$@"
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
exec "$SELECTED_PYTHON" "$@"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
run_script() {
|
|
105
|
+
script_path=$1
|
|
106
|
+
shift
|
|
107
|
+
|
|
108
|
+
if [ ! -f "$script_path" ]; then
|
|
109
|
+
echo "错误:找不到脚本:$script_path" >&2
|
|
110
|
+
exit 2
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
exec_python "$script_path" "$@"
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if [ "$#" -eq 0 ]; then
|
|
117
|
+
print_usage >&2
|
|
118
|
+
exit 2
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
command_name=$1
|
|
122
|
+
shift
|
|
123
|
+
|
|
124
|
+
case "$command_name" in
|
|
125
|
+
-h|--help|help)
|
|
126
|
+
print_usage
|
|
127
|
+
exit 0
|
|
128
|
+
;;
|
|
129
|
+
python)
|
|
130
|
+
exec_python "$@"
|
|
131
|
+
;;
|
|
132
|
+
resume)
|
|
133
|
+
run_script "$SCRIPTS_DIR/resume.py" "$@"
|
|
134
|
+
;;
|
|
135
|
+
task)
|
|
136
|
+
run_script "$SCRIPTS_DIR/task.py" "$@"
|
|
137
|
+
;;
|
|
138
|
+
change)
|
|
139
|
+
run_script "$SCRIPTS_DIR/change.py" "$@"
|
|
140
|
+
;;
|
|
141
|
+
get-context|get_context)
|
|
142
|
+
run_script "$SCRIPTS_DIR/get_context.py" "$@"
|
|
143
|
+
;;
|
|
144
|
+
get-developer|get_developer)
|
|
145
|
+
run_script "$SCRIPTS_DIR/get_developer.py" "$@"
|
|
146
|
+
;;
|
|
147
|
+
init-developer|init_developer)
|
|
148
|
+
run_script "$SCRIPTS_DIR/init_developer.py" "$@"
|
|
149
|
+
;;
|
|
150
|
+
add-session|add_session)
|
|
151
|
+
run_script "$SCRIPTS_DIR/add_session.py" "$@"
|
|
152
|
+
;;
|
|
153
|
+
*)
|
|
154
|
+
if [ -f "$SCRIPTS_DIR/$command_name.py" ]; then
|
|
155
|
+
run_script "$SCRIPTS_DIR/$command_name.py" "$@"
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
echo "错误:未知 cowork-flow 命令:$command_name" >&2
|
|
159
|
+
print_usage >&2
|
|
160
|
+
exit 2
|
|
161
|
+
;;
|
|
162
|
+
esac
|