murmur8 4.2.0 → 4.3.1
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/.blueprint/agents/AGENT_SPECIFICATION_ALEX.md +33 -3
- package/.blueprint/features/feature_config-factory/FEATURE_SPEC.md +138 -0
- package/.blueprint/features/feature_config-factory/IMPLEMENTATION_PLAN.md +187 -0
- package/.blueprint/features/feature_config-factory/handoff-nigel.md +57 -0
- package/.blueprint/features/feature_cost-tracking/FEATURE_SPEC.md +216 -0
- package/.blueprint/features/feature_cost-tracking/IMPLEMENTATION_PLAN.md +50 -0
- package/.blueprint/features/feature_diff-preview/FEATURE_SPEC.md +182 -0
- package/.blueprint/features/feature_diff-preview/IMPLEMENTATION_PLAN.md +42 -0
- package/.blueprint/features/feature_extract-prompt-util/FEATURE_SPEC.md +42 -0
- package/.blueprint/features/feature_fix-status-icons/FEATURE_SPEC.md +37 -0
- package/.blueprint/features/feature_murm-subagent/FEATURE_SPEC.md +137 -0
- package/.blueprint/features/feature_murm-subagent/SKILL_CHANGES.md +345 -0
- package/.blueprint/features/feature_split-cli-commands/FEATURE_SPEC.md +125 -0
- package/.blueprint/features/feature_split-cli-commands/IMPLEMENTATION_PLAN.md +119 -0
- package/.blueprint/features/feature_split-cli-commands/handoff-nigel.md +45 -0
- package/.blueprint/features/feature_theme-adoption/FEATURE_SPEC.md +143 -0
- package/.blueprint/features/feature_theme-adoption/IMPLEMENTATION_PLAN.md +68 -0
- package/.blueprint/features/feature_theme-adoption/handoff-nigel.md +35 -0
- package/.blueprint/templates/BACKLOG_TEMPLATE.md +46 -0
- package/README.md +79 -12
- package/SKILL.md +377 -3
- package/bin/cli.js +20 -411
- package/package.json +1 -1
- package/src/commands/cost-config.js +28 -0
- package/src/commands/feedback-config.js +32 -0
- package/src/commands/help.js +86 -0
- package/src/commands/history.js +42 -0
- package/src/commands/init.js +12 -0
- package/src/commands/insights.js +23 -0
- package/src/commands/murm-config.js +52 -0
- package/src/commands/murm.js +109 -0
- package/src/commands/queue.js +19 -0
- package/src/commands/retry-config.js +28 -0
- package/src/commands/stack-config.js +32 -0
- package/src/commands/update.js +12 -0
- package/src/commands/utils.js +25 -0
- package/src/commands/validate.js +15 -0
- package/src/config-factory.js +190 -0
- package/src/cost.js +122 -0
- package/src/diff-preview.js +165 -0
- package/src/feedback.js +5 -2
- package/src/history.js +51 -3
- package/src/index.js +25 -0
- package/src/init.js +1 -15
- package/src/insights.js +19 -16
- package/src/retry.js +5 -2
- package/src/stack.js +4 -1
- package/src/theme.js +6 -5
- package/src/update.js +2 -15
- package/src/utils.js +26 -0
- package/src/validate.js +5 -12
|
@@ -8,6 +8,7 @@ inputs:
|
|
|
8
8
|
outputs:
|
|
9
9
|
- feature_spec
|
|
10
10
|
- system_spec
|
|
11
|
+
- feature_backlog
|
|
11
12
|
---
|
|
12
13
|
|
|
13
14
|
# Agent: Alex — System Specification & Chief-of-Staff
|
|
@@ -74,7 +75,36 @@ Once drafted, the feature specification is handed to **Cass** for user story ela
|
|
|
74
75
|
|
|
75
76
|
---
|
|
76
77
|
|
|
77
|
-
### 3.
|
|
78
|
+
### 3. Feature Backlog Ownership
|
|
79
|
+
|
|
80
|
+
Alex owns the **Feature Backlog** at `.blueprint/features/BACKLOG.md` — a prioritised list of features ready for implementation.
|
|
81
|
+
|
|
82
|
+
**Template:** `.blueprint/templates/BACKLOG_TEMPLATE.md`
|
|
83
|
+
|
|
84
|
+
**Format (token-efficient table):**
|
|
85
|
+
```markdown
|
|
86
|
+
| Status | P | E | Slug | Description |
|
|
87
|
+
|--------|---|---|------|-------------|
|
|
88
|
+
| ⏳ | P1 | M | user-auth | Login and registration flow |
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**When to create/update:**
|
|
92
|
+
- After creating a system spec — propose initial feature breakdown
|
|
93
|
+
- After completing a feature — pipeline removes entry automatically
|
|
94
|
+
- When scope changes — reprioritise and update descriptions
|
|
95
|
+
|
|
96
|
+
**Prioritisation criteria:**
|
|
97
|
+
- Business value and user impact
|
|
98
|
+
- Dependencies (what must come first?)
|
|
99
|
+
- Technical risk (surface unknowns early)
|
|
100
|
+
|
|
101
|
+
**Status icons:** ⏳ ready, 🚧 in progress, ❓ needs clarification
|
|
102
|
+
|
|
103
|
+
Alex keeps the backlog aligned with the system specification. If a proposed feature contradicts the system design, Alex flags it rather than adding it silently.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### 4. Living Collaboration with Cass (BA)
|
|
78
108
|
Alex and Cass operate in a **continuous, collaborative loop**:
|
|
79
109
|
- Cass may query, challenge, or request refinement of a specification before writing stories
|
|
80
110
|
- Alex clarifies intent, resolves ambiguities, or adjusts the specification where appropriate
|
|
@@ -89,7 +119,7 @@ Alex does **not** silently accept spec drift.
|
|
|
89
119
|
|
|
90
120
|
---
|
|
91
121
|
|
|
92
|
-
###
|
|
122
|
+
### 5. Conceptual Coherence Guardian (Hover Mode)
|
|
93
123
|
After initial specification and story creation, Alex remains active as a **conceptual coherence guardian**.
|
|
94
124
|
|
|
95
125
|
Alex reacts to:
|
|
@@ -109,7 +139,7 @@ When meaningful change is detected, Alex:
|
|
|
109
139
|
|
|
110
140
|
---
|
|
111
141
|
|
|
112
|
-
###
|
|
142
|
+
### 6. Managing Evolution & Breaking Change Proposals
|
|
113
143
|
When a feature exposes a flaw or limitation in the system specification:
|
|
114
144
|
- Alex may propose a **breaking or structural change** to the system spec
|
|
115
145
|
- Alex must clearly articulate:
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Feature Specification — Config Factory
|
|
2
|
+
|
|
3
|
+
## 1. Feature Intent
|
|
4
|
+
**Why this feature exists.**
|
|
5
|
+
|
|
6
|
+
- Four config modules (retry, feedback, murm, stack) share identical patterns
|
|
7
|
+
- Each implements: `getDefaultConfig()`, `readConfig()`, `writeConfig()`, `displayConfig()`, `setConfigValue()`, `resetConfig()`
|
|
8
|
+
- ~80 lines of boilerplate duplicated 4 times (~320 lines total)
|
|
9
|
+
- Inconsistent validation and error handling across modules
|
|
10
|
+
- Adding a new config module requires copying boilerplate
|
|
11
|
+
|
|
12
|
+
> Technical refactoring feature — consolidate to a factory pattern.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 2. Scope
|
|
17
|
+
### In Scope
|
|
18
|
+
- Create `src/config-factory.js` with `createConfigModule(options)` factory
|
|
19
|
+
- Refactor retry.js, feedback.js, stack.js to use the factory
|
|
20
|
+
- Refactor murm.js config functions to use the factory
|
|
21
|
+
- Standardize validation, error messages, and display formatting
|
|
22
|
+
- Preserve all existing config behaviour exactly
|
|
23
|
+
|
|
24
|
+
### Out of Scope
|
|
25
|
+
- Adding new config modules
|
|
26
|
+
- Changing config file locations or formats
|
|
27
|
+
- Modifying default values
|
|
28
|
+
- Adding new config keys
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 3. Actors Involved
|
|
33
|
+
**Who interacts with this feature.**
|
|
34
|
+
|
|
35
|
+
- **Developer**: Creates new config modules with minimal boilerplate
|
|
36
|
+
- **CLI User**: No change in experience — all config commands work identically
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 4. Behaviour Overview
|
|
41
|
+
**What the feature does, conceptually.**
|
|
42
|
+
|
|
43
|
+
The factory creates a config module with standard methods:
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
const myConfig = createConfigModule({
|
|
47
|
+
name: 'my-config',
|
|
48
|
+
file: '.claude/my-config.json',
|
|
49
|
+
defaults: { key1: 'value1', key2: 42 },
|
|
50
|
+
validators: {
|
|
51
|
+
key1: (v) => typeof v === 'string',
|
|
52
|
+
key2: (v) => Number.isInteger(v) && v > 0
|
|
53
|
+
},
|
|
54
|
+
formatters: {
|
|
55
|
+
key2: (v) => `${v} items`
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Returns: { read, write, reset, display, setValue, getDefault, CONFIG_FILE }
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Each existing config module becomes a thin wrapper calling the factory.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 5. State & Lifecycle Interactions
|
|
67
|
+
**How this feature touches the system lifecycle.**
|
|
68
|
+
|
|
69
|
+
- No state changes — pure refactoring
|
|
70
|
+
- Config files remain in same locations
|
|
71
|
+
- No runtime behaviour differences
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 6. Rules & Decision Logic
|
|
76
|
+
**New or exercised rules.**
|
|
77
|
+
|
|
78
|
+
| Rule | Description |
|
|
79
|
+
|------|-------------|
|
|
80
|
+
| Default merging | Factory merges missing keys from defaults on read |
|
|
81
|
+
| Validation | Factory validates values before write using validators map |
|
|
82
|
+
| Display format | Factory uses formatters map or falls back to default display |
|
|
83
|
+
| Error messages | Standardized format: `Invalid value for {key}: {value}. {reason}` |
|
|
84
|
+
| Array handling | Arrays validated and displayed consistently (JSON parse for set) |
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 7. Dependencies
|
|
89
|
+
**What this feature relies on.**
|
|
90
|
+
|
|
91
|
+
- Node.js `fs` module (already used)
|
|
92
|
+
- No new external dependencies
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 8. Non-Functional Considerations
|
|
97
|
+
|
|
98
|
+
- **Code reduction**: ~200+ lines removed across 4 modules
|
|
99
|
+
- **Consistency**: Identical error messages and validation across all configs
|
|
100
|
+
- **Extensibility**: New config modules require ~10 lines instead of ~80
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 9. Assumptions & Open Questions
|
|
105
|
+
|
|
106
|
+
**Assumptions:**
|
|
107
|
+
- All four config modules can use the same factory pattern
|
|
108
|
+
- Specialized validation (like feedback's issueMappings) can be handled via validators
|
|
109
|
+
|
|
110
|
+
**Open Questions:**
|
|
111
|
+
- Should murm.js config functions be split to a separate file or remain inline?
|
|
112
|
+
- Should the factory support nested config objects (like retry's `strategies`)?
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 10. Impact on System Specification
|
|
117
|
+
|
|
118
|
+
- No impact — internal refactoring only
|
|
119
|
+
- Public APIs of all config modules remain unchanged
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 11. Handover to BA (Cass)
|
|
124
|
+
|
|
125
|
+
**Skip Cass stage** — this is a technical refactoring feature with no user stories needed.
|
|
126
|
+
|
|
127
|
+
Direct handover to Nigel for test creation:
|
|
128
|
+
- Tests should verify all config commands work after refactoring
|
|
129
|
+
- Tests should verify validation errors are consistent
|
|
130
|
+
- Tests should verify display output format is preserved
|
|
131
|
+
- Tests should verify default values are unchanged
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 12. Change Log (Feature-Level)
|
|
136
|
+
| Date | Change | Reason | Raised By |
|
|
137
|
+
|------|--------|--------|-----------|
|
|
138
|
+
| 2026-03-03 | Initial spec | DRY up config modules | Alex |
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Implementation Plan: Config Factory
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Create a factory function to eliminate ~320 lines of duplicated boilerplate across four config modules (retry.js, feedback.js, stack.js, murm.js).
|
|
5
|
+
|
|
6
|
+
## Step 1: Create `src/config-factory.js`
|
|
7
|
+
|
|
8
|
+
Create the factory module with the following structure:
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
function createConfigModule(options) {
|
|
12
|
+
const { name, file, defaults, validators = {}, formatters = {}, arrayKeys = [] } = options;
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
CONFIG_FILE: file,
|
|
16
|
+
getDefault: () => ({ ...defaults }),
|
|
17
|
+
read: () => { /* merge defaults, handle errors */ },
|
|
18
|
+
write: (config) => { /* ensure dir, write JSON */ },
|
|
19
|
+
reset: () => { /* write defaults */ },
|
|
20
|
+
setValue: (key, value) => { /* validate, write */ },
|
|
21
|
+
display: () => { /* format and log */ }
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Factory Methods Detail
|
|
27
|
+
|
|
28
|
+
| Method | Behavior |
|
|
29
|
+
|--------|----------|
|
|
30
|
+
| `getDefault()` | Return shallow copy of defaults |
|
|
31
|
+
| `read()` | Return defaults if missing/corrupted, merge missing keys |
|
|
32
|
+
| `write(config)` | Create dir if needed, write JSON with 2-space indent |
|
|
33
|
+
| `reset()` | Call write(getDefault()) |
|
|
34
|
+
| `setValue(key, value)` | Validate key exists, parse arrays, run validator, write |
|
|
35
|
+
| `display()` | Log name header, iterate keys with formatters |
|
|
36
|
+
|
|
37
|
+
### Validation Logic
|
|
38
|
+
```js
|
|
39
|
+
setValue(key, value) {
|
|
40
|
+
if (!(key in defaults)) throw Error(`Unknown config key: ${key}. Valid keys: ...`);
|
|
41
|
+
|
|
42
|
+
let parsed = value;
|
|
43
|
+
if (arrayKeys.includes(key)) {
|
|
44
|
+
parsed = JSON.parse(value); // throws on invalid
|
|
45
|
+
if (!Array.isArray(parsed)) throw Error(`${key} must be a JSON array`);
|
|
46
|
+
} else if (typeof defaults[key] === 'number') {
|
|
47
|
+
parsed = parseFloat(value);
|
|
48
|
+
} else if (typeof defaults[key] === 'boolean') {
|
|
49
|
+
parsed = value === 'true';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (validators[key]) {
|
|
53
|
+
const result = validators[key](parsed);
|
|
54
|
+
if (result !== true) {
|
|
55
|
+
throw Error(`Invalid value for ${key}: ${value}. ${result}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const config = read();
|
|
60
|
+
config[key] = parsed;
|
|
61
|
+
write(config);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Step 2: Refactor retry.js
|
|
66
|
+
|
|
67
|
+
Keep existing business logic functions (calculateFailureRate, recommendStrategy, etc.).
|
|
68
|
+
Replace config boilerplate with factory:
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
const { createConfigModule } = require('./config-factory');
|
|
72
|
+
|
|
73
|
+
const configModule = createConfigModule({
|
|
74
|
+
name: 'Retry',
|
|
75
|
+
file: '.claude/retry-config.json',
|
|
76
|
+
defaults: {
|
|
77
|
+
maxRetries: 3,
|
|
78
|
+
windowSize: 10,
|
|
79
|
+
highFailureThreshold: 0.2,
|
|
80
|
+
strategies: { /* ... */ }
|
|
81
|
+
},
|
|
82
|
+
validators: {
|
|
83
|
+
maxRetries: (v) => Number.isInteger(v) && v >= 0 ? true : 'must be a non-negative integer',
|
|
84
|
+
windowSize: (v) => Number.isInteger(v) && v >= 1 ? true : 'must be a positive integer',
|
|
85
|
+
highFailureThreshold: (v) => v >= 0 && v <= 1 ? true : 'must be between 0 and 1'
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Re-export with same names for backward compatibility
|
|
90
|
+
const {
|
|
91
|
+
CONFIG_FILE,
|
|
92
|
+
getDefault: getDefaultConfig,
|
|
93
|
+
read: readConfig,
|
|
94
|
+
write: writeConfig,
|
|
95
|
+
reset: resetConfig,
|
|
96
|
+
display: displayConfig,
|
|
97
|
+
setValue: setConfigValue
|
|
98
|
+
} = configModule;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Step 3: Refactor feedback.js
|
|
102
|
+
|
|
103
|
+
Similar pattern. Keep validateFeedback, shouldPause, parseFeedbackFromOutput, normalizeFeedbackKeys.
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
const configModule = createConfigModule({
|
|
107
|
+
name: 'Feedback',
|
|
108
|
+
file: '.claude/feedback-config.json',
|
|
109
|
+
defaults: {
|
|
110
|
+
minRatingThreshold: 3.0,
|
|
111
|
+
enabled: true,
|
|
112
|
+
issueMappings: { /* ... */ }
|
|
113
|
+
},
|
|
114
|
+
validators: {
|
|
115
|
+
minRatingThreshold: (v) => v >= 1.0 && v <= 5.0 ? true : 'must be between 1.0 and 5.0',
|
|
116
|
+
enabled: (v) => typeof v === 'boolean' ? true : 'must be true or false'
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Step 4: Refactor stack.js
|
|
122
|
+
|
|
123
|
+
Keep detectStackConfig. Note: stack uses `*StackConfig` naming convention.
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
const configModule = createConfigModule({
|
|
127
|
+
name: 'Stack',
|
|
128
|
+
file: '.claude/stack-config.json',
|
|
129
|
+
defaults: {
|
|
130
|
+
language: '', runtime: '', packageManager: '',
|
|
131
|
+
frameworks: [], testRunner: '', testCommand: '',
|
|
132
|
+
linter: '', tools: []
|
|
133
|
+
},
|
|
134
|
+
arrayKeys: ['frameworks', 'tools']
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Alias exports with Stack suffix for backward compatibility
|
|
138
|
+
const getDefaultStackConfig = configModule.getDefault;
|
|
139
|
+
const readStackConfig = configModule.read;
|
|
140
|
+
// etc.
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Step 5: Refactor murm.js Config Functions
|
|
144
|
+
|
|
145
|
+
Murm.js has additional complexity (migrations, special merge logic). Keep using factory for core operations but preserve migration logic.
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
const configModule = createConfigModule({
|
|
149
|
+
name: 'Murmuration',
|
|
150
|
+
file: '.claude/murm-config.json',
|
|
151
|
+
defaults: {
|
|
152
|
+
maxConcurrency: 3, maxFeatures: 10, timeout: 30,
|
|
153
|
+
minDiskSpaceMB: 500, cli: 'npx claude',
|
|
154
|
+
skill: '/implement-feature', skillFlags: '--no-commit',
|
|
155
|
+
worktreeDir: '.claude/worktrees', queueFile: '.claude/murm-queue.json'
|
|
156
|
+
},
|
|
157
|
+
validators: {
|
|
158
|
+
maxConcurrency: (v) => Number.isInteger(v) && v >= 1 ? true : 'must be a positive integer',
|
|
159
|
+
timeout: (v) => Number.isInteger(v) && v >= 1 ? true : 'must be a positive integer'
|
|
160
|
+
},
|
|
161
|
+
formatters: {
|
|
162
|
+
timeout: (v) => `${v} min`
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Note: readMurmConfig needs to preserve migration logic for legacy files.
|
|
168
|
+
|
|
169
|
+
## Step 6: Run Tests
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
node --test test/feature_config-factory.test.js
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Fix any failures, iterate until all 19 tests pass.
|
|
176
|
+
|
|
177
|
+
## Files Modified
|
|
178
|
+
- `src/config-factory.js` (new)
|
|
179
|
+
- `src/retry.js` (refactored)
|
|
180
|
+
- `src/feedback.js` (refactored)
|
|
181
|
+
- `src/stack.js` (refactored)
|
|
182
|
+
- `src/murm.js` (refactored config functions)
|
|
183
|
+
|
|
184
|
+
## Risk Mitigation
|
|
185
|
+
- All existing exports preserved with same names
|
|
186
|
+
- Business logic functions untouched
|
|
187
|
+
- Tests verify backward compatibility
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Nigel Handoff: Config Factory
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
Created test suite for the config-factory feature with 19 test cases covering:
|
|
5
|
+
- Factory core functions (7 tests)
|
|
6
|
+
- Validation (5 tests)
|
|
7
|
+
- Display formatting (3 tests)
|
|
8
|
+
- Backward compatibility (4 tests)
|
|
9
|
+
- Error message consistency (2 tests)
|
|
10
|
+
|
|
11
|
+
## Test Files Created
|
|
12
|
+
- `test/artifacts/feature_config-factory/test-spec.md` - Test mapping document
|
|
13
|
+
- `test/feature_config-factory.test.js` - Executable test file
|
|
14
|
+
|
|
15
|
+
## Key Test Coverage
|
|
16
|
+
|
|
17
|
+
### Factory API
|
|
18
|
+
- Factory returns: read, write, reset, display, setValue, getDefault, CONFIG_FILE
|
|
19
|
+
- getDefault returns provided defaults unchanged
|
|
20
|
+
- read handles missing/corrupted files gracefully
|
|
21
|
+
- read merges missing keys from defaults
|
|
22
|
+
- write/reset operations
|
|
23
|
+
|
|
24
|
+
### Validation System
|
|
25
|
+
- Validators map prevents invalid values
|
|
26
|
+
- Array keys parsed from JSON strings
|
|
27
|
+
- Unknown keys rejected with helpful error
|
|
28
|
+
|
|
29
|
+
### Backward Compatibility
|
|
30
|
+
- retry.js exports unchanged
|
|
31
|
+
- feedback.js exports unchanged
|
|
32
|
+
- stack.js (with Stack prefix) exports unchanged
|
|
33
|
+
- murm.js config functions unchanged
|
|
34
|
+
|
|
35
|
+
## Implementation Notes for Codey
|
|
36
|
+
|
|
37
|
+
1. **Create `src/config-factory.js`** with `createConfigModule(options)` factory
|
|
38
|
+
2. **Options object shape**:
|
|
39
|
+
```js
|
|
40
|
+
{
|
|
41
|
+
name: string, // Config name for display
|
|
42
|
+
file: string, // Path like '.claude/foo.json'
|
|
43
|
+
defaults: object, // Default config values
|
|
44
|
+
validators?: object, // Key -> validator function
|
|
45
|
+
formatters?: object, // Key -> display formatter
|
|
46
|
+
arrayKeys?: string[] // Keys that accept JSON array values
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
3. **Validator functions** return `true` for valid, or error string for invalid
|
|
50
|
+
4. **Error format**: `Invalid value for {key}: {value}. {reason}`
|
|
51
|
+
5. **Refactor existing modules** to use factory while preserving all exports
|
|
52
|
+
|
|
53
|
+
## Running Tests
|
|
54
|
+
```bash
|
|
55
|
+
cd .claude/worktrees/feat-config-factory
|
|
56
|
+
node --test test/feature_config-factory.test.js
|
|
57
|
+
```
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Feature Specification — Cost Tracking
|
|
2
|
+
|
|
3
|
+
## 1. Feature Intent
|
|
4
|
+
**Why this feature exists.**
|
|
5
|
+
|
|
6
|
+
- Users have no visibility into token consumption or estimated costs when running the pipeline
|
|
7
|
+
- Without cost data, users cannot identify expensive stages or optimize prompt efficiency
|
|
8
|
+
- Cost awareness enables informed decisions about when to use `--skip-stories` or other optimizations
|
|
9
|
+
- Aligns with existing observability patterns (history, insights, feedback) in the system spec
|
|
10
|
+
|
|
11
|
+
> This feature reinforces Section 8 (Cross-Cutting Concerns: Observability) of the System Spec.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Scope
|
|
16
|
+
### In Scope
|
|
17
|
+
- Track input/output tokens per agent stage (alex, cass, nigel, codey-plan, codey-implement)
|
|
18
|
+
- Estimate cost per stage using configurable pricing (default: Claude Sonnet pricing)
|
|
19
|
+
- Store token/cost data in pipeline history alongside existing timing data
|
|
20
|
+
- Display cost summary at pipeline completion
|
|
21
|
+
- Add `--cost` flag to `history` command to show cost breakdowns
|
|
22
|
+
- Add `cost-config` CLI command for pricing configuration
|
|
23
|
+
|
|
24
|
+
### Out of Scope
|
|
25
|
+
- Real-time token streaming (report after each stage completes)
|
|
26
|
+
- Multi-model pricing within a single run (assumes one model for entire pipeline)
|
|
27
|
+
- Billing integration or payment tracking
|
|
28
|
+
- Token optimization recommendations (covered by insights.js)
|
|
29
|
+
- Cost alerts or budget limits (potential future feature)
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 3. Actors Involved
|
|
34
|
+
|
|
35
|
+
| Actor | Role in Cost Tracking |
|
|
36
|
+
|-------|----------------------|
|
|
37
|
+
| Human User | Views cost summaries, configures pricing, uses data for optimization decisions |
|
|
38
|
+
| Pipeline Orchestrator | Records token usage at each stage transition |
|
|
39
|
+
| History Module | Persists and retrieves cost data |
|
|
40
|
+
| Each Agent (Alex, Cass, Nigel, Codey) | Token consumption is measured but agents are unaware of tracking |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 4. Behaviour Overview
|
|
45
|
+
|
|
46
|
+
**Happy Path:**
|
|
47
|
+
1. User runs `/implement-feature "slug"`
|
|
48
|
+
2. At each stage completion, orchestrator records tokens used (input + output)
|
|
49
|
+
3. Pipeline completion displays cost summary table
|
|
50
|
+
4. History entry includes token/cost data per stage
|
|
51
|
+
|
|
52
|
+
**Cost Summary Display (at pipeline end):**
|
|
53
|
+
```
|
|
54
|
+
Cost Summary for feature: user-auth
|
|
55
|
+
|
|
56
|
+
STAGE INPUT OUTPUT COST
|
|
57
|
+
alex 2,450 1,230 $0.014
|
|
58
|
+
cass 3,100 1,850 $0.019
|
|
59
|
+
nigel 2,800 2,100 $0.018
|
|
60
|
+
codey-plan 1,500 890 $0.009
|
|
61
|
+
codey-impl 4,200 3,500 $0.028
|
|
62
|
+
─────────────────────────────────────────
|
|
63
|
+
TOTAL 14,050 9,570 $0.088
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**History with Costs:**
|
|
67
|
+
```bash
|
|
68
|
+
$ murmur8 history --cost
|
|
69
|
+
|
|
70
|
+
SLUG STATUS DURATION TOTAL COST
|
|
71
|
+
user-auth success 12m 30s $0.088
|
|
72
|
+
api-validation success 8m 15s $0.062
|
|
73
|
+
cache-layer failed 4m 22s $0.031 (failed at: nigel)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Stats with Costs:**
|
|
77
|
+
```bash
|
|
78
|
+
$ murmur8 history --stats --cost
|
|
79
|
+
|
|
80
|
+
Pipeline Statistics (based on 15 runs)
|
|
81
|
+
|
|
82
|
+
METRIC VALUE
|
|
83
|
+
...existing stats...
|
|
84
|
+
Avg cost per run $0.075
|
|
85
|
+
Total cost (all runs) $1.12
|
|
86
|
+
Most expensive stage codey-implement ($0.42 total)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 5. State & Lifecycle Interactions
|
|
92
|
+
|
|
93
|
+
**State additions to history entry:**
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"slug": "user-auth",
|
|
97
|
+
"stages": {
|
|
98
|
+
"alex": {
|
|
99
|
+
"durationMs": 45000,
|
|
100
|
+
"tokens": { "input": 2450, "output": 1230 },
|
|
101
|
+
"cost": 0.014
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"totalTokens": { "input": 14050, "output": 9570 },
|
|
105
|
+
"totalCost": 0.088
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Lifecycle:**
|
|
110
|
+
- **State-extending:** Adds new fields to existing history entries
|
|
111
|
+
- No new states created
|
|
112
|
+
- Backward compatible (missing token data displays "N/A")
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 6. Rules & Decision Logic
|
|
117
|
+
|
|
118
|
+
| Rule | Description | Deterministic |
|
|
119
|
+
|------|-------------|---------------|
|
|
120
|
+
| Token counting | Sum of input + output tokens per stage | Yes |
|
|
121
|
+
| Cost calculation | `(input_tokens * input_price) + (output_tokens * output_price)` | Yes |
|
|
122
|
+
| Default pricing | Claude Sonnet 3.5: $3/M input, $15/M output | Yes (configurable) |
|
|
123
|
+
| Skipped stages | Record 0 tokens for skipped stages (e.g., Cass when `--skip-stories`) | Yes |
|
|
124
|
+
| Failed stages | Record tokens consumed up to failure point | Yes |
|
|
125
|
+
| Rounding | Costs rounded to 3 decimal places ($0.001 precision) | Yes |
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 7. Dependencies
|
|
130
|
+
|
|
131
|
+
**System Dependencies:**
|
|
132
|
+
- `src/history.js` - Extended to store/retrieve token data
|
|
133
|
+
- `.claude/pipeline-history.json` - Schema extended with token fields
|
|
134
|
+
|
|
135
|
+
**New Files:**
|
|
136
|
+
- `src/cost.js` - Token counting, cost calculation, formatting
|
|
137
|
+
- `src/commands/cost-config.js` - CLI command for pricing config
|
|
138
|
+
- `.claude/cost-config.json` - Pricing configuration (gitignored)
|
|
139
|
+
|
|
140
|
+
**Technical Dependencies:**
|
|
141
|
+
- Claude Code must expose token usage in Task tool responses
|
|
142
|
+
- If token data unavailable, feature gracefully degrades to "N/A"
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 8. Non-Functional Considerations
|
|
147
|
+
|
|
148
|
+
| Concern | Consideration |
|
|
149
|
+
|---------|---------------|
|
|
150
|
+
| Performance | Token counting adds negligible overhead (<1ms per stage) |
|
|
151
|
+
| Storage | ~100 bytes additional per history entry |
|
|
152
|
+
| Backward compatibility | Existing history entries without token data display "N/A" |
|
|
153
|
+
| Accuracy | Estimated costs only; actual billing may differ |
|
|
154
|
+
| Privacy | No sensitive data; token counts are numeric |
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## 9. Assumptions & Open Questions
|
|
159
|
+
|
|
160
|
+
**Assumptions:**
|
|
161
|
+
- Claude Code Task tool responses include token usage metadata
|
|
162
|
+
- Single pricing model per pipeline run is acceptable
|
|
163
|
+
- Users want cost visibility but not enforcement (no budget limits)
|
|
164
|
+
|
|
165
|
+
**Open Questions:**
|
|
166
|
+
- How does Claude Code expose token usage? Via response metadata or separate API?
|
|
167
|
+
- Should we support custom pricing for enterprise/volume discounts?
|
|
168
|
+
- Should cost data be included in CSV/JSON exports by default?
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 10. Impact on System Specification
|
|
173
|
+
|
|
174
|
+
**Reinforces existing patterns:**
|
|
175
|
+
- Section 8 (Observability) - Adds cost as new observability dimension
|
|
176
|
+
- Section 9 (Reliability) - Token data helps diagnose token limit failures
|
|
177
|
+
|
|
178
|
+
**No contradictions identified.**
|
|
179
|
+
|
|
180
|
+
**Suggested System Spec addition (Section 8):**
|
|
181
|
+
```markdown
|
|
182
|
+
### Cost Visibility
|
|
183
|
+
- Token usage tracked per stage
|
|
184
|
+
- Estimated costs calculated and persisted
|
|
185
|
+
- Cost summaries available via `history --cost`
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 11. Handover to BA (Cass)
|
|
191
|
+
|
|
192
|
+
**Story themes:**
|
|
193
|
+
1. **Core tracking** - Record token usage at each stage completion
|
|
194
|
+
2. **Cost calculation** - Apply pricing model to token counts
|
|
195
|
+
3. **Display** - Show cost summary at pipeline end
|
|
196
|
+
4. **History integration** - Store in history, display in `history` command
|
|
197
|
+
5. **Configuration** - `cost-config` command for pricing settings
|
|
198
|
+
|
|
199
|
+
**Expected story boundaries:**
|
|
200
|
+
- Story 1: Token tracking infrastructure (cost.js, history schema)
|
|
201
|
+
- Story 2: Cost calculation and formatting
|
|
202
|
+
- Story 3: Pipeline completion summary display
|
|
203
|
+
- Story 4: History command integration (`--cost` flag)
|
|
204
|
+
- Story 5: Configuration CLI (`cost-config` command)
|
|
205
|
+
|
|
206
|
+
**Areas needing careful framing:**
|
|
207
|
+
- Graceful degradation when token data unavailable
|
|
208
|
+
- Backward compatibility with existing history entries
|
|
209
|
+
- Cost display formatting (currency, precision)
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 12. Change Log (Feature-Level)
|
|
214
|
+
| Date | Change | Reason | Raised By |
|
|
215
|
+
|-----|------|--------|-----------|
|
|
216
|
+
| 2026-03-04 | Initial spec | Enable cost visibility for pipeline optimization | Alex |
|