@hustle-together/api-dev-tools 3.12.3 → 4.5.1

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 (159) hide show
  1. package/.claude/adr-requests/.gitkeep +10 -0
  2. package/.claude/agents/adr-researcher.md +109 -0
  3. package/.claude/agents/visual-analyzer.md +183 -0
  4. package/.claude/api-dev-state.json +7 -463
  5. package/.claude/documentation-audit.json +114 -0
  6. package/.claude/registry.json +289 -0
  7. package/.claude/settings.json +45 -1
  8. package/.claude/workflow-logs/None.json +49 -0
  9. package/.claude/workflow-logs/session-20251230-143727.json +106 -0
  10. package/.skills/adr-deep-research/SKILL.md +351 -0
  11. package/.skills/api-create/SKILL.md +116 -17
  12. package/.skills/api-research/SKILL.md +130 -0
  13. package/.skills/docs-sync/SKILL.md +260 -0
  14. package/.skills/docs-update/SKILL.md +205 -0
  15. package/.skills/hustle-brand/SKILL.md +368 -0
  16. package/.skills/hustle-build/SKILL.md +786 -0
  17. package/.skills/hustle-build-review/SKILL.md +518 -0
  18. package/.skills/parallel-spawn/SKILL.md +212 -0
  19. package/.skills/ralph-continue/SKILL.md +151 -0
  20. package/.skills/ralph-loop/SKILL.md +341 -0
  21. package/.skills/ralph-status/SKILL.md +87 -0
  22. package/.skills/refactor/SKILL.md +59 -0
  23. package/.skills/shadcn/SKILL.md +522 -0
  24. package/.skills/test-all/SKILL.md +210 -0
  25. package/.skills/test-builds/SKILL.md +208 -0
  26. package/.skills/test-debug/SKILL.md +212 -0
  27. package/.skills/test-e2e/SKILL.md +168 -0
  28. package/.skills/test-review/SKILL.md +707 -0
  29. package/.skills/test-unit/SKILL.md +143 -0
  30. package/.skills/test-visual/SKILL.md +301 -0
  31. package/.skills/token-report/SKILL.md +132 -0
  32. package/CHANGELOG.md +575 -0
  33. package/README.md +426 -56
  34. package/bin/cli.js +1538 -88
  35. package/commands/hustle-api-create.md +22 -0
  36. package/commands/hustle-build.md +259 -0
  37. package/commands/hustle-combine.md +81 -2
  38. package/commands/hustle-ui-create-page.md +84 -2
  39. package/commands/hustle-ui-create.md +82 -2
  40. package/hooks/__pycache__/api-workflow-check.cpython-314.pyc +0 -0
  41. package/hooks/__pycache__/auto-answer.cpython-314.pyc +0 -0
  42. package/hooks/__pycache__/cache-research.cpython-314.pyc +0 -0
  43. package/hooks/__pycache__/check-api-routes.cpython-314.pyc +0 -0
  44. package/hooks/__pycache__/check-playwright-setup.cpython-314.pyc +0 -0
  45. package/hooks/__pycache__/check-storybook-setup.cpython-314.pyc +0 -0
  46. package/hooks/__pycache__/check-update.cpython-314.pyc +0 -0
  47. package/hooks/__pycache__/completion-promise-detector.cpython-314.pyc +0 -0
  48. package/hooks/__pycache__/context-capacity-warning.cpython-314.pyc +0 -0
  49. package/hooks/__pycache__/detect-interruption.cpython-314.pyc +0 -0
  50. package/hooks/__pycache__/docs-update-check.cpython-314.pyc +0 -0
  51. package/hooks/__pycache__/enforce-a11y-audit.cpython-314.pyc +0 -0
  52. package/hooks/__pycache__/enforce-brand-guide.cpython-314.pyc +0 -0
  53. package/hooks/__pycache__/enforce-component-type-confirm.cpython-314.pyc +0 -0
  54. package/hooks/__pycache__/enforce-deep-research.cpython-314.pyc +0 -0
  55. package/hooks/__pycache__/enforce-disambiguation.cpython-314.pyc +0 -0
  56. package/hooks/__pycache__/enforce-documentation.cpython-314.pyc +0 -0
  57. package/hooks/__pycache__/enforce-dry-run.cpython-314.pyc +0 -0
  58. package/hooks/__pycache__/enforce-environment.cpython-314.pyc +0 -0
  59. package/hooks/__pycache__/enforce-external-research.cpython-314.pyc +0 -0
  60. package/hooks/__pycache__/enforce-freshness.cpython-314.pyc +0 -0
  61. package/hooks/__pycache__/enforce-interview.cpython-314.pyc +0 -0
  62. package/hooks/__pycache__/enforce-page-components.cpython-314.pyc +0 -0
  63. package/hooks/__pycache__/enforce-page-data-schema.cpython-314.pyc +0 -0
  64. package/hooks/__pycache__/enforce-questions-sourced.cpython-314.pyc +0 -0
  65. package/hooks/__pycache__/enforce-refactor.cpython-314.pyc +0 -0
  66. package/hooks/__pycache__/enforce-research.cpython-314.pyc +0 -0
  67. package/hooks/__pycache__/enforce-schema-from-interview.cpython-314.pyc +0 -0
  68. package/hooks/__pycache__/enforce-schema.cpython-314.pyc +0 -0
  69. package/hooks/__pycache__/enforce-scope.cpython-314.pyc +0 -0
  70. package/hooks/__pycache__/enforce-tdd-red.cpython-314.pyc +0 -0
  71. package/hooks/__pycache__/enforce-ui-disambiguation.cpython-314.pyc +0 -0
  72. package/hooks/__pycache__/enforce-ui-interview.cpython-314.pyc +0 -0
  73. package/hooks/__pycache__/enforce-verify.cpython-314.pyc +0 -0
  74. package/hooks/__pycache__/generate-adr-options.cpython-314.pyc +0 -0
  75. package/hooks/__pycache__/generate-manifest-entry.cpython-314.pyc +0 -0
  76. package/hooks/__pycache__/hook_utils.cpython-314.pyc +0 -0
  77. package/hooks/__pycache__/notify-input-needed.cpython-314.pyc +0 -0
  78. package/hooks/__pycache__/notify-phase-complete.cpython-314.pyc +0 -0
  79. package/hooks/__pycache__/ntfy-on-question.cpython-314.pyc +0 -0
  80. package/hooks/__pycache__/orchestrator-completion.cpython-314.pyc +0 -0
  81. package/hooks/__pycache__/orchestrator-handoff.cpython-314.pyc +0 -0
  82. package/hooks/__pycache__/orchestrator-session-startup.cpython-314.pyc +0 -0
  83. package/hooks/__pycache__/parallel-orchestrator.cpython-314.pyc +0 -0
  84. package/hooks/__pycache__/periodic-reground.cpython-314.pyc +0 -0
  85. package/hooks/__pycache__/project-document-prompt.cpython-314.pyc +0 -0
  86. package/hooks/__pycache__/remote-question-proxy.cpython-314.pyc +0 -0
  87. package/hooks/__pycache__/remote-question-server.cpython-314.pyc +0 -0
  88. package/hooks/__pycache__/run-code-review.cpython-314.pyc +0 -0
  89. package/hooks/__pycache__/run-visual-qa.cpython-314.pyc +0 -0
  90. package/hooks/__pycache__/session-logger.cpython-314.pyc +0 -0
  91. package/hooks/__pycache__/session-startup.cpython-314.pyc +0 -0
  92. package/hooks/__pycache__/track-scope-coverage.cpython-314.pyc +0 -0
  93. package/hooks/__pycache__/track-token-usage.cpython-314.pyc +0 -0
  94. package/hooks/__pycache__/track-tool-use.cpython-314.pyc +0 -0
  95. package/hooks/__pycache__/update-adr-decision.cpython-314.pyc +0 -0
  96. package/hooks/__pycache__/update-api-showcase.cpython-314.pyc +0 -0
  97. package/hooks/__pycache__/update-registry.cpython-314.pyc +0 -0
  98. package/hooks/__pycache__/update-ui-showcase.cpython-314.pyc +0 -0
  99. package/hooks/__pycache__/verify-after-green.cpython-314.pyc +0 -0
  100. package/hooks/__pycache__/verify-implementation.cpython-314.pyc +0 -0
  101. package/hooks/api-workflow-check.py +34 -0
  102. package/hooks/auto-answer.py +305 -0
  103. package/hooks/check-update.py +132 -0
  104. package/hooks/completion-promise-detector.py +293 -0
  105. package/hooks/context-capacity-warning.py +171 -0
  106. package/hooks/docs-update-check.py +120 -0
  107. package/hooks/enforce-dry-run.py +134 -0
  108. package/hooks/enforce-external-research.py +25 -0
  109. package/hooks/enforce-interview.py +20 -0
  110. package/hooks/generate-adr-options.py +282 -0
  111. package/hooks/hook_utils.py +609 -0
  112. package/hooks/lib/__pycache__/__init__.cpython-314.pyc +0 -0
  113. package/hooks/lib/__pycache__/greptile.cpython-314.pyc +0 -0
  114. package/hooks/lib/__pycache__/ntfy.cpython-314.pyc +0 -0
  115. package/hooks/ntfy-on-question.py +240 -0
  116. package/hooks/orchestrator-completion.py +313 -0
  117. package/hooks/orchestrator-handoff.py +267 -0
  118. package/hooks/orchestrator-session-startup.py +146 -0
  119. package/hooks/parallel-orchestrator.py +451 -0
  120. package/hooks/periodic-reground.py +270 -67
  121. package/hooks/project-document-prompt.py +302 -0
  122. package/hooks/remote-question-proxy.py +284 -0
  123. package/hooks/remote-question-server.py +1224 -0
  124. package/hooks/run-code-review.py +176 -29
  125. package/hooks/run-visual-qa.py +338 -0
  126. package/hooks/session-logger.py +27 -1
  127. package/hooks/session-startup.py +113 -0
  128. package/hooks/update-adr-decision.py +236 -0
  129. package/hooks/update-api-showcase.py +13 -1
  130. package/hooks/update-testing-checklist.py +195 -0
  131. package/hooks/update-ui-showcase.py +13 -1
  132. package/package.json +7 -3
  133. package/scripts/extract-schema-docs.cjs +322 -0
  134. package/templates/.skills/hustle-interview/SKILL.md +174 -0
  135. package/templates/CLAUDE-SECTION.md +89 -64
  136. package/templates/adr-viewer/_components/ADRViewer.tsx +326 -0
  137. package/templates/api-dev-state.json +33 -1
  138. package/templates/api-showcase/_components/APIModal.tsx +100 -8
  139. package/templates/api-showcase/_components/APIShowcase.tsx +36 -4
  140. package/templates/api-showcase/_components/APITester.tsx +367 -58
  141. package/templates/brand-page/page.tsx +645 -0
  142. package/templates/component/Component.visual.spec.ts +30 -24
  143. package/templates/docs/page.tsx +230 -0
  144. package/templates/eslint-plugin-zod-schema/index.js +446 -0
  145. package/templates/eslint-plugin-zod-schema/package.json +26 -0
  146. package/templates/github-workflows/security.yml +274 -0
  147. package/templates/hustle-build-defaults.json +136 -0
  148. package/templates/hustle-dev-dashboard/page.tsx +365 -0
  149. package/templates/page/page.e2e.test.ts +30 -26
  150. package/templates/performance-budgets.json +63 -5
  151. package/templates/playwright-report/page.tsx +258 -0
  152. package/templates/registry.json +279 -3
  153. package/templates/review-dashboard/page.tsx +510 -0
  154. package/templates/settings.json +155 -7
  155. package/templates/test-results/page.tsx +237 -0
  156. package/templates/typedoc.json +19 -0
  157. package/templates/ui-showcase/_components/UIShowcase.tsx +48 -1
  158. package/templates/ui-showcase/_components/VisualTestingDashboard.tsx +579 -0
  159. package/templates/ui-showcase/page.tsx +1 -1
@@ -91,32 +91,38 @@ test.describe("__COMPONENT_NAME__ Visual Regression", () => {
91
91
  });
92
92
 
93
93
  // ===================================
94
- // Responsive Viewport Tests
94
+ // Responsive Viewport Tests (7 Viewports)
95
95
  // ===================================
96
96
 
97
- test("renders correctly on mobile viewport", async ({ page }) => {
98
- await page.setViewportSize({ width: 375, height: 667 });
99
- await page.goto(
100
- `${STORYBOOK_URL}/iframe.html?id=components-__component_name__--primary&viewMode=story`,
101
- );
102
- await page.waitForLoadState("networkidle");
103
-
104
- await expect(page.locator("#storybook-root")).toHaveScreenshot(
105
- "__COMPONENT_NAME__-mobile.png",
106
- );
107
- });
108
-
109
- test("renders correctly on tablet viewport", async ({ page }) => {
110
- await page.setViewportSize({ width: 768, height: 1024 });
111
- await page.goto(
112
- `${STORYBOOK_URL}/iframe.html?id=components-__component_name__--primary&viewMode=story`,
113
- );
114
- await page.waitForLoadState("networkidle");
115
-
116
- await expect(page.locator("#storybook-root")).toHaveScreenshot(
117
- "__COMPONENT_NAME__-tablet.png",
118
- );
119
- });
97
+ // All 7 viewports from performance-budgets.json
98
+ const viewports = [
99
+ { name: "mobile-portrait", width: 375, height: 667 },
100
+ { name: "mobile-notch", width: 393, height: 852 },
101
+ { name: "mobile-landscape", width: 667, height: 375 },
102
+ { name: "tablet-portrait", width: 768, height: 1024 },
103
+ { name: "tablet-landscape", width: 1024, height: 768 },
104
+ { name: "small-desktop", width: 1280, height: 720 },
105
+ { name: "desktop", width: 1920, height: 1080 },
106
+ ];
107
+
108
+ for (const viewport of viewports) {
109
+ test(`renders correctly on ${viewport.name} (${viewport.width}x${viewport.height})`, async ({
110
+ page,
111
+ }) => {
112
+ await page.setViewportSize({
113
+ width: viewport.width,
114
+ height: viewport.height,
115
+ });
116
+ await page.goto(
117
+ `${STORYBOOK_URL}/iframe.html?id=components-__component_name__--primary&viewMode=story`,
118
+ );
119
+ await page.waitForLoadState("networkidle");
120
+
121
+ await expect(page.locator("#storybook-root")).toHaveScreenshot(
122
+ `__COMPONENT_NAME__-${viewport.name}.png`,
123
+ );
124
+ });
125
+ }
120
126
 
121
127
  // ===================================
122
128
  // Interaction State Tests
@@ -0,0 +1,230 @@
1
+ "use client";
2
+
3
+ import Link from "next/link";
4
+ import { useEffect, useState } from "react";
5
+
6
+ /**
7
+ * Documentation Page
8
+ *
9
+ * Shows TypeDoc-generated documentation or instructions to generate it.
10
+ * Links to the generated markdown files in docs/api/.
11
+ *
12
+ * Created with Hustle API Dev Tools (v3.12.12)
13
+ */
14
+ export default function DocsPage() {
15
+ const [hasContent, setHasContent] = useState<boolean | null>(null);
16
+
17
+ useEffect(() => {
18
+ // Check if docs exist by trying to fetch the index
19
+ fetch("/docs/api/README.md")
20
+ .then((res) => {
21
+ setHasContent(res.ok);
22
+ })
23
+ .catch(() => {
24
+ setHasContent(false);
25
+ });
26
+ }, []);
27
+
28
+ return (
29
+ <div className="min-h-screen bg-white dark:bg-gray-950">
30
+ {/* Header */}
31
+ <header className="border-b-4 border-black bg-[#BA0C2F] px-6 py-8 dark:border-gray-600">
32
+ <div className="mx-auto max-w-4xl">
33
+ <div className="flex items-center gap-2">
34
+ <Link
35
+ href="/hustle-dev-dashboard"
36
+ className="text-white/80 hover:text-white"
37
+ >
38
+ Dashboard
39
+ </Link>
40
+ <span className="text-white/60">/</span>
41
+ <span className="text-white">Documentation</span>
42
+ </div>
43
+ <h1 className="mt-2 text-3xl font-black text-white">
44
+ API DOCUMENTATION
45
+ </h1>
46
+ <p className="mt-2 text-white/80">
47
+ TypeDoc-generated code documentation
48
+ </p>
49
+ </div>
50
+ </header>
51
+
52
+ {/* Main Content */}
53
+ <main className="mx-auto max-w-4xl px-6 py-8">
54
+ {hasContent === null ? (
55
+ <div className="flex items-center justify-center py-16">
56
+ <div className="h-8 w-8 animate-spin rounded-full border-4 border-[#BA0C2F] border-t-transparent" />
57
+ </div>
58
+ ) : hasContent ? (
59
+ <DocsContent />
60
+ ) : (
61
+ <EmptyState />
62
+ )}
63
+ </main>
64
+
65
+ {/* Footer */}
66
+ <footer className="border-t-2 border-black px-6 py-4 dark:border-gray-600">
67
+ <div className="mx-auto max-w-4xl text-center text-sm text-gray-600 dark:text-gray-400">
68
+ Built with{" "}
69
+ <a
70
+ href="https://github.com/hustle-together/api-dev-tools"
71
+ className="font-bold text-[#BA0C2F] hover:underline"
72
+ >
73
+ Hustle API Dev Tools
74
+ </a>
75
+ </div>
76
+ </footer>
77
+ </div>
78
+ );
79
+ }
80
+
81
+ function DocsContent() {
82
+ return (
83
+ <div className="space-y-6">
84
+ <div className="border-2 border-black p-6 dark:border-gray-600">
85
+ <h2 className="mb-4 text-xl font-bold text-black dark:text-white">
86
+ Generated Documentation
87
+ </h2>
88
+ <p className="mb-4 text-gray-600 dark:text-gray-400">
89
+ Documentation has been generated. Browse the API reference:
90
+ </p>
91
+ <div className="space-y-2">
92
+ <DocLink href="/docs/api" title="API Reference" description="Full API documentation" />
93
+ </div>
94
+ </div>
95
+
96
+ <div className="border-2 border-black bg-gray-50 p-6 dark:border-gray-600 dark:bg-gray-900">
97
+ <h3 className="mb-2 font-bold text-black dark:text-white">
98
+ Regenerate Documentation
99
+ </h3>
100
+ <p className="mb-4 text-sm text-gray-600 dark:text-gray-400">
101
+ Run this command to update the documentation:
102
+ </p>
103
+ <code className="block rounded bg-white px-4 py-2 font-mono text-[#BA0C2F] dark:bg-gray-800">
104
+ pnpm typedoc
105
+ </code>
106
+ </div>
107
+ </div>
108
+ );
109
+ }
110
+
111
+ function EmptyState() {
112
+ return (
113
+ <div className="space-y-6">
114
+ {/* Status Card */}
115
+ <div className="border-2 border-black p-6 dark:border-gray-600">
116
+ <div className="flex items-center gap-3">
117
+ <div className="flex h-12 w-12 items-center justify-center rounded-full bg-gray-100 text-2xl dark:bg-gray-800">
118
+ 0
119
+ </div>
120
+ <div>
121
+ <h2 className="text-xl font-bold text-black dark:text-white">
122
+ No Documentation Generated
123
+ </h2>
124
+ <p className="text-gray-600 dark:text-gray-400">
125
+ Run TypeDoc to generate API documentation
126
+ </p>
127
+ </div>
128
+ </div>
129
+ </div>
130
+
131
+ {/* Instructions */}
132
+ <div className="border-2 border-black bg-gray-50 p-6 dark:border-gray-600 dark:bg-gray-900">
133
+ <h3 className="mb-4 font-bold text-black dark:text-white">
134
+ Generate Documentation
135
+ </h3>
136
+ <div className="space-y-4">
137
+ <Step
138
+ number={1}
139
+ title="Run TypeDoc"
140
+ command="pnpm typedoc"
141
+ description="Generates Markdown documentation from TSDoc comments"
142
+ />
143
+ <Step
144
+ number={2}
145
+ title="View Output"
146
+ command="ls docs/api/"
147
+ description="Documentation files are generated in the docs/api/ folder"
148
+ />
149
+ <Step
150
+ number={3}
151
+ title="Refresh Page"
152
+ description="Refresh this page to see your documentation"
153
+ />
154
+ </div>
155
+ </div>
156
+
157
+ {/* Requirements */}
158
+ <div className="border-2 border-black p-6 dark:border-gray-600">
159
+ <h3 className="mb-4 font-bold text-black dark:text-white">
160
+ Requirements
161
+ </h3>
162
+ <ul className="space-y-2 text-sm text-gray-600 dark:text-gray-400">
163
+ <li className="flex items-center gap-2">
164
+ <span className="text-[#BA0C2F]">*</span>
165
+ typedoc.json configuration file in project root
166
+ </li>
167
+ <li className="flex items-center gap-2">
168
+ <span className="text-[#BA0C2F]">*</span>
169
+ TSDoc comments in your TypeScript files
170
+ </li>
171
+ <li className="flex items-center gap-2">
172
+ <span className="text-[#BA0C2F]">*</span>
173
+ typedoc and typedoc-plugin-markdown installed
174
+ </li>
175
+ </ul>
176
+ </div>
177
+ </div>
178
+ );
179
+ }
180
+
181
+ function Step({
182
+ number,
183
+ title,
184
+ command,
185
+ description,
186
+ }: {
187
+ number: number;
188
+ title: string;
189
+ command?: string;
190
+ description: string;
191
+ }) {
192
+ return (
193
+ <div className="flex gap-4">
194
+ <div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-[#BA0C2F] text-sm font-bold text-white">
195
+ {number}
196
+ </div>
197
+ <div>
198
+ <p className="font-medium text-black dark:text-white">{title}</p>
199
+ {command && (
200
+ <code className="mt-1 block rounded bg-white px-3 py-1 font-mono text-sm text-[#BA0C2F] dark:bg-gray-800">
201
+ {command}
202
+ </code>
203
+ )}
204
+ <p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
205
+ {description}
206
+ </p>
207
+ </div>
208
+ </div>
209
+ );
210
+ }
211
+
212
+ function DocLink({
213
+ href,
214
+ title,
215
+ description,
216
+ }: {
217
+ href: string;
218
+ title: string;
219
+ description: string;
220
+ }) {
221
+ return (
222
+ <Link
223
+ href={href}
224
+ className="block rounded border border-gray-200 p-4 transition-colors hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800"
225
+ >
226
+ <p className="font-medium text-[#BA0C2F]">{title}</p>
227
+ <p className="text-sm text-gray-600 dark:text-gray-400">{description}</p>
228
+ </Link>
229
+ );
230
+ }