@arvorco/relentless 0.7.0 → 0.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.
- package/.claude/commands/relentless.learn.md +52 -0
- package/.claude/skills/checklist/SKILL.md +9 -2
- package/.claude/skills/constitution/SKILL.md +11 -0
- package/.claude/skills/constitution/templates/constitution.md +0 -3
- package/.claude/skills/learn/SKILL.md +361 -0
- package/.claude/skills/learn/scripts/common.sh +46 -0
- package/.claude/skills/learn/scripts/extract-costs.sh +48 -0
- package/.claude/skills/learn/scripts/extract-errors.sh +47 -0
- package/.claude/skills/learn/scripts/extract-failures.sh +47 -0
- package/.claude/skills/learn/scripts/extract-learnings.sh +66 -0
- package/.claude/skills/learn/scripts/extract-patterns.sh +72 -0
- package/.claude/skills/learn/scripts/extract-session-context.sh +77 -0
- package/.claude/skills/learn/scripts/generate-stats.sh +129 -0
- package/.claude/skills/learn/templates/learning-proposal.md +105 -0
- package/.claude/skills/learn/templates/stats.md +69 -0
- package/.claude/skills/plan/SKILL.md +10 -3
- package/.claude/skills/specify/SKILL.md +9 -3
- package/.claude/skills/tasks/SKILL.md +10 -3
- package/.claude/skills/validators/SKILL.md +174 -0
- package/.claude/skills/validators/scripts/common.sh +182 -0
- package/.claude/skills/validators/scripts/validate-checklist.sh +190 -0
- package/.claude/skills/validators/scripts/validate-constitution.sh +111 -0
- package/.claude/skills/validators/scripts/validate-plan.sh +163 -0
- package/.claude/skills/validators/scripts/validate-prompt.sh +125 -0
- package/.claude/skills/validators/scripts/validate-spec.sh +214 -0
- package/.claude/skills/validators/scripts/validate-tasks.sh +179 -0
- package/.claude/skills/validators/scripts/validate.sh +295 -0
- package/CHANGELOG.md +53 -1
- package/package.json +1 -1
- package/relentless/constitution.md +0 -3
- package/src/execution/runner.ts +4 -0
- package/src/init/scaffolder.ts +2 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Distill learnings from completed feature and propose amendments to constitution.md or prompt.md.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Load the learn skill (`[skills_path]/learn/SKILL.md`) and follow its workflow.
|
|
6
|
+
|
|
7
|
+
**Usage:** `/relentless.learn [feature-name]`
|
|
8
|
+
|
|
9
|
+
**Context:** $ARGUMENTS
|
|
10
|
+
|
|
11
|
+
The learn skill will guide you through:
|
|
12
|
+
|
|
13
|
+
1. **Extract Learnings** - Run CLI scripts to extract patterns, costs, failures, errors
|
|
14
|
+
2. **Classify** - Categorize as Constitutional (governance) or Tactical (tech-specific)
|
|
15
|
+
3. **Generate Proposals** - Create max 5 constitutional + 5 tactical proposals
|
|
16
|
+
4. **Human Approval** - Present proposals for user review
|
|
17
|
+
5. **Apply Amendments** - Update constitution.md or prompt.md with approved changes
|
|
18
|
+
6. **Update Stats** - Regenerate aggregate stats
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
1. Complete a feature (all stories `passes: true`)
|
|
23
|
+
2. Run `/relentless.learn <feature-name>` to capture learnings
|
|
24
|
+
3. Review and approve/modify/reject proposals
|
|
25
|
+
4. Approved amendments are applied automatically
|
|
26
|
+
|
|
27
|
+
## What Gets Updated
|
|
28
|
+
|
|
29
|
+
After approval:
|
|
30
|
+
- `constitution.md` - New MUST/SHOULD rules (version bumped)
|
|
31
|
+
- `prompt.md` - New patterns or tips
|
|
32
|
+
- `relentless/features/<feature>/learnings.md` - Learning log
|
|
33
|
+
- `relentless/stats.md` - Aggregate statistics
|
|
34
|
+
|
|
35
|
+
## Prerequisites
|
|
36
|
+
|
|
37
|
+
- Feature must be complete (all stories done or skipped)
|
|
38
|
+
- `progress.txt` must exist with iteration learnings
|
|
39
|
+
- `constitution.md` and/or `prompt.md` must exist
|
|
40
|
+
|
|
41
|
+
## Version Bumping
|
|
42
|
+
|
|
43
|
+
| Rule Type | Version Bump |
|
|
44
|
+
|-----------|--------------|
|
|
45
|
+
| MUST rule | MINOR (e.g., 2.0.0 → 2.1.0) |
|
|
46
|
+
| SHOULD rule | PATCH (e.g., 2.0.0 → 2.0.1) |
|
|
47
|
+
|
|
48
|
+
## See Also
|
|
49
|
+
|
|
50
|
+
- `/relentless.constitution` - Create or update project governance
|
|
51
|
+
- `/relentless.implement` - Implement feature stories
|
|
52
|
+
- `relentless/stats.md` - View aggregate statistics
|
|
@@ -152,15 +152,22 @@ Ensure checklist includes items for constitution MUST rules:
|
|
|
152
152
|
|
|
153
153
|
---
|
|
154
154
|
|
|
155
|
-
## Step 6: Save &
|
|
155
|
+
## Step 6: Save & Validate
|
|
156
156
|
|
|
157
157
|
1. Save to `relentless/features/NNN-feature/checklist.md`
|
|
158
|
-
2.
|
|
158
|
+
2. **Run the validator to ensure checklist.md is correctly formatted:**
|
|
159
|
+
```bash
|
|
160
|
+
.claude/skills/validators/scripts/validate-checklist.sh "relentless/features/NNN-feature/checklist.md"
|
|
161
|
+
```
|
|
162
|
+
- If validation fails, fix the errors and re-run
|
|
163
|
+
- Warnings are acceptable but should be reviewed
|
|
164
|
+
3. Report:
|
|
159
165
|
- Total checklist items: N
|
|
160
166
|
- Items per category
|
|
161
167
|
- Mandatory items included: TDD ✓, Quality Gates ✓, Routing ✓
|
|
162
168
|
- Constitution compliance items: N
|
|
163
169
|
- Gaps identified: N
|
|
170
|
+
- Validation: PASS/FAIL
|
|
164
171
|
- Next step: `/relentless.convert` (if not done) or `/relentless.analyze`
|
|
165
172
|
|
|
166
173
|
---
|
|
@@ -222,6 +222,17 @@ Save both files:
|
|
|
222
222
|
- `relentless/constitution.md`
|
|
223
223
|
- `relentless/prompt.md`
|
|
224
224
|
|
|
225
|
+
**Run the validators to ensure both files are correctly formatted:**
|
|
226
|
+
```bash
|
|
227
|
+
# Validate constitution.md
|
|
228
|
+
.claude/skills/validators/scripts/validate-constitution.sh "relentless/constitution.md"
|
|
229
|
+
|
|
230
|
+
# Validate prompt.md
|
|
231
|
+
.claude/skills/validators/scripts/validate-prompt.sh "relentless/prompt.md"
|
|
232
|
+
```
|
|
233
|
+
- If validation fails, fix the errors and re-run
|
|
234
|
+
- Warnings are acceptable but should be reviewed
|
|
235
|
+
|
|
225
236
|
---
|
|
226
237
|
|
|
227
238
|
## Step 6: Report
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: learn
|
|
3
|
+
description: "Distill learnings from completed features and propose amendments to constitution.md or prompt.md. Use after feature completion. Triggers on: capture learnings, learn from feature, distill learnings, relentless learn."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Relentless Learning System
|
|
7
|
+
|
|
8
|
+
Capture learnings from completed features and propose amendments to improve future runs.
|
|
9
|
+
|
|
10
|
+
**Philosophy**: "Loop Ralph" - Create a feedback loop where each feature execution improves the system for future features.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## SpecKit Workflow
|
|
15
|
+
|
|
16
|
+
This skill is **optional** and runs after feature completion:
|
|
17
|
+
|
|
18
|
+
specify → plan → tasks → convert → analyze → implement → **(optional) learn**
|
|
19
|
+
|
|
20
|
+
Prerequisites:
|
|
21
|
+
- Feature must be complete (all stories `passes: true` or `skipped: true`)
|
|
22
|
+
- `progress.txt` must exist with iteration learnings
|
|
23
|
+
- `prd.json` must exist with execution data
|
|
24
|
+
- `constitution.md` and/or `prompt.md` must exist in `relentless/`
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## The Job
|
|
29
|
+
|
|
30
|
+
1. Extract learnings from completed feature (using CLI scripts)
|
|
31
|
+
2. Classify each learning (Constitutional / Tactical / Discard)
|
|
32
|
+
3. Generate proposals for human approval
|
|
33
|
+
4. Apply approved amendments to constitution.md or prompt.md
|
|
34
|
+
5. Save learning log to feature directory
|
|
35
|
+
6. Update aggregate stats
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Step 0: Run Extraction Scripts
|
|
40
|
+
|
|
41
|
+
**IMPORTANT**: Use CLI scripts for extraction - do NOT read entire files into context.
|
|
42
|
+
|
|
43
|
+
Run the extraction scripts from `.claude/skills/learn/scripts/`:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Main extraction - runs all extractors
|
|
47
|
+
bash .claude/skills/learn/scripts/extract-learnings.sh relentless/features/<feature-name>
|
|
48
|
+
|
|
49
|
+
# Individual extractors (run by main script):
|
|
50
|
+
# - extract-patterns.sh - Patterns from progress.txt
|
|
51
|
+
# - extract-costs.sh - Cost accuracy from prd.json
|
|
52
|
+
# - extract-failures.sh - Failed checks from checklist.md
|
|
53
|
+
# - extract-errors.sh - Error patterns from progress.txt
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The output is compact JSON (~500 tokens max):
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"patterns": ["Pattern 1: description", "Pattern 2: description"],
|
|
61
|
+
"costs": {"feature": "name", "estimated": 0.45, "actual": 0.52},
|
|
62
|
+
"failures": ["Unchecked item 1", "Unchecked item 2"],
|
|
63
|
+
"errors": ["Error context 1", "Error context 2"]
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**If more context is needed for a specific story:**
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Extract session context for deeper investigation
|
|
71
|
+
bash .claude/skills/learn/scripts/extract-session-context.sh relentless/features/<feature-name> US-XXX
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Step 1: Parse Extracted Data
|
|
77
|
+
|
|
78
|
+
Parse the JSON output from the extraction scripts:
|
|
79
|
+
|
|
80
|
+
1. **Patterns**: Reusable learnings discovered during implementation
|
|
81
|
+
2. **Costs**: Cost accuracy metrics (estimated vs actual)
|
|
82
|
+
3. **Failures**: Unchecked checklist items (potential gaps)
|
|
83
|
+
4. **Errors**: Error patterns that were fixed (potential rules)
|
|
84
|
+
|
|
85
|
+
Count and categorize:
|
|
86
|
+
- How many patterns were discovered?
|
|
87
|
+
- Was cost estimation accurate (>80%)?
|
|
88
|
+
- Are there unchecked checklist items (quality gaps)?
|
|
89
|
+
- What error patterns emerged?
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Step 2: Classify Learnings
|
|
94
|
+
|
|
95
|
+
For each learning, classify as:
|
|
96
|
+
|
|
97
|
+
| Type | Target | Criteria | Example |
|
|
98
|
+
|------|--------|----------|---------|
|
|
99
|
+
| **Constitutional** | constitution.md | Applies to ALL features, governance/quality/process, prevents significant issues | "Always export new types with implementation" |
|
|
100
|
+
| **Tactical** | prompt.md | Specific to task types or tech stack, workflow tips, common pitfalls | "Mock CLI calls in adapter tests" |
|
|
101
|
+
| **Discard** | None | One-time edge case, already covered, too specific | "Fixed typo in variable name" |
|
|
102
|
+
|
|
103
|
+
**Constitutional criteria** (becomes a MUST or SHOULD rule):
|
|
104
|
+
- Applies universally to all features
|
|
105
|
+
- Related to governance, quality, or process
|
|
106
|
+
- Prevents significant issues if violated
|
|
107
|
+
- Not already covered in constitution
|
|
108
|
+
|
|
109
|
+
**Tactical criteria** (becomes a prompt.md pattern):
|
|
110
|
+
- Specific to certain task types or tech stack
|
|
111
|
+
- Workflow tip or common pitfall
|
|
112
|
+
- Helps agents avoid repeated mistakes
|
|
113
|
+
- Not governance-level
|
|
114
|
+
|
|
115
|
+
**Discard criteria** (do not propose):
|
|
116
|
+
- One-time edge case
|
|
117
|
+
- Already covered by existing rules
|
|
118
|
+
- Too specific to be reusable
|
|
119
|
+
- Subjective preference
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Step 3: Generate Proposals
|
|
124
|
+
|
|
125
|
+
Generate **maximum 5 constitutional + 5 tactical proposals** per feature.
|
|
126
|
+
|
|
127
|
+
### Constitutional Proposal Format:
|
|
128
|
+
|
|
129
|
+
```markdown
|
|
130
|
+
### PROP-C01: [Short Title]
|
|
131
|
+
|
|
132
|
+
**Target:** constitution.md > Principle [N] > [MUST|SHOULD]
|
|
133
|
+
|
|
134
|
+
**Amendment:**
|
|
135
|
+
> [1-2 sentence rule in imperative form]
|
|
136
|
+
|
|
137
|
+
**Evidence:**
|
|
138
|
+
> [Quote from progress.txt showing the issue]
|
|
139
|
+
|
|
140
|
+
**Classification:** Constitutional - [Rationale why this applies to all features]
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Tactical Proposal Format:
|
|
144
|
+
|
|
145
|
+
```markdown
|
|
146
|
+
### PROP-T01: [Short Title]
|
|
147
|
+
|
|
148
|
+
**Target:** prompt.md > [Section Name]
|
|
149
|
+
|
|
150
|
+
**Amendment:**
|
|
151
|
+
> [1-2 sentence tip or pattern]
|
|
152
|
+
|
|
153
|
+
**Evidence:**
|
|
154
|
+
> [Quote from progress.txt showing the context]
|
|
155
|
+
|
|
156
|
+
**Classification:** Tactical - [Rationale why this is task-specific]
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Discarded Learnings (include for transparency):
|
|
160
|
+
|
|
161
|
+
```markdown
|
|
162
|
+
### Discarded Learnings
|
|
163
|
+
|
|
164
|
+
| Learning | Reason |
|
|
165
|
+
|----------|--------|
|
|
166
|
+
| Fixed typo in variable name | One-time edge case |
|
|
167
|
+
| Used specific API endpoint | Already covered in docs |
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Step 4: Present for Human Approval
|
|
173
|
+
|
|
174
|
+
Use the proposal template from `templates/learning-proposal.md` to format the output.
|
|
175
|
+
|
|
176
|
+
The proposal should include:
|
|
177
|
+
1. **Feature Summary**: Name, stories, escalations, cost accuracy
|
|
178
|
+
2. **Constitutional Proposals**: PROP-C01, PROP-C02, etc.
|
|
179
|
+
3. **Tactical Proposals**: PROP-T01, PROP-T02, etc.
|
|
180
|
+
4. **Discarded Learnings**: With reasons
|
|
181
|
+
5. **Approval Request**: Ask user to approve, modify, or reject each proposal
|
|
182
|
+
|
|
183
|
+
**Ask the user:**
|
|
184
|
+
```
|
|
185
|
+
Please review the proposals above. For each one:
|
|
186
|
+
- APPROVE: Apply as written
|
|
187
|
+
- MODIFY: Suggest changes
|
|
188
|
+
- REJECT: Do not apply
|
|
189
|
+
|
|
190
|
+
Which proposals do you approve?
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Step 5: Apply Approved Amendments
|
|
196
|
+
|
|
197
|
+
For each approved proposal:
|
|
198
|
+
|
|
199
|
+
### Constitutional Amendments (constitution.md):
|
|
200
|
+
|
|
201
|
+
1. Read current version from constitution.md frontmatter
|
|
202
|
+
2. Find the appropriate Principle section
|
|
203
|
+
3. Add the new rule under MUST or SHOULD
|
|
204
|
+
4. Update version number:
|
|
205
|
+
- **MUST rules**: Bump MINOR version (e.g., 2.0.0 → 2.1.0)
|
|
206
|
+
- **SHOULD rules**: Bump PATCH version (e.g., 2.0.0 → 2.0.1)
|
|
207
|
+
5. Update `LAST_AMENDED_DATE` to today
|
|
208
|
+
6. Add amendment note at top of file
|
|
209
|
+
|
|
210
|
+
**Amendment note format:**
|
|
211
|
+
```markdown
|
|
212
|
+
<!-- Amendment: v2.1.0 - Added [rule title] from feature [feature-name] -->
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Tactical Amendments (prompt.md):
|
|
216
|
+
|
|
217
|
+
1. Find the appropriate section in prompt.md
|
|
218
|
+
2. Add the new pattern or tip
|
|
219
|
+
3. Update "Generated" date at bottom
|
|
220
|
+
4. If no appropriate section exists, create a new "## Learned Patterns" section
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Step 6: Save Learning Log
|
|
225
|
+
|
|
226
|
+
Create a learning log file in the feature directory:
|
|
227
|
+
|
|
228
|
+
**Path:** `relentless/features/<feature-name>/learnings.md`
|
|
229
|
+
|
|
230
|
+
```markdown
|
|
231
|
+
# Learnings: [Feature Name]
|
|
232
|
+
|
|
233
|
+
**Extracted:** [date]
|
|
234
|
+
**Proposals Generated:** [count]
|
|
235
|
+
**Approved:** [count]
|
|
236
|
+
**Applied:** [count]
|
|
237
|
+
|
|
238
|
+
## Constitutional Amendments Applied
|
|
239
|
+
|
|
240
|
+
- PROP-C01: [Title] → constitution.md v[version]
|
|
241
|
+
|
|
242
|
+
## Tactical Amendments Applied
|
|
243
|
+
|
|
244
|
+
- PROP-T01: [Title] → prompt.md
|
|
245
|
+
|
|
246
|
+
## Discarded Learnings
|
|
247
|
+
|
|
248
|
+
- [Learning] - [Reason]
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
*Generated by /relentless.learn*
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Step 7: Update Aggregate Stats
|
|
258
|
+
|
|
259
|
+
Run the stats generator to update `relentless/stats.md`:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
bash .claude/skills/learn/scripts/generate-stats.sh relentless
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
This generates a human-readable report with:
|
|
266
|
+
- Total features, stories, completion rate
|
|
267
|
+
- Cost summary (estimated vs actual)
|
|
268
|
+
- Token usage
|
|
269
|
+
- Complexity distribution
|
|
270
|
+
- Escalation rate
|
|
271
|
+
- Model usage breakdown
|
|
272
|
+
|
|
273
|
+
The stats file is for human review, NOT loaded into agent context.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Version Bumping Rules
|
|
278
|
+
|
|
279
|
+
| Amendment Type | Version Bump | Example |
|
|
280
|
+
|----------------|--------------|---------|
|
|
281
|
+
| MUST rule | MINOR | 2.0.0 → 2.1.0 |
|
|
282
|
+
| SHOULD rule | PATCH | 2.0.0 → 2.0.1 |
|
|
283
|
+
| Multiple rules | Highest bump applies | 2.0.0 → 2.1.0 if any MUST |
|
|
284
|
+
|
|
285
|
+
**Never bump MAJOR** - only `/relentless.constitution` can do that (for breaking governance changes).
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Common Patterns to Look For
|
|
290
|
+
|
|
291
|
+
### Constitutional-Level Patterns:
|
|
292
|
+
- Type safety rules (export types with implementation)
|
|
293
|
+
- Testing patterns (TDD workflow, test structure)
|
|
294
|
+
- Error handling patterns (graceful degradation)
|
|
295
|
+
- Documentation requirements (JSDoc, README updates)
|
|
296
|
+
- Code quality patterns (zero-lint, typecheck)
|
|
297
|
+
|
|
298
|
+
### Tactical-Level Patterns:
|
|
299
|
+
- Schema naming conventions (XxxSchema for Zod)
|
|
300
|
+
- Mock patterns for testing (mock CLI, mock adapters)
|
|
301
|
+
- File organization patterns (where to put new files)
|
|
302
|
+
- Common pitfalls for specific tech stack
|
|
303
|
+
- Performance optimizations
|
|
304
|
+
|
|
305
|
+
### Patterns to Discard:
|
|
306
|
+
- Typo fixes
|
|
307
|
+
- One-time debugging steps
|
|
308
|
+
- Temporary workarounds (already removed)
|
|
309
|
+
- Personal preferences (formatting choices)
|
|
310
|
+
- Already documented patterns
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Example Session
|
|
315
|
+
|
|
316
|
+
**Input:**
|
|
317
|
+
```
|
|
318
|
+
/relentless.learn 001-queued-prompts
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**Extraction Output:**
|
|
322
|
+
```json
|
|
323
|
+
{
|
|
324
|
+
"patterns": [
|
|
325
|
+
"Atomic writes: Use temp file + rename for safety",
|
|
326
|
+
"Zod naming: Use XxxSchema to avoid no-redeclare"
|
|
327
|
+
],
|
|
328
|
+
"costs": {"estimated": 0.45, "actual": 0.52, "accuracy": "87%"},
|
|
329
|
+
"failures": [],
|
|
330
|
+
"errors": ["ESLint no-redeclare on UserStory type - fixed with XxxSchema pattern"]
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**Generated Proposals:**
|
|
335
|
+
```markdown
|
|
336
|
+
### PROP-C01: Atomic Write Pattern
|
|
337
|
+
|
|
338
|
+
**Target:** constitution.md > Principle 11 (Data Safety) > SHOULD
|
|
339
|
+
**Amendment:**
|
|
340
|
+
> Use atomic writes (temp file + rename) when modifying files to prevent corruption.
|
|
341
|
+
|
|
342
|
+
**Evidence:**
|
|
343
|
+
> "Uses atomic writes (temp file + rename) to prevent corruption" - progress.txt
|
|
344
|
+
|
|
345
|
+
**Classification:** Constitutional - Applies to all file-modifying operations across features
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**User Response:** "APPROVE PROP-C01"
|
|
349
|
+
|
|
350
|
+
**Applied:** constitution.md v2.0.1 updated with new SHOULD rule
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## Notes
|
|
355
|
+
|
|
356
|
+
- This skill is **opt-in** - only run after user decides to capture learnings
|
|
357
|
+
- Maximum 10 proposals per feature to avoid overwhelming the user
|
|
358
|
+
- Use extraction scripts to minimize context usage
|
|
359
|
+
- Human approval required for all amendments
|
|
360
|
+
- Stats file is for transparency, not agent context
|
|
361
|
+
- Session context extraction is available for deeper investigation when needed
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# common.sh - Shared functions for learning extraction scripts
|
|
3
|
+
|
|
4
|
+
# Detect available search tool (prefer ripgrep for speed)
|
|
5
|
+
detect_grep() {
|
|
6
|
+
if command -v rg >/dev/null 2>&1; then
|
|
7
|
+
echo "rg"
|
|
8
|
+
else
|
|
9
|
+
echo "grep"
|
|
10
|
+
fi
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
# Escape string for JSON
|
|
14
|
+
json_escape() {
|
|
15
|
+
local str="$1"
|
|
16
|
+
# Escape backslashes, quotes, and control characters
|
|
17
|
+
printf '%s' "$str" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/\t/\\t/g' | tr '\n' ' '
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
# Convert array of strings to JSON array
|
|
21
|
+
to_json_array() {
|
|
22
|
+
local first=true
|
|
23
|
+
echo -n "["
|
|
24
|
+
while IFS= read -r line; do
|
|
25
|
+
[[ -z "$line" ]] && continue
|
|
26
|
+
if [[ "$first" == "true" ]]; then
|
|
27
|
+
first=false
|
|
28
|
+
else
|
|
29
|
+
echo -n ","
|
|
30
|
+
fi
|
|
31
|
+
echo -n "\"$(json_escape "$line")\""
|
|
32
|
+
done
|
|
33
|
+
echo "]"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# Extract feature name from path
|
|
37
|
+
get_feature_name() {
|
|
38
|
+
local path="$1"
|
|
39
|
+
basename "$path"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# Check if file exists and is readable
|
|
43
|
+
check_file() {
|
|
44
|
+
local path="$1"
|
|
45
|
+
[[ -f "$path" && -r "$path" ]]
|
|
46
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# extract-costs.sh - Extract cost data from prd.json
|
|
3
|
+
# Output: JSON object with cost statistics
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
FEATURE_PATH="${1:-}"
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
|
|
10
|
+
source "$SCRIPT_DIR/common.sh"
|
|
11
|
+
|
|
12
|
+
if [[ -z "$FEATURE_PATH" ]]; then
|
|
13
|
+
echo "{}"
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
PRD_FILE="$FEATURE_PATH/prd.json"
|
|
18
|
+
|
|
19
|
+
if ! check_file "$PRD_FILE"; then
|
|
20
|
+
echo "{}"
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Check if jq is available
|
|
25
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
26
|
+
# Minimal fallback without jq
|
|
27
|
+
FEATURE_NAME=$(get_feature_name "$FEATURE_PATH")
|
|
28
|
+
echo "{\"feature\": \"$FEATURE_NAME\", \"note\": \"jq not available for detailed extraction\"}"
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Extract cost data using jq
|
|
33
|
+
jq '{
|
|
34
|
+
feature: (.branchName // .project // "unknown"),
|
|
35
|
+
totalStories: (.userStories | length),
|
|
36
|
+
completedStories: ([.userStories[] | select(.passes == true)] | length),
|
|
37
|
+
skippedStories: ([.userStories[] | select(.skipped == true)] | length),
|
|
38
|
+
storiesWithRouting: ([.userStories[] | select(.routing != null)] | length),
|
|
39
|
+
estimatedCost: ([.userStories[].routing.estimatedCost // 0] | add),
|
|
40
|
+
actualCost: ([.userStories[].execution.actualCost // 0] | add),
|
|
41
|
+
escalations: ([.userStories[] | select(.execution.attempts != null and .execution.attempts > 1)] | length),
|
|
42
|
+
complexityBreakdown: {
|
|
43
|
+
simple: ([.userStories[] | select(.routing.complexity == "simple")] | length),
|
|
44
|
+
medium: ([.userStories[] | select(.routing.complexity == "medium")] | length),
|
|
45
|
+
complex: ([.userStories[] | select(.routing.complexity == "complex")] | length),
|
|
46
|
+
expert: ([.userStories[] | select(.routing.complexity == "expert")] | length)
|
|
47
|
+
}
|
|
48
|
+
}' "$PRD_FILE" 2>/dev/null || echo "{}"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# extract-errors.sh - Extract error patterns from progress.txt
|
|
3
|
+
# Output: JSON array of error-related lines
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
FEATURE_PATH="${1:-}"
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
|
|
10
|
+
source "$SCRIPT_DIR/common.sh"
|
|
11
|
+
|
|
12
|
+
if [[ -z "$FEATURE_PATH" ]]; then
|
|
13
|
+
echo "[]"
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
PROGRESS_FILE="$FEATURE_PATH/progress.txt"
|
|
18
|
+
|
|
19
|
+
if ! check_file "$PROGRESS_FILE"; then
|
|
20
|
+
echo "[]"
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
GREP_CMD=$(detect_grep)
|
|
25
|
+
|
|
26
|
+
# Extract error-related lines (case-insensitive)
|
|
27
|
+
errors=()
|
|
28
|
+
|
|
29
|
+
if [[ "$GREP_CMD" == "rg" ]]; then
|
|
30
|
+
while IFS= read -r line; do
|
|
31
|
+
# Clean up the line
|
|
32
|
+
cleaned=$(echo "$line" | sed -E 's/^\s*[-*]\s*//' | tr -s ' ')
|
|
33
|
+
[[ -n "$cleaned" ]] && errors+=("$cleaned")
|
|
34
|
+
done < <(rg -i --no-filename '(error|failed|bug|fix|issue|problem|warning)' "$PROGRESS_FILE" 2>/dev/null | head -15)
|
|
35
|
+
else
|
|
36
|
+
while IFS= read -r line; do
|
|
37
|
+
cleaned=$(echo "$line" | sed -E 's/^\s*[-*]\s*//' | tr -s ' ')
|
|
38
|
+
[[ -n "$cleaned" ]] && errors+=("$cleaned")
|
|
39
|
+
done < <(grep -i -E '(error|failed|bug|fix|issue|problem|warning)' "$PROGRESS_FILE" 2>/dev/null | head -15)
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Deduplicate and output as JSON array
|
|
43
|
+
if [[ ${#errors[@]} -eq 0 ]]; then
|
|
44
|
+
echo "[]"
|
|
45
|
+
else
|
|
46
|
+
printf '%s\n' "${errors[@]}" | sort -u | head -10 | to_json_array
|
|
47
|
+
fi
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# extract-failures.sh - Extract failed checks from checklist.md
|
|
3
|
+
# Output: JSON array of unchecked items
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
FEATURE_PATH="${1:-}"
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
|
|
10
|
+
source "$SCRIPT_DIR/common.sh"
|
|
11
|
+
|
|
12
|
+
if [[ -z "$FEATURE_PATH" ]]; then
|
|
13
|
+
echo "[]"
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
CHECKLIST_FILE="$FEATURE_PATH/checklist.md"
|
|
18
|
+
|
|
19
|
+
if ! check_file "$CHECKLIST_FILE"; then
|
|
20
|
+
echo "[]"
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
GREP_CMD=$(detect_grep)
|
|
25
|
+
|
|
26
|
+
# Extract unchecked items (- [ ] or * [ ])
|
|
27
|
+
failures=()
|
|
28
|
+
|
|
29
|
+
if [[ "$GREP_CMD" == "rg" ]]; then
|
|
30
|
+
while IFS= read -r line; do
|
|
31
|
+
# Clean up the line (remove checkbox prefix)
|
|
32
|
+
cleaned=$(echo "$line" | sed -E 's/^\s*[-*]\s*\[ \]\s*//')
|
|
33
|
+
[[ -n "$cleaned" ]] && failures+=("$cleaned")
|
|
34
|
+
done < <(rg --no-filename '^\s*[-*]\s*\[ \]' "$CHECKLIST_FILE" 2>/dev/null | head -10)
|
|
35
|
+
else
|
|
36
|
+
while IFS= read -r line; do
|
|
37
|
+
cleaned=$(echo "$line" | sed -E 's/^\s*[-*]\s*\[ \]\s*//')
|
|
38
|
+
[[ -n "$cleaned" ]] && failures+=("$cleaned")
|
|
39
|
+
done < <(grep -E '^\s*[-*]\s*\[ \]' "$CHECKLIST_FILE" 2>/dev/null | head -10)
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Output as JSON array
|
|
43
|
+
if [[ ${#failures[@]} -eq 0 ]]; then
|
|
44
|
+
echo "[]"
|
|
45
|
+
else
|
|
46
|
+
printf '%s\n' "${failures[@]}" | to_json_array
|
|
47
|
+
fi
|