@paths.design/caws-cli 7.0.2 โ†’ 7.0.3

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 (117) hide show
  1. package/dist/budget-derivation.js +5 -4
  2. package/dist/commands/diagnose.js +24 -19
  3. package/dist/commands/init.js +51 -4
  4. package/dist/commands/specs.js +40 -1
  5. package/dist/commands/status.js +2 -2
  6. package/dist/commands/tool.js +2 -3
  7. package/dist/config/index.js +17 -8
  8. package/dist/generators/working-spec.js +19 -6
  9. package/dist/scaffold/git-hooks.js +127 -29
  10. package/dist/scaffold/index.js +53 -7
  11. package/dist/templates/.caws/tools/README.md +20 -0
  12. package/dist/templates/.cursor/README.md +311 -0
  13. package/dist/templates/.cursor/hooks/audit.sh +55 -0
  14. package/dist/templates/.cursor/hooks/block-dangerous.sh +83 -0
  15. package/dist/templates/.cursor/hooks/caws-quality-check.sh +52 -0
  16. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +130 -0
  17. package/dist/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
  18. package/dist/templates/.cursor/hooks/format.sh +38 -0
  19. package/dist/templates/.cursor/hooks/naming-check.sh +64 -0
  20. package/dist/templates/.cursor/hooks/scan-secrets.sh +46 -0
  21. package/dist/templates/.cursor/hooks/scope-guard.sh +52 -0
  22. package/dist/templates/.cursor/hooks/validate-spec.sh +83 -0
  23. package/dist/templates/.cursor/hooks.json +59 -0
  24. package/dist/templates/.cursor/rules/00-claims-verification.mdc +144 -0
  25. package/dist/templates/.cursor/rules/01-working-style.mdc +50 -0
  26. package/dist/templates/.cursor/rules/02-quality-gates.mdc +370 -0
  27. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
  28. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
  29. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
  30. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
  31. package/dist/templates/.cursor/rules/07-process-ops.mdc +20 -0
  32. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
  33. package/dist/templates/.cursor/rules/09-docstrings.mdc +89 -0
  34. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +390 -0
  35. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +385 -0
  36. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +516 -0
  37. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +588 -0
  38. package/dist/templates/.cursor/rules/README.md +148 -0
  39. package/dist/templates/.github/copilot/instructions.md +311 -0
  40. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
  41. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
  42. package/dist/templates/.vscode/launch.json +56 -0
  43. package/dist/templates/.vscode/settings.json +93 -0
  44. package/dist/templates/.windsurf/workflows/caws-guided-development.md +92 -0
  45. package/dist/templates/COMMIT_CONVENTIONS.md +86 -0
  46. package/dist/templates/OIDC_SETUP.md +300 -0
  47. package/dist/templates/agents.md +1047 -0
  48. package/dist/templates/codemod/README.md +1 -0
  49. package/dist/templates/codemod/test.js +93 -0
  50. package/dist/templates/docs/README.md +150 -0
  51. package/dist/templates/scripts/quality-gates/check-god-objects.js +146 -0
  52. package/dist/templates/scripts/quality-gates/run-quality-gates.js +50 -0
  53. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +1997 -0
  54. package/dist/tool-loader.js +6 -1
  55. package/dist/tool-validator.js +8 -2
  56. package/dist/utils/detection.js +4 -3
  57. package/dist/utils/git-lock.js +118 -0
  58. package/dist/utils/gitignore-updater.js +148 -0
  59. package/dist/utils/quality-gates.js +47 -7
  60. package/dist/utils/spec-resolver.js +23 -3
  61. package/dist/utils/yaml-validation.js +155 -0
  62. package/dist/validation/spec-validation.js +81 -2
  63. package/package.json +2 -2
  64. package/templates/.caws/schemas/waivers.schema.json +30 -0
  65. package/templates/.caws/schemas/working-spec.schema.json +133 -0
  66. package/templates/.caws/templates/working-spec.template.yml +74 -0
  67. package/templates/.caws/tools/README.md +20 -0
  68. package/templates/.caws/tools/scope-guard.js +208 -0
  69. package/templates/.caws/tools-allow.json +331 -0
  70. package/templates/.caws/waivers.yml +19 -0
  71. package/templates/.cursor/hooks/scope-guard.sh +2 -2
  72. package/templates/.cursor/hooks/validate-spec.sh +42 -7
  73. package/templates/apps/tools/caws/COMPLETION_REPORT.md +0 -331
  74. package/templates/apps/tools/caws/MIGRATION_SUMMARY.md +0 -360
  75. package/templates/apps/tools/caws/README.md +0 -463
  76. package/templates/apps/tools/caws/TEST_STATUS.md +0 -365
  77. package/templates/apps/tools/caws/attest.js +0 -357
  78. package/templates/apps/tools/caws/ci-optimizer.js +0 -642
  79. package/templates/apps/tools/caws/config.ts +0 -245
  80. package/templates/apps/tools/caws/cross-functional.js +0 -876
  81. package/templates/apps/tools/caws/dashboard.js +0 -1112
  82. package/templates/apps/tools/caws/flake-detector.ts +0 -362
  83. package/templates/apps/tools/caws/gates.js +0 -198
  84. package/templates/apps/tools/caws/gates.ts +0 -271
  85. package/templates/apps/tools/caws/language-adapters.ts +0 -381
  86. package/templates/apps/tools/caws/language-support.d.ts +0 -367
  87. package/templates/apps/tools/caws/language-support.d.ts.map +0 -1
  88. package/templates/apps/tools/caws/language-support.js +0 -585
  89. package/templates/apps/tools/caws/legacy-assessment.ts +0 -408
  90. package/templates/apps/tools/caws/legacy-assessor.js +0 -764
  91. package/templates/apps/tools/caws/mutant-analyzer.js +0 -734
  92. package/templates/apps/tools/caws/perf-budgets.ts +0 -349
  93. package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
  94. package/templates/apps/tools/caws/property-testing.js +0 -707
  95. package/templates/apps/tools/caws/provenance.d.ts +0 -14
  96. package/templates/apps/tools/caws/provenance.d.ts.map +0 -1
  97. package/templates/apps/tools/caws/provenance.js +0 -132
  98. package/templates/apps/tools/caws/provenance.js.backup +0 -73
  99. package/templates/apps/tools/caws/provenance.ts +0 -211
  100. package/templates/apps/tools/caws/security-provenance.ts +0 -483
  101. package/templates/apps/tools/caws/shared/base-tool.ts +0 -281
  102. package/templates/apps/tools/caws/shared/config-manager.ts +0 -366
  103. package/templates/apps/tools/caws/shared/gate-checker.ts +0 -849
  104. package/templates/apps/tools/caws/shared/types.ts +0 -444
  105. package/templates/apps/tools/caws/shared/validator.ts +0 -305
  106. package/templates/apps/tools/caws/shared/waivers-manager.ts +0 -174
  107. package/templates/apps/tools/caws/spec-test-mapper.ts +0 -391
  108. package/templates/apps/tools/caws/test-quality.js +0 -578
  109. package/templates/apps/tools/caws/validate.js +0 -76
  110. package/templates/apps/tools/caws/validate.ts +0 -228
  111. package/templates/apps/tools/caws/waivers.js +0 -344
  112. /package/{templates/apps/tools/caws โ†’ dist/templates/.caws}/schemas/waivers.schema.json +0 -0
  113. /package/{templates/apps/tools/caws โ†’ dist/templates/.caws}/schemas/working-spec.schema.json +0 -0
  114. /package/{templates/apps/tools/caws โ†’ dist/templates/.caws}/templates/working-spec.template.yml +0 -0
  115. /package/{templates/apps/tools/caws โ†’ dist/templates/.caws/tools}/scope-guard.js +0 -0
  116. /package/{templates/apps/tools/caws โ†’ dist/templates/.caws}/tools-allow.json +0 -0
  117. /package/{templates/apps/tools/caws โ†’ dist/templates/.caws}/waivers.yml +0 -0
@@ -1,707 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * @fileoverview CAWS Property-Based Testing Integration
5
- * Generates and runs property-based tests for enhanced test coverage
6
- * @author @darianrosebrook
7
- */
8
-
9
- const fs = require('fs');
10
- const path = require('path');
11
- const { execSync } = require('child_process');
12
-
13
- /**
14
- * Property-based testing configurations for different languages
15
- */
16
- const PROPERTY_TESTING_CONFIGS = {
17
- javascript: {
18
- library: 'fast-check',
19
- setup: {
20
- install: 'npm install --save-dev fast-check',
21
- import: "import fc from 'fast-check';",
22
- runner: 'npm test',
23
- },
24
- templates: {
25
- number: (propertyName) => `
26
- describe('${propertyName}', () => {
27
- test('should satisfy ${propertyName}', () => {
28
- fc.assert(
29
- fc.property(
30
- fc.integer(),
31
- fc.string(),
32
- (a, b) => {
33
- // Property: ${propertyName}
34
- // Implement your property here
35
- return true; // Replace with actual property
36
- }
37
- )
38
- );
39
- });
40
- });`,
41
-
42
- array: (propertyName) => `
43
- describe('${propertyName}', () => {
44
- test('should satisfy ${propertyName}', () => {
45
- fc.assert(
46
- fc.property(
47
- fc.array(fc.integer()),
48
- (arr) => {
49
- // Property: ${propertyName}
50
- // Implement your property here
51
- return true; // Replace with actual property
52
- }
53
- )
54
- );
55
- });
56
- });`,
57
-
58
- object: (propertyName) => `
59
- describe('${propertyName}', () => {
60
- test('should satisfy ${propertyName}', () => {
61
- fc.assert(
62
- fc.property(
63
- fc.record({
64
- id: fc.integer(),
65
- name: fc.string(),
66
- active: fc.boolean()
67
- }),
68
- (obj) => {
69
- // Property: ${propertyName}
70
- // Implement your property here
71
- return true; // Replace with actual property
72
- }
73
- )
74
- );
75
- });
76
- });`,
77
- },
78
- },
79
-
80
- python: {
81
- library: 'hypothesis',
82
- setup: {
83
- install: 'pip install hypothesis',
84
- import: 'from hypothesis import given, strategies as st',
85
- runner: 'pytest',
86
- },
87
- templates: {
88
- number: (propertyName) => `
89
- @given(st.integers(), st.text())
90
- def test_${propertyName.replace(/\s+/g, '_').toLowerCase()}(a, b):
91
- # Property: ${propertyName}
92
- # Implement your property here
93
- assert True # Replace with actual property`,
94
-
95
- array: (propertyName) => `
96
- @given(st.lists(st.integers()))
97
- def test_${propertyName.replace(/\s+/g, '_').toLowerCase()}(arr):
98
- # Property: ${propertyName}
99
- # Implement your property here
100
- assert True # Replace with actual property`,
101
-
102
- object: (propertyName) => `
103
- @given(st.fixed_dictionaries({
104
- 'id': st.integers(),
105
- 'name': st.text(),
106
- 'active': st.booleans()
107
- }))
108
- def test_${propertyName.replace(/\s+/g, '_').toLowerCase()}(obj):
109
- # Property: ${propertyName}
110
- # Implement your property here
111
- assert True # Replace with actual property`,
112
- },
113
- },
114
-
115
- java: {
116
- library: 'jqwik',
117
- setup: {
118
- install: 'implementation "net.jqwik:jqwik:1.7.4"',
119
- import: 'import net.jqwik.api.*;',
120
- runner: './gradlew test',
121
- },
122
- templates: {
123
- number: (propertyName) => `
124
- @Property
125
- boolean ${propertyName.replace(/\s+/g, '_').toLowerCase()}(
126
- @ForAll int a,
127
- @ForAll String b) {
128
- // Property: ${propertyName}
129
- // Implement your property here
130
- return true; // Replace with actual property
131
- }`,
132
-
133
- array: (propertyName) => `
134
- @Property
135
- boolean ${propertyName.replace(/\s+/g, '_').toLowerCase()}(
136
- @ForAll List<Integer> arr) {
137
- // Property: ${propertyName}
138
- // Implement your property here
139
- return true; // Replace with actual property
140
- }`,
141
-
142
- object: (propertyName) => `
143
- @Property
144
- boolean ${propertyName.replace(/\s+/g, '_').toLowerCase()}(
145
- @ForAll("person") Person person) {
146
- // Property: ${propertyName}
147
- // Implement your property here
148
- return true; // Replace with actual property
149
- }
150
-
151
- @Provide
152
- Arbitrary<Person> person() {
153
- return Combinators.combine(Person::new)
154
- .with(Arbitraries.integers())
155
- .with(Arbitraries.strings())
156
- .with(Arbitraries.of(true, false));
157
- }`,
158
- },
159
- },
160
- };
161
-
162
- /**
163
- * Common property types that should be tested
164
- */
165
- const COMMON_PROPERTIES = {
166
- idempotent: {
167
- name: 'Idempotent operations',
168
- description:
169
- 'Running the same operation multiple times should have the same effect as running it once',
170
- examples: ['sorting algorithms', 'normalization functions', 'cleanup operations'],
171
- },
172
-
173
- commutative: {
174
- name: 'Commutative operations',
175
- description: 'Order of operations should not matter',
176
- examples: ['addition', 'set operations', 'string concatenation'],
177
- },
178
-
179
- associative: {
180
- name: 'Associative operations',
181
- description: 'Grouping of operations should not matter',
182
- examples: ['addition', 'multiplication', 'function composition'],
183
- },
184
-
185
- inverse: {
186
- name: 'Inverse operations',
187
- description: 'Operations should have meaningful inverses',
188
- examples: ['encode/decode', 'encrypt/decrypt', 'parse/format'],
189
- },
190
-
191
- monotonic: {
192
- name: 'Monotonic functions',
193
- description: 'Functions should preserve or reverse order',
194
- examples: ['sorting functions', 'comparison operations'],
195
- },
196
-
197
- roundtrip: {
198
- name: 'Roundtrip consistency',
199
- description: 'Convert to another format and back should preserve original',
200
- examples: ['serialization/deserialization', 'encoding/decoding'],
201
- },
202
-
203
- error_handling: {
204
- name: 'Error handling',
205
- description: 'Invalid inputs should be handled gracefully',
206
- examples: ['null/undefined checks', 'boundary conditions', 'invalid formats'],
207
- },
208
- };
209
-
210
- /**
211
- * Generate property-based tests for a given language and properties
212
- * @param {string} language - Target language (javascript, python, java)
213
- * @param {Array} properties - List of property names to generate tests for
214
- * @param {string} outputDir - Output directory for test files
215
- */
216
- function generatePropertyTests(language, properties, outputDir = 'tests/property') {
217
- const config = PROPERTY_TESTING_CONFIGS[language];
218
- if (!config) {
219
- throw new Error(`Unsupported language: ${language}`);
220
- }
221
-
222
- console.log(`๐Ÿ”ง Generating property-based tests for ${language}...`);
223
-
224
- // Ensure output directory exists
225
- if (!fs.existsSync(outputDir)) {
226
- fs.mkdirSync(outputDir, { recursive: true });
227
- }
228
-
229
- // Generate setup file
230
- generateSetupFile(language, outputDir);
231
-
232
- // Generate tests for each property type
233
- properties.forEach((propertyName) => {
234
- const property = COMMON_PROPERTIES[propertyName];
235
- if (!property) {
236
- console.warn(`โš ๏ธ Unknown property: ${propertyName}`);
237
- return;
238
- }
239
-
240
- const templateKey = inferTemplateType(property);
241
- const testContent = config.templates[templateKey](property.name);
242
-
243
- const fileName = `${propertyName}.test.${getFileExtension(language)}`;
244
- const filePath = path.join(outputDir, fileName);
245
-
246
- // Add property description as comments
247
- const enhancedContent = `/**
248
- * Property-based test: ${property.name}
249
- * Description: ${property.description}
250
- * Examples: ${property.examples.join(', ')}
251
- */
252
-
253
- ${testContent}`;
254
-
255
- fs.writeFileSync(filePath, enhancedContent);
256
- console.log(`โœ… Generated ${propertyName} test: ${filePath}`);
257
- });
258
-
259
- // Generate README
260
- generatePropertyTestingReadme(language, properties, outputDir);
261
- }
262
-
263
- /**
264
- * Infer template type from property description
265
- */
266
- function inferTemplateType(property) {
267
- if (property.examples.some((ex) => ex.includes('array') || ex.includes('list'))) {
268
- return 'array';
269
- }
270
- if (property.examples.some((ex) => ex.includes('object') || ex.includes('record'))) {
271
- return 'object';
272
- }
273
- return 'number'; // Default
274
- }
275
-
276
- /**
277
- * Get file extension for language
278
- */
279
- function getFileExtension(language) {
280
- const extensions = {
281
- javascript: 'js',
282
- python: 'py',
283
- java: 'java',
284
- };
285
- return extensions[language] || 'js';
286
- }
287
-
288
- /**
289
- * Generate setup file for property-based testing
290
- */
291
- function generateSetupFile(language, outputDir) {
292
- const config = PROPERTY_TESTING_CONFIGS[language];
293
-
294
- let setupContent = '';
295
-
296
- switch (language) {
297
- case 'javascript':
298
- setupContent = `// Property-based testing setup for JavaScript
299
- // Run: ${config.setup.install}
300
-
301
- ${config.setup.import}
302
-
303
- // Configure fast-check for better shrinking and debugging
304
- fc.configureGlobal({
305
- verbose: true,
306
- seed: 42,
307
- numRuns: 100 // Increase for production
308
- });
309
-
310
- module.exports = { fc };
311
- `;
312
- break;
313
-
314
- case 'python':
315
- setupContent = `# Property-based testing setup for Python
316
- # Run: ${config.setup.install}
317
-
318
- ${config.setup.import}
319
-
320
- # Configure hypothesis for better test runs
321
- settings.register_profile("ci", settings(max_examples=1000))
322
- settings.load_profile("ci")
323
- `;
324
- break;
325
-
326
- case 'java':
327
- setupContent = `// Property-based testing setup for Java
328
- // Add to build.gradle: ${config.setup.install}
329
-
330
- ${config.setup.import}
331
-
332
- // Configure jqwik for better test runs
333
- @Configure
334
- class JqwikConfiguration {
335
- @Provide
336
- Arbitrary<Integer> integers() {
337
- return Arbitraries.integers().between(-1000, 1000);
338
- }
339
-
340
- @Provide
341
- Arbitrary<String> strings() {
342
- return Arbitraries.strings().withLength(0, 50);
343
- }
344
- }
345
- `;
346
- break;
347
- }
348
-
349
- const setupPath = path.join(outputDir, `setup.${getFileExtension(language)}`);
350
- fs.writeFileSync(setupPath, setupContent);
351
- console.log(`โœ… Generated setup file: ${setupPath}`);
352
- }
353
-
354
- /**
355
- * Generate README for property-based testing
356
- */
357
- function generatePropertyTestingReadme(language, properties, outputDir) {
358
- const config = PROPERTY_TESTING_CONFIGS[language];
359
-
360
- const readmeContent = `# Property-Based Testing
361
-
362
- This directory contains property-based tests generated by CAWS.
363
-
364
- ## Setup
365
-
366
- 1. Install dependencies:
367
- \`\`\`bash
368
- ${config.setup.install}
369
- \`\`\`
370
-
371
- 2. Run property tests:
372
- \`\`\`bash
373
- ${config.setup.runner}
374
- \`\`\`
375
-
376
- ## Generated Properties
377
-
378
- ${properties.map((prop) => `- **${COMMON_PROPERTIES[prop].name}**: ${COMMON_PROPERTIES[prop].description}`).join('\n')}
379
-
380
- ## Understanding Properties
381
-
382
- ### Idempotent Operations
383
- An operation is idempotent if running it multiple times has the same effect as running it once.
384
-
385
- ### Commutative Operations
386
- Order doesn't matter - f(a, b) = f(b, a)
387
-
388
- ### Associative Operations
389
- Grouping doesn't matter - f(f(a, b), c) = f(a, f(b, c))
390
-
391
- ### Inverse Operations
392
- Operations should have meaningful inverses that restore original state
393
-
394
- ## Tips for Writing Properties
395
-
396
- 1. **Start Simple**: Begin with obvious properties, then add more complex ones
397
- 2. **Use Generators**: Create appropriate input generators for your domain
398
- 3. **Handle Edge Cases**: Ensure properties work with null, empty, and boundary values
399
- 4. **Document Assumptions**: Clearly state what your property assumes about inputs
400
-
401
- ## Examples
402
-
403
- \`\`\`${language}
404
- ${config.templates.number('Example property')}
405
- \`\`\`
406
- `;
407
-
408
- fs.writeFileSync(path.join(outputDir, 'README.md'), readmeContent);
409
- console.log(`โœ… Generated README: ${path.join(outputDir, 'README.md')}`);
410
- }
411
-
412
- /**
413
- * Run property-based tests and analyze results
414
- * @param {string} language - Target language
415
- * @param {string} testDir - Test directory
416
- * @returns {Object} Test results
417
- */
418
- function runPropertyTests(language, testDir = 'tests/property') {
419
- const config = PROPERTY_TESTING_CONFIGS[language];
420
- if (!config) {
421
- throw new Error(`Unsupported language: ${language}`);
422
- }
423
-
424
- console.log(`๐Ÿงช Running property-based tests for ${language}...`);
425
-
426
- const results = {
427
- total: 0,
428
- passed: 0,
429
- failed: 0,
430
- errors: [],
431
- coverage: {},
432
- };
433
-
434
- try {
435
- // Check if test files exist
436
- if (!fs.existsSync(testDir)) {
437
- results.errors.push(`Test directory not found: ${testDir}`);
438
- return results;
439
- }
440
-
441
- const testFiles = fs
442
- .readdirSync(testDir)
443
- .filter(
444
- (file) =>
445
- file.endsWith(`.test.${getFileExtension(language)}`) ||
446
- file.endsWith(`_test.${getFileExtension(language)}`)
447
- );
448
-
449
- if (testFiles.length === 0) {
450
- results.errors.push(`No property test files found in ${testDir}`);
451
- return results;
452
- }
453
-
454
- // Run tests based on language
455
- let testOutput;
456
- try {
457
- switch (language) {
458
- case 'javascript':
459
- testOutput = execSync(`${config.setup.runner} -- --testPathPattern=property`, {
460
- encoding: 'utf8',
461
- cwd: process.cwd(),
462
- });
463
- break;
464
- case 'python':
465
- testOutput = execSync(`${config.setup.runner} ${testDir}`, {
466
- encoding: 'utf8',
467
- cwd: process.cwd(),
468
- });
469
- break;
470
- case 'java':
471
- testOutput = execSync(config.setup.runner, {
472
- encoding: 'utf8',
473
- cwd: process.cwd(),
474
- });
475
- break;
476
- }
477
-
478
- // Parse test output
479
- results.total = (testOutput.match(/test|spec/g) || []).length;
480
- results.passed = (testOutput.match(/โœ“|passed|ok/g) || []).length;
481
- results.failed = (testOutput.match(/โœ—|failed|error/g) || []).length;
482
- } catch (error) {
483
- results.errors.push(`Test execution failed: ${error.message}`);
484
- results.failed = testFiles.length; // Assume all failed if execution failed
485
- }
486
- } catch (error) {
487
- results.errors.push(`Error running property tests: ${error.message}`);
488
- }
489
-
490
- return results;
491
- }
492
-
493
- /**
494
- * Analyze property testing coverage and suggest improvements
495
- * @param {Object} testResults - Results from runPropertyTests
496
- * @param {Array} implementedProperties - List of implemented properties
497
- * @returns {Object} Coverage analysis
498
- */
499
- function analyzePropertyCoverage(testResults, implementedProperties) {
500
- const analysis = {
501
- coverage_score: 0,
502
- missing_properties: [],
503
- recommendations: [],
504
- strengths: [],
505
- weaknesses: [],
506
- };
507
-
508
- if (testResults.total === 0) {
509
- analysis.missing_properties = Object.keys(COMMON_PROPERTIES);
510
- analysis.recommendations.push('No property tests implemented');
511
- return analysis;
512
- }
513
-
514
- // Calculate coverage score
515
- const implementedSet = new Set(implementedProperties);
516
- const totalProperties = Object.keys(COMMON_PROPERTIES).length;
517
- analysis.coverage_score = (implementedSet.size / totalProperties) * 100;
518
-
519
- // Find missing properties
520
- Object.keys(COMMON_PROPERTIES).forEach((prop) => {
521
- if (!implementedSet.has(prop)) {
522
- analysis.missing_properties.push(prop);
523
- }
524
- });
525
-
526
- // Generate recommendations
527
- if (analysis.missing_properties.length > 0) {
528
- analysis.recommendations.push(
529
- `Missing ${analysis.missing_properties.length} property types: ${analysis.missing_properties.join(', ')}`
530
- );
531
- }
532
-
533
- if (testResults.failed > 0) {
534
- analysis.weaknesses.push(`${testResults.failed} property tests are failing`);
535
- analysis.recommendations.push('Fix failing property tests and strengthen property definitions');
536
- }
537
-
538
- if (testResults.passed > 0) {
539
- analysis.strengths.push(`${testResults.passed} property tests are passing`);
540
- }
541
-
542
- if (analysis.coverage_score >= 80) {
543
- analysis.strengths.push('Good property coverage');
544
- } else if (analysis.coverage_score >= 50) {
545
- analysis.recommendations.push('Consider adding more property types for better coverage');
546
- } else {
547
- analysis.recommendations.push(
548
- 'Property testing coverage is low - prioritize adding key properties'
549
- );
550
- }
551
-
552
- return analysis;
553
- }
554
-
555
- // CLI interface
556
- if (require.main === module) {
557
- const command = process.argv[2];
558
-
559
- switch (command) {
560
- case 'generate':
561
- const language = process.argv[3] || 'javascript';
562
- const properties = process.argv[4]
563
- ? process.argv[4].split(',')
564
- : ['idempotent', 'commutative'];
565
- const outputDir = process.argv[5] || 'tests/property';
566
-
567
- if (!PROPERTY_TESTING_CONFIGS[language]) {
568
- console.error(`โŒ Unsupported language: ${language}`);
569
- console.error(`Supported languages: ${Object.keys(PROPERTY_TESTING_CONFIGS).join(', ')}`);
570
- process.exit(1);
571
- }
572
-
573
- try {
574
- generatePropertyTests(language, properties, outputDir);
575
- console.log(`\n๐ŸŽฏ Generated property-based tests for ${language}`);
576
- console.log(`Properties: ${properties.join(', ')}`);
577
- console.log(`Output directory: ${outputDir}`);
578
- } catch (error) {
579
- console.error(`โŒ Error generating property tests: ${error.message}`);
580
- process.exit(1);
581
- }
582
- break;
583
-
584
- case 'run':
585
- const runLanguage = process.argv[3] || 'javascript';
586
- const testDir = process.argv[4] || 'tests/property';
587
-
588
- try {
589
- const results = runPropertyTests(runLanguage, testDir);
590
-
591
- console.log('\n๐Ÿงช Property Test Results:');
592
- console.log(` Total: ${results.total}`);
593
- console.log(` Passed: ${results.passed}`);
594
- console.log(` Failed: ${results.failed}`);
595
-
596
- if (results.errors.length > 0) {
597
- console.log('\nโŒ Errors:');
598
- results.errors.forEach((error) => console.log(` - ${error}`));
599
- }
600
-
601
- if (results.failed > 0) {
602
- console.error(`\nโŒ ${results.failed} property tests failed`);
603
- process.exit(1);
604
- } else if (results.passed === 0) {
605
- console.warn('โš ๏ธ No property tests passed');
606
- process.exit(1);
607
- } else {
608
- console.log('โœ… All property tests passed');
609
- }
610
- } catch (error) {
611
- console.error(`โŒ Error running property tests: ${error.message}`);
612
- process.exit(1);
613
- }
614
- break;
615
-
616
- case 'analyze':
617
- const analyzeLanguage = process.argv[3] || 'javascript';
618
- const testResultsArg = process.argv[4] || 'tests/property';
619
- const implementedProps = process.argv[5] ? process.argv[5].split(',') : [];
620
-
621
- try {
622
- // Run tests first if not provided
623
- let results;
624
- if (typeof testResultsArg === 'string' && fs.existsSync(testResultsArg)) {
625
- results = runPropertyTests(analyzeLanguage, testResultsArg);
626
- } else {
627
- // Assume test results are passed as arguments
628
- results = {
629
- total: parseInt(process.argv[4]) || 0,
630
- passed: parseInt(process.argv[5]) || 0,
631
- failed: parseInt(process.argv[6]) || 0,
632
- errors: [],
633
- };
634
- }
635
-
636
- const coverage = analyzePropertyCoverage(results, implementedProps);
637
-
638
- console.log('\n๐Ÿ“Š Property Testing Coverage Analysis:');
639
- console.log(` Coverage Score: ${Math.round(coverage.coverage_score)}/100`);
640
-
641
- if (coverage.strengths.length > 0) {
642
- console.log('\nโœ… Strengths:');
643
- coverage.strengths.forEach((strength) => console.log(` - ${strength}`));
644
- }
645
-
646
- if (coverage.weaknesses.length > 0) {
647
- console.log('\nโš ๏ธ Weaknesses:');
648
- coverage.weaknesses.forEach((weakness) => console.log(` - ${weakness}`));
649
- }
650
-
651
- if (coverage.missing_properties.length > 0) {
652
- console.log('\n๐Ÿ“‹ Missing Properties:');
653
- coverage.missing_properties.forEach((prop) => {
654
- const property = COMMON_PROPERTIES[prop];
655
- console.log(` - ${property.name}: ${property.description}`);
656
- });
657
- }
658
-
659
- if (coverage.recommendations.length > 0) {
660
- console.log('\n๐Ÿ’ก Recommendations:');
661
- coverage.recommendations.forEach((rec) => console.log(` - ${rec}`));
662
- }
663
-
664
- if (coverage.coverage_score < 70) {
665
- console.error(
666
- `\nโŒ Property testing coverage too low: ${Math.round(coverage.coverage_score)}/100`
667
- );
668
- process.exit(1);
669
- }
670
- } catch (error) {
671
- console.error(`โŒ Error analyzing property coverage: ${error.message}`);
672
- process.exit(1);
673
- }
674
- break;
675
-
676
- default:
677
- console.log('CAWS Property-Based Testing Tool');
678
- console.log('Usage:');
679
- console.log(' node property-testing.js generate <language> [properties] [output-dir]');
680
- console.log(' node property-testing.js run <language> [test-dir]');
681
- console.log(' node property-testing.js analyze <language> [test-dir] [properties]');
682
- console.log('');
683
- console.log('Supported languages:');
684
- Object.keys(PROPERTY_TESTING_CONFIGS).forEach((lang) => {
685
- console.log(` - ${lang}: ${PROPERTY_TESTING_CONFIGS[lang].library}`);
686
- });
687
- console.log('');
688
- console.log('Available properties:');
689
- Object.keys(COMMON_PROPERTIES).forEach((prop) => {
690
- console.log(` - ${prop}: ${COMMON_PROPERTIES[prop].name}`);
691
- });
692
- console.log('');
693
- console.log('Examples:');
694
- console.log(' node property-testing.js generate javascript idempotent,commutative');
695
- console.log(' node property-testing.js run python tests/property');
696
- console.log(' node property-testing.js analyze java 5 3 2');
697
- process.exit(1);
698
- }
699
- }
700
-
701
- module.exports = {
702
- generatePropertyTests,
703
- runPropertyTests,
704
- analyzePropertyCoverage,
705
- COMMON_PROPERTIES,
706
- PROPERTY_TESTING_CONFIGS,
707
- };
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Generate provenance manifest
4
- * @param {Object} options - Provenance options
5
- * @returns {Object} Provenance manifest
6
- */
7
- export function generateProvenance(options?: any): any;
8
- /**
9
- * Save provenance manifest to file
10
- * @param {Object} provenance - Provenance manifest
11
- * @param {string} filepath - File path to save to
12
- */
13
- export function saveProvenance(provenance: any, filepath: string): void;
14
- //# sourceMappingURL=provenance.d.ts.map