@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
|
@@ -24,9 +24,8 @@ from click.testing import CliRunner
|
|
|
24
24
|
from pennyfarthing_scripts.cli import cli
|
|
25
25
|
from pennyfarthing_scripts.workflow import get_workflow_state
|
|
26
26
|
|
|
27
|
-
# Mock path:
|
|
28
|
-
|
|
29
|
-
MOCK_PATH = "pennyfarthing_scripts.workflow.get_workflow_state"
|
|
27
|
+
# Mock path: workflow.cli imports from workflow.state, so mock at the source module
|
|
28
|
+
MOCK_PATH = "pennyfarthing_scripts.workflow.state.get_workflow_state"
|
|
30
29
|
|
|
31
30
|
|
|
32
31
|
class TestWorkflowCheckCLI:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"""Tandem awareness validator adapter.
|
|
2
|
+
|
|
3
|
+
Validates that agent definitions include proper tandem consultation sections
|
|
4
|
+
per ADR-0012 and the tandem-consultation protocol.
|
|
5
|
+
|
|
6
|
+
Story: MSSCI-14499 (86-4)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import re
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from pennyfarthing_scripts.validate import ValidateReport
|
|
15
|
+
|
|
16
|
+
# Regex to extract <tandem-consultation> section content
|
|
17
|
+
_TANDEM_RE = re.compile(
|
|
18
|
+
r"<tandem-consultation>(.*?)</tandem-consultation>", re.DOTALL
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# Regex to extract role from heading: ## Tandem Consultation (Leader + Partner)
|
|
22
|
+
_HEADING_RE = re.compile(r"##\s+Tandem Consultation\s*\(([^)]+)\)")
|
|
23
|
+
|
|
24
|
+
# Required response format fields for partner agents
|
|
25
|
+
_PARTNER_FIELDS = {
|
|
26
|
+
"Recommendation": "**Recommendation:**",
|
|
27
|
+
"Rationale": "**Rationale:**",
|
|
28
|
+
"Watch-Out-For": "**Watch-Out-For:**",
|
|
29
|
+
"Confidence": "**Confidence:**",
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# ADR-0012 high-value pairings (leader, partner) — directional
|
|
33
|
+
ADR_0012_PAIRINGS: list[tuple[str, str]] = [
|
|
34
|
+
("dev", "architect"),
|
|
35
|
+
("dev", "tea"),
|
|
36
|
+
("reviewer", "architect"),
|
|
37
|
+
("dev", "devops"),
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _extract_tandem_section(content: str) -> str | None:
|
|
42
|
+
"""Extract content between <tandem-consultation> tags."""
|
|
43
|
+
m = _TANDEM_RE.search(content)
|
|
44
|
+
return m.group(1) if m else None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def classify_tandem_roles(
|
|
48
|
+
agents_dir: Path,
|
|
49
|
+
) -> tuple[list[Path], list[Path]]:
|
|
50
|
+
"""Classify agent files into leaders and partners based on tandem sections.
|
|
51
|
+
|
|
52
|
+
Classification is based on the heading within the tandem-consultation section:
|
|
53
|
+
- "(Leader)" → leader only
|
|
54
|
+
- "(Partner)" → partner only
|
|
55
|
+
- "(Leader + Partner)" → both
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
(leaders, partners) — two lists of Path objects. An agent may appear in both.
|
|
59
|
+
"""
|
|
60
|
+
leaders: list[Path] = []
|
|
61
|
+
partners: list[Path] = []
|
|
62
|
+
|
|
63
|
+
for f in sorted(agents_dir.glob("*.md")):
|
|
64
|
+
if f.name == "README.md":
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
content = f.read_text()
|
|
68
|
+
section = _extract_tandem_section(content)
|
|
69
|
+
if section is None:
|
|
70
|
+
continue
|
|
71
|
+
|
|
72
|
+
# Match heading like "## Tandem Consultation (Leader + Partner)"
|
|
73
|
+
heading = _HEADING_RE.search(section)
|
|
74
|
+
if heading:
|
|
75
|
+
role = heading.group(1)
|
|
76
|
+
if "Leader" in role:
|
|
77
|
+
leaders.append(f)
|
|
78
|
+
if "Partner" in role:
|
|
79
|
+
partners.append(f)
|
|
80
|
+
|
|
81
|
+
return leaders, partners
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def validate_leader_tandem(path: Path) -> tuple[list[str], list[str]]:
|
|
85
|
+
"""Validate leader tandem consultation section content.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
(errors, warnings) — two lists of message strings.
|
|
89
|
+
"""
|
|
90
|
+
errors: list[str] = []
|
|
91
|
+
warnings: list[str] = []
|
|
92
|
+
content = path.read_text()
|
|
93
|
+
section = _extract_tandem_section(content)
|
|
94
|
+
|
|
95
|
+
if section is None:
|
|
96
|
+
errors.append("Missing <tandem-consultation> section")
|
|
97
|
+
return errors, warnings
|
|
98
|
+
|
|
99
|
+
stripped = section.strip()
|
|
100
|
+
if not stripped:
|
|
101
|
+
errors.append("Empty <tandem-consultation> section — no content")
|
|
102
|
+
return errors, warnings
|
|
103
|
+
|
|
104
|
+
# Workflow phase check — must reference tandem.mode
|
|
105
|
+
if "tandem.mode" not in section:
|
|
106
|
+
errors.append(
|
|
107
|
+
"Leader section must reference workflow phase availability (tandem.mode)"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# Request format template (recommended)
|
|
111
|
+
if "request format" not in section.lower():
|
|
112
|
+
warnings.append("Missing request format template in leader section")
|
|
113
|
+
|
|
114
|
+
# Graceful degradation guidance (recommended)
|
|
115
|
+
section_lower = section.lower()
|
|
116
|
+
if not any(term in section_lower for term in ("fail", "degrad", "solo")):
|
|
117
|
+
warnings.append(
|
|
118
|
+
"Missing graceful degradation guidance (what to do if consultation fails)"
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
return errors, warnings
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def validate_partner_tandem(path: Path) -> tuple[list[str], list[str]]:
|
|
125
|
+
"""Validate partner tandem consultation response guidance.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
(errors, warnings) — two lists of message strings.
|
|
129
|
+
"""
|
|
130
|
+
errors: list[str] = []
|
|
131
|
+
warnings: list[str] = []
|
|
132
|
+
content = path.read_text()
|
|
133
|
+
section = _extract_tandem_section(content)
|
|
134
|
+
|
|
135
|
+
if section is None:
|
|
136
|
+
errors.append("Missing <tandem-consultation> section")
|
|
137
|
+
return errors, warnings
|
|
138
|
+
|
|
139
|
+
# Check for required response format fields
|
|
140
|
+
missing = [
|
|
141
|
+
name for name, marker in _PARTNER_FIELDS.items() if marker not in section
|
|
142
|
+
]
|
|
143
|
+
if missing:
|
|
144
|
+
errors.append(
|
|
145
|
+
f"Partner response format missing required fields: {', '.join(missing)}"
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
return errors, warnings
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def validate_pairings_documented(
|
|
152
|
+
leader_names: set[str],
|
|
153
|
+
partner_names: set[str],
|
|
154
|
+
pairings: list[tuple[str, str]],
|
|
155
|
+
) -> tuple[list[tuple[str, str]], list[tuple[str, str]]]:
|
|
156
|
+
"""Check which ADR-0012 pairings are covered by agent tandem sections.
|
|
157
|
+
|
|
158
|
+
Directional check: verifies the leader agent is classified as a leader
|
|
159
|
+
and the partner agent is classified as a partner.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
(covered, missing) — two lists of (leader, partner) tuples.
|
|
163
|
+
"""
|
|
164
|
+
covered: list[tuple[str, str]] = []
|
|
165
|
+
missing: list[tuple[str, str]] = []
|
|
166
|
+
|
|
167
|
+
for leader, partner in pairings:
|
|
168
|
+
if leader in leader_names and partner in partner_names:
|
|
169
|
+
covered.append((leader, partner))
|
|
170
|
+
else:
|
|
171
|
+
missing.append((leader, partner))
|
|
172
|
+
|
|
173
|
+
return covered, missing
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def run(
|
|
177
|
+
root: Path, *, fix: bool = False, strict: bool = False
|
|
178
|
+
) -> ValidateReport:
|
|
179
|
+
"""Validate agent tandem awareness sections."""
|
|
180
|
+
report = ValidateReport(validator="tandem-awareness")
|
|
181
|
+
agents_dir = root / "pennyfarthing-dist" / "agents"
|
|
182
|
+
|
|
183
|
+
if not agents_dir.is_dir():
|
|
184
|
+
report.details.append("[ERROR] agents directory not found")
|
|
185
|
+
report.errors += 1
|
|
186
|
+
return report
|
|
187
|
+
|
|
188
|
+
leaders, partners = classify_tandem_roles(agents_dir)
|
|
189
|
+
|
|
190
|
+
for path in leaders:
|
|
191
|
+
file_errors, file_warnings = validate_leader_tandem(path)
|
|
192
|
+
|
|
193
|
+
for e in file_errors:
|
|
194
|
+
report.errors += 1
|
|
195
|
+
report.details.append(f"[ERROR] {path.name}: {e}")
|
|
196
|
+
|
|
197
|
+
for w in file_warnings:
|
|
198
|
+
if strict:
|
|
199
|
+
report.errors += 1
|
|
200
|
+
report.details.append(f"[ERROR] {path.name}: {w}")
|
|
201
|
+
else:
|
|
202
|
+
report.warnings += 1
|
|
203
|
+
report.details.append(f"[WARN] {path.name}: {w}")
|
|
204
|
+
|
|
205
|
+
if not file_errors:
|
|
206
|
+
report.passed += 1
|
|
207
|
+
|
|
208
|
+
for path in partners:
|
|
209
|
+
file_errors, file_warnings = validate_partner_tandem(path)
|
|
210
|
+
|
|
211
|
+
for e in file_errors:
|
|
212
|
+
report.errors += 1
|
|
213
|
+
report.details.append(f"[ERROR] {path.name}: {e}")
|
|
214
|
+
|
|
215
|
+
for w in file_warnings:
|
|
216
|
+
if strict:
|
|
217
|
+
report.errors += 1
|
|
218
|
+
report.details.append(f"[ERROR] {path.name}: {w}")
|
|
219
|
+
else:
|
|
220
|
+
report.warnings += 1
|
|
221
|
+
report.details.append(f"[WARN] {path.name}: {w}")
|
|
222
|
+
|
|
223
|
+
if not file_errors:
|
|
224
|
+
report.passed += 1
|
|
225
|
+
|
|
226
|
+
# Validate ADR-0012 pairings (directional)
|
|
227
|
+
leader_names = {f.stem for f in leaders}
|
|
228
|
+
partner_names = {f.stem for f in partners}
|
|
229
|
+
covered, missing_pairings = validate_pairings_documented(
|
|
230
|
+
leader_names, partner_names, ADR_0012_PAIRINGS
|
|
231
|
+
)
|
|
232
|
+
for leader_name, partner_name in missing_pairings:
|
|
233
|
+
report.errors += 1
|
|
234
|
+
report.details.append(
|
|
235
|
+
f"[ERROR] ADR-0012 pairing {leader_name}\u2192{partner_name} not covered "
|
|
236
|
+
f"(leader or partner missing tandem section with correct role)"
|
|
237
|
+
)
|
|
238
|
+
if covered:
|
|
239
|
+
report.passed += 1
|
|
240
|
+
|
|
241
|
+
# Detect agents with tandem section but no matching heading
|
|
242
|
+
classified_stems = leader_names | partner_names
|
|
243
|
+
for f in sorted(agents_dir.glob("*.md")):
|
|
244
|
+
if f.name == "README.md":
|
|
245
|
+
continue
|
|
246
|
+
content = f.read_text()
|
|
247
|
+
if _extract_tandem_section(content) is not None and f.stem not in classified_stems:
|
|
248
|
+
report.warnings += 1
|
|
249
|
+
report.details.append(
|
|
250
|
+
f"[WARN] {f.name}: has <tandem-consultation> section but no "
|
|
251
|
+
f"matching '## Tandem Consultation (Role)' heading"
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
return report
|
|
@@ -131,6 +131,7 @@ def validate_phased(
|
|
|
131
131
|
return errors, warnings
|
|
132
132
|
|
|
133
133
|
seen_names: set[str] = set()
|
|
134
|
+
next_refs: list[tuple[str, str]] = [] # (phase_name, next_target)
|
|
134
135
|
|
|
135
136
|
for i, phase in enumerate(phases):
|
|
136
137
|
if not isinstance(phase, dict):
|
|
@@ -228,6 +229,24 @@ def validate_phased(
|
|
|
228
229
|
f"Phase '{label}' tandem triggers must be a list"
|
|
229
230
|
)
|
|
230
231
|
|
|
232
|
+
# next: directive (optional, must be string)
|
|
233
|
+
next_target = phase.get("next")
|
|
234
|
+
if next_target is not None:
|
|
235
|
+
if not isinstance(next_target, str):
|
|
236
|
+
errors.append(
|
|
237
|
+
f"Phase '{phase_name or i}' next must be a string"
|
|
238
|
+
)
|
|
239
|
+
elif phase_name:
|
|
240
|
+
next_refs.append((phase_name, next_target))
|
|
241
|
+
|
|
242
|
+
# Cross-validate next: references point to existing phase names
|
|
243
|
+
for source_phase, target_phase in next_refs:
|
|
244
|
+
if target_phase not in seen_names:
|
|
245
|
+
errors.append(
|
|
246
|
+
f"Phase '{source_phase}' next references unknown phase: "
|
|
247
|
+
f"'{target_phase}'"
|
|
248
|
+
)
|
|
249
|
+
|
|
231
250
|
return errors, warnings
|
|
232
251
|
|
|
233
252
|
|
|
@@ -22,6 +22,7 @@ VALIDATORS = {
|
|
|
22
22
|
"agent": "pennyfarthing_scripts.validate.adapters.agent",
|
|
23
23
|
"workflow": "pennyfarthing_scripts.validate.adapters.workflow",
|
|
24
24
|
"skill-command": "pennyfarthing_scripts.validate.adapters.skill_command",
|
|
25
|
+
"tandem-awareness": "pennyfarthing_scripts.validate.adapters.tandem_awareness",
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
|
|
@@ -83,11 +84,12 @@ def validate(ctx, fix: bool, strict: bool):
|
|
|
83
84
|
|
|
84
85
|
\b
|
|
85
86
|
Validators:
|
|
86
|
-
sprint
|
|
87
|
-
schema
|
|
88
|
-
agent
|
|
89
|
-
workflow
|
|
90
|
-
skill-command
|
|
87
|
+
sprint - Sprint YAML (epics, initiatives, future, current-sprint)
|
|
88
|
+
schema - XML schema (sessions, skills, workflow steps)
|
|
89
|
+
agent - Agent definitions (required sections, model values, subagent refs)
|
|
90
|
+
workflow - Workflow definitions (phased/stepped/procedural structure)
|
|
91
|
+
skill-command - Skill registry and command files (prefix, deprecated, cross-ref)
|
|
92
|
+
tandem-awareness - Agent tandem consultation sections (ADR-0012 pairings)
|
|
91
93
|
"""
|
|
92
94
|
ctx.ensure_object(dict)
|
|
93
95
|
ctx.obj["fix"] = fix
|
|
@@ -150,3 +152,13 @@ def validate_skill_command(ctx):
|
|
|
150
152
|
_print_reports([report])
|
|
151
153
|
if not report.success:
|
|
152
154
|
raise SystemExit(1)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@validate.command("tandem-awareness")
|
|
158
|
+
@click.pass_context
|
|
159
|
+
def validate_tandem_awareness(ctx):
|
|
160
|
+
"""Validate agent tandem consultation sections (ADR-0012 pairings, roles)."""
|
|
161
|
+
report = _run_validator("tandem-awareness", fix=ctx.obj["fix"], strict=ctx.obj["strict"])
|
|
162
|
+
_print_reports([report])
|
|
163
|
+
if not report.success:
|
|
164
|
+
raise SystemExit(1)
|
|
@@ -1,156 +1,10 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
1
|
"""
|
|
3
|
-
|
|
2
|
+
Backward-compatibility shim — welcome hook moved to hooks/session_start.py.
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
For CLI: Displays ASCII art of a penny-farthing bicycle
|
|
8
|
-
For Cyclist: Sends WebSocket message to display logo and welcome
|
|
9
|
-
|
|
10
|
-
Called by Claude Code SessionStart hook.
|
|
11
|
-
|
|
12
|
-
Story: MSSCI-12409 - Hook consistency and WheelHub consolidation
|
|
4
|
+
This file will be removed in a future version.
|
|
13
5
|
"""
|
|
14
6
|
|
|
15
|
-
import
|
|
16
|
-
import os
|
|
17
|
-
import sys
|
|
18
|
-
from pathlib import Path
|
|
19
|
-
|
|
20
|
-
# Add parent directory to path for imports
|
|
21
|
-
sys.path.insert(0, str(Path(__file__).parent))
|
|
22
|
-
|
|
23
|
-
from hooks import (
|
|
24
|
-
find_project_root,
|
|
25
|
-
is_cyclist_running,
|
|
26
|
-
load_settings,
|
|
27
|
-
send_to_cyclist,
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
# Once-per-session guard
|
|
31
|
-
_welcome_shown_file: Path | None = None
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def get_welcome_lock_path(project_root: Path) -> Path:
|
|
35
|
-
"""Get path to welcome shown lock file."""
|
|
36
|
-
session_id = os.environ.get("CLAUDE_SESSION_ID", str(os.getpid()))
|
|
37
|
-
session_dir = project_root / ".session"
|
|
38
|
-
session_dir.mkdir(parents=True, exist_ok=True)
|
|
39
|
-
return session_dir / f".welcome-shown-{session_id}"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def was_welcome_shown(project_root: Path) -> bool:
|
|
43
|
-
"""Check if welcome was already shown for this session."""
|
|
44
|
-
lock_path = get_welcome_lock_path(project_root)
|
|
45
|
-
return lock_path.exists()
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def mark_welcome_shown(project_root: Path) -> None:
|
|
49
|
-
"""Mark welcome as shown for this session."""
|
|
50
|
-
lock_path = get_welcome_lock_path(project_root)
|
|
51
|
-
lock_path.touch()
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def get_project_name(project_root: Path) -> str:
|
|
55
|
-
"""Get project name from package.json or directory name."""
|
|
56
|
-
package_json = project_root / "package.json"
|
|
57
|
-
if package_json.exists():
|
|
58
|
-
try:
|
|
59
|
-
with open(package_json) as f:
|
|
60
|
-
data = json.load(f)
|
|
61
|
-
name = data.get("name")
|
|
62
|
-
if name:
|
|
63
|
-
return name
|
|
64
|
-
except (json.JSONDecodeError, OSError):
|
|
65
|
-
pass
|
|
66
|
-
|
|
67
|
-
return project_root.name
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def get_theme(project_root: Path) -> str | None:
|
|
71
|
-
"""Get current theme from settings."""
|
|
72
|
-
settings = load_settings(project_root)
|
|
73
|
-
return settings.theme
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
def display_cli_welcome(project_name: str, theme: str | None) -> None:
|
|
77
|
-
"""Display ASCII art welcome for CLI mode."""
|
|
78
|
-
print("""
|
|
79
|
-
___
|
|
80
|
-
/ \\
|
|
81
|
-
| | Welcome to
|
|
82
|
-
| | ╔═══════════════════════════════════╗
|
|
83
|
-
\\___/ ║ ╔═╗╔═╗╔╗╔╔╗╔╦═╗╔═╗╔═╗╔═╗╦╔═╗ ║
|
|
84
|
-
║ ║ ╠═╝║╣ ║║║║║║ ╠╣ ╠═╣╠╦╝ ║ ╠═╣ ║
|
|
85
|
-
║ ║ ╩ ╚═╝╝╚╝╝╚╝╩ ╩ ╩╩╚═ ╩ ╩ ╩ ║
|
|
86
|
-
╔═╩═╗ ╚═══════════════════════════════════╝
|
|
87
|
-
/ \\
|
|
88
|
-
│ O │ Agent-powered development with style
|
|
89
|
-
\\ /
|
|
90
|
-
╚═══╝
|
|
91
|
-
""")
|
|
92
|
-
|
|
93
|
-
if project_name:
|
|
94
|
-
print(f" Project: {project_name}")
|
|
95
|
-
if theme:
|
|
96
|
-
print(f" Theme: {theme}")
|
|
97
|
-
print()
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def send_cyclist_welcome(project_root: Path, project_name: str, theme: str | None) -> None:
|
|
101
|
-
"""Send welcome message to Cyclist via WebSocket API."""
|
|
102
|
-
try:
|
|
103
|
-
send_to_cyclist(
|
|
104
|
-
endpoint="/api/welcome",
|
|
105
|
-
data={
|
|
106
|
-
"project": project_name or "",
|
|
107
|
-
"theme": theme or "",
|
|
108
|
-
},
|
|
109
|
-
project_root=project_root,
|
|
110
|
-
timeout=5,
|
|
111
|
-
)
|
|
112
|
-
except Exception:
|
|
113
|
-
# Ignore errors - don't block hook
|
|
114
|
-
pass
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
def main() -> None:
|
|
118
|
-
"""Main entry point for SessionStart welcome hook."""
|
|
119
|
-
try:
|
|
120
|
-
# Read and discard stdin (required by hook protocol)
|
|
121
|
-
sys.stdin.read()
|
|
122
|
-
|
|
123
|
-
# Find project root
|
|
124
|
-
project_root = find_project_root()
|
|
125
|
-
if not project_root:
|
|
126
|
-
sys.exit(0)
|
|
127
|
-
|
|
128
|
-
# Check if welcome was already shown for this session
|
|
129
|
-
if was_welcome_shown(project_root):
|
|
130
|
-
sys.exit(0)
|
|
131
|
-
|
|
132
|
-
# Mark welcome as shown
|
|
133
|
-
mark_welcome_shown(project_root)
|
|
134
|
-
|
|
135
|
-
# Get project info
|
|
136
|
-
project_name = get_project_name(project_root)
|
|
137
|
-
theme = get_theme(project_root)
|
|
138
|
-
|
|
139
|
-
# Check if running in Cyclist
|
|
140
|
-
if is_cyclist_running(project_root):
|
|
141
|
-
# Send welcome via WebSocket API
|
|
142
|
-
send_cyclist_welcome(project_root, project_name, theme)
|
|
143
|
-
else:
|
|
144
|
-
# CLI mode - display ASCII art
|
|
145
|
-
display_cli_welcome(project_name, theme)
|
|
146
|
-
|
|
147
|
-
sys.exit(0)
|
|
148
|
-
|
|
149
|
-
except Exception as e:
|
|
150
|
-
# On error, exit silently
|
|
151
|
-
print(f"[welcome-hook] Error: {e}", file=sys.stderr)
|
|
152
|
-
sys.exit(0)
|
|
153
|
-
|
|
7
|
+
from pennyfarthing_scripts.hooks.session_start import main # noqa: F401
|
|
154
8
|
|
|
155
9
|
if __name__ == "__main__":
|
|
156
10
|
main()
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Workflow package — scale levels, phase ownership, and workflow CLI commands.
|
|
3
|
+
|
|
4
|
+
Re-exports all public symbols for backward compatibility with
|
|
5
|
+
`from pennyfarthing_scripts.workflow import ...`.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from pennyfarthing_scripts.workflow.scale import (
|
|
9
|
+
SCALE_LEVELS,
|
|
10
|
+
detect_scale_level,
|
|
11
|
+
determine_scale_level,
|
|
12
|
+
get_required_artifacts,
|
|
13
|
+
get_scale_level_info,
|
|
14
|
+
get_workflow_for_scale_level,
|
|
15
|
+
scale_level_from_story_count,
|
|
16
|
+
)
|
|
17
|
+
from pennyfarthing_scripts.workflow.state import (
|
|
18
|
+
TDD_PHASE_OWNERS,
|
|
19
|
+
TRIVIAL_PHASE_OWNERS,
|
|
20
|
+
WORKFLOW_PHASES,
|
|
21
|
+
get_phase_owner,
|
|
22
|
+
get_workflow_state,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
# Scale
|
|
27
|
+
"SCALE_LEVELS",
|
|
28
|
+
"detect_scale_level",
|
|
29
|
+
"determine_scale_level",
|
|
30
|
+
"get_required_artifacts",
|
|
31
|
+
"get_scale_level_info",
|
|
32
|
+
"get_workflow_for_scale_level",
|
|
33
|
+
"scale_level_from_story_count",
|
|
34
|
+
# State
|
|
35
|
+
"TDD_PHASE_OWNERS",
|
|
36
|
+
"TRIVIAL_PHASE_OWNERS",
|
|
37
|
+
"WORKFLOW_PHASES",
|
|
38
|
+
"get_phase_owner",
|
|
39
|
+
"get_workflow_state",
|
|
40
|
+
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|