rafcode 3.0.0 → 3.8.0

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 (235) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/CLAUDE.md +0 -1
  3. package/RAF/38-dual-wielder/decisions.md +9 -0
  4. package/RAF/38-dual-wielder/input.md +6 -1
  5. package/RAF/38-dual-wielder/outcomes/8-e2e-test-codex-provider.md +139 -0
  6. package/RAF/38-dual-wielder/plans/8-e2e-test-codex-provider.md +95 -0
  7. package/RAF/39-pathless-rover/decisions.md +16 -0
  8. package/RAF/39-pathless-rover/input.md +2 -0
  9. package/RAF/39-pathless-rover/outcomes/1-fix-codex-stream-renderer.md +21 -0
  10. package/RAF/39-pathless-rover/outcomes/2-wire-provider-flag.md +28 -0
  11. package/RAF/39-pathless-rover/outcomes/3-remove-worktree-flag-do.md +41 -0
  12. package/RAF/39-pathless-rover/outcomes/4-remove-worktree-flag-plan-amend.md +30 -0
  13. package/RAF/39-pathless-rover/outcomes/5-update-prompts-and-docs.md +26 -0
  14. package/RAF/39-pathless-rover/plans/1-fix-codex-stream-renderer.md +43 -0
  15. package/RAF/39-pathless-rover/plans/2-wire-provider-flag.md +48 -0
  16. package/RAF/39-pathless-rover/plans/3-remove-worktree-flag-do.md +41 -0
  17. package/RAF/39-pathless-rover/plans/4-remove-worktree-flag-plan-amend.md +43 -0
  18. package/RAF/39-pathless-rover/plans/5-update-prompts-and-docs.md +31 -0
  19. package/RAF/40-numeric-order-fix/decisions.md +7 -0
  20. package/RAF/40-numeric-order-fix/input.md +19 -0
  21. package/RAF/40-numeric-order-fix/outcomes/1-fix-numeric-sort-order.md +18 -0
  22. package/RAF/40-numeric-order-fix/outcomes/2-add-npm-keywords.md +10 -0
  23. package/RAF/40-numeric-order-fix/plans/1-fix-numeric-sort-order.md +48 -0
  24. package/RAF/40-numeric-order-fix/plans/2-add-npm-keywords.md +23 -0
  25. package/RAF/41-echo-chamber/decisions.md +13 -0
  26. package/RAF/41-echo-chamber/input.md +4 -0
  27. package/RAF/41-echo-chamber/outcomes/1-update-codex-model-defaults.md +24 -0
  28. package/RAF/41-echo-chamber/outcomes/2-e2e-test-codex-provider.md +74 -0
  29. package/RAF/41-echo-chamber/plans/1-update-codex-model-defaults.md +28 -0
  30. package/RAF/41-echo-chamber/plans/2-e2e-test-codex-provider.md +103 -0
  31. package/RAF/42-patch-parade/decisions.md +29 -0
  32. package/RAF/42-patch-parade/input.md +9 -0
  33. package/RAF/42-patch-parade/outcomes/1-fix-codex-model-resolution.md +36 -0
  34. package/RAF/42-patch-parade/outcomes/2-fix-provider-aware-name-generation.md +31 -0
  35. package/RAF/42-patch-parade/outcomes/3-fix-codex-error-event-rendering.md +32 -0
  36. package/RAF/42-patch-parade/outcomes/4-update-cli-help-docs.md +28 -0
  37. package/RAF/42-patch-parade/outcomes/5-update-default-codex-models-to-gpt-5-4.md +33 -0
  38. package/RAF/42-patch-parade/outcomes/6-unify-model-config-schema.md +89 -0
  39. package/RAF/42-patch-parade/plans/1-fix-codex-model-resolution.md +35 -0
  40. package/RAF/42-patch-parade/plans/2-fix-provider-aware-name-generation.md +38 -0
  41. package/RAF/42-patch-parade/plans/3-fix-codex-error-event-rendering.md +32 -0
  42. package/RAF/42-patch-parade/plans/4-update-cli-help-docs.md +31 -0
  43. package/RAF/42-patch-parade/plans/5-update-default-codex-models-to-gpt-5-4.md +35 -0
  44. package/RAF/42-patch-parade/plans/6-unify-model-config-schema.md +46 -0
  45. package/RAF/43-swiss-army/decisions.md +34 -0
  46. package/RAF/43-swiss-army/input.md +7 -0
  47. package/RAF/43-swiss-army/outcomes/1-fix-model-validation.md +21 -0
  48. package/RAF/43-swiss-army/outcomes/2-update-commit-format.md +31 -0
  49. package/RAF/43-swiss-army/outcomes/3-wire-reasoning-effort.md +28 -0
  50. package/RAF/43-swiss-army/outcomes/4-remove-provider-flag.md +27 -0
  51. package/RAF/43-swiss-army/outcomes/5-config-wizard-validation.md +23 -0
  52. package/RAF/43-swiss-army/outcomes/6-add-fast-mode.md +32 -0
  53. package/RAF/43-swiss-army/outcomes/7-config-preset.md +31 -0
  54. package/RAF/43-swiss-army/plans/1-fix-model-validation.md +38 -0
  55. package/RAF/43-swiss-army/plans/2-update-commit-format.md +46 -0
  56. package/RAF/43-swiss-army/plans/3-wire-reasoning-effort.md +39 -0
  57. package/RAF/43-swiss-army/plans/4-remove-provider-flag.md +43 -0
  58. package/RAF/43-swiss-army/plans/5-config-wizard-validation.md +42 -0
  59. package/RAF/43-swiss-army/plans/6-add-fast-mode.md +46 -0
  60. package/RAF/43-swiss-army/plans/7-config-preset.md +51 -0
  61. package/RAF/44-config-api-change/decisions.md +22 -0
  62. package/RAF/44-config-api-change/input.md +5 -0
  63. package/RAF/44-config-api-change/outcomes/1-restructure-config-subcommands.md +19 -0
  64. package/RAF/44-config-api-change/outcomes/2-move-preset-under-config.md +17 -0
  65. package/RAF/44-config-api-change/outcomes/3-update-existing-tests-for-config-api.md +14 -0
  66. package/RAF/44-config-api-change/outcomes/4-update-config-command-docs.md +11 -0
  67. package/RAF/44-config-api-change/outcomes/5-fix-codex-name-generation.md +18 -0
  68. package/RAF/44-config-api-change/plans/1-restructure-config-subcommands.md +37 -0
  69. package/RAF/44-config-api-change/plans/2-move-preset-under-config.md +38 -0
  70. package/RAF/44-config-api-change/plans/3-update-existing-tests-for-config-api.md +38 -0
  71. package/RAF/44-config-api-change/plans/4-update-config-command-docs.md +36 -0
  72. package/RAF/44-config-api-change/plans/5-fix-codex-name-generation.md +49 -0
  73. package/RAF/45-signal-cairn/decisions.md +7 -0
  74. package/RAF/45-signal-cairn/input.md +2 -0
  75. package/RAF/45-signal-cairn/outcomes/1-rename-provider-to-harness.md +19 -0
  76. package/RAF/45-signal-cairn/outcomes/2-normalize-model-display-names.md +18 -0
  77. package/RAF/45-signal-cairn/plans/1-rename-provider-to-harness.md +40 -0
  78. package/RAF/45-signal-cairn/plans/2-normalize-model-display-names.md +41 -0
  79. package/RAF/45-signal-lantern/decisions.md +10 -0
  80. package/RAF/45-signal-lantern/input.md +2 -0
  81. package/RAF/45-signal-lantern/outcomes/1-add-effort-and-fast-to-do-model-display.md +15 -0
  82. package/RAF/45-signal-lantern/outcomes/2-capture-codex-post-run-token-usage.md +15 -0
  83. package/RAF/45-signal-lantern/outcomes/3-show-codex-token-summaries-without-fake-cost.md +14 -0
  84. package/RAF/45-signal-lantern/plans/1-add-effort-and-fast-to-do-model-display.md +38 -0
  85. package/RAF/45-signal-lantern/plans/2-capture-codex-post-run-token-usage.md +37 -0
  86. package/RAF/45-signal-lantern/plans/3-show-codex-token-summaries-without-fake-cost.md +40 -0
  87. package/RAF/46-lantern-arc/decisions.md +19 -0
  88. package/RAF/46-lantern-arc/input.md +6 -0
  89. package/RAF/46-lantern-arc/outcomes/1-remove-spark-alias.md +16 -0
  90. package/RAF/46-lantern-arc/outcomes/2-clean-up-worktree-plan-command.md +30 -0
  91. package/RAF/46-lantern-arc/outcomes/3-fix-token-usage-accumulation.md +32 -0
  92. package/RAF/46-lantern-arc/outcomes/4-display-effort-in-compact-mode.md +22 -0
  93. package/RAF/46-lantern-arc/outcomes/5-codex-fast-mode-research.md +38 -0
  94. package/RAF/46-lantern-arc/outcomes/6-optimize-llm-prompts.md +39 -0
  95. package/RAF/46-lantern-arc/plans/1-remove-spark-alias.md +38 -0
  96. package/RAF/46-lantern-arc/plans/2-clean-up-worktree-plan-command.md +33 -0
  97. package/RAF/46-lantern-arc/plans/3-fix-token-usage-accumulation.md +33 -0
  98. package/RAF/46-lantern-arc/plans/4-display-effort-in-compact-mode.md +28 -0
  99. package/RAF/46-lantern-arc/plans/5-codex-fast-mode-research.md +34 -0
  100. package/RAF/46-lantern-arc/plans/6-optimize-llm-prompts.md +48 -0
  101. package/RAF/47-signal-trim/decisions.md +13 -0
  102. package/RAF/47-signal-trim/input.md +2 -0
  103. package/RAF/47-signal-trim/plans/1-remove-cache-from-status.md +73 -0
  104. package/README.md +50 -63
  105. package/dist/commands/config.d.ts.map +1 -1
  106. package/dist/commands/config.js +47 -49
  107. package/dist/commands/config.js.map +1 -1
  108. package/dist/commands/do.d.ts +2 -0
  109. package/dist/commands/do.d.ts.map +1 -1
  110. package/dist/commands/do.js +91 -230
  111. package/dist/commands/do.js.map +1 -1
  112. package/dist/commands/plan.d.ts.map +1 -1
  113. package/dist/commands/plan.js +54 -259
  114. package/dist/commands/plan.js.map +1 -1
  115. package/dist/commands/preset.d.ts +3 -0
  116. package/dist/commands/preset.d.ts.map +1 -0
  117. package/dist/commands/preset.js +158 -0
  118. package/dist/commands/preset.js.map +1 -0
  119. package/dist/core/claude-runner.d.ts +2 -0
  120. package/dist/core/claude-runner.d.ts.map +1 -1
  121. package/dist/core/claude-runner.js +36 -12
  122. package/dist/core/claude-runner.js.map +1 -1
  123. package/dist/core/codex-runner.d.ts +1 -0
  124. package/dist/core/codex-runner.d.ts.map +1 -1
  125. package/dist/core/codex-runner.js +26 -7
  126. package/dist/core/codex-runner.js.map +1 -1
  127. package/dist/core/failure-analyzer.js +2 -1
  128. package/dist/core/failure-analyzer.js.map +1 -1
  129. package/dist/core/git.d.ts +2 -2
  130. package/dist/core/git.d.ts.map +1 -1
  131. package/dist/core/git.js +53 -3
  132. package/dist/core/git.js.map +1 -1
  133. package/dist/core/project-manager.d.ts.map +1 -1
  134. package/dist/core/project-manager.js +2 -2
  135. package/dist/core/project-manager.js.map +1 -1
  136. package/dist/core/pull-request.js +5 -5
  137. package/dist/core/pull-request.js.map +1 -1
  138. package/dist/core/runner-factory.d.ts +4 -4
  139. package/dist/core/runner-factory.d.ts.map +1 -1
  140. package/dist/core/runner-factory.js +8 -8
  141. package/dist/core/runner-factory.js.map +1 -1
  142. package/dist/core/runner-interface.d.ts +1 -1
  143. package/dist/core/runner-types.d.ts +17 -4
  144. package/dist/core/runner-types.d.ts.map +1 -1
  145. package/dist/core/state-derivation.js +3 -3
  146. package/dist/core/state-derivation.js.map +1 -1
  147. package/dist/parsers/codex-stream-renderer.d.ts +28 -4
  148. package/dist/parsers/codex-stream-renderer.d.ts.map +1 -1
  149. package/dist/parsers/codex-stream-renderer.js +110 -0
  150. package/dist/parsers/codex-stream-renderer.js.map +1 -1
  151. package/dist/prompts/amend.d.ts +0 -1
  152. package/dist/prompts/amend.d.ts.map +1 -1
  153. package/dist/prompts/amend.js +31 -104
  154. package/dist/prompts/amend.js.map +1 -1
  155. package/dist/prompts/execution.d.ts.map +1 -1
  156. package/dist/prompts/execution.js +17 -34
  157. package/dist/prompts/execution.js.map +1 -1
  158. package/dist/prompts/planning.d.ts.map +1 -1
  159. package/dist/prompts/planning.js +23 -123
  160. package/dist/prompts/planning.js.map +1 -1
  161. package/dist/types/config.d.ts +33 -32
  162. package/dist/types/config.d.ts.map +1 -1
  163. package/dist/types/config.js +14 -28
  164. package/dist/types/config.js.map +1 -1
  165. package/dist/utils/config.d.ts +36 -16
  166. package/dist/utils/config.d.ts.map +1 -1
  167. package/dist/utils/config.js +209 -104
  168. package/dist/utils/config.js.map +1 -1
  169. package/dist/utils/name-generator.d.ts.map +1 -1
  170. package/dist/utils/name-generator.js +25 -12
  171. package/dist/utils/name-generator.js.map +1 -1
  172. package/dist/utils/paths.d.ts +5 -0
  173. package/dist/utils/paths.d.ts.map +1 -1
  174. package/dist/utils/paths.js +9 -0
  175. package/dist/utils/paths.js.map +1 -1
  176. package/dist/utils/terminal-symbols.d.ts +15 -2
  177. package/dist/utils/terminal-symbols.d.ts.map +1 -1
  178. package/dist/utils/terminal-symbols.js +36 -4
  179. package/dist/utils/terminal-symbols.js.map +1 -1
  180. package/dist/utils/token-tracker.d.ts +6 -1
  181. package/dist/utils/token-tracker.d.ts.map +1 -1
  182. package/dist/utils/token-tracker.js +84 -51
  183. package/dist/utils/token-tracker.js.map +1 -1
  184. package/dist/utils/validation.d.ts +1 -2
  185. package/dist/utils/validation.d.ts.map +1 -1
  186. package/dist/utils/validation.js +4 -25
  187. package/dist/utils/validation.js.map +1 -1
  188. package/package.json +7 -2
  189. package/src/commands/config.ts +60 -63
  190. package/src/commands/do.ts +96 -262
  191. package/src/commands/plan.ts +55 -279
  192. package/src/commands/preset.ts +186 -0
  193. package/src/core/claude-runner.ts +45 -5
  194. package/src/core/codex-runner.ts +32 -7
  195. package/src/core/failure-analyzer.ts +2 -1
  196. package/src/core/git.ts +57 -3
  197. package/src/core/project-manager.ts +2 -1
  198. package/src/core/pull-request.ts +5 -5
  199. package/src/core/runner-factory.ts +9 -9
  200. package/src/core/runner-interface.ts +1 -1
  201. package/src/core/runner-types.ts +17 -4
  202. package/src/core/state-derivation.ts +3 -3
  203. package/src/parsers/codex-stream-renderer.ts +149 -4
  204. package/src/prompts/amend.ts +30 -105
  205. package/src/prompts/config-docs.md +206 -62
  206. package/src/prompts/execution.ts +17 -34
  207. package/src/prompts/planning.ts +23 -124
  208. package/src/types/config.ts +47 -59
  209. package/src/utils/config.ts +248 -115
  210. package/src/utils/name-generator.ts +29 -13
  211. package/src/utils/paths.ts +10 -0
  212. package/src/utils/terminal-symbols.ts +46 -6
  213. package/src/utils/token-tracker.ts +96 -57
  214. package/src/utils/validation.ts +5 -30
  215. package/tests/unit/amend-prompt.test.ts +3 -2
  216. package/tests/unit/claude-runner-interactive.test.ts +21 -3
  217. package/tests/unit/claude-runner.test.ts +39 -0
  218. package/tests/unit/codex-runner.test.ts +163 -0
  219. package/tests/unit/codex-stream-renderer.test.ts +127 -0
  220. package/tests/unit/command-output.test.ts +57 -0
  221. package/tests/unit/commit-planning-artifacts-worktree.test.ts +24 -7
  222. package/tests/unit/commit-planning-artifacts.test.ts +26 -4
  223. package/tests/unit/config-command.test.ts +215 -303
  224. package/tests/unit/config.test.ts +319 -235
  225. package/tests/unit/dependency-integration.test.ts +27 -1
  226. package/tests/unit/do-model-display.test.ts +35 -0
  227. package/tests/unit/execution-prompt.test.ts +49 -19
  228. package/tests/unit/name-generator.test.ts +82 -12
  229. package/tests/unit/plan-command-auto-flag.test.ts +7 -10
  230. package/tests/unit/plan-command.test.ts +14 -17
  231. package/tests/unit/planning-prompt.test.ts +9 -8
  232. package/tests/unit/terminal-symbols.test.ts +94 -3
  233. package/tests/unit/token-tracker.test.ts +180 -1
  234. package/tests/unit/validation.test.ts +9 -41
  235. package/tests/unit/worktree-flag-override.test.ts +0 -186
@@ -13,7 +13,7 @@ The config file is a JSON object. All keys are optional at every level. User val
13
13
  ```json
14
14
  {
15
15
  "models": {
16
- "plan": "opus"
16
+ "plan": { "model": "sonnet", "harness": "claude" }
17
17
  }
18
18
  }
19
19
  ```
@@ -24,50 +24,80 @@ The above only changes `models.plan` — all other model settings keep their def
24
24
 
25
25
  ### `models` — Model Selection
26
26
 
27
- Controls which model is used for each scenario. Values can be a short alias (`"sonnet"`, `"haiku"`, `"opus"`) or a full model ID.
27
+ Controls which model and harness is used for each scenario. Each entry is a `ModelEntry` object with the following shape:
28
28
 
29
- **Model ID format**: Full model IDs follow the pattern `claude-{family}-{version}`, for example:
30
- - `"claude-opus-4-5-20251101"` Opus 4.5 from November 2025
31
- - `"claude-opus-4-6"` — Opus 4.6 (latest)
32
- - `"claude-sonnet-4-5-20250929"` — Sonnet 4.5 from September 2025
33
- - `"claude-haiku-4-5-20251001"` Haiku 4.5 from October 2025
29
+ ```json
30
+ { "model": "<model-name>", "harness": "<harness>", "reasoningEffort": "<effort>", "fast": true }
31
+ ```
32
+
33
+ - **`model`** (required): A short alias (`"sonnet"`, `"haiku"`, `"opus"`) or a full model ID (e.g., `"claude-opus-4-6"`, `"gpt-5.4"`, `"o3"`).
34
+ - **`harness`** (required): The CLI harness — `"claude"` or `"codex"`.
35
+ - **`fast`** (optional): Enable fast mode for faster output. Claude only — uses the same model with ~2.5x faster responses at higher per-token cost. Default: `false`/omitted. Codex does not support fast mode; RAF warns and ignores `fast: true` on Codex entries.
36
+ - **`reasoningEffort`** (optional): Controls reasoning depth. Accepted values differ by harness:
37
+ - **Claude** (`output_config.effort`): `"low"`, `"medium"`, `"high"` (default), `"max"` (Opus 4.6 only). Supported on Opus 4.5+, Sonnet 4.6+. Haiku does not support reasoning.
38
+ - **Codex** (`model_reasoning_effort`): `"none"`, `"minimal"`, `"low"`, `"medium"` (default), `"high"`, `"xhigh"`.
34
39
 
35
- **Short aliases**: Using aliases (`"opus"`, `"sonnet"`, `"haiku"`) automatically selects the latest version of that model family.
40
+ **Claude model aliases**: `"opus"`, `"sonnet"`, `"haiku"` automatically select the latest version.
41
+ **Known Codex models**: `"gpt-5.4"`, `"gpt-5.4-2026-03-05"` (pinned), `"gpt-5.4-pro"`, `"gpt-5.4-mini"`, `"gpt-5.4-nano"`, `"o3"`.
36
42
 
37
43
  | Key | Default | Description |
38
44
  |-----|---------|-------------|
39
- | `models.plan` | `"opus"` | Model used for planning sessions (`raf plan`) |
40
- | `models.execute` | `"opus"` | Ceiling model for task execution (`raf do`). Per-task models from effort frontmatter are capped to this tier. Also used as the fallback when a plan has no effort frontmatter. |
41
- | `models.nameGeneration` | `"sonnet"` | Model used for generating project names |
42
- | `models.failureAnalysis` | `"haiku"` | Model used for analyzing task failures |
43
- | `models.prGeneration` | `"sonnet"` | Model used for generating PR titles and descriptions |
44
- | `models.config` | `"sonnet"` | Model used for the interactive config editor (`raf config`) |
45
+ | `models.plan` | `{ "model": "opus", "harness": "claude" }` | Model used for planning sessions (`raf plan`) |
46
+ | `models.execute` | `{ "model": "opus", "harness": "claude" }` | Ceiling model for task execution (`raf do`). Per-task models from effort frontmatter are capped to this tier. Also used as the fallback when a plan has no effort frontmatter. |
47
+ | `models.nameGeneration` | `{ "model": "sonnet", "harness": "claude" }` | Model used for generating project names |
48
+ | `models.failureAnalysis` | `{ "model": "haiku", "harness": "claude" }` | Model used for analyzing task failures |
49
+ | `models.prGeneration` | `{ "model": "sonnet", "harness": "claude" }` | Model used for generating PR titles and descriptions |
50
+ | `models.config` | `{ "model": "sonnet", "harness": "claude" }` | Model used for the interactive config editor (`raf config wizard`) |
51
+
52
+ **Partial overrides**: When deep-merging, you can override just the `model` or `harness` within an entry:
53
+
54
+ ```json
55
+ {
56
+ "models": {
57
+ "execute": { "model": "gpt-5.4", "harness": "codex" }
58
+ }
59
+ }
60
+ ```
45
61
 
46
62
  ### `effortMapping` — Task Effort to Model Mapping
47
63
 
48
- Maps task complexity labels (in plan frontmatter) to models. When a plan file has `effort: medium`, RAF resolves the execution model using this mapping.
64
+ Maps task complexity labels (in plan frontmatter) to `ModelEntry` objects. When a plan file has `effort: medium`, RAF resolves the execution model using this mapping.
49
65
 
50
66
  | Key | Default | Description |
51
67
  |-----|---------|-------------|
52
- | `effortMapping.low` | `"sonnet"` | Model for low-complexity tasks |
53
- | `effortMapping.medium` | `"opus"` | Model for medium-complexity tasks |
54
- | `effortMapping.high` | `"opus"` | Model for high-complexity tasks |
68
+ | `effortMapping.low` | `{ "model": "sonnet", "harness": "claude" }` | Model for low-complexity tasks |
69
+ | `effortMapping.medium` | `{ "model": "opus", "harness": "claude" }` | Model for medium-complexity tasks |
70
+ | `effortMapping.high` | `{ "model": "opus", "harness": "claude" }` | Model for high-complexity tasks |
55
71
 
56
- Values must be a short alias (`"sonnet"`, `"haiku"`, `"opus"`) or a full model ID.
72
+ Each value is a `ModelEntry` object (same shape as `models.*` entries).
57
73
 
58
74
  **Interaction with `models.execute`**: The `models.execute` value acts as a ceiling. If a task's effort maps to a more expensive model than the ceiling, the ceiling model is used instead. This gives users budget control while allowing tasks to use cheaper models when appropriate.
59
75
 
60
76
  Example:
61
77
  ```json
62
78
  {
63
- "models": { "execute": "sonnet" },
64
- "effortMapping": { "low": "sonnet", "medium": "opus", "high": "opus" }
79
+ "models": { "execute": { "model": "sonnet", "harness": "claude" } },
80
+ "effortMapping": {
81
+ "low": { "model": "sonnet", "harness": "claude" },
82
+ "medium": { "model": "opus", "harness": "claude" },
83
+ "high": { "model": "opus", "harness": "claude" }
84
+ }
65
85
  }
66
86
  ```
67
87
  - Task with `effort: low` → sonnet (at ceiling)
68
88
  - Task with `effort: medium` → sonnet (capped to ceiling, not opus)
69
89
  - Task with `effort: high` → sonnet (capped to ceiling, not opus)
70
90
 
91
+ **Mixed harnesses**: You can mix Claude and Codex models freely:
92
+ ```json
93
+ {
94
+ "effortMapping": {
95
+ "low": { "model": "sonnet", "harness": "claude" },
96
+ "high": { "model": "gpt-5.4", "harness": "codex" }
97
+ }
98
+ }
99
+ ```
100
+
71
101
  ### `timeout` — Task Timeout
72
102
 
73
103
  - **Type**: number (positive)
@@ -90,7 +120,7 @@ Example:
90
120
 
91
121
  - **Type**: boolean
92
122
  - **Default**: `false`
93
- - **Description**: When `true`, `raf plan` and `raf do` default to worktree mode (isolated git worktree). Can be overridden per-command with `--worktree` flag.
123
+ - **Description**: When `true`, `raf plan` defaults to worktree mode (isolated git worktree). `raf do` auto-detects worktree projects regardless of this setting.
94
124
 
95
125
  ### `syncMainBranch` — Sync Main Branch with Remote
96
126
 
@@ -110,28 +140,31 @@ Controls the format of git commit messages. Templates use `{placeholder}` syntax
110
140
 
111
141
  | Key | Default | Description |
112
142
  |-----|---------|-------------|
113
- | `commitFormat.task` | `"{prefix}[{projectId}:{taskId}] {description}"` | Format for task completion commits |
114
- | `commitFormat.plan` | `"{prefix}[{projectId}] Plan: {projectName}"` | Format for plan creation commits |
115
- | `commitFormat.amend` | `"{prefix}[{projectId}] Amend: {projectName}"` | Format for plan amendment commits |
143
+ | `commitFormat.task` | `"{prefix}[{projectName}:{taskId}] {description}"` | Format for task completion commits |
144
+ | `commitFormat.plan` | `"{prefix}[{projectName}] Plan: {description}"` | Format for plan creation commits |
145
+ | `commitFormat.amend` | `"{prefix}[{projectName}] Amend: {description}"` | Format for plan amendment commits |
116
146
  | `commitFormat.prefix` | `"RAF"` | Prefix string substituted into `{prefix}` placeholder |
117
147
 
118
148
  #### Template Variables
119
149
 
120
150
  **Task commits** (`commitFormat.task`):
121
151
  - `{prefix}` — The value of `commitFormat.prefix`
122
- - `{projectId}` — The 6-character project identifier (e.g., `abcdef`)
123
- - `{taskId}` — The 2-character task identifier (e.g., `01`, `0a`)
152
+ - `{projectName}` — The project name extracted from the folder (e.g., `swiss-army` from `43-swiss-army`)
153
+ - `{projectId}` — Backwards-compatible alias for `{projectName}`
154
+ - `{taskId}` — The task number (e.g., `1`, `10`)
124
155
  - `{description}` — A concise description of what was accomplished
125
156
 
126
157
  **Plan commits** (`commitFormat.plan`):
127
158
  - `{prefix}` — The value of `commitFormat.prefix`
128
- - `{projectId}` — The 6-character project identifier
129
- - `{projectName}` — The human-readable project name (e.g., `fix-auth-bug`)
159
+ - `{projectName}` — The project name extracted from the folder
160
+ - `{projectId}` — Backwards-compatible alias for `{projectName}`
161
+ - `{description}` — Auto-generated summary from input.md
130
162
 
131
163
  **Amend commits** (`commitFormat.amend`):
132
164
  - `{prefix}` — The value of `commitFormat.prefix`
133
- - `{projectId}` — The 6-character project identifier
134
- - `{projectName}` — The human-readable project name
165
+ - `{projectName}` — The project name extracted from the folder
166
+ - `{projectId}` — Backwards-compatible alias for `{projectName}`
167
+ - `{description}` — Auto-generated description of what was amended
135
168
 
136
169
  Unknown placeholders are left as-is in the output.
137
170
 
@@ -153,12 +186,93 @@ Example:
153
186
  }
154
187
  ```
155
188
 
189
+ ## Valid Model Names
190
+
191
+ When configuring models, use one of the known names below. Aliases automatically resolve to the latest version.
192
+
193
+ ### Claude Models (harness: `"claude"`)
194
+
195
+ | Alias | Resolves To | Notes |
196
+ |-------|------------|-------|
197
+ | `"opus"` | `claude-opus-4-6` | Most capable, highest cost |
198
+ | `"sonnet"` | `claude-sonnet-4-5-20250929` | Balanced capability and cost |
199
+ | `"haiku"` | `claude-haiku-4-5-20251001` | Fastest, lowest cost |
200
+
201
+ You can also use full model IDs directly for version pinning:
202
+ - `"claude-opus-4-6"`, `"claude-opus-4-5-20251101"`
203
+ - `"claude-sonnet-4-6"`, `"claude-sonnet-4-5-20250929"`
204
+ - `"claude-haiku-4-5-20251001"`
205
+
206
+ Any string matching the pattern `claude-<family>-*` is accepted as a valid Claude model ID.
207
+
208
+ ### Codex Models (harness: `"codex"`)
209
+
210
+ | Alias | Resolves To | Notes |
211
+ |-------|------------|-------|
212
+ | `"codex"` | `gpt-5.3-codex` | Lightweight, fast |
213
+ | `"gpt54"` | `gpt-5.4` | Most capable Codex model |
214
+
215
+ You can also use raw Codex model IDs directly:
216
+ - `"gpt-5.4"`, `"gpt-5.4-2026-03-05"` (pinned), `"gpt-5.4-pro"`, `"gpt-5.4-mini"`, `"gpt-5.4-nano"`
217
+ - `"gpt-5.3-codex"`
218
+ - `"o3"`
219
+
220
+ Any string matching the pattern `gpt-<version>` or containing a dot-separated version number is accepted as a valid Codex model ID.
221
+
222
+ ### Prefixed Format
223
+
224
+ You can also use `harness/model` format: `"claude/opus"`, `"codex/gpt-5.4"`. The harness prefix is stripped and used to set the harness field.
225
+
226
+ ## Reasoning Effort
227
+
228
+ Reasoning effort controls how much thinking the model does before responding. Higher values produce more thorough responses but cost more tokens.
229
+
230
+ ### Claude Reasoning Effort
231
+
232
+ - **Valid values**: `"low"`, `"medium"`, `"high"` (default), `"max"`
233
+ - **`"max"`** is only available on Opus 4.5+
234
+ - Supported on Opus 4.5+ and Sonnet 4.6+. Haiku does not support reasoning effort.
235
+ - Passed as the `--effort` flag to Claude CLI.
236
+
237
+ ### Codex Reasoning Effort
238
+
239
+ - **Valid values**: `"none"`, `"minimal"`, `"low"`, `"medium"` (default), `"high"`, `"xhigh"`
240
+ - Passed as `-c model_reasoning_effort="<level>"` to Codex CLI.
241
+
242
+ ### When to Adjust
243
+
244
+ - **Lower effort** (low/minimal): Simple tasks like renaming, formatting, or config changes. Saves cost and time.
245
+ - **Default effort** (medium/high): Good for most tasks. Balanced cost and quality.
246
+ - **Higher effort** (max/xhigh): Complex architectural decisions, subtle bugs, or security-sensitive code.
247
+
248
+ Reasoning effort is optional — omit it to use the harness's default.
249
+
250
+ ## Fast Mode
251
+
252
+ Fast mode enables faster output from Claude by routing requests through a higher-priority serving path. It uses the same model but delivers responses roughly 2.5x faster at a higher per-token cost.
253
+
254
+ - **Claude only** — Codex does not support fast mode. RAF warns and ignores `fast: true` on Codex entries.
255
+ - **Default**: `false`/omitted (standard speed).
256
+ - Passed as `--settings '{"fastMode": true}'` to Claude CLI.
257
+ - Useful for interactive planning sessions where rapid iteration matters. For batch execution where cost efficiency is the priority, standard mode is recommended.
258
+
259
+ Example — fast planning, standard execution:
260
+ ```json
261
+ {
262
+ "models": {
263
+ "plan": { "model": "opus", "harness": "claude", "fast": true },
264
+ "execute": { "model": "opus", "harness": "claude" }
265
+ }
266
+ }
267
+ ```
268
+
156
269
  ## Validation Rules
157
270
 
158
271
  The config is validated when loaded. Invalid configs cause an error with a descriptive message. The following rules are enforced:
159
272
 
160
273
  - **Unknown keys are rejected** at every nesting level. Typos like `"model"` instead of `"models"` will be caught.
161
- - **Model values** (`models.*`, `effortMapping.*`) must be a short alias (`"sonnet"`, `"haiku"`, `"opus"`) or a full model ID (e.g., `"claude-sonnet-4-5-20250929"`, `"o3"`).
274
+ - **Removed legacy keys** (`provider`, `codexModels`, `codexEffortMapping`) are rejected with helpful migration messages.
275
+ - **Model entries** (`models.*`, `effortMapping.*`) must be `ModelEntry` objects with required `model` and `harness` fields. Plain strings (e.g., `"sonnet"`) are not accepted — use `{ "model": "sonnet", "harness": "claude" }` instead.
162
276
  - **`effortMapping` keys** must be `"low"`, `"medium"`, or `"high"`.
163
277
  - **`timeout`** must be a positive finite number.
164
278
  - **`maxRetries`** must be a non-negative integer.
@@ -167,14 +281,11 @@ The config is validated when loaded. Invalid configs cause an error with a descr
167
281
  - **`display` values** (`showCacheTokens`) must be booleans.
168
282
  - The config file must be valid JSON containing an object (not an array or primitive).
169
283
 
170
- ## CLI Precedence
171
-
172
- CLI flags always override config values. For example:
284
+ ## Precedence
173
285
 
174
- - `raf do --model haiku` uses Haiku regardless of `models.execute` in config
175
- - `raf plan --worktree` enables worktree mode regardless of the `worktree` config value
286
+ The harness for each model is set via the `harness` field in each `ModelEntry` in the config. There is no CLI flag to override harnesses at runtime.
176
287
 
177
- The precedence order is: **CLI flag > config file > default value**.
288
+ The precedence order is: **config file > default value**.
178
289
 
179
290
  ## Example Configs
180
291
 
@@ -183,7 +294,7 @@ The precedence order is: **CLI flag > config file > default value**.
183
294
  ```json
184
295
  {
185
296
  "models": {
186
- "execute": "sonnet"
297
+ "execute": { "model": "sonnet", "harness": "claude" }
187
298
  }
188
299
  }
189
300
  ```
@@ -195,8 +306,8 @@ Uses Sonnet instead of Opus for task execution. Everything else stays at default
195
306
  ```json
196
307
  {
197
308
  "models": {
198
- "plan": "sonnet",
199
- "execute": "sonnet"
309
+ "plan": { "model": "sonnet", "harness": "claude" },
310
+ "execute": { "model": "sonnet", "harness": "claude" }
200
311
  },
201
312
  "worktree": true
202
313
  }
@@ -204,22 +315,39 @@ Uses Sonnet instead of Opus for task execution. Everything else stays at default
204
315
 
205
316
  Uses Sonnet for planning and caps task execution at Sonnet (tasks with `effort: high` will use Sonnet instead of Opus). Defaults to worktree mode.
206
317
 
318
+ ### Mixed Harnesses — Claude Planning, Codex Execution
319
+
320
+ ```json
321
+ {
322
+ "models": {
323
+ "plan": { "model": "opus", "harness": "claude" },
324
+ "execute": { "model": "gpt-5.4", "harness": "codex" }
325
+ },
326
+ "effortMapping": {
327
+ "low": { "model": "sonnet", "harness": "claude" },
328
+ "high": { "model": "gpt-5.4", "harness": "codex" }
329
+ }
330
+ }
331
+ ```
332
+
333
+ Uses Claude Opus for planning but Codex for execution. Low-effort tasks use Claude Sonnet, high-effort tasks use Codex.
334
+
207
335
  ### Full — All Settings Explicit
208
336
 
209
337
  ```json
210
338
  {
211
339
  "models": {
212
- "plan": "opus",
213
- "execute": "opus",
214
- "nameGeneration": "sonnet",
215
- "failureAnalysis": "haiku",
216
- "prGeneration": "sonnet",
217
- "config": "sonnet"
340
+ "plan": { "model": "opus", "harness": "claude" },
341
+ "execute": { "model": "opus", "harness": "claude" },
342
+ "nameGeneration": { "model": "sonnet", "harness": "claude" },
343
+ "failureAnalysis": { "model": "haiku", "harness": "claude" },
344
+ "prGeneration": { "model": "sonnet", "harness": "claude" },
345
+ "config": { "model": "sonnet", "harness": "claude" }
218
346
  },
219
347
  "effortMapping": {
220
- "low": "sonnet",
221
- "medium": "opus",
222
- "high": "opus"
348
+ "low": { "model": "sonnet", "harness": "claude" },
349
+ "medium": { "model": "opus", "harness": "claude" },
350
+ "high": { "model": "opus", "harness": "claude" }
223
351
  },
224
352
  "timeout": 60,
225
353
  "maxRetries": 3,
@@ -227,9 +355,9 @@ Uses Sonnet for planning and caps task execution at Sonnet (tasks with `effort:
227
355
  "worktree": false,
228
356
  "syncMainBranch": true,
229
357
  "commitFormat": {
230
- "task": "{prefix}[{projectId}:{taskId}] {description}",
231
- "plan": "{prefix}[{projectId}] Plan: {projectName}",
232
- "amend": "{prefix}[{projectId}] Amend: {projectName}",
358
+ "task": "{prefix}[{projectName}:{taskId}] {description}",
359
+ "plan": "{prefix}[{projectName}] Plan: {description}",
360
+ "amend": "{prefix}[{projectName}] Amend: {description}",
233
361
  "prefix": "RAF"
234
362
  },
235
363
  "display": {
@@ -245,8 +373,8 @@ This is equivalent to having no config file at all — all values match the defa
245
373
  ```json
246
374
  {
247
375
  "models": {
248
- "plan": "claude-opus-4-5-20251101",
249
- "execute": "claude-sonnet-4-5-20250929"
376
+ "plan": { "model": "claude-opus-4-5-20251101", "harness": "claude" },
377
+ "execute": { "model": "claude-sonnet-4-5-20250929", "harness": "claude" }
250
378
  }
251
379
  }
252
380
  ```
@@ -263,23 +391,25 @@ Uses specific model versions for planning and execution. Useful for pinning to a
263
391
  }
264
392
  ```
265
393
 
266
- Commits will read `ACME[abcdef:01] Add login page` instead of `RAF[abcdef:01] Add login page`.
394
+ Commits will read `ACME[my-project:1] Add login page` instead of `RAF[my-project:1] Add login page`.
267
395
 
268
396
  ## Resetting to Defaults
269
397
 
270
- To reset all settings to defaults, delete the config file:
398
+ To reset all settings to defaults, run:
271
399
 
272
400
  ```bash
273
- rm ~/.raf/raf.config.json
401
+ raf config reset
274
402
  ```
275
403
 
276
- To reset a single setting, remove its key from the config file. Any key not present in the file will use its default value.
404
+ This deletes `~/.raf/raf.config.json` after confirmation.
405
+
406
+ To reset a single setting, remove its key from the config file or set it back to the default with `raf config set <key> <value>`. Any key not present in the file will use its default value.
277
407
 
278
408
  ---
279
409
 
280
410
  ## Config Editing Session Instructions
281
411
 
282
- This section contains instructions for the LLM when operating as the interactive config editor during `raf config` sessions.
412
+ This section contains instructions for the LLM when operating as the interactive config editor during `raf config wizard` sessions.
283
413
 
284
414
  ### Your Role
285
415
 
@@ -303,7 +433,7 @@ You are helping the user view and edit their RAF configuration. Be helpful, expl
303
433
 
304
434
  After making a change, briefly confirm what was changed and what the effective value is. For example:
305
435
 
306
- > Set `models.execute` to `"sonnet"`. Task execution will now use the Sonnet model instead of Opus.
436
+ > Set `models.execute` to `{ "model": "sonnet", "harness": "claude" }`. Task execution will now use the Sonnet model instead of Opus.
307
437
 
308
438
  ### Showing Current Config
309
439
 
@@ -313,10 +443,24 @@ When the user asks to see their config, show:
313
443
 
314
444
  Distinguish between user-set values and defaults so the user knows what they've customized.
315
445
 
446
+ ### Validating Model Names
447
+
448
+ When the user specifies a model name, check it against the "Valid Model Names" section above:
449
+
450
+ 1. **Known alias or full ID** — Accept it and proceed.
451
+ 2. **Unknown model name** — Warn the user that the name isn't in the known list. Suggest they double-check the name. If you have web search capabilities (WebSearch tool), offer to search for the model name to verify it exists. If web search is not available, tell the user to verify the name themselves before saving.
452
+ 3. **Common mistakes** — Watch for typos like `"claude-sonnet"` (missing version), `"gpt5.4"` (missing hyphen), or `"Opus"` (capitalized). Suggest the correct form.
453
+
454
+ When configuring reasoning effort, validate that the value is appropriate for the harness:
455
+ - Claude: `"low"`, `"medium"`, `"high"`, `"max"`
456
+ - Codex: `"none"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`
457
+
458
+ If the user sets reasoning effort on a model that may not support it (e.g., Haiku), warn them.
459
+
316
460
  ### Common User Requests
317
461
 
318
462
  - **"Show my config"** — Read and display the config file, noting defaults
319
- - **"Use sonnet for everything"** — Set all `models.*` keys to `"sonnet"`
463
+ - **"Use sonnet for everything"** — Set all `models.*` entries to `{ "model": "sonnet", "harness": "claude" }`
320
464
  - **"Reset to defaults"** — Delete the config file (confirm with user first)
321
465
  - **"What does X do?"** — Explain the setting using the reference above
322
466
  - **"Set timeout to 90"** — Update `timeout` to `90` in the config file
@@ -1,4 +1,5 @@
1
1
  import { getCommitFormat, getCommitPrefix, renderCommitMessage } from '../utils/config.js';
2
+ import { extractProjectName } from '../utils/paths.js';
2
3
 
3
4
  /**
4
5
  * Maximum characters for a dependency outcome summary.
@@ -91,9 +92,11 @@ ${previousOutcomes.map((o) => `### Task ${o.taskId}\n${o.content}`).join('\n\n')
91
92
  // Build example commit message from config template
92
93
  const commitTemplate = getCommitFormat('task');
93
94
  const commitPrefix = getCommitPrefix();
95
+ const projectName = extractProjectName(projectPath) ?? projectNumber;
94
96
  const exampleCommit = renderCommitMessage(commitTemplate, {
95
97
  prefix: commitPrefix,
96
- projectId: projectNumber,
98
+ projectId: projectName, // backwards compat: {projectId} resolves to projectName
99
+ projectName,
97
100
  taskId: paddedTaskNumber,
98
101
  description: '<description>',
99
102
  });
@@ -168,20 +171,19 @@ ${depOutcomesFormatted}
168
171
  2. Execute the task according to the plan
169
172
  3. Verify all acceptance criteria are met
170
173
  4. Signal completion with the appropriate marker
171
-
172
- ## Instructions
173
174
  ${retryContextSection}
175
+ ## Instructions
176
+
174
177
  ### Step 1: Read the Plan
175
178
 
176
- First, read the plan file to understand exactly what needs to be done.
179
+ Read the plan file to understand exactly what needs to be done.
177
180
 
178
181
  ### Step 2: Execute the Task
179
182
 
180
- Follow the implementation steps in the plan. Key guidelines:
181
- - Write clean, maintainable code
182
- - Follow existing code patterns in the project
183
- - Add appropriate error handling
183
+ Follow the implementation steps in the plan:
184
+ - Write clean, maintainable code following existing patterns
184
185
  - Follow any CLAUDE.md instructions
186
+ - If you encounter blockers, try to resolve them before giving up
185
187
  ${dependencyContextSection}${outcomesSection}
186
188
  ### Step 3: Verify Completion
187
189
 
@@ -192,47 +194,28 @@ Before marking the task complete:
192
194
  ${commitInstructions}
193
195
  ### Step 4: Write Outcome File
194
196
 
195
- **CRITICAL**: You MUST write an outcome file to document what was accomplished.
196
-
197
197
  **Outcome file path**: \`${outcomeFilePath}\`
198
198
 
199
- The outcome file should contain:
199
+ The outcome file must contain:
200
200
  1. A summary of what was done
201
201
  2. Key changes made (files modified, features added, etc.)
202
202
  3. Any important notes or follow-up items
203
- 4. The completion marker as the LAST line
203
+ 4. The completion marker as the LAST line (exactly one marker per file)
204
204
 
205
- **For code tasks**: Summarize what was changed and why
206
- **For documentation/report tasks**: The outcome IS the deliverable - include the full content
205
+ **For documentation/report tasks**: The outcome IS the deliverable — include the full content.
207
206
 
208
- **CRITICAL**: The outcome file MUST end with one of these markers:
207
+ The outcome file MUST end with one of these markers:
209
208
 
210
- If the task was completed successfully, end the file with:
209
+ On success:
211
210
  \`\`\`
212
211
  <promise>COMPLETE</promise>
213
212
  \`\`\`
214
213
 
215
- If the task failed and cannot be completed, end the file with:
214
+ On failure (do NOT commit just write the outcome and stop):
216
215
  \`\`\`
217
216
  <promise>FAILED</promise>
218
217
  Reason: [explain why the task failed]
219
218
  \`\`\`
220
219
 
221
- ## Important Rules
222
-
223
- 1. ALWAYS read the plan file first
224
- 2. Follow the plan precisely
225
- 3. Do not skip any acceptance criteria
226
- 4. If you encounter blockers, try to resolve them
227
- 5. The outcome file MUST contain EXACTLY ONE completion marker
228
- 6. The completion marker MUST be the LAST line in the outcome file
229
- 7. On SUCCESS: Commit code changes AND outcome file together BEFORE you finish
230
- 8. On FAILURE: Do NOT commit - just write the outcome file with FAILED marker
231
-
232
- ## Error Handling
233
-
234
- If you encounter errors:
235
- - Try to fix them yourself first
236
- - If an error prevents completion, write the outcome file with FAILED status and a clear reason
237
- - Do not mark COMPLETE if there are failing tests or unmet criteria`;
220
+ Do not mark COMPLETE if there are failing tests or unmet criteria.`;
238
221
  }