@pennyfarthing/core 7.4.0 → 7.5.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.
- package/dist/cli/utils/files.d.ts +0 -1
- package/dist/cli/utils/files.js +73 -56
- package/dist/cli/utils/manifest.d.ts +0 -1
- package/dist/cli/utils/manifest.js +48 -45
- package/dist/cli/utils/version.d.ts +0 -1
- package/dist/cli/utils/version.js +38 -32
- package/dist/index.d.ts +0 -1
- package/dist/index.js +39 -11
- package/dist/permissions/index.d.ts +0 -1
- package/dist/permissions/index.js +7 -4
- package/dist/permissions/permission-schema.d.ts +0 -1
- package/dist/permissions/permission-schema.js +13 -9
- package/dist/scripts/job-fair-aggregator.d.ts +0 -1
- package/dist/scripts/job-fair-aggregator.js +484 -341
- package/dist/workflow/index.d.ts +0 -1
- package/dist/workflow/index.js +12 -5
- package/dist/workflow/workflow-loader.d.ts +0 -1
- package/dist/workflow/workflow-loader.js +40 -34
- package/dist/workflow/workflow-permissions.d.ts +0 -1
- package/dist/workflow/workflow-permissions.js +14 -8
- package/dist/workflow/workflow-router.d.ts +0 -1
- package/dist/workflow/workflow-router.js +70 -51
- package/dist/workflow/workflow-schema.d.ts +0 -1
- package/dist/workflow/workflow-schema.js +62 -59
- package/package.json +1 -1
- package/dist/bmad/context-reader.d.ts +0 -71
- package/dist/bmad/context-reader.d.ts.map +0 -1
- package/dist/bmad/context-reader.js +0 -369
- package/dist/bmad/context-reader.js.map +0 -1
- package/dist/bmad/context-reader.test.d.ts +0 -71
- package/dist/bmad/context-reader.test.d.ts.map +0 -1
- package/dist/bmad/context-reader.test.js +0 -878
- package/dist/bmad/context-reader.test.js.map +0 -1
- package/dist/bmad/epics-parser.d.ts +0 -61
- package/dist/bmad/epics-parser.d.ts.map +0 -1
- package/dist/bmad/epics-parser.js +0 -331
- package/dist/bmad/epics-parser.js.map +0 -1
- package/dist/bmad/epics-parser.test.d.ts +0 -7
- package/dist/bmad/epics-parser.test.d.ts.map +0 -1
- package/dist/bmad/epics-parser.test.js +0 -449
- package/dist/bmad/epics-parser.test.js.map +0 -1
- package/dist/bmad/index.d.ts +0 -11
- package/dist/bmad/index.d.ts.map +0 -1
- package/dist/bmad/index.js +0 -24
- package/dist/bmad/index.js.map +0 -1
- package/dist/bmad/status-sync.d.ts +0 -173
- package/dist/bmad/status-sync.d.ts.map +0 -1
- package/dist/bmad/status-sync.js +0 -463
- package/dist/bmad/status-sync.js.map +0 -1
- package/dist/bmad/status-sync.test.d.ts +0 -7
- package/dist/bmad/status-sync.test.d.ts.map +0 -1
- package/dist/bmad/status-sync.test.js +0 -702
- package/dist/bmad/status-sync.test.js.map +0 -1
- package/dist/bmad/story-exporter.d.ts +0 -55
- package/dist/bmad/story-exporter.d.ts.map +0 -1
- package/dist/bmad/story-exporter.js +0 -170
- package/dist/bmad/story-exporter.js.map +0 -1
- package/dist/bmad/story-exporter.test.d.ts +0 -51
- package/dist/bmad/story-exporter.test.d.ts.map +0 -1
- package/dist/bmad/story-exporter.test.js +0 -603
- package/dist/bmad/story-exporter.test.js.map +0 -1
- package/dist/bmad/story-parser.d.ts +0 -44
- package/dist/bmad/story-parser.d.ts.map +0 -1
- package/dist/bmad/story-parser.js +0 -307
- package/dist/bmad/story-parser.js.map +0 -1
- package/dist/bmad/story-parser.test.d.ts +0 -44
- package/dist/bmad/story-parser.test.d.ts.map +0 -1
- package/dist/bmad/story-parser.test.js +0 -693
- package/dist/bmad/story-parser.test.js.map +0 -1
- package/dist/cli/commands/command.d.ts +0 -28
- package/dist/cli/commands/command.d.ts.map +0 -1
- package/dist/cli/commands/command.js +0 -399
- package/dist/cli/commands/command.js.map +0 -1
- package/dist/cli/commands/cyclist.d.ts +0 -46
- package/dist/cli/commands/cyclist.d.ts.map +0 -1
- package/dist/cli/commands/cyclist.js +0 -196
- package/dist/cli/commands/cyclist.js.map +0 -1
- package/dist/cli/commands/cyclist.test.d.ts +0 -13
- package/dist/cli/commands/cyclist.test.d.ts.map +0 -1
- package/dist/cli/commands/cyclist.test.js +0 -245
- package/dist/cli/commands/cyclist.test.js.map +0 -1
- package/dist/cli/commands/doctor.d.ts +0 -9
- package/dist/cli/commands/doctor.d.ts.map +0 -1
- package/dist/cli/commands/doctor.js +0 -652
- package/dist/cli/commands/doctor.js.map +0 -1
- package/dist/cli/commands/init.d.ts +0 -8
- package/dist/cli/commands/init.d.ts.map +0 -1
- package/dist/cli/commands/init.js +0 -524
- package/dist/cli/commands/init.js.map +0 -1
- package/dist/cli/commands/skill.d.ts +0 -28
- package/dist/cli/commands/skill.d.ts.map +0 -1
- package/dist/cli/commands/skill.js +0 -416
- package/dist/cli/commands/skill.js.map +0 -1
- package/dist/cli/commands/theme.d.ts +0 -21
- package/dist/cli/commands/theme.d.ts.map +0 -1
- package/dist/cli/commands/theme.js +0 -201
- package/dist/cli/commands/theme.js.map +0 -1
- package/dist/cli/commands/uninstall.d.ts +0 -8
- package/dist/cli/commands/uninstall.d.ts.map +0 -1
- package/dist/cli/commands/uninstall.js +0 -237
- package/dist/cli/commands/uninstall.js.map +0 -1
- package/dist/cli/commands/update.d.ts +0 -9
- package/dist/cli/commands/update.d.ts.map +0 -1
- package/dist/cli/commands/update.js +0 -418
- package/dist/cli/commands/update.js.map +0 -1
- package/dist/cli/commands/version.d.ts +0 -2
- package/dist/cli/commands/version.d.ts.map +0 -1
- package/dist/cli/commands/version.js +0 -28
- package/dist/cli/commands/version.js.map +0 -1
- package/dist/cli/customization.test.d.ts +0 -12
- package/dist/cli/customization.test.d.ts.map +0 -1
- package/dist/cli/customization.test.js +0 -84
- package/dist/cli/customization.test.js.map +0 -1
- package/dist/cli/cyclist-migration.test.d.ts +0 -16
- package/dist/cli/cyclist-migration.test.d.ts.map +0 -1
- package/dist/cli/cyclist-migration.test.js +0 -225
- package/dist/cli/cyclist-migration.test.js.map +0 -1
- package/dist/cli/index.d.ts +0 -3
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js +0 -174
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/ocean-profiles.test.d.ts +0 -13
- package/dist/cli/ocean-profiles.test.d.ts.map +0 -1
- package/dist/cli/ocean-profiles.test.js +0 -134
- package/dist/cli/ocean-profiles.test.js.map +0 -1
- package/dist/cli/theme-maker.test.d.ts +0 -11
- package/dist/cli/theme-maker.test.d.ts.map +0 -1
- package/dist/cli/theme-maker.test.js +0 -356
- package/dist/cli/theme-maker.test.js.map +0 -1
- package/dist/cli/utils/constants.d.ts +0 -66
- package/dist/cli/utils/constants.d.ts.map +0 -1
- package/dist/cli/utils/constants.js +0 -54
- package/dist/cli/utils/constants.js.map +0 -1
- package/dist/cli/utils/files.d.ts.map +0 -1
- package/dist/cli/utils/files.js.map +0 -1
- package/dist/cli/utils/logger.d.ts +0 -26
- package/dist/cli/utils/logger.d.ts.map +0 -1
- package/dist/cli/utils/logger.js +0 -88
- package/dist/cli/utils/logger.js.map +0 -1
- package/dist/cli/utils/manifest.d.ts.map +0 -1
- package/dist/cli/utils/manifest.js.map +0 -1
- package/dist/cli/utils/node-modules.d.ts +0 -6
- package/dist/cli/utils/node-modules.d.ts.map +0 -1
- package/dist/cli/utils/node-modules.js +0 -31
- package/dist/cli/utils/node-modules.js.map +0 -1
- package/dist/cli/utils/prompts.d.ts +0 -34
- package/dist/cli/utils/prompts.d.ts.map +0 -1
- package/dist/cli/utils/prompts.js +0 -93
- package/dist/cli/utils/prompts.js.map +0 -1
- package/dist/cli/utils/symlinks.d.ts +0 -29
- package/dist/cli/utils/symlinks.d.ts.map +0 -1
- package/dist/cli/utils/symlinks.js +0 -181
- package/dist/cli/utils/symlinks.js.map +0 -1
- package/dist/cli/utils/themes.d.ts +0 -101
- package/dist/cli/utils/themes.d.ts.map +0 -1
- package/dist/cli/utils/themes.js +0 -373
- package/dist/cli/utils/themes.js.map +0 -1
- package/dist/cli/utils/themes.test.d.ts +0 -12
- package/dist/cli/utils/themes.test.d.ts.map +0 -1
- package/dist/cli/utils/themes.test.js +0 -147
- package/dist/cli/utils/themes.test.js.map +0 -1
- package/dist/cli/utils/version.d.ts.map +0 -1
- package/dist/cli/utils/version.js.map +0 -1
- package/dist/cli/workspace.test.d.ts +0 -8
- package/dist/cli/workspace.test.d.ts.map +0 -1
- package/dist/cli/workspace.test.js +0 -151
- package/dist/cli/workspace.test.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/jira/jira-epic-creation.d.ts +0 -109
- package/dist/jira/jira-epic-creation.d.ts.map +0 -1
- package/dist/jira/jira-epic-creation.js +0 -253
- package/dist/jira/jira-epic-creation.js.map +0 -1
- package/dist/jira/jira-epic-creation.test.d.ts +0 -16
- package/dist/jira/jira-epic-creation.test.d.ts.map +0 -1
- package/dist/jira/jira-epic-creation.test.js +0 -387
- package/dist/jira/jira-epic-creation.test.js.map +0 -1
- package/dist/jira/jira-sprint-sync.d.ts +0 -247
- package/dist/jira/jira-sprint-sync.d.ts.map +0 -1
- package/dist/jira/jira-sprint-sync.js +0 -670
- package/dist/jira/jira-sprint-sync.js.map +0 -1
- package/dist/jira/jira-sprint-sync.test.d.ts +0 -16
- package/dist/jira/jira-sprint-sync.test.d.ts.map +0 -1
- package/dist/jira/jira-sprint-sync.test.js +0 -845
- package/dist/jira/jira-sprint-sync.test.js.map +0 -1
- package/dist/permissions/index.d.ts.map +0 -1
- package/dist/permissions/index.js.map +0 -1
- package/dist/permissions/permission-schema.d.ts.map +0 -1
- package/dist/permissions/permission-schema.js.map +0 -1
- package/dist/permissions/permission-schema.test.d.ts +0 -40
- package/dist/permissions/permission-schema.test.d.ts.map +0 -1
- package/dist/permissions/permission-schema.test.js +0 -367
- package/dist/permissions/permission-schema.test.js.map +0 -1
- package/dist/scripts/add-ocean-profiles.d.ts +0 -9
- package/dist/scripts/add-ocean-profiles.d.ts.map +0 -1
- package/dist/scripts/add-ocean-profiles.js +0 -695
- package/dist/scripts/add-ocean-profiles.js.map +0 -1
- package/dist/scripts/benchmark-integration.d.ts +0 -182
- package/dist/scripts/benchmark-integration.d.ts.map +0 -1
- package/dist/scripts/benchmark-integration.js +0 -691
- package/dist/scripts/benchmark-integration.js.map +0 -1
- package/dist/scripts/benchmark-integration.test.d.ts +0 -13
- package/dist/scripts/benchmark-integration.test.d.ts.map +0 -1
- package/dist/scripts/benchmark-integration.test.js +0 -680
- package/dist/scripts/benchmark-integration.test.js.map +0 -1
- package/dist/scripts/debugging-scenarios.test.d.ts +0 -18
- package/dist/scripts/debugging-scenarios.test.d.ts.map +0 -1
- package/dist/scripts/debugging-scenarios.test.js +0 -317
- package/dist/scripts/debugging-scenarios.test.js.map +0 -1
- package/dist/scripts/generate-all-spiders.d.ts +0 -10
- package/dist/scripts/generate-all-spiders.d.ts.map +0 -1
- package/dist/scripts/generate-all-spiders.js +0 -306
- package/dist/scripts/generate-all-spiders.js.map +0 -1
- package/dist/scripts/generate-report.d.ts +0 -65
- package/dist/scripts/generate-report.d.ts.map +0 -1
- package/dist/scripts/generate-report.js +0 -378
- package/dist/scripts/generate-report.js.map +0 -1
- package/dist/scripts/generate-report.test.d.ts +0 -13
- package/dist/scripts/generate-report.test.d.ts.map +0 -1
- package/dist/scripts/generate-report.test.js +0 -363
- package/dist/scripts/generate-report.test.js.map +0 -1
- package/dist/scripts/generate-spider-report.d.ts +0 -65
- package/dist/scripts/generate-spider-report.d.ts.map +0 -1
- package/dist/scripts/generate-spider-report.js +0 -366
- package/dist/scripts/generate-spider-report.js.map +0 -1
- package/dist/scripts/generate-spider-report.test.d.ts +0 -13
- package/dist/scripts/generate-spider-report.test.d.ts.map +0 -1
- package/dist/scripts/generate-spider-report.test.js +0 -367
- package/dist/scripts/generate-spider-report.test.js.map +0 -1
- package/dist/scripts/generate-spider.d.ts +0 -47
- package/dist/scripts/generate-spider.d.ts.map +0 -1
- package/dist/scripts/generate-spider.js +0 -338
- package/dist/scripts/generate-spider.js.map +0 -1
- package/dist/scripts/generate-spider.test.d.ts +0 -14
- package/dist/scripts/generate-spider.test.d.ts.map +0 -1
- package/dist/scripts/generate-spider.test.js +0 -271
- package/dist/scripts/generate-spider.test.js.map +0 -1
- package/dist/scripts/job-fair-aggregator.d.ts.map +0 -1
- package/dist/scripts/job-fair-aggregator.js.map +0 -1
- package/dist/scripts/job-fair-aggregator.test.d.ts +0 -14
- package/dist/scripts/job-fair-aggregator.test.d.ts.map +0 -1
- package/dist/scripts/job-fair-aggregator.test.js +0 -616
- package/dist/scripts/job-fair-aggregator.test.js.map +0 -1
- package/dist/scripts/run-ci.test.d.ts +0 -20
- package/dist/scripts/run-ci.test.d.ts.map +0 -1
- package/dist/scripts/run-ci.test.js +0 -127
- package/dist/scripts/run-ci.test.js.map +0 -1
- package/dist/scripts/theme-detail.test.d.ts +0 -10
- package/dist/scripts/theme-detail.test.d.ts.map +0 -1
- package/dist/scripts/theme-detail.test.js +0 -199
- package/dist/scripts/theme-detail.test.js.map +0 -1
- package/dist/scripts/validate-ocean-profiles.d.ts +0 -9
- package/dist/scripts/validate-ocean-profiles.d.ts.map +0 -1
- package/dist/scripts/validate-ocean-profiles.js +0 -130
- package/dist/scripts/validate-ocean-profiles.js.map +0 -1
- package/dist/workflow/gate-handler.d.ts +0 -94
- package/dist/workflow/gate-handler.d.ts.map +0 -1
- package/dist/workflow/gate-handler.js +0 -189
- package/dist/workflow/gate-handler.js.map +0 -1
- package/dist/workflow/gate-handler.test.d.ts +0 -14
- package/dist/workflow/gate-handler.test.d.ts.map +0 -1
- package/dist/workflow/gate-handler.test.js +0 -543
- package/dist/workflow/gate-handler.test.js.map +0 -1
- package/dist/workflow/generic-handoff.d.ts +0 -281
- package/dist/workflow/generic-handoff.d.ts.map +0 -1
- package/dist/workflow/generic-handoff.js +0 -411
- package/dist/workflow/generic-handoff.js.map +0 -1
- package/dist/workflow/generic-handoff.test.d.ts +0 -21
- package/dist/workflow/generic-handoff.test.d.ts.map +0 -1
- package/dist/workflow/generic-handoff.test.js +0 -499
- package/dist/workflow/generic-handoff.test.js.map +0 -1
- package/dist/workflow/generic-sm-finish.d.ts +0 -89
- package/dist/workflow/generic-sm-finish.d.ts.map +0 -1
- package/dist/workflow/generic-sm-finish.js +0 -157
- package/dist/workflow/generic-sm-finish.js.map +0 -1
- package/dist/workflow/generic-sm-setup.d.ts +0 -138
- package/dist/workflow/generic-sm-setup.d.ts.map +0 -1
- package/dist/workflow/generic-sm-setup.js +0 -382
- package/dist/workflow/generic-sm-setup.js.map +0 -1
- package/dist/workflow/index.d.ts.map +0 -1
- package/dist/workflow/index.js.map +0 -1
- package/dist/workflow/session-state.d.ts +0 -92
- package/dist/workflow/session-state.d.ts.map +0 -1
- package/dist/workflow/session-state.js +0 -198
- package/dist/workflow/session-state.js.map +0 -1
- package/dist/workflow/session-state.test.d.ts +0 -8
- package/dist/workflow/session-state.test.d.ts.map +0 -1
- package/dist/workflow/session-state.test.js +0 -551
- package/dist/workflow/session-state.test.js.map +0 -1
- package/dist/workflow/sm-subagents.test.d.ts +0 -23
- package/dist/workflow/sm-subagents.test.d.ts.map +0 -1
- package/dist/workflow/sm-subagents.test.js +0 -727
- package/dist/workflow/sm-subagents.test.js.map +0 -1
- package/dist/workflow/step-parser.d.ts +0 -45
- package/dist/workflow/step-parser.d.ts.map +0 -1
- package/dist/workflow/step-parser.js +0 -147
- package/dist/workflow/step-parser.js.map +0 -1
- package/dist/workflow/step-parser.test.d.ts +0 -14
- package/dist/workflow/step-parser.test.d.ts.map +0 -1
- package/dist/workflow/step-parser.test.js +0 -470
- package/dist/workflow/step-parser.test.js.map +0 -1
- package/dist/workflow/story-workflow-routing.test.d.ts +0 -17
- package/dist/workflow/story-workflow-routing.test.d.ts.map +0 -1
- package/dist/workflow/story-workflow-routing.test.js +0 -559
- package/dist/workflow/story-workflow-routing.test.js.map +0 -1
- package/dist/workflow/test-cache.d.ts +0 -131
- package/dist/workflow/test-cache.d.ts.map +0 -1
- package/dist/workflow/test-cache.js +0 -226
- package/dist/workflow/test-cache.js.map +0 -1
- package/dist/workflow/test-cache.test.d.ts +0 -17
- package/dist/workflow/test-cache.test.d.ts.map +0 -1
- package/dist/workflow/test-cache.test.js +0 -438
- package/dist/workflow/test-cache.test.js.map +0 -1
- package/dist/workflow/trimodal.d.ts +0 -86
- package/dist/workflow/trimodal.d.ts.map +0 -1
- package/dist/workflow/trimodal.js +0 -118
- package/dist/workflow/trimodal.js.map +0 -1
- package/dist/workflow/trimodal.test.d.ts +0 -11
- package/dist/workflow/trimodal.test.d.ts.map +0 -1
- package/dist/workflow/trimodal.test.js +0 -395
- package/dist/workflow/trimodal.test.js.map +0 -1
- package/dist/workflow/variable-resolver.d.ts +0 -67
- package/dist/workflow/variable-resolver.d.ts.map +0 -1
- package/dist/workflow/variable-resolver.js +0 -156
- package/dist/workflow/variable-resolver.js.map +0 -1
- package/dist/workflow/variable-resolver.test.d.ts +0 -14
- package/dist/workflow/variable-resolver.test.d.ts.map +0 -1
- package/dist/workflow/variable-resolver.test.js +0 -400
- package/dist/workflow/variable-resolver.test.js.map +0 -1
- package/dist/workflow/workflow-executor.d.ts +0 -163
- package/dist/workflow/workflow-executor.d.ts.map +0 -1
- package/dist/workflow/workflow-executor.js +0 -197
- package/dist/workflow/workflow-executor.js.map +0 -1
- package/dist/workflow/workflow-executor.test.d.ts +0 -8
- package/dist/workflow/workflow-executor.test.d.ts.map +0 -1
- package/dist/workflow/workflow-executor.test.js +0 -444
- package/dist/workflow/workflow-executor.test.js.map +0 -1
- package/dist/workflow/workflow-loader.d.ts.map +0 -1
- package/dist/workflow/workflow-loader.js.map +0 -1
- package/dist/workflow/workflow-loader.test.d.ts +0 -15
- package/dist/workflow/workflow-loader.test.d.ts.map +0 -1
- package/dist/workflow/workflow-loader.test.js +0 -354
- package/dist/workflow/workflow-loader.test.js.map +0 -1
- package/dist/workflow/workflow-migration.test.d.ts +0 -17
- package/dist/workflow/workflow-migration.test.d.ts.map +0 -1
- package/dist/workflow/workflow-migration.test.js +0 -371
- package/dist/workflow/workflow-migration.test.js.map +0 -1
- package/dist/workflow/workflow-permissions.d.ts.map +0 -1
- package/dist/workflow/workflow-permissions.js.map +0 -1
- package/dist/workflow/workflow-permissions.test.d.ts +0 -15
- package/dist/workflow/workflow-permissions.test.d.ts.map +0 -1
- package/dist/workflow/workflow-permissions.test.js +0 -301
- package/dist/workflow/workflow-permissions.test.js.map +0 -1
- package/dist/workflow/workflow-router.d.ts.map +0 -1
- package/dist/workflow/workflow-router.js.map +0 -1
- package/dist/workflow/workflow-router.test.d.ts +0 -20
- package/dist/workflow/workflow-router.test.d.ts.map +0 -1
- package/dist/workflow/workflow-router.test.js +0 -607
- package/dist/workflow/workflow-router.test.js.map +0 -1
- package/dist/workflow/workflow-schema.d.ts.map +0 -1
- package/dist/workflow/workflow-schema.js.map +0 -1
- package/dist/workflow/workflow-schema.test.d.ts +0 -45
- package/dist/workflow/workflow-schema.test.d.ts.map +0 -1
- package/dist/workflow/workflow-schema.test.js +0 -512
- package/dist/workflow/workflow-schema.test.js.map +0 -1
- package/dist/workflow/workflow-stepped-schema.test.d.ts +0 -18
- package/dist/workflow/workflow-stepped-schema.test.d.ts.map +0 -1
- package/dist/workflow/workflow-stepped-schema.test.js +0 -608
- package/dist/workflow/workflow-stepped-schema.test.js.map +0 -1
|
@@ -1,691 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Benchmark Integration Module
|
|
3
|
-
*
|
|
4
|
-
* Story 11-8: Integrate with Benchmark Output
|
|
5
|
-
* Story 12-6: Update for local results (Epic 12 migration)
|
|
6
|
-
*
|
|
7
|
-
* Correlates Chernoff faces and OCEAN profiles with benchmark performance data.
|
|
8
|
-
* Reads benchmark results from internal/results/ directory (or BENCHMARK_PATH env var).
|
|
9
|
-
*/
|
|
10
|
-
import { readdirSync, readFileSync, existsSync } from 'fs';
|
|
11
|
-
import { join, dirname } from 'path';
|
|
12
|
-
import { fileURLToPath } from 'url';
|
|
13
|
-
import { parse as parseYaml } from 'yaml';
|
|
14
|
-
import { findMonorepoRoot } from '../cli/utils/files.js';
|
|
15
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
-
const __dirname = dirname(__filename);
|
|
17
|
-
// Find monorepo root by walking up from current directory
|
|
18
|
-
const projectRoot = findMonorepoRoot(__dirname);
|
|
19
|
-
const themesDir = join(projectRoot, 'pennyfarthing-dist', 'personas', 'themes');
|
|
20
|
-
const _facesDir = join(projectRoot, 'pennyfarthing-dist', 'personas', 'faces');
|
|
21
|
-
// Benchmark results location
|
|
22
|
-
// Configurable via BENCHMARK_PATH environment variable
|
|
23
|
-
// Defaults to internal/results/benchmarks/ directory (dev-only, excluded from npm)
|
|
24
|
-
const benchmarksDir = process.env.BENCHMARK_PATH
|
|
25
|
-
? join(process.env.BENCHMARK_PATH, 'benchmarks')
|
|
26
|
-
: join(projectRoot, 'internal', 'results', 'benchmarks');
|
|
27
|
-
// ============================================================================
|
|
28
|
-
// Constants
|
|
29
|
-
// ============================================================================
|
|
30
|
-
const VALID_ROLES = [
|
|
31
|
-
'orchestrator', 'sm', 'tea', 'dev', 'reviewer',
|
|
32
|
-
'architect', 'pm', 'tech-writer', 'ux-designer', 'devops',
|
|
33
|
-
];
|
|
34
|
-
const VALID_DIMENSIONS = ['O', 'C', 'E', 'A', 'N'];
|
|
35
|
-
// ============================================================================
|
|
36
|
-
// Helper Functions
|
|
37
|
-
// ============================================================================
|
|
38
|
-
/**
|
|
39
|
-
* Load theme YAML data
|
|
40
|
-
*/
|
|
41
|
-
function loadThemeData(theme) {
|
|
42
|
-
const themePath = join(themesDir, `${theme}.yaml`);
|
|
43
|
-
if (!existsSync(themePath)) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
const content = readFileSync(themePath, 'utf-8');
|
|
47
|
-
return parseYaml(content);
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Get character info from theme data
|
|
51
|
-
*/
|
|
52
|
-
function getCharacterInfo(theme, role) {
|
|
53
|
-
const data = loadThemeData(theme);
|
|
54
|
-
if (!data)
|
|
55
|
-
return null;
|
|
56
|
-
const agents = data.agents;
|
|
57
|
-
if (!agents || !agents[role])
|
|
58
|
-
return null;
|
|
59
|
-
const agentData = agents[role];
|
|
60
|
-
const ocean = agentData.ocean;
|
|
61
|
-
if (!ocean)
|
|
62
|
-
return null;
|
|
63
|
-
return {
|
|
64
|
-
character: agentData.character || role,
|
|
65
|
-
ocean: {
|
|
66
|
-
O: ocean.O,
|
|
67
|
-
C: ocean.C,
|
|
68
|
-
E: ocean.E,
|
|
69
|
-
A: ocean.A,
|
|
70
|
-
N: ocean.N,
|
|
71
|
-
},
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Get face SVG path for a character
|
|
76
|
-
*/
|
|
77
|
-
function getFacePath(theme, role) {
|
|
78
|
-
return `by-theme/${theme}/${role}.svg`;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Load benchmark summary from thunderdome
|
|
82
|
-
*/
|
|
83
|
-
function loadBenchmarkSummary(scenario, theme, role) {
|
|
84
|
-
const benchmarkPath = join(benchmarksDir, scenario, `${theme}-${role}`, 'summary.yaml');
|
|
85
|
-
if (!existsSync(benchmarkPath)) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
try {
|
|
89
|
-
const content = readFileSync(benchmarkPath, 'utf-8');
|
|
90
|
-
const data = parseYaml(content);
|
|
91
|
-
const stats = data.statistics;
|
|
92
|
-
const baseline = data.baseline_comparison;
|
|
93
|
-
return {
|
|
94
|
-
mean: stats.mean,
|
|
95
|
-
stdDev: stats.std_dev,
|
|
96
|
-
delta: baseline ? parseFloat(String(baseline.delta).replace('+', '')) : 0,
|
|
97
|
-
n: stats.n,
|
|
98
|
-
scores: stats.scores || [],
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Get all available scenarios
|
|
107
|
-
*/
|
|
108
|
-
function getAvailableScenarios() {
|
|
109
|
-
if (!existsSync(benchmarksDir)) {
|
|
110
|
-
return [];
|
|
111
|
-
}
|
|
112
|
-
return readdirSync(benchmarksDir).filter(f => {
|
|
113
|
-
// Skip hidden files and .gitkeep
|
|
114
|
-
if (f.startsWith('.'))
|
|
115
|
-
return false;
|
|
116
|
-
const fullPath = join(benchmarksDir, f);
|
|
117
|
-
try {
|
|
118
|
-
const entries = readdirSync(fullPath);
|
|
119
|
-
return entries.length > 0;
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
// Not a directory
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Get all benchmarked themes for a scenario/role
|
|
129
|
-
*/
|
|
130
|
-
function getBenchmarkedThemes(scenario, role) {
|
|
131
|
-
const scenarioPath = join(benchmarksDir, scenario);
|
|
132
|
-
if (!existsSync(scenarioPath)) {
|
|
133
|
-
return [];
|
|
134
|
-
}
|
|
135
|
-
const dirs = readdirSync(scenarioPath);
|
|
136
|
-
return dirs
|
|
137
|
-
.filter(d => d.endsWith(`-${role}`))
|
|
138
|
-
.map(d => d.replace(`-${role}`, ''));
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Parse OCEAN filter expression
|
|
142
|
-
*/
|
|
143
|
-
function parseOceanFilter(expr) {
|
|
144
|
-
const match = expr.match(/^([OCEAN])(>=|<=|=|>|<)(\d+)$/);
|
|
145
|
-
if (!match) {
|
|
146
|
-
const dimMatch = expr.match(/^([A-Z])/);
|
|
147
|
-
if (dimMatch && !VALID_DIMENSIONS.includes(dimMatch[1])) {
|
|
148
|
-
throw new Error(`Invalid OCEAN dimension: ${dimMatch[1]}. Valid dimensions are O, C, E, A, N`);
|
|
149
|
-
}
|
|
150
|
-
throw new Error(`Invalid OCEAN filter format: ${expr}`);
|
|
151
|
-
}
|
|
152
|
-
return {
|
|
153
|
-
dimension: match[1],
|
|
154
|
-
operator: match[2],
|
|
155
|
-
value: parseInt(match[3], 10),
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Check if OCEAN scores match filter
|
|
160
|
-
*/
|
|
161
|
-
function matchesOceanFilter(ocean, filter) {
|
|
162
|
-
const score = ocean[filter.dimension];
|
|
163
|
-
switch (filter.operator) {
|
|
164
|
-
case '>=': return score >= filter.value;
|
|
165
|
-
case '<=': return score <= filter.value;
|
|
166
|
-
case '=': return score === filter.value;
|
|
167
|
-
case '>': return score > filter.value;
|
|
168
|
-
case '<': return score < filter.value;
|
|
169
|
-
default: return false;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Calculate average OCEAN scores from a set of results
|
|
174
|
-
*/
|
|
175
|
-
function calculateAverageOcean(results) {
|
|
176
|
-
if (results.length === 0) {
|
|
177
|
-
return { O: 3, C: 3, E: 3, A: 3, N: 3 };
|
|
178
|
-
}
|
|
179
|
-
const sum = { O: 0, C: 0, E: 0, A: 0, N: 0 };
|
|
180
|
-
for (const r of results) {
|
|
181
|
-
sum.O += r.ocean.O;
|
|
182
|
-
sum.C += r.ocean.C;
|
|
183
|
-
sum.E += r.ocean.E;
|
|
184
|
-
sum.A += r.ocean.A;
|
|
185
|
-
sum.N += r.ocean.N;
|
|
186
|
-
}
|
|
187
|
-
return {
|
|
188
|
-
O: Math.round(sum.O / results.length),
|
|
189
|
-
C: Math.round(sum.C / results.length),
|
|
190
|
-
E: Math.round(sum.E / results.length),
|
|
191
|
-
A: Math.round(sum.A / results.length),
|
|
192
|
-
N: Math.round(sum.N / results.length),
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Calculate correlation effect between OCEAN dimension and performance
|
|
197
|
-
*/
|
|
198
|
-
function calculateDimensionEffect(results, dimension) {
|
|
199
|
-
if (results.length < 2) {
|
|
200
|
-
return { effect: 0, direction: 'none' };
|
|
201
|
-
}
|
|
202
|
-
// Group by low (1-2), medium (3), high (4-5)
|
|
203
|
-
const low = results.filter(r => r.ocean[dimension] <= 2);
|
|
204
|
-
const high = results.filter(r => r.ocean[dimension] >= 4);
|
|
205
|
-
if (low.length === 0 || high.length === 0) {
|
|
206
|
-
return { effect: 0, direction: 'none' };
|
|
207
|
-
}
|
|
208
|
-
const lowMean = low.reduce((sum, r) => sum + r.mean, 0) / low.length;
|
|
209
|
-
const highMean = high.reduce((sum, r) => sum + r.mean, 0) / high.length;
|
|
210
|
-
const effect = Math.abs(highMean - lowMean);
|
|
211
|
-
const direction = highMean > lowMean ? 'positive' : highMean < lowMean ? 'negative' : 'none';
|
|
212
|
-
return { effect: Math.round(effect * 100) / 100, direction };
|
|
213
|
-
}
|
|
214
|
-
// ============================================================================
|
|
215
|
-
// Exported Functions
|
|
216
|
-
// ============================================================================
|
|
217
|
-
/**
|
|
218
|
-
* Load benchmark data from thunderdome results
|
|
219
|
-
*/
|
|
220
|
-
export function loadBenchmarkData(scenario, role) {
|
|
221
|
-
const themes = getBenchmarkedThemes(scenario, role);
|
|
222
|
-
const results = [];
|
|
223
|
-
for (const theme of themes) {
|
|
224
|
-
const benchmark = loadBenchmarkSummary(scenario, theme, role);
|
|
225
|
-
const charInfo = getCharacterInfo(theme, role);
|
|
226
|
-
if (benchmark && charInfo) {
|
|
227
|
-
results.push({
|
|
228
|
-
theme,
|
|
229
|
-
role,
|
|
230
|
-
character: charInfo.character,
|
|
231
|
-
scenario,
|
|
232
|
-
mean: benchmark.mean,
|
|
233
|
-
stdDev: benchmark.stdDev,
|
|
234
|
-
delta: benchmark.delta,
|
|
235
|
-
n: benchmark.n,
|
|
236
|
-
scores: benchmark.scores,
|
|
237
|
-
ocean: charInfo.ocean,
|
|
238
|
-
face: getFacePath(theme, role),
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
return results.sort((a, b) => b.mean - a.mean);
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Get benchmark result with face visualization attached
|
|
246
|
-
*/
|
|
247
|
-
export function getBenchmarkWithFace(theme, role, scenario) {
|
|
248
|
-
const benchmark = loadBenchmarkSummary(scenario, theme, role);
|
|
249
|
-
const charInfo = getCharacterInfo(theme, role);
|
|
250
|
-
if (!benchmark) {
|
|
251
|
-
if (charInfo) {
|
|
252
|
-
// Theme exists but no benchmark data
|
|
253
|
-
return {
|
|
254
|
-
theme,
|
|
255
|
-
role,
|
|
256
|
-
character: charInfo.character,
|
|
257
|
-
scenario,
|
|
258
|
-
mean: 0,
|
|
259
|
-
stdDev: 0,
|
|
260
|
-
delta: 0,
|
|
261
|
-
n: 0,
|
|
262
|
-
scores: [],
|
|
263
|
-
ocean: charInfo.ocean,
|
|
264
|
-
face: getFacePath(theme, role),
|
|
265
|
-
benchmarkMissing: true,
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
return null;
|
|
269
|
-
}
|
|
270
|
-
if (!charInfo) {
|
|
271
|
-
return null;
|
|
272
|
-
}
|
|
273
|
-
return {
|
|
274
|
-
theme,
|
|
275
|
-
role,
|
|
276
|
-
character: charInfo.character,
|
|
277
|
-
scenario,
|
|
278
|
-
mean: benchmark.mean,
|
|
279
|
-
stdDev: benchmark.stdDev,
|
|
280
|
-
delta: benchmark.delta,
|
|
281
|
-
n: benchmark.n,
|
|
282
|
-
scores: benchmark.scores,
|
|
283
|
-
ocean: charInfo.ocean,
|
|
284
|
-
face: getFacePath(theme, role),
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Calculate OCEAN correlation with benchmark performance
|
|
289
|
-
*/
|
|
290
|
-
export function calculateOceanCorrelation(scenario, role) {
|
|
291
|
-
const results = loadBenchmarkData(scenario, role);
|
|
292
|
-
const correlations = {
|
|
293
|
-
O: calculateDimensionEffect(results, 'O'),
|
|
294
|
-
C: calculateDimensionEffect(results, 'C'),
|
|
295
|
-
E: calculateDimensionEffect(results, 'E'),
|
|
296
|
-
A: calculateDimensionEffect(results, 'A'),
|
|
297
|
-
N: calculateDimensionEffect(results, 'N'),
|
|
298
|
-
strongest: { dimension: 'O', effect: 0 },
|
|
299
|
-
};
|
|
300
|
-
// Find strongest correlation
|
|
301
|
-
let maxEffect = 0;
|
|
302
|
-
let strongestDim = 'O';
|
|
303
|
-
for (const dim of VALID_DIMENSIONS) {
|
|
304
|
-
if (correlations[dim].effect > maxEffect) {
|
|
305
|
-
maxEffect = correlations[dim].effect;
|
|
306
|
-
strongestDim = dim;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
correlations.strongest = { dimension: strongestDim, effect: maxEffect };
|
|
310
|
-
return correlations;
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* Generate markdown correlation report
|
|
314
|
-
*/
|
|
315
|
-
export function generateCorrelationReport(scenario, role) {
|
|
316
|
-
const correlation = calculateOceanCorrelation(scenario, role);
|
|
317
|
-
const results = loadBenchmarkData(scenario, role);
|
|
318
|
-
let md = `# OCEAN Correlation Report: ${role} on ${scenario}\n\n`;
|
|
319
|
-
md += '## Dimension Effects\n\n';
|
|
320
|
-
md += '| Dimension | Effect Size | Direction | Delta Impact |\n';
|
|
321
|
-
md += '|:----------|:-----------:|:---------:|:------------:|\n';
|
|
322
|
-
for (const dim of VALID_DIMENSIONS) {
|
|
323
|
-
const c = correlation[dim];
|
|
324
|
-
const arrow = c.direction === 'positive' ? '↑' : c.direction === 'negative' ? '↓' : '—';
|
|
325
|
-
const deltaStr = c.direction === 'positive' ? `+${c.effect}` : c.direction === 'negative' ? `-${c.effect}` : '0';
|
|
326
|
-
md += `| **${dim}** | ${c.effect.toFixed(2)} | ${arrow} ${c.direction} | ${deltaStr} pts |\n`;
|
|
327
|
-
}
|
|
328
|
-
md += `\n## Strongest Correlation\n\n`;
|
|
329
|
-
md += `**${correlation.strongest.dimension}** has the largest effect (${correlation.strongest.effect.toFixed(2)} points).\n\n`;
|
|
330
|
-
if (results.length > 0) {
|
|
331
|
-
md += `## Top Performers\n\n`;
|
|
332
|
-
const top3 = results.slice(0, 3);
|
|
333
|
-
for (const r of top3) {
|
|
334
|
-
md += `- **${r.character}** (${r.theme}): ${r.mean} pts (delta: +${r.delta})\n`;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
return md;
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* Get optimal OCEAN profile for a role based on benchmark data
|
|
341
|
-
*/
|
|
342
|
-
export function getOptimalProfile(role) {
|
|
343
|
-
if (!VALID_ROLES.includes(role)) {
|
|
344
|
-
throw new Error(`Invalid role: ${role}. Valid roles are: ${VALID_ROLES.join(', ')}`);
|
|
345
|
-
}
|
|
346
|
-
// Find scenarios that have this role benchmarked
|
|
347
|
-
const scenarios = getAvailableScenarios();
|
|
348
|
-
const allResults = [];
|
|
349
|
-
for (const scenario of scenarios) {
|
|
350
|
-
const results = loadBenchmarkData(scenario, role);
|
|
351
|
-
allResults.push(...results);
|
|
352
|
-
}
|
|
353
|
-
if (allResults.length === 0) {
|
|
354
|
-
// Return balanced profile if no data
|
|
355
|
-
return {
|
|
356
|
-
ocean: { O: 3, C: 3, E: 3, A: 3, N: 3 },
|
|
357
|
-
reasoning: `No benchmark data available for ${role} role. Returning balanced profile.`,
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
// Get top performers (top 25%)
|
|
361
|
-
allResults.sort((a, b) => b.mean - a.mean);
|
|
362
|
-
const topCount = Math.max(1, Math.floor(allResults.length * 0.25));
|
|
363
|
-
const topPerformers = allResults.slice(0, topCount);
|
|
364
|
-
const optimalOcean = calculateAverageOcean(topPerformers);
|
|
365
|
-
const topNames = topPerformers.slice(0, 3).map(r => r.character).join(', ');
|
|
366
|
-
return {
|
|
367
|
-
ocean: optimalOcean,
|
|
368
|
-
reasoning: `Based on ${topCount} top performers (${topNames}). Profile reflects OCEAN averages of highest-scoring personas.`,
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
/**
|
|
372
|
-
* Get role recommendations (top themes, themes to avoid)
|
|
373
|
-
*/
|
|
374
|
-
export function getRoleRecommendations(role) {
|
|
375
|
-
if (!VALID_ROLES.includes(role)) {
|
|
376
|
-
throw new Error(`Invalid role: ${role}. Valid roles are: ${VALID_ROLES.join(', ')}`);
|
|
377
|
-
}
|
|
378
|
-
const scenarios = getAvailableScenarios();
|
|
379
|
-
const allResults = [];
|
|
380
|
-
for (const scenario of scenarios) {
|
|
381
|
-
const results = loadBenchmarkData(scenario, role);
|
|
382
|
-
allResults.push(...results);
|
|
383
|
-
}
|
|
384
|
-
if (allResults.length === 0) {
|
|
385
|
-
return {
|
|
386
|
-
role,
|
|
387
|
-
topThemes: [],
|
|
388
|
-
avoidThemes: [],
|
|
389
|
-
insight: `No benchmark data available for ${role} role.`,
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
// Sort by score
|
|
393
|
-
allResults.sort((a, b) => b.mean - a.mean);
|
|
394
|
-
// Top themes (top 3)
|
|
395
|
-
const topThemes = allResults.slice(0, 3).map(r => ({
|
|
396
|
-
theme: r.theme,
|
|
397
|
-
character: r.character,
|
|
398
|
-
score: r.mean,
|
|
399
|
-
ocean: r.ocean,
|
|
400
|
-
}));
|
|
401
|
-
// Avoid themes (bottom 3)
|
|
402
|
-
const avoidThemes = allResults.slice(-3).reverse().map(r => ({
|
|
403
|
-
theme: r.theme,
|
|
404
|
-
character: r.character,
|
|
405
|
-
score: r.mean,
|
|
406
|
-
}));
|
|
407
|
-
// Generate insight based on correlation
|
|
408
|
-
const correlation = calculateOceanCorrelation(scenarios[0] || 'race-condition-cache', role);
|
|
409
|
-
let insight = `For ${role} role: `;
|
|
410
|
-
if (correlation.strongest.effect > 0) {
|
|
411
|
-
const dir = correlation[correlation.strongest.dimension].direction;
|
|
412
|
-
insight += `${dir === 'negative' ? 'Low' : 'High'} ${correlation.strongest.dimension} correlates with +${correlation.strongest.effect.toFixed(1)} points improvement. `;
|
|
413
|
-
}
|
|
414
|
-
if (topThemes.length > 0) {
|
|
415
|
-
insight += `Top performer: ${topThemes[0].character} (${topThemes[0].theme}) at ${topThemes[0].score} pts.`;
|
|
416
|
-
}
|
|
417
|
-
return {
|
|
418
|
-
role,
|
|
419
|
-
topThemes,
|
|
420
|
-
avoidThemes,
|
|
421
|
-
insight,
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
/**
|
|
425
|
-
* Find top performers for a scenario/role with optional filters
|
|
426
|
-
*/
|
|
427
|
-
export function findTopPerformers(options) {
|
|
428
|
-
const { scenario, role, ocean, limit, minScore } = options;
|
|
429
|
-
if (!scenario || !role) {
|
|
430
|
-
return [];
|
|
431
|
-
}
|
|
432
|
-
let results = loadBenchmarkData(scenario, role);
|
|
433
|
-
// Apply OCEAN filter if provided
|
|
434
|
-
if (ocean) {
|
|
435
|
-
const filter = parseOceanFilter(ocean);
|
|
436
|
-
results = results.filter(r => matchesOceanFilter(r.ocean, filter));
|
|
437
|
-
}
|
|
438
|
-
// Apply minimum score filter
|
|
439
|
-
if (minScore !== undefined) {
|
|
440
|
-
results = results.filter(r => r.mean >= minScore);
|
|
441
|
-
}
|
|
442
|
-
// Convert to PerformerResult format
|
|
443
|
-
let performers = results.map(r => ({
|
|
444
|
-
theme: r.theme,
|
|
445
|
-
character: r.character,
|
|
446
|
-
score: r.mean,
|
|
447
|
-
delta: r.delta,
|
|
448
|
-
ocean: r.ocean,
|
|
449
|
-
face: r.face,
|
|
450
|
-
}));
|
|
451
|
-
// Sort by score (already sorted, but ensure)
|
|
452
|
-
performers.sort((a, b) => b.score - a.score);
|
|
453
|
-
// Apply limit
|
|
454
|
-
if (limit !== undefined && limit > 0) {
|
|
455
|
-
performers = performers.slice(0, limit);
|
|
456
|
-
}
|
|
457
|
-
return performers;
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* General query interface for benchmark data
|
|
461
|
-
*/
|
|
462
|
-
export function queryBenchmarks(options) {
|
|
463
|
-
const { scenario, role, filter, ocean, limit, sortBy } = options;
|
|
464
|
-
if (!scenario || !role) {
|
|
465
|
-
return [];
|
|
466
|
-
}
|
|
467
|
-
let results = loadBenchmarkData(scenario, role);
|
|
468
|
-
// Apply OCEAN filter from 'ocean' or 'filter' option
|
|
469
|
-
const oceanFilter = ocean || filter;
|
|
470
|
-
if (oceanFilter) {
|
|
471
|
-
const parsed = parseOceanFilter(oceanFilter);
|
|
472
|
-
results = results.filter(r => matchesOceanFilter(r.ocean, parsed));
|
|
473
|
-
}
|
|
474
|
-
// Convert to PerformerResult
|
|
475
|
-
let performers = results.map(r => ({
|
|
476
|
-
theme: r.theme,
|
|
477
|
-
character: r.character,
|
|
478
|
-
score: r.mean,
|
|
479
|
-
delta: r.delta,
|
|
480
|
-
ocean: r.ocean,
|
|
481
|
-
face: r.face,
|
|
482
|
-
}));
|
|
483
|
-
// Sort
|
|
484
|
-
switch (sortBy) {
|
|
485
|
-
case 'delta':
|
|
486
|
-
performers.sort((a, b) => b.delta - a.delta);
|
|
487
|
-
break;
|
|
488
|
-
case 'name':
|
|
489
|
-
performers.sort((a, b) => a.theme.localeCompare(b.theme));
|
|
490
|
-
break;
|
|
491
|
-
case 'score':
|
|
492
|
-
default:
|
|
493
|
-
performers.sort((a, b) => b.score - a.score);
|
|
494
|
-
}
|
|
495
|
-
// Apply limit
|
|
496
|
-
if (limit !== undefined && limit > 0) {
|
|
497
|
-
performers = performers.slice(0, limit);
|
|
498
|
-
}
|
|
499
|
-
return performers;
|
|
500
|
-
}
|
|
501
|
-
// ============================================================================
|
|
502
|
-
// Story 14-5: OCEAN × Error-Type Correlation Functions
|
|
503
|
-
// ============================================================================
|
|
504
|
-
const ERROR_TYPES = ['reasoning', 'planning', 'execution'];
|
|
505
|
-
/**
|
|
506
|
-
* Get arrow direction based on correlation value
|
|
507
|
-
* ↑ for positive (≥0.3), ↓ for negative (≤-0.3), → for neutral
|
|
508
|
-
*/
|
|
509
|
-
function getArrow(correlation) {
|
|
510
|
-
if (correlation >= 0.3)
|
|
511
|
-
return '↑';
|
|
512
|
-
if (correlation <= -0.3)
|
|
513
|
-
return '↓';
|
|
514
|
-
return '→';
|
|
515
|
-
}
|
|
516
|
-
/**
|
|
517
|
-
* Calculate correlation between OCEAN dimension and error-type detection rate
|
|
518
|
-
*/
|
|
519
|
-
function calculateErrorDimensionEffect(results, judgeScores, dimension, errorType) {
|
|
520
|
-
// Need at least 2 entries to calculate correlation
|
|
521
|
-
if (results.length < 2 || judgeScores.length < 1) {
|
|
522
|
-
return { correlation: 0, arrow: '→' };
|
|
523
|
-
}
|
|
524
|
-
// Pair results with judge scores (use minimum length)
|
|
525
|
-
const minLen = Math.min(results.length, judgeScores.length);
|
|
526
|
-
const pairs = [];
|
|
527
|
-
for (let i = 0; i < minLen; i++) {
|
|
528
|
-
const result = results[i];
|
|
529
|
-
const judge = judgeScores[i];
|
|
530
|
-
if (result?.ocean && judge?.detection_by_type) {
|
|
531
|
-
pairs.push({
|
|
532
|
-
ocean: result.ocean[dimension],
|
|
533
|
-
detection: judge.detection_by_type[errorType],
|
|
534
|
-
});
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
if (pairs.length < 2) {
|
|
538
|
-
return { correlation: 0, arrow: '→' };
|
|
539
|
-
}
|
|
540
|
-
// Group by low (1-2) and high (4-5) OCEAN values
|
|
541
|
-
const low = pairs.filter(p => p.ocean <= 2);
|
|
542
|
-
const high = pairs.filter(p => p.ocean >= 4);
|
|
543
|
-
if (low.length === 0 || high.length === 0) {
|
|
544
|
-
return { correlation: 0, arrow: '→' };
|
|
545
|
-
}
|
|
546
|
-
// Calculate mean detection rates for low and high groups
|
|
547
|
-
const lowMean = low.reduce((sum, p) => sum + p.detection, 0) / low.length;
|
|
548
|
-
const highMean = high.reduce((sum, p) => sum + p.detection, 0) / high.length;
|
|
549
|
-
// Correlation is the difference (high - low)
|
|
550
|
-
const correlation = Math.round((highMean - lowMean) * 100) / 100;
|
|
551
|
-
return {
|
|
552
|
-
correlation,
|
|
553
|
-
arrow: getArrow(correlation),
|
|
554
|
-
};
|
|
555
|
-
}
|
|
556
|
-
/**
|
|
557
|
-
* Calculate OCEAN × error-type correlation matrix
|
|
558
|
-
* Story 14-5: Correlates OCEAN dimensions with error detection rates
|
|
559
|
-
*/
|
|
560
|
-
export function calculateErrorTypeCorrelation(results, judgeScores) {
|
|
561
|
-
// Default matrix structure - always return valid object
|
|
562
|
-
const matrix = {
|
|
563
|
-
O: { reasoning: { correlation: 0, arrow: '→' }, planning: { correlation: 0, arrow: '→' }, execution: { correlation: 0, arrow: '→' } },
|
|
564
|
-
C: { reasoning: { correlation: 0, arrow: '→' }, planning: { correlation: 0, arrow: '→' }, execution: { correlation: 0, arrow: '→' } },
|
|
565
|
-
E: { reasoning: { correlation: 0, arrow: '→' }, planning: { correlation: 0, arrow: '→' }, execution: { correlation: 0, arrow: '→' } },
|
|
566
|
-
A: { reasoning: { correlation: 0, arrow: '→' }, planning: { correlation: 0, arrow: '→' }, execution: { correlation: 0, arrow: '→' } },
|
|
567
|
-
N: { reasoning: { correlation: 0, arrow: '→' }, planning: { correlation: 0, arrow: '→' }, execution: { correlation: 0, arrow: '→' } },
|
|
568
|
-
};
|
|
569
|
-
// Calculate correlation for each dimension × error type combination
|
|
570
|
-
for (const dim of VALID_DIMENSIONS) {
|
|
571
|
-
for (const errType of ERROR_TYPES) {
|
|
572
|
-
matrix[dim][errType] = calculateErrorDimensionEffect(results, judgeScores, dim, errType);
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
// Find strongest correlation
|
|
576
|
-
let strongest = { dimension: 'O', errorType: 'reasoning', correlation: 0 };
|
|
577
|
-
for (const dim of VALID_DIMENSIONS) {
|
|
578
|
-
for (const errType of ERROR_TYPES) {
|
|
579
|
-
const absCorr = Math.abs(matrix[dim][errType].correlation);
|
|
580
|
-
if (absCorr > Math.abs(strongest.correlation)) {
|
|
581
|
-
strongest = {
|
|
582
|
-
dimension: dim,
|
|
583
|
-
errorType: errType,
|
|
584
|
-
correlation: matrix[dim][errType].correlation,
|
|
585
|
-
};
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
return { matrix, strongest };
|
|
590
|
-
}
|
|
591
|
-
/**
|
|
592
|
-
* Generate markdown heat map for OCEAN × error-type correlations
|
|
593
|
-
* Story 14-5: Produces 5×3 matrix with directional arrows and effect sizes
|
|
594
|
-
*/
|
|
595
|
-
export function generateOceanErrorHeatMap(correlation) {
|
|
596
|
-
const dimensionLabels = {
|
|
597
|
-
O: 'O (Open)',
|
|
598
|
-
C: 'C (Consc)',
|
|
599
|
-
E: 'E (Extra)',
|
|
600
|
-
A: 'A (Agree)',
|
|
601
|
-
N: 'N (Neuro)',
|
|
602
|
-
};
|
|
603
|
-
let md = '## OCEAN × Error-Type Correlation\n\n';
|
|
604
|
-
// Table header
|
|
605
|
-
md += '| | Reasoning | Planning | Execution |\n';
|
|
606
|
-
md += '|-----------|-----------|----------|----------|\n';
|
|
607
|
-
// Table rows
|
|
608
|
-
for (const dim of VALID_DIMENSIONS) {
|
|
609
|
-
const row = correlation.matrix[dim];
|
|
610
|
-
const label = dimensionLabels[dim];
|
|
611
|
-
const reasoning = `${row.reasoning.arrow} ${row.reasoning.correlation.toFixed(2)}`;
|
|
612
|
-
const planning = `${row.planning.arrow} ${row.planning.correlation.toFixed(2)}`;
|
|
613
|
-
const execution = `${row.execution.arrow} ${row.execution.correlation.toFixed(2)}`;
|
|
614
|
-
md += `| ${label} | ${reasoning} | ${planning} | ${execution} |\n`;
|
|
615
|
-
}
|
|
616
|
-
// Legend
|
|
617
|
-
md += '\nLegend: ↑ positive (≥0.3), ↓ negative (≤-0.3), → neutral\n';
|
|
618
|
-
// Strongest correlation callout
|
|
619
|
-
if (correlation.strongest.correlation !== 0) {
|
|
620
|
-
const arrow = getArrow(correlation.strongest.correlation);
|
|
621
|
-
md += `\n**Strongest:** ${correlation.strongest.dimension} × ${correlation.strongest.errorType} `;
|
|
622
|
-
md += `(${arrow} ${correlation.strongest.correlation.toFixed(2)})\n`;
|
|
623
|
-
}
|
|
624
|
-
return md;
|
|
625
|
-
}
|
|
626
|
-
/**
|
|
627
|
-
* Generate complete benchmark report with faces and correlations
|
|
628
|
-
*/
|
|
629
|
-
export function generateBenchmarkReport(options) {
|
|
630
|
-
const { scenario, role, includeErrorTypeCorrelation } = options;
|
|
631
|
-
const performers = findTopPerformers({ scenario, role });
|
|
632
|
-
const correlation = calculateOceanCorrelation(scenario, role);
|
|
633
|
-
const recommendations = getRoleRecommendations(role);
|
|
634
|
-
let md = `# Benchmark Report: ${role} on ${scenario}\n\n`;
|
|
635
|
-
// Top performers with faces
|
|
636
|
-
md += '## Top Performers\n\n';
|
|
637
|
-
md += '| Rank | Theme | Character | Face | Score | Delta | O | C | E | A | N |\n';
|
|
638
|
-
md += '|:----:|:------|:----------|:----:|:-----:|:-----:|:-:|:-:|:-:|:-:|:-:|\n';
|
|
639
|
-
performers.slice(0, 5).forEach((p, i) => {
|
|
640
|
-
md += `| ${i + 1} | ${p.theme} | ${p.character} `;
|
|
641
|
-
md += `| <img src="${p.face}" width="40"> `;
|
|
642
|
-
md += `| ${p.score} | +${p.delta} `;
|
|
643
|
-
md += `| ${p.ocean.O} | ${p.ocean.C} | ${p.ocean.E} | ${p.ocean.A} | ${p.ocean.N} |\n`;
|
|
644
|
-
});
|
|
645
|
-
// Correlation summary
|
|
646
|
-
md += '\n## OCEAN Correlation\n\n';
|
|
647
|
-
md += `Strongest effect: **${correlation.strongest.dimension}** (${correlation.strongest.effect.toFixed(1)} points)\n\n`;
|
|
648
|
-
for (const dim of VALID_DIMENSIONS) {
|
|
649
|
-
const c = correlation[dim];
|
|
650
|
-
if (c.effect > 0) {
|
|
651
|
-
const arrow = c.direction === 'positive' ? '↑' : '↓';
|
|
652
|
-
md += `- **${dim}**: ${arrow} ${c.effect.toFixed(1)} pts (${c.direction})\n`;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
// Recommendations
|
|
656
|
-
md += '\n## Recommended Themes\n\n';
|
|
657
|
-
for (const t of recommendations.topThemes) {
|
|
658
|
-
md += `- **${t.character}** (${t.theme}): ${t.score} pts\n`;
|
|
659
|
-
}
|
|
660
|
-
// Themes to avoid
|
|
661
|
-
if (recommendations.avoidThemes.length > 0) {
|
|
662
|
-
md += '\n## Avoid These Themes\n\n';
|
|
663
|
-
md += 'These themes underperform the control baseline:\n\n';
|
|
664
|
-
for (const t of recommendations.avoidThemes) {
|
|
665
|
-
md += `- ${t.character} (${t.theme}): ${t.score} pts\n`;
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
// Insight
|
|
669
|
-
md += `\n## Insight\n\n${recommendations.insight}\n`;
|
|
670
|
-
// Error-type correlation (Story 14-5)
|
|
671
|
-
let errorCorrelation;
|
|
672
|
-
if (includeErrorTypeCorrelation) {
|
|
673
|
-
// For integration, we would calculate from actual judge scores
|
|
674
|
-
// For now, provide placeholder structure when flag is set
|
|
675
|
-
const results = performers.map(p => ({ ocean: p.ocean, mean: p.score }));
|
|
676
|
-
// Note: In real usage, judgeScores would come from actual benchmark runs
|
|
677
|
-
// This placeholder allows the integration test to pass
|
|
678
|
-
errorCorrelation = calculateErrorTypeCorrelation(results, []);
|
|
679
|
-
md += '\n' + generateOceanErrorHeatMap(errorCorrelation);
|
|
680
|
-
}
|
|
681
|
-
return {
|
|
682
|
-
markdown: md,
|
|
683
|
-
data: {
|
|
684
|
-
performers,
|
|
685
|
-
correlation,
|
|
686
|
-
recommendations,
|
|
687
|
-
errorCorrelation,
|
|
688
|
-
},
|
|
689
|
-
};
|
|
690
|
-
}
|
|
691
|
-
//# sourceMappingURL=benchmark-integration.js.map
|