cowork-flow 0.0.30 → 0.0.32

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.
Files changed (137) hide show
  1. package/README.md +116 -284
  2. package/package.json +2 -2
  3. package/src/cli.js +6 -0
  4. package/src/commands/install-zcode-plugin.js +125 -0
  5. package/src/lib/copy-template.js +54 -2
  6. package/src/lib/platforms.js +27 -2
  7. package/template/.claude/agents/cowork-check.md +4 -3
  8. package/template/.claude/agents/cowork-implement.md +2 -1
  9. package/template/.codex/agents/cowork-check.toml +11 -3
  10. package/template/.codex/agents/cowork-implement.toml +8 -1
  11. package/template/.codex/hooks/inject-workflow-state.py +0 -0
  12. package/template/.codex/hooks.json +1 -1
  13. package/template/.cowork-flow/.version +1 -1
  14. package/template/.cowork-flow/run +3 -3
  15. package/template/.cowork-flow/run.cmd +88 -88
  16. package/template/.cowork-flow/scripts/commands/doctor.py +5 -42
  17. package/template/.cowork-flow/scripts/common/gates/validate_coding_standards.py +254 -132
  18. package/template/.cowork-flow/scripts/common/gates/validate_rules.py +13 -5
  19. package/template/.cowork-flow/spec/contracts/workflow-state-templates.md +2 -2
  20. package/template/.opencode/agents/cowork-check.md +1 -1
  21. package/template/.opencode/agents/cowork-implement.md +9 -7
  22. package/template/.zcode/.zcode-plugin/plugin.json +10 -0
  23. package/template/.zcode/hooks/hooks.json +27 -0
  24. package/template/.zcode/hooks/inject-context.js +397 -0
  25. package/template/.zcode/hooks/inject-context.selfcheck.mjs +191 -0
  26. package/template/.zcode/hooks/runtime/run +58 -0
  27. package/template/.zcode/hooks/runtime/run.cmd +37 -0
  28. package/template/.zcode/hooks/runtime/scripts/commands/__init__.py +1 -0
  29. package/template/.zcode/hooks/runtime/scripts/commands/_bootstrap.py +10 -0
  30. package/template/.zcode/hooks/runtime/scripts/commands/add_session.py +452 -0
  31. package/template/.zcode/hooks/runtime/scripts/commands/change.py +412 -0
  32. package/template/.zcode/hooks/runtime/scripts/commands/doctor.py +471 -0
  33. package/template/.zcode/hooks/runtime/scripts/commands/get_context.py +20 -0
  34. package/template/.zcode/hooks/runtime/scripts/commands/get_developer.py +30 -0
  35. package/template/.zcode/hooks/runtime/scripts/commands/init_developer.py +55 -0
  36. package/template/.zcode/hooks/runtime/scripts/commands/party_mode_v2.py +1166 -0
  37. package/template/.zcode/hooks/runtime/scripts/commands/resume.py +62 -0
  38. package/template/.zcode/hooks/runtime/scripts/commands/subagent.py +321 -0
  39. package/template/.zcode/hooks/runtime/scripts/commands/task.py +2040 -0
  40. package/template/.zcode/hooks/runtime/scripts/common/__init__.py +79 -0
  41. package/template/.zcode/hooks/runtime/scripts/common/core/__init__.py +1 -0
  42. package/template/.zcode/hooks/runtime/scripts/common/core/config.py +242 -0
  43. package/template/.zcode/hooks/runtime/scripts/common/core/developer.py +205 -0
  44. package/template/.zcode/hooks/runtime/scripts/common/core/execution_context.py +385 -0
  45. package/template/.zcode/hooks/runtime/scripts/common/core/files.py +37 -0
  46. package/template/.zcode/hooks/runtime/scripts/common/core/paths.py +239 -0
  47. package/template/.zcode/hooks/runtime/scripts/common/gates/__init__.py +1 -0
  48. package/template/.zcode/hooks/runtime/scripts/common/gates/coding_standards.py +210 -0
  49. package/template/.zcode/hooks/runtime/scripts/common/gates/gates.py +66 -0
  50. package/template/.zcode/hooks/runtime/scripts/common/gates/tdd_evidence.py +367 -0
  51. package/template/.zcode/hooks/runtime/scripts/common/gates/test_intent.py +266 -0
  52. package/template/.zcode/hooks/runtime/scripts/common/gates/validate_coding_standards.py +181 -0
  53. package/template/.zcode/hooks/runtime/scripts/common/gates/validate_coding_standaries.py +316 -0
  54. package/template/.zcode/hooks/runtime/scripts/common/gates/validate_implementation.py +243 -0
  55. package/template/.zcode/hooks/runtime/scripts/common/gates/validate_rules.py +473 -0
  56. package/template/.zcode/hooks/runtime/scripts/common/git/__init__.py +1 -0
  57. package/template/.zcode/hooks/runtime/scripts/common/git/git_context.py +765 -0
  58. package/template/.zcode/hooks/runtime/scripts/common/git/git_snapshot.py +83 -0
  59. package/template/.zcode/hooks/runtime/scripts/common/task/__init__.py +1 -0
  60. package/template/.zcode/hooks/runtime/scripts/common/task/active_task.py +403 -0
  61. package/template/.zcode/hooks/runtime/scripts/common/task/archive_utils.py +72 -0
  62. package/template/.zcode/hooks/runtime/scripts/common/task/readiness.py +249 -0
  63. package/template/.zcode/hooks/runtime/scripts/common/task/state_machine.py +56 -0
  64. package/template/.zcode/hooks/runtime/scripts/common/task/task_utils.py +187 -0
  65. package/template/.zcode/hooks/runtime/scripts/run.py +138 -0
  66. package/template/.zcode/scaffold/.cowork-flow/.version +1 -0
  67. package/template/.zcode/scaffold/.cowork-flow/config.yaml +65 -0
  68. package/template/.zcode/scaffold/.cowork-flow/spec/backend/database-guidelines.md +23 -0
  69. package/template/.zcode/scaffold/.cowork-flow/spec/backend/directory-structure.md +27 -0
  70. package/template/.zcode/scaffold/.cowork-flow/spec/backend/encoding-guidelines.md +27 -0
  71. package/template/.zcode/scaffold/.cowork-flow/spec/backend/error-handling.md +20 -0
  72. package/template/.zcode/scaffold/.cowork-flow/spec/backend/index.md +40 -0
  73. package/template/.zcode/scaffold/.cowork-flow/spec/backend/logging-guidelines.md +20 -0
  74. package/template/.zcode/scaffold/.cowork-flow/spec/backend/quality-guidelines.md +25 -0
  75. package/template/.zcode/scaffold/.cowork-flow/spec/contracts/capabilities.md +34 -0
  76. package/template/.zcode/scaffold/.cowork-flow/spec/contracts/index.md +11 -0
  77. package/template/.zcode/scaffold/.cowork-flow/spec/contracts/party-mode-v2-board.md +68 -0
  78. package/template/.zcode/scaffold/.cowork-flow/spec/contracts/subagent-dispatch.md +85 -0
  79. package/template/.zcode/scaffold/.cowork-flow/spec/contracts/workflow-state-templates.md +72 -0
  80. package/template/.zcode/scaffold/.cowork-flow/spec/frontend/component-guidelines.md +19 -0
  81. package/template/.zcode/scaffold/.cowork-flow/spec/frontend/directory-structure.md +18 -0
  82. package/template/.zcode/scaffold/.cowork-flow/spec/frontend/hook-guidelines.md +17 -0
  83. package/template/.zcode/scaffold/.cowork-flow/spec/frontend/index.md +39 -0
  84. package/template/.zcode/scaffold/.cowork-flow/spec/frontend/quality-guidelines.md +25 -0
  85. package/template/.zcode/scaffold/.cowork-flow/spec/frontend/state-management.md +18 -0
  86. package/template/.zcode/scaffold/.cowork-flow/spec/frontend/type-safety.md +18 -0
  87. package/template/.zcode/scaffold/.cowork-flow/spec/game/asset-pipeline.md +53 -0
  88. package/template/.zcode/scaffold/.cowork-flow/spec/game/engine-guidelines.md +43 -0
  89. package/template/.zcode/scaffold/.cowork-flow/spec/game/index.md +23 -0
  90. package/template/.zcode/scaffold/.cowork-flow/spec/game/multiplayer-guidelines.md +44 -0
  91. package/template/.zcode/scaffold/.cowork-flow/spec/game/performance-guidelines.md +58 -0
  92. package/template/.zcode/scaffold/.cowork-flow/spec/guides/code-reuse-thinking-guide.md +26 -0
  93. package/template/.zcode/scaffold/.cowork-flow/spec/guides/cross-layer-thinking-guide.md +21 -0
  94. package/template/.zcode/scaffold/.cowork-flow/spec/guides/index.md +31 -0
  95. package/template/.zcode/scaffold/.cowork-flow/spec/guides/pre-implementation-checklist.md +15 -0
  96. package/template/.zcode/scaffold/.cowork-flow/spec/index.md +15 -0
  97. package/template/.zcode/scaffold/.cowork-flow/spec/runtime/contract-registry.json +68 -0
  98. package/template/.zcode/scaffold/.cowork-flow/spec/runtime/index.md +10 -0
  99. package/template/.zcode/scaffold/.cowork-flow/spec/runtime/rules.json +173 -0
  100. package/template/.zcode/scaffold/.cowork-flow/spec/schemas/adapter.schema.json +128 -0
  101. package/template/.zcode/scaffold/.cowork-flow/spec/schemas/index.md +10 -0
  102. package/template/.zcode/scaffold/.cowork-flow/spec/schemas/party-mode-v2-actions.schema.json +90 -0
  103. package/template/.zcode/scaffold/.cowork-flow/spec/schemas/rules.schema.json +80 -0
  104. package/template/.zcode/scaffold/.cowork-flow/workflow.md +247 -0
  105. package/template/.zcode/scaffold/AGENTS.md +126 -0
  106. package/template/.zcode/scaffold/CLAUDE.md +5 -0
  107. package/template/AGENTS.md +22 -14
  108. package/template/{.agents/skills → skills}/before-dev/SKILL.md +6 -5
  109. package/template/{.claude/skills → skills}/writing-plans/SKILL.md +23 -1
  110. package/template/.agents/skills/writing-plans/SKILL.md +0 -71
  111. package/template/.claude/skills/before-dev/SKILL.md +0 -144
  112. package/template/.claude/skills/brainstorming/SKILL.md +0 -32
  113. package/template/.claude/skills/break-loop/SKILL.md +0 -26
  114. package/template/.claude/skills/check/SKILL.md +0 -35
  115. package/template/.claude/skills/continue/SKILL.md +0 -29
  116. package/template/.claude/skills/finish-work/SKILL.md +0 -32
  117. package/template/.claude/skills/game-design/SKILL.md +0 -39
  118. package/template/.claude/skills/meta/SKILL.md +0 -30
  119. package/template/.claude/skills/party-mode/SKILL.md +0 -151
  120. package/template/.claude/skills/party-mode-v2/SKILL.md +0 -75
  121. package/template/.claude/skills/python-design/SKILL.md +0 -27
  122. package/template/.claude/skills/start/SKILL.md +0 -78
  123. package/template/.claude/skills/tdd/SKILL.md +0 -61
  124. package/template/.claude/skills/update-spec/SKILL.md +0 -39
  125. /package/template/{.agents/skills → skills}/brainstorming/SKILL.md +0 -0
  126. /package/template/{.agents/skills → skills}/break-loop/SKILL.md +0 -0
  127. /package/template/{.agents/skills → skills}/check/SKILL.md +0 -0
  128. /package/template/{.agents/skills → skills}/continue/SKILL.md +0 -0
  129. /package/template/{.agents/skills → skills}/finish-work/SKILL.md +0 -0
  130. /package/template/{.agents/skills → skills}/game-design/SKILL.md +0 -0
  131. /package/template/{.agents/skills → skills}/meta/SKILL.md +0 -0
  132. /package/template/{.agents/skills → skills}/party-mode/SKILL.md +0 -0
  133. /package/template/{.agents/skills → skills}/party-mode-v2/SKILL.md +0 -0
  134. /package/template/{.agents/skills → skills}/python-design/SKILL.md +0 -0
  135. /package/template/{.agents/skills → skills}/start/SKILL.md +0 -0
  136. /package/template/{.agents/skills → skills}/tdd/SKILL.md +0 -0
  137. /package/template/{.agents/skills → skills}/update-spec/SKILL.md +0 -0
@@ -3,7 +3,7 @@ import { access, chmod, copyFile, mkdir, readFile, readdir, rm, stat, writeFile
3
3
  import { dirname, join, relative } from 'node:path';
4
4
 
5
5
  import { templateRoot } from './paths.js';
6
- import { shouldIncludeForPlatforms } from './platforms.js';
6
+ import { shouldIncludeForPlatforms, skillDestinationForPlatform } from './platforms.js';
7
7
 
8
8
  async function pathExists(path) {
9
9
  try {
@@ -41,6 +41,7 @@ export async function buildInitPlan(targetDir, options = {}) {
41
41
  const files = await listFiles(templateRoot);
42
42
  const actions = [];
43
43
  const platforms = options.platforms ?? [];
44
+ const seen = new Set();
44
45
 
45
46
  for (const file of files) {
46
47
  if (!shouldIncludeForPlatforms(file, platforms)) {
@@ -54,6 +55,7 @@ export async function buildInitPlan(targetDir, options = {}) {
54
55
 
55
56
  const source = join(templateRoot, file);
56
57
  const destination = join(targetDir, file);
58
+ seen.add(destination);
57
59
  const exists = await pathExists(destination);
58
60
  const action = exists
59
61
  ? (options.force && templatePath !== '.cowork-flow/.developer' ? 'update' : 'skip')
@@ -61,6 +63,29 @@ export async function buildInitPlan(targetDir, options = {}) {
61
63
  actions.push({ action, source, destination, relativePath: file });
62
64
  }
63
65
 
66
+ // Inject per-platform skills directories from the canonical template/skills/.
67
+ const skillsSrc = join(templateRoot, 'skills');
68
+ if (await pathExists(skillsSrc)) {
69
+ const skillEntries = await readdir(skillsSrc, { withFileTypes: true });
70
+ for (const entry of skillEntries) {
71
+ if (!entry.isDirectory()) continue;
72
+ const skillName = entry.name;
73
+ for (const platform of platforms) {
74
+ const destBase = skillDestinationForPlatform(platform);
75
+ if (!destBase) continue;
76
+ const dest = join(targetDir, destBase, skillName, 'SKILL.md');
77
+ if (seen.has(dest)) continue;
78
+ seen.add(dest);
79
+ actions.push({
80
+ action: (await pathExists(dest)) ? 'skip' : 'create',
81
+ source: join(skillsSrc, skillName, 'SKILL.md'),
82
+ destination: dest,
83
+ relativePath: join(destBase, skillName, 'SKILL.md')
84
+ });
85
+ }
86
+ }
87
+ }
88
+
64
89
  const versionDestination = join(targetDir, '.cowork-flow', '.version');
65
90
  const versionExists = await pathExists(versionDestination);
66
91
  actions.push({
@@ -206,18 +231,21 @@ export async function buildSyncPlan(targetDir, options = {}) {
206
231
  const files = await listFiles(templateRoot);
207
232
  const actions = [];
208
233
  const platforms = options.platforms ?? await detectInstalledPlatforms(targetDir);
234
+ const seen = new Set();
209
235
 
210
236
  for (const file of files) {
211
237
  if (!shouldIncludeForPlatforms(file, platforms)) {
212
238
  continue;
213
239
  }
214
240
 
241
+ const destination = join(targetDir, file);
242
+ seen.add(destination);
243
+
215
244
  if (toTemplatePath(file) === '.cowork-flow/.version') {
216
245
  continue;
217
246
  }
218
247
 
219
248
  const source = join(templateRoot, file);
220
- const destination = join(targetDir, file);
221
249
  const exists = await pathExists(destination);
222
250
  if (file === 'AGENTS.md' || file === 'CLAUDE.md') {
223
251
  actions.push(await buildManagedBlockSyncAction({ source, destination, exists, options, relativePath: file }));
@@ -238,6 +266,30 @@ export async function buildSyncPlan(targetDir, options = {}) {
238
266
  }
239
267
  }
240
268
 
269
+ // Inject per-platform skills directories from the canonical template/skills/.
270
+ const skillsSrc = join(templateRoot, 'skills');
271
+ if (await pathExists(skillsSrc)) {
272
+ const skillEntries = await readdir(skillsSrc, { withFileTypes: true });
273
+ for (const entry of skillEntries) {
274
+ if (!entry.isDirectory()) continue;
275
+ const skillName = entry.name;
276
+ for (const platform of platforms) {
277
+ const destBase = skillDestinationForPlatform(platform);
278
+ if (!destBase) continue;
279
+ const dest = join(targetDir, destBase, skillName, 'SKILL.md');
280
+ if (seen.has(dest)) continue;
281
+ seen.add(dest);
282
+ const destExists = await pathExists(dest);
283
+ const safe = ['.agents/skills', '.claude/skills'].some((p) => dest.startsWith(join(targetDir, p)));
284
+ if (destExists && (safe || options.force)) {
285
+ actions.push({ action: 'update', source: join(skillsSrc, skillName, 'SKILL.md'), destination: dest, relativePath: join(destBase, skillName, 'SKILL.md') });
286
+ } else if (!destExists) {
287
+ actions.push({ action: 'create', source: join(skillsSrc, skillName, 'SKILL.md'), destination: dest, relativePath: join(destBase, skillName, 'SKILL.md') });
288
+ }
289
+ }
290
+ }
291
+ }
292
+
241
293
  for (const file of OBSOLETE_SYNC_FILES) {
242
294
  const destination = join(targetDir, file);
243
295
  if (await pathExists(destination)) {
@@ -50,9 +50,19 @@ export function formatPlatformList(platforms) {
50
50
 
51
51
  export function shouldIncludeForPlatforms(relativePath, platforms) {
52
52
  const normalized = relativePath.replaceAll('\\', '/');
53
- if (normalized.startsWith('.agents/skills/')) {
54
- return platforms.includes('codex') || platforms.includes('opencode');
53
+
54
+ // Canonical skills directory at template root — never copied directly;
55
+ // init logic injects per-platform copies separately.
56
+ if (normalized.startsWith('skills/')) {
57
+ return false;
58
+ }
59
+
60
+ // ZCode plugin bundle (.zcode/) is installed via a dedicated
61
+ // command, not by init/sync; keep it out of project directories.
62
+ if (normalized.startsWith(".zcode")) {
63
+ return false;
55
64
  }
65
+
56
66
  if (normalized.startsWith('.codex/') || normalized.startsWith('.cowork-flow/adapters/codex/')) {
57
67
  return platforms.includes('codex');
58
68
  }
@@ -68,3 +78,18 @@ export function shouldIncludeForPlatforms(relativePath, platforms) {
68
78
  }
69
79
  return true;
70
80
  }
81
+
82
+ // Destination directory for copied skills, per host platform.
83
+ // ZCode is absent because it ships the plugin bundle via install-zcode-plugin,
84
+ // not by stashing files next to the project.
85
+ export function skillDestinationForPlatform(platform) {
86
+ switch (platform) {
87
+ case 'codex':
88
+ case 'opencode':
89
+ return '.agents/skills';
90
+ case 'claude-code':
91
+ return '.claude/skills';
92
+ default:
93
+ return null;
94
+ }
95
+ }
@@ -36,9 +36,10 @@ the task.
36
36
  Load context before checking:
37
37
  1. Read the task directory from the bound runtime context.
38
38
  2. Read `<task>/prd.md`.
39
- 3. Read `<task>/check.jsonl`.
40
- 4. Read `git diff`.
41
- 5. Include `test_intent_review` in the review output for meaningful behavior
39
+ 3. Read the plan file linked from this task (check `<task>/task.json` `relatedFiles` for a plan path, or search `.cowork-flow/plans/` for a plan file referencing this task directory). Use the plan's Verify commands and Expected results as the checklist for each step.
40
+ 4. Read `<task>/check.jsonl`.
41
+ 5. Read `git diff`.
42
+ 6. Include `test_intent_review` in the review output for meaningful behavior
42
43
  breaks coverage and shallow tests rejection.
43
44
 
44
45
  Rules:
@@ -39,7 +39,8 @@ Load context before editing:
39
39
  3. Read `<task>/info.md` if present.
40
40
  4. Read `<task>/implement.jsonl`.
41
41
  5. Read each JSONL `file` entry.
42
- 6. For behavior-change tasks, create or verify `<task>/tdd.jsonl` before
42
+ 6. Read the plan file linked from this task (check `<task>/task.json` `relatedFiles` for a plan path, or search `.cowork-flow/plans/` for a plan file referencing this task directory). Follow the plan steps in order — each step has Files, Action, Verify, and Expected fields.
43
+ 7. For behavior-change tasks, create or verify `<task>/tdd.jsonl` before
43
44
  implementation or record a documented exemption.
44
45
 
45
46
  Rules:
@@ -27,9 +27,10 @@ the task.
27
27
  Load context before checking:
28
28
  1. Read the task directory from the bound runtime context.
29
29
  2. Read `<task>/prd.md`.
30
- 3. Read `<task>/check.jsonl`.
31
- 4. Read `git diff`.
32
- 5. Include `test_intent_review` in the review output for meaningful behavior breaks coverage and shallow tests rejection.
30
+ 3. Read the plan file linked from this task (check `<task>/task.json` `relatedFiles` for a plan path, or search `.cowork-flow/plans/` for a plan file referencing this task directory). Use the plan's Verify commands and Expected results as the checklist for each step.
31
+ 4. Read `<task>/check.jsonl`.
32
+ 5. Read `git diff`.
33
+ 6. Include `test_intent_review` in the review output for meaningful behavior breaks coverage and shallow tests rejection.
33
34
 
34
35
  Rules:
35
36
  - Fix issues directly when they are clearly in scope.
@@ -37,6 +38,13 @@ Rules:
37
38
  - MUST NOT commit, archive, or mutate cowork-flow task state.
38
39
  - Report findings, changed files, and exact verification commands.
39
40
  - Include test intent findings that map tests back to PRD acceptance or regression behavior.
41
+ - BEFORE declaring PRD acceptance passed, run the spec-driven coding gate and
42
+ treat a nonzero exit as a hard blocker:
43
+ ./.cowork-flow/run python .cowork-flow/scripts/common/gates/validate_coding_standaries.py --validate --repo-root .
44
+ This naturally enforces every rule the user added to
45
+ .cowork-flow/spec/backend/*.md and spec/frontend/*.md — they are not just
46
+ documentation but active validators. On violation, either fix the code or
47
+ explicitly discard the rule from the spec; do not skip the gate.
40
48
  """
41
49
 
42
50
  [features]
@@ -30,7 +30,8 @@ Load context before editing:
30
30
  3. Read `<task>/info.md` if present.
31
31
  4. Read `<task>/implement.jsonl`.
32
32
  5. Read each JSONL `file` entry.
33
- 6. For behavior-change tasks, create or verify `<task>/tdd.jsonl` before implementation or record a documented exemption.
33
+ 6. Read the plan file linked from this task (check `<task>/task.json` `relatedFiles` for a plan path, or search `.cowork-flow/plans/` for a plan file referencing this task directory). Follow the plan steps in order — each step has Files, Action, Verify, and Expected fields.
34
+ 7. For behavior-change tasks, create or verify `<task>/tdd.jsonl` before implementation or record a documented exemption.
34
35
 
35
36
  Rules:
36
37
  - MUST NOT spawn, wait for, list, or close other agents.
@@ -39,6 +40,12 @@ Rules:
39
40
  - Keep edits inside requested scope.
40
41
  - Do not treat shallow tests as TDD evidence; red-green-refactor proof must include redCommand, redExitCode, greenCommand, greenExitCode, and PRD acceptance ID mapping.
41
42
  - Report changed files and exact verification commands.
43
+ - BEFORE editing any source file, run the spec-driven coding gate and treat a
44
+ nonzero exit as a hard blocker:
45
+ ./.cowork-flow/run python .cowork-flow/scripts/common/gates/validate_coding_standaries.py --validate --repo-root .
46
+ Parse every *.md under .cowork-flow/spec/backend and spec/frontend; rules
47
+ declared there activate validators dynamically. On violation, fix the code
48
+ (do not disable the rule) and re-run until exit code 0.
42
49
  """
43
50
 
44
51
  [features]
File without changes
@@ -5,7 +5,7 @@
5
5
  "hooks": [
6
6
  {
7
7
  "type": "command",
8
- "command": ".cowork-flow/run python .codex/hooks/inject-workflow-state.py",
8
+ "command": ".codex/hooks/inject-workflow-state.py",
9
9
  "timeout": 5
10
10
  }
11
11
  ]
@@ -1 +1 @@
1
- 0.0.30
1
+ 0.0.32
@@ -1,8 +1,8 @@
1
1
  #!/bin/sh
2
2
  set -u
3
3
 
4
- MIN_PYTHON_LABEL="Python 3.8+"
5
- VERSION_CHECK='import sys; raise SystemExit(0 if sys.version_info >= (3, 8) else 1)'
4
+ MIN_PYTHON_LABEL="Python 3.9+"
5
+ VERSION_CHECK='import sys; raise SystemExit(0 if sys.version_info >= (3, 9) else 1)'
6
6
  WORKFLOW_DIR=$(CDPATH= cd "$(dirname "$0")" && pwd) || exit 1
7
7
  RUNNER_SCRIPT="$WORKFLOW_DIR/scripts/run.py"
8
8
 
@@ -30,7 +30,7 @@ select_explicit_python() {
30
30
  fi
31
31
 
32
32
  echo "Error: $env_name does not point to a usable ${MIN_PYTHON_LABEL} interpreter: $env_value" >&2
33
- echo "Set $env_name to an executable Python 3.8+ interpreter path." >&2
33
+ echo "Set $env_name to an executable ${MIN_PYTHON_LABEL} interpreter path." >&2
34
34
  exit 127
35
35
  }
36
36
 
@@ -1,88 +1,88 @@
1
- @echo off
2
- setlocal EnableExtensions
3
-
4
- set "MIN_PYTHON_LABEL=Python 3.8+"
5
- set "VERSION_CHECK=import sys; raise SystemExit(0 if sys.version_info >= (3, 8) else 1)"
6
- set "WORKFLOW_DIR=%~dp0"
7
- set "RUNNER_SCRIPT=%WORKFLOW_DIR%scripts\run.py"
8
- set "SELECTED_PYTHON="
9
- set "SELECTED_PYTHON_ARG="
10
-
11
- call :select_python
12
- if errorlevel 1 exit /b %ERRORLEVEL%
13
-
14
- if not "%SELECTED_PYTHON_ARG%"=="" (
15
- "%SELECTED_PYTHON%" "%SELECTED_PYTHON_ARG%" "%RUNNER_SCRIPT%" %*
16
- ) else (
17
- "%SELECTED_PYTHON%" "%RUNNER_SCRIPT%" %*
18
- )
19
- exit /b %ERRORLEVEL%
20
-
21
- :candidate_is_valid
22
- set "CANDIDATE_CMD=%~1"
23
- set "CANDIDATE_ARG=%~2"
24
-
25
- where "%CANDIDATE_CMD%" >nul 2>nul
26
- if errorlevel 1 (
27
- if not exist "%CANDIDATE_CMD%" exit /b 1
28
- )
29
-
30
- if not "%CANDIDATE_ARG%"=="" (
31
- "%CANDIDATE_CMD%" "%CANDIDATE_ARG%" -c "%VERSION_CHECK%" >nul 2>nul
32
- ) else (
33
- "%CANDIDATE_CMD%" -c "%VERSION_CHECK%" >nul 2>nul
34
- )
35
- exit /b %ERRORLEVEL%
36
-
37
- :select_explicit_python
38
- set "ENV_NAME=%~1"
39
- set "ENV_VALUE=%~2"
40
-
41
- call :candidate_is_valid "%ENV_VALUE%" ""
42
- if not errorlevel 1 (
43
- set "SELECTED_PYTHON=%ENV_VALUE%"
44
- set "SELECTED_PYTHON_ARG="
45
- exit /b 0
46
- )
47
-
48
- echo Error: %ENV_NAME% does not point to a usable %MIN_PYTHON_LABEL% interpreter: %ENV_VALUE% 1>&2
49
- echo Set %ENV_NAME% to an executable Python 3.8+ interpreter path. 1>&2
50
- exit /b 127
51
-
52
- :select_python
53
- set "SELECTED_PYTHON="
54
- set "SELECTED_PYTHON_ARG="
55
-
56
- if not "%COWORK_FLOW_PYTHON%"=="" (
57
- call :select_explicit_python "COWORK_FLOW_PYTHON" "%COWORK_FLOW_PYTHON%"
58
- exit /b %ERRORLEVEL%
59
- )
60
-
61
- if not "%PYTHON%"=="" (
62
- call :select_explicit_python "PYTHON" "%PYTHON%"
63
- exit /b %ERRORLEVEL%
64
- )
65
-
66
- call :candidate_is_valid "python3" ""
67
- if not errorlevel 1 (
68
- set "SELECTED_PYTHON=python3"
69
- exit /b 0
70
- )
71
-
72
- call :candidate_is_valid "python" ""
73
- if not errorlevel 1 (
74
- set "SELECTED_PYTHON=python"
75
- exit /b 0
76
- )
77
-
78
- call :candidate_is_valid "py" "-3"
79
- if not errorlevel 1 (
80
- set "SELECTED_PYTHON=py"
81
- set "SELECTED_PYTHON_ARG=-3"
82
- exit /b 0
83
- )
84
-
85
- echo Error: %MIN_PYTHON_LABEL% is required, but no usable interpreter was found. 1>&2
86
- echo Tried: COWORK_FLOW_PYTHON, PYTHON, python3, python, py -3. 1>&2
87
- echo Set COWORK_FLOW_PYTHON=C:\Path\To\python.exe and retry. 1>&2
88
- exit /b 127
1
+ @echo off
2
+ setlocal EnableExtensions
3
+
4
+ set "MIN_PYTHON_LABEL=Python 3.9+"
5
+ set "VERSION_CHECK=import sys; raise SystemExit(0 if sys.version_info >= (3, 9) else 1)"
6
+ set "WORKFLOW_DIR=%~dp0"
7
+ set "RUNNER_SCRIPT=%WORKFLOW_DIR%scripts\run.py"
8
+ set "SELECTED_PYTHON="
9
+ set "SELECTED_PYTHON_ARG="
10
+
11
+ call :select_python
12
+ if errorlevel 1 exit /b %ERRORLEVEL%
13
+
14
+ if not "%SELECTED_PYTHON_ARG%"=="" (
15
+ "%SELECTED_PYTHON%" "%SELECTED_PYTHON_ARG%" "%RUNNER_SCRIPT%" %*
16
+ ) else (
17
+ "%SELECTED_PYTHON%" "%RUNNER_SCRIPT%" %*
18
+ )
19
+ exit /b %ERRORLEVEL%
20
+
21
+ :candidate_is_valid
22
+ set "CANDIDATE_CMD=%~1"
23
+ set "CANDIDATE_ARG=%~2"
24
+
25
+ where "%CANDIDATE_CMD%" >nul 2>nul
26
+ if errorlevel 1 (
27
+ if not exist "%CANDIDATE_CMD%" exit /b 1
28
+ )
29
+
30
+ if not "%CANDIDATE_ARG%"=="" (
31
+ "%CANDIDATE_CMD%" "%CANDIDATE_ARG%" -c "%VERSION_CHECK%" >nul 2>nul
32
+ ) else (
33
+ "%CANDIDATE_CMD%" -c "%VERSION_CHECK%" >nul 2>nul
34
+ )
35
+ exit /b %ERRORLEVEL%
36
+
37
+ :select_explicit_python
38
+ set "ENV_NAME=%~1"
39
+ set "ENV_VALUE=%~2"
40
+
41
+ call :candidate_is_valid "%ENV_VALUE%" ""
42
+ if not errorlevel 1 (
43
+ set "SELECTED_PYTHON=%ENV_VALUE%"
44
+ set "SELECTED_PYTHON_ARG="
45
+ exit /b 0
46
+ )
47
+
48
+ echo Error: %ENV_NAME% does not point to a usable %MIN_PYTHON_LABEL% interpreter: %ENV_VALUE% 1>&2
49
+ echo Set %ENV_NAME% to an executable Python 3.9+ interpreter path. 1>&2
50
+ exit /b 127
51
+
52
+ :select_python
53
+ set "SELECTED_PYTHON="
54
+ set "SELECTED_PYTHON_ARG="
55
+
56
+ if not "%COWORK_FLOW_PYTHON%"=="" (
57
+ call :select_explicit_python "COWORK_FLOW_PYTHON" "%COWORK_FLOW_PYTHON%"
58
+ exit /b %ERRORLEVEL%
59
+ )
60
+
61
+ if not "%PYTHON%"=="" (
62
+ call :select_explicit_python "PYTHON" "%PYTHON%"
63
+ exit /b %ERRORLEVEL%
64
+ )
65
+
66
+ call :candidate_is_valid "python3" ""
67
+ if not errorlevel 1 (
68
+ set "SELECTED_PYTHON=python3"
69
+ exit /b 0
70
+ )
71
+
72
+ call :candidate_is_valid "python" ""
73
+ if not errorlevel 1 (
74
+ set "SELECTED_PYTHON=python"
75
+ exit /b 0
76
+ )
77
+
78
+ call :candidate_is_valid "py" "-3"
79
+ if not errorlevel 1 (
80
+ set "SELECTED_PYTHON=py"
81
+ set "SELECTED_PYTHON_ARG=-3"
82
+ exit /b 0
83
+ )
84
+
85
+ echo Error: %MIN_PYTHON_LABEL% is required, but no usable interpreter was found. 1>&2
86
+ echo Tried: COWORK_FLOW_PYTHON, PYTHON, python3, python, py -3. 1>&2
87
+ echo Set COWORK_FLOW_PYTHON=C:\Path\To\python.exe and retry. 1>&2
88
+ exit /b 127
@@ -240,16 +240,12 @@ def _check_host_adapters(repo_root: Path, errors: list[str]) -> None:
240
240
  errors,
241
241
  )
242
242
  for rel in (
243
- ".cowork-flow/adapters/codex/adapter.yaml",
244
- ".cowork-flow/adapters/opencode/adapter.yaml",
245
- ".cowork-flow/adapters/claude-code/adapter.yaml",
246
243
  "template/.cowork-flow/adapters/codex/adapter.yaml",
247
244
  "template/.cowork-flow/adapters/opencode/adapter.yaml",
248
245
  "template/.cowork-flow/adapters/claude-code/adapter.yaml",
249
246
  ):
250
247
  _check_file_contains(repo_root / rel, REQUIRED_ADAPTER_SNIPPETS, errors)
251
248
  for rel in (
252
- ".cowork-flow/adapters/claude-code/adapter.yaml",
253
249
  "template/.cowork-flow/adapters/claude-code/adapter.yaml",
254
250
  ):
255
251
  _check_file_contains(
@@ -268,30 +264,18 @@ def cmd_host_adapters(_: argparse.Namespace) -> int:
268
264
  errors: list[str] = []
269
265
  _check_host_adapters(repo_root, errors)
270
266
  for rel in (
271
- ".opencode/agents/cowork-research.md",
272
- ".opencode/agents/cowork-implement.md",
273
- ".opencode/agents/cowork-check.md",
274
267
  "template/.opencode/agents/cowork-research.md",
275
268
  "template/.opencode/agents/cowork-implement.md",
276
269
  "template/.opencode/agents/cowork-check.md",
277
270
  ):
278
271
  _check_file_contains(repo_root / rel, REQUIRED_OPENCODE_AGENT_SNIPPETS, errors)
279
272
  for rel in (
280
- ".claude/agents/cowork-research.md",
281
- ".claude/agents/cowork-implement.md",
282
- ".claude/agents/cowork-check.md",
283
273
  "template/.claude/agents/cowork-research.md",
284
274
  "template/.claude/agents/cowork-implement.md",
285
275
  "template/.claude/agents/cowork-check.md",
286
276
  ):
287
277
  _check_file_contains(repo_root / rel, REQUIRED_CLAUDE_AGENT_SNIPPETS, errors)
288
278
  for rel in (
289
- ".claude/commands/cowork-research.md",
290
- ".claude/commands/cowork-implement.md",
291
- ".claude/commands/cowork-check.md",
292
- ".opencode/commands/cowork-research.md",
293
- ".opencode/commands/cowork-implement.md",
294
- ".opencode/commands/cowork-check.md",
295
279
  "template/.claude/commands/cowork-research.md",
296
280
  "template/.claude/commands/cowork-implement.md",
297
281
  "template/.claude/commands/cowork-check.md",
@@ -301,26 +285,20 @@ def cmd_host_adapters(_: argparse.Namespace) -> int:
301
285
  ):
302
286
  _check_file_contains(repo_root / rel, REQUIRED_RUNTIME_COMMAND_SNIPPETS, errors)
303
287
  for rel in (
304
- ".claude/skills/start/SKILL.md",
305
- ".claude/skills/check/SKILL.md",
306
- "template/.claude/skills/start/SKILL.md",
307
- "template/.claude/skills/check/SKILL.md",
288
+ "template/skills/start/SKILL.md",
289
+ "template/skills/check/SKILL.md",
308
290
  ):
309
291
  _check_file_contains(repo_root / rel, REQUIRED_CLAUDE_SKILL_SNIPPETS, errors)
310
292
  for rel in (
311
- f".claude/skills/{ENTRY_BOUNDARY_DIR}/SKILL.md",
312
- f"template/.claude/skills/{ENTRY_BOUNDARY_DIR}/SKILL.md",
293
+ f"template/skills/{ENTRY_BOUNDARY_DIR}/SKILL.md",
313
294
  ):
314
295
  _check_file_absent(repo_root / rel, errors)
315
296
  for rel in (
316
- ".claude/settings.json",
317
297
  "template/.claude/settings.json",
318
298
  ):
319
299
  _check_file_contains(repo_root / rel, REQUIRED_CLAUDE_HOOK_SETTINGS_SNIPPETS, errors)
320
300
  for rel in (
321
- ".claude/hooks/inject-workflow-state.py",
322
301
  "template/.claude/hooks/inject-workflow-state.py",
323
- ".codex/hooks/inject-workflow-state.py",
324
302
  "template/.codex/hooks/inject-workflow-state.py",
325
303
  ):
326
304
  _check_file_contains(repo_root / rel, REQUIRED_RUNTIME_HOOK_SNIPPETS, errors)
@@ -337,7 +315,6 @@ def cmd_host_adapters(_: argparse.Namespace) -> int:
337
315
  errors,
338
316
  )
339
317
  for rel in (
340
- ".opencode/plugins/cowork-flow.js",
341
318
  "template/.opencode/plugins/cowork-flow.js",
342
319
  ):
343
320
  _check_file_contains(
@@ -366,19 +343,14 @@ def cmd_subagent_safety(_: argparse.Namespace) -> int:
366
343
  repo_root = get_repo_root()
367
344
  errors: list[str] = []
368
345
  for rel in (
369
- ".agents/skills/start/SKILL.md",
370
- "template/.agents/skills/start/SKILL.md",
346
+ "template/skills/start/SKILL.md",
371
347
  ):
372
348
  _check_file_contains(repo_root / rel, REQUIRED_START_SNIPPETS, errors)
373
349
  for rel in (
374
- f".agents/skills/{ENTRY_BOUNDARY_DIR}/SKILL.md",
375
- f"template/.agents/skills/{ENTRY_BOUNDARY_DIR}/SKILL.md",
350
+ f"template/skills/{ENTRY_BOUNDARY_DIR}/SKILL.md",
376
351
  ):
377
352
  _check_file_absent(repo_root / rel, errors)
378
353
  for rel in (
379
- ".codex/agents/cowork-research.toml",
380
- ".codex/agents/cowork-implement.toml",
381
- ".codex/agents/cowork-check.toml",
382
354
  "template/.codex/agents/cowork-research.toml",
383
355
  "template/.codex/agents/cowork-implement.toml",
384
356
  "template/.codex/agents/cowork-check.toml",
@@ -401,9 +373,6 @@ def cmd_subagent_safety(_: argparse.Namespace) -> int:
401
373
  if (repo_root / "README.md").is_file():
402
374
  _check_file_omits(repo_root / "README.md", FORBIDDEN_README_DISPATCH_SNIPPETS, errors)
403
375
  for rel in (
404
- ".codex/agents/worker.toml",
405
- ".codex/agents/default.toml",
406
- ".codex/agents/explorer.toml",
407
376
  "template/.codex/agents/worker.toml",
408
377
  "template/.codex/agents/default.toml",
409
378
  "template/.codex/agents/explorer.toml",
@@ -420,23 +389,17 @@ def cmd_subagent_safety(_: argparse.Namespace) -> int:
420
389
  _check_common_contracts(repo_root, errors)
421
390
  _check_host_adapters(repo_root, errors)
422
391
  for rel in (
423
- ".codex/hooks.json",
424
392
  "template/.codex/hooks.json",
425
393
  ):
426
394
  _check_file_contains(repo_root / rel, REQUIRED_HOOK_SNIPPETS, errors)
427
395
  for rel in (
428
- ".codex/hooks/inject-workflow-state.py",
429
396
  "template/.codex/hooks/inject-workflow-state.py",
430
- ".claude/hooks/inject-workflow-state.py",
431
397
  "template/.claude/hooks/inject-workflow-state.py",
432
398
  ):
433
399
  _check_file_contains(repo_root / rel, REQUIRED_RUNTIME_HOOK_SNIPPETS, errors)
434
400
  for rel in (
435
- ".cowork-flow/scripts/commands/subagent.py",
436
401
  "template/.cowork-flow/scripts/commands/subagent.py",
437
- ".cowork-flow/scripts/common/core/execution_context.py",
438
402
  "template/.cowork-flow/scripts/common/core/execution_context.py",
439
- ".cowork-flow/scripts/common/task/active_task.py",
440
403
  "template/.cowork-flow/scripts/common/task/active_task.py",
441
404
  ):
442
405
  if not (repo_root / rel).is_file():