red64-cli 0.1.0 → 0.2.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 (103) hide show
  1. package/dist/cli/parseArgs.d.ts.map +1 -1
  2. package/dist/cli/parseArgs.js +5 -0
  3. package/dist/cli/parseArgs.js.map +1 -1
  4. package/dist/components/init/CompleteStep.d.ts.map +1 -1
  5. package/dist/components/init/CompleteStep.js +2 -2
  6. package/dist/components/init/CompleteStep.js.map +1 -1
  7. package/dist/components/init/TestCheckStep.d.ts +16 -0
  8. package/dist/components/init/TestCheckStep.d.ts.map +1 -0
  9. package/dist/components/init/TestCheckStep.js +120 -0
  10. package/dist/components/init/TestCheckStep.js.map +1 -0
  11. package/dist/components/init/index.d.ts +1 -0
  12. package/dist/components/init/index.d.ts.map +1 -1
  13. package/dist/components/init/index.js +1 -0
  14. package/dist/components/init/index.js.map +1 -1
  15. package/dist/components/init/types.d.ts +9 -0
  16. package/dist/components/init/types.d.ts.map +1 -1
  17. package/dist/components/screens/InitScreen.d.ts.map +1 -1
  18. package/dist/components/screens/InitScreen.js +69 -6
  19. package/dist/components/screens/InitScreen.js.map +1 -1
  20. package/dist/components/screens/StartScreen.d.ts.map +1 -1
  21. package/dist/components/screens/StartScreen.js +89 -3
  22. package/dist/components/screens/StartScreen.js.map +1 -1
  23. package/dist/services/ConfigService.d.ts +1 -0
  24. package/dist/services/ConfigService.d.ts.map +1 -1
  25. package/dist/services/ConfigService.js.map +1 -1
  26. package/dist/services/ProjectDetector.d.ts +28 -0
  27. package/dist/services/ProjectDetector.d.ts.map +1 -0
  28. package/dist/services/ProjectDetector.js +236 -0
  29. package/dist/services/ProjectDetector.js.map +1 -0
  30. package/dist/services/TestRunner.d.ts +46 -0
  31. package/dist/services/TestRunner.d.ts.map +1 -0
  32. package/dist/services/TestRunner.js +85 -0
  33. package/dist/services/TestRunner.js.map +1 -0
  34. package/dist/services/index.d.ts +2 -0
  35. package/dist/services/index.d.ts.map +1 -1
  36. package/dist/services/index.js +2 -0
  37. package/dist/services/index.js.map +1 -1
  38. package/dist/types/index.d.ts +1 -0
  39. package/dist/types/index.d.ts.map +1 -1
  40. package/dist/types/index.js.map +1 -1
  41. package/framework/agents/claude/.claude/agents/red64/spec-impl.md +131 -2
  42. package/framework/agents/claude/.claude/commands/red64/spec-impl.md +24 -0
  43. package/framework/agents/codex/.codex/agents/red64/spec-impl.md +131 -2
  44. package/framework/agents/codex/.codex/commands/red64/spec-impl.md +24 -0
  45. package/framework/stacks/generic/feedback.md +80 -0
  46. package/framework/stacks/nextjs/accessibility.md +437 -0
  47. package/framework/stacks/nextjs/api.md +431 -0
  48. package/framework/stacks/nextjs/coding-style.md +282 -0
  49. package/framework/stacks/nextjs/commenting.md +226 -0
  50. package/framework/stacks/nextjs/components.md +411 -0
  51. package/framework/stacks/nextjs/conventions.md +333 -0
  52. package/framework/stacks/nextjs/css.md +310 -0
  53. package/framework/stacks/nextjs/error-handling.md +442 -0
  54. package/framework/stacks/nextjs/feedback.md +124 -0
  55. package/framework/stacks/nextjs/migrations.md +332 -0
  56. package/framework/stacks/nextjs/models.md +362 -0
  57. package/framework/stacks/nextjs/queries.md +410 -0
  58. package/framework/stacks/nextjs/responsive.md +338 -0
  59. package/framework/stacks/nextjs/tech-stack.md +177 -0
  60. package/framework/stacks/nextjs/test-writing.md +475 -0
  61. package/framework/stacks/nextjs/validation.md +467 -0
  62. package/framework/stacks/python/api.md +468 -0
  63. package/framework/stacks/python/authentication.md +342 -0
  64. package/framework/stacks/python/code-quality.md +283 -0
  65. package/framework/stacks/python/code-refactoring.md +315 -0
  66. package/framework/stacks/python/coding-style.md +462 -0
  67. package/framework/stacks/python/conventions.md +399 -0
  68. package/framework/stacks/python/error-handling.md +512 -0
  69. package/framework/stacks/python/feedback.md +92 -0
  70. package/framework/stacks/python/implement-ai-llm.md +468 -0
  71. package/framework/stacks/python/migrations.md +388 -0
  72. package/framework/stacks/python/models.md +399 -0
  73. package/framework/stacks/python/python.md +232 -0
  74. package/framework/stacks/python/queries.md +451 -0
  75. package/framework/stacks/python/structure.md +245 -58
  76. package/framework/stacks/python/tech.md +92 -35
  77. package/framework/stacks/python/testing.md +380 -0
  78. package/framework/stacks/python/validation.md +471 -0
  79. package/framework/stacks/rails/authentication.md +176 -0
  80. package/framework/stacks/rails/code-quality.md +287 -0
  81. package/framework/stacks/rails/code-refactoring.md +299 -0
  82. package/framework/stacks/rails/feedback.md +130 -0
  83. package/framework/stacks/rails/implement-ai-llm-with-rubyllm.md +342 -0
  84. package/framework/stacks/rails/rails.md +301 -0
  85. package/framework/stacks/rails/rails8-best-practices.md +498 -0
  86. package/framework/stacks/rails/rails8-css.md +573 -0
  87. package/framework/stacks/rails/structure.md +140 -0
  88. package/framework/stacks/rails/tech.md +108 -0
  89. package/framework/stacks/react/code-quality.md +521 -0
  90. package/framework/stacks/react/components.md +625 -0
  91. package/framework/stacks/react/data-fetching.md +586 -0
  92. package/framework/stacks/react/feedback.md +110 -0
  93. package/framework/stacks/react/forms.md +694 -0
  94. package/framework/stacks/react/performance.md +640 -0
  95. package/framework/stacks/react/product.md +22 -9
  96. package/framework/stacks/react/state-management.md +472 -0
  97. package/framework/stacks/react/structure.md +351 -44
  98. package/framework/stacks/react/tech.md +219 -30
  99. package/framework/stacks/react/testing.md +690 -0
  100. package/package.json +1 -1
  101. package/framework/stacks/node/product.md +0 -27
  102. package/framework/stacks/node/structure.md +0 -82
  103. package/framework/stacks/node/tech.md +0 -63
@@ -0,0 +1,80 @@
1
+ # Feedback Configuration
2
+
3
+ Project-specific commands for automated feedback during implementation.
4
+
5
+ ---
6
+
7
+ ## Test Commands
8
+
9
+ Commands to run tests during implementation. The agent will use these to verify code changes.
10
+
11
+ ```yaml
12
+ # Primary test command (REQUIRED)
13
+ test: npm test
14
+
15
+ # Test with coverage report
16
+ test_coverage: npm test -- --coverage
17
+
18
+ # Run specific test file (use {file} as placeholder)
19
+ test_file: npm test -- {file}
20
+ ```
21
+
22
+ ---
23
+
24
+ ## Linting Commands
25
+
26
+ Commands for code quality checks.
27
+
28
+ ```yaml
29
+ # Primary lint command
30
+ lint: npm run lint
31
+
32
+ # Lint with auto-fix
33
+ lint_fix: npm run lint -- --fix
34
+
35
+ # Type checking (if applicable)
36
+ type_check: npm run type-check
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Development Server
42
+
43
+ Commands for starting the development server (required for UI verification).
44
+
45
+ ```yaml
46
+ # Start dev server
47
+ dev_server: npm run dev
48
+
49
+ # Dev server port
50
+ dev_port: 3000
51
+
52
+ # Dev server base URL
53
+ dev_url: http://localhost:3000
54
+ ```
55
+
56
+ ---
57
+
58
+ ## UI Verification
59
+
60
+ Settings for agent-browser UI verification.
61
+
62
+ ```yaml
63
+ # Enable UI verification for this project
64
+ ui_verification_enabled: true
65
+
66
+ # Default wait time after navigation (milliseconds)
67
+ navigation_wait: 3000
68
+
69
+ # Screenshot directory
70
+ screenshot_dir: /tmp/ui-captures
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Notes
76
+
77
+ - Update these commands to match your project's setup
78
+ - The agent reads this file to determine how to run tests and verify UI
79
+ - If a command doesn't apply, leave it empty or remove the line
80
+ - All commands should be runnable from the project root directory
@@ -0,0 +1,437 @@
1
+ # Accessibility
2
+
3
+ Accessibility patterns for Next.js applications with semantic HTML, ARIA, keyboard navigation, focus management, and testing.
4
+
5
+ ---
6
+
7
+ ## Philosophy
8
+
9
+ - **Semantic first**: Use the right HTML element before reaching for ARIA
10
+ - **Keyboard complete**: Every interactive element must be operable without a mouse
11
+ - **Visible focus**: Focus indicators are a feature, not a bug
12
+ - **Test with real tools**: Automated checks catch 30% of issues; screen readers catch the rest
13
+
14
+ ---
15
+
16
+ ## Semantic HTML
17
+
18
+ ### Use the Right Element
19
+
20
+ | Need | Correct Element | Not This |
21
+ |---|---|---|
22
+ | Navigation | `<nav>` | `<div className="nav">` |
23
+ | Page sections | `<main>`, `<section>`, `<aside>` | `<div>` |
24
+ | Clickable action | `<button>` | `<div onClick>`, `<a href="#">` |
25
+ | Link to page | `<a href="/path">` | `<button onClick={navigate}>` |
26
+ | List of items | `<ul>` / `<ol>` with `<li>` | Nested `<div>` |
27
+ | Form field label | `<label htmlFor="id">` | `<span>` before input |
28
+ | Table data | `<table>` with `<thead>`, `<tbody>` | Grid of `<div>` |
29
+ | Heading hierarchy | `<h1>` through `<h6>` | `<div className="heading">` |
30
+
31
+ ### Page Structure
32
+
33
+ ```typescript
34
+ // app/dashboard/page.tsx
35
+ export default async function DashboardPage() {
36
+ return (
37
+ <main>
38
+ <h1>Dashboard</h1>
39
+
40
+ <section aria-labelledby="stats-heading">
41
+ <h2 id="stats-heading">Statistics</h2>
42
+ <StatsGrid />
43
+ </section>
44
+
45
+ <section aria-labelledby="recent-heading">
46
+ <h2 id="recent-heading">Recent Activity</h2>
47
+ <ActivityFeed />
48
+ </section>
49
+ </main>
50
+ );
51
+ }
52
+ ```
53
+
54
+ ### Heading Hierarchy
55
+
56
+ ```typescript
57
+ // GOOD: Sequential heading levels
58
+ <h1>User Settings</h1>
59
+ <h2>Profile</h2>
60
+ <h3>Avatar</h3>
61
+ <h3>Display Name</h3>
62
+ <h2>Notifications</h2>
63
+ <h3>Email Preferences</h3>
64
+
65
+ // BAD: Skipped heading levels
66
+ <h1>User Settings</h1>
67
+ <h4>Profile</h4> // Skipped h2 and h3
68
+ ```
69
+
70
+ ---
71
+
72
+ ## ARIA Patterns
73
+
74
+ ### When to Use ARIA
75
+
76
+ 1. Use semantic HTML first
77
+ 2. Add ARIA only when HTML semantics are insufficient
78
+ 3. Never use ARIA to fix broken HTML structure
79
+
80
+ ### Common ARIA Attributes
81
+
82
+ ```typescript
83
+ // Live regions for dynamic updates
84
+ <div aria-live="polite" aria-atomic="true">
85
+ {notification && <p>{notification}</p>}
86
+ </div>
87
+
88
+ // Loading states
89
+ <button disabled={isPending} aria-busy={isPending}>
90
+ {isPending ? "Saving..." : "Save"}
91
+ </button>
92
+
93
+ // Expanded/collapsed
94
+ <button aria-expanded={isOpen} aria-controls="menu-panel" onClick={toggle}>
95
+ Menu
96
+ </button>
97
+ <div id="menu-panel" hidden={!isOpen}>
98
+ {/* menu content */}
99
+ </div>
100
+
101
+ // Required fields
102
+ <input aria-required="true" aria-invalid={!!error} aria-describedby="email-error" />
103
+ {error && <p id="email-error" role="alert">{error}</p>}
104
+ ```
105
+
106
+ ### Dialog/Modal Pattern
107
+
108
+ ```typescript
109
+ "use client";
110
+
111
+ import { useRef, useEffect } from "react";
112
+
113
+ interface DialogProps {
114
+ open: boolean;
115
+ onClose: () => void;
116
+ title: string;
117
+ children: React.ReactNode;
118
+ }
119
+
120
+ export function Dialog({ open, onClose, title, children }: DialogProps) {
121
+ const dialogRef = useRef<HTMLDialogElement>(null);
122
+
123
+ useEffect(() => {
124
+ const dialog = dialogRef.current;
125
+ if (!dialog) return;
126
+
127
+ if (open) {
128
+ dialog.showModal();
129
+ } else {
130
+ dialog.close();
131
+ }
132
+ }, [open]);
133
+
134
+ return (
135
+ <dialog
136
+ ref={dialogRef}
137
+ onClose={onClose}
138
+ aria-labelledby="dialog-title"
139
+ className="rounded-xl border bg-background p-6 shadow-lg backdrop:bg-black/50"
140
+ >
141
+ <h2 id="dialog-title" className="text-lg font-semibold">{title}</h2>
142
+ <div className="mt-4">{children}</div>
143
+ <button onClick={onClose} aria-label="Close dialog" className="absolute right-4 top-4">
144
+ <XIcon />
145
+ </button>
146
+ </dialog>
147
+ );
148
+ }
149
+ ```
150
+
151
+ ---
152
+
153
+ ## Keyboard Navigation
154
+
155
+ ### Focus Management
156
+
157
+ ```typescript
158
+ "use client";
159
+
160
+ import { useRef, useEffect } from "react";
161
+
162
+ // Auto-focus on mount (for modals, drawers)
163
+ export function SearchPanel({ isOpen }: { isOpen: boolean }) {
164
+ const inputRef = useRef<HTMLInputElement>(null);
165
+
166
+ useEffect(() => {
167
+ if (isOpen) {
168
+ inputRef.current?.focus();
169
+ }
170
+ }, [isOpen]);
171
+
172
+ return (
173
+ <div role="search">
174
+ <input ref={inputRef} type="search" placeholder="Search..." aria-label="Search" />
175
+ </div>
176
+ );
177
+ }
178
+ ```
179
+
180
+ ### Skip Navigation Link
181
+
182
+ ```typescript
183
+ // app/layout.tsx
184
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
185
+ return (
186
+ <html lang="en">
187
+ <body>
188
+ <a
189
+ href="#main-content"
190
+ className="sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-4 focus:z-50 focus:rounded-md focus:bg-primary focus:px-4 focus:py-2 focus:text-white"
191
+ >
192
+ Skip to main content
193
+ </a>
194
+ <Header />
195
+ <main id="main-content" tabIndex={-1}>
196
+ {children}
197
+ </main>
198
+ <Footer />
199
+ </body>
200
+ </html>
201
+ );
202
+ }
203
+ ```
204
+
205
+ ### Keyboard Shortcuts
206
+
207
+ ```typescript
208
+ // Roving tabindex for toolbar/menu
209
+ "use client";
210
+
211
+ import { useState, useRef } from "react";
212
+
213
+ export function Toolbar({ items }: { items: { label: string; onClick: () => void }[] }) {
214
+ const [activeIndex, setActiveIndex] = useState(0);
215
+ const refs = useRef<(HTMLButtonElement | null)[]>([]);
216
+
217
+ function handleKeyDown(e: React.KeyboardEvent, index: number) {
218
+ let nextIndex = index;
219
+ if (e.key === "ArrowRight") nextIndex = (index + 1) % items.length;
220
+ if (e.key === "ArrowLeft") nextIndex = (index - 1 + items.length) % items.length;
221
+
222
+ if (nextIndex !== index) {
223
+ e.preventDefault();
224
+ setActiveIndex(nextIndex);
225
+ refs.current[nextIndex]?.focus();
226
+ }
227
+ }
228
+
229
+ return (
230
+ <div role="toolbar" aria-label="Actions">
231
+ {items.map((item, i) => (
232
+ <button
233
+ key={i}
234
+ ref={(el) => { refs.current[i] = el; }}
235
+ tabIndex={i === activeIndex ? 0 : -1}
236
+ onKeyDown={(e) => handleKeyDown(e, i)}
237
+ onClick={item.onClick}
238
+ >
239
+ {item.label}
240
+ </button>
241
+ ))}
242
+ </div>
243
+ );
244
+ }
245
+ ```
246
+
247
+ ---
248
+
249
+ ## Next.js Specific Patterns
250
+
251
+ ### Images
252
+
253
+ ```typescript
254
+ import Image from "next/image";
255
+
256
+ // GOOD: Descriptive alt text
257
+ <Image src="/team/jane.jpg" alt="Jane Doe, CTO" width={200} height={200} />
258
+
259
+ // GOOD: Decorative image
260
+ <Image src="/pattern.svg" alt="" width={100} height={100} aria-hidden="true" />
261
+
262
+ // BAD
263
+ <Image src="/team/jane.jpg" alt="image" width={200} height={200} />
264
+ <Image src="/team/jane.jpg" alt="photo.jpg" width={200} height={200} />
265
+ ```
266
+
267
+ ### Links
268
+
269
+ ```typescript
270
+ import Link from "next/link";
271
+
272
+ // GOOD: Descriptive link text
273
+ <Link href="/settings">Account settings</Link>
274
+
275
+ // GOOD: Link with context via aria-label
276
+ <Link href={`/users/${user.id}`} aria-label={`View profile for ${user.name}`}>
277
+ View profile
278
+ </Link>
279
+
280
+ // BAD: Ambiguous link text
281
+ <Link href="/settings">Click here</Link>
282
+ ```
283
+
284
+ ### Dynamic Route Announcements
285
+
286
+ ```typescript
287
+ // components/route-announcer.tsx
288
+ "use client";
289
+
290
+ import { usePathname } from "next/navigation";
291
+ import { useEffect, useState } from "react";
292
+
293
+ export function RouteAnnouncer() {
294
+ const pathname = usePathname();
295
+ const [announcement, setAnnouncement] = useState("");
296
+
297
+ useEffect(() => {
298
+ const pageTitle = document.title;
299
+ setAnnouncement(`Navigated to ${pageTitle}`);
300
+ }, [pathname]);
301
+
302
+ return (
303
+ <div aria-live="assertive" aria-atomic="true" className="sr-only">
304
+ {announcement}
305
+ </div>
306
+ );
307
+ }
308
+ ```
309
+
310
+ ---
311
+
312
+ ## Color and Contrast
313
+
314
+ ### Minimum Ratios (WCAG 2.1 AA)
315
+
316
+ | Element | Minimum Ratio |
317
+ |---|---|
318
+ | Normal text (< 18px) | 4.5:1 |
319
+ | Large text (>= 18px bold, >= 24px) | 3:1 |
320
+ | UI components and icons | 3:1 |
321
+ | Focus indicators | 3:1 against adjacent colors |
322
+
323
+ ### Never Rely on Color Alone
324
+
325
+ ```typescript
326
+ // GOOD: Color + icon + text
327
+ <Badge variant="error">
328
+ <AlertIcon className="mr-1" aria-hidden="true" />
329
+ Failed
330
+ </Badge>
331
+
332
+ // BAD: Color only
333
+ <span className="text-red-500">Failed</span>
334
+ ```
335
+
336
+ ---
337
+
338
+ ## Forms
339
+
340
+ ### Accessible Form Pattern
341
+
342
+ ```typescript
343
+ export function LoginForm() {
344
+ return (
345
+ <form aria-labelledby="login-heading">
346
+ <h2 id="login-heading">Sign in to your account</h2>
347
+
348
+ <div>
349
+ <label htmlFor="email">Email address</label>
350
+ <input
351
+ id="email"
352
+ name="email"
353
+ type="email"
354
+ required
355
+ autoComplete="email"
356
+ aria-describedby="email-hint"
357
+ />
358
+ <p id="email-hint" className="text-sm text-muted-foreground">
359
+ We will never share your email.
360
+ </p>
361
+ </div>
362
+
363
+ <div>
364
+ <label htmlFor="password">Password</label>
365
+ <input
366
+ id="password"
367
+ name="password"
368
+ type="password"
369
+ required
370
+ autoComplete="current-password"
371
+ aria-invalid={!!errors.password}
372
+ aria-describedby={errors.password ? "password-error" : undefined}
373
+ />
374
+ {errors.password && (
375
+ <p id="password-error" role="alert" className="text-sm text-destructive">
376
+ {errors.password}
377
+ </p>
378
+ )}
379
+ </div>
380
+
381
+ <button type="submit">Sign in</button>
382
+ </form>
383
+ );
384
+ }
385
+ ```
386
+
387
+ ---
388
+
389
+ ## Testing
390
+
391
+ ### Automated Tools
392
+
393
+ | Tool | Purpose | Integration |
394
+ |---|---|---|
395
+ | axe-core | Automated a11y checks | Vitest + @axe-core/react |
396
+ | Playwright | E2E a11y assertions | Built-in accessibility snapshots |
397
+ | eslint-plugin-jsx-a11y | Lint-time checks | ESLint config |
398
+
399
+ ### Axe Integration with Vitest
400
+
401
+ ```typescript
402
+ import { render } from "@testing-library/react";
403
+ import { axe, toHaveNoViolations } from "jest-axe";
404
+
405
+ expect.extend(toHaveNoViolations);
406
+
407
+ test("LoginForm has no accessibility violations", async () => {
408
+ const { container } = render(<LoginForm />);
409
+ const results = await axe(container);
410
+ expect(results).toHaveNoViolations();
411
+ });
412
+ ```
413
+
414
+ ### Manual Testing Checklist
415
+
416
+ - Navigate the entire page using only the keyboard (Tab, Shift+Tab, Enter, Escape, Arrow keys)
417
+ - Test with VoiceOver (macOS: Cmd+F5) or NVDA (Windows)
418
+ - Zoom to 200% and verify layout does not break
419
+ - Enable "Reduce Motion" in OS settings and verify animations respect it
420
+ - Test with forced colors mode (Windows High Contrast)
421
+
422
+ ---
423
+
424
+ ## Anti-Patterns
425
+
426
+ | Anti-Pattern | Problem | Correct Approach |
427
+ |---|---|---|
428
+ | `<div onClick>` for buttons | Not keyboard accessible, no role | Use `<button>` |
429
+ | Missing alt text on images | Screen readers say "image" with no context | Descriptive alt or `alt=""` for decorative |
430
+ | `outline: none` without replacement | Keyboard users lose their place | Use `focus-visible` with visible ring |
431
+ | Color-only status indicators | Invisible to color-blind users | Add icons, text, or patterns |
432
+ | Auto-playing media | Disorienting, cannot be stopped | Never auto-play; provide controls |
433
+ | `tabIndex > 0` | Breaks natural tab order | Use `tabIndex={0}` or `tabIndex={-1}` only |
434
+
435
+ ---
436
+
437
+ _Accessibility is not a feature to add later. It is a quality of well-built software. If it does not work with a keyboard and a screen reader, it does not work._