@pennyfarthing/core 9.2.0 → 9.3.0
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/package.json +36 -32
- package/LICENSE +0 -14
- package/README.md +0 -218
- package/pennyfarthing-dist/agents/README.md +0 -348
- package/pennyfarthing-dist/agents/architect.md +0 -180
- package/pennyfarthing-dist/agents/dev.md +0 -169
- package/pennyfarthing-dist/agents/devops.md +0 -203
- package/pennyfarthing-dist/agents/handoff.md +0 -235
- package/pennyfarthing-dist/agents/orchestrator.md +0 -182
- package/pennyfarthing-dist/agents/pm.md +0 -152
- package/pennyfarthing-dist/agents/reviewer-preflight.md +0 -129
- package/pennyfarthing-dist/agents/reviewer.md +0 -197
- package/pennyfarthing-dist/agents/sm-file-summary.md +0 -79
- package/pennyfarthing-dist/agents/sm-finish.md +0 -82
- package/pennyfarthing-dist/agents/sm-handoff.md +0 -129
- package/pennyfarthing-dist/agents/sm-setup.md +0 -251
- package/pennyfarthing-dist/agents/sm.md +0 -294
- package/pennyfarthing-dist/agents/tea.md +0 -161
- package/pennyfarthing-dist/agents/tech-writer.md +0 -226
- package/pennyfarthing-dist/agents/testing-runner.md +0 -184
- package/pennyfarthing-dist/agents/ux-designer.md +0 -236
- package/pennyfarthing-dist/agents/workflow-status-check.md +0 -96
- package/pennyfarthing-dist/commands/architect.md +0 -9
- package/pennyfarthing-dist/commands/benchmark-control.md +0 -69
- package/pennyfarthing-dist/commands/benchmark.md +0 -485
- package/pennyfarthing-dist/commands/brainstorming.md +0 -91
- package/pennyfarthing-dist/commands/check.md +0 -156
- package/pennyfarthing-dist/commands/chore.md +0 -218
- package/pennyfarthing-dist/commands/close-epic.md +0 -139
- package/pennyfarthing-dist/commands/continue-session.md +0 -218
- package/pennyfarthing-dist/commands/create-branches-from-story.md +0 -358
- package/pennyfarthing-dist/commands/create-theme.md +0 -29
- package/pennyfarthing-dist/commands/dev.md +0 -9
- package/pennyfarthing-dist/commands/devops.md +0 -9
- package/pennyfarthing-dist/commands/fix-blocker.md +0 -22
- package/pennyfarthing-dist/commands/git-cleanup.md +0 -57
- package/pennyfarthing-dist/commands/health-check.md +0 -143
- package/pennyfarthing-dist/commands/help.md +0 -264
- package/pennyfarthing-dist/commands/job-fair.md +0 -102
- package/pennyfarthing-dist/commands/list-themes.md +0 -21
- package/pennyfarthing-dist/commands/new-work.md +0 -23
- package/pennyfarthing-dist/commands/orchestrator.md +0 -9
- package/pennyfarthing-dist/commands/parallel-work.md +0 -73
- package/pennyfarthing-dist/commands/party-mode.md +0 -77
- package/pennyfarthing-dist/commands/patch.md +0 -210
- package/pennyfarthing-dist/commands/permissions.md +0 -193
- package/pennyfarthing-dist/commands/pm.md +0 -9
- package/pennyfarthing-dist/commands/prime.md +0 -136
- package/pennyfarthing-dist/commands/release.md +0 -58
- package/pennyfarthing-dist/commands/repo-status.md +0 -49
- package/pennyfarthing-dist/commands/retro.md +0 -200
- package/pennyfarthing-dist/commands/reviewer.md +0 -9
- package/pennyfarthing-dist/commands/run-ci.md +0 -116
- package/pennyfarthing-dist/commands/set-theme.md +0 -56
- package/pennyfarthing-dist/commands/setup.md +0 -65
- package/pennyfarthing-dist/commands/show-theme.md +0 -21
- package/pennyfarthing-dist/commands/sm.md +0 -9
- package/pennyfarthing-dist/commands/solo.md +0 -447
- package/pennyfarthing-dist/commands/sprint-planning.md +0 -109
- package/pennyfarthing-dist/commands/sprint.md +0 -142
- package/pennyfarthing-dist/commands/standalone.md +0 -194
- package/pennyfarthing-dist/commands/start-epic.md +0 -168
- package/pennyfarthing-dist/commands/sync-epic-to-jira.md +0 -184
- package/pennyfarthing-dist/commands/sync-work-with-sprint.md +0 -373
- package/pennyfarthing-dist/commands/tea.md +0 -9
- package/pennyfarthing-dist/commands/tech-writer.md +0 -9
- package/pennyfarthing-dist/commands/theme-maker.md +0 -676
- package/pennyfarthing-dist/commands/update-domain-docs.md +0 -83
- package/pennyfarthing-dist/commands/ux-designer.md +0 -9
- package/pennyfarthing-dist/commands/work.md +0 -25
- package/pennyfarthing-dist/commands/workflow.md +0 -21
- package/pennyfarthing-dist/guides/agent-behavior.md +0 -90
- package/pennyfarthing-dist/guides/agent-coordination.md +0 -480
- package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +0 -432
- package/pennyfarthing-dist/guides/agent-template-strategic.md +0 -148
- package/pennyfarthing-dist/guides/agent-template-tactical.md +0 -162
- package/pennyfarthing-dist/guides/hooks.md +0 -230
- package/pennyfarthing-dist/guides/measurement-framework.md +0 -210
- package/pennyfarthing-dist/guides/patterns/approval-gates-pattern.md +0 -766
- package/pennyfarthing-dist/guides/patterns/fan-out-fan-in-pattern.md +0 -574
- package/pennyfarthing-dist/guides/patterns/helper-delegation-pattern.md +0 -488
- package/pennyfarthing-dist/guides/patterns/tdd-flow-pattern.md +0 -402
- package/pennyfarthing-dist/guides/permission-protocol.md +0 -188
- package/pennyfarthing-dist/guides/persona-loading.md +0 -46
- package/pennyfarthing-dist/guides/prompt-patterns.md +0 -338
- package/pennyfarthing-dist/guides/scale-levels.md +0 -114
- package/pennyfarthing-dist/guides/session-artifacts.md +0 -193
- package/pennyfarthing-dist/guides/session-schema.md +0 -346
- package/pennyfarthing-dist/guides/skill-schema.md +0 -412
- package/pennyfarthing-dist/guides/workflow-schema.md +0 -257
- package/pennyfarthing-dist/guides/workflow-step-schema.md +0 -512
- package/pennyfarthing-dist/guides/worktree-mode.md +0 -113
- package/pennyfarthing-dist/guides/xml-tags.md +0 -627
- package/pennyfarthing-dist/output-styles/teaching.md +0 -33
- package/pennyfarthing-dist/output-styles/terse.md +0 -20
- package/pennyfarthing-dist/output-styles/verbose.md +0 -28
- package/pennyfarthing-dist/personas/themes/a-team.yaml +0 -331
- package/pennyfarthing-dist/personas/themes/alice-in-wonderland.yaml +0 -324
- package/pennyfarthing-dist/personas/themes/battlestar-galactica.yaml +0 -282
- package/pennyfarthing-dist/personas/themes/blade-runner.yaml +0 -289
- package/pennyfarthing-dist/personas/themes/catch-22.yaml +0 -304
- package/pennyfarthing-dist/personas/themes/control.yaml +0 -201
- package/pennyfarthing-dist/personas/themes/cowboy-bebop.yaml +0 -315
- package/pennyfarthing-dist/personas/themes/discworld.yaml +0 -334
- package/pennyfarthing-dist/personas/themes/doctor-who.yaml +0 -284
- package/pennyfarthing-dist/personas/themes/dune.yaml +0 -301
- package/pennyfarthing-dist/personas/themes/firefly.yaml +0 -320
- package/pennyfarthing-dist/personas/themes/game-of-thrones.yaml +0 -284
- package/pennyfarthing-dist/personas/themes/harry-potter.yaml +0 -316
- package/pennyfarthing-dist/personas/themes/hitchhikers-guide.yaml +0 -323
- package/pennyfarthing-dist/personas/themes/lord-of-the-rings.yaml +0 -326
- package/pennyfarthing-dist/personas/themes/mad-max.yaml +0 -349
- package/pennyfarthing-dist/personas/themes/mash.yaml +0 -329
- package/pennyfarthing-dist/personas/themes/princess-bride.yaml +0 -344
- package/pennyfarthing-dist/personas/themes/sandman.yaml +0 -282
- package/pennyfarthing-dist/personas/themes/star-trek-tng.yaml +0 -358
- package/pennyfarthing-dist/personas/themes/star-wars.yaml +0 -297
- package/pennyfarthing-dist/personas/themes/the-expanse.yaml +0 -337
- package/pennyfarthing-dist/personas/themes/the-matrix.yaml +0 -342
- package/pennyfarthing-dist/personas/themes/watchmen.yaml +0 -285
- package/pennyfarthing-dist/personas/themes/west-wing.yaml +0 -285
- package/pennyfarthing-dist/personas/themes/x-files.yaml +0 -296
- package/pennyfarthing-dist/scripts/README.md +0 -87
- package/pennyfarthing-dist/scripts/core/README.md +0 -25
- package/pennyfarthing-dist/scripts/core/agent-session.sh +0 -390
- package/pennyfarthing-dist/scripts/core/check-context.sh +0 -194
- package/pennyfarthing-dist/scripts/core/handoff-marker.sh +0 -112
- package/pennyfarthing-dist/scripts/core/phase-check-start.sh +0 -90
- package/pennyfarthing-dist/scripts/core/prime.sh +0 -30
- package/pennyfarthing-dist/scripts/cyclist/is-cyclist.sh +0 -21
- package/pennyfarthing-dist/scripts/git/README.md +0 -25
- package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +0 -267
- package/pennyfarthing-dist/scripts/git/git-status-all.sh +0 -152
- package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +0 -79
- package/pennyfarthing-dist/scripts/git/release.sh +0 -246
- package/pennyfarthing-dist/scripts/git/worktree-manager.sh +0 -497
- package/pennyfarthing-dist/scripts/health/drift-detection.sh +0 -156
- package/pennyfarthing-dist/scripts/hooks/README.md +0 -32
- package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +0 -106
- package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +0 -95
- package/pennyfarthing-dist/scripts/hooks/context-warning.sh +0 -65
- package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +0 -35
- package/pennyfarthing-dist/scripts/hooks/post-merge.sh +0 -150
- package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +0 -102
- package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +0 -71
- package/pennyfarthing-dist/scripts/hooks/pre-push.sh +0 -42
- package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +0 -20
- package/pennyfarthing-dist/scripts/hooks/question_reflector_check.py +0 -499
- package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +0 -30
- package/pennyfarthing-dist/scripts/hooks/session-start.sh +0 -97
- package/pennyfarthing-dist/scripts/hooks/session-stop.sh +0 -65
- package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +0 -78
- package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +0 -94
- package/pennyfarthing-dist/scripts/jira/README.md +0 -36
- package/pennyfarthing-dist/scripts/jira/create-jira-epic.sh +0 -95
- package/pennyfarthing-dist/scripts/jira/create-jira-story.sh +0 -91
- package/pennyfarthing-dist/scripts/jira/jira-claim-story.sh +0 -22
- package/pennyfarthing-dist/scripts/jira/jira-lib.sh +0 -464
- package/pennyfarthing-dist/scripts/jira/jira-reconcile.sh +0 -260
- package/pennyfarthing-dist/scripts/jira/jira-sync-story.sh +0 -18
- package/pennyfarthing-dist/scripts/jira/jira-sync.sh +0 -16
- package/pennyfarthing-dist/scripts/jira/sync-epic-jira.sh +0 -16
- package/pennyfarthing-dist/scripts/jira/sync-epic-to-jira.sh +0 -16
- package/pennyfarthing-dist/scripts/lib/README.md +0 -29
- package/pennyfarthing-dist/scripts/lib/background-tasks.sh +0 -177
- package/pennyfarthing-dist/scripts/lib/checkpoint.sh +0 -136
- package/pennyfarthing-dist/scripts/lib/common.sh +0 -212
- package/pennyfarthing-dist/scripts/lib/file-lock.sh +0 -269
- package/pennyfarthing-dist/scripts/lib/find-root.sh +0 -58
- package/pennyfarthing-dist/scripts/lib/logging.sh +0 -186
- package/pennyfarthing-dist/scripts/lib/retry.sh +0 -76
- package/pennyfarthing-dist/scripts/maintenance/migrate-theme-schema.mjs +0 -102
- package/pennyfarthing-dist/scripts/maintenance/sidecar-health.sh +0 -91
- package/pennyfarthing-dist/scripts/misc/README.md +0 -44
- package/pennyfarthing-dist/scripts/misc/add-short-names.sh +0 -13
- package/pennyfarthing-dist/scripts/misc/add_short_names.py +0 -226
- package/pennyfarthing-dist/scripts/misc/backlog.sh +0 -77
- package/pennyfarthing-dist/scripts/misc/check-status.sh +0 -247
- package/pennyfarthing-dist/scripts/misc/find-related-work.sh +0 -231
- package/pennyfarthing-dist/scripts/misc/generate-skill-docs.sh +0 -107
- package/pennyfarthing-dist/scripts/misc/log-skill-usage.sh +0 -74
- package/pennyfarthing-dist/scripts/misc/migrate-bmad-workflow.sh +0 -10
- package/pennyfarthing-dist/scripts/misc/migrate_bmad_workflow.py +0 -319
- package/pennyfarthing-dist/scripts/misc/repo-scan.sh +0 -141
- package/pennyfarthing-dist/scripts/misc/repo-utils.sh +0 -778
- package/pennyfarthing-dist/scripts/misc/run-ci.sh +0 -212
- package/pennyfarthing-dist/scripts/misc/run-timestamp.sh +0 -7
- package/pennyfarthing-dist/scripts/misc/session-cleanup.sh +0 -319
- package/pennyfarthing-dist/scripts/misc/skill-usage-report.sh +0 -193
- package/pennyfarthing-dist/scripts/misc/statusline.sh +0 -259
- package/pennyfarthing-dist/scripts/misc/uninstall.sh +0 -275
- package/pennyfarthing-dist/scripts/misc/validate-subagent-frontmatter.sh +0 -160
- package/pennyfarthing-dist/scripts/portraits/generate-portraits.py +0 -417
- package/pennyfarthing-dist/scripts/portraits/generate-portraits.sh +0 -54
- package/pennyfarthing-dist/scripts/sprint/README.md +0 -29
- package/pennyfarthing-dist/scripts/sprint/archive-story.sh +0 -133
- package/pennyfarthing-dist/scripts/sprint/available-stories.sh +0 -91
- package/pennyfarthing-dist/scripts/sprint/check-story.sh +0 -158
- package/pennyfarthing-dist/scripts/sprint/get-epic-field.sh +0 -52
- package/pennyfarthing-dist/scripts/sprint/get-story-field.sh +0 -63
- package/pennyfarthing-dist/scripts/sprint/list-future.sh +0 -145
- package/pennyfarthing-dist/scripts/sprint/new-sprint.sh +0 -110
- package/pennyfarthing-dist/scripts/sprint/promote-epic.sh +0 -148
- package/pennyfarthing-dist/scripts/sprint/sprint-common.sh +0 -415
- package/pennyfarthing-dist/scripts/sprint/sprint-info.sh +0 -33
- package/pennyfarthing-dist/scripts/sprint/sprint-metrics.sh +0 -230
- package/pennyfarthing-dist/scripts/sprint/sprint-status.sh +0 -134
- package/pennyfarthing-dist/scripts/sprint/validate-sprint-yaml.sh +0 -139
- package/pennyfarthing-dist/scripts/story/README.md +0 -23
- package/pennyfarthing-dist/scripts/story/create-story.sh +0 -19
- package/pennyfarthing-dist/scripts/story/size-story.sh +0 -18
- package/pennyfarthing-dist/scripts/story/story-template.sh +0 -18
- package/pennyfarthing-dist/scripts/test/README.md +0 -23
- package/pennyfarthing-dist/scripts/test/ensure-swebench-data.sh +0 -59
- package/pennyfarthing-dist/scripts/test/ground-truth-judge.py +0 -220
- package/pennyfarthing-dist/scripts/test/swebench-judge.py +0 -374
- package/pennyfarthing-dist/scripts/test/test-cache.sh +0 -165
- package/pennyfarthing-dist/scripts/test/test-setup.sh +0 -337
- package/pennyfarthing-dist/scripts/tests/check.test.sh +0 -582
- package/pennyfarthing-dist/scripts/tests/dev-story-workflow-import.test.sh +0 -515
- package/pennyfarthing-dist/scripts/tests/epics-and-stories-workflow-import.test.sh +0 -599
- package/pennyfarthing-dist/scripts/tests/handoff-phase-update.test.sh +0 -332
- package/pennyfarthing-dist/scripts/tests/implementation-readiness-workflow-import.test.sh +0 -573
- package/pennyfarthing-dist/scripts/tests/migrate-bmad-workflow.test.sh +0 -859
- package/pennyfarthing-dist/scripts/tests/prd-workflow-import.test.sh +0 -662
- package/pennyfarthing-dist/scripts/tests/project-context-workflow-import.test.sh +0 -589
- package/pennyfarthing-dist/scripts/tests/test-character-voice.sh +0 -106
- package/pennyfarthing-dist/scripts/tests/test-drift-detection.sh +0 -597
- package/pennyfarthing-dist/scripts/tests/test-post-merge-hook.sh +0 -514
- package/pennyfarthing-dist/scripts/tests/test-session-checkpoint.sh +0 -517
- package/pennyfarthing-dist/scripts/tests/test-solo-command.sh +0 -331
- package/pennyfarthing-dist/scripts/tests/ux-design-workflow-import.test.sh +0 -647
- package/pennyfarthing-dist/scripts/theme/README.md +0 -22
- package/pennyfarthing-dist/scripts/theme/compute-theme-tiers.sh +0 -13
- package/pennyfarthing-dist/scripts/theme/compute_theme_tiers.py +0 -402
- package/pennyfarthing-dist/scripts/theme/list-themes.sh +0 -30
- package/pennyfarthing-dist/scripts/theme/update-theme-tiers.sh +0 -97
- package/pennyfarthing-dist/scripts/validation/validate-agent-schema.sh +0 -576
- package/pennyfarthing-dist/scripts/workflow/README.md +0 -28
- package/pennyfarthing-dist/scripts/workflow/check.py +0 -502
- package/pennyfarthing-dist/scripts/workflow/check.sh +0 -24
- package/pennyfarthing-dist/scripts/workflow/finish-story.sh +0 -154
- package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +0 -222
- package/pennyfarthing-dist/scripts/workflow/get-workflow-type.py +0 -61
- package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +0 -13
- package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +0 -124
- package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +0 -34
- package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +0 -157
- package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +0 -132
- package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +0 -250
- package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +0 -161
- package/pennyfarthing-dist/skills/agentic-patterns/SKILL.md +0 -246
- package/pennyfarthing-dist/skills/changelog/SKILL.md +0 -385
- package/pennyfarthing-dist/skills/code-review/SKILL.md +0 -172
- package/pennyfarthing-dist/skills/context-engineering/SKILL.md +0 -277
- package/pennyfarthing-dist/skills/cyclist/SKILL.md +0 -88
- package/pennyfarthing-dist/skills/dev-patterns/SKILL.md +0 -461
- package/pennyfarthing-dist/skills/finalize-run/SKILL.md +0 -261
- package/pennyfarthing-dist/skills/jira/SKILL.md +0 -508
- package/pennyfarthing-dist/skills/judge/SKILL.md +0 -644
- package/pennyfarthing-dist/skills/just/SKILL.md +0 -414
- package/pennyfarthing-dist/skills/mermaid/SKILL.md +0 -256
- package/pennyfarthing-dist/skills/otel/skill.md +0 -227
- package/pennyfarthing-dist/skills/permissions/skill.md +0 -175
- package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +0 -187
- package/pennyfarthing-dist/skills/skill-registry.schema.json +0 -107
- package/pennyfarthing-dist/skills/skill-registry.yaml +0 -393
- package/pennyfarthing-dist/skills/sprint/scripts/archive-story.sh +0 -101
- package/pennyfarthing-dist/skills/sprint/scripts/available-stories.sh +0 -97
- package/pennyfarthing-dist/skills/sprint/scripts/check-story.sh +0 -164
- package/pennyfarthing-dist/skills/sprint/scripts/create-jira-epic.sh +0 -101
- package/pennyfarthing-dist/skills/sprint/scripts/new-sprint.sh +0 -116
- package/pennyfarthing-dist/skills/sprint/scripts/promote-epic.sh +0 -164
- package/pennyfarthing-dist/skills/sprint/scripts/sprint-info.sh +0 -39
- package/pennyfarthing-dist/skills/sprint/scripts/sprint-status.sh +0 -147
- package/pennyfarthing-dist/skills/sprint/scripts/sync-epic-jira.sh +0 -93
- package/pennyfarthing-dist/skills/sprint/skill.md +0 -465
- package/pennyfarthing-dist/skills/story/scripts/create-story.sh +0 -159
- package/pennyfarthing-dist/skills/story/scripts/size-story.sh +0 -198
- package/pennyfarthing-dist/skills/story/scripts/story-template.sh +0 -162
- package/pennyfarthing-dist/skills/story/skill.md +0 -219
- package/pennyfarthing-dist/skills/systematic-debugging/SKILL.md +0 -446
- package/pennyfarthing-dist/skills/testing/SKILL.md +0 -121
- package/pennyfarthing-dist/skills/testing/references/troubleshooting.md +0 -124
- package/pennyfarthing-dist/skills/theme/skill.md +0 -141
- package/pennyfarthing-dist/skills/theme-creation/SKILL.md +0 -178
- package/pennyfarthing-dist/skills/workflow/scripts/list-workflows.sh +0 -91
- package/pennyfarthing-dist/skills/workflow/scripts/resume-workflow.sh +0 -163
- package/pennyfarthing-dist/skills/workflow/scripts/show-workflow.sh +0 -138
- package/pennyfarthing-dist/skills/workflow/scripts/start-workflow.sh +0 -273
- package/pennyfarthing-dist/skills/workflow/scripts/workflow-status.sh +0 -167
- package/pennyfarthing-dist/skills/workflow/skill.md +0 -345
- package/pennyfarthing-dist/skills/yq/SKILL.md +0 -272
- package/pennyfarthing-dist/templates/LEADERBOARD.schema.yaml +0 -187
- package/pennyfarthing-dist/templates/LEADERBOARD.template.md +0 -59
- package/pennyfarthing-dist/templates/agent-scopes.yaml.template +0 -276
- package/pennyfarthing-dist/templates/pennyfarthing-settings.yaml.template +0 -61
- package/pennyfarthing-dist/templates/persona-config.yaml.template +0 -22
- package/pennyfarthing-dist/templates/preferences.yaml.template +0 -15
- package/pennyfarthing-dist/templates/settings.local.json.template +0 -110
- package/pennyfarthing-dist/templates/setup-env.sh.template +0 -18
- package/pennyfarthing-dist/templates/shared-context.md.template +0 -70
- package/pennyfarthing-dist/templates/sidecar/decisions.md.template +0 -40
- package/pennyfarthing-dist/templates/sidecar/gotchas.md.template +0 -37
- package/pennyfarthing-dist/templates/sidecar/patterns.md.template +0 -34
- package/pennyfarthing-dist/workflows/agent-docs.yaml +0 -70
- package/pennyfarthing-dist/workflows/architecture/steps/step-01-initialize.md +0 -113
- package/pennyfarthing-dist/workflows/architecture/steps/step-01b-continue.md +0 -105
- package/pennyfarthing-dist/workflows/architecture/steps/step-02-context.md +0 -127
- package/pennyfarthing-dist/workflows/architecture/steps/step-03-patterns.md +0 -145
- package/pennyfarthing-dist/workflows/architecture/steps/step-04-components.md +0 -150
- package/pennyfarthing-dist/workflows/architecture/steps/step-05-interfaces.md +0 -145
- package/pennyfarthing-dist/workflows/architecture/steps/step-06-risks.md +0 -154
- package/pennyfarthing-dist/workflows/architecture/steps/step-07-document.md +0 -172
- package/pennyfarthing-dist/workflows/architecture/templates/architecture-decision.md +0 -102
- package/pennyfarthing-dist/workflows/architecture.yaml +0 -65
- package/pennyfarthing-dist/workflows/bdd.yaml +0 -60
- package/pennyfarthing-dist/workflows/brainstorming/brain-methods.csv +0 -62
- package/pennyfarthing-dist/workflows/brainstorming/checklist.md +0 -44
- package/pennyfarthing-dist/workflows/brainstorming/instructions.md +0 -736
- package/pennyfarthing-dist/workflows/brainstorming/workflow.yaml +0 -49
- package/pennyfarthing-dist/workflows/code-review/checklist.md +0 -23
- package/pennyfarthing-dist/workflows/code-review/instructions.md +0 -234
- package/pennyfarthing-dist/workflows/code-review/workflow.yaml +0 -51
- package/pennyfarthing-dist/workflows/dev-story/checklist.md +0 -80
- package/pennyfarthing-dist/workflows/dev-story/instructions.xml +0 -410
- package/pennyfarthing-dist/workflows/dev-story/workflow.yaml +0 -50
- package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-01-validate-prerequisites.md +0 -281
- package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-02-design-epics.md +0 -256
- package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-03-create-stories.md +0 -298
- package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-04-final-validation.md +0 -177
- package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +0 -145
- package/pennyfarthing-dist/workflows/epics-and-stories/templates/epics-template.md +0 -57
- package/pennyfarthing-dist/workflows/epics-and-stories/workflow.yaml +0 -28
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +0 -103
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-02-categorize.md +0 -147
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-03-execute.md +0 -215
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +0 -97
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +0 -78
- package/pennyfarthing-dist/workflows/git-cleanup.yaml +0 -59
- package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-01-document-discovery.md +0 -211
- package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-02-prd-analysis.md +0 -199
- package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-03-epic-coverage-validation.md +0 -202
- package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-04-ux-alignment.md +0 -162
- package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-05-epic-quality-review.md +0 -280
- package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-06-final-assessment.md +0 -158
- package/pennyfarthing-dist/workflows/implementation-readiness/templates/readiness-report-template.md +0 -4
- package/pennyfarthing-dist/workflows/implementation-readiness/workflow.yaml +0 -40
- package/pennyfarthing-dist/workflows/interactive-debug/steps/step-01-connect.md +0 -257
- package/pennyfarthing-dist/workflows/interactive-debug/steps/step-02-explore.md +0 -107
- package/pennyfarthing-dist/workflows/interactive-debug/steps/step-03-fix.md +0 -127
- package/pennyfarthing-dist/workflows/interactive-debug/steps/step-04-commit.md +0 -122
- package/pennyfarthing-dist/workflows/interactive-debug/workflow.yaml +0 -51
- package/pennyfarthing-dist/workflows/patch.yaml +0 -67
- package/pennyfarthing-dist/workflows/prd/data/domain-complexity.csv +0 -13
- package/pennyfarthing-dist/workflows/prd/data/prd-purpose.md +0 -197
- package/pennyfarthing-dist/workflows/prd/data/project-types.csv +0 -11
- package/pennyfarthing-dist/workflows/prd/steps-c/step-01-init.md +0 -197
- package/pennyfarthing-dist/workflows/prd/steps-c/step-01b-continue.md +0 -159
- package/pennyfarthing-dist/workflows/prd/steps-c/step-02-discovery.md +0 -230
- package/pennyfarthing-dist/workflows/prd/steps-c/step-03-success.md +0 -232
- package/pennyfarthing-dist/workflows/prd/steps-c/step-04-journeys.md +0 -219
- package/pennyfarthing-dist/workflows/prd/steps-c/step-05-domain.md +0 -213
- package/pennyfarthing-dist/workflows/prd/steps-c/step-06-innovation.md +0 -232
- package/pennyfarthing-dist/workflows/prd/steps-c/step-07-project-type.md +0 -243
- package/pennyfarthing-dist/workflows/prd/steps-c/step-08-scoping.md +0 -234
- package/pennyfarthing-dist/workflows/prd/steps-c/step-09-functional.md +0 -237
- package/pennyfarthing-dist/workflows/prd/steps-c/step-10-nonfunctional.md +0 -248
- package/pennyfarthing-dist/workflows/prd/steps-c/step-11-polish.md +0 -223
- package/pennyfarthing-dist/workflows/prd/steps-c/step-12-complete.md +0 -186
- package/pennyfarthing-dist/workflows/prd/steps-e/step-e-01-discovery.md +0 -253
- package/pennyfarthing-dist/workflows/prd/steps-e/step-e-01b-legacy-conversion.md +0 -214
- package/pennyfarthing-dist/workflows/prd/steps-e/step-e-02-review.md +0 -255
- package/pennyfarthing-dist/workflows/prd/steps-e/step-e-03-edit.md +0 -259
- package/pennyfarthing-dist/workflows/prd/steps-e/step-e-04-complete.md +0 -174
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-01-discovery.md +0 -224
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-02-format-detection.md +0 -197
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-02b-parity-check.md +0 -215
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-03-density-validation.md +0 -180
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-04-brief-coverage-validation.md +0 -220
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-05-measurability-validation.md +0 -234
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-06-traceability-validation.md +0 -223
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-07-implementation-leakage-validation.md +0 -211
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-08-domain-compliance-validation.md +0 -249
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-09-project-type-validation.md +0 -269
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-10-smart-validation.md +0 -215
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-11-holistic-quality-validation.md +0 -270
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-12-completeness-validation.md +0 -248
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-13-report-complete.md +0 -238
- package/pennyfarthing-dist/workflows/prd/templates/prd-template.md +0 -10
- package/pennyfarthing-dist/workflows/prd/workflow.yaml +0 -42
- package/pennyfarthing-dist/workflows/product-brief/steps/step-01-init.md +0 -195
- package/pennyfarthing-dist/workflows/product-brief/steps/step-01b-continue.md +0 -180
- package/pennyfarthing-dist/workflows/product-brief/steps/step-02-vision.md +0 -221
- package/pennyfarthing-dist/workflows/product-brief/steps/step-03-users.md +0 -224
- package/pennyfarthing-dist/workflows/product-brief/steps/step-04-metrics.md +0 -228
- package/pennyfarthing-dist/workflows/product-brief/steps/step-05-scope.md +0 -243
- package/pennyfarthing-dist/workflows/product-brief/steps/step-06-complete.md +0 -216
- package/pennyfarthing-dist/workflows/product-brief/templates/product-brief.template.md +0 -10
- package/pennyfarthing-dist/workflows/product-brief/workflow.yaml +0 -31
- package/pennyfarthing-dist/workflows/project-context/project-context-template.md +0 -21
- package/pennyfarthing-dist/workflows/project-context/steps/step-01-discover.md +0 -206
- package/pennyfarthing-dist/workflows/project-context/steps/step-02-generate.md +0 -349
- package/pennyfarthing-dist/workflows/project-context/steps/step-03-complete.md +0 -306
- package/pennyfarthing-dist/workflows/project-context/workflow.yaml +0 -27
- package/pennyfarthing-dist/workflows/project-setup/steps/step-01-discover.md +0 -157
- package/pennyfarthing-dist/workflows/project-setup/steps/step-02-clone-repos.md +0 -217
- package/pennyfarthing-dist/workflows/project-setup/steps/step-03-repos-yaml.md +0 -159
- package/pennyfarthing-dist/workflows/project-setup/steps/step-04-claude-md.md +0 -186
- package/pennyfarthing-dist/workflows/project-setup/steps/step-05-shared-context.md +0 -185
- package/pennyfarthing-dist/workflows/project-setup/steps/step-06-task-runner.md +0 -279
- package/pennyfarthing-dist/workflows/project-setup/steps/step-07-theme.md +0 -200
- package/pennyfarthing-dist/workflows/project-setup/steps/step-08-theme-packs.md +0 -142
- package/pennyfarthing-dist/workflows/project-setup/steps/step-09-cyclist.md +0 -245
- package/pennyfarthing-dist/workflows/project-setup/steps/step-10-complete.md +0 -204
- package/pennyfarthing-dist/workflows/project-setup/workflow.yaml +0 -41
- package/pennyfarthing-dist/workflows/quick-dev/steps/step-01-mode-detection.md +0 -177
- package/pennyfarthing-dist/workflows/quick-dev/steps/step-02-context-gathering.md +0 -143
- package/pennyfarthing-dist/workflows/quick-dev/steps/step-03-execute.md +0 -138
- package/pennyfarthing-dist/workflows/quick-dev/steps/step-04-self-check.md +0 -135
- package/pennyfarthing-dist/workflows/quick-dev/steps/step-05-adversarial-review.md +0 -129
- package/pennyfarthing-dist/workflows/quick-dev/steps/step-06-resolve-findings.md +0 -163
- package/pennyfarthing-dist/workflows/quick-dev/workflow.yaml +0 -27
- package/pennyfarthing-dist/workflows/quick-spec/steps/step-01-understand.md +0 -201
- package/pennyfarthing-dist/workflows/quick-spec/steps/step-02-investigate.md +0 -156
- package/pennyfarthing-dist/workflows/quick-spec/steps/step-03-generate.md +0 -140
- package/pennyfarthing-dist/workflows/quick-spec/steps/step-04-review.md +0 -203
- package/pennyfarthing-dist/workflows/quick-spec/tech-spec-template.md +0 -74
- package/pennyfarthing-dist/workflows/quick-spec/workflow.yaml +0 -27
- package/pennyfarthing-dist/workflows/research/steps-domain/step-01-init.md +0 -159
- package/pennyfarthing-dist/workflows/research/steps-domain/step-02-domain-analysis.md +0 -253
- package/pennyfarthing-dist/workflows/research/steps-domain/step-03-competitive-landscape.md +0 -263
- package/pennyfarthing-dist/workflows/research/steps-domain/step-04-regulatory-focus.md +0 -232
- package/pennyfarthing-dist/workflows/research/steps-domain/step-05-technical-trends.md +0 -260
- package/pennyfarthing-dist/workflows/research/steps-domain/step-06-research-synthesis.md +0 -477
- package/pennyfarthing-dist/workflows/research/steps-market/step-01-init.md +0 -205
- package/pennyfarthing-dist/workflows/research/steps-market/step-02-customer-behavior.md +0 -262
- package/pennyfarthing-dist/workflows/research/steps-market/step-02-customer-insights.md +0 -227
- package/pennyfarthing-dist/workflows/research/steps-market/step-03-customer-pain-points.md +0 -275
- package/pennyfarthing-dist/workflows/research/steps-market/step-04-customer-decisions.md +0 -286
- package/pennyfarthing-dist/workflows/research/steps-market/step-05-competitive-analysis.md +0 -203
- package/pennyfarthing-dist/workflows/research/steps-market/step-06-research-completion.md +0 -510
- package/pennyfarthing-dist/workflows/research/steps-technical/step-01-init.md +0 -159
- package/pennyfarthing-dist/workflows/research/steps-technical/step-02-technical-overview.md +0 -264
- package/pennyfarthing-dist/workflows/research/steps-technical/step-03-integration-patterns.md +0 -274
- package/pennyfarthing-dist/workflows/research/steps-technical/step-04-architectural-patterns.md +0 -228
- package/pennyfarthing-dist/workflows/research/steps-technical/step-05-implementation-research.md +0 -267
- package/pennyfarthing-dist/workflows/research/steps-technical/step-06-research-synthesis.md +0 -522
- package/pennyfarthing-dist/workflows/research/templates/research.template.md +0 -29
- package/pennyfarthing-dist/workflows/research/workflow.yaml +0 -45
- package/pennyfarthing-dist/workflows/retrospective/checklist.md +0 -31
- package/pennyfarthing-dist/workflows/retrospective/instructions.md +0 -1443
- package/pennyfarthing-dist/workflows/retrospective/workflow.yaml +0 -50
- package/pennyfarthing-dist/workflows/sprint-planning/checklist.md +0 -33
- package/pennyfarthing-dist/workflows/sprint-planning/sprint-status-template.yaml +0 -55
- package/pennyfarthing-dist/workflows/sprint-planning/steps/step-01-parse-epic-files.md +0 -69
- package/pennyfarthing-dist/workflows/sprint-planning/steps/step-02-build-sprint-status.md +0 -61
- package/pennyfarthing-dist/workflows/sprint-planning/steps/step-03-status-detection.md +0 -80
- package/pennyfarthing-dist/workflows/sprint-planning/steps/step-04-generate-status-file.md +0 -90
- package/pennyfarthing-dist/workflows/sprint-planning/steps/step-05-validate-and-report.md +0 -78
- package/pennyfarthing-dist/workflows/sprint-planning/workflow.yaml +0 -34
- package/pennyfarthing-dist/workflows/tdd.yaml +0 -50
- package/pennyfarthing-dist/workflows/trivial.yaml +0 -40
- package/pennyfarthing-dist/workflows/ux-design/steps/step-01-init.md +0 -141
- package/pennyfarthing-dist/workflows/ux-design/steps/step-01b-continue.md +0 -133
- package/pennyfarthing-dist/workflows/ux-design/steps/step-02-discovery.md +0 -196
- package/pennyfarthing-dist/workflows/ux-design/steps/step-03-core-experience.md +0 -222
- package/pennyfarthing-dist/workflows/ux-design/steps/step-04-emotional-response.md +0 -225
- package/pennyfarthing-dist/workflows/ux-design/steps/step-05-inspiration.md +0 -240
- package/pennyfarthing-dist/workflows/ux-design/steps/step-06-design-system.md +0 -258
- package/pennyfarthing-dist/workflows/ux-design/steps/step-07-defining-experience.md +0 -260
- package/pennyfarthing-dist/workflows/ux-design/steps/step-08-visual-foundation.md +0 -230
- package/pennyfarthing-dist/workflows/ux-design/steps/step-09-design-directions.md +0 -230
- package/pennyfarthing-dist/workflows/ux-design/steps/step-10-user-journeys.md +0 -247
- package/pennyfarthing-dist/workflows/ux-design/steps/step-11-component-strategy.md +0 -254
- package/pennyfarthing-dist/workflows/ux-design/steps/step-12-ux-patterns.md +0 -243
- package/pennyfarthing-dist/workflows/ux-design/steps/step-13-responsive-accessibility.md +0 -270
- package/pennyfarthing-dist/workflows/ux-design/steps/step-14-complete.md +0 -234
- package/pennyfarthing-dist/workflows/ux-design/ux-design-template.md +0 -13
- package/pennyfarthing-dist/workflows/ux-design/workflow.yaml +0 -41
- package/pennyfarthing_scripts/README.md +0 -66
- package/pennyfarthing_scripts/__init__.py +0 -17
- package/pennyfarthing_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/__init__.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__/hooks.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/output.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/patch_mode.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/sprint.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/workflow.cpython-311.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bellmode_hook.py +0 -154
- package/pennyfarthing_scripts/brownfield/__init__.py +0 -35
- package/pennyfarthing_scripts/brownfield/__main__.py +0 -7
- 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/brownfield/cli.py +0 -131
- package/pennyfarthing_scripts/brownfield/discover.py +0 -753
- package/pennyfarthing_scripts/cli.py +0 -174
- package/pennyfarthing_scripts/common/__init__.py +0 -49
- 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 +0 -91
- package/pennyfarthing_scripts/common/output.py +0 -180
- package/pennyfarthing_scripts/common/themes.py +0 -253
- package/pennyfarthing_scripts/config.py +0 -21
- package/pennyfarthing_scripts/context.py +0 -414
- package/pennyfarthing_scripts/git/__init__.py +0 -29
- package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/create_branches.py +0 -439
- package/pennyfarthing_scripts/git/status_all.py +0 -310
- package/pennyfarthing_scripts/hooks.py +0 -455
- package/pennyfarthing_scripts/jira/__init__.py +0 -93
- package/pennyfarthing_scripts/jira/__main__.py +0 -10
- package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/compat.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/mappings.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/bidirectional.py +0 -561
- package/pennyfarthing_scripts/jira/claim.py +0 -211
- package/pennyfarthing_scripts/jira/cli.py +0 -150
- package/pennyfarthing_scripts/jira/client.py +0 -613
- package/pennyfarthing_scripts/jira/epic.py +0 -176
- package/pennyfarthing_scripts/jira/story.py +0 -219
- package/pennyfarthing_scripts/jira/sync.py +0 -350
- package/pennyfarthing_scripts/jira_bidirectional_sync.py +0 -37
- package/pennyfarthing_scripts/jira_epic_creation.py +0 -30
- package/pennyfarthing_scripts/jira_sync.py +0 -36
- package/pennyfarthing_scripts/jira_sync_story.py +0 -30
- package/pennyfarthing_scripts/migration/__init__.py +0 -39
- package/pennyfarthing_scripts/migration/__main__.py +0 -10
- package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/cli.py +0 -304
- package/pennyfarthing_scripts/migration/session.py +0 -384
- package/pennyfarthing_scripts/migration/skill.py +0 -188
- package/pennyfarthing_scripts/migration/step.py +0 -229
- package/pennyfarthing_scripts/migration/validate.py +0 -282
- package/pennyfarthing_scripts/output.py +0 -37
- package/pennyfarthing_scripts/patch_mode.py +0 -449
- package/pennyfarthing_scripts/preflight/__init__.py +0 -17
- package/pennyfarthing_scripts/preflight/__main__.py +0 -10
- 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/preflight/cli.py +0 -141
- package/pennyfarthing_scripts/preflight/finish.py +0 -382
- package/pennyfarthing_scripts/pretooluse_hook.py +0 -142
- package/pennyfarthing_scripts/prime/__init__.py +0 -125
- package/pennyfarthing_scripts/prime/__main__.py +0 -8
- package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/cli.py +0 -645
- package/pennyfarthing_scripts/prime/loader.py +0 -239
- package/pennyfarthing_scripts/prime/models.py +0 -206
- package/pennyfarthing_scripts/prime/persona.py +0 -308
- package/pennyfarthing_scripts/prime/session.py +0 -183
- package/pennyfarthing_scripts/prime/tiers.py +0 -201
- package/pennyfarthing_scripts/prime/workflow.py +0 -275
- package/pennyfarthing_scripts/schema_validation_hook.py +0 -306
- package/pennyfarthing_scripts/sprint/__init__.py +0 -66
- package/pennyfarthing_scripts/sprint/__main__.py +0 -10
- 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__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/status.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/archive.py +0 -108
- package/pennyfarthing_scripts/sprint/archive_epic.py +0 -399
- package/pennyfarthing_scripts/sprint/cli.py +0 -284
- package/pennyfarthing_scripts/sprint/import_epic.py +0 -431
- package/pennyfarthing_scripts/sprint/loader.py +0 -193
- package/pennyfarthing_scripts/sprint/status.py +0 -122
- package/pennyfarthing_scripts/sprint/validator.py +0 -405
- package/pennyfarthing_scripts/sprint/work.py +0 -192
- package/pennyfarthing_scripts/story/__init__.py +0 -67
- package/pennyfarthing_scripts/story/__main__.py +0 -10
- 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/story/cli.py +0 -105
- package/pennyfarthing_scripts/story/create.py +0 -167
- package/pennyfarthing_scripts/story/size.py +0 -113
- package/pennyfarthing_scripts/story/template.py +0 -151
- package/pennyfarthing_scripts/swebench.py +0 -216
- package/pennyfarthing_scripts/tests/__init__.py +0 -1
- 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_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_common.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_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.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_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_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/conftest.py +0 -106
- package/pennyfarthing_scripts/tests/test_brownfield.py +0 -842
- package/pennyfarthing_scripts/tests/test_cli_modules.py +0 -245
- package/pennyfarthing_scripts/tests/test_common.py +0 -180
- package/pennyfarthing_scripts/tests/test_git_utils.py +0 -866
- package/pennyfarthing_scripts/tests/test_jira_package.py +0 -334
- package/pennyfarthing_scripts/tests/test_package_structure.py +0 -372
- package/pennyfarthing_scripts/tests/test_patch_mode.py +0 -830
- package/pennyfarthing_scripts/tests/test_prime.py +0 -1050
- package/pennyfarthing_scripts/tests/test_sprint_package.py +0 -236
- package/pennyfarthing_scripts/tests/test_sprint_validator.py +0 -675
- package/pennyfarthing_scripts/tests/test_story_package.py +0 -156
- package/pennyfarthing_scripts/tests/test_tiers.py +0 -1090
- package/pennyfarthing_scripts/tests/test_token_counting.py +0 -559
- package/pennyfarthing_scripts/tests/test_workflow_check.py +0 -341
- package/pennyfarthing_scripts/welcome_hook.py +0 -157
- package/pennyfarthing_scripts/workflow.py +0 -287
- /package/{packages/core/bin → bin}/pennyfarthing.js +0 -0
- /package/{packages/core/dist → dist}/bmad/context-reader.d.ts +0 -0
- /package/{packages/core/dist → dist}/bmad/context-reader.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/bmad/context-reader.js +0 -0
- /package/{packages/core/dist → dist}/bmad/context-reader.js.map +0 -0
- /package/{packages/core/dist → dist}/bmad/context-reader.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/bmad/context-reader.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/bmad/context-reader.test.js +0 -0
- /package/{packages/core/dist → dist}/bmad/context-reader.test.js.map +0 -0
- /package/{packages/core/dist → dist}/bmad/epics-parser.d.ts +0 -0
- /package/{packages/core/dist → dist}/bmad/epics-parser.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/bmad/epics-parser.js +0 -0
- /package/{packages/core/dist → dist}/bmad/epics-parser.js.map +0 -0
- /package/{packages/core/dist → dist}/bmad/epics-parser.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/bmad/epics-parser.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/bmad/epics-parser.test.js +0 -0
- /package/{packages/core/dist → dist}/bmad/epics-parser.test.js.map +0 -0
- /package/{packages/core/dist → dist}/bmad/index.d.ts +0 -0
- /package/{packages/core/dist → dist}/bmad/index.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/bmad/index.js +0 -0
- /package/{packages/core/dist → dist}/bmad/index.js.map +0 -0
- /package/{packages/core/dist → dist}/bmad/status-sync.d.ts +0 -0
- /package/{packages/core/dist → dist}/bmad/status-sync.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/bmad/status-sync.js +0 -0
- /package/{packages/core/dist → dist}/bmad/status-sync.js.map +0 -0
- /package/{packages/core/dist → dist}/bmad/status-sync.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/bmad/status-sync.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/bmad/status-sync.test.js +0 -0
- /package/{packages/core/dist → dist}/bmad/status-sync.test.js.map +0 -0
- /package/{packages/core/dist → dist}/bmad/story-exporter.d.ts +0 -0
- /package/{packages/core/dist → dist}/bmad/story-exporter.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/bmad/story-exporter.js +0 -0
- /package/{packages/core/dist → dist}/bmad/story-exporter.js.map +0 -0
- /package/{packages/core/dist → dist}/bmad/story-exporter.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/bmad/story-exporter.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/bmad/story-exporter.test.js +0 -0
- /package/{packages/core/dist → dist}/bmad/story-exporter.test.js.map +0 -0
- /package/{packages/core/dist → dist}/bmad/story-parser.d.ts +0 -0
- /package/{packages/core/dist → dist}/bmad/story-parser.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/bmad/story-parser.js +0 -0
- /package/{packages/core/dist → dist}/bmad/story-parser.js.map +0 -0
- /package/{packages/core/dist → dist}/bmad/story-parser.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/bmad/story-parser.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/bmad/story-parser.test.js +0 -0
- /package/{packages/core/dist → dist}/bmad/story-parser.test.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/command.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/commands/command.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/command.js +0 -0
- /package/{packages/core/dist → dist}/cli/commands/command.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/cyclist.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/commands/cyclist.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/cyclist.js +0 -0
- /package/{packages/core/dist → dist}/cli/commands/cyclist.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/cyclist.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/commands/cyclist.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/cyclist.test.js +0 -0
- /package/{packages/core/dist → dist}/cli/commands/cyclist.test.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/doctor-legacy.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/commands/doctor-legacy.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/doctor-legacy.test.js +0 -0
- /package/{packages/core/dist → dist}/cli/commands/doctor-legacy.test.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/doctor.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/commands/doctor.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/doctor.js +0 -0
- /package/{packages/core/dist → dist}/cli/commands/doctor.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/init.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/commands/init.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/init.js +0 -0
- /package/{packages/core/dist → dist}/cli/commands/init.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/skill.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/commands/skill.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/skill.js +0 -0
- /package/{packages/core/dist → dist}/cli/commands/skill.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/theme.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/commands/theme.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/theme.js +0 -0
- /package/{packages/core/dist → dist}/cli/commands/theme.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/uninstall.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/commands/uninstall.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/uninstall.js +0 -0
- /package/{packages/core/dist → dist}/cli/commands/uninstall.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/update.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/commands/update.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/update.js +0 -0
- /package/{packages/core/dist → dist}/cli/commands/update.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/version.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/commands/version.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/commands/version.js +0 -0
- /package/{packages/core/dist → dist}/cli/commands/version.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/customization.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/customization.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/customization.test.js +0 -0
- /package/{packages/core/dist → dist}/cli/customization.test.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/cyclist-migration.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/cyclist-migration.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/cyclist-migration.test.js +0 -0
- /package/{packages/core/dist → dist}/cli/cyclist-migration.test.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/index.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/index.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/index.js +0 -0
- /package/{packages/core/dist → dist}/cli/index.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/ocean-profiles.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/ocean-profiles.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/ocean-profiles.test.js +0 -0
- /package/{packages/core/dist → dist}/cli/ocean-profiles.test.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/theme-maker.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/theme-maker.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/theme-maker.test.js +0 -0
- /package/{packages/core/dist → dist}/cli/theme-maker.test.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/constants.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/utils/constants.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/constants.js +0 -0
- /package/{packages/core/dist → dist}/cli/utils/constants.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/files.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/utils/files.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/files.js +0 -0
- /package/{packages/core/dist → dist}/cli/utils/files.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/logger.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/utils/logger.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/logger.js +0 -0
- /package/{packages/core/dist → dist}/cli/utils/logger.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/manifest.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/utils/manifest.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/manifest.js +0 -0
- /package/{packages/core/dist → dist}/cli/utils/manifest.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/node-modules.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/utils/node-modules.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/node-modules.js +0 -0
- /package/{packages/core/dist → dist}/cli/utils/node-modules.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/prompts.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/utils/prompts.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/prompts.js +0 -0
- /package/{packages/core/dist → dist}/cli/utils/prompts.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/settings.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/utils/settings.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/settings.js +0 -0
- /package/{packages/core/dist → dist}/cli/utils/settings.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/symlinks.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/utils/symlinks.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/symlinks.js +0 -0
- /package/{packages/core/dist → dist}/cli/utils/symlinks.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/themes.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/utils/themes.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/themes.js +0 -0
- /package/{packages/core/dist → dist}/cli/utils/themes.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/themes.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/utils/themes.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/themes.test.js +0 -0
- /package/{packages/core/dist → dist}/cli/utils/themes.test.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/version.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/utils/version.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/utils/version.js +0 -0
- /package/{packages/core/dist → dist}/cli/utils/version.js.map +0 -0
- /package/{packages/core/dist → dist}/cli/workspace.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/cli/workspace.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/cli/workspace.test.js +0 -0
- /package/{packages/core/dist → dist}/cli/workspace.test.js.map +0 -0
- /package/{packages/core/dist → dist}/index.d.ts +0 -0
- /package/{packages/core/dist → dist}/index.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/index.js +0 -0
- /package/{packages/core/dist → dist}/index.js.map +0 -0
- /package/{packages/core/dist → dist}/jira/jira-epic-creation.d.ts +0 -0
- /package/{packages/core/dist → dist}/jira/jira-epic-creation.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/jira/jira-epic-creation.js +0 -0
- /package/{packages/core/dist → dist}/jira/jira-epic-creation.js.map +0 -0
- /package/{packages/core/dist → dist}/jira/jira-epic-creation.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/jira/jira-epic-creation.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/jira/jira-epic-creation.test.js +0 -0
- /package/{packages/core/dist → dist}/jira/jira-epic-creation.test.js.map +0 -0
- /package/{packages/core/dist → dist}/jira/jira-sprint-sync.d.ts +0 -0
- /package/{packages/core/dist → dist}/jira/jira-sprint-sync.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/jira/jira-sprint-sync.js +0 -0
- /package/{packages/core/dist → dist}/jira/jira-sprint-sync.js.map +0 -0
- /package/{packages/core/dist → dist}/jira/jira-sprint-sync.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/jira/jira-sprint-sync.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/jira/jira-sprint-sync.test.js +0 -0
- /package/{packages/core/dist → dist}/jira/jira-sprint-sync.test.js.map +0 -0
- /package/{packages/core/dist → dist}/permissions/index.d.ts +0 -0
- /package/{packages/core/dist → dist}/permissions/index.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/permissions/index.js +0 -0
- /package/{packages/core/dist → dist}/permissions/index.js.map +0 -0
- /package/{packages/core/dist → dist}/permissions/permission-schema.d.ts +0 -0
- /package/{packages/core/dist → dist}/permissions/permission-schema.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/permissions/permission-schema.js +0 -0
- /package/{packages/core/dist → dist}/permissions/permission-schema.js.map +0 -0
- /package/{packages/core/dist → dist}/permissions/permission-schema.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/permissions/permission-schema.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/permissions/permission-schema.test.js +0 -0
- /package/{packages/core/dist → dist}/permissions/permission-schema.test.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/add-ocean-profiles.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/add-ocean-profiles.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/add-ocean-profiles.js +0 -0
- /package/{packages/core/dist → dist}/scripts/add-ocean-profiles.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/benchmark-integration.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/benchmark-integration.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/benchmark-integration.js +0 -0
- /package/{packages/core/dist → dist}/scripts/benchmark-integration.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/benchmark-integration.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/benchmark-integration.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/benchmark-integration.test.js +0 -0
- /package/{packages/core/dist → dist}/scripts/benchmark-integration.test.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/debugging-scenarios.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/debugging-scenarios.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/debugging-scenarios.test.js +0 -0
- /package/{packages/core/dist → dist}/scripts/debugging-scenarios.test.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-all-spiders.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-all-spiders.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-all-spiders.js +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-all-spiders.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-report.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-report.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-report.js +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-report.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-report.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-report.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-report.test.js +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-report.test.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider-report.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider-report.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider-report.js +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider-report.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider-report.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider-report.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider-report.test.js +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider-report.test.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider.js +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider.test.js +0 -0
- /package/{packages/core/dist → dist}/scripts/generate-spider.test.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/job-fair-aggregator.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/job-fair-aggregator.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/job-fair-aggregator.js +0 -0
- /package/{packages/core/dist → dist}/scripts/job-fair-aggregator.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/job-fair-aggregator.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/job-fair-aggregator.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/job-fair-aggregator.test.js +0 -0
- /package/{packages/core/dist → dist}/scripts/job-fair-aggregator.test.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/run-ci.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/run-ci.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/run-ci.test.js +0 -0
- /package/{packages/core/dist → dist}/scripts/run-ci.test.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/theme-detail.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/theme-detail.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/theme-detail.test.js +0 -0
- /package/{packages/core/dist → dist}/scripts/theme-detail.test.js.map +0 -0
- /package/{packages/core/dist → dist}/scripts/validate-ocean-profiles.d.ts +0 -0
- /package/{packages/core/dist → dist}/scripts/validate-ocean-profiles.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/scripts/validate-ocean-profiles.js +0 -0
- /package/{packages/core/dist → dist}/scripts/validate-ocean-profiles.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/gate-handler.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/gate-handler.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/gate-handler.js +0 -0
- /package/{packages/core/dist → dist}/workflow/gate-handler.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/gate-handler.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/gate-handler.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/gate-handler.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/gate-handler.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/generic-sm-finish.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/generic-sm-finish.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/generic-sm-finish.js +0 -0
- /package/{packages/core/dist → dist}/workflow/generic-sm-finish.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/generic-sm-setup.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/generic-sm-setup.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/generic-sm-setup.js +0 -0
- /package/{packages/core/dist → dist}/workflow/generic-sm-setup.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/handoff.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/handoff.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/handoff.js +0 -0
- /package/{packages/core/dist → dist}/workflow/handoff.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/handoff.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/handoff.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/handoff.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/handoff.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/index.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/index.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/index.js +0 -0
- /package/{packages/core/dist → dist}/workflow/index.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/session-state.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/session-state.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/session-state.js +0 -0
- /package/{packages/core/dist → dist}/workflow/session-state.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/session-state.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/session-state.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/session-state.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/session-state.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/sm-subagents.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/sm-subagents.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/sm-subagents.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/sm-subagents.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/step-parser.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/step-parser.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/step-parser.js +0 -0
- /package/{packages/core/dist → dist}/workflow/step-parser.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/step-parser.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/step-parser.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/step-parser.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/step-parser.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/story-workflow-routing.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/story-workflow-routing.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/story-workflow-routing.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/story-workflow-routing.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/test-cache.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/test-cache.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/test-cache.js +0 -0
- /package/{packages/core/dist → dist}/workflow/test-cache.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/test-cache.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/test-cache.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/test-cache.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/test-cache.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/trimodal.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/trimodal.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/trimodal.js +0 -0
- /package/{packages/core/dist → dist}/workflow/trimodal.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/trimodal.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/trimodal.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/trimodal.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/trimodal.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/variable-resolver.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/variable-resolver.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/variable-resolver.js +0 -0
- /package/{packages/core/dist → dist}/workflow/variable-resolver.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/variable-resolver.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/variable-resolver.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/variable-resolver.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/variable-resolver.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-executor.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-executor.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-executor.js +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-executor.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-executor.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-executor.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-executor.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-executor.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-loader.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-loader.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-loader.js +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-loader.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-loader.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-loader.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-loader.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-loader.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-migration.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-migration.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-migration.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-migration.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-permissions.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-permissions.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-permissions.js +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-permissions.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-permissions.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-permissions.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-permissions.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-permissions.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-router.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-router.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-router.js +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-router.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-router.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-router.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-router.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-router.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-schema.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-schema.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-schema.js +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-schema.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-schema.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-schema.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-schema.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-schema.test.js.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-stepped-schema.test.d.ts +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-stepped-schema.test.d.ts.map +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-stepped-schema.test.js +0 -0
- /package/{packages/core/dist → dist}/workflow/workflow-stepped-schema.test.js.map +0 -0
|
@@ -1,866 +0,0 @@
|
|
|
1
|
-
"""Tests for git/ utility modules.
|
|
2
|
-
|
|
3
|
-
Story: MSSCI-12402 - Port git utility scripts to Python
|
|
4
|
-
|
|
5
|
-
TDD RED phase: All tests should FAIL until implementation.
|
|
6
|
-
|
|
7
|
-
Acceptance Criteria:
|
|
8
|
-
1. Python script implements git-status-all functionality with parallel execution
|
|
9
|
-
2. Python script implements create-feature-branches functionality with parallel execution
|
|
10
|
-
3. Both scripts use asyncio.gather for parallelism
|
|
11
|
-
4. Error handling is robust and provides clear messages
|
|
12
|
-
5. Output formatting is consistent across platforms
|
|
13
|
-
6. Cross-platform compatibility verified
|
|
14
|
-
7. Tests pass with 100% coverage
|
|
15
|
-
8. Performance is equivalent or better than bash versions
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
import asyncio
|
|
19
|
-
import tempfile
|
|
20
|
-
from pathlib import Path
|
|
21
|
-
from typing import Any
|
|
22
|
-
from unittest.mock import AsyncMock, MagicMock, patch
|
|
23
|
-
|
|
24
|
-
import pytest
|
|
25
|
-
|
|
26
|
-
from pennyfarthing_scripts.git.status_all import (
|
|
27
|
-
RepoStatus,
|
|
28
|
-
format_status_brief,
|
|
29
|
-
format_status_full,
|
|
30
|
-
format_summary,
|
|
31
|
-
get_all_repo_status,
|
|
32
|
-
get_repo_status,
|
|
33
|
-
)
|
|
34
|
-
from pennyfarthing_scripts.git.create_branches import (
|
|
35
|
-
BranchAction,
|
|
36
|
-
BranchResult,
|
|
37
|
-
create_feature_branches,
|
|
38
|
-
create_or_checkout_branch,
|
|
39
|
-
detect_worktree,
|
|
40
|
-
filter_repos,
|
|
41
|
-
format_results,
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
# =============================================================================
|
|
46
|
-
# Test Fixtures
|
|
47
|
-
# =============================================================================
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
@pytest.fixture
|
|
51
|
-
def temp_git_repo(tmp_path: Path) -> Path:
|
|
52
|
-
"""Create a temporary git repository for testing."""
|
|
53
|
-
import subprocess
|
|
54
|
-
|
|
55
|
-
repo_path = tmp_path / "test-repo"
|
|
56
|
-
repo_path.mkdir()
|
|
57
|
-
|
|
58
|
-
# Initialize git repo
|
|
59
|
-
subprocess.run(["git", "init"], cwd=repo_path, capture_output=True)
|
|
60
|
-
subprocess.run(
|
|
61
|
-
["git", "config", "user.email", "test@test.com"], cwd=repo_path, capture_output=True
|
|
62
|
-
)
|
|
63
|
-
subprocess.run(
|
|
64
|
-
["git", "config", "user.name", "Test User"], cwd=repo_path, capture_output=True
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
# Create initial commit
|
|
68
|
-
(repo_path / "README.md").write_text("# Test Repo")
|
|
69
|
-
subprocess.run(["git", "add", "."], cwd=repo_path, capture_output=True)
|
|
70
|
-
subprocess.run(
|
|
71
|
-
["git", "commit", "-m", "Initial commit"], cwd=repo_path, capture_output=True
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
# Create develop branch
|
|
75
|
-
subprocess.run(["git", "branch", "develop"], cwd=repo_path, capture_output=True)
|
|
76
|
-
|
|
77
|
-
return repo_path
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
@pytest.fixture
|
|
81
|
-
def sample_repos(tmp_path: Path) -> list[tuple[str, Path]]:
|
|
82
|
-
"""Create sample repos list for testing."""
|
|
83
|
-
return [
|
|
84
|
-
("repo-a", tmp_path / "repo-a"),
|
|
85
|
-
("repo-b", tmp_path / "repo-b"),
|
|
86
|
-
]
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
@pytest.fixture
|
|
90
|
-
def clean_repo_status() -> RepoStatus:
|
|
91
|
-
"""A clean repo with no changes."""
|
|
92
|
-
return RepoStatus(
|
|
93
|
-
name="clean-repo",
|
|
94
|
-
path=Path("/test/clean-repo"),
|
|
95
|
-
branch="develop",
|
|
96
|
-
changes=[],
|
|
97
|
-
unpushed_commits=[],
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
@pytest.fixture
|
|
102
|
-
def dirty_repo_status() -> RepoStatus:
|
|
103
|
-
"""A repo with uncommitted changes."""
|
|
104
|
-
return RepoStatus(
|
|
105
|
-
name="dirty-repo",
|
|
106
|
-
path=Path("/test/dirty-repo"),
|
|
107
|
-
branch="feature/test",
|
|
108
|
-
changes=[
|
|
109
|
-
" M src/file1.py",
|
|
110
|
-
"?? src/newfile.py",
|
|
111
|
-
],
|
|
112
|
-
unpushed_commits=[],
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
@pytest.fixture
|
|
117
|
-
def repo_with_unpushed() -> RepoStatus:
|
|
118
|
-
"""A repo with unpushed commits."""
|
|
119
|
-
return RepoStatus(
|
|
120
|
-
name="unpushed-repo",
|
|
121
|
-
path=Path("/test/unpushed-repo"),
|
|
122
|
-
branch="feature/test",
|
|
123
|
-
changes=[],
|
|
124
|
-
unpushed_commits=[
|
|
125
|
-
"abc1234 Add new feature",
|
|
126
|
-
"def5678 Fix bug",
|
|
127
|
-
],
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
# =============================================================================
|
|
132
|
-
# AC1: git-status-all functionality
|
|
133
|
-
# =============================================================================
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
class TestRepoStatus:
|
|
137
|
-
"""Tests for RepoStatus dataclass."""
|
|
138
|
-
|
|
139
|
-
def test_is_clean_with_no_changes(self, clean_repo_status: RepoStatus) -> None:
|
|
140
|
-
"""is_clean should be True when no changes."""
|
|
141
|
-
assert clean_repo_status.is_clean is True
|
|
142
|
-
|
|
143
|
-
def test_is_clean_with_changes(self, dirty_repo_status: RepoStatus) -> None:
|
|
144
|
-
"""is_clean should be False when there are changes."""
|
|
145
|
-
assert dirty_repo_status.is_clean is False
|
|
146
|
-
|
|
147
|
-
def test_has_unpushed_with_no_commits(self, clean_repo_status: RepoStatus) -> None:
|
|
148
|
-
"""has_unpushed should be False when no unpushed commits."""
|
|
149
|
-
assert clean_repo_status.has_unpushed is False
|
|
150
|
-
|
|
151
|
-
def test_has_unpushed_with_commits(self, repo_with_unpushed: RepoStatus) -> None:
|
|
152
|
-
"""has_unpushed should be True when there are unpushed commits."""
|
|
153
|
-
assert repo_with_unpushed.has_unpushed is True
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
class TestGetRepoStatus:
|
|
157
|
-
"""Tests for get_repo_status function."""
|
|
158
|
-
|
|
159
|
-
@pytest.mark.asyncio
|
|
160
|
-
async def test_returns_repo_status(self, temp_git_repo: Path) -> None:
|
|
161
|
-
"""get_repo_status should return a RepoStatus object."""
|
|
162
|
-
result = await get_repo_status("test-repo", temp_git_repo)
|
|
163
|
-
|
|
164
|
-
assert isinstance(result, RepoStatus)
|
|
165
|
-
assert result.name == "test-repo"
|
|
166
|
-
assert result.path == temp_git_repo
|
|
167
|
-
|
|
168
|
-
@pytest.mark.asyncio
|
|
169
|
-
async def test_captures_current_branch(self, temp_git_repo: Path) -> None:
|
|
170
|
-
"""get_repo_status should capture the current branch name."""
|
|
171
|
-
result = await get_repo_status("test-repo", temp_git_repo)
|
|
172
|
-
|
|
173
|
-
assert result.branch is not None
|
|
174
|
-
assert isinstance(result.branch, str)
|
|
175
|
-
|
|
176
|
-
@pytest.mark.asyncio
|
|
177
|
-
async def test_handles_detached_head(self, temp_git_repo: Path) -> None:
|
|
178
|
-
"""get_repo_status should handle detached HEAD state."""
|
|
179
|
-
# When in detached HEAD, branch should be "detached" or similar
|
|
180
|
-
result = await get_repo_status("test-repo", temp_git_repo)
|
|
181
|
-
|
|
182
|
-
assert result.branch is not None # Should not crash
|
|
183
|
-
|
|
184
|
-
@pytest.mark.asyncio
|
|
185
|
-
async def test_captures_uncommitted_changes(self, temp_git_repo: Path) -> None:
|
|
186
|
-
"""get_repo_status should capture uncommitted changes."""
|
|
187
|
-
result = await get_repo_status("test-repo", temp_git_repo)
|
|
188
|
-
|
|
189
|
-
assert isinstance(result.changes, list)
|
|
190
|
-
|
|
191
|
-
@pytest.mark.asyncio
|
|
192
|
-
async def test_captures_unpushed_commits(self, temp_git_repo: Path) -> None:
|
|
193
|
-
"""get_repo_status should capture unpushed commits."""
|
|
194
|
-
result = await get_repo_status("test-repo", temp_git_repo)
|
|
195
|
-
|
|
196
|
-
assert isinstance(result.unpushed_commits, list)
|
|
197
|
-
|
|
198
|
-
@pytest.mark.asyncio
|
|
199
|
-
async def test_handles_nonexistent_path(self) -> None:
|
|
200
|
-
"""get_repo_status should handle non-existent paths gracefully."""
|
|
201
|
-
result = await get_repo_status("missing-repo", Path("/nonexistent/path"))
|
|
202
|
-
|
|
203
|
-
assert result.error is not None
|
|
204
|
-
|
|
205
|
-
@pytest.mark.asyncio
|
|
206
|
-
async def test_handles_non_git_directory(self, tmp_path: Path) -> None:
|
|
207
|
-
"""get_repo_status should handle non-git directories gracefully."""
|
|
208
|
-
result = await get_repo_status("not-git", tmp_path)
|
|
209
|
-
|
|
210
|
-
assert result.error is not None
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
# =============================================================================
|
|
214
|
-
# AC3: asyncio.gather for parallelism
|
|
215
|
-
# =============================================================================
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
class TestGetAllRepoStatus:
|
|
219
|
-
"""Tests for get_all_repo_status function."""
|
|
220
|
-
|
|
221
|
-
@pytest.mark.asyncio
|
|
222
|
-
async def test_returns_list_of_statuses(
|
|
223
|
-
self, sample_repos: list[tuple[str, Path]]
|
|
224
|
-
) -> None:
|
|
225
|
-
"""get_all_repo_status should return list of RepoStatus objects."""
|
|
226
|
-
results = await get_all_repo_status(sample_repos)
|
|
227
|
-
|
|
228
|
-
assert isinstance(results, list)
|
|
229
|
-
assert len(results) == len(sample_repos)
|
|
230
|
-
assert all(isinstance(r, RepoStatus) for r in results)
|
|
231
|
-
|
|
232
|
-
@pytest.mark.asyncio
|
|
233
|
-
async def test_preserves_order(self, sample_repos: list[tuple[str, Path]]) -> None:
|
|
234
|
-
"""get_all_repo_status should preserve input order."""
|
|
235
|
-
results = await get_all_repo_status(sample_repos)
|
|
236
|
-
|
|
237
|
-
for i, (name, _) in enumerate(sample_repos):
|
|
238
|
-
assert results[i].name == name
|
|
239
|
-
|
|
240
|
-
@pytest.mark.asyncio
|
|
241
|
-
async def test_uses_asyncio_gather(
|
|
242
|
-
self, sample_repos: list[tuple[str, Path]]
|
|
243
|
-
) -> None:
|
|
244
|
-
"""get_all_repo_status should use asyncio.gather for parallelism."""
|
|
245
|
-
with patch(
|
|
246
|
-
"pennyfarthing_scripts.git.status_all.get_repo_status",
|
|
247
|
-
new_callable=AsyncMock,
|
|
248
|
-
) as mock_get_status:
|
|
249
|
-
mock_get_status.return_value = RepoStatus(
|
|
250
|
-
name="test",
|
|
251
|
-
path=Path("/test"),
|
|
252
|
-
branch="main",
|
|
253
|
-
changes=[],
|
|
254
|
-
unpushed_commits=[],
|
|
255
|
-
)
|
|
256
|
-
|
|
257
|
-
await get_all_repo_status(sample_repos)
|
|
258
|
-
|
|
259
|
-
# Should be called once per repo
|
|
260
|
-
assert mock_get_status.call_count == len(sample_repos)
|
|
261
|
-
|
|
262
|
-
@pytest.mark.asyncio
|
|
263
|
-
async def test_handles_empty_repos_list(self) -> None:
|
|
264
|
-
"""get_all_repo_status should handle empty repos list."""
|
|
265
|
-
results = await get_all_repo_status([])
|
|
266
|
-
|
|
267
|
-
assert results == []
|
|
268
|
-
|
|
269
|
-
@pytest.mark.asyncio
|
|
270
|
-
async def test_continues_on_individual_errors(
|
|
271
|
-
self, sample_repos: list[tuple[str, Path]]
|
|
272
|
-
) -> None:
|
|
273
|
-
"""get_all_repo_status should continue even if one repo has errors."""
|
|
274
|
-
# Even if first repo fails, second should still be processed
|
|
275
|
-
results = await get_all_repo_status(sample_repos)
|
|
276
|
-
|
|
277
|
-
assert len(results) == len(sample_repos)
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
# =============================================================================
|
|
281
|
-
# AC5: Output formatting
|
|
282
|
-
# =============================================================================
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
class TestFormatStatusBrief:
|
|
286
|
-
"""Tests for format_status_brief function."""
|
|
287
|
-
|
|
288
|
-
def test_formats_clean_repo(self, clean_repo_status: RepoStatus) -> None:
|
|
289
|
-
"""format_status_brief should show checkmark for clean repos."""
|
|
290
|
-
output = format_status_brief([clean_repo_status])
|
|
291
|
-
|
|
292
|
-
assert clean_repo_status.name in output
|
|
293
|
-
assert clean_repo_status.branch in output
|
|
294
|
-
|
|
295
|
-
def test_formats_dirty_repo(self, dirty_repo_status: RepoStatus) -> None:
|
|
296
|
-
"""format_status_brief should show M indicator for dirty repos."""
|
|
297
|
-
output = format_status_brief([dirty_repo_status])
|
|
298
|
-
|
|
299
|
-
assert dirty_repo_status.name in output
|
|
300
|
-
assert "M" in output # Modified indicator
|
|
301
|
-
|
|
302
|
-
def test_formats_unpushed_repo(self, repo_with_unpushed: RepoStatus) -> None:
|
|
303
|
-
"""format_status_brief should show unpushed count."""
|
|
304
|
-
output = format_status_brief([repo_with_unpushed])
|
|
305
|
-
|
|
306
|
-
assert repo_with_unpushed.name in output
|
|
307
|
-
assert "2" in output # 2 unpushed commits
|
|
308
|
-
|
|
309
|
-
def test_one_line_per_repo(
|
|
310
|
-
self, clean_repo_status: RepoStatus, dirty_repo_status: RepoStatus
|
|
311
|
-
) -> None:
|
|
312
|
-
"""format_status_brief should output one line per repo."""
|
|
313
|
-
output = format_status_brief([clean_repo_status, dirty_repo_status])
|
|
314
|
-
lines = [line for line in output.strip().split("\n") if line]
|
|
315
|
-
|
|
316
|
-
assert len(lines) == 2
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
class TestFormatStatusFull:
|
|
320
|
-
"""Tests for format_status_full function."""
|
|
321
|
-
|
|
322
|
-
def test_includes_repo_header(self, clean_repo_status: RepoStatus) -> None:
|
|
323
|
-
"""format_status_full should include repo name header."""
|
|
324
|
-
output = format_status_full([clean_repo_status])
|
|
325
|
-
|
|
326
|
-
assert clean_repo_status.name in output
|
|
327
|
-
|
|
328
|
-
def test_includes_branch_name(self, clean_repo_status: RepoStatus) -> None:
|
|
329
|
-
"""format_status_full should include branch name."""
|
|
330
|
-
output = format_status_full([clean_repo_status])
|
|
331
|
-
|
|
332
|
-
assert clean_repo_status.branch in output
|
|
333
|
-
|
|
334
|
-
def test_lists_changes(self, dirty_repo_status: RepoStatus) -> None:
|
|
335
|
-
"""format_status_full should list file changes."""
|
|
336
|
-
output = format_status_full([dirty_repo_status])
|
|
337
|
-
|
|
338
|
-
# Should include at least one change
|
|
339
|
-
assert "file1.py" in output or "Changes" in output
|
|
340
|
-
|
|
341
|
-
def test_truncates_many_changes(self) -> None:
|
|
342
|
-
"""format_status_full should truncate if more than 10 changes."""
|
|
343
|
-
many_changes = RepoStatus(
|
|
344
|
-
name="many-changes",
|
|
345
|
-
path=Path("/test"),
|
|
346
|
-
branch="main",
|
|
347
|
-
changes=[f" M file{i}.py" for i in range(15)],
|
|
348
|
-
unpushed_commits=[],
|
|
349
|
-
)
|
|
350
|
-
|
|
351
|
-
output = format_status_full([many_changes])
|
|
352
|
-
|
|
353
|
-
assert "more" in output.lower() or "..." in output
|
|
354
|
-
|
|
355
|
-
def test_lists_unpushed_commits(self, repo_with_unpushed: RepoStatus) -> None:
|
|
356
|
-
"""format_status_full should list unpushed commits."""
|
|
357
|
-
output = format_status_full([repo_with_unpushed])
|
|
358
|
-
|
|
359
|
-
assert "Unpushed" in output or "unpushed" in output
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
class TestFormatSummary:
|
|
363
|
-
"""Tests for format_summary function."""
|
|
364
|
-
|
|
365
|
-
def test_shows_all_clean(self, clean_repo_status: RepoStatus) -> None:
|
|
366
|
-
"""format_summary should indicate when all repos are clean."""
|
|
367
|
-
output = format_summary([clean_repo_status])
|
|
368
|
-
|
|
369
|
-
assert "clean" in output.lower() or "pushed" in output.lower()
|
|
370
|
-
|
|
371
|
-
def test_shows_change_count(
|
|
372
|
-
self, dirty_repo_status: RepoStatus, clean_repo_status: RepoStatus
|
|
373
|
-
) -> None:
|
|
374
|
-
"""format_summary should show total uncommitted changes."""
|
|
375
|
-
output = format_summary([dirty_repo_status, clean_repo_status])
|
|
376
|
-
|
|
377
|
-
# dirty_repo_status has 2 changes
|
|
378
|
-
assert "2" in output or "change" in output.lower()
|
|
379
|
-
|
|
380
|
-
def test_shows_unpushed_count(self, repo_with_unpushed: RepoStatus) -> None:
|
|
381
|
-
"""format_summary should show total unpushed commits."""
|
|
382
|
-
output = format_summary([repo_with_unpushed])
|
|
383
|
-
|
|
384
|
-
# repo_with_unpushed has 2 unpushed commits
|
|
385
|
-
assert "2" in output or "unpushed" in output.lower()
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
# =============================================================================
|
|
389
|
-
# AC2: create-feature-branches functionality
|
|
390
|
-
# =============================================================================
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
class TestBranchResult:
|
|
394
|
-
"""Tests for BranchResult dataclass."""
|
|
395
|
-
|
|
396
|
-
def test_created_action(self) -> None:
|
|
397
|
-
"""BranchResult should represent created branch."""
|
|
398
|
-
result = BranchResult(
|
|
399
|
-
name="test-repo",
|
|
400
|
-
path=Path("/test"),
|
|
401
|
-
branch="feature/new",
|
|
402
|
-
action=BranchAction.CREATED,
|
|
403
|
-
current_branch="feature/new",
|
|
404
|
-
)
|
|
405
|
-
|
|
406
|
-
assert result.action == BranchAction.CREATED
|
|
407
|
-
|
|
408
|
-
def test_error_action(self) -> None:
|
|
409
|
-
"""BranchResult should represent error with message."""
|
|
410
|
-
result = BranchResult(
|
|
411
|
-
name="test-repo",
|
|
412
|
-
path=Path("/test"),
|
|
413
|
-
branch="feature/new",
|
|
414
|
-
action=BranchAction.ERROR,
|
|
415
|
-
error="Failed to create branch",
|
|
416
|
-
)
|
|
417
|
-
|
|
418
|
-
assert result.action == BranchAction.ERROR
|
|
419
|
-
assert result.error is not None
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
class TestCreateOrCheckoutBranch:
|
|
423
|
-
"""Tests for create_or_checkout_branch function."""
|
|
424
|
-
|
|
425
|
-
@pytest.mark.asyncio
|
|
426
|
-
async def test_returns_branch_result(self, temp_git_repo: Path) -> None:
|
|
427
|
-
"""create_or_checkout_branch should return a BranchResult."""
|
|
428
|
-
result = await create_or_checkout_branch(
|
|
429
|
-
"test-repo", temp_git_repo, "feature/test"
|
|
430
|
-
)
|
|
431
|
-
|
|
432
|
-
assert isinstance(result, BranchResult)
|
|
433
|
-
|
|
434
|
-
@pytest.mark.asyncio
|
|
435
|
-
async def test_creates_new_branch_from_develop(self, temp_git_repo: Path) -> None:
|
|
436
|
-
"""create_or_checkout_branch should create new branch from develop."""
|
|
437
|
-
result = await create_or_checkout_branch(
|
|
438
|
-
"test-repo", temp_git_repo, "feature/new-branch"
|
|
439
|
-
)
|
|
440
|
-
|
|
441
|
-
# Should create branch (no remote in test repo, so creates locally)
|
|
442
|
-
assert result.action in (BranchAction.CREATED, BranchAction.ERROR)
|
|
443
|
-
if result.action == BranchAction.CREATED:
|
|
444
|
-
assert result.current_branch == "feature/new-branch"
|
|
445
|
-
|
|
446
|
-
@pytest.mark.asyncio
|
|
447
|
-
async def test_checks_out_existing_local_branch(self, temp_git_repo: Path) -> None:
|
|
448
|
-
"""create_or_checkout_branch should checkout existing local branch."""
|
|
449
|
-
import subprocess
|
|
450
|
-
|
|
451
|
-
# Create the branch first
|
|
452
|
-
subprocess.run(
|
|
453
|
-
["git", "checkout", "-b", "existing-branch"],
|
|
454
|
-
cwd=temp_git_repo,
|
|
455
|
-
capture_output=True,
|
|
456
|
-
)
|
|
457
|
-
subprocess.run(
|
|
458
|
-
["git", "checkout", "main"],
|
|
459
|
-
cwd=temp_git_repo,
|
|
460
|
-
capture_output=True,
|
|
461
|
-
)
|
|
462
|
-
|
|
463
|
-
result = await create_or_checkout_branch(
|
|
464
|
-
"test-repo", temp_git_repo, "existing-branch"
|
|
465
|
-
)
|
|
466
|
-
|
|
467
|
-
assert result.action in (
|
|
468
|
-
BranchAction.CHECKED_OUT_LOCAL,
|
|
469
|
-
BranchAction.CREATED,
|
|
470
|
-
BranchAction.ERROR, # May fail if no remote
|
|
471
|
-
)
|
|
472
|
-
|
|
473
|
-
@pytest.mark.asyncio
|
|
474
|
-
async def test_tracks_remote_branch(self, temp_git_repo: Path) -> None:
|
|
475
|
-
"""create_or_checkout_branch should track remote if branch exists there."""
|
|
476
|
-
result = await create_or_checkout_branch(
|
|
477
|
-
"test-repo", temp_git_repo, "remote-branch"
|
|
478
|
-
)
|
|
479
|
-
|
|
480
|
-
# In test repo without remote, should either create or error
|
|
481
|
-
assert result.action in (
|
|
482
|
-
BranchAction.CHECKED_OUT_REMOTE,
|
|
483
|
-
BranchAction.CREATED,
|
|
484
|
-
BranchAction.ERROR, # May fail if no remote to fetch from
|
|
485
|
-
)
|
|
486
|
-
|
|
487
|
-
@pytest.mark.asyncio
|
|
488
|
-
async def test_handles_missing_directory(self) -> None:
|
|
489
|
-
"""create_or_checkout_branch should handle missing directory."""
|
|
490
|
-
result = await create_or_checkout_branch(
|
|
491
|
-
"missing-repo", Path("/nonexistent"), "feature/test"
|
|
492
|
-
)
|
|
493
|
-
|
|
494
|
-
assert result.action == BranchAction.SKIPPED
|
|
495
|
-
|
|
496
|
-
@pytest.mark.asyncio
|
|
497
|
-
async def test_fetches_before_branching(self, temp_git_repo: Path) -> None:
|
|
498
|
-
"""create_or_checkout_branch should fetch from origin before creating."""
|
|
499
|
-
result = await create_or_checkout_branch(
|
|
500
|
-
"test-repo", temp_git_repo, "feature/test"
|
|
501
|
-
)
|
|
502
|
-
|
|
503
|
-
# Should not error (fetch happens internally)
|
|
504
|
-
assert result.action != BranchAction.ERROR or "fetch" not in (
|
|
505
|
-
result.error or ""
|
|
506
|
-
).lower()
|
|
507
|
-
|
|
508
|
-
@pytest.mark.asyncio
|
|
509
|
-
async def test_includes_commit_info(self, temp_git_repo: Path) -> None:
|
|
510
|
-
"""create_or_checkout_branch should include latest commit info."""
|
|
511
|
-
result = await create_or_checkout_branch(
|
|
512
|
-
"test-repo", temp_git_repo, "feature/test"
|
|
513
|
-
)
|
|
514
|
-
|
|
515
|
-
# commit_info should be populated on success
|
|
516
|
-
if result.action != BranchAction.SKIPPED:
|
|
517
|
-
assert result.commit_info is not None or result.error is not None
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
class TestCreateFeatureBranches:
|
|
521
|
-
"""Tests for create_feature_branches function."""
|
|
522
|
-
|
|
523
|
-
@pytest.mark.asyncio
|
|
524
|
-
async def test_returns_list_of_results(
|
|
525
|
-
self, sample_repos: list[tuple[str, Path]]
|
|
526
|
-
) -> None:
|
|
527
|
-
"""create_feature_branches should return list of BranchResult objects."""
|
|
528
|
-
results = await create_feature_branches(sample_repos, "feature/test")
|
|
529
|
-
|
|
530
|
-
assert isinstance(results, list)
|
|
531
|
-
assert len(results) == len(sample_repos)
|
|
532
|
-
assert all(isinstance(r, BranchResult) for r in results)
|
|
533
|
-
|
|
534
|
-
@pytest.mark.asyncio
|
|
535
|
-
async def test_uses_asyncio_gather(
|
|
536
|
-
self, sample_repos: list[tuple[str, Path]]
|
|
537
|
-
) -> None:
|
|
538
|
-
"""create_feature_branches should use asyncio.gather for parallelism."""
|
|
539
|
-
with patch(
|
|
540
|
-
"pennyfarthing_scripts.git.create_branches.create_or_checkout_branch",
|
|
541
|
-
new_callable=AsyncMock,
|
|
542
|
-
) as mock_create:
|
|
543
|
-
mock_create.return_value = BranchResult(
|
|
544
|
-
name="test",
|
|
545
|
-
path=Path("/test"),
|
|
546
|
-
branch="feature/test",
|
|
547
|
-
action=BranchAction.CREATED,
|
|
548
|
-
)
|
|
549
|
-
|
|
550
|
-
await create_feature_branches(sample_repos, "feature/test")
|
|
551
|
-
|
|
552
|
-
assert mock_create.call_count == len(sample_repos)
|
|
553
|
-
|
|
554
|
-
@pytest.mark.asyncio
|
|
555
|
-
async def test_preserves_order(
|
|
556
|
-
self, sample_repos: list[tuple[str, Path]]
|
|
557
|
-
) -> None:
|
|
558
|
-
"""create_feature_branches should preserve input order."""
|
|
559
|
-
results = await create_feature_branches(sample_repos, "feature/test")
|
|
560
|
-
|
|
561
|
-
for i, (name, _) in enumerate(sample_repos):
|
|
562
|
-
assert results[i].name == name
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
# =============================================================================
|
|
566
|
-
# Worktree Detection
|
|
567
|
-
# =============================================================================
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
class TestDetectWorktree:
|
|
571
|
-
"""Tests for detect_worktree function."""
|
|
572
|
-
|
|
573
|
-
def test_detects_main_checkout(self, tmp_path: Path) -> None:
|
|
574
|
-
"""detect_worktree should detect main checkout (not worktree)."""
|
|
575
|
-
is_worktree, name, base_path = detect_worktree(tmp_path)
|
|
576
|
-
|
|
577
|
-
assert is_worktree is False
|
|
578
|
-
assert name is None
|
|
579
|
-
|
|
580
|
-
def test_detects_worktree(self, tmp_path: Path) -> None:
|
|
581
|
-
"""detect_worktree should detect worktree from path."""
|
|
582
|
-
worktree_path = tmp_path / "worktrees" / "my-feature"
|
|
583
|
-
worktree_path.mkdir(parents=True)
|
|
584
|
-
|
|
585
|
-
is_worktree, name, base_path = detect_worktree(worktree_path)
|
|
586
|
-
|
|
587
|
-
assert is_worktree is True
|
|
588
|
-
assert name == "my-feature"
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
# =============================================================================
|
|
592
|
-
# Repo Filtering
|
|
593
|
-
# =============================================================================
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
class TestFilterRepos:
|
|
597
|
-
"""Tests for filter_repos function."""
|
|
598
|
-
|
|
599
|
-
def test_filter_all_returns_all(
|
|
600
|
-
self, sample_repos: list[tuple[str, Path]]
|
|
601
|
-
) -> None:
|
|
602
|
-
"""filter_repos with 'all' should return all repos."""
|
|
603
|
-
result = filter_repos(sample_repos, "all")
|
|
604
|
-
|
|
605
|
-
assert len(result) == len(sample_repos)
|
|
606
|
-
|
|
607
|
-
def test_filter_api_returns_api_only(self) -> None:
|
|
608
|
-
"""filter_repos with 'api' should return only API repos."""
|
|
609
|
-
repos = [
|
|
610
|
-
("Pennyfarthing-api", Path("/api")),
|
|
611
|
-
("Pennyfarthing-ui", Path("/ui")),
|
|
612
|
-
]
|
|
613
|
-
|
|
614
|
-
result = filter_repos(repos, "api")
|
|
615
|
-
|
|
616
|
-
assert len(result) == 1
|
|
617
|
-
assert result[0][0] == "Pennyfarthing-api"
|
|
618
|
-
|
|
619
|
-
def test_filter_ui_returns_ui_only(self) -> None:
|
|
620
|
-
"""filter_repos with 'ui' should return only UI repos."""
|
|
621
|
-
repos = [
|
|
622
|
-
("Pennyfarthing-api", Path("/api")),
|
|
623
|
-
("Pennyfarthing-ui", Path("/ui")),
|
|
624
|
-
]
|
|
625
|
-
|
|
626
|
-
result = filter_repos(repos, "ui")
|
|
627
|
-
|
|
628
|
-
assert len(result) == 1
|
|
629
|
-
assert result[0][0] == "Pennyfarthing-ui"
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
# =============================================================================
|
|
633
|
-
# AC4: Error handling
|
|
634
|
-
# =============================================================================
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
class TestErrorHandling:
|
|
638
|
-
"""Tests for error handling across git utilities."""
|
|
639
|
-
|
|
640
|
-
@pytest.mark.asyncio
|
|
641
|
-
async def test_status_handles_git_command_failure(self) -> None:
|
|
642
|
-
"""get_repo_status should handle git command failures gracefully."""
|
|
643
|
-
result = await get_repo_status("test", Path("/nonexistent"))
|
|
644
|
-
|
|
645
|
-
assert result.error is not None
|
|
646
|
-
assert isinstance(result.error, str)
|
|
647
|
-
|
|
648
|
-
@pytest.mark.asyncio
|
|
649
|
-
async def test_branch_handles_git_command_failure(self) -> None:
|
|
650
|
-
"""create_or_checkout_branch should handle git command failures."""
|
|
651
|
-
result = await create_or_checkout_branch(
|
|
652
|
-
"test", Path("/nonexistent"), "feature/test"
|
|
653
|
-
)
|
|
654
|
-
|
|
655
|
-
assert result.action in (BranchAction.SKIPPED, BranchAction.ERROR)
|
|
656
|
-
|
|
657
|
-
@pytest.mark.asyncio
|
|
658
|
-
async def test_status_all_handles_partial_failures(self) -> None:
|
|
659
|
-
"""get_all_repo_status should return results even with partial failures."""
|
|
660
|
-
repos = [
|
|
661
|
-
("good-repo", Path(".")), # Current dir should work
|
|
662
|
-
("bad-repo", Path("/nonexistent")),
|
|
663
|
-
]
|
|
664
|
-
|
|
665
|
-
results = await get_all_repo_status(repos)
|
|
666
|
-
|
|
667
|
-
assert len(results) == 2
|
|
668
|
-
# One should have error, one should not
|
|
669
|
-
|
|
670
|
-
@pytest.mark.asyncio
|
|
671
|
-
async def test_branches_handles_partial_failures(self) -> None:
|
|
672
|
-
"""create_feature_branches should return results even with partial failures."""
|
|
673
|
-
repos = [
|
|
674
|
-
("good-repo", Path(".")),
|
|
675
|
-
("bad-repo", Path("/nonexistent")),
|
|
676
|
-
]
|
|
677
|
-
|
|
678
|
-
results = await create_feature_branches(repos, "feature/test")
|
|
679
|
-
|
|
680
|
-
assert len(results) == 2
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
# =============================================================================
|
|
684
|
-
# AC5: Output formatting - Results
|
|
685
|
-
# =============================================================================
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
class TestFormatResults:
|
|
689
|
-
"""Tests for format_results function."""
|
|
690
|
-
|
|
691
|
-
def test_includes_branch_name(self) -> None:
|
|
692
|
-
"""format_results should include the target branch name."""
|
|
693
|
-
results = [
|
|
694
|
-
BranchResult(
|
|
695
|
-
name="test-repo",
|
|
696
|
-
path=Path("/test"),
|
|
697
|
-
branch="feature/test",
|
|
698
|
-
action=BranchAction.CREATED,
|
|
699
|
-
current_branch="feature/test",
|
|
700
|
-
)
|
|
701
|
-
]
|
|
702
|
-
|
|
703
|
-
output = format_results(results, "feature/test")
|
|
704
|
-
|
|
705
|
-
assert "feature/test" in output
|
|
706
|
-
|
|
707
|
-
def test_shows_action_taken(self) -> None:
|
|
708
|
-
"""format_results should show what action was taken."""
|
|
709
|
-
results = [
|
|
710
|
-
BranchResult(
|
|
711
|
-
name="test-repo",
|
|
712
|
-
path=Path("/test"),
|
|
713
|
-
branch="feature/test",
|
|
714
|
-
action=BranchAction.CREATED,
|
|
715
|
-
current_branch="feature/test",
|
|
716
|
-
)
|
|
717
|
-
]
|
|
718
|
-
|
|
719
|
-
output = format_results(results, "feature/test")
|
|
720
|
-
|
|
721
|
-
assert "created" in output.lower() or "Created" in output
|
|
722
|
-
|
|
723
|
-
def test_shows_verification_summary(self) -> None:
|
|
724
|
-
"""format_results should include verification summary."""
|
|
725
|
-
results = [
|
|
726
|
-
BranchResult(
|
|
727
|
-
name="repo-a",
|
|
728
|
-
path=Path("/a"),
|
|
729
|
-
branch="feature/test",
|
|
730
|
-
action=BranchAction.CREATED,
|
|
731
|
-
current_branch="feature/test",
|
|
732
|
-
),
|
|
733
|
-
BranchResult(
|
|
734
|
-
name="repo-b",
|
|
735
|
-
path=Path("/b"),
|
|
736
|
-
branch="feature/test",
|
|
737
|
-
action=BranchAction.CHECKED_OUT_LOCAL,
|
|
738
|
-
current_branch="feature/test",
|
|
739
|
-
),
|
|
740
|
-
]
|
|
741
|
-
|
|
742
|
-
output = format_results(results, "feature/test")
|
|
743
|
-
|
|
744
|
-
# Should have some kind of summary/verification section
|
|
745
|
-
assert "Verification" in output or "Summary" in output or "Done" in output
|
|
746
|
-
|
|
747
|
-
def test_shows_errors(self) -> None:
|
|
748
|
-
"""format_results should show errors clearly."""
|
|
749
|
-
results = [
|
|
750
|
-
BranchResult(
|
|
751
|
-
name="bad-repo",
|
|
752
|
-
path=Path("/bad"),
|
|
753
|
-
branch="feature/test",
|
|
754
|
-
action=BranchAction.ERROR,
|
|
755
|
-
error="Git command failed",
|
|
756
|
-
)
|
|
757
|
-
]
|
|
758
|
-
|
|
759
|
-
output = format_results(results, "feature/test")
|
|
760
|
-
|
|
761
|
-
assert "error" in output.lower() or "Error" in output
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
# =============================================================================
|
|
765
|
-
# AC6: Cross-platform compatibility
|
|
766
|
-
# =============================================================================
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
class TestCrossPlatformCompatibility:
|
|
770
|
-
"""Tests for cross-platform compatibility."""
|
|
771
|
-
|
|
772
|
-
def test_paths_use_pathlib(self) -> None:
|
|
773
|
-
"""All path handling should use pathlib.Path."""
|
|
774
|
-
# RepoStatus uses Path
|
|
775
|
-
status = RepoStatus(
|
|
776
|
-
name="test",
|
|
777
|
-
path=Path("/test"),
|
|
778
|
-
branch="main",
|
|
779
|
-
changes=[],
|
|
780
|
-
unpushed_commits=[],
|
|
781
|
-
)
|
|
782
|
-
assert isinstance(status.path, Path)
|
|
783
|
-
|
|
784
|
-
# BranchResult uses Path
|
|
785
|
-
result = BranchResult(
|
|
786
|
-
name="test",
|
|
787
|
-
path=Path("/test"),
|
|
788
|
-
branch="main",
|
|
789
|
-
action=BranchAction.CREATED,
|
|
790
|
-
)
|
|
791
|
-
assert isinstance(result.path, Path)
|
|
792
|
-
|
|
793
|
-
def test_no_shell_specific_commands(self) -> None:
|
|
794
|
-
"""Implementation should not use shell-specific commands."""
|
|
795
|
-
# This is more of a code review check, but we can verify the modules exist
|
|
796
|
-
import pennyfarthing_scripts.git.status_all as status_mod
|
|
797
|
-
import pennyfarthing_scripts.git.create_branches as branch_mod
|
|
798
|
-
|
|
799
|
-
# Modules should exist and be importable
|
|
800
|
-
assert status_mod is not None
|
|
801
|
-
assert branch_mod is not None
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
# =============================================================================
|
|
805
|
-
# AC7/AC8: Performance (asyncio.gather verification)
|
|
806
|
-
# =============================================================================
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
class TestAsyncPerformance:
|
|
810
|
-
"""Tests verifying async parallel execution."""
|
|
811
|
-
|
|
812
|
-
@pytest.mark.asyncio
|
|
813
|
-
async def test_status_runs_in_parallel(self) -> None:
|
|
814
|
-
"""get_all_repo_status should run git commands in parallel."""
|
|
815
|
-
# Create mock that tracks call timing
|
|
816
|
-
call_times = []
|
|
817
|
-
|
|
818
|
-
async def mock_get_status(name: str, path: Path) -> RepoStatus:
|
|
819
|
-
import time
|
|
820
|
-
|
|
821
|
-
call_times.append(time.time())
|
|
822
|
-
await asyncio.sleep(0.01) # Small delay
|
|
823
|
-
return RepoStatus(
|
|
824
|
-
name=name, path=path, branch="main", changes=[], unpushed_commits=[]
|
|
825
|
-
)
|
|
826
|
-
|
|
827
|
-
repos = [(f"repo-{i}", Path(f"/repo-{i}")) for i in range(3)]
|
|
828
|
-
|
|
829
|
-
with patch(
|
|
830
|
-
"pennyfarthing_scripts.git.status_all.get_repo_status",
|
|
831
|
-
side_effect=mock_get_status,
|
|
832
|
-
):
|
|
833
|
-
await get_all_repo_status(repos)
|
|
834
|
-
|
|
835
|
-
# All calls should happen nearly simultaneously (within 0.05s of each other)
|
|
836
|
-
if len(call_times) >= 2:
|
|
837
|
-
time_spread = max(call_times) - min(call_times)
|
|
838
|
-
assert time_spread < 0.05 # Should be nearly simultaneous
|
|
839
|
-
|
|
840
|
-
@pytest.mark.asyncio
|
|
841
|
-
async def test_branch_creation_runs_in_parallel(self) -> None:
|
|
842
|
-
"""create_feature_branches should run git commands in parallel."""
|
|
843
|
-
call_times = []
|
|
844
|
-
|
|
845
|
-
async def mock_create_branch(
|
|
846
|
-
name: str, path: Path, branch: str
|
|
847
|
-
) -> BranchResult:
|
|
848
|
-
import time
|
|
849
|
-
|
|
850
|
-
call_times.append(time.time())
|
|
851
|
-
await asyncio.sleep(0.01)
|
|
852
|
-
return BranchResult(
|
|
853
|
-
name=name, path=path, branch=branch, action=BranchAction.CREATED
|
|
854
|
-
)
|
|
855
|
-
|
|
856
|
-
repos = [(f"repo-{i}", Path(f"/repo-{i}")) for i in range(3)]
|
|
857
|
-
|
|
858
|
-
with patch(
|
|
859
|
-
"pennyfarthing_scripts.git.create_branches.create_or_checkout_branch",
|
|
860
|
-
side_effect=mock_create_branch,
|
|
861
|
-
):
|
|
862
|
-
await create_feature_branches(repos, "feature/test")
|
|
863
|
-
|
|
864
|
-
if len(call_times) >= 2:
|
|
865
|
-
time_spread = max(call_times) - min(call_times)
|
|
866
|
-
assert time_spread < 0.05
|