@pennyfarthing/core 11.3.7 → 11.4.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 +17 -16
- package/packages/core/dist/public/css/react.css +1 -1
- package/packages/core/dist/public/js/react/react.js +24 -24
- package/packages/core/src/public/App.tsx +356 -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 +217 -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 +749 -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/FontPicker/FontPicker.css +276 -0
- package/packages/core/src/public/components/FontPicker/index.tsx +430 -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 +82 -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/ThemePalette/ThemePalette.css +179 -0
- package/packages/core/src/public/components/ThemePalette/index.tsx +326 -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/BackgroundPanel.tsx +115 -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 +361 -0
- package/packages/core/src/public/components/panels/SprintPanel.tsx +723 -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 +24 -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/switch.tsx +27 -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 +49 -0
- package/packages/core/src/public/hooks/useAgentLoad.ts +105 -0
- package/packages/core/src/public/hooks/useBackgroundTasks.ts +131 -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 +157 -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/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 +4454 -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/pf/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/__pycache__/context.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bc/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bc/__pycache__/cli.cpython-314.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 -1
- package/pennyfarthing-dist/pf/bc/focus.py +0 -1
- package/pennyfarthing-dist/pf/bikerack/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/cli.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-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/__pycache__/portrait_resolver.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__/tui.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bikerack/base_panel.py +0 -1
- 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 +21 -0
- package/pennyfarthing-dist/pf/bikerack/sprint_panel.py +58 -1
- package/pennyfarthing-dist/pf/bikerack/tui.py +5 -20
- 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/__pycache__/parser.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/bmad/parser.py +15 -9
- package/pennyfarthing-dist/pf/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/common/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/common/__pycache__/config.cpython-314.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/pr_config.py +27 -2
- package/pennyfarthing-dist/pf/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/complexity/__pycache__/analyze.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-314.pyc +0 -0
- package/pennyfarthing-dist/pf/consultation/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/deadcode/__pycache__/__init__.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-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__/analyze.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-314.pyc +0 -0
- package/pennyfarthing-dist/pf/epic/__pycache__/cli.cpython-314.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-314.pyc +0 -0
- package/pennyfarthing-dist/pf/handoff/__pycache__/__init__.cpython-314.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__/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/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-314.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-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/bell_mode.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/cli.cpython-314.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-314.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-314.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-314.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-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/__pycache__/statusline.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hooks/cyclist-pretooluse-hook.sh +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/hotspots/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/claim.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/client.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/create.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/epic.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/operations.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/story.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/jira/__pycache__/sync.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/launch/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/launch/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/prime/__pycache__/__init__.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__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/session/__pycache__/__init__.cpython-314.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-314.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-314.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-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/status.cpython-314.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-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/validator.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/work.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/sprint/story_finish.py +14 -2
- package/pennyfarthing-dist/pf/sprint/validator.py +7 -7
- 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_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing-dist/pf/tests/test_sprint_validator.py +44 -0
- package/pennyfarthing-dist/pf/theme/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/theme/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/validate/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/pf/workflow/__pycache__/__init__.cpython-314.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-314.pyc +0 -0
- package/pennyfarthing-dist/pf/workflow/__pycache__/state.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/scripts/core/agent-session.sh +0 -0
- package/pennyfarthing-dist/scripts/core/check-context.sh +0 -0
- package/pennyfarthing-dist/scripts/core/dialogue-manager.sh +0 -0
- package/pennyfarthing-dist/scripts/core/pf.sh +0 -0
- package/pennyfarthing-dist/scripts/core/phase-check-start.sh +0 -0
- package/pennyfarthing-dist/scripts/core/prime.sh +0 -0
- package/pennyfarthing-dist/scripts/cyclist/is-cyclist.sh +0 -0
- package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +0 -0
- package/pennyfarthing-dist/scripts/git/git-status-all.sh +0 -0
- package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +0 -0
- package/pennyfarthing-dist/scripts/git/release.sh +0 -0
- package/pennyfarthing-dist/scripts/git/worktree-manager.sh +0 -0
- package/pennyfarthing-dist/scripts/health/drift-detection.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/context-warning.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/dispatcher-template.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/post-merge.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/pre-push.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/question_reflector_check.py +0 -0
- package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/session-start.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/session-stop.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +0 -0
- package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +0 -0
- package/pennyfarthing-dist/scripts/jira/create-jira-epic.sh +0 -0
- package/pennyfarthing-dist/scripts/jira/create-jira-story.sh +0 -0
- package/pennyfarthing-dist/scripts/jira/jira-claim-story.sh +0 -0
- package/pennyfarthing-dist/scripts/jira/jira-reconcile.sh +0 -0
- package/pennyfarthing-dist/scripts/jira/jira-sync-story.sh +0 -0
- package/pennyfarthing-dist/scripts/jira/sync-epic-jira.sh +0 -0
- package/pennyfarthing-dist/scripts/lib/background-tasks.sh +0 -0
- package/pennyfarthing-dist/scripts/lib/checkpoint.sh +0 -0
- package/pennyfarthing-dist/scripts/lib/common.sh +0 -0
- package/pennyfarthing-dist/scripts/lib/env.sh +0 -0
- package/pennyfarthing-dist/scripts/lib/file-lock.sh +0 -0
- package/pennyfarthing-dist/scripts/lib/find-root.sh +1 -1
- package/pennyfarthing-dist/scripts/lib/logging.sh +0 -0
- package/pennyfarthing-dist/scripts/lib/retry.sh +0 -0
- package/pennyfarthing-dist/scripts/lib/run-pf.sh +0 -0
- package/pennyfarthing-dist/scripts/maintenance/migrate-theme-schema.mjs +0 -0
- package/pennyfarthing-dist/scripts/maintenance/sidecar-health.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/add-short-names.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/add_short_names.py +0 -0
- package/pennyfarthing-dist/scripts/misc/backlog.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/check-status.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/find-related-work.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/generate-skill-docs.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/log-skill-usage.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/migrate-bmad-workflow.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/migrate_bmad_workflow.py +0 -1
- package/pennyfarthing-dist/scripts/misc/repo-scan.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/repo-utils.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/run-ci.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/run-timestamp.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/session-cleanup.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/skill-usage-report.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/statusline.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/uninstall.sh +0 -0
- package/pennyfarthing-dist/scripts/misc/validate-subagent-frontmatter.sh +0 -0
- package/pennyfarthing-dist/scripts/portraits/generate-portraits.py +13 -13
- package/pennyfarthing-dist/scripts/portraits/generate-portraits.sh +0 -0
- package/pennyfarthing-dist/scripts/portraits/generate-tandem-portraits.sh +0 -0
- package/pennyfarthing-dist/scripts/story/create-story.sh +0 -0
- package/pennyfarthing-dist/scripts/story/size-story.sh +0 -0
- package/pennyfarthing-dist/scripts/story/story-template.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/check.test.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/dev-story-workflow-import.test.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/epics-and-stories-workflow-import.test.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/handoff-phase-update.test.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/implementation-readiness-workflow-import.test.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/migrate-bmad-workflow.test.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/prd-workflow-import.test.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/project-context-workflow-import.test.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/test-character-voice.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/test-drift-detection.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/test-post-merge-hook.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/test-session-checkpoint.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/test-solo-command.sh +0 -0
- package/pennyfarthing-dist/scripts/tests/ux-design-workflow-import.test.sh +0 -0
- package/pennyfarthing-dist/scripts/theme/list-themes.sh +0 -0
- package/pennyfarthing-dist/scripts/validation/validate-agent-schema.sh +0 -0
- package/pennyfarthing-dist/scripts/workflow/check.py +4 -6
- package/pennyfarthing-dist/scripts/workflow/check.sh +0 -0
- package/pennyfarthing-dist/scripts/workflow/complete-step.py +2 -2
- package/pennyfarthing-dist/scripts/workflow/finish-story.sh +0 -0
- package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +0 -0
- package/pennyfarthing-dist/scripts/workflow/get-workflow-type.py +0 -0
- package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +0 -0
- package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +0 -0
- package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +0 -0
- package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +0 -0
- package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +0 -0
- package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +0 -0
- package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +0 -0
- package/pennyfarthing-dist/skills/pf-story/scripts/create-story.sh +0 -0
- package/pennyfarthing-dist/skills/pf-story/scripts/size-story.sh +0 -0
- package/pennyfarthing-dist/skills/pf-story/scripts/story-template.sh +0 -0
- package/pennyfarthing-dist/skills/skill-registry.yaml +19 -0
- package/pennyfarthing-dist/workflows/release/steps/step-10-publish.md +41 -9
- package/pennyfarthing-dist/workflows/tdd-tandem.yaml +15 -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/pennyfarthing-dist/pf/bikerack/changed_panel.py +0 -201
- package/scripts/README.md +0 -41
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syntax Highlighting Utilities
|
|
3
|
+
*
|
|
4
|
+
* Story MSSCI-13970: TypeScript syntax highlighting utilities extracted from
|
|
5
|
+
* js/components/message-view/syntax-highlighter.js
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Tokenizer-based highlighting (avoids regex conflicts)
|
|
9
|
+
* - Multi-language support: JS/TS, Python, Go, Rust, Bash
|
|
10
|
+
* - Theme-aware via CSS classes
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Keyword sets by language family
|
|
14
|
+
const jsKeywords = new Set([
|
|
15
|
+
'const', 'let', 'var', 'function', 'return', 'if', 'else', 'for', 'while',
|
|
16
|
+
'do', 'switch', 'case', 'break', 'continue', 'new', 'this', 'class',
|
|
17
|
+
'extends', 'import', 'export', 'from', 'default', 'async', 'await', 'try',
|
|
18
|
+
'catch', 'finally', 'throw', 'typeof', 'instanceof', 'in', 'of', 'true',
|
|
19
|
+
'false', 'null', 'undefined', 'void',
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
const pyKeywords = new Set([
|
|
23
|
+
'def', 'class', 'return', 'if', 'elif', 'else', 'for', 'while', 'break',
|
|
24
|
+
'continue', 'import', 'from', 'as', 'try', 'except', 'finally', 'raise',
|
|
25
|
+
'with', 'lambda', 'yield', 'True', 'False', 'None', 'and', 'or', 'not',
|
|
26
|
+
'in', 'is', 'pass', 'self',
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
const goKeywords = new Set([
|
|
30
|
+
'func', 'return', 'if', 'else', 'for', 'range', 'switch', 'case', 'break',
|
|
31
|
+
'continue', 'go', 'defer', 'chan', 'select', 'type', 'struct', 'interface',
|
|
32
|
+
'map', 'package', 'import', 'var', 'const', 'true', 'false', 'nil', 'make',
|
|
33
|
+
'new', 'append', 'len', 'cap', 'error',
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
const rustKeywords = new Set([
|
|
37
|
+
'fn', 'let', 'mut', 'return', 'if', 'else', 'for', 'while', 'loop', 'match',
|
|
38
|
+
'break', 'continue', 'impl', 'struct', 'enum', 'trait', 'pub', 'use', 'mod',
|
|
39
|
+
'crate', 'self', 'super', 'where', 'async', 'await', 'true', 'false', 'Some',
|
|
40
|
+
'None', 'Ok', 'Err',
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
const shKeywords = new Set([
|
|
44
|
+
'if', 'then', 'else', 'elif', 'fi', 'for', 'while', 'do', 'done', 'case',
|
|
45
|
+
'esac', 'function', 'return', 'exit', 'export', 'source', 'alias', 'cd',
|
|
46
|
+
'echo', 'printf', 'read', 'local',
|
|
47
|
+
]);
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Supported language identifiers for syntax highlighting.
|
|
51
|
+
*/
|
|
52
|
+
export type SupportedLanguage =
|
|
53
|
+
| 'js' | 'javascript' | 'ts' | 'typescript' | 'jsx' | 'tsx'
|
|
54
|
+
| 'python' | 'py'
|
|
55
|
+
| 'go' | 'golang'
|
|
56
|
+
| 'rust' | 'rs'
|
|
57
|
+
| 'bash' | 'sh' | 'shell' | 'zsh';
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get keywords set for a language.
|
|
61
|
+
* @param lang - Language identifier
|
|
62
|
+
* @returns Keywords for the language, or empty set if unsupported
|
|
63
|
+
*/
|
|
64
|
+
export function getKeywordsForLanguage(lang: string): Set<string> {
|
|
65
|
+
const language = lang.toLowerCase();
|
|
66
|
+
|
|
67
|
+
if (['js', 'javascript', 'ts', 'typescript', 'jsx', 'tsx'].includes(language)) {
|
|
68
|
+
return jsKeywords;
|
|
69
|
+
}
|
|
70
|
+
if (['python', 'py'].includes(language)) {
|
|
71
|
+
return pyKeywords;
|
|
72
|
+
}
|
|
73
|
+
if (['go', 'golang'].includes(language)) {
|
|
74
|
+
return goKeywords;
|
|
75
|
+
}
|
|
76
|
+
if (['rust', 'rs'].includes(language)) {
|
|
77
|
+
return rustKeywords;
|
|
78
|
+
}
|
|
79
|
+
if (['bash', 'sh', 'shell', 'zsh'].includes(language)) {
|
|
80
|
+
return shKeywords;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return new Set();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Check if a language is supported for syntax highlighting.
|
|
88
|
+
* @param lang - Language identifier
|
|
89
|
+
* @returns true if language is supported
|
|
90
|
+
*/
|
|
91
|
+
export function isSupportedLanguage(lang: string): boolean {
|
|
92
|
+
return getKeywordsForLanguage(lang).size > 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Check if language uses // for comments.
|
|
97
|
+
* @param lang - Language identifier
|
|
98
|
+
* @returns true if language uses slash comments
|
|
99
|
+
*/
|
|
100
|
+
function usesSlashComments(lang: string): boolean {
|
|
101
|
+
const language = lang.toLowerCase();
|
|
102
|
+
return ['js', 'javascript', 'ts', 'typescript', 'jsx', 'tsx', 'go', 'golang', 'rust', 'rs'].includes(language);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Check if language uses # for comments.
|
|
107
|
+
* @param lang - Language identifier
|
|
108
|
+
* @returns true if language uses hash comments
|
|
109
|
+
*/
|
|
110
|
+
function usesHashComments(lang: string): boolean {
|
|
111
|
+
const language = lang.toLowerCase();
|
|
112
|
+
return ['python', 'py', 'bash', 'sh', 'shell', 'zsh'].includes(language);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Highlight a single line of code using tokenizer approach.
|
|
117
|
+
* @param line - Line to highlight (already HTML-escaped)
|
|
118
|
+
* @param keywords - Keywords set for the language
|
|
119
|
+
* @param lang - Language for comment detection
|
|
120
|
+
* @returns HTML with highlighting spans
|
|
121
|
+
*/
|
|
122
|
+
function highlightLine(line: string, keywords: Set<string>, lang: string): string {
|
|
123
|
+
if (!line.trim()) return line;
|
|
124
|
+
|
|
125
|
+
// Handle full-line comments
|
|
126
|
+
const trimmed = line.trim();
|
|
127
|
+
if (usesSlashComments(lang) && trimmed.startsWith('//')) {
|
|
128
|
+
return `<span class="comment">${line}</span>`;
|
|
129
|
+
}
|
|
130
|
+
if (usesHashComments(lang) && trimmed.startsWith('#')) {
|
|
131
|
+
return `<span class="comment">${line}</span>`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Tokenize the line character by character
|
|
135
|
+
let result = '';
|
|
136
|
+
let i = 0;
|
|
137
|
+
|
|
138
|
+
while (i < line.length) {
|
|
139
|
+
// Check for HTML-escaped double quote string: "..."
|
|
140
|
+
if (line.slice(i, i + 6) === '"') {
|
|
141
|
+
const endIdx = line.indexOf('"', i + 6);
|
|
142
|
+
if (endIdx !== -1) {
|
|
143
|
+
result += `<span class="string">${line.slice(i, endIdx + 6)}</span>`;
|
|
144
|
+
i = endIdx + 6;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Check for HTML-escaped single quote string: '...' or '...'
|
|
150
|
+
if (line.slice(i, i + 5) === ''' || line.slice(i, i + 6) === ''') {
|
|
151
|
+
const quoteLen = line.slice(i, i + 6) === ''' ? 6 : 5;
|
|
152
|
+
const quote = line.slice(i, i + quoteLen);
|
|
153
|
+
const endIdx = line.indexOf(quote, i + quoteLen);
|
|
154
|
+
if (endIdx !== -1) {
|
|
155
|
+
result += `<span class="string">${line.slice(i, endIdx + quoteLen)}</span>`;
|
|
156
|
+
i = endIdx + quoteLen;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Check for word (identifier/keyword)
|
|
162
|
+
if (/[a-zA-Z_]/.test(line[i])) {
|
|
163
|
+
let word = '';
|
|
164
|
+
while (i < line.length && /[a-zA-Z0-9_]/.test(line[i])) {
|
|
165
|
+
word += line[i];
|
|
166
|
+
i++;
|
|
167
|
+
}
|
|
168
|
+
if (keywords.has(word)) {
|
|
169
|
+
result += `<span class="keyword">${word}</span>`;
|
|
170
|
+
} else if (line[i] === '(') {
|
|
171
|
+
result += `<span class="function">${word}</span>`;
|
|
172
|
+
} else {
|
|
173
|
+
result += word;
|
|
174
|
+
}
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Check for number
|
|
179
|
+
if (/[0-9]/.test(line[i])) {
|
|
180
|
+
let num = '';
|
|
181
|
+
while (i < line.length && /[0-9.]/.test(line[i])) {
|
|
182
|
+
num += line[i];
|
|
183
|
+
i++;
|
|
184
|
+
}
|
|
185
|
+
result += `<span class="number">${num}</span>`;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Default: pass through character
|
|
190
|
+
result += line[i];
|
|
191
|
+
i++;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return result;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Highlight code with syntax highlighting.
|
|
199
|
+
* @param code - The code to highlight (already HTML escaped)
|
|
200
|
+
* @param lang - Language identifier (js, ts, python, etc.)
|
|
201
|
+
* @returns HTML with syntax highlighting spans
|
|
202
|
+
*/
|
|
203
|
+
export function highlightCode(code: string, lang: string): string {
|
|
204
|
+
if (!code || !lang) return code || '';
|
|
205
|
+
|
|
206
|
+
const keywords = getKeywordsForLanguage(lang);
|
|
207
|
+
|
|
208
|
+
// Process line by line
|
|
209
|
+
const lines = code.split('\n');
|
|
210
|
+
const highlightedLines = lines.map((line) => highlightLine(line, keywords, lang));
|
|
211
|
+
|
|
212
|
+
return highlightedLines.join('\n');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export default {
|
|
216
|
+
highlightCode,
|
|
217
|
+
getKeywordsForLanguage,
|
|
218
|
+
isSupportedLanguage,
|
|
219
|
+
};
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Intent Summarizer
|
|
3
|
+
*
|
|
4
|
+
* Story 74-1: Generates human-readable summaries of tool use intent.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const MAX_LENGTH = 70;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Truncates a string to the max length, adding ellipsis if needed.
|
|
11
|
+
* Also removes newlines to ensure single-line output.
|
|
12
|
+
*/
|
|
13
|
+
function truncate(str: string, maxLen: number = MAX_LENGTH - 10): string {
|
|
14
|
+
// Replace newlines with spaces for single-line output
|
|
15
|
+
const singleLine = str.replace(/\n/g, ' ');
|
|
16
|
+
if (singleLine.length <= maxLen) return singleLine;
|
|
17
|
+
return singleLine.slice(0, maxLen - 3) + '...';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Safely gets a string value from input, returning empty string for null/undefined.
|
|
22
|
+
*/
|
|
23
|
+
function getString(input: Record<string, unknown> | null | undefined, key: string): string {
|
|
24
|
+
if (!input) return '';
|
|
25
|
+
const value = input[key];
|
|
26
|
+
if (value === null || value === undefined || value === '') return '';
|
|
27
|
+
return String(value);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Extracts the hostname from a URL.
|
|
32
|
+
*/
|
|
33
|
+
function extractHostname(url: string): string {
|
|
34
|
+
try {
|
|
35
|
+
const parsed = new URL(url);
|
|
36
|
+
return parsed.hostname;
|
|
37
|
+
} catch {
|
|
38
|
+
return url;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Detects special bash command patterns and returns a semantic summary.
|
|
44
|
+
*/
|
|
45
|
+
function summarizeBashCommand(command: string): string {
|
|
46
|
+
const cmd = command.toLowerCase();
|
|
47
|
+
|
|
48
|
+
// Package install commands
|
|
49
|
+
if (
|
|
50
|
+
cmd.startsWith('npm install') ||
|
|
51
|
+
cmd.startsWith('npm i ') ||
|
|
52
|
+
cmd === 'npm i' ||
|
|
53
|
+
cmd.startsWith('pnpm install') ||
|
|
54
|
+
cmd.startsWith('pnpm add') ||
|
|
55
|
+
cmd.startsWith('yarn install') ||
|
|
56
|
+
cmd.startsWith('yarn add')
|
|
57
|
+
) {
|
|
58
|
+
return 'Installing dependencies';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Test commands
|
|
62
|
+
if (
|
|
63
|
+
cmd.startsWith('npm test') ||
|
|
64
|
+
cmd.startsWith('npm run test') ||
|
|
65
|
+
cmd.startsWith('pnpm test') ||
|
|
66
|
+
cmd.startsWith('pnpm run test') ||
|
|
67
|
+
cmd.startsWith('yarn test') ||
|
|
68
|
+
cmd.startsWith('vitest') ||
|
|
69
|
+
cmd.startsWith('jest')
|
|
70
|
+
) {
|
|
71
|
+
return 'Running tests';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Build commands
|
|
75
|
+
if (
|
|
76
|
+
cmd.startsWith('npm run build') ||
|
|
77
|
+
cmd.startsWith('pnpm run build') ||
|
|
78
|
+
cmd.startsWith('pnpm build') ||
|
|
79
|
+
cmd.startsWith('yarn build')
|
|
80
|
+
) {
|
|
81
|
+
return 'Building project';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// TypeScript type checking
|
|
85
|
+
if (cmd.startsWith('tsc')) {
|
|
86
|
+
return 'Type checking';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Linting
|
|
90
|
+
if (cmd.startsWith('eslint') || cmd.startsWith('npm run lint') || cmd.startsWith('pnpm lint')) {
|
|
91
|
+
return 'Linting code';
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Formatting
|
|
95
|
+
if (cmd.startsWith('prettier')) {
|
|
96
|
+
return 'Formatting code';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Default: show the command
|
|
100
|
+
return `Running ${truncate(command, MAX_LENGTH - 8)}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Generates a human-readable summary of what a tool is doing based on its name and input.
|
|
105
|
+
*
|
|
106
|
+
* @param toolName - The name of the tool (Read, Bash, Glob, Grep, Write, Edit, Task, etc.)
|
|
107
|
+
* @param input - The input parameters passed to the tool
|
|
108
|
+
* @returns A human-readable summary string
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* generateToolIntentSummary('Read', { file_path: '/src/foo.ts' })
|
|
112
|
+
* // Returns: "Reading /src/foo.ts"
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* generateToolIntentSummary('Bash', { command: 'npm install' })
|
|
116
|
+
* // Returns: "Installing dependencies"
|
|
117
|
+
*/
|
|
118
|
+
export function generateToolIntentSummary(
|
|
119
|
+
toolName: string,
|
|
120
|
+
input: Record<string, unknown>
|
|
121
|
+
): string {
|
|
122
|
+
// Handle null/undefined input
|
|
123
|
+
const safeInput = input ?? {};
|
|
124
|
+
|
|
125
|
+
switch (toolName) {
|
|
126
|
+
case 'Read': {
|
|
127
|
+
const filePath = getString(safeInput, 'file_path');
|
|
128
|
+
if (!filePath) return 'Read';
|
|
129
|
+
return truncate(`Reading ${filePath}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
case 'Bash': {
|
|
133
|
+
// Prefer Claude's description if provided (human-readable intent)
|
|
134
|
+
const description = getString(safeInput, 'description');
|
|
135
|
+
if (description) return truncate(description);
|
|
136
|
+
// Fall back to command-based summarization
|
|
137
|
+
const command = getString(safeInput, 'command');
|
|
138
|
+
if (!command) return 'Bash';
|
|
139
|
+
return summarizeBashCommand(command);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
case 'Glob': {
|
|
143
|
+
const pattern = getString(safeInput, 'pattern');
|
|
144
|
+
if (!pattern) return 'Glob';
|
|
145
|
+
return truncate(`Finding ${pattern} files`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
case 'Grep': {
|
|
149
|
+
const pattern = getString(safeInput, 'pattern');
|
|
150
|
+
if (!pattern) return 'Grep';
|
|
151
|
+
// Remove outer quotes if present for display
|
|
152
|
+
const displayPattern = pattern.replace(/^["']|["']$/g, '');
|
|
153
|
+
return truncate(`Searching for '${displayPattern}'`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
case 'Write': {
|
|
157
|
+
const filePath = getString(safeInput, 'file_path');
|
|
158
|
+
if (!filePath) return 'Write';
|
|
159
|
+
return truncate(`Creating ${filePath}`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
case 'Edit': {
|
|
163
|
+
const filePath = getString(safeInput, 'file_path');
|
|
164
|
+
if (!filePath) return 'Edit';
|
|
165
|
+
return truncate(`Editing ${filePath}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
case 'Task': {
|
|
169
|
+
const subagentType = getString(safeInput, 'subagent_type');
|
|
170
|
+
if (!subagentType) return 'Task';
|
|
171
|
+
return `Launching ${subagentType} agent`;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
case 'WebFetch': {
|
|
175
|
+
const url = getString(safeInput, 'url');
|
|
176
|
+
if (!url) return 'WebFetch';
|
|
177
|
+
const hostname = extractHostname(url);
|
|
178
|
+
return truncate(`Fetching ${hostname}`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
case 'WebSearch': {
|
|
182
|
+
const query = getString(safeInput, 'query');
|
|
183
|
+
if (!query) return 'WebSearch';
|
|
184
|
+
return truncate(`Searching web for '${query}'`);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
default: {
|
|
188
|
+
// Unknown tool: show tool name with truncated JSON
|
|
189
|
+
try {
|
|
190
|
+
const jsonStr = JSON.stringify(safeInput);
|
|
191
|
+
if (jsonStr === '{}') return toolName;
|
|
192
|
+
const maxJsonLen = MAX_LENGTH - toolName.length - 3; // space + parens
|
|
193
|
+
return `${toolName} (${truncate(jsonStr, maxJsonLen)})`;
|
|
194
|
+
} catch {
|
|
195
|
+
return toolName;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Stack Grouper Utility
|
|
3
|
+
*
|
|
4
|
+
* Groups consecutive tool_use messages into collapsible stacks.
|
|
5
|
+
* Story MSSCI-13400 - Tool use stack between messages
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface ToolUseMessage {
|
|
9
|
+
type: 'tool_use';
|
|
10
|
+
tool_name: string;
|
|
11
|
+
tool_id: string;
|
|
12
|
+
input: Record<string, unknown>;
|
|
13
|
+
timestamp: number;
|
|
14
|
+
isStreaming?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ToolStackData {
|
|
18
|
+
stackId: string;
|
|
19
|
+
tools: ToolUseMessage[];
|
|
20
|
+
count: number;
|
|
21
|
+
isActive: boolean;
|
|
22
|
+
timestamp: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface Message {
|
|
26
|
+
type: string;
|
|
27
|
+
timestamp: number;
|
|
28
|
+
tool_name?: string;
|
|
29
|
+
tool_id?: string;
|
|
30
|
+
input?: Record<string, unknown>;
|
|
31
|
+
isStreaming?: boolean;
|
|
32
|
+
content?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Groups consecutive tool_use messages into stacks.
|
|
37
|
+
*
|
|
38
|
+
* Rules:
|
|
39
|
+
* - tool_result messages do NOT break the stack (they're paired with tool_use elsewhere)
|
|
40
|
+
* - assistant/user messages DO break the stack
|
|
41
|
+
* - Single tool_use messages ARE grouped (consistent rendering with multi-tool stacks)
|
|
42
|
+
* - Returns array of ToolStackData, each representing 1+ consecutive tools
|
|
43
|
+
*
|
|
44
|
+
* @param messages - Array of messages to process
|
|
45
|
+
* @returns Array of tool stacks (only stacks with 2+ tools)
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* Generate a stable stack ID from the first tool's ID.
|
|
49
|
+
* This ensures the same stack keeps the same key across re-renders,
|
|
50
|
+
* preventing React from remounting and losing collapse state.
|
|
51
|
+
*/
|
|
52
|
+
function generateStableStackId(tools: ToolUseMessage[]): string {
|
|
53
|
+
if (tools.length === 0) return 'stack-empty';
|
|
54
|
+
// Use first tool's ID as anchor - it won't change as more tools are added
|
|
55
|
+
return `stack-${tools[0].tool_id}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function groupToolsIntoStacks(messages: Message[]): ToolStackData[] {
|
|
59
|
+
const stacks: ToolStackData[] = [];
|
|
60
|
+
let currentTools: ToolUseMessage[] = [];
|
|
61
|
+
|
|
62
|
+
for (const msg of messages) {
|
|
63
|
+
if (msg.type === 'tool_use') {
|
|
64
|
+
// Add to current stack
|
|
65
|
+
currentTools.push({
|
|
66
|
+
type: 'tool_use',
|
|
67
|
+
tool_name: msg.tool_name || '',
|
|
68
|
+
tool_id: msg.tool_id || '',
|
|
69
|
+
input: msg.input || {},
|
|
70
|
+
timestamp: msg.timestamp,
|
|
71
|
+
isStreaming: msg.isStreaming,
|
|
72
|
+
});
|
|
73
|
+
} else if (msg.type === 'tool_result') {
|
|
74
|
+
// tool_result does NOT break the stack - it's matched separately
|
|
75
|
+
continue;
|
|
76
|
+
} else {
|
|
77
|
+
// assistant, user, or other message types break the stack
|
|
78
|
+
// Create stack for any tools (single tools also get stacked for consistent rendering)
|
|
79
|
+
if (currentTools.length >= 1) {
|
|
80
|
+
const lastTool = currentTools[currentTools.length - 1];
|
|
81
|
+
stacks.push({
|
|
82
|
+
stackId: generateStableStackId(currentTools),
|
|
83
|
+
tools: [...currentTools],
|
|
84
|
+
count: currentTools.length,
|
|
85
|
+
isActive: lastTool.isStreaming === true,
|
|
86
|
+
timestamp: currentTools[0].timestamp,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
currentTools = [];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Handle remaining tools at end of messages
|
|
94
|
+
if (currentTools.length >= 1) {
|
|
95
|
+
const lastTool = currentTools[currentTools.length - 1];
|
|
96
|
+
stacks.push({
|
|
97
|
+
stackId: generateStableStackId(currentTools),
|
|
98
|
+
tools: [...currentTools],
|
|
99
|
+
count: currentTools.length,
|
|
100
|
+
isActive: lastTool.isStreaming === true,
|
|
101
|
+
timestamp: currentTools[0].timestamp,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return stacks;
|
|
106
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool type color mappings
|
|
3
|
+
*
|
|
4
|
+
* Story MSSCI-13402 - Tool use visual design polish
|
|
5
|
+
*
|
|
6
|
+
* Provides color values and CSS class names for each tool type.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** Tool type to color hex mapping */
|
|
10
|
+
export const TOOL_TYPE_COLORS: Record<string, string> = {
|
|
11
|
+
Read: '#3b82f6', // blue
|
|
12
|
+
Write: '#f97316', // orange
|
|
13
|
+
Bash: '#22c55e', // green
|
|
14
|
+
Glob: '#a855f7', // purple
|
|
15
|
+
Grep: '#06b6d4', // cyan
|
|
16
|
+
Edit: '#eab308', // yellow
|
|
17
|
+
Task: '#ec4899', // pink
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/** Default color for unknown tools */
|
|
21
|
+
export const DEFAULT_TOOL_COLOR = '#6b7280'; // gray
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get the color hex value for a tool type
|
|
25
|
+
*
|
|
26
|
+
* @param toolName - The name of the tool
|
|
27
|
+
* @returns Color hex string
|
|
28
|
+
*/
|
|
29
|
+
export function getToolTypeColor(toolName: string): string {
|
|
30
|
+
return TOOL_TYPE_COLORS[toolName] || DEFAULT_TOOL_COLOR;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get the CSS class name for a tool type
|
|
35
|
+
*
|
|
36
|
+
* @param toolName - The name of the tool
|
|
37
|
+
* @returns CSS class name like "tool-read" or "tool-unknown"
|
|
38
|
+
*/
|
|
39
|
+
export function getToolTypeClass(toolName: string): string {
|
|
40
|
+
const knownTools = ['Read', 'Write', 'Bash', 'Glob', 'Grep', 'Edit', 'Task'];
|
|
41
|
+
if (knownTools.includes(toolName)) {
|
|
42
|
+
return `tool-${toolName.toLowerCase()}`;
|
|
43
|
+
}
|
|
44
|
+
return '';
|
|
45
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -84,7 +84,6 @@ def bc():
|
|
|
84
84
|
workflow - Focus on Workflow panel
|
|
85
85
|
background - Focus on Background panel
|
|
86
86
|
audit-log - Focus on Audit Log panel
|
|
87
|
-
changed - Focus on Changed panel
|
|
88
87
|
ac - Focus on Acceptance Criteria panel
|
|
89
88
|
debug - Focus on Debug panel
|
|
90
89
|
settings - Focus on Settings panel
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -22,7 +22,6 @@ PANEL_ICONS: dict[str, tuple[str, str]] = {
|
|
|
22
22
|
"workflow": ("\uf126", "W"), # nf-fa-code_fork
|
|
23
23
|
"background": ("\uf110", "B"), # nf-fa-spinner
|
|
24
24
|
"audit-log": ("\uf15c", "L"), # nf-fa-file_text
|
|
25
|
-
"changed": ("\uf044", "C"), # nf-fa-pencil_square_o
|
|
26
25
|
"ac": ("\uf00c", "A"), # nf-fa-check
|
|
27
26
|
"debug": ("\uf188", "d"), # nf-fa-bug
|
|
28
27
|
"settings": ("\uf013", "S"), # nf-fa-gear
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"""Cross-panel event bus for BikeRack TUI (Story 110-1).
|
|
2
2
|
|
|
3
3
|
Defines Textual Message subclasses for inter-panel communication.
|
|
4
|
-
First use case: NavigateToFile posted by ChangedPanel, handled by App
|
|
5
|
-
to switch to DiffsPanel filtered to that file.
|
|
6
4
|
"""
|
|
7
5
|
|
|
8
6
|
from __future__ import annotations
|
|
@@ -17,11 +15,7 @@ class PanelEvent(Message):
|
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
class NavigateToFile(PanelEvent):
|
|
20
|
-
"""Navigate to a specific file in the diffs panel.
|
|
21
|
-
|
|
22
|
-
Posted by ChangedPanel when user presses Enter on a selected file.
|
|
23
|
-
Handled by BikeRackApp to switch to DiffsPanel and navigate to that file.
|
|
24
|
-
"""
|
|
18
|
+
"""Navigate to a specific file in the diffs panel."""
|
|
25
19
|
|
|
26
20
|
def __init__(self, path: str) -> None:
|
|
27
21
|
super().__init__()
|