@pennyfarthing/core 10.0.1 → 10.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +13 -3
- package/pennyfarthing-dist/agents/README.md +348 -0
- package/pennyfarthing-dist/agents/architect.md +180 -0
- package/pennyfarthing-dist/agents/dev.md +169 -0
- package/pennyfarthing-dist/agents/devops.md +203 -0
- package/pennyfarthing-dist/agents/handoff.md +235 -0
- package/pennyfarthing-dist/agents/orchestrator.md +182 -0
- package/pennyfarthing-dist/agents/pm.md +152 -0
- package/pennyfarthing-dist/agents/reviewer-preflight.md +129 -0
- package/pennyfarthing-dist/agents/reviewer.md +197 -0
- package/pennyfarthing-dist/agents/sm-file-summary.md +79 -0
- package/pennyfarthing-dist/agents/sm-finish.md +82 -0
- package/pennyfarthing-dist/agents/sm-handoff.md +129 -0
- package/pennyfarthing-dist/agents/sm-setup.md +251 -0
- package/pennyfarthing-dist/agents/sm.md +298 -0
- package/pennyfarthing-dist/agents/tea.md +161 -0
- package/pennyfarthing-dist/agents/tech-writer.md +226 -0
- package/pennyfarthing-dist/agents/testing-runner.md +184 -0
- package/pennyfarthing-dist/agents/ux-designer.md +236 -0
- package/pennyfarthing-dist/agents/workflow-status-check.md +96 -0
- package/pennyfarthing-dist/commands/architect.md +9 -0
- package/pennyfarthing-dist/commands/benchmark-control.md +69 -0
- package/pennyfarthing-dist/commands/benchmark.md +485 -0
- package/pennyfarthing-dist/commands/brainstorming.md +91 -0
- package/pennyfarthing-dist/commands/check.md +156 -0
- package/pennyfarthing-dist/commands/chore.md +218 -0
- package/pennyfarthing-dist/commands/close-epic.md +139 -0
- package/pennyfarthing-dist/commands/continue-session.md +218 -0
- package/pennyfarthing-dist/commands/create-branches-from-story.md +358 -0
- package/pennyfarthing-dist/commands/create-theme.md +29 -0
- package/pennyfarthing-dist/commands/dev.md +9 -0
- package/pennyfarthing-dist/commands/devops.md +9 -0
- package/pennyfarthing-dist/commands/fix-blocker.md +22 -0
- package/pennyfarthing-dist/commands/git-cleanup.md +57 -0
- package/pennyfarthing-dist/commands/health-check.md +143 -0
- package/pennyfarthing-dist/commands/help.md +264 -0
- package/pennyfarthing-dist/commands/job-fair.md +102 -0
- package/pennyfarthing-dist/commands/list-themes.md +21 -0
- package/pennyfarthing-dist/commands/new-work.md +23 -0
- package/pennyfarthing-dist/commands/orchestrator.md +9 -0
- package/pennyfarthing-dist/commands/parallel-work.md +73 -0
- package/pennyfarthing-dist/commands/party-mode.md +77 -0
- package/pennyfarthing-dist/commands/patch.md +210 -0
- package/pennyfarthing-dist/commands/permissions.md +193 -0
- package/pennyfarthing-dist/commands/pm.md +9 -0
- package/pennyfarthing-dist/commands/prime.md +136 -0
- package/pennyfarthing-dist/commands/release.md +74 -0
- package/pennyfarthing-dist/commands/repo-status.md +49 -0
- package/pennyfarthing-dist/commands/retro.md +200 -0
- package/pennyfarthing-dist/commands/reviewer.md +9 -0
- package/pennyfarthing-dist/commands/run-ci.md +116 -0
- package/pennyfarthing-dist/commands/set-theme.md +56 -0
- package/pennyfarthing-dist/commands/setup.md +65 -0
- package/pennyfarthing-dist/commands/show-theme.md +21 -0
- package/pennyfarthing-dist/commands/sm.md +9 -0
- package/pennyfarthing-dist/commands/solo.md +447 -0
- package/pennyfarthing-dist/commands/sprint-planning.md +109 -0
- package/pennyfarthing-dist/commands/sprint.md +142 -0
- package/pennyfarthing-dist/commands/standalone.md +194 -0
- package/pennyfarthing-dist/commands/start-epic.md +168 -0
- package/pennyfarthing-dist/commands/sync-epic-to-jira.md +184 -0
- package/pennyfarthing-dist/commands/sync-work-with-sprint.md +373 -0
- package/pennyfarthing-dist/commands/tea.md +9 -0
- package/pennyfarthing-dist/commands/tech-writer.md +9 -0
- package/pennyfarthing-dist/commands/theme-maker.md +676 -0
- package/pennyfarthing-dist/commands/update-domain-docs.md +83 -0
- package/pennyfarthing-dist/commands/ux-designer.md +9 -0
- package/pennyfarthing-dist/commands/work.md +25 -0
- package/pennyfarthing-dist/commands/workflow.md +21 -0
- package/pennyfarthing-dist/guides/agent-behavior.md +92 -0
- package/pennyfarthing-dist/guides/agent-coordination.md +475 -0
- package/pennyfarthing-dist/guides/agent-tag-taxonomy.md +432 -0
- package/pennyfarthing-dist/guides/agent-template-strategic.md +148 -0
- package/pennyfarthing-dist/guides/agent-template-tactical.md +162 -0
- package/pennyfarthing-dist/guides/hooks.md +230 -0
- package/pennyfarthing-dist/guides/measurement-framework.md +210 -0
- package/pennyfarthing-dist/guides/patterns/approval-gates-pattern.md +766 -0
- package/pennyfarthing-dist/guides/patterns/fan-out-fan-in-pattern.md +574 -0
- package/pennyfarthing-dist/guides/patterns/helper-delegation-pattern.md +488 -0
- package/pennyfarthing-dist/guides/patterns/tdd-flow-pattern.md +402 -0
- package/pennyfarthing-dist/guides/permission-protocol.md +188 -0
- package/pennyfarthing-dist/guides/persona-loading.md +46 -0
- package/pennyfarthing-dist/guides/prompt-patterns.md +338 -0
- package/pennyfarthing-dist/guides/scale-levels.md +114 -0
- package/pennyfarthing-dist/guides/session-artifacts.md +193 -0
- package/pennyfarthing-dist/guides/session-schema.md +346 -0
- package/pennyfarthing-dist/guides/skill-schema.md +412 -0
- package/pennyfarthing-dist/guides/workflow-schema.md +257 -0
- package/pennyfarthing-dist/guides/workflow-step-schema.md +512 -0
- package/pennyfarthing-dist/guides/worktree-mode.md +113 -0
- package/pennyfarthing-dist/guides/xml-tags.md +627 -0
- package/pennyfarthing-dist/output-styles/teaching.md +33 -0
- package/pennyfarthing-dist/output-styles/terse.md +20 -0
- package/pennyfarthing-dist/output-styles/verbose.md +28 -0
- package/pennyfarthing-dist/personas/themes/a-team.yaml +331 -0
- package/pennyfarthing-dist/personas/themes/alice-in-wonderland.yaml +324 -0
- package/pennyfarthing-dist/personas/themes/battlestar-galactica.yaml +282 -0
- package/pennyfarthing-dist/personas/themes/blade-runner.yaml +289 -0
- package/pennyfarthing-dist/personas/themes/catch-22.yaml +304 -0
- package/pennyfarthing-dist/personas/themes/control.yaml +201 -0
- package/pennyfarthing-dist/personas/themes/cowboy-bebop.yaml +315 -0
- package/pennyfarthing-dist/personas/themes/discworld.yaml +334 -0
- package/pennyfarthing-dist/personas/themes/doctor-who.yaml +284 -0
- package/pennyfarthing-dist/personas/themes/dune.yaml +301 -0
- package/pennyfarthing-dist/personas/themes/firefly.yaml +320 -0
- package/pennyfarthing-dist/personas/themes/game-of-thrones.yaml +284 -0
- package/pennyfarthing-dist/personas/themes/harry-potter.yaml +316 -0
- package/pennyfarthing-dist/personas/themes/hitchhikers-guide.yaml +323 -0
- package/pennyfarthing-dist/personas/themes/lord-of-the-rings.yaml +326 -0
- package/pennyfarthing-dist/personas/themes/mad-max.yaml +349 -0
- package/pennyfarthing-dist/personas/themes/mash.yaml +329 -0
- package/pennyfarthing-dist/personas/themes/princess-bride.yaml +344 -0
- package/pennyfarthing-dist/personas/themes/sandman.yaml +282 -0
- package/pennyfarthing-dist/personas/themes/star-trek-tng.yaml +358 -0
- package/pennyfarthing-dist/personas/themes/star-wars.yaml +297 -0
- package/pennyfarthing-dist/personas/themes/the-expanse.yaml +337 -0
- package/pennyfarthing-dist/personas/themes/the-matrix.yaml +342 -0
- package/pennyfarthing-dist/personas/themes/watchmen.yaml +285 -0
- package/pennyfarthing-dist/personas/themes/west-wing.yaml +285 -0
- package/pennyfarthing-dist/personas/themes/x-files.yaml +296 -0
- package/pennyfarthing-dist/scripts/README.md +87 -0
- package/pennyfarthing-dist/scripts/core/README.md +25 -0
- package/pennyfarthing-dist/scripts/core/agent-session.sh +390 -0
- package/pennyfarthing-dist/scripts/core/check-context.sh +194 -0
- package/pennyfarthing-dist/scripts/core/handoff-marker.sh +112 -0
- package/pennyfarthing-dist/scripts/core/phase-check-start.sh +90 -0
- package/pennyfarthing-dist/scripts/core/prime.sh +30 -0
- package/pennyfarthing-dist/scripts/cyclist/is-cyclist.sh +21 -0
- package/pennyfarthing-dist/scripts/git/README.md +25 -0
- package/pennyfarthing-dist/scripts/git/create-feature-branches.sh +267 -0
- package/pennyfarthing-dist/scripts/git/git-status-all.sh +152 -0
- package/pennyfarthing-dist/scripts/git/install-git-hooks.sh +79 -0
- package/pennyfarthing-dist/scripts/git/release.sh +246 -0
- package/pennyfarthing-dist/scripts/git/worktree-manager.sh +497 -0
- package/pennyfarthing-dist/scripts/health/drift-detection.sh +156 -0
- package/pennyfarthing-dist/scripts/hooks/README.md +32 -0
- package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
- package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +106 -0
- package/pennyfarthing-dist/scripts/hooks/context-circuit-breaker.sh +95 -0
- package/pennyfarthing-dist/scripts/hooks/context-warning.sh +65 -0
- package/pennyfarthing-dist/scripts/hooks/otel-auto-config.sh +35 -0
- package/pennyfarthing-dist/scripts/hooks/post-merge.sh +150 -0
- package/pennyfarthing-dist/scripts/hooks/pre-commit.sh +190 -0
- package/pennyfarthing-dist/scripts/hooks/pre-edit-check.sh +71 -0
- package/pennyfarthing-dist/scripts/hooks/pre-push.sh +42 -0
- package/pennyfarthing-dist/scripts/hooks/question-reflector-check.sh +20 -0
- package/pennyfarthing-dist/scripts/hooks/question_reflector_check.py +499 -0
- package/pennyfarthing-dist/scripts/hooks/schema-validation.sh +30 -0
- package/pennyfarthing-dist/scripts/hooks/session-start.sh +97 -0
- package/pennyfarthing-dist/scripts/hooks/session-stop.sh +65 -0
- package/pennyfarthing-dist/scripts/hooks/sprint-yaml-validation.sh +78 -0
- package/pennyfarthing-dist/scripts/hooks/welcome-hook.sh +94 -0
- package/pennyfarthing-dist/scripts/jira/README.md +36 -0
- package/pennyfarthing-dist/scripts/jira/create-jira-epic.sh +95 -0
- package/pennyfarthing-dist/scripts/jira/create-jira-story.sh +91 -0
- package/pennyfarthing-dist/scripts/jira/jira-claim-story.sh +22 -0
- package/pennyfarthing-dist/scripts/jira/jira-lib.sh +464 -0
- package/pennyfarthing-dist/scripts/jira/jira-reconcile.sh +260 -0
- package/pennyfarthing-dist/scripts/jira/jira-sync-story.sh +18 -0
- package/pennyfarthing-dist/scripts/jira/jira-sync.sh +16 -0
- package/pennyfarthing-dist/scripts/jira/sync-epic-jira.sh +16 -0
- package/pennyfarthing-dist/scripts/jira/sync-epic-to-jira.sh +16 -0
- package/pennyfarthing-dist/scripts/lib/README.md +29 -0
- package/pennyfarthing-dist/scripts/lib/background-tasks.sh +177 -0
- package/pennyfarthing-dist/scripts/lib/checkpoint.sh +136 -0
- package/pennyfarthing-dist/scripts/lib/common.sh +212 -0
- package/pennyfarthing-dist/scripts/lib/file-lock.sh +269 -0
- package/pennyfarthing-dist/scripts/lib/find-root.sh +58 -0
- package/pennyfarthing-dist/scripts/lib/logging.sh +186 -0
- package/pennyfarthing-dist/scripts/lib/retry.sh +76 -0
- package/pennyfarthing-dist/scripts/maintenance/migrate-theme-schema.mjs +102 -0
- package/pennyfarthing-dist/scripts/maintenance/sidecar-health.sh +91 -0
- package/pennyfarthing-dist/scripts/misc/README.md +44 -0
- package/pennyfarthing-dist/scripts/misc/add-short-names.sh +13 -0
- package/pennyfarthing-dist/scripts/misc/add_short_names.py +226 -0
- package/pennyfarthing-dist/scripts/misc/backlog.sh +77 -0
- package/pennyfarthing-dist/scripts/misc/check-status.sh +247 -0
- package/pennyfarthing-dist/scripts/misc/find-related-work.sh +231 -0
- package/pennyfarthing-dist/scripts/misc/generate-skill-docs.sh +107 -0
- package/pennyfarthing-dist/scripts/misc/log-skill-usage.sh +74 -0
- package/pennyfarthing-dist/scripts/misc/migrate-bmad-workflow.sh +10 -0
- package/pennyfarthing-dist/scripts/misc/migrate_bmad_workflow.py +319 -0
- package/pennyfarthing-dist/scripts/misc/repo-scan.sh +141 -0
- package/pennyfarthing-dist/scripts/misc/repo-utils.sh +778 -0
- package/pennyfarthing-dist/scripts/misc/run-ci.sh +212 -0
- package/pennyfarthing-dist/scripts/misc/run-timestamp.sh +7 -0
- package/pennyfarthing-dist/scripts/misc/session-cleanup.sh +319 -0
- package/pennyfarthing-dist/scripts/misc/skill-usage-report.sh +193 -0
- package/pennyfarthing-dist/scripts/misc/statusline.sh +257 -0
- package/pennyfarthing-dist/scripts/misc/uninstall.sh +275 -0
- package/pennyfarthing-dist/scripts/misc/validate-subagent-frontmatter.sh +160 -0
- package/pennyfarthing-dist/scripts/portraits/generate-portraits.py +417 -0
- package/pennyfarthing-dist/scripts/portraits/generate-portraits.sh +54 -0
- package/pennyfarthing-dist/scripts/sprint/README.md +29 -0
- package/pennyfarthing-dist/scripts/sprint/archive-story.sh +133 -0
- package/pennyfarthing-dist/scripts/sprint/available-stories.sh +91 -0
- package/pennyfarthing-dist/scripts/sprint/check-story.sh +158 -0
- package/pennyfarthing-dist/scripts/sprint/get-epic-field.sh +52 -0
- package/pennyfarthing-dist/scripts/sprint/get-story-field.sh +63 -0
- package/pennyfarthing-dist/scripts/sprint/list-future.sh +145 -0
- package/pennyfarthing-dist/scripts/sprint/new-sprint.sh +110 -0
- package/pennyfarthing-dist/scripts/sprint/promote-epic.sh +148 -0
- package/pennyfarthing-dist/scripts/sprint/sprint-common.sh +415 -0
- package/pennyfarthing-dist/scripts/sprint/sprint-info.sh +33 -0
- package/pennyfarthing-dist/scripts/sprint/sprint-metrics.sh +230 -0
- package/pennyfarthing-dist/scripts/sprint/sprint-status.sh +134 -0
- package/pennyfarthing-dist/scripts/sprint/validate-sprint-yaml.sh +139 -0
- package/pennyfarthing-dist/scripts/story/README.md +23 -0
- package/pennyfarthing-dist/scripts/story/create-story.sh +19 -0
- package/pennyfarthing-dist/scripts/story/size-story.sh +18 -0
- package/pennyfarthing-dist/scripts/story/story-template.sh +18 -0
- package/pennyfarthing-dist/scripts/test/README.md +23 -0
- package/pennyfarthing-dist/scripts/test/ensure-swebench-data.sh +59 -0
- package/pennyfarthing-dist/scripts/test/ground-truth-judge.py +220 -0
- package/pennyfarthing-dist/scripts/test/swebench-judge.py +374 -0
- package/pennyfarthing-dist/scripts/test/test-cache.sh +165 -0
- package/pennyfarthing-dist/scripts/test/test-setup.sh +337 -0
- package/pennyfarthing-dist/scripts/tests/check.test.sh +582 -0
- package/pennyfarthing-dist/scripts/tests/dev-story-workflow-import.test.sh +515 -0
- package/pennyfarthing-dist/scripts/tests/epics-and-stories-workflow-import.test.sh +599 -0
- package/pennyfarthing-dist/scripts/tests/handoff-phase-update.test.sh +332 -0
- package/pennyfarthing-dist/scripts/tests/implementation-readiness-workflow-import.test.sh +573 -0
- package/pennyfarthing-dist/scripts/tests/migrate-bmad-workflow.test.sh +859 -0
- package/pennyfarthing-dist/scripts/tests/prd-workflow-import.test.sh +662 -0
- package/pennyfarthing-dist/scripts/tests/project-context-workflow-import.test.sh +589 -0
- package/pennyfarthing-dist/scripts/tests/test-character-voice.sh +106 -0
- package/pennyfarthing-dist/scripts/tests/test-drift-detection.sh +597 -0
- package/pennyfarthing-dist/scripts/tests/test-post-merge-hook.sh +514 -0
- package/pennyfarthing-dist/scripts/tests/test-session-checkpoint.sh +517 -0
- package/pennyfarthing-dist/scripts/tests/test-solo-command.sh +331 -0
- package/pennyfarthing-dist/scripts/tests/ux-design-workflow-import.test.sh +647 -0
- package/pennyfarthing-dist/scripts/theme/README.md +22 -0
- package/pennyfarthing-dist/scripts/theme/compute-theme-tiers.sh +13 -0
- package/pennyfarthing-dist/scripts/theme/compute_theme_tiers.py +402 -0
- package/pennyfarthing-dist/scripts/theme/list-themes.sh +30 -0
- package/pennyfarthing-dist/scripts/theme/update-theme-tiers.sh +97 -0
- package/pennyfarthing-dist/scripts/validation/validate-agent-schema.sh +576 -0
- package/pennyfarthing-dist/scripts/workflow/README.md +28 -0
- package/pennyfarthing-dist/scripts/workflow/check.py +502 -0
- package/pennyfarthing-dist/scripts/workflow/check.sh +24 -0
- package/pennyfarthing-dist/scripts/workflow/complete-step.py +304 -0
- package/pennyfarthing-dist/scripts/workflow/finish-story.sh +154 -0
- package/pennyfarthing-dist/scripts/workflow/fix-session-phase.sh +222 -0
- package/pennyfarthing-dist/scripts/workflow/get-workflow-type.py +61 -0
- package/pennyfarthing-dist/scripts/workflow/get-workflow-type.sh +13 -0
- package/pennyfarthing-dist/scripts/workflow/list-workflows.sh +124 -0
- package/pennyfarthing-dist/scripts/workflow/phase-owner.sh +34 -0
- package/pennyfarthing-dist/scripts/workflow/resume-workflow.sh +157 -0
- package/pennyfarthing-dist/scripts/workflow/show-workflow.sh +132 -0
- package/pennyfarthing-dist/scripts/workflow/start-workflow.sh +250 -0
- package/pennyfarthing-dist/scripts/workflow/workflow-status.sh +161 -0
- package/pennyfarthing-dist/skills/agentic-patterns/SKILL.md +246 -0
- package/pennyfarthing-dist/skills/changelog/SKILL.md +385 -0
- package/pennyfarthing-dist/skills/code-review/SKILL.md +172 -0
- package/pennyfarthing-dist/skills/context-engineering/SKILL.md +277 -0
- package/pennyfarthing-dist/skills/cyclist/SKILL.md +88 -0
- package/pennyfarthing-dist/skills/dev-patterns/SKILL.md +461 -0
- package/pennyfarthing-dist/skills/finalize-run/SKILL.md +261 -0
- package/pennyfarthing-dist/skills/jira/SKILL.md +508 -0
- package/pennyfarthing-dist/skills/judge/SKILL.md +644 -0
- package/pennyfarthing-dist/skills/just/SKILL.md +414 -0
- package/pennyfarthing-dist/skills/mermaid/SKILL.md +256 -0
- package/pennyfarthing-dist/skills/otel/skill.md +227 -0
- package/pennyfarthing-dist/skills/permissions/skill.md +157 -0
- package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +187 -0
- package/pennyfarthing-dist/skills/skill-registry.schema.json +107 -0
- package/pennyfarthing-dist/skills/skill-registry.yaml +393 -0
- package/pennyfarthing-dist/skills/sprint/scripts/archive-story.sh +101 -0
- package/pennyfarthing-dist/skills/sprint/scripts/available-stories.sh +97 -0
- package/pennyfarthing-dist/skills/sprint/scripts/check-story.sh +164 -0
- package/pennyfarthing-dist/skills/sprint/scripts/create-jira-epic.sh +101 -0
- package/pennyfarthing-dist/skills/sprint/scripts/new-sprint.sh +116 -0
- package/pennyfarthing-dist/skills/sprint/scripts/promote-epic.sh +164 -0
- package/pennyfarthing-dist/skills/sprint/scripts/sprint-info.sh +39 -0
- package/pennyfarthing-dist/skills/sprint/scripts/sprint-status.sh +147 -0
- package/pennyfarthing-dist/skills/sprint/scripts/sync-epic-jira.sh +93 -0
- package/pennyfarthing-dist/skills/sprint/skill.md +465 -0
- package/pennyfarthing-dist/skills/story/scripts/create-story.sh +159 -0
- package/pennyfarthing-dist/skills/story/scripts/size-story.sh +198 -0
- package/pennyfarthing-dist/skills/story/scripts/story-template.sh +162 -0
- package/pennyfarthing-dist/skills/story/skill.md +219 -0
- package/pennyfarthing-dist/skills/systematic-debugging/SKILL.md +446 -0
- package/pennyfarthing-dist/skills/testing/SKILL.md +121 -0
- package/pennyfarthing-dist/skills/testing/references/troubleshooting.md +124 -0
- package/pennyfarthing-dist/skills/theme/skill.md +141 -0
- package/pennyfarthing-dist/skills/theme-creation/SKILL.md +178 -0
- package/pennyfarthing-dist/skills/workflow/scripts/list-workflows.sh +91 -0
- package/pennyfarthing-dist/skills/workflow/scripts/resume-workflow.sh +163 -0
- package/pennyfarthing-dist/skills/workflow/scripts/show-workflow.sh +138 -0
- package/pennyfarthing-dist/skills/workflow/scripts/start-workflow.sh +273 -0
- package/pennyfarthing-dist/skills/workflow/scripts/workflow-status.sh +167 -0
- package/pennyfarthing-dist/skills/workflow/skill.md +345 -0
- package/pennyfarthing-dist/skills/yq/SKILL.md +272 -0
- package/pennyfarthing-dist/templates/LEADERBOARD.schema.yaml +187 -0
- package/pennyfarthing-dist/templates/LEADERBOARD.template.md +59 -0
- package/pennyfarthing-dist/templates/agent-scopes.yaml.template +276 -0
- package/pennyfarthing-dist/templates/pennyfarthing-settings.yaml.template +61 -0
- package/pennyfarthing-dist/templates/persona-config.yaml.template +22 -0
- package/pennyfarthing-dist/templates/preferences.yaml.template +15 -0
- package/pennyfarthing-dist/templates/settings.local.json.template +130 -0
- package/pennyfarthing-dist/templates/setup-env.sh.template +18 -0
- package/pennyfarthing-dist/templates/shared-context.md.template +70 -0
- package/pennyfarthing-dist/templates/sidecar/decisions.md.template +40 -0
- package/pennyfarthing-dist/templates/sidecar/gotchas.md.template +37 -0
- package/pennyfarthing-dist/templates/sidecar/patterns.md.template +34 -0
- package/pennyfarthing-dist/workflows/agent-docs.yaml +70 -0
- package/pennyfarthing-dist/workflows/architecture/steps/step-01-initialize.md +113 -0
- package/pennyfarthing-dist/workflows/architecture/steps/step-01b-continue.md +105 -0
- package/pennyfarthing-dist/workflows/architecture/steps/step-02-context.md +127 -0
- package/pennyfarthing-dist/workflows/architecture/steps/step-03-patterns.md +145 -0
- package/pennyfarthing-dist/workflows/architecture/steps/step-04-components.md +150 -0
- package/pennyfarthing-dist/workflows/architecture/steps/step-05-interfaces.md +145 -0
- package/pennyfarthing-dist/workflows/architecture/steps/step-06-risks.md +154 -0
- package/pennyfarthing-dist/workflows/architecture/steps/step-07-document.md +172 -0
- package/pennyfarthing-dist/workflows/architecture/templates/architecture-decision.md +102 -0
- package/pennyfarthing-dist/workflows/architecture.yaml +65 -0
- package/pennyfarthing-dist/workflows/bdd.yaml +60 -0
- package/pennyfarthing-dist/workflows/brainstorming/brain-methods.csv +62 -0
- package/pennyfarthing-dist/workflows/brainstorming/checklist.md +44 -0
- package/pennyfarthing-dist/workflows/brainstorming/instructions.md +736 -0
- package/pennyfarthing-dist/workflows/brainstorming/workflow.yaml +49 -0
- package/pennyfarthing-dist/workflows/code-review/checklist.md +23 -0
- package/pennyfarthing-dist/workflows/code-review/instructions.md +234 -0
- package/pennyfarthing-dist/workflows/code-review/workflow.yaml +51 -0
- package/pennyfarthing-dist/workflows/dev-story/checklist.md +80 -0
- package/pennyfarthing-dist/workflows/dev-story/instructions.xml +410 -0
- package/pennyfarthing-dist/workflows/dev-story/workflow.yaml +50 -0
- package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-01-validate-prerequisites.md +281 -0
- package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-02-design-epics.md +256 -0
- package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-03-create-stories.md +298 -0
- package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-04-final-validation.md +177 -0
- package/pennyfarthing-dist/workflows/epics-and-stories/steps/step-05-import-to-future.md +145 -0
- package/pennyfarthing-dist/workflows/epics-and-stories/templates/epics-template.md +57 -0
- package/pennyfarthing-dist/workflows/epics-and-stories/workflow.yaml +28 -0
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-01-analyze.md +103 -0
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-02-categorize.md +147 -0
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-03-execute.md +215 -0
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-04-verify.md +97 -0
- package/pennyfarthing-dist/workflows/git-cleanup/steps/step-05-complete.md +78 -0
- package/pennyfarthing-dist/workflows/git-cleanup.yaml +59 -0
- package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-01-document-discovery.md +211 -0
- package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-02-prd-analysis.md +199 -0
- package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-03-epic-coverage-validation.md +202 -0
- package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-04-ux-alignment.md +162 -0
- package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-05-epic-quality-review.md +280 -0
- package/pennyfarthing-dist/workflows/implementation-readiness/steps/step-06-final-assessment.md +158 -0
- package/pennyfarthing-dist/workflows/implementation-readiness/templates/readiness-report-template.md +4 -0
- package/pennyfarthing-dist/workflows/implementation-readiness/workflow.yaml +40 -0
- package/pennyfarthing-dist/workflows/interactive-debug/steps/step-01-connect.md +257 -0
- package/pennyfarthing-dist/workflows/interactive-debug/steps/step-02-explore.md +107 -0
- package/pennyfarthing-dist/workflows/interactive-debug/steps/step-03-fix.md +127 -0
- package/pennyfarthing-dist/workflows/interactive-debug/steps/step-04-commit.md +122 -0
- package/pennyfarthing-dist/workflows/interactive-debug/workflow.yaml +51 -0
- package/pennyfarthing-dist/workflows/patch.yaml +67 -0
- package/pennyfarthing-dist/workflows/prd/data/domain-complexity.csv +13 -0
- package/pennyfarthing-dist/workflows/prd/data/prd-purpose.md +197 -0
- package/pennyfarthing-dist/workflows/prd/data/project-types.csv +11 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-01-init.md +197 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-01b-continue.md +159 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-02-discovery.md +230 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-03-success.md +232 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-04-journeys.md +219 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-05-domain.md +213 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-06-innovation.md +232 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-07-project-type.md +243 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-08-scoping.md +234 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-09-functional.md +237 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-10-nonfunctional.md +248 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-11-polish.md +223 -0
- package/pennyfarthing-dist/workflows/prd/steps-c/step-12-complete.md +186 -0
- package/pennyfarthing-dist/workflows/prd/steps-e/step-e-01-discovery.md +253 -0
- package/pennyfarthing-dist/workflows/prd/steps-e/step-e-01b-legacy-conversion.md +214 -0
- package/pennyfarthing-dist/workflows/prd/steps-e/step-e-02-review.md +255 -0
- package/pennyfarthing-dist/workflows/prd/steps-e/step-e-03-edit.md +259 -0
- package/pennyfarthing-dist/workflows/prd/steps-e/step-e-04-complete.md +174 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-01-discovery.md +224 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-02-format-detection.md +197 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-02b-parity-check.md +215 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-03-density-validation.md +180 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-04-brief-coverage-validation.md +220 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-05-measurability-validation.md +234 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-06-traceability-validation.md +223 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-07-implementation-leakage-validation.md +211 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-08-domain-compliance-validation.md +249 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-09-project-type-validation.md +269 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-10-smart-validation.md +215 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-11-holistic-quality-validation.md +270 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-12-completeness-validation.md +248 -0
- package/pennyfarthing-dist/workflows/prd/steps-v/step-v-13-report-complete.md +238 -0
- package/pennyfarthing-dist/workflows/prd/templates/prd-template.md +10 -0
- package/pennyfarthing-dist/workflows/prd/workflow.yaml +42 -0
- package/pennyfarthing-dist/workflows/product-brief/steps/step-01-init.md +195 -0
- package/pennyfarthing-dist/workflows/product-brief/steps/step-01b-continue.md +180 -0
- package/pennyfarthing-dist/workflows/product-brief/steps/step-02-vision.md +221 -0
- package/pennyfarthing-dist/workflows/product-brief/steps/step-03-users.md +224 -0
- package/pennyfarthing-dist/workflows/product-brief/steps/step-04-metrics.md +228 -0
- package/pennyfarthing-dist/workflows/product-brief/steps/step-05-scope.md +243 -0
- package/pennyfarthing-dist/workflows/product-brief/steps/step-06-complete.md +216 -0
- package/pennyfarthing-dist/workflows/product-brief/templates/product-brief.template.md +10 -0
- package/pennyfarthing-dist/workflows/product-brief/workflow.yaml +31 -0
- package/pennyfarthing-dist/workflows/project-context/project-context-template.md +21 -0
- package/pennyfarthing-dist/workflows/project-context/steps/step-01-discover.md +206 -0
- package/pennyfarthing-dist/workflows/project-context/steps/step-02-generate.md +349 -0
- package/pennyfarthing-dist/workflows/project-context/steps/step-03-complete.md +306 -0
- package/pennyfarthing-dist/workflows/project-context/workflow.yaml +27 -0
- package/pennyfarthing-dist/workflows/project-setup/steps/step-01-discover.md +157 -0
- package/pennyfarthing-dist/workflows/project-setup/steps/step-02-clone-repos.md +217 -0
- package/pennyfarthing-dist/workflows/project-setup/steps/step-03-repos-yaml.md +159 -0
- package/pennyfarthing-dist/workflows/project-setup/steps/step-04-claude-md.md +186 -0
- package/pennyfarthing-dist/workflows/project-setup/steps/step-05-shared-context.md +185 -0
- package/pennyfarthing-dist/workflows/project-setup/steps/step-06-task-runner.md +279 -0
- package/pennyfarthing-dist/workflows/project-setup/steps/step-07-theme.md +200 -0
- package/pennyfarthing-dist/workflows/project-setup/steps/step-08-theme-packs.md +142 -0
- package/pennyfarthing-dist/workflows/project-setup/steps/step-09-cyclist.md +245 -0
- package/pennyfarthing-dist/workflows/project-setup/steps/step-10-complete.md +204 -0
- package/pennyfarthing-dist/workflows/project-setup/workflow.yaml +41 -0
- package/pennyfarthing-dist/workflows/quick-dev/steps/step-01-mode-detection.md +177 -0
- package/pennyfarthing-dist/workflows/quick-dev/steps/step-02-context-gathering.md +143 -0
- package/pennyfarthing-dist/workflows/quick-dev/steps/step-03-execute.md +138 -0
- package/pennyfarthing-dist/workflows/quick-dev/steps/step-04-self-check.md +135 -0
- package/pennyfarthing-dist/workflows/quick-dev/steps/step-05-adversarial-review.md +129 -0
- package/pennyfarthing-dist/workflows/quick-dev/steps/step-06-resolve-findings.md +163 -0
- package/pennyfarthing-dist/workflows/quick-dev/workflow.yaml +27 -0
- package/pennyfarthing-dist/workflows/quick-spec/steps/step-01-understand.md +201 -0
- package/pennyfarthing-dist/workflows/quick-spec/steps/step-02-investigate.md +156 -0
- package/pennyfarthing-dist/workflows/quick-spec/steps/step-03-generate.md +140 -0
- package/pennyfarthing-dist/workflows/quick-spec/steps/step-04-review.md +203 -0
- package/pennyfarthing-dist/workflows/quick-spec/tech-spec-template.md +74 -0
- package/pennyfarthing-dist/workflows/quick-spec/workflow.yaml +27 -0
- package/pennyfarthing-dist/workflows/release/steps/step-01-preflight.md +105 -0
- package/pennyfarthing-dist/workflows/release/steps/step-02-bump.md +95 -0
- package/pennyfarthing-dist/workflows/release/steps/step-03-changelog.md +125 -0
- package/pennyfarthing-dist/workflows/release/steps/step-04-readme.md +101 -0
- package/pennyfarthing-dist/workflows/release/steps/step-05-claude-md.md +102 -0
- package/pennyfarthing-dist/workflows/release/steps/step-06-retro.md +59 -0
- package/pennyfarthing-dist/workflows/release/steps/step-07-commit.md +109 -0
- package/pennyfarthing-dist/workflows/release/steps/step-08-merge.md +65 -0
- package/pennyfarthing-dist/workflows/release/steps/step-09-push.md +75 -0
- package/pennyfarthing-dist/workflows/release/steps/step-10-publish.md +93 -0
- package/pennyfarthing-dist/workflows/release/steps/step-11-finalize.md +71 -0
- package/pennyfarthing-dist/workflows/release.yaml +62 -0
- package/pennyfarthing-dist/workflows/research/steps-domain/step-01-init.md +159 -0
- package/pennyfarthing-dist/workflows/research/steps-domain/step-02-domain-analysis.md +253 -0
- package/pennyfarthing-dist/workflows/research/steps-domain/step-03-competitive-landscape.md +263 -0
- package/pennyfarthing-dist/workflows/research/steps-domain/step-04-regulatory-focus.md +232 -0
- package/pennyfarthing-dist/workflows/research/steps-domain/step-05-technical-trends.md +260 -0
- package/pennyfarthing-dist/workflows/research/steps-domain/step-06-research-synthesis.md +477 -0
- package/pennyfarthing-dist/workflows/research/steps-market/step-01-init.md +205 -0
- package/pennyfarthing-dist/workflows/research/steps-market/step-02-customer-behavior.md +262 -0
- package/pennyfarthing-dist/workflows/research/steps-market/step-02-customer-insights.md +227 -0
- package/pennyfarthing-dist/workflows/research/steps-market/step-03-customer-pain-points.md +275 -0
- package/pennyfarthing-dist/workflows/research/steps-market/step-04-customer-decisions.md +286 -0
- package/pennyfarthing-dist/workflows/research/steps-market/step-05-competitive-analysis.md +203 -0
- package/pennyfarthing-dist/workflows/research/steps-market/step-06-research-completion.md +510 -0
- package/pennyfarthing-dist/workflows/research/steps-technical/step-01-init.md +159 -0
- package/pennyfarthing-dist/workflows/research/steps-technical/step-02-technical-overview.md +264 -0
- package/pennyfarthing-dist/workflows/research/steps-technical/step-03-integration-patterns.md +274 -0
- package/pennyfarthing-dist/workflows/research/steps-technical/step-04-architectural-patterns.md +228 -0
- package/pennyfarthing-dist/workflows/research/steps-technical/step-05-implementation-research.md +267 -0
- package/pennyfarthing-dist/workflows/research/steps-technical/step-06-research-synthesis.md +522 -0
- package/pennyfarthing-dist/workflows/research/templates/research.template.md +29 -0
- package/pennyfarthing-dist/workflows/research/workflow.yaml +45 -0
- package/pennyfarthing-dist/workflows/retrospective/checklist.md +31 -0
- package/pennyfarthing-dist/workflows/retrospective/instructions.md +1443 -0
- package/pennyfarthing-dist/workflows/retrospective/workflow.yaml +50 -0
- package/pennyfarthing-dist/workflows/sprint-planning/checklist.md +33 -0
- package/pennyfarthing-dist/workflows/sprint-planning/sprint-status-template.yaml +55 -0
- package/pennyfarthing-dist/workflows/sprint-planning/steps/step-01-parse-epic-files.md +69 -0
- package/pennyfarthing-dist/workflows/sprint-planning/steps/step-02-build-sprint-status.md +61 -0
- package/pennyfarthing-dist/workflows/sprint-planning/steps/step-03-status-detection.md +80 -0
- package/pennyfarthing-dist/workflows/sprint-planning/steps/step-04-generate-status-file.md +90 -0
- package/pennyfarthing-dist/workflows/sprint-planning/steps/step-05-validate-and-report.md +78 -0
- package/pennyfarthing-dist/workflows/sprint-planning/workflow.yaml +34 -0
- package/pennyfarthing-dist/workflows/tdd.yaml +50 -0
- package/pennyfarthing-dist/workflows/trivial.yaml +40 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-01-init.md +141 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-01b-continue.md +133 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-02-discovery.md +196 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-03-core-experience.md +222 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-04-emotional-response.md +225 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-05-inspiration.md +240 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-06-design-system.md +258 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-07-defining-experience.md +260 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-08-visual-foundation.md +230 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-09-design-directions.md +230 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-10-user-journeys.md +247 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-11-component-strategy.md +254 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-12-ux-patterns.md +243 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-13-responsive-accessibility.md +270 -0
- package/pennyfarthing-dist/workflows/ux-design/steps/step-14-complete.md +234 -0
- package/pennyfarthing-dist/workflows/ux-design/ux-design-template.md +13 -0
- package/pennyfarthing-dist/workflows/ux-design/workflow.yaml +41 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
complete-step.py - Complete the current step of a stepped workflow
|
|
4
|
+
|
|
5
|
+
Usage: python complete-step.py [name] [--step N]
|
|
6
|
+
|
|
7
|
+
Advances session state: increments current step, updates steps completed,
|
|
8
|
+
recalculates completion percentage, and marks workflow as completed when
|
|
9
|
+
all steps are done.
|
|
10
|
+
|
|
11
|
+
If no name provided, detects from active session.
|
|
12
|
+
If --step N provided, completes that specific step instead of current step.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import re
|
|
17
|
+
import sys
|
|
18
|
+
from datetime import datetime, timezone
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
import yaml
|
|
23
|
+
except ImportError:
|
|
24
|
+
print("Error: PyYAML required. Install with: pip install pyyaml", file=sys.stderr)
|
|
25
|
+
sys.exit(1)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def find_project_root() -> Path:
|
|
29
|
+
"""Find project root by looking for .pennyfarthing directory."""
|
|
30
|
+
# Honor explicit PROJECT_ROOT override
|
|
31
|
+
import os
|
|
32
|
+
override = os.environ.get("PROJECT_ROOT")
|
|
33
|
+
if override:
|
|
34
|
+
return Path(override)
|
|
35
|
+
|
|
36
|
+
current = Path.cwd()
|
|
37
|
+
while current != current.parent:
|
|
38
|
+
if (current / ".pennyfarthing").is_dir():
|
|
39
|
+
return current
|
|
40
|
+
current = current.parent
|
|
41
|
+
print("Error: Could not find .pennyfarthing/ directory", file=sys.stderr)
|
|
42
|
+
print("Are you in a Pennyfarthing-enabled project?", file=sys.stderr)
|
|
43
|
+
sys.exit(1)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def parse_session_field(content: str, field: str) -> str:
|
|
47
|
+
"""Extract a field value from session markdown."""
|
|
48
|
+
pattern = rf"^- \*\*{re.escape(field)}:\*\*\s*(.+)$"
|
|
49
|
+
match = re.search(pattern, content, re.MULTILINE)
|
|
50
|
+
return match.group(1).strip() if match else ""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def find_session_file(session_dir: Path, workflow_name: str | None) -> tuple[Path, str]:
|
|
54
|
+
"""Find session file and determine workflow name.
|
|
55
|
+
|
|
56
|
+
Returns (session_path, workflow_name).
|
|
57
|
+
"""
|
|
58
|
+
if workflow_name:
|
|
59
|
+
session_file = session_dir / f"{workflow_name}-workflow-session.md"
|
|
60
|
+
if not session_file.exists():
|
|
61
|
+
print(f"Error: No session found for workflow '{workflow_name}'", file=sys.stderr)
|
|
62
|
+
print(f"\nUse `/workflow start {workflow_name}` to begin.", file=sys.stderr)
|
|
63
|
+
sys.exit(1)
|
|
64
|
+
return session_file, workflow_name
|
|
65
|
+
|
|
66
|
+
# Auto-detect from session directory
|
|
67
|
+
sessions = list(session_dir.glob("*-workflow-session.md"))
|
|
68
|
+
if not sessions:
|
|
69
|
+
print("Error: No active workflow session found.", file=sys.stderr)
|
|
70
|
+
print("\nUsage: complete-step.py [name] [--step N]", file=sys.stderr)
|
|
71
|
+
sys.exit(1)
|
|
72
|
+
|
|
73
|
+
session_file = sorted(sessions)[0]
|
|
74
|
+
content = session_file.read_text()
|
|
75
|
+
|
|
76
|
+
# Try to extract workflow name from content
|
|
77
|
+
wf_match = re.search(r"^\*\*Workflow:\*\*\s*(.+)$", content, re.MULTILINE)
|
|
78
|
+
if wf_match:
|
|
79
|
+
name = wf_match.group(1).strip()
|
|
80
|
+
else:
|
|
81
|
+
# Derive from filename
|
|
82
|
+
name = session_file.stem.replace("-workflow-session", "")
|
|
83
|
+
|
|
84
|
+
return session_file, name
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def find_workflow_file(workflows_dir: Path, workflow_name: str) -> Path:
|
|
88
|
+
"""Find workflow YAML definition."""
|
|
89
|
+
flat = workflows_dir / f"{workflow_name}.yaml"
|
|
90
|
+
if flat.exists():
|
|
91
|
+
return flat
|
|
92
|
+
|
|
93
|
+
nested = workflows_dir / workflow_name / "workflow.yaml"
|
|
94
|
+
if nested.exists():
|
|
95
|
+
return nested
|
|
96
|
+
|
|
97
|
+
print(f"Error: Workflow definition '{workflow_name}' not found", file=sys.stderr)
|
|
98
|
+
sys.exit(1)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def count_steps(steps_path: Path) -> int:
|
|
102
|
+
"""Count step files in a directory."""
|
|
103
|
+
return len([
|
|
104
|
+
f for f in steps_path.iterdir()
|
|
105
|
+
if f.is_file() and re.match(r"step-\d+", f.name) and f.suffix == ".md"
|
|
106
|
+
])
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def parse_steps_completed(value: str) -> list[int]:
|
|
110
|
+
"""Parse steps completed array from string like '[1, 2, 3]'."""
|
|
111
|
+
if not value or value == "[]":
|
|
112
|
+
return []
|
|
113
|
+
# Extract numbers from the bracket notation
|
|
114
|
+
return [int(n) for n in re.findall(r"\d+", value)]
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def format_steps_completed(steps: list[int]) -> str:
|
|
118
|
+
"""Format steps list as bracket notation."""
|
|
119
|
+
if not steps:
|
|
120
|
+
return "[]"
|
|
121
|
+
return "[" + ", ".join(str(s) for s in steps) + "]"
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def find_next_step_file(steps_path: Path, step_number: int) -> Path | None:
|
|
125
|
+
"""Find step file for a given step number."""
|
|
126
|
+
padded = f"{step_number:02d}"
|
|
127
|
+
matches = sorted([
|
|
128
|
+
f for f in steps_path.iterdir()
|
|
129
|
+
if f.is_file()
|
|
130
|
+
and (f.name.startswith(f"step-{padded}") or f.name.startswith(f"step-{step_number}-"))
|
|
131
|
+
and f.suffix == ".md"
|
|
132
|
+
])
|
|
133
|
+
return matches[0] if matches else None
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def strip_frontmatter(content: str) -> str:
|
|
137
|
+
"""Remove YAML frontmatter from step file content."""
|
|
138
|
+
if not content.startswith("---"):
|
|
139
|
+
return content
|
|
140
|
+
# Find the closing ---
|
|
141
|
+
end = content.find("---", 3)
|
|
142
|
+
if end == -1:
|
|
143
|
+
return content
|
|
144
|
+
return content[end + 3:].lstrip("\n")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def main() -> int:
|
|
148
|
+
parser = argparse.ArgumentParser(
|
|
149
|
+
description="Complete the current step of a stepped workflow"
|
|
150
|
+
)
|
|
151
|
+
parser.add_argument("name", nargs="?", default=None,
|
|
152
|
+
help="Workflow name (auto-detects from session if omitted)")
|
|
153
|
+
parser.add_argument("--step", type=int, default=None, dest="step_override",
|
|
154
|
+
help="Complete a specific step number instead of current step")
|
|
155
|
+
args = parser.parse_args()
|
|
156
|
+
|
|
157
|
+
project_root = find_project_root()
|
|
158
|
+
workflows_dir = project_root / ".pennyfarthing" / "workflows"
|
|
159
|
+
session_dir = project_root / ".session"
|
|
160
|
+
|
|
161
|
+
# Find session file
|
|
162
|
+
session_file, workflow_name = find_session_file(session_dir, args.name)
|
|
163
|
+
content = session_file.read_text()
|
|
164
|
+
|
|
165
|
+
# Parse session state
|
|
166
|
+
current_step_str = parse_session_field(content, "Current Step") or "1"
|
|
167
|
+
current_step = int(current_step_str)
|
|
168
|
+
mode = parse_session_field(content, "Mode") or "create"
|
|
169
|
+
status = parse_session_field(content, "Status") or "in_progress"
|
|
170
|
+
steps_completed_str = parse_session_field(content, "Steps Completed") or "[]"
|
|
171
|
+
|
|
172
|
+
# Check if already completed
|
|
173
|
+
if status == "completed":
|
|
174
|
+
print(f"# Workflow Already Completed: {workflow_name}")
|
|
175
|
+
print()
|
|
176
|
+
print("This workflow has already been completed.")
|
|
177
|
+
print()
|
|
178
|
+
print("To start a new session, delete the session file:")
|
|
179
|
+
print("```bash")
|
|
180
|
+
print(f'rm "{session_file}"')
|
|
181
|
+
print("```")
|
|
182
|
+
print()
|
|
183
|
+
print(f"Then run `/workflow start {workflow_name}`")
|
|
184
|
+
return 0
|
|
185
|
+
|
|
186
|
+
# Determine which step to complete
|
|
187
|
+
completing_step = args.step_override if args.step_override is not None else current_step
|
|
188
|
+
|
|
189
|
+
# Find workflow file and resolve steps path
|
|
190
|
+
workflow_file = find_workflow_file(workflows_dir, workflow_name)
|
|
191
|
+
workflow_dir = workflow_file.parent
|
|
192
|
+
|
|
193
|
+
with open(workflow_file) as f:
|
|
194
|
+
wf_data = yaml.safe_load(f)
|
|
195
|
+
|
|
196
|
+
wf = wf_data.get("workflow", {})
|
|
197
|
+
|
|
198
|
+
# Resolve steps path based on mode
|
|
199
|
+
modes = wf.get("modes", {})
|
|
200
|
+
mode_path = modes.get(mode)
|
|
201
|
+
if mode_path and mode_path != "null":
|
|
202
|
+
steps_path_str = mode_path
|
|
203
|
+
else:
|
|
204
|
+
steps_path_str = wf.get("steps", {}).get("path", ".")
|
|
205
|
+
|
|
206
|
+
# Resolve relative path
|
|
207
|
+
if steps_path_str.startswith("./"):
|
|
208
|
+
steps_path = workflow_dir / steps_path_str[2:]
|
|
209
|
+
elif not Path(steps_path_str).is_absolute():
|
|
210
|
+
steps_path = project_root / steps_path_str
|
|
211
|
+
else:
|
|
212
|
+
steps_path = Path(steps_path_str)
|
|
213
|
+
|
|
214
|
+
# Count total steps
|
|
215
|
+
step_count = count_steps(steps_path)
|
|
216
|
+
|
|
217
|
+
# Update Steps Completed array
|
|
218
|
+
steps_completed = parse_steps_completed(steps_completed_str)
|
|
219
|
+
if completing_step not in steps_completed:
|
|
220
|
+
steps_completed.append(completing_step)
|
|
221
|
+
new_steps_completed = format_steps_completed(steps_completed)
|
|
222
|
+
|
|
223
|
+
# Calculate new current step
|
|
224
|
+
next_step = completing_step + 1
|
|
225
|
+
|
|
226
|
+
# Count completed and calculate percentage
|
|
227
|
+
completed_count = len(steps_completed)
|
|
228
|
+
completion_pct = (completed_count * 100 // step_count) if step_count > 0 else 0
|
|
229
|
+
|
|
230
|
+
# Determine new status
|
|
231
|
+
new_status = "completed" if completed_count >= step_count else "in_progress"
|
|
232
|
+
|
|
233
|
+
# Update timestamp
|
|
234
|
+
now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
235
|
+
|
|
236
|
+
# Update session file content
|
|
237
|
+
content = re.sub(
|
|
238
|
+
r"^- \*\*Current Step:\*\*.*$",
|
|
239
|
+
f"- **Current Step:** {next_step}",
|
|
240
|
+
content, flags=re.MULTILINE
|
|
241
|
+
)
|
|
242
|
+
content = re.sub(
|
|
243
|
+
r"^- \*\*Steps Completed:\*\*.*$",
|
|
244
|
+
f"- **Steps Completed:** {new_steps_completed}",
|
|
245
|
+
content, flags=re.MULTILINE
|
|
246
|
+
)
|
|
247
|
+
content = re.sub(
|
|
248
|
+
r"^- \*\*Last Updated:\*\*.*$",
|
|
249
|
+
f"- **Last Updated:** {now}",
|
|
250
|
+
content, flags=re.MULTILINE
|
|
251
|
+
)
|
|
252
|
+
content = re.sub(
|
|
253
|
+
r"^- \*\*Status:\*\*.*$",
|
|
254
|
+
f"- **Status:** {new_status}",
|
|
255
|
+
content, flags=re.MULTILINE
|
|
256
|
+
)
|
|
257
|
+
content = re.sub(
|
|
258
|
+
r"^- Completion:.*$",
|
|
259
|
+
f"- Completion: {completion_pct}%",
|
|
260
|
+
content, flags=re.MULTILINE
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
# Write updated session file
|
|
264
|
+
session_file.write_text(content)
|
|
265
|
+
|
|
266
|
+
# Output result
|
|
267
|
+
if new_status == "completed":
|
|
268
|
+
print(f"# Workflow Complete: {workflow_name}")
|
|
269
|
+
print()
|
|
270
|
+
print(f"All {step_count} steps completed!")
|
|
271
|
+
print()
|
|
272
|
+
print(f"**Final Progress:** {completion_pct}%")
|
|
273
|
+
print(f"**Steps Completed:** {new_steps_completed}")
|
|
274
|
+
print()
|
|
275
|
+
print(f"Session updated: {session_file}")
|
|
276
|
+
else:
|
|
277
|
+
print(f"# Step {completing_step} Complete")
|
|
278
|
+
print()
|
|
279
|
+
print(f"**Progress:** Step {next_step} of {step_count} ({completion_pct}% complete)")
|
|
280
|
+
print(f"**Steps Completed:** {new_steps_completed}")
|
|
281
|
+
print()
|
|
282
|
+
print("---")
|
|
283
|
+
print()
|
|
284
|
+
print(f"## Step {next_step} of {step_count}")
|
|
285
|
+
print()
|
|
286
|
+
|
|
287
|
+
# Find and output next step file
|
|
288
|
+
next_step_file = find_next_step_file(steps_path, next_step)
|
|
289
|
+
if next_step_file:
|
|
290
|
+
step_content = next_step_file.read_text()
|
|
291
|
+
print(strip_frontmatter(step_content))
|
|
292
|
+
|
|
293
|
+
print()
|
|
294
|
+
print("---")
|
|
295
|
+
print()
|
|
296
|
+
print("**Controls:**")
|
|
297
|
+
print("- `C` - Continue to next step")
|
|
298
|
+
print("- `/workflow status` - Check progress")
|
|
299
|
+
|
|
300
|
+
return 0
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
if __name__ == "__main__":
|
|
304
|
+
sys.exit(main())
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Finish a story: archive, merge PR, transition Jira, update sprint YAML
|
|
3
|
+
# Usage: finish-story.sh <story-id> [--dry-run]
|
|
4
|
+
#
|
|
5
|
+
# Example: finish-story.sh MSSCI-12052
|
|
6
|
+
# finish-story.sh MSSCI-12052 --dry-run
|
|
7
|
+
#
|
|
8
|
+
# Prerequisites:
|
|
9
|
+
# - Session file exists at .session/{story-id}-session.md
|
|
10
|
+
# - PR is approved and mergeable
|
|
11
|
+
# - Reviewer has approved (phase: finish in session)
|
|
12
|
+
#
|
|
13
|
+
# This script performs:
|
|
14
|
+
# 1. Archive session file to sprint/archive/{jira-key}-session.md
|
|
15
|
+
# 2. Squash merge PR and delete remote branch
|
|
16
|
+
# 3. Transition Jira to Done
|
|
17
|
+
# 4. Update sprint YAML (status: done, completed date)
|
|
18
|
+
# 5. Clean up local branch and session file
|
|
19
|
+
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
STORY_ID="${1:-}"
|
|
23
|
+
DRY_RUN=false
|
|
24
|
+
|
|
25
|
+
# Parse options
|
|
26
|
+
for arg in "$@"; do
|
|
27
|
+
case $arg in
|
|
28
|
+
--dry-run)
|
|
29
|
+
DRY_RUN=true
|
|
30
|
+
shift
|
|
31
|
+
;;
|
|
32
|
+
esac
|
|
33
|
+
done
|
|
34
|
+
|
|
35
|
+
if [[ -z "$STORY_ID" ]]; then
|
|
36
|
+
echo "Usage: finish-story.sh <story-id> [--dry-run]"
|
|
37
|
+
echo ""
|
|
38
|
+
echo "Options:"
|
|
39
|
+
echo " --dry-run Show what would be done without executing"
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Find project root
|
|
44
|
+
source "$(dirname "${BASH_SOURCE[0]}")/../lib/find-root.sh"
|
|
45
|
+
|
|
46
|
+
SESSION_FILE="$PROJECT_ROOT/.session/${STORY_ID}-session.md"
|
|
47
|
+
SPRINT_FILE="$PROJECT_ROOT/sprint/current-sprint.yaml"
|
|
48
|
+
ARCHIVE_DIR="$PROJECT_ROOT/sprint/archive"
|
|
49
|
+
|
|
50
|
+
# Ensure archive directory exists
|
|
51
|
+
mkdir -p "$ARCHIVE_DIR"
|
|
52
|
+
|
|
53
|
+
# Validate session file exists
|
|
54
|
+
if [[ ! -f "$SESSION_FILE" ]]; then
|
|
55
|
+
echo "Error: Session file not found: $SESSION_FILE"
|
|
56
|
+
exit 1
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
# Extract metadata from session file (handle both "**Jira:**" and "- **Jira:**" formats)
|
|
60
|
+
# Also handle markdown link format: [MSSCI-12721](https://...)
|
|
61
|
+
JIRA_KEY=$(grep -E '\*\*Jira:\*\*' "$SESSION_FILE" | sed 's/.*\*\*Jira:\*\* //' | sed 's/\[//' | sed 's/\].*//' | tr -d ' ' || echo "")
|
|
62
|
+
# Extract branch - strip any trailing annotations like "(pushed)"
|
|
63
|
+
BRANCH=$(grep -E '\*\*Branch:\*\*' "$SESSION_FILE" | sed 's/.*\*\*Branch:\*\* //' | sed 's/ *(.*//' | tr -d ' ' || echo "")
|
|
64
|
+
|
|
65
|
+
# Try to get PR number from session file first (format: **PR:** #422 - title)
|
|
66
|
+
PR_NUMBER=$(grep -E '\*\*PR:\*\*' "$SESSION_FILE" | sed 's/.*#\([0-9]*\).*/\1/' || echo "")
|
|
67
|
+
|
|
68
|
+
# Fallback: try to get Jira key from sprint YAML if not in session
|
|
69
|
+
if [[ -z "$JIRA_KEY" || "$JIRA_KEY" == "null" ]]; then
|
|
70
|
+
JIRA_KEY=$(yq ".epics[].stories[] | select(.id == \"$STORY_ID\") | .jira // \"\"" "$SPRINT_FILE" 2>/dev/null | head -1 || echo "")
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
if [[ -z "$JIRA_KEY" || "$JIRA_KEY" == "null" ]]; then
|
|
74
|
+
echo "Error: Could not determine Jira key for story $STORY_ID"
|
|
75
|
+
echo "Check session file or sprint YAML for jira: field"
|
|
76
|
+
exit 1
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Fallback: get PR number from GitHub if not in session file
|
|
80
|
+
if [[ -z "$PR_NUMBER" ]] && [[ -n "$BRANCH" ]]; then
|
|
81
|
+
PR_NUMBER=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null || echo "")
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
TODAY=$(date +%Y-%m-%d)
|
|
85
|
+
|
|
86
|
+
echo "=== Finish Story: $STORY_ID ==="
|
|
87
|
+
echo "Jira Key: $JIRA_KEY"
|
|
88
|
+
echo "Branch: ${BRANCH:-none}"
|
|
89
|
+
echo "PR: ${PR_NUMBER:-none}"
|
|
90
|
+
echo ""
|
|
91
|
+
|
|
92
|
+
if $DRY_RUN; then
|
|
93
|
+
echo "[DRY RUN] Would perform:"
|
|
94
|
+
echo " 1. Archive session → $ARCHIVE_DIR/${JIRA_KEY}-session.md"
|
|
95
|
+
if [[ -n "$PR_NUMBER" ]]; then
|
|
96
|
+
echo " 2. Merge PR #$PR_NUMBER (squash, delete branch)"
|
|
97
|
+
else
|
|
98
|
+
echo " 2. No PR to merge"
|
|
99
|
+
fi
|
|
100
|
+
echo " 3. Transition $JIRA_KEY to Done"
|
|
101
|
+
echo " 4. Update sprint YAML (status: done, completed: $TODAY)"
|
|
102
|
+
echo " 5. Delete local branch: $BRANCH"
|
|
103
|
+
echo " 6. Remove session file"
|
|
104
|
+
exit 0
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# Step 1: Archive session file
|
|
108
|
+
echo "1. Archiving session file..."
|
|
109
|
+
cp "$SESSION_FILE" "$ARCHIVE_DIR/${JIRA_KEY}-session.md"
|
|
110
|
+
echo " → $ARCHIVE_DIR/${JIRA_KEY}-session.md"
|
|
111
|
+
|
|
112
|
+
# Step 2: Merge PR (if exists)
|
|
113
|
+
if [[ -n "$PR_NUMBER" ]]; then
|
|
114
|
+
echo "2. Merging PR #$PR_NUMBER..."
|
|
115
|
+
gh pr merge "$PR_NUMBER" --squash --delete-branch || {
|
|
116
|
+
echo " Warning: PR merge failed (may already be merged)"
|
|
117
|
+
}
|
|
118
|
+
else
|
|
119
|
+
echo "2. No PR found for branch $BRANCH (skipping merge)"
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# Step 3: Transition Jira to Done
|
|
123
|
+
echo "3. Transitioning Jira to Done..."
|
|
124
|
+
jira issue move "$JIRA_KEY" "Done" 2>/dev/null || {
|
|
125
|
+
echo " Warning: Jira transition failed (may already be Done)"
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# Step 4: Update sprint YAML
|
|
129
|
+
echo "4. Updating sprint YAML..."
|
|
130
|
+
# Update status to done
|
|
131
|
+
yq eval -i "(.epics[].stories[] | select(.id == \"$STORY_ID\")).status = \"done\"" "$SPRINT_FILE"
|
|
132
|
+
# Add completed date
|
|
133
|
+
yq eval -i "(.epics[].stories[] | select(.id == \"$STORY_ID\")).completed = \"$TODAY\"" "$SPRINT_FILE"
|
|
134
|
+
# Remove assigned_to (no longer in progress)
|
|
135
|
+
yq eval -i "del((.epics[].stories[] | select(.id == \"$STORY_ID\")).assigned_to)" "$SPRINT_FILE"
|
|
136
|
+
echo " → status: done, completed: $TODAY"
|
|
137
|
+
|
|
138
|
+
# Step 5: Clean up git
|
|
139
|
+
echo "5. Cleaning up git..."
|
|
140
|
+
git checkout develop 2>/dev/null || git checkout main 2>/dev/null || true
|
|
141
|
+
git pull origin "$(git branch --show-current)" 2>/dev/null || true
|
|
142
|
+
|
|
143
|
+
if [[ -n "$BRANCH" ]]; then
|
|
144
|
+
git branch -d "$BRANCH" 2>/dev/null || echo " Local branch already deleted"
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
# Step 6: Remove session file
|
|
148
|
+
echo "6. Removing session file..."
|
|
149
|
+
rm "$SESSION_FILE"
|
|
150
|
+
|
|
151
|
+
echo ""
|
|
152
|
+
echo "=== Story $STORY_ID Complete ==="
|
|
153
|
+
echo "Archived: sprint/archive/${JIRA_KEY}-session.md"
|
|
154
|
+
echo "Jira: https://1898andco.atlassian.net/browse/$JIRA_KEY"
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Fix session file phase tracking when handoffs didn't update properly
|
|
3
|
+
# Usage: fix-session-phase.sh <story-id> <target-phase> [--dry-run]
|
|
4
|
+
#
|
|
5
|
+
# Example: fix-session-phase.sh 56-1 review
|
|
6
|
+
# fix-session-phase.sh MSSCI-12190 approved --dry-run
|
|
7
|
+
#
|
|
8
|
+
# This script detects the current phase, validates the target phase is reachable,
|
|
9
|
+
# and updates the session file's Workflow Tracking section:
|
|
10
|
+
# - Updates **Phase:** field to target phase
|
|
11
|
+
# - Adds missing rows to Phase History table
|
|
12
|
+
# - Adds missing rows to Handoff History table
|
|
13
|
+
#
|
|
14
|
+
# Valid phases for TDD workflow: setup → red → green → review → approved → finish
|
|
15
|
+
# Valid phases for trivial workflow: setup → implement → review → approved → finish
|
|
16
|
+
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
|
|
19
|
+
STORY_ID="${1:-}"
|
|
20
|
+
TARGET_PHASE="${2:-}"
|
|
21
|
+
DRY_RUN=false
|
|
22
|
+
|
|
23
|
+
# Parse options
|
|
24
|
+
for arg in "$@"; do
|
|
25
|
+
case $arg in
|
|
26
|
+
--dry-run)
|
|
27
|
+
DRY_RUN=true
|
|
28
|
+
;;
|
|
29
|
+
esac
|
|
30
|
+
done
|
|
31
|
+
|
|
32
|
+
if [[ -z "$STORY_ID" ]] || [[ -z "$TARGET_PHASE" ]]; then
|
|
33
|
+
echo "Usage: fix-session-phase.sh <story-id> <target-phase> [--dry-run]"
|
|
34
|
+
echo ""
|
|
35
|
+
echo "Arguments:"
|
|
36
|
+
echo " story-id Story ID (e.g., 56-1 or MSSCI-12190)"
|
|
37
|
+
echo " target-phase Target phase to set (e.g., review, approved, finish)"
|
|
38
|
+
echo ""
|
|
39
|
+
echo "Options:"
|
|
40
|
+
echo " --dry-run Show what would be done without executing"
|
|
41
|
+
echo ""
|
|
42
|
+
echo "Examples:"
|
|
43
|
+
echo " fix-session-phase.sh 56-1 review # Update to review phase"
|
|
44
|
+
echo " fix-session-phase.sh 56-1 approved # Update to approved phase"
|
|
45
|
+
echo " fix-session-phase.sh 56-1 finish --dry-run # Preview finish update"
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Find project root
|
|
50
|
+
source "$(dirname "${BASH_SOURCE[0]}")/../lib/find-root.sh"
|
|
51
|
+
|
|
52
|
+
# Try multiple session file naming patterns
|
|
53
|
+
SESSION_FILE=""
|
|
54
|
+
STORY_ID_LOWER=$(echo "$STORY_ID" | tr '[:upper:]' '[:lower:]')
|
|
55
|
+
for pattern in "${STORY_ID}-session.md" "${STORY_ID_LOWER}-session.md"; do
|
|
56
|
+
if [[ -f "$PROJECT_ROOT/.session/$pattern" ]]; then
|
|
57
|
+
SESSION_FILE="$PROJECT_ROOT/.session/$pattern"
|
|
58
|
+
break
|
|
59
|
+
fi
|
|
60
|
+
done
|
|
61
|
+
|
|
62
|
+
# Also try without the epic prefix (e.g., MSSCI-12190 might be in 56-1-session.md)
|
|
63
|
+
if [[ -z "$SESSION_FILE" ]]; then
|
|
64
|
+
# Search for session files containing this story ID
|
|
65
|
+
found=$(grep -l "Jira:.*$STORY_ID\|ID:.*$STORY_ID" "$PROJECT_ROOT/.session/"*-session.md 2>/dev/null | head -1 || echo "")
|
|
66
|
+
if [[ -n "$found" ]]; then
|
|
67
|
+
SESSION_FILE="$found"
|
|
68
|
+
fi
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
if [[ -z "$SESSION_FILE" ]] || [[ ! -f "$SESSION_FILE" ]]; then
|
|
72
|
+
echo "Error: Session file not found for story $STORY_ID"
|
|
73
|
+
echo "Searched in: $PROJECT_ROOT/.session/"
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
echo "Session file: $SESSION_FILE"
|
|
78
|
+
|
|
79
|
+
# Extract current state
|
|
80
|
+
CURRENT_PHASE=$(grep -E '^\*\*Phase:\*\*' "$SESSION_FILE" | sed 's/\*\*Phase:\*\* //' | tr -d ' ' || echo "unknown")
|
|
81
|
+
WORKFLOW=$(grep -E '^\*\*Workflow:\*\*' "$SESSION_FILE" | head -1 | sed 's/\*\*Workflow:\*\* //' | tr -d ' ' || echo "tdd")
|
|
82
|
+
PHASE_STARTED=$(grep -E '^\*\*Phase Started:\*\*' "$SESSION_FILE" | sed 's/\*\*Phase Started:\*\* //' | tr -d ' ' || echo "")
|
|
83
|
+
|
|
84
|
+
echo "Current phase: $CURRENT_PHASE"
|
|
85
|
+
echo "Target phase: $TARGET_PHASE"
|
|
86
|
+
echo "Workflow: $WORKFLOW"
|
|
87
|
+
|
|
88
|
+
# Define valid phase sequences
|
|
89
|
+
case "$WORKFLOW" in
|
|
90
|
+
tdd)
|
|
91
|
+
PHASES=("setup" "red" "green" "review" "approved" "finish")
|
|
92
|
+
AGENTS=("sm" "tea" "dev" "reviewer" "sm" "sm")
|
|
93
|
+
GATES=("manual" "tests_fail" "tests_pass" "approval" "complete" "")
|
|
94
|
+
;;
|
|
95
|
+
trivial)
|
|
96
|
+
PHASES=("setup" "implement" "review" "approved" "finish")
|
|
97
|
+
AGENTS=("sm" "dev" "reviewer" "sm" "sm")
|
|
98
|
+
GATES=("manual" "tests_pass" "approval" "complete" "")
|
|
99
|
+
;;
|
|
100
|
+
*)
|
|
101
|
+
echo "Warning: Unknown workflow '$WORKFLOW', assuming TDD"
|
|
102
|
+
PHASES=("setup" "red" "green" "review" "approved" "finish")
|
|
103
|
+
AGENTS=("sm" "tea" "dev" "reviewer" "sm" "sm")
|
|
104
|
+
GATES=("manual" "tests_fail" "tests_pass" "approval" "complete" "")
|
|
105
|
+
;;
|
|
106
|
+
esac
|
|
107
|
+
|
|
108
|
+
# Find indices
|
|
109
|
+
CURRENT_IDX=-1
|
|
110
|
+
TARGET_IDX=-1
|
|
111
|
+
for i in "${!PHASES[@]}"; do
|
|
112
|
+
if [[ "${PHASES[$i]}" == "$CURRENT_PHASE" ]]; then
|
|
113
|
+
CURRENT_IDX=$i
|
|
114
|
+
fi
|
|
115
|
+
if [[ "${PHASES[$i]}" == "$TARGET_PHASE" ]]; then
|
|
116
|
+
TARGET_IDX=$i
|
|
117
|
+
fi
|
|
118
|
+
done
|
|
119
|
+
|
|
120
|
+
if [[ $CURRENT_IDX -eq -1 ]]; then
|
|
121
|
+
echo "Error: Current phase '$CURRENT_PHASE' not found in $WORKFLOW workflow"
|
|
122
|
+
echo "Valid phases: ${PHASES[*]}"
|
|
123
|
+
exit 1
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
if [[ $TARGET_IDX -eq -1 ]]; then
|
|
127
|
+
echo "Error: Target phase '$TARGET_PHASE' not found in $WORKFLOW workflow"
|
|
128
|
+
echo "Valid phases: ${PHASES[*]}"
|
|
129
|
+
exit 1
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
if [[ $TARGET_IDX -le $CURRENT_IDX ]]; then
|
|
133
|
+
echo "Error: Target phase '$TARGET_PHASE' is not ahead of current phase '$CURRENT_PHASE'"
|
|
134
|
+
echo "Phase sequence: ${PHASES[*]}"
|
|
135
|
+
exit 1
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
# Calculate what transitions are needed
|
|
139
|
+
echo ""
|
|
140
|
+
echo "Transitions needed:"
|
|
141
|
+
NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
142
|
+
TRANSITIONS=()
|
|
143
|
+
|
|
144
|
+
for ((i=CURRENT_IDX; i<TARGET_IDX; i++)); do
|
|
145
|
+
FROM_PHASE="${PHASES[$i]}"
|
|
146
|
+
TO_PHASE="${PHASES[$((i+1))]}"
|
|
147
|
+
FROM_AGENT="${AGENTS[$i]}"
|
|
148
|
+
TO_AGENT="${AGENTS[$((i+1))]}"
|
|
149
|
+
GATE="${GATES[$((i+1))]}"
|
|
150
|
+
|
|
151
|
+
echo " $FROM_PHASE ($FROM_AGENT) → $TO_PHASE ($TO_AGENT) [gate: $GATE]"
|
|
152
|
+
TRANSITIONS+=("$FROM_PHASE|$TO_PHASE|$FROM_AGENT|$TO_AGENT|$GATE")
|
|
153
|
+
done
|
|
154
|
+
|
|
155
|
+
if [[ "$DRY_RUN" == "true" ]]; then
|
|
156
|
+
echo ""
|
|
157
|
+
echo "[DRY RUN] Would update session file with:"
|
|
158
|
+
echo " - **Phase:** $TARGET_PHASE"
|
|
159
|
+
echo " - **Phase Started:** $NOW"
|
|
160
|
+
echo " - Phase History: close out $CURRENT_PHASE, add intermediate phases"
|
|
161
|
+
echo " - Handoff History: add ${#TRANSITIONS[@]} handoff(s)"
|
|
162
|
+
exit 0
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
echo ""
|
|
166
|
+
echo "Updating session file..."
|
|
167
|
+
|
|
168
|
+
# Build the Phase History additions
|
|
169
|
+
PHASE_HISTORY_ADDITIONS=""
|
|
170
|
+
HANDOFF_HISTORY_ADDITIONS=""
|
|
171
|
+
PREV_END="$NOW"
|
|
172
|
+
|
|
173
|
+
for transition in "${TRANSITIONS[@]}"; do
|
|
174
|
+
IFS='|' read -r FROM_PHASE TO_PHASE FROM_AGENT TO_AGENT GATE <<< "$transition"
|
|
175
|
+
|
|
176
|
+
# Add phase history row (close out the FROM phase)
|
|
177
|
+
# We'll use NOW for ended time since we don't know actual times
|
|
178
|
+
PHASE_HISTORY_ADDITIONS+="| $FROM_PHASE | - | $NOW | - |\n"
|
|
179
|
+
|
|
180
|
+
# Add handoff history row
|
|
181
|
+
HANDOFF_HISTORY_ADDITIONS+="| $FROM_AGENT | $TO_AGENT | $GATE | PASSED | $NOW |\n"
|
|
182
|
+
done
|
|
183
|
+
|
|
184
|
+
# Update the **Phase:** line
|
|
185
|
+
sed -i.bak "s/^\*\*Phase:\*\*.*/\*\*Phase:\*\* $TARGET_PHASE/" "$SESSION_FILE"
|
|
186
|
+
|
|
187
|
+
# Update the **Phase Started:** line
|
|
188
|
+
sed -i.bak "s/^\*\*Phase Started:\*\*.*/\*\*Phase Started:\*\* $NOW/" "$SESSION_FILE"
|
|
189
|
+
|
|
190
|
+
# Close out the current phase in Phase History (update the row that has "| - | - |" at the end)
|
|
191
|
+
# This is tricky - we need to find the row for current phase and add end time
|
|
192
|
+
# For now, we'll add a note about manual review needed
|
|
193
|
+
|
|
194
|
+
# Add handoff history rows before the "## Story Context" section
|
|
195
|
+
if [[ -n "$HANDOFF_HISTORY_ADDITIONS" ]]; then
|
|
196
|
+
# Find the last handoff history row and add after it
|
|
197
|
+
# The handoff history table ends before a blank line or next section
|
|
198
|
+
|
|
199
|
+
# Use awk to insert after the last handoff history row
|
|
200
|
+
awk -v additions="$HANDOFF_HISTORY_ADDITIONS" '
|
|
201
|
+
/^\| .* \| .* \| .* \| .* \| .*\|$/ && /PASSED|FAILED/ {
|
|
202
|
+
last_handoff = NR
|
|
203
|
+
last_handoff_line = $0
|
|
204
|
+
}
|
|
205
|
+
{
|
|
206
|
+
print
|
|
207
|
+
if (NR == last_handoff && additions != "") {
|
|
208
|
+
printf "%s", additions
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
' "$SESSION_FILE" > "$SESSION_FILE.tmp" && mv "$SESSION_FILE.tmp" "$SESSION_FILE"
|
|
212
|
+
fi
|
|
213
|
+
|
|
214
|
+
# Clean up backup
|
|
215
|
+
rm -f "$SESSION_FILE.bak"
|
|
216
|
+
|
|
217
|
+
echo ""
|
|
218
|
+
echo "✓ Session file updated"
|
|
219
|
+
echo " Phase: $CURRENT_PHASE → $TARGET_PHASE"
|
|
220
|
+
echo " Handoffs added: ${#TRANSITIONS[@]}"
|
|
221
|
+
echo ""
|
|
222
|
+
echo "Note: Phase History end times set to now. Review and adjust if needed."
|