@pennyfarthing/core 11.3.8 → 11.5.0-alpha.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 +1 -1
- package/package.json +4 -1
- package/packages/core/dist/cli/commands/cyclist.js +1 -1
- package/packages/core/dist/cli/commands/cyclist.js.map +1 -1
- package/packages/core/dist/cli/commands/cyclist.test.js +3 -3
- package/packages/core/dist/cli/commands/cyclist.test.js.map +1 -1
- package/packages/core/dist/cli/commands/doctor-persona-config-false-negative.test.d.ts +22 -0
- package/packages/core/dist/cli/commands/doctor-persona-config-false-negative.test.d.ts.map +1 -0
- package/packages/core/dist/cli/commands/doctor-persona-config-false-negative.test.js +161 -0
- package/packages/core/dist/cli/commands/doctor-persona-config-false-negative.test.js.map +1 -0
- package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/doctor.js +101 -33
- package/packages/core/dist/cli/commands/doctor.js.map +1 -1
- package/packages/core/dist/cli/commands/init.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/init.js +33 -13
- package/packages/core/dist/cli/commands/init.js.map +1 -1
- package/packages/core/dist/cli/commands/stale-artifacts-cleanup.test.d.ts +17 -0
- package/packages/core/dist/cli/commands/stale-artifacts-cleanup.test.d.ts.map +1 -0
- package/packages/core/dist/cli/commands/stale-artifacts-cleanup.test.js +470 -0
- package/packages/core/dist/cli/commands/stale-artifacts-cleanup.test.js.map +1 -0
- package/packages/core/dist/cli/commands/update.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/update.js +68 -17
- package/packages/core/dist/cli/commands/update.js.map +1 -1
- 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 +229 -0
- package/packages/core/dist/cli/cyclist-migration.test.js.map +1 -0
- package/packages/core/dist/cli/index.js +2 -21
- package/packages/core/dist/cli/index.js.map +1 -1
- package/packages/core/dist/cli/utils/node-modules.d.ts +7 -0
- package/packages/core/dist/cli/utils/node-modules.d.ts.map +1 -1
- package/packages/core/dist/cli/utils/node-modules.js +39 -0
- package/packages/core/dist/cli/utils/node-modules.js.map +1 -1
- package/packages/core/dist/cli/utils/settings.d.ts +1 -1
- package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
- package/packages/core/dist/cli/utils/settings.js +24 -21
- package/packages/core/dist/cli/utils/settings.js.map +1 -1
- package/packages/core/dist/cli/utils/stale-artifacts.d.ts +59 -0
- package/packages/core/dist/cli/utils/stale-artifacts.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/stale-artifacts.js +163 -0
- package/packages/core/dist/cli/utils/stale-artifacts.js.map +1 -0
- package/packages/core/dist/public/css/react.css +1 -1
- package/packages/core/dist/public/js/react/react.js +39 -39
- 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/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/theme-detail.test.d.ts.map +1 -0
- package/packages/core/dist/scripts/theme-detail.test.js.map +1 -0
- package/packages/core/dist/server/api/context.d.ts.map +1 -1
- package/packages/core/dist/server/api/context.js +23 -5
- package/packages/core/dist/server/api/context.js.map +1 -1
- package/packages/core/dist/server/api/index.d.ts +0 -1
- package/packages/core/dist/server/api/index.d.ts.map +1 -1
- package/packages/core/dist/server/api/index.js +0 -2
- package/packages/core/dist/server/api/index.js.map +1 -1
- package/packages/core/dist/server/api/settings.d.ts.map +1 -1
- package/packages/core/dist/server/api/settings.js +6 -0
- package/packages/core/dist/server/api/settings.js.map +1 -1
- package/packages/core/dist/server/otlp-receiver.d.ts +0 -4
- package/packages/core/dist/server/otlp-receiver.d.ts.map +1 -1
- package/packages/core/dist/server/otlp-receiver.js +0 -18
- package/packages/core/dist/server/otlp-receiver.js.map +1 -1
- package/packages/core/dist/server/otlp-receiver.test.js +0 -27
- package/packages/core/dist/server/otlp-receiver.test.js.map +1 -1
- package/packages/core/dist/server/server.d.ts +1 -1
- package/packages/core/dist/server/server.d.ts.map +1 -1
- package/packages/core/dist/server/server.js +2 -4
- package/packages/core/dist/server/server.js.map +1 -1
- package/packages/core/dist/workflow/cross-entity-validation.d.ts.map +1 -1
- package/packages/core/dist/workflow/cross-entity-validation.js.map +1 -1
- package/packages/core/src/public/App.tsx +354 -0
- package/packages/core/src/public/components/AgentLoadDialog.tsx +202 -0
- package/packages/core/src/public/components/AgentPopup.tsx +308 -0
- package/packages/core/src/public/components/ApprovalModal/ApprovalModal.css +35 -0
- package/packages/core/src/public/components/ApprovalModal/index.tsx +632 -0
- package/packages/core/src/public/components/BikeRackIndex.tsx +53 -0
- package/packages/core/src/public/components/BikeRackWorkspace.tsx +215 -0
- package/packages/core/src/public/components/CommandPalette.tsx +554 -0
- package/packages/core/src/public/components/ConfirmDialog.tsx +168 -0
- package/packages/core/src/public/components/ContextIndicator/ContextIndicator.css +85 -0
- package/packages/core/src/public/components/ContextIndicator/index.tsx +330 -0
- package/packages/core/src/public/components/ContextSparkline.tsx +56 -0
- package/packages/core/src/public/components/ControlBar.tsx +636 -0
- package/packages/core/src/public/components/DeadCodeDialog.tsx +169 -0
- package/packages/core/src/public/components/DiffViewer.tsx +585 -0
- package/packages/core/src/public/components/DockviewWorkspace.tsx +745 -0
- package/packages/core/src/public/components/Editor.tsx +630 -0
- package/packages/core/src/public/components/ErrorBoundary.tsx +67 -0
- package/packages/core/src/public/components/FileTree.tsx +379 -0
- package/packages/core/src/public/components/FullFileTree.tsx +237 -0
- package/packages/core/src/public/components/HealthGauge.tsx +181 -0
- package/packages/core/src/public/components/Message.tsx +225 -0
- package/packages/core/src/public/components/MessageList.tsx +98 -0
- package/packages/core/src/public/components/MessageView.tsx +400 -0
- package/packages/core/src/public/components/ModeSwitch/ModeSwitch.css +165 -0
- package/packages/core/src/public/components/ModeSwitch/index.tsx +372 -0
- package/packages/core/src/public/components/PersonaHeader.tsx +242 -0
- package/packages/core/src/public/components/ProjectInfoBar.tsx +45 -0
- package/packages/core/src/public/components/QuickActions.tsx +267 -0
- package/packages/core/src/public/components/SpanTimeline.tsx +352 -0
- package/packages/core/src/public/components/StandalonePanel.tsx +80 -0
- package/packages/core/src/public/components/StatsStrip.tsx +162 -0
- package/packages/core/src/public/components/StreamingContent.tsx +77 -0
- package/packages/core/src/public/components/SubagentSpan.tsx +180 -0
- package/packages/core/src/public/components/TandemPortrait.tsx +72 -0
- package/packages/core/src/public/components/ToolCallBlock.tsx +252 -0
- package/packages/core/src/public/components/ToolStack.tsx +209 -0
- package/packages/core/src/public/components/ToolStatus.tsx +57 -0
- package/packages/core/src/public/components/dialogs/CodeMarkersDialog.tsx +169 -0
- package/packages/core/src/public/components/dialogs/ComplexityDialog.tsx +163 -0
- package/packages/core/src/public/components/dialogs/DependenciesDialog.tsx +120 -0
- package/packages/core/src/public/components/dialogs/HotspotsDialog.tsx +451 -0
- package/packages/core/src/public/components/dialogs/ToolDialog.tsx +43 -0
- package/packages/core/src/public/components/panel-registry.ts +13 -0
- package/packages/core/src/public/components/panels/ACPanel.tsx +93 -0
- package/packages/core/src/public/components/panels/AcceptanceCriteriaPanel.tsx +104 -0
- package/packages/core/src/public/components/panels/AuditLogPanel.tsx +489 -0
- package/packages/core/src/public/components/panels/BikeLanePanel.tsx +214 -0
- package/packages/core/src/public/components/panels/DebugPanel.tsx +344 -0
- package/packages/core/src/public/components/panels/DiffView.tsx +109 -0
- package/packages/core/src/public/components/panels/DiffsPanel.tsx +56 -0
- package/packages/core/src/public/components/panels/GitPanel.tsx +260 -0
- package/packages/core/src/public/components/panels/HotspotsPanel.tsx +365 -0
- package/packages/core/src/public/components/panels/MessageFeed.tsx +39 -0
- package/packages/core/src/public/components/panels/MessagePanel.tsx +497 -0
- package/packages/core/src/public/components/panels/ProgressPanel.tsx +189 -0
- package/packages/core/src/public/components/panels/SettingsPanel.tsx +161 -0
- package/packages/core/src/public/components/panels/SprintPanel.tsx +731 -0
- package/packages/core/src/public/components/panels/TandemPanel.tsx +104 -0
- package/packages/core/src/public/components/panels/TaskTracker.tsx +48 -0
- package/packages/core/src/public/components/panels/TeamPanel.tsx +64 -0
- package/packages/core/src/public/components/panels/TeamRoster.tsx +67 -0
- package/packages/core/src/public/components/panels/TodoPanel.tsx +142 -0
- package/packages/core/src/public/components/panels/WorkflowPanel.tsx +224 -0
- package/packages/core/src/public/components/panels/index.ts +23 -0
- package/packages/core/src/public/components/ui/alert-dialog.tsx +139 -0
- package/packages/core/src/public/components/ui/badge.tsx +36 -0
- package/packages/core/src/public/components/ui/button.tsx +57 -0
- package/packages/core/src/public/components/ui/checkbox.tsx +28 -0
- package/packages/core/src/public/components/ui/collapsible.tsx +9 -0
- package/packages/core/src/public/components/ui/command.tsx +151 -0
- package/packages/core/src/public/components/ui/dialog.tsx +120 -0
- package/packages/core/src/public/components/ui/popover.tsx +31 -0
- package/packages/core/src/public/components/ui/progress.tsx +28 -0
- package/packages/core/src/public/components/ui/scroll-area.tsx +46 -0
- package/packages/core/src/public/components/ui/select.tsx +157 -0
- package/packages/core/src/public/components/ui/separator.tsx +29 -0
- package/packages/core/src/public/components/ui/skeleton.tsx +15 -0
- package/packages/core/src/public/components/ui/toggle-group.tsx +59 -0
- package/packages/core/src/public/components/ui/toggle.tsx +43 -0
- package/packages/core/src/public/components/ui/tooltip.tsx +30 -0
- package/packages/core/src/public/contexts/ClaudeContext.tsx +311 -0
- package/packages/core/src/public/contexts/MessageQueueContext.tsx +143 -0
- package/packages/core/src/public/css/theme-browser.css +550 -0
- package/packages/core/src/public/css/theme-system.css +630 -0
- package/packages/core/src/public/hooks/index.ts +46 -0
- package/packages/core/src/public/hooks/useAgentLoad.ts +105 -0
- package/packages/core/src/public/hooks/useClaude.ts +234 -0
- package/packages/core/src/public/hooks/useCodeMarkers.ts +101 -0
- package/packages/core/src/public/hooks/useColorScheme.ts +42 -0
- package/packages/core/src/public/hooks/useCommandHistory.ts +99 -0
- package/packages/core/src/public/hooks/useComplexity.ts +80 -0
- package/packages/core/src/public/hooks/useDeadCode.ts +99 -0
- package/packages/core/src/public/hooks/useDependencies.ts +82 -0
- package/packages/core/src/public/hooks/useDiffs.ts +143 -0
- package/packages/core/src/public/hooks/useFileBrowser.ts +73 -0
- package/packages/core/src/public/hooks/useFocusPanel.ts +137 -0
- package/packages/core/src/public/hooks/useGitStatus.ts +233 -0
- package/packages/core/src/public/hooks/useHealthScore.ts +71 -0
- package/packages/core/src/public/hooks/useHotspots.ts +123 -0
- package/packages/core/src/public/hooks/useLayoutPersistence.ts +141 -0
- package/packages/core/src/public/hooks/useMarkdownParser.ts +36 -0
- package/packages/core/src/public/hooks/useMarkerActions.ts +234 -0
- package/packages/core/src/public/hooks/useMessageQueue.ts +380 -0
- package/packages/core/src/public/hooks/useMessageStream.ts +131 -0
- package/packages/core/src/public/hooks/usePersona.ts +112 -0
- package/packages/core/src/public/hooks/usePlanModeExit.ts +105 -0
- package/packages/core/src/public/hooks/useResponsiveLayout.ts +173 -0
- package/packages/core/src/public/hooks/useSprint.ts +166 -0
- package/packages/core/src/public/hooks/useStatsStrip.ts +204 -0
- package/packages/core/src/public/hooks/useStory.ts +135 -0
- package/packages/core/src/public/hooks/useSubagentHelper.ts +64 -0
- package/packages/core/src/public/hooks/useSyntaxHighlighter.ts +52 -0
- package/packages/core/src/public/hooks/useTabCompletion.ts +124 -0
- package/packages/core/src/public/hooks/useTandemObservations.ts +165 -0
- package/packages/core/src/public/hooks/useTeamMembers.ts +273 -0
- package/packages/core/src/public/hooks/useTodos.ts +93 -0
- package/packages/core/src/public/hooks/useUserAvatar.ts +54 -0
- package/packages/core/src/public/images/cyclist-dark.png +0 -0
- package/packages/core/src/public/images/cyclist-light.png +0 -0
- package/packages/core/src/public/images/cyclist-tandem-source.png +0 -0
- package/packages/core/src/public/index.html +14 -0
- package/packages/core/src/public/index.tsx +10 -0
- package/packages/core/src/public/lib/utils.ts +6 -0
- package/packages/core/src/public/styles/dockview-theme.css +376 -0
- package/packages/core/src/public/styles/tailwind.css +4353 -0
- package/packages/core/src/public/types/message.ts +51 -0
- package/packages/core/src/public/utils/avatar-service.ts +73 -0
- package/packages/core/src/public/utils/color-presets.ts +940 -0
- package/packages/core/src/public/utils/font-presets.ts +362 -0
- package/packages/core/src/public/utils/formatDuration.ts +14 -0
- package/packages/core/src/public/utils/markdown.ts +249 -0
- package/packages/core/src/public/utils/messageFilters.ts +128 -0
- package/packages/core/src/public/utils/slash-commands.ts +341 -0
- package/packages/core/src/public/utils/subagent-display.ts +146 -0
- package/packages/core/src/public/utils/syntax.ts +219 -0
- package/packages/core/src/public/utils/toolIntentSummarizer.ts +199 -0
- package/packages/core/src/public/utils/toolStackGrouper.ts +106 -0
- package/packages/core/src/public/utils/toolTypeColors.ts +45 -0
- package/pennyfarthing-dist/guides/bikerack.md +94 -0
- package/pennyfarthing-dist/personas/themes/firefly.yaml +12 -12
- package/pennyfarthing-dist/pf/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/bellmode_hook.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/config.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/context.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/context.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/hooks.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/jira.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/jira_sync.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/output.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/patch_mode.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/session_start_hook.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/sprint.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/workflow.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bc/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/bc/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bc/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/bc/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bc/__pycache__/focus.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/bc/__pycache__/focus.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bc/__pycache__/split.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bc/cli.py +0 -2
- package/pennyfarthing-dist/pf/bc/focus.py +0 -2
- package/pennyfarthing-dist/pf/bikerack/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/audit_log_panel.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/background_panel.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/context_meter_footer.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/events.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/git_panel.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/launcher.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/portrait_resolver.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/story_detail_data.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/story_detail_screen.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/story_detail_widget.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/base_panel.py +0 -1
- package/pennyfarthing-dist/pf/bikerack/context_meter_footer.py +115 -35
- package/pennyfarthing-dist/pf/bikerack/events.py +1 -7
- package/pennyfarthing-dist/pf/bikerack/git_panel.py +273 -10
- package/pennyfarthing-dist/pf/bikerack/portrait_resolver.py +35 -2
- package/pennyfarthing-dist/pf/bikerack/progress_panel.py +54 -0
- package/pennyfarthing-dist/pf/bikerack/sprint_panel.py +116 -1
- package/pennyfarthing-dist/pf/bikerack/story_detail_screen.py +10 -105
- package/pennyfarthing-dist/pf/bikerack/story_detail_widget.py +167 -0
- package/pennyfarthing-dist/pf/bikerack/tui.py +141 -66
- package/pennyfarthing-dist/pf/bmad/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bmad/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bmad/cli.py +0 -1
- package/pennyfarthing-dist/pf/bmad/importer.py +0 -1
- package/pennyfarthing-dist/pf/bmad/parser.py +15 -10
- package/pennyfarthing-dist/pf/bmad/sync.py +1 -3
- package/pennyfarthing-dist/pf/bmad/test_parser.py +0 -4
- package/pennyfarthing-dist/pf/bmad/test_sync.py +0 -3
- package/pennyfarthing-dist/pf/brownfield/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/brownfield/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/brownfield/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/brownfield/__pycache__/discover.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/brownfield/cli.py +1 -1
- package/pennyfarthing-dist/pf/cli.py +145 -111
- package/pennyfarthing-dist/pf/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/common/__init__.py +2 -0
- package/pennyfarthing-dist/pf/common/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/common/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/common/__pycache__/config.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/common/__pycache__/config.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/common/__pycache__/output.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/common/__pycache__/output.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/common/__pycache__/pr_config.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/common/__pycache__/themes.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/common/config.py +43 -0
- package/pennyfarthing-dist/pf/common/pr_config.py +27 -2
- package/pennyfarthing-dist/pf/common/themes.py +7 -5
- package/pennyfarthing-dist/pf/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/complexity/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/complexity/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/consultation/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/consultation/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/consultation/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/consultation/__pycache__/dialogue_manager.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/context.py +1 -1
- package/pennyfarthing-dist/pf/deadcode/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/deadcode/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/deadcode/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/dependencies/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/epic/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/epic/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/epic/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/epic/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/git/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/git/__pycache__/create_branches.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/git/__pycache__/status_all.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/git/hooks_installer.py +7 -6
- package/pennyfarthing-dist/pf/git_group/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/git_group/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/git_group/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/git_group/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/handoff/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/handoff/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/handoff/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/handoff/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/handoff/__pycache__/gate_file.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/handoff/__pycache__/gate_runner.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/handoff/__pycache__/marker.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/handoff/__pycache__/phase_check.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/handoff/gate_file.py +5 -1
- package/pennyfarthing-dist/pf/healthscore/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/healthscore/__pycache__/analyze.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/healthscore/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/healthscore/__pycache__/models.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/healthscore/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/bell_mode.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/bell_mode.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/context_breaker.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/context_breaker.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/context_warning.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/context_warning.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/cyclist_pretooluse.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/cyclist_pretooluse.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/pre_edit_check.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/pre_edit_check.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/reflector_check.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/reflector_check.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/schema_validation.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/schema_validation.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/session_start.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/session_start.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/session_stop.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/sprint_yaml_validation.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/sprint_yaml_validation.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/statusline.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/statusline.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/statusline.py +11 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/analyze.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/models.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__init__.py +0 -6
- package/pennyfarthing-dist/pf/jira/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/bidirectional.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/claim.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/claim.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/client.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/client.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/compat.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/create.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/create.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/epic.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/epic.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/mappings.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/operations.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/operations.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/reconcile.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/story.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/story.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/sync.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/sync.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/claim.py +14 -44
- package/pennyfarthing-dist/pf/jira/cli.py +124 -14
- package/pennyfarthing-dist/pf/jira/client.py +51 -87
- package/pennyfarthing-dist/pf/jira/reconcile.py +1 -1
- package/pennyfarthing-dist/pf/jira/story.py +6 -4
- package/pennyfarthing-dist/pf/jira/sync.py +2 -2
- package/pennyfarthing-dist/pf/launch/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/launch/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/launch/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/launch/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/migration/__init__.py +1 -1
- package/pennyfarthing-dist/pf/migration/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/migration/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/migration/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/migration/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/migration/__pycache__/skill.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/migration/__pycache__/step.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/migration/__pycache__/validate.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/migration/cli.py +0 -1
- package/pennyfarthing-dist/pf/package/__init__.py +0 -0
- package/pennyfarthing-dist/pf/package/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/package/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/package/__pycache__/discovery.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/package/__pycache__/portraits.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/package/cli.py +186 -0
- package/pennyfarthing-dist/pf/package/discovery.py +130 -0
- package/pennyfarthing-dist/pf/package/portraits.py +243 -0
- package/pennyfarthing-dist/pf/preflight/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/preflight/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/preflight/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/preflight/__pycache__/finish.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/prime/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/prime/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/prime/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/prime/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/prime/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/prime/__pycache__/persona.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/prime/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/prime/__pycache__/tiers.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/prime/__pycache__/version_sentinel.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/prime/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/prime/loader.py +21 -7
- package/pennyfarthing-dist/pf/prime/workflow.py +11 -3
- package/pennyfarthing-dist/pf/release/__init__.py +0 -0
- package/pennyfarthing-dist/pf/release/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/release/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/release/__pycache__/deprecate.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/release/__pycache__/dry_run.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/release/cli.py +112 -0
- package/pennyfarthing-dist/pf/release/deprecate.py +187 -0
- package/pennyfarthing-dist/pf/release/dry_run.py +187 -0
- package/pennyfarthing-dist/pf/session/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/session/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/session/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/session/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/settings/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/settings/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/settings/__pycache__/settings.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/settings/settings.py +44 -8
- package/pennyfarthing-dist/pf/sprint/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/archive.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/archive.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/epic_add.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/epic_update.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/epic_update.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/import_epic.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/loader.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/shard_merge.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/status.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/status.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/story_add.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/story_add.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/story_update.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/validate_cmd.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/validator.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/validator.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/work.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/work.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/yaml_io.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/cli.py +1 -1
- package/pennyfarthing-dist/pf/sprint/loader.py +6 -74
- package/pennyfarthing-dist/pf/sprint/shard_merge.py +126 -0
- package/pennyfarthing-dist/pf/sprint/story_finish.py +18 -4
- package/pennyfarthing-dist/pf/sprint/validator.py +7 -7
- package/pennyfarthing-dist/pf/sprint/yaml_io.py +8 -53
- package/pennyfarthing-dist/pf/story/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/story/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/story/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/story/__pycache__/create.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/story/__pycache__/size.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/story/__pycache__/template.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_108_1_gate_migration.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_archive_epic.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_bc.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_bikerack.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_brownfield.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_cli_modules.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_cli_normalization.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_codemarkers.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_common.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_confidence_sm_evaluation.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_confidence_sm_gate.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_dialogue_manager.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_epic_shard_validation.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_git_utils.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_handoff_cli.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_handoff_e2e.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_sprint_panel.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_story_add.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_story_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_story_update.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_tiers.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_token_counting.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_topology_loader.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_tui_focus.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_tui_panel_persistence.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_validate_cmd.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_version_sentinel.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/test_cli_modules.py +32 -137
- package/pennyfarthing-dist/pf/tests/test_codemarkers.py +0 -15
- package/pennyfarthing-dist/pf/tests/test_dist_root.py +720 -0
- package/pennyfarthing-dist/pf/tests/test_package_structure.py +24 -70
- package/pennyfarthing-dist/pf/tests/test_sprint_validator.py +44 -0
- package/pennyfarthing-dist/pf/theme/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/theme/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/theme/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/theme/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/adapters/__pycache__/agent.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/adapters/__pycache__/schema.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/adapters/__pycache__/sprint.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/adapters/__pycache__/tandem_awareness.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/adapters/agent.py +11 -1
- package/pennyfarthing-dist/pf/validate/adapters/skill_command.py +15 -4
- package/pennyfarthing-dist/pf/validate/adapters/tandem_awareness.py +7 -1
- package/pennyfarthing-dist/pf/validate/adapters/team_mode.py +8 -2
- package/pennyfarthing-dist/pf/validate/adapters/workflow.py +12 -2
- package/pennyfarthing-dist/pf/workflow/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/workflow/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/workflow/__pycache__/cli.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/workflow/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/workflow/__pycache__/helpers.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/workflow/__pycache__/scale.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/workflow/__pycache__/scale.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/workflow/__pycache__/state.cpython-311.pyc +0 -0
- package/pennyfarthing-dist/pf/workflow/__pycache__/state.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pyproject.toml +1 -1
- package/pennyfarthing-dist/scripts/core/check-context.sh +2 -2
- package/pennyfarthing-dist/scripts/git/changelog-links.sh +216 -0
- package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/scripts/lib/README.md +0 -1
- package/pennyfarthing-dist/scripts/lib/find-root.sh +1 -1
- package/pennyfarthing-dist/scripts/misc/migrate_bmad_workflow.py +0 -1
- package/pennyfarthing-dist/scripts/portraits/generate-portraits.py +67 -13
- package/pennyfarthing-dist/scripts/portraits/generate-tandem-portraits.sh +7 -3
- package/pennyfarthing-dist/scripts/workflow/check.py +4 -6
- package/pennyfarthing-dist/scripts/workflow/complete-step.py +2 -2
- package/pennyfarthing-dist/skills/skill-registry.yaml +19 -0
- package/pennyfarthing-dist/workflows/patch.yaml +5 -6
- package/pennyfarthing-dist/workflows/tdd-tandem.yaml +27 -2
- package/packages/core/dist/workflow/__test_context_watch__/.session/.tandem-turn-counter +0 -1
- package/packages/core/dist/workflow/__test_context_watch__/.session/95-6-session.md +0 -3
- package/packages/core/dist/workflow/__test_context_watch__/.session/95-6-tandem-architect.md +0 -6
- package/packages/core/dist/workflow/__test_file_watch__/.session/95-4-tandem-architect.md +0 -6
- package/packages/core/dist/workflow/__test_file_watch__/workdir/trigger.ts +0 -1
- package/packages/core/dist/workflow/__test_tool_watch__/.session/95-5-tandem-architect.md +0 -6
- package/packages/core/dist/workflow/__test_tool_watch__/.session/95-5-tandem-toolcalls.jsonl +0 -1
- package/packages/core/dist/workflow/team-lifecycle.d.ts +0 -169
- package/packages/core/dist/workflow/team-lifecycle.d.ts.map +0 -1
- package/packages/core/dist/workflow/team-lifecycle.js +0 -217
- package/packages/core/dist/workflow/team-lifecycle.js.map +0 -1
- package/packages/core/dist/workflow/team-lifecycle.test.d.ts +0 -20
- package/packages/core/dist/workflow/team-lifecycle.test.d.ts.map +0 -1
- package/packages/core/dist/workflow/team-lifecycle.test.js +0 -966
- package/packages/core/dist/workflow/team-lifecycle.test.js.map +0 -1
- package/pennyfarthing-dist/pf/bikerack/background_panel.py +0 -162
- package/pennyfarthing-dist/pf/bikerack/changed_panel.py +0 -201
- package/pennyfarthing-dist/pf/brownfield/__main__.py +0 -8
- package/pennyfarthing-dist/pf/config.py +0 -21
- package/pennyfarthing-dist/pf/hooks.py +0 -32
- package/pennyfarthing-dist/pf/jira_bidirectional_sync.py +0 -37
- package/pennyfarthing-dist/pf/jira_epic_creation.py +0 -30
- package/pennyfarthing-dist/pf/jira_sync.py +0 -36
- package/pennyfarthing-dist/pf/jira_sync_story.py +0 -30
- package/pennyfarthing-dist/pf/migration/__main__.py +0 -10
- package/pennyfarthing-dist/pf/output.py +0 -37
- package/pennyfarthing-dist/pf/theme/__main__.py +0 -6
- package/pennyfarthing-dist/scripts/lib/background-tasks.sh +0 -177
|
@@ -0,0 +1,720 @@
|
|
|
1
|
+
"""Tests for get_dist_root() unified path resolution.
|
|
2
|
+
|
|
3
|
+
Stories 120-5, 120-7: Fix npm path resolution assuming monorepo layout.
|
|
4
|
+
|
|
5
|
+
These tests verify that pennyfarthing-dist/ can be located in both
|
|
6
|
+
monorepo development and npm-installed consumer contexts.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from unittest.mock import patch
|
|
13
|
+
|
|
14
|
+
import pytest
|
|
15
|
+
|
|
16
|
+
from pf.common.config import get_dist_root
|
|
17
|
+
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
19
|
+
# Fixtures
|
|
20
|
+
# ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@pytest.fixture
|
|
24
|
+
def monorepo_layout(tmp_path: Path) -> Path:
|
|
25
|
+
"""Create a directory tree simulating monorepo development layout.
|
|
26
|
+
|
|
27
|
+
Structure:
|
|
28
|
+
tmp/
|
|
29
|
+
pennyfarthing-dist/
|
|
30
|
+
agents/
|
|
31
|
+
sm.md
|
|
32
|
+
workflows/
|
|
33
|
+
tdd.yaml
|
|
34
|
+
gates/
|
|
35
|
+
red-gate.md
|
|
36
|
+
personas/
|
|
37
|
+
themes/
|
|
38
|
+
mash.yaml
|
|
39
|
+
guides/
|
|
40
|
+
agent-behavior.md
|
|
41
|
+
skills/
|
|
42
|
+
skill-registry.yaml
|
|
43
|
+
command-registry.yaml
|
|
44
|
+
.pennyfarthing/ (would be a symlink in real usage)
|
|
45
|
+
"""
|
|
46
|
+
dist = tmp_path / "pennyfarthing-dist"
|
|
47
|
+
dist.mkdir()
|
|
48
|
+
|
|
49
|
+
# Agents
|
|
50
|
+
agents = dist / "agents"
|
|
51
|
+
agents.mkdir()
|
|
52
|
+
(agents / "sm.md").write_text("# SM Agent\n")
|
|
53
|
+
|
|
54
|
+
# Workflows
|
|
55
|
+
workflows = dist / "workflows"
|
|
56
|
+
workflows.mkdir()
|
|
57
|
+
(workflows / "tdd.yaml").write_text("workflow:\n name: tdd\n")
|
|
58
|
+
|
|
59
|
+
# Gates
|
|
60
|
+
gates = dist / "gates"
|
|
61
|
+
gates.mkdir()
|
|
62
|
+
(gates / "red-gate.md").write_text("# Red Gate\n")
|
|
63
|
+
|
|
64
|
+
# Personas/themes
|
|
65
|
+
themes = dist / "personas" / "themes"
|
|
66
|
+
themes.mkdir(parents=True)
|
|
67
|
+
(themes / "mash.yaml").write_text("name: mash\n")
|
|
68
|
+
|
|
69
|
+
# Guides
|
|
70
|
+
guides = dist / "guides"
|
|
71
|
+
guides.mkdir()
|
|
72
|
+
(guides / "agent-behavior.md").write_text("# Behavior\n")
|
|
73
|
+
|
|
74
|
+
# Skills
|
|
75
|
+
skills = dist / "skills"
|
|
76
|
+
skills.mkdir()
|
|
77
|
+
(skills / "skill-registry.yaml").write_text("version: 1\n")
|
|
78
|
+
|
|
79
|
+
# Command registry
|
|
80
|
+
(dist / "command-registry.yaml").write_text("commands: []\n")
|
|
81
|
+
|
|
82
|
+
return tmp_path
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@pytest.fixture
|
|
86
|
+
def npm_layout(tmp_path: Path) -> Path:
|
|
87
|
+
"""Create a directory tree simulating npm-installed consumer project.
|
|
88
|
+
|
|
89
|
+
Structure:
|
|
90
|
+
tmp/
|
|
91
|
+
.pennyfarthing/
|
|
92
|
+
config.local.yaml
|
|
93
|
+
node_modules/
|
|
94
|
+
@pennyfarthing/
|
|
95
|
+
core/
|
|
96
|
+
pennyfarthing-dist/
|
|
97
|
+
agents/
|
|
98
|
+
sm.md
|
|
99
|
+
workflows/
|
|
100
|
+
tdd.yaml
|
|
101
|
+
gates/
|
|
102
|
+
red-gate.md
|
|
103
|
+
personas/
|
|
104
|
+
themes/
|
|
105
|
+
mash.yaml
|
|
106
|
+
guides/
|
|
107
|
+
agent-behavior.md
|
|
108
|
+
skills/
|
|
109
|
+
skill-registry.yaml
|
|
110
|
+
command-registry.yaml
|
|
111
|
+
"""
|
|
112
|
+
# Consumer project marker
|
|
113
|
+
pf_config = tmp_path / ".pennyfarthing"
|
|
114
|
+
pf_config.mkdir()
|
|
115
|
+
(pf_config / "config.local.yaml").write_text("theme: mash\n")
|
|
116
|
+
|
|
117
|
+
# npm-installed dist
|
|
118
|
+
dist = (
|
|
119
|
+
tmp_path
|
|
120
|
+
/ "node_modules"
|
|
121
|
+
/ "@pennyfarthing"
|
|
122
|
+
/ "core"
|
|
123
|
+
/ "pennyfarthing-dist"
|
|
124
|
+
)
|
|
125
|
+
dist.mkdir(parents=True)
|
|
126
|
+
|
|
127
|
+
# Agents (sm.md must pass validation; others are stubs for cross-ref)
|
|
128
|
+
agents = dist / "agents"
|
|
129
|
+
agents.mkdir()
|
|
130
|
+
(agents / "sm.md").write_text(
|
|
131
|
+
"# SM Agent\n"
|
|
132
|
+
"<role>Scrum Master</role>\n"
|
|
133
|
+
"<critical>Follow workflow</critical>\n"
|
|
134
|
+
"<helpers>Use haiku subagents</helpers>\n"
|
|
135
|
+
"<skills>Sprint management</skills>\n"
|
|
136
|
+
)
|
|
137
|
+
(agents / "tea.md").write_text("# TEA Agent\n")
|
|
138
|
+
(agents / "dev.md").write_text("# Dev Agent\n")
|
|
139
|
+
(agents / "reviewer.md").write_text("# Reviewer Agent\n")
|
|
140
|
+
|
|
141
|
+
# Workflows (with full phase data for get_phase_owner tests)
|
|
142
|
+
workflows = dist / "workflows"
|
|
143
|
+
workflows.mkdir()
|
|
144
|
+
(workflows / "tdd.yaml").write_text(
|
|
145
|
+
"workflow:\n"
|
|
146
|
+
" name: tdd\n"
|
|
147
|
+
" description: Test-driven development\n"
|
|
148
|
+
" phases:\n"
|
|
149
|
+
" - name: setup\n"
|
|
150
|
+
" agent: sm\n"
|
|
151
|
+
" - name: red\n"
|
|
152
|
+
" agent: tea\n"
|
|
153
|
+
" - name: green\n"
|
|
154
|
+
" agent: dev\n"
|
|
155
|
+
" - name: review\n"
|
|
156
|
+
" agent: reviewer\n"
|
|
157
|
+
" - name: finish\n"
|
|
158
|
+
" agent: sm\n"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# Gates
|
|
162
|
+
gates = dist / "gates"
|
|
163
|
+
gates.mkdir()
|
|
164
|
+
(gates / "red-gate.md").write_text("# Red Gate\n")
|
|
165
|
+
|
|
166
|
+
# Personas/themes
|
|
167
|
+
themes = dist / "personas" / "themes"
|
|
168
|
+
themes.mkdir(parents=True)
|
|
169
|
+
(themes / "mash.yaml").write_text("name: mash\nagents:\n tea:\n character: Radar\n")
|
|
170
|
+
|
|
171
|
+
# Guides
|
|
172
|
+
guides = dist / "guides"
|
|
173
|
+
guides.mkdir()
|
|
174
|
+
(guides / "agent-behavior.md").write_text(
|
|
175
|
+
"# Behavior Guide\n"
|
|
176
|
+
"<team-mode>\n"
|
|
177
|
+
"TeamCreate for team creation. Spawn teammates with Task tool. "
|
|
178
|
+
"SendMessage for communication. TeamDelete for cleanup.\n"
|
|
179
|
+
"</team-mode>\n"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Skills
|
|
183
|
+
skills = dist / "skills"
|
|
184
|
+
skills.mkdir()
|
|
185
|
+
(skills / "skill-registry.yaml").write_text(
|
|
186
|
+
"version: \"1.0.0\"\nskills:\n pf-testing:\n name: pf-testing\n"
|
|
187
|
+
)
|
|
188
|
+
(skills / "skill-registry.schema.json").write_text('{"type": "object"}')
|
|
189
|
+
|
|
190
|
+
# Commands
|
|
191
|
+
commands = dist / "commands"
|
|
192
|
+
commands.mkdir()
|
|
193
|
+
(commands / "example.md").write_text("# Example Command\n")
|
|
194
|
+
|
|
195
|
+
# Command registry
|
|
196
|
+
(dist / "command-registry.yaml").write_text("commands:\n example:\n file: example.md\n")
|
|
197
|
+
|
|
198
|
+
return tmp_path
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
@pytest.fixture
|
|
202
|
+
def bare_project(tmp_path: Path) -> Path:
|
|
203
|
+
"""Create a directory tree with no pennyfarthing-dist anywhere.
|
|
204
|
+
|
|
205
|
+
Structure:
|
|
206
|
+
tmp/
|
|
207
|
+
.pennyfarthing/
|
|
208
|
+
config.local.yaml
|
|
209
|
+
src/
|
|
210
|
+
app.py
|
|
211
|
+
"""
|
|
212
|
+
pf_config = tmp_path / ".pennyfarthing"
|
|
213
|
+
pf_config.mkdir()
|
|
214
|
+
(pf_config / "config.local.yaml").write_text("theme: mash\n")
|
|
215
|
+
|
|
216
|
+
src = tmp_path / "src"
|
|
217
|
+
src.mkdir()
|
|
218
|
+
(src / "app.py").write_text("print('hello')\n")
|
|
219
|
+
|
|
220
|
+
return tmp_path
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
# ---------------------------------------------------------------------------
|
|
224
|
+
# AC1: get_dist_root() resolves correctly in both contexts
|
|
225
|
+
# ---------------------------------------------------------------------------
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
class TestGetDistRootMonorepo:
|
|
229
|
+
"""AC1: get_dist_root() in monorepo development layout."""
|
|
230
|
+
|
|
231
|
+
def test_finds_pennyfarthing_dist_at_project_root(
|
|
232
|
+
self, monorepo_layout: Path
|
|
233
|
+
) -> None:
|
|
234
|
+
"""Should find pennyfarthing-dist/ directly under project root."""
|
|
235
|
+
result = get_dist_root(project_root=monorepo_layout)
|
|
236
|
+
assert result is not None
|
|
237
|
+
assert result.is_dir()
|
|
238
|
+
assert result.name == "pennyfarthing-dist"
|
|
239
|
+
assert result == monorepo_layout / "pennyfarthing-dist"
|
|
240
|
+
|
|
241
|
+
def test_returned_path_contains_agents(self, monorepo_layout: Path) -> None:
|
|
242
|
+
"""Resolved dist root should contain expected subdirectories."""
|
|
243
|
+
result = get_dist_root(project_root=monorepo_layout)
|
|
244
|
+
assert result is not None
|
|
245
|
+
assert (result / "agents").is_dir()
|
|
246
|
+
assert (result / "workflows").is_dir()
|
|
247
|
+
assert (result / "gates").is_dir()
|
|
248
|
+
|
|
249
|
+
def test_returned_path_is_absolute(self, monorepo_layout: Path) -> None:
|
|
250
|
+
"""Resolved path should be absolute, not relative."""
|
|
251
|
+
result = get_dist_root(project_root=monorepo_layout)
|
|
252
|
+
assert result is not None
|
|
253
|
+
assert result.is_absolute()
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
class TestGetDistRootNpm:
|
|
257
|
+
"""AC1/AC5: get_dist_root() in npm-installed consumer project."""
|
|
258
|
+
|
|
259
|
+
def test_finds_dist_in_node_modules(self, npm_layout: Path) -> None:
|
|
260
|
+
"""Should find pennyfarthing-dist/ inside node_modules/@pennyfarthing/core/."""
|
|
261
|
+
result = get_dist_root(project_root=npm_layout)
|
|
262
|
+
assert result is not None
|
|
263
|
+
assert result.is_dir()
|
|
264
|
+
assert result.name == "pennyfarthing-dist"
|
|
265
|
+
|
|
266
|
+
def test_npm_path_contains_expected_content(self, npm_layout: Path) -> None:
|
|
267
|
+
"""Resolved npm dist root should contain expected subdirectories."""
|
|
268
|
+
result = get_dist_root(project_root=npm_layout)
|
|
269
|
+
assert result is not None
|
|
270
|
+
assert (result / "agents").is_dir()
|
|
271
|
+
assert (result / "workflows").is_dir()
|
|
272
|
+
assert (result / "gates").is_dir()
|
|
273
|
+
assert (result / "personas" / "themes").is_dir()
|
|
274
|
+
|
|
275
|
+
def test_no_symlink_required(self, npm_layout: Path) -> None:
|
|
276
|
+
"""AC5: Should resolve without any symlink workaround."""
|
|
277
|
+
# Verify no pennyfarthing-dist symlink exists at project root
|
|
278
|
+
assert not (npm_layout / "pennyfarthing-dist").exists()
|
|
279
|
+
# But get_dist_root still works
|
|
280
|
+
result = get_dist_root(project_root=npm_layout)
|
|
281
|
+
assert result is not None
|
|
282
|
+
assert result.is_dir()
|
|
283
|
+
|
|
284
|
+
def test_npm_returned_path_is_absolute(self, npm_layout: Path) -> None:
|
|
285
|
+
"""Resolved npm path should be absolute."""
|
|
286
|
+
result = get_dist_root(project_root=npm_layout)
|
|
287
|
+
assert result is not None
|
|
288
|
+
assert result.is_absolute()
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
class TestGetDistRootPrecedence:
|
|
292
|
+
"""AC1: Precedence when multiple layouts coexist."""
|
|
293
|
+
|
|
294
|
+
def test_prefers_monorepo_over_npm(self, tmp_path: Path) -> None:
|
|
295
|
+
"""When both monorepo and npm layouts exist, prefer monorepo (direct)."""
|
|
296
|
+
# Create both layouts
|
|
297
|
+
direct = tmp_path / "pennyfarthing-dist"
|
|
298
|
+
direct.mkdir()
|
|
299
|
+
(direct / "agents").mkdir()
|
|
300
|
+
|
|
301
|
+
npm = (
|
|
302
|
+
tmp_path
|
|
303
|
+
/ "node_modules"
|
|
304
|
+
/ "@pennyfarthing"
|
|
305
|
+
/ "core"
|
|
306
|
+
/ "pennyfarthing-dist"
|
|
307
|
+
)
|
|
308
|
+
npm.mkdir(parents=True)
|
|
309
|
+
(npm / "agents").mkdir()
|
|
310
|
+
|
|
311
|
+
result = get_dist_root(project_root=tmp_path)
|
|
312
|
+
assert result is not None
|
|
313
|
+
# Should prefer the direct monorepo path
|
|
314
|
+
assert result == direct
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
class TestGetDistRootFromFile:
|
|
318
|
+
"""AC1: Resolution relative to __file__ (inside pennyfarthing-dist/pf/)."""
|
|
319
|
+
|
|
320
|
+
def test_resolves_from_file_inside_dist(self, monorepo_layout: Path) -> None:
|
|
321
|
+
"""When called from within pennyfarthing-dist/pf/, should resolve up."""
|
|
322
|
+
# Simulate a module at pennyfarthing-dist/pf/common/config.py
|
|
323
|
+
pf_dir = monorepo_layout / "pennyfarthing-dist" / "pf" / "common"
|
|
324
|
+
pf_dir.mkdir(parents=True)
|
|
325
|
+
|
|
326
|
+
# get_dist_root with project_root should still resolve
|
|
327
|
+
result = get_dist_root(project_root=monorepo_layout)
|
|
328
|
+
assert result is not None
|
|
329
|
+
assert result == monorepo_layout / "pennyfarthing-dist"
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
class TestGetDistRootNotFound:
|
|
333
|
+
"""AC1: Behavior when pennyfarthing-dist/ is not found anywhere."""
|
|
334
|
+
|
|
335
|
+
def test_returns_none_when_not_found(self, bare_project: Path) -> None:
|
|
336
|
+
"""Should return None when no pennyfarthing-dist/ exists."""
|
|
337
|
+
result = get_dist_root(project_root=bare_project)
|
|
338
|
+
assert result is None
|
|
339
|
+
|
|
340
|
+
def test_returns_none_for_empty_directory(self, tmp_path: Path) -> None:
|
|
341
|
+
"""Should return None for a totally empty directory."""
|
|
342
|
+
result = get_dist_root(project_root=tmp_path)
|
|
343
|
+
assert result is None
|
|
344
|
+
|
|
345
|
+
def test_auto_detects_project_root_when_not_given(
|
|
346
|
+
self, monorepo_layout: Path
|
|
347
|
+
) -> None:
|
|
348
|
+
"""When project_root is None, should auto-detect via get_project_root()."""
|
|
349
|
+
# Patch get_project_root to return our monorepo layout
|
|
350
|
+
with patch(
|
|
351
|
+
"pf.common.config.get_project_root", return_value=monorepo_layout
|
|
352
|
+
):
|
|
353
|
+
result = get_dist_root() # No project_root argument
|
|
354
|
+
assert result is not None
|
|
355
|
+
assert result == monorepo_layout / "pennyfarthing-dist"
|
|
356
|
+
|
|
357
|
+
def test_returns_none_when_project_root_detection_fails(self) -> None:
|
|
358
|
+
"""Should return None (not raise) when get_project_root() fails.
|
|
359
|
+
|
|
360
|
+
Reviewer finding: get_dist_root() propagates FileNotFoundError
|
|
361
|
+
when project_root is None and get_project_root() raises.
|
|
362
|
+
Docstring promises None return on failure.
|
|
363
|
+
"""
|
|
364
|
+
with patch(
|
|
365
|
+
"pf.common.config.get_project_root",
|
|
366
|
+
side_effect=FileNotFoundError("no root"),
|
|
367
|
+
):
|
|
368
|
+
result = get_dist_root() # Should return None, not raise
|
|
369
|
+
assert result is None
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
# ---------------------------------------------------------------------------
|
|
373
|
+
# AC2: Call sites resolve correctly in npm context
|
|
374
|
+
# These tests call the ACTUAL module functions, not get_dist_root() directly.
|
|
375
|
+
# ---------------------------------------------------------------------------
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
class TestCallSitesNpmResolution:
|
|
379
|
+
"""AC2: Verify actual modules work correctly in npm-installed context.
|
|
380
|
+
|
|
381
|
+
These tests import and call the ACTUAL module functions against an
|
|
382
|
+
npm-layout directory. They fail when modules hardcode
|
|
383
|
+
`root / "pennyfarthing-dist" / ...` instead of using get_dist_root().
|
|
384
|
+
"""
|
|
385
|
+
|
|
386
|
+
def test_agent_validator_finds_agents_in_npm(self, npm_layout: Path) -> None:
|
|
387
|
+
"""agent.run() should find and validate agents in npm layout."""
|
|
388
|
+
from pf.validate.adapters.agent import run
|
|
389
|
+
|
|
390
|
+
report = run(npm_layout, fix=False, strict=False)
|
|
391
|
+
# Should NOT report "agents directory not found" error
|
|
392
|
+
has_dir_not_found = any(
|
|
393
|
+
"not found" in d.lower() for d in report.details
|
|
394
|
+
)
|
|
395
|
+
assert not has_dir_not_found, (
|
|
396
|
+
f"Agent validator failed to find agents in npm layout: {report.details}"
|
|
397
|
+
)
|
|
398
|
+
# Should find and validate at least 1 agent file
|
|
399
|
+
assert report.passed > 0 or report.warnings > 0, (
|
|
400
|
+
"Agent validator found 0 files in npm layout — call site not refactored"
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
def test_workflow_validator_finds_workflows_in_npm(
|
|
404
|
+
self, npm_layout: Path
|
|
405
|
+
) -> None:
|
|
406
|
+
"""workflow.run() should find and validate workflows in npm layout."""
|
|
407
|
+
from pf.validate.adapters.workflow import run
|
|
408
|
+
|
|
409
|
+
report = run(npm_layout, fix=False, strict=False)
|
|
410
|
+
has_dir_not_found = any(
|
|
411
|
+
"not found" in d.lower() for d in report.details
|
|
412
|
+
)
|
|
413
|
+
assert not has_dir_not_found, (
|
|
414
|
+
f"Workflow validator failed to find workflows in npm layout: {report.details}"
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
def test_skill_command_discovers_registry_in_npm(
|
|
418
|
+
self, npm_layout: Path
|
|
419
|
+
) -> None:
|
|
420
|
+
"""skill_command.discover_skill_registry() should find registry in npm."""
|
|
421
|
+
from pf.validate.adapters.skill_command import discover_skill_registry
|
|
422
|
+
|
|
423
|
+
result = discover_skill_registry(npm_layout)
|
|
424
|
+
assert result is not None, (
|
|
425
|
+
"discover_skill_registry returned None for npm layout — "
|
|
426
|
+
"call site not refactored to use get_dist_root()"
|
|
427
|
+
)
|
|
428
|
+
assert result.is_file()
|
|
429
|
+
|
|
430
|
+
def test_gate_file_resolves_in_npm(self, npm_layout: Path) -> None:
|
|
431
|
+
"""gate_file.resolve_gate_file() should find gates in npm layout."""
|
|
432
|
+
from pf.handoff.gate_file import resolve_gate_file
|
|
433
|
+
|
|
434
|
+
result = resolve_gate_file("gates/red-gate", project_root=npm_layout)
|
|
435
|
+
assert result.get("status") == "found", (
|
|
436
|
+
f"resolve_gate_file failed in npm layout: {result}"
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
def test_theme_discovery_includes_npm_path(self, npm_layout: Path) -> None:
|
|
440
|
+
"""themes.discover_all_theme_dirs() should find themes in npm layout."""
|
|
441
|
+
from pf.common.themes import discover_all_theme_dirs
|
|
442
|
+
|
|
443
|
+
dirs = discover_all_theme_dirs(project_root=npm_layout)
|
|
444
|
+
# Should include the npm-installed themes directory
|
|
445
|
+
npm_themes = (
|
|
446
|
+
npm_layout
|
|
447
|
+
/ "node_modules"
|
|
448
|
+
/ "@pennyfarthing"
|
|
449
|
+
/ "core"
|
|
450
|
+
/ "pennyfarthing-dist"
|
|
451
|
+
/ "personas"
|
|
452
|
+
/ "themes"
|
|
453
|
+
)
|
|
454
|
+
assert any(d == npm_themes or d.resolve() == npm_themes.resolve() for d in dirs), (
|
|
455
|
+
f"discover_all_theme_dirs did not include npm themes path. "
|
|
456
|
+
f"Got: {dirs}"
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
def test_workflow_get_phase_owner_in_npm(self, npm_layout: Path) -> None:
|
|
460
|
+
"""workflow.get_phase_owner() should resolve workflow in npm layout."""
|
|
461
|
+
from pf.prime.workflow import get_phase_owner
|
|
462
|
+
|
|
463
|
+
owner = get_phase_owner("tdd", "red", npm_layout)
|
|
464
|
+
assert owner == "tea", (
|
|
465
|
+
f"get_phase_owner returned {owner!r} in npm layout — "
|
|
466
|
+
"expected 'tea'. Call site not refactored."
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
def test_loader_finds_agent_in_npm(self, npm_layout: Path) -> None:
|
|
470
|
+
"""loader.load_agent_definition() should find agents in npm layout."""
|
|
471
|
+
from pf.prime.loader import load_agent_definition
|
|
472
|
+
|
|
473
|
+
content = load_agent_definition("sm", project_root=npm_layout)
|
|
474
|
+
assert content is not None, (
|
|
475
|
+
"load_agent_definition returned None for npm layout — "
|
|
476
|
+
"call site not refactored to use get_dist_root()"
|
|
477
|
+
)
|
|
478
|
+
assert "SM Agent" in content
|
|
479
|
+
|
|
480
|
+
def test_loader_finds_behavior_guide_in_npm(self, npm_layout: Path) -> None:
|
|
481
|
+
"""loader.load_behavior_guide() should find guide in npm layout."""
|
|
482
|
+
from pf.prime.loader import load_behavior_guide
|
|
483
|
+
|
|
484
|
+
content = load_behavior_guide(project_root=npm_layout)
|
|
485
|
+
assert content is not None, (
|
|
486
|
+
"load_behavior_guide returned None for npm layout — "
|
|
487
|
+
"call site not refactored to use get_dist_root()"
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
def test_team_mode_validator_finds_guides_in_npm(
|
|
491
|
+
self, npm_layout: Path
|
|
492
|
+
) -> None:
|
|
493
|
+
"""team_mode.run() should find and validate guides in npm layout."""
|
|
494
|
+
from pf.validate.adapters.team_mode import run
|
|
495
|
+
|
|
496
|
+
report = run(npm_layout, fix=False, strict=False)
|
|
497
|
+
# Should have actually found and validated files (passed > 0),
|
|
498
|
+
# not just produced an error about missing directories
|
|
499
|
+
assert report.passed > 0, (
|
|
500
|
+
f"team_mode validator found 0 valid files in npm layout — "
|
|
501
|
+
f"call site not refactored. Details: {report.details}"
|
|
502
|
+
)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
# ---------------------------------------------------------------------------
|
|
506
|
+
# AC3: Validate reports "0 files found" as warning
|
|
507
|
+
# ---------------------------------------------------------------------------
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
class TestValidateZeroFilesWarning:
|
|
511
|
+
"""AC3: pf validate should warn when 0 files are discovered."""
|
|
512
|
+
|
|
513
|
+
def test_agent_validator_warns_on_zero_agents(self, tmp_path: Path) -> None:
|
|
514
|
+
"""Agent validator should warn (not silently pass) when 0 agents found."""
|
|
515
|
+
from pf.validate.adapters.agent import run
|
|
516
|
+
|
|
517
|
+
# Create a pennyfarthing-dist with empty agents dir
|
|
518
|
+
dist = tmp_path / "pennyfarthing-dist"
|
|
519
|
+
agents = dist / "agents"
|
|
520
|
+
agents.mkdir(parents=True)
|
|
521
|
+
|
|
522
|
+
report = run(tmp_path, fix=False, strict=False)
|
|
523
|
+
# With 0 agents, should have a warning — not a clean pass
|
|
524
|
+
assert report.warnings > 0 or report.errors > 0, (
|
|
525
|
+
"Validator silently passed with 0 agent files — should warn"
|
|
526
|
+
)
|
|
527
|
+
|
|
528
|
+
def test_workflow_validator_warns_on_zero_workflows(
|
|
529
|
+
self, tmp_path: Path
|
|
530
|
+
) -> None:
|
|
531
|
+
"""Workflow validator should warn when 0 workflow files found."""
|
|
532
|
+
from pf.validate.adapters.workflow import run
|
|
533
|
+
|
|
534
|
+
# Create pennyfarthing-dist with empty workflows dir
|
|
535
|
+
dist = tmp_path / "pennyfarthing-dist"
|
|
536
|
+
workflows = dist / "workflows"
|
|
537
|
+
workflows.mkdir(parents=True)
|
|
538
|
+
# Also need agents dir for workflow validator
|
|
539
|
+
(dist / "agents").mkdir()
|
|
540
|
+
|
|
541
|
+
report = run(tmp_path, fix=False, strict=False)
|
|
542
|
+
assert report.warnings > 0 or report.errors > 0, (
|
|
543
|
+
"Validator silently passed with 0 workflow files — should warn"
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
def test_agent_validator_report_mentions_zero_files(
|
|
547
|
+
self, tmp_path: Path
|
|
548
|
+
) -> None:
|
|
549
|
+
"""Report details should mention that 0 files were found."""
|
|
550
|
+
from pf.validate.adapters.agent import run
|
|
551
|
+
|
|
552
|
+
dist = tmp_path / "pennyfarthing-dist"
|
|
553
|
+
agents = dist / "agents"
|
|
554
|
+
agents.mkdir(parents=True)
|
|
555
|
+
|
|
556
|
+
report = run(tmp_path, fix=False, strict=False)
|
|
557
|
+
# Should have a detail mentioning 0 files
|
|
558
|
+
detail_text = " ".join(report.details).lower()
|
|
559
|
+
assert "0" in detail_text or "no " in detail_text or "empty" in detail_text, (
|
|
560
|
+
f"Report details should mention 0 files found, got: {report.details}"
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
def test_zero_files_is_not_success(self, tmp_path: Path) -> None:
|
|
564
|
+
"""A validator with 0 files should NOT report success."""
|
|
565
|
+
from pf.validate.adapters.agent import run
|
|
566
|
+
|
|
567
|
+
dist = tmp_path / "pennyfarthing-dist"
|
|
568
|
+
agents = dist / "agents"
|
|
569
|
+
agents.mkdir(parents=True)
|
|
570
|
+
|
|
571
|
+
report = run(tmp_path, fix=False, strict=False)
|
|
572
|
+
# success property is errors == 0, but with 0 files it should
|
|
573
|
+
# at minimum have a warning
|
|
574
|
+
assert report.warnings > 0 or not report.success, (
|
|
575
|
+
"0 files should not produce a clean success report"
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
# ---------------------------------------------------------------------------
|
|
580
|
+
# AC6: Integration test — npm-installed context
|
|
581
|
+
# ---------------------------------------------------------------------------
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
class TestIntegrationNpmContext:
|
|
585
|
+
"""AC6: End-to-end integration verifying multiple modules in npm context.
|
|
586
|
+
|
|
587
|
+
These tests run actual pf operations against the npm-installed layout
|
|
588
|
+
to verify the full resolution chain works.
|
|
589
|
+
"""
|
|
590
|
+
|
|
591
|
+
def test_validate_agent_end_to_end_npm(self, npm_layout: Path) -> None:
|
|
592
|
+
"""Full agent validation should succeed in npm layout."""
|
|
593
|
+
from pf.validate.adapters.agent import run
|
|
594
|
+
|
|
595
|
+
report = run(npm_layout, fix=False, strict=False)
|
|
596
|
+
# After refactoring, should validate at least 1 agent successfully
|
|
597
|
+
assert report.passed >= 1, (
|
|
598
|
+
f"Expected at least 1 agent validated, got {report.passed}. "
|
|
599
|
+
f"Details: {report.details}"
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
def test_theme_resolution_end_to_end_npm(self, npm_layout: Path) -> None:
|
|
603
|
+
"""Theme resolution should find themes in npm layout."""
|
|
604
|
+
from pf.common.themes import resolve_theme_path
|
|
605
|
+
|
|
606
|
+
result = resolve_theme_path("mash", project_root=npm_layout)
|
|
607
|
+
assert result is not None, (
|
|
608
|
+
"resolve_theme_path('mash') returned None in npm layout"
|
|
609
|
+
)
|
|
610
|
+
assert result.is_file()
|
|
611
|
+
|
|
612
|
+
def test_gate_resolution_end_to_end_npm(self, npm_layout: Path) -> None:
|
|
613
|
+
"""Gate resolution should find built-in gates in npm layout."""
|
|
614
|
+
from pf.handoff.gate_file import resolve_gate_file
|
|
615
|
+
|
|
616
|
+
result = resolve_gate_file("gates/red-gate", project_root=npm_layout)
|
|
617
|
+
assert result.get("status") == "found", (
|
|
618
|
+
f"Gate resolution failed in npm layout: {result}"
|
|
619
|
+
)
|
|
620
|
+
assert "path" in result
|
|
621
|
+
|
|
622
|
+
def test_workflow_phase_lookup_end_to_end_npm(self, npm_layout: Path) -> None:
|
|
623
|
+
"""Workflow phase lookup should resolve in npm layout."""
|
|
624
|
+
from pf.prime.workflow import get_phase_owner
|
|
625
|
+
|
|
626
|
+
# Verify multiple phases resolve correctly
|
|
627
|
+
assert get_phase_owner("tdd", "red", npm_layout) == "tea"
|
|
628
|
+
assert get_phase_owner("tdd", "green", npm_layout) == "dev"
|
|
629
|
+
assert get_phase_owner("tdd", "setup", npm_layout) == "sm"
|
|
630
|
+
|
|
631
|
+
def test_skill_registry_end_to_end_npm(self, npm_layout: Path) -> None:
|
|
632
|
+
"""Skill registry discovery should work in npm layout."""
|
|
633
|
+
from pf.validate.adapters.skill_command import discover_skill_registry
|
|
634
|
+
|
|
635
|
+
path = discover_skill_registry(npm_layout)
|
|
636
|
+
assert path is not None, "Skill registry not found in npm layout"
|
|
637
|
+
assert path.is_file()
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
# ---------------------------------------------------------------------------
|
|
641
|
+
# Story 120-7: Remaining call sites
|
|
642
|
+
# ---------------------------------------------------------------------------
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
class TestRemainingCallSitesNpmResolution:
|
|
646
|
+
"""Story 120-7: Verify remaining call sites use get_dist_root().
|
|
647
|
+
|
|
648
|
+
These cover the 4 modules that were not refactored in 120-5:
|
|
649
|
+
hooks_installer, cli help, tandem_awareness, statusline.
|
|
650
|
+
"""
|
|
651
|
+
|
|
652
|
+
def test_hooks_installer_finds_dist_in_npm(self, npm_layout: Path) -> None:
|
|
653
|
+
"""hooks_installer should find pennyfarthing-dist in npm layout."""
|
|
654
|
+
from pf.git.hooks_installer import install_git_hooks
|
|
655
|
+
|
|
656
|
+
# Create .git/hooks directory structure
|
|
657
|
+
git_dir = npm_layout / ".git"
|
|
658
|
+
git_dir.mkdir()
|
|
659
|
+
hooks_dir = git_dir / "hooks"
|
|
660
|
+
hooks_dir.mkdir()
|
|
661
|
+
|
|
662
|
+
# Create hooks source files and dispatcher template in dist
|
|
663
|
+
dist = (
|
|
664
|
+
npm_layout / "node_modules" / "@pennyfarthing" / "core"
|
|
665
|
+
/ "pennyfarthing-dist"
|
|
666
|
+
)
|
|
667
|
+
hooks_source = dist / "scripts" / "hooks"
|
|
668
|
+
hooks_source.mkdir(parents=True)
|
|
669
|
+
(hooks_source / "dispatcher-template.sh").write_text(
|
|
670
|
+
"#!/bin/bash\n# __HOOK_NAME__ dispatcher\n"
|
|
671
|
+
)
|
|
672
|
+
(hooks_source / "pre-commit.sh").write_text("#!/bin/bash\n# pre-commit\n")
|
|
673
|
+
|
|
674
|
+
result = install_git_hooks(project_root=npm_layout)
|
|
675
|
+
assert result == 0, (
|
|
676
|
+
"install_git_hooks failed in npm layout — "
|
|
677
|
+
"call site not refactored to use get_dist_root()"
|
|
678
|
+
)
|
|
679
|
+
|
|
680
|
+
def test_tandem_awareness_finds_agents_in_npm(self, npm_layout: Path) -> None:
|
|
681
|
+
"""tandem_awareness.run() should find agents in npm layout."""
|
|
682
|
+
from pf.validate.adapters.tandem_awareness import run
|
|
683
|
+
|
|
684
|
+
report = run(npm_layout, fix=False, strict=False)
|
|
685
|
+
has_dir_not_found = any(
|
|
686
|
+
"not found" in d.lower() for d in report.details
|
|
687
|
+
)
|
|
688
|
+
assert not has_dir_not_found, (
|
|
689
|
+
f"Tandem awareness failed to find agents in npm layout: {report.details}"
|
|
690
|
+
)
|
|
691
|
+
|
|
692
|
+
def test_cli_help_finds_registry_in_npm(self, npm_layout: Path) -> None:
|
|
693
|
+
"""cli help_cmd should find command-registry.yaml in npm layout."""
|
|
694
|
+
import yaml
|
|
695
|
+
|
|
696
|
+
from pf.common.config import get_dist_root
|
|
697
|
+
|
|
698
|
+
# Verify the registry is reachable via get_dist_root
|
|
699
|
+
dist_root = get_dist_root(project_root=npm_layout)
|
|
700
|
+
assert dist_root is not None
|
|
701
|
+
registry_path = dist_root / "command-registry.yaml"
|
|
702
|
+
assert registry_path.is_file(), (
|
|
703
|
+
"command-registry.yaml not found via get_dist_root in npm layout"
|
|
704
|
+
)
|
|
705
|
+
data = yaml.safe_load(registry_path.read_text())
|
|
706
|
+
assert data is not None
|
|
707
|
+
|
|
708
|
+
def test_statusline_theme_resolves_in_npm(self, npm_layout: Path) -> None:
|
|
709
|
+
"""statusline _get_character_display should find theme via dist fallback."""
|
|
710
|
+
from pf.hooks.statusline import _get_character_display
|
|
711
|
+
|
|
712
|
+
# Remove .pennyfarthing/personas/ to simulate npm without symlinks
|
|
713
|
+
# .pennyfarthing exists (config) but has no personas/themes symlink
|
|
714
|
+
# So the primary path fails and fallback via get_dist_root should work
|
|
715
|
+
display, theme_file = _get_character_display(str(npm_layout), "tea")
|
|
716
|
+
# Should resolve the theme file (even if character isn't found for tea,
|
|
717
|
+
# theme_file path should point to the dist location)
|
|
718
|
+
assert theme_file is not None, (
|
|
719
|
+
"statusline could not resolve theme file in npm layout"
|
|
720
|
+
)
|