@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
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Hook CLI group — internal hooks called by Claude Code settings.
|
|
3
|
+
|
|
4
|
+
All hooks read JSON from stdin (Claude Code protocol) and output
|
|
5
|
+
JSON/text to stdout. Exit codes: 0=allow, 2=block (PreToolUse).
|
|
6
|
+
|
|
7
|
+
Usage in settings.local.json:
|
|
8
|
+
"command": "pf hooks session-start"
|
|
9
|
+
"command": "pf hooks bell-mode"
|
|
10
|
+
"command": "pf hooks statusline"
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import click
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@click.group(hidden=True)
|
|
17
|
+
def hooks():
|
|
18
|
+
"""Internal hooks (called by Claude Code settings)."""
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@hooks.command("session-start")
|
|
23
|
+
def session_start():
|
|
24
|
+
"""SessionStart hook — session setup, WheelHub auto-start, OTEL config."""
|
|
25
|
+
from pennyfarthing_scripts.hooks.session_start import main
|
|
26
|
+
main()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@hooks.command("session-stop")
|
|
30
|
+
def session_stop():
|
|
31
|
+
"""Stop hook — save checkpoint for cross-session continuity."""
|
|
32
|
+
from pennyfarthing_scripts.hooks.session_stop import main
|
|
33
|
+
main()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@hooks.command("reflector-check")
|
|
37
|
+
def reflector_check():
|
|
38
|
+
"""Stop hook — enforce CYCLIST reflector markers on every turn."""
|
|
39
|
+
from pennyfarthing_scripts.hooks.reflector_check import main
|
|
40
|
+
main()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@hooks.command("pre-edit-check")
|
|
44
|
+
def pre_edit_check():
|
|
45
|
+
"""PreToolUse hook — block edits to protected files."""
|
|
46
|
+
from pennyfarthing_scripts.hooks.pre_edit_check import main
|
|
47
|
+
main()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@hooks.command("context-warning")
|
|
51
|
+
def context_warning():
|
|
52
|
+
"""PreToolUse hook — warn when context usage is high."""
|
|
53
|
+
from pennyfarthing_scripts.hooks.context_warning import main
|
|
54
|
+
main()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@hooks.command("context-breaker")
|
|
58
|
+
def context_breaker():
|
|
59
|
+
"""PreToolUse hook — block tool execution at critical context usage."""
|
|
60
|
+
from pennyfarthing_scripts.hooks.context_breaker import main
|
|
61
|
+
main()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@hooks.command("cyclist-pretooluse")
|
|
65
|
+
def cyclist_pretooluse():
|
|
66
|
+
"""PreToolUse hook — route approval through WheelHub when Cyclist is running."""
|
|
67
|
+
from pennyfarthing_scripts.hooks.cyclist_pretooluse import main
|
|
68
|
+
main()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@hooks.command("schema-validation")
|
|
72
|
+
def schema_validation():
|
|
73
|
+
"""PreToolUse hook — validate XML schema on Write operations."""
|
|
74
|
+
from pennyfarthing_scripts.hooks.schema_validation import main
|
|
75
|
+
main()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@hooks.command("bell-mode")
|
|
79
|
+
def bell_mode():
|
|
80
|
+
"""PostToolUse hook — bell queue + tandem observation injection."""
|
|
81
|
+
from pennyfarthing_scripts.hooks.bell_mode import main
|
|
82
|
+
main()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@hooks.command("sprint-yaml")
|
|
86
|
+
def sprint_yaml():
|
|
87
|
+
"""PostToolUse hook — validate sprint YAML after Edit/Write."""
|
|
88
|
+
from pennyfarthing_scripts.hooks.sprint_yaml_validation import main
|
|
89
|
+
main()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@hooks.command("statusline")
|
|
93
|
+
def statusline():
|
|
94
|
+
"""statusLine hook — render Claude Code status bar."""
|
|
95
|
+
from pennyfarthing_scripts.hooks.statusline import main
|
|
96
|
+
main()
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Context circuit breaker hook (PreToolUse) — block tool execution at critical usage.
|
|
3
|
+
|
|
4
|
+
When context exceeds the critical threshold (default 80%), blocks tool execution
|
|
5
|
+
with exit code 2 and saves the active agent to a checkpoint for /continue-session.
|
|
6
|
+
|
|
7
|
+
Unlike context_warning.py which only warns, this is a hard stop.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
import sys
|
|
15
|
+
from datetime import UTC, datetime
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
from pennyfarthing_scripts.context import check_context, load_config
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _checkpoint_save(project_dir: str, label: str, data: str) -> None:
|
|
22
|
+
"""Save a checkpoint entry (reimplements checkpoint.sh logic in Python)."""
|
|
23
|
+
try:
|
|
24
|
+
checkpoint_file = Path(project_dir) / ".session" / "checkpoints.log"
|
|
25
|
+
checkpoint_file.parent.mkdir(parents=True, exist_ok=True)
|
|
26
|
+
timestamp = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
27
|
+
with open(checkpoint_file, "a") as f:
|
|
28
|
+
f.write(f"{timestamp}|{label}|{data}\n")
|
|
29
|
+
except OSError:
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def main() -> None:
|
|
34
|
+
"""Main entry point for context circuit breaker hook."""
|
|
35
|
+
try:
|
|
36
|
+
# Read stdin to get session_id
|
|
37
|
+
raw_input = sys.stdin.read()
|
|
38
|
+
input_data = {}
|
|
39
|
+
try:
|
|
40
|
+
input_data = json.loads(raw_input)
|
|
41
|
+
except (json.JSONDecodeError, ValueError):
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
project_dir = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
|
|
45
|
+
config = load_config(project_dir)
|
|
46
|
+
|
|
47
|
+
result = check_context(project_dir=project_dir)
|
|
48
|
+
|
|
49
|
+
if result.error:
|
|
50
|
+
sys.exit(0)
|
|
51
|
+
|
|
52
|
+
critical_threshold = config.critical_threshold
|
|
53
|
+
pct = result.usable_percent
|
|
54
|
+
|
|
55
|
+
if pct >= critical_threshold:
|
|
56
|
+
# Auto-save active agent to checkpoint
|
|
57
|
+
session_id = input_data.get("session_id", "")
|
|
58
|
+
active_agent = ""
|
|
59
|
+
|
|
60
|
+
if session_id:
|
|
61
|
+
agent_file = Path(project_dir) / ".session" / "agents" / session_id
|
|
62
|
+
if agent_file.is_file():
|
|
63
|
+
try:
|
|
64
|
+
active_agent = agent_file.read_text().strip()
|
|
65
|
+
except OSError:
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
if active_agent:
|
|
69
|
+
_checkpoint_save(project_dir, "circuit_breaker_agent", active_agent)
|
|
70
|
+
|
|
71
|
+
# Send error to stderr (Claude sees this)
|
|
72
|
+
msg = f"""CONTEXT CIRCUIT BREAKER TRIGGERED
|
|
73
|
+
|
|
74
|
+
Context usage: {pct}% - CRITICAL (threshold: {critical_threshold}%)
|
|
75
|
+
|
|
76
|
+
Tool execution BLOCKED. You must stop and hand off."""
|
|
77
|
+
|
|
78
|
+
if active_agent:
|
|
79
|
+
msg += f"""
|
|
80
|
+
|
|
81
|
+
Active agent saved: {active_agent}
|
|
82
|
+
The agent will be restored with FULL context when you run /continue-session."""
|
|
83
|
+
|
|
84
|
+
msg += """
|
|
85
|
+
|
|
86
|
+
Required actions:
|
|
87
|
+
1. Commit any pending changes
|
|
88
|
+
2. Tell user to start fresh session with /continue-session
|
|
89
|
+
|
|
90
|
+
DO NOT attempt further tool calls. This is a hard stop.
|
|
91
|
+
|
|
92
|
+
To resume later: /continue-session"""
|
|
93
|
+
|
|
94
|
+
print(msg, file=sys.stderr)
|
|
95
|
+
sys.exit(2)
|
|
96
|
+
|
|
97
|
+
except Exception:
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
sys.exit(0)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
if __name__ == "__main__":
|
|
104
|
+
main()
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Context warning hook (PreToolUse) — warn agent when context usage is high.
|
|
3
|
+
|
|
4
|
+
Uses context.py to check transcript-based context percentage.
|
|
5
|
+
Outputs warning text to stdout but always exits 0 (never blocks).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
from pennyfarthing_scripts.context import check_context, load_config
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main() -> None:
|
|
17
|
+
"""Main entry point for context warning hook."""
|
|
18
|
+
try:
|
|
19
|
+
# Read and discard stdin (required by hook protocol)
|
|
20
|
+
sys.stdin.read()
|
|
21
|
+
|
|
22
|
+
project_dir = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
|
|
23
|
+
config = load_config(project_dir)
|
|
24
|
+
|
|
25
|
+
result = check_context(project_dir=project_dir)
|
|
26
|
+
|
|
27
|
+
if result.error:
|
|
28
|
+
sys.exit(0)
|
|
29
|
+
|
|
30
|
+
warning_threshold = config.warning_threshold
|
|
31
|
+
critical_threshold = config.critical_threshold
|
|
32
|
+
pct = result.usable_percent
|
|
33
|
+
|
|
34
|
+
if pct >= critical_threshold:
|
|
35
|
+
print(f"""
|
|
36
|
+
---
|
|
37
|
+
CONTEXT WARNING: {pct}% (CRITICAL)
|
|
38
|
+
|
|
39
|
+
Context usage is critically high. Recommended actions:
|
|
40
|
+
1. Complete current task immediately
|
|
41
|
+
2. Commit any pending changes
|
|
42
|
+
3. Hand off to next agent or ask user to start fresh session
|
|
43
|
+
|
|
44
|
+
Do NOT start new subtasks. Wrap up and hand off.
|
|
45
|
+
---
|
|
46
|
+
""")
|
|
47
|
+
elif pct >= warning_threshold:
|
|
48
|
+
print(f"""
|
|
49
|
+
---
|
|
50
|
+
CONTEXT WARNING: {pct}%
|
|
51
|
+
|
|
52
|
+
Context usage is high. Consider:
|
|
53
|
+
- Wrapping up current task soon
|
|
54
|
+
- Preparing for handoff to next agent
|
|
55
|
+
- Avoiding large file reads or complex operations
|
|
56
|
+
---
|
|
57
|
+
""")
|
|
58
|
+
|
|
59
|
+
except Exception:
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
sys.exit(0)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if __name__ == "__main__":
|
|
66
|
+
main()
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Cyclist PreToolUse Hook — route tool approval through WheelHub.
|
|
3
|
+
|
|
4
|
+
When Cyclist is running, sends approval requests to WheelHub's /api/hook-request
|
|
5
|
+
endpoint. Falls back to Claude Code's built-in permissions when Cyclist is not active.
|
|
6
|
+
|
|
7
|
+
Consolidates pretooluse_hook.py into the hooks subpackage.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import sys
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
from pennyfarthing_scripts.hooks import (
|
|
16
|
+
HookResponse,
|
|
17
|
+
find_project_root,
|
|
18
|
+
get_context_state,
|
|
19
|
+
is_cyclist_running,
|
|
20
|
+
load_settings,
|
|
21
|
+
output_hook_response,
|
|
22
|
+
read_stdin_json,
|
|
23
|
+
send_to_cyclist,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _resolve_agent(session_id: str | None, project_root: Path | None) -> str | None:
|
|
28
|
+
"""Resolve agent name from session file."""
|
|
29
|
+
if not project_root:
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
agents_dir = project_root / ".session" / "agents"
|
|
33
|
+
if not agents_dir.is_dir():
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
if session_id:
|
|
37
|
+
agent_file = agents_dir / session_id
|
|
38
|
+
if agent_file.is_file():
|
|
39
|
+
try:
|
|
40
|
+
return agent_file.read_text().strip() or None
|
|
41
|
+
except OSError:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
agent_files = sorted(
|
|
46
|
+
(f for f in agents_dir.iterdir() if f.is_file()),
|
|
47
|
+
key=lambda f: f.stat().st_mtime,
|
|
48
|
+
reverse=True,
|
|
49
|
+
)
|
|
50
|
+
if agent_files:
|
|
51
|
+
return agent_files[0].read_text().strip() or None
|
|
52
|
+
except OSError:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def main() -> None:
|
|
59
|
+
"""Main entry point for PreToolUse hook."""
|
|
60
|
+
try:
|
|
61
|
+
tool_data = read_stdin_json()
|
|
62
|
+
tool_name = tool_data.get("tool_name", "")
|
|
63
|
+
tool_id = tool_data.get("tool_use_id", "")
|
|
64
|
+
tool_input = tool_data.get("tool_input", {})
|
|
65
|
+
session_id = tool_data.get("session_id")
|
|
66
|
+
|
|
67
|
+
project_root = find_project_root()
|
|
68
|
+
agent_name = _resolve_agent(session_id, project_root)
|
|
69
|
+
|
|
70
|
+
if not is_cyclist_running(project_root):
|
|
71
|
+
sys.exit(0)
|
|
72
|
+
|
|
73
|
+
settings = load_settings(project_root)
|
|
74
|
+
if settings.permission_mode == "accept":
|
|
75
|
+
output_hook_response(HookResponse(
|
|
76
|
+
event_name="PreToolUse",
|
|
77
|
+
decision="allow",
|
|
78
|
+
reason="Auto-accept mode enabled",
|
|
79
|
+
))
|
|
80
|
+
sys.exit(0)
|
|
81
|
+
|
|
82
|
+
context = get_context_state(project_root)
|
|
83
|
+
request_data = {
|
|
84
|
+
"toolName": tool_name,
|
|
85
|
+
"toolId": tool_id,
|
|
86
|
+
"input": tool_input,
|
|
87
|
+
"sessionId": session_id,
|
|
88
|
+
"context": {
|
|
89
|
+
"percentage": context.percentage,
|
|
90
|
+
"isHigh": context.is_high,
|
|
91
|
+
"isCritical": context.is_critical,
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
if agent_name:
|
|
95
|
+
request_data["agent"] = agent_name
|
|
96
|
+
|
|
97
|
+
response = send_to_cyclist(
|
|
98
|
+
endpoint="/api/hook-request",
|
|
99
|
+
data=request_data,
|
|
100
|
+
project_root=project_root,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
if response is None:
|
|
104
|
+
output_hook_response(HookResponse(
|
|
105
|
+
event_name="PreToolUse",
|
|
106
|
+
decision="ask",
|
|
107
|
+
reason="Could not connect to WheelHub",
|
|
108
|
+
))
|
|
109
|
+
sys.exit(0)
|
|
110
|
+
|
|
111
|
+
decision = response.get("decision", "ask")
|
|
112
|
+
reason = response.get("reason", "")
|
|
113
|
+
data = response.get("data")
|
|
114
|
+
|
|
115
|
+
output_hook_response(HookResponse(
|
|
116
|
+
event_name="PreToolUse",
|
|
117
|
+
decision=decision,
|
|
118
|
+
reason=reason,
|
|
119
|
+
updated_input=data,
|
|
120
|
+
))
|
|
121
|
+
sys.exit(0)
|
|
122
|
+
|
|
123
|
+
except Exception as e:
|
|
124
|
+
print(f"[pretooluse-hook] Error: {e}", file=sys.stderr)
|
|
125
|
+
sys.exit(0)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
if __name__ == "__main__":
|
|
129
|
+
main()
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pre-edit check hook (PreToolUse) — block edits to protected files.
|
|
3
|
+
|
|
4
|
+
Prevents editing sensitive files (.env, .pem, .key, credentials, secrets),
|
|
5
|
+
git internals, node_modules, and managed pennyfarthing files.
|
|
6
|
+
|
|
7
|
+
Exit 0 = allow, Exit 2 = block.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import fnmatch
|
|
13
|
+
import json
|
|
14
|
+
import os
|
|
15
|
+
import sys
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Protected patterns — files that should never be edited automatically
|
|
20
|
+
PROTECTED_PATTERNS = [
|
|
21
|
+
"*.env",
|
|
22
|
+
"*.pem",
|
|
23
|
+
"*.key",
|
|
24
|
+
"*credentials*",
|
|
25
|
+
"*secrets*",
|
|
26
|
+
".git/*",
|
|
27
|
+
"node_modules/*",
|
|
28
|
+
"vendor/*",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def main() -> None:
|
|
33
|
+
"""Main entry point for pre-edit check hook."""
|
|
34
|
+
try:
|
|
35
|
+
raw = sys.stdin.read()
|
|
36
|
+
try:
|
|
37
|
+
input_data = json.loads(raw)
|
|
38
|
+
except (json.JSONDecodeError, ValueError):
|
|
39
|
+
sys.exit(0)
|
|
40
|
+
|
|
41
|
+
tool_input = input_data.get("tool_input", {})
|
|
42
|
+
file_path = tool_input.get("file_path", "") or tool_input.get("path", "")
|
|
43
|
+
|
|
44
|
+
if not file_path:
|
|
45
|
+
sys.exit(0)
|
|
46
|
+
|
|
47
|
+
# Check managed pennyfarthing files protection
|
|
48
|
+
# EXCEPTION: If we ARE in the pennyfarthing library itself, allow edits
|
|
49
|
+
project_dir = os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
|
|
50
|
+
is_pennyfarthing_lib = Path(project_dir, "pennyfarthing-dist").is_dir()
|
|
51
|
+
|
|
52
|
+
if ".claude/pennyfarthing/" in file_path and not is_pennyfarthing_lib:
|
|
53
|
+
print("BLOCKED: Cannot edit managed pennyfarthing files.", file=sys.stderr)
|
|
54
|
+
print(f"File: {file_path}", file=sys.stderr)
|
|
55
|
+
print("", file=sys.stderr)
|
|
56
|
+
print("These files are managed by pennyfarthing and will be overwritten on update.", file=sys.stderr)
|
|
57
|
+
print("Instead:", file=sys.stderr)
|
|
58
|
+
print(" - Put project-specific customizations in .claude/project/", file=sys.stderr)
|
|
59
|
+
print(" - For framework changes, edit the pennyfarthing repo and run 'pennyfarthing update'", file=sys.stderr)
|
|
60
|
+
sys.exit(2)
|
|
61
|
+
|
|
62
|
+
# Check protected patterns
|
|
63
|
+
for pattern in PROTECTED_PATTERNS:
|
|
64
|
+
if fnmatch.fnmatch(file_path, pattern):
|
|
65
|
+
print(f"BLOCKED: Cannot edit protected file matching pattern: {pattern}", file=sys.stderr)
|
|
66
|
+
print(f"File: {file_path}", file=sys.stderr)
|
|
67
|
+
sys.exit(2)
|
|
68
|
+
|
|
69
|
+
except SystemExit:
|
|
70
|
+
raise
|
|
71
|
+
except Exception:
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
sys.exit(0)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
if __name__ == "__main__":
|
|
78
|
+
main()
|