@pennyfarthing/benchmark 10.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/commands/benchmark-control.md +69 -0
  2. package/commands/benchmark.md +485 -0
  3. package/commands/job-fair.md +102 -0
  4. package/commands/solo.md +447 -0
  5. package/dist/benchmark-integration.d.ts +182 -0
  6. package/dist/benchmark-integration.d.ts.map +1 -0
  7. package/dist/benchmark-integration.js +710 -0
  8. package/dist/benchmark-integration.js.map +1 -0
  9. package/dist/benchmark-integration.test.d.ts +6 -0
  10. package/dist/benchmark-integration.test.d.ts.map +1 -0
  11. package/dist/benchmark-integration.test.js +41 -0
  12. package/dist/benchmark-integration.test.js.map +1 -0
  13. package/dist/index.d.ts +3 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +5 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/job-fair-aggregator.d.ts +150 -0
  18. package/dist/job-fair-aggregator.d.ts.map +1 -0
  19. package/dist/job-fair-aggregator.js +547 -0
  20. package/dist/job-fair-aggregator.js.map +1 -0
  21. package/dist/job-fair-aggregator.test.d.ts +6 -0
  22. package/dist/job-fair-aggregator.test.d.ts.map +1 -0
  23. package/dist/job-fair-aggregator.test.js +35 -0
  24. package/dist/job-fair-aggregator.test.js.map +1 -0
  25. package/dist/package-exports.test.d.ts +13 -0
  26. package/dist/package-exports.test.d.ts.map +1 -0
  27. package/dist/package-exports.test.js +192 -0
  28. package/dist/package-exports.test.js.map +1 -0
  29. package/docs/BENCHMARK-METHODOLOGY.md +105 -0
  30. package/docs/BENCHMARKING.md +311 -0
  31. package/docs/OCEAN-BENCHMARKING.md +210 -0
  32. package/docs/benchmarks-guide.md +62 -0
  33. package/package.json +66 -0
  34. package/scenarios/README.md +145 -0
  35. package/scenarios/architecture/database-selection.yaml +119 -0
  36. package/scenarios/architecture/legacy-modernization.yaml +153 -0
  37. package/scenarios/architecture/scaling-decision.yaml +88 -0
  38. package/scenarios/code-review/graphql-api-review.yaml +714 -0
  39. package/scenarios/code-review/order-service.yaml +622 -0
  40. package/scenarios/code-review/react-auth-component.yaml +569 -0
  41. package/scenarios/code-review/security-review.yaml +145 -0
  42. package/scenarios/code-review/terraform-infrastructure.yaml +582 -0
  43. package/scenarios/debug/buggy-user-service.yaml +541 -0
  44. package/scenarios/debug/null-pointer.yaml +130 -0
  45. package/scenarios/debugging/async-control-flow.yaml +161 -0
  46. package/scenarios/debugging/auth-bypass.yaml +197 -0
  47. package/scenarios/debugging/error-handling.yaml +178 -0
  48. package/scenarios/debugging/input-validation.yaml +157 -0
  49. package/scenarios/debugging/null-check-missing.yaml +139 -0
  50. package/scenarios/debugging/off-by-one-loop.yaml +132 -0
  51. package/scenarios/debugging/race-condition.yaml +180 -0
  52. package/scenarios/debugging/resource-leak.yaml +166 -0
  53. package/scenarios/debugging/simple-logic-error.yaml +115 -0
  54. package/scenarios/debugging/sql-injection.yaml +163 -0
  55. package/scenarios/dev/event-processor-tdd.yaml +764 -0
  56. package/scenarios/dev/migration-disaster.yaml +415 -0
  57. package/scenarios/dev/race-condition-cache.yaml +546 -0
  58. package/scenarios/dev/tdd-shopping-cart.yaml +681 -0
  59. package/scenarios/schema.yaml +639 -0
  60. package/scenarios/sm/dependency-deadlock.yaml +414 -0
  61. package/scenarios/sm/executive-pet-project.yaml +336 -0
  62. package/scenarios/sm/layoff-planning.yaml +356 -0
  63. package/scenarios/sm/sprint-planning-conflict.yaml +303 -0
  64. package/scenarios/sm/story-breakdown.yaml +240 -0
  65. package/scenarios/sm/three-sprint-failure.yaml +397 -0
  66. package/scenarios/swe-bench/README.md +57 -0
  67. package/scenarios/swe-bench/astropy-12907.yaml +128 -0
  68. package/scenarios/swe-bench/astropy-13398.yaml +177 -0
  69. package/scenarios/swe-bench/astropy-14309.yaml +180 -0
  70. package/scenarios/swe-bench/django-10097.yaml +106 -0
  71. package/scenarios/swe-bench/django-10554.yaml +140 -0
  72. package/scenarios/swe-bench/django-10973.yaml +93 -0
  73. package/scenarios/swe-bench/flask-5014-reviewer.yaml +145 -0
  74. package/scenarios/swe-bench/flask-5014-tea.yaml +123 -0
  75. package/scenarios/swe-bench/flask-5014.yaml +91 -0
  76. package/scenarios/swe-bench/import-swebench.py +246 -0
  77. package/scenarios/swe-bench/matplotlib-13989.yaml +139 -0
  78. package/scenarios/swe-bench/matplotlib-14623.yaml +127 -0
  79. package/scenarios/swe-bench/requests-1142-reviewer.yaml +144 -0
  80. package/scenarios/swe-bench/requests-1142-tea.yaml +135 -0
  81. package/scenarios/swe-bench/requests-1142.yaml +100 -0
  82. package/scenarios/swe-bench/requests-2931.yaml +98 -0
  83. package/scenarios/swe-bench/seaborn-3069.yaml +102 -0
  84. package/scenarios/swe-bench/sphinx-7590.yaml +108 -0
  85. package/scenarios/swe-bench/xarray-3993.yaml +104 -0
  86. package/scenarios/swe-bench/xarray-6992.yaml +136 -0
  87. package/scenarios/tea/checkout-component-tests.yaml +596 -0
  88. package/scenarios/tea/cli-tool-tests.yaml +561 -0
  89. package/scenarios/tea/microservice-integration-tests.yaml +520 -0
  90. package/scenarios/tea/payment-processor-tests.yaml +550 -0
  91. package/scripts/aggregate-benchmark-stats.js +315 -0
  92. package/scripts/aggregate-benchmark-stats.sh +8 -0
  93. package/scripts/benchmark-runner.js +392 -0
  94. package/scripts/benchmark-runner.sh +8 -0
  95. package/scripts/consolidate-job-fair.sh +107 -0
  96. package/scripts/convert-jobfair-to-benchmarks.sh +230 -0
  97. package/scripts/job-fair-batch.sh +116 -0
  98. package/scripts/job-fair-progress.sh +35 -0
  99. package/scripts/job-fair-runner.sh +278 -0
  100. package/scripts/job-fair-status.sh +80 -0
  101. package/scripts/job-fair-watcher-v2.sh +38 -0
  102. package/scripts/job-fair-watcher.sh +50 -0
  103. package/scripts/parallel-benchmark.sh +140 -0
  104. package/scripts/solo-runner.sh +344 -0
  105. package/scripts/test/ensure-swebench-data.sh +59 -0
  106. package/scripts/test/ground-truth-judge.py +220 -0
  107. package/scripts/test/swebench-judge.py +374 -0
  108. package/scripts/test/test-cache.sh +165 -0
  109. package/scripts/test/test-setup.sh +337 -0
  110. package/scripts/theme/compute-theme-tiers.sh +13 -0
  111. package/scripts/theme/compute_theme_tiers.py +402 -0
  112. package/scripts/theme/update-theme-tiers.sh +97 -0
  113. package/skills/finalize-run/SKILL.md +261 -0
  114. package/skills/judge/SKILL.md +644 -0
  115. package/skills/persona-benchmark/SKILL.md +187 -0
@@ -0,0 +1,561 @@
1
+ ---
2
+ # Scenario: CLI Tool Test Suite
3
+ # Category: tea
4
+ # Purpose: Test CLI/systems testing skills with Go
5
+
6
+ id: tea-004
7
+ name: cli-tool-tests
8
+ title: "CLI Tool Test Suite Design"
9
+ category: tea
10
+ difficulty: hard # Empirical: control mean 64.50
11
+ version: "1.0"
12
+
13
+ description: |
14
+ A CLI tool for managing configuration files with subcommands for init, get,
15
+ set, delete, and validate. Must write tests covering argument parsing, file
16
+ I/O, error handling, and user-facing output. Tests systems programming test
17
+ skills distinct from web/API testing.
18
+
19
+ purpose: |
20
+ This scenario tests CLI testing expertise. CLI tools have unique testing
21
+ concerns: argument parsing, exit codes, stdout/stderr handling, file system
22
+ interactions. Measures ability to test command-line interfaces thoroughly.
23
+
24
+ prompt: |
25
+ You are a Test Engineer designing tests for a configuration management CLI tool.
26
+ Write a comprehensive test suite using Go's testing package.
27
+
28
+ The CLI has these commands:
29
+ - `config init` - Initialize a new config file
30
+ - `config get <key>` - Get a config value
31
+ - `config set <key> <value>` - Set a config value
32
+ - `config delete <key>` - Delete a config key
33
+ - `config validate` - Validate config file syntax
34
+ - `config list` - List all config keys
35
+
36
+ Global flags:
37
+ - `--config <path>` - Config file path (default: ~/.config/app/config.yaml)
38
+ - `--format <json|yaml|text>` - Output format
39
+ - `--quiet` - Suppress non-essential output
40
+ - `--verbose` - Show detailed output
41
+
42
+ Write tests covering:
43
+ 1. Argument parsing (valid/invalid args, flags, subcommands)
44
+ 2. Exit codes (0 for success, 1 for error, 2 for usage error)
45
+ 3. Stdout vs stderr output (data to stdout, errors to stderr)
46
+ 4. File system operations (create, read, write, permissions)
47
+ 5. Error messages (user-friendly, actionable)
48
+ 6. Edge cases (missing file, invalid YAML, concurrent access)
49
+
50
+ For each test:
51
+ 1. Use table-driven tests where appropriate
52
+ 2. Test both success and failure paths
53
+ 3. Verify exit codes, stdout, and stderr
54
+ 4. Use temporary directories for file tests
55
+
56
+ code:
57
+ language: go
58
+ filename: config_cli.go
59
+ content: |
60
+ package main
61
+
62
+ import (
63
+ "encoding/json"
64
+ "fmt"
65
+ "io"
66
+ "os"
67
+ "path/filepath"
68
+
69
+ "gopkg.in/yaml.v3"
70
+ )
71
+
72
+ // Config represents the configuration structure
73
+ type Config struct {
74
+ data map[string]interface{}
75
+ filepath string
76
+ }
77
+
78
+ // CLI represents the command-line interface
79
+ type CLI struct {
80
+ stdout io.Writer
81
+ stderr io.Writer
82
+ configDir string
83
+ }
84
+
85
+ // NewCLI creates a new CLI instance
86
+ func NewCLI(stdout, stderr io.Writer, configDir string) *CLI {
87
+ return &CLI{
88
+ stdout: stdout,
89
+ stderr: stderr,
90
+ configDir: configDir,
91
+ }
92
+ }
93
+
94
+ // Run executes the CLI with the given arguments
95
+ func (c *CLI) Run(args []string) int {
96
+ if len(args) < 1 {
97
+ fmt.Fprintln(c.stderr, "Usage: config <command> [options]")
98
+ return 2
99
+ }
100
+
101
+ // Parse global flags
102
+ configPath := filepath.Join(c.configDir, "config.yaml")
103
+ format := "text"
104
+ quiet := false
105
+ verbose := false
106
+
107
+ // Filter out flags and get command
108
+ var cmdArgs []string
109
+ for i := 0; i < len(args); i++ {
110
+ switch args[i] {
111
+ case "--config":
112
+ if i+1 < len(args) {
113
+ configPath = args[i+1]
114
+ i++
115
+ }
116
+ case "--format":
117
+ if i+1 < len(args) {
118
+ format = args[i+1]
119
+ i++
120
+ }
121
+ case "--quiet":
122
+ quiet = true
123
+ case "--verbose":
124
+ verbose = true
125
+ default:
126
+ cmdArgs = append(cmdArgs, args[i])
127
+ }
128
+ }
129
+
130
+ if len(cmdArgs) < 1 {
131
+ fmt.Fprintln(c.stderr, "Error: no command specified")
132
+ return 2
133
+ }
134
+
135
+ command := cmdArgs[0]
136
+ cmdArgs = cmdArgs[1:]
137
+
138
+ switch command {
139
+ case "init":
140
+ return c.cmdInit(configPath, quiet)
141
+ case "get":
142
+ if len(cmdArgs) < 1 {
143
+ fmt.Fprintln(c.stderr, "Error: get requires a key argument")
144
+ return 2
145
+ }
146
+ return c.cmdGet(configPath, cmdArgs[0], format)
147
+ case "set":
148
+ if len(cmdArgs) < 2 {
149
+ fmt.Fprintln(c.stderr, "Error: set requires key and value arguments")
150
+ return 2
151
+ }
152
+ return c.cmdSet(configPath, cmdArgs[0], cmdArgs[1], quiet)
153
+ case "delete":
154
+ if len(cmdArgs) < 1 {
155
+ fmt.Fprintln(c.stderr, "Error: delete requires a key argument")
156
+ return 2
157
+ }
158
+ return c.cmdDelete(configPath, cmdArgs[0], quiet)
159
+ case "validate":
160
+ return c.cmdValidate(configPath, verbose)
161
+ case "list":
162
+ return c.cmdList(configPath, format)
163
+ default:
164
+ fmt.Fprintf(c.stderr, "Error: unknown command %q\n", command)
165
+ return 2
166
+ }
167
+ }
168
+
169
+ func (c *CLI) cmdInit(configPath string, quiet bool) int {
170
+ dir := filepath.Dir(configPath)
171
+ if err := os.MkdirAll(dir, 0755); err != nil {
172
+ fmt.Fprintf(c.stderr, "Error creating directory: %v\n", err)
173
+ return 1
174
+ }
175
+
176
+ if _, err := os.Stat(configPath); err == nil {
177
+ fmt.Fprintln(c.stderr, "Error: config file already exists")
178
+ return 1
179
+ }
180
+
181
+ initialConfig := map[string]interface{}{
182
+ "version": "1.0",
183
+ }
184
+
185
+ data, err := yaml.Marshal(initialConfig)
186
+ if err != nil {
187
+ fmt.Fprintf(c.stderr, "Error encoding config: %v\n", err)
188
+ return 1
189
+ }
190
+
191
+ if err := os.WriteFile(configPath, data, 0644); err != nil {
192
+ fmt.Fprintf(c.stderr, "Error writing config: %v\n", err)
193
+ return 1
194
+ }
195
+
196
+ if !quiet {
197
+ fmt.Fprintf(c.stdout, "Initialized config at %s\n", configPath)
198
+ }
199
+ return 0
200
+ }
201
+
202
+ func (c *CLI) cmdGet(configPath, key, format string) int {
203
+ config, err := c.loadConfig(configPath)
204
+ if err != nil {
205
+ fmt.Fprintf(c.stderr, "Error loading config: %v\n", err)
206
+ return 1
207
+ }
208
+
209
+ value, ok := config[key]
210
+ if !ok {
211
+ fmt.Fprintf(c.stderr, "Error: key %q not found\n", key)
212
+ return 1
213
+ }
214
+
215
+ return c.outputValue(value, format)
216
+ }
217
+
218
+ func (c *CLI) cmdSet(configPath, key, value string, quiet bool) int {
219
+ config, err := c.loadConfig(configPath)
220
+ if err != nil {
221
+ // If file doesn't exist, start fresh
222
+ if os.IsNotExist(err) {
223
+ config = make(map[string]interface{})
224
+ } else {
225
+ fmt.Fprintf(c.stderr, "Error loading config: %v\n", err)
226
+ return 1
227
+ }
228
+ }
229
+
230
+ config[key] = value
231
+
232
+ if err := c.saveConfig(configPath, config); err != nil {
233
+ fmt.Fprintf(c.stderr, "Error saving config: %v\n", err)
234
+ return 1
235
+ }
236
+
237
+ if !quiet {
238
+ fmt.Fprintf(c.stdout, "Set %s = %s\n", key, value)
239
+ }
240
+ return 0
241
+ }
242
+
243
+ func (c *CLI) cmdDelete(configPath, key string, quiet bool) int {
244
+ config, err := c.loadConfig(configPath)
245
+ if err != nil {
246
+ fmt.Fprintf(c.stderr, "Error loading config: %v\n", err)
247
+ return 1
248
+ }
249
+
250
+ if _, ok := config[key]; !ok {
251
+ fmt.Fprintf(c.stderr, "Error: key %q not found\n", key)
252
+ return 1
253
+ }
254
+
255
+ delete(config, key)
256
+
257
+ if err := c.saveConfig(configPath, config); err != nil {
258
+ fmt.Fprintf(c.stderr, "Error saving config: %v\n", err)
259
+ return 1
260
+ }
261
+
262
+ if !quiet {
263
+ fmt.Fprintf(c.stdout, "Deleted %s\n", key)
264
+ }
265
+ return 0
266
+ }
267
+
268
+ func (c *CLI) cmdValidate(configPath string, verbose bool) int {
269
+ data, err := os.ReadFile(configPath)
270
+ if err != nil {
271
+ fmt.Fprintf(c.stderr, "Error reading config: %v\n", err)
272
+ return 1
273
+ }
274
+
275
+ var config map[string]interface{}
276
+ if err := yaml.Unmarshal(data, &config); err != nil {
277
+ fmt.Fprintf(c.stderr, "Error: invalid YAML syntax: %v\n", err)
278
+ return 1
279
+ }
280
+
281
+ if verbose {
282
+ fmt.Fprintf(c.stdout, "Config file: %s\n", configPath)
283
+ fmt.Fprintf(c.stdout, "Keys: %d\n", len(config))
284
+ }
285
+ fmt.Fprintln(c.stdout, "Config is valid")
286
+ return 0
287
+ }
288
+
289
+ func (c *CLI) cmdList(configPath, format string) int {
290
+ config, err := c.loadConfig(configPath)
291
+ if err != nil {
292
+ fmt.Fprintf(c.stderr, "Error loading config: %v\n", err)
293
+ return 1
294
+ }
295
+
296
+ switch format {
297
+ case "json":
298
+ data, _ := json.MarshalIndent(config, "", " ")
299
+ fmt.Fprintln(c.stdout, string(data))
300
+ case "yaml":
301
+ data, _ := yaml.Marshal(config)
302
+ fmt.Fprint(c.stdout, string(data))
303
+ default:
304
+ for k, v := range config {
305
+ fmt.Fprintf(c.stdout, "%s: %v\n", k, v)
306
+ }
307
+ }
308
+ return 0
309
+ }
310
+
311
+ func (c *CLI) loadConfig(path string) (map[string]interface{}, error) {
312
+ data, err := os.ReadFile(path)
313
+ if err != nil {
314
+ return nil, err
315
+ }
316
+
317
+ var config map[string]interface{}
318
+ if err := yaml.Unmarshal(data, &config); err != nil {
319
+ return nil, err
320
+ }
321
+
322
+ return config, nil
323
+ }
324
+
325
+ func (c *CLI) saveConfig(path string, config map[string]interface{}) error {
326
+ data, err := yaml.Marshal(config)
327
+ if err != nil {
328
+ return err
329
+ }
330
+ return os.WriteFile(path, data, 0644)
331
+ }
332
+
333
+ func (c *CLI) outputValue(value interface{}, format string) int {
334
+ switch format {
335
+ case "json":
336
+ data, _ := json.Marshal(value)
337
+ fmt.Fprintln(c.stdout, string(data))
338
+ case "yaml":
339
+ data, _ := yaml.Marshal(value)
340
+ fmt.Fprint(c.stdout, string(data))
341
+ default:
342
+ fmt.Fprintln(c.stdout, value)
343
+ }
344
+ return 0
345
+ }
346
+
347
+ func main() {
348
+ cli := NewCLI(os.Stdout, os.Stderr, os.Getenv("HOME"))
349
+ os.Exit(cli.Run(os.Args[1:]))
350
+ }
351
+
352
+ # =============================================================================
353
+ # BASELINE TEST SCENARIOS
354
+ # =============================================================================
355
+
356
+ baseline_issues:
357
+ argument_parsing:
358
+ - id: VALID_COMMANDS
359
+ description: "All valid commands are recognized"
360
+
361
+ - id: INVALID_COMMAND
362
+ description: "Unknown commands return exit code 2"
363
+
364
+ - id: MISSING_ARGS
365
+ description: "Missing required args show usage error"
366
+
367
+ - id: FLAG_PARSING
368
+ description: "Global flags parsed correctly"
369
+
370
+ exit_codes:
371
+ - id: SUCCESS_EXIT_0
372
+ description: "Successful operations return 0"
373
+
374
+ - id: ERROR_EXIT_1
375
+ description: "Errors return 1"
376
+
377
+ - id: USAGE_EXIT_2
378
+ description: "Usage errors return 2"
379
+
380
+ output_streams:
381
+ - id: DATA_TO_STDOUT
382
+ description: "Data output goes to stdout"
383
+
384
+ - id: ERRORS_TO_STDERR
385
+ description: "Error messages go to stderr"
386
+
387
+ - id: QUIET_MODE
388
+ description: "--quiet suppresses informational output"
389
+
390
+ file_operations:
391
+ - id: INIT_CREATES_FILE
392
+ description: "init creates config file and directories"
393
+
394
+ - id: GET_READS_VALUE
395
+ description: "get returns correct value"
396
+
397
+ - id: SET_PERSISTS
398
+ description: "set writes to file correctly"
399
+
400
+ - id: DELETE_REMOVES
401
+ description: "delete removes key from file"
402
+
403
+ error_handling:
404
+ - id: MISSING_FILE
405
+ description: "Graceful error for missing config"
406
+
407
+ - id: INVALID_YAML
408
+ description: "Clear error for malformed YAML"
409
+
410
+ - id: KEY_NOT_FOUND
411
+ description: "Clear error when key doesn't exist"
412
+
413
+ - id: PERMISSION_ERROR
414
+ description: "Clear error for permission issues"
415
+
416
+ output_formats:
417
+ - id: TEXT_FORMAT
418
+ description: "Default text format works"
419
+
420
+ - id: JSON_FORMAT
421
+ description: "--format json outputs valid JSON"
422
+
423
+ - id: YAML_FORMAT
424
+ description: "--format yaml outputs valid YAML"
425
+
426
+ # =============================================================================
427
+ # BONUS TEST SCENARIOS
428
+ # =============================================================================
429
+
430
+ bonus_issues:
431
+ advanced:
432
+ - id: CONCURRENT_ACCESS
433
+ description: "Handles concurrent reads/writes safely"
434
+
435
+ - id: LARGE_CONFIG
436
+ description: "Handles large config files efficiently"
437
+
438
+ - id: SPECIAL_CHARACTERS
439
+ description: "Keys/values with special chars handled"
440
+
441
+ robustness:
442
+ - id: PARTIAL_WRITE
443
+ description: "Atomic writes prevent corruption"
444
+
445
+ - id: SYMLINK_HANDLING
446
+ description: "Config path symlinks work correctly"
447
+
448
+ - id: RELATIVE_PATHS
449
+ description: "Relative --config paths resolved correctly"
450
+
451
+ usability:
452
+ - id: HELPFUL_ERRORS
453
+ description: "Error messages suggest fixes"
454
+
455
+ - id: VERBOSE_MODE
456
+ description: "--verbose shows additional info"
457
+
458
+ # =============================================================================
459
+ # SCORING
460
+ # =============================================================================
461
+
462
+ scoring:
463
+ total_baseline_scenarios: 20
464
+ total_bonus_scenarios: 8
465
+
466
+ categories:
467
+ - name: coverage
468
+ weight: 40
469
+ criteria:
470
+ - id: BASELINE_COVERED
471
+ description: "All baseline test scenarios covered"
472
+ points: 30
473
+ - id: BONUS_COVERED
474
+ description: "Additional valuable test scenarios"
475
+ points: 10
476
+
477
+ - name: quality
478
+ weight: 30
479
+ criteria:
480
+ - id: TABLE_DRIVEN
481
+ description: "Uses table-driven tests appropriately"
482
+ points: 10
483
+ - id: ISOLATION
484
+ description: "Tests use temp dirs, are isolated"
485
+ points: 10
486
+ - id: ASSERTIONS
487
+ description: "Clear, comprehensive assertions"
488
+ points: 10
489
+
490
+ - name: cli_specific
491
+ weight: 15
492
+ criteria:
493
+ - id: EXIT_CODES
494
+ description: "Tests verify exit codes"
495
+ points: 5
496
+ - id: STREAM_SEPARATION
497
+ description: "Tests verify stdout vs stderr"
498
+ points: 5
499
+ - id: FILE_CLEANUP
500
+ description: "Tests clean up temp files"
501
+ points: 5
502
+
503
+ - name: persona
504
+ weight: 15
505
+ criteria:
506
+ - id: CHARACTER_CONSISTENCY
507
+ description: "Stays in character throughout"
508
+ points: 8
509
+ - id: PERSONA_VALUE_ADD
510
+ description: "Persona enhances test documentation"
511
+ points: 7
512
+
513
+ # =============================================================================
514
+ # PERSONA INFLUENCE
515
+ # =============================================================================
516
+
517
+ persona_influence:
518
+ dimensions:
519
+ - name: test_style
520
+ description: "How tests are organized"
521
+ spectrum:
522
+ individual: "One test per scenario"
523
+ table_driven: "Extensive use of table tests"
524
+ hybrid: "Mix based on complexity"
525
+
526
+ - name: coverage_focus
527
+ description: "What gets tested most"
528
+ spectrum:
529
+ happy_path: "Focus on successful operations"
530
+ error_focused: "Emphasizes error handling"
531
+ comprehensive: "Equal coverage of both"
532
+
533
+ - name: systems_depth
534
+ description: "Depth of file system testing"
535
+ spectrum:
536
+ basic: "Simple file read/write"
537
+ intermediate: "Permissions, directories"
538
+ advanced: "Symlinks, atomicity, concurrency"
539
+
540
+ expected_tendencies:
541
+ discworld_tea:
542
+ character: "Igor"
543
+ expected_traits:
544
+ - "Thorough - covers edge cases"
545
+ - "Practical - focuses on real failures"
546
+ - "May suggest unusual test scenarios"
547
+ coverage_prediction: "comprehensive"
548
+
549
+ star_trek_tea:
550
+ character: "Scotty"
551
+ expected_traits:
552
+ - "Systems focus - file operations"
553
+ - "Engineering rigor - thorough coverage"
554
+ - "May emphasize robustness testing"
555
+ coverage_prediction: "comprehensive"
556
+
557
+ control_tea:
558
+ character: "None (baseline)"
559
+ expected_traits:
560
+ - "Standard CLI testing approach"
561
+ coverage_prediction: "baseline reference"