@pennyfarthing/core 11.1.1 → 11.2.1
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 +8 -8
- package/package.json +2 -1
- package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/doctor.js +381 -66
- package/packages/core/dist/cli/commands/doctor.js.map +1 -1
- package/packages/core/dist/cli/commands/init.js +4 -4
- package/packages/core/dist/cli/commands/init.js.map +1 -1
- package/packages/core/dist/cli/commands/update.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/update.js +4 -5
- package/packages/core/dist/cli/commands/update.js.map +1 -1
- package/packages/core/dist/cli/utils/constants.d.ts +3 -8
- package/packages/core/dist/cli/utils/constants.d.ts.map +1 -1
- package/packages/core/dist/cli/utils/constants.js +3 -4
- package/packages/core/dist/cli/utils/constants.js.map +1 -1
- package/packages/core/dist/cli/utils/settings.d.ts +11 -0
- package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
- package/packages/core/dist/cli/utils/settings.js +65 -29
- package/packages/core/dist/cli/utils/settings.js.map +1 -1
- package/packages/core/dist/cli/utils/symlinks.js +16 -16
- package/packages/core/dist/cli/utils/symlinks.js.map +1 -1
- package/packages/core/dist/consultation/tandem-metrics.d.ts +91 -0
- package/packages/core/dist/consultation/tandem-metrics.d.ts.map +1 -0
- package/packages/core/dist/consultation/tandem-metrics.js +131 -0
- package/packages/core/dist/consultation/tandem-metrics.js.map +1 -0
- package/packages/core/dist/consultation/tandem-metrics.test.d.ts +18 -0
- package/packages/core/dist/consultation/tandem-metrics.test.d.ts.map +1 -0
- package/packages/core/dist/consultation/tandem-metrics.test.js +457 -0
- package/packages/core/dist/consultation/tandem-metrics.test.js.map +1 -0
- package/packages/core/dist/public/js/react/react.js +14 -14
- 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/server/api/agent-load.js +1 -1
- package/packages/core/dist/server/api/agent-load.js.map +1 -1
- package/packages/core/dist/server/otlp-receiver.d.ts +16 -11
- package/packages/core/dist/server/otlp-receiver.d.ts.map +1 -1
- package/packages/core/dist/server/otlp-receiver.js +185 -24
- package/packages/core/dist/server/otlp-receiver.js.map +1 -1
- package/packages/core/dist/server/otlp-receiver.test.d.ts +21 -0
- package/packages/core/dist/server/otlp-receiver.test.d.ts.map +1 -0
- package/packages/core/dist/server/otlp-receiver.test.js +446 -0
- package/packages/core/dist/server/otlp-receiver.test.js.map +1 -0
- package/packages/core/dist/server/server.d.ts +0 -3
- package/packages/core/dist/server/server.d.ts.map +1 -1
- package/packages/core/dist/server/server.js +3 -37
- package/packages/core/dist/server/server.js.map +1 -1
- package/packages/core/dist/server/server.test.d.ts +1 -1
- package/packages/core/dist/server/server.test.js +12 -23
- package/packages/core/dist/server/server.test.js.map +1 -1
- package/packages/core/dist/shared/capabilities.d.ts +88 -0
- package/packages/core/dist/shared/capabilities.d.ts.map +1 -0
- package/packages/core/dist/shared/capabilities.js +133 -0
- package/packages/core/dist/shared/capabilities.js.map +1 -0
- package/packages/core/dist/shared/capabilities.test.d.ts +2 -0
- package/packages/core/dist/shared/capabilities.test.d.ts.map +1 -0
- package/packages/core/dist/shared/capabilities.test.js +217 -0
- package/packages/core/dist/shared/capabilities.test.js.map +1 -0
- package/packages/core/dist/shared/portrait-resolver.d.ts +9 -0
- package/packages/core/dist/shared/portrait-resolver.d.ts.map +1 -1
- package/packages/core/dist/shared/portrait-resolver.js +27 -0
- package/packages/core/dist/shared/portrait-resolver.js.map +1 -1
- package/packages/core/dist/shared/portrait-resolver.test.js +47 -1
- package/packages/core/dist/shared/portrait-resolver.test.js.map +1 -1
- package/packages/core/dist/shared/spawn-prompt.d.ts +47 -0
- package/packages/core/dist/shared/spawn-prompt.d.ts.map +1 -0
- package/packages/core/dist/shared/spawn-prompt.js +82 -0
- package/packages/core/dist/shared/spawn-prompt.js.map +1 -0
- package/packages/core/dist/shared/spawn-prompt.test.d.ts +2 -0
- package/packages/core/dist/shared/spawn-prompt.test.d.ts.map +1 -0
- package/packages/core/dist/shared/spawn-prompt.test.js +251 -0
- package/packages/core/dist/shared/spawn-prompt.test.js.map +1 -0
- package/packages/core/dist/shared/tandem-portrait-inventory.test.d.ts +13 -0
- package/packages/core/dist/shared/tandem-portrait-inventory.test.d.ts.map +1 -0
- package/packages/core/dist/shared/tandem-portrait-inventory.test.js +126 -0
- package/packages/core/dist/shared/tandem-portrait-inventory.test.js.map +1 -0
- package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts +18 -0
- package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/tandem-workflow-templates.test.js +434 -0
- package/packages/core/dist/workflow/tandem-workflow-templates.test.js.map +1 -0
- package/packages/core/dist/workflow/workflow-schema.d.ts +32 -0
- package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.js +120 -0
- package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.test.js +570 -1
- package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
- package/pennyfarthing-dist/agents/dev.md +7 -11
- package/pennyfarthing-dist/agents/reviewer.md +9 -3
- package/pennyfarthing-dist/agents/sm-finish.md +18 -1
- package/pennyfarthing-dist/agents/sm-setup.md +1 -1
- package/pennyfarthing-dist/agents/sm.md +2 -2
- package/pennyfarthing-dist/agents/tea.md +1 -1
- package/pennyfarthing-dist/agents/testing-runner.md +2 -1
- package/pennyfarthing-dist/commands/pf-chore.md +2 -2
- package/pennyfarthing-dist/commands/pf-git.md +4 -2
- package/pennyfarthing-dist/commands/pf-standalone.md +7 -2
- package/pennyfarthing-dist/gates/approval.md +63 -0
- package/pennyfarthing-dist/gates/confidence-sm.md +71 -0
- package/pennyfarthing-dist/gates/context-ok.md +56 -0
- package/pennyfarthing-dist/gates/evaluations/confidence-sm.md +54 -0
- package/pennyfarthing-dist/gates/quality-pass.md +67 -0
- package/pennyfarthing-dist/gates/tests-fail.md +84 -0
- package/pennyfarthing-dist/gates/tests-pass.md +79 -0
- package/pennyfarthing-dist/guides/agent-behavior.md +23 -19
- package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +1 -1
- package/pennyfarthing-dist/guides/bell-mode.md +1 -1
- package/pennyfarthing-dist/guides/bikerack.md +3 -3
- package/pennyfarthing-dist/guides/hooks.md +29 -29
- package/pennyfarthing-dist/guides/reflector.md +1 -1
- package/pennyfarthing-dist/guides/tandem-protocol.md +3 -3
- package/pennyfarthing-dist/guides/worktree-mode.md +3 -3
- package/pennyfarthing-dist/guides/xml-tags.md +2 -2
- package/pennyfarthing-dist/scripts/README.md +1 -1
- package/pennyfarthing-dist/scripts/core/check-context.sh +3 -1
- package/pennyfarthing-dist/scripts/core/phase-check-start.sh +5 -87
- package/pennyfarthing-dist/scripts/git/README.md +24 -14
- package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +5 -266
- package/pennyfarthing-dist/scripts/git/git-status-all.sh +5 -151
- package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +6 -144
- package/pennyfarthing-dist/scripts/git/worktree-manager.sh +5 -496
- package/pennyfarthing-dist/scripts/hooks/README.md +6 -6
- package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +4 -183
- package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +4 -95
- package/pennyfarthing-dist/scripts/hooks/context-warning.sh +4 -65
- package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +3 -31
- package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +9 -11
- package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +27 -33
- package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +4 -71
- package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +3 -19
- package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +4 -30
- package/pennyfarthing-dist/scripts/hooks/session-start.sh +3 -32
- package/pennyfarthing-dist/scripts/hooks/session-stop.sh +4 -65
- package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +4 -78
- package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +4 -93
- package/pennyfarthing-dist/scripts/misc/README.md +1 -1
- package/pennyfarthing-dist/scripts/misc/statusline.sh +4 -301
- package/pennyfarthing-dist/scripts/portraits/generate-tandem-portraits.sh +76 -0
- package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +4 -221
- package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +5 -13
- package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +4 -123
- package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +4 -33
- package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +4 -156
- package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +4 -131
- package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +4 -249
- package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +4 -160
- package/pennyfarthing-dist/skills/pf-bc/usage.md +1 -1
- package/pennyfarthing-dist/skills/pf-jira/examples.md +5 -2
- package/pennyfarthing-dist/skills/pf-workflow/examples.md +27 -16
- package/pennyfarthing-dist/skills/pf-workflow/skill.md +9 -12
- package/pennyfarthing-dist/skills/pf-workflow/usage.md +33 -8
- package/pennyfarthing-dist/templates/settings.local.json.template +19 -10
- package/pennyfarthing-dist/workflows/bdd-tandem.yaml +18 -6
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +1 -1
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +1 -1
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +1 -1
- package/pennyfarthing-dist/workflows/review-tandem.yaml +65 -0
- package/pennyfarthing-dist/workflows/tdd-tandem.yaml +16 -8
- package/pennyfarthing-dist/workflows/tdd.yaml +11 -2
- package/pennyfarthing_scripts/CLAUDE.md +45 -14
- package/pennyfarthing_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/bellmode_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/config.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/context.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/output.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/patch_mode.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/session_start_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/sprint.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/workflow.cpython-311.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/__pycache__/focus.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/cli.py +3 -5
- package/pennyfarthing_scripts/bellmode_hook.py +12 -296
- package/pennyfarthing_scripts/bikerack/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/audit_log_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/background_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/context_meter_footer.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/events.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/git_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/portrait_resolver.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_data.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_screen.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/audit_log_panel.py +119 -0
- package/pennyfarthing_scripts/bikerack/background_panel.py +86 -5
- package/pennyfarthing_scripts/bikerack/base_panel.py +87 -2
- package/pennyfarthing_scripts/bikerack/changed_panel.py +125 -29
- package/pennyfarthing_scripts/bikerack/context_meter_footer.py +88 -0
- package/pennyfarthing_scripts/bikerack/debug_panel.py +32 -2
- package/pennyfarthing_scripts/bikerack/diffs_panel.py +104 -17
- package/pennyfarthing_scripts/bikerack/events.py +28 -0
- package/pennyfarthing_scripts/bikerack/git_panel.py +103 -33
- package/pennyfarthing_scripts/bikerack/launcher.py +15 -15
- package/pennyfarthing_scripts/bikerack/portrait_resolver.py +139 -0
- package/pennyfarthing_scripts/bikerack/progress_panel.py +315 -0
- package/pennyfarthing_scripts/bikerack/sprint_panel.py +395 -32
- package/pennyfarthing_scripts/bikerack/story_detail_data.py +244 -0
- package/pennyfarthing_scripts/bikerack/story_detail_screen.py +176 -0
- package/pennyfarthing_scripts/bikerack/tui.py +575 -37
- package/pennyfarthing_scripts/bikerack/ws_client.py +2 -2
- package/pennyfarthing_scripts/brownfield/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/brownfield/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/brownfield/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/brownfield/__pycache__/discover.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/cli.py +42 -65
- package/pennyfarthing_scripts/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/__pycache__/output.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/__pycache__/themes.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/pr_config.py +38 -0
- package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/__init__.py +1 -0
- package/pennyfarthing_scripts/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/__pycache__/dialogue_manager.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/cli.py +149 -0
- package/pennyfarthing_scripts/consultation/dialogue_manager.py +417 -0
- package/pennyfarthing_scripts/context.py +3 -3
- package/pennyfarthing_scripts/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/epic/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/epic/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__init__.py +12 -1
- package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/create_branches.py +3 -4
- package/pennyfarthing_scripts/git/hooks_installer.py +152 -0
- package/pennyfarthing_scripts/git/repos.py +196 -0
- package/pennyfarthing_scripts/git/status_all.py +27 -11
- package/pennyfarthing_scripts/git/worktree.py +302 -0
- package/pennyfarthing_scripts/git_group/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git_group/cli.py +143 -40
- package/pennyfarthing_scripts/handoff/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/gate_file.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/gate_runner.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/marker.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/cli.py +33 -1
- package/pennyfarthing_scripts/handoff/complete_phase.py +40 -0
- package/pennyfarthing_scripts/handoff/marker.py +15 -15
- package/pennyfarthing_scripts/handoff/phase_check.py +96 -0
- package/pennyfarthing_scripts/handoff/resolve_gate.py +18 -15
- package/pennyfarthing_scripts/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__init__.py +437 -0
- package/pennyfarthing_scripts/hooks/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/bell_mode.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/context_breaker.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/context_warning.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/cyclist_pretooluse.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/pre_edit_check.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/reflector_check.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/schema_validation.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/session_start.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/session_stop.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/sprint_yaml_validation.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/statusline.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/bell_mode.py +215 -0
- package/pennyfarthing_scripts/hooks/cli.py +96 -0
- package/pennyfarthing_scripts/hooks/context_breaker.py +104 -0
- package/pennyfarthing_scripts/hooks/context_warning.py +66 -0
- package/pennyfarthing_scripts/hooks/cyclist_pretooluse.py +129 -0
- package/pennyfarthing_scripts/hooks/pre_edit_check.py +78 -0
- package/pennyfarthing_scripts/hooks/reflector_check.py +271 -0
- package/pennyfarthing_scripts/hooks/schema_validation.py +203 -0
- package/pennyfarthing_scripts/hooks/session_start.py +296 -0
- package/pennyfarthing_scripts/hooks/session_stop.py +111 -0
- package/pennyfarthing_scripts/hooks/sprint_yaml_validation.py +97 -0
- package/pennyfarthing_scripts/hooks/statusline.py +420 -0
- package/pennyfarthing_scripts/hooks.py +27 -446
- package/pennyfarthing_scripts/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/compat.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/create.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/mappings.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/operations.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/launch/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/launch/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/preflight/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/preflight/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/preflight/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/preflight/__pycache__/finish.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/pretooluse_hook.py +3 -185
- package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/version_sentinel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/heatmap.py +655 -0
- package/pennyfarthing_scripts/prime/workflow.py +2 -1
- package/pennyfarthing_scripts/schema_validation_hook.py +3 -298
- package/pennyfarthing_scripts/session/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/session/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/session_start_hook.py +4 -186
- package/pennyfarthing_scripts/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/epic_update.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/import_epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/status.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/story_add.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/loader.py +15 -1
- package/pennyfarthing_scripts/sprint/story_update.py +19 -0
- package/pennyfarthing_scripts/story/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/create.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/size.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/template.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_108_1_gate_migration.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_archive_epic.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_bc.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_bikerack.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_brownfield.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_cli_modules.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_cli_normalization.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_codemarkers.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_common.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_evaluation.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_gate.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_dialogue_manager.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_epic_shard_validation.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_git_utils.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_handoff_cli.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_handoff_e2e.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_sprint_panel.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_story_add.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_story_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_story_update.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_tiers.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_token_counting.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_topology_loader.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_tui_focus.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_tui_panel_persistence.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_validate_cmd.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_version_sentinel.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/test_bikerack.py +51 -51
- package/pennyfarthing_scripts/tests/test_dialogue_manager.py +811 -0
- package/pennyfarthing_scripts/tests/test_handoff_cli.py +16 -11
- package/pennyfarthing_scripts/tests/test_sprint_panel.py +344 -265
- package/pennyfarthing_scripts/tests/test_workflow_check.py +2 -3
- package/pennyfarthing_scripts/theme/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/theme/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/agent.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/schema.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/sprint.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/tandem_awareness.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/tandem_awareness.py +254 -0
- package/pennyfarthing_scripts/validate/adapters/workflow.py +19 -0
- package/pennyfarthing_scripts/validate/cli.py +17 -5
- package/pennyfarthing_scripts/welcome_hook.py +3 -149
- package/pennyfarthing_scripts/workflow/__init__.py +40 -0
- package/pennyfarthing_scripts/workflow/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/helpers.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/scale.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/state.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/cli.py +1100 -0
- package/pennyfarthing_scripts/workflow/helpers.py +241 -0
- package/pennyfarthing_scripts/{workflow.py → workflow/scale.py} +0 -104
- package/pennyfarthing_scripts/workflow/state.py +112 -0
- package/pennyfarthing_scripts/workflow/team_lifecycle.py +257 -0
- package/packages/core/dist/scripts/theme-detail.test.d.ts +0 -10
- package/packages/core/dist/scripts/theme-detail.test.js +0 -199
- package/pennyfarthing-dist/skills/pf-workflow/scripts/list-workflows.sh +0 -91
- package/pennyfarthing-dist/skills/pf-workflow/scripts/resume-workflow.sh +0 -163
- package/pennyfarthing-dist/skills/pf-workflow/scripts/show-workflow.sh +0 -138
- package/pennyfarthing-dist/skills/pf-workflow/scripts/start-workflow.sh +0 -273
- package/pennyfarthing-dist/skills/pf-workflow/scripts/workflow-status.sh +0 -167
- package/pennyfarthing_scripts/gate/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/gate/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/gate/__pycache__/validate.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_108_2_remove_handoff_fallback.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_gate_file_resolution.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_gate_runner.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_resolve_gate_file_field.cpython-314-pytest-9.0.2.pyc +0 -0
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { existsSync, readFileSync, readdirSync, writeFileSync, chmodSync, statSync, readlinkSync, symlinkSync, unlinkSync, mkdirSync, renameSync } from 'fs';
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, writeFileSync, chmodSync, statSync, readlinkSync, symlinkSync, unlinkSync, mkdirSync, renameSync, copyFileSync } from 'fs';
|
|
2
2
|
import { join, relative, dirname } from 'path';
|
|
3
3
|
import YAML from 'yaml';
|
|
4
4
|
import { spawnSync } from 'child_process';
|
|
5
5
|
import fsExtra from 'fs-extra';
|
|
6
|
-
const { removeSync, ensureDirSync } = fsExtra;
|
|
6
|
+
const { removeSync, ensureDirSync, copySync } = fsExtra;
|
|
7
7
|
import { logger } from '../utils/logger.js';
|
|
8
8
|
import { readManifest } from '../utils/manifest.js';
|
|
9
|
-
import { pathExists, isDirectory, isSymlink, fileMatchesHash } from '../utils/files.js';
|
|
10
|
-
import { getPackageVersion } from '../utils/version.js';
|
|
9
|
+
import { pathExists, isDirectory, isSymlink, fileMatchesHash, filesMatch } from '../utils/files.js';
|
|
10
|
+
import { getPackageVersion, getAssetsPath } from '../utils/version.js';
|
|
11
11
|
import { findNodeModulesPath } from '../utils/node-modules.js';
|
|
12
12
|
import { ALL_SYMLINKS, CORE_AGENTS } from '../utils/constants.js';
|
|
13
13
|
import { getPfVersion, installPfCli } from '../utils/python.js';
|
|
14
|
+
import { LEGACY_HOOK_MIGRATIONS, migrateHookPaths } from '../utils/settings.js';
|
|
14
15
|
export async function doctorCommand(options) {
|
|
15
16
|
const projectRoot = process.cwd();
|
|
16
17
|
// Handle dogfood mode - run checks for framework/orchestrator development
|
|
@@ -47,6 +48,7 @@ export async function doctorCommand(options) {
|
|
|
47
48
|
// Run checks
|
|
48
49
|
results.push(...checkInstallation(projectRoot, manifest));
|
|
49
50
|
results.push(...checkCoreFiles(projectRoot, manifest));
|
|
51
|
+
results.push(...checkCommandsAndSkills(projectRoot, nodeModulesPath));
|
|
50
52
|
results.push(...checkUserFiles(projectRoot));
|
|
51
53
|
results.push(...checkDirectories(projectRoot));
|
|
52
54
|
results.push(...checkHooks(projectRoot));
|
|
@@ -54,6 +56,7 @@ export async function doctorCommand(options) {
|
|
|
54
56
|
results.push(...checkFileLayout(projectRoot));
|
|
55
57
|
results.push(...checkLegacyFiles(projectRoot));
|
|
56
58
|
results.push(checkLegacyStatuslinePath(projectRoot));
|
|
59
|
+
results.push(checkLegacyHookCommands(projectRoot));
|
|
57
60
|
results.push(...checkCyclist(projectRoot));
|
|
58
61
|
results.push(checkPfCli(nodeModulesPath));
|
|
59
62
|
// Output results
|
|
@@ -64,7 +67,8 @@ export async function doctorCommand(options) {
|
|
|
64
67
|
// Display results by category
|
|
65
68
|
const categories = [
|
|
66
69
|
{ name: 'Installation', filter: (r) => r.name.startsWith('manifest') },
|
|
67
|
-
{ name: 'Core Files', filter: (r) => r.name.startsWith('core/') },
|
|
70
|
+
{ name: 'Core Files', filter: (r) => r.name.startsWith('core/') && r.name !== 'core/commands' && r.name !== 'core/skills' },
|
|
71
|
+
{ name: 'Commands & Skills', filter: (r) => r.name === 'core/commands' || r.name === 'core/skills' },
|
|
68
72
|
{ name: 'User Files', filter: (r) => r.name.startsWith('project/') || r.name.startsWith('persona') || r.name.startsWith('settings') },
|
|
69
73
|
{ name: 'Directories', filter: (r) => r.name.startsWith('dir/') },
|
|
70
74
|
{ name: 'Hooks', filter: (r) => r.name.startsWith('hook/') },
|
|
@@ -188,6 +192,211 @@ function checkCoreFiles(projectRoot, manifest) {
|
|
|
188
192
|
}
|
|
189
193
|
return results;
|
|
190
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Check commands and skills are properly copied (not symlinked) and up to date.
|
|
197
|
+
* Commands and skills are file copies since v11.3.0 to avoid node_modules drift.
|
|
198
|
+
*/
|
|
199
|
+
function checkCommandsAndSkills(projectRoot, nodeModulesPath) {
|
|
200
|
+
const results = [];
|
|
201
|
+
// Use assetsPath for source resolution (correct pf-* prefix in dogfood)
|
|
202
|
+
let assetsPath = null;
|
|
203
|
+
try {
|
|
204
|
+
assetsPath = getAssetsPath();
|
|
205
|
+
}
|
|
206
|
+
catch { /* no assets available */ }
|
|
207
|
+
if (!assetsPath) {
|
|
208
|
+
// Can't check freshness without assets, but check dirs exist
|
|
209
|
+
const commandsDir = join(projectRoot, '.claude/commands');
|
|
210
|
+
const skillsDir = join(projectRoot, '.claude/skills');
|
|
211
|
+
results.push({
|
|
212
|
+
name: 'core/commands',
|
|
213
|
+
status: pathExists(commandsDir) ? 'pass' : 'fail',
|
|
214
|
+
detail: pathExists(commandsDir) ? undefined : 'Missing .claude/commands/'
|
|
215
|
+
});
|
|
216
|
+
results.push({
|
|
217
|
+
name: 'core/skills',
|
|
218
|
+
status: pathExists(skillsDir) ? 'pass' : 'fail',
|
|
219
|
+
detail: pathExists(skillsDir) ? undefined : 'Missing .claude/skills/'
|
|
220
|
+
});
|
|
221
|
+
return results;
|
|
222
|
+
}
|
|
223
|
+
// Check commands
|
|
224
|
+
const commandsDir = join(projectRoot, '.claude/commands');
|
|
225
|
+
const builtInCommandsPath = join(assetsPath, 'commands');
|
|
226
|
+
if (!pathExists(commandsDir)) {
|
|
227
|
+
results.push({
|
|
228
|
+
name: 'core/commands',
|
|
229
|
+
status: 'fail',
|
|
230
|
+
detail: 'Missing .claude/commands/ — run pennyfarthing update'
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
else if (pathExists(builtInCommandsPath)) {
|
|
234
|
+
const sourceCommands = readdirSync(builtInCommandsPath).filter(f => f.endsWith('.md') && f.startsWith('pf-'));
|
|
235
|
+
const installedEntries = readdirSync(commandsDir).filter(f => f.startsWith('pf-'));
|
|
236
|
+
let staleCount = 0;
|
|
237
|
+
let symlinkCount = 0;
|
|
238
|
+
// Check for stale symlinks (legacy) or stale copies
|
|
239
|
+
for (const cmd of sourceCommands) {
|
|
240
|
+
const installedPath = join(commandsDir, cmd);
|
|
241
|
+
const sourcePath = join(builtInCommandsPath, cmd);
|
|
242
|
+
if (!pathExists(installedPath)) {
|
|
243
|
+
staleCount++;
|
|
244
|
+
}
|
|
245
|
+
else if (isSymlink(installedPath)) {
|
|
246
|
+
symlinkCount++;
|
|
247
|
+
}
|
|
248
|
+
else if (!filesMatch(installedPath, sourcePath)) {
|
|
249
|
+
staleCount++;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (symlinkCount > 0) {
|
|
253
|
+
results.push({
|
|
254
|
+
name: 'core/commands',
|
|
255
|
+
status: 'warn',
|
|
256
|
+
detail: `${symlinkCount} command(s) are symlinks — should be copies. Run pennyfarthing update`,
|
|
257
|
+
fix: () => {
|
|
258
|
+
refreshCommandsCopy(projectRoot, builtInCommandsPath);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
else if (staleCount > 0) {
|
|
263
|
+
results.push({
|
|
264
|
+
name: 'core/commands',
|
|
265
|
+
status: 'warn',
|
|
266
|
+
detail: `${staleCount} command(s) out of date — run pennyfarthing update`,
|
|
267
|
+
fix: () => {
|
|
268
|
+
refreshCommandsCopy(projectRoot, builtInCommandsPath);
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
results.push({
|
|
274
|
+
name: 'core/commands',
|
|
275
|
+
status: 'pass',
|
|
276
|
+
detail: `${installedEntries.length} commands`
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// Check skills
|
|
281
|
+
const skillsDir = join(projectRoot, '.claude/skills');
|
|
282
|
+
const builtInSkillsPath = join(assetsPath, 'skills');
|
|
283
|
+
if (!pathExists(skillsDir)) {
|
|
284
|
+
results.push({
|
|
285
|
+
name: 'core/skills',
|
|
286
|
+
status: 'fail',
|
|
287
|
+
detail: 'Missing .claude/skills/ — run pennyfarthing update'
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
else if (pathExists(builtInSkillsPath)) {
|
|
291
|
+
const sourceSkills = readdirSync(builtInSkillsPath).filter(f => {
|
|
292
|
+
const fullPath = join(builtInSkillsPath, f);
|
|
293
|
+
return isDirectory(fullPath) && f.startsWith('pf-');
|
|
294
|
+
});
|
|
295
|
+
const installedEntries = readdirSync(skillsDir).filter(f => f.startsWith('pf-'));
|
|
296
|
+
let missingCount = 0;
|
|
297
|
+
let symlinkCount = 0;
|
|
298
|
+
for (const skill of sourceSkills) {
|
|
299
|
+
const installedPath = join(skillsDir, skill);
|
|
300
|
+
if (!pathExists(installedPath)) {
|
|
301
|
+
missingCount++;
|
|
302
|
+
}
|
|
303
|
+
else if (isSymlink(installedPath)) {
|
|
304
|
+
symlinkCount++;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (symlinkCount > 0) {
|
|
308
|
+
results.push({
|
|
309
|
+
name: 'core/skills',
|
|
310
|
+
status: 'warn',
|
|
311
|
+
detail: `${symlinkCount} skill(s) are symlinks — should be copies. Run pennyfarthing update`,
|
|
312
|
+
fix: () => {
|
|
313
|
+
refreshSkillsCopy(projectRoot, builtInSkillsPath);
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
else if (missingCount > 0) {
|
|
318
|
+
results.push({
|
|
319
|
+
name: 'core/skills',
|
|
320
|
+
status: 'warn',
|
|
321
|
+
detail: `${missingCount} skill(s) missing — run pennyfarthing update`,
|
|
322
|
+
fix: () => {
|
|
323
|
+
refreshSkillsCopy(projectRoot, builtInSkillsPath);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
results.push({
|
|
329
|
+
name: 'core/skills',
|
|
330
|
+
status: 'pass',
|
|
331
|
+
detail: `${installedEntries.length} skills`
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return results;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Fix function: refresh commands by cleaning managed entries and copying fresh
|
|
339
|
+
*/
|
|
340
|
+
function refreshCommandsCopy(projectRoot, builtInCommandsPath) {
|
|
341
|
+
const commandsDir = join(projectRoot, '.claude/commands');
|
|
342
|
+
ensureDirSync(commandsDir);
|
|
343
|
+
// Clean all pf-* entries (symlinks or files)
|
|
344
|
+
const entries = readdirSync(commandsDir).filter(f => f.startsWith('pf-'));
|
|
345
|
+
for (const entry of entries) {
|
|
346
|
+
const entryPath = join(commandsDir, entry);
|
|
347
|
+
try {
|
|
348
|
+
unlinkSync(entryPath);
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
// Already gone
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// Copy fresh from source
|
|
355
|
+
const sourceCommands = readdirSync(builtInCommandsPath).filter(f => f.endsWith('.md') && f.startsWith('pf-'));
|
|
356
|
+
for (const cmd of sourceCommands) {
|
|
357
|
+
const sourcePath = join(builtInCommandsPath, cmd);
|
|
358
|
+
const destPath = join(commandsDir, cmd);
|
|
359
|
+
try {
|
|
360
|
+
copyFileSync(sourcePath, destPath);
|
|
361
|
+
}
|
|
362
|
+
catch (e) {
|
|
363
|
+
logger.warning(`Could not copy command ${cmd}: ${e}`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Fix function: refresh skills by cleaning managed entries and copying fresh
|
|
369
|
+
*/
|
|
370
|
+
function refreshSkillsCopy(projectRoot, builtInSkillsPath) {
|
|
371
|
+
const skillsDir = join(projectRoot, '.claude/skills');
|
|
372
|
+
ensureDirSync(skillsDir);
|
|
373
|
+
// Clean all pf-* entries (symlinks or directories)
|
|
374
|
+
const entries = readdirSync(skillsDir).filter(f => f.startsWith('pf-'));
|
|
375
|
+
for (const entry of entries) {
|
|
376
|
+
const entryPath = join(skillsDir, entry);
|
|
377
|
+
try {
|
|
378
|
+
removeSync(entryPath);
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
// Already gone
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
// Copy fresh from source
|
|
385
|
+
const sourceSkills = readdirSync(builtInSkillsPath).filter(f => {
|
|
386
|
+
const fullPath = join(builtInSkillsPath, f);
|
|
387
|
+
return isDirectory(fullPath) && f.startsWith('pf-');
|
|
388
|
+
});
|
|
389
|
+
for (const skill of sourceSkills) {
|
|
390
|
+
const sourcePath = join(builtInSkillsPath, skill);
|
|
391
|
+
const destPath = join(skillsDir, skill);
|
|
392
|
+
try {
|
|
393
|
+
copySync(sourcePath, destPath, { overwrite: true });
|
|
394
|
+
}
|
|
395
|
+
catch (e) {
|
|
396
|
+
logger.warning(`Could not copy skill ${skill}: ${e}`);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
191
400
|
/**
|
|
192
401
|
* Check symlinks for symlink installation mode
|
|
193
402
|
*/
|
|
@@ -441,11 +650,11 @@ function checkSessionStartHooks(projectRoot, installationType) {
|
|
|
441
650
|
}
|
|
442
651
|
};
|
|
443
652
|
}
|
|
444
|
-
// Check if session-start
|
|
653
|
+
// Check if session-start hook is configured (pf hooks or legacy .sh)
|
|
445
654
|
const hasSessionStartHook = settings.hooks.SessionStart.some((entry) => {
|
|
446
655
|
if (typeof entry === 'object' && entry !== null) {
|
|
447
656
|
const hookEntry = entry;
|
|
448
|
-
return hookEntry.hooks?.some(h => h.command?.includes('session-start.sh'));
|
|
657
|
+
return hookEntry.hooks?.some(h => h.command?.includes('pf hooks session-start') || h.command?.includes('session-start.sh'));
|
|
449
658
|
}
|
|
450
659
|
return false;
|
|
451
660
|
});
|
|
@@ -453,7 +662,7 @@ function checkSessionStartHooks(projectRoot, installationType) {
|
|
|
453
662
|
return {
|
|
454
663
|
name: 'settings/session-start-hook',
|
|
455
664
|
status: 'fail',
|
|
456
|
-
detail: 'session-start
|
|
665
|
+
detail: 'session-start hook not configured - PROJECT_ROOT will be undefined',
|
|
457
666
|
fix: () => {
|
|
458
667
|
addSessionStartHooks(projectRoot, installationType);
|
|
459
668
|
}
|
|
@@ -619,11 +828,11 @@ function checkStopHook(projectRoot, installationType) {
|
|
|
619
828
|
}
|
|
620
829
|
};
|
|
621
830
|
}
|
|
622
|
-
// Check if
|
|
831
|
+
// Check if reflector-check hook is configured (pf hooks or legacy .sh)
|
|
623
832
|
const hasReflectorHook = settings.hooks.Stop.some((entry) => {
|
|
624
833
|
if (typeof entry === 'object' && entry !== null) {
|
|
625
834
|
const hookEntry = entry;
|
|
626
|
-
return hookEntry.hooks?.some(h => h.command?.includes('question-reflector-check'));
|
|
835
|
+
return hookEntry.hooks?.some(h => h.command?.includes('pf hooks reflector-check') || h.command?.includes('question-reflector-check'));
|
|
627
836
|
}
|
|
628
837
|
return false;
|
|
629
838
|
});
|
|
@@ -631,7 +840,7 @@ function checkStopHook(projectRoot, installationType) {
|
|
|
631
840
|
return {
|
|
632
841
|
name: 'settings/stop-hook',
|
|
633
842
|
status: 'warn',
|
|
634
|
-
detail: '
|
|
843
|
+
detail: 'reflector-check hook not configured',
|
|
635
844
|
fix: () => {
|
|
636
845
|
addStopHook(projectRoot, installationType);
|
|
637
846
|
}
|
|
@@ -670,11 +879,11 @@ function checkContextCircuitBreaker(projectRoot, installationType) {
|
|
|
670
879
|
}
|
|
671
880
|
};
|
|
672
881
|
}
|
|
673
|
-
// Check if context-
|
|
882
|
+
// Check if context-breaker hook is configured (pf hooks or legacy .sh)
|
|
674
883
|
const hasCircuitBreaker = settings.hooks.PreToolUse.some((entry) => {
|
|
675
884
|
if (typeof entry === 'object' && entry !== null) {
|
|
676
885
|
const hookEntry = entry;
|
|
677
|
-
return hookEntry.hooks?.some(h => h.command?.includes('context-circuit-breaker'));
|
|
886
|
+
return hookEntry.hooks?.some(h => h.command?.includes('pf hooks context-breaker') || h.command?.includes('context-circuit-breaker'));
|
|
678
887
|
}
|
|
679
888
|
return false;
|
|
680
889
|
});
|
|
@@ -682,7 +891,7 @@ function checkContextCircuitBreaker(projectRoot, installationType) {
|
|
|
682
891
|
return {
|
|
683
892
|
name: 'settings/context-circuit-breaker',
|
|
684
893
|
status: 'warn',
|
|
685
|
-
detail: 'context-
|
|
894
|
+
detail: 'context-breaker hook not configured - context exhaustion protection disabled',
|
|
686
895
|
fix: () => {
|
|
687
896
|
addContextCircuitBreaker(projectRoot, installationType);
|
|
688
897
|
}
|
|
@@ -705,15 +914,14 @@ function checkContextCircuitBreaker(projectRoot, installationType) {
|
|
|
705
914
|
/**
|
|
706
915
|
* Fix function: Add context-circuit-breaker hook to PreToolUse in settings.local.json
|
|
707
916
|
*/
|
|
708
|
-
function addContextCircuitBreaker(projectRoot,
|
|
917
|
+
function addContextCircuitBreaker(projectRoot, _installationType) {
|
|
709
918
|
const settingsPath = join(projectRoot, '.claude/settings.local.json');
|
|
710
|
-
const scriptBase = getScriptBasePath(installationType);
|
|
711
919
|
const requiredHook = {
|
|
712
920
|
matcher: 'Edit|Write|Bash|Task',
|
|
713
921
|
hooks: [
|
|
714
922
|
{
|
|
715
923
|
type: 'command',
|
|
716
|
-
command:
|
|
924
|
+
command: 'pf hooks context-breaker'
|
|
717
925
|
}
|
|
718
926
|
]
|
|
719
927
|
};
|
|
@@ -794,15 +1002,14 @@ function checkSchemaValidationHook(projectRoot, installationType) {
|
|
|
794
1002
|
/**
|
|
795
1003
|
* Fix function: Add schema-validation hook to PreToolUse in settings.local.json
|
|
796
1004
|
*/
|
|
797
|
-
function addSchemaValidationHook(projectRoot,
|
|
1005
|
+
function addSchemaValidationHook(projectRoot, _installationType) {
|
|
798
1006
|
const settingsPath = join(projectRoot, '.claude/settings.local.json');
|
|
799
|
-
const scriptBase = getScriptBasePath(installationType);
|
|
800
1007
|
const requiredHook = {
|
|
801
1008
|
matcher: 'Write',
|
|
802
1009
|
hooks: [
|
|
803
1010
|
{
|
|
804
1011
|
type: 'command',
|
|
805
|
-
command:
|
|
1012
|
+
command: 'pf hooks schema-validation'
|
|
806
1013
|
}
|
|
807
1014
|
]
|
|
808
1015
|
};
|
|
@@ -848,11 +1055,11 @@ function checkPostToolUseHook(projectRoot, installationType) {
|
|
|
848
1055
|
}
|
|
849
1056
|
};
|
|
850
1057
|
}
|
|
851
|
-
// Check if bell-mode
|
|
1058
|
+
// Check if bell-mode hook is configured (pf hooks or legacy .sh)
|
|
852
1059
|
const hasBellModeHook = settings.hooks.PostToolUse.some((entry) => {
|
|
853
1060
|
if (typeof entry === 'object' && entry !== null) {
|
|
854
1061
|
const hookEntry = entry;
|
|
855
|
-
return hookEntry.hooks?.some(h => h.command?.includes('bell-mode-hook'));
|
|
1062
|
+
return hookEntry.hooks?.some(h => h.command?.includes('pf hooks bell-mode') || h.command?.includes('bell-mode-hook'));
|
|
856
1063
|
}
|
|
857
1064
|
return false;
|
|
858
1065
|
});
|
|
@@ -860,7 +1067,7 @@ function checkPostToolUseHook(projectRoot, installationType) {
|
|
|
860
1067
|
return {
|
|
861
1068
|
name: 'settings/post-tool-use-hook',
|
|
862
1069
|
status: 'warn',
|
|
863
|
-
detail: 'bell-mode
|
|
1070
|
+
detail: 'bell-mode hook not configured - bell mode will not work',
|
|
864
1071
|
fix: () => {
|
|
865
1072
|
addPostToolUseHook(projectRoot, installationType);
|
|
866
1073
|
}
|
|
@@ -884,15 +1091,14 @@ function checkPostToolUseHook(projectRoot, installationType) {
|
|
|
884
1091
|
* Fix function: Add PostToolUse hook to settings.local.json
|
|
885
1092
|
* Required for bell mode to inject queued messages via additionalContext
|
|
886
1093
|
*/
|
|
887
|
-
function addPostToolUseHook(projectRoot,
|
|
1094
|
+
function addPostToolUseHook(projectRoot, _installationType) {
|
|
888
1095
|
const settingsPath = join(projectRoot, '.claude/settings.local.json');
|
|
889
|
-
const scriptBase = getScriptBasePath(installationType);
|
|
890
1096
|
const requiredHook = {
|
|
891
1097
|
matcher: '',
|
|
892
1098
|
hooks: [
|
|
893
1099
|
{
|
|
894
1100
|
type: 'command',
|
|
895
|
-
command:
|
|
1101
|
+
command: 'pf hooks bell-mode'
|
|
896
1102
|
}
|
|
897
1103
|
]
|
|
898
1104
|
};
|
|
@@ -938,11 +1144,11 @@ function checkSprintYamlValidationHook(projectRoot, installationType) {
|
|
|
938
1144
|
}
|
|
939
1145
|
};
|
|
940
1146
|
}
|
|
941
|
-
// Check if sprint-yaml
|
|
1147
|
+
// Check if sprint-yaml hook is configured (pf hooks or legacy .sh)
|
|
942
1148
|
const hasSprintYamlValidation = settings.hooks.PostToolUse.some((entry) => {
|
|
943
1149
|
if (typeof entry === 'object' && entry !== null) {
|
|
944
1150
|
const hookEntry = entry;
|
|
945
|
-
return hookEntry.hooks?.some(h => h.command?.includes('sprint-yaml-validation'));
|
|
1151
|
+
return hookEntry.hooks?.some(h => h.command?.includes('pf hooks sprint-yaml') || h.command?.includes('sprint-yaml-validation'));
|
|
946
1152
|
}
|
|
947
1153
|
return false;
|
|
948
1154
|
});
|
|
@@ -950,7 +1156,7 @@ function checkSprintYamlValidationHook(projectRoot, installationType) {
|
|
|
950
1156
|
return {
|
|
951
1157
|
name: 'settings/sprint-yaml-validation',
|
|
952
1158
|
status: 'warn',
|
|
953
|
-
detail: 'sprint-yaml
|
|
1159
|
+
detail: 'sprint-yaml hook not configured - sprint YAML errors may break SprintPanel',
|
|
954
1160
|
fix: () => {
|
|
955
1161
|
addSprintYamlValidationHook(projectRoot, installationType);
|
|
956
1162
|
}
|
|
@@ -974,15 +1180,14 @@ function checkSprintYamlValidationHook(projectRoot, installationType) {
|
|
|
974
1180
|
* Fix function: Add sprint-yaml-validation hook to PostToolUse in settings.local.json
|
|
975
1181
|
* Validates sprint YAML files after Edit/Write for Cyclist SprintPanel compatibility
|
|
976
1182
|
*/
|
|
977
|
-
function addSprintYamlValidationHook(projectRoot,
|
|
1183
|
+
function addSprintYamlValidationHook(projectRoot, _installationType) {
|
|
978
1184
|
const settingsPath = join(projectRoot, '.claude/settings.local.json');
|
|
979
|
-
const scriptBase = getScriptBasePath(installationType);
|
|
980
1185
|
const requiredHook = {
|
|
981
1186
|
matcher: 'Edit|Write',
|
|
982
1187
|
hooks: [
|
|
983
1188
|
{
|
|
984
1189
|
type: 'command',
|
|
985
|
-
command:
|
|
1190
|
+
command: 'pf hooks sprint-yaml'
|
|
986
1191
|
}
|
|
987
1192
|
]
|
|
988
1193
|
};
|
|
@@ -1012,18 +1217,28 @@ function addSprintYamlValidationHook(projectRoot, installationType) {
|
|
|
1012
1217
|
/**
|
|
1013
1218
|
* Fix function: Add Stop hook to settings.local.json
|
|
1014
1219
|
*/
|
|
1015
|
-
function addStopHook(projectRoot,
|
|
1220
|
+
function addStopHook(projectRoot, _installationType) {
|
|
1016
1221
|
const settingsPath = join(projectRoot, '.claude/settings.local.json');
|
|
1017
|
-
const
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1222
|
+
const requiredHooks = [
|
|
1223
|
+
{
|
|
1224
|
+
matcher: '',
|
|
1225
|
+
hooks: [
|
|
1226
|
+
{
|
|
1227
|
+
type: 'command',
|
|
1228
|
+
command: 'pf hooks reflector-check'
|
|
1229
|
+
}
|
|
1230
|
+
]
|
|
1231
|
+
},
|
|
1232
|
+
{
|
|
1233
|
+
matcher: '',
|
|
1234
|
+
hooks: [
|
|
1235
|
+
{
|
|
1236
|
+
type: 'command',
|
|
1237
|
+
command: 'pf hooks session-stop'
|
|
1238
|
+
}
|
|
1239
|
+
]
|
|
1240
|
+
}
|
|
1241
|
+
];
|
|
1027
1242
|
let settings = {};
|
|
1028
1243
|
if (pathExists(settingsPath)) {
|
|
1029
1244
|
try {
|
|
@@ -1039,11 +1254,11 @@ function addStopHook(projectRoot, installationType) {
|
|
|
1039
1254
|
}
|
|
1040
1255
|
const hooks = settings.hooks;
|
|
1041
1256
|
if (!hooks.Stop) {
|
|
1042
|
-
hooks.Stop =
|
|
1257
|
+
hooks.Stop = requiredHooks;
|
|
1043
1258
|
}
|
|
1044
1259
|
else if (Array.isArray(hooks.Stop)) {
|
|
1045
|
-
// Prepend the required
|
|
1046
|
-
hooks.Stop = [
|
|
1260
|
+
// Prepend the required hooks
|
|
1261
|
+
hooks.Stop = [...requiredHooks, ...hooks.Stop];
|
|
1047
1262
|
}
|
|
1048
1263
|
writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
1049
1264
|
}
|
|
@@ -1060,15 +1275,14 @@ function getScriptBasePath(installationType) {
|
|
|
1060
1275
|
/**
|
|
1061
1276
|
* Fix function: Add SessionStart hooks to settings.local.json
|
|
1062
1277
|
*/
|
|
1063
|
-
function addSessionStartHooks(projectRoot,
|
|
1278
|
+
function addSessionStartHooks(projectRoot, _installationType) {
|
|
1064
1279
|
const settingsPath = join(projectRoot, '.claude/settings.local.json');
|
|
1065
|
-
const scriptBase = getScriptBasePath(installationType);
|
|
1066
1280
|
const requiredHooks = [
|
|
1067
1281
|
{
|
|
1068
1282
|
hooks: [
|
|
1069
1283
|
{
|
|
1070
1284
|
type: 'command',
|
|
1071
|
-
command:
|
|
1285
|
+
command: 'pf hooks session-start'
|
|
1072
1286
|
}
|
|
1073
1287
|
]
|
|
1074
1288
|
},
|
|
@@ -1117,10 +1331,9 @@ function addSessionStartHooks(projectRoot, installationType) {
|
|
|
1117
1331
|
* Create settings.local.json from template
|
|
1118
1332
|
* This is the critical fix for installations that are missing this file
|
|
1119
1333
|
*/
|
|
1120
|
-
function createSettingsLocalJson(projectRoot,
|
|
1334
|
+
function createSettingsLocalJson(projectRoot, _installationType) {
|
|
1121
1335
|
const settingsPath = join(projectRoot, '.claude/settings.local.json');
|
|
1122
|
-
|
|
1123
|
-
// Create full settings structure matching the template
|
|
1336
|
+
// Create full settings structure matching the template — uses pf hooks commands
|
|
1124
1337
|
const settings = {
|
|
1125
1338
|
permissions: {
|
|
1126
1339
|
allow: [
|
|
@@ -1163,7 +1376,7 @@ function createSettingsLocalJson(projectRoot, installationType) {
|
|
|
1163
1376
|
hooks: [
|
|
1164
1377
|
{
|
|
1165
1378
|
type: 'command',
|
|
1166
|
-
command:
|
|
1379
|
+
command: 'pf hooks session-start'
|
|
1167
1380
|
}
|
|
1168
1381
|
]
|
|
1169
1382
|
},
|
|
@@ -1185,33 +1398,42 @@ function createSettingsLocalJson(projectRoot, installationType) {
|
|
|
1185
1398
|
]
|
|
1186
1399
|
}
|
|
1187
1400
|
],
|
|
1188
|
-
|
|
1401
|
+
Stop: [
|
|
1189
1402
|
{
|
|
1190
1403
|
matcher: '',
|
|
1191
1404
|
hooks: [
|
|
1192
1405
|
{
|
|
1193
1406
|
type: 'command',
|
|
1194
|
-
command:
|
|
1407
|
+
command: 'pf hooks reflector-check'
|
|
1195
1408
|
}
|
|
1196
1409
|
]
|
|
1197
1410
|
},
|
|
1198
1411
|
{
|
|
1199
|
-
matcher: '
|
|
1412
|
+
matcher: '',
|
|
1200
1413
|
hooks: [
|
|
1201
1414
|
{
|
|
1202
1415
|
type: 'command',
|
|
1203
|
-
command:
|
|
1416
|
+
command: 'pf hooks session-stop'
|
|
1204
1417
|
}
|
|
1205
1418
|
]
|
|
1206
1419
|
}
|
|
1207
1420
|
],
|
|
1208
|
-
|
|
1421
|
+
PostToolUse: [
|
|
1209
1422
|
{
|
|
1210
1423
|
matcher: '',
|
|
1211
1424
|
hooks: [
|
|
1212
1425
|
{
|
|
1213
1426
|
type: 'command',
|
|
1214
|
-
command:
|
|
1427
|
+
command: 'pf hooks bell-mode'
|
|
1428
|
+
}
|
|
1429
|
+
]
|
|
1430
|
+
},
|
|
1431
|
+
{
|
|
1432
|
+
matcher: 'Edit|Write',
|
|
1433
|
+
hooks: [
|
|
1434
|
+
{
|
|
1435
|
+
type: 'command',
|
|
1436
|
+
command: 'pf hooks sprint-yaml'
|
|
1215
1437
|
}
|
|
1216
1438
|
]
|
|
1217
1439
|
}
|
|
@@ -1222,7 +1444,16 @@ function createSettingsLocalJson(projectRoot, installationType) {
|
|
|
1222
1444
|
hooks: [
|
|
1223
1445
|
{
|
|
1224
1446
|
type: 'command',
|
|
1225
|
-
command:
|
|
1447
|
+
command: 'pf hooks pre-edit-check'
|
|
1448
|
+
}
|
|
1449
|
+
]
|
|
1450
|
+
},
|
|
1451
|
+
{
|
|
1452
|
+
matcher: 'Write',
|
|
1453
|
+
hooks: [
|
|
1454
|
+
{
|
|
1455
|
+
type: 'command',
|
|
1456
|
+
command: 'pf hooks schema-validation'
|
|
1226
1457
|
}
|
|
1227
1458
|
]
|
|
1228
1459
|
},
|
|
@@ -1231,7 +1462,7 @@ function createSettingsLocalJson(projectRoot, installationType) {
|
|
|
1231
1462
|
hooks: [
|
|
1232
1463
|
{
|
|
1233
1464
|
type: 'command',
|
|
1234
|
-
command:
|
|
1465
|
+
command: 'pf hooks context-warning'
|
|
1235
1466
|
}
|
|
1236
1467
|
]
|
|
1237
1468
|
},
|
|
@@ -1240,7 +1471,15 @@ function createSettingsLocalJson(projectRoot, installationType) {
|
|
|
1240
1471
|
hooks: [
|
|
1241
1472
|
{
|
|
1242
1473
|
type: 'command',
|
|
1243
|
-
command:
|
|
1474
|
+
command: 'pf hooks context-breaker'
|
|
1475
|
+
}
|
|
1476
|
+
]
|
|
1477
|
+
},
|
|
1478
|
+
{
|
|
1479
|
+
hooks: [
|
|
1480
|
+
{
|
|
1481
|
+
type: 'command',
|
|
1482
|
+
command: 'pf hooks cyclist-pretooluse'
|
|
1244
1483
|
}
|
|
1245
1484
|
]
|
|
1246
1485
|
}
|
|
@@ -1248,7 +1487,7 @@ function createSettingsLocalJson(projectRoot, installationType) {
|
|
|
1248
1487
|
},
|
|
1249
1488
|
statusLine: {
|
|
1250
1489
|
type: 'command',
|
|
1251
|
-
command:
|
|
1490
|
+
command: 'pf hooks statusline'
|
|
1252
1491
|
}
|
|
1253
1492
|
};
|
|
1254
1493
|
ensureDirSync(join(projectRoot, '.claude'));
|
|
@@ -1809,8 +2048,8 @@ export function checkLegacyStatuslinePath(projectRoot) {
|
|
|
1809
2048
|
// or plain paths like .pennyfarthing/scripts/misc/statusline.sh
|
|
1810
2049
|
const pathMatch = command.match(/(?:\"\$CLAUDE_PROJECT_DIR\"\/)?([^\s"]+)/);
|
|
1811
2050
|
const currentPath = pathMatch ? pathMatch[1] : command;
|
|
1812
|
-
// Check if it
|
|
1813
|
-
if (currentPath.includes('misc/statusline.sh') || command.includes('misc/statusline.sh')) {
|
|
2051
|
+
// Check if it's the canonical pf hooks command or the legacy .sh path
|
|
2052
|
+
if (command === 'pf hooks statusline' || currentPath.includes('misc/statusline.sh') || command.includes('misc/statusline.sh')) {
|
|
1814
2053
|
return {
|
|
1815
2054
|
name: 'settings/statusline-path',
|
|
1816
2055
|
status: 'pass',
|
|
@@ -1831,7 +2070,7 @@ export function checkLegacyStatuslinePath(projectRoot) {
|
|
|
1831
2070
|
const updatedSettings = { ...settings };
|
|
1832
2071
|
updatedSettings.statusLine = {
|
|
1833
2072
|
type: 'command',
|
|
1834
|
-
command:
|
|
2073
|
+
command: 'pf hooks statusline'
|
|
1835
2074
|
};
|
|
1836
2075
|
writeFileSync(settingsPath, JSON.stringify(updatedSettings, null, 2));
|
|
1837
2076
|
}
|
|
@@ -1845,6 +2084,82 @@ export function checkLegacyStatuslinePath(projectRoot) {
|
|
|
1845
2084
|
detail: 'Configured'
|
|
1846
2085
|
};
|
|
1847
2086
|
}
|
|
2087
|
+
/**
|
|
2088
|
+
* Check if settings.local.json contains legacy .sh hook commands that should
|
|
2089
|
+
* be migrated to `pf hooks` commands. The .sh scripts still work (they're shims)
|
|
2090
|
+
* but `pf hooks` is the canonical path — faster, no shell indirection.
|
|
2091
|
+
*/
|
|
2092
|
+
function checkLegacyHookCommands(projectRoot) {
|
|
2093
|
+
const settingsPath = join(projectRoot, '.claude/settings.local.json');
|
|
2094
|
+
if (!pathExists(settingsPath)) {
|
|
2095
|
+
return { name: 'legacy/hook-commands', status: 'pass', detail: 'No settings file' };
|
|
2096
|
+
}
|
|
2097
|
+
let settings;
|
|
2098
|
+
try {
|
|
2099
|
+
settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
2100
|
+
}
|
|
2101
|
+
catch {
|
|
2102
|
+
return { name: 'legacy/hook-commands', status: 'warn', detail: 'Cannot parse settings.local.json' };
|
|
2103
|
+
}
|
|
2104
|
+
if (!settings.hooks) {
|
|
2105
|
+
return { name: 'legacy/hook-commands', status: 'pass' };
|
|
2106
|
+
}
|
|
2107
|
+
// Count how many hook commands still reference .sh scripts
|
|
2108
|
+
const hooks = settings.hooks;
|
|
2109
|
+
let legacyCount = 0;
|
|
2110
|
+
for (const hookType of ['SessionStart', 'SessionEnd', 'PreToolUse', 'PostToolUse', 'Stop']) {
|
|
2111
|
+
if (!Array.isArray(hooks[hookType]))
|
|
2112
|
+
continue;
|
|
2113
|
+
for (const entry of hooks[hookType]) {
|
|
2114
|
+
if (!entry.hooks)
|
|
2115
|
+
continue;
|
|
2116
|
+
for (const h of entry.hooks) {
|
|
2117
|
+
if (!h.command)
|
|
2118
|
+
continue;
|
|
2119
|
+
for (const shName of Object.keys(LEGACY_HOOK_MIGRATIONS)) {
|
|
2120
|
+
if (h.command.includes(shName)) {
|
|
2121
|
+
legacyCount++;
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
// Also check statusLine
|
|
2128
|
+
const statusLine = settings.statusLine;
|
|
2129
|
+
if (statusLine?.command && statusLine.command !== 'pf hooks statusline') {
|
|
2130
|
+
for (const shName of Object.keys(LEGACY_HOOK_MIGRATIONS)) {
|
|
2131
|
+
if (statusLine.command.includes(shName)) {
|
|
2132
|
+
legacyCount++;
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
if (legacyCount === 0) {
|
|
2137
|
+
return { name: 'legacy/hook-commands', status: 'pass' };
|
|
2138
|
+
}
|
|
2139
|
+
return {
|
|
2140
|
+
name: 'legacy/hook-commands',
|
|
2141
|
+
status: 'warn',
|
|
2142
|
+
detail: `${legacyCount} hook(s) still use .sh scripts — should use pf hooks commands`,
|
|
2143
|
+
fix: () => {
|
|
2144
|
+
// Migrate all hook arrays
|
|
2145
|
+
for (const hookType of ['SessionStart', 'SessionEnd', 'PreToolUse', 'PostToolUse', 'Stop']) {
|
|
2146
|
+
if (Array.isArray(hooks[hookType])) {
|
|
2147
|
+
migrateHookPaths(hooks[hookType]);
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
// Migrate statusLine
|
|
2151
|
+
if (statusLine?.command && statusLine.command !== 'pf hooks statusline') {
|
|
2152
|
+
for (const [shName, pfCommand] of Object.entries(LEGACY_HOOK_MIGRATIONS)) {
|
|
2153
|
+
if (statusLine.command.includes(shName)) {
|
|
2154
|
+
statusLine.command = pfCommand;
|
|
2155
|
+
break;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
2160
|
+
}
|
|
2161
|
+
};
|
|
2162
|
+
}
|
|
1848
2163
|
/**
|
|
1849
2164
|
* Check file layout — validate files are at correct .pennyfarthing/ locations.
|
|
1850
2165
|
* Flags old .claude/ locations with migration instructions.
|