@runecraft/grimoire 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -0
  3. package/catalog.json +9 -0
  4. package/dist/grimoire.js +1758 -0
  5. package/package.json +54 -0
  6. package/references/definition-of-done.md +67 -0
  7. package/references/testing-patterns.md +260 -0
  8. package/skills/code-review-and-quality/README.md +13 -0
  9. package/skills/code-review-and-quality/SKILL.md +389 -0
  10. package/skills/code-simplification/README.md +13 -0
  11. package/skills/code-simplification/SKILL.md +338 -0
  12. package/skills/debugging-and-error-recovery/README.md +13 -0
  13. package/skills/debugging-and-error-recovery/SKILL.md +343 -0
  14. package/skills/debugging-and-error-recovery/scripts/__pycache__/triage_state.cpython-314.pyc +0 -0
  15. package/skills/debugging-and-error-recovery/scripts/triage_state.py +206 -0
  16. package/skills/deprecation-and-migration/README.md +13 -0
  17. package/skills/deprecation-and-migration/SKILL.md +248 -0
  18. package/skills/deprecation-and-migration/scripts/__pycache__/migration_tracker.cpython-314.pyc +0 -0
  19. package/skills/deprecation-and-migration/scripts/migration_tracker.py +237 -0
  20. package/skills/doubt-driven-development/README.md +13 -0
  21. package/skills/doubt-driven-development/SKILL.md +251 -0
  22. package/skills/git-commit-learning/.skill-meta.json +14 -0
  23. package/skills/git-commit-learning/README.md +205 -0
  24. package/skills/git-commit-learning/SKILL.md +435 -0
  25. package/skills/git-commit-learning/references/commit-patterns.md +595 -0
  26. package/skills/git-worktree/README.md +13 -0
  27. package/skills/git-worktree/SKILL.md +220 -0
  28. package/skills/idea-refine/README.md +13 -0
  29. package/skills/idea-refine/SKILL.md +186 -0
  30. package/skills/interview-me/README.md +13 -0
  31. package/skills/interview-me/SKILL.md +233 -0
  32. package/skills/linkedin-audit/SKILL.md +98 -0
  33. package/skills/linkedin-audit/references/dashboard-spec.md +43 -0
  34. package/skills/memory-management/README.md +13 -0
  35. package/skills/memory-management/SKILL.md +198 -0
  36. package/skills/security-and-hardening/README.md +13 -0
  37. package/skills/security-and-hardening/SKILL.md +472 -0
  38. package/skills/shipping-and-launch/README.md +13 -0
  39. package/skills/shipping-and-launch/SKILL.md +317 -0
  40. package/skills/skill-forge/README.md +153 -0
  41. package/skills/skill-forge/SKILL.md +291 -0
  42. package/skills/skill-forge/assets/SKILL.template.md +73 -0
  43. package/skills/skill-forge/references/authoring-patterns.md +249 -0
  44. package/skills/skill-forge/references/description-optimization.md +171 -0
  45. package/skills/skill-forge/references/output-evaluation.md +276 -0
  46. package/skills/skill-forge/references/scripts-guide.md +232 -0
  47. package/skills/skill-forge/references/spec.md +175 -0
  48. package/skills/skill-forge/scripts/validate.py +536 -0
  49. package/skills/spec-driven/.skill-meta.json +14 -0
  50. package/skills/spec-driven/README.md +335 -0
  51. package/skills/spec-driven/SKILL.md +174 -0
  52. package/skills/spec-driven/references/code-analysis.md +98 -0
  53. package/skills/spec-driven/references/coding-principles.md +56 -0
  54. package/skills/spec-driven/references/context-limits.md +31 -0
  55. package/skills/spec-driven/references/design.md +199 -0
  56. package/skills/spec-driven/references/discuss.md +136 -0
  57. package/skills/spec-driven/references/implement.md +425 -0
  58. package/skills/spec-driven/references/lessons.md +113 -0
  59. package/skills/spec-driven/references/memory.md +126 -0
  60. package/skills/spec-driven/references/specify.md +210 -0
  61. package/skills/spec-driven/references/sub-agents.md +96 -0
  62. package/skills/spec-driven/references/tasks.md +484 -0
  63. package/skills/spec-driven/references/validate.md +350 -0
  64. package/skills/spec-driven/scripts/__pycache__/lessons.cpython-314.pyc +0 -0
  65. package/skills/spec-driven/scripts/lessons.py +370 -0
  66. package/skills/spec-loop/README.md +36 -0
  67. package/skills/spec-loop/SKILL.md +61 -0
  68. package/skills/test-driven-development/README.md +13 -0
  69. package/skills/test-driven-development/SKILL.md +388 -0
  70. package/skills/typescript-patterns/README.md +13 -0
  71. package/skills/typescript-patterns/SKILL.md +346 -0
  72. package/skills/using-agent-skills/README.md +13 -0
  73. package/skills/using-agent-skills/SKILL.md +187 -0
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@runecraft/grimoire",
3
+ "version": "1.0.0",
4
+ "description": "Interactive catalog and installer for agent skills",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "engines": {
8
+ "node": ">=20.12.0"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "bin": {
14
+ "grimoire": "dist/grimoire.js"
15
+ },
16
+ "files": [
17
+ "skills/",
18
+ "references/",
19
+ "dist/",
20
+ "catalog.json"
21
+ ],
22
+ "scripts": {
23
+ "build": "rm -rf dist && bun build src/index.ts --target=node --format=esm --outfile dist/grimoire.js && chmod +x dist/grimoire.js",
24
+ "dev": "bun run src/index.ts",
25
+ "lint": "bun run typecheck",
26
+ "test": "bun test",
27
+ "typecheck": "tsc --noEmit",
28
+ "prepack": "bun run build",
29
+ "prepublishOnly": "bun run build"
30
+ },
31
+ "keywords": [
32
+ "grimoire",
33
+ "agent",
34
+ "skills",
35
+ "prompts",
36
+ "ai",
37
+ "coding-agent",
38
+ "claude",
39
+ "codex",
40
+ "opencode",
41
+ "copilot",
42
+ "installer",
43
+ "cli"
44
+ ],
45
+ "dependencies": {
46
+ "@clack/prompts": "^1.7.0",
47
+ "picocolors": "^1.1.1"
48
+ },
49
+ "devDependencies": {
50
+ "@types/bun": "^1.3.14",
51
+ "@types/node": "^26.2.0",
52
+ "typescript": "^7.0.2"
53
+ }
54
+ }
@@ -0,0 +1,67 @@
1
+ # Definition of Done
2
+
3
+ A standing, project-wide bar that every change must clear before it counts as done. Unlike acceptance criteria, which vary per task and answer "did we build the right thing?", the Definition of Done is the same every time and answers "is this finished to our standard?". Use it as the final gate in `spec-driven` and `shipping-and-launch`.
4
+
5
+ ## Definition of Done vs. Acceptance Criteria
6
+
7
+ | | Acceptance Criteria | Definition of Done |
8
+ |---|---|---|
9
+ | Scope | Specific to one task or spec | Applies to every increment |
10
+ | Changes | Different for each item | Fixed and reused |
11
+ | Answers | "Did we build *this thing*?" | "Is it *ready*?" |
12
+ | Owner | Defined when planning the task | Defined once for the project |
13
+ | Example | "User can reset password via email link" | "Tests pass, no regressions, docs updated" |
14
+
15
+ The two are complementary. A task is done only when **its** acceptance criteria are met **and** the standing Definition of Done is satisfied. Skipping either leaves work that looks finished but is not.
16
+
17
+ ## The Standing Checklist
18
+
19
+ Apply this to every change before declaring it done.
20
+
21
+ ### Correctness
22
+ - [ ] All acceptance criteria for the task are met
23
+ - [ ] Code runs and behaves as intended, verified at runtime, not just compiled or typechecked
24
+ - [ ] New behavior is covered by tests that fail without the change and pass with it
25
+ - [ ] Existing tests still pass; no regressions introduced
26
+ - [ ] Edge cases and error paths are handled, not just the happy path
27
+
28
+ ### Quality
29
+ - [ ] Code reveals intent through naming and structure; no comments needed to explain *what* it does
30
+ - [ ] No duplicated business logic
31
+ - [ ] No dead code, debug output, or commented-out blocks left behind
32
+ - [ ] Changes are scoped to the task; no unrelated refactors snuck in
33
+ - [ ] Linting and formatting pass
34
+
35
+ The depth behind these items lives in `code-review-and-quality` (the five-axis review) and `code-simplification` (reducing complexity without changing behavior).
36
+
37
+ ### Integration
38
+ - [ ] Change works with the rest of the system, not just in isolation
39
+ - [ ] Database migrations, config changes, and feature flags are accounted for
40
+ - [ ] Backward compatibility considered for any public interface or API change
41
+
42
+ ### Documentation
43
+ - [ ] Public interfaces, APIs, and user-facing behavior are documented
44
+ - [ ] Architectural decisions worth preserving are recorded
45
+ - [ ] Documentation describes the current state in timeless language, not the change history
46
+
47
+ ### Ship-readiness
48
+ - [ ] Security implications reviewed for any untrusted input, auth, or data handling (see `security-and-hardening`)
49
+ - [ ] Observability in place for new critical paths (logs, metrics, traces)
50
+ - [ ] Rollback path exists for anything risky (see `shipping-and-launch`)
51
+ - [ ] The human has reviewed and approved before merge or deploy
52
+
53
+ ## How to Apply
54
+
55
+ - **Per task**: confirm the Correctness and Quality sections before checking the task off.
56
+ - **Per feature**: confirm Integration and Documentation before considering the feature complete.
57
+ - **Per release**: the full checklist is the floor; `shipping-and-launch` adds the deploy-specific gates on top.
58
+
59
+ Tailor the list to the project once, then reuse it unchanged. A Definition of Done that is renegotiated every sprint is not a Definition of Done.
60
+
61
+ ## Red Flags
62
+
63
+ - "It's done, I just haven't run it yet": unverified work is not done.
64
+ - "Tests pass" used as a synonym for done while docs, regressions, or runtime verification are skipped.
65
+ - A different bar applied depending on deadline pressure.
66
+ - Acceptance criteria treated as the whole bar, with no standing quality floor.
67
+ - "Done" declared before human review on changes that need it.
@@ -0,0 +1,260 @@
1
+ # Testing Patterns Reference
2
+
3
+ Quick reference for common testing patterns across the stack. Use alongside the `test-driven-development` skill.
4
+
5
+ ## Test Pyramid (80/15/5)
6
+
7
+ Target distribution for a healthy suite:
8
+
9
+ ```
10
+ /\
11
+ / \ E2E ~5% (slow, brittle, high signal)
12
+ /----\
13
+ / \ Integration ~15% (contract-level, balanced)
14
+ /--------\
15
+ / \ Unit ~80% (fast, focused, cheap)
16
+ /------------\
17
+ ```
18
+
19
+ - **80% unit** — pure functions, single behavior, milliseconds
20
+ - **15% integration** — module boundaries, contracts between collaborators
21
+ - **5% E2E** — critical user journeys only; every E2E test is expensive
22
+
23
+ ## Beyonce Rule
24
+
25
+ > "If you liked it then you should've put a test on it."
26
+
27
+ Every shipped behavior needs a regression test. "We'll add tests later" is a known failure mode — the gap is rarely closed, and the next change touches untested code. New behavior without a test is unfinished work, not done work.
28
+
29
+ ## Table of Contents
30
+
31
+ - [Test Structure (Arrange-Act-Assert)](#test-structure-arrange-act-assert)
32
+ - [Test Naming Conventions](#test-naming-conventions)
33
+ - [Common Assertions](#common-assertions)
34
+ - [Mocking Patterns](#mocking-patterns)
35
+ - [React/Component Testing](#reactcomponent-testing)
36
+ - [API / Integration Testing](#api--integration-testing)
37
+ - [E2E Testing (Playwright)](#e2e-testing-playwright)
38
+ - [Test Anti-Patterns](#test-anti-patterns)
39
+
40
+ ## Test Structure (Arrange-Act-Assert)
41
+
42
+ ```typescript
43
+ it('describes expected behavior', () => {
44
+ // Arrange: Set up test data and preconditions
45
+ const input = { title: 'Test Task', priority: 'high' };
46
+
47
+ // Act: Perform the action being tested
48
+ const result = createTask(input);
49
+
50
+ // Assert: Verify the outcome
51
+ expect(result.title).toBe('Test Task');
52
+ expect(result.priority).toBe('high');
53
+ expect(result.status).toBe('pending');
54
+ });
55
+ ```
56
+
57
+ ## Test Naming Conventions
58
+
59
+ ```typescript
60
+ // Pattern: [unit] [expected behavior] [condition]
61
+ describe('TaskService.createTask', () => {
62
+ it('creates a task with default pending status', () => {});
63
+ it('throws ValidationError when title is empty', () => {});
64
+ it('trims whitespace from title', () => {});
65
+ it('generates a unique ID for each task', () => {});
66
+ });
67
+ ```
68
+
69
+ ## Common Assertions
70
+
71
+ ```typescript
72
+ // Equality
73
+ expect(result).toBe(expected); // Strict equality (===)
74
+ expect(result).toEqual(expected); // Deep equality (objects/arrays)
75
+ expect(result).toStrictEqual(expected); // Deep equality + type matching
76
+
77
+ // Truthiness
78
+ expect(result).toBeTruthy();
79
+ expect(result).toBeFalsy();
80
+ expect(result).toBeNull();
81
+ expect(result).toBeDefined();
82
+ expect(result).toBeUndefined();
83
+
84
+ // Numbers
85
+ expect(result).toBeGreaterThan(5);
86
+ expect(result).toBeLessThanOrEqual(10);
87
+ expect(result).toBeCloseTo(0.3, 5); // Floating point
88
+
89
+ // Strings
90
+ expect(result).toMatch(/pattern/);
91
+ expect(result).toContain('substring');
92
+
93
+ // Arrays / Objects
94
+ expect(array).toContain(item);
95
+ expect(array).toHaveLength(3);
96
+ expect(object).toHaveProperty('key', 'value');
97
+
98
+ // Errors
99
+ expect(() => fn()).toThrow();
100
+ expect(() => fn()).toThrow(ValidationError);
101
+ expect(() => fn()).toThrow('specific message');
102
+
103
+ // Async
104
+ await expect(asyncFn()).resolves.toBe(value);
105
+ await expect(asyncFn()).rejects.toThrow(Error);
106
+ ```
107
+
108
+ ## Mocking Patterns
109
+
110
+ ### Mock Functions
111
+
112
+ ```typescript
113
+ const mockFn = jest.fn();
114
+ mockFn.mockReturnValue(42);
115
+ mockFn.mockResolvedValue({ data: 'test' });
116
+ mockFn.mockImplementation((x) => x * 2);
117
+
118
+ expect(mockFn).toHaveBeenCalled();
119
+ expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');
120
+ expect(mockFn).toHaveBeenCalledTimes(3);
121
+ ```
122
+
123
+ ### Mock Modules
124
+
125
+ ```typescript
126
+ // Mock an entire module
127
+ jest.mock('./database', () => ({
128
+ query: jest.fn().mockResolvedValue([{ id: 1, title: 'Test' }]),
129
+ }));
130
+
131
+ // Mock specific exports
132
+ jest.mock('./utils', () => ({
133
+ ...jest.requireActual('./utils'),
134
+ generateId: jest.fn().mockReturnValue('test-id'),
135
+ }));
136
+ ```
137
+
138
+ ### Mock at Boundaries Only
139
+
140
+ ```
141
+ Mock these: Don't mock these:
142
+ ├── Database calls ├── Internal utility functions
143
+ ├── HTTP requests ├── Business logic
144
+ ├── File system operations ├── Data transformations
145
+ ├── External API calls ├── Validation functions
146
+ └── Time/Date (when needed) └── Pure functions
147
+ ```
148
+
149
+ ## React/Component Testing
150
+
151
+ ```tsx
152
+ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
153
+
154
+ describe('TaskForm', () => {
155
+ it('submits the form with entered data', async () => {
156
+ const onSubmit = jest.fn();
157
+ render(<TaskForm onSubmit={onSubmit} />);
158
+
159
+ // Find elements by accessible role/label (not test IDs)
160
+ await screen.findByRole('textbox', { name: /title/i });
161
+ fireEvent.change(screen.getByRole('textbox', { name: /title/i }), {
162
+ target: { value: 'New Task' },
163
+ });
164
+ fireEvent.click(screen.getByRole('button', { name: /create/i }));
165
+
166
+ await waitFor(() => {
167
+ expect(onSubmit).toHaveBeenCalledWith({ title: 'New Task' });
168
+ });
169
+ });
170
+
171
+ it('shows validation error for empty title', async () => {
172
+ render(<TaskForm onSubmit={jest.fn()} />);
173
+
174
+ fireEvent.click(screen.getByRole('button', { name: /create/i }));
175
+
176
+ expect(await screen.findByText(/title is required/i)).toBeInTheDocument();
177
+ });
178
+ });
179
+ ```
180
+
181
+ ## API / Integration Testing
182
+
183
+ ```typescript
184
+ import request from 'supertest';
185
+ import { app } from '../src/app';
186
+
187
+ describe('POST /api/tasks', () => {
188
+ it('creates a task and returns 201', async () => {
189
+ const response = await request(app)
190
+ .post('/api/tasks')
191
+ .send({ title: 'Test Task' })
192
+ .set('Authorization', `Bearer ${testToken}`)
193
+ .expect(201);
194
+
195
+ expect(response.body).toMatchObject({
196
+ id: expect.any(String),
197
+ title: 'Test Task',
198
+ status: 'pending',
199
+ });
200
+ });
201
+
202
+ it('returns 422 for invalid input', async () => {
203
+ const response = await request(app)
204
+ .post('/api/tasks')
205
+ .send({ title: '' })
206
+ .set('Authorization', `Bearer ${testToken}`)
207
+ .expect(422);
208
+
209
+ expect(response.body.error.code).toBe('VALIDATION_ERROR');
210
+ });
211
+
212
+ it('returns 401 without authentication', async () => {
213
+ await request(app)
214
+ .post('/api/tasks')
215
+ .send({ title: 'Test' })
216
+ .expect(401);
217
+ });
218
+ });
219
+ ```
220
+
221
+ ## E2E Testing (Playwright)
222
+
223
+ ```typescript
224
+ import { test, expect } from '@playwright/test';
225
+
226
+ test('user can create and complete a task', async ({ page }) => {
227
+ // Navigate and authenticate
228
+ await page.goto('/');
229
+ await page.fill('[name="email"]', 'test@example.com');
230
+ await page.fill('[name="password"]', 'testpass123');
231
+ await page.click('button:has-text("Log in")');
232
+
233
+ // Create a task
234
+ await page.click('button:has-text("New Task")');
235
+ await page.fill('[name="title"]', 'Buy groceries');
236
+ await page.click('button:has-text("Create")');
237
+
238
+ // Verify task appears
239
+ await expect(page.locator('text=Buy groceries')).toBeVisible();
240
+
241
+ // Complete the task
242
+ await page.click('[aria-label="Complete Buy groceries"]');
243
+ await expect(page.locator('text=Buy groceries')).toHaveCSS(
244
+ 'text-decoration-line', 'line-through'
245
+ );
246
+ });
247
+ ```
248
+
249
+ ## Test Anti-Patterns
250
+
251
+ | Anti-Pattern | Problem | Better Approach |
252
+ |---|---|---|
253
+ | Testing implementation details | Breaks on refactor | Test inputs/outputs |
254
+ | Snapshot everything | No one reviews snapshot diffs | Assert specific values |
255
+ | Shared mutable state | Tests pollute each other | Setup/teardown per test |
256
+ | Testing third-party code | Wastes time, not your bug | Mock the boundary |
257
+ | Skipping tests to pass CI | Hides real bugs | Fix or delete the test |
258
+ | Using `test.skip` permanently | Dead code | Remove or fix it |
259
+ | Overly broad assertions | Doesn't catch regressions | Be specific |
260
+ | No async error handling | Swallowed errors, false passes | Always `await` async tests |
@@ -0,0 +1,13 @@
1
+ # code-review-and-quality
2
+
3
+ Multi-axis code review (correctness, readability, architecture, security, performance) with severity labels (Blocker, Required, Optional, Nit, FYI).
4
+
5
+ | Field | Value |
6
+ |-------|-------|
7
+ | Version | 1.0.0 |
8
+ | Trigger | `/review`, "code review", "PR review", "merge gate", "five-axis review" |
9
+ | PT trigger | `/revisar`, "revisão de código", "revisão de PR" |
10
+
11
+ **Do not use for** in-flight decisions on non-trivial work (that's `/harden`), single-line typo fixes, or when the user explicitly skips review.
12
+
13
+ See [SKILL.md](SKILL.md) for the full process.