@pennyfarthing/core 11.0.0 → 11.1.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 +81 -23
- package/package.json +1 -1
- package/packages/core/dist/cli/utils/010-detect-remove-old-packages.test.d.ts +20 -0
- package/packages/core/dist/cli/utils/010-detect-remove-old-packages.test.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/010-detect-remove-old-packages.test.js +278 -0
- package/packages/core/dist/cli/utils/010-detect-remove-old-packages.test.js.map +1 -0
- package/packages/core/dist/cli/utils/constants.d.ts +8 -2
- package/packages/core/dist/cli/utils/constants.d.ts.map +1 -1
- package/packages/core/dist/cli/utils/constants.js +4 -1
- package/packages/core/dist/cli/utils/constants.js.map +1 -1
- package/packages/core/dist/cli/utils/constants.test.d.ts +10 -0
- package/packages/core/dist/cli/utils/constants.test.d.ts.map +1 -0
- package/packages/core/dist/cli/utils/constants.test.js +38 -0
- package/packages/core/dist/cli/utils/constants.test.js.map +1 -0
- package/packages/core/dist/consultation/consultation-protocol.d.ts +139 -0
- package/packages/core/dist/consultation/consultation-protocol.d.ts.map +1 -0
- package/packages/core/dist/consultation/consultation-protocol.js +178 -0
- package/packages/core/dist/consultation/consultation-protocol.js.map +1 -0
- package/packages/core/dist/consultation/consultation-protocol.test.d.ts +20 -0
- package/packages/core/dist/consultation/consultation-protocol.test.d.ts.map +1 -0
- package/packages/core/dist/consultation/consultation-protocol.test.js +474 -0
- package/packages/core/dist/consultation/consultation-protocol.test.js.map +1 -0
- package/packages/core/dist/consultation/dialogue-manager.d.ts +75 -0
- package/packages/core/dist/consultation/dialogue-manager.d.ts.map +1 -0
- package/packages/core/dist/consultation/dialogue-manager.js +334 -0
- package/packages/core/dist/consultation/dialogue-manager.js.map +1 -0
- package/packages/core/dist/consultation/dialogue-manager.test.d.ts +19 -0
- package/packages/core/dist/consultation/dialogue-manager.test.d.ts.map +1 -0
- package/packages/core/dist/consultation/dialogue-manager.test.js +444 -0
- package/packages/core/dist/consultation/dialogue-manager.test.js.map +1 -0
- package/packages/core/dist/public/js/react/react.js +3 -3
- package/packages/core/dist/scripts/theme-detail.test.d.ts +10 -0
- package/packages/core/dist/scripts/theme-detail.test.js +199 -0
- package/packages/core/dist/server/api/git.d.ts +13 -1
- package/packages/core/dist/server/api/git.d.ts.map +1 -1
- package/packages/core/dist/server/api/git.js +53 -34
- package/packages/core/dist/server/api/git.js.map +1 -1
- package/packages/core/dist/server/api/health-score.d.ts.map +1 -1
- package/packages/core/dist/server/api/health-score.js +25 -1
- package/packages/core/dist/server/api/health-score.js.map +1 -1
- package/packages/core/dist/server/api/settings.d.ts.map +1 -1
- package/packages/core/dist/server/api/settings.js +63 -1
- package/packages/core/dist/server/api/settings.js.map +1 -1
- package/packages/core/dist/server/api/theme-agents.d.ts.map +1 -1
- package/packages/core/dist/server/api/theme-agents.js +61 -0
- package/packages/core/dist/server/api/theme-agents.js.map +1 -1
- package/packages/core/dist/server/server.d.ts.map +1 -1
- package/packages/core/dist/server/server.js +17 -12
- package/packages/core/dist/server/server.js.map +1 -1
- package/packages/core/dist/shared/skill-search.test.js +2 -2
- package/packages/core/dist/workflow/gate-file-validation.d.ts +49 -0
- package/packages/core/dist/workflow/gate-file-validation.d.ts.map +1 -0
- package/packages/core/dist/workflow/gate-file-validation.js +157 -0
- package/packages/core/dist/workflow/gate-file-validation.js.map +1 -0
- package/packages/core/dist/workflow/gate-file-validation.test.d.ts +19 -0
- package/packages/core/dist/workflow/gate-file-validation.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/gate-file-validation.test.js +536 -0
- package/packages/core/dist/workflow/gate-file-validation.test.js.map +1 -0
- package/packages/core/dist/workflow/gate-schema-validation.test.d.ts +14 -0
- package/packages/core/dist/workflow/gate-schema-validation.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/gate-schema-validation.test.js +339 -0
- package/packages/core/dist/workflow/gate-schema-validation.test.js.map +1 -0
- package/packages/core/dist/workflow/handoff.js +2 -2
- package/packages/core/dist/workflow/handoff.js.map +1 -1
- package/packages/core/dist/workflow/handoff.test.js +16 -0
- package/packages/core/dist/workflow/handoff.test.js.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.d.ts +4 -2
- package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.js +43 -8
- package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
- package/pennyfarthing-dist/agents/README.md +6 -14
- package/pennyfarthing-dist/agents/architect.md +43 -29
- package/pennyfarthing-dist/agents/ba.md +30 -29
- package/pennyfarthing-dist/agents/dev.md +32 -43
- package/pennyfarthing-dist/agents/devops.md +57 -21
- package/pennyfarthing-dist/agents/orchestrator.md +3 -10
- package/pennyfarthing-dist/agents/pm.md +45 -31
- package/pennyfarthing-dist/agents/reviewer.md +20 -66
- package/pennyfarthing-dist/agents/sm-setup.md +2 -2
- package/pennyfarthing-dist/agents/sm.md +8 -30
- package/pennyfarthing-dist/agents/tea.md +25 -41
- package/pennyfarthing-dist/agents/tech-writer.md +33 -90
- package/pennyfarthing-dist/agents/ux-designer.md +39 -39
- package/pennyfarthing-dist/commands/benchmark-control.md +8 -64
- package/pennyfarthing-dist/commands/benchmark.md +8 -480
- package/pennyfarthing-dist/commands/job-fair.md +8 -97
- package/pennyfarthing-dist/commands/pf-benchmark-control.md +70 -0
- package/pennyfarthing-dist/commands/pf-benchmark.md +486 -0
- package/pennyfarthing-dist/commands/pf-chore.md +4 -4
- package/pennyfarthing-dist/commands/pf-ci.md +40 -0
- package/pennyfarthing-dist/commands/pf-close-epic.md +9 -27
- package/pennyfarthing-dist/commands/pf-continue-session.md +9 -213
- package/pennyfarthing-dist/commands/pf-create-branches-from-story.md +11 -353
- package/pennyfarthing-dist/commands/pf-docs.md +28 -0
- package/pennyfarthing-dist/commands/pf-epic.md +67 -0
- package/pennyfarthing-dist/commands/pf-git-cleanup.md +11 -52
- package/pennyfarthing-dist/commands/pf-git.md +75 -0
- package/pennyfarthing-dist/commands/pf-help.md +110 -128
- package/pennyfarthing-dist/commands/pf-job-fair.md +102 -0
- package/pennyfarthing-dist/commands/pf-new-work.md +9 -18
- package/pennyfarthing-dist/commands/pf-parallel-work.md +6 -66
- package/pennyfarthing-dist/commands/pf-release.md +11 -76
- package/pennyfarthing-dist/commands/pf-repo-status.md +11 -44
- package/pennyfarthing-dist/commands/pf-run-ci.md +8 -111
- package/pennyfarthing-dist/commands/pf-session.md +51 -0
- package/pennyfarthing-dist/commands/pf-solo.md +447 -0
- package/pennyfarthing-dist/commands/pf-sprint-planning.md +8 -104
- package/pennyfarthing-dist/commands/pf-standalone.md +1 -1
- package/pennyfarthing-dist/commands/pf-start-epic.md +9 -163
- package/pennyfarthing-dist/commands/pf-sync-epic-to-jira.md +8 -179
- package/pennyfarthing-dist/commands/pf-sync-work-with-sprint.md +8 -368
- package/pennyfarthing-dist/commands/pf-update-domain-docs.md +8 -78
- package/pennyfarthing-dist/commands/solo.md +8 -442
- package/pennyfarthing-dist/guides/agent-behavior.md +13 -13
- package/pennyfarthing-dist/guides/agent-coordination.md +7 -7
- package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +6 -5
- package/pennyfarthing-dist/guides/bikerack.md +128 -0
- package/pennyfarthing-dist/guides/brownfield-tools.md +133 -0
- package/pennyfarthing-dist/guides/command-tag-taxonomy.md +2 -2
- package/pennyfarthing-dist/guides/gate-schema.md +227 -0
- package/pennyfarthing-dist/guides/gates.md +120 -0
- package/pennyfarthing-dist/guides/handoff-cli.md +116 -0
- package/pennyfarthing-dist/guides/hooks.md +86 -4
- package/pennyfarthing-dist/guides/output-styles.md +65 -0
- package/pennyfarthing-dist/guides/patterns/approval-gates-pattern.md +5 -5
- package/pennyfarthing-dist/guides/patterns/tdd-flow-pattern.md +4 -4
- package/pennyfarthing-dist/guides/prompt-patterns.md +5 -5
- package/pennyfarthing-dist/guides/reflector.md +4 -4
- package/pennyfarthing-dist/guides/session-artifacts.md +1 -1
- package/pennyfarthing-dist/guides/skill-schema.md +1 -1
- package/pennyfarthing-dist/guides/tandem-protocol.md +13 -1
- package/pennyfarthing-dist/guides/worktree-mode.md +3 -3
- package/pennyfarthing-dist/guides/xml-tags.md +5 -4
- package/pennyfarthing-dist/personas/themes/hogans-heroes.yaml +11 -22
- package/pennyfarthing-dist/personas/themes/stephen-king.yaml +13 -24
- package/pennyfarthing-dist/scripts/core/dialogue-manager.sh +322 -0
- package/pennyfarthing-dist/scripts/core/phase-check-start.sh +1 -1
- package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +19 -14
- package/pennyfarthing-dist/scripts/portraits/generate-portraits.py +191 -57
- package/pennyfarthing-dist/scripts/portraits/generate-portraits.sh +26 -10
- package/pennyfarthing-dist/skills/pf-changelog/SKILL.md +4 -4
- package/pennyfarthing-dist/skills/pf-sprint/skill.md +1 -1
- package/pennyfarthing-dist/skills/skill-registry.schema.json +4 -0
- package/pennyfarthing-dist/skills/skill-registry.yaml +5 -0
- package/pennyfarthing-dist/workflows/2party-tdd.yaml +11 -0
- package/pennyfarthing-dist/workflows/agent-docs.yaml +2 -0
- package/pennyfarthing-dist/workflows/bdd-tandem.yaml +4 -0
- package/pennyfarthing-dist/workflows/bdd.yaml +4 -0
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +1 -1
- package/pennyfarthing-dist/workflows/tdd-tandem.yaml +3 -0
- package/pennyfarthing-dist/workflows/tdd.yaml +3 -0
- package/pennyfarthing-dist/workflows/trivial.yaml +2 -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_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/bikerack/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/__main__.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__/debug_panel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bikerack/__pycache__/diffs_panel.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__/sprint_panel.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/cli.py +10 -11
- package/pennyfarthing_scripts/bikerack/debug_panel.py +218 -0
- package/pennyfarthing_scripts/bikerack/diffs_panel.py +203 -27
- 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 +114 -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/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/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/__init__.py +0 -0
- package/pennyfarthing_scripts/epic/cli.py +64 -0
- package/pennyfarthing_scripts/gate/__init__.py +1 -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/gate/cli.py +56 -0
- package/pennyfarthing_scripts/gate/validate.py +266 -0
- package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git_group/__init__.py +0 -0
- package/pennyfarthing_scripts/git_group/cli.py +100 -0
- package/pennyfarthing_scripts/handoff/__init__.py +1 -0
- package/pennyfarthing_scripts/handoff/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/complete_phase.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/gate_file.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/gate_runner.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/marker.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/__pycache__/resolve_gate.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/handoff/cli.py +120 -0
- package/pennyfarthing_scripts/handoff/complete_phase.py +155 -0
- package/pennyfarthing_scripts/handoff/gate_file.py +105 -0
- package/pennyfarthing_scripts/handoff/gate_runner.py +152 -0
- package/pennyfarthing_scripts/handoff/marker.py +109 -0
- package/pennyfarthing_scripts/handoff/resolve_gate.py +152 -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/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__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/version_sentinel.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/workflow.py +39 -0
- package/pennyfarthing_scripts/session/__init__.py +0 -0
- package/pennyfarthing_scripts/session/cli.py +87 -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/story_finish.py +14 -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_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/test_108_1_gate_migration.py +540 -0
- package/pennyfarthing_scripts/tests/test_108_2_remove_handoff_fallback.py +339 -0
- package/pennyfarthing_scripts/tests/test_confidence_sm_evaluation.py +253 -0
- package/pennyfarthing_scripts/tests/test_confidence_sm_gate.py +315 -0
- package/pennyfarthing_scripts/tests/test_gate_file_resolution.py +341 -0
- package/pennyfarthing_scripts/tests/test_gate_runner.py +620 -0
- package/pennyfarthing_scripts/tests/test_handoff_cli.py +929 -0
- package/pennyfarthing_scripts/tests/test_handoff_e2e.py +454 -0
- package/pennyfarthing_scripts/tests/test_resolve_gate_file_field.py +464 -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__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/skill_command.py +200 -0
- package/pennyfarthing_scripts/validate/adapters/workflow.py +64 -0
- package/pennyfarthing_scripts/validate/cli.py +15 -4
- 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/pennyfarthing-dist/agents/handoff.md +0 -250
- package/pennyfarthing-dist/agents/sm-handoff.md +0 -152
- package/pennyfarthing-dist/scripts/core/handoff-marker.sh +0 -112
- 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/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_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
|
@@ -14,22 +14,27 @@
|
|
|
14
14
|
|
|
15
15
|
# Determine project directory
|
|
16
16
|
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
17
|
-
PORT_FILE="$PROJECT_DIR/.cyclist-port"
|
|
18
17
|
|
|
19
|
-
# Check
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
# Check .cyclist-port first, then .bikerack-port as fallback
|
|
19
|
+
PORT=""
|
|
20
|
+
for PORT_FILE in "$PROJECT_DIR/.cyclist-port" "$PROJECT_DIR/.bikerack-port"; do
|
|
21
|
+
if [[ -f "$PORT_FILE" ]]; then
|
|
22
|
+
PORT=$(cat "$PORT_FILE" 2>/dev/null)
|
|
23
|
+
# Validate port is a number
|
|
24
|
+
if [[ "$PORT" =~ ^[0-9]+$ ]]; then
|
|
25
|
+
break
|
|
26
|
+
fi
|
|
27
|
+
PORT=""
|
|
28
|
+
fi
|
|
29
|
+
done
|
|
23
30
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:$PORT"
|
|
31
|
+
# Configure OTEL if a valid port was found
|
|
32
|
+
if [[ -n "$PORT" ]]; then
|
|
33
|
+
export OTEL_EXPORTER_OTLP_PROTOCOL="http/json"
|
|
34
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:$PORT"
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
fi
|
|
36
|
+
# Optional: Log for debugging (can be silenced by setting CYCLIST_QUIET=1)
|
|
37
|
+
if [[ -z "$CYCLIST_QUIET" ]]; then
|
|
38
|
+
echo "[otel-auto-config] Configured OTEL to http://localhost:$PORT (from $PORT_FILE)" >&2
|
|
34
39
|
fi
|
|
35
40
|
fi
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
"""
|
|
3
3
|
Individual Portrait Generator for Pennyfarthing Themes
|
|
4
4
|
|
|
5
|
-
Generates individual portraits per theme
|
|
5
|
+
Generates individual portraits per theme on M3 Max (MPS).
|
|
6
|
+
Supports multiple engines: SDXL (Stable Diffusion XL) and Flux.
|
|
6
7
|
Reads visual prompts from theme YAML files in three locations:
|
|
7
8
|
- Package: packages/themes-*/themes/ (output to packages/themes-*/portraits/)
|
|
8
9
|
- Built-in: pennyfarthing-dist/personas/themes/ (output to pennyfarthing-dist/personas/portraits/)
|
|
@@ -11,9 +12,9 @@ Reads visual prompts from theme YAML files in three locations:
|
|
|
11
12
|
Output: {portraits-dir}/{theme}/{slug}-{OCEAN}.png (512x512px each)
|
|
12
13
|
|
|
13
14
|
Usage:
|
|
14
|
-
python3 scripts/generate-portraits.py [--dry-run] [--theme THEME]
|
|
15
|
-
python3 scripts/generate-portraits.py --theme gilligans-island --dry-run
|
|
16
|
-
python3 scripts/generate-portraits.py --role ba --skip-existing
|
|
15
|
+
python3 scripts/generate-portraits.py [--dry-run] [--theme THEME] [--engine ENGINE]
|
|
16
|
+
python3 scripts/generate-portraits.py --engine flux --theme gilligans-island --dry-run
|
|
17
|
+
python3 scripts/generate-portraits.py --engine sdxl --role ba --skip-existing
|
|
17
18
|
"""
|
|
18
19
|
|
|
19
20
|
import argparse
|
|
@@ -47,6 +48,11 @@ except ImportError as e:
|
|
|
47
48
|
HAS_TORCH = False
|
|
48
49
|
TORCH_ERROR = str(e)
|
|
49
50
|
|
|
51
|
+
# Native Flux repo (Black Forest Labs) — loaded lazily when --engine flux is used
|
|
52
|
+
HAS_FLUX = False
|
|
53
|
+
FLUX_ERROR = ""
|
|
54
|
+
FLUX_PROJECT_DIR = Path.home() / "Projects" / "flux"
|
|
55
|
+
|
|
50
56
|
# CLIP tokenizer for accurate token counting (optional - falls back to word estimate)
|
|
51
57
|
try:
|
|
52
58
|
from transformers import CLIPTokenizer
|
|
@@ -81,18 +87,29 @@ BUILTIN_THEMES_DIR = PROJECT_ROOT / "pennyfarthing-dist" / "personas" / "themes"
|
|
|
81
87
|
CUSTOM_THEMES_DIR = PROJECT_ROOT / ".claude" / "pennyfarthing" / "themes"
|
|
82
88
|
BUILTIN_OUTPUT_DIR = PROJECT_ROOT / "pennyfarthing-dist" / "personas" / "portraits"
|
|
83
89
|
PACKAGES_DIR = PROJECT_ROOT / "packages"
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
# Engine configurations
|
|
91
|
+
ENGINES = {
|
|
92
|
+
"sdxl": {
|
|
93
|
+
"model_id": "stabilityai/stable-diffusion-xl-base-1.0",
|
|
94
|
+
"generation_size": 1024,
|
|
95
|
+
"output_size": 512,
|
|
96
|
+
"num_inference_steps": 30,
|
|
97
|
+
"guidance_scale": 7.5,
|
|
98
|
+
"max_tokens": 77,
|
|
99
|
+
"supports_negative_prompt": True,
|
|
100
|
+
},
|
|
101
|
+
"flux": {
|
|
102
|
+
"model_name": "flux-schnell",
|
|
103
|
+
"generation_size": 1024,
|
|
104
|
+
"output_size": 512,
|
|
105
|
+
"num_inference_steps": 4,
|
|
106
|
+
"guidance_scale": 3.5,
|
|
107
|
+
"max_tokens": 256,
|
|
108
|
+
"supports_negative_prompt": False,
|
|
109
|
+
},
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
DEFAULT_ENGINE = "sdxl"
|
|
96
113
|
|
|
97
114
|
# Role order for the 11 agents
|
|
98
115
|
ROLES = [
|
|
@@ -124,7 +141,7 @@ def count_clip_tokens(text: str) -> int:
|
|
|
124
141
|
return int(len(text.split()) * 1.3)
|
|
125
142
|
|
|
126
143
|
|
|
127
|
-
def truncate_prompt_to_clip_limit(visual: str, style_suffix: str, max_tokens: int =
|
|
144
|
+
def truncate_prompt_to_clip_limit(visual: str, style_suffix: str, max_tokens: int = 77) -> tuple[str, bool]:
|
|
128
145
|
"""Truncate prompt to fit within CLIP token limit.
|
|
129
146
|
|
|
130
147
|
Strategy: Prioritize the visual description over the style suffix.
|
|
@@ -208,61 +225,167 @@ def parse_theme_file(theme_path: Path) -> dict:
|
|
|
208
225
|
return result
|
|
209
226
|
|
|
210
227
|
|
|
211
|
-
def build_portrait_prompt(visual: str, style_suffix: str = None) -> tuple[str, bool, int]:
|
|
212
|
-
"""Build a prompt for portrait generation with
|
|
228
|
+
def build_portrait_prompt(visual: str, style_suffix: str = None, max_tokens: int = 77) -> tuple[str, bool, int]:
|
|
229
|
+
"""Build a prompt for portrait generation with token limit enforcement.
|
|
213
230
|
|
|
214
231
|
Args:
|
|
215
232
|
visual: The character's visual description from theme YAML
|
|
216
233
|
style_suffix: Optional theme-specific style suffix. Falls back to DEFAULT_STYLE_SUFFIX.
|
|
234
|
+
max_tokens: Token limit for the engine (77 for SDXL/CLIP, 256 for Flux/T5).
|
|
217
235
|
|
|
218
236
|
Returns:
|
|
219
237
|
tuple: (prompt, was_truncated, token_count)
|
|
220
238
|
"""
|
|
221
239
|
suffix = style_suffix if style_suffix is not None else DEFAULT_STYLE_SUFFIX
|
|
222
|
-
prompt, was_truncated = truncate_prompt_to_clip_limit(visual, suffix)
|
|
240
|
+
prompt, was_truncated = truncate_prompt_to_clip_limit(visual, suffix, max_tokens=max_tokens)
|
|
223
241
|
token_count = count_clip_tokens(prompt)
|
|
224
242
|
return prompt, was_truncated, token_count
|
|
225
243
|
|
|
226
244
|
|
|
227
|
-
def
|
|
228
|
-
"""
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
245
|
+
def _load_flux_modules():
|
|
246
|
+
"""Lazy-load the native Flux repo and return its modules."""
|
|
247
|
+
global HAS_FLUX, FLUX_ERROR
|
|
248
|
+
|
|
249
|
+
if not FLUX_PROJECT_DIR.exists():
|
|
250
|
+
FLUX_ERROR = f"Flux project not found at {FLUX_PROJECT_DIR}"
|
|
251
|
+
return None
|
|
252
|
+
|
|
253
|
+
# Add flux src to path so we can import it
|
|
254
|
+
flux_src = str(FLUX_PROJECT_DIR / "src")
|
|
255
|
+
if flux_src not in sys.path:
|
|
256
|
+
sys.path.insert(0, flux_src)
|
|
257
|
+
|
|
258
|
+
try:
|
|
259
|
+
from flux.sampling import denoise, get_noise, get_schedule, prepare, unpack
|
|
260
|
+
from flux.util import configs, load_ae, load_clip, load_flow_model, load_t5
|
|
261
|
+
HAS_FLUX = True
|
|
262
|
+
return {
|
|
263
|
+
"denoise": denoise,
|
|
264
|
+
"get_noise": get_noise,
|
|
265
|
+
"get_schedule": get_schedule,
|
|
266
|
+
"prepare": prepare,
|
|
267
|
+
"unpack": unpack,
|
|
268
|
+
"configs": configs,
|
|
269
|
+
"load_ae": load_ae,
|
|
270
|
+
"load_clip": load_clip,
|
|
271
|
+
"load_flow_model": load_flow_model,
|
|
272
|
+
"load_t5": load_t5,
|
|
273
|
+
}
|
|
274
|
+
except ImportError as e:
|
|
275
|
+
FLUX_ERROR = str(e)
|
|
276
|
+
return None
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def load_pipeline(engine_name: str):
|
|
280
|
+
"""Load the image generation pipeline for the specified engine.
|
|
281
|
+
|
|
282
|
+
Returns a dict with engine-specific components.
|
|
283
|
+
For SDXL: {"pipe": StableDiffusionXLPipeline}
|
|
284
|
+
For Flux: {"model", "ae", "t5", "clip", "flux_modules", "device"}
|
|
285
|
+
"""
|
|
286
|
+
engine = ENGINES[engine_name]
|
|
287
|
+
|
|
288
|
+
if engine_name == "flux":
|
|
289
|
+
model_name = engine["model_name"]
|
|
290
|
+
print(f"\nLoading Flux ({model_name}) on MPS...")
|
|
291
|
+
print(" (First run downloads the model)")
|
|
292
|
+
|
|
293
|
+
flux = _load_flux_modules()
|
|
294
|
+
if flux is None:
|
|
295
|
+
print(f"Error loading Flux: {FLUX_ERROR}")
|
|
296
|
+
print(f"Expected Flux repo at: {FLUX_PROJECT_DIR}")
|
|
297
|
+
print("Install: git clone https://github.com/black-forest-labs/flux ~/Projects/flux")
|
|
298
|
+
sys.exit(1)
|
|
238
299
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
300
|
+
device = torch.device("mps")
|
|
301
|
+
t5 = flux["load_t5"](device, max_length=256)
|
|
302
|
+
clip = flux["load_clip"](device)
|
|
303
|
+
model = flux["load_flow_model"](model_name, device=device)
|
|
304
|
+
ae = flux["load_ae"](model_name, device=device)
|
|
305
|
+
|
|
306
|
+
print("Flux models loaded.\n")
|
|
307
|
+
return {
|
|
308
|
+
"model": model, "ae": ae, "t5": t5, "clip": clip,
|
|
309
|
+
"flux_modules": flux, "device": device,
|
|
310
|
+
}
|
|
311
|
+
else:
|
|
312
|
+
model_id = engine["model_id"]
|
|
313
|
+
print(f"\nLoading SDXL model on MPS...")
|
|
314
|
+
print(f" Model: {model_id}")
|
|
315
|
+
print(" (First run downloads ~6.5GB model)")
|
|
316
|
+
|
|
317
|
+
pipe = StableDiffusionXLPipeline.from_pretrained(
|
|
318
|
+
model_id,
|
|
319
|
+
torch_dtype=torch.float32,
|
|
320
|
+
use_safetensors=True,
|
|
321
|
+
)
|
|
322
|
+
pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
|
|
323
|
+
pipe = pipe.to("mps")
|
|
324
|
+
pipe.enable_attention_slicing()
|
|
325
|
+
|
|
326
|
+
print("Model loaded.\n")
|
|
327
|
+
return {"pipe": pipe}
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def generate_portrait(pipeline_components: dict, prompt: str, engine_name: str, seed: int = 42) -> "Image.Image":
|
|
331
|
+
"""Generate a single portrait using the specified engine."""
|
|
332
|
+
engine = ENGINES[engine_name]
|
|
333
|
+
gen_size = engine["generation_size"]
|
|
334
|
+
out_size = engine["output_size"]
|
|
335
|
+
|
|
336
|
+
if engine_name == "flux":
|
|
337
|
+
from einops import rearrange
|
|
338
|
+
|
|
339
|
+
flux = pipeline_components["flux_modules"]
|
|
340
|
+
model = pipeline_components["model"]
|
|
341
|
+
ae = pipeline_components["ae"]
|
|
342
|
+
t5 = pipeline_components["t5"]
|
|
343
|
+
clip = pipeline_components["clip"]
|
|
344
|
+
device = pipeline_components["device"]
|
|
345
|
+
|
|
346
|
+
# Flux native sampling pipeline
|
|
347
|
+
x = flux["get_noise"](
|
|
348
|
+
1, gen_size, gen_size,
|
|
349
|
+
device=device, dtype=torch.bfloat16, seed=seed,
|
|
350
|
+
)
|
|
351
|
+
inp = flux["prepare"](t5, clip, x, prompt=prompt)
|
|
352
|
+
timesteps = flux["get_schedule"](
|
|
353
|
+
engine["num_inference_steps"], inp["img"].shape[1], shift=False,
|
|
354
|
+
)
|
|
242
355
|
|
|
243
|
-
|
|
244
|
-
|
|
356
|
+
with torch.no_grad():
|
|
357
|
+
x = flux["denoise"](model, **inp, timesteps=timesteps, guidance=engine["guidance_scale"])
|
|
245
358
|
|
|
359
|
+
x = flux["unpack"](x.float(), gen_size, gen_size)
|
|
360
|
+
with torch.autocast(device_type=device.type, dtype=torch.bfloat16):
|
|
361
|
+
x = ae.decode(x)
|
|
246
362
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
363
|
+
# Convert tensor to PIL
|
|
364
|
+
x = x.clamp(-1, 1)
|
|
365
|
+
x = rearrange(x[0], "c h w -> h w c")
|
|
366
|
+
image = Image.fromarray((127.5 * (x + 1.0)).cpu().byte().numpy())
|
|
367
|
+
else:
|
|
368
|
+
# SDXL via diffusers
|
|
369
|
+
pipe = pipeline_components["pipe"]
|
|
370
|
+
generator = torch.Generator().manual_seed(seed)
|
|
251
371
|
|
|
252
|
-
|
|
253
|
-
result = pipe(
|
|
372
|
+
kwargs = dict(
|
|
254
373
|
prompt=prompt,
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
guidance_scale=GUIDANCE_SCALE,
|
|
374
|
+
width=gen_size,
|
|
375
|
+
height=gen_size,
|
|
376
|
+
num_inference_steps=engine["num_inference_steps"],
|
|
377
|
+
guidance_scale=engine["guidance_scale"],
|
|
260
378
|
generator=generator,
|
|
261
379
|
)
|
|
380
|
+
if engine["supports_negative_prompt"]:
|
|
381
|
+
kwargs["negative_prompt"] = "color, grayscale, photorealistic, blurry, deformed"
|
|
262
382
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
383
|
+
with torch.no_grad():
|
|
384
|
+
result = pipe(**kwargs)
|
|
385
|
+
|
|
386
|
+
image = result.images[0]
|
|
387
|
+
|
|
388
|
+
return image.resize((out_size, out_size), Image.Resampling.LANCZOS)
|
|
266
389
|
|
|
267
390
|
|
|
268
391
|
def main():
|
|
@@ -273,8 +396,13 @@ def main():
|
|
|
273
396
|
parser.add_argument("--seed", type=int, default=42, help="Random seed")
|
|
274
397
|
parser.add_argument("--skip-existing", action="store_true", help="Skip existing files")
|
|
275
398
|
parser.add_argument("--output-dir", type=str, help="Output to different directory (default: pennyfarthing-dist/personas/portraits)")
|
|
399
|
+
parser.add_argument("--engine", type=str, choices=list(ENGINES.keys()), default=DEFAULT_ENGINE,
|
|
400
|
+
help=f"Image generation engine (default: {DEFAULT_ENGINE})")
|
|
276
401
|
args = parser.parse_args()
|
|
277
402
|
|
|
403
|
+
engine_name = args.engine
|
|
404
|
+
engine = ENGINES[engine_name]
|
|
405
|
+
|
|
278
406
|
# Determine output directory override
|
|
279
407
|
output_override = Path(args.output_dir) if args.output_dir else None
|
|
280
408
|
|
|
@@ -323,9 +451,11 @@ def main():
|
|
|
323
451
|
print(f" Package: {src}")
|
|
324
452
|
print(f" Custom: {CUSTOM_THEMES_DIR}")
|
|
325
453
|
print(f"Found {len(theme_entries)} themes")
|
|
454
|
+
engine_label = engine.get("model_id", engine.get("model_name", engine_name))
|
|
455
|
+
print(f"Engine: {engine_name.upper()} ({engine_label})")
|
|
326
456
|
|
|
327
457
|
if args.dry_run:
|
|
328
|
-
print(f"\
|
|
458
|
+
print(f"\nToken limit: {engine['max_tokens']} tokens ({engine_name.upper()})")
|
|
329
459
|
print(f"Tokenizer: {'CLIP (accurate)' if HAS_CLIP_TOKENIZER else 'word estimate (fallback)'}")
|
|
330
460
|
roles_to_show = [args.role] if args.role else ROLES
|
|
331
461
|
print(f"\nDry run - portraits to generate (roles: {', '.join(roles_to_show)}):")
|
|
@@ -348,7 +478,9 @@ def main():
|
|
|
348
478
|
status = "EXISTS" if out_path.exists() else "PENDING"
|
|
349
479
|
|
|
350
480
|
# Check token count and truncation
|
|
351
|
-
prompt, was_truncated, token_count = build_portrait_prompt(
|
|
481
|
+
prompt, was_truncated, token_count = build_portrait_prompt(
|
|
482
|
+
char["visual"], parsed["portrait_style"], max_tokens=engine["max_tokens"]
|
|
483
|
+
)
|
|
352
484
|
token_status = f"{token_count}tok"
|
|
353
485
|
if was_truncated:
|
|
354
486
|
token_status = f"⚠️ {token_count}tok TRUNCATED"
|
|
@@ -362,7 +494,7 @@ def main():
|
|
|
362
494
|
if truncation_warnings:
|
|
363
495
|
print(f"\n{'='*60}")
|
|
364
496
|
print(f"⚠️ WARNING: {len(truncation_warnings)} prompts will be truncated!")
|
|
365
|
-
print(f"
|
|
497
|
+
print(f" Token limit is {engine['max_tokens']} ({engine_name.upper()}). Consider shortening:")
|
|
366
498
|
for theme, role, filename in truncation_warnings[:10]:
|
|
367
499
|
print(f" - {theme}/{filename} ({role})")
|
|
368
500
|
if len(truncation_warnings) > 10:
|
|
@@ -376,7 +508,7 @@ def main():
|
|
|
376
508
|
sys.exit(1)
|
|
377
509
|
|
|
378
510
|
# Load model
|
|
379
|
-
|
|
511
|
+
pipeline_components = load_pipeline(engine_name)
|
|
380
512
|
|
|
381
513
|
# Track results
|
|
382
514
|
successful = 0
|
|
@@ -406,7 +538,9 @@ def main():
|
|
|
406
538
|
print(f" SKIP (exists): {char['filename']}")
|
|
407
539
|
continue
|
|
408
540
|
|
|
409
|
-
prompt, was_truncated, token_count = build_portrait_prompt(
|
|
541
|
+
prompt, was_truncated, token_count = build_portrait_prompt(
|
|
542
|
+
char["visual"], parsed["portrait_style"], max_tokens=engine["max_tokens"]
|
|
543
|
+
)
|
|
410
544
|
|
|
411
545
|
if was_truncated:
|
|
412
546
|
truncated.append((theme, char["filename"], token_count))
|
|
@@ -417,7 +551,7 @@ def main():
|
|
|
417
551
|
try:
|
|
418
552
|
# Vary seed per character for diversity (base_seed + role_index)
|
|
419
553
|
role_seed = args.seed + ROLES.index(role)
|
|
420
|
-
image = generate_portrait(
|
|
554
|
+
image = generate_portrait(pipeline_components, prompt, engine_name, seed=role_seed)
|
|
421
555
|
image.save(out_path, "PNG")
|
|
422
556
|
successful += 1
|
|
423
557
|
print(f" DONE: {char['filename']}")
|
|
@@ -430,7 +564,7 @@ def main():
|
|
|
430
564
|
print(f"\n{'='*50}")
|
|
431
565
|
print(f"Complete: {successful} portraits in {elapsed}")
|
|
432
566
|
if truncated:
|
|
433
|
-
print(f"Truncated: {len(truncated)} prompts exceeded {
|
|
567
|
+
print(f"Truncated: {len(truncated)} prompts exceeded {engine['max_tokens']} token limit ({engine_name.upper()})")
|
|
434
568
|
if failed:
|
|
435
569
|
print(f"Failed: {len(failed)}")
|
|
436
570
|
for t, r, e in failed:
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
#
|
|
6
6
|
# Usage:
|
|
7
7
|
# ./scripts/generate-portraits.sh --theme arthurian-mythos --dry-run
|
|
8
|
-
# ./scripts/generate-portraits.sh --theme shakespeare
|
|
9
|
-
# ./scripts/generate-portraits.sh --theme star-trek-tos --output-dir /tmp/portraits
|
|
8
|
+
# ./scripts/generate-portraits.sh --engine flux --theme shakespeare
|
|
9
|
+
# ./scripts/generate-portraits.sh --engine sdxl --theme star-trek-tos --output-dir /tmp/portraits
|
|
10
10
|
# ./scripts/generate-portraits.sh --help
|
|
11
11
|
|
|
12
12
|
set -euo pipefail
|
|
@@ -20,12 +20,25 @@ while [[ ! -d "$_dir/.pennyfarthing" ]] && [[ ! -d "$_dir/pennyfarthing-dist" ]]
|
|
|
20
20
|
done
|
|
21
21
|
PROJECT_ROOT="$_dir"
|
|
22
22
|
|
|
23
|
-
#
|
|
24
|
-
# Priority: VENV_DIR env var > project .venv > ~/.venvs/sd > ~/.venv
|
|
23
|
+
# Detect engine from args to select the right venv
|
|
25
24
|
PYTHON_SCRIPT="$SCRIPT_DIR/generate-portraits.py"
|
|
25
|
+
ENGINE="sdxl"
|
|
26
|
+
prev_arg=""
|
|
27
|
+
for arg in "$@"; do
|
|
28
|
+
if [[ "$prev_arg" == "--engine" ]]; then
|
|
29
|
+
ENGINE="$arg"
|
|
30
|
+
break
|
|
31
|
+
fi
|
|
32
|
+
prev_arg="$arg"
|
|
33
|
+
done
|
|
26
34
|
|
|
35
|
+
# Find Python venv based on engine
|
|
36
|
+
# Flux uses ~/.venvs/flux, SDXL uses ~/.venvs/sd
|
|
37
|
+
# Priority: VENV_DIR env var > engine-specific > project .venv > fallback
|
|
27
38
|
if [[ -z "${VENV_DIR:-}" ]]; then
|
|
28
|
-
if [[ -d "$
|
|
39
|
+
if [[ "$ENGINE" == "flux" ]] && [[ -d "$HOME/.venvs/flux" ]]; then
|
|
40
|
+
VENV_DIR="$HOME/.venvs/flux"
|
|
41
|
+
elif [[ -d "$PROJECT_ROOT/.venv" ]]; then
|
|
29
42
|
VENV_DIR="$PROJECT_ROOT/.venv"
|
|
30
43
|
elif [[ -d "$HOME/.venvs/sd" ]]; then
|
|
31
44
|
VENV_DIR="$HOME/.venvs/sd"
|
|
@@ -36,14 +49,17 @@ fi
|
|
|
36
49
|
|
|
37
50
|
# Check venv exists
|
|
38
51
|
if [[ -z "${VENV_DIR:-}" ]] || [[ ! -d "$VENV_DIR" ]]; then
|
|
39
|
-
echo "Error: Virtual environment not found"
|
|
40
|
-
echo "Searched: $PROJECT_ROOT/.venv, ~/.venvs/sd, ~/.venv"
|
|
52
|
+
echo "Error: Virtual environment not found for engine '$ENGINE'"
|
|
53
|
+
echo "Searched: $PROJECT_ROOT/.venv, ~/.venvs/sd, ~/.venvs/flux, ~/.venv"
|
|
41
54
|
echo "Or set VENV_DIR=/path/to/venv"
|
|
42
|
-
|
|
43
|
-
|
|
55
|
+
if [[ "$ENGINE" == "flux" ]]; then
|
|
56
|
+
echo "For Flux: python3 -m venv ~/.venvs/flux && pip install torch einops transformers pillow pyyaml"
|
|
57
|
+
else
|
|
58
|
+
echo "For SDXL: python3 -m venv ~/.venvs/sd && pip install diffusers transformers accelerate torch pillow pyyaml"
|
|
59
|
+
fi
|
|
44
60
|
exit 1
|
|
45
61
|
fi
|
|
46
|
-
echo "Using venv: $VENV_DIR"
|
|
62
|
+
echo "Using venv: $VENV_DIR (engine: $ENGINE)"
|
|
47
63
|
|
|
48
64
|
# Check Python script exists
|
|
49
65
|
if [[ ! -f "$PYTHON_SCRIPT" ]]; then
|
|
@@ -306,16 +306,16 @@ git tag -a "v$NEW_VERSION" -m "Release $NEW_VERSION"
|
|
|
306
306
|
git push origin main --tags
|
|
307
307
|
```
|
|
308
308
|
|
|
309
|
-
## Integration with /release Command
|
|
309
|
+
## Integration with /pf-git release Command
|
|
310
310
|
|
|
311
|
-
The `/release` command in Pennyfarthing can use this skill for:
|
|
311
|
+
The `/pf-git release` command in Pennyfarthing can use this skill for:
|
|
312
312
|
|
|
313
313
|
1. **Auto-detecting new commits** - Run conventional commit analysis since last tag
|
|
314
314
|
2. **Generating changelog sections** - Create properly formatted entries
|
|
315
315
|
3. **Version bumping** - Semantic versioning based on commit types
|
|
316
316
|
4. **Tagging** - Create annotated tags for releases
|
|
317
317
|
|
|
318
|
-
Reference in `/release` command:
|
|
318
|
+
Reference in `/pf-git release` command:
|
|
319
319
|
|
|
320
320
|
```markdown
|
|
321
321
|
See the [Changelog Skill](/changelog) for patterns on:
|
|
@@ -382,4 +382,4 @@ npx conventional-changelog -p angular -i CHANGELOG.md -s
|
|
|
382
382
|
- **Conventional Commits:** https://www.conventionalcommits.org/
|
|
383
383
|
- **Semantic Versioning:** https://semver.org/
|
|
384
384
|
- **conventional-changelog:** https://github.com/conventional-changelog/conventional-changelog
|
|
385
|
-
- **Pennyfarthing Release:** `/release` command
|
|
385
|
+
- **Pennyfarthing Release:** `/pf-git release` command
|
|
@@ -71,7 +71,7 @@ Never manually edit `sprint/current-sprint.yaml`. Use `pf sprint` CLI commands f
|
|
|
71
71
|
| `pf backlog` | `pf sprint backlog` |
|
|
72
72
|
| `pf work` | `pf sprint work` |
|
|
73
73
|
| `pf story` | `pf sprint story` |
|
|
74
|
-
| `/new
|
|
74
|
+
| `/pf-session new` | `/pf-sprint work` |
|
|
75
75
|
|
|
76
76
|
---
|
|
77
77
|
|
|
@@ -106,6 +106,10 @@
|
|
|
106
106
|
"redirect": {
|
|
107
107
|
"type": "string",
|
|
108
108
|
"description": "Skill name to redirect to when deprecated"
|
|
109
|
+
},
|
|
110
|
+
"command_group": {
|
|
111
|
+
"type": "string",
|
|
112
|
+
"description": "Command group name from command-registry.yaml that this skill manages"
|
|
109
113
|
}
|
|
110
114
|
},
|
|
111
115
|
"required": ["name", "description", "category", "tags"],
|
|
@@ -115,6 +115,7 @@ skills:
|
|
|
115
115
|
category: project-management
|
|
116
116
|
tags: [jira, issues, sprint]
|
|
117
117
|
version: "1.0.0"
|
|
118
|
+
command_group: jira
|
|
118
119
|
prerequisites: []
|
|
119
120
|
examples:
|
|
120
121
|
- context: Viewing sprint issues
|
|
@@ -200,6 +201,7 @@ skills:
|
|
|
200
201
|
category: project-management
|
|
201
202
|
tags: [permissions, security, tools]
|
|
202
203
|
version: "1.0.0"
|
|
204
|
+
command_group: permissions
|
|
203
205
|
prerequisites: []
|
|
204
206
|
examples:
|
|
205
207
|
- context: Viewing active grants
|
|
@@ -237,6 +239,7 @@ skills:
|
|
|
237
239
|
category: project-management
|
|
238
240
|
tags: [sprint, status, backlog, stories, epics]
|
|
239
241
|
version: "2.0.0"
|
|
242
|
+
command_group: sprint
|
|
240
243
|
prerequisites: []
|
|
241
244
|
examples:
|
|
242
245
|
- context: Checking sprint status
|
|
@@ -317,6 +320,7 @@ skills:
|
|
|
317
320
|
category: theming
|
|
318
321
|
tags: [personas, themes, customization, creation]
|
|
319
322
|
version: "2.0.0"
|
|
323
|
+
command_group: theme
|
|
320
324
|
prerequisites: []
|
|
321
325
|
examples:
|
|
322
326
|
- context: Listing available themes
|
|
@@ -357,6 +361,7 @@ skills:
|
|
|
357
361
|
category: project-management
|
|
358
362
|
tags: [workflow, phases, tdd]
|
|
359
363
|
version: "1.0.0"
|
|
364
|
+
command_group: workflow
|
|
360
365
|
prerequisites: []
|
|
361
366
|
examples:
|
|
362
367
|
- context: Listing available workflows
|
|
@@ -53,6 +53,7 @@ workflow:
|
|
|
53
53
|
Present findings to user. User decides what to add/change.
|
|
54
54
|
Update the story description with agreed refinements.
|
|
55
55
|
gate:
|
|
56
|
+
file: gates/approval
|
|
56
57
|
type: approval
|
|
57
58
|
condition: User reviewed dev-perspective gaps and decided on each item
|
|
58
59
|
|
|
@@ -73,6 +74,7 @@ workflow:
|
|
|
73
74
|
Present findings to user. User decides what to add/change.
|
|
74
75
|
Update the story description with agreed refinements.
|
|
75
76
|
gate:
|
|
77
|
+
file: gates/approval
|
|
76
78
|
type: approval
|
|
77
79
|
condition: User reviewed tea-perspective gaps and decided on each item
|
|
78
80
|
|
|
@@ -93,6 +95,7 @@ workflow:
|
|
|
93
95
|
|
|
94
96
|
Fix any remaining issues, then hand off to TEA.
|
|
95
97
|
gate:
|
|
98
|
+
file: gates/approval
|
|
96
99
|
type: approval
|
|
97
100
|
condition: Story passes quality check and is ready for TEA
|
|
98
101
|
|
|
@@ -122,6 +125,7 @@ workflow:
|
|
|
122
125
|
In the TEA Assessment handoff, list what quality gates Dev
|
|
123
126
|
should expect to pass beyond the functional tests.
|
|
124
127
|
gate:
|
|
128
|
+
file: gates/tests-fail
|
|
125
129
|
type: tests_fail
|
|
126
130
|
condition: All acceptance criteria have test coverage, including quality gate check
|
|
127
131
|
|
|
@@ -154,6 +158,7 @@ workflow:
|
|
|
154
158
|
|
|
155
159
|
Reviewer should only receive code that is verified clean.
|
|
156
160
|
gate:
|
|
161
|
+
file: gates/quality-pass
|
|
157
162
|
type: quality_pass
|
|
158
163
|
condition: >
|
|
159
164
|
All project quality gates pass locally — tests, lint, format,
|
|
@@ -181,6 +186,7 @@ workflow:
|
|
|
181
186
|
- Set review_verdict: approved in story
|
|
182
187
|
- DO NOT merge the PR — hand off to SM for finish phase
|
|
183
188
|
gate:
|
|
189
|
+
file: gates/approval
|
|
184
190
|
type: approval
|
|
185
191
|
condition: Code review passed, no blocking issues
|
|
186
192
|
|
|
@@ -194,6 +200,7 @@ workflow:
|
|
|
194
200
|
from the story. Write failing tests for each testable finding.
|
|
195
201
|
Commit RED tests. Hand off to Dev.
|
|
196
202
|
gate:
|
|
203
|
+
file: gates/tests-fail
|
|
197
204
|
type: tests_fail
|
|
198
205
|
condition: New tests cover reviewer findings
|
|
199
206
|
|
|
@@ -227,6 +234,7 @@ workflow:
|
|
|
227
234
|
If verification fails, hand back to Dev with specifics.
|
|
228
235
|
If verification passes, hand off to Reviewer for re-review.
|
|
229
236
|
gate:
|
|
237
|
+
file: gates/quality-pass
|
|
230
238
|
type: quality_pass
|
|
231
239
|
condition: >
|
|
232
240
|
All project quality gates pass. Each review finding verified
|
|
@@ -255,6 +263,7 @@ workflow:
|
|
|
255
263
|
5. Only after user approves: create PR (draft by default,
|
|
256
264
|
or per user pr_mode preference in pennyfarthing config)
|
|
257
265
|
gate:
|
|
266
|
+
file: gates/approval
|
|
258
267
|
type: approval
|
|
259
268
|
condition: User has reviewed and approved PR content before submission
|
|
260
269
|
|
|
@@ -315,6 +324,7 @@ workflow:
|
|
|
315
324
|
|
|
316
325
|
Present decisions to user. User has final say on every item.
|
|
317
326
|
gate:
|
|
327
|
+
file: gates/approval
|
|
318
328
|
type: approval
|
|
319
329
|
condition: User has decided on every external review comment
|
|
320
330
|
|
|
@@ -340,6 +350,7 @@ workflow:
|
|
|
340
350
|
|
|
341
351
|
Commit fixes. Push branch. Present all draft replies to user.
|
|
342
352
|
gate:
|
|
353
|
+
file: gates/approval
|
|
343
354
|
type: approval
|
|
344
355
|
condition: >
|
|
345
356
|
User has approved every draft reply. Fixes pass quality
|
|
@@ -28,6 +28,7 @@ workflow:
|
|
|
28
28
|
input: [audit_report, proposed_changes]
|
|
29
29
|
output: [updated_files]
|
|
30
30
|
gate:
|
|
31
|
+
file: gates/validation
|
|
31
32
|
type: validation
|
|
32
33
|
condition: Agent files parse correctly, no broken references
|
|
33
34
|
|
|
@@ -36,6 +37,7 @@ workflow:
|
|
|
36
37
|
input: [updated_files]
|
|
37
38
|
output: [approval]
|
|
38
39
|
gate:
|
|
40
|
+
file: gates/approval
|
|
39
41
|
type: approval
|
|
40
42
|
condition: |
|
|
41
43
|
Documentation quality review:
|