@pennyfarthing/core 11.2.1 → 11.2.2
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 +100 -40
- package/package.json +1 -1
- package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/doctor.js +121 -28
- package/packages/core/dist/cli/commands/doctor.js.map +1 -1
- package/packages/core/dist/cli/utils/settings.d.ts +0 -4
- package/packages/core/dist/cli/utils/settings.d.ts.map +1 -1
- package/packages/core/dist/cli/utils/settings.js +31 -26
- package/packages/core/dist/cli/utils/settings.js.map +1 -1
- package/packages/core/dist/consultation/dialogue-manager.d.ts +1 -1
- package/packages/core/dist/consultation/dialogue-manager.d.ts.map +1 -1
- package/packages/core/dist/consultation/dialogue-manager.js +1 -1
- package/packages/core/dist/consultation/dialogue-manager.js.map +1 -1
- package/packages/core/dist/consultation/dialogue-manager.test.js.map +1 -1
- package/packages/core/dist/consultation/tandem-metrics.test.js.map +1 -1
- package/packages/core/dist/public/css/react.css +1 -1
- package/packages/core/dist/public/js/react/react.js +9 -9
- package/packages/core/dist/server/api/git.d.ts.map +1 -1
- package/packages/core/dist/server/api/git.js +0 -1
- package/packages/core/dist/server/api/git.js.map +1 -1
- package/packages/core/dist/server/api/index.d.ts +2 -0
- package/packages/core/dist/server/api/index.d.ts.map +1 -1
- package/packages/core/dist/server/api/index.js +2 -0
- package/packages/core/dist/server/api/index.js.map +1 -1
- package/packages/core/dist/server/api/project-info.d.ts +11 -0
- package/packages/core/dist/server/api/project-info.d.ts.map +1 -0
- package/packages/core/dist/server/api/project-info.js +18 -0
- package/packages/core/dist/server/api/project-info.js.map +1 -0
- package/packages/core/dist/server/otlp-receiver.d.ts.map +1 -1
- package/packages/core/dist/server/otlp-receiver.js +18 -1
- package/packages/core/dist/server/otlp-receiver.js.map +1 -1
- package/packages/core/dist/server/otlp-receiver.test.js +1 -1
- package/packages/core/dist/server/otlp-receiver.test.js.map +1 -1
- package/packages/core/dist/server/server.d.ts.map +1 -1
- package/packages/core/dist/server/server.js +3 -2
- 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 +8 -8
- package/packages/core/dist/server/settings.d.ts +1 -0
- package/packages/core/dist/server/settings.d.ts.map +1 -1
- package/packages/core/dist/server/settings.js +13 -0
- package/packages/core/dist/server/settings.js.map +1 -1
- package/packages/core/dist/workflow/team-lifecycle.d.ts +169 -0
- package/packages/core/dist/workflow/team-lifecycle.d.ts.map +1 -0
- package/packages/core/dist/workflow/team-lifecycle.js +217 -0
- package/packages/core/dist/workflow/team-lifecycle.js.map +1 -0
- package/packages/core/dist/workflow/team-lifecycle.test.d.ts +20 -0
- package/packages/core/dist/workflow/team-lifecycle.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/team-lifecycle.test.js +966 -0
- package/packages/core/dist/workflow/team-lifecycle.test.js.map +1 -0
- package/packages/core/dist/workflow/workflow-team-templates.test.d.ts +17 -0
- package/packages/core/dist/workflow/workflow-team-templates.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/workflow-team-templates.test.js +275 -0
- package/packages/core/dist/workflow/workflow-team-templates.test.js.map +1 -0
- package/pennyfarthing-dist/agents/dev.md +15 -2
- package/pennyfarthing-dist/agents/reviewer.md +17 -4
- package/pennyfarthing-dist/agents/sm-finish.md +1 -1
- package/pennyfarthing-dist/agents/sm-setup.md +7 -7
- package/pennyfarthing-dist/agents/sm.md +12 -12
- package/pennyfarthing-dist/agents/tea.md +2 -2
- package/pennyfarthing-dist/agents/testing-runner.md +1 -1
- package/pennyfarthing-dist/commands/pf-architect.md +1 -1
- package/pennyfarthing-dist/commands/pf-ba.md +1 -1
- package/pennyfarthing-dist/commands/pf-chore.md +2 -2
- package/pennyfarthing-dist/commands/pf-dev.md +1 -1
- package/pennyfarthing-dist/commands/pf-devops.md +1 -1
- package/pennyfarthing-dist/commands/pf-epic.md +6 -6
- package/pennyfarthing-dist/commands/pf-git.md +10 -10
- package/pennyfarthing-dist/commands/pf-health-check.md +1 -1
- package/pennyfarthing-dist/commands/pf-help.md +12 -12
- package/pennyfarthing-dist/commands/pf-orchestrator.md +1 -1
- package/pennyfarthing-dist/commands/pf-pm.md +1 -1
- package/pennyfarthing-dist/commands/pf-prime.md +8 -8
- package/pennyfarthing-dist/commands/pf-reviewer.md +1 -1
- package/pennyfarthing-dist/commands/pf-session.md +7 -7
- package/pennyfarthing-dist/commands/pf-sm.md +1 -1
- package/pennyfarthing-dist/commands/pf-sprint.md +7 -7
- package/pennyfarthing-dist/commands/pf-tea.md +1 -1
- package/pennyfarthing-dist/commands/pf-tech-writer.md +1 -1
- package/pennyfarthing-dist/commands/pf-theme.md +9 -9
- package/pennyfarthing-dist/commands/pf-ux-designer.md +1 -1
- package/pennyfarthing-dist/commands/pf-work.md +1 -1
- package/pennyfarthing-dist/guides/agent-behavior.md +70 -19
- package/pennyfarthing-dist/guides/agent-coordination.md +10 -10
- package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +6 -6
- package/pennyfarthing-dist/guides/agent-template-tactical.md +1 -1
- package/pennyfarthing-dist/guides/bell-mode.md +1 -1
- package/pennyfarthing-dist/guides/bikerack.md +10 -10
- package/pennyfarthing-dist/guides/brownfield-tools.md +24 -24
- package/pennyfarthing-dist/guides/command-tag-taxonomy.md +1 -1
- package/pennyfarthing-dist/guides/gate-schema.md +2 -2
- package/pennyfarthing-dist/guides/gates.md +3 -3
- package/pennyfarthing-dist/guides/handoff-cli.md +8 -8
- package/pennyfarthing-dist/guides/hooks.md +27 -27
- package/pennyfarthing-dist/guides/prime.md +2 -2
- package/pennyfarthing-dist/guides/reflector.md +1 -1
- package/pennyfarthing-dist/guides/skill-schema.md +6 -6
- package/pennyfarthing-dist/guides/tandem-protocol.md +3 -3
- package/pennyfarthing-dist/guides/workflow-schema.md +1 -1
- package/pennyfarthing-dist/guides/worktree-mode.md +3 -3
- package/pennyfarthing-dist/guides/xml-tags.md +8 -8
- package/pennyfarthing-dist/scripts/README.md +4 -4
- package/pennyfarthing-dist/scripts/core/agent-session.sh +2 -5
- package/pennyfarthing-dist/scripts/core/check-context.sh +1 -1
- package/pennyfarthing-dist/scripts/core/pf.sh +5 -0
- package/pennyfarthing-dist/scripts/core/phase-check-start.sh +2 -5
- package/pennyfarthing-dist/scripts/core/prime.sh +2 -25
- package/pennyfarthing-dist/scripts/git/README.md +14 -14
- package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +2 -3
- package/pennyfarthing-dist/scripts/git/git-status-all.sh +2 -3
- package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +2 -3
- package/pennyfarthing-dist/scripts/git/worktree-manager.sh +2 -4
- package/pennyfarthing-dist/scripts/hooks/README.md +6 -6
- package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +3 -3
- package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +3 -3
- package/pennyfarthing-dist/scripts/hooks/context-warning.sh +3 -3
- package/pennyfarthing-dist/scripts/hooks/cyclist-pretooluse-hook.sh +3 -3
- package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +5 -4
- package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +2 -1
- package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +3 -3
- package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +3 -3
- package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +3 -3
- package/pennyfarthing-dist/scripts/hooks/session-start.sh +3 -3
- package/pennyfarthing-dist/scripts/hooks/session-stop.sh +3 -3
- package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +3 -3
- package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +3 -4
- package/pennyfarthing-dist/scripts/lib/env.sh +34 -0
- package/pennyfarthing-dist/scripts/lib/run-pf.sh +39 -0
- package/pennyfarthing-dist/scripts/misc/README.md +1 -1
- package/pennyfarthing-dist/scripts/misc/statusline.sh +3 -3
- package/pennyfarthing-dist/scripts/sprint/README.md +21 -21
- package/pennyfarthing-dist/scripts/workflow/README.md +2 -2
- package/pennyfarthing-dist/scripts/workflow/finish-story.sh +2 -16
- package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +3 -3
- package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +3 -3
- package/pennyfarthing-dist/skills/pf-bc/examples.md +23 -23
- package/pennyfarthing-dist/skills/pf-bc/skill.md +17 -17
- package/pennyfarthing-dist/skills/pf-bc/usage.md +8 -8
- package/pennyfarthing-dist/skills/pf-jira/SKILL.md +15 -15
- package/pennyfarthing-dist/skills/pf-jira/examples.md +48 -48
- package/pennyfarthing-dist/skills/pf-jira/usage.md +15 -15
- package/pennyfarthing-dist/skills/pf-sprint/examples.md +80 -80
- package/pennyfarthing-dist/skills/pf-sprint/skill.md +35 -35
- package/pennyfarthing-dist/skills/pf-sprint/usage.md +30 -30
- package/pennyfarthing-dist/skills/pf-theme/examples.md +15 -15
- package/pennyfarthing-dist/skills/pf-theme/skill.md +6 -6
- package/pennyfarthing-dist/skills/pf-theme/usage.md +5 -5
- package/pennyfarthing-dist/skills/pf-workflow/examples.md +27 -27
- package/pennyfarthing-dist/skills/pf-workflow/skill.md +11 -11
- package/pennyfarthing-dist/skills/pf-workflow/usage.md +11 -11
- package/pennyfarthing-dist/skills/skill-registry.yaml +19 -19
- package/pennyfarthing-dist/templates/settings.local.json.template +11 -11
- package/pennyfarthing-dist/workflows/bdd-team.yaml +89 -0
- package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +1 -1
- 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/project-setup/steps/step-01-discover.md +47 -0
- package/pennyfarthing-dist/workflows/tdd-team.yaml +80 -0
- package/pennyfarthing_scripts/__init__.py +1 -1
- 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_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__/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/__pycache__/split.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bc/cli.py +2 -2
- package/pennyfarthing_scripts/bellmode_hook.py +2 -5
- 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.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 +48 -6
- package/pennyfarthing_scripts/bikerack/launcher.py +6 -6
- package/pennyfarthing_scripts/bikerack/progress_panel.py +0 -1
- package/pennyfarthing_scripts/bikerack/sprint_panel.py +1 -1
- package/pennyfarthing_scripts/bikerack/story_detail_data.py +4 -1
- package/pennyfarthing_scripts/bikerack/story_detail_screen.py +2 -1
- package/pennyfarthing_scripts/bikerack/tui.py +12 -2
- 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/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/config.py +29 -2
- package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/consultation/cli.py +3 -3
- 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/gate/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/gate/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/gate/__pycache__/validate.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/hooks_installer.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/repos.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/worktree.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/hooks_installer.py +2 -3
- package/pennyfarthing_scripts/git/status_all.py +1 -1
- package/pennyfarthing_scripts/git/worktree.py +2 -2
- package/pennyfarthing_scripts/git_group/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git_group/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/gate_file.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/gate_runner.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/marker.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/phase_check.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
- 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 +8 -3
- 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 +0 -1
- package/pennyfarthing_scripts/hooks/pre_edit_check.py +0 -1
- package/pennyfarthing_scripts/hooks/reflector_check.py +1 -2
- package/pennyfarthing_scripts/hooks/schema_validation.py +0 -1
- package/pennyfarthing_scripts/hooks/session_start.py +6 -8
- package/pennyfarthing_scripts/hooks/statusline.py +10 -1
- 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__/create.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/epic.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__/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/prime/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/heatmap.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 +3 -15
- 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/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/cli.py +121 -0
- package/pennyfarthing_scripts/sprint/loader.py +154 -3
- package/pennyfarthing_scripts/sprint/story_update.py +7 -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_2_remove_handoff_fallback.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_epic_shard_validation.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_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_resolve_gate_file_field.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_list_team.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 +26 -26
- package/pennyfarthing_scripts/tests/test_dialogue_manager.py +0 -1
- package/pennyfarthing_scripts/tests/test_workflow_list_team.py +147 -0
- 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__/team_mode.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/team_mode.py +323 -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/__pycache__/team_lifecycle.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/workflow/cli.py +15 -14
- package/pennyfarthing_scripts/workflow/state.py +0 -1
- package/pennyfarthing_scripts/workflow/team_lifecycle.py +3 -4
- package/packages/core/dist/cli/cyclist-migration.test.d.ts +0 -16
- package/packages/core/dist/cli/cyclist-migration.test.d.ts.map +0 -1
- package/packages/core/dist/cli/cyclist-migration.test.js +0 -229
- package/packages/core/dist/cli/cyclist-migration.test.js.map +0 -1
- package/packages/core/dist/scripts/benchmark-integration.d.ts +0 -182
- package/packages/core/dist/scripts/benchmark-integration.d.ts.map +0 -1
- package/packages/core/dist/scripts/benchmark-integration.js +0 -691
- package/packages/core/dist/scripts/benchmark-integration.js.map +0 -1
- package/packages/core/dist/scripts/job-fair-aggregator.d.ts +0 -150
- package/packages/core/dist/scripts/job-fair-aggregator.d.ts.map +0 -1
- package/packages/core/dist/scripts/job-fair-aggregator.js +0 -547
- package/packages/core/dist/scripts/job-fair-aggregator.js.map +0 -1
- package/packages/core/dist/scripts/theme-detail.test.d.ts.map +0 -1
- package/packages/core/dist/scripts/theme-detail.test.js.map +0 -1
- package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira.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/consultation/__pycache__/dialogue_manager.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/compat.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/migration/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.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_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_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"""Tests for Story 86-15 AC4: workflow list shows team-enabled workflows with indicator.
|
|
2
|
+
|
|
3
|
+
Story: 86-15 — Team-enabled workflow templates
|
|
4
|
+
Epic: 86 — Agent Collaboration: Tandem to Teams
|
|
5
|
+
|
|
6
|
+
Acceptance Criteria:
|
|
7
|
+
- [AC4] /workflow list shows team-enabled workflows with indicator
|
|
8
|
+
|
|
9
|
+
The `pf workflow list` command should visually distinguish team-enabled
|
|
10
|
+
workflows from regular and tandem workflows. When a workflow has `team:`
|
|
11
|
+
blocks on any phase, the output must include an indicator.
|
|
12
|
+
|
|
13
|
+
These tests verify the CLI output format. Tests should fail until
|
|
14
|
+
both the workflow templates (tdd-team.yaml, bdd-team.yaml) and the
|
|
15
|
+
workflow list team indicator are implemented.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from unittest.mock import patch
|
|
22
|
+
|
|
23
|
+
import pytest
|
|
24
|
+
import yaml
|
|
25
|
+
from click.testing import CliRunner
|
|
26
|
+
|
|
27
|
+
from pennyfarthing_scripts.cli import cli
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TestWorkflowListTeamIndicator:
|
|
31
|
+
"""Tests for team indicator in workflow list output (AC4)."""
|
|
32
|
+
|
|
33
|
+
@pytest.fixture
|
|
34
|
+
def runner(self) -> CliRunner:
|
|
35
|
+
return CliRunner()
|
|
36
|
+
|
|
37
|
+
def test_workflow_list_shows_team_workflows(self, runner: CliRunner) -> None:
|
|
38
|
+
"""AC4: workflow list should include tdd-team and bdd-team."""
|
|
39
|
+
result = runner.invoke(cli, ["workflow", "list"])
|
|
40
|
+
assert result.exit_code == 0
|
|
41
|
+
assert "tdd-team" in result.output, "tdd-team workflow should appear in list"
|
|
42
|
+
assert "bdd-team" in result.output, "bdd-team workflow should appear in list"
|
|
43
|
+
|
|
44
|
+
def test_workflow_list_has_team_indicator_for_tdd_team(
|
|
45
|
+
self, runner: CliRunner
|
|
46
|
+
) -> None:
|
|
47
|
+
"""AC4: tdd-team should have a team indicator in workflow list."""
|
|
48
|
+
result = runner.invoke(cli, ["workflow", "list"])
|
|
49
|
+
assert result.exit_code == 0
|
|
50
|
+
|
|
51
|
+
# Find the tdd-team row in the markdown table
|
|
52
|
+
tdd_team_line = None
|
|
53
|
+
for line in result.output.splitlines():
|
|
54
|
+
if "tdd-team" in line and "|" in line:
|
|
55
|
+
tdd_team_line = line
|
|
56
|
+
break
|
|
57
|
+
|
|
58
|
+
assert tdd_team_line is not None, "tdd-team should appear as a table row"
|
|
59
|
+
|
|
60
|
+
# The row should have a team indicator — could be a column value,
|
|
61
|
+
# emoji, or tag that distinguishes it from non-team workflows
|
|
62
|
+
line_lower = tdd_team_line.lower()
|
|
63
|
+
assert (
|
|
64
|
+
"team" in line_lower
|
|
65
|
+
), "tdd-team row should contain a 'team' indicator"
|
|
66
|
+
|
|
67
|
+
def test_workflow_list_has_team_indicator_for_bdd_team(
|
|
68
|
+
self, runner: CliRunner
|
|
69
|
+
) -> None:
|
|
70
|
+
"""AC4: bdd-team should have a team indicator in workflow list."""
|
|
71
|
+
result = runner.invoke(cli, ["workflow", "list"])
|
|
72
|
+
assert result.exit_code == 0
|
|
73
|
+
|
|
74
|
+
bdd_team_line = None
|
|
75
|
+
for line in result.output.splitlines():
|
|
76
|
+
if "bdd-team" in line and "|" in line:
|
|
77
|
+
bdd_team_line = line
|
|
78
|
+
break
|
|
79
|
+
|
|
80
|
+
assert bdd_team_line is not None, "bdd-team should appear as a table row"
|
|
81
|
+
|
|
82
|
+
line_lower = bdd_team_line.lower()
|
|
83
|
+
assert (
|
|
84
|
+
"team" in line_lower
|
|
85
|
+
), "bdd-team row should contain a 'team' indicator"
|
|
86
|
+
|
|
87
|
+
def test_non_team_workflows_lack_team_indicator(
|
|
88
|
+
self, runner: CliRunner
|
|
89
|
+
) -> None:
|
|
90
|
+
"""AC4: Regular workflows should NOT have team indicator."""
|
|
91
|
+
result = runner.invoke(cli, ["workflow", "list"])
|
|
92
|
+
assert result.exit_code == 0
|
|
93
|
+
|
|
94
|
+
for line in result.output.splitlines():
|
|
95
|
+
if "|" not in line:
|
|
96
|
+
continue
|
|
97
|
+
# Skip header, separator, and team workflows
|
|
98
|
+
if "tdd-team" in line or "bdd-team" in line:
|
|
99
|
+
continue
|
|
100
|
+
if "Workflow" in line or "---" in line:
|
|
101
|
+
continue
|
|
102
|
+
|
|
103
|
+
# Check columns (split by |)
|
|
104
|
+
cols = [c.strip() for c in line.split("|")]
|
|
105
|
+
name_col = cols[1] if len(cols) > 1 else ""
|
|
106
|
+
|
|
107
|
+
# tdd-tandem and bdd-tandem are tandem, not team
|
|
108
|
+
if "tandem" in name_col:
|
|
109
|
+
continue
|
|
110
|
+
|
|
111
|
+
# Plain workflows like tdd, trivial, bdd should not show team
|
|
112
|
+
# in their mode/indicator columns (but "team" might appear
|
|
113
|
+
# in description text, which is fine — we check indicator columns)
|
|
114
|
+
# The name itself (e.g., "tdd") doesn't contain "team", confirming
|
|
115
|
+
# no false positives in the name column
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class TestWorkflowListTeamColumnOrTag:
|
|
119
|
+
"""Verify the team indicator mechanism in workflow list."""
|
|
120
|
+
|
|
121
|
+
@pytest.fixture
|
|
122
|
+
def runner(self) -> CliRunner:
|
|
123
|
+
return CliRunner()
|
|
124
|
+
|
|
125
|
+
def test_workflow_list_distinguishes_team_from_tandem(
|
|
126
|
+
self, runner: CliRunner
|
|
127
|
+
) -> None:
|
|
128
|
+
"""Team workflows should be distinguishable from tandem workflows."""
|
|
129
|
+
result = runner.invoke(cli, ["workflow", "list"])
|
|
130
|
+
assert result.exit_code == 0
|
|
131
|
+
|
|
132
|
+
tdd_team_line = None
|
|
133
|
+
tdd_tandem_line = None
|
|
134
|
+
for line in result.output.splitlines():
|
|
135
|
+
if "tdd-team" in line and "|" in line:
|
|
136
|
+
tdd_team_line = line
|
|
137
|
+
elif "tdd-tandem" in line and "|" in line:
|
|
138
|
+
tdd_tandem_line = line
|
|
139
|
+
|
|
140
|
+
assert tdd_team_line is not None, "tdd-team should be in the list"
|
|
141
|
+
assert tdd_tandem_line is not None, "tdd-tandem should be in the list"
|
|
142
|
+
|
|
143
|
+
# They should have different indicators — team vs tandem
|
|
144
|
+
# At minimum, the descriptions should be distinct
|
|
145
|
+
assert tdd_team_line != tdd_tandem_line, (
|
|
146
|
+
"tdd-team and tdd-tandem should have different rows"
|
|
147
|
+
)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/pennyfarthing_scripts/validate/adapters/__pycache__/tandem_awareness.cpython-314.pyc
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"""Team-mode protocol validator adapter.
|
|
2
|
+
|
|
3
|
+
Validates that agent definitions include proper team-mode sections
|
|
4
|
+
for Claude Code native Agent Teams integration.
|
|
5
|
+
|
|
6
|
+
Story: MSSCI-15109 (86-14)
|
|
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 <team-mode> section content
|
|
17
|
+
_TEAM_MODE_RE = re.compile(r"<team-mode>(.*?)</team-mode>", re.DOTALL)
|
|
18
|
+
|
|
19
|
+
# Required topics in the behavior guide's <team-mode> section
|
|
20
|
+
_BEHAVIOR_GUIDE_TOPICS = {
|
|
21
|
+
"team_creation": ["TeamCreate", "team creation", "create team"],
|
|
22
|
+
"spawning": ["spawn", "Task tool", "teammate"],
|
|
23
|
+
"sendmessage": ["SendMessage"],
|
|
24
|
+
"cleanup": ["cleanup", "TeamDelete", "shut down", "shutdown"],
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# Required lead agent topics
|
|
28
|
+
_LEAD_TOPICS = {
|
|
29
|
+
"phase_entry": ["phase entry", "phase start", "on phase"],
|
|
30
|
+
"spawn_per_yaml": ["spawn", "teammates", "workflow YAML", "YAML"],
|
|
31
|
+
"shutdown_before_exit": ["shut down", "shutdown", "before exit", "before handoff"],
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# Required teammate awareness topics
|
|
35
|
+
_TEAMMATE_TOPICS = {
|
|
36
|
+
"identity": ["teammate", "not lead", "not the lead"],
|
|
37
|
+
"sendmessage": ["SendMessage"],
|
|
38
|
+
"idle": ["idle", "go idle"],
|
|
39
|
+
"shutdown_response": ["shutdown", "shutdown_response", "shutdown request"],
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def extract_team_mode_section(content: str) -> str | None:
|
|
44
|
+
"""Extract content between <team-mode> tags."""
|
|
45
|
+
m = _TEAM_MODE_RE.search(content)
|
|
46
|
+
return m.group(1) if m else None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def validate_behavior_guide_team_mode(
|
|
50
|
+
path: Path,
|
|
51
|
+
) -> tuple[list[str], list[str]]:
|
|
52
|
+
"""Validate the behavior guide has a <team-mode> section with required topics.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
(errors, warnings) — two lists of message strings.
|
|
56
|
+
"""
|
|
57
|
+
errors: list[str] = []
|
|
58
|
+
warnings: list[str] = []
|
|
59
|
+
content = path.read_text()
|
|
60
|
+
section = extract_team_mode_section(content)
|
|
61
|
+
|
|
62
|
+
if section is None:
|
|
63
|
+
errors.append("Missing <team-mode> section in behavior guide")
|
|
64
|
+
return errors, warnings
|
|
65
|
+
|
|
66
|
+
stripped = section.strip()
|
|
67
|
+
if not stripped:
|
|
68
|
+
errors.append("Empty <team-mode> section — no content")
|
|
69
|
+
return errors, warnings
|
|
70
|
+
|
|
71
|
+
# Check required topics
|
|
72
|
+
for topic_name, keywords in _BEHAVIOR_GUIDE_TOPICS.items():
|
|
73
|
+
if not any(kw.lower() in section.lower() for kw in keywords):
|
|
74
|
+
errors.append(
|
|
75
|
+
f"<team-mode> section missing required topic: {topic_name} "
|
|
76
|
+
f"(expected one of: {', '.join(keywords)})"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return errors, warnings
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def validate_lead_agent_team_mode(
|
|
83
|
+
path: Path,
|
|
84
|
+
) -> tuple[list[str], list[str]]:
|
|
85
|
+
"""Validate lead agent has team-mode behavior section.
|
|
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_team_mode_section(content)
|
|
94
|
+
|
|
95
|
+
if section is None:
|
|
96
|
+
errors.append(f"Missing <team-mode> section in lead agent {path.name}")
|
|
97
|
+
return errors, warnings
|
|
98
|
+
|
|
99
|
+
stripped = section.strip()
|
|
100
|
+
if not stripped:
|
|
101
|
+
errors.append(f"Empty <team-mode> section in lead agent {path.name}")
|
|
102
|
+
return errors, warnings
|
|
103
|
+
|
|
104
|
+
section_lower = section.lower()
|
|
105
|
+
|
|
106
|
+
# Must reference lead role
|
|
107
|
+
if "lead" not in section_lower:
|
|
108
|
+
errors.append("Lead agent <team-mode> section must reference 'lead' role")
|
|
109
|
+
|
|
110
|
+
# Check lead-specific topics
|
|
111
|
+
for topic_name, keywords in _LEAD_TOPICS.items():
|
|
112
|
+
if not any(kw.lower() in section_lower for kw in keywords):
|
|
113
|
+
warnings.append(
|
|
114
|
+
f"Lead agent <team-mode> missing topic: {topic_name} "
|
|
115
|
+
f"(expected one of: {', '.join(keywords)})"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
return errors, warnings
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def validate_teammate_awareness(
|
|
122
|
+
content: str,
|
|
123
|
+
) -> tuple[list[str], list[str]]:
|
|
124
|
+
"""Validate teammate behavior content in team-mode section.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
(errors, warnings) — two lists of message strings.
|
|
128
|
+
"""
|
|
129
|
+
errors: list[str] = []
|
|
130
|
+
warnings: list[str] = []
|
|
131
|
+
section = extract_team_mode_section(content)
|
|
132
|
+
|
|
133
|
+
if section is None:
|
|
134
|
+
errors.append("Missing <team-mode> section for teammate awareness")
|
|
135
|
+
return errors, warnings
|
|
136
|
+
|
|
137
|
+
section_lower = section.lower()
|
|
138
|
+
|
|
139
|
+
# Check teammate-specific topics
|
|
140
|
+
for topic_name, keywords in _TEAMMATE_TOPICS.items():
|
|
141
|
+
if not any(kw.lower() in section_lower for kw in keywords):
|
|
142
|
+
errors.append(
|
|
143
|
+
f"Teammate awareness missing topic: {topic_name} "
|
|
144
|
+
f"(expected one of: {', '.join(keywords)})"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return errors, warnings
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def validate_exit_protocol_team_branch(
|
|
151
|
+
content: str,
|
|
152
|
+
) -> tuple[list[str], list[str]]:
|
|
153
|
+
"""Validate exit protocol has team-mode cleanup branch.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
(errors, warnings) — two lists of message strings.
|
|
157
|
+
"""
|
|
158
|
+
errors: list[str] = []
|
|
159
|
+
warnings: list[str] = []
|
|
160
|
+
|
|
161
|
+
# Look for team cleanup in exit protocol section
|
|
162
|
+
# The exit protocol is in <agent-exit-protocol> tags
|
|
163
|
+
exit_re = re.compile(
|
|
164
|
+
r"<agent-exit-protocol>(.*?)</agent-exit-protocol>", re.DOTALL
|
|
165
|
+
)
|
|
166
|
+
exit_match = exit_re.search(content)
|
|
167
|
+
|
|
168
|
+
if exit_match is None:
|
|
169
|
+
errors.append("Missing <agent-exit-protocol> section")
|
|
170
|
+
return errors, warnings
|
|
171
|
+
|
|
172
|
+
exit_content = exit_match.group(1).lower()
|
|
173
|
+
|
|
174
|
+
# Must reference team cleanup
|
|
175
|
+
team_cleanup_terms = ["team", "teamdelete", "cleanup team", "shut down teammate"]
|
|
176
|
+
if not any(term in exit_content for term in team_cleanup_terms):
|
|
177
|
+
errors.append(
|
|
178
|
+
"Exit protocol missing team-mode branch "
|
|
179
|
+
"(must reference team cleanup before handoff)"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
return errors, warnings
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def validate_communication_protocols(
|
|
186
|
+
content: str,
|
|
187
|
+
) -> tuple[list[str], list[str]]:
|
|
188
|
+
"""Validate that reflector markers and SendMessage are properly documented.
|
|
189
|
+
|
|
190
|
+
Reflector markers for inter-phase handoff (unchanged).
|
|
191
|
+
SendMessage for intra-phase teammate communication (new).
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
(errors, warnings) — two lists of message strings.
|
|
195
|
+
"""
|
|
196
|
+
errors: list[str] = []
|
|
197
|
+
warnings: list[str] = []
|
|
198
|
+
|
|
199
|
+
# Reflector section must still exist
|
|
200
|
+
if "<critical>" not in content or "CYCLIST" not in content:
|
|
201
|
+
errors.append("Reflector/CYCLIST marker section missing — must remain for inter-phase handoff")
|
|
202
|
+
|
|
203
|
+
# Team-mode section must reference SendMessage for intra-phase
|
|
204
|
+
section = extract_team_mode_section(content)
|
|
205
|
+
if section is not None:
|
|
206
|
+
if "SendMessage" not in section:
|
|
207
|
+
errors.append(
|
|
208
|
+
"<team-mode> must reference SendMessage for intra-phase communication"
|
|
209
|
+
)
|
|
210
|
+
# Should distinguish inter-phase (markers) from intra-phase (SendMessage)
|
|
211
|
+
if "inter-phase" not in section.lower() and "intra-phase" not in section.lower():
|
|
212
|
+
warnings.append(
|
|
213
|
+
"<team-mode> should distinguish inter-phase (markers) "
|
|
214
|
+
"from intra-phase (SendMessage) communication"
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
return errors, warnings
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def classify_team_mode_agents(
|
|
221
|
+
agents_dir: Path,
|
|
222
|
+
) -> tuple[list[Path], list[Path]]:
|
|
223
|
+
"""Classify agent files into lead agents and all agents with team-mode.
|
|
224
|
+
|
|
225
|
+
Lead agents are those whose <team-mode> section mentions 'lead'.
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
(lead_agents, all_team_mode_agents)
|
|
229
|
+
"""
|
|
230
|
+
leads: list[Path] = []
|
|
231
|
+
all_tm: list[Path] = []
|
|
232
|
+
|
|
233
|
+
for f in sorted(agents_dir.glob("*.md")):
|
|
234
|
+
if f.name == "README.md":
|
|
235
|
+
continue
|
|
236
|
+
|
|
237
|
+
content = f.read_text()
|
|
238
|
+
section = extract_team_mode_section(content)
|
|
239
|
+
if section is None:
|
|
240
|
+
continue
|
|
241
|
+
|
|
242
|
+
all_tm.append(f)
|
|
243
|
+
if "lead" in section.lower():
|
|
244
|
+
leads.append(f)
|
|
245
|
+
|
|
246
|
+
return leads, all_tm
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def run(
|
|
250
|
+
root: Path, *, fix: bool = False, strict: bool = False
|
|
251
|
+
) -> ValidateReport:
|
|
252
|
+
"""Validate agent team-mode protocol sections."""
|
|
253
|
+
report = ValidateReport(validator="team-mode")
|
|
254
|
+
|
|
255
|
+
# Validate behavior guide
|
|
256
|
+
guides_dir = root / "pennyfarthing-dist" / "guides"
|
|
257
|
+
behavior_guide = guides_dir / "agent-behavior.md"
|
|
258
|
+
if behavior_guide.is_file():
|
|
259
|
+
file_errors, file_warnings = validate_behavior_guide_team_mode(behavior_guide)
|
|
260
|
+
for e in file_errors:
|
|
261
|
+
report.errors += 1
|
|
262
|
+
report.details.append(f"[ERROR] agent-behavior.md: {e}")
|
|
263
|
+
for w in file_warnings:
|
|
264
|
+
if strict:
|
|
265
|
+
report.errors += 1
|
|
266
|
+
report.details.append(f"[ERROR] agent-behavior.md: {w}")
|
|
267
|
+
else:
|
|
268
|
+
report.warnings += 1
|
|
269
|
+
report.details.append(f"[WARN] agent-behavior.md: {w}")
|
|
270
|
+
if not file_errors:
|
|
271
|
+
report.passed += 1
|
|
272
|
+
|
|
273
|
+
# Validate exit protocol team branch
|
|
274
|
+
guide_content = behavior_guide.read_text()
|
|
275
|
+
exit_errors, exit_warnings = validate_exit_protocol_team_branch(guide_content)
|
|
276
|
+
for e in exit_errors:
|
|
277
|
+
report.errors += 1
|
|
278
|
+
report.details.append(f"[ERROR] agent-behavior.md exit: {e}")
|
|
279
|
+
for w in exit_warnings:
|
|
280
|
+
if strict:
|
|
281
|
+
report.errors += 1
|
|
282
|
+
report.details.append(f"[ERROR] agent-behavior.md exit: {w}")
|
|
283
|
+
else:
|
|
284
|
+
report.warnings += 1
|
|
285
|
+
report.details.append(f"[WARN] agent-behavior.md exit: {w}")
|
|
286
|
+
|
|
287
|
+
# Validate communication protocol distinction
|
|
288
|
+
comm_errors, comm_warnings = validate_communication_protocols(guide_content)
|
|
289
|
+
for e in comm_errors:
|
|
290
|
+
report.errors += 1
|
|
291
|
+
report.details.append(f"[ERROR] agent-behavior.md comm: {e}")
|
|
292
|
+
for w in comm_warnings:
|
|
293
|
+
if strict:
|
|
294
|
+
report.errors += 1
|
|
295
|
+
report.details.append(f"[ERROR] agent-behavior.md comm: {w}")
|
|
296
|
+
else:
|
|
297
|
+
report.warnings += 1
|
|
298
|
+
report.details.append(f"[WARN] agent-behavior.md comm: {w}")
|
|
299
|
+
else:
|
|
300
|
+
report.errors += 1
|
|
301
|
+
report.details.append("[ERROR] agent-behavior.md guide not found")
|
|
302
|
+
|
|
303
|
+
# Validate lead agents
|
|
304
|
+
agents_dir = root / "pennyfarthing-dist" / "agents"
|
|
305
|
+
if agents_dir.is_dir():
|
|
306
|
+
for agent_name in ("dev", "reviewer"):
|
|
307
|
+
agent_path = agents_dir / f"{agent_name}.md"
|
|
308
|
+
if agent_path.is_file():
|
|
309
|
+
lead_errors, lead_warnings = validate_lead_agent_team_mode(agent_path)
|
|
310
|
+
for e in lead_errors:
|
|
311
|
+
report.errors += 1
|
|
312
|
+
report.details.append(f"[ERROR] {agent_name}.md: {e}")
|
|
313
|
+
for w in lead_warnings:
|
|
314
|
+
if strict:
|
|
315
|
+
report.errors += 1
|
|
316
|
+
report.details.append(f"[ERROR] {agent_name}.md: {w}")
|
|
317
|
+
else:
|
|
318
|
+
report.warnings += 1
|
|
319
|
+
report.details.append(f"[WARN] {agent_name}.md: {w}")
|
|
320
|
+
if not lead_errors:
|
|
321
|
+
report.passed += 1
|
|
322
|
+
|
|
323
|
+
return report
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -16,6 +16,8 @@ Usage:
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
+
from datetime import UTC
|
|
20
|
+
|
|
19
21
|
import click
|
|
20
22
|
|
|
21
23
|
|
|
@@ -141,7 +143,6 @@ def workflow_list_cmd():
|
|
|
141
143
|
|
|
142
144
|
Shows a markdown table with type, phases/steps, modes, and descriptions.
|
|
143
145
|
"""
|
|
144
|
-
import yaml as yaml_mod
|
|
145
146
|
|
|
146
147
|
from pennyfarthing_scripts.workflow.helpers import (
|
|
147
148
|
count_steps,
|
|
@@ -353,7 +354,7 @@ def workflow_start_cmd(name: str, mode: str | None):
|
|
|
353
354
|
Arguments:
|
|
354
355
|
NAME - Workflow name (e.g., architecture, release)
|
|
355
356
|
"""
|
|
356
|
-
from datetime import datetime
|
|
357
|
+
from datetime import datetime
|
|
357
358
|
|
|
358
359
|
from pennyfarthing_scripts.common.config import get_project_root
|
|
359
360
|
from pennyfarthing_scripts.workflow.helpers import (
|
|
@@ -444,7 +445,7 @@ def workflow_start_cmd(name: str, mode: str | None):
|
|
|
444
445
|
return
|
|
445
446
|
|
|
446
447
|
# Create session file
|
|
447
|
-
now = datetime.now(
|
|
448
|
+
now = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
448
449
|
wf_agent = wf.get("agent", "pm")
|
|
449
450
|
wf_desc = wf.get("description", "-")
|
|
450
451
|
|
|
@@ -516,7 +517,7 @@ def workflow_resume_cmd(name: str | None):
|
|
|
516
517
|
Arguments:
|
|
517
518
|
NAME - Workflow name (auto-detects from active session if omitted)
|
|
518
519
|
"""
|
|
519
|
-
from datetime import datetime
|
|
520
|
+
from datetime import datetime
|
|
520
521
|
|
|
521
522
|
from pennyfarthing_scripts.common.config import get_project_root
|
|
522
523
|
from pennyfarthing_scripts.workflow.helpers import (
|
|
@@ -601,7 +602,7 @@ def workflow_resume_cmd(name: str | None):
|
|
|
601
602
|
raise SystemExit(1)
|
|
602
603
|
|
|
603
604
|
# Update last updated timestamp
|
|
604
|
-
now = datetime.now(
|
|
605
|
+
now = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
605
606
|
import re
|
|
606
607
|
|
|
607
608
|
updated_content = re.sub(
|
|
@@ -788,7 +789,7 @@ def workflow_fix_phase_cmd(story_id: str, target_phase: str, dry_run: bool):
|
|
|
788
789
|
TARGET_PHASE - Target phase to set (e.g., review, approved, finish)
|
|
789
790
|
"""
|
|
790
791
|
import re
|
|
791
|
-
from datetime import datetime
|
|
792
|
+
from datetime import datetime
|
|
792
793
|
|
|
793
794
|
from pennyfarthing_scripts.common.config import get_project_root
|
|
794
795
|
from pennyfarthing_scripts.workflow.helpers import (
|
|
@@ -849,17 +850,17 @@ def workflow_fix_phase_cmd(story_id: str, target_phase: str, dry_run: bool):
|
|
|
849
850
|
# Find indices
|
|
850
851
|
try:
|
|
851
852
|
current_idx = phases.index(current_phase)
|
|
852
|
-
except ValueError:
|
|
853
|
+
except ValueError as err:
|
|
853
854
|
click.echo(f"Error: Current phase '{current_phase}' not found in {workflow_name} workflow", err=True)
|
|
854
855
|
click.echo(f"Valid phases: {', '.join(phases)}", err=True)
|
|
855
|
-
raise SystemExit(1)
|
|
856
|
+
raise SystemExit(1) from err
|
|
856
857
|
|
|
857
858
|
try:
|
|
858
859
|
target_idx = phases.index(target_phase)
|
|
859
|
-
except ValueError:
|
|
860
|
+
except ValueError as err:
|
|
860
861
|
click.echo(f"Error: Target phase '{target_phase}' not found in {workflow_name} workflow", err=True)
|
|
861
862
|
click.echo(f"Valid phases: {', '.join(phases)}", err=True)
|
|
862
|
-
raise SystemExit(1)
|
|
863
|
+
raise SystemExit(1) from err
|
|
863
864
|
|
|
864
865
|
if target_idx <= current_idx:
|
|
865
866
|
click.echo(f"Error: Target phase '{target_phase}' is not ahead of current phase '{current_phase}'", err=True)
|
|
@@ -867,7 +868,7 @@ def workflow_fix_phase_cmd(story_id: str, target_phase: str, dry_run: bool):
|
|
|
867
868
|
raise SystemExit(1)
|
|
868
869
|
|
|
869
870
|
# Calculate transitions
|
|
870
|
-
now = datetime.now(
|
|
871
|
+
now = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
871
872
|
click.echo("")
|
|
872
873
|
click.echo("Transitions needed:")
|
|
873
874
|
|
|
@@ -909,7 +910,7 @@ def workflow_fix_phase_cmd(story_id: str, target_phase: str, dry_run: bool):
|
|
|
909
910
|
|
|
910
911
|
# Build handoff history additions
|
|
911
912
|
handoff_lines = []
|
|
912
|
-
for
|
|
913
|
+
for _from_phase, _to_phase, from_agent, to_agent, gate in transitions:
|
|
913
914
|
handoff_lines.append(f"| {from_agent} | {to_agent} | {gate} | PASSED | {now} |")
|
|
914
915
|
|
|
915
916
|
# Insert handoff rows after the last PASSED/FAILED row
|
|
@@ -951,7 +952,7 @@ def workflow_complete_step_cmd(name: str | None, step_override: int | None):
|
|
|
951
952
|
NAME - Workflow name (auto-detects from session if omitted)
|
|
952
953
|
"""
|
|
953
954
|
import re
|
|
954
|
-
from datetime import datetime
|
|
955
|
+
from datetime import datetime
|
|
955
956
|
|
|
956
957
|
from pennyfarthing_scripts.common.config import get_project_root
|
|
957
958
|
from pennyfarthing_scripts.workflow.helpers import (
|
|
@@ -1036,7 +1037,7 @@ def workflow_complete_step_cmd(name: str | None, step_override: int | None):
|
|
|
1036
1037
|
new_status = "completed" if completed_count >= step_count else "in_progress"
|
|
1037
1038
|
|
|
1038
1039
|
# Update session file
|
|
1039
|
-
now = datetime.now(
|
|
1040
|
+
now = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
1040
1041
|
|
|
1041
1042
|
content = re.sub(
|
|
1042
1043
|
r"^- \*\*Current Step:\*\*.*$",
|
|
@@ -10,11 +10,10 @@ Python port of packages/core/dist/workflow/team-lifecycle.js.
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
-
from datetime import
|
|
13
|
+
from datetime import UTC, datetime
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
from typing import Any
|
|
16
16
|
|
|
17
|
-
|
|
18
17
|
# =============================================================================
|
|
19
18
|
# In-memory registries
|
|
20
19
|
# =============================================================================
|
|
@@ -61,7 +60,7 @@ async def create_team(
|
|
|
61
60
|
"storyId": story_id,
|
|
62
61
|
"phase": phase["name"],
|
|
63
62
|
"teammates": [],
|
|
64
|
-
"createdAt": datetime.now(
|
|
63
|
+
"createdAt": datetime.now(UTC).isoformat(),
|
|
65
64
|
}
|
|
66
65
|
|
|
67
66
|
if adapter:
|
|
@@ -213,7 +212,7 @@ def acquire_sidecar_lock(
|
|
|
213
212
|
lock: dict[str, Any] = {
|
|
214
213
|
"lockPath": f"{file_path}.lock",
|
|
215
214
|
"storyId": story_id,
|
|
216
|
-
"acquiredAt": datetime.now(
|
|
215
|
+
"acquiredAt": datetime.now(UTC).isoformat(),
|
|
217
216
|
}
|
|
218
217
|
_sidecar_locks[file_path] = lock
|
|
219
218
|
return {"success": True, "data": lock}
|