oh-my-githubcopilot 1.5.7 → 1.8.0-alpha.021bf87
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-plugin/plugin.json +27 -5
- package/AGENTS.md +78 -9
- package/CHANGELOG.md +92 -0
- package/README.de.md +112 -26
- package/README.es.md +115 -29
- package/README.fr.md +114 -28
- package/README.it.md +114 -28
- package/README.ja.md +112 -26
- package/README.ko.md +112 -26
- package/README.md +96 -175
- package/README.pt.md +116 -30
- package/README.ru.md +116 -30
- package/README.tr.md +115 -29
- package/README.vi.md +116 -30
- package/README.zh.md +112 -26
- package/bin/omp.mjs +423 -19
- package/bin/omp.mjs.map +4 -4
- package/dist/hooks/keyword-detector.mjs +18 -3
- package/dist/hooks/keyword-detector.mjs.map +2 -2
- package/dist/mcp/server.mjs +28 -12
- package/dist/mcp/server.mjs.map +2 -2
- package/hooks/hooks.json +1 -1
- package/package.json +3 -2
- package/plugin.json +27 -5
- package/skills/ai-slop-cleaner/SKILL.md +137 -0
- package/skills/doctor/SKILL.md +188 -0
- package/skills/graph-context/SKILL.md +119 -0
- package/skills/improve-codebase-architecture/SKILL.md +214 -0
- package/skills/interactive-menu/SKILL.md +102 -0
- package/skills/interview/SKILL.md +203 -0
- package/skills/notifications/SKILL.md +190 -0
- package/skills/omp-doctor/SKILL.md +146 -0
- package/skills/omp-plan/SKILL.md +215 -4
- package/skills/omp-reference/SKILL.md +174 -0
- package/skills/ralplan/SKILL.md +148 -0
- package/skills/research/SKILL.md +149 -0
- package/skills/session/SKILL.md +220 -0
- package/skills/skillify/SKILL.md +66 -0
- package/skills/tdd/SKILL.md +246 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tdd
|
|
3
|
+
description: Test-Driven Development with Red-Green-Refactor cycle, vertical slices, and tracer bullets
|
|
4
|
+
triggers:
|
|
5
|
+
- /omp:tdd
|
|
6
|
+
- tdd:
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# TDD — Test-Driven Development
|
|
10
|
+
|
|
11
|
+
Use this skill when implementing any feature or bugfix using the Red-Green-Refactor cycle. Write the failing test first, write minimal code to pass it, then refactor.
|
|
12
|
+
|
|
13
|
+
## <Do_Not_Use_When>
|
|
14
|
+
|
|
15
|
+
- **Exploratory prototyping** — When you are still discovering the problem space and requirements are unclear, writing tests first creates a moving target and wastes cycles. Explore first, then TDD once the interface stabilizes.
|
|
16
|
+
- **One-off automation scripts** — Scripts with no expected reuse, no downstream consumers, and no need for regression coverage. A quick one-liner in a REPL is faster and cleaner.
|
|
17
|
+
- **Trivial boilerplate** — Generating getters/setters, scaffolding files, or copy-paste patterns that carry no behavioral logic.
|
|
18
|
+
- **UI/visual refinements** — Tweaking colors, spacing, or copy where the "right behavior" is subjective and visual inspection beats assertions.
|
|
19
|
+
- **Learning a new API** — When experimenting with unfamiliar SDKs or frameworks, write scratch code to build intuition first. Add tests once the API shape is stable.
|
|
20
|
+
- **Performance optimization passes** — Before measuring, you do not know what is slow. Tests written for correctness can conflict with benchmarks. Keep them separate.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Red-Green-Refactor Cycle
|
|
25
|
+
|
|
26
|
+
The core TDD loop has exactly three phases. Never skip or reorder them.
|
|
27
|
+
|
|
28
|
+
### RED: Write a focused failing test
|
|
29
|
+
Write a test that describes the behavior you want. Run it — it must fail. A test that passes before any implementation is written is not a test, it is a false signal.
|
|
30
|
+
|
|
31
|
+
### GREEN: Write minimal code to pass
|
|
32
|
+
Write the smallest amount of production code that makes the test pass. Do not write code for future requirements. Do not generalize. Make the test green and stop.
|
|
33
|
+
|
|
34
|
+
### REFACTOR: Clean up with tests green
|
|
35
|
+
With the test green, clean up the implementation — remove duplication, improve naming, extract deep modules. Run tests after every edit. If they go red, revert immediately.
|
|
36
|
+
|
|
37
|
+
Repeat this cycle for each behavioral slice.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## <Tool_Usage>
|
|
42
|
+
|
|
43
|
+
| Tool | When to Use |
|
|
44
|
+
|------|-------------|
|
|
45
|
+
| `Bash` (test runner) | Run `npm test`, `pytest`, `go test`, or equivalent to get fast per-file feedback during RED-GREEN cycles. |
|
|
46
|
+
| `Write` / `Edit` | Write failing test first (RED), then write minimal production code (GREEN), then clean up (REFACTOR). |
|
|
47
|
+
| `mcp__plugin_oh-my-claudecode_t__lsp_diagnostics` | Catch type errors and missing imports immediately after edits. |
|
|
48
|
+
| `mcp__plugin_oh-my-claudecode_t__lsp_diagnostics_directory` | Run full project diagnostics before marking a cycle done. |
|
|
49
|
+
| `Grep` | Find existing tests for the same module before writing a new one — avoid duplication. |
|
|
50
|
+
| `Glob` | Locate test files matching the module under development. |
|
|
51
|
+
|
|
52
|
+
**Typical cycle:**
|
|
53
|
+
1. Write a failing test (RED) — `Write` to the test file.
|
|
54
|
+
2. Run the test runner via `Bash` to confirm the failure.
|
|
55
|
+
3. Write minimal code to pass (GREEN) — `Edit` the production file.
|
|
56
|
+
4. Run diagnostics — `mcp__plugin_oh-my-claudecode_t__lsp_diagnostics` on both files.
|
|
57
|
+
5. Refactor (REFACTOR) — `Edit` production code, confirm tests stay green.
|
|
58
|
+
6. Repeat.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## <Why_This_Exists>
|
|
63
|
+
|
|
64
|
+
TDD provides a tight feedback loop that keeps implementation anchored to behavior. Without it, code grows inward — implementation details proliferate, coupling increases, and tests (when written at all) fight the code instead of guiding it.
|
|
65
|
+
|
|
66
|
+
The OMP-specific variant emphasizes **vertical slices via tracer bullets** rather than horizontal layering. Horizontal TDD (write all tests for Layer A, then all for Layer B) produces integration gaps: every layer compiles in isolation but the system fails end-to-end. Vertical TDD traces one complete path from user input to data storage before moving to the next slice, delivering working software incrementally.
|
|
67
|
+
|
|
68
|
+
Deep modules are preferred because they minimize the interface surface you must test, making each test more powerful and easier to reason about. A large, well-hidden implementation behind a small interface is easier to verify, easier to refactor, and cheaper to change.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## <Examples>
|
|
73
|
+
|
|
74
|
+
### RED: Write a focused failing test
|
|
75
|
+
|
|
76
|
+
A test for a user-authentication module:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// auth.test.ts
|
|
80
|
+
import { authenticate } from './auth';
|
|
81
|
+
|
|
82
|
+
describe('authenticate', () => {
|
|
83
|
+
it('returns a session token when credentials are valid', async () => {
|
|
84
|
+
const token = await authenticate({ username: 'alice', password: 'secret123' });
|
|
85
|
+
expect(token).toMatch(/^[a-z0-9]{32}$/);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('throws AuthError when password is incorrect', async () => {
|
|
89
|
+
await expect(
|
|
90
|
+
authenticate({ username: 'alice', password: 'wrong' })
|
|
91
|
+
).rejects.toThrow('Invalid credentials');
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Notice: tests describe **what** the function returns and **when** it throws — not **how** it works internally.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### GREEN: Write minimal code
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// auth.ts
|
|
104
|
+
import crypto from 'crypto';
|
|
105
|
+
|
|
106
|
+
export class AuthError extends Error {
|
|
107
|
+
constructor(message: string) {
|
|
108
|
+
super(message);
|
|
109
|
+
this.name = 'AuthError';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const VALID_CREDENTIALS = { alice: 'secret123' };
|
|
114
|
+
|
|
115
|
+
export async function authenticate({
|
|
116
|
+
username,
|
|
117
|
+
password,
|
|
118
|
+
}: {
|
|
119
|
+
username: string;
|
|
120
|
+
password: string;
|
|
121
|
+
}): Promise<string> {
|
|
122
|
+
const expected = VALID_CREDENTIALS[username];
|
|
123
|
+
if (!expected || expected !== password) {
|
|
124
|
+
throw new AuthError('Invalid credentials');
|
|
125
|
+
}
|
|
126
|
+
return crypto.randomBytes(16).toString('hex');
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
This is the **minimum** code to make both tests pass. It is not the final architecture — it is the seed. The test survives refactoring because it tests behavior, not implementation.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
### REFACTOR: Hide complexity behind a deep module
|
|
135
|
+
|
|
136
|
+
The first green pass exposes that the credentials check and token generation are interleaved. Refactor to a deep module:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// credentials.ts (deep module — small interface, large hidden implementation)
|
|
140
|
+
const STORE = new Map<string, string>(); // currently in-memory; swap to DB later
|
|
141
|
+
|
|
142
|
+
export async function checkCredentials(username: string, password: string): Promise<boolean> {
|
|
143
|
+
const stored = STORE.get(username);
|
|
144
|
+
return stored !== undefined && stored === password;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export async function addCredential(username: string, password: string): Promise<void> {
|
|
148
|
+
// future: hash before storing
|
|
149
|
+
STORE.set(username, password);
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The `authenticate` function becomes a thin, shallow orchestrator that delegates to deep modules. Tests for `authenticate` do not change — they only test the public interface.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
### Vertical Slice: User signup end-to-end
|
|
158
|
+
|
|
159
|
+
**Slice 1 — Register and retrieve a user**
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// user.test.ts
|
|
163
|
+
it('stores a user and retrieves them by id', async () => {
|
|
164
|
+
const id = await registerUser({ username: 'bob', password: 'pw' });
|
|
165
|
+
const user = await getUser(id);
|
|
166
|
+
expect(user.username).toBe('bob');
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Write minimal code: in-memory store, `registerUser` writes to it, `getUser` reads back.
|
|
171
|
+
|
|
172
|
+
**Slice 2 — Reject duplicate usernames**
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
it('throws DuplicateError when username is already taken', async () => {
|
|
176
|
+
await registerUser({ username: 'bob', password: 'pw' });
|
|
177
|
+
await expect(
|
|
178
|
+
registerUser({ username: 'bob', password: 'pw2' })
|
|
179
|
+
).rejects.toThrow('Duplicate username');
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Add the check to the existing `registerUser` — no new classes, no abstraction layers yet.
|
|
184
|
+
|
|
185
|
+
**Slice 3 — Persist to database**
|
|
186
|
+
|
|
187
|
+
Swap the in-memory store for a real DB adapter. Tests pass unchanged because the interface is the same.
|
|
188
|
+
|
|
189
|
+
Horizontal TDD would have written all in-memory tests, then all DB tests, then all business-logic tests — producing a large integration gap before any slice works end-to-end. Vertical TDD delivered a working registration flow after Slice 1.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## <Escalation_And_Stop_Conditions>
|
|
194
|
+
|
|
195
|
+
### Escalate when:
|
|
196
|
+
|
|
197
|
+
- **Test is flaky or environment-dependent** — A test that passes locally but fails in CI is noise, not signal. Escalate to omp architect to design a stable test fixture strategy.
|
|
198
|
+
- **The interface is unstable** — If the "right" public API is unclear after 3 cycles, stop. The problem definition is incomplete. Escalate to omp analyst to refine requirements.
|
|
199
|
+
- **A refactor breaks many tests** — Tests that fail because implementation details changed indicate the tests are testing internals. This is a signal to re-examine what the public interface should be. Escalate before continuing.
|
|
200
|
+
- **You are writing tests that replicate production logic** — If your test re-implements the function under test to verify it, you are testing the wrong thing. Escalate to omp verifier for a second opinion.
|
|
201
|
+
|
|
202
|
+
### Stop when:
|
|
203
|
+
|
|
204
|
+
- All tests in the current slice pass and `lsp_diagnostics_directory` reports zero errors.
|
|
205
|
+
- The per-cycle checklist (below) is satisfied.
|
|
206
|
+
- The vertical slice connects all layers — input, business logic, and storage — in a working path.
|
|
207
|
+
- Next steps require business decisions (e.g., which user flow to slice next) — those belong to omp analyst or the user.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## <Per-Cycle_Checklist>
|
|
212
|
+
|
|
213
|
+
Run through these before marking a TDD cycle complete:
|
|
214
|
+
|
|
215
|
+
- [ ] **Is this test focused on a PUBLIC interface, not internals?**
|
|
216
|
+
Test `authenticate(params)` — not `authenticate._tokenCache` or any private state.
|
|
217
|
+
|
|
218
|
+
- [ ] **Does the test describe BEHAVIOR, not implementation?**
|
|
219
|
+
"returns a session token when credentials are valid" is behavior.
|
|
220
|
+
"calls `crypto.randomBytes`" is implementation — avoid it.
|
|
221
|
+
|
|
222
|
+
- [ ] **Will this test SURVIVE refactoring?**
|
|
223
|
+
If you refactor `credentials.ts` internals, does this test still pass?
|
|
224
|
+
If not, the test is coupled to internals — rewrite it.
|
|
225
|
+
|
|
226
|
+
- [ ] **Is the code I wrote the MINIMAL amount to pass?**
|
|
227
|
+
No early optimization. No generalized abstractions. No extra parameters.
|
|
228
|
+
Write what makes the test pass, nothing more.
|
|
229
|
+
|
|
230
|
+
- [ ] **Is this slice vertical — does it span from input to storage?**
|
|
231
|
+
If you only added a DB call without connecting it to the public API, the slice is incomplete.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## <Final_Checklist>
|
|
236
|
+
|
|
237
|
+
Before declaring a TDD skill session complete:
|
|
238
|
+
|
|
239
|
+
- [ ] All new test files exist and are committed to the repo alongside production files.
|
|
240
|
+
- [ ] `npm test` (or equivalent) runs green with zero failures.
|
|
241
|
+
- [ ] `lsp_diagnostics_directory` reports zero errors across the modified package.
|
|
242
|
+
- [ ] No `TODO`, `HACK`, `debugger`, or `console.log` statements remain in production or test code.
|
|
243
|
+
- [ ] Tracer-bullet slices are connected: at least one complete vertical path (input → logic → storage) is working and tested end-to-end.
|
|
244
|
+
- [ ] Tests are named for the behavior they verify, not the method they call.
|
|
245
|
+
- [ ] Deep modules are used for complex internals; orchestrators stay thin.
|
|
246
|
+
- [ ] Any new skill-worthy pattern (3+ repetitions of the same logic) is noted and escalated to omp analyst for skill extraction.
|