create-harness-vibe-coding 0.8.9 → 0.8.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-CN.md +5 -5
- package/README.md +6 -6
- package/docs/images/harness-architecture.drawio +2 -2
- package/package.json +3 -2
- package/templates/common/.claude/commands/wf-help.md +1 -1
- package/templates/common/.claude/settings.json +2 -2
- package/templates/common/.claude/skills/subagent-orchestrator/SKILL.md +2 -2
- package/templates/common/.claude/skills/wf-max/SKILL.md +3 -3
- package/templates/common/.claude/skills/wf-review/SKILL.md +63 -12
- package/templates/common/.codex/hooks.json +5 -5
- package/templates/common/.harness-version +28 -28
- package/templates/common/.opencode/commands/wf-help.md +1 -1
- package/templates/common/.opencode/commands/wf-review.md +2 -2
- package/templates/common/.opencode/plugins/harness-wf-status.mjs +12 -21
- package/templates/common/Harness/MEMORY.md +2 -2
- package/templates/common/Harness/README.md +3 -3
- package/templates/common/Harness/SETUP.md +1 -1
- package/templates/common/Harness/WF-AUTO-ANGLES.md +1 -1
- package/templates/common/Harness/WF-AUTO-SPARK.md +21 -4
- package/templates/common/Harness/WF-AUTO.md +9 -8
- package/templates/common/Harness/WF-MAX.md +37 -3
- package/templates/common/Harness/dispatch.md +1 -1
- package/templates/common/Harness/scripts/scan-clean.mjs +2 -1
- package/templates/common/Harness/scripts/validate-harness.mjs +36 -0
- package/templates/common/Harness/scripts/wf-auto-update-prompt.mjs +2 -2
- package/templates/common/Harness/scripts/wf-remove.mjs +1 -0
- package/templates/common/Harness/scripts/wf-update-check.mjs +123 -45
- package/templates/common/Harness/subagents.md +8 -1
- package/templates/common/README.md +1 -1
|
@@ -24,6 +24,8 @@ WF-AUTO-SPARK is a `/wf` variant layered on WF-AUTO: it inherits the WF-KERNEL c
|
|
|
24
24
|
|
|
25
25
|
Accepted spark candidates re-enter the standard W2-W5 gates per [WF-KERNEL.md](WF-KERNEL.md): implementer (one file_claim, ≤3 files, ≤50 lines), verifier, reviewer(s), reflector. Spark searchers are read-only. Any implementation must use the dispatch packet from `Harness/dispatch.md` with explicit write set, forbidden truth files, AC IDs, and verification commands. A candidate with no verifier evidence or no reflector PASS is not accepted, even if the idea is valuable.
|
|
26
26
|
|
|
27
|
+
For task-state writes, CEO provides concise bullets and decisions; task-scribe formats task-state writes for roadmap, cycle PLAN, heartbeat, evidence pointers, and closeout. If task-scribe is unavailable, CEO may write the smallest durable checkpoint and must record that degradation in `PROGRESS.md`. This keeps the high-reasoning controller focused on decisions instead of spending tokens formatting process files.
|
|
28
|
+
|
|
27
29
|
## Startup: Roadmap Declaration
|
|
28
30
|
|
|
29
31
|
Before first spark cycle, CEO MUST declare a roadmap. This is written to `Harness/tasks/auto/SPARK-ROADMAP.md`.
|
|
@@ -89,12 +91,12 @@ STARTUP: Declare roadmap (North Star + Milestones) → user confirms
|
|
|
89
91
|
│ ↓ │
|
|
90
92
|
│ VERIFY + CROSS-REVIEW + REFLECTOR PASS │
|
|
91
93
|
│ ↓ │
|
|
92
|
-
│ VALUE REFLECTION: CEO writes
|
|
94
|
+
│ VALUE REFLECTION: CEO gives bullets; task-scribe writes PROGRESS.md │
|
|
93
95
|
│ "Driven by [source]. Matters because [reason]. │
|
|
94
96
|
│ Without this [consequence]. User notices [evidence]." │
|
|
95
97
|
│ ↓ │
|
|
96
98
|
│ MILESTONE CHECK: Is current milestone complete? │
|
|
97
|
-
│ Yes →
|
|
99
|
+
│ Yes → task-scribe updates SPARK-ROADMAP.md + PROGRESS │
|
|
98
100
|
│ No → continue │
|
|
99
101
|
│ ↓ │
|
|
100
102
|
│ RE-ANCHOR GATE (every 10 cycles): │
|
|
@@ -122,6 +124,13 @@ STARTUP: Declare roadmap (North Star + Milestones) → user confirms
|
|
|
122
124
|
| 7 | **Developer Experience** | WebSearch / Docs | New tooling, better CLI patterns, improved error messages |
|
|
123
125
|
| 8 | **Performance Benchmarks** | WebSearch | Industry benchmarks, optimization techniques, profiling tools |
|
|
124
126
|
|
|
127
|
+
### Spark Search Fallbacks
|
|
128
|
+
|
|
129
|
+
- If a researcher/search subagent is filtered, unavailable, or blocked by tool policy, CEO may run direct WebSearch/Tavily for discovery only and records `searchFallback: ceo-direct`.
|
|
130
|
+
- If a scoped skill name is unavailable, use the unscoped skill name plus a dispatch packet; if that still fails, continue with direct search and record the failure.
|
|
131
|
+
- Discovery fallback never authorizes source edits. Any accepted candidate still needs the standard implementer/verifier/reviewer/reflector chain.
|
|
132
|
+
- Search breadth is adaptive. Rotate source families and record skipped families; do not require a fixed count of external searches.
|
|
133
|
+
|
|
125
134
|
## Deviation Guard (50% Rule)
|
|
126
135
|
|
|
127
136
|
### What "50% deviation" means
|
|
@@ -161,7 +170,7 @@ Milestones CANNOT be changed without user confirmation IF:
|
|
|
161
170
|
|
|
162
171
|
## Value Reflection (per cycle)
|
|
163
172
|
|
|
164
|
-
After EVERY spark cycle, CEO writes:
|
|
173
|
+
After EVERY spark cycle, CEO gives the value-reflection bullets and task-scribe writes:
|
|
165
174
|
|
|
166
175
|
```text
|
|
167
176
|
## Cycle N — Value Reflection
|
|
@@ -177,6 +186,10 @@ Cumulative deviation (10-cycle): [X]%
|
|
|
177
186
|
|
|
178
187
|
If CEO CANNOT write a convincing value reflection → spark was NOT valuable → record as rejected and move on.
|
|
179
188
|
|
|
189
|
+
### Reflector Escalation
|
|
190
|
+
|
|
191
|
+
CEO may self-score low-risk candidates during pre-implementation triage, but final acceptance for an implemented spark still requires verifier evidence, cross-review, and reflector PASS. Use a reflector subagent for milestone completion, cumulative deviation concerns, high-risk changes, multi-file implementation, conflicting reviewer findings, or unclear value.
|
|
192
|
+
|
|
180
193
|
## Stop Condition
|
|
181
194
|
|
|
182
195
|
**Spark mode does NOT auto-stop.** Only these events stop it:
|
|
@@ -199,6 +212,10 @@ If CEO CANNOT write a convincing value reflection → spark was NOT valuable →
|
|
|
199
212
|
| SP4 | **Silent North Star drift** | Small changes accumulate, direction shifts without noticing | Cumulative deviation check every 10 cycles |
|
|
200
213
|
| SP5 | **Milestone rot** | Milestones become irrelevant but aren't updated | Milestone review at Re-Anchor Gate |
|
|
201
214
|
| SP6 | **Spark tunnel vision** | Only looking at one type of source | Rotate through the registered source families and record skipped sources |
|
|
215
|
+
| SP7 | **Literal anti-pattern matching** | A rule only catches one exact phrase and misses nearby violations | State the invariant and forbidden behavior, not just a magic string |
|
|
216
|
+
| SP8 | **Checksum drift after doc changes** | Root docs, templates, or `.harness-version` disagree after edits | Sync root + templates, then run `node scripts/build-version.mjs --check` |
|
|
217
|
+
| SP9 | **Process-file token burn** | CEO spends high-reasoning tokens formatting PLAN/PROGRESS/ROADMAP | CEO sends bullets; task-scribe formats task-state writes |
|
|
218
|
+
| SP10 | **Fake delegation** | In-process helper calls are logged as independent workers | Record channel fallback honestly; discovery fallback is not implementation delegation |
|
|
202
219
|
|
|
203
220
|
## Integration with /wf-auto
|
|
204
221
|
|
|
@@ -260,7 +277,7 @@ WF-AUTO-SPARK uses a dedicated task capsule at `Harness/tasks/auto/`. Shared wit
|
|
|
260
277
|
|
|
261
278
|
### PLAN.md Format (per cycle)
|
|
262
279
|
|
|
263
|
-
Before implementing, CEO
|
|
280
|
+
Before implementing, CEO gives one cycle-plan brief and task-scribe writes:
|
|
264
281
|
|
|
265
282
|
```markdown
|
|
266
283
|
# Cycle N Plan
|
|
@@ -205,7 +205,7 @@ TIER 2 — Did any selected probe find an actionable direction?
|
|
|
205
205
|
└── NO → Run a confirmation pass with a different scan strategy.
|
|
206
206
|
|
|
207
207
|
TIER 3 — Is uncertainty still high or coverage borderline?
|
|
208
|
-
├── YES → Re-run only the uncertain probe, or invoke the
|
|
208
|
+
├── YES → Re-run only the uncertain probe, or invoke the peer-review oracle.
|
|
209
209
|
└── NO → Record an empty confirmation pass.
|
|
210
210
|
|
|
211
211
|
TIER 4 — Two different confirmation strategies are empty?
|
|
@@ -215,9 +215,10 @@ TIER 4 — Two different confirmation strategies are empty?
|
|
|
215
215
|
|
|
216
216
|
**Oracle Rules (modeled on /wf-review):**
|
|
217
217
|
|
|
218
|
-
- [ ] CEO detects
|
|
219
|
-
- [ ] CEO invokes
|
|
220
|
-
- [ ] If
|
|
218
|
+
- [ ] CEO detects available peer CLIs: `claude`, `codex`, and `opencode`
|
|
219
|
+
- [ ] CEO invokes a peer CLI only when unresolved high-risk uncertainty or borderline coverage justifies it
|
|
220
|
+
- [ ] If no peer CLI is available, dispatch the installed `reviewer` role as an independent subagent context
|
|
221
|
+
- [ ] If neither peer CLI nor subagent surface is available, record "oracle unavailable" in PROGRESS.md and continue with local confirmation
|
|
221
222
|
- [ ] Oracle is invoked at most once per adaptive exhaustion event
|
|
222
223
|
- [ ] Oracle findings are treated as severity=high by default (external model perspective gets extra weight)
|
|
223
224
|
|
|
@@ -360,7 +361,7 @@ CEO presents:
|
|
|
360
361
|
|
|
361
362
|
### Spark: External Candidate Provider
|
|
362
363
|
|
|
363
|
-
Spark is NOT a separate optimization engine. It is a **candidate provider** plugged into W0, alongside the adaptive probe scan and the
|
|
364
|
+
Spark is NOT a separate optimization engine. It is a **candidate provider** plugged into W0, alongside the adaptive probe scan and the peer-review oracle. W1 still owns prioritization across ALL sources.
|
|
364
365
|
|
|
365
366
|
**When spark activates:**
|
|
366
367
|
- W0 internal scan returns empty AND oracle also empty → `auto.spark` state
|
|
@@ -398,7 +399,7 @@ Spark is NOT a separate optimization engine. It is a **candidate provider** plug
|
|
|
398
399
|
|
|
399
400
|
W1 prioritization now handles three source types:
|
|
400
401
|
- `source=internal` — from adaptive probe scan
|
|
401
|
-
- `source=oracle` — from
|
|
402
|
+
- `source=oracle` — from peer CLI or reviewer-subagent review
|
|
402
403
|
- `source=spark-<name>` — from external inspiration search
|
|
403
404
|
|
|
404
405
|
Tie-breaking: internal > oracle > spark (local context beats external inspiration).
|
|
@@ -490,14 +491,14 @@ Mini PRD-derived AC IDs in `/wf-auto`.
|
|
|
490
491
|
|-----------|-----|---------|----------|
|
|
491
492
|
| Scope | Task-bounded | Task-bounded | Unbounded |
|
|
492
493
|
| Stop condition | Task complete | Task complete | Dynamic obligations covered + two different empty confirmation passes |
|
|
493
|
-
| Direction | User-specified | User-specified | AI-inferred +
|
|
494
|
+
| Direction | User-specified | User-specified | AI-inferred + peer-review oracle + external spark |
|
|
494
495
|
| Organization | Flat (CEO + agents) | 3-tier (CEO→Mgr→Worker) | Flat (CEO + selected probes + oracle + spark searchers + build agents) |
|
|
495
496
|
| Duration | One task | One task | Perpetual |
|
|
496
497
|
| User interaction | At key gates | At key gates | Adaptive checkpoint (2→5→10 cycles), 2 questions only |
|
|
497
498
|
| Cycle count | 1 | 1 (multi-wave) | ∞ (until exhaustion) |
|
|
498
499
|
| Files/cycle | Per task | Per wave (many) | ≤3 per cycle |
|
|
499
500
|
| Exploration | 3-5 agents once | 5-10 agents once | Dynamic probes + triggered spark sources per cycle |
|
|
500
|
-
|
|
|
501
|
+
| Peer review check | No (wf-review is separate) | No (wf-review is separate) | Yes — peer-review oracle built into A-GATE Tier 1.5 |
|
|
501
502
|
| External inspiration | No | No | Yes — Spark candidate provider when internal sources empty |
|
|
502
503
|
| Evidence tracking | Per task | Per task | Evidence ledger per cycle with measured impact |
|
|
503
504
|
|
|
@@ -26,9 +26,43 @@ WF-MAX is **explicit only**. Enter ONLY when the user explicitly types `/wf-max`
|
|
|
26
26
|
|
|
27
27
|
CEO reads, plans, dispatches, synthesizes, and writes task state only.
|
|
28
28
|
- **CEO never writes production source code.** All source edits are delegated to Workers.
|
|
29
|
-
- CEO
|
|
29
|
+
- CEO spawns task-scribe (haiku) by default to maintain dispatch ledger, heartbeat, and evidence pointers; if unavailable, CEO records the degradation and writes only the smallest durable checkpoint.
|
|
30
30
|
- CEO may spawn codebase-explorer(s) (haiku) for scoped source discovery.
|
|
31
31
|
|
|
32
|
+
## Worker Channel Degradation & Independence
|
|
33
|
+
|
|
34
|
+
WF-MAX Workers MUST execute as **independent agent contexts** — never as in-process tool calls from the CEO thread. When a worker channel is unavailable, degrade honestly; never disguise an in-process tool call as a Worker.
|
|
35
|
+
|
|
36
|
+
### Independence Levels
|
|
37
|
+
|
|
38
|
+
| Channel | Independence | Counts as Worker? |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| native subagent (Agent-tool dispatch) | independent | yes |
|
|
41
|
+
| peer CLI (`claude -p`, `codex exec`, `opencode run`) | independent (separate process) | yes |
|
|
42
|
+
| MCP tools (`mcp__codex.codex_implement`, `mcp__claude.claude_implement`, etc.) | inprocess (CEO thread) | NEVER |
|
|
43
|
+
|
|
44
|
+
### Degradation Chain
|
|
45
|
+
|
|
46
|
+
When delegating source edits to a Worker, try channels in order; descend on failure; when all independent channels are unavailable, stop honestly and ask the user — do NOT fall back to an in-process MCP tool:
|
|
47
|
+
|
|
48
|
+
0. **Probe first** — before dispatching any Worker, run `node Harness/scripts/probe-worker-channels.mjs` and read the live matrix (`Harness/tasks/auto/CHANNEL-MATRIX.md`). Degrade based on facts, not assumptions. Start the chain at the highest-priority channel the probe reports `available`.
|
|
49
|
+
1. native subagent (preferred — independent context, bounded writeSet)
|
|
50
|
+
2. `claude -p` peer CLI (independent process)
|
|
51
|
+
3. `codex exec` peer CLI (independent process)
|
|
52
|
+
4. all unavailable → honest pause + human escalation (record blocker in task PROGRESS.md)
|
|
53
|
+
|
|
54
|
+
### Hard Prohibition
|
|
55
|
+
|
|
56
|
+
`mcp__codex.codex_implement`, `mcp__claude.claude_implement`, and any CEO-thread MCP tool call MUST NOT be recorded or used as Worker execution. An in-process tool call has no independent context boundary and no enforced writeSet — using it and logging "CEO did not edit source" is fake compliance. Historical instance: `tasks/task-framework-metrics-and-entry-contract/PLAN.md:791`.
|
|
57
|
+
|
|
58
|
+
### Timeout & Retry
|
|
59
|
+
|
|
60
|
+
Every channel probe is bounded to ≤15s via `Promise.race` (see `probe-worker-channels.mjs`). A Worker dispatch that returns `unavailable-timeout` or `unavailable-error` (transient) is retried **once**; a second failure descends to the next channel in the chain. WF-MAX MUST NEVER hang on an unresponsive channel (historical failure: a 300s Codex read-only query hang, `tasks/task-framework-metrics-and-entry-contract/PLAN.md`). Bounded probes + single retry + honest descent replace silent hangs.
|
|
61
|
+
|
|
62
|
+
### Probe the current environment
|
|
63
|
+
|
|
64
|
+
Run `node Harness/scripts/probe-worker-channels.mjs` to get the live availability + independence matrix (see `tasks/auto/CHANNEL-MATRIX.md`). Degrade based on facts, not assumptions.
|
|
65
|
+
|
|
32
66
|
## Parallelism Priority
|
|
33
67
|
|
|
34
68
|
1. Read-only exploration — max parallel, all readSets
|
|
@@ -51,7 +85,7 @@ Manager_max = min(max(Manager_min * 2, Manager_min), 7)
|
|
|
51
85
|
- One file_claim per write Worker
|
|
52
86
|
- WriteSet must be disjoint across parallel Workers
|
|
53
87
|
- Workers return <=250 tokens + evidence/file paths
|
|
54
|
-
- task-scribe (haiku) runs alongside any wave
|
|
88
|
+
- task-scribe (haiku) runs alongside any wave when available; process-file delegation is the default, not a token-heavy CEO formatting task
|
|
55
89
|
|
|
56
90
|
## Token Budget and Fan-Out Caps
|
|
57
91
|
|
|
@@ -80,7 +114,7 @@ D-GATE is mandatory before implementation waves per [WF-KERNEL.md](WF-KERNEL.md)
|
|
|
80
114
|
|
|
81
115
|
1. Current runtime subagents first.
|
|
82
116
|
2. Close completed agents; fill idle slots immediately.
|
|
83
|
-
3. Cross-CLI overflow:
|
|
117
|
+
3. Cross-CLI overflow: use an available peer CLI with explicit dispatch packets: `claude -p`, `codex exec`, or `opencode run --agent <role> --dir .`.
|
|
84
118
|
4. Bounded-pass fallback only when subagents and overflow are exhausted.
|
|
85
119
|
5. Generated Codex config defaults to `agents.max_threads = 12` and `agents.max_depth = 1`. Ask the user before raising `agents.max_threads` above that default. Keep `max_depth = 1` unless recursive delegation is explicitly approved.
|
|
86
120
|
6. Do not rely on Codex++, undocumented config, environment variables, forked/derived conversations, or third-party forks as stable capacity.
|
|
@@ -13,7 +13,7 @@ Use when work needs parallel reading, independent review, cross-layer analysis,
|
|
|
13
13
|
- Important assumptions, decisions, blockers, evidence, and handoffs must be written to `Harness/tasks/<task-id>/PROGRESS.md` and `Harness/tasks/<task-id>/PLAN.md`, the current feature doc, `Harness/MEMORY.md`, or `Harness/memory/*` as appropriate.
|
|
14
14
|
- Resumable state is governed by [WF-STATE.md](WF-STATE.md). On session start, the controller reads STATE.json before building a fresh dispatch table.
|
|
15
15
|
- PRD-derived Acceptance Criteria are the source of truth. Dispatch packets must carry the relevant AC IDs and contracts.
|
|
16
|
-
- Agent count: default (non-WF) <=3 active agents; `/wf` selects a tier dynamically per [WF-KERNEL.md](WF-KERNEL.md) (Light/Standard/Full); `/wf-max` inherits the selected tier and adds maximum safe fan-out (WF-Max-Useful default; WF-Max-Strict explicit only), removing the Harness default cap through the span formula. Real concurrency is still bounded by runtime thread budget, config, billing, and local resources. Use current runtime subagents first, close completed agents, then
|
|
16
|
+
- Agent count: default (non-WF) <=3 active agents; `/wf` selects a tier dynamically per [WF-KERNEL.md](WF-KERNEL.md) (Light/Standard/Full); `/wf-max` inherits the selected tier and adds maximum safe fan-out (WF-Max-Useful default; WF-Max-Strict explicit only), removing the Harness default cap through the span formula. Real concurrency is still bounded by runtime thread budget, config, billing, and local resources. Use current runtime subagents first, close completed agents, then peer-CLI overflow (`claude -p`, `codex exec`, or `opencode run --agent <role> --dir .`). Generated Codex config defaults to `agents.max_threads = 12` and `agents.max_depth = 1`; ask the user before raising `agents.max_threads` above that default. See [WF.md](WF.md) and [WF-MAX.md](WF-MAX.md).
|
|
17
17
|
- Read-only agents may run in parallel.
|
|
18
18
|
- Writing agents run serially unless write sets are disjoint.
|
|
19
19
|
- Use a worktree when two agents may touch overlapping files or long-running branches.
|
|
@@ -23,7 +23,7 @@ import { createInterface } from 'readline';
|
|
|
23
23
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
24
24
|
const ROOT = process.env.WF_ROOT ? resolve(process.env.WF_ROOT) : resolve(__dirname, '..', '..');
|
|
25
25
|
const VERSION_FILE = resolve(ROOT, 'Harness', '.harness-version');
|
|
26
|
-
const DEFAULT_SOURCE_BASE = 'https://raw.githubusercontent.com/
|
|
26
|
+
const DEFAULT_SOURCE_BASE = 'https://raw.githubusercontent.com/LiWeny16/create-harness-vibe-coding/main/templates/common/';
|
|
27
27
|
|
|
28
28
|
// ── Classification constants ────────────────────────────────────────
|
|
29
29
|
|
|
@@ -65,6 +65,7 @@ const MANAGED_SUBDIRS = new Set([
|
|
|
65
65
|
|
|
66
66
|
/** Reject paths that escape ROOT (traversal, absolute, .., etc.). */
|
|
67
67
|
function safePath(file) {
|
|
68
|
+
if (/^[A-Za-z]:/.test(file)) return null;
|
|
68
69
|
let normalized = file.replace(/\\/g, '/').replace(/^\/+/, '');
|
|
69
70
|
if (/\/\//.test(normalized)) return null;
|
|
70
71
|
if (normalized.split('/').some(p => p === '..')) return null;
|
|
@@ -97,6 +97,7 @@ const required = [
|
|
|
97
97
|
'.opencode/commands/wf-help.md',
|
|
98
98
|
'.opencode/commands/wf-update.md',
|
|
99
99
|
...opencodeWorkflowCommands.map(command => `.opencode/commands/${command}.md`),
|
|
100
|
+
'.opencode/plugins/harness-wf-status.mjs',
|
|
100
101
|
'.claude/rules/ecc/common.md',
|
|
101
102
|
...commonAgents.map(agent => `.claude/agents/${agent}.md`),
|
|
102
103
|
...commonAgents.map(agent => `.opencode/agents/${agent}.md`),
|
|
@@ -324,6 +325,23 @@ for (const taskDir of taskDirs) {
|
|
|
324
325
|
}
|
|
325
326
|
}
|
|
326
327
|
|
|
328
|
+
// M2: MCP-as-Worker fake-compliance guard.
|
|
329
|
+
// Task capsules MUST NOT record mcp__codex.codex_implement / mcp__claude.claude_implement
|
|
330
|
+
// as Worker execution. Historical do-not-repeat references are allowed only when the
|
|
331
|
+
// file is marked ANTI-PATTERN. See Harness/WF-MAX.md "Worker Channel Degradation & Independence".
|
|
332
|
+
const MCP_AS_WORKER_RE = /mcp__(?:codex)\.codex_implement|mcp__(?:claude)\.claude_implement/;
|
|
333
|
+
for (const taskDir of taskDirs) {
|
|
334
|
+
if (!taskDir.startsWith('task-')) continue;
|
|
335
|
+
for (const f of ['PLAN.md', 'PROGRESS.md']) {
|
|
336
|
+
const rel = `Harness/tasks/${taskDir}/${f}`;
|
|
337
|
+
const text = read(rel);
|
|
338
|
+
if (!text) continue;
|
|
339
|
+
if (MCP_AS_WORKER_RE.test(text) && !/ANTI-PATTERN/i.test(text)) {
|
|
340
|
+
errors.push(`${rel} records mcp__*.implement as Worker execution (fake compliance; see WF-MAX.md "Worker Channel Degradation & Independence"). Mark historical references with "ANTI-PATTERN" or remove the tool call.`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
327
345
|
if (fs.existsSync(path.join(root, 'Harness/research/scaffolds.md'))) {
|
|
328
346
|
errors.push('legacy research file should be renamed: Harness/research/scaffolds.md -> Harness/research/research-results.md');
|
|
329
347
|
}
|
|
@@ -710,6 +728,12 @@ requireText('Harness/WF-AUTO.md', 'reflector PASS', 'wf-auto reflector gate');
|
|
|
710
728
|
requireText('Harness/WF-AUTO-SPARK.md', 'Inherited Execution Chain', 'wf-auto-spark inherited execution chain');
|
|
711
729
|
requireText('Harness/WF-AUTO-SPARK.md', 'External spark search replaces discovery only', 'wf-auto-spark discovery-only inheritance');
|
|
712
730
|
requireText('Harness/WF-AUTO-SPARK.md', 'reflector PASS', 'wf-auto-spark reflector gate');
|
|
731
|
+
requireText('Harness/WF-AUTO-SPARK.md', 'task-scribe formats task-state writes', 'wf-auto-spark task-scribe recorder delegation');
|
|
732
|
+
requireText('Harness/WF-AUTO-SPARK.md', 'searchFallback: ceo-direct', 'wf-auto-spark search fallback');
|
|
733
|
+
requireText('Harness/WF-AUTO-SPARK.md', 'pre-implementation triage', 'wf-auto-spark reflector escalation');
|
|
734
|
+
requireText('Harness/WF-AUTO-SPARK.md', 'Literal anti-pattern matching', 'wf-auto-spark anti-pattern invariant guard');
|
|
735
|
+
requireText('Harness/WF-AUTO-SPARK.md', 'node scripts/build-version.mjs --check', 'wf-auto-spark checksum drift guard');
|
|
736
|
+
requireText('Harness/WF-MAX.md', 'process-file delegation is the default', 'WF-MAX task-scribe process-file delegation default');
|
|
713
737
|
requireText('Harness/MEMORY_PROTOCOL.md', 'Scenario Memory Hints', 'memory protocol scenario hints');
|
|
714
738
|
requireText('Harness/MEMORY_PROTOCOL.md', 'WF closeout', 'memory protocol WF closeout injection row');
|
|
715
739
|
requireText('Harness/MEMORY_PROTOCOL.md', 'memory-master owns writes', 'memory protocol memory write ownership');
|
|
@@ -725,6 +749,11 @@ requireText('.claude/skills/tdd/SKILL.md', 'No syntax-only acceptance', 'tdd ski
|
|
|
725
749
|
requireText('.claude/skills/wf-remove/SKILL.md', 'User-facing removal is the slash/skill command', 'wf-remove slash command is user-facing');
|
|
726
750
|
requireText('.claude/skills/wf-remove/SKILL.md', 'agent-internal execution steps', 'wf-remove script commands are agent-internal');
|
|
727
751
|
requireText('.claude/skills/wf-remove/SKILL.md', 'verify residual discovery folders', 'wf-remove residual discovery verification');
|
|
752
|
+
requireText('.claude/skills/wf-review/SKILL.md', 'opencode run --agent reviewer', 'wf-review OpenCode peer CLI path');
|
|
753
|
+
requireText('.claude/skills/wf-review/SKILL.md', 'Role: reviewer', 'wf-review installed reviewer role fallback');
|
|
754
|
+
requireText('.claude/skills/wf-review/SKILL.md', 'The main agent is the controller', 'wf-review controller final authority');
|
|
755
|
+
requireText('.opencode/commands/wf-review.md', 'peer-review contract', 'OpenCode wf-review wrapper peer-review contract');
|
|
756
|
+
requireText('Harness/subagents.md', 'For `/wf-review`, use the installed `reviewer` role', 'subagents wf-review role fallback');
|
|
728
757
|
requireText('.claude/agents/tdd-guide.md', 'Browser Acceptance Rules', 'tdd-guide browser acceptance rules');
|
|
729
758
|
requireText('.claude/agents/tdd-guide.md', 'real user actions', 'tdd-guide real user action requirement');
|
|
730
759
|
requireText('.claude/agents/test-writer.md', 'Harness/ACCEPTANCE_PROTOCOL.md', 'test-writer loads acceptance protocol');
|
|
@@ -766,6 +795,12 @@ forbidText('.claude/settings.json', 'wf-mode-hook.mjs', 'Claude WF hook command
|
|
|
766
795
|
forbidText('.codex/hooks.json', 'wf-mode-hook.mjs', 'Codex WF hook command registration');
|
|
767
796
|
const codexHookConfig = read('.codex/hooks.json');
|
|
768
797
|
const claudeSettings = read('.claude/settings.json');
|
|
798
|
+
requireText('.codex/hooks.json', '"SessionStart"', 'Codex startup-only update hook');
|
|
799
|
+
requireText('.claude/settings.json', '"SessionStart"', 'Claude startup-only update hook');
|
|
800
|
+
forbidText('.codex/hooks.json', 'UserPromptSubmit', 'Codex turn-by-turn update hook');
|
|
801
|
+
forbidText('.claude/settings.json', 'UserPromptSubmit', 'Claude turn-by-turn update hook');
|
|
802
|
+
requireText('.opencode/plugins/harness-wf-status.mjs', 'opencode.startup', 'OpenCode startup-only update check');
|
|
803
|
+
forbidText('.opencode/plugins/harness-wf-status.mjs', "'chat.message'", 'OpenCode turn-by-turn update hook');
|
|
769
804
|
if (codexHookConfig && !codexHookConfig.includes('wf-auto')) {
|
|
770
805
|
errors.push('.codex/hooks.json may only exist for a wf-auto hook configuration');
|
|
771
806
|
}
|
|
@@ -840,6 +875,7 @@ requireText('Harness/WF-KERNEL.md', 'small-fast', 'WF-KERNEL small-fast tier map
|
|
|
840
875
|
// WF variants reference WF-KERNEL
|
|
841
876
|
requireText('Harness/WF.md', 'WF-KERNEL.md', 'WF.md references WF-KERNEL');
|
|
842
877
|
requireText('Harness/WF-MAX.md', 'WF-KERNEL.md', 'WF-MAX.md references WF-KERNEL');
|
|
878
|
+
requireText('Harness/WF-MAX.md', 'probe-worker-channels.mjs', 'WF-MAX references worker-channel probe (M3 anti-regression)');
|
|
843
879
|
|
|
844
880
|
// Tier-aware acceptance: WF-Light must NOT require global cross-review/reflector
|
|
845
881
|
requireText('Harness/WF.md', 'Cross-review and reflector NOT mandatory', 'WF.md WF-Light no mandatory cross-review');
|
|
@@ -142,7 +142,7 @@ function buildMessage(update) {
|
|
|
142
142
|
`Harness update available: ${from} -> ${to}.`,
|
|
143
143
|
`Before unrelated work, ask the user whether to run /wf-update.`,
|
|
144
144
|
];
|
|
145
|
-
// Only include summary counts
|
|
145
|
+
// Only include summary counts; never list individual conflict files in hook output.
|
|
146
146
|
if (update.conflict > 0) {
|
|
147
147
|
parts.push(`${update.conflict} conflict file(s) will need agent/user merge decisions.`);
|
|
148
148
|
}
|
|
@@ -174,7 +174,7 @@ function emit(message, payload = {}) {
|
|
|
174
174
|
if (context) {
|
|
175
175
|
console.log(JSON.stringify({
|
|
176
176
|
hookSpecificOutput: {
|
|
177
|
-
hookEventName: input.hook_event_name || '
|
|
177
|
+
hookEventName: input.hook_event_name || 'SessionStart',
|
|
178
178
|
additionalContext: context,
|
|
179
179
|
},
|
|
180
180
|
}));
|
|
@@ -214,6 +214,7 @@ const CLEANUP_DIRS = [
|
|
|
214
214
|
|
|
215
215
|
/** Reject paths that escape ROOT (traversal, absolute, .., etc.). Sync with wf-update-check. */
|
|
216
216
|
function safePath(file) {
|
|
217
|
+
if (/^[A-Za-z]:/.test(file)) return null;
|
|
217
218
|
let normalized = file.replace(/\\/g, '/').replace(/^\/+/, '');
|
|
218
219
|
if (normalized.includes('//')) return null; // double slash bypass
|
|
219
220
|
if (normalized.split('/').some(p => p === '..')) return null;
|