rafcode 2.1.1 → 2.3.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 (135) hide show
  1. package/.claude/settings.local.json +4 -1
  2. package/CLAUDE.md +59 -11
  3. package/RAF/ahslfe-config-wizard/decisions.md +34 -0
  4. package/RAF/ahslfe-config-wizard/input.md +1 -0
  5. package/RAF/ahslfe-config-wizard/outcomes/01-define-config-schema.md +38 -0
  6. package/RAF/ahslfe-config-wizard/outcomes/02-refactor-codebase-to-use-config.md +67 -0
  7. package/RAF/ahslfe-config-wizard/outcomes/03-create-config-documentation.md +37 -0
  8. package/RAF/ahslfe-config-wizard/outcomes/04-implement-raf-config-command.md +47 -0
  9. package/RAF/ahslfe-config-wizard/outcomes/05-update-claude-md.md +26 -0
  10. package/RAF/ahslfe-config-wizard/plans/01-define-config-schema.md +73 -0
  11. package/RAF/ahslfe-config-wizard/plans/02-refactor-codebase-to-use-config.md +74 -0
  12. package/RAF/ahslfe-config-wizard/plans/03-create-config-documentation.md +57 -0
  13. package/RAF/ahslfe-config-wizard/plans/04-implement-raf-config-command.md +66 -0
  14. package/RAF/ahslfe-config-wizard/plans/05-update-claude-md.md +60 -0
  15. package/RAF/ahstvo-token-tracker/decisions.md +44 -0
  16. package/RAF/ahstvo-token-tracker/input.md +3 -0
  17. package/RAF/ahstvo-token-tracker/outcomes/01-full-model-id-support.md +43 -0
  18. package/RAF/ahstvo-token-tracker/outcomes/02-name-generation-no-session.md +33 -0
  19. package/RAF/ahstvo-token-tracker/outcomes/03-unify-stream-json-execution.md +48 -0
  20. package/RAF/ahstvo-token-tracker/outcomes/04-token-tracking-cost-calculation.md +53 -0
  21. package/RAF/ahstvo-token-tracker/outcomes/05-token-cost-console-reporting.md +57 -0
  22. package/RAF/ahstvo-token-tracker/outcomes/06-runtime-verbose-toggle.md +53 -0
  23. package/RAF/ahstvo-token-tracker/outcomes/07-readme-config-docs.md +36 -0
  24. package/RAF/ahstvo-token-tracker/plans/01-full-model-id-support.md +35 -0
  25. package/RAF/ahstvo-token-tracker/plans/02-name-generation-no-session.md +36 -0
  26. package/RAF/ahstvo-token-tracker/plans/03-unify-stream-json-execution.md +44 -0
  27. package/RAF/ahstvo-token-tracker/plans/04-token-tracking-cost-calculation.md +56 -0
  28. package/RAF/ahstvo-token-tracker/plans/05-token-cost-console-reporting.md +55 -0
  29. package/RAF/ahstvo-token-tracker/plans/06-runtime-verbose-toggle.md +48 -0
  30. package/RAF/ahstvo-token-tracker/plans/07-readme-config-docs.md +44 -0
  31. package/RAF/ahtahs-token-reaper/decisions.md +37 -0
  32. package/RAF/ahtahs-token-reaper/input.md +20 -0
  33. package/RAF/ahtahs-token-reaper/outcomes/01-extend-token-tracker-data-model.md +42 -0
  34. package/RAF/ahtahs-token-reaper/outcomes/02-accumulate-usage-in-retry-loop.md +31 -0
  35. package/RAF/ahtahs-token-reaper/outcomes/03-per-attempt-display-formatting.md +60 -0
  36. package/RAF/ahtahs-token-reaper/outcomes/04-add-model-name-to-claude-call-logs.md +57 -0
  37. package/RAF/ahtahs-token-reaper/outcomes/05-handle-invalid-config-in-raf-config.md +46 -0
  38. package/RAF/ahtahs-token-reaper/outcomes/06-fix-verbose-toggle-timer-display.md +38 -0
  39. package/RAF/ahtahs-token-reaper/plans/01-extend-token-tracker-data-model.md +36 -0
  40. package/RAF/ahtahs-token-reaper/plans/02-accumulate-usage-in-retry-loop.md +36 -0
  41. package/RAF/ahtahs-token-reaper/plans/03-per-attempt-display-formatting.md +43 -0
  42. package/RAF/ahtahs-token-reaper/plans/04-add-model-name-to-claude-call-logs.md +38 -0
  43. package/RAF/ahtahs-token-reaper/plans/05-handle-invalid-config-in-raf-config.md +36 -0
  44. package/RAF/ahtahs-token-reaper/plans/06-fix-verbose-toggle-timer-display.md +40 -0
  45. package/README.md +34 -0
  46. package/dist/commands/config.d.ts +3 -0
  47. package/dist/commands/config.d.ts.map +1 -0
  48. package/dist/commands/config.js +195 -0
  49. package/dist/commands/config.js.map +1 -0
  50. package/dist/commands/do.d.ts.map +1 -1
  51. package/dist/commands/do.js +55 -7
  52. package/dist/commands/do.js.map +1 -1
  53. package/dist/commands/plan.d.ts.map +1 -1
  54. package/dist/commands/plan.js +5 -3
  55. package/dist/commands/plan.js.map +1 -1
  56. package/dist/core/claude-runner.d.ts +19 -2
  57. package/dist/core/claude-runner.d.ts.map +1 -1
  58. package/dist/core/claude-runner.js +43 -96
  59. package/dist/core/claude-runner.js.map +1 -1
  60. package/dist/core/failure-analyzer.d.ts.map +1 -1
  61. package/dist/core/failure-analyzer.js +6 -3
  62. package/dist/core/failure-analyzer.js.map +1 -1
  63. package/dist/core/git.d.ts.map +1 -1
  64. package/dist/core/git.js +10 -3
  65. package/dist/core/git.js.map +1 -1
  66. package/dist/core/pull-request.d.ts +1 -1
  67. package/dist/core/pull-request.d.ts.map +1 -1
  68. package/dist/core/pull-request.js +9 -4
  69. package/dist/core/pull-request.js.map +1 -1
  70. package/dist/index.js +2 -0
  71. package/dist/index.js.map +1 -1
  72. package/dist/parsers/stream-renderer.d.ts +16 -1
  73. package/dist/parsers/stream-renderer.d.ts.map +1 -1
  74. package/dist/parsers/stream-renderer.js +34 -4
  75. package/dist/parsers/stream-renderer.js.map +1 -1
  76. package/dist/prompts/execution.d.ts.map +1 -1
  77. package/dist/prompts/execution.js +11 -1
  78. package/dist/prompts/execution.js.map +1 -1
  79. package/dist/types/config.d.ts +95 -4
  80. package/dist/types/config.d.ts.map +1 -1
  81. package/dist/types/config.js +63 -3
  82. package/dist/types/config.js.map +1 -1
  83. package/dist/utils/config.d.ts +65 -7
  84. package/dist/utils/config.d.ts.map +1 -1
  85. package/dist/utils/config.js +297 -21
  86. package/dist/utils/config.js.map +1 -1
  87. package/dist/utils/name-generator.d.ts +3 -7
  88. package/dist/utils/name-generator.d.ts.map +1 -1
  89. package/dist/utils/name-generator.js +75 -61
  90. package/dist/utils/name-generator.js.map +1 -1
  91. package/dist/utils/terminal-symbols.d.ts +25 -0
  92. package/dist/utils/terminal-symbols.d.ts.map +1 -1
  93. package/dist/utils/terminal-symbols.js +87 -0
  94. package/dist/utils/terminal-symbols.js.map +1 -1
  95. package/dist/utils/token-tracker.d.ts +55 -0
  96. package/dist/utils/token-tracker.d.ts.map +1 -0
  97. package/dist/utils/token-tracker.js +142 -0
  98. package/dist/utils/token-tracker.js.map +1 -0
  99. package/dist/utils/validation.d.ts +5 -5
  100. package/dist/utils/validation.d.ts.map +1 -1
  101. package/dist/utils/validation.js +10 -6
  102. package/dist/utils/validation.js.map +1 -1
  103. package/dist/utils/verbose-toggle.d.ts +33 -0
  104. package/dist/utils/verbose-toggle.d.ts.map +1 -0
  105. package/dist/utils/verbose-toggle.js +94 -0
  106. package/dist/utils/verbose-toggle.js.map +1 -0
  107. package/package.json +1 -1
  108. package/src/commands/config.ts +230 -0
  109. package/src/commands/do.ts +64 -6
  110. package/src/commands/plan.ts +5 -3
  111. package/src/core/claude-runner.ts +59 -115
  112. package/src/core/failure-analyzer.ts +6 -3
  113. package/src/core/git.ts +10 -3
  114. package/src/core/pull-request.ts +9 -4
  115. package/src/index.ts +2 -0
  116. package/src/parsers/stream-renderer.ts +54 -4
  117. package/src/prompts/config-docs.md +331 -0
  118. package/src/prompts/execution.ts +13 -1
  119. package/src/types/config.ts +156 -7
  120. package/src/utils/config.ts +357 -21
  121. package/src/utils/name-generator.ts +84 -71
  122. package/src/utils/terminal-symbols.ts +103 -0
  123. package/src/utils/token-tracker.ts +177 -0
  124. package/src/utils/validation.ts +15 -10
  125. package/src/utils/verbose-toggle.ts +103 -0
  126. package/tests/unit/claude-runner.test.ts +171 -7
  127. package/tests/unit/config-command.test.ts +242 -0
  128. package/tests/unit/config.test.ts +632 -30
  129. package/tests/unit/name-generator.test.ts +99 -75
  130. package/tests/unit/pull-request.test.ts +2 -0
  131. package/tests/unit/stream-renderer.test.ts +83 -0
  132. package/tests/unit/terminal-symbols.test.ts +245 -0
  133. package/tests/unit/timer-verbose-integration.test.ts +170 -0
  134. package/tests/unit/token-tracker.test.ts +685 -0
  135. package/tests/unit/verbose-toggle.test.ts +204 -0
@@ -0,0 +1,331 @@
1
+ # RAF Configuration Reference
2
+
3
+ ## Overview
4
+
5
+ RAF uses a JSON configuration file at `~/.raf/raf.config.json` to control its behavior. All keys are optional — only set what you want to change. Unset keys use sensible defaults.
6
+
7
+ The config is loaded once per process and cached. Changes take effect on the next RAF command invocation.
8
+
9
+ ## File Format
10
+
11
+ The config file is a JSON object. All keys are optional at every level. User values are deep-merged with defaults: you can override a single nested key without specifying the entire object.
12
+
13
+ ```json
14
+ {
15
+ "models": {
16
+ "plan": "opus"
17
+ }
18
+ }
19
+ ```
20
+
21
+ The above only changes `models.plan` — all other model settings keep their defaults.
22
+
23
+ ## Config Reference
24
+
25
+ ### `models` — Claude Model Selection
26
+
27
+ Controls which Claude model is used for each scenario. Values can be a short alias (`"sonnet"`, `"haiku"`, `"opus"`) or a full model ID.
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
34
+
35
+ **Short aliases**: Using aliases (`"opus"`, `"sonnet"`, `"haiku"`) automatically selects the latest version of that model family.
36
+
37
+ | Key | Default | Description |
38
+ |-----|---------|-------------|
39
+ | `models.plan` | `"opus"` | Model used for planning sessions (`raf plan`) |
40
+ | `models.execute` | `"opus"` | Model used for task execution (`raf do`) |
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
+
46
+ ### `effort` — Claude Effort Level
47
+
48
+ Controls the effort level passed to Claude for each scenario. All values must be one of: `"low"`, `"medium"`, `"high"`.
49
+
50
+ | Key | Default | Description |
51
+ |-----|---------|-------------|
52
+ | `effort.plan` | `"high"` | Effort level for planning sessions |
53
+ | `effort.execute` | `"medium"` | Effort level for task execution |
54
+ | `effort.nameGeneration` | `"low"` | Effort level for project name generation |
55
+ | `effort.failureAnalysis` | `"low"` | Effort level for failure analysis |
56
+ | `effort.prGeneration` | `"medium"` | Effort level for PR generation |
57
+ | `effort.config` | `"medium"` | Effort level for config editing sessions |
58
+
59
+ ### `timeout` — Task Timeout
60
+
61
+ - **Type**: number (positive)
62
+ - **Default**: `60`
63
+ - **Description**: Timeout in minutes for each task execution. Must be a positive number.
64
+
65
+ ### `maxRetries` — Maximum Retry Attempts
66
+
67
+ - **Type**: number (non-negative integer)
68
+ - **Default**: `3`
69
+ - **Description**: How many times RAF retries a failed task before giving up. Must be a non-negative integer (0 disables retries).
70
+
71
+ ### `autoCommit` — Automatic Git Commits
72
+
73
+ - **Type**: boolean
74
+ - **Default**: `true`
75
+ - **Description**: When `true`, Claude automatically commits changes after completing each task. When `false`, changes are left uncommitted.
76
+
77
+ ### `worktree` — Default Worktree Mode
78
+
79
+ - **Type**: boolean
80
+ - **Default**: `false`
81
+ - **Description**: When `true`, `raf plan` and `raf do` default to worktree mode (isolated git worktree). Can be overridden per-command with `--worktree` flag.
82
+
83
+ ### `commitFormat` — Commit Message Templates
84
+
85
+ Controls the format of git commit messages. Templates use `{placeholder}` syntax for variable substitution.
86
+
87
+ | Key | Default | Description |
88
+ |-----|---------|-------------|
89
+ | `commitFormat.task` | `"{prefix}[{projectId}:{taskId}] {description}"` | Format for task completion commits |
90
+ | `commitFormat.plan` | `"{prefix}[{projectId}] Plan: {projectName}"` | Format for plan creation commits |
91
+ | `commitFormat.amend` | `"{prefix}[{projectId}] Amend: {projectName}"` | Format for plan amendment commits |
92
+ | `commitFormat.prefix` | `"RAF"` | Prefix string substituted into `{prefix}` placeholder |
93
+
94
+ #### Template Variables
95
+
96
+ **Task commits** (`commitFormat.task`):
97
+ - `{prefix}` — The value of `commitFormat.prefix`
98
+ - `{projectId}` — The 6-character project identifier (e.g., `abcdef`)
99
+ - `{taskId}` — The 2-character task identifier (e.g., `01`, `0a`)
100
+ - `{description}` — A concise description of what was accomplished
101
+
102
+ **Plan commits** (`commitFormat.plan`):
103
+ - `{prefix}` — The value of `commitFormat.prefix`
104
+ - `{projectId}` — The 6-character project identifier
105
+ - `{projectName}` — The human-readable project name (e.g., `fix-auth-bug`)
106
+
107
+ **Amend commits** (`commitFormat.amend`):
108
+ - `{prefix}` — The value of `commitFormat.prefix`
109
+ - `{projectId}` — The 6-character project identifier
110
+ - `{projectName}` — The human-readable project name
111
+
112
+ Unknown placeholders are left as-is in the output.
113
+
114
+ ### `pricing` — Token Cost Pricing
115
+
116
+ Controls per-model token pricing used for cost estimation. Prices are in dollars per million tokens. Each model category (`opus`, `sonnet`, `haiku`) has four pricing fields:
117
+
118
+ | Field | Description |
119
+ |-------|-------------|
120
+ | `inputPerMTok` | Cost per million input tokens |
121
+ | `outputPerMTok` | Cost per million output tokens |
122
+ | `cacheReadPerMTok` | Cost per million cache read tokens (discounted) |
123
+ | `cacheCreatePerMTok` | Cost per million cache creation tokens |
124
+
125
+ **Default values:**
126
+
127
+ | Category | Input | Output | Cache Read | Cache Create |
128
+ |----------|-------|--------|------------|--------------|
129
+ | `opus` | $15 | $75 | $1.50 | $18.75 |
130
+ | `sonnet` | $3 | $15 | $0.30 | $3.75 |
131
+ | `haiku` | $1 | $5 | $0.10 | $1.25 |
132
+
133
+ Full model IDs from CLI output (e.g., `claude-opus-4-6`) are automatically mapped to the corresponding pricing category based on the model family name.
134
+
135
+ Example override:
136
+
137
+ ```json
138
+ {
139
+ "pricing": {
140
+ "opus": {
141
+ "inputPerMTok": 10,
142
+ "outputPerMTok": 50
143
+ }
144
+ }
145
+ }
146
+ ```
147
+
148
+ Only specify the fields you want to change — unset fields keep their defaults.
149
+
150
+ ### `claudeCommand` — Claude CLI Path
151
+
152
+ - **Type**: string (non-empty)
153
+ - **Default**: `"claude"`
154
+ - **Description**: The command or path used to invoke the Claude CLI. Change this if `claude` is not on your PATH or you want to use a wrapper script.
155
+
156
+ ## Validation Rules
157
+
158
+ The config is validated when loaded. Invalid configs cause an error with a descriptive message. The following rules are enforced:
159
+
160
+ - **Unknown keys are rejected** at every nesting level. Typos like `"model"` instead of `"models"` will be caught.
161
+ - **Model values** must be a short alias (`"sonnet"`, `"haiku"`, `"opus"`) or a full model ID matching the pattern `claude-{family}-{version}` (e.g., `"claude-sonnet-4-5-20250929"`).
162
+ - **Effort values** must be exactly `"low"`, `"medium"`, or `"high"` (case-sensitive).
163
+ - **`timeout`** must be a positive finite number.
164
+ - **`maxRetries`** must be a non-negative integer.
165
+ - **`autoCommit`** and **`worktree`** must be booleans.
166
+ - **`commitFormat` values** must be strings.
167
+ - **`claudeCommand`** must be a non-empty string.
168
+ - **`pricing`** categories must be `"opus"`, `"sonnet"`, or `"haiku"`. Each field must be a non-negative number.
169
+ - The config file must be valid JSON containing an object (not an array or primitive).
170
+
171
+ ## CLI Precedence
172
+
173
+ CLI flags always override config values. For example:
174
+
175
+ - `raf do --model haiku` uses Haiku regardless of `models.execute` in config
176
+ - `raf plan --worktree` enables worktree mode regardless of the `worktree` config value
177
+
178
+ The precedence order is: **CLI flag > config file > default value**.
179
+
180
+ ## Example Configs
181
+
182
+ ### Minimal — Just Change the Default Model
183
+
184
+ ```json
185
+ {
186
+ "models": {
187
+ "execute": "sonnet"
188
+ }
189
+ }
190
+ ```
191
+
192
+ Uses Sonnet instead of Opus for task execution. Everything else stays at defaults.
193
+
194
+ ### Common — Cost-Conscious Setup
195
+
196
+ ```json
197
+ {
198
+ "models": {
199
+ "plan": "sonnet",
200
+ "execute": "sonnet"
201
+ },
202
+ "effort": {
203
+ "plan": "medium"
204
+ },
205
+ "worktree": true
206
+ }
207
+ ```
208
+
209
+ Uses Sonnet for both planning and execution, reduces planning effort, and defaults to worktree mode.
210
+
211
+ ### Full — All Settings Explicit
212
+
213
+ ```json
214
+ {
215
+ "models": {
216
+ "plan": "opus",
217
+ "execute": "opus",
218
+ "nameGeneration": "sonnet",
219
+ "failureAnalysis": "haiku",
220
+ "prGeneration": "sonnet",
221
+ "config": "sonnet"
222
+ },
223
+ "effort": {
224
+ "plan": "high",
225
+ "execute": "medium",
226
+ "nameGeneration": "low",
227
+ "failureAnalysis": "low",
228
+ "prGeneration": "medium",
229
+ "config": "medium"
230
+ },
231
+ "timeout": 60,
232
+ "maxRetries": 3,
233
+ "autoCommit": true,
234
+ "worktree": false,
235
+ "commitFormat": {
236
+ "task": "{prefix}[{projectId}:{taskId}] {description}",
237
+ "plan": "{prefix}[{projectId}] Plan: {projectName}",
238
+ "amend": "{prefix}[{projectId}] Amend: {projectName}",
239
+ "prefix": "RAF"
240
+ },
241
+ "claudeCommand": "claude",
242
+ "pricing": {
243
+ "opus": { "inputPerMTok": 15, "outputPerMTok": 75, "cacheReadPerMTok": 1.5, "cacheCreatePerMTok": 18.75 },
244
+ "sonnet": { "inputPerMTok": 3, "outputPerMTok": 15, "cacheReadPerMTok": 0.3, "cacheCreatePerMTok": 3.75 },
245
+ "haiku": { "inputPerMTok": 1, "outputPerMTok": 5, "cacheReadPerMTok": 0.1, "cacheCreatePerMTok": 1.25 }
246
+ }
247
+ }
248
+ ```
249
+
250
+ This is equivalent to having no config file at all — all values match the defaults.
251
+
252
+ ### Pinned Model Versions
253
+
254
+ ```json
255
+ {
256
+ "models": {
257
+ "plan": "claude-opus-4-5-20251101",
258
+ "execute": "claude-sonnet-4-5-20250929"
259
+ }
260
+ }
261
+ ```
262
+
263
+ Uses specific model versions for planning and execution. Useful for pinning to a known-good model version.
264
+
265
+ ### Team Branding — Custom Commit Prefix
266
+
267
+ ```json
268
+ {
269
+ "commitFormat": {
270
+ "prefix": "ACME"
271
+ }
272
+ }
273
+ ```
274
+
275
+ Commits will read `ACME[abcdef:01] Add login page` instead of `RAF[abcdef:01] Add login page`.
276
+
277
+ ## Resetting to Defaults
278
+
279
+ To reset all settings to defaults, delete the config file:
280
+
281
+ ```bash
282
+ rm ~/.raf/raf.config.json
283
+ ```
284
+
285
+ To reset a single setting, remove its key from the config file. Any key not present in the file will use its default value.
286
+
287
+ ---
288
+
289
+ ## For Claude — Config Editing Session Instructions
290
+
291
+ This section contains instructions for Claude when operating as the interactive config editor during `raf config` sessions.
292
+
293
+ ### Your Role
294
+
295
+ You are helping the user view and edit their RAF configuration. Be helpful, explain what each setting does when asked, and make changes accurately.
296
+
297
+ ### Reading the Config
298
+
299
+ 1. Read the current config file at `~/.raf/raf.config.json`
300
+ 2. If the file does not exist, tell the user they have no custom config and all defaults are active
301
+ 3. Show the user their current settings when asked, noting which are custom vs. default
302
+
303
+ ### Making Changes
304
+
305
+ 1. **Only change what the user asks for.** Never modify keys the user didn't mention.
306
+ 2. **Write partial configs.** Only include keys that differ from defaults. If the user sets a value back to its default, remove that key.
307
+ 3. **Validate before saving.** Ensure all values conform to the validation rules above before writing the file.
308
+ 4. **Create the directory if needed.** If `~/.raf/` doesn't exist, create it before writing the file.
309
+ 5. **Preserve existing keys.** Read the current file first, merge the user's changes, then write the result.
310
+
311
+ ### Explaining Changes
312
+
313
+ After making a change, briefly confirm what was changed and what the effective value is. For example:
314
+
315
+ > Set `models.execute` to `"sonnet"`. Task execution will now use the Sonnet model instead of Opus.
316
+
317
+ ### Showing Current Config
318
+
319
+ When the user asks to see their config, show:
320
+ 1. Their custom settings (from the config file)
321
+ 2. The effective resolved config (custom + defaults merged)
322
+
323
+ Distinguish between user-set values and defaults so the user knows what they've customized.
324
+
325
+ ### Common User Requests
326
+
327
+ - **"Show my config"** — Read and display the config file, noting defaults
328
+ - **"Use sonnet for everything"** — Set all `models.*` keys to `"sonnet"`
329
+ - **"Reset to defaults"** — Delete the config file (confirm with user first)
330
+ - **"What does X do?"** — Explain the setting using the reference above
331
+ - **"Set timeout to 90"** — Update `timeout` to `90` in the config file
@@ -1,3 +1,5 @@
1
+ import { getCommitFormat, getCommitPrefix, renderCommitMessage } from '../utils/config.js';
2
+
1
3
  /**
2
4
  * Maximum characters for a dependency outcome summary.
3
5
  * Outcomes larger than this will be truncated to avoid context bloat.
@@ -86,6 +88,16 @@ ${previousOutcomes.map((o) => `### Task ${o.taskId}\n${o.content}`).join('\n\n')
86
88
  // Encode task number to 2-char base36
87
89
  const paddedTaskNumber = taskNumber.toString(36).padStart(2, '0');
88
90
 
91
+ // Build example commit message from config template
92
+ const commitTemplate = getCommitFormat('task');
93
+ const commitPrefix = getCommitPrefix();
94
+ const exampleCommit = renderCommitMessage(commitTemplate, {
95
+ prefix: commitPrefix,
96
+ projectId: projectNumber,
97
+ taskId: paddedTaskNumber,
98
+ description: '<description>',
99
+ });
100
+
89
101
  const commitInstructions = autoCommit
90
102
  ? `
91
103
  ## Git Instructions
@@ -95,7 +107,7 @@ After successfully completing the task:
95
107
  - Add each code file you changed: \`git add <file1> <file2> ...\`
96
108
  - Add the outcome file: \`git add ${outcomeFilePath}\`
97
109
  - Add this task's plan file: \`git add ${planPath}\`
98
- 2. Commit with message: "RAF[${projectNumber}:${paddedTaskNumber}] <description>"
110
+ 2. Commit with message: "${exampleCommit}"
99
111
  - Write a concise description of what was accomplished
100
112
  - Focus on the actual change, not the task name
101
113
  - The commit message must be a SINGLE LINE — no body, no trailers
@@ -1,19 +1,149 @@
1
+ /** Short alias for a Claude model family */
2
+ export type ClaudeModelAlias = 'sonnet' | 'haiku' | 'opus';
3
+
4
+ /**
5
+ * Accepts short aliases (`sonnet`, `haiku`, `opus`) or full model IDs
6
+ * matching the pattern `claude-{family}-{version}` (e.g., `claude-opus-4-5-20251101`).
7
+ */
8
+ export type ClaudeModelName = ClaudeModelAlias | (string & { __brand?: 'FullModelId' });
9
+ export type EffortLevel = 'low' | 'medium' | 'high';
10
+
11
+ export type ModelScenario = 'plan' | 'execute' | 'nameGeneration' | 'failureAnalysis' | 'prGeneration' | 'config';
12
+ export type EffortScenario = ModelScenario;
13
+ export type CommitFormatType = 'task' | 'plan' | 'amend';
14
+
15
+ export interface ModelsConfig {
16
+ plan: ClaudeModelName;
17
+ execute: ClaudeModelName;
18
+ nameGeneration: ClaudeModelName;
19
+ failureAnalysis: ClaudeModelName;
20
+ prGeneration: ClaudeModelName;
21
+ config: ClaudeModelName;
22
+ }
23
+
24
+ export interface EffortConfig {
25
+ plan: EffortLevel;
26
+ execute: EffortLevel;
27
+ nameGeneration: EffortLevel;
28
+ failureAnalysis: EffortLevel;
29
+ prGeneration: EffortLevel;
30
+ config: EffortLevel;
31
+ }
32
+
33
+ export interface CommitFormatConfig {
34
+ task: string;
35
+ plan: string;
36
+ amend: string;
37
+ prefix: string;
38
+ }
39
+
40
+ /** Pricing category derived from model family name. */
41
+ export type PricingCategory = 'opus' | 'sonnet' | 'haiku';
42
+
43
+ /** Per-direction pricing for a single model category, in dollars per million tokens. */
44
+ export interface ModelPricing {
45
+ inputPerMTok: number;
46
+ outputPerMTok: number;
47
+ cacheReadPerMTok: number;
48
+ cacheCreatePerMTok: number;
49
+ }
50
+
51
+ /** Pricing config: per-category pricing in dollars per million tokens. */
52
+ export interface PricingConfig {
53
+ opus: ModelPricing;
54
+ sonnet: ModelPricing;
55
+ haiku: ModelPricing;
56
+ }
57
+
1
58
  export interface RafConfig {
2
- defaultTimeout: number;
3
- defaultMaxRetries: number;
59
+ models: ModelsConfig;
60
+ effort: EffortConfig;
61
+ timeout: number;
62
+ maxRetries: number;
4
63
  autoCommit: boolean;
64
+ worktree: boolean;
65
+ commitFormat: CommitFormatConfig;
5
66
  claudeCommand: string;
6
- editor?: string;
67
+ pricing: PricingConfig;
7
68
  }
8
69
 
9
- export const DEFAULT_RAF_CONFIG: RafConfig = {
10
- defaultTimeout: 60,
11
- defaultMaxRetries: 3,
70
+ export const DEFAULT_CONFIG: RafConfig = {
71
+ models: {
72
+ plan: 'opus',
73
+ execute: 'opus',
74
+ nameGeneration: 'sonnet',
75
+ failureAnalysis: 'haiku',
76
+ prGeneration: 'sonnet',
77
+ config: 'sonnet',
78
+ },
79
+ effort: {
80
+ plan: 'high',
81
+ execute: 'medium',
82
+ nameGeneration: 'low',
83
+ failureAnalysis: 'low',
84
+ prGeneration: 'medium',
85
+ config: 'medium',
86
+ },
87
+ timeout: 60,
88
+ maxRetries: 3,
12
89
  autoCommit: true,
90
+ worktree: false,
91
+ commitFormat: {
92
+ task: '{prefix}[{projectId}:{taskId}] {description}',
93
+ plan: '{prefix}[{projectId}] Plan: {projectName}',
94
+ amend: '{prefix}[{projectId}] Amend: {projectName}',
95
+ prefix: 'RAF',
96
+ },
13
97
  claudeCommand: 'claude',
98
+ pricing: {
99
+ opus: {
100
+ inputPerMTok: 15,
101
+ outputPerMTok: 75,
102
+ cacheReadPerMTok: 1.5,
103
+ cacheCreatePerMTok: 18.75,
104
+ },
105
+ sonnet: {
106
+ inputPerMTok: 3,
107
+ outputPerMTok: 15,
108
+ cacheReadPerMTok: 0.3,
109
+ cacheCreatePerMTok: 3.75,
110
+ },
111
+ haiku: {
112
+ inputPerMTok: 1,
113
+ outputPerMTok: 5,
114
+ cacheReadPerMTok: 0.1,
115
+ cacheCreatePerMTok: 1.25,
116
+ },
117
+ },
118
+ };
119
+
120
+ /** Deep partial type for user config files — all fields optional at every level */
121
+ export type DeepPartial<T> = {
122
+ [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
14
123
  };
15
124
 
16
- export type ClaudeModelName = 'sonnet' | 'haiku' | 'opus';
125
+ export type UserConfig = DeepPartial<RafConfig>;
126
+
127
+ export const VALID_MODEL_ALIASES: readonly ClaudeModelAlias[] = ['sonnet', 'haiku', 'opus'];
128
+
129
+ /**
130
+ * Regex for full Claude model IDs (e.g., `claude-sonnet-4-5-20250929`, `claude-opus-4-5-20251101`).
131
+ * Pattern: claude-{family}-{major}(-{minor})?(-{date})?
132
+ */
133
+ export const FULL_MODEL_ID_PATTERN = /^claude-[a-z]+-\d+(-\d+)*$/;
134
+
135
+ /** @deprecated Use VALID_MODEL_ALIASES instead */
136
+ export const VALID_MODELS = VALID_MODEL_ALIASES;
137
+ export const VALID_EFFORTS: readonly EffortLevel[] = ['low', 'medium', 'high'];
138
+
139
+ // Keep backward-compat exports used by other modules
140
+ /** @deprecated Use DEFAULT_CONFIG instead */
141
+ export const DEFAULT_RAF_CONFIG = {
142
+ defaultTimeout: DEFAULT_CONFIG.timeout,
143
+ defaultMaxRetries: DEFAULT_CONFIG.maxRetries,
144
+ autoCommit: DEFAULT_CONFIG.autoCommit,
145
+ claudeCommand: DEFAULT_CONFIG.claudeCommand,
146
+ };
17
147
 
18
148
  export interface PlanCommandOptions {
19
149
  projectName?: string;
@@ -39,3 +169,22 @@ export interface MigrateCommandOptions {
39
169
  dryRun?: boolean;
40
170
  worktree?: boolean;
41
171
  }
172
+
173
+ /** Per-model token usage breakdown from stream-json result event. */
174
+ export interface ModelTokenUsage {
175
+ inputTokens: number;
176
+ outputTokens: number;
177
+ cacheReadInputTokens: number;
178
+ cacheCreationInputTokens: number;
179
+ }
180
+
181
+ /** Token usage data extracted from Claude CLI stream-json result event. */
182
+ export interface UsageData {
183
+ /** Aggregate token counts across all models. */
184
+ inputTokens: number;
185
+ outputTokens: number;
186
+ cacheReadInputTokens: number;
187
+ cacheCreationInputTokens: number;
188
+ /** Per-model breakdown (e.g., { "claude-opus-4-6": { ... } }). */
189
+ modelUsage: Record<string, ModelTokenUsage>;
190
+ }