create-harness-vibe-coding 0.8.18 → 0.8.19

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 (128) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +1 -0
  3. package/package.json +5 -2
  4. package/src/index.js +383 -267
  5. package/src/ui/dist/assets/AgentsRoute-CuSKYmFu.js +17 -0
  6. package/src/ui/dist/assets/AgentsRoute-CuSKYmFu.js.map +1 -0
  7. package/src/ui/dist/assets/RolesRoute-DOzTYVRm.js +7 -0
  8. package/src/ui/dist/assets/RolesRoute-DOzTYVRm.js.map +1 -0
  9. package/src/ui/dist/assets/SettingsRoute-DPU7jSQm.js +12 -0
  10. package/src/ui/dist/assets/SettingsRoute-DPU7jSQm.js.map +1 -0
  11. package/src/ui/dist/assets/TaskList-BN4r8s1i.js +50 -0
  12. package/src/ui/dist/assets/TaskList-BN4r8s1i.js.map +1 -0
  13. package/src/ui/dist/assets/TerminalDrawer-6GBZ9nXN.css +32 -0
  14. package/src/ui/dist/assets/TerminalDrawer-Cej4PxsH.js +74 -0
  15. package/src/ui/dist/assets/TerminalDrawer-Cej4PxsH.js.map +1 -0
  16. package/src/ui/dist/assets/WorkflowRoute-BnuhLJ6X.css +1 -0
  17. package/src/ui/dist/assets/WorkflowRoute-C-clKe-j.js +39 -0
  18. package/src/ui/dist/assets/WorkflowRoute-C-clKe-j.js.map +1 -0
  19. package/src/ui/dist/assets/index-BOVYWntB.js +117 -0
  20. package/src/ui/dist/assets/index-BOVYWntB.js.map +1 -0
  21. package/src/ui/dist/assets/index-DaUObq0H.css +1 -0
  22. package/src/ui/dist/assets/maximize-2-LNrr_rKr.js +7 -0
  23. package/src/ui/dist/assets/maximize-2-LNrr_rKr.js.map +1 -0
  24. package/src/ui/dist/assets/plus-QuTJyoT3.js +7 -0
  25. package/src/ui/dist/assets/plus-QuTJyoT3.js.map +1 -0
  26. package/src/ui/dist/assets/proxy-D0vUbds5.js +2 -0
  27. package/src/ui/dist/assets/proxy-D0vUbds5.js.map +1 -0
  28. package/src/ui/dist/assets/refresh-cw-JNmExijd.js +7 -0
  29. package/src/ui/dist/assets/refresh-cw-JNmExijd.js.map +1 -0
  30. package/src/ui/dist/assets/terminal-BBQvnOAK.js +7 -0
  31. package/src/ui/dist/assets/terminal-BBQvnOAK.js.map +1 -0
  32. package/src/ui/dist/assets/useReducedMotion-BqmH0Tf7.js +7 -0
  33. package/src/ui/dist/assets/useReducedMotion-BqmH0Tf7.js.map +1 -0
  34. package/src/ui/dist/assets/x-DoIOGAJz.js +7 -0
  35. package/src/ui/dist/assets/x-DoIOGAJz.js.map +1 -0
  36. package/src/ui/dist/index.html +18 -0
  37. package/src/ui/index.html +17 -0
  38. package/src/ui/package.json +33 -0
  39. package/src/ui/pnpm-lock.yaml +1582 -0
  40. package/src/ui/pnpm-workspace.yaml +2 -0
  41. package/src/ui/src/App.tsx +86 -0
  42. package/src/ui/src/api.ts +93 -0
  43. package/src/ui/src/components/AgentsRoute.tsx +503 -0
  44. package/src/ui/src/components/Footer.tsx +69 -0
  45. package/src/ui/src/components/Header.tsx +175 -0
  46. package/src/ui/src/components/LoadingView.tsx +22 -0
  47. package/src/ui/src/components/RolesRoute.tsx +169 -0
  48. package/src/ui/src/components/SettingsRoute.tsx +166 -0
  49. package/src/ui/src/components/TaskList.tsx +388 -0
  50. package/src/ui/src/components/TerminalDrawer.tsx +611 -0
  51. package/src/ui/src/components/WorkflowRoute.tsx +670 -0
  52. package/src/ui/src/hooks/useReducedMotion.ts +17 -0
  53. package/src/ui/src/hooks/useServerConnection.ts +114 -0
  54. package/src/ui/src/index.css +281 -0
  55. package/src/ui/src/main.tsx +11 -0
  56. package/src/ui/src/types.ts +108 -0
  57. package/src/ui/tsconfig.json +21 -0
  58. package/src/ui/vite.config.ts +19 -0
  59. package/src/wf-ui-server/__tests__/a2a-store.test.mjs +79 -0
  60. package/src/wf-ui-server/__tests__/peer-capsule.test.mjs +268 -0
  61. package/src/wf-ui-server/__tests__/pty-adapter.test.mjs +70 -0
  62. package/src/wf-ui-server/__tests__/runtime-config.test.mjs +43 -0
  63. package/src/wf-ui-server/__tests__/runtime-detector.test.mjs +90 -0
  64. package/src/wf-ui-server/__tests__/security.test.mjs +59 -0
  65. package/src/wf-ui-server/__tests__/server.integration.test.mjs +150 -0
  66. package/src/wf-ui-server/__tests__/session-registry.test.mjs +238 -0
  67. package/src/wf-ui-server/__tests__/settings.test.mjs +135 -0
  68. package/src/wf-ui-server/__tests__/task-parser.test.mjs +200 -0
  69. package/src/wf-ui-server/__tests__/terminal-store.test.mjs +138 -0
  70. package/src/wf-ui-server/__tests__/token.test.mjs +48 -0
  71. package/src/wf-ui-server/__tests__/ws-events.integration.test.mjs +419 -0
  72. package/src/wf-ui-server/__tests__/ws-terminal.integration.test.mjs +383 -0
  73. package/src/wf-ui-server/a2a-store.mjs +296 -0
  74. package/src/wf-ui-server/peer-capsule.mjs +213 -0
  75. package/src/wf-ui-server/pty-adapter.mjs +155 -0
  76. package/src/wf-ui-server/runtime-config.mjs +153 -0
  77. package/src/wf-ui-server/runtime-detector.mjs +374 -0
  78. package/src/wf-ui-server/security.mjs +67 -0
  79. package/src/wf-ui-server/server.mjs +849 -0
  80. package/src/wf-ui-server/session-registry.mjs +204 -0
  81. package/src/wf-ui-server/settings.mjs +100 -0
  82. package/src/wf-ui-server/task-parser.mjs +133 -0
  83. package/src/wf-ui-server/terminal-store.mjs +225 -0
  84. package/src/wf-ui-server/token.mjs +41 -0
  85. package/src/wf-ui-server/ws-events.mjs +354 -0
  86. package/src/wf-ui-server/ws-terminal.mjs +473 -0
  87. package/templates/common/.claude/commands/wf-help.md +1 -0
  88. package/templates/common/.claude/commands/wf-task-list.md +2 -0
  89. package/templates/common/.claude/commands/wf-ui.md +26 -0
  90. package/templates/common/.claude/commands/wf-update.md +54 -9
  91. package/templates/common/.claude/rules/ecc/common.md +1 -1
  92. package/templates/common/.claude/skills/wf-auto/SKILL.md +3 -3
  93. package/templates/common/.claude/skills/wf-auto-spark/SKILL.md +2 -2
  94. package/templates/common/.claude/skills/wf-ui/SKILL.md +78 -0
  95. package/templates/common/.claude/skills/wf-update/SKILL.md +55 -58
  96. package/templates/common/.harness-version +63 -39
  97. package/templates/common/.opencode/commands/wf-help.md +1 -0
  98. package/templates/common/.opencode/commands/wf-task-list.md +2 -0
  99. package/templates/common/.opencode/commands/wf-ui.md +26 -0
  100. package/templates/common/.opencode/commands/wf-update.md +54 -9
  101. package/templates/common/CLAUDE.md +1 -1
  102. package/templates/common/Harness/MEMORY.md +2 -0
  103. package/templates/common/Harness/README.md +6 -4
  104. package/templates/common/Harness/a2a/role-graph.json +79 -0
  105. package/templates/common/Harness/a2a/runtime-registry.json +5 -0
  106. package/templates/common/Harness/a2a/skills/terminal-control.json +15 -0
  107. package/templates/common/Harness/ownership.manifest.json +57 -2
  108. package/templates/common/Harness/scripts/README.md +134 -0
  109. package/templates/common/Harness/scripts/a2a-terminal.mjs +191 -0
  110. package/templates/common/Harness/scripts/context-budget.mjs +1 -1
  111. package/templates/common/Harness/scripts/sync-host-global.mjs +278 -0
  112. package/templates/common/Harness/scripts/task-state.mjs +556 -23
  113. package/templates/common/Harness/scripts/validate-harness.mjs +229 -19
  114. package/templates/common/Harness/scripts/wf-remove.mjs +8 -3
  115. package/templates/common/Harness/scripts/wf-update-check.mjs +37 -9
  116. package/templates/common/Harness/scripts/wf-update-runner.mjs +325 -0
  117. package/templates/common/Harness/settings.json +35 -0
  118. package/templates/common/Harness/specs/protocols/TASK_ARCHIVE.md +7 -2
  119. package/templates/common/Harness/specs/runtime/command-surface.json +14 -0
  120. package/templates/common/Harness/specs/workflows/WF-AUTO-SPARK.md +8 -8
  121. package/templates/common/Harness/specs/workflows/WF-AUTO.md +12 -12
  122. package/templates/common/Harness/tasks/_template/NAMING.md +16 -16
  123. package/templates/common/Harness/tasks/_template/PLAN.md +17 -60
  124. package/templates/common/Harness/tasks/_template/PROBLEM.md +18 -0
  125. package/templates/common/Harness/tasks/_template/PROGRESS.md +9 -14
  126. package/templates/common/Harness/tasks/_template/REFERENCES.md +26 -0
  127. package/templates/common/Harness/tasks/_template/ARTIFACTS.md +0 -3
  128. package/templates/common/Harness/tasks/_template/NOTES.md +0 -3
@@ -0,0 +1,325 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { spawnSync } from 'node:child_process';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const SCRIPT_ROOT = path.resolve(__dirname, '..', '..');
10
+ const rawArgs = process.argv.slice(2);
11
+ const JSON_OUT = rawArgs.includes('--json');
12
+
13
+ function readFlagValue(args, flagName) {
14
+ const idx = args.indexOf(flagName);
15
+ if (idx === -1) return null;
16
+ const value = args[idx + 1];
17
+ return value && !value.startsWith('--') ? value : null;
18
+ }
19
+
20
+ function stripFlagWithValue(args, flagName) {
21
+ const next = [];
22
+ for (let i = 0; i < args.length; i += 1) {
23
+ if (args[i] === flagName) {
24
+ i += 1;
25
+ continue;
26
+ }
27
+ if (args[i].startsWith(`${flagName}=`)) continue;
28
+ next.push(args[i]);
29
+ }
30
+ return next;
31
+ }
32
+
33
+ function normalizePath(value) {
34
+ return String(value || '').replace(/\\/g, '/');
35
+ }
36
+
37
+ function comparablePath(value) {
38
+ const resolved = path.resolve(value);
39
+ return process.platform === 'win32' ? resolved.toLowerCase() : resolved;
40
+ }
41
+
42
+ function samePath(a, b) {
43
+ if (!a || !b) return false;
44
+ return comparablePath(a) === comparablePath(b);
45
+ }
46
+
47
+ function parseSemver(value) {
48
+ if (!value || typeof value !== 'string') return [0, 0, 0];
49
+ return value.replace(/^[^0-9]*/, '').split('.').slice(0, 3).map(part => Number(part) || 0);
50
+ }
51
+
52
+ function cmpSemver(a, b) {
53
+ const left = parseSemver(a);
54
+ const right = parseSemver(b);
55
+ for (let i = 0; i < 3; i += 1) {
56
+ if ((left[i] || 0) > (right[i] || 0)) return 1;
57
+ if ((left[i] || 0) < (right[i] || 0)) return -1;
58
+ }
59
+ return 0;
60
+ }
61
+
62
+ function shouldAutoRepair(firstJson, targetVersion) {
63
+ if (firstJson?.status !== 'up-to-date') return false;
64
+ const remote = firstJson.remote || firstJson.to || null;
65
+ if (remote && targetVersion && cmpSemver(remote, targetVersion) < 0) return false;
66
+ return true;
67
+ }
68
+
69
+ function defaultGlobalDir() {
70
+ return process.env.HARNESS_GLOBAL_HOME
71
+ || path.join(os.homedir(), '.harness', 'create-harness-vibe-coding');
72
+ }
73
+
74
+ function versionPath(root) {
75
+ return path.join(root, 'Harness', '.harness-version');
76
+ }
77
+
78
+ function updateScriptPath(root) {
79
+ return path.join(root, 'Harness', 'scripts', 'wf-update-check.mjs');
80
+ }
81
+
82
+ function syncScriptPath(root) {
83
+ return path.join(root, 'Harness', 'scripts', 'sync-host-global.mjs');
84
+ }
85
+
86
+ function validateScriptPath(root) {
87
+ return path.join(root, 'Harness', 'scripts', 'validate-harness.mjs');
88
+ }
89
+
90
+ function scanCleanScriptPath(root) {
91
+ return path.join(root, 'Harness', 'scripts', 'scan-clean.mjs');
92
+ }
93
+
94
+ function readVersion(root) {
95
+ try {
96
+ const file = versionPath(root);
97
+ if (!fs.existsSync(file)) return null;
98
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
99
+ } catch {
100
+ return null;
101
+ }
102
+ }
103
+
104
+ function hasRunnableUpdater(root) {
105
+ return fs.existsSync(versionPath(root)) && fs.existsSync(updateScriptPath(root));
106
+ }
107
+
108
+ function discoverGlobalRuntime(projectVersion) {
109
+ const candidates = [];
110
+ if (projectVersion?.globalDir) candidates.push(projectVersion.globalDir);
111
+ if (process.env.HARNESS_GLOBAL_HOME) candidates.push(process.env.HARNESS_GLOBAL_HOME);
112
+ candidates.push(defaultGlobalDir());
113
+ const scriptVersion = readVersion(SCRIPT_ROOT);
114
+ if (scriptVersion?.installScope === 'global') candidates.push(SCRIPT_ROOT);
115
+
116
+ for (const candidate of candidates) {
117
+ if (!candidate) continue;
118
+ const resolved = path.resolve(candidate);
119
+ if (hasRunnableUpdater(resolved)) return resolved;
120
+ }
121
+ return null;
122
+ }
123
+
124
+ function dedupeTargets(targets) {
125
+ const seen = new Set();
126
+ const result = [];
127
+ for (const target of targets) {
128
+ const key = comparablePath(target.root);
129
+ if (seen.has(key)) continue;
130
+ seen.add(key);
131
+ result.push(target);
132
+ }
133
+ return result;
134
+ }
135
+
136
+ function discoverTargets(projectRoot) {
137
+ const targets = [];
138
+ const projectVersion = readVersion(projectRoot);
139
+ const projectHasUpdater = hasRunnableUpdater(projectRoot);
140
+ const globalRoot = discoverGlobalRuntime(projectVersion);
141
+
142
+ if (projectHasUpdater && !samePath(projectRoot, globalRoot)) {
143
+ targets.push({
144
+ scope: projectVersion?.installScope === 'global' && projectVersion?.globalDir ? 'project-bridge' : 'project',
145
+ root: projectRoot,
146
+ version: projectVersion?.generator || null,
147
+ });
148
+ }
149
+
150
+ if (globalRoot) {
151
+ const globalVersion = readVersion(globalRoot);
152
+ targets.push({
153
+ scope: 'global',
154
+ root: globalRoot,
155
+ version: globalVersion?.generator || null,
156
+ });
157
+ }
158
+
159
+ return dedupeTargets(targets);
160
+ }
161
+
162
+ function runNode(root, scriptPath, args, { parseJson = false } = {}) {
163
+ const result = spawnSync(process.execPath, [scriptPath, ...args], {
164
+ cwd: root,
165
+ encoding: 'utf8',
166
+ env: process.env,
167
+ });
168
+ const stdout = result.stdout || '';
169
+ const stderr = result.stderr || '';
170
+ let json = null;
171
+ if (parseJson && stdout.trim()) {
172
+ try {
173
+ json = JSON.parse(stdout.trim());
174
+ } catch {
175
+ json = { rawOutput: stdout };
176
+ }
177
+ }
178
+ return {
179
+ status: result.status ?? 1,
180
+ stdout,
181
+ stderr,
182
+ ...(parseJson ? { json } : {}),
183
+ };
184
+ }
185
+
186
+ function wantsApply(args) {
187
+ return args.includes('--apply') || args.includes('--apply-safe') || args.includes('--safe-only') || args.includes('--finalize');
188
+ }
189
+
190
+ function wantsRepair(args) {
191
+ return args.includes('--repair') || args.includes('--ignore-version') || args.includes('--force-check');
192
+ }
193
+
194
+ function ensureJsonArg(args) {
195
+ return args.includes('--json') ? args : [...args, '--json'];
196
+ }
197
+
198
+ function withRepair(args) {
199
+ return wantsRepair(args) ? args : [...args, '--repair'];
200
+ }
201
+
202
+ function runUpdateForTarget(target, forwardArgs) {
203
+ const parseJson = forwardArgs.includes('--json');
204
+ const script = updateScriptPath(target.root);
205
+ const first = runNode(target.root, script, forwardArgs, { parseJson });
206
+ const runs = [{ command: `node Harness/scripts/wf-update-check.mjs ${forwardArgs.join(' ')}`.trim(), ...first }];
207
+ let effective = first;
208
+
209
+ if (
210
+ parseJson
211
+ && first.status === 0
212
+ && shouldAutoRepair(first.json, target.version)
213
+ && !wantsRepair(forwardArgs)
214
+ ) {
215
+ const repairArgs = withRepair(forwardArgs);
216
+ const repair = runNode(target.root, script, repairArgs, { parseJson });
217
+ runs.push({ command: `node Harness/scripts/wf-update-check.mjs ${repairArgs.join(' ')}`.trim(), ...repair });
218
+ effective = repair;
219
+ }
220
+
221
+ return { ...target, update: effective, runs };
222
+ }
223
+
224
+ function runPostUpdate(target, forwardArgs) {
225
+ const post = [];
226
+ const apply = wantsApply(forwardArgs);
227
+ const syncScript = syncScriptPath(target.root);
228
+ if (target.scope === 'global' && fs.existsSync(syncScript)) {
229
+ const syncArgs = apply ? ['--apply', '--json'] : ['--json'];
230
+ post.push({
231
+ step: 'sync-host-global',
232
+ ...runNode(target.root, syncScript, syncArgs, { parseJson: true }),
233
+ });
234
+ }
235
+ if (apply && fs.existsSync(validateScriptPath(target.root))) {
236
+ post.push({
237
+ step: 'validate',
238
+ ...runNode(target.root, validateScriptPath(target.root), [], { parseJson: false }),
239
+ });
240
+ post.push({
241
+ step: 'manifest-audit',
242
+ ...runNode(target.root, validateScriptPath(target.root), ['--manifest-audit'], { parseJson: false }),
243
+ });
244
+ }
245
+ if (apply && target.scope !== 'global' && fs.existsSync(scanCleanScriptPath(target.root))) {
246
+ post.push({
247
+ step: 'scan-clean',
248
+ ...runNode(target.root, scanCleanScriptPath(target.root), ['--json'], { parseJson: true }),
249
+ });
250
+ }
251
+ return post;
252
+ }
253
+
254
+ function printText(result) {
255
+ if (!result.targets.length) {
256
+ console.error(result.message);
257
+ return;
258
+ }
259
+ for (const target of result.targets) {
260
+ console.log(`\n[${target.scope}] ${target.root}`);
261
+ for (const run of target.runs || []) {
262
+ if (run.stdout) process.stdout.write(run.stdout);
263
+ if (run.stderr) process.stderr.write(run.stderr);
264
+ }
265
+ for (const post of target.post || []) {
266
+ console.log(`[post:${post.step}] exit ${post.status}`);
267
+ if (post.stdout) process.stdout.write(post.stdout);
268
+ if (post.stderr) process.stderr.write(post.stderr);
269
+ }
270
+ }
271
+ }
272
+
273
+ function main() {
274
+ const projectRoot = path.resolve(readFlagValue(rawArgs, '--project') || process.cwd());
275
+ const forwardArgs = stripFlagWithValue(rawArgs, '--project');
276
+ const effectiveArgs = JSON_OUT ? ensureJsonArg(forwardArgs) : forwardArgs;
277
+ const targets = discoverTargets(projectRoot);
278
+
279
+ if (targets.length === 0) {
280
+ const result = {
281
+ success: false,
282
+ status: 'no-harness-target',
283
+ projectRoot: normalizePath(projectRoot),
284
+ message: 'No project Harness updater or global Harness runtime was found. No project files were modified.',
285
+ targets: [],
286
+ };
287
+ if (JSON_OUT) console.log(JSON.stringify(result, null, 2));
288
+ else printText(result);
289
+ process.exitCode = 1;
290
+ return;
291
+ }
292
+
293
+ const updatedTargets = targets.map(target => {
294
+ const withUpdate = runUpdateForTarget(target, effectiveArgs);
295
+ return {
296
+ ...withUpdate,
297
+ post: runPostUpdate(withUpdate, effectiveArgs),
298
+ };
299
+ });
300
+
301
+ const failures = [];
302
+ for (const target of updatedTargets) {
303
+ if (target.update.status !== 0) failures.push(`${target.scope}: update exit ${target.update.status}`);
304
+ for (const post of target.post || []) {
305
+ if (post.status !== 0) failures.push(`${target.scope}: ${post.step} exit ${post.status}`);
306
+ }
307
+ }
308
+
309
+ const result = {
310
+ success: failures.length === 0,
311
+ status: failures.length === 0 ? 'ok' : 'failed',
312
+ projectRoot: normalizePath(projectRoot),
313
+ targets: updatedTargets.map(target => ({
314
+ ...target,
315
+ root: normalizePath(target.root),
316
+ })),
317
+ ...(failures.length ? { failures } : {}),
318
+ };
319
+
320
+ if (JSON_OUT) console.log(JSON.stringify(result, null, 2));
321
+ else printText(result);
322
+ if (failures.length) process.exitCode = 1;
323
+ }
324
+
325
+ main();
@@ -39,5 +39,40 @@
39
39
  "claimMinReadRatioPercent": 95,
40
40
  "claimMinUpliftPoints": 2
41
41
  }
42
+ },
43
+ "server": {
44
+ "host": "127.0.0.1",
45
+ "port": 0
46
+ },
47
+ "terminal": {
48
+ "enabled": false,
49
+ "attachMode": false,
50
+ "defaultRuntime": "codex"
51
+ },
52
+ "peers": {
53
+ "allowlist": [
54
+ "claude",
55
+ "cc",
56
+ "codex",
57
+ "opencode",
58
+ "gemini",
59
+ "qwen",
60
+ "deepseek",
61
+ "pi",
62
+ "aider",
63
+ "goose",
64
+ "amp",
65
+ "crush",
66
+ "cline",
67
+ "plandex",
68
+ "openclaw",
69
+ "chatgpt",
70
+ "openai"
71
+ ]
72
+ },
73
+ "ui": {
74
+ "theme": "auto",
75
+ "language": "zh",
76
+ "reducedMotion": false
42
77
  }
43
78
  }
@@ -11,7 +11,7 @@ Archived tasks move to `Harness/tasks/_archive/YYYY/<task-id>/`.
11
11
  ## What Is Never Archived
12
12
 
13
13
  - `Harness/tasks/_template/` - scaffold template, never moved.
14
- - `Harness/tasks/auto/` - WF-AUTO permanent state capsule, never moved unless
14
+ - `Harness/tasks/continuous/` - WF-AUTO/WF-AUTO-SPARK permanent state capsule, never moved unless
15
15
  explicitly allowed by WF-AUTO docs.
16
16
  - `Harness/tasks/_archive/` - the archive directory itself.
17
17
  - Active, blocked, in-progress, running, pending, or needs-user-decision tasks.
@@ -62,11 +62,16 @@ User-facing command:
62
62
 
63
63
  Underlying implementation: `Harness/scripts/task-state.mjs archive`.
64
64
 
65
- - Default: dry-run.
65
+ - Default: dry-run (respects `--keep` cap, archives oldest-eligible up to cap).
66
66
  - `--apply` to execute.
67
+ - Explicit `--apply` with no `--task` filter: archives **ALL** eligible tasks, bypassing `--keep`.
67
68
  - `--keep 5` to set the non-archived task threshold.
68
69
  - `--task <task-id>` to archive a specific task.
69
70
  - `--json` for machine-readable output.
71
+ - After archiving, `Harness/tasks/_archive/INDEX.md` is regenerated with a full
72
+ task graph: roots, dependency chains, blocks relationships, and per-task details
73
+ (status, phase, goal, depends-on, blocks). The graph covers **all** archived tasks
74
+ across all years, so it stays accurate as tasks accumulate.
70
75
  - Run `node Harness/scripts/task-state.mjs archive --dry-run --json` before
71
76
  applying a risky cleanup.
72
77
 
@@ -210,6 +210,20 @@
210
210
  "codexSkill": true,
211
211
  "helpRow": true
212
212
  }
213
+ },
214
+ {
215
+ "id": "wf-ui",
216
+ "classification": "direct",
217
+ "aliases": ["/wf-ui", "$wf-ui", "/skills wf-ui"],
218
+ "entersWf": false,
219
+ "taskCapsulePolicy": "none",
220
+ "surfaces": {
221
+ "claudeCommand": true,
222
+ "opencodeCommand": true,
223
+ "claudeSkill": true,
224
+ "codexSkill": true,
225
+ "helpRow": true
226
+ }
213
227
  }
214
228
  ]
215
229
  }
@@ -28,7 +28,7 @@ For task-state writes, CEO provides concise bullets and decisions; task-scribe f
28
28
 
29
29
  ## Startup: Roadmap Declaration
30
30
 
31
- Before first spark cycle, CEO MUST declare a roadmap. This is written to `Harness/tasks/auto/SPARK-ROADMAP.md`.
31
+ Before first spark cycle, CEO MUST declare a roadmap. This is written to `Harness/tasks/continuous/SPARK-ROADMAP.md`.
32
32
 
33
33
  ### Roadmap Format
34
34
 
@@ -239,15 +239,15 @@ Re-Anchor Gate (every preset interval)
239
239
 
240
240
  ## Task Capsule & Recording
241
241
 
242
- WF-AUTO-SPARK uses a dedicated task capsule at `Harness/tasks/auto/`. Shared with `/wf-auto` — same capsule, different operational mode.
242
+ WF-AUTO-SPARK uses a dedicated task capsule at `Harness/tasks/continuous/`. Shared with `/wf-auto` — same capsule, different operational mode.
243
243
 
244
244
  ### Capsule Structure
245
245
 
246
246
  | File | Purpose | Updated |
247
247
  |------|---------|---------|
248
- | `Harness/tasks/auto/SPARK-ROADMAP.md` | North Star + milestones + deviation log | At startup + every milestone change |
249
- | `Harness/tasks/auto/PLAN.md` | Current cycle's change spec (write set, acceptance criteria) | Before each implementation |
250
- | `Harness/tasks/auto/PROGRESS.md` | Cycle log, value reflections, cumulative stats, evidence | After each cycle |
248
+ | `Harness/tasks/continuous/SPARK-ROADMAP.md` | North Star + milestones + deviation log | At startup + every milestone change |
249
+ | `Harness/tasks/continuous/PLAN.md` | Current cycle's change spec (write set, acceptance criteria) | Before each implementation |
250
+ | `Harness/tasks/continuous/PROGRESS.md` | Cycle log, value reflections, cumulative stats, evidence | After each cycle |
251
251
  | `Harness/PROGRESS.md` | Global task index — active spark session status | At session start, milestone, and stop |
252
252
 
253
253
  ### Heartbeat Protocol (per cycle, in `PROGRESS.md`)
@@ -314,9 +314,9 @@ This replaces the broken `/wf-auto` auto-continue. No silent drift across sessio
314
314
  | File | Purpose |
315
315
  |------|---------|
316
316
  | `Harness/specs/workflows/WF-AUTO-SPARK.md` | This spec |
317
- | `Harness/tasks/auto/SPARK-ROADMAP.md` | Active roadmap (created at startup) |
318
- | `Harness/tasks/auto/PLAN.md` | Per-cycle change spec |
319
- | `Harness/tasks/auto/PROGRESS.md` | Cycle log, heartbeat, evidence ledger |
317
+ | `Harness/tasks/continuous/SPARK-ROADMAP.md` | Active roadmap (created at startup) |
318
+ | `Harness/tasks/continuous/PLAN.md` | Per-cycle change spec |
319
+ | `Harness/tasks/continuous/PROGRESS.md` | Cycle log, heartbeat, evidence ledger |
320
320
  | `Harness/PROGRESS.md` | Global task index linkage |
321
321
  | `.claude/skills/wf-auto-spark/SKILL.md` | Claude Code skill loader |
322
322
  | `.agents/skills/wf-auto-spark/SKILL.md` | Codex skill loader (mirror) |
@@ -113,7 +113,7 @@ WF-AUTO operates in explicit states. Without a state machine, "auto-degrade", "s
113
113
  | `auto.exhausted` | A-GATE passed permanently | Two different confirmation strategies return no actionable finding |
114
114
  | `paused` | User interrupted, waiting for direction | User says "stop" or interrupts at any point |
115
115
 
116
- **State transitions are CEO-owned.** The CEO decides which state to enter based on W0 results and checkpoint responses. The state machine is recorded in `Harness/tasks/auto/PROGRESS.md` at each transition.
116
+ **State transitions are CEO-owned.** The CEO decides which state to enter based on W0 results and checkpoint responses. The state machine is recorded in `Harness/tasks/continuous/PROGRESS.md` at each transition.
117
117
 
118
118
  ## Adaptive coverage instead of a magic angle count
119
119
 
@@ -271,7 +271,7 @@ CEO NEVER writes production code (per WF-KERNEL State Ownership). Implementer wr
271
271
 
272
272
  ### RECORD
273
273
 
274
- Every cycle writes one entry to `Harness/tasks/auto/PROGRESS.md`:
274
+ Every cycle writes one entry to `Harness/tasks/continuous/PROGRESS.md`:
275
275
 
276
276
  ```text
277
277
  ## Cycle N (timestamp) — State: auto.internal | auto.spark | auto.checkpoint
@@ -304,18 +304,18 @@ enabled `/wf-auto` tick hook may drive long-running auto-optimization.
304
304
 
305
305
  Manual or benchmark-driven single-cycle `/wf-auto` runs use the same bounded
306
306
  tick contract: they may stop because the caller explicitly requested one tick,
307
- but they still MUST create or update `Harness/tasks/auto/PLAN.md` and
308
- `Harness/tasks/auto/PROGRESS.md` before returning.
307
+ but they still MUST create or update `Harness/tasks/continuous/PLAN.md` and
308
+ `Harness/tasks/continuous/PROGRESS.md` before returning.
309
309
 
310
310
  The hook is not a role-enforcement mechanism, not a memory injection mechanism,
311
311
  and not WF-MAX state. It is only a bounded tick trigger:
312
312
 
313
313
  ```text
314
314
  wf-auto hook event
315
- -> confirm /wf-auto is active in Harness/tasks/auto/
315
+ -> confirm /wf-auto is active in Harness/tasks/continuous/
316
316
  -> check STOP/paused/user-interrupt state
317
317
  -> request exactly one W0-W5 tick or one Intent Checkpoint
318
- -> append heartbeat/evidence to Harness/tasks/auto/PROGRESS.md
318
+ -> append heartbeat/evidence to Harness/tasks/continuous/PROGRESS.md
319
319
  -> exit
320
320
  ```
321
321
 
@@ -324,7 +324,7 @@ Hard boundaries:
324
324
  - no execution-control hook is installed or registered by default
325
325
  - only `/wf-auto` may use a runtime hook to drive auto-optimization
326
326
  - the hook must run one bounded tick, not an unbounded process
327
- - the hook must respect `Harness/tasks/auto/STOP`, `state=paused`, user stop,
327
+ - the hook must respect `Harness/tasks/continuous/STOP`, `state=paused`, user stop,
328
328
  and the Adaptive Coverage Exhaustion Gate
329
329
  - the hook must not enforce WF-MAX roles, writeSet, or agent identity
330
330
  - the hook must not inject memory directly; use `MEMORY_PROTOCOL.md` scenario
@@ -449,7 +449,7 @@ If a spark cycle's measured result is NEGLIGIBLE or REVERTED, increment `weakSpa
449
449
 
450
450
  ## CEO Constraints
451
451
 
452
- CEO tool boundaries follow [WF-KERNEL.md](WF-KERNEL.md) State Ownership: CEO plans, dispatches, synthesizes, and writes ONLY the auto task capsule (`Harness/tasks/auto/PROGRESS.md`, `Harness/tasks/auto/PLAN.md`). CEO never writes production source code — all implementation is delegated to Workers.
452
+ CEO tool boundaries follow [WF-KERNEL.md](WF-KERNEL.md) State Ownership: CEO plans, dispatches, synthesizes, and writes ONLY the auto task capsule (`Harness/tasks/continuous/PROGRESS.md`, `Harness/tasks/continuous/PLAN.md`). CEO never writes production source code — all implementation is delegated to Workers.
453
453
 
454
454
  ## Anti-Pattern Catalog
455
455
 
@@ -509,10 +509,10 @@ Mini PRD-derived AC IDs in `/wf-auto`.
509
509
 
510
510
  ## Task Capsule
511
511
 
512
- WF-AUTO uses a dedicated task capsule at `Harness/tasks/auto/`:
512
+ WF-AUTO uses a dedicated task capsule at `Harness/tasks/continuous/`:
513
513
 
514
- - `Harness/tasks/auto/PROGRESS.md` — cycle log, exhaustion evidence, cumulative stats
515
- - `Harness/tasks/auto/PLAN.md` — current cycle's change spec
514
+ - `Harness/tasks/continuous/PROGRESS.md` — cycle log, exhaustion evidence, cumulative stats
515
+ - `Harness/tasks/continuous/PLAN.md` — current cycle's change spec
516
516
 
517
517
  Unlike normal task capsules, this one is never archived — it's the permanent home of the auto-optimization state.
518
518
 
@@ -522,6 +522,6 @@ Closeout happens exactly once, when A-GATE passes permanently:
522
522
 
523
523
  1. CEO records final exhaustion evidence: dynamic obligations, selected and skipped probes, coverage, confidence, and two different confirmation strategies
524
524
  2. CEO writes summary: total cycles, files changed, findings addressed, findings rejected, residual risk
525
- 3. CEO marks `Harness/tasks/auto/PROGRESS.md` as "WF-AUTO EXHAUSTED" with timestamp
525
+ 3. CEO marks `Harness/tasks/continuous/PROGRESS.md` as "WF-AUTO EXHAUSTED" with timestamp
526
526
  4. `Harness/PROGRESS.md` is updated with the auto session outcome
527
527
  5. No further automatic action is taken
@@ -3,20 +3,20 @@
3
3
  ## Format
4
4
 
5
5
  ```
6
- task-<verb>-<noun>[-detail]
6
+ task-<verb>-<noun>[-detail]-<MMDD>
7
7
  ```
8
8
 
9
- All task directories MUST have the `task-` prefix. This distinguishes tasks from system directories at a glance.
9
+ All task directories MUST have the `task-` prefix and end with a 4-digit month-day suffix (MMDD, e.g. `0729` for July 29). This distinguishes tasks from system directories and provides chronological ordering.
10
10
 
11
11
  ## Rules
12
12
 
13
13
  | Rule | Example ✓ | Example ✗ |
14
14
  |------|-----------|-----------|
15
- | `task-` prefix required | `task-fix-ceo-inheritance` | `fix-ceo-inheritance` |
16
- | kebab-case (lowercase, hyphens) | `task-fix-ceo-inheritance` | `task-fix_ceo_inheritance` |
17
- | Verb-first after prefix | `task-add-goal-persistence` | `task-goal-persistence-add` |
18
- | 2-5 words after prefix, <=46 total chars | `task-refactor-role-contract` | `task-refactor-the-entire-role-contract-model` |
19
- | No abbreviations unless domain-standard | `task-fix-auth-middleware` | `task-fx-ath-mdw` |
15
+ | `task-` prefix + MMDD suffix required | `task-fix-ceo-inheritance-0730` | `fix-ceo-inheritance-0730` |
16
+ | kebab-case (lowercase, hyphens) | `task-fix-ceo-inheritance-0730` | `task-fix_ceo_inheritance-0730` |
17
+ | Verb-first after prefix | `task-add-goal-persistence-0730` | `task-goal-persistence-add-0730` |
18
+ | 2-5 words after prefix + MMDD date, <=46 total chars | `task-refactor-role-contract-0729` | `task-refactor-the-entire-role-contract-model-0729` |
19
+ | No abbreviations unless domain-standard | `task-fix-auth-middleware-0730` | `task-fx-ath-mdw-0730` |
20
20
 
21
21
  ## Reserved Names
22
22
 
@@ -27,7 +27,7 @@ All task directories MUST have the `task-` prefix. This distinguishes tasks from
27
27
 
28
28
  ## Task ID Lifecycle
29
29
 
30
- 1. Created by copying `_template/` → `task-<verb>-<noun>/`
30
+ 1. Created by copying `_template/` → `task-<verb>-<noun>-<MMDD>/`
31
31
  2. Directory name IS the task ID - used in `Harness/PROGRESS.md` and dispatch packets
32
32
  3. Directory archived (not renamed) when task completes
33
33
  4. Task ID is immutable after creation (changing it breaks cross-references)
@@ -36,12 +36,12 @@ All task directories MUST have the `task-` prefix. This distinguishes tasks from
36
36
  ## Examples
37
37
 
38
38
  ```
39
- task-add-dark-mode-support
40
- task-fix-auth-token-expiry
41
- task-update-harness-lifecycle-docs
42
- task-remove-legacy-config-files
43
- task-refactor-agent-dispatch-model
44
- task-migrate-to-esm-imports
45
- task-audit-security-headers
46
- task-benchmark-wf-max-throughput
39
+ task-add-dark-mode-support-0729
40
+ task-fix-auth-token-expiry-0730
41
+ task-update-harness-lifecycle-docs-0728
42
+ task-remove-legacy-config-files-0731
43
+ task-refactor-agent-dispatch-model-0801
44
+ task-migrate-to-esm-imports-0802
45
+ task-audit-security-headers-0803
46
+ task-benchmark-wf-max-throughput-0804
47
47
  ```