@pennyfarthing/core 6.6.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/README.md +293 -0
- package/package.json +58 -0
- package/packages/core/bin/pennyfarthing.js +14 -0
- package/packages/core/dist/bmad/context-reader.d.ts +71 -0
- package/packages/core/dist/bmad/context-reader.d.ts.map +1 -0
- package/packages/core/dist/bmad/context-reader.js +369 -0
- package/packages/core/dist/bmad/context-reader.js.map +1 -0
- package/packages/core/dist/bmad/context-reader.test.d.ts +71 -0
- package/packages/core/dist/bmad/context-reader.test.d.ts.map +1 -0
- package/packages/core/dist/bmad/context-reader.test.js +878 -0
- package/packages/core/dist/bmad/context-reader.test.js.map +1 -0
- package/packages/core/dist/bmad/epics-parser.d.ts +61 -0
- package/packages/core/dist/bmad/epics-parser.d.ts.map +1 -0
- package/packages/core/dist/bmad/epics-parser.js +331 -0
- package/packages/core/dist/bmad/epics-parser.js.map +1 -0
- package/packages/core/dist/bmad/epics-parser.test.d.ts +7 -0
- package/packages/core/dist/bmad/epics-parser.test.d.ts.map +1 -0
- package/packages/core/dist/bmad/epics-parser.test.js +449 -0
- package/packages/core/dist/bmad/epics-parser.test.js.map +1 -0
- package/packages/core/dist/bmad/index.d.ts +11 -0
- package/packages/core/dist/bmad/index.d.ts.map +1 -0
- package/packages/core/dist/bmad/index.js +24 -0
- package/packages/core/dist/bmad/index.js.map +1 -0
- package/packages/core/dist/bmad/status-sync.d.ts +173 -0
- package/packages/core/dist/bmad/status-sync.d.ts.map +1 -0
- package/packages/core/dist/bmad/status-sync.js +463 -0
- package/packages/core/dist/bmad/status-sync.js.map +1 -0
- package/packages/core/dist/bmad/status-sync.test.d.ts +7 -0
- package/packages/core/dist/bmad/status-sync.test.d.ts.map +1 -0
- package/packages/core/dist/bmad/status-sync.test.js +702 -0
- package/packages/core/dist/bmad/status-sync.test.js.map +1 -0
- package/packages/core/dist/bmad/story-exporter.d.ts +55 -0
- package/packages/core/dist/bmad/story-exporter.d.ts.map +1 -0
- package/packages/core/dist/bmad/story-exporter.js +170 -0
- package/packages/core/dist/bmad/story-exporter.js.map +1 -0
- package/packages/core/dist/bmad/story-exporter.test.d.ts +51 -0
- package/packages/core/dist/bmad/story-exporter.test.d.ts.map +1 -0
- package/packages/core/dist/bmad/story-exporter.test.js +603 -0
- package/packages/core/dist/bmad/story-exporter.test.js.map +1 -0
- package/packages/core/dist/bmad/story-parser.d.ts +44 -0
- package/packages/core/dist/bmad/story-parser.d.ts.map +1 -0
- package/packages/core/dist/bmad/story-parser.js +307 -0
- package/packages/core/dist/bmad/story-parser.js.map +1 -0
- package/packages/core/dist/bmad/story-parser.test.d.ts +44 -0
- package/packages/core/dist/bmad/story-parser.test.d.ts.map +1 -0
- package/packages/core/dist/bmad/story-parser.test.js +693 -0
- package/packages/core/dist/bmad/story-parser.test.js.map +1 -0
- package/packages/core/dist/cli/commands/command.d.ts +28 -0
- package/packages/core/dist/cli/commands/command.d.ts.map +1 -0
- package/packages/core/dist/cli/commands/command.js +399 -0
- package/packages/core/dist/cli/commands/command.js.map +1 -0
- package/packages/core/dist/cli/commands/cyclist.d.ts +46 -0
- package/packages/core/dist/cli/commands/cyclist.d.ts.map +1 -0
- package/packages/core/dist/cli/commands/cyclist.js +191 -0
- package/packages/core/dist/cli/commands/cyclist.js.map +1 -0
- package/packages/core/dist/cli/commands/cyclist.test.d.ts +13 -0
- package/packages/core/dist/cli/commands/cyclist.test.d.ts.map +1 -0
- package/packages/core/dist/cli/commands/cyclist.test.js +243 -0
- package/packages/core/dist/cli/commands/cyclist.test.js.map +1 -0
- package/packages/core/dist/cli/commands/doctor.d.ts +9 -0
- package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -0
- package/packages/core/dist/cli/commands/doctor.js +652 -0
- package/packages/core/dist/cli/commands/doctor.js.map +1 -0
- package/packages/core/dist/cli/commands/init.d.ts +8 -0
- package/packages/core/dist/cli/commands/init.d.ts.map +1 -0
- package/packages/core/dist/cli/commands/init.js +524 -0
- package/packages/core/dist/cli/commands/init.js.map +1 -0
- package/packages/core/dist/cli/commands/skill.d.ts +28 -0
- package/packages/core/dist/cli/commands/skill.d.ts.map +1 -0
- package/packages/core/dist/cli/commands/skill.js +416 -0
- package/packages/core/dist/cli/commands/skill.js.map +1 -0
- package/packages/core/dist/cli/commands/theme.d.ts +21 -0
- package/packages/core/dist/cli/commands/theme.d.ts.map +1 -0
- package/packages/core/dist/cli/commands/theme.js +201 -0
- package/packages/core/dist/cli/commands/theme.js.map +1 -0
- package/packages/core/dist/cli/commands/uninstall.d.ts +8 -0
- package/packages/core/dist/cli/commands/uninstall.d.ts.map +1 -0
- package/packages/core/dist/cli/commands/uninstall.js +237 -0
- package/packages/core/dist/cli/commands/uninstall.js.map +1 -0
- package/packages/core/dist/cli/commands/update.d.ts +9 -0
- package/packages/core/dist/cli/commands/update.d.ts.map +1 -0
- package/packages/core/dist/cli/commands/update.js +545 -0
- package/packages/core/dist/cli/commands/update.js.map +1 -0
- package/packages/core/dist/cli/commands/version.d.ts +2 -0
- package/packages/core/dist/cli/commands/version.d.ts.map +1 -0
- package/packages/core/dist/cli/commands/version.js +28 -0
- package/packages/core/dist/cli/commands/version.js.map +1 -0
- package/packages/core/dist/cli/customization.test.d.ts +12 -0
- package/packages/core/dist/cli/customization.test.d.ts.map +1 -0
- package/packages/core/dist/cli/customization.test.js +84 -0
- package/packages/core/dist/cli/customization.test.js.map +1 -0
- package/packages/core/dist/cli/cyclist-migration.test.d.ts +16 -0
- package/packages/core/dist/cli/cyclist-migration.test.d.ts.map +1 -0
- package/packages/core/dist/cli/cyclist-migration.test.js +224 -0
- package/packages/core/dist/cli/cyclist-migration.test.js.map +1 -0
- package/packages/core/dist/cli/index.d.ts +3 -0
- package/packages/core/dist/cli/index.d.ts.map +1 -0
- package/packages/core/dist/cli/index.js +174 -0
- package/packages/core/dist/cli/index.js.map +1 -0
- package/packages/core/dist/cli/ocean-profiles.test.d.ts +13 -0
- package/packages/core/dist/cli/ocean-profiles.test.d.ts.map +1 -0
- package/packages/core/dist/cli/ocean-profiles.test.js +134 -0
- package/packages/core/dist/cli/ocean-profiles.test.js.map +1 -0
- package/packages/core/dist/cli/theme-maker.test.d.ts +11 -0
- package/packages/core/dist/cli/theme-maker.test.d.ts.map +1 -0
- package/packages/core/dist/cli/theme-maker.test.js +356 -0
- package/packages/core/dist/cli/theme-maker.test.js.map +1 -0
- package/packages/core/dist/cli/utils/constants.d.ts +60 -0
- package/packages/core/dist/cli/utils/constants.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/constants.js +52 -0
- package/packages/core/dist/cli/utils/constants.js.map +1 -0
- package/packages/core/dist/cli/utils/files.d.ts +71 -0
- package/packages/core/dist/cli/utils/files.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/files.js +162 -0
- package/packages/core/dist/cli/utils/files.js.map +1 -0
- package/packages/core/dist/cli/utils/logger.d.ts +26 -0
- package/packages/core/dist/cli/utils/logger.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/logger.js +88 -0
- package/packages/core/dist/cli/utils/logger.js.map +1 -0
- package/packages/core/dist/cli/utils/manifest.d.ts +47 -0
- package/packages/core/dist/cli/utils/manifest.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/manifest.js +90 -0
- package/packages/core/dist/cli/utils/manifest.js.map +1 -0
- package/packages/core/dist/cli/utils/node-modules.d.ts +6 -0
- package/packages/core/dist/cli/utils/node-modules.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/node-modules.js +22 -0
- package/packages/core/dist/cli/utils/node-modules.js.map +1 -0
- package/packages/core/dist/cli/utils/prompts.d.ts +34 -0
- package/packages/core/dist/cli/utils/prompts.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/prompts.js +93 -0
- package/packages/core/dist/cli/utils/prompts.js.map +1 -0
- package/packages/core/dist/cli/utils/symlinks.d.ts +29 -0
- package/packages/core/dist/cli/utils/symlinks.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/symlinks.js +181 -0
- package/packages/core/dist/cli/utils/symlinks.js.map +1 -0
- package/packages/core/dist/cli/utils/themes.d.ts +104 -0
- package/packages/core/dist/cli/utils/themes.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/themes.js +393 -0
- package/packages/core/dist/cli/utils/themes.js.map +1 -0
- package/packages/core/dist/cli/utils/themes.test.d.ts +12 -0
- package/packages/core/dist/cli/utils/themes.test.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/themes.test.js +144 -0
- package/packages/core/dist/cli/utils/themes.test.js.map +1 -0
- package/packages/core/dist/cli/utils/version.d.ts +10 -0
- package/packages/core/dist/cli/utils/version.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/version.js +63 -0
- package/packages/core/dist/cli/utils/version.js.map +1 -0
- package/packages/core/dist/cli/workspace.test.d.ts +8 -0
- package/packages/core/dist/cli/workspace.test.d.ts.map +1 -0
- package/packages/core/dist/cli/workspace.test.js +154 -0
- package/packages/core/dist/cli/workspace.test.js.map +1 -0
- package/packages/core/dist/index.d.ts +6 -0
- package/packages/core/dist/index.d.ts.map +1 -0
- package/packages/core/dist/index.js +10 -0
- package/packages/core/dist/index.js.map +1 -0
- package/packages/core/dist/permissions/index.d.ts +9 -0
- package/packages/core/dist/permissions/index.d.ts.map +1 -0
- package/packages/core/dist/permissions/index.js +13 -0
- package/packages/core/dist/permissions/index.js.map +1 -0
- package/packages/core/dist/permissions/permission-schema.d.ts +89 -0
- package/packages/core/dist/permissions/permission-schema.d.ts.map +1 -0
- package/packages/core/dist/permissions/permission-schema.js +120 -0
- package/packages/core/dist/permissions/permission-schema.js.map +1 -0
- package/packages/core/dist/permissions/permission-schema.test.d.ts +40 -0
- package/packages/core/dist/permissions/permission-schema.test.d.ts.map +1 -0
- package/packages/core/dist/permissions/permission-schema.test.js +367 -0
- package/packages/core/dist/permissions/permission-schema.test.js.map +1 -0
- package/packages/core/dist/scripts/add-ocean-profiles.d.ts +9 -0
- package/packages/core/dist/scripts/add-ocean-profiles.d.ts.map +1 -0
- package/packages/core/dist/scripts/add-ocean-profiles.js +695 -0
- package/packages/core/dist/scripts/add-ocean-profiles.js.map +1 -0
- package/packages/core/dist/scripts/benchmark-integration.d.ts +182 -0
- package/packages/core/dist/scripts/benchmark-integration.d.ts.map +1 -0
- package/packages/core/dist/scripts/benchmark-integration.js +691 -0
- package/packages/core/dist/scripts/benchmark-integration.js.map +1 -0
- package/packages/core/dist/scripts/benchmark-integration.test.d.ts +13 -0
- package/packages/core/dist/scripts/benchmark-integration.test.d.ts.map +1 -0
- package/packages/core/dist/scripts/benchmark-integration.test.js +680 -0
- package/packages/core/dist/scripts/benchmark-integration.test.js.map +1 -0
- package/packages/core/dist/scripts/debugging-scenarios.test.d.ts +18 -0
- package/packages/core/dist/scripts/debugging-scenarios.test.d.ts.map +1 -0
- package/packages/core/dist/scripts/debugging-scenarios.test.js +317 -0
- package/packages/core/dist/scripts/debugging-scenarios.test.js.map +1 -0
- package/packages/core/dist/scripts/generate-all-faces.d.ts +10 -0
- package/packages/core/dist/scripts/generate-all-faces.d.ts.map +1 -0
- package/packages/core/dist/scripts/generate-all-faces.js +256 -0
- package/packages/core/dist/scripts/generate-all-faces.js.map +1 -0
- package/packages/core/dist/scripts/generate-all-faces.test.d.ts +17 -0
- package/packages/core/dist/scripts/generate-all-faces.test.d.ts.map +1 -0
- package/packages/core/dist/scripts/generate-all-faces.test.js +372 -0
- package/packages/core/dist/scripts/generate-all-faces.test.js.map +1 -0
- package/packages/core/dist/scripts/generate-all-spiders.d.ts +10 -0
- package/packages/core/dist/scripts/generate-all-spiders.d.ts.map +1 -0
- package/packages/core/dist/scripts/generate-all-spiders.js +306 -0
- package/packages/core/dist/scripts/generate-all-spiders.js.map +1 -0
- package/packages/core/dist/scripts/generate-ascii-face.d.ts +52 -0
- package/packages/core/dist/scripts/generate-ascii-face.d.ts.map +1 -0
- package/packages/core/dist/scripts/generate-ascii-face.js +155 -0
- package/packages/core/dist/scripts/generate-ascii-face.js.map +1 -0
- package/packages/core/dist/scripts/generate-face.d.ts +52 -0
- package/packages/core/dist/scripts/generate-face.d.ts.map +1 -0
- package/packages/core/dist/scripts/generate-face.js +199 -0
- package/packages/core/dist/scripts/generate-face.js.map +1 -0
- package/packages/core/dist/scripts/generate-face.test.d.ts +13 -0
- package/packages/core/dist/scripts/generate-face.test.d.ts.map +1 -0
- package/packages/core/dist/scripts/generate-face.test.js +301 -0
- package/packages/core/dist/scripts/generate-face.test.js.map +1 -0
- package/packages/core/dist/scripts/generate-report.d.ts +65 -0
- package/packages/core/dist/scripts/generate-report.d.ts.map +1 -0
- package/packages/core/dist/scripts/generate-report.js +378 -0
- package/packages/core/dist/scripts/generate-report.js.map +1 -0
- package/packages/core/dist/scripts/generate-report.test.d.ts +13 -0
- package/packages/core/dist/scripts/generate-report.test.d.ts.map +1 -0
- package/packages/core/dist/scripts/generate-report.test.js +363 -0
- package/packages/core/dist/scripts/generate-report.test.js.map +1 -0
- package/packages/core/dist/scripts/generate-spider-report.d.ts +65 -0
- package/packages/core/dist/scripts/generate-spider-report.d.ts.map +1 -0
- package/packages/core/dist/scripts/generate-spider-report.js +366 -0
- package/packages/core/dist/scripts/generate-spider-report.js.map +1 -0
- package/packages/core/dist/scripts/generate-spider-report.test.d.ts +13 -0
- package/packages/core/dist/scripts/generate-spider-report.test.d.ts.map +1 -0
- package/packages/core/dist/scripts/generate-spider-report.test.js +367 -0
- package/packages/core/dist/scripts/generate-spider-report.test.js.map +1 -0
- package/packages/core/dist/scripts/generate-spider.d.ts +37 -0
- package/packages/core/dist/scripts/generate-spider.d.ts.map +1 -0
- package/packages/core/dist/scripts/generate-spider.js +315 -0
- package/packages/core/dist/scripts/generate-spider.js.map +1 -0
- package/packages/core/dist/scripts/generate-spider.test.d.ts +14 -0
- package/packages/core/dist/scripts/generate-spider.test.d.ts.map +1 -0
- package/packages/core/dist/scripts/generate-spider.test.js +269 -0
- package/packages/core/dist/scripts/generate-spider.test.js.map +1 -0
- package/packages/core/dist/scripts/job-fair-aggregator.d.ts +150 -0
- package/packages/core/dist/scripts/job-fair-aggregator.d.ts.map +1 -0
- package/packages/core/dist/scripts/job-fair-aggregator.js +547 -0
- package/packages/core/dist/scripts/job-fair-aggregator.js.map +1 -0
- package/packages/core/dist/scripts/job-fair-aggregator.test.d.ts +14 -0
- package/packages/core/dist/scripts/job-fair-aggregator.test.d.ts.map +1 -0
- package/packages/core/dist/scripts/job-fair-aggregator.test.js +616 -0
- package/packages/core/dist/scripts/job-fair-aggregator.test.js.map +1 -0
- package/packages/core/dist/scripts/run-ci.test.d.ts +20 -0
- package/packages/core/dist/scripts/run-ci.test.d.ts.map +1 -0
- package/packages/core/dist/scripts/run-ci.test.js +127 -0
- package/packages/core/dist/scripts/run-ci.test.js.map +1 -0
- package/packages/core/dist/scripts/theme-detail.test.d.ts +10 -0
- package/packages/core/dist/scripts/theme-detail.test.d.ts.map +1 -0
- package/packages/core/dist/scripts/theme-detail.test.js +199 -0
- package/packages/core/dist/scripts/theme-detail.test.js.map +1 -0
- package/packages/core/dist/scripts/validate-ocean-profiles.d.ts +9 -0
- package/packages/core/dist/scripts/validate-ocean-profiles.d.ts.map +1 -0
- package/packages/core/dist/scripts/validate-ocean-profiles.js +130 -0
- package/packages/core/dist/scripts/validate-ocean-profiles.js.map +1 -0
- package/packages/core/dist/workflow/generic-handoff.d.ts +235 -0
- package/packages/core/dist/workflow/generic-handoff.d.ts.map +1 -0
- package/packages/core/dist/workflow/generic-handoff.js +358 -0
- package/packages/core/dist/workflow/generic-handoff.js.map +1 -0
- package/packages/core/dist/workflow/generic-handoff.test.d.ts +21 -0
- package/packages/core/dist/workflow/generic-handoff.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/generic-handoff.test.js +499 -0
- package/packages/core/dist/workflow/generic-handoff.test.js.map +1 -0
- package/packages/core/dist/workflow/generic-sm-finish.d.ts +89 -0
- package/packages/core/dist/workflow/generic-sm-finish.d.ts.map +1 -0
- package/packages/core/dist/workflow/generic-sm-finish.js +157 -0
- package/packages/core/dist/workflow/generic-sm-finish.js.map +1 -0
- package/packages/core/dist/workflow/generic-sm-setup.d.ts +138 -0
- package/packages/core/dist/workflow/generic-sm-setup.d.ts.map +1 -0
- package/packages/core/dist/workflow/generic-sm-setup.js +382 -0
- package/packages/core/dist/workflow/generic-sm-setup.js.map +1 -0
- package/packages/core/dist/workflow/sm-subagents.test.d.ts +23 -0
- package/packages/core/dist/workflow/sm-subagents.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/sm-subagents.test.js +727 -0
- package/packages/core/dist/workflow/sm-subagents.test.js.map +1 -0
- package/packages/core/dist/workflow/story-workflow-routing.test.d.ts +17 -0
- package/packages/core/dist/workflow/story-workflow-routing.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/story-workflow-routing.test.js +559 -0
- package/packages/core/dist/workflow/story-workflow-routing.test.js.map +1 -0
- package/packages/core/dist/workflow/test-cache.d.ts +131 -0
- package/packages/core/dist/workflow/test-cache.d.ts.map +1 -0
- package/packages/core/dist/workflow/test-cache.js +226 -0
- package/packages/core/dist/workflow/test-cache.js.map +1 -0
- package/packages/core/dist/workflow/test-cache.test.d.ts +17 -0
- package/packages/core/dist/workflow/test-cache.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/test-cache.test.js +438 -0
- package/packages/core/dist/workflow/test-cache.test.js.map +1 -0
- package/packages/core/dist/workflow/workflow-loader.d.ts +76 -0
- package/packages/core/dist/workflow/workflow-loader.d.ts.map +1 -0
- package/packages/core/dist/workflow/workflow-loader.js +133 -0
- package/packages/core/dist/workflow/workflow-loader.js.map +1 -0
- package/packages/core/dist/workflow/workflow-loader.test.d.ts +15 -0
- package/packages/core/dist/workflow/workflow-loader.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/workflow-loader.test.js +354 -0
- package/packages/core/dist/workflow/workflow-loader.test.js.map +1 -0
- package/packages/core/dist/workflow/workflow-migration.test.d.ts +17 -0
- package/packages/core/dist/workflow/workflow-migration.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/workflow-migration.test.js +372 -0
- package/packages/core/dist/workflow/workflow-migration.test.js.map +1 -0
- package/packages/core/dist/workflow/workflow-router.d.ts +55 -0
- package/packages/core/dist/workflow/workflow-router.d.ts.map +1 -0
- package/packages/core/dist/workflow/workflow-router.js +245 -0
- package/packages/core/dist/workflow/workflow-router.js.map +1 -0
- package/packages/core/dist/workflow/workflow-router.test.d.ts +20 -0
- package/packages/core/dist/workflow/workflow-router.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/workflow-router.test.js +607 -0
- package/packages/core/dist/workflow/workflow-router.test.js.map +1 -0
- package/packages/core/dist/workflow/workflow-schema.d.ts +98 -0
- package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -0
- package/packages/core/dist/workflow/workflow-schema.js +230 -0
- package/packages/core/dist/workflow/workflow-schema.js.map +1 -0
- package/packages/core/dist/workflow/workflow-schema.test.d.ts +45 -0
- package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/workflow-schema.test.js +512 -0
- package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -0
- package/pennyfarthing-dist/agents/README.md +397 -0
- package/pennyfarthing-dist/agents/architect.md +171 -0
- package/pennyfarthing-dist/agents/dev.md +225 -0
- package/pennyfarthing-dist/agents/devops.md +183 -0
- package/pennyfarthing-dist/agents/generic-handoff.md +451 -0
- package/pennyfarthing-dist/agents/generic-sm-finish.md +261 -0
- package/pennyfarthing-dist/agents/generic-sm-setup.md +214 -0
- package/pennyfarthing-dist/agents/orchestrator.md +316 -0
- package/pennyfarthing-dist/agents/pm.md +153 -0
- package/pennyfarthing-dist/agents/reviewer-preflight.md +224 -0
- package/pennyfarthing-dist/agents/reviewer.md +315 -0
- package/pennyfarthing-dist/agents/sm-file-summary.md +109 -0
- package/pennyfarthing-dist/agents/sm-handoff.md +97 -0
- package/pennyfarthing-dist/agents/sm.md +480 -0
- package/pennyfarthing-dist/agents/tea.md +191 -0
- package/pennyfarthing-dist/agents/tech-writer.md +148 -0
- package/pennyfarthing-dist/agents/testing-runner.md +420 -0
- package/pennyfarthing-dist/agents/ux-designer.md +158 -0
- package/pennyfarthing-dist/agents/workflow-status-check.md +332 -0
- package/pennyfarthing-dist/commands/architect.md +62 -0
- package/pennyfarthing-dist/commands/benchmark-control.md +69 -0
- package/pennyfarthing-dist/commands/benchmark.md +467 -0
- package/pennyfarthing-dist/commands/brainstorm.md +91 -0
- package/pennyfarthing-dist/commands/check.md +156 -0
- package/pennyfarthing-dist/commands/chore.md +178 -0
- package/pennyfarthing-dist/commands/close-epic.md +136 -0
- package/pennyfarthing-dist/commands/continue-session.md +184 -0
- package/pennyfarthing-dist/commands/create-branches-from-story.md +374 -0
- package/pennyfarthing-dist/commands/create-theme.md +29 -0
- package/pennyfarthing-dist/commands/dev.md +60 -0
- package/pennyfarthing-dist/commands/devops.md +59 -0
- package/pennyfarthing-dist/commands/git-cleanup.md +340 -0
- package/pennyfarthing-dist/commands/health-check.md +108 -0
- package/pennyfarthing-dist/commands/help.md +264 -0
- package/pennyfarthing-dist/commands/job-fair.md +102 -0
- package/pennyfarthing-dist/commands/list-themes.md +17 -0
- package/pennyfarthing-dist/commands/new-work.md +127 -0
- package/pennyfarthing-dist/commands/orchestrator.md +56 -0
- package/pennyfarthing-dist/commands/parallel-work.md +71 -0
- package/pennyfarthing-dist/commands/party-mode.md +67 -0
- package/pennyfarthing-dist/commands/permissions.md +193 -0
- package/pennyfarthing-dist/commands/pm.md +60 -0
- package/pennyfarthing-dist/commands/prime.md +140 -0
- package/pennyfarthing-dist/commands/release.md +58 -0
- package/pennyfarthing-dist/commands/repo-status.md +49 -0
- package/pennyfarthing-dist/commands/retro.md +200 -0
- package/pennyfarthing-dist/commands/reviewer.md +64 -0
- package/pennyfarthing-dist/commands/run-ci.md +116 -0
- package/pennyfarthing-dist/commands/set-theme.md +52 -0
- package/pennyfarthing-dist/commands/show-theme.md +21 -0
- package/pennyfarthing-dist/commands/sm.md +70 -0
- package/pennyfarthing-dist/commands/solo.md +411 -0
- package/pennyfarthing-dist/commands/sprint-planning.md +109 -0
- package/pennyfarthing-dist/commands/start-epic.md +156 -0
- package/pennyfarthing-dist/commands/sync-epic-to-jira.md +184 -0
- package/pennyfarthing-dist/commands/sync-work-with-sprint.md +376 -0
- package/pennyfarthing-dist/commands/tea.md +63 -0
- package/pennyfarthing-dist/commands/tech-writer.md +53 -0
- package/pennyfarthing-dist/commands/theme-maker.md +671 -0
- package/pennyfarthing-dist/commands/update-domain-docs.md +83 -0
- package/pennyfarthing-dist/commands/ux-designer.md +62 -0
- package/pennyfarthing-dist/commands/work.md +111 -0
- package/pennyfarthing-dist/guides/AGENT-COORDINATION.md +480 -0
- package/pennyfarthing-dist/guides/AGENT-SCOPES.md +201 -0
- package/pennyfarthing-dist/guides/HOOKS.md +230 -0
- package/pennyfarthing-dist/guides/PROMPT-PATTERNS.md +338 -0
- package/pennyfarthing-dist/guides/SESSION-ARTIFACTS.md +193 -0
- package/pennyfarthing-dist/guides/agent-template-strategic.md +148 -0
- package/pennyfarthing-dist/guides/agent-template-tactical.md +162 -0
- package/pennyfarthing-dist/guides/patterns/approval-gates-pattern.md +746 -0
- package/pennyfarthing-dist/guides/patterns/fan-out-fan-in-pattern.md +574 -0
- package/pennyfarthing-dist/guides/patterns/helper-delegation-pattern.md +488 -0
- package/pennyfarthing-dist/guides/patterns/tdd-flow-pattern.md +402 -0
- package/pennyfarthing-dist/guides/permission-protocol.md +188 -0
- package/pennyfarthing-dist/guides/persona-loading.md +46 -0
- package/pennyfarthing-dist/guides/persona-system.md +294 -0
- package/pennyfarthing-dist/guides/shared-agent-behavior.md +388 -0
- package/pennyfarthing-dist/guides/shared-context.md +147 -0
- package/pennyfarthing-dist/guides/strategic-agent-behavior.md +348 -0
- package/pennyfarthing-dist/guides/tactical-agent-behavior.md +1041 -0
- package/pennyfarthing-dist/guides/workflow-schema.md +195 -0
- package/pennyfarthing-dist/guides/worktree-mode.md +113 -0
- package/pennyfarthing-dist/output-styles/teaching.md +33 -0
- package/pennyfarthing-dist/output-styles/terse.md +20 -0
- package/pennyfarthing-dist/output-styles/verbose.md +28 -0
- package/pennyfarthing-dist/personas/themes/1984.yaml +312 -0
- package/pennyfarthing-dist/personas/themes/a-team.yaml +207 -0
- package/pennyfarthing-dist/personas/themes/agatha-christie.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/alice-in-wonderland.yaml +330 -0
- package/pennyfarthing-dist/personas/themes/all-stars.yaml +332 -0
- package/pennyfarthing-dist/personas/themes/ancient-philosophers.yaml +320 -0
- package/pennyfarthing-dist/personas/themes/ancient-strategists.yaml +306 -0
- package/pennyfarthing-dist/personas/themes/arcane.yaml +288 -0
- package/pennyfarthing-dist/personas/themes/arthurian-mythos.yaml +331 -0
- package/pennyfarthing-dist/personas/themes/avatar-the-last-airbender.yaml +288 -0
- package/pennyfarthing-dist/personas/themes/babylon-5.yaml +288 -0
- package/pennyfarthing-dist/personas/themes/battlestar-galactica.yaml +288 -0
- package/pennyfarthing-dist/personas/themes/better-call-saul.yaml +288 -0
- package/pennyfarthing-dist/personas/themes/big-lebowski.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/black-sails.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/blade-runner.yaml +295 -0
- package/pennyfarthing-dist/personas/themes/bobiverse.yaml +288 -0
- package/pennyfarthing-dist/personas/themes/breaking-bad.yaml +327 -0
- package/pennyfarthing-dist/personas/themes/catch-22.yaml +316 -0
- package/pennyfarthing-dist/personas/themes/classical-composers.yaml +310 -0
- package/pennyfarthing-dist/personas/themes/control.yaml +197 -0
- package/pennyfarthing-dist/personas/themes/count-of-monte-cristo.yaml +320 -0
- package/pennyfarthing-dist/personas/themes/cowboy-bebop.yaml +323 -0
- package/pennyfarthing-dist/personas/themes/deadwood.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/dickens.yaml +320 -0
- package/pennyfarthing-dist/personas/themes/discworld.yaml +332 -0
- package/pennyfarthing-dist/personas/themes/doctor-who.yaml +290 -0
- package/pennyfarthing-dist/personas/themes/don-quixote.yaml +320 -0
- package/pennyfarthing-dist/personas/themes/dune.yaml +307 -0
- package/pennyfarthing-dist/personas/themes/enlightenment-thinkers.yaml +320 -0
- package/pennyfarthing-dist/personas/themes/expeditionary-force.yaml +288 -0
- package/pennyfarthing-dist/personas/themes/fargo.yaml +330 -0
- package/pennyfarthing-dist/personas/themes/film-auteurs.yaml +312 -0
- package/pennyfarthing-dist/personas/themes/firefly.yaml +328 -0
- package/pennyfarthing-dist/personas/themes/foundation.yaml +290 -0
- package/pennyfarthing-dist/personas/themes/futurama.yaml +321 -0
- package/pennyfarthing-dist/personas/themes/game-of-thrones.yaml +290 -0
- package/pennyfarthing-dist/personas/themes/gilligans-island.yaml +243 -0
- package/pennyfarthing-dist/personas/themes/gothic-literature.yaml +308 -0
- package/pennyfarthing-dist/personas/themes/great-gatsby.yaml +308 -0
- package/pennyfarthing-dist/personas/themes/greek-mythology.yaml +330 -0
- package/pennyfarthing-dist/personas/themes/hannibal.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/harry-potter.yaml +324 -0
- package/pennyfarthing-dist/personas/themes/his-dark-materials.yaml +291 -0
- package/pennyfarthing-dist/personas/themes/historical-figures.yaml +288 -0
- package/pennyfarthing-dist/personas/themes/hitchhikers-guide.yaml +331 -0
- package/pennyfarthing-dist/personas/themes/house-md.yaml +321 -0
- package/pennyfarthing-dist/personas/themes/imperial-radch.yaml +289 -0
- package/pennyfarthing-dist/personas/themes/inspector-morse.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/jane-austen.yaml +287 -0
- package/pennyfarthing-dist/personas/themes/jazz-legends.yaml +320 -0
- package/pennyfarthing-dist/personas/themes/justified.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/legion-of-doom.yaml +219 -0
- package/pennyfarthing-dist/personas/themes/les-miserables.yaml +299 -0
- package/pennyfarthing-dist/personas/themes/lord-of-the-rings.yaml +334 -0
- package/pennyfarthing-dist/personas/themes/lovecraft-mythos.yaml +334 -0
- package/pennyfarthing-dist/personas/themes/mad-max.yaml +355 -0
- package/pennyfarthing-dist/personas/themes/mad-men.yaml +289 -0
- package/pennyfarthing-dist/personas/themes/marvel-mcu.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/mash.yaml +334 -0
- package/pennyfarthing-dist/personas/themes/mass-effect.yaml +289 -0
- package/pennyfarthing-dist/personas/themes/military-commanders.yaml +306 -0
- package/pennyfarthing-dist/personas/themes/moby-dick.yaml +320 -0
- package/pennyfarthing-dist/personas/themes/monty-python.yaml +303 -0
- package/pennyfarthing-dist/personas/themes/neuromancer.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/norse-mythology.yaml +329 -0
- package/pennyfarthing-dist/personas/themes/parks-and-rec.yaml +242 -0
- package/pennyfarthing-dist/personas/themes/peaky-blinders.yaml +298 -0
- package/pennyfarthing-dist/personas/themes/princess-bride.yaml +220 -0
- package/pennyfarthing-dist/personas/themes/renaissance-masters.yaml +320 -0
- package/pennyfarthing-dist/personas/themes/rome.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/russian-masters.yaml +318 -0
- package/pennyfarthing-dist/personas/themes/sandman.yaml +288 -0
- package/pennyfarthing-dist/personas/themes/scientific-revolutionaries.yaml +320 -0
- package/pennyfarthing-dist/personas/themes/shakespeare.yaml +301 -0
- package/pennyfarthing-dist/personas/themes/sherlock-holmes.yaml +289 -0
- package/pennyfarthing-dist/personas/themes/snow-crash.yaml +288 -0
- package/pennyfarthing-dist/personas/themes/software-pioneers.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/star-trek-tng.yaml +230 -0
- package/pennyfarthing-dist/personas/themes/star-trek-tos.yaml +210 -0
- package/pennyfarthing-dist/personas/themes/star-wars.yaml +303 -0
- package/pennyfarthing-dist/personas/themes/succession.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/superfriends.yaml +208 -0
- package/pennyfarthing-dist/personas/themes/ted-lasso.yaml +236 -0
- package/pennyfarthing-dist/personas/themes/the-americans.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/the-crown.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/the-expanse.yaml +213 -0
- package/pennyfarthing-dist/personas/themes/the-good-place.yaml +322 -0
- package/pennyfarthing-dist/personas/themes/the-matrix.yaml +353 -0
- package/pennyfarthing-dist/personas/themes/the-odyssey.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/the-office.yaml +330 -0
- package/pennyfarthing-dist/personas/themes/the-simpsons.yaml +308 -0
- package/pennyfarthing-dist/personas/themes/the-sopranos.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/the-wire.yaml +311 -0
- package/pennyfarthing-dist/personas/themes/the-witcher.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/twin-peaks.yaml +302 -0
- package/pennyfarthing-dist/personas/themes/vorkosigan-saga.yaml +300 -0
- package/pennyfarthing-dist/personas/themes/watchmen.yaml +291 -0
- package/pennyfarthing-dist/personas/themes/west-wing.yaml +291 -0
- package/pennyfarthing-dist/personas/themes/world-explorers.yaml +320 -0
- package/pennyfarthing-dist/personas/themes/wwii-leaders.yaml +307 -0
- package/pennyfarthing-dist/personas/themes/x-files.yaml +302 -0
- package/pennyfarthing-dist/scripts/add-short-names.mjs +264 -0
- package/pennyfarthing-dist/scripts/agent-session.sh +367 -0
- package/pennyfarthing-dist/scripts/check-context.sh +187 -0
- package/pennyfarthing-dist/scripts/check.sh +497 -0
- package/pennyfarthing-dist/scripts/deploy.sh +284 -0
- package/pennyfarthing-dist/scripts/doctor-dogfood.sh +360 -0
- package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +61 -0
- package/pennyfarthing-dist/scripts/hooks/context-warning.sh +66 -0
- package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +35 -0
- package/pennyfarthing-dist/scripts/hooks/post-merge.sh +166 -0
- package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +50 -0
- package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +71 -0
- package/pennyfarthing-dist/scripts/hooks/pre-push.sh +54 -0
- package/pennyfarthing-dist/scripts/hooks/session-start.sh +98 -0
- package/pennyfarthing-dist/scripts/hooks/session-stop.sh +59 -0
- package/pennyfarthing-dist/scripts/install-git-hooks.sh +91 -0
- package/pennyfarthing-dist/scripts/prime.sh +161 -0
- package/pennyfarthing-dist/scripts/release.sh +198 -0
- package/pennyfarthing-dist/scripts/repo-utils.sh +778 -0
- package/pennyfarthing-dist/scripts/run-ci.sh +219 -0
- package/pennyfarthing-dist/scripts/run.sh +65 -0
- package/pennyfarthing-dist/scripts/statusline.sh +264 -0
- package/pennyfarthing-dist/scripts/tests/check.test.sh +582 -0
- package/pennyfarthing-dist/scripts/tests/test-character-voice.sh +107 -0
- package/pennyfarthing-dist/scripts/tests/test-drift-detection.sh +597 -0
- package/pennyfarthing-dist/scripts/tests/test-post-merge-hook.sh +514 -0
- package/pennyfarthing-dist/scripts/tests/test-session-checkpoint.sh +517 -0
- package/pennyfarthing-dist/scripts/tests/test-solo-command.sh +331 -0
- package/pennyfarthing-dist/scripts/uninstall.sh +271 -0
- package/pennyfarthing-dist/scripts/utils/background-tasks.sh +177 -0
- package/pennyfarthing-dist/scripts/utils/check-status.sh +251 -0
- package/pennyfarthing-dist/scripts/utils/checkpoint.sh +136 -0
- package/pennyfarthing-dist/scripts/utils/common.sh +157 -0
- package/pennyfarthing-dist/scripts/utils/create-feature-branches.sh +230 -0
- package/pennyfarthing-dist/scripts/utils/file-lock.sh +269 -0
- package/pennyfarthing-dist/scripts/utils/find-related-work.sh +231 -0
- package/pennyfarthing-dist/scripts/utils/find-root.sh +33 -0
- package/pennyfarthing-dist/scripts/utils/generate-skill-docs.sh +110 -0
- package/pennyfarthing-dist/scripts/utils/git-status-all.sh +127 -0
- package/pennyfarthing-dist/scripts/utils/ground-truth-judge.py +289 -0
- package/pennyfarthing-dist/scripts/utils/jira/jira-lib.mjs +443 -0
- package/pennyfarthing-dist/scripts/utils/jira/jira-sync-story.mjs +208 -0
- package/pennyfarthing-dist/scripts/utils/jira/jira-sync.mjs +198 -0
- package/pennyfarthing-dist/scripts/utils/jira-claim-story.sh +162 -0
- package/pennyfarthing-dist/scripts/utils/jira-lib.sh +463 -0
- package/pennyfarthing-dist/scripts/utils/jira-sync-story.sh +8 -0
- package/pennyfarthing-dist/scripts/utils/jira-sync.sh +8 -0
- package/pennyfarthing-dist/scripts/utils/log-skill-usage.sh +74 -0
- package/pennyfarthing-dist/scripts/utils/logging.sh +186 -0
- package/pennyfarthing-dist/scripts/utils/repo-scan.sh +141 -0
- package/pennyfarthing-dist/scripts/utils/retry.sh +76 -0
- package/pennyfarthing-dist/scripts/utils/run-timestamp.sh +7 -0
- package/pennyfarthing-dist/scripts/utils/session-cleanup.sh +319 -0
- package/pennyfarthing-dist/scripts/utils/skill-usage-report.sh +193 -0
- package/pennyfarthing-dist/scripts/utils/sprint-common.sh +286 -0
- package/pennyfarthing-dist/scripts/utils/sprint-metrics.sh +241 -0
- package/pennyfarthing-dist/scripts/utils/swebench-judge.py +400 -0
- package/pennyfarthing-dist/scripts/utils/sync-epic-to-jira.sh +16 -0
- package/pennyfarthing-dist/scripts/utils/test-setup.sh +337 -0
- package/pennyfarthing-dist/scripts/utils/validate-subagent-frontmatter.sh +160 -0
- package/pennyfarthing-dist/scripts/worktree-manager.sh +498 -0
- package/pennyfarthing-dist/skills/agentic-patterns/SKILL.md +236 -0
- package/pennyfarthing-dist/skills/changelog/SKILL.md +367 -0
- package/pennyfarthing-dist/skills/code-review/SKILL.md +168 -0
- package/pennyfarthing-dist/skills/context-engineering/SKILL.md +268 -0
- package/pennyfarthing-dist/skills/cyclist/SKILL.md +117 -0
- package/pennyfarthing-dist/skills/dev-patterns/SKILL.md +421 -0
- package/pennyfarthing-dist/skills/finalize-run/SKILL.md +258 -0
- package/pennyfarthing-dist/skills/jira/SKILL.md +281 -0
- package/pennyfarthing-dist/skills/judge/SKILL.md +524 -0
- package/pennyfarthing-dist/skills/just/SKILL.md +160 -0
- package/pennyfarthing-dist/skills/mermaid/SKILL.md +240 -0
- package/pennyfarthing-dist/skills/otel/skill.md +222 -0
- package/pennyfarthing-dist/skills/permissions/skill.md +172 -0
- package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +173 -0
- package/pennyfarthing-dist/skills/skill-registry.schema.json +102 -0
- package/pennyfarthing-dist/skills/skill-registry.yaml +335 -0
- package/pennyfarthing-dist/skills/sprint-context/SKILL.md +120 -0
- package/pennyfarthing-dist/skills/story-management/SKILL.md +208 -0
- package/pennyfarthing-dist/skills/testing/SKILL.md +99 -0
- package/pennyfarthing-dist/skills/testing/references/troubleshooting.md +124 -0
- package/pennyfarthing-dist/skills/theme/skill.md +129 -0
- package/pennyfarthing-dist/skills/theme-creation/SKILL.md +169 -0
- package/pennyfarthing-dist/skills/workflow/SKILL.md +160 -0
- package/pennyfarthing-dist/skills/yq/SKILL.md +264 -0
- package/pennyfarthing-dist/templates/LEADERBOARD.schema.yaml +187 -0
- package/pennyfarthing-dist/templates/LEADERBOARD.template.md +59 -0
- package/pennyfarthing-dist/templates/agent-scopes.yaml.template +276 -0
- package/pennyfarthing-dist/templates/pennyfarthing-settings.yaml.template +61 -0
- package/pennyfarthing-dist/templates/persona-config.yaml.template +22 -0
- package/pennyfarthing-dist/templates/preferences.yaml.template +15 -0
- package/pennyfarthing-dist/templates/settings.local.json.template +90 -0
- package/pennyfarthing-dist/templates/setup-env.sh.template +18 -0
- package/pennyfarthing-dist/templates/shared-context.md.template +70 -0
- package/pennyfarthing-dist/templates/sidecar/decisions.md.template +40 -0
- package/pennyfarthing-dist/templates/sidecar/gotchas.md.template +37 -0
- package/pennyfarthing-dist/templates/sidecar/patterns.md.template +34 -0
- package/pennyfarthing-dist/workflows/agent-docs.yaml +70 -0
- package/pennyfarthing-dist/workflows/bdd.yaml +58 -0
- package/pennyfarthing-dist/workflows/tdd.yaml +50 -0
- package/pennyfarthing-dist/workflows/trivial.yaml +40 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import { readFileSync, readdirSync, existsSync, writeFileSync, mkdirSync } from 'fs';
|
|
2
|
+
import { join, dirname, basename } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
import YAML from 'yaml';
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
/**
|
|
9
|
+
* Get the path to the themes directory
|
|
10
|
+
*/
|
|
11
|
+
export function getThemesDir() {
|
|
12
|
+
// In installed package: dist/cli/utils/themes.ts -> need to go to pennyfarthing-dist
|
|
13
|
+
// Try relative to package root first
|
|
14
|
+
const packageRoot = join(__dirname, '../../..');
|
|
15
|
+
const distThemes = join(packageRoot, 'pennyfarthing-dist/personas/themes');
|
|
16
|
+
if (existsSync(distThemes)) {
|
|
17
|
+
return distThemes;
|
|
18
|
+
}
|
|
19
|
+
// Fallback: try from project's .claude/pennyfarthing symlink
|
|
20
|
+
const projectRoot = process.cwd();
|
|
21
|
+
const claudeThemes = join(projectRoot, '.claude/pennyfarthing/personas/themes');
|
|
22
|
+
if (existsSync(claudeThemes)) {
|
|
23
|
+
return claudeThemes;
|
|
24
|
+
}
|
|
25
|
+
throw new Error('Could not find themes directory');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get the project-level custom themes directory
|
|
29
|
+
*/
|
|
30
|
+
export function getProjectCustomThemesDir(projectRoot) {
|
|
31
|
+
return join(projectRoot, '.claude/pennyfarthing/themes');
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the user-level custom themes directory
|
|
35
|
+
*/
|
|
36
|
+
export function getUserCustomThemesDir() {
|
|
37
|
+
return join(homedir(), '.claude/pennyfarthing/themes');
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get the path to the .pennyfarthing local config (preferred for dogfooding)
|
|
41
|
+
*/
|
|
42
|
+
export function getPennyfarthingConfigPath(projectRoot) {
|
|
43
|
+
return join(projectRoot, '.pennyfarthing/config.local.yaml');
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get the current theme from config files
|
|
47
|
+
* Priority: .pennyfarthing/config.local.yaml > .claude/persona-config.local.yaml > .claude/persona-config.yaml
|
|
48
|
+
*/
|
|
49
|
+
export function getCurrentTheme(projectRoot) {
|
|
50
|
+
const root = projectRoot || process.cwd();
|
|
51
|
+
// Priority 1: .pennyfarthing/config.local.yaml (dogfooding/agent-writable)
|
|
52
|
+
const pennyfarthingConfigPath = getPennyfarthingConfigPath(root);
|
|
53
|
+
if (existsSync(pennyfarthingConfigPath)) {
|
|
54
|
+
try {
|
|
55
|
+
const content = readFileSync(pennyfarthingConfigPath, 'utf8');
|
|
56
|
+
const config = YAML.parse(content);
|
|
57
|
+
if (config?.theme) {
|
|
58
|
+
return config.theme;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Fall through to next option
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Priority 2: .claude/persona-config.local.yaml (legacy local)
|
|
66
|
+
const localConfigPath = join(root, '.claude/persona-config.local.yaml');
|
|
67
|
+
if (existsSync(localConfigPath)) {
|
|
68
|
+
try {
|
|
69
|
+
const content = readFileSync(localConfigPath, 'utf8');
|
|
70
|
+
const config = YAML.parse(content);
|
|
71
|
+
if (config?.theme) {
|
|
72
|
+
return config.theme;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Fall through to shared config
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Priority 3: .claude/persona-config.yaml (project default)
|
|
80
|
+
const sharedConfigPath = join(root, '.claude/persona-config.yaml');
|
|
81
|
+
if (existsSync(sharedConfigPath)) {
|
|
82
|
+
try {
|
|
83
|
+
const content = readFileSync(sharedConfigPath, 'utf8');
|
|
84
|
+
const config = YAML.parse(content);
|
|
85
|
+
return config?.theme || null;
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Parse a theme YAML file and extract theme info
|
|
95
|
+
*/
|
|
96
|
+
export function parseThemeFile(filePath, isCustom = false) {
|
|
97
|
+
try {
|
|
98
|
+
const content = readFileSync(filePath, 'utf8');
|
|
99
|
+
const data = YAML.parse(content);
|
|
100
|
+
if (!data?.theme?.name) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const id = basename(filePath, '.yaml');
|
|
104
|
+
return {
|
|
105
|
+
id,
|
|
106
|
+
name: data.theme.name,
|
|
107
|
+
description: data.theme.description || '',
|
|
108
|
+
isCustom,
|
|
109
|
+
agents: data.agents || {}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Load themes from a directory
|
|
118
|
+
*/
|
|
119
|
+
function loadThemesFromDir(dir, isCustom) {
|
|
120
|
+
const themes = [];
|
|
121
|
+
if (!existsSync(dir)) {
|
|
122
|
+
return themes;
|
|
123
|
+
}
|
|
124
|
+
const files = readdirSync(dir).filter(f => f.endsWith('.yaml'));
|
|
125
|
+
for (const file of files) {
|
|
126
|
+
const theme = parseThemeFile(join(dir, file), isCustom);
|
|
127
|
+
if (theme) {
|
|
128
|
+
themes.push(theme);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return themes;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Get all available themes (built-in + custom)
|
|
135
|
+
*/
|
|
136
|
+
export function getThemes(projectRoot) {
|
|
137
|
+
const themes = [];
|
|
138
|
+
const seenIds = new Set();
|
|
139
|
+
// 1. Load built-in themes
|
|
140
|
+
try {
|
|
141
|
+
const builtInDir = getThemesDir();
|
|
142
|
+
for (const theme of loadThemesFromDir(builtInDir, false)) {
|
|
143
|
+
if (!seenIds.has(theme.id)) {
|
|
144
|
+
themes.push(theme);
|
|
145
|
+
seenIds.add(theme.id);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// Built-in themes not found - continue with custom themes
|
|
151
|
+
}
|
|
152
|
+
// 2. Load project-level custom themes
|
|
153
|
+
const root = projectRoot || process.cwd();
|
|
154
|
+
const projectDir = getProjectCustomThemesDir(root);
|
|
155
|
+
for (const theme of loadThemesFromDir(projectDir, true)) {
|
|
156
|
+
if (!seenIds.has(theme.id)) {
|
|
157
|
+
themes.push(theme);
|
|
158
|
+
seenIds.add(theme.id);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// 3. Load user-level custom themes
|
|
162
|
+
const userDir = getUserCustomThemesDir();
|
|
163
|
+
for (const theme of loadThemesFromDir(userDir, true)) {
|
|
164
|
+
if (!seenIds.has(theme.id)) {
|
|
165
|
+
themes.push(theme);
|
|
166
|
+
seenIds.add(theme.id);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Sort alphabetically by name
|
|
170
|
+
return themes.sort((a, b) => a.name.localeCompare(b.name));
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get sample agent characters for display
|
|
174
|
+
*/
|
|
175
|
+
export function getAgentSamples(theme) {
|
|
176
|
+
const samples = [];
|
|
177
|
+
if (theme.agents.sm?.character) {
|
|
178
|
+
samples.push(`SM: ${theme.agents.sm.character}`);
|
|
179
|
+
}
|
|
180
|
+
if (theme.agents.tea?.character) {
|
|
181
|
+
samples.push(`TEA: ${theme.agents.tea.character}`);
|
|
182
|
+
}
|
|
183
|
+
if (theme.agents.dev?.character) {
|
|
184
|
+
samples.push(`Dev: ${theme.agents.dev.character}`);
|
|
185
|
+
}
|
|
186
|
+
return samples.join(' | ');
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Set the active theme
|
|
190
|
+
* By default writes to .pennyfarthing/config.local.yaml (agent-writable, dogfooding-friendly)
|
|
191
|
+
* Use { legacy: true } to write to .claude/persona-config.local.yaml
|
|
192
|
+
* Use { global: true } to write to .claude/persona-config.yaml (project default)
|
|
193
|
+
* Returns the ThemeInfo if successful, throws if theme not found
|
|
194
|
+
*/
|
|
195
|
+
export function setTheme(themeName, projectRoot, options = {}) {
|
|
196
|
+
const themes = getThemes(projectRoot);
|
|
197
|
+
const theme = themes.find(t => t.id === themeName);
|
|
198
|
+
if (!theme) {
|
|
199
|
+
const available = themes.map(t => t.id).join(', ');
|
|
200
|
+
throw new Error(`Theme '${themeName}' not found. Available themes: ${available}`);
|
|
201
|
+
}
|
|
202
|
+
let configPath;
|
|
203
|
+
let header;
|
|
204
|
+
if (options.global) {
|
|
205
|
+
// Project default - shared with team
|
|
206
|
+
configPath = join(projectRoot, '.claude/persona-config.yaml');
|
|
207
|
+
header = '# Pennyfarthing Persona Configuration (Project Default)\n\n';
|
|
208
|
+
}
|
|
209
|
+
else if (options.legacy) {
|
|
210
|
+
// Legacy local config location
|
|
211
|
+
configPath = join(projectRoot, '.claude/persona-config.local.yaml');
|
|
212
|
+
header = '# Pennyfarthing Persona Configuration (Local User Preference)\n# This file is gitignored - your personal theme choice\n\n';
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
// Default: .pennyfarthing/ directory (agent-writable, dogfooding-friendly)
|
|
216
|
+
configPath = getPennyfarthingConfigPath(projectRoot);
|
|
217
|
+
header = '# Pennyfarthing Local Configuration\n# This file is gitignored - your personal preferences\n# Agents can write to this file during dogfooding\n\n';
|
|
218
|
+
}
|
|
219
|
+
// Ensure parent directory exists
|
|
220
|
+
const configDir = dirname(configPath);
|
|
221
|
+
if (!existsSync(configDir)) {
|
|
222
|
+
mkdirSync(configDir, { recursive: true });
|
|
223
|
+
}
|
|
224
|
+
// Read existing config or create new one
|
|
225
|
+
let config = {};
|
|
226
|
+
if (existsSync(configPath)) {
|
|
227
|
+
try {
|
|
228
|
+
const content = readFileSync(configPath, 'utf8');
|
|
229
|
+
config = YAML.parse(content) || {};
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
// If parse fails, start fresh
|
|
233
|
+
config = {};
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// Update theme
|
|
237
|
+
config.theme = themeName;
|
|
238
|
+
// Write back with comment header
|
|
239
|
+
const yamlContent = YAML.stringify(config);
|
|
240
|
+
writeFileSync(configPath, header + yamlContent, 'utf8');
|
|
241
|
+
return theme;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Validate a theme name
|
|
245
|
+
*/
|
|
246
|
+
export function validateThemeName(name) {
|
|
247
|
+
if (!name) {
|
|
248
|
+
return { valid: false, error: 'Theme name is required' };
|
|
249
|
+
}
|
|
250
|
+
if (name !== name.toLowerCase()) {
|
|
251
|
+
return { valid: false, error: 'Theme name must be lowercase' };
|
|
252
|
+
}
|
|
253
|
+
if (/\s/.test(name)) {
|
|
254
|
+
return { valid: false, error: 'Theme name cannot contain spaces (use hyphens instead)' };
|
|
255
|
+
}
|
|
256
|
+
if (!/^[a-z][a-z0-9-]*$/.test(name)) {
|
|
257
|
+
return { valid: false, error: 'Theme name must start with a letter and contain only lowercase letters, numbers, and hyphens' };
|
|
258
|
+
}
|
|
259
|
+
return { valid: true };
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Get the path to a theme file (built-in or custom)
|
|
263
|
+
*/
|
|
264
|
+
export function getThemeFilePath(themeId) {
|
|
265
|
+
// Check built-in themes first
|
|
266
|
+
try {
|
|
267
|
+
const builtInPath = join(getThemesDir(), `${themeId}.yaml`);
|
|
268
|
+
if (existsSync(builtInPath)) {
|
|
269
|
+
return builtInPath;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
// Built-in dir not found
|
|
274
|
+
}
|
|
275
|
+
// Check project-level
|
|
276
|
+
const projectPath = join(getProjectCustomThemesDir(process.cwd()), `${themeId}.yaml`);
|
|
277
|
+
if (existsSync(projectPath)) {
|
|
278
|
+
return projectPath;
|
|
279
|
+
}
|
|
280
|
+
// Check user-level
|
|
281
|
+
const userPath = join(getUserCustomThemesDir(), `${themeId}.yaml`);
|
|
282
|
+
if (existsSync(userPath)) {
|
|
283
|
+
return userPath;
|
|
284
|
+
}
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Create a new custom theme
|
|
289
|
+
* Returns the path to the created theme file
|
|
290
|
+
*/
|
|
291
|
+
export function createTheme(themeName, projectRoot, options = {}) {
|
|
292
|
+
const { baseTheme = 'minimalist', userLevel = false } = options;
|
|
293
|
+
// Validate theme name
|
|
294
|
+
const validation = validateThemeName(themeName);
|
|
295
|
+
if (!validation.valid) {
|
|
296
|
+
throw new Error(validation.error);
|
|
297
|
+
}
|
|
298
|
+
// Check if theme already exists
|
|
299
|
+
const existingThemes = getThemes(projectRoot);
|
|
300
|
+
if (existingThemes.some(t => t.id === themeName)) {
|
|
301
|
+
throw new Error(`Theme '${themeName}' already exists`);
|
|
302
|
+
}
|
|
303
|
+
// Find base theme file
|
|
304
|
+
const baseThemePath = getThemeFilePath(baseTheme);
|
|
305
|
+
if (!baseThemePath) {
|
|
306
|
+
const available = existingThemes.map(t => t.id).join(', ');
|
|
307
|
+
throw new Error(`Base theme '${baseTheme}' not found. Available themes: ${available}`);
|
|
308
|
+
}
|
|
309
|
+
// Determine target directory
|
|
310
|
+
const targetDir = userLevel
|
|
311
|
+
? getUserCustomThemesDir()
|
|
312
|
+
: getProjectCustomThemesDir(projectRoot);
|
|
313
|
+
// Create directory if needed
|
|
314
|
+
if (!existsSync(targetDir)) {
|
|
315
|
+
mkdirSync(targetDir, { recursive: true });
|
|
316
|
+
}
|
|
317
|
+
// Read base theme content
|
|
318
|
+
const baseContent = readFileSync(baseThemePath, 'utf8');
|
|
319
|
+
const baseData = YAML.parse(baseContent);
|
|
320
|
+
// Update theme metadata
|
|
321
|
+
baseData.theme.name = themeName.charAt(0).toUpperCase() + themeName.slice(1).replace(/-/g, ' ');
|
|
322
|
+
baseData.theme.description = `Custom theme based on ${baseTheme}`;
|
|
323
|
+
// Write new theme file
|
|
324
|
+
const targetPath = join(targetDir, `${themeName}.yaml`);
|
|
325
|
+
const header = `# Custom Theme: ${themeName}\n# Based on: ${baseTheme}\n# Edit this file to customize your agent personas\n\n`;
|
|
326
|
+
const yamlContent = YAML.stringify(baseData);
|
|
327
|
+
writeFileSync(targetPath, header + yamlContent, 'utf8');
|
|
328
|
+
return targetPath;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* All 10 required agent types for a complete theme
|
|
332
|
+
*/
|
|
333
|
+
const REQUIRED_AGENTS = [
|
|
334
|
+
'orchestrator',
|
|
335
|
+
'sm',
|
|
336
|
+
'tea',
|
|
337
|
+
'dev',
|
|
338
|
+
'reviewer',
|
|
339
|
+
'architect',
|
|
340
|
+
'pm',
|
|
341
|
+
'tech-writer',
|
|
342
|
+
'ux-designer',
|
|
343
|
+
'devops'
|
|
344
|
+
];
|
|
345
|
+
/**
|
|
346
|
+
* Validate a theme object has all required fields and agents
|
|
347
|
+
* Used to validate AI-generated themes before writing to file
|
|
348
|
+
*/
|
|
349
|
+
export function validateThemeSchema(themeData) {
|
|
350
|
+
const errors = [];
|
|
351
|
+
// Check if themeData is an object
|
|
352
|
+
if (!themeData || typeof themeData !== 'object') {
|
|
353
|
+
return { valid: false, errors: ['Theme data must be an object'] };
|
|
354
|
+
}
|
|
355
|
+
const data = themeData;
|
|
356
|
+
// Check theme section
|
|
357
|
+
if (!data.theme || typeof data.theme !== 'object') {
|
|
358
|
+
errors.push('Missing theme section');
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
const theme = data.theme;
|
|
362
|
+
if (!theme.name) {
|
|
363
|
+
errors.push('Missing theme.name');
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
// Check agents section
|
|
367
|
+
if (!data.agents || typeof data.agents !== 'object') {
|
|
368
|
+
errors.push('Missing agents section');
|
|
369
|
+
return { valid: false, errors };
|
|
370
|
+
}
|
|
371
|
+
const agents = data.agents;
|
|
372
|
+
// Check all required agents are present with required fields
|
|
373
|
+
for (const agentType of REQUIRED_AGENTS) {
|
|
374
|
+
const agent = agents[agentType];
|
|
375
|
+
if (!agent || typeof agent !== 'object') {
|
|
376
|
+
errors.push(`Missing required agent: ${agentType}`);
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
const agentData = agent;
|
|
380
|
+
// Check required fields for each agent
|
|
381
|
+
if (!agentData.character) {
|
|
382
|
+
errors.push(`Agent ${agentType} missing required field: character`);
|
|
383
|
+
}
|
|
384
|
+
if (!agentData.style) {
|
|
385
|
+
errors.push(`Agent ${agentType} missing required field: style`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (errors.length > 0) {
|
|
389
|
+
return { valid: false, errors };
|
|
390
|
+
}
|
|
391
|
+
return { valid: true };
|
|
392
|
+
}
|
|
393
|
+
//# sourceMappingURL=themes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.js","sourceRoot":"","sources":["../../../src/cli/utils/themes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for BL-1: Store theme preference in local settings
|
|
3
|
+
*
|
|
4
|
+
* These tests verify:
|
|
5
|
+
* - getCurrentTheme() checks local config first, falls back to shared
|
|
6
|
+
* - setTheme() writes to local config by default
|
|
7
|
+
* - setTheme() with global option writes to shared config
|
|
8
|
+
*
|
|
9
|
+
* Run with: npm test
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=themes.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.test.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/themes.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for BL-1: Store theme preference in local settings
|
|
3
|
+
*
|
|
4
|
+
* These tests verify:
|
|
5
|
+
* - getCurrentTheme() checks local config first, falls back to shared
|
|
6
|
+
* - setTheme() writes to local config by default
|
|
7
|
+
* - setTheme() with global option writes to shared config
|
|
8
|
+
*
|
|
9
|
+
* Run with: npm test
|
|
10
|
+
*/
|
|
11
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
12
|
+
import assert from 'node:assert';
|
|
13
|
+
import { existsSync, mkdirSync, writeFileSync, rmSync, readFileSync } from 'fs';
|
|
14
|
+
import { join } from 'path';
|
|
15
|
+
import { tmpdir } from 'os';
|
|
16
|
+
import { stringify as yamlStringify, parse as yamlParse } from 'yaml';
|
|
17
|
+
// Import functions to test
|
|
18
|
+
import { getCurrentTheme, setTheme } from './themes.js';
|
|
19
|
+
describe('Theme Local Settings (BL-1)', () => {
|
|
20
|
+
let testDir;
|
|
21
|
+
let claudeDir;
|
|
22
|
+
let themesDir;
|
|
23
|
+
// Minimal valid theme for testing
|
|
24
|
+
const testTheme = {
|
|
25
|
+
theme: { name: 'Test Theme', description: 'Test theme for unit tests' },
|
|
26
|
+
agents: {
|
|
27
|
+
orchestrator: { character: 'Test Orchestrator', style: 'test' },
|
|
28
|
+
sm: { character: 'Test SM', style: 'test' },
|
|
29
|
+
tea: { character: 'Test TEA', style: 'test' },
|
|
30
|
+
dev: { character: 'Test Dev', style: 'test' },
|
|
31
|
+
reviewer: { character: 'Test Reviewer', style: 'test' },
|
|
32
|
+
architect: { character: 'Test Architect', style: 'test' },
|
|
33
|
+
pm: { character: 'Test PM', style: 'test' },
|
|
34
|
+
'tech-writer': { character: 'Test Writer', style: 'test' },
|
|
35
|
+
'ux-designer': { character: 'Test UX', style: 'test' },
|
|
36
|
+
devops: { character: 'Test DevOps', style: 'test' }
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
// Create a temporary project directory for each test
|
|
41
|
+
testDir = join(tmpdir(), `pennyfarthing-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
42
|
+
claudeDir = join(testDir, '.claude');
|
|
43
|
+
themesDir = join(claudeDir, 'pennyfarthing/themes');
|
|
44
|
+
mkdirSync(themesDir, { recursive: true });
|
|
45
|
+
// Create a test theme so setTheme can find it
|
|
46
|
+
writeFileSync(join(themesDir, 'test-theme.yaml'), yamlStringify(testTheme));
|
|
47
|
+
});
|
|
48
|
+
afterEach(() => {
|
|
49
|
+
// Clean up test directory
|
|
50
|
+
if (existsSync(testDir)) {
|
|
51
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
describe('getCurrentTheme() local precedence', () => {
|
|
55
|
+
it('should return local theme when both local and shared exist', () => {
|
|
56
|
+
// Setup: local config with "star-trek", shared config with "discworld"
|
|
57
|
+
const localConfig = { theme: 'star-trek' };
|
|
58
|
+
const sharedConfig = { theme: 'discworld' };
|
|
59
|
+
writeFileSync(join(claudeDir, 'persona-config.local.yaml'), yamlStringify(localConfig));
|
|
60
|
+
writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify(sharedConfig));
|
|
61
|
+
// Act
|
|
62
|
+
const result = getCurrentTheme(testDir);
|
|
63
|
+
// Assert: should prefer local over shared
|
|
64
|
+
assert.strictEqual(result, 'star-trek', 'Should return local theme when both exist');
|
|
65
|
+
});
|
|
66
|
+
it('should fall back to shared theme when local does not exist', () => {
|
|
67
|
+
// Setup: only shared config
|
|
68
|
+
const sharedConfig = { theme: 'discworld' };
|
|
69
|
+
writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify(sharedConfig));
|
|
70
|
+
// Act
|
|
71
|
+
const result = getCurrentTheme(testDir);
|
|
72
|
+
// Assert: should use shared config
|
|
73
|
+
assert.strictEqual(result, 'discworld', 'Should fall back to shared theme');
|
|
74
|
+
});
|
|
75
|
+
it('should return null when neither local nor shared exist', () => {
|
|
76
|
+
// Setup: no config files (just empty .claude dir)
|
|
77
|
+
// Act
|
|
78
|
+
const result = getCurrentTheme(testDir);
|
|
79
|
+
// Assert
|
|
80
|
+
assert.strictEqual(result, null, 'Should return null when no config exists');
|
|
81
|
+
});
|
|
82
|
+
it('should prefer local even when local theme is different', () => {
|
|
83
|
+
// Setup: local explicitly set to minimalist, shared is elaborate theme
|
|
84
|
+
const localConfig = { theme: 'minimalist' };
|
|
85
|
+
const sharedConfig = { theme: 'shakespeare' };
|
|
86
|
+
writeFileSync(join(claudeDir, 'persona-config.local.yaml'), yamlStringify(localConfig));
|
|
87
|
+
writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify(sharedConfig));
|
|
88
|
+
// Act
|
|
89
|
+
const result = getCurrentTheme(testDir);
|
|
90
|
+
// Assert
|
|
91
|
+
assert.strictEqual(result, 'minimalist', 'Should always prefer local config');
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
describe('setTheme() writes to local config', () => {
|
|
95
|
+
it('should write to local config file by default', () => {
|
|
96
|
+
// Setup: create shared config with a different theme
|
|
97
|
+
const sharedConfig = { theme: 'other-theme' };
|
|
98
|
+
writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify(sharedConfig));
|
|
99
|
+
// Act: set theme using our test theme
|
|
100
|
+
setTheme('test-theme', testDir);
|
|
101
|
+
// Assert: local config should exist with the new theme
|
|
102
|
+
const localPath = join(claudeDir, 'persona-config.local.yaml');
|
|
103
|
+
assert.ok(existsSync(localPath), 'setTheme should write to persona-config.local.yaml');
|
|
104
|
+
const localContent = yamlParse(readFileSync(localPath, 'utf-8'));
|
|
105
|
+
assert.strictEqual(localContent.theme, 'test-theme', 'Local config should have the theme');
|
|
106
|
+
});
|
|
107
|
+
it('should not modify shared config when setting theme locally', () => {
|
|
108
|
+
// Setup: shared config with original theme
|
|
109
|
+
const originalSharedConfig = { theme: 'original-theme' };
|
|
110
|
+
writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify(originalSharedConfig));
|
|
111
|
+
// Act: set theme locally
|
|
112
|
+
setTheme('test-theme', testDir);
|
|
113
|
+
// Assert: shared config should be unchanged
|
|
114
|
+
const sharedContent = yamlParse(readFileSync(join(claudeDir, 'persona-config.yaml'), 'utf-8'));
|
|
115
|
+
assert.strictEqual(sharedContent.theme, 'original-theme', 'Shared config should remain unchanged when setting local theme');
|
|
116
|
+
});
|
|
117
|
+
it('should write to shared config when global option is true', () => {
|
|
118
|
+
// Setup: shared config with original theme
|
|
119
|
+
const sharedConfig = { theme: 'original-theme' };
|
|
120
|
+
writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify(sharedConfig));
|
|
121
|
+
// Act: set theme with global option
|
|
122
|
+
setTheme('test-theme', testDir, { global: true });
|
|
123
|
+
// Assert: shared config should be updated
|
|
124
|
+
const sharedContent = yamlParse(readFileSync(join(claudeDir, 'persona-config.yaml'), 'utf-8'));
|
|
125
|
+
assert.strictEqual(sharedContent.theme, 'test-theme', 'Global option should update shared config');
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
describe('Theme precedence integration', () => {
|
|
129
|
+
it('should allow multiple users to have different themes', () => {
|
|
130
|
+
// This test simulates the scenario where:
|
|
131
|
+
// - Shared config has team default "discworld"
|
|
132
|
+
// - User A sets local to "star-trek"
|
|
133
|
+
// - getCurrentTheme should return "star-trek" for User A
|
|
134
|
+
// Setup: shared team default
|
|
135
|
+
writeFileSync(join(claudeDir, 'persona-config.yaml'), yamlStringify({ theme: 'discworld' }));
|
|
136
|
+
// User A sets their local preference
|
|
137
|
+
writeFileSync(join(claudeDir, 'persona-config.local.yaml'), yamlStringify({ theme: 'star-trek' }));
|
|
138
|
+
// Assert: User A sees their local theme
|
|
139
|
+
const result = getCurrentTheme(testDir);
|
|
140
|
+
assert.strictEqual(result, 'star-trek', 'User should see their local theme preference');
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
//# sourceMappingURL=themes.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.test.js","sourceRoot":"","sources":["../../../src/cli/utils/themes.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the package version from VERSION file or package.json
|
|
3
|
+
*/
|
|
4
|
+
export declare function getPackageVersion(): string;
|
|
5
|
+
/**
|
|
6
|
+
* Get the distributable package directory path
|
|
7
|
+
* This contains all files that get installed to target projects
|
|
8
|
+
*/
|
|
9
|
+
export declare function getAssetsPath(): string;
|
|
10
|
+
//# sourceMappingURL=version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/version.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAoC1C;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAgBtC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'fs';
|
|
2
|
+
import { join, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = dirname(__filename);
|
|
6
|
+
/**
|
|
7
|
+
* Get the package version from VERSION file or package.json
|
|
8
|
+
*/
|
|
9
|
+
export function getPackageVersion() {
|
|
10
|
+
// Try VERSION file first (relative to compiled output location)
|
|
11
|
+
const versionPaths = [
|
|
12
|
+
join(__dirname, '../../../VERSION'), // From dist/cli/utils/
|
|
13
|
+
join(__dirname, '../../VERSION'), // Fallback
|
|
14
|
+
join(process.cwd(), 'VERSION') // If running from package root
|
|
15
|
+
];
|
|
16
|
+
for (const versionPath of versionPaths) {
|
|
17
|
+
if (existsSync(versionPath)) {
|
|
18
|
+
try {
|
|
19
|
+
return readFileSync(versionPath, 'utf8').trim();
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Fallback to package.json
|
|
27
|
+
const packagePaths = [
|
|
28
|
+
join(__dirname, '../../../package.json'),
|
|
29
|
+
join(__dirname, '../../package.json')
|
|
30
|
+
];
|
|
31
|
+
for (const packagePath of packagePaths) {
|
|
32
|
+
if (existsSync(packagePath)) {
|
|
33
|
+
try {
|
|
34
|
+
const pkg = JSON.parse(readFileSync(packagePath, 'utf8'));
|
|
35
|
+
return pkg.version;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return '0.0.0';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get the distributable package directory path
|
|
46
|
+
* This contains all files that get installed to target projects
|
|
47
|
+
*/
|
|
48
|
+
export function getAssetsPath() {
|
|
49
|
+
const searchPaths = [
|
|
50
|
+
join(__dirname, '../../../../../pennyfarthing-dist'), // From packages/core/dist/cli/utils/ to package root
|
|
51
|
+
join(__dirname, '../../../../pennyfarthing-dist'),
|
|
52
|
+
join(__dirname, '../../../pennyfarthing-dist'),
|
|
53
|
+
join(__dirname, '../../pennyfarthing-dist'),
|
|
54
|
+
join(process.cwd(), 'pennyfarthing-dist')
|
|
55
|
+
];
|
|
56
|
+
for (const searchPath of searchPaths) {
|
|
57
|
+
if (existsSync(searchPath)) {
|
|
58
|
+
return searchPath;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
throw new Error('Package directory not found (looked for pennyfarthing-dist/)');
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=version.js.map
|