@pennyfarthing/core 11.1.1 → 11.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/package.json +2 -1
- package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/doctor.js +381 -66
- package/packages/core/dist/cli/commands/doctor.js.map +1 -1
- package/packages/core/dist/cli/commands/init.js +4 -4
- package/packages/core/dist/cli/commands/init.js.map +1 -1
- package/packages/core/dist/cli/commands/update.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/update.js +4 -5
- package/packages/core/dist/cli/commands/update.js.map +1 -1
- package/packages/core/dist/cli/utils/constants.d.ts +3 -8
- package/packages/core/dist/cli/utils/constants.d.ts.map +1 -1
- package/packages/core/dist/cli/utils/constants.js +3 -4
- package/packages/core/dist/cli/utils/constants.js.map +1 -1
- package/packages/core/dist/cli/utils/settings.d.ts +11 -0
- package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
- package/packages/core/dist/cli/utils/settings.js +65 -29
- package/packages/core/dist/cli/utils/settings.js.map +1 -1
- package/packages/core/dist/cli/utils/symlinks.js +16 -16
- package/packages/core/dist/cli/utils/symlinks.js.map +1 -1
- package/packages/core/dist/consultation/tandem-metrics.d.ts +91 -0
- package/packages/core/dist/consultation/tandem-metrics.d.ts.map +1 -0
- package/packages/core/dist/consultation/tandem-metrics.js +131 -0
- package/packages/core/dist/consultation/tandem-metrics.js.map +1 -0
- package/packages/core/dist/consultation/tandem-metrics.test.d.ts +18 -0
- package/packages/core/dist/consultation/tandem-metrics.test.d.ts.map +1 -0
- package/packages/core/dist/consultation/tandem-metrics.test.js +457 -0
- package/packages/core/dist/consultation/tandem-metrics.test.js.map +1 -0
- package/packages/core/dist/public/js/react/react.js +14 -14
- package/packages/core/dist/scripts/benchmark-integration.d.ts +182 -0
- package/packages/core/dist/scripts/benchmark-integration.d.ts.map +1 -0
- package/packages/core/dist/scripts/benchmark-integration.js +691 -0
- package/packages/core/dist/scripts/benchmark-integration.js.map +1 -0
- package/packages/core/dist/scripts/job-fair-aggregator.d.ts +150 -0
- package/packages/core/dist/scripts/job-fair-aggregator.d.ts.map +1 -0
- package/packages/core/dist/scripts/job-fair-aggregator.js +547 -0
- package/packages/core/dist/scripts/job-fair-aggregator.js.map +1 -0
- package/packages/core/dist/server/api/agent-load.js +1 -1
- package/packages/core/dist/server/api/agent-load.js.map +1 -1
- package/packages/core/dist/server/otlp-receiver.d.ts +16 -11
- package/packages/core/dist/server/otlp-receiver.d.ts.map +1 -1
- package/packages/core/dist/server/otlp-receiver.js +185 -24
- package/packages/core/dist/server/otlp-receiver.js.map +1 -1
- package/packages/core/dist/server/otlp-receiver.test.d.ts +21 -0
- package/packages/core/dist/server/otlp-receiver.test.d.ts.map +1 -0
- package/packages/core/dist/server/otlp-receiver.test.js +446 -0
- package/packages/core/dist/server/otlp-receiver.test.js.map +1 -0
- package/packages/core/dist/server/server.d.ts +0 -3
- package/packages/core/dist/server/server.d.ts.map +1 -1
- package/packages/core/dist/server/server.js +3 -37
- package/packages/core/dist/server/server.js.map +1 -1
- package/packages/core/dist/server/server.test.d.ts +1 -1
- package/packages/core/dist/server/server.test.js +12 -23
- package/packages/core/dist/server/server.test.js.map +1 -1
- package/packages/core/dist/shared/capabilities.d.ts +88 -0
- package/packages/core/dist/shared/capabilities.d.ts.map +1 -0
- package/packages/core/dist/shared/capabilities.js +133 -0
- package/packages/core/dist/shared/capabilities.js.map +1 -0
- package/packages/core/dist/shared/capabilities.test.d.ts +2 -0
- package/packages/core/dist/shared/capabilities.test.d.ts.map +1 -0
- package/packages/core/dist/shared/capabilities.test.js +217 -0
- package/packages/core/dist/shared/capabilities.test.js.map +1 -0
- package/packages/core/dist/shared/portrait-resolver.d.ts +9 -0
- package/packages/core/dist/shared/portrait-resolver.d.ts.map +1 -1
- package/packages/core/dist/shared/portrait-resolver.js +27 -0
- package/packages/core/dist/shared/portrait-resolver.js.map +1 -1
- package/packages/core/dist/shared/portrait-resolver.test.js +47 -1
- package/packages/core/dist/shared/portrait-resolver.test.js.map +1 -1
- package/packages/core/dist/shared/spawn-prompt.d.ts +47 -0
- package/packages/core/dist/shared/spawn-prompt.d.ts.map +1 -0
- package/packages/core/dist/shared/spawn-prompt.js +82 -0
- package/packages/core/dist/shared/spawn-prompt.js.map +1 -0
- package/packages/core/dist/shared/spawn-prompt.test.d.ts +2 -0
- package/packages/core/dist/shared/spawn-prompt.test.d.ts.map +1 -0
- package/packages/core/dist/shared/spawn-prompt.test.js +251 -0
- package/packages/core/dist/shared/spawn-prompt.test.js.map +1 -0
- package/packages/core/dist/shared/tandem-portrait-inventory.test.d.ts +13 -0
- package/packages/core/dist/shared/tandem-portrait-inventory.test.d.ts.map +1 -0
- package/packages/core/dist/shared/tandem-portrait-inventory.test.js +126 -0
- package/packages/core/dist/shared/tandem-portrait-inventory.test.js.map +1 -0
- package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts +18 -0
- package/packages/core/dist/workflow/tandem-workflow-templates.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/tandem-workflow-templates.test.js +434 -0
- package/packages/core/dist/workflow/tandem-workflow-templates.test.js.map +1 -0
- package/packages/core/dist/workflow/workflow-schema.d.ts +32 -0
- package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.js +120 -0
- package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.test.js +570 -1
- package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
- package/pennyfarthing-dist/agents/dev.md +7 -11
- package/pennyfarthing-dist/agents/reviewer.md +9 -3
- package/pennyfarthing-dist/agents/sm-finish.md +18 -1
- package/pennyfarthing-dist/agents/sm-setup.md +1 -1
- package/pennyfarthing-dist/agents/sm.md +2 -2
- package/pennyfarthing-dist/agents/tea.md +1 -1
- package/pennyfarthing-dist/agents/testing-runner.md +2 -1
- package/pennyfarthing-dist/commands/pf-chore.md +2 -2
- package/pennyfarthing-dist/commands/pf-git.md +4 -2
- package/pennyfarthing-dist/commands/pf-standalone.md +7 -2
- package/pennyfarthing-dist/gates/approval.md +63 -0
- package/pennyfarthing-dist/gates/confidence-sm.md +71 -0
- package/pennyfarthing-dist/gates/context-ok.md +56 -0
- package/pennyfarthing-dist/gates/evaluations/confidence-sm.md +54 -0
- package/pennyfarthing-dist/gates/quality-pass.md +67 -0
- package/pennyfarthing-dist/gates/tests-fail.md +84 -0
- package/pennyfarthing-dist/gates/tests-pass.md +79 -0
- package/pennyfarthing-dist/guides/agent-behavior.md +23 -19
- package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +1 -1
- package/pennyfarthing-dist/guides/bell-mode.md +1 -1
- package/pennyfarthing-dist/guides/bikerack.md +3 -3
- package/pennyfarthing-dist/guides/hooks.md +29 -29
- package/pennyfarthing-dist/guides/reflector.md +1 -1
- package/pennyfarthing-dist/guides/tandem-protocol.md +3 -3
- package/pennyfarthing-dist/guides/worktree-mode.md +3 -3
- package/pennyfarthing-dist/guides/xml-tags.md +2 -2
- package/pennyfarthing-dist/scripts/README.md +1 -1
- package/pennyfarthing-dist/scripts/core/check-context.sh +3 -1
- package/pennyfarthing-dist/scripts/core/phase-check-start.sh +5 -87
- package/pennyfarthing-dist/scripts/git/README.md +24 -14
- package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +5 -266
- package/pennyfarthing-dist/scripts/git/git-status-all.sh +5 -151
- package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +6 -144
- package/pennyfarthing-dist/scripts/git/worktree-manager.sh +5 -496
- package/pennyfarthing-dist/scripts/hooks/README.md +6 -6
- package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +4 -183
- package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +4 -95
- package/pennyfarthing-dist/scripts/hooks/context-warning.sh +4 -65
- package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +3 -31
- package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +9 -11
- package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +27 -33
- package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +4 -71
- package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +3 -19
- package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +4 -30
- package/pennyfarthing-dist/scripts/hooks/session-start.sh +3 -32
- package/pennyfarthing-dist/scripts/hooks/session-stop.sh +4 -65
- package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +4 -78
- package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +4 -93
- package/pennyfarthing-dist/scripts/misc/README.md +1 -1
- package/pennyfarthing-dist/scripts/misc/statusline.sh +4 -301
- package/pennyfarthing-dist/scripts/portraits/generate-tandem-portraits.sh +76 -0
- package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +4 -221
- package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +5 -13
- package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +4 -123
- package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +4 -33
- package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +4 -156
- package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +4 -131
- package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +4 -249
- package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +4 -160
- package/pennyfarthing-dist/skills/pf-bc/usage.md +1 -1
- package/pennyfarthing-dist/skills/pf-jira/examples.md +5 -2
- package/pennyfarthing-dist/skills/pf-workflow/examples.md +27 -16
- package/pennyfarthing-dist/skills/pf-workflow/skill.md +9 -12
- package/pennyfarthing-dist/skills/pf-workflow/usage.md +33 -8
- package/pennyfarthing-dist/templates/settings.local.json.template +19 -10
- package/pennyfarthing-dist/workflows/bdd-tandem.yaml +18 -6
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +1 -1
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +1 -1
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +1 -1
- package/pennyfarthing-dist/workflows/review-tandem.yaml +65 -0
- package/pennyfarthing-dist/workflows/tdd-tandem.yaml +16 -8
- package/pennyfarthing-dist/workflows/tdd.yaml +11 -2
- package/pennyfarthing_scripts/CLAUDE.md +45 -14
- package/pennyfarthing_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/bellmode_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/config.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/context.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/output.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/patch_mode.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/pretooluse_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/session_start_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/sprint.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/workflow.cpython-311.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/__pycache__/focus.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/cli.py +3 -5
- package/pennyfarthing_scripts/bellmode_hook.py +12 -296
- package/pennyfarthing_scripts/bikerack/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/audit_log_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/background_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/base_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/changed_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/context_meter_footer.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/debug_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/events.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/git_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/launcher.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/portrait_resolver.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/progress_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/sprint_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_data.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/story_detail_screen.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/tui.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/ws_client.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/audit_log_panel.py +119 -0
- package/pennyfarthing_scripts/bikerack/background_panel.py +86 -5
- package/pennyfarthing_scripts/bikerack/base_panel.py +87 -2
- package/pennyfarthing_scripts/bikerack/changed_panel.py +125 -29
- package/pennyfarthing_scripts/bikerack/context_meter_footer.py +88 -0
- package/pennyfarthing_scripts/bikerack/debug_panel.py +32 -2
- package/pennyfarthing_scripts/bikerack/diffs_panel.py +104 -17
- package/pennyfarthing_scripts/bikerack/events.py +28 -0
- package/pennyfarthing_scripts/bikerack/git_panel.py +103 -33
- package/pennyfarthing_scripts/bikerack/launcher.py +15 -15
- package/pennyfarthing_scripts/bikerack/portrait_resolver.py +139 -0
- package/pennyfarthing_scripts/bikerack/progress_panel.py +315 -0
- package/pennyfarthing_scripts/bikerack/sprint_panel.py +395 -32
- package/pennyfarthing_scripts/bikerack/story_detail_data.py +244 -0
- package/pennyfarthing_scripts/bikerack/story_detail_screen.py +176 -0
- package/pennyfarthing_scripts/bikerack/tui.py +575 -37
- package/pennyfarthing_scripts/bikerack/ws_client.py +2 -2
- package/pennyfarthing_scripts/brownfield/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/brownfield/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/brownfield/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/brownfield/__pycache__/discover.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/cli.py +42 -65
- package/pennyfarthing_scripts/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/__pycache__/config.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/__pycache__/output.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/__pycache__/themes.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/common/pr_config.py +38 -0
- package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/__init__.py +1 -0
- package/pennyfarthing_scripts/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/__pycache__/dialogue_manager.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/cli.py +149 -0
- package/pennyfarthing_scripts/consultation/dialogue_manager.py +417 -0
- package/pennyfarthing_scripts/context.py +3 -3
- package/pennyfarthing_scripts/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/epic/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/epic/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__init__.py +12 -1
- package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/create_branches.py +3 -4
- package/pennyfarthing_scripts/git/hooks_installer.py +152 -0
- package/pennyfarthing_scripts/git/repos.py +196 -0
- package/pennyfarthing_scripts/git/status_all.py +27 -11
- package/pennyfarthing_scripts/git/worktree.py +302 -0
- package/pennyfarthing_scripts/git_group/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git_group/cli.py +143 -40
- package/pennyfarthing_scripts/handoff/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/gate_file.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/gate_runner.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/marker.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/cli.py +33 -1
- package/pennyfarthing_scripts/handoff/complete_phase.py +40 -0
- package/pennyfarthing_scripts/handoff/marker.py +15 -15
- package/pennyfarthing_scripts/handoff/phase_check.py +96 -0
- package/pennyfarthing_scripts/handoff/resolve_gate.py +18 -15
- package/pennyfarthing_scripts/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__init__.py +437 -0
- package/pennyfarthing_scripts/hooks/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/bell_mode.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/context_breaker.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/context_warning.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/cyclist_pretooluse.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/pre_edit_check.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/reflector_check.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/schema_validation.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/session_start.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/session_stop.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/sprint_yaml_validation.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/__pycache__/statusline.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hooks/bell_mode.py +215 -0
- package/pennyfarthing_scripts/hooks/cli.py +96 -0
- package/pennyfarthing_scripts/hooks/context_breaker.py +104 -0
- package/pennyfarthing_scripts/hooks/context_warning.py +66 -0
- package/pennyfarthing_scripts/hooks/cyclist_pretooluse.py +129 -0
- package/pennyfarthing_scripts/hooks/pre_edit_check.py +78 -0
- package/pennyfarthing_scripts/hooks/reflector_check.py +271 -0
- package/pennyfarthing_scripts/hooks/schema_validation.py +203 -0
- package/pennyfarthing_scripts/hooks/session_start.py +296 -0
- package/pennyfarthing_scripts/hooks/session_stop.py +111 -0
- package/pennyfarthing_scripts/hooks/sprint_yaml_validation.py +97 -0
- package/pennyfarthing_scripts/hooks/statusline.py +420 -0
- package/pennyfarthing_scripts/hooks.py +27 -446
- package/pennyfarthing_scripts/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/compat.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/create.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/mappings.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/operations.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/launch/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/launch/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/preflight/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/preflight/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/preflight/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/preflight/__pycache__/finish.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/pretooluse_hook.py +3 -185
- package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/version_sentinel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/heatmap.py +655 -0
- package/pennyfarthing_scripts/prime/workflow.py +2 -1
- package/pennyfarthing_scripts/schema_validation_hook.py +3 -298
- package/pennyfarthing_scripts/session/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/session/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/session_start_hook.py +4 -186
- package/pennyfarthing_scripts/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/epic_update.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/import_epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/status.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/story_add.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/loader.py +15 -1
- package/pennyfarthing_scripts/sprint/story_update.py +19 -0
- package/pennyfarthing_scripts/story/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/create.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/size.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/story/__pycache__/template.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/conftest.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_108_1_gate_migration.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_archive_epic.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_bc.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_bikerack.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_brownfield.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_cli_modules.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_cli_normalization.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_codemarkers.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_common.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_evaluation.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_confidence_sm_gate.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_dialogue_manager.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_epic_shard_validation.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_git_utils.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_handoff_cli.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_handoff_e2e.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_sprint_panel.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_story_add.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_story_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_story_update.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_tiers.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_token_counting.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_topology_loader.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_tui_focus.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_tui_panel_persistence.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_validate_cmd.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_version_sentinel.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/test_bikerack.py +51 -51
- package/pennyfarthing_scripts/tests/test_dialogue_manager.py +811 -0
- package/pennyfarthing_scripts/tests/test_handoff_cli.py +16 -11
- package/pennyfarthing_scripts/tests/test_sprint_panel.py +344 -265
- package/pennyfarthing_scripts/tests/test_workflow_check.py +2 -3
- package/pennyfarthing_scripts/theme/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/theme/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/agent.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/schema.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/sprint.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/tandem_awareness.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/tandem_awareness.py +254 -0
- package/pennyfarthing_scripts/validate/adapters/workflow.py +19 -0
- package/pennyfarthing_scripts/validate/cli.py +17 -5
- package/pennyfarthing_scripts/welcome_hook.py +3 -149
- package/pennyfarthing_scripts/workflow/__init__.py +40 -0
- package/pennyfarthing_scripts/workflow/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/helpers.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/scale.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/__pycache__/state.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/cli.py +1100 -0
- package/pennyfarthing_scripts/workflow/helpers.py +241 -0
- package/pennyfarthing_scripts/{workflow.py → workflow/scale.py} +0 -104
- package/pennyfarthing_scripts/workflow/state.py +112 -0
- package/pennyfarthing_scripts/workflow/team_lifecycle.py +257 -0
- package/packages/core/dist/scripts/theme-detail.test.d.ts +0 -10
- package/packages/core/dist/scripts/theme-detail.test.js +0 -199
- package/pennyfarthing-dist/skills/pf-workflow/scripts/list-workflows.sh +0 -91
- package/pennyfarthing-dist/skills/pf-workflow/scripts/resume-workflow.sh +0 -163
- package/pennyfarthing-dist/skills/pf-workflow/scripts/show-workflow.sh +0 -138
- package/pennyfarthing-dist/skills/pf-workflow/scripts/start-workflow.sh +0 -273
- package/pennyfarthing-dist/skills/pf-workflow/scripts/workflow-status.sh +0 -167
- package/pennyfarthing_scripts/gate/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/gate/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/gate/__pycache__/validate.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_108_2_remove_handoff_fallback.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_gate_file_resolution.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_gate_runner.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_resolve_gate_file_field.cpython-314-pytest-9.0.2.pyc +0 -0
|
@@ -1,305 +1,10 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
1
|
"""
|
|
3
|
-
|
|
2
|
+
Backward-compatibility shim — schema validation hook moved to hooks/schema_validation.py.
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
Blocks the tool call if validation fails, providing immediate feedback.
|
|
7
|
-
|
|
8
|
-
Usage in settings.json:
|
|
9
|
-
{
|
|
10
|
-
"hooks": {
|
|
11
|
-
"PreToolUse": [{
|
|
12
|
-
"matcher": "Write|Edit",
|
|
13
|
-
"hooks": [{
|
|
14
|
-
"type": "command",
|
|
15
|
-
"command": "python3 -m pennyfarthing_scripts.schema_validation_hook"
|
|
16
|
-
}]
|
|
17
|
-
}]
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
Story: XML Schema Migration Tools
|
|
4
|
+
This file will be removed in a future version.
|
|
22
5
|
"""
|
|
23
6
|
|
|
24
|
-
import
|
|
25
|
-
import sys
|
|
26
|
-
from pathlib import Path
|
|
27
|
-
|
|
28
|
-
# Add parent directory to path for imports
|
|
29
|
-
sys.path.insert(0, str(Path(__file__).parent))
|
|
30
|
-
|
|
31
|
-
from hooks import (
|
|
32
|
-
HookResponse,
|
|
33
|
-
output_hook_response,
|
|
34
|
-
read_stdin_json,
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
# =============================================================================
|
|
38
|
-
# File Type Detection
|
|
39
|
-
# =============================================================================
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def is_session_file(file_path: str) -> bool:
|
|
43
|
-
"""Check if path is a session file."""
|
|
44
|
-
return file_path.endswith("-session.md") and ".session/" in file_path
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def is_skill_file(file_path: str) -> bool:
|
|
48
|
-
"""Check if path is a skill SKILL.md file."""
|
|
49
|
-
return file_path.endswith("/SKILL.md") and "/skills/" in file_path
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def is_step_file(file_path: str) -> bool:
|
|
53
|
-
"""Check if path is a workflow step file."""
|
|
54
|
-
path = Path(file_path)
|
|
55
|
-
return (
|
|
56
|
-
path.name.startswith("step-")
|
|
57
|
-
and path.name.endswith(".md")
|
|
58
|
-
and "/workflows/" in file_path
|
|
59
|
-
and "/steps/" in file_path
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def get_file_type(file_path: str) -> str | None:
|
|
64
|
-
"""Detect file type from path."""
|
|
65
|
-
if is_session_file(file_path):
|
|
66
|
-
return "session"
|
|
67
|
-
elif is_skill_file(file_path):
|
|
68
|
-
return "skill"
|
|
69
|
-
elif is_step_file(file_path):
|
|
70
|
-
return "step"
|
|
71
|
-
return None
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
# =============================================================================
|
|
75
|
-
# Content-Based Validation (inline to avoid import issues)
|
|
76
|
-
# =============================================================================
|
|
77
|
-
|
|
78
|
-
# Skill required tags
|
|
79
|
-
SKILL_REQUIRED_TAGS = ["run", "output"]
|
|
80
|
-
|
|
81
|
-
# Workflow step required tags
|
|
82
|
-
STEP_REQUIRED_TAGS = ["purpose", "instructions", "output"]
|
|
83
|
-
|
|
84
|
-
# Step meta required fields
|
|
85
|
-
STEP_META_FIELDS = ["step", "workflow", "agent", "next"]
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def _has_tag(content: str, tag: str) -> bool:
|
|
89
|
-
"""Check if content contains a specific XML tag."""
|
|
90
|
-
return f"<{tag}>" in content or f"<{tag} " in content
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def validate_session_content(content: str) -> list[str]:
|
|
94
|
-
"""Validate session file content.
|
|
95
|
-
|
|
96
|
-
Args:
|
|
97
|
-
content: File content to validate
|
|
98
|
-
|
|
99
|
-
Returns:
|
|
100
|
-
List of error messages (empty if valid)
|
|
101
|
-
"""
|
|
102
|
-
errors = []
|
|
103
|
-
|
|
104
|
-
# Check for XML format indicator
|
|
105
|
-
if "<session" not in content:
|
|
106
|
-
# Old markdown format - warn but don't block during migration
|
|
107
|
-
return []
|
|
108
|
-
|
|
109
|
-
# Validate <session> root with attributes
|
|
110
|
-
if not re.search(r'<session\s+story="[^"]+"', content):
|
|
111
|
-
errors.append("Missing story attribute on <session>")
|
|
112
|
-
|
|
113
|
-
if not re.search(r'<session[^>]+workflow="[^"]+"', content):
|
|
114
|
-
errors.append("Missing workflow attribute on <session>")
|
|
115
|
-
|
|
116
|
-
# Validate <meta> section
|
|
117
|
-
if not _has_tag(content, "meta"):
|
|
118
|
-
errors.append("Missing <meta> section")
|
|
119
|
-
else:
|
|
120
|
-
if "<jira>" not in content:
|
|
121
|
-
errors.append("Missing <jira> in <meta>")
|
|
122
|
-
if "<started>" not in content:
|
|
123
|
-
errors.append("Missing <started> in <meta>")
|
|
124
|
-
|
|
125
|
-
# Validate <status> element
|
|
126
|
-
if not _has_tag(content, "status"):
|
|
127
|
-
errors.append("Missing <status> element")
|
|
128
|
-
else:
|
|
129
|
-
if 'phase="' not in content:
|
|
130
|
-
errors.append("Missing phase attribute on <status>")
|
|
131
|
-
|
|
132
|
-
return errors
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
def validate_skill_content(content: str) -> list[str]:
|
|
136
|
-
"""Validate skill file content.
|
|
137
|
-
|
|
138
|
-
Args:
|
|
139
|
-
content: File content to validate
|
|
140
|
-
|
|
141
|
-
Returns:
|
|
142
|
-
List of error messages (empty if valid)
|
|
143
|
-
"""
|
|
144
|
-
errors = []
|
|
145
|
-
|
|
146
|
-
# Check YAML frontmatter
|
|
147
|
-
if not content.startswith("---\n"):
|
|
148
|
-
errors.append("Missing YAML frontmatter")
|
|
149
|
-
else:
|
|
150
|
-
parts = content.split("---", 2)
|
|
151
|
-
if len(parts) >= 2:
|
|
152
|
-
frontmatter = parts[1]
|
|
153
|
-
if "name:" not in frontmatter:
|
|
154
|
-
errors.append("Missing 'name' in frontmatter")
|
|
155
|
-
if "description:" not in frontmatter:
|
|
156
|
-
errors.append("Missing 'description' in frontmatter")
|
|
157
|
-
|
|
158
|
-
# Check required tags
|
|
159
|
-
for tag in SKILL_REQUIRED_TAGS:
|
|
160
|
-
if not _has_tag(content, tag):
|
|
161
|
-
errors.append(f"Missing <{tag}> tag (required)")
|
|
162
|
-
|
|
163
|
-
return errors
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
def validate_step_content(content: str) -> list[str]:
|
|
167
|
-
"""Validate workflow step file content.
|
|
168
|
-
|
|
169
|
-
Args:
|
|
170
|
-
content: File content to validate
|
|
171
|
-
|
|
172
|
-
Returns:
|
|
173
|
-
List of error messages (empty if valid)
|
|
174
|
-
"""
|
|
175
|
-
errors = []
|
|
176
|
-
|
|
177
|
-
# Check required tags
|
|
178
|
-
for tag in STEP_REQUIRED_TAGS:
|
|
179
|
-
if not _has_tag(content, tag):
|
|
180
|
-
errors.append(f"Missing <{tag}> tag")
|
|
181
|
-
|
|
182
|
-
# Check step-meta fields if tag exists
|
|
183
|
-
if _has_tag(content, "step-meta"):
|
|
184
|
-
meta_match = re.search(r"<step-meta>(.+?)</step-meta>", content, re.DOTALL)
|
|
185
|
-
if meta_match:
|
|
186
|
-
meta_content = meta_match.group(1)
|
|
187
|
-
for field_name in STEP_META_FIELDS:
|
|
188
|
-
if f"{field_name}:" not in meta_content:
|
|
189
|
-
errors.append(f"Missing '{field_name}' in step-meta")
|
|
190
|
-
|
|
191
|
-
return errors
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
def validate_content(file_path: str, content: str) -> list[str]:
|
|
195
|
-
"""Validate content based on file type.
|
|
196
|
-
|
|
197
|
-
Args:
|
|
198
|
-
file_path: Path to file being written
|
|
199
|
-
content: Content being written
|
|
200
|
-
|
|
201
|
-
Returns:
|
|
202
|
-
List of error messages (empty if valid)
|
|
203
|
-
"""
|
|
204
|
-
file_type = get_file_type(file_path)
|
|
205
|
-
|
|
206
|
-
if file_type == "session":
|
|
207
|
-
return validate_session_content(content)
|
|
208
|
-
elif file_type == "skill":
|
|
209
|
-
return validate_skill_content(content)
|
|
210
|
-
elif file_type == "step":
|
|
211
|
-
return validate_step_content(content)
|
|
212
|
-
|
|
213
|
-
return []
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
# =============================================================================
|
|
217
|
-
# Hook Entry Point
|
|
218
|
-
# =============================================================================
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
def main() -> None:
|
|
222
|
-
"""Main entry point for schema validation hook."""
|
|
223
|
-
try:
|
|
224
|
-
# Read tool data from Claude Code
|
|
225
|
-
tool_data = read_stdin_json()
|
|
226
|
-
|
|
227
|
-
tool_name = tool_data.get("tool_name", "")
|
|
228
|
-
tool_input = tool_data.get("tool_input", {})
|
|
229
|
-
|
|
230
|
-
# Only process Write and Edit tools
|
|
231
|
-
if tool_name not in ("Write", "Edit"):
|
|
232
|
-
output_hook_response(HookResponse(
|
|
233
|
-
event_name="PreToolUse",
|
|
234
|
-
decision="allow",
|
|
235
|
-
reason="Not a Write/Edit operation",
|
|
236
|
-
))
|
|
237
|
-
sys.exit(0)
|
|
238
|
-
|
|
239
|
-
# Get file path
|
|
240
|
-
file_path = tool_input.get("file_path", "")
|
|
241
|
-
if not file_path:
|
|
242
|
-
output_hook_response(HookResponse(
|
|
243
|
-
event_name="PreToolUse",
|
|
244
|
-
decision="allow",
|
|
245
|
-
reason="No file path",
|
|
246
|
-
))
|
|
247
|
-
sys.exit(0)
|
|
248
|
-
|
|
249
|
-
# Check if this is a file we care about
|
|
250
|
-
file_type = get_file_type(file_path)
|
|
251
|
-
if not file_type:
|
|
252
|
-
output_hook_response(HookResponse(
|
|
253
|
-
event_name="PreToolUse",
|
|
254
|
-
decision="allow",
|
|
255
|
-
reason="Not a session/skill/step file",
|
|
256
|
-
))
|
|
257
|
-
sys.exit(0)
|
|
258
|
-
|
|
259
|
-
# Get content to validate
|
|
260
|
-
# For Write: use 'content'
|
|
261
|
-
# For Edit: we need to simulate the edit result
|
|
262
|
-
if tool_name == "Write":
|
|
263
|
-
content = tool_input.get("content", "")
|
|
264
|
-
else:
|
|
265
|
-
# Edit operation - we can't easily validate without reading the file
|
|
266
|
-
# For now, allow Edits and validate on Write only
|
|
267
|
-
output_hook_response(HookResponse(
|
|
268
|
-
event_name="PreToolUse",
|
|
269
|
-
decision="allow",
|
|
270
|
-
reason="Edit operations validated post-hoc",
|
|
271
|
-
))
|
|
272
|
-
sys.exit(0)
|
|
273
|
-
|
|
274
|
-
# Validate content
|
|
275
|
-
errors = validate_content(file_path, content)
|
|
276
|
-
|
|
277
|
-
if errors:
|
|
278
|
-
# Block the write
|
|
279
|
-
error_msg = f"Schema validation failed for {file_type} file:\n"
|
|
280
|
-
error_msg += "\n".join(f" - {e}" for e in errors)
|
|
281
|
-
error_msg += f"\n\nFile: {file_path}"
|
|
282
|
-
|
|
283
|
-
output_hook_response(HookResponse(
|
|
284
|
-
event_name="PreToolUse",
|
|
285
|
-
decision="deny",
|
|
286
|
-
reason=error_msg,
|
|
287
|
-
))
|
|
288
|
-
sys.exit(0)
|
|
289
|
-
|
|
290
|
-
# Validation passed
|
|
291
|
-
output_hook_response(HookResponse(
|
|
292
|
-
event_name="PreToolUse",
|
|
293
|
-
decision="allow",
|
|
294
|
-
reason=f"Schema validation passed for {file_type} file",
|
|
295
|
-
))
|
|
296
|
-
sys.exit(0)
|
|
297
|
-
|
|
298
|
-
except Exception as e:
|
|
299
|
-
# On error, allow to avoid blocking legitimate work
|
|
300
|
-
print(f"[schema-validation-hook] Error: {e}", file=sys.stderr)
|
|
301
|
-
sys.exit(0)
|
|
302
|
-
|
|
7
|
+
from pennyfarthing_scripts.hooks.schema_validation import main # noqa: F401
|
|
303
8
|
|
|
304
9
|
if __name__ == "__main__":
|
|
305
10
|
main()
|
|
Binary file
|
|
@@ -1,192 +1,10 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Session start hook — initialize environment for Claude Code session.
|
|
3
|
-
|
|
4
|
-
Handles:
|
|
5
|
-
1. Session directory setup and logging
|
|
6
|
-
2. Checkpoint validation (cross-session drift detection)
|
|
7
|
-
3. WheelHub auto-start (ensure BikeRack server is running)
|
|
8
|
-
4. OTEL auto-configuration via CLAUDE_ENV_FILE
|
|
9
|
-
|
|
10
|
-
Called by Claude Code SessionStart hook via shell wrapper.
|
|
11
1
|
"""
|
|
2
|
+
Backward-compatibility shim — session start hook moved to hooks/session_start.py.
|
|
12
3
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import json
|
|
16
|
-
import os
|
|
17
|
-
import sys
|
|
18
|
-
from pathlib import Path
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def _read_input() -> dict:
|
|
22
|
-
"""Read JSON from stdin (hook protocol)."""
|
|
23
|
-
raw = sys.stdin.read()
|
|
24
|
-
try:
|
|
25
|
-
return json.loads(raw)
|
|
26
|
-
except (json.JSONDecodeError, ValueError):
|
|
27
|
-
return {}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def _setup_session_dir(project_dir: Path, session_id: str, source_type: str) -> None:
|
|
31
|
-
"""Ensure .session directory exists and log session start."""
|
|
32
|
-
session_dir = project_dir / ".session"
|
|
33
|
-
session_dir.mkdir(parents=True, exist_ok=True)
|
|
34
|
-
(session_dir / "agents").mkdir(exist_ok=True)
|
|
35
|
-
|
|
36
|
-
from datetime import UTC, datetime
|
|
37
|
-
|
|
38
|
-
timestamp = datetime.now(UTC).isoformat()
|
|
39
|
-
log_file = session_dir / "session-log.txt"
|
|
40
|
-
with open(log_file, "a") as f:
|
|
41
|
-
f.write(f"{timestamp} | Session {source_type}: {session_id}\n")
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def _validate_checkpoint(project_dir: Path) -> None:
|
|
45
|
-
"""Validate previous session checkpoint for cross-session drift detection."""
|
|
46
|
-
try:
|
|
47
|
-
import subprocess
|
|
48
|
-
|
|
49
|
-
script_dir = Path(__file__).resolve().parent.parent
|
|
50
|
-
checkpoint_lib = script_dir / "pennyfarthing-dist" / "scripts" / "lib" / "checkpoint.sh"
|
|
51
|
-
|
|
52
|
-
if not checkpoint_lib.exists():
|
|
53
|
-
return
|
|
54
|
-
|
|
55
|
-
result = subprocess.run(
|
|
56
|
-
["bash", "-c", f'source "{checkpoint_lib}" && checkpoint_restore session_state'],
|
|
57
|
-
capture_output=True,
|
|
58
|
-
text=True,
|
|
59
|
-
cwd=str(project_dir),
|
|
60
|
-
timeout=5,
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
prev_state = result.stdout.strip()
|
|
64
|
-
if not prev_state:
|
|
65
|
-
return
|
|
66
|
-
|
|
67
|
-
# Parse checkpoint data
|
|
68
|
-
fields = {}
|
|
69
|
-
for part in prev_state.split(";"):
|
|
70
|
-
if "=" in part:
|
|
71
|
-
k, v = part.split("=", 1)
|
|
72
|
-
fields[k] = v
|
|
73
|
-
|
|
74
|
-
prev_sha = fields.get("sha", "")
|
|
75
|
-
if not prev_sha:
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
# Get current git SHA
|
|
79
|
-
result = subprocess.run(
|
|
80
|
-
["git", "rev-parse", "--short", "HEAD"],
|
|
81
|
-
capture_output=True,
|
|
82
|
-
text=True,
|
|
83
|
-
cwd=str(project_dir),
|
|
84
|
-
timeout=5,
|
|
85
|
-
)
|
|
86
|
-
current_sha = result.stdout.strip()
|
|
87
|
-
if not current_sha or current_sha == prev_sha:
|
|
88
|
-
return
|
|
89
|
-
|
|
90
|
-
# Log drift
|
|
91
|
-
from datetime import UTC, datetime
|
|
92
|
-
|
|
93
|
-
timestamp = datetime.now(UTC).isoformat()
|
|
94
|
-
session_dir = project_dir / ".session"
|
|
95
|
-
|
|
96
|
-
warning = f"CROSS_SESSION_DRIFT: Git changed (was: {prev_sha}, now: {current_sha})"
|
|
97
|
-
if fields.get("story"):
|
|
98
|
-
warning += f" | Story: {fields['story']}"
|
|
99
|
-
if fields.get("agent"):
|
|
100
|
-
warning += f" | Agent: {fields['agent']}"
|
|
101
|
-
|
|
102
|
-
with open(session_dir / "session-log.txt", "a") as f:
|
|
103
|
-
f.write(f"{timestamp} | {warning}\n")
|
|
104
|
-
|
|
105
|
-
drift_entry = f"{timestamp} | prev_sha={prev_sha} | current_sha={current_sha}"
|
|
106
|
-
for key in ("story", "agent", "phase"):
|
|
107
|
-
if fields.get(key):
|
|
108
|
-
drift_entry += f" | {key}={fields[key]}"
|
|
109
|
-
with open(session_dir / "drift-log.txt", "a") as f:
|
|
110
|
-
f.write(drift_entry + "\n")
|
|
111
|
-
|
|
112
|
-
except Exception:
|
|
113
|
-
pass
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def _ensure_wheelhub(project_dir: Path) -> int | None:
|
|
117
|
-
"""Auto-start WheelHub if not already running. Returns port or None."""
|
|
118
|
-
from pennyfarthing_scripts.bikerack.launcher import (
|
|
119
|
-
is_already_running,
|
|
120
|
-
poll_for_port_file,
|
|
121
|
-
start_wheelhub,
|
|
122
|
-
write_pid_file,
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
# Skip if full Cyclist is running
|
|
126
|
-
cyclist_port_file = project_dir / ".cyclist-port"
|
|
127
|
-
if cyclist_port_file.exists():
|
|
128
|
-
try:
|
|
129
|
-
return int(cyclist_port_file.read_text().strip())
|
|
130
|
-
except (ValueError, OSError):
|
|
131
|
-
return None
|
|
132
|
-
|
|
133
|
-
# Check if BikeRack WheelHub is already running
|
|
134
|
-
running, _pid, port = is_already_running(project_dir)
|
|
135
|
-
if running:
|
|
136
|
-
return port
|
|
137
|
-
|
|
138
|
-
# Start WheelHub
|
|
139
|
-
try:
|
|
140
|
-
proc = start_wheelhub(project_dir)
|
|
141
|
-
write_pid_file(project_dir, proc.pid)
|
|
142
|
-
return poll_for_port_file(project_dir)
|
|
143
|
-
except Exception:
|
|
144
|
-
return None
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def _write_env_file(project_dir: Path, session_id: str, otel_port: int | None) -> None:
|
|
148
|
-
"""Write environment variables to CLAUDE_ENV_FILE."""
|
|
149
|
-
env_file = os.environ.get("CLAUDE_ENV_FILE")
|
|
150
|
-
if not env_file:
|
|
151
|
-
return
|
|
152
|
-
|
|
153
|
-
lines = [
|
|
154
|
-
"# Pennyfarthing core environment",
|
|
155
|
-
f'export PROJECT_ROOT="{project_dir}"',
|
|
156
|
-
f'export SESSION_ID="{session_id}"',
|
|
157
|
-
]
|
|
158
|
-
|
|
159
|
-
if otel_port is not None:
|
|
160
|
-
lines.extend([
|
|
161
|
-
"# OTEL auto-configuration for Cyclist/WheelHub",
|
|
162
|
-
'export OTEL_EXPORTER_OTLP_PROTOCOL="http/json"',
|
|
163
|
-
f'export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:{otel_port}"',
|
|
164
|
-
])
|
|
165
|
-
|
|
166
|
-
with open(env_file, "a") as f:
|
|
167
|
-
f.write("\n".join(lines) + "\n")
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
def main() -> None:
|
|
171
|
-
"""Entry point for SessionStart hook."""
|
|
172
|
-
try:
|
|
173
|
-
input_data = _read_input()
|
|
174
|
-
session_id = input_data.get("session_id", "unknown")
|
|
175
|
-
source_type = input_data.get("source", "unknown")
|
|
176
|
-
|
|
177
|
-
project_dir = Path(os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd()))
|
|
178
|
-
|
|
179
|
-
_setup_session_dir(project_dir, session_id, source_type)
|
|
180
|
-
_validate_checkpoint(project_dir)
|
|
181
|
-
|
|
182
|
-
otel_port = _ensure_wheelhub(project_dir)
|
|
183
|
-
_write_env_file(project_dir, session_id, otel_port)
|
|
184
|
-
|
|
185
|
-
except Exception:
|
|
186
|
-
pass
|
|
187
|
-
|
|
188
|
-
sys.exit(0)
|
|
4
|
+
This file will be removed in a future version.
|
|
5
|
+
"""
|
|
189
6
|
|
|
7
|
+
from pennyfarthing_scripts.hooks.session_start import main # noqa: F401
|
|
190
8
|
|
|
191
9
|
if __name__ == "__main__":
|
|
192
10
|
main()
|
|
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
|
|
@@ -62,6 +62,17 @@ def _merge_epic_shards(data: dict[str, Any], sprint_dir: Path) -> dict[str, Any]
|
|
|
62
62
|
stacklevel=2,
|
|
63
63
|
)
|
|
64
64
|
|
|
65
|
+
# Collect epic refs owned by initiatives so we don't warn about them.
|
|
66
|
+
initiative_refs: set[str] = set()
|
|
67
|
+
for init_file in sorted(sprint_dir.glob("initiative-*.yaml")):
|
|
68
|
+
init_data = load_yaml_config(init_file)
|
|
69
|
+
if init_data and isinstance(init_data, dict):
|
|
70
|
+
for ref in init_data.get("epics", []):
|
|
71
|
+
if isinstance(ref, str):
|
|
72
|
+
initiative_refs.add(ref)
|
|
73
|
+
# Also add normalized form (strip "epic-" prefix)
|
|
74
|
+
initiative_refs.add(ref.replace("epic-", ""))
|
|
75
|
+
|
|
65
76
|
# Log unindexed shard files on disk (but do NOT auto-merge —
|
|
66
77
|
# orphan shards may belong to future initiatives).
|
|
67
78
|
for shard_file in sorted(sprint_dir.glob("epic-*.yaml")):
|
|
@@ -74,7 +85,10 @@ def _merge_epic_shards(data: dict[str, Any], sprint_dir: Path) -> dict[str, Any]
|
|
|
74
85
|
jira_key = str(epic_data.get("jira", ""))
|
|
75
86
|
if eid in loaded_epic_ids or (jira_key and jira_key in loaded_epic_ids):
|
|
76
87
|
continue
|
|
77
|
-
#
|
|
88
|
+
# Skip shards owned by initiatives (not orphans)
|
|
89
|
+
if eid in initiative_refs or jira_key in initiative_refs:
|
|
90
|
+
continue
|
|
91
|
+
# Warn only about truly orphaned shards
|
|
78
92
|
warnings.warn(
|
|
79
93
|
f"Unindexed shard {shard_file.name} (epic {eid}) not in epics list — skipping",
|
|
80
94
|
stacklevel=2,
|
|
@@ -30,6 +30,8 @@ def update_story(
|
|
|
30
30
|
completed_date: str | None = None,
|
|
31
31
|
started_date: str | None = None,
|
|
32
32
|
workflow: str | None = None,
|
|
33
|
+
review_findings: str | None = None,
|
|
34
|
+
review_verdict: str | None = None,
|
|
33
35
|
dry_run: bool = False,
|
|
34
36
|
) -> dict[str, Any]:
|
|
35
37
|
"""Update fields on a story in the sprint YAML.
|
|
@@ -44,6 +46,8 @@ def update_story(
|
|
|
44
46
|
completed_date: Completed date (ISO format)
|
|
45
47
|
started_date: Started date (ISO format)
|
|
46
48
|
workflow: Workflow type (tdd, trivial, bdd, agent-docs)
|
|
49
|
+
review_findings: Reviewer findings text
|
|
50
|
+
review_verdict: Review verdict (approved, rejected, pending)
|
|
47
51
|
dry_run: If True, report changes without writing
|
|
48
52
|
|
|
49
53
|
Returns:
|
|
@@ -97,6 +101,15 @@ def update_story(
|
|
|
97
101
|
story["started"] = started_date
|
|
98
102
|
if workflow is not None:
|
|
99
103
|
story["workflow"] = workflow
|
|
104
|
+
if review_findings is not None:
|
|
105
|
+
story["review_findings"] = review_findings
|
|
106
|
+
if review_verdict is not None:
|
|
107
|
+
if review_verdict not in ("approved", "rejected", "pending"):
|
|
108
|
+
return {
|
|
109
|
+
"success": False,
|
|
110
|
+
"error": f"Invalid review_verdict '{review_verdict}'. Must be one of: approved, rejected, pending",
|
|
111
|
+
}
|
|
112
|
+
story["review_verdict"] = review_verdict
|
|
100
113
|
|
|
101
114
|
# Auto-cleanup rules
|
|
102
115
|
if status == "done":
|
|
@@ -153,6 +166,8 @@ def update_story(
|
|
|
153
166
|
@click.option("--priority", default=None)
|
|
154
167
|
@click.option("--started", "started_date", default=None)
|
|
155
168
|
@click.option("--workflow", default=None)
|
|
169
|
+
@click.option("--review-findings", default=None, help="Reviewer findings text")
|
|
170
|
+
@click.option("--review-verdict", type=click.Choice(["approved", "rejected", "pending"]), default=None)
|
|
156
171
|
@click.option("--dry-run", is_flag=True)
|
|
157
172
|
@click.option("--sprint-file", type=click.Path(), default=None, help="Path to sprint YAML file")
|
|
158
173
|
def story_update_command(
|
|
@@ -164,6 +179,8 @@ def story_update_command(
|
|
|
164
179
|
priority: str | None,
|
|
165
180
|
started_date: str | None,
|
|
166
181
|
workflow: str | None,
|
|
182
|
+
review_findings: str | None,
|
|
183
|
+
review_verdict: str | None,
|
|
167
184
|
dry_run: bool,
|
|
168
185
|
sprint_file: str | None,
|
|
169
186
|
) -> None:
|
|
@@ -184,6 +201,8 @@ def story_update_command(
|
|
|
184
201
|
completed_date=completed_date,
|
|
185
202
|
started_date=started_date,
|
|
186
203
|
workflow=workflow,
|
|
204
|
+
review_findings=review_findings,
|
|
205
|
+
review_verdict=review_verdict,
|
|
187
206
|
dry_run=dry_run,
|
|
188
207
|
)
|
|
189
208
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/pennyfarthing_scripts/tests/__pycache__/test_archive_epic.cpython-314-pytest-9.0.2.pyc
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/pennyfarthing_scripts/tests/__pycache__/test_brownfield.cpython-314-pytest-9.0.2.pyc
CHANGED
|
Binary file
|