@pennyfarthing/core 11.2.0 → 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 +1 -1
- 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/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/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/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 +6 -10
- package/pennyfarthing-dist/agents/reviewer.md +8 -2
- package/pennyfarthing-dist/agents/sm-finish.md +18 -1
- package/pennyfarthing-dist/commands/pf-git.md +4 -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/bell-mode.md +1 -1
- package/pennyfarthing-dist/guides/hooks.md +28 -28
- package/pennyfarthing-dist/guides/reflector.md +1 -1
- package/pennyfarthing-dist/guides/tandem-protocol.md +3 -3
- package/pennyfarthing-dist/scripts/core/check-context.sh +2 -0
- package/pennyfarthing-dist/scripts/core/phase-check-start.sh +5 -87
- package/pennyfarthing-dist/scripts/hooks/README.md +5 -5
- 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/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/templates/settings.local.json.template +19 -10
- package/pennyfarthing-dist/workflows/tdd.yaml +11 -2
- package/pennyfarthing_scripts/CLAUDE.md +19 -10
- 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/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/base_panel.py +27 -4
- package/pennyfarthing_scripts/bikerack/changed_panel.py +96 -4
- package/pennyfarthing_scripts/bikerack/context_meter_footer.py +88 -0
- package/pennyfarthing_scripts/bikerack/debug_panel.py +1 -1
- package/pennyfarthing_scripts/bikerack/diffs_panel.py +30 -0
- package/pennyfarthing_scripts/bikerack/events.py +28 -0
- package/pennyfarthing_scripts/bikerack/portrait_resolver.py +139 -0
- package/pennyfarthing_scripts/bikerack/sprint_panel.py +373 -142
- 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 +293 -61
- 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 +5 -0
- 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/__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/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/__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_group/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
- 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 +28 -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 +13 -1
- 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 -432
- 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/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/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_sprint_panel.py +344 -265
- 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/workflow.py +19 -0
- package/pennyfarthing_scripts/welcome_hook.py +3 -149
- 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 +7 -6
- 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_scripts/bikerack/__pycache__/portrait.cpython-314.pyc +0 -0
- 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/git/__pycache__/hooks_installer.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/repos.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/worktree.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/heatmap.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,437 +1,32 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Backward-compatibility shim — hooks utilities moved to hooks/ subpackage.
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- Settings loading (relay_mode, permission_mode)
|
|
8
|
-
- Context state checking
|
|
9
|
-
- HTTP communication with Cyclist
|
|
4
|
+
All exports are re-imported from pennyfarthing_scripts.hooks (the package).
|
|
5
|
+
Existing code that does `from hooks import ...` or
|
|
6
|
+
`from pennyfarthing_scripts.hooks import ...` continues to work.
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Story: MSSCI-12409 - Hook consistency and relay mode compatibility
|
|
8
|
+
This file will be removed in a future version.
|
|
14
9
|
"""
|
|
15
10
|
|
|
16
|
-
|
|
17
|
-
import
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# HTTP timeout for Cyclist communication
|
|
39
|
-
HTTP_TIMEOUT_SECONDS = 120
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
# =============================================================================
|
|
43
|
-
# Project Root Detection
|
|
44
|
-
# =============================================================================
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def find_project_root(start_dir: Path | None = None) -> Path | None:
|
|
48
|
-
"""Find the project root by looking for marker files.
|
|
49
|
-
|
|
50
|
-
Searches for (in order):
|
|
51
|
-
1. .wheelhub-port (WheelHub is running)
|
|
52
|
-
2. .pennyfarthing directory
|
|
53
|
-
3. .claude directory
|
|
54
|
-
|
|
55
|
-
Args:
|
|
56
|
-
start_dir: Directory to start search from (defaults to cwd)
|
|
57
|
-
|
|
58
|
-
Returns:
|
|
59
|
-
Path to project root, or None if not found
|
|
60
|
-
"""
|
|
61
|
-
current = Path(start_dir) if start_dir else Path.cwd()
|
|
62
|
-
current = current.resolve()
|
|
63
|
-
|
|
64
|
-
while current != current.parent:
|
|
65
|
-
# Check for Cyclist port files first (indicates Cyclist is running)
|
|
66
|
-
if (current / CYCLIST_PORT_FILE).exists():
|
|
67
|
-
return current
|
|
68
|
-
# Fall back to directory markers
|
|
69
|
-
if (current / ".pennyfarthing").is_dir():
|
|
70
|
-
return current
|
|
71
|
-
if (current / ".claude").is_dir():
|
|
72
|
-
return current
|
|
73
|
-
current = current.parent
|
|
74
|
-
|
|
75
|
-
return None
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
# =============================================================================
|
|
79
|
-
# Port File Reading
|
|
80
|
-
# =============================================================================
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def read_port_file(file_name: str, project_root: Path | None = None) -> int | None:
|
|
84
|
-
"""Read a port number from a Cyclist port file.
|
|
85
|
-
|
|
86
|
-
Args:
|
|
87
|
-
file_name: Name of the port file (e.g. .wheelhub-port)
|
|
88
|
-
project_root: Project root directory (auto-detected if not provided)
|
|
89
|
-
|
|
90
|
-
Returns:
|
|
91
|
-
Port number, or None if file not found or invalid
|
|
92
|
-
"""
|
|
93
|
-
root = project_root or find_project_root()
|
|
94
|
-
if not root:
|
|
95
|
-
return None
|
|
96
|
-
|
|
97
|
-
port_file = root / file_name
|
|
98
|
-
if not port_file.exists():
|
|
99
|
-
return None
|
|
100
|
-
|
|
101
|
-
try:
|
|
102
|
-
content = port_file.read_text().strip()
|
|
103
|
-
port = int(content)
|
|
104
|
-
if 0 < port < 65536:
|
|
105
|
-
return port
|
|
106
|
-
except (ValueError, OSError):
|
|
107
|
-
pass
|
|
108
|
-
|
|
109
|
-
return None
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def get_cyclist_port(project_root: Path | None = None) -> int:
|
|
113
|
-
"""Get the WheelHub server port.
|
|
114
|
-
|
|
115
|
-
WheelHub is the central coordination server for all Cyclist communication,
|
|
116
|
-
including hook requests, OTEL, REST APIs, and WebSocket.
|
|
117
|
-
|
|
118
|
-
Args:
|
|
119
|
-
project_root: Project root directory (auto-detected if not provided)
|
|
120
|
-
|
|
121
|
-
Returns:
|
|
122
|
-
Port number (default if file not found)
|
|
123
|
-
"""
|
|
124
|
-
port = read_port_file(CYCLIST_PORT_FILE, project_root)
|
|
125
|
-
if port:
|
|
126
|
-
return port
|
|
127
|
-
|
|
128
|
-
return DEFAULT_CYCLIST_PORT
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
# =============================================================================
|
|
132
|
-
# Settings Loading
|
|
133
|
-
# =============================================================================
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
@dataclass
|
|
137
|
-
class CyclistSettings:
|
|
138
|
-
"""Cyclist workflow settings from config.local.yaml."""
|
|
139
|
-
|
|
140
|
-
permission_mode: str = "manual" # plan, manual, accept
|
|
141
|
-
relay_mode: bool = False
|
|
142
|
-
bell_mode: bool = False
|
|
143
|
-
theme: str | None = None
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
def load_settings(project_root: Path | None = None) -> CyclistSettings:
|
|
147
|
-
"""Load Cyclist settings from .pennyfarthing/config.local.yaml.
|
|
148
|
-
|
|
149
|
-
Handles legacy setting migrations:
|
|
150
|
-
- permission_mode: 'turbo' -> 'accept' + relay_mode: True
|
|
151
|
-
- handoff_mode: 'auto' -> relay_mode: True
|
|
152
|
-
- auto_handoff: True -> relay_mode: True
|
|
153
|
-
|
|
154
|
-
Args:
|
|
155
|
-
project_root: Project root directory (auto-detected if not provided)
|
|
156
|
-
|
|
157
|
-
Returns:
|
|
158
|
-
CyclistSettings with current configuration
|
|
159
|
-
"""
|
|
160
|
-
settings = CyclistSettings()
|
|
161
|
-
|
|
162
|
-
root = project_root or find_project_root()
|
|
163
|
-
if not root:
|
|
164
|
-
return settings
|
|
165
|
-
|
|
166
|
-
config_path = root / ".pennyfarthing" / "config.local.yaml"
|
|
167
|
-
if not config_path.exists():
|
|
168
|
-
return settings
|
|
169
|
-
|
|
170
|
-
try:
|
|
171
|
-
with open(config_path) as f:
|
|
172
|
-
config = yaml.safe_load(f) or {}
|
|
173
|
-
except (OSError, yaml.YAMLError):
|
|
174
|
-
return settings
|
|
175
|
-
|
|
176
|
-
# Extract theme
|
|
177
|
-
settings.theme = config.get("theme")
|
|
178
|
-
|
|
179
|
-
# Extract workflow settings
|
|
180
|
-
workflow = config.get("workflow", {})
|
|
181
|
-
if not isinstance(workflow, dict):
|
|
182
|
-
return settings
|
|
183
|
-
|
|
184
|
-
# Handle permission_mode
|
|
185
|
-
mode = workflow.get("permission_mode", "manual")
|
|
186
|
-
if mode == "turbo":
|
|
187
|
-
# Migrate turbo -> accept + relay_mode
|
|
188
|
-
settings.permission_mode = "accept"
|
|
189
|
-
settings.relay_mode = True
|
|
190
|
-
elif mode in ("plan", "manual", "accept"):
|
|
191
|
-
settings.permission_mode = mode
|
|
192
|
-
else:
|
|
193
|
-
settings.permission_mode = "manual"
|
|
194
|
-
|
|
195
|
-
# Handle explicit relay_mode (overrides migration)
|
|
196
|
-
if "relay_mode" in workflow and isinstance(workflow["relay_mode"], bool):
|
|
197
|
-
settings.relay_mode = workflow["relay_mode"]
|
|
198
|
-
elif not settings.relay_mode:
|
|
199
|
-
# Check legacy settings
|
|
200
|
-
if workflow.get("handoff_mode") == "auto":
|
|
201
|
-
settings.relay_mode = True
|
|
202
|
-
elif workflow.get("auto_handoff") is True:
|
|
203
|
-
settings.relay_mode = True
|
|
204
|
-
|
|
205
|
-
# Handle bell_mode
|
|
206
|
-
if "bell_mode" in workflow and isinstance(workflow["bell_mode"], bool):
|
|
207
|
-
settings.bell_mode = workflow["bell_mode"]
|
|
208
|
-
|
|
209
|
-
return settings
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
def is_relay_mode_enabled(project_root: Path | None = None) -> bool:
|
|
213
|
-
"""Check if relay mode (auto-handoff) is enabled.
|
|
214
|
-
|
|
215
|
-
Args:
|
|
216
|
-
project_root: Project root directory (auto-detected if not provided)
|
|
217
|
-
|
|
218
|
-
Returns:
|
|
219
|
-
True if relay mode is enabled
|
|
220
|
-
"""
|
|
221
|
-
return load_settings(project_root).relay_mode
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
def is_bell_mode_enabled(project_root: Path | None = None) -> bool:
|
|
225
|
-
"""Check if bell mode is enabled.
|
|
226
|
-
|
|
227
|
-
Args:
|
|
228
|
-
project_root: Project root directory (auto-detected if not provided)
|
|
229
|
-
|
|
230
|
-
Returns:
|
|
231
|
-
True if bell mode is enabled
|
|
232
|
-
"""
|
|
233
|
-
return load_settings(project_root).bell_mode
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
# =============================================================================
|
|
237
|
-
# Context State
|
|
238
|
-
# =============================================================================
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
@dataclass
|
|
242
|
-
class ContextState:
|
|
243
|
-
"""Current context usage state."""
|
|
244
|
-
|
|
245
|
-
used_tokens: int = 0
|
|
246
|
-
max_tokens: int = 200000
|
|
247
|
-
percentage: float = 0.0
|
|
248
|
-
is_high: bool = False # > 60%
|
|
249
|
-
is_critical: bool = False # > 80%
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
def get_context_state(project_root: Path | None = None) -> ContextState:
|
|
253
|
-
"""Get current context usage from Cyclist API.
|
|
254
|
-
|
|
255
|
-
Calls Cyclist's /api/context endpoint which runs check-context.sh.
|
|
256
|
-
|
|
257
|
-
Args:
|
|
258
|
-
project_root: Project root directory (auto-detected if not provided)
|
|
259
|
-
|
|
260
|
-
Returns:
|
|
261
|
-
ContextState with current usage (defaults if Cyclist not running)
|
|
262
|
-
"""
|
|
263
|
-
state = ContextState()
|
|
264
|
-
|
|
265
|
-
port = get_cyclist_port(project_root)
|
|
266
|
-
url = f"http://127.0.0.1:{port}/api/context"
|
|
267
|
-
|
|
268
|
-
try:
|
|
269
|
-
with urllib.request.urlopen(url, timeout=5) as response:
|
|
270
|
-
data = json.loads(response.read().decode())
|
|
271
|
-
state.used_tokens = data.get("used_tokens", 0)
|
|
272
|
-
state.max_tokens = data.get("max_tokens", 200000)
|
|
273
|
-
if state.max_tokens > 0:
|
|
274
|
-
state.percentage = (state.used_tokens / state.max_tokens) * 100
|
|
275
|
-
state.is_high = state.percentage > 60
|
|
276
|
-
state.is_critical = state.percentage > 80
|
|
277
|
-
except (urllib.error.URLError, json.JSONDecodeError, OSError):
|
|
278
|
-
# Cyclist not running or error - return defaults
|
|
279
|
-
pass
|
|
280
|
-
|
|
281
|
-
return state
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
# =============================================================================
|
|
285
|
-
# Cyclist HTTP Communication
|
|
286
|
-
# =============================================================================
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
def send_to_cyclist(
|
|
290
|
-
endpoint: str,
|
|
291
|
-
data: dict[str, Any],
|
|
292
|
-
port: int | None = None,
|
|
293
|
-
project_root: Path | None = None,
|
|
294
|
-
timeout: int = HTTP_TIMEOUT_SECONDS,
|
|
295
|
-
) -> dict[str, Any] | None:
|
|
296
|
-
"""Send a POST request to WheelHub (Cyclist's central coordination server).
|
|
297
|
-
|
|
298
|
-
All endpoints go through WheelHub per ADR-0004.
|
|
299
|
-
|
|
300
|
-
Args:
|
|
301
|
-
endpoint: API endpoint path (e.g., "/api/hook-request")
|
|
302
|
-
data: JSON data to send
|
|
303
|
-
port: Port to use (auto-detected if not provided)
|
|
304
|
-
project_root: Project root for port discovery
|
|
305
|
-
timeout: Request timeout in seconds
|
|
306
|
-
|
|
307
|
-
Returns:
|
|
308
|
-
Response JSON as dict, or None on error
|
|
309
|
-
"""
|
|
310
|
-
if port is None:
|
|
311
|
-
port = get_cyclist_port(project_root)
|
|
312
|
-
|
|
313
|
-
url = f"http://127.0.0.1:{port}{endpoint}"
|
|
314
|
-
json_data = json.dumps(data).encode("utf-8")
|
|
315
|
-
|
|
316
|
-
request = urllib.request.Request(
|
|
317
|
-
url,
|
|
318
|
-
data=json_data,
|
|
319
|
-
headers={"Content-Type": "application/json"},
|
|
320
|
-
method="POST",
|
|
321
|
-
)
|
|
322
|
-
|
|
323
|
-
try:
|
|
324
|
-
with urllib.request.urlopen(request, timeout=timeout) as response:
|
|
325
|
-
return json.loads(response.read().decode())
|
|
326
|
-
except urllib.error.URLError as e:
|
|
327
|
-
# Connection refused means Cyclist isn't running
|
|
328
|
-
if "Connection refused" in str(e):
|
|
329
|
-
return None
|
|
330
|
-
raise
|
|
331
|
-
except (json.JSONDecodeError, OSError):
|
|
332
|
-
return None
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
# =============================================================================
|
|
336
|
-
# Hook Response Formatting
|
|
337
|
-
# =============================================================================
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
@dataclass
|
|
341
|
-
class HookResponse:
|
|
342
|
-
"""Standard hook response for Claude Code."""
|
|
343
|
-
|
|
344
|
-
event_name: str
|
|
345
|
-
decision: str | None = None # allow, deny, ask (for PreToolUse)
|
|
346
|
-
reason: str | None = None
|
|
347
|
-
updated_input: dict[str, Any] | None = None
|
|
348
|
-
additional_context: str | None = None # For PostToolUse context injection
|
|
349
|
-
|
|
350
|
-
def to_json(self) -> str:
|
|
351
|
-
"""Format as Claude Code hook JSON output."""
|
|
352
|
-
output: dict[str, Any] = {
|
|
353
|
-
"hookSpecificOutput": {
|
|
354
|
-
"hookEventName": self.event_name,
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
hook_output = output["hookSpecificOutput"]
|
|
359
|
-
|
|
360
|
-
if self.decision:
|
|
361
|
-
hook_output["permissionDecision"] = self.decision
|
|
362
|
-
if self.reason:
|
|
363
|
-
hook_output["permissionDecisionReason"] = self.reason
|
|
364
|
-
if self.updated_input:
|
|
365
|
-
hook_output["updatedInput"] = self.updated_input
|
|
366
|
-
if self.additional_context:
|
|
367
|
-
hook_output["additionalContext"] = self.additional_context
|
|
368
|
-
|
|
369
|
-
return json.dumps(output)
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
def output_hook_response(response: HookResponse) -> None:
|
|
373
|
-
"""Output hook response to stdout for Claude Code."""
|
|
374
|
-
print(response.to_json())
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
def read_stdin_json() -> dict[str, Any]:
|
|
378
|
-
"""Read JSON from stdin (hook input from Claude Code).
|
|
379
|
-
|
|
380
|
-
Returns:
|
|
381
|
-
Parsed JSON as dict
|
|
382
|
-
|
|
383
|
-
Raises:
|
|
384
|
-
ValueError: If input is not valid JSON
|
|
385
|
-
"""
|
|
386
|
-
data = sys.stdin.read()
|
|
387
|
-
try:
|
|
388
|
-
return json.loads(data)
|
|
389
|
-
except json.JSONDecodeError as e:
|
|
390
|
-
raise ValueError(f"Invalid JSON input: {e}") from e
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
# =============================================================================
|
|
394
|
-
# Hook Execution Utilities
|
|
395
|
-
# =============================================================================
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
def is_cyclist_running(project_root: Path | None = None) -> bool:
|
|
399
|
-
"""Check if Cyclist server is running.
|
|
400
|
-
|
|
401
|
-
Checks the CYCLIST environment variable set by ClaudeService when
|
|
402
|
-
spawning Claude inside Cyclist. No file I/O, no HTTP, no signals —
|
|
403
|
-
this runs on every tool invocation and must be instant.
|
|
404
|
-
|
|
405
|
-
The project_root parameter is kept for backward compatibility but
|
|
406
|
-
is no longer used.
|
|
407
|
-
|
|
408
|
-
Returns:
|
|
409
|
-
True if running inside a Cyclist-spawned Claude process
|
|
410
|
-
"""
|
|
411
|
-
return os.environ.get("CYCLIST") == "1"
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
def should_auto_approve(settings: CyclistSettings) -> bool:
|
|
415
|
-
"""Check if requests should be auto-approved based on settings.
|
|
416
|
-
|
|
417
|
-
Auto-approve when permission_mode is 'accept' (formerly turbo).
|
|
418
|
-
|
|
419
|
-
Args:
|
|
420
|
-
settings: Current Cyclist settings
|
|
421
|
-
|
|
422
|
-
Returns:
|
|
423
|
-
True if auto-approval is enabled
|
|
424
|
-
"""
|
|
425
|
-
return settings.permission_mode == "accept"
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
def should_auto_handoff(settings: CyclistSettings) -> bool:
|
|
429
|
-
"""Check if handoffs should be automatic based on settings.
|
|
430
|
-
|
|
431
|
-
Args:
|
|
432
|
-
settings: Current Cyclist settings
|
|
433
|
-
|
|
434
|
-
Returns:
|
|
435
|
-
True if relay_mode is enabled
|
|
436
|
-
"""
|
|
437
|
-
return settings.relay_mode
|
|
11
|
+
# Re-export everything from the hooks package
|
|
12
|
+
from pennyfarthing_scripts.hooks import ( # noqa: F401
|
|
13
|
+
CYCLIST_PORT_FILE,
|
|
14
|
+
DEFAULT_CYCLIST_PORT,
|
|
15
|
+
HTTP_TIMEOUT_SECONDS,
|
|
16
|
+
ContextState,
|
|
17
|
+
CyclistSettings,
|
|
18
|
+
HookResponse,
|
|
19
|
+
find_project_root,
|
|
20
|
+
get_context_state,
|
|
21
|
+
get_cyclist_port,
|
|
22
|
+
is_bell_mode_enabled,
|
|
23
|
+
is_cyclist_running,
|
|
24
|
+
is_relay_mode_enabled,
|
|
25
|
+
load_settings,
|
|
26
|
+
output_hook_response,
|
|
27
|
+
read_port_file,
|
|
28
|
+
read_stdin_json,
|
|
29
|
+
send_to_cyclist,
|
|
30
|
+
should_auto_approve,
|
|
31
|
+
should_auto_handoff,
|
|
32
|
+
)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|