devflow-kit 1.0.0 → 1.1.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/CHANGELOG.md +30 -0
- package/README.md +13 -6
- package/dist/cli.js +5 -1
- package/dist/commands/ambient.d.ts +18 -0
- package/dist/commands/ambient.js +136 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +97 -10
- package/dist/commands/memory.d.ts +22 -0
- package/dist/commands/memory.js +175 -0
- package/dist/commands/uninstall.js +72 -5
- package/dist/plugins.js +8 -1
- package/dist/utils/post-install.d.ts +12 -0
- package/dist/utils/post-install.js +82 -1
- package/dist/utils/safe-delete-install.d.ts +7 -0
- package/dist/utils/safe-delete-install.js +40 -5
- package/package.json +1 -1
- package/plugins/devflow-ambient/.claude-plugin/plugin.json +7 -0
- package/plugins/devflow-ambient/README.md +49 -0
- package/plugins/devflow-ambient/commands/ambient.md +110 -0
- package/plugins/devflow-ambient/skills/ambient-router/SKILL.md +89 -0
- package/plugins/devflow-ambient/skills/ambient-router/references/skill-catalog.md +64 -0
- package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-code-review/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-core-skills/.claude-plugin/plugin.json +2 -1
- package/plugins/devflow-core-skills/skills/docs-framework/SKILL.md +10 -6
- package/plugins/devflow-core-skills/skills/test-driven-development/SKILL.md +139 -0
- package/plugins/devflow-core-skills/skills/test-driven-development/references/rationalization-prevention.md +111 -0
- package/plugins/devflow-debug/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-implement/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-resolve/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-self-review/.claude-plugin/plugin.json +1 -1
- package/plugins/devflow-specify/.claude-plugin/plugin.json +1 -1
- package/scripts/hooks/ambient-prompt.sh +48 -0
- package/scripts/hooks/background-memory-update.sh +49 -8
- package/scripts/hooks/ensure-memory-gitignore.sh +17 -0
- package/scripts/hooks/pre-compact-memory.sh +12 -6
- package/scripts/hooks/session-start-memory.sh +50 -8
- package/scripts/hooks/stop-update-memory.sh +10 -6
- package/shared/skills/ambient-router/SKILL.md +89 -0
- package/shared/skills/ambient-router/references/skill-catalog.md +64 -0
- package/shared/skills/docs-framework/SKILL.md +10 -6
- package/shared/skills/test-driven-development/SKILL.md +139 -0
- package/shared/skills/test-driven-development/references/rationalization-prevention.md +111 -0
- package/src/templates/managed-settings.json +14 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Ambient Router — Skill Catalog
|
|
2
|
+
|
|
3
|
+
Full mapping of DevFlow skills to ambient intents and file-type triggers. The ambient-router SKILL.md references this for detailed selection logic.
|
|
4
|
+
|
|
5
|
+
## Skills Available for Ambient Loading
|
|
6
|
+
|
|
7
|
+
These skills may be loaded during STANDARD-depth ambient routing.
|
|
8
|
+
|
|
9
|
+
### BUILD Intent
|
|
10
|
+
|
|
11
|
+
| Skill | When to Load | File Patterns |
|
|
12
|
+
|-------|-------------|---------------|
|
|
13
|
+
| test-driven-development | Always for BUILD | `*.ts`, `*.tsx`, `*.js`, `*.jsx`, `*.py` |
|
|
14
|
+
| implementation-patterns | Always for BUILD | Any code file |
|
|
15
|
+
| typescript | TypeScript files in scope | `*.ts`, `*.tsx` |
|
|
16
|
+
| react | React components in scope | `*.tsx`, `*.jsx` |
|
|
17
|
+
| frontend-design | UI/styling work | `*.css`, `*.scss`, `*.tsx` with styling keywords |
|
|
18
|
+
| input-validation | Forms, APIs, user input | Files with form/input/validation keywords |
|
|
19
|
+
| security-patterns | Auth, crypto, secrets | Files with auth/token/crypto/password keywords |
|
|
20
|
+
|
|
21
|
+
### DEBUG Intent
|
|
22
|
+
|
|
23
|
+
| Skill | When to Load | File Patterns |
|
|
24
|
+
|-------|-------------|---------------|
|
|
25
|
+
| test-patterns | Always for DEBUG | Any test-related context |
|
|
26
|
+
| core-patterns | Always for DEBUG | Any code file |
|
|
27
|
+
| git-safety | Git operations involved | User mentions git, rebase, merge, etc. |
|
|
28
|
+
|
|
29
|
+
### REVIEW Intent
|
|
30
|
+
|
|
31
|
+
| Skill | When to Load | File Patterns |
|
|
32
|
+
|-------|-------------|---------------|
|
|
33
|
+
| self-review | Always for REVIEW | Any code file |
|
|
34
|
+
| core-patterns | Always for REVIEW | Any code file |
|
|
35
|
+
| test-patterns | Test files in scope | `*.test.*`, `*.spec.*` |
|
|
36
|
+
|
|
37
|
+
### PLAN Intent
|
|
38
|
+
|
|
39
|
+
| Skill | When to Load | File Patterns |
|
|
40
|
+
|-------|-------------|---------------|
|
|
41
|
+
| implementation-patterns | Always for PLAN | Any planning context |
|
|
42
|
+
| core-patterns | Architectural planning | System design discussions |
|
|
43
|
+
|
|
44
|
+
## Skills Excluded from Ambient
|
|
45
|
+
|
|
46
|
+
These skills are loaded only by explicit DevFlow commands (primarily `/code-review`):
|
|
47
|
+
|
|
48
|
+
- review-methodology — Full review process (6-step, 3-category classification)
|
|
49
|
+
- complexity-patterns — Cyclomatic complexity, deep nesting analysis
|
|
50
|
+
- consistency-patterns — Naming convention, pattern deviation detection
|
|
51
|
+
- database-patterns — Index analysis, query optimization, migration safety
|
|
52
|
+
- dependencies-patterns — CVE detection, license audit, outdated packages
|
|
53
|
+
- documentation-patterns — Doc drift, stale comments, missing API docs
|
|
54
|
+
- regression-patterns — Lost functionality, broken exports, behavioral changes
|
|
55
|
+
- architecture-patterns — SOLID analysis, coupling detection, layering issues
|
|
56
|
+
- accessibility — WCAG compliance, ARIA roles, keyboard navigation
|
|
57
|
+
- performance-patterns — N+1 queries, memory leaks, caching opportunities
|
|
58
|
+
|
|
59
|
+
## Selection Limits
|
|
60
|
+
|
|
61
|
+
- **Maximum 3 skills** per ambient response (primary + up to 2 secondary)
|
|
62
|
+
- **Primary skills** are always loaded for the classified intent
|
|
63
|
+
- **Secondary skills** are loaded only when file patterns match conversation context
|
|
64
|
+
- If more than 3 skills seem relevant, this is an ESCALATE signal
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "DevFlow Contributors",
|
|
6
6
|
"email": "dean@keren.dev"
|
|
7
7
|
},
|
|
8
|
-
"version": "1.
|
|
8
|
+
"version": "1.1.0",
|
|
9
9
|
"homepage": "https://github.com/dean0x/devflow",
|
|
10
10
|
"repository": "https://github.com/dean0x/devflow",
|
|
11
11
|
"license": "MIT",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"github-patterns",
|
|
22
22
|
"input-validation",
|
|
23
23
|
"react",
|
|
24
|
+
"test-driven-development",
|
|
24
25
|
"test-patterns",
|
|
25
26
|
"typescript"
|
|
26
27
|
]
|
|
@@ -32,10 +32,14 @@ All generated documentation lives under `.docs/` in the project root:
|
|
|
32
32
|
│ ├── {timestamp}.md
|
|
33
33
|
│ ├── compact/{timestamp}.md
|
|
34
34
|
│ └── INDEX.md
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
└── swarm/ # Swarm operation state
|
|
36
|
+
├── state.json
|
|
37
|
+
└── plans/
|
|
38
|
+
|
|
39
|
+
.memory/
|
|
40
|
+
├── WORKING-MEMORY.md # Auto-maintained by Stop hook (overwritten)
|
|
41
|
+
├── PROJECT-PATTERNS.md # Accumulated patterns (merged across sessions)
|
|
42
|
+
└── backup.json # Pre-compact git state snapshot
|
|
39
43
|
```
|
|
40
44
|
|
|
41
45
|
---
|
|
@@ -92,7 +96,7 @@ source .devflow/scripts/docs-helpers.sh 2>/dev/null || {
|
|
|
92
96
|
| Agent | Output Location | Behavior |
|
|
93
97
|
|-------|-----------------|----------|
|
|
94
98
|
| Reviewer | `.docs/reviews/{branch-slug}/{type}-report.{timestamp}.md` | Creates new |
|
|
95
|
-
| Working Memory | `.
|
|
99
|
+
| Working Memory | `.memory/WORKING-MEMORY.md` | Overwrites (auto-maintained by Stop hook) |
|
|
96
100
|
|
|
97
101
|
### Agents That Don't Persist
|
|
98
102
|
|
|
@@ -120,7 +124,7 @@ When creating or modifying persisting agents:
|
|
|
120
124
|
|
|
121
125
|
This framework is used by:
|
|
122
126
|
- **Review agents**: Creates review reports
|
|
123
|
-
- **Working Memory hooks**: Auto-maintains `.
|
|
127
|
+
- **Working Memory hooks**: Auto-maintains `.memory/WORKING-MEMORY.md`
|
|
124
128
|
|
|
125
129
|
All persisting agents should load this skill to ensure consistent documentation.
|
|
126
130
|
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-driven-development
|
|
3
|
+
description: >-
|
|
4
|
+
Enforce RED-GREEN-REFACTOR cycle during implementation. Write failing tests before
|
|
5
|
+
production code. Distinct from test-patterns (which reviews test quality) — this
|
|
6
|
+
skill enforces the TDD workflow during code generation.
|
|
7
|
+
user-invocable: false
|
|
8
|
+
allowed-tools: Read, Grep, Glob
|
|
9
|
+
activation:
|
|
10
|
+
file-patterns:
|
|
11
|
+
- "**/*.ts"
|
|
12
|
+
- "**/*.tsx"
|
|
13
|
+
- "**/*.js"
|
|
14
|
+
- "**/*.jsx"
|
|
15
|
+
- "**/*.py"
|
|
16
|
+
exclude:
|
|
17
|
+
- "node_modules/**"
|
|
18
|
+
- "dist/**"
|
|
19
|
+
- "**/*.test.*"
|
|
20
|
+
- "**/*.spec.*"
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# Test-Driven Development
|
|
24
|
+
|
|
25
|
+
Enforce the RED-GREEN-REFACTOR cycle for all implementation work. Tests define the design. Code satisfies the tests. Refactoring improves the design without changing behavior.
|
|
26
|
+
|
|
27
|
+
## Iron Law
|
|
28
|
+
|
|
29
|
+
> **TESTS FIRST, ALWAYS**
|
|
30
|
+
>
|
|
31
|
+
> Write the failing test before the production code. No exceptions. If you catch
|
|
32
|
+
> yourself writing production code without a failing test, stop immediately, delete
|
|
33
|
+
> the production code, write the test, watch it fail, then write the minimum code
|
|
34
|
+
> to make it pass. The test IS the specification.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## The Cycle
|
|
39
|
+
|
|
40
|
+
### Step 1: RED — Write a Failing Test
|
|
41
|
+
|
|
42
|
+
Write a test that describes the behavior you want. Run it. Watch it fail. The failure message IS your specification.
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Describe what the code SHOULD do, not how it does it.
|
|
46
|
+
One behavior per test. One assertion per test (ideally).
|
|
47
|
+
Name tests as sentences: "returns error when email is invalid"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Checkpoint:** The test MUST fail before proceeding. A test that passes immediately proves nothing.
|
|
51
|
+
|
|
52
|
+
### Step 2: GREEN — Write Minimum Code to Pass
|
|
53
|
+
|
|
54
|
+
Write the simplest production code that makes the failing test pass. No more, no less.
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
Hardcode first if that's simplest. Generalize when the next test forces it.
|
|
58
|
+
Don't write code "you'll need later." Write code the test demands NOW.
|
|
59
|
+
Don't optimize. Don't refactor. Don't clean up. Just pass the test.
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Checkpoint:** All tests pass. If any test fails, fix it before moving on.
|
|
63
|
+
|
|
64
|
+
### Step 3: REFACTOR — Improve Without Changing Behavior
|
|
65
|
+
|
|
66
|
+
Now clean up. Extract helpers, rename variables, simplify logic. Tests stay green throughout.
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
Run tests after every refactoring step.
|
|
70
|
+
If a test breaks during refactor, undo immediately — you changed behavior.
|
|
71
|
+
Apply DRY, extract patterns, improve readability.
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Checkpoint:** All tests still pass. Code is clean. Repeat from Step 1 for next behavior.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Rationalization Prevention
|
|
79
|
+
|
|
80
|
+
These are the excuses developers use to skip TDD. Recognize and reject them.
|
|
81
|
+
|
|
82
|
+
| Excuse | Why It Feels Right | Why It's Wrong | Correct Action |
|
|
83
|
+
|--------|-------------------|---------------|----------------|
|
|
84
|
+
| "I'll write tests after" | Need to see the shape first | Tests ARE the shape — they define the interface before implementation exists | Write the test first |
|
|
85
|
+
| "Too simple to test" | It's just a getter/setter | Getters break, defaults change, edge cases hide in "simple" code | Write it — takes 30 seconds |
|
|
86
|
+
| "I'll refactor later" | Just get it working now | "Later" never comes; technical debt compounds silently | Refactor now in Step 3 |
|
|
87
|
+
| "Test is too hard to write" | Setup is complex, mocking is painful | Hard-to-test code = bad design; the test is telling you the interface is wrong | Simplify the interface first |
|
|
88
|
+
| "Need to see the whole picture" | Can't test what I haven't designed yet | TDD IS design; each test reveals the next piece of the interface | Let the test guide the design |
|
|
89
|
+
| "Tests slow me down" | Faster to just write the code | Faster until the first regression; TDD is faster for anything > 50 lines | Trust the cycle |
|
|
90
|
+
|
|
91
|
+
See `references/rationalization-prevention.md` for extended examples with code.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Process Enforcement
|
|
96
|
+
|
|
97
|
+
When implementing any feature under ambient BUILD/STANDARD:
|
|
98
|
+
|
|
99
|
+
1. **Identify the first behavior** — What is the simplest thing this feature must do?
|
|
100
|
+
2. **Write the test** — Describe that behavior as a failing test
|
|
101
|
+
3. **Run the test** — Confirm it fails (RED)
|
|
102
|
+
4. **Write minimum code** — Just enough to pass (GREEN)
|
|
103
|
+
5. **Refactor** — Clean up while tests stay green (REFACTOR)
|
|
104
|
+
6. **Repeat** — Next behavior, next test, next cycle
|
|
105
|
+
|
|
106
|
+
### File Organization
|
|
107
|
+
|
|
108
|
+
- Test file lives next to production file: `user.ts` → `user.test.ts`
|
|
109
|
+
- Follow project's existing test conventions (Jest, Vitest, pytest, etc.)
|
|
110
|
+
- Import the module under test, not internal helpers
|
|
111
|
+
|
|
112
|
+
### What to Test
|
|
113
|
+
|
|
114
|
+
| Test | Don't Test |
|
|
115
|
+
|------|-----------|
|
|
116
|
+
| Public API behavior | Private implementation details |
|
|
117
|
+
| Error conditions and edge cases | Framework internals |
|
|
118
|
+
| Integration points (boundaries) | Third-party library correctness |
|
|
119
|
+
| State transitions | Getter/setter plumbing (unless non-trivial) |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## When TDD Does Not Apply
|
|
124
|
+
|
|
125
|
+
- **QUICK depth** — Ambient classified as QUICK (chat, exploration, trivial edits)
|
|
126
|
+
- **Non-code tasks** — Documentation, configuration, CI changes
|
|
127
|
+
- **Exploratory prototyping** — User explicitly says "just spike this" or "prototype"
|
|
128
|
+
- **Existing test suite changes** — Modifying tests themselves (test-patterns skill applies instead)
|
|
129
|
+
|
|
130
|
+
When skipping TDD, never rationalize. State clearly: "Skipping TDD because: [specific reason from list above]."
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Integration with Ambient Mode
|
|
135
|
+
|
|
136
|
+
- **BUILD/STANDARD** → TDD enforced. Every new function/method gets test-first treatment.
|
|
137
|
+
- **BUILD/QUICK** → TDD skipped (trivial single-file edit).
|
|
138
|
+
- **BUILD/ESCALATE** → TDD mentioned in nudge toward `/implement`.
|
|
139
|
+
- **DEBUG/STANDARD** → TDD applies to the fix: write a test that reproduces the bug first, then fix.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# TDD Rationalization Prevention — Extended Examples
|
|
2
|
+
|
|
3
|
+
Detailed code examples showing how each rationalization leads to worse outcomes.
|
|
4
|
+
|
|
5
|
+
## "I'll write tests after"
|
|
6
|
+
|
|
7
|
+
### What happens:
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
// Developer writes production code first
|
|
11
|
+
function calculateDiscount(price: number, tier: string): number {
|
|
12
|
+
if (tier === 'gold') return price * 0.8;
|
|
13
|
+
if (tier === 'silver') return price * 0.9;
|
|
14
|
+
return price;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Then "writes tests after" — but only for the happy path they remember
|
|
18
|
+
test('gold tier gets 20% off', () => {
|
|
19
|
+
expect(calculateDiscount(100, 'gold')).toBe(80);
|
|
20
|
+
});
|
|
21
|
+
// Missing: negative prices, unknown tiers, zero prices, NaN handling
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### What TDD would have caught:
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
// Test first — forces you to think about the contract
|
|
28
|
+
test('returns error for negative price', () => {
|
|
29
|
+
expect(calculateDiscount(-100, 'gold')).toEqual({ ok: false, error: 'NEGATIVE_PRICE' });
|
|
30
|
+
});
|
|
31
|
+
// Now the interface includes error handling from the start
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## "Too simple to test"
|
|
35
|
+
|
|
36
|
+
### What happens:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
// "It's just a config getter, no test needed"
|
|
40
|
+
function getMaxRetries(): number {
|
|
41
|
+
return parseInt(process.env.MAX_RETRIES || '3');
|
|
42
|
+
}
|
|
43
|
+
// 6 months later: someone sets MAX_RETRIES="three" and prod crashes with NaN retries
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### What TDD would have caught:
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
test('returns default when env var is not a number', () => {
|
|
50
|
+
process.env.MAX_RETRIES = 'three';
|
|
51
|
+
expect(getMaxRetries()).toBe(3); // Forces validation logic
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## "Test is too hard to write"
|
|
56
|
+
|
|
57
|
+
### What happens:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// "I can't test this easily because it needs database + email + filesystem"
|
|
61
|
+
async function processOrder(orderId: string) {
|
|
62
|
+
const db = new Database();
|
|
63
|
+
const order = await db.find(orderId);
|
|
64
|
+
await sendEmail(order.customerEmail, 'Your order is processing');
|
|
65
|
+
await fs.writeFile(`/invoices/${orderId}.pdf`, generateInvoice(order));
|
|
66
|
+
await db.update(orderId, { status: 'processing' });
|
|
67
|
+
}
|
|
68
|
+
// Result: untestable monolith, test would need real DB + email + filesystem
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### What TDD forces:
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
// Hard-to-test = bad design. TDD forces dependency injection:
|
|
75
|
+
async function processOrder(
|
|
76
|
+
orderId: string,
|
|
77
|
+
deps: { db: OrderRepository; emailer: Emailer; invoices: InvoiceStore }
|
|
78
|
+
): Promise<Result<void, OrderError>> {
|
|
79
|
+
// Now trivially testable with mocks
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## "I'll refactor later"
|
|
84
|
+
|
|
85
|
+
### What happens:
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
// Sprint 1: "just get it working"
|
|
89
|
+
function handleRequest(req: any) {
|
|
90
|
+
if (req.type === 'create') { /* 50 lines */ }
|
|
91
|
+
else if (req.type === 'update') { /* 50 lines */ }
|
|
92
|
+
else if (req.type === 'delete') { /* 30 lines */ }
|
|
93
|
+
// Sprint 2-10: more conditions added, function grows to 500 lines
|
|
94
|
+
// "Refactor later" never comes because nobody wants to touch it
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### What TDD enforces:
|
|
99
|
+
|
|
100
|
+
Step 3 (REFACTOR) happens every cycle. The function never grows beyond what's clean because you clean it every 5-10 minutes.
|
|
101
|
+
|
|
102
|
+
## "Tests slow me down"
|
|
103
|
+
|
|
104
|
+
### The math:
|
|
105
|
+
|
|
106
|
+
| Approach | Time to write | Time to first bug | Time to fix bug | Total (1 month) |
|
|
107
|
+
|----------|:---:|:---:|:---:|:---:|
|
|
108
|
+
| No TDD | 2h | 4h | 3h (no repro test) | 9h+ |
|
|
109
|
+
| TDD | 3h | Caught in test | 15min (test pinpoints) | 3h 15min |
|
|
110
|
+
|
|
111
|
+
TDD is slower for the first 30 minutes. It's faster for everything after that.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devflow-self-review",
|
|
3
3
|
"description": "Self-review workflow: Simplifier + Scrutinizer for code quality",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"agents": ["simplifier", "scrutinizer", "validator"],
|
|
6
6
|
"skills": ["self-review", "core-patterns"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Ambient Mode: UserPromptSubmit Hook
|
|
4
|
+
# Injects a classification preamble before every user prompt so Claude applies
|
|
5
|
+
# relevant skill loading via the ambient-router skill.
|
|
6
|
+
# Zero file I/O beyond stdin — static injection only.
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
# jq is required to parse hook input JSON — silently no-op if missing
|
|
11
|
+
if ! command -v jq &>/dev/null; then exit 0; fi
|
|
12
|
+
|
|
13
|
+
INPUT=$(cat)
|
|
14
|
+
|
|
15
|
+
CWD=$(echo "$INPUT" | jq -r '.cwd // ""' 2>/dev/null)
|
|
16
|
+
if [ -z "$CWD" ]; then
|
|
17
|
+
exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
PROMPT=$(echo "$INPUT" | jq -r '.prompt // ""' 2>/dev/null)
|
|
21
|
+
|
|
22
|
+
# Skip slash commands — they have their own orchestration
|
|
23
|
+
if [[ "$PROMPT" == /* ]]; then
|
|
24
|
+
exit 0
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Skip single-word confirmations (< 2 words)
|
|
28
|
+
WORD_COUNT=$(echo "$PROMPT" | wc -w | tr -d ' ')
|
|
29
|
+
if [ "$WORD_COUNT" -lt 2 ]; then
|
|
30
|
+
exit 0
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Inject classification preamble
|
|
34
|
+
PREAMBLE="AMBIENT MODE ACTIVE: Before responding, silently classify this prompt:
|
|
35
|
+
Intent: BUILD | DEBUG | REVIEW | PLAN | EXPLORE | CHAT
|
|
36
|
+
Depth: QUICK (no overhead) | STANDARD (load skills) | ESCALATE (suggest /command)
|
|
37
|
+
|
|
38
|
+
If STANDARD+: Read the ambient-router skill for classification details and skill selection matrix. For BUILD tasks, also load test-driven-development skill and enforce RED-GREEN-REFACTOR.
|
|
39
|
+
|
|
40
|
+
If QUICK: Respond normally without stating classification.
|
|
41
|
+
Only state classification aloud for STANDARD/ESCALATE."
|
|
42
|
+
|
|
43
|
+
jq -n --arg ctx "$PREAMBLE" '{
|
|
44
|
+
"hookSpecificOutput": {
|
|
45
|
+
"hookEventName": "UserPromptSubmit",
|
|
46
|
+
"additionalContext": $ctx
|
|
47
|
+
}
|
|
48
|
+
}'
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Background Working Memory Updater
|
|
4
4
|
# Called by stop-update-memory.sh as a detached background process.
|
|
5
|
-
# Resumes the parent session headlessly to update .
|
|
5
|
+
# Resumes the parent session headlessly to update .memory/WORKING-MEMORY.md.
|
|
6
6
|
# On failure: logs error, does nothing (no fallback).
|
|
7
7
|
|
|
8
8
|
set -euo pipefail
|
|
@@ -12,8 +12,8 @@ SESSION_ID="$2"
|
|
|
12
12
|
MEMORY_FILE="$3"
|
|
13
13
|
CLAUDE_BIN="$4"
|
|
14
14
|
|
|
15
|
-
LOG_FILE="$CWD/.
|
|
16
|
-
LOCK_DIR="$CWD/.
|
|
15
|
+
LOG_FILE="$CWD/.memory/.working-memory-update.log"
|
|
16
|
+
LOCK_DIR="$CWD/.memory/.working-memory.lock"
|
|
17
17
|
|
|
18
18
|
# --- Logging ---
|
|
19
19
|
|
|
@@ -102,20 +102,60 @@ fi
|
|
|
102
102
|
|
|
103
103
|
# Build instruction
|
|
104
104
|
if [ -n "$EXISTING_MEMORY" ]; then
|
|
105
|
-
|
|
105
|
+
PATTERNS_INSTRUCTION=""
|
|
106
|
+
PATTERNS_FILE="$CWD/.memory/PROJECT-PATTERNS.md"
|
|
107
|
+
EXISTING_PATTERNS=""
|
|
108
|
+
if [ -f "$PATTERNS_FILE" ]; then
|
|
109
|
+
EXISTING_PATTERNS=$(cat "$PATTERNS_FILE")
|
|
110
|
+
PATTERNS_INSTRUCTION="
|
|
111
|
+
|
|
112
|
+
Also update $PATTERNS_FILE by APPENDING any new recurring patterns discovered during this session. Do NOT overwrite existing entries — only add new ones. Skip if no new patterns were observed. Format each entry as: - **Pattern name**: Brief description (discovered: YYYY-MM-DD). Keep patterns.md under 40 entries. When approaching the limit, consolidate related patterns into broader entries rather than adding duplicates.
|
|
113
|
+
|
|
114
|
+
Existing patterns:
|
|
115
|
+
$EXISTING_PATTERNS"
|
|
116
|
+
else
|
|
117
|
+
PATTERNS_INSTRUCTION="
|
|
118
|
+
|
|
119
|
+
If recurring patterns were observed during this session (coding conventions, architectural decisions, team preferences, tooling quirks), create $PATTERNS_FILE with entries formatted as: - **Pattern name**: Brief description (discovered: YYYY-MM-DD). Only create this file if genuine patterns were observed — do not fabricate entries."
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
INSTRUCTION="Update the file $MEMORY_FILE with working memory from this session. The file already has content — possibly from a concurrent session that just wrote it moments ago. Merge this session's context with the existing content to produce a single unified working memory snapshot. Both this session and the existing content represent fresh, concurrent work — integrate both fully. Working memory captures what's active now, not a changelog. Deduplicate overlapping information. Keep under 120 lines total. Use the same structure: ## Now, ## Progress, ## Decisions, ## Modified Files, ## Context, ## Session Log.
|
|
123
|
+
|
|
124
|
+
## Progress tracks Done (completed items), Remaining (next steps), and Blockers (if any). Keep each sub-list to 1-3 items. This section reflects current work state, not historical logs.
|
|
125
|
+
|
|
126
|
+
## Decisions entries must include date and status. Format: - **[Decision]** — [rationale] (YYYY-MM-DD) [ACTIVE|SUPERSEDED]. Mark superseded decisions rather than deleting them.${PATTERNS_INSTRUCTION}
|
|
106
127
|
|
|
107
128
|
Existing content:
|
|
108
129
|
$EXISTING_MEMORY"
|
|
109
130
|
else
|
|
110
|
-
|
|
131
|
+
PATTERNS_INSTRUCTION=""
|
|
132
|
+
PATTERNS_FILE="$CWD/.memory/PROJECT-PATTERNS.md"
|
|
133
|
+
if [ -f "$PATTERNS_FILE" ]; then
|
|
134
|
+
EXISTING_PATTERNS=$(cat "$PATTERNS_FILE")
|
|
135
|
+
PATTERNS_INSTRUCTION="
|
|
136
|
+
|
|
137
|
+
Also update $PATTERNS_FILE by APPENDING any new recurring patterns discovered during this session. Do NOT overwrite existing entries — only add new ones. Skip if no new patterns were observed. Format each entry as: - **Pattern name**: Brief description (discovered: YYYY-MM-DD). Keep patterns.md under 40 entries. When approaching the limit, consolidate related patterns into broader entries rather than adding duplicates.
|
|
138
|
+
|
|
139
|
+
Existing patterns:
|
|
140
|
+
$EXISTING_PATTERNS"
|
|
141
|
+
else
|
|
142
|
+
PATTERNS_INSTRUCTION="
|
|
143
|
+
|
|
144
|
+
If recurring patterns were observed during this session (coding conventions, architectural decisions, team preferences, tooling quirks), create $PATTERNS_FILE with entries formatted as: - **Pattern name**: Brief description (discovered: YYYY-MM-DD). Only create this file if genuine patterns were observed — do not fabricate entries."
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
INSTRUCTION="Create the file $MEMORY_FILE with working memory from this session. Keep under 120 lines. Use this structure:
|
|
111
148
|
|
|
112
149
|
# Working Memory
|
|
113
150
|
|
|
114
151
|
## Now
|
|
115
152
|
<!-- Current focus, status, blockers (1-3 bullets) -->
|
|
116
153
|
|
|
154
|
+
## Progress
|
|
155
|
+
<!-- Done: completed items (1-3). Remaining: next steps (1-3). Blockers: if any. -->
|
|
156
|
+
|
|
117
157
|
## Decisions
|
|
118
|
-
<!--
|
|
158
|
+
<!-- Format: - **[Decision]** — [rationale] (YYYY-MM-DD) [ACTIVE|SUPERSEDED] -->
|
|
119
159
|
|
|
120
160
|
## Modified Files
|
|
121
161
|
<!-- File paths only, most recent first -->
|
|
@@ -129,7 +169,7 @@ else
|
|
|
129
169
|
<!-- Chronological summary of work done today (2-5 bullets) -->
|
|
130
170
|
|
|
131
171
|
### This Week
|
|
132
|
-
<!-- Broader multi-day context if relevant
|
|
172
|
+
<!-- Broader multi-day context if relevant -->${PATTERNS_INSTRUCTION}"
|
|
133
173
|
fi
|
|
134
174
|
|
|
135
175
|
# Resume session headlessly to perform the update
|
|
@@ -138,7 +178,8 @@ TIMEOUT=120 # Normal runtime 30-60s; 2x margin
|
|
|
138
178
|
DEVFLOW_BG_UPDATER=1 env -u CLAUDECODE "$CLAUDE_BIN" -p \
|
|
139
179
|
--resume "$SESSION_ID" \
|
|
140
180
|
--model haiku \
|
|
141
|
-
--
|
|
181
|
+
--tools "Write" \
|
|
182
|
+
--allowedTools "Write($CWD/.memory/WORKING-MEMORY.md)" "Write($CWD/.memory/PROJECT-PATTERNS.md)" \
|
|
142
183
|
--no-session-persistence \
|
|
143
184
|
--output-format text \
|
|
144
185
|
"$INSTRUCTION" \
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Ensures .memory/ exists and .gitignore entries are configured.
|
|
3
|
+
# Called from stop and pre-compact hooks. Idempotent, ~1μs after first run.
|
|
4
|
+
# Usage: source ensure-memory-gitignore.sh "$CWD"
|
|
5
|
+
|
|
6
|
+
_MEMORY_DIR="$1/.memory"
|
|
7
|
+
|
|
8
|
+
# Create .memory/ if needed
|
|
9
|
+
mkdir -p "$_MEMORY_DIR" 2>/dev/null || return 1
|
|
10
|
+
|
|
11
|
+
# One-time .gitignore setup (marker prevents repeated checks)
|
|
12
|
+
if [ ! -f "$_MEMORY_DIR/.gitignore-configured" ] && [ -e "$1/.git" ]; then
|
|
13
|
+
for _entry in ".memory/" ".docs/"; do
|
|
14
|
+
grep -qxF "$_entry" "$1/.gitignore" 2>/dev/null || echo "$_entry" >> "$1/.gitignore"
|
|
15
|
+
done
|
|
16
|
+
touch "$_MEMORY_DIR/.gitignore-configured"
|
|
17
|
+
fi
|
|
@@ -18,12 +18,10 @@ if [ -z "$CWD" ]; then
|
|
|
18
18
|
exit 0
|
|
19
19
|
fi
|
|
20
20
|
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
exit 0
|
|
24
|
-
fi
|
|
21
|
+
# Auto-create .memory/ and ensure .gitignore entries (idempotent after first run)
|
|
22
|
+
source "$(cd "$(dirname "$0")" && pwd)/ensure-memory-gitignore.sh" "$CWD" || exit 0
|
|
25
23
|
|
|
26
|
-
BACKUP_FILE="$CWD/.
|
|
24
|
+
BACKUP_FILE="$CWD/.memory/backup.json"
|
|
27
25
|
|
|
28
26
|
# Capture git state
|
|
29
27
|
GIT_BRANCH=""
|
|
@@ -39,6 +37,12 @@ if cd "$CWD" 2>/dev/null && git rev-parse --git-dir >/dev/null 2>&1; then
|
|
|
39
37
|
GIT_DIFF_STAT=$(git diff --stat HEAD 2>/dev/null || echo "")
|
|
40
38
|
fi
|
|
41
39
|
|
|
40
|
+
# Snapshot current WORKING-MEMORY.md (preserves session context through compaction)
|
|
41
|
+
MEMORY_SNAPSHOT=""
|
|
42
|
+
if [ -f "$CWD/.memory/WORKING-MEMORY.md" ]; then
|
|
43
|
+
MEMORY_SNAPSHOT=$(cat "$CWD/.memory/WORKING-MEMORY.md")
|
|
44
|
+
fi
|
|
45
|
+
|
|
42
46
|
# Write backup JSON
|
|
43
47
|
jq -n \
|
|
44
48
|
--arg ts "$TIMESTAMP" \
|
|
@@ -46,9 +50,11 @@ jq -n \
|
|
|
46
50
|
--arg status "$GIT_STATUS" \
|
|
47
51
|
--arg log "$GIT_LOG" \
|
|
48
52
|
--arg diff "$GIT_DIFF_STAT" \
|
|
53
|
+
--arg memory "$MEMORY_SNAPSHOT" \
|
|
49
54
|
'{
|
|
50
55
|
timestamp: $ts,
|
|
51
56
|
trigger: "pre-compact",
|
|
57
|
+
memory_snapshot: $memory,
|
|
52
58
|
git: {
|
|
53
59
|
branch: $branch,
|
|
54
60
|
status: $status,
|
|
@@ -59,7 +65,7 @@ jq -n \
|
|
|
59
65
|
|
|
60
66
|
# Bootstrap minimal WORKING-MEMORY.md if none exists yet
|
|
61
67
|
# This ensures SessionStart has context to inject after compaction
|
|
62
|
-
MEMORY_FILE="$CWD/.
|
|
68
|
+
MEMORY_FILE="$CWD/.memory/WORKING-MEMORY.md"
|
|
63
69
|
if [ ! -f "$MEMORY_FILE" ] && [ -n "$GIT_BRANCH" ]; then
|
|
64
70
|
{
|
|
65
71
|
echo "# Working Memory"
|