guardrail-core 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 (189) hide show
  1. package/dist/__tests__/autopilot.test.d.ts +7 -0
  2. package/dist/__tests__/autopilot.test.d.ts.map +1 -0
  3. package/dist/__tests__/autopilot.test.js +156 -0
  4. package/dist/__tests__/tier-config.test.d.ts +9 -0
  5. package/dist/__tests__/tier-config.test.d.ts.map +1 -0
  6. package/dist/__tests__/tier-config.test.js +230 -0
  7. package/dist/__tests__/utils/hash-inline.test.d.ts +2 -0
  8. package/dist/__tests__/utils/hash-inline.test.d.ts.map +1 -0
  9. package/dist/__tests__/utils/hash-inline.test.js +62 -0
  10. package/dist/__tests__/utils/hash.test.d.ts +3 -0
  11. package/dist/__tests__/utils/hash.test.d.ts.map +1 -0
  12. package/dist/__tests__/utils/hash.test.js +95 -0
  13. package/dist/__tests__/utils/simple.test.d.ts +1 -0
  14. package/dist/__tests__/utils/simple.test.d.ts.map +1 -0
  15. package/dist/__tests__/utils/simple.test.js +10 -0
  16. package/dist/__tests__/utils/utils-simple.test.d.ts +1 -0
  17. package/dist/__tests__/utils/utils-simple.test.d.ts.map +1 -0
  18. package/dist/__tests__/utils/utils-simple.test.js +6 -0
  19. package/dist/__tests__/utils/utils.test.d.ts +15 -0
  20. package/dist/__tests__/utils/utils.test.d.ts.map +1 -0
  21. package/dist/__tests__/utils/utils.test.js +172 -0
  22. package/dist/autopilot/autopilot-runner.d.ts +33 -0
  23. package/dist/autopilot/autopilot-runner.d.ts.map +1 -0
  24. package/dist/autopilot/autopilot-runner.js +479 -0
  25. package/dist/autopilot/index.d.ts +6 -0
  26. package/dist/autopilot/index.d.ts.map +1 -0
  27. package/dist/autopilot/index.js +25 -0
  28. package/dist/autopilot/types.d.ts +102 -0
  29. package/dist/autopilot/types.d.ts.map +1 -0
  30. package/dist/autopilot/types.js +18 -0
  31. package/dist/cache/index.d.ts +7 -0
  32. package/dist/cache/index.d.ts.map +1 -0
  33. package/dist/cache/index.js +22 -0
  34. package/dist/cache/redis-cache.d.ts +145 -0
  35. package/dist/cache/redis-cache.d.ts.map +1 -0
  36. package/dist/cache/redis-cache.js +459 -0
  37. package/dist/ci/github-actions.d.ts +77 -0
  38. package/dist/ci/github-actions.d.ts.map +1 -0
  39. package/dist/ci/github-actions.js +277 -0
  40. package/dist/ci/index.d.ts +12 -0
  41. package/dist/ci/index.d.ts.map +1 -0
  42. package/dist/ci/index.js +27 -0
  43. package/dist/ci/pre-commit.d.ts +65 -0
  44. package/dist/ci/pre-commit.d.ts.map +1 -0
  45. package/dist/ci/pre-commit.js +286 -0
  46. package/dist/entitlements.d.ts +149 -0
  47. package/dist/entitlements.d.ts.map +1 -0
  48. package/dist/entitlements.js +464 -0
  49. package/dist/env.d.ts +113 -0
  50. package/dist/env.d.ts.map +1 -0
  51. package/dist/env.js +204 -0
  52. package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts +7 -0
  53. package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts.map +1 -0
  54. package/dist/fix-packs/__tests__/generate-fix-packs.test.js +250 -0
  55. package/dist/fix-packs/generate-fix-packs.d.ts +15 -0
  56. package/dist/fix-packs/generate-fix-packs.d.ts.map +1 -0
  57. package/dist/fix-packs/generate-fix-packs.js +505 -0
  58. package/dist/fix-packs/index.d.ts +8 -0
  59. package/dist/fix-packs/index.d.ts.map +1 -0
  60. package/dist/fix-packs/index.js +23 -0
  61. package/dist/fix-packs/types.d.ts +113 -0
  62. package/dist/fix-packs/types.d.ts.map +1 -0
  63. package/dist/fix-packs/types.js +71 -0
  64. package/dist/index.d.ts +13 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +28 -0
  67. package/dist/metrics/prometheus.d.ts +99 -0
  68. package/dist/metrics/prometheus.d.ts.map +1 -0
  69. package/dist/metrics/prometheus.js +306 -0
  70. package/dist/quota-ledger.d.ts +119 -0
  71. package/dist/quota-ledger.d.ts.map +1 -0
  72. package/dist/quota-ledger.js +462 -0
  73. package/dist/rbac/__tests__/permissions.test.d.ts +8 -0
  74. package/dist/rbac/__tests__/permissions.test.d.ts.map +1 -0
  75. package/dist/rbac/__tests__/permissions.test.js +350 -0
  76. package/dist/rbac/index.d.ts +9 -0
  77. package/dist/rbac/index.d.ts.map +1 -0
  78. package/dist/rbac/index.js +32 -0
  79. package/dist/rbac/permissions.d.ts +71 -0
  80. package/dist/rbac/permissions.d.ts.map +1 -0
  81. package/dist/rbac/permissions.js +247 -0
  82. package/dist/rbac/types.d.ts +69 -0
  83. package/dist/rbac/types.d.ts.map +1 -0
  84. package/dist/rbac/types.js +213 -0
  85. package/dist/tier-config.d.ts +203 -0
  86. package/dist/tier-config.d.ts.map +1 -0
  87. package/dist/tier-config.js +675 -0
  88. package/dist/types.d.ts +365 -0
  89. package/dist/types.d.ts.map +1 -0
  90. package/dist/types.js +5 -0
  91. package/dist/utils.d.ts +36 -0
  92. package/dist/utils.d.ts.map +1 -0
  93. package/dist/utils.js +127 -0
  94. package/dist/verified-autofix/__tests__/format-validator.test.d.ts +11 -0
  95. package/dist/verified-autofix/__tests__/format-validator.test.d.ts.map +1 -0
  96. package/dist/verified-autofix/__tests__/format-validator.test.js +285 -0
  97. package/dist/verified-autofix/__tests__/pipeline.test.d.ts +11 -0
  98. package/dist/verified-autofix/__tests__/pipeline.test.d.ts.map +1 -0
  99. package/dist/verified-autofix/__tests__/pipeline.test.js +389 -0
  100. package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts +11 -0
  101. package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts.map +1 -0
  102. package/dist/verified-autofix/__tests__/repo-fingerprint.test.js +236 -0
  103. package/dist/verified-autofix/__tests__/workspace.test.d.ts +11 -0
  104. package/dist/verified-autofix/__tests__/workspace.test.d.ts.map +1 -0
  105. package/dist/verified-autofix/__tests__/workspace.test.js +314 -0
  106. package/dist/verified-autofix/format-validator.d.ts +101 -0
  107. package/dist/verified-autofix/format-validator.d.ts.map +1 -0
  108. package/dist/verified-autofix/format-validator.js +446 -0
  109. package/dist/verified-autofix/index.d.ts +14 -0
  110. package/dist/verified-autofix/index.d.ts.map +1 -0
  111. package/dist/verified-autofix/index.js +39 -0
  112. package/dist/verified-autofix/pipeline.d.ts +68 -0
  113. package/dist/verified-autofix/pipeline.d.ts.map +1 -0
  114. package/dist/verified-autofix/pipeline.js +330 -0
  115. package/dist/verified-autofix/repo-fingerprint.d.ts +56 -0
  116. package/dist/verified-autofix/repo-fingerprint.d.ts.map +1 -0
  117. package/dist/verified-autofix/repo-fingerprint.js +396 -0
  118. package/dist/verified-autofix/workspace.d.ts +83 -0
  119. package/dist/verified-autofix/workspace.d.ts.map +1 -0
  120. package/dist/verified-autofix/workspace.js +454 -0
  121. package/dist/verified-autofix.d.ts +182 -0
  122. package/dist/verified-autofix.d.ts.map +1 -0
  123. package/dist/verified-autofix.js +1021 -0
  124. package/dist/visualization/dependency-graph.d.ts +79 -0
  125. package/dist/visualization/dependency-graph.d.ts.map +1 -0
  126. package/dist/visualization/dependency-graph.js +399 -0
  127. package/dist/visualization/index.d.ts +5 -0
  128. package/dist/visualization/index.d.ts.map +1 -0
  129. package/dist/visualization/index.js +20 -0
  130. package/package.json +29 -0
  131. package/src/__tests__/autopilot.test.ts +196 -0
  132. package/src/__tests__/tier-config.test.ts +289 -0
  133. package/src/__tests__/utils/hash-inline.test.ts +76 -0
  134. package/src/__tests__/utils/hash.test.ts +119 -0
  135. package/src/__tests__/utils/simple.test.ts +10 -0
  136. package/src/__tests__/utils/utils-simple.test.ts +5 -0
  137. package/src/__tests__/utils/utils.test.ts +203 -0
  138. package/src/autopilot/autopilot-runner.ts +503 -0
  139. package/src/autopilot/index.ts +6 -0
  140. package/src/autopilot/types.ts +119 -0
  141. package/src/cache/index.ts +7 -0
  142. package/src/cache/redis-cache.d.ts +155 -0
  143. package/src/cache/redis-cache.d.ts.map +1 -0
  144. package/src/cache/redis-cache.ts +517 -0
  145. package/src/ci/github-actions.ts +335 -0
  146. package/src/ci/index.ts +12 -0
  147. package/src/ci/pre-commit.ts +338 -0
  148. package/src/db/usage-schema.prisma +114 -0
  149. package/src/entitlements.ts +570 -0
  150. package/src/env.d.ts +68 -0
  151. package/src/env.d.ts.map +1 -0
  152. package/src/env.ts +247 -0
  153. package/src/fix-packs/__tests__/generate-fix-packs.test.ts +317 -0
  154. package/src/fix-packs/generate-fix-packs.ts +577 -0
  155. package/src/fix-packs/index.ts +8 -0
  156. package/src/fix-packs/types.ts +206 -0
  157. package/src/index.d.ts +7 -0
  158. package/src/index.d.ts.map +1 -0
  159. package/src/index.ts +12 -0
  160. package/src/metrics/prometheus.d.ts +104 -0
  161. package/src/metrics/prometheus.d.ts.map +1 -0
  162. package/src/metrics/prometheus.ts +446 -0
  163. package/src/quota-ledger.ts +548 -0
  164. package/src/rbac/__tests__/permissions.test.ts +446 -0
  165. package/src/rbac/index.ts +46 -0
  166. package/src/rbac/permissions.ts +301 -0
  167. package/src/rbac/types.ts +298 -0
  168. package/src/tier-config.json +157 -0
  169. package/src/tier-config.ts +815 -0
  170. package/src/types.d.ts +365 -0
  171. package/src/types.d.ts.map +1 -0
  172. package/src/types.ts +441 -0
  173. package/src/utils.d.ts +36 -0
  174. package/src/utils.d.ts.map +1 -0
  175. package/src/utils.ts +140 -0
  176. package/src/verified-autofix/__tests__/format-validator.test.ts +335 -0
  177. package/src/verified-autofix/__tests__/pipeline.test.ts +419 -0
  178. package/src/verified-autofix/__tests__/repo-fingerprint.test.ts +241 -0
  179. package/src/verified-autofix/__tests__/workspace.test.ts +373 -0
  180. package/src/verified-autofix/format-validator.ts +517 -0
  181. package/src/verified-autofix/index.ts +63 -0
  182. package/src/verified-autofix/pipeline.ts +403 -0
  183. package/src/verified-autofix/repo-fingerprint.ts +459 -0
  184. package/src/verified-autofix/workspace.ts +531 -0
  185. package/src/verified-autofix.ts +1187 -0
  186. package/src/visualization/dependency-graph.d.ts +85 -0
  187. package/src/visualization/dependency-graph.d.ts.map +1 -0
  188. package/src/visualization/dependency-graph.ts +495 -0
  189. package/src/visualization/index.ts +5 -0
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Repo Fingerprint Tests
3
+ *
4
+ * Tests for project detection and configuration:
5
+ * - Package manager detection
6
+ * - Build tool detection
7
+ * - Framework detection
8
+ * - Test runner detection
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=repo-fingerprint.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-fingerprint.test.d.ts","sourceRoot":"","sources":["../../../src/verified-autofix/__tests__/repo-fingerprint.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ /**
3
+ * Repo Fingerprint Tests
4
+ *
5
+ * Tests for project detection and configuration:
6
+ * - Package manager detection
7
+ * - Build tool detection
8
+ * - Framework detection
9
+ * - Test runner detection
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ const fs = __importStar(require("fs"));
46
+ const path = __importStar(require("path"));
47
+ const os = __importStar(require("os"));
48
+ const repo_fingerprint_1 = require("../repo-fingerprint");
49
+ describe('fingerprintRepo', () => {
50
+ let tempDir;
51
+ beforeEach(async () => {
52
+ tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'fingerprint-test-'));
53
+ });
54
+ afterEach(async () => {
55
+ await fs.promises.rm(tempDir, { recursive: true, force: true });
56
+ });
57
+ it('detects pnpm from lock file', async () => {
58
+ await fs.promises.writeFile(path.join(tempDir, 'pnpm-lock.yaml'), '');
59
+ await fs.promises.writeFile(path.join(tempDir, 'package.json'), JSON.stringify({
60
+ name: 'test',
61
+ dependencies: {},
62
+ }));
63
+ const { fingerprint } = (0, repo_fingerprint_1.fingerprintRepo)(tempDir);
64
+ expect(fingerprint.packageManager).toBe('pnpm');
65
+ });
66
+ it('detects yarn from lock file', async () => {
67
+ await fs.promises.writeFile(path.join(tempDir, 'yarn.lock'), '');
68
+ await fs.promises.writeFile(path.join(tempDir, 'package.json'), JSON.stringify({
69
+ name: 'test',
70
+ }));
71
+ const { fingerprint } = (0, repo_fingerprint_1.fingerprintRepo)(tempDir);
72
+ expect(fingerprint.packageManager).toBe('yarn');
73
+ });
74
+ it('detects npm from lock file', async () => {
75
+ await fs.promises.writeFile(path.join(tempDir, 'package-lock.json'), '{}');
76
+ await fs.promises.writeFile(path.join(tempDir, 'package.json'), JSON.stringify({
77
+ name: 'test',
78
+ }));
79
+ const { fingerprint } = (0, repo_fingerprint_1.fingerprintRepo)(tempDir);
80
+ expect(fingerprint.packageManager).toBe('npm');
81
+ });
82
+ it('detects Next.js framework', async () => {
83
+ await fs.promises.writeFile(path.join(tempDir, 'package.json'), JSON.stringify({
84
+ name: 'test',
85
+ dependencies: { next: '^14.0.0', react: '^18.0.0' },
86
+ }));
87
+ const { fingerprint } = (0, repo_fingerprint_1.fingerprintRepo)(tempDir);
88
+ expect(fingerprint.framework).toBe('next');
89
+ });
90
+ it('detects Vite framework', async () => {
91
+ await fs.promises.writeFile(path.join(tempDir, 'package.json'), JSON.stringify({
92
+ name: 'test',
93
+ devDependencies: { vite: '^5.0.0' },
94
+ }));
95
+ const { fingerprint } = (0, repo_fingerprint_1.fingerprintRepo)(tempDir);
96
+ expect(fingerprint.framework).toBe('vite');
97
+ });
98
+ it('detects Jest test runner', async () => {
99
+ await fs.promises.writeFile(path.join(tempDir, 'package.json'), JSON.stringify({
100
+ name: 'test',
101
+ devDependencies: { jest: '^29.0.0' },
102
+ }));
103
+ const { fingerprint } = (0, repo_fingerprint_1.fingerprintRepo)(tempDir);
104
+ expect(fingerprint.testRunner).toBe('jest');
105
+ });
106
+ it('detects Vitest test runner', async () => {
107
+ await fs.promises.writeFile(path.join(tempDir, 'package.json'), JSON.stringify({
108
+ name: 'test',
109
+ devDependencies: { vitest: '^1.0.0' },
110
+ }));
111
+ const { fingerprint } = (0, repo_fingerprint_1.fingerprintRepo)(tempDir);
112
+ expect(fingerprint.testRunner).toBe('vitest');
113
+ });
114
+ it('detects TypeScript', async () => {
115
+ await fs.promises.writeFile(path.join(tempDir, 'tsconfig.json'), '{}');
116
+ await fs.promises.writeFile(path.join(tempDir, 'package.json'), JSON.stringify({
117
+ name: 'test',
118
+ }));
119
+ const { fingerprint } = (0, repo_fingerprint_1.fingerprintRepo)(tempDir);
120
+ expect(fingerprint.hasTypeScript).toBe(true);
121
+ });
122
+ it('detects Turbo build tool', async () => {
123
+ await fs.promises.writeFile(path.join(tempDir, 'turbo.json'), '{}');
124
+ await fs.promises.writeFile(path.join(tempDir, 'package.json'), JSON.stringify({
125
+ name: 'test',
126
+ }));
127
+ const { fingerprint } = (0, repo_fingerprint_1.fingerprintRepo)(tempDir);
128
+ expect(fingerprint.buildTool).toBe('turbo');
129
+ });
130
+ it('detects monorepo from workspaces', async () => {
131
+ await fs.promises.writeFile(path.join(tempDir, 'package.json'), JSON.stringify({
132
+ name: 'monorepo',
133
+ workspaces: ['packages/*'],
134
+ }));
135
+ const { fingerprint } = (0, repo_fingerprint_1.fingerprintRepo)(tempDir);
136
+ expect(fingerprint.isMonorepo).toBe(true);
137
+ expect(fingerprint.workspaces).toContain('packages/*');
138
+ });
139
+ it('detects build script', async () => {
140
+ await fs.promises.writeFile(path.join(tempDir, 'package.json'), JSON.stringify({
141
+ name: 'test',
142
+ scripts: { build: 'tsc' },
143
+ }));
144
+ const { fingerprint } = (0, repo_fingerprint_1.fingerprintRepo)(tempDir);
145
+ expect(fingerprint.hasBuildScript).toBe(true);
146
+ });
147
+ it('handles missing package.json gracefully', () => {
148
+ const { fingerprint, confidence, detectionNotes } = (0, repo_fingerprint_1.fingerprintRepo)(tempDir);
149
+ expect(fingerprint.packageManager).toBe('unknown');
150
+ expect(confidence).toBeLessThan(100);
151
+ expect(detectionNotes).toContain('No package.json found');
152
+ });
153
+ });
154
+ describe('command helpers', () => {
155
+ it('returns correct install command for pnpm', () => {
156
+ expect((0, repo_fingerprint_1.getInstallCommand)('pnpm')).toBe('pnpm install --frozen-lockfile');
157
+ });
158
+ it('returns correct install command for yarn', () => {
159
+ expect((0, repo_fingerprint_1.getInstallCommand)('yarn')).toBe('yarn install --frozen-lockfile');
160
+ });
161
+ it('returns correct install command for npm', () => {
162
+ expect((0, repo_fingerprint_1.getInstallCommand)('npm')).toBe('npm ci');
163
+ });
164
+ it('returns turbo build command when turbo detected', () => {
165
+ const fingerprint = {
166
+ buildTool: 'turbo',
167
+ hasBuildScript: true,
168
+ hasTypeScript: true,
169
+ packageManager: 'pnpm',
170
+ framework: 'next',
171
+ testRunner: 'jest',
172
+ hasESLint: true,
173
+ hasPrettier: true,
174
+ hasTestScript: true,
175
+ isMonorepo: true,
176
+ workspaces: ['packages/*'],
177
+ dependencies: {},
178
+ devDependencies: {},
179
+ };
180
+ expect((0, repo_fingerprint_1.getBuildCommand)(fingerprint)).toBe('npx turbo run build');
181
+ });
182
+ it('returns vitest command for vitest runner', () => {
183
+ const fingerprint = {
184
+ testRunner: 'vitest',
185
+ hasTestScript: true,
186
+ buildTool: 'none',
187
+ hasBuildScript: false,
188
+ hasTypeScript: false,
189
+ packageManager: 'npm',
190
+ framework: 'none',
191
+ hasESLint: false,
192
+ hasPrettier: false,
193
+ isMonorepo: false,
194
+ workspaces: [],
195
+ dependencies: {},
196
+ devDependencies: {},
197
+ };
198
+ expect((0, repo_fingerprint_1.getTestCommand)(fingerprint)).toBe('npx vitest run');
199
+ });
200
+ it('returns typecheck command when TypeScript present', () => {
201
+ const fingerprint = {
202
+ hasTypeScript: true,
203
+ testRunner: 'none',
204
+ hasTestScript: false,
205
+ buildTool: 'none',
206
+ hasBuildScript: false,
207
+ packageManager: 'npm',
208
+ framework: 'none',
209
+ hasESLint: false,
210
+ hasPrettier: false,
211
+ isMonorepo: false,
212
+ workspaces: [],
213
+ dependencies: {},
214
+ devDependencies: {},
215
+ };
216
+ expect((0, repo_fingerprint_1.getTypecheckCommand)(fingerprint)).toBe('npx tsc --noEmit');
217
+ });
218
+ it('returns null typecheck command when no TypeScript', () => {
219
+ const fingerprint = {
220
+ hasTypeScript: false,
221
+ testRunner: 'none',
222
+ hasTestScript: false,
223
+ buildTool: 'none',
224
+ hasBuildScript: false,
225
+ packageManager: 'npm',
226
+ framework: 'none',
227
+ hasESLint: false,
228
+ hasPrettier: false,
229
+ isMonorepo: false,
230
+ workspaces: [],
231
+ dependencies: {},
232
+ devDependencies: {},
233
+ };
234
+ expect((0, repo_fingerprint_1.getTypecheckCommand)(fingerprint)).toBeNull();
235
+ });
236
+ });
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Workspace Tests - Temp Workspace Manager
3
+ *
4
+ * Tests for isolated workspace verification:
5
+ * - Workspace creation (copy and worktree)
6
+ * - Diff application via git apply
7
+ * - Verification command execution
8
+ * - Top 3 failure context extraction
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=workspace.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.test.d.ts","sourceRoot":"","sources":["../../../src/verified-autofix/__tests__/workspace.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,314 @@
1
+ "use strict";
2
+ /**
3
+ * Workspace Tests - Temp Workspace Manager
4
+ *
5
+ * Tests for isolated workspace verification:
6
+ * - Workspace creation (copy and worktree)
7
+ * - Diff application via git apply
8
+ * - Verification command execution
9
+ * - Top 3 failure context extraction
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ const fs = __importStar(require("fs"));
46
+ const path = __importStar(require("path"));
47
+ const os = __importStar(require("os"));
48
+ const child_process_1 = require("child_process");
49
+ const workspace_1 = require("../workspace");
50
+ describe('TempWorkspace', () => {
51
+ let tempDir;
52
+ let workspace;
53
+ beforeEach(async () => {
54
+ tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'workspace-test-'));
55
+ workspace = new workspace_1.TempWorkspace();
56
+ // Create minimal project structure
57
+ await fs.promises.writeFile(path.join(tempDir, 'package.json'), JSON.stringify({
58
+ name: 'test-project',
59
+ version: '1.0.0',
60
+ scripts: {
61
+ build: 'echo "build complete"',
62
+ test: 'echo "tests passed"',
63
+ },
64
+ }));
65
+ // Create a source file
66
+ await fs.promises.mkdir(path.join(tempDir, 'src'), { recursive: true });
67
+ await fs.promises.writeFile(path.join(tempDir, 'src', 'index.ts'), 'export const version = "1.0.0";\n');
68
+ });
69
+ afterEach(async () => {
70
+ await workspace.cleanupAll();
71
+ await fs.promises.rm(tempDir, { recursive: true, force: true });
72
+ });
73
+ describe('create', () => {
74
+ it('creates workspace via copy when not a git repo', async () => {
75
+ const info = await workspace.create({
76
+ projectPath: tempDir,
77
+ useWorktree: true, // Will fall back to copy since no .git
78
+ });
79
+ expect(info.type).toBe('copy');
80
+ expect(fs.existsSync(info.path)).toBe(true);
81
+ expect(fs.existsSync(path.join(info.path, 'package.json'))).toBe(true);
82
+ expect(fs.existsSync(path.join(info.path, 'src', 'index.ts'))).toBe(true);
83
+ });
84
+ it('excludes node_modules from copy', async () => {
85
+ // Create fake node_modules
86
+ await fs.promises.mkdir(path.join(tempDir, 'node_modules', 'lodash'), { recursive: true });
87
+ await fs.promises.writeFile(path.join(tempDir, 'node_modules', 'lodash', 'index.js'), 'module.exports = {};');
88
+ const info = await workspace.create({
89
+ projectPath: tempDir,
90
+ });
91
+ expect(fs.existsSync(path.join(info.path, 'node_modules'))).toBe(false);
92
+ });
93
+ it('excludes .git from copy', async () => {
94
+ // Create fake .git
95
+ await fs.promises.mkdir(path.join(tempDir, '.git'), { recursive: true });
96
+ await fs.promises.writeFile(path.join(tempDir, '.git', 'config'), '');
97
+ const info = await workspace.create({
98
+ projectPath: tempDir,
99
+ useWorktree: false, // Force copy mode
100
+ });
101
+ expect(fs.existsSync(path.join(info.path, '.git'))).toBe(false);
102
+ });
103
+ });
104
+ describe('applyDiff', () => {
105
+ it('applies simple hunk to file', async () => {
106
+ const info = await workspace.create({ projectPath: tempDir });
107
+ const hunks = [{
108
+ file: 'src/index.ts',
109
+ oldStart: 1,
110
+ oldLines: 1,
111
+ newStart: 1,
112
+ newLines: 2,
113
+ content: `@@ -1,1 +1,2 @@
114
+ export const version = "1.0.0";
115
+ +export const name = "test";`,
116
+ }];
117
+ const diff = `--- a/src/index.ts
118
+ +++ b/src/index.ts
119
+ @@ -1,1 +1,2 @@
120
+ export const version = "1.0.0";
121
+ +export const name = "test";`;
122
+ const result = await workspace.applyDiff(info.path, diff, hunks);
123
+ expect(result.success).toBe(true);
124
+ expect(result.applied).toBe(1);
125
+ expect(result.errors).toHaveLength(0);
126
+ // Verify file was modified
127
+ const content = await fs.promises.readFile(path.join(info.path, 'src', 'index.ts'), 'utf8');
128
+ expect(content).toContain('export const name = "test"');
129
+ });
130
+ it('creates new file from diff', async () => {
131
+ const info = await workspace.create({ projectPath: tempDir });
132
+ const hunks = [{
133
+ file: 'src/utils.ts',
134
+ oldStart: 0,
135
+ oldLines: 0,
136
+ newStart: 1,
137
+ newLines: 1,
138
+ content: `@@ -0,0 +1,1 @@
139
+ +export const add = (a: number, b: number) => a + b;`,
140
+ }];
141
+ const diff = `--- /dev/null
142
+ +++ b/src/utils.ts
143
+ @@ -0,0 +1,1 @@
144
+ +export const add = (a: number, b: number) => a + b;`;
145
+ const result = await workspace.applyDiff(info.path, diff, hunks);
146
+ expect(result.applied).toBeGreaterThan(0);
147
+ expect(fs.existsSync(path.join(info.path, 'src', 'utils.ts'))).toBe(true);
148
+ });
149
+ });
150
+ describe('verify', () => {
151
+ it('runs verification commands based on fingerprint', async () => {
152
+ const info = await workspace.create({ projectPath: tempDir });
153
+ const fingerprint = {
154
+ packageManager: 'npm',
155
+ buildTool: 'none',
156
+ framework: 'none',
157
+ testRunner: 'none',
158
+ hasTypeScript: false,
159
+ hasESLint: false,
160
+ hasPrettier: false,
161
+ hasBuildScript: true,
162
+ hasTestScript: true,
163
+ isMonorepo: false,
164
+ workspaces: [],
165
+ dependencies: {},
166
+ devDependencies: {},
167
+ };
168
+ const result = await workspace.verify(info.path, fingerprint, {
169
+ skipTests: true,
170
+ });
171
+ // Build should pass (echo command)
172
+ expect(result.passed).toBe(true);
173
+ expect(result.checks.length).toBeGreaterThan(0);
174
+ });
175
+ it('extracts top 3 failure context on error', async () => {
176
+ const info = await workspace.create({ projectPath: tempDir });
177
+ // Create a failing build script
178
+ await fs.promises.writeFile(path.join(info.path, 'package.json'), JSON.stringify({
179
+ name: 'test',
180
+ scripts: {
181
+ build: 'echo "error TS2322: Type mismatch" && echo "error TS2345: Wrong arg" && echo "error TS2339: Missing prop" && exit 1',
182
+ },
183
+ }));
184
+ const fingerprint = {
185
+ packageManager: 'npm',
186
+ buildTool: 'none',
187
+ framework: 'none',
188
+ testRunner: 'none',
189
+ hasTypeScript: false,
190
+ hasESLint: false,
191
+ hasPrettier: false,
192
+ hasBuildScript: true,
193
+ hasTestScript: false,
194
+ isMonorepo: false,
195
+ workspaces: [],
196
+ dependencies: {},
197
+ devDependencies: {},
198
+ };
199
+ const result = await workspace.verify(info.path, fingerprint, {
200
+ skipTests: true,
201
+ });
202
+ expect(result.passed).toBe(false);
203
+ expect(result.failureContext.length).toBeLessThanOrEqual(3);
204
+ });
205
+ });
206
+ describe('copyBack', () => {
207
+ it('copies modified files back to project', async () => {
208
+ const info = await workspace.create({ projectPath: tempDir });
209
+ // Modify file in workspace
210
+ await fs.promises.writeFile(path.join(info.path, 'src', 'index.ts'), 'export const version = "2.0.0";\n');
211
+ await workspace.copyBack(info.path, tempDir, ['src/index.ts']);
212
+ // Verify original project was updated
213
+ const content = await fs.promises.readFile(path.join(tempDir, 'src', 'index.ts'), 'utf8');
214
+ expect(content).toBe('export const version = "2.0.0";\n');
215
+ });
216
+ it('creates backup before overwriting', async () => {
217
+ const info = await workspace.create({ projectPath: tempDir });
218
+ // Modify file in workspace
219
+ await fs.promises.writeFile(path.join(info.path, 'src', 'index.ts'), 'export const version = "2.0.0";\n');
220
+ await workspace.copyBack(info.path, tempDir, ['src/index.ts']);
221
+ // Backup should exist
222
+ const backupPath = path.join(tempDir, 'src', 'index.ts.guardrail-backup');
223
+ expect(fs.existsSync(backupPath)).toBe(true);
224
+ const backupContent = await fs.promises.readFile(backupPath, 'utf8');
225
+ expect(backupContent).toBe('export const version = "1.0.0";\n');
226
+ });
227
+ });
228
+ describe('cleanup', () => {
229
+ it('removes workspace directory', async () => {
230
+ const info = await workspace.create({ projectPath: tempDir });
231
+ const workspacePath = info.path;
232
+ expect(fs.existsSync(workspacePath)).toBe(true);
233
+ await workspace.cleanup(info.id);
234
+ expect(fs.existsSync(workspacePath)).toBe(false);
235
+ });
236
+ });
237
+ });
238
+ describe('TempWorkspace with git repo', () => {
239
+ let tempDir;
240
+ let workspace;
241
+ let isGitAvailable;
242
+ beforeAll(() => {
243
+ // Check if git is available
244
+ try {
245
+ (0, child_process_1.execSync)('git --version', { stdio: 'pipe' });
246
+ isGitAvailable = true;
247
+ }
248
+ catch {
249
+ isGitAvailable = false;
250
+ }
251
+ });
252
+ beforeEach(async () => {
253
+ if (!isGitAvailable)
254
+ return;
255
+ tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'workspace-git-test-'));
256
+ workspace = new workspace_1.TempWorkspace();
257
+ // Initialize git repo
258
+ (0, child_process_1.execSync)('git init', { cwd: tempDir, stdio: 'pipe' });
259
+ (0, child_process_1.execSync)('git config user.email "test@test.com"', { cwd: tempDir, stdio: 'pipe' });
260
+ (0, child_process_1.execSync)('git config user.name "Test"', { cwd: tempDir, stdio: 'pipe' });
261
+ // Create and commit a file
262
+ await fs.promises.writeFile(path.join(tempDir, 'file.ts'), 'const x = 1;\n');
263
+ (0, child_process_1.execSync)('git add .', { cwd: tempDir, stdio: 'pipe' });
264
+ (0, child_process_1.execSync)('git commit -m "initial"', { cwd: tempDir, stdio: 'pipe' });
265
+ });
266
+ afterEach(async () => {
267
+ if (!isGitAvailable)
268
+ return;
269
+ await workspace.cleanupAll();
270
+ await fs.promises.rm(tempDir, { recursive: true, force: true });
271
+ });
272
+ it('uses git worktree when available', async () => {
273
+ if (!isGitAvailable) {
274
+ console.log('Skipping git worktree test - git not available');
275
+ return;
276
+ }
277
+ const info = await workspace.create({
278
+ projectPath: tempDir,
279
+ useWorktree: true,
280
+ });
281
+ expect(info.type).toBe('worktree');
282
+ expect(fs.existsSync(path.join(info.path, 'file.ts'))).toBe(true);
283
+ });
284
+ it('applies diff with git apply', async () => {
285
+ if (!isGitAvailable) {
286
+ console.log('Skipping git apply test - git not available');
287
+ return;
288
+ }
289
+ const info = await workspace.create({
290
+ projectPath: tempDir,
291
+ useWorktree: true,
292
+ });
293
+ const diff = `--- a/file.ts
294
+ +++ b/file.ts
295
+ @@ -1 +1,2 @@
296
+ const x = 1;
297
+ +const y = 2;
298
+ `;
299
+ const hunks = [{
300
+ file: 'file.ts',
301
+ oldStart: 1,
302
+ oldLines: 1,
303
+ newStart: 1,
304
+ newLines: 2,
305
+ content: `@@ -1 +1,2 @@
306
+ const x = 1;
307
+ +const y = 2;`,
308
+ }];
309
+ const result = await workspace.applyDiff(info.path, diff, hunks);
310
+ expect(result.success).toBe(true);
311
+ const content = await fs.promises.readFile(path.join(info.path, 'file.ts'), 'utf8');
312
+ expect(content).toContain('const y = 2');
313
+ });
314
+ });
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Format Validator - Strict Output Protocol Enforcement
3
+ *
4
+ * Validates AI agent output format:
5
+ * 1. JSON shape validation (guardrail-v1 format)
6
+ * 2. Unified diff validity checking
7
+ * 3. Markdown fence stripping (forgiving)
8
+ * 4. Path safety validation
9
+ * 5. Stub/placeholder detection
10
+ */
11
+ export interface GuardrailV1Output {
12
+ format: 'guardrail-v1';
13
+ diff: string;
14
+ commands: string[];
15
+ tests: string[];
16
+ notes: string;
17
+ }
18
+ export interface ValidationResult {
19
+ valid: boolean;
20
+ errors: string[];
21
+ warnings: string[];
22
+ sanitized?: GuardrailV1Output;
23
+ }
24
+ export interface DiffValidationResult {
25
+ valid: boolean;
26
+ errors: string[];
27
+ hunks: ParsedHunk[];
28
+ filesAffected: string[];
29
+ }
30
+ export interface ParsedHunk {
31
+ file: string;
32
+ oldStart: number;
33
+ oldLines: number;
34
+ newStart: number;
35
+ newLines: number;
36
+ content: string;
37
+ }
38
+ /**
39
+ * Strip markdown code fences from raw agent output (forgiving mode)
40
+ */
41
+ export declare function stripMarkdownFences(raw: string): string;
42
+ /**
43
+ * Validate the guardrail-v1 JSON shape
44
+ */
45
+ export declare function validateJsonShape(obj: unknown): ValidationResult;
46
+ /**
47
+ * Parse and validate unified diff format
48
+ */
49
+ export declare function validateUnifiedDiff(diff: string): DiffValidationResult;
50
+ /**
51
+ * Validate that file paths are safe (no traversal, no system paths)
52
+ */
53
+ export declare function validatePathSafety(paths: string[], projectRoot: string): {
54
+ safe: boolean;
55
+ issues: string[];
56
+ };
57
+ /**
58
+ * Validate that commands are safe to run
59
+ */
60
+ export declare function validateCommandSafety(commands: string[]): {
61
+ safe: boolean;
62
+ issues: string[];
63
+ };
64
+ /**
65
+ * Detect placeholder/stub code in diff additions
66
+ */
67
+ export declare function detectStubs(diff: string): {
68
+ hasStubs: boolean;
69
+ stubs: string[];
70
+ };
71
+ export interface FullValidationResult {
72
+ valid: boolean;
73
+ errors: string[];
74
+ warnings: string[];
75
+ output?: GuardrailV1Output;
76
+ diffValidation?: DiffValidationResult;
77
+ pathSafety?: {
78
+ safe: boolean;
79
+ issues: string[];
80
+ };
81
+ commandSafety?: {
82
+ safe: boolean;
83
+ issues: string[];
84
+ };
85
+ stubDetection?: {
86
+ hasStubs: boolean;
87
+ stubs: string[];
88
+ };
89
+ wasMarkdownWrapped?: boolean;
90
+ }
91
+ /**
92
+ * Full validation pipeline for agent output
93
+ */
94
+ export declare function validateAgentOutput(raw: string, projectRoot: string, options?: {
95
+ strictMarkdown?: boolean;
96
+ }): FullValidationResult;
97
+ /**
98
+ * Quick check if output is markdown-wrapped (for error messages)
99
+ */
100
+ export declare function isMarkdownWrapped(raw: string): boolean;
101
+ //# sourceMappingURL=format-validator.d.ts.map