create-merlin-brain 5.0.2 → 5.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -4
- package/bin/install.cjs +95 -0
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +75 -0
- package/dist/server/server.js.map +1 -1
- package/dist/server/tools/context.d.ts.map +1 -1
- package/dist/server/tools/context.js +60 -0
- package/dist/server/tools/context.js.map +1 -1
- package/dist/server/tools/project-picture.d.ts +17 -0
- package/dist/server/tools/project-picture.d.ts.map +1 -0
- package/dist/server/tools/project-picture.js +204 -0
- package/dist/server/tools/project-picture.js.map +1 -0
- package/dist/server/tools/types.d.ts +24 -0
- package/dist/server/tools/types.d.ts.map +1 -1
- package/files/agents/challenger-academic.md +8 -0
- package/files/agents/challenger-arbiter.md +8 -0
- package/files/agents/challenger-insider.md +8 -0
- package/files/agents/code-organization-supervisor.md +8 -0
- package/files/agents/codex-planner.md +36 -9
- package/files/agents/context-guardian.md +8 -0
- package/files/agents/docs-keeper.md +8 -0
- package/files/agents/dry-refactor.md +8 -0
- package/files/agents/elite-code-refactorer.md +8 -0
- package/files/agents/hardening-guard.md +8 -0
- package/files/agents/implementation-dev.md +8 -0
- package/files/agents/merlin-access-control-reviewer.md +8 -0
- package/files/agents/merlin-api-designer.md +8 -0
- package/files/agents/merlin-codebase-mapper.md +8 -0
- package/files/agents/merlin-debugger.md +8 -0
- package/files/agents/merlin-dependency-auditor.md +8 -0
- package/files/agents/merlin-edge-case-hunter.md +8 -0
- package/files/agents/merlin-executor.md +8 -0
- package/files/agents/merlin-frontend.md +8 -0
- package/files/agents/merlin-input-validator.md +8 -0
- package/files/agents/merlin-integration-checker.md +8 -0
- package/files/agents/merlin-migrator.md +8 -0
- package/files/agents/merlin-milestone-auditor.md +8 -0
- package/files/agents/merlin-party-review.md +8 -0
- package/files/agents/merlin-performance.md +8 -0
- package/files/agents/merlin-planner.md +9 -1
- package/files/agents/merlin-researcher.md +8 -0
- package/files/agents/merlin-reviewer.md +8 -0
- package/files/agents/merlin-sast-reviewer.md +8 -0
- package/files/agents/merlin-secret-scanner.md +8 -0
- package/files/agents/merlin-security.md +8 -0
- package/files/agents/merlin-verifier.md +8 -0
- package/files/agents/merlin-work-verifier.md +8 -0
- package/files/agents/merlin.md +8 -0
- package/files/agents/ops-railway.md +8 -0
- package/files/agents/orchestrator-retrofit.md +8 -0
- package/files/agents/product-spec.md +8 -0
- package/files/agents/remotion.md +8 -0
- package/files/agents/system-architect.md +8 -0
- package/files/agents/tests-qa.md +8 -0
- package/files/commands/merlin/course-correct.md +8 -0
- package/files/commands/merlin/design-audit.md +92 -0
- package/files/commands/merlin/health.md +8 -0
- package/files/commands/merlin/next.md +8 -0
- package/files/commands/merlin/optimize.md +89 -0
- package/files/commands/merlin/polish.md +99 -0
- package/files/commands/merlin/quick.md +8 -0
- package/files/commands/merlin/readiness-gate.md +8 -0
- package/files/commands/merlin/redesign.md +108 -0
- package/files/loop/README.md +11 -0
- package/files/merlin/skills/SKILLS-INDEX.md +16 -1
- package/files/merlin/skills/TASK-OPTIMIZER.json +310 -0
- package/files/merlin/skills/coding/focus-mode.md +8 -0
- package/files/merlin/skills/design/emil-design-eng.md +31 -0
- package/files/merlin/skills/design/impeccable.md +36 -0
- package/files/merlin/skills/duo/offer.md +20 -7
- package/files/merlin/skills/duo/on.md +26 -17
- package/files/merlin/skills/duo/status.md +10 -3
- package/files/merlin/templates/DEBUG.md +11 -0
- package/files/merlin/templates/UAT.md +11 -0
- package/files/merlin/templates/phase-prompt.md +11 -0
- package/files/merlin/templates/project.md +11 -0
- package/files/merlin/templates/requirements.md +11 -0
- package/files/merlin/templates/roadmap.md +11 -0
- package/files/merlin/templates/state.md +11 -0
- package/files/merlin/templates/verification-report.md +11 -0
- package/files/merlin/workflows/execute-phase.md +11 -0
- package/files/merlin/workflows/plan-phase.md +11 -0
- package/files/merlin/workflows/progress.md +11 -0
- package/files/merlin/workflows/resume-project.md +11 -0
- package/files/merlin/workflows/verify-phase.md +11 -0
- package/files/merlin/workflows/verify-work.md +11 -0
- package/files/merlin-system-prompt.txt +35 -1
- package/files/rules/codex-routing.md +19 -0
- package/files/rules/duo-routing.md +109 -10
- package/files/rules/merlin-routing.md +40 -0
- package/files/scripts/codex-as.sh +5 -2
- package/files/scripts/design-intent-detect.sh +8 -0
- package/files/scripts/duo-badge.sh +3 -5
- package/files/scripts/duo-installed.sh +3 -3
- package/files/scripts/duo-mode-read.sh +30 -10
- package/files/scripts/duo-mode-write.sh +28 -3
- package/files/scripts/duo-pre-route.sh +2 -8
- package/files/scripts/install-design-skills.sh +86 -0
- package/files/scripts/merlin-codex.sh +9 -4
- package/files/scripts/task-optimize.sh +335 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: duo-offer
|
|
3
|
-
description: Auto-offer prompt for enabling duo mode on risky tasks. Invoked by duo-pre-route.sh when risk score >= threshold and
|
|
3
|
+
description: Auto-offer prompt for enabling duo mode on risky tasks. Invoked by duo-pre-route.sh when risk score >= threshold and duo is off and task is not suppressed.
|
|
4
4
|
type: skill
|
|
5
5
|
subcommand: offer
|
|
6
6
|
---
|
|
@@ -13,9 +13,10 @@ You are executing the duo auto-offer flow. Follow every step in sequence.
|
|
|
13
13
|
|
|
14
14
|
Run `~/.claude/scripts/duo-mode-read.sh`. If output is `enabled`, exit silently — duo is already on, no offer needed.
|
|
15
15
|
|
|
16
|
-
## Step 2 —
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
## Step 2 — Detect pair (informational only — never blocks the offer).
|
|
17
|
+
Run `~/.claude/scripts/codex-installed.sh`. Capture exit code.
|
|
18
|
+
If exit 0 → PAIR=claude+codex
|
|
19
|
+
Else → PAIR=claude+claude
|
|
19
20
|
|
|
20
21
|
## Step 3 — Read context
|
|
21
22
|
|
|
@@ -95,8 +96,9 @@ Map reasons to human-readable category labels (never display raw file paths):
|
|
|
95
96
|
- `keyword:ship`, `keyword:release`, `keyword:critical` → "release-critical"
|
|
96
97
|
- `dep:package.json`, `dep:go.mod`, `dep:Cargo.toml`, `dep:requirements.txt` → "dependency changes"
|
|
97
98
|
|
|
98
|
-
Display (show at most 3 categories, never raw paths):
|
|
99
|
+
Display (show at most 3 categories, never raw paths). Tailor the pair line to PAIR:
|
|
99
100
|
|
|
101
|
+
If PAIR == claude+codex:
|
|
100
102
|
```
|
|
101
103
|
⟡🔮 MERLIN › This task looks risky (score <SCORE>/100).
|
|
102
104
|
• Areas: <comma-separated categories>
|
|
@@ -107,13 +109,24 @@ Reply: yes (enable duo) · no (solo) · skip session · never
|
|
|
107
109
|
(default = solo if you don't reply explicitly)
|
|
108
110
|
```
|
|
109
111
|
|
|
112
|
+
If PAIR == claude+claude:
|
|
113
|
+
```
|
|
114
|
+
⟡🔮 MERLIN › This task looks risky (score <SCORE>/100).
|
|
115
|
+
• Areas: <comma-separated categories>
|
|
116
|
+
• Workflow: <workflow or "general">
|
|
117
|
+
Twin-Claude pair would tag-team this (sequential write + review with decider gate).
|
|
118
|
+
|
|
119
|
+
Reply: yes (enable duo) · no (solo) · skip session · never
|
|
120
|
+
(default = solo if you don't reply explicitly)
|
|
121
|
+
```
|
|
122
|
+
|
|
110
123
|
## Step 7 — Parse user reply (case-insensitive)
|
|
111
124
|
|
|
112
125
|
Wait for the user's response, then:
|
|
113
126
|
|
|
114
127
|
| Reply contains | Action |
|
|
115
128
|
|---|---|
|
|
116
|
-
| `yes` / `enable duo` / `do it` | Call `~/.claude/scripts/duo-mode-write.sh on "auto-offer accepted: <reasons>"` then set `DUO_OFFER_OUTCOME=yes` |
|
|
129
|
+
| `yes` / `enable duo` / `do it` | Call `~/.claude/scripts/duo-mode-write.sh on "auto-offer accepted: <reasons>" "$PAIR"` then set `DUO_OFFER_OUTCOME=yes` |
|
|
117
130
|
| `skip session` / `skip this session` | Set `session_skip:true` in duo-suppress.json (atomic, flock), set `DUO_OFFER_OUTCOME=skip-session` |
|
|
118
131
|
| `never` | Add intent fingerprint to `never_for_intents` (FIFO cap 20, with timestamp), set `DUO_OFFER_OUTCOME=never` |
|
|
119
132
|
| `no` / anything else / silence | Add task_hash to `task_hashes_declined` (FIFO cap 100), set `DUO_OFFER_OUTCOME=no` |
|
|
@@ -149,7 +162,7 @@ EOF
|
|
|
149
162
|
Append to `~/.claude/merlin-state/duo-decisions.log` (create if missing, JSONL):
|
|
150
163
|
|
|
151
164
|
```json
|
|
152
|
-
{"ts":"<ISO8601>","event":"offer","score":<N>,"reasons":[...],"response":"<yes|no|skip-session|never|silent>","action":"<enable|solo|suppress-session|suppress-intent|suppress-task>"}
|
|
165
|
+
{"ts":"<ISO8601>","event":"offer","score":<N>,"reasons":[...],"response":"<yes|no|skip-session|never|silent>","action":"<enable|solo|suppress-session|suppress-intent|suppress-task>","pair":"<claude+codex|claude+claude>"}
|
|
153
166
|
```
|
|
154
167
|
|
|
155
168
|
## Step 9 — Continue
|
|
@@ -2,29 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
## Steps
|
|
4
4
|
|
|
5
|
-
**Step 1 — Check
|
|
6
|
-
|
|
7
|
-
~/.claude/scripts/duo-installed.sh
|
|
8
|
-
EXIT_CODE=$?
|
|
9
|
-
```
|
|
5
|
+
**Step 1 — Check current state.**
|
|
6
|
+
Run `~/.claude/scripts/duo-mode-read.sh`. If output is `enabled`, duo is already on — skip to Step 4 to show current confirmation and stop.
|
|
10
7
|
|
|
11
|
-
**Step 2 —
|
|
12
|
-
If exit
|
|
13
|
-
```bash
|
|
14
|
-
~/.claude/scripts/duo-mode-write.sh off "install gate failed (silent fallback)"
|
|
15
|
-
```
|
|
16
|
-
Do NOT mention duo mode, Codex, or this branch to the user. Continue with whatever
|
|
17
|
-
the user originally requested as if this skill was never invoked. Stop here.
|
|
8
|
+
**Step 2 — Detect pair.**
|
|
9
|
+
Run `~/.claude/scripts/codex-installed.sh`. If exit 0 → PAIR=claude+codex. Else → PAIR=claude+claude.
|
|
18
10
|
|
|
19
|
-
**Step 3 —
|
|
11
|
+
**Step 3 — Enable duo with pair.**
|
|
20
12
|
```bash
|
|
21
|
-
~/.claude/scripts/duo-mode-write.sh on "<user's phrase that triggered enable>"
|
|
13
|
+
~/.claude/scripts/duo-mode-write.sh on "<user's phrase that triggered enable>" "$PAIR"
|
|
22
14
|
BADGE=$(~/.claude/scripts/duo-badge.sh)
|
|
23
15
|
```
|
|
24
16
|
|
|
25
|
-
**Step 4 — Emit confirmation.**
|
|
17
|
+
**Step 4 — Emit confirmation tailored to pair.**
|
|
18
|
+
|
|
19
|
+
If PAIR == claude+codex:
|
|
26
20
|
```
|
|
27
|
-
⟡🔮↔🔮 MERLIN·DUO › Duo mode enabled.
|
|
21
|
+
⟡🔮↔🔮 MERLIN·DUO › Duo mode enabled (Claude + Codex).
|
|
28
22
|
• Parallel: planning, docs, code review, tests
|
|
29
23
|
• Sequential: code write/modify (codex writes → claude reviews → decider gates)
|
|
30
24
|
• Verification stays with Claude
|
|
@@ -33,7 +27,22 @@ BADGE=$(~/.claude/scripts/duo-badge.sh)
|
|
|
33
27
|
Try: "plan the next phase" to see dual-planning.
|
|
34
28
|
```
|
|
35
29
|
|
|
36
|
-
|
|
30
|
+
If PAIR == claude+claude:
|
|
31
|
+
```
|
|
32
|
+
⟡🔮↔🔮 MERLIN·DUO › Duo mode enabled (twin-Claude — Codex not installed).
|
|
33
|
+
Two Claude specialists tag-team your work:
|
|
34
|
+
• Parallel planning: merlin-planner + challenger-academic → arbiter
|
|
35
|
+
• Parallel review: code-review + merlin-reviewer → arbiter
|
|
36
|
+
• Parallel testing: tests-qa + merlin-edge-case-hunter → arbiter
|
|
37
|
+
• Sequential code: implementation-dev writes → code-review reviews → decider gates
|
|
38
|
+
• Verification stays with Claude
|
|
39
|
+
• Auto-expires in 24h
|
|
40
|
+
(Install Codex if you want claude+codex pairing instead.)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Step 5 — Codex-mode coexistence check (claude+codex pair only).**
|
|
44
|
+
Skip this step if PAIR == claude+claude.
|
|
45
|
+
|
|
37
46
|
```bash
|
|
38
47
|
python3 -c "
|
|
39
48
|
import json, os, sys
|
|
@@ -12,11 +12,13 @@ state_path = os.path.expanduser("~/.claude/merlin-state/duo-mode.json")
|
|
|
12
12
|
try:
|
|
13
13
|
data = json.load(open(state_path))
|
|
14
14
|
except:
|
|
15
|
-
data = {"enabled": False, "sinceISO": None, "lastToggleReason": None}
|
|
15
|
+
data = {"enabled": False, "sinceISO": None, "lastToggleReason": None, "pair": None}
|
|
16
16
|
|
|
17
17
|
enabled = data.get("enabled", False)
|
|
18
18
|
since_iso = data.get("sinceISO")
|
|
19
19
|
reason = data.get("lastToggleReason") or "never enabled"
|
|
20
|
+
# Legacy state: if enabled but no pair field, default to claude+codex
|
|
21
|
+
pair = data.get("pair") or ("claude+codex" if enabled else None)
|
|
20
22
|
|
|
21
23
|
age_str = ""
|
|
22
24
|
status_label = "OFF"
|
|
@@ -30,6 +32,7 @@ if enabled and since_iso:
|
|
|
30
32
|
if delta > timedelta(hours=24):
|
|
31
33
|
expired = True
|
|
32
34
|
status_label = "AUTO-EXPIRED"
|
|
35
|
+
pair = None
|
|
33
36
|
else:
|
|
34
37
|
status_label = "ON"
|
|
35
38
|
total_s = int(delta.total_seconds())
|
|
@@ -37,18 +40,20 @@ if enabled and since_iso:
|
|
|
37
40
|
except:
|
|
38
41
|
expired = True
|
|
39
42
|
status_label = "AUTO-EXPIRED"
|
|
43
|
+
pair = None
|
|
40
44
|
|
|
41
45
|
print(f"status={status_label}")
|
|
42
46
|
print(f"since={since_iso or 'n/a'}")
|
|
43
47
|
print(f"age={age_str or 'n/a'}")
|
|
44
48
|
print(f"reason={reason}")
|
|
45
49
|
print(f"expired={expired}")
|
|
50
|
+
print(f"pair={pair or 'none'}")
|
|
46
51
|
PYEOF
|
|
47
52
|
```
|
|
48
53
|
|
|
49
54
|
**Step 2 — Check Codex install gate.**
|
|
50
55
|
```bash
|
|
51
|
-
~/.claude/scripts/
|
|
56
|
+
~/.claude/scripts/codex-installed.sh 2>/dev/null && echo "gate=pass" || echo "gate=fail"
|
|
52
57
|
```
|
|
53
58
|
|
|
54
59
|
**Step 3 — Parse duo-suppress.json.**
|
|
@@ -74,6 +79,7 @@ Use the values above to emit ONE of these formats:
|
|
|
74
79
|
If status=ON:
|
|
75
80
|
```
|
|
76
81
|
⟡🔮↔🔮 MERLIN·DUO › Duo: ON · since {sinceISO} · age {hh:mm} · reason: {lastToggleReason}
|
|
82
|
+
Pair: {claude+codex|claude+claude}
|
|
77
83
|
```
|
|
78
84
|
|
|
79
85
|
If status=OFF:
|
|
@@ -88,7 +94,8 @@ If status=AUTO-EXPIRED:
|
|
|
88
94
|
|
|
89
95
|
Then append install gate and suppression lines:
|
|
90
96
|
```
|
|
91
|
-
Codex install gate: ✓ pass
|
|
97
|
+
Codex install gate: ✓ pass (claude+codex pair available) [when gate=pass]
|
|
98
|
+
Codex install gate: ✗ fail (duo runs as twin-Claude pair) [when gate=fail]
|
|
92
99
|
Session skip: {true|false}
|
|
93
100
|
Suppressed intents: {N} (if N > 0, add: — run Skill("merlin:duo", args="unsuppress") to clear)
|
|
94
101
|
Recently declined task hashes: {N}
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: templates/DEBUG.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD planning template
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
# Debug Template
|
|
2
13
|
|
|
3
14
|
Template for `.planning/debug/[slug].md` — active debug session tracking.
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: templates/UAT.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD planning template
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
# UAT Template
|
|
2
13
|
|
|
3
14
|
Template for `.planning/phases/XX-name/{phase}-UAT.md` — persistent UAT session tracking.
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: templates/phase-prompt.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD planning template
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
# Phase Prompt Template
|
|
2
13
|
|
|
3
14
|
Template for `.planning/phases/XX-name/{phase}-{plan}-PLAN.md` - executable phase plans optimized for parallel execution.
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: templates/project.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD planning template
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
# PROJECT.md Template
|
|
2
13
|
|
|
3
14
|
Template for `.planning/PROJECT.md` — the living project context document.
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: templates/requirements.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD planning template
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
# Requirements Template
|
|
2
13
|
|
|
3
14
|
Template for `.planning/REQUIREMENTS.md` — checkable requirements that define "done."
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: templates/roadmap.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD planning template
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
# Roadmap Template
|
|
2
13
|
|
|
3
14
|
Template for `.planning/ROADMAP.md`.
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: templates/state.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD planning template
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
# State Template
|
|
2
13
|
|
|
3
14
|
Template for `.planning/STATE.md` — the project's living memory.
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: templates/verification-report.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD planning template
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
# Verification Report Template
|
|
2
13
|
|
|
3
14
|
Template for `.planning/phases/XX-name/{phase}-VERIFICATION.md` — phase goal verification results.
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: workflows/execute-phase.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD workflow pattern
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
<purpose>
|
|
2
13
|
Execute all plans in a phase using wave-based parallel execution. Orchestrator stays lean by delegating plan execution to subagents.
|
|
3
14
|
</purpose>
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: workflows/plan-phase.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD workflow pattern
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
<decimal_phase_numbering>
|
|
2
13
|
Decimal phases enable urgent work insertion without renumbering:
|
|
3
14
|
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: workflows/progress.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD workflow pattern
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
<purpose>
|
|
2
13
|
Check project progress, ensure backlog health, and route to next action.
|
|
3
14
|
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: workflows/resume-project.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD workflow pattern
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
<trigger>
|
|
2
13
|
Use this workflow when:
|
|
3
14
|
- Starting a new session on an existing project
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: workflows/verify-phase.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD workflow pattern
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
<purpose>
|
|
2
13
|
Verify phase goal achievement through goal-backward analysis. Check that the codebase actually delivers what the phase promised, not just that tasks were completed.
|
|
3
14
|
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
provenance:
|
|
3
|
+
upstream: gsd-build/get-shit-done
|
|
4
|
+
upstream_path: workflows/verify-work.md
|
|
5
|
+
upstream_commit: 9045c81
|
|
6
|
+
license: MIT
|
|
7
|
+
license_verification: confirmed
|
|
8
|
+
adapted: "2026-03-14"
|
|
9
|
+
changes: adapted from GSD workflow pattern
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
<purpose>
|
|
2
13
|
Validate built features through conversational testing with persistent state. Creates UAT.md that tracks test progress, survives /clear, and feeds gaps into /merlin:plan-phase --gaps.
|
|
3
14
|
|
|
@@ -1 +1,35 @@
|
|
|
1
|
-
MANDATORY: You are Merlin, an orchestrator. Before processing any user request, call merlin_get_selected_repo, merlin_get_project_status, merlin_get_rules and merlin_get_brief. Route ALL implementation work to specialist agents via Skill("merlin:workflow") or merlin_route(). NEVER write, edit, or debug code yourself. Prefix every action with the badge from ~/.claude/scripts/duo-badge.sh (solo: ⟡🔮 MERLIN ›, duo: ⟡🔮↔🔮 MERLIN·DUO ›). Run independent agents in PARALLEL. Before editing code, call merlin_get_context first.
|
|
1
|
+
MANDATORY: You are Merlin, an orchestrator. Before processing any user request, call merlin_get_selected_repo, merlin_get_project_status, merlin_get_rules and merlin_get_brief. Route ALL implementation work to specialist agents via Skill("merlin:workflow") or merlin_route(). NEVER write, edit, or debug code yourself. Prefix every action with the badge from ~/.claude/scripts/duo-badge.sh (solo: ⟡🔮 MERLIN ›, duo: ⟡🔮↔🔮 MERLIN·DUO ›). Run independent agents in PARALLEL. Before editing code, call merlin_get_context first.
|
|
2
|
+
|
|
3
|
+
## Duo mode (codex+codex)
|
|
4
|
+
|
|
5
|
+
When `~/.claude/scripts/duo-mode-read.sh` outputs `enabled` AND `~/.claude/scripts/duo-mode-read.sh --pair` outputs `codex+codex`, you orchestrate two Codex instances per task instead of one.
|
|
6
|
+
|
|
7
|
+
**Toggle from chat:**
|
|
8
|
+
- "duo on" → run `~/.claude/scripts/duo-mode-write.sh on "<user phrase>"` (auto-detects codex+codex via MERLIN_RUNTIME), then announce: "⟡🔮↔🔮 MERLIN·DUO › Duo enabled (codex+codex). Two Codex specialists tag-team your work."
|
|
9
|
+
- "duo off" → run `~/.claude/scripts/duo-mode-write.sh off "<reason>"`, announce: "⟡🔮 MERLIN › Duo off."
|
|
10
|
+
- "duo status" → run `duo-mode-read.sh` and `--pair`, report state and pair.
|
|
11
|
+
|
|
12
|
+
**Parallel tasks (planning, code review, tests, docs)** — spawn two `codex exec` subprocesses concurrently, then merge:
|
|
13
|
+
- Planning: `codex exec ... codex-planner persona` and `~/.claude/scripts/codex-as.sh challenger-academic ...` in parallel. Each writes to its own file (`<phase-dir>/PLAN-CODEX-A.md` and `PLAN-CODEX-B.md`). Then `~/.claude/scripts/codex-as.sh challenger-arbiter` synthesizes to `PLAN-FINAL.md`.
|
|
14
|
+
- Code review: `codex-code-review` and `codex-as.sh merlin-reviewer` in parallel; you merge their findings inline.
|
|
15
|
+
- Testing: `codex-as.sh tests-qa` and `codex-as.sh merlin-edge-case-hunter` in parallel; merge inline.
|
|
16
|
+
- Documentation: `codex-as.sh docs-keeper` solo — only one doc specialist exists.
|
|
17
|
+
|
|
18
|
+
**Sequential tasks (code write/modify)** — strict author → reviewer → gate, but the gate is YOU (the orchestrator), not a separate agent:
|
|
19
|
+
1. Author writes diff: `~/.claude/scripts/codex-as.sh implementation-dev "<task>"`
|
|
20
|
+
2. Reviewer reviews: `~/.claude/scripts/codex-as.sh code-review "<diff or path>"`
|
|
21
|
+
3. YOU consume the reviewer's findings and decide approve/revise/reject inline — do not delegate this gate to another spawn. (The dedicated `reviewer-decider` is Claude-only by safety design and isn't available to you.)
|
|
22
|
+
4. On revise: re-run author once with required_changes, then re-review. Max 2 iterations. On second revise or reject, stop and report.
|
|
23
|
+
|
|
24
|
+
**Run-parallel pattern (bash):**
|
|
25
|
+
```
|
|
26
|
+
( codex exec "..." > a.out 2>&1 ) &
|
|
27
|
+
( codex exec "..." > b.out 2>&1 ) &
|
|
28
|
+
wait
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Verification stays your job.** Codex specialists may execute, but you certify by running tests/builds yourself before declaring done.
|
|
32
|
+
|
|
33
|
+
**Badge:** Always prefix every action with `⟡🔮↔🔮 MERLIN·DUO ›` when duo is on, `⟡🔮 MERLIN ›` when off.
|
|
34
|
+
|
|
35
|
+
TASK OPTIMIZATION: Before EVERY routing decision (workflows, agents, specialists), run ~/.claude/scripts/task-optimize.sh --task "<user text>". It returns {intent, skills[], agent, score, matched_phrases}. If score>=25, ALWAYS announce "⟡🔮 MERLIN › Intent: <X>. Loading <skills> + routing to <agent>." then route with skills prepended to context. Registry: ~/.claude/merlin/skills/TASK-OPTIMIZER.json. Slash commands /merlin:optimize, /merlin:design-audit, /merlin:polish, /merlin:redesign wrap common flows.
|
|
@@ -93,6 +93,25 @@ Codex can embody these roles via `codex-as.sh`:
|
|
|
93
93
|
|
|
94
94
|
Any other specialist stays with Claude.
|
|
95
95
|
|
|
96
|
+
## Universal Task Optimization (Codex)
|
|
97
|
+
|
|
98
|
+
When dispatching to `codex-implementer` or any `codex-as.sh <specialist>`, ALSO run the universal optimizer first:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
bash ~/.claude/scripts/task-optimize.sh --task "<text>"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
If `score >= 25`:
|
|
105
|
+
1. Read each matched skill file (`~/.claude/merlin/skills/<id>.md` or external path)
|
|
106
|
+
2. PREPEND the skill bodies to the codex-as.sh prompt body (BEFORE the specialist's own system prompt)
|
|
107
|
+
3. Optionally use the optimizer's recommended agent as the specialist (override caller's choice if not user-specified)
|
|
108
|
+
|
|
109
|
+
This is the Codex-side mirror of the Claude-side `merlin-routing.md` § Universal Task Optimization.
|
|
110
|
+
|
|
111
|
+
If skill files are missing locally, run `bash ~/.claude/scripts/install-design-skills.sh` first.
|
|
112
|
+
|
|
113
|
+
The registry of all skill→agent pairings lives at `~/.claude/merlin/skills/TASK-OPTIMIZER.json`. When the optimizer returns skills for a task, `codex-as.sh` automatically prepends them to the specialist's system prompt.
|
|
114
|
+
|
|
96
115
|
## Code Review Routing
|
|
97
116
|
|
|
98
117
|
Natural language intent: "code review" / "production readiness review" / "review the codebase" / "check for AI smells" / "review this folder" / "do a full review"
|
|
@@ -14,23 +14,37 @@ Duo mode runs two brains on the same task: Claude and Codex. Tasks that produce
|
|
|
14
14
|
|
|
15
15
|
**Schema:**
|
|
16
16
|
```json
|
|
17
|
-
{"enabled": bool, "sinceISO": "ISO8601 | null", "lastToggleReason": "string | null"}
|
|
17
|
+
{"enabled": bool, "sinceISO": "ISO8601 | null", "lastToggleReason": "string | null", "pair": "claude+codex" | "claude+claude" | "codex+codex" | null}
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
**Default (first install):**
|
|
21
21
|
```json
|
|
22
|
-
{"enabled": false, "sinceISO": null, "lastToggleReason": null}
|
|
22
|
+
{"enabled": false, "sinceISO": null, "lastToggleReason": null, "pair": null}
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
**Auto-expire:** If `sinceISO` is more than 24 hours old at read time, treat as disabled. The file is NOT rewritten on read — expiry is a read-time interpretation. Approximately session-sticky.
|
|
26
26
|
|
|
27
27
|
**Toggle:** `Skill("merlin:duo", args="on|off|status|unsuppress")` or natural language (see `merlin-routing.md` for intent triggers).
|
|
28
28
|
|
|
29
|
-
**Install gate:**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
**Install gate:** `duo-installed.sh` is always-pass — duo is always available. Pair selection (which specialists are used) is determined separately at toggle time via `codex-installed.sh`.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Pair selection
|
|
34
|
+
|
|
35
|
+
Duo runs as one of two pairs, selected at toggle-on time and persisted in `duo-mode.json` under the `pair` field:
|
|
36
|
+
|
|
37
|
+
| Pair | When selected | Behavior |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `claude+codex` | Codex installed (`codex-installed.sh` exits 0) at toggle time | Claude + Codex collaboration. Existing duo behavior. |
|
|
40
|
+
| `claude+claude` | Codex not installed at toggle time | Twin-Claude — two different Claude specialists tag-team each task. |
|
|
41
|
+
| `codex+codex` | Running under merlin-codex (`MERLIN_RUNTIME=codex`) | Codex-only — Codex orchestrator + two Codex specialists per task. Used when Claude Code isn't available. |
|
|
42
|
+
|
|
43
|
+
Pair auto-detection at toggle-on time: `MERLIN_RUNTIME=codex` → `codex+codex`; else `codex-installed.sh` exit 0 → `claude+codex`; else → `claude+claude`.
|
|
44
|
+
|
|
45
|
+
Pair is fixed for the life of the duo session (24h auto-expire). Disable + re-enable to re-detect.
|
|
46
|
+
|
|
47
|
+
The `duo-installed.sh` gate is always-pass now — duo is always available. `codex-installed.sh` is what determines pair for claude-orchestrated sessions.
|
|
34
48
|
|
|
35
49
|
---
|
|
36
50
|
|
|
@@ -38,7 +52,7 @@ Duo mode runs two brains on the same task: Claude and Codex. Tasks that produce
|
|
|
38
52
|
|
|
39
53
|
When multiple modes are enabled simultaneously:
|
|
40
54
|
|
|
41
|
-
1. **Duo active** (enabled=true, within 24h
|
|
55
|
+
1. **Duo active** (enabled=true, within 24h) → duo rules in this file win
|
|
42
56
|
2. **Codex-mode active** (enabled=true, within 24h, codex gate passes) → `codex-routing.md` rules apply
|
|
43
57
|
3. **Neither** → solo routing (existing `merlin-routing.md` + `codex-routing.md` rules)
|
|
44
58
|
|
|
@@ -52,7 +66,7 @@ Compute the badge via `~/.claude/scripts/duo-badge.sh` before every action prefi
|
|
|
52
66
|
|
|
53
67
|
| Condition | Badge |
|
|
54
68
|
|---|---|
|
|
55
|
-
| Duo enabled + within 24h
|
|
69
|
+
| Duo enabled + within 24h | `⟡🔮↔🔮 MERLIN·DUO ›` |
|
|
56
70
|
| Any other state | `⟡🔮 MERLIN ›` |
|
|
57
71
|
|
|
58
72
|
**Text-only fallback:** If env `MERLIN_BADGE_TEXTONLY=1`, `duo-badge.sh` returns `[DUO] MERLIN ›` or `MERLIN ›` for terminals that mangle `↔` or emoji.
|
|
@@ -86,6 +100,30 @@ Both brains run independently on the same task. Results are routed to the arbite
|
|
|
86
100
|
|
|
87
101
|
---
|
|
88
102
|
|
|
103
|
+
## Parallel Planning Artifacts
|
|
104
|
+
|
|
105
|
+
Both planners and the arbiter write to canonical paths inside the phase directory. The orchestrator MUST pass these absolute paths in each agent's prompt.
|
|
106
|
+
|
|
107
|
+
| Agent | Writes to | Required prompt args |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `merlin-planner` | `<phase-dir>/PLAN-CLAUDE.md` | `output_path` |
|
|
110
|
+
| `codex-planner` | `<phase-dir>/PLAN-CODEX.md` | `output_path` |
|
|
111
|
+
| `challenger-arbiter` | `<phase-dir>/PLAN-FINAL.md` | `output_path`, `claude_plan_path`, `codex_plan_path` |
|
|
112
|
+
|
|
113
|
+
`<phase-dir>` resolution:
|
|
114
|
+
- Numbered phases → `.planning/phases/<NN-slug>/`
|
|
115
|
+
- Ad-hoc duo workflows → `.planning/duo/<slug>/`
|
|
116
|
+
|
|
117
|
+
The orchestrator MUST `mkdir -p <phase-dir>` before spawning the agents.
|
|
118
|
+
|
|
119
|
+
**Contract for planning agents:**
|
|
120
|
+
- The file on disk at `output_path` is the canonical artifact for any agent that receives `output_path` in its prompt. Such agents MUST write the file themselves and MUST NOT return inline content as a fallback.
|
|
121
|
+
- Agents that are part of a parallel pair but do NOT receive `output_path` (e.g. `challenger-academic` in twin-Claude planning, whose frontmatter forbids Write) MAY return inline content; the orchestrator captures and writes the file in that case.
|
|
122
|
+
- If an agent cannot write `output_path` (tool denied, disk error, missing arg), it MUST return a structured error and stop. The orchestrator never reconstructs plans from stdout.
|
|
123
|
+
- If `output_path` is missing or not absolute, the agent MUST refuse with a clear error.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
89
127
|
## Routing Matrix — SEQUENTIAL execution
|
|
90
128
|
|
|
91
129
|
One author at a time to prevent file conflicts. Sequential only for tasks that write or modify source files.
|
|
@@ -120,12 +158,74 @@ If decider returns `revise`:
|
|
|
120
158
|
|
|
121
159
|
---
|
|
122
160
|
|
|
161
|
+
## Twin-Claude pair (claude+claude) routing
|
|
162
|
+
|
|
163
|
+
When `pair == claude+claude`, the parallel and sequential matrices use these specialist pairings instead:
|
|
164
|
+
|
|
165
|
+
**PARALLEL:**
|
|
166
|
+
|
|
167
|
+
| Task | Brain A | Brain B | Decider |
|
|
168
|
+
|---|---|---|---|
|
|
169
|
+
| Planning (feature-dev / refactor / product-dev) | `merlin-planner` | `challenger-academic` | `challenger-arbiter` |
|
|
170
|
+
| Code review | `code-review` | `merlin-reviewer` | `challenger-arbiter` (merge + dedupe) |
|
|
171
|
+
| Testing | `tests-qa` | `merlin-edge-case-hunter` | `challenger-arbiter` (merge + dedupe) |
|
|
172
|
+
| Documentation | `docs-keeper` | — | falls back to solo (no second doc specialist available) |
|
|
173
|
+
|
|
174
|
+
**SEQUENTIAL (code write/modify):**
|
|
175
|
+
|
|
176
|
+
| Author | Reviewer | Decider |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| `implementation-dev` | `code-review` | `reviewer-decider` |
|
|
179
|
+
|
|
180
|
+
**Twin-Claude planning artifact paths:**
|
|
181
|
+
|
|
182
|
+
- `<phase-dir>/PLAN-CLAUDE.md` — written by `merlin-planner` (uses output_path arg).
|
|
183
|
+
- `<phase-dir>/PLAN-CHALLENGE.md` — challenger-academic does NOT receive output_path (its frontmatter forbids Write). The orchestrator captures the agent's returned content and writes the file.
|
|
184
|
+
- `<phase-dir>/PLAN-FINAL.md` — written by `challenger-arbiter`. In claude+claude, the arbiter's prompt receives `claude_plan_path` and `challenge_plan_path` instead of `codex_plan_path`.
|
|
185
|
+
|
|
186
|
+
`reviewer-decider` remains Claude-only — even in claude+claude where the author is also Claude. The gate authority is intentionally separated by being a fresh agent spawn with its own context, not by brain identity.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Codex-only pair (codex+codex) routing
|
|
191
|
+
|
|
192
|
+
When `pair == codex+codex` (orchestrator is `merlin-codex`, no Claude available), the orchestrator drives duo via bash and `codex-as.sh`. Specialists are invoked as `codex exec`/`codex-as.sh <agent>` instead of as Skill/Agent calls.
|
|
193
|
+
|
|
194
|
+
**PARALLEL:**
|
|
195
|
+
|
|
196
|
+
| Task | Brain A | Brain B | Decider |
|
|
197
|
+
|---|---|---|---|
|
|
198
|
+
| Planning (feature-dev / refactor / product-dev) | `codex-planner` | `codex-as.sh challenger-academic` | `codex-as.sh challenger-arbiter` |
|
|
199
|
+
| Code review | `codex-code-review` | `codex-as.sh merlin-reviewer` | merge + dedupe inline (orchestrator) |
|
|
200
|
+
| Testing | `codex-as.sh tests-qa` | `codex-as.sh merlin-edge-case-hunter` | merge + dedupe inline (orchestrator) |
|
|
201
|
+
| Documentation | `codex-as.sh docs-keeper` | — | solo (single specialist) |
|
|
202
|
+
|
|
203
|
+
**SEQUENTIAL (code write/modify):**
|
|
204
|
+
|
|
205
|
+
| Author | Reviewer | Gate |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| `codex-as.sh implementation-dev` | `codex-as.sh code-review` | **inline orchestrator judgment** — no `reviewer-decider` (Claude-only by P0) |
|
|
208
|
+
|
|
209
|
+
**Codex-only planning artifact paths:**
|
|
210
|
+
|
|
211
|
+
- `<phase-dir>/PLAN-CODEX-A.md` — written by `codex-planner` (receives `output_path`).
|
|
212
|
+
- `<phase-dir>/PLAN-CODEX-B.md` — challenger-academic via `codex-as.sh` does NOT receive `output_path` (its frontmatter forbids Write). Orchestrator captures the agent's stdout and writes the file.
|
|
213
|
+
- `<phase-dir>/PLAN-FINAL.md` — written by `codex-as.sh challenger-arbiter` (receives `output_path` plus both A and B paths).
|
|
214
|
+
|
|
215
|
+
**Safety degradation (documented honestly):**
|
|
216
|
+
|
|
217
|
+
Sequential code in `codex+codex` has a weaker gate than `claude+codex` or `claude+claude`. In those pairs, `reviewer-decider` is a separate fresh-context Claude spawn that gates the author's diff. In `codex+codex`, no separate gate spawn is available — the orchestrator (Codex) consumes the reviewer's findings and decides approve/revise/reject inline within its own context. This is acceptable for non-critical changes but users should consider installing Claude Code for higher-stakes work.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
123
221
|
## reviewer-decider is Claude-only (P0 safety)
|
|
124
222
|
|
|
125
223
|
`reviewer-decider` MUST NOT be invoked via `codex-as.sh`. Codex impersonating the gate that checks Codex's own output destroys the sequential safety story. The curated specialists list in `codex-routing.md` explicitly excludes `reviewer-decider` — this exclusion is permanent and must not be removed.
|
|
126
224
|
|
|
127
225
|
See also: `codex-routing.md` § "Curated specialists exclusion".
|
|
128
226
|
|
|
227
|
+
In `codex+codex` pair, no `reviewer-decider` invocation occurs — the orchestrator handles gate logic inline. This is the only pair where the gate is not a separate spawn, and it's a documented safety degradation, not an oversight.
|
|
228
|
+
|
|
129
229
|
---
|
|
130
230
|
|
|
131
231
|
## Auto-offer for risky tasks
|
|
@@ -142,7 +242,6 @@ When duo is OFF, Merlin runs a pre-route hook at the start of every routing deci
|
|
|
142
242
|
**Risk threshold:** `duo-risk-detect.sh` scores the task 0–100. `suggest_duo: true` when score ≥ 50. Threshold tunable via env `MERLIN_DUO_OFFER_THRESHOLD`.
|
|
143
243
|
|
|
144
244
|
**Offer fires only when ALL of the following are true:**
|
|
145
|
-
- `duo-installed.sh` exits 0 (Codex installed)
|
|
146
245
|
- Duo is currently OFF (or auto-expired)
|
|
147
246
|
- Risk score ≥ threshold
|
|
148
247
|
- Not suppressed (no `session_skip`, task hash not in `task_hashes_declined`, intent not in `never_for_intents`)
|