agentic-loop 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 (162) hide show
  1. package/.claude/commands/explain.md +114 -0
  2. package/.claude/commands/idea.md +398 -0
  3. package/.claude/commands/my-dna.md +122 -0
  4. package/.claude/commands/prd.md +286 -0
  5. package/.claude/commands/review.md +167 -0
  6. package/.claude/commands/sign.md +32 -0
  7. package/.claude/commands/styleguide.md +450 -0
  8. package/.claude/commands/tour.md +301 -0
  9. package/.claude/commands/vibe-check.md +116 -0
  10. package/.claude/commands/vibe-help.md +47 -0
  11. package/.claude/commands/vibe-list.md +203 -0
  12. package/.pre-commit-hooks.yaml +102 -0
  13. package/LICENSE +21 -0
  14. package/README.md +238 -0
  15. package/bin/agentic-loop.sh +24 -0
  16. package/bin/postinstall.sh +29 -0
  17. package/bin/ralph.sh +171 -0
  18. package/bin/vibe-check.js +19 -0
  19. package/dist/checks/check-any-types.d.ts +6 -0
  20. package/dist/checks/check-any-types.d.ts.map +1 -0
  21. package/dist/checks/check-any-types.js +73 -0
  22. package/dist/checks/check-any-types.js.map +1 -0
  23. package/dist/checks/check-commented-code.d.ts +6 -0
  24. package/dist/checks/check-commented-code.d.ts.map +1 -0
  25. package/dist/checks/check-commented-code.js +81 -0
  26. package/dist/checks/check-commented-code.js.map +1 -0
  27. package/dist/checks/check-console-error.d.ts +6 -0
  28. package/dist/checks/check-console-error.d.ts.map +1 -0
  29. package/dist/checks/check-console-error.js +41 -0
  30. package/dist/checks/check-console-error.js.map +1 -0
  31. package/dist/checks/check-debug-statements.d.ts +6 -0
  32. package/dist/checks/check-debug-statements.d.ts.map +1 -0
  33. package/dist/checks/check-debug-statements.js +120 -0
  34. package/dist/checks/check-debug-statements.js.map +1 -0
  35. package/dist/checks/check-deep-nesting.d.ts +6 -0
  36. package/dist/checks/check-deep-nesting.d.ts.map +1 -0
  37. package/dist/checks/check-deep-nesting.js +116 -0
  38. package/dist/checks/check-deep-nesting.js.map +1 -0
  39. package/dist/checks/check-docker-platform.d.ts +6 -0
  40. package/dist/checks/check-docker-platform.d.ts.map +1 -0
  41. package/dist/checks/check-docker-platform.js +42 -0
  42. package/dist/checks/check-docker-platform.js.map +1 -0
  43. package/dist/checks/check-dry-violations.d.ts +6 -0
  44. package/dist/checks/check-dry-violations.d.ts.map +1 -0
  45. package/dist/checks/check-dry-violations.js +124 -0
  46. package/dist/checks/check-dry-violations.js.map +1 -0
  47. package/dist/checks/check-empty-catch.d.ts +6 -0
  48. package/dist/checks/check-empty-catch.d.ts.map +1 -0
  49. package/dist/checks/check-empty-catch.js +111 -0
  50. package/dist/checks/check-empty-catch.js.map +1 -0
  51. package/dist/checks/check-function-length.d.ts +6 -0
  52. package/dist/checks/check-function-length.d.ts.map +1 -0
  53. package/dist/checks/check-function-length.js +152 -0
  54. package/dist/checks/check-function-length.js.map +1 -0
  55. package/dist/checks/check-hardcoded-ai-models.d.ts +10 -0
  56. package/dist/checks/check-hardcoded-ai-models.d.ts.map +1 -0
  57. package/dist/checks/check-hardcoded-ai-models.js +102 -0
  58. package/dist/checks/check-hardcoded-ai-models.js.map +1 -0
  59. package/dist/checks/check-hardcoded-urls.d.ts +6 -0
  60. package/dist/checks/check-hardcoded-urls.d.ts.map +1 -0
  61. package/dist/checks/check-hardcoded-urls.js +124 -0
  62. package/dist/checks/check-hardcoded-urls.js.map +1 -0
  63. package/dist/checks/check-magic-numbers.d.ts +6 -0
  64. package/dist/checks/check-magic-numbers.d.ts.map +1 -0
  65. package/dist/checks/check-magic-numbers.js +116 -0
  66. package/dist/checks/check-magic-numbers.js.map +1 -0
  67. package/dist/checks/check-secrets.d.ts +6 -0
  68. package/dist/checks/check-secrets.d.ts.map +1 -0
  69. package/dist/checks/check-secrets.js +138 -0
  70. package/dist/checks/check-secrets.js.map +1 -0
  71. package/dist/checks/check-snake-case-ts.d.ts +6 -0
  72. package/dist/checks/check-snake-case-ts.d.ts.map +1 -0
  73. package/dist/checks/check-snake-case-ts.js +78 -0
  74. package/dist/checks/check-snake-case-ts.js.map +1 -0
  75. package/dist/checks/check-todo-fixme.d.ts +6 -0
  76. package/dist/checks/check-todo-fixme.d.ts.map +1 -0
  77. package/dist/checks/check-todo-fixme.js +41 -0
  78. package/dist/checks/check-todo-fixme.js.map +1 -0
  79. package/dist/checks/check-unsafe-html.d.ts +6 -0
  80. package/dist/checks/check-unsafe-html.d.ts.map +1 -0
  81. package/dist/checks/check-unsafe-html.js +101 -0
  82. package/dist/checks/check-unsafe-html.js.map +1 -0
  83. package/dist/checks/index.d.ts +30 -0
  84. package/dist/checks/index.d.ts.map +1 -0
  85. package/dist/checks/index.js +57 -0
  86. package/dist/checks/index.js.map +1 -0
  87. package/dist/cli.d.ts +13 -0
  88. package/dist/cli.d.ts.map +1 -0
  89. package/dist/cli.js +208 -0
  90. package/dist/cli.js.map +1 -0
  91. package/dist/index.d.ts +9 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +10 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/utils/file-reader.d.ts +24 -0
  96. package/dist/utils/file-reader.d.ts.map +1 -0
  97. package/dist/utils/file-reader.js +146 -0
  98. package/dist/utils/file-reader.js.map +1 -0
  99. package/dist/utils/patterns.d.ts +27 -0
  100. package/dist/utils/patterns.d.ts.map +1 -0
  101. package/dist/utils/patterns.js +84 -0
  102. package/dist/utils/patterns.js.map +1 -0
  103. package/dist/utils/reporters.d.ts +21 -0
  104. package/dist/utils/reporters.d.ts.map +1 -0
  105. package/dist/utils/reporters.js +115 -0
  106. package/dist/utils/reporters.js.map +1 -0
  107. package/dist/utils/types.d.ts +71 -0
  108. package/dist/utils/types.d.ts.map +1 -0
  109. package/dist/utils/types.js +5 -0
  110. package/dist/utils/types.js.map +1 -0
  111. package/package.json +83 -0
  112. package/ralph/api.sh +216 -0
  113. package/ralph/backup.sh +838 -0
  114. package/ralph/browser-verify/README.md +135 -0
  115. package/ralph/browser-verify/verify.ts +450 -0
  116. package/ralph/checks/check-fastapi-responses.py +155 -0
  117. package/ralph/hooks/hooks-config.json +72 -0
  118. package/ralph/hooks/inject-context.sh +44 -0
  119. package/ralph/hooks/install.sh +207 -0
  120. package/ralph/hooks/log-tools.sh +45 -0
  121. package/ralph/hooks/protect-prd.sh +27 -0
  122. package/ralph/hooks/save-learnings.sh +36 -0
  123. package/ralph/hooks/warn-debug.sh +54 -0
  124. package/ralph/hooks/warn-empty-catch.sh +63 -0
  125. package/ralph/hooks/warn-secrets.sh +89 -0
  126. package/ralph/hooks/warn-urls.sh +77 -0
  127. package/ralph/init.sh +515 -0
  128. package/ralph/loop.sh +730 -0
  129. package/ralph/playwright.sh +238 -0
  130. package/ralph/prd.sh +295 -0
  131. package/ralph/setup/feature-tour.sh +155 -0
  132. package/ralph/setup/quick-setup.sh +239 -0
  133. package/ralph/setup/tutorial.sh +159 -0
  134. package/ralph/setup/ui.sh +136 -0
  135. package/ralph/setup.sh +401 -0
  136. package/ralph/signs.sh +150 -0
  137. package/ralph/utils.sh +682 -0
  138. package/ralph/verify/browser.sh +324 -0
  139. package/ralph/verify/lint.sh +363 -0
  140. package/ralph/verify/review.sh +152 -0
  141. package/ralph/verify/tests.sh +81 -0
  142. package/ralph/verify.sh +268 -0
  143. package/templates/PROMPT.md +235 -0
  144. package/templates/config/fullstack.json +86 -0
  145. package/templates/config/go.json +81 -0
  146. package/templates/config/minimal.json +76 -0
  147. package/templates/config/node.json +81 -0
  148. package/templates/config/python.json +81 -0
  149. package/templates/config/rust.json +81 -0
  150. package/templates/examples/CLAUDE-django.md +174 -0
  151. package/templates/examples/CLAUDE-fastapi.md +270 -0
  152. package/templates/examples/CLAUDE-fastmcp.md +352 -0
  153. package/templates/examples/CLAUDE-fullstack.md +256 -0
  154. package/templates/examples/CLAUDE-node.md +246 -0
  155. package/templates/examples/CLAUDE-react.md +138 -0
  156. package/templates/optional/cursorrules.template +147 -0
  157. package/templates/optional/eslint.config.js +34 -0
  158. package/templates/optional/lint-staged.config.js +34 -0
  159. package/templates/optional/ruff.toml +125 -0
  160. package/templates/optional/vibe-check.yml +116 -0
  161. package/templates/optional/vscode-settings.json +127 -0
  162. package/templates/signs.json +46 -0
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Output formatters for CLI results
3
+ */
4
+ // ANSI color codes
5
+ const colors = {
6
+ reset: '\x1b[0m',
7
+ bold: '\x1b[1m',
8
+ dim: '\x1b[2m',
9
+ red: '\x1b[31m',
10
+ yellow: '\x1b[33m',
11
+ blue: '\x1b[34m',
12
+ cyan: '\x1b[36m',
13
+ gray: '\x1b[90m',
14
+ };
15
+ function severityColor(severity) {
16
+ switch (severity) {
17
+ case 'error':
18
+ return colors.red;
19
+ case 'warning':
20
+ return colors.yellow;
21
+ case 'info':
22
+ return colors.blue;
23
+ }
24
+ }
25
+ function severityIcon(severity) {
26
+ switch (severity) {
27
+ case 'error':
28
+ return '✖';
29
+ case 'warning':
30
+ return '⚠';
31
+ case 'info':
32
+ return 'ℹ';
33
+ }
34
+ }
35
+ /**
36
+ * Pretty format - colored terminal output
37
+ */
38
+ export function formatPretty(summary) {
39
+ const lines = [];
40
+ // Header
41
+ lines.push('');
42
+ lines.push(`${colors.bold}vibe-check${colors.reset}`);
43
+ lines.push('');
44
+ // Results by file
45
+ for (const result of summary.results) {
46
+ if (result.issues.length === 0)
47
+ continue;
48
+ lines.push(`${colors.cyan}${result.filePath}${colors.reset}`);
49
+ for (const issue of result.issues) {
50
+ const color = severityColor(issue.severity);
51
+ const icon = severityIcon(issue.severity);
52
+ const location = issue.column
53
+ ? `${issue.line}:${issue.column}`
54
+ : `${issue.line}`;
55
+ lines.push(` ${colors.gray}${location.padEnd(8)}${colors.reset}` +
56
+ `${color}${icon}${colors.reset} ` +
57
+ `${issue.message} ${colors.dim}${issue.ruleId}${colors.reset}`);
58
+ }
59
+ lines.push('');
60
+ }
61
+ // Summary
62
+ const problems = [];
63
+ if (summary.errorCount > 0) {
64
+ problems.push(`${colors.red}${summary.errorCount} error${summary.errorCount === 1 ? '' : 's'}${colors.reset}`);
65
+ }
66
+ if (summary.warningCount > 0) {
67
+ problems.push(`${colors.yellow}${summary.warningCount} warning${summary.warningCount === 1 ? '' : 's'}${colors.reset}`);
68
+ }
69
+ if (summary.infoCount > 0) {
70
+ problems.push(`${colors.blue}${summary.infoCount} info${colors.reset}`);
71
+ }
72
+ if (problems.length > 0) {
73
+ lines.push(`${problems.join(', ')} in ${summary.filesWithIssues} file${summary.filesWithIssues === 1 ? '' : 's'}`);
74
+ }
75
+ else {
76
+ lines.push(`${colors.bold}✓${colors.reset} ${summary.filesChecked} file${summary.filesChecked === 1 ? '' : 's'} checked - no issues found`);
77
+ }
78
+ lines.push('');
79
+ return lines.join('\n');
80
+ }
81
+ /**
82
+ * JSON format - machine-readable output
83
+ */
84
+ export function formatJson(summary) {
85
+ return JSON.stringify(summary, null, 2);
86
+ }
87
+ /**
88
+ * Compact format - one line per issue
89
+ */
90
+ export function formatCompact(summary) {
91
+ const lines = [];
92
+ for (const result of summary.results) {
93
+ for (const issue of result.issues) {
94
+ const location = issue.column
95
+ ? `${issue.line}:${issue.column}`
96
+ : `${issue.line}`;
97
+ lines.push(`${result.filePath}:${location}: ${issue.severity}: ${issue.message} [${issue.ruleId}]`);
98
+ }
99
+ }
100
+ return lines.join('\n');
101
+ }
102
+ /**
103
+ * Format results based on output format option
104
+ */
105
+ export function formatResults(summary, format) {
106
+ switch (format) {
107
+ case 'pretty':
108
+ return formatPretty(summary);
109
+ case 'json':
110
+ return formatJson(summary);
111
+ case 'compact':
112
+ return formatCompact(summary);
113
+ }
114
+ }
115
+ //# sourceMappingURL=reporters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporters.js","sourceRoot":"","sources":["../../src/utils/reporters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Shared types for agentic-loop
3
+ */
4
+ export type Severity = 'error' | 'warning' | 'info';
5
+ export interface FileContext {
6
+ /** Absolute path to the file */
7
+ filePath: string;
8
+ /** File content as string */
9
+ content: string;
10
+ /** File extension without dot (e.g., 'ts', 'py') */
11
+ extension: string;
12
+ }
13
+ export interface HookResult {
14
+ /** 1-based line number */
15
+ line: number;
16
+ /** 0-based column number */
17
+ column?: number;
18
+ /** Human-readable message */
19
+ message: string;
20
+ /** Severity level */
21
+ severity: Severity;
22
+ /** Rule identifier (e.g., 'secrets/aws-key') */
23
+ ruleId: string;
24
+ /** Optional fix suggestion */
25
+ fix?: string;
26
+ }
27
+ export interface Hook {
28
+ /** Unique identifier (e.g., 'secrets', 'debug-statements') */
29
+ id: string;
30
+ /** Human-readable name */
31
+ name: string;
32
+ /** Description of what this hook checks */
33
+ description: string;
34
+ /** Default severity level */
35
+ severity: Severity;
36
+ /** File extensions this hook applies to (without dots) */
37
+ fileTypes: string[];
38
+ /** Check function that returns issues found */
39
+ check: (context: FileContext) => HookResult[];
40
+ }
41
+ export interface CheckOptions {
42
+ /** Only run these hooks (by id) */
43
+ only?: string[];
44
+ /** Skip these hooks (by id) */
45
+ skip?: string[];
46
+ /** Minimum severity to fail on */
47
+ failOn?: Severity;
48
+ /** Output format */
49
+ format?: 'pretty' | 'json' | 'compact';
50
+ /** Auto-fix issues where possible */
51
+ fix?: boolean;
52
+ }
53
+ export interface CheckResult {
54
+ /** File path */
55
+ filePath: string;
56
+ /** All issues found in this file */
57
+ issues: HookResult[];
58
+ }
59
+ export interface SummaryResult {
60
+ /** Total files checked */
61
+ filesChecked: number;
62
+ /** Files with issues */
63
+ filesWithIssues: number;
64
+ /** Total issues by severity */
65
+ errorCount: number;
66
+ warningCount: number;
67
+ infoCount: number;
68
+ /** All results */
69
+ results: CheckResult[];
70
+ }
71
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,gCAAgC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,IAAI;IACnB,8DAA8D;IAC9D,EAAE,EAAE,MAAM,CAAC;IACX,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,0DAA0D;IAC1D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,+CAA+C;IAC/C,KAAK,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,UAAU,EAAE,CAAC;CAC/C;AAED,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,kCAAkC;IAClC,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,oBAAoB;IACpB,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IACvC,qCAAqC;IACrC,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,wBAAwB;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Shared types for agentic-loop
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,83 @@
1
+ {
2
+ "name": "agentic-loop",
3
+ "version": "1.0.0",
4
+ "description": "Autonomous AI coding loop - PRD-driven development with Claude Code",
5
+ "author": "Allie Jones <allie@allthrive.ai>",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/allthriveai/agentic-loop"
10
+ },
11
+ "homepage": "https://github.com/allthriveai/agentic-loop#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/allthriveai/agentic-loop/issues"
14
+ },
15
+ "keywords": [
16
+ "ai",
17
+ "agentic",
18
+ "autonomous",
19
+ "claude",
20
+ "claude-code",
21
+ "coding-agent",
22
+ "prd",
23
+ "ralph",
24
+ "ai-development",
25
+ "code-generation"
26
+ ],
27
+ "type": "module",
28
+ "main": "dist/index.js",
29
+ "types": "dist/index.d.ts",
30
+ "bin": {
31
+ "agentic-loop": "./bin/agentic-loop.sh",
32
+ "vibe-check": "./bin/vibe-check.js"
33
+ },
34
+ "exports": {
35
+ ".": {
36
+ "types": "./dist/index.d.ts",
37
+ "import": "./dist/index.js"
38
+ }
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "bin",
43
+ "ralph",
44
+ "templates",
45
+ ".claude",
46
+ ".pre-commit-hooks.yaml"
47
+ ],
48
+ "scripts": {
49
+ "build": "tsc",
50
+ "dev": "tsc --watch",
51
+ "test": "vitest",
52
+ "test:run": "vitest run",
53
+ "lint": "eslint src",
54
+ "typecheck": "tsc --noEmit",
55
+ "clean": "rm -rf dist",
56
+ "prepublishOnly": "npm run clean && npm run build",
57
+ "postinstall": "./bin/postinstall.sh",
58
+ "release": "npm version patch && git push && git push --tags && npm publish",
59
+ "release:minor": "npm version minor && git push && git push --tags && npm publish",
60
+ "release:major": "npm version major && git push && git push --tags && npm publish"
61
+ },
62
+ "engines": {
63
+ "node": ">=18.0.0"
64
+ },
65
+ "peerDependencies": {
66
+ "playwright": ">=1.40.0"
67
+ },
68
+ "peerDependenciesMeta": {
69
+ "playwright": {
70
+ "optional": true
71
+ }
72
+ },
73
+ "dependencies": {
74
+ "tsx": "^4.0.0"
75
+ },
76
+ "devDependencies": {
77
+ "@types/node": "^20.0.0",
78
+ "eslint": "^9.0.0",
79
+ "playwright": "^1.40.0",
80
+ "typescript": "^5.0.0",
81
+ "vitest": "^4.0.18"
82
+ }
83
+ }
package/ralph/api.sh ADDED
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env bash
2
+ # shellcheck shell=bash
3
+ # api.sh - API validation for backend stories
4
+
5
+ # Parse an endpoint string into method and path
6
+ # Usage: parse_endpoint "POST /api/users" "http://localhost:3000"
7
+ # Sets: ENDPOINT_METHOD, ENDPOINT_PATH, ENDPOINT_URL
8
+ parse_endpoint() {
9
+ local endpoint="$1"
10
+ local base_url="${2:-}"
11
+
12
+ # Defaults
13
+ ENDPOINT_METHOD="GET"
14
+ ENDPOINT_PATH="$endpoint"
15
+ ENDPOINT_URL=""
16
+
17
+ # Parse method if present (e.g., "POST /api/contact")
18
+ if [[ "$endpoint" =~ ^(GET|POST|PUT|PATCH|DELETE)[[:space:]]+(.*) ]]; then
19
+ ENDPOINT_METHOD="${BASH_REMATCH[1]}"
20
+ ENDPOINT_PATH="${BASH_REMATCH[2]}"
21
+ fi
22
+
23
+ # Build full URL
24
+ if [[ "$ENDPOINT_PATH" =~ ^https?:// ]]; then
25
+ ENDPOINT_URL="$ENDPOINT_PATH"
26
+ elif [[ -n "$base_url" ]]; then
27
+ ENDPOINT_URL="${base_url}${ENDPOINT_PATH}"
28
+ fi
29
+ }
30
+
31
+ # Check if endpoint is a WebSocket (can't be tested with HTTP)
32
+ is_websocket_endpoint() {
33
+ local endpoint="$1"
34
+ [[ "$endpoint" =~ ^wss?:// ]] || [[ "$endpoint" =~ ^(GET|POST|PUT|PATCH|DELETE)[[:space:]]+wss?:// ]]
35
+ }
36
+
37
+ # Validate API endpoints for a backend story
38
+ run_api_validation() {
39
+ local story="$1"
40
+
41
+ # Get API endpoints from story
42
+ local endpoints
43
+ endpoints=$(jq -r --arg id "$story" '.stories[] | select(.id==$id) | .apiEndpoints[]?' "$RALPH_DIR/prd.json" 2>/dev/null)
44
+
45
+ if [[ -z "$endpoints" ]]; then
46
+ echo " (no apiEndpoints defined, skipping API validation)"
47
+ return 0
48
+ fi
49
+
50
+ # Get base URL from config or use default
51
+ local base_url
52
+ base_url=$(get_config '.api.baseUrl' "http://localhost:3000")
53
+
54
+ local failed=0
55
+
56
+ echo " Validating API endpoints..."
57
+
58
+ while IFS= read -r endpoint; do
59
+ [[ -z "$endpoint" ]] && continue
60
+
61
+ # Skip WebSocket endpoints - they can't be tested with HTTP curl
62
+ if is_websocket_endpoint "$endpoint"; then
63
+ echo " Skipping WebSocket endpoint: $endpoint (use integration tests)"
64
+ continue
65
+ fi
66
+
67
+ # Parse endpoint into method, path, and full URL
68
+ parse_endpoint "$endpoint" "$base_url"
69
+
70
+ echo -n " $ENDPOINT_METHOD $ENDPOINT_PATH... "
71
+
72
+ # Make the request
73
+ local response_code
74
+ response_code=$(curl -sf -m "$CURL_TIMEOUT_SECONDS" -o /dev/null -w "%{http_code}" -X "$ENDPOINT_METHOD" "$ENDPOINT_URL" 2>/dev/null)
75
+
76
+ if [[ "$response_code" =~ ^2[0-9][0-9]$ ]]; then
77
+ print_success "$response_code"
78
+ elif [[ "$response_code" == "000" ]]; then
79
+ print_error "connection failed"
80
+ failed=1
81
+ elif [[ "$response_code" == "422" || "$response_code" == "400" ]]; then
82
+ # 422/400 = endpoint exists but needs params - don't fail verification
83
+ print_warning "$response_code (needs params)"
84
+ elif [[ "$response_code" == "401" || "$response_code" == "403" ]]; then
85
+ # Auth required - endpoint exists
86
+ print_warning "$response_code (auth required)"
87
+ else
88
+ print_error "$response_code"
89
+ failed=1
90
+ fi
91
+ done <<< "$endpoints"
92
+
93
+ return $failed
94
+ }
95
+
96
+ # Run comprehensive API tests for a story
97
+ run_api_tests() {
98
+ local story="$1"
99
+
100
+ # Get test steps that look like API calls
101
+ local test_steps
102
+ test_steps=$(jq -r --arg id "$story" '.stories[] | select(.id==$id) | .testSteps[]?' "$RALPH_DIR/prd.json" 2>/dev/null)
103
+
104
+ if [[ -z "$test_steps" ]]; then
105
+ return 0
106
+ fi
107
+
108
+ local failed=0
109
+ local log_file
110
+ log_file=$(create_temp_file ".log") || return 1
111
+
112
+ echo " Running API test steps..."
113
+
114
+ while IFS= read -r step; do
115
+ [[ -z "$step" ]] && continue
116
+
117
+ # Check if this looks like a curl command or API test
118
+ if [[ "$step" =~ ^curl ]]; then
119
+ echo -n " $step... "
120
+
121
+ if safe_exec "$step" "$log_file"; then
122
+ print_success "passed"
123
+ else
124
+ print_error "failed"
125
+ echo ""
126
+ echo " Response:"
127
+ tail -"$MAX_OUTPUT_PREVIEW_LINES" "$log_file" | sed 's/^/ /'
128
+ failed=1
129
+ fi
130
+ fi
131
+ done <<< "$test_steps"
132
+
133
+ rm -f "$log_file"
134
+ return $failed
135
+ }
136
+
137
+ # Validate error handling for API
138
+ run_api_error_tests() {
139
+ local story="$1"
140
+
141
+ # Get error handling requirements
142
+ local error_handling
143
+ error_handling=$(jq -r --arg id "$story" '.stories[] | select(.id==$id) | .errorHandling[]?' "$RALPH_DIR/prd.json" 2>/dev/null)
144
+
145
+ if [[ -z "$error_handling" ]]; then
146
+ return 0
147
+ fi
148
+
149
+ # Get base URL and endpoints
150
+ local base_url
151
+ base_url=$(get_config '.api.baseUrl' "http://localhost:3000")
152
+
153
+ local endpoints
154
+ endpoints=$(jq -r --arg id "$story" '.stories[] | select(.id==$id) | .apiEndpoints[0]?' "$RALPH_DIR/prd.json" 2>/dev/null)
155
+
156
+ if [[ -z "$endpoints" ]]; then
157
+ return 0
158
+ fi
159
+
160
+ # Skip WebSocket endpoints
161
+ if is_websocket_endpoint "$endpoints"; then
162
+ echo " Skipping error tests for WebSocket endpoint"
163
+ return 0
164
+ fi
165
+
166
+ # Parse endpoint (default to POST for error tests)
167
+ parse_endpoint "$endpoints" "$base_url"
168
+ [[ "$ENDPOINT_METHOD" == "GET" ]] && ENDPOINT_METHOD="POST"
169
+
170
+ local failed=0
171
+
172
+ echo " Testing API error handling..."
173
+
174
+ # Test common error cases
175
+ while IFS= read -r error_case; do
176
+ [[ -z "$error_case" ]] && continue
177
+
178
+ # Check for 400 tests (bad input)
179
+ if [[ "$error_case" =~ 400 ]]; then
180
+ echo -n " Testing 400 (bad request)... "
181
+
182
+ local response_code
183
+ response_code=$(curl -sf -m "$CURL_TIMEOUT_SECONDS" -o /dev/null -w "%{http_code}" \
184
+ -X "$ENDPOINT_METHOD" \
185
+ -H "Content-Type: application/json" \
186
+ -d '{}' \
187
+ "$ENDPOINT_URL" 2>/dev/null)
188
+
189
+ if [[ "$response_code" == "400" ]]; then
190
+ print_success "correctly returns 400"
191
+ else
192
+ print_warning "got $response_code (expected 400)"
193
+ failed=1
194
+ fi
195
+ fi
196
+
197
+ # Check for 401 tests (unauthorized)
198
+ if [[ "$error_case" =~ 401 ]]; then
199
+ echo -n " Testing 401 (unauthorized)... "
200
+
201
+ local response_code
202
+ response_code=$(curl -sf -m "$CURL_TIMEOUT_SECONDS" -o /dev/null -w "%{http_code}" \
203
+ -X "$ENDPOINT_METHOD" \
204
+ "$ENDPOINT_URL" 2>/dev/null)
205
+
206
+ if [[ "$response_code" == "401" ]]; then
207
+ print_success "correctly returns 401"
208
+ else
209
+ print_warning "got $response_code (expected 401)"
210
+ failed=1
211
+ fi
212
+ fi
213
+ done <<< "$error_handling"
214
+
215
+ return $failed
216
+ }