@pennyfarthing/core 10.1.0 → 10.2.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/README.md +13 -18
- package/package.json +3 -1
- package/packages/core/dist/cli/commands/doctor-file-layout.test.js.map +1 -1
- package/packages/core/dist/cli/commands/doctor-legacy.test.js +24 -0
- package/packages/core/dist/cli/commands/doctor-legacy.test.js.map +1 -1
- package/packages/core/dist/cli/commands/doctor.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/doctor.js +101 -15
- package/packages/core/dist/cli/commands/doctor.js.map +1 -1
- package/packages/core/dist/cli/commands/e2e-fresh-install.test.js +1 -1
- package/packages/core/dist/cli/commands/e2e-fresh-install.test.js.map +1 -1
- package/packages/core/dist/cli/commands/e2e-upgrade.test.js +1 -1
- package/packages/core/dist/cli/commands/e2e-upgrade.test.js.map +1 -1
- package/packages/core/dist/cli/commands/hooks-consolidation.test.js +2 -2
- package/packages/core/dist/cli/commands/hooks-consolidation.test.js.map +1 -1
- package/packages/core/dist/cli/commands/init-consolidation.test.js.map +1 -1
- package/packages/core/dist/cli/commands/uninstall.d.ts.map +1 -1
- package/packages/core/dist/cli/commands/uninstall.js +24 -13
- package/packages/core/dist/cli/commands/uninstall.js.map +1 -1
- package/packages/core/dist/cli/commands/update-consolidation.test.js +0 -10
- package/packages/core/dist/cli/commands/update-consolidation.test.js.map +1 -1
- package/packages/core/dist/cli/commands/update.js.map +1 -1
- package/packages/core/dist/cli/ocean-profiles.test.js.map +1 -1
- package/packages/core/dist/cli/theme-maker.test.js +64 -115
- package/packages/core/dist/cli/theme-maker.test.js.map +1 -1
- package/packages/core/dist/index.d.ts +1 -1
- package/packages/core/dist/index.d.ts.map +1 -1
- package/packages/core/dist/index.js +2 -2
- package/packages/core/dist/index.js.map +1 -1
- package/packages/core/dist/plugins/plugin-discovery.d.ts +116 -0
- package/packages/core/dist/plugins/plugin-discovery.d.ts.map +1 -0
- package/packages/core/dist/plugins/plugin-discovery.js +165 -0
- package/packages/core/dist/plugins/plugin-discovery.js.map +1 -0
- package/packages/core/dist/plugins/plugin-discovery.test.d.ts +22 -0
- package/packages/core/dist/plugins/plugin-discovery.test.d.ts.map +1 -0
- package/packages/core/dist/plugins/plugin-discovery.test.js +498 -0
- package/packages/core/dist/plugins/plugin-discovery.test.js.map +1 -0
- package/packages/core/dist/scripts/generate-spider-report.js.map +1 -1
- package/packages/core/dist/workflow/context-watch.d.ts +80 -0
- package/packages/core/dist/workflow/context-watch.d.ts.map +1 -0
- package/packages/core/dist/workflow/context-watch.js +235 -0
- package/packages/core/dist/workflow/context-watch.js.map +1 -0
- package/packages/core/dist/workflow/context-watch.test.d.ts +1 -0
- package/packages/core/dist/workflow/context-watch.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/context-watch.test.js +746 -0
- package/packages/core/dist/workflow/context-watch.test.js.map +1 -0
- package/packages/core/dist/workflow/file-watch.d.ts +82 -0
- package/packages/core/dist/workflow/file-watch.d.ts.map +1 -0
- package/packages/core/dist/workflow/file-watch.js +198 -0
- package/packages/core/dist/workflow/file-watch.js.map +1 -0
- package/packages/core/dist/workflow/file-watch.test.d.ts +21 -0
- package/packages/core/dist/workflow/file-watch.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/file-watch.test.js +469 -0
- package/packages/core/dist/workflow/file-watch.test.js.map +1 -0
- package/packages/core/dist/workflow/observation-writer.d.ts +79 -0
- package/packages/core/dist/workflow/observation-writer.d.ts.map +1 -0
- package/packages/core/dist/workflow/observation-writer.js +97 -0
- package/packages/core/dist/workflow/observation-writer.js.map +1 -0
- package/packages/core/dist/workflow/observation-writer.test.d.ts +18 -0
- package/packages/core/dist/workflow/observation-writer.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/observation-writer.test.js +424 -0
- package/packages/core/dist/workflow/observation-writer.test.js.map +1 -0
- package/packages/core/dist/workflow/story-workflow-routing.test.js +4 -2
- package/packages/core/dist/workflow/story-workflow-routing.test.js.map +1 -1
- package/packages/core/dist/workflow/tandem-lifecycle.d.ts +117 -0
- package/packages/core/dist/workflow/tandem-lifecycle.d.ts.map +1 -0
- package/packages/core/dist/workflow/tandem-lifecycle.js +186 -0
- package/packages/core/dist/workflow/tandem-lifecycle.js.map +1 -0
- package/packages/core/dist/workflow/tandem-lifecycle.test.d.ts +16 -0
- package/packages/core/dist/workflow/tandem-lifecycle.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/tandem-lifecycle.test.js +531 -0
- package/packages/core/dist/workflow/tandem-lifecycle.test.js.map +1 -0
- package/packages/core/dist/workflow/tool-watch.d.ts +68 -0
- package/packages/core/dist/workflow/tool-watch.d.ts.map +1 -0
- package/packages/core/dist/workflow/tool-watch.js +166 -0
- package/packages/core/dist/workflow/tool-watch.js.map +1 -0
- package/packages/core/dist/workflow/tool-watch.test.d.ts +18 -0
- package/packages/core/dist/workflow/tool-watch.test.d.ts.map +1 -0
- package/packages/core/dist/workflow/tool-watch.test.js +718 -0
- package/packages/core/dist/workflow/tool-watch.test.js.map +1 -0
- package/packages/core/dist/workflow/workflow-migration.test.js +8 -4
- package/packages/core/dist/workflow/workflow-migration.test.js.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.d.ts +7 -0
- package/packages/core/dist/workflow/workflow-schema.d.ts.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.js +44 -0
- package/packages/core/dist/workflow/workflow-schema.js.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.test.d.ts.map +1 -1
- package/packages/core/dist/workflow/workflow-schema.test.js +192 -0
- package/packages/core/dist/workflow/workflow-schema.test.js.map +1 -1
- package/pennyfarthing-dist/agents/handoff.md +18 -3
- package/pennyfarthing-dist/agents/sm-finish.md +1 -1
- package/pennyfarthing-dist/agents/sm-handoff.md +27 -4
- package/pennyfarthing-dist/agents/sm.md +11 -5
- package/pennyfarthing-dist/agents/tandem-backseat.md +119 -0
- package/pennyfarthing-dist/commands/setup.md +4 -0
- package/pennyfarthing-dist/guides/agent-behavior.md +62 -6
- package/pennyfarthing-dist/guides/bikelane.md +3 -2
- package/pennyfarthing-dist/guides/scale-levels.md +4 -6
- package/pennyfarthing-dist/guides/tandem-protocol.md +158 -0
- package/pennyfarthing-dist/personas/themes/discworld.yaml +1 -1
- package/pennyfarthing-dist/personas/themes/fifth-element.yaml +295 -0
- package/pennyfarthing-dist/scripts/README.md +1 -1
- package/pennyfarthing-dist/scripts/hooks/bell-mode-hook.sh +131 -54
- package/pennyfarthing-dist/scripts/hooks/post-merge.sh +20 -10
- package/pennyfarthing-dist/scripts/misc/statusline.sh +50 -8
- package/pennyfarthing-dist/scripts/workflow/README.md +2 -2
- package/pennyfarthing-dist/scripts/workflow/finish-story.sh +10 -189
- package/pennyfarthing-dist/skills/skill-registry.schema.json +8 -0
- package/pennyfarthing-dist/skills/skill-registry.yaml +1 -1
- package/pennyfarthing-dist/skills/sprint/skill.md +25 -2
- package/pennyfarthing-dist/skills/workflow/skill.md +24 -1
- package/pennyfarthing-dist/workflows/architecture/workflow.yaml +65 -0
- package/pennyfarthing-dist/workflows/bdd-tandem.yaml +70 -0
- package/pennyfarthing-dist/workflows/tdd-tandem.yaml +61 -0
- package/pennyfarthing_scripts/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/bellmode_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/config.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/hooks.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_bidirectional_sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_epic_creation.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira_sync_story.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/output.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/patch_mode.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/schema_validation_hook.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/bellmode_hook.py +202 -47
- package/pennyfarthing_scripts/brownfield/__init__.py +6 -6
- package/pennyfarthing_scripts/brownfield/__main__.py +1 -0
- 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 -1
- package/pennyfarthing_scripts/brownfield/discover.py +1 -2
- package/pennyfarthing_scripts/cli.py +11 -6
- package/pennyfarthing_scripts/codemarkers/__init__.py +5 -1
- package/pennyfarthing_scripts/codemarkers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/codemarkers/analyze.py +177 -2
- package/pennyfarthing_scripts/codemarkers/cli.py +50 -0
- package/pennyfarthing_scripts/codemarkers/formatters.py +0 -1
- package/pennyfarthing_scripts/codemarkers/models.py +15 -0
- package/pennyfarthing_scripts/common/__init__.py +8 -9
- 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 +1 -1
- package/pennyfarthing_scripts/complexity/__init__.py +1 -1
- package/pennyfarthing_scripts/complexity/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/complexity/analyze.py +1 -1
- package/pennyfarthing_scripts/complexity/cli.py +5 -1
- package/pennyfarthing_scripts/complexity/formatters.py +1 -1
- package/pennyfarthing_scripts/context.py +14 -15
- package/pennyfarthing_scripts/deadcode/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/deadcode/analyze.py +3 -4
- package/pennyfarthing_scripts/deadcode/cli.py +2 -2
- package/pennyfarthing_scripts/dependencies/__init__.py +2 -2
- package/pennyfarthing_scripts/dependencies/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/dependencies/analyze.py +1 -1
- package/pennyfarthing_scripts/dependencies/cli.py +8 -4
- package/pennyfarthing_scripts/dependencies/formatters.py +1 -1
- package/pennyfarthing_scripts/git/__init__.py +5 -5
- package/pennyfarthing_scripts/git/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/create_branches.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/__pycache__/status_all.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/git/create_branches.py +3 -2
- package/pennyfarthing_scripts/git/status_all.py +1 -1
- package/pennyfarthing_scripts/healthscore/__init__.py +2 -2
- package/pennyfarthing_scripts/healthscore/__main__.py +8 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/healthscore/analyze.py +451 -21
- package/pennyfarthing_scripts/healthscore/cli.py +5 -1
- package/pennyfarthing_scripts/healthscore/models.py +0 -1
- package/pennyfarthing_scripts/hooks.py +8 -11
- package/pennyfarthing_scripts/hotspots/__init__.py +6 -6
- package/pennyfarthing_scripts/hotspots/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/analyze.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/formatters.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/hotspots/analyze.py +128 -14
- package/pennyfarthing_scripts/hotspots/cli.py +2 -2
- package/pennyfarthing_scripts/hotspots/models.py +0 -1
- package/pennyfarthing_scripts/jira/__init__.py +15 -17
- package/pennyfarthing_scripts/jira/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/bidirectional.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/claim.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/client.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/create.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/operations.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/reconcile.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/story.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/sync.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/bidirectional.py +2 -3
- package/pennyfarthing_scripts/jira/claim.py +21 -0
- package/pennyfarthing_scripts/jira/cli.py +2 -2
- package/pennyfarthing_scripts/jira/client.py +4 -4
- package/pennyfarthing_scripts/jira/create.py +45 -1
- package/pennyfarthing_scripts/jira/epic.py +3 -2
- package/pennyfarthing_scripts/jira/reconcile.py +0 -1
- package/pennyfarthing_scripts/jira/story.py +2 -0
- package/pennyfarthing_scripts/jira/sync.py +1 -1
- package/pennyfarthing_scripts/migration/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/skill.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/step.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/validate.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/skill.py +0 -1
- package/pennyfarthing_scripts/migration/step.py +0 -1
- package/pennyfarthing_scripts/migration/validate.py +8 -5
- package/pennyfarthing_scripts/patch_mode.py +2 -2
- package/pennyfarthing_scripts/preflight/__init__.py +1 -1
- 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/finish.py +0 -1
- package/pennyfarthing_scripts/pretooluse_hook.py +6 -7
- package/pennyfarthing_scripts/prime/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/session.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/tiers.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/cli.py +5 -1
- package/pennyfarthing_scripts/prime/loader.py +2 -3
- package/pennyfarthing_scripts/prime/persona.py +2 -1
- package/pennyfarthing_scripts/prime/tiers.py +4 -4
- package/pennyfarthing_scripts/schema_validation_hook.py +2 -3
- package/pennyfarthing_scripts/sprint/__init__.py +10 -12
- package/pennyfarthing_scripts/sprint/__main__.py +2 -2
- package/pennyfarthing_scripts/sprint/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/archive.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/epic_add.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/import_epic.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/loader.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/status.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/story_add.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/story_finish.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/story_update.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/validate_cmd.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/validator.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/work.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/__pycache__/yaml_io.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/sprint/archive.py +0 -1
- package/pennyfarthing_scripts/sprint/archive_epic.py +1 -4
- package/pennyfarthing_scripts/sprint/cli.py +34 -28
- package/pennyfarthing_scripts/sprint/epic_add.py +8 -1
- package/pennyfarthing_scripts/sprint/import_epic.py +42 -18
- package/pennyfarthing_scripts/sprint/loader.py +6 -0
- package/pennyfarthing_scripts/sprint/status.py +1 -2
- package/pennyfarthing_scripts/sprint/story_add.py +2 -2
- package/pennyfarthing_scripts/sprint/story_finish.py +3 -5
- package/pennyfarthing_scripts/sprint/story_update.py +11 -3
- package/pennyfarthing_scripts/sprint/validate_cmd.py +0 -1
- package/pennyfarthing_scripts/sprint/validator.py +120 -6
- package/pennyfarthing_scripts/sprint/work.py +1 -4
- package/pennyfarthing_scripts/sprint/yaml_io.py +10 -2
- package/pennyfarthing_scripts/story/__init__.py +14 -16
- 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/size.py +0 -1
- package/pennyfarthing_scripts/story/template.py +0 -1
- package/pennyfarthing_scripts/swebench.py +1 -2
- 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_codemarkers.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_common.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_git_utils.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_healthscore.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_jira_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_package_structure.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_patch_mode.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_prime.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_sprint_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_sprint_validator.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_story_add.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_story_package.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_story_update.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_tiers.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_token_counting.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_validate_cmd.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_workflow_check.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_yaml_io.cpython-314-pytest-9.0.2.pyc +0 -0
- package/pennyfarthing_scripts/tests/conftest.py +1 -2
- package/pennyfarthing_scripts/tests/test_brownfield.py +10 -13
- package/pennyfarthing_scripts/tests/test_cli_modules.py +0 -4
- package/pennyfarthing_scripts/tests/test_codemarkers.py +13 -8
- package/pennyfarthing_scripts/tests/test_common.py +9 -4
- package/pennyfarthing_scripts/tests/test_epic_shard_validation.py +699 -0
- package/pennyfarthing_scripts/tests/test_git_utils.py +10 -13
- package/pennyfarthing_scripts/tests/test_healthscore.py +17 -25
- package/pennyfarthing_scripts/tests/test_jira_package.py +0 -3
- package/pennyfarthing_scripts/tests/test_package_structure.py +3 -16
- package/pennyfarthing_scripts/tests/test_patch_mode.py +7 -11
- package/pennyfarthing_scripts/tests/test_prime.py +39 -21
- package/pennyfarthing_scripts/tests/test_sprint_package.py +3 -8
- package/pennyfarthing_scripts/tests/test_sprint_validator.py +53 -5
- package/pennyfarthing_scripts/tests/test_story_add.py +3 -7
- package/pennyfarthing_scripts/tests/test_story_package.py +0 -3
- package/pennyfarthing_scripts/tests/test_story_update.py +5 -10
- package/pennyfarthing_scripts/tests/test_tiers.py +18 -17
- package/pennyfarthing_scripts/tests/test_token_counting.py +19 -13
- package/pennyfarthing_scripts/tests/test_validate_cmd.py +2 -7
- package/pennyfarthing_scripts/tests/test_workflow_check.py +0 -2
- package/pennyfarthing_scripts/tests/test_yaml_io.py +0 -3
- package/pennyfarthing_scripts/theme/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/theme/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/theme/cli.py +3 -2
- package/pennyfarthing_scripts/validate/__init__.py +21 -0
- package/pennyfarthing_scripts/validate/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__init__.py +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/agent.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/schema.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/skill_command.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/sprint.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/__pycache__/workflow.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/validate/adapters/agent.py +239 -0
- package/pennyfarthing_scripts/validate/adapters/schema.py +30 -0
- package/pennyfarthing_scripts/validate/adapters/skill_command.py +292 -0
- package/pennyfarthing_scripts/validate/adapters/sprint.py +69 -0
- package/pennyfarthing_scripts/validate/adapters/workflow.py +320 -0
- package/pennyfarthing_scripts/validate/cli.py +141 -0
- package/pennyfarthing_scripts/welcome_hook.py +2 -3
- package/pennyfarthing_scripts/workflow.py +3 -3
- package/scripts/README.md +3 -15
- package/pennyfarthing-dist/commands/benchmark-control.md +0 -69
- package/pennyfarthing-dist/commands/benchmark.md +0 -485
- package/pennyfarthing-dist/commands/job-fair.md +0 -102
- package/pennyfarthing-dist/commands/solo.md +0 -447
- package/pennyfarthing-dist/guides/benchmarks.md +0 -62
- package/pennyfarthing-dist/scripts/hooks/__pycache__/question_reflector_check.cpython-314.pyc +0 -0
- 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/theme/compute-theme-tiers.sh +0 -13
- package/pennyfarthing-dist/scripts/theme/compute_theme_tiers.py +0 -402
- package/pennyfarthing-dist/scripts/theme/update-theme-tiers.sh +0 -97
- package/pennyfarthing-dist/skills/finalize-run/SKILL.md +0 -261
- package/pennyfarthing-dist/skills/judge/SKILL.md +0 -644
- package/pennyfarthing-dist/skills/persona-benchmark/SKILL.md +0 -187
- 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/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_scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/jira.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/__pycache__/pretooluse_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/jira/__pycache__/compat.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/mappings.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/jira/__pycache__/models.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/migration/__pycache__/cli.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/prime/__pycache__/__main__.cpython-314.pyc +0 -0
- package/pennyfarthing_scripts/tests/__pycache__/test_workflow_cli.cpython-314-pytest-9.0.2.pyc +0 -0
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
#
|
|
3
|
-
# Bell Mode
|
|
3
|
+
# PostToolUse Hook — Bell Mode + Tandem Injection
|
|
4
4
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# the first queued message as additionalContext to be injected into
|
|
8
|
-
# Claude's next API call.
|
|
5
|
+
# Called by Claude Code after each tool execution. Handles two independent
|
|
6
|
+
# injection systems:
|
|
9
7
|
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
8
|
+
# 1. Bell queue (Cyclist only) — injects queued user messages when Cyclist
|
|
9
|
+
# is running and bell_mode is enabled. In CLI sessions this is a no-op.
|
|
10
|
+
# 2. Tandem observations (always active) — injects backseat agent observations
|
|
11
|
+
# when tandem observation files exist. No configuration required.
|
|
12
|
+
#
|
|
13
|
+
# Bell queue takes precedence: if a queued message exists, tandem is
|
|
14
|
+
# deferred to the next hook invocation.
|
|
13
15
|
#
|
|
14
16
|
# Output format (when injecting):
|
|
15
17
|
# {
|
|
16
18
|
# "hookSpecificOutput": {
|
|
17
19
|
# "hookEventName": "PostToolUse",
|
|
18
|
-
# "additionalContext": "
|
|
20
|
+
# "additionalContext": "<message>"
|
|
19
21
|
# }
|
|
20
22
|
# }
|
|
21
23
|
#
|
|
22
|
-
# Output when
|
|
24
|
+
# Output when nothing to inject: (nothing - exit 0)
|
|
23
25
|
|
|
24
26
|
# Find project root (walk up to find .pennyfarthing)
|
|
25
27
|
PROJECT_ROOT="$PWD"
|
|
@@ -31,76 +33,151 @@ while [[ "$PROJECT_ROOT" != "/" ]]; do
|
|
|
31
33
|
done
|
|
32
34
|
|
|
33
35
|
if [[ ! -d "$PROJECT_ROOT/.pennyfarthing" ]]; then
|
|
34
|
-
# No .pennyfarthing directory found - exit silently
|
|
35
36
|
exit 0
|
|
36
37
|
fi
|
|
37
38
|
|
|
38
39
|
CONFIG_LOCAL_YAML="$PROJECT_ROOT/.pennyfarthing/config.local.yaml"
|
|
39
40
|
BELL_QUEUE_FILE="$PROJECT_ROOT/.pennyfarthing/bell-queue.json"
|
|
40
41
|
|
|
41
|
-
#
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
# Detect Cyclist — bell queue is a Cyclist-only feature
|
|
43
|
+
IS_CYCLIST=false
|
|
44
|
+
CYCLIST_PORT=""
|
|
45
|
+
PORT_FILE="$PROJECT_ROOT/.cyclist-port"
|
|
46
|
+
if [[ -f "$PORT_FILE" ]]; then
|
|
47
|
+
CYCLIST_PORT=$(cat "$PORT_FILE" 2>/dev/null)
|
|
48
|
+
if [[ -n "$CYCLIST_PORT" ]] && [[ "$CYCLIST_PORT" =~ ^[0-9]+$ ]]; then
|
|
49
|
+
IS_CYCLIST=true
|
|
50
|
+
fi
|
|
44
51
|
fi
|
|
45
52
|
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
if [[ -
|
|
50
|
-
|
|
53
|
+
# --- Bell queue check (Cyclist only, requires bell_mode: true) ---
|
|
54
|
+
# Takes precedence over tandem injection when active.
|
|
55
|
+
|
|
56
|
+
if [[ "$IS_CYCLIST" == "true" ]] && [[ -f "$CONFIG_LOCAL_YAML" ]]; then
|
|
57
|
+
BELL_ENABLED=$(grep -E '^\s*bell_mode:\s*true' "$CONFIG_LOCAL_YAML" 2>/dev/null || true)
|
|
58
|
+
|
|
59
|
+
if [[ -n "$BELL_ENABLED" ]] && [[ -f "$BELL_QUEUE_FILE" ]]; then
|
|
60
|
+
QUEUE_CONTENT=$(cat "$BELL_QUEUE_FILE" 2>/dev/null)
|
|
61
|
+
if [[ -n "$QUEUE_CONTENT" ]] && [[ "$QUEUE_CONTENT" != "[]" ]]; then
|
|
62
|
+
FIRST_MESSAGE_TEXT=$(echo "$QUEUE_CONTENT" | sed -n 's/.*"text"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
|
|
63
|
+
|
|
64
|
+
if [[ -n "$FIRST_MESSAGE_TEXT" ]]; then
|
|
65
|
+
cat << EOF
|
|
66
|
+
{
|
|
67
|
+
"hookSpecificOutput": {
|
|
68
|
+
"hookEventName": "PostToolUse",
|
|
69
|
+
"additionalContext": "User feedback: $FIRST_MESSAGE_TEXT"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
EOF
|
|
73
|
+
|
|
74
|
+
# Dequeue and notify Cyclist in background
|
|
75
|
+
(
|
|
76
|
+
if command -v jq &> /dev/null; then
|
|
77
|
+
jq 'if length > 0 then .[1:] else [] end' "$BELL_QUEUE_FILE" > "$BELL_QUEUE_FILE.tmp" 2>/dev/null && mv "$BELL_QUEUE_FILE.tmp" "$BELL_QUEUE_FILE"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
curl -s -X POST "http://localhost:$CYCLIST_PORT/api/bell-consumed" \
|
|
81
|
+
-H "Content-Type: application/json" \
|
|
82
|
+
-d "{\"text\": \"$FIRST_MESSAGE_TEXT\"}" \
|
|
83
|
+
>/dev/null 2>&1 || true
|
|
84
|
+
) &
|
|
85
|
+
|
|
86
|
+
exit 0
|
|
87
|
+
fi
|
|
88
|
+
fi
|
|
89
|
+
fi
|
|
51
90
|
fi
|
|
52
91
|
|
|
53
|
-
#
|
|
54
|
-
|
|
92
|
+
# --- Tandem observation injection ---
|
|
93
|
+
# Always active. No configuration required.
|
|
94
|
+
# Checks .session/*-tandem-*.md files for new observations via mtime comparison.
|
|
95
|
+
|
|
96
|
+
SESSION_DIR="$PROJECT_ROOT/.session"
|
|
97
|
+
if [[ ! -d "$SESSION_DIR" ]]; then
|
|
55
98
|
exit 0
|
|
56
99
|
fi
|
|
57
100
|
|
|
58
|
-
#
|
|
59
|
-
|
|
60
|
-
if [[ -z "$
|
|
101
|
+
# Find tandem observation files
|
|
102
|
+
TANDEM_FILES=$(find "$SESSION_DIR" -maxdepth 1 -name "*-tandem-*.md" 2>/dev/null)
|
|
103
|
+
if [[ -z "$TANDEM_FILES" ]]; then
|
|
61
104
|
exit 0
|
|
62
105
|
fi
|
|
63
106
|
|
|
64
|
-
#
|
|
65
|
-
|
|
66
|
-
|
|
107
|
+
# Check each tandem file for new content
|
|
108
|
+
for TANDEM_FILE in $TANDEM_FILES; do
|
|
109
|
+
# Extract agent name from filename: *-tandem-{agent}.md
|
|
110
|
+
AGENT=$(echo "$TANDEM_FILE" | sed -n 's/.*-tandem-\([a-zA-Z_]*\)\.md$/\1/p')
|
|
111
|
+
if [[ -z "$AGENT" ]]; then
|
|
112
|
+
continue
|
|
113
|
+
fi
|
|
67
114
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
115
|
+
# Get file mtime (portable: stat -f %m on macOS, stat -c %Y on Linux)
|
|
116
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
117
|
+
FILE_MTIME=$(stat -f %m "$TANDEM_FILE" 2>/dev/null)
|
|
118
|
+
else
|
|
119
|
+
FILE_MTIME=$(stat -c %Y "$TANDEM_FILE" 2>/dev/null)
|
|
120
|
+
fi
|
|
121
|
+
if [[ -z "$FILE_MTIME" ]]; then
|
|
122
|
+
continue
|
|
123
|
+
fi
|
|
71
124
|
|
|
72
|
-
#
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if [[ -f "$
|
|
76
|
-
|
|
77
|
-
fi
|
|
125
|
+
# Compare with saved mtime sidecar
|
|
126
|
+
MTIME_SIDECAR="$SESSION_DIR/.tandem-mtime-$AGENT"
|
|
127
|
+
SAVED_MTIME="0"
|
|
128
|
+
if [[ -f "$MTIME_SIDECAR" ]]; then
|
|
129
|
+
SAVED_MTIME=$(cat "$MTIME_SIDECAR" 2>/dev/null)
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
if [[ "$FILE_MTIME" == "$SAVED_MTIME" ]]; then
|
|
133
|
+
continue
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
# Read tandem file and extract latest observation
|
|
137
|
+
CONTENT=$(cat "$TANDEM_FILE" 2>/dev/null)
|
|
138
|
+
if [[ -z "$CONTENT" ]]; then
|
|
139
|
+
continue
|
|
140
|
+
fi
|
|
78
141
|
|
|
79
|
-
#
|
|
80
|
-
|
|
142
|
+
# Extract persona from header: **Observer:** agent (Persona Name)
|
|
143
|
+
PERSONA=$(echo "$CONTENT" | sed -n 's/.*\*\*Observer:\*\*[[:space:]]*[a-zA-Z_]*[[:space:]]*(\([^)]*\)).*/\1/p' | head -1)
|
|
144
|
+
if [[ -z "$PERSONA" ]]; then
|
|
145
|
+
PERSONA="Unknown"
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
# Extract latest observation text (last ## [HH:MM] Observation block)
|
|
149
|
+
# Get text between last observation header and trailing ---
|
|
150
|
+
OBS_TEXT=$(echo "$CONTENT" | awk '
|
|
151
|
+
/^## \[[0-9]+:[0-9]+\] Observation/ { found=1; text=""; next }
|
|
152
|
+
found && /^---/ { next }
|
|
153
|
+
found && /^\*\*Trigger:\*\*/ { next }
|
|
154
|
+
found { text = text (text ? "\n" : "") $0 }
|
|
155
|
+
END { if (text) print text }
|
|
156
|
+
' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
157
|
+
|
|
158
|
+
if [[ -z "$OBS_TEXT" ]]; then
|
|
159
|
+
# Update mtime even if no parseable observation
|
|
160
|
+
echo "$FILE_MTIME" > "$MTIME_SIDECAR"
|
|
161
|
+
continue
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
# Format as [Tandem] prefix and output
|
|
165
|
+
TANDEM_MSG="[Tandem] $PERSONA: $OBS_TEXT"
|
|
166
|
+
|
|
167
|
+
cat << EOF
|
|
81
168
|
{
|
|
82
169
|
"hookSpecificOutput": {
|
|
83
170
|
"hookEventName": "PostToolUse",
|
|
84
|
-
"additionalContext": "
|
|
171
|
+
"additionalContext": "$TANDEM_MSG"
|
|
85
172
|
}
|
|
86
173
|
}
|
|
87
174
|
EOF
|
|
88
175
|
|
|
89
|
-
#
|
|
90
|
-
|
|
91
|
-
(
|
|
92
|
-
# Dequeue using jq if available
|
|
93
|
-
if command -v jq &> /dev/null; then
|
|
94
|
-
jq 'if length > 0 then .[1:] else [] end' "$BELL_QUEUE_FILE" > "$BELL_QUEUE_FILE.tmp" 2>/dev/null && mv "$BELL_QUEUE_FILE.tmp" "$BELL_QUEUE_FILE"
|
|
95
|
-
fi
|
|
176
|
+
# Save mtime sidecar
|
|
177
|
+
echo "$FILE_MTIME" > "$MTIME_SIDECAR"
|
|
96
178
|
|
|
97
|
-
#
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
-H "Content-Type: application/json" \
|
|
101
|
-
-d "{\"text\": \"$FIRST_MESSAGE_TEXT\"}" \
|
|
102
|
-
>/dev/null 2>&1 || true
|
|
103
|
-
fi
|
|
104
|
-
) &
|
|
179
|
+
# Only inject one tandem observation per hook invocation
|
|
180
|
+
exit 0
|
|
181
|
+
done
|
|
105
182
|
|
|
106
183
|
exit 0
|
|
@@ -47,7 +47,7 @@ extract_story_id() {
|
|
|
47
47
|
|
|
48
48
|
# update_story_status STORY_ID NEW_STATUS
|
|
49
49
|
# Update story status in sprint YAML and add completed date
|
|
50
|
-
#
|
|
50
|
+
# Handles both inline stories in current-sprint.yaml and sharded epic files
|
|
51
51
|
update_story_status() {
|
|
52
52
|
local story_id="$1"
|
|
53
53
|
local new_status="${2:-done}"
|
|
@@ -58,23 +58,33 @@ update_story_status() {
|
|
|
58
58
|
return 1
|
|
59
59
|
fi
|
|
60
60
|
|
|
61
|
-
# Check if yq is available
|
|
62
61
|
if ! command -v yq &>/dev/null; then
|
|
63
62
|
echo "Warning: yq not found, cannot update sprint YAML" >&2
|
|
64
63
|
return 1
|
|
65
64
|
fi
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
local story_num="${story_id#*-}"
|
|
66
|
+
local sprint_dir
|
|
67
|
+
sprint_dir="$(dirname "$SPRINT_FILE")"
|
|
70
68
|
|
|
71
|
-
#
|
|
69
|
+
# Try inline stories in current-sprint.yaml first
|
|
72
70
|
yq eval -i "
|
|
73
|
-
(.
|
|
74
|
-
(.
|
|
75
|
-
" "$SPRINT_FILE"
|
|
71
|
+
(.stories[] | select(.id == \"$story_id\")).status = \"$new_status\" |
|
|
72
|
+
(.stories[] | select(.id == \"$story_id\")).completed = \"$completed_date\"
|
|
73
|
+
" "$SPRINT_FILE" 2>/dev/null
|
|
74
|
+
|
|
75
|
+
# Also try each epic shard file
|
|
76
|
+
for shard in "$sprint_dir"/epic-*.yaml; do
|
|
77
|
+
[[ -f "$shard" ]] || continue
|
|
78
|
+
if yq eval ".stories[] | select(.id == \"$story_id\")" "$shard" 2>/dev/null | grep -q "$story_id"; then
|
|
79
|
+
yq eval -i "
|
|
80
|
+
(.stories[] | select(.id == \"$story_id\")).status = \"$new_status\" |
|
|
81
|
+
(.stories[] | select(.id == \"$story_id\")).completed = \"$completed_date\"
|
|
82
|
+
" "$shard"
|
|
83
|
+
return $?
|
|
84
|
+
fi
|
|
85
|
+
done
|
|
76
86
|
|
|
77
|
-
return
|
|
87
|
+
return 0
|
|
78
88
|
}
|
|
79
89
|
|
|
80
90
|
# log_reconciliation STORY_ID MESSAGE
|
|
@@ -134,6 +134,39 @@ if [ -n "$config_file" ] && [ -n "$agent_name" ]; then
|
|
|
134
134
|
fi
|
|
135
135
|
theme_display="$character_display"
|
|
136
136
|
|
|
137
|
+
# Tandem indicator: detect active backseat agent from observation files
|
|
138
|
+
# Files: .session/{storyId}-tandem-{partner}.md (created by backseat spawn, cleaned on finish)
|
|
139
|
+
tandem_partner=""
|
|
140
|
+
tandem_partner_display=""
|
|
141
|
+
if [ -d "$PROJECT_ROOT/.session" ]; then
|
|
142
|
+
tandem_file=$(find "$PROJECT_ROOT/.session" -maxdepth 1 -name "*-tandem-*.md" -print 2>/dev/null | head -1)
|
|
143
|
+
if [ -n "$tandem_file" ]; then
|
|
144
|
+
# Extract partner name from filename: {storyId}-tandem-{partner}.md
|
|
145
|
+
tandem_partner=$(basename "$tandem_file" | sed -n 's/.*-tandem-\([a-zA-Z_-]*\)\.md$/\1/p')
|
|
146
|
+
if [ -n "$tandem_partner" ] && [ -n "$theme_file" ] && [ -f "$theme_file" ]; then
|
|
147
|
+
# Look up partner's character name from theme
|
|
148
|
+
partner_full=$(yq ".agents.${tandem_partner}.character" "$theme_file" 2>/dev/null)
|
|
149
|
+
if [ -n "$partner_full" ] && [ "$partner_full" != "null" ]; then
|
|
150
|
+
partner_clean=$(echo "$partner_full" | sed 's/ *([^)]*)//g' | xargs)
|
|
151
|
+
partner_clean=$(echo "$partner_clean" | sed -E 's/^(Captain|Lieutenant|Dr\.|Doc|Mr\.|Mrs\.|Ms\.|Admiral|Commander|Chief|Ensign|Translator|Agent|Colonel|Major|Sergeant|Professor|Lord|Lady|Sir|The) +//i')
|
|
152
|
+
partner_wc=$(echo "$partner_clean" | wc -w | tr -d ' ')
|
|
153
|
+
if [ "$partner_wc" -eq 1 ]; then
|
|
154
|
+
tandem_partner_display="$partner_clean"
|
|
155
|
+
else
|
|
156
|
+
tandem_partner_display=$(echo "$partner_clean" | awk '{print $NF}')
|
|
157
|
+
fi
|
|
158
|
+
fi
|
|
159
|
+
# Fallback to agent abbreviation if no theme character
|
|
160
|
+
if [ -z "$tandem_partner_display" ]; then
|
|
161
|
+
tandem_partner_display=$(get_agent_abbrev "$tandem_partner")
|
|
162
|
+
fi
|
|
163
|
+
elif [ -n "$tandem_partner" ]; then
|
|
164
|
+
# No theme file — use abbreviation
|
|
165
|
+
tandem_partner_display=$(get_agent_abbrev "$tandem_partner")
|
|
166
|
+
fi
|
|
167
|
+
fi
|
|
168
|
+
fi
|
|
169
|
+
|
|
137
170
|
# ANSI colors
|
|
138
171
|
RESET=$'\033[0m'
|
|
139
172
|
DIM=$'\033[2m'
|
|
@@ -214,20 +247,29 @@ repo_fmt=$(printf "%-14s" "$dir_name")
|
|
|
214
247
|
branch_fmt=$(printf "%-12s" "${branch}${branch_dirty}")
|
|
215
248
|
model_fmt=$(printf "%-10s" "$model")
|
|
216
249
|
|
|
217
|
-
# Build
|
|
250
|
+
# Build tandem suffix: "+ Partner" when backseat agent is active
|
|
251
|
+
tandem_suffix=""
|
|
252
|
+
tandem_suffix_len=0
|
|
253
|
+
if [ -n "$tandem_partner_display" ]; then
|
|
254
|
+
partner_color=$(get_agent_color "$tandem_partner")
|
|
255
|
+
tandem_suffix=" ${DIM}+${RESET} ${partner_color}${tandem_partner_display}${RESET}"
|
|
256
|
+
tandem_suffix_len=$((3 + ${#tandem_partner_display})) # " + " + name
|
|
257
|
+
fi
|
|
258
|
+
|
|
259
|
+
# Build agent display: [ROLE] Theme (+ Partner) (role in reverse text with color)
|
|
218
260
|
if [ -n "$agent_abbrev" ]; then
|
|
219
261
|
agent_color=$(get_agent_color "$agent_name")
|
|
220
262
|
# Role in reverse text with color, then theme
|
|
221
263
|
if [ -n "$theme_display" ]; then
|
|
222
|
-
agent_section="${agent_color}${REVERSE} ${agent_abbrev} ${RESET} ${DIM}${theme_display}${RESET}"
|
|
223
|
-
# Pad to ~20 chars visual width (abbrev ~3 + spaces ~2 + theme ~10 = ~15
|
|
224
|
-
pad_len=$((18 - ${#agent_abbrev} - ${#theme_display}))
|
|
264
|
+
agent_section="${agent_color}${REVERSE} ${agent_abbrev} ${RESET} ${DIM}${theme_display}${RESET}${tandem_suffix}"
|
|
265
|
+
# Pad to ~20 chars visual width (abbrev ~3 + spaces ~2 + theme ~10 + tandem = ~15+, pad to 20)
|
|
266
|
+
pad_len=$((18 - ${#agent_abbrev} - ${#theme_display} - tandem_suffix_len))
|
|
225
267
|
[ "$pad_len" -lt 0 ] && pad_len=0
|
|
226
268
|
padding=$(printf "%${pad_len}s" "")
|
|
227
269
|
agent_section="${agent_section}${padding}"
|
|
228
270
|
else
|
|
229
|
-
agent_section="${agent_color}${REVERSE} ${agent_abbrev} ${RESET}"
|
|
230
|
-
pad_len=$((17 - ${#agent_abbrev}))
|
|
271
|
+
agent_section="${agent_color}${REVERSE} ${agent_abbrev} ${RESET}${tandem_suffix}"
|
|
272
|
+
pad_len=$((17 - ${#agent_abbrev} - tandem_suffix_len))
|
|
231
273
|
[ "$pad_len" -lt 0 ] && pad_len=0
|
|
232
274
|
padding=$(printf "%${pad_len}s" "")
|
|
233
275
|
agent_section="${agent_section}${padding}"
|
|
@@ -235,8 +277,8 @@ if [ -n "$agent_abbrev" ]; then
|
|
|
235
277
|
else
|
|
236
278
|
# No agent - just show theme if available
|
|
237
279
|
if [ -n "$theme_display" ]; then
|
|
238
|
-
agent_section="${DIM}${theme_display}${RESET}"
|
|
239
|
-
pad_len=$((20 - ${#theme_display}))
|
|
280
|
+
agent_section="${DIM}${theme_display}${RESET}${tandem_suffix}"
|
|
281
|
+
pad_len=$((20 - ${#theme_display} - tandem_suffix_len))
|
|
240
282
|
[ "$pad_len" -lt 0 ] && pad_len=0
|
|
241
283
|
padding=$(printf "%${pad_len}s" "")
|
|
242
284
|
agent_section="${agent_section}${padding}"
|
|
@@ -6,7 +6,7 @@ Scripts for workflow mechanics, phase transitions, and quality gates.
|
|
|
6
6
|
|
|
7
7
|
| Script | Purpose |
|
|
8
8
|
|--------|---------|
|
|
9
|
-
| `finish-story.sh` |
|
|
9
|
+
| `finish-story.sh` | **DEPRECATED** — forwards to `pf sprint story finish` |
|
|
10
10
|
| `fix-session-phase.sh` | Repair session file phase state |
|
|
11
11
|
| `check.sh` | Quality gates runner (lint, type check, tests) |
|
|
12
12
|
| `list-workflows.sh` | List available workflows |
|
|
@@ -18,7 +18,7 @@ Scripts for workflow mechanics, phase transitions, and quality gates.
|
|
|
18
18
|
## Usage
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
|
|
21
|
+
pf sprint story finish MSSCI-12345
|
|
22
22
|
.pennyfarthing/scripts/workflow/start-workflow.sh prd --mode create
|
|
23
23
|
```
|
|
24
24
|
|
|
@@ -1,199 +1,20 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
#
|
|
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
|
|
2
|
+
# DEPRECATED: Use `pf sprint story finish` instead.
|
|
7
3
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
4
|
+
# This shell script had a bug where yq paths targeted .epics[].stories[]
|
|
5
|
+
# but the sprint YAML uses sharded epic files with .stories[] at root.
|
|
6
|
+
# The Python implementation (pennyfarthing_scripts.sprint.story_finish)
|
|
7
|
+
# correctly handles sharded YAML via read_sprint/write_sprint.
|
|
12
8
|
#
|
|
13
|
-
#
|
|
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. Archive completed epics (if last story in epic was just finished)
|
|
19
|
-
# 6. Clean up local branch and session file
|
|
9
|
+
# Usage: finish-story.sh <story-id> [--dry-run]
|
|
20
10
|
|
|
21
11
|
set -euo pipefail
|
|
22
12
|
|
|
23
|
-
|
|
24
|
-
DRY_RUN=false
|
|
13
|
+
echo "DEPRECATED: finish-story.sh is deprecated. Forwarding to 'pf sprint story finish'." >&2
|
|
25
14
|
|
|
26
|
-
|
|
15
|
+
ARGS=()
|
|
27
16
|
for arg in "$@"; do
|
|
28
|
-
|
|
29
|
-
--dry-run)
|
|
30
|
-
DRY_RUN=true
|
|
31
|
-
shift
|
|
32
|
-
;;
|
|
33
|
-
esac
|
|
17
|
+
ARGS+=("$arg")
|
|
34
18
|
done
|
|
35
19
|
|
|
36
|
-
|
|
37
|
-
echo "Usage: finish-story.sh <story-id> [--dry-run]"
|
|
38
|
-
echo ""
|
|
39
|
-
echo "Options:"
|
|
40
|
-
echo " --dry-run Show what would be done without executing"
|
|
41
|
-
exit 1
|
|
42
|
-
fi
|
|
43
|
-
|
|
44
|
-
# Find project root
|
|
45
|
-
source "$(dirname "${BASH_SOURCE[0]}")/../lib/find-root.sh"
|
|
46
|
-
|
|
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
|
-
# Resolve session file: prefer Jira key, fall back to numeric story ID
|
|
54
|
-
SESSION_FILE="$PROJECT_ROOT/.session/${STORY_ID}-session.md"
|
|
55
|
-
if [[ ! -f "$SESSION_FILE" ]]; then
|
|
56
|
-
# Look up Jira key from sprint YAML and try that
|
|
57
|
-
_JIRA_LOOKUP=$(pf sprint story field "$STORY_ID" jira 2>/dev/null || echo "")
|
|
58
|
-
if [[ -n "$_JIRA_LOOKUP" && "$_JIRA_LOOKUP" != "null" ]]; then
|
|
59
|
-
ALT_SESSION="$PROJECT_ROOT/.session/${_JIRA_LOOKUP}-session.md"
|
|
60
|
-
if [[ -f "$ALT_SESSION" ]]; then
|
|
61
|
-
SESSION_FILE="$ALT_SESSION"
|
|
62
|
-
fi
|
|
63
|
-
fi
|
|
64
|
-
fi
|
|
65
|
-
|
|
66
|
-
# Also try the reverse: if called with Jira key, try numeric ID
|
|
67
|
-
if [[ ! -f "$SESSION_FILE" ]]; then
|
|
68
|
-
# List session files and look for one containing the story ID
|
|
69
|
-
for f in "$PROJECT_ROOT/.session/"*-session.md; do
|
|
70
|
-
[[ -f "$f" ]] || continue
|
|
71
|
-
if grep -q "$STORY_ID" "$f" 2>/dev/null; then
|
|
72
|
-
SESSION_FILE="$f"
|
|
73
|
-
break
|
|
74
|
-
fi
|
|
75
|
-
done
|
|
76
|
-
fi
|
|
77
|
-
|
|
78
|
-
# Validate session file exists
|
|
79
|
-
if [[ ! -f "$SESSION_FILE" ]]; then
|
|
80
|
-
echo "Error: Session file not found for story $STORY_ID"
|
|
81
|
-
echo "Looked for: $PROJECT_ROOT/.session/${STORY_ID}-session.md"
|
|
82
|
-
[[ -n "${_JIRA_LOOKUP:-}" ]] && echo "Also tried: $PROJECT_ROOT/.session/${_JIRA_LOOKUP}-session.md"
|
|
83
|
-
exit 1
|
|
84
|
-
fi
|
|
85
|
-
|
|
86
|
-
# Extract metadata from session file
|
|
87
|
-
# Try **Jira:** field first (handle both "**Jira:**" and "- **Jira:**", markdown link format)
|
|
88
|
-
JIRA_KEY=$(grep -E '\*\*Jira:\*\*' "$SESSION_FILE" | sed 's/.*\*\*Jira:\*\* //' | sed 's/\[//' | sed 's/\].*//' | tr -d ' ' || echo "")
|
|
89
|
-
|
|
90
|
-
# Fallback: extract MSSCI key from **ID:** field (format: "MSSCI-14459 (81-2)" or just "MSSCI-14459")
|
|
91
|
-
if [[ -z "$JIRA_KEY" || "$JIRA_KEY" == "null" ]]; then
|
|
92
|
-
JIRA_KEY=$(grep -E '\*\*ID:\*\*' "$SESSION_FILE" | grep -oE 'MSSCI-[0-9]+' | head -1 || echo "")
|
|
93
|
-
fi
|
|
94
|
-
|
|
95
|
-
# Fallback: if STORY_ID itself is a Jira key, use it directly
|
|
96
|
-
if [[ -z "$JIRA_KEY" || "$JIRA_KEY" == "null" ]]; then
|
|
97
|
-
if [[ "$STORY_ID" =~ ^MSSCI-[0-9]+$ ]]; then
|
|
98
|
-
JIRA_KEY="$STORY_ID"
|
|
99
|
-
fi
|
|
100
|
-
fi
|
|
101
|
-
|
|
102
|
-
# Fallback: look up Jira key from sprint YAML via pf CLI
|
|
103
|
-
if [[ -z "$JIRA_KEY" || "$JIRA_KEY" == "null" ]]; then
|
|
104
|
-
JIRA_KEY=$(pf sprint story field "$STORY_ID" jira 2>/dev/null || echo "")
|
|
105
|
-
fi
|
|
106
|
-
|
|
107
|
-
if [[ -z "$JIRA_KEY" || "$JIRA_KEY" == "null" ]]; then
|
|
108
|
-
echo "Error: Could not determine Jira key for story $STORY_ID"
|
|
109
|
-
echo "Check session file or sprint YAML for jira: field"
|
|
110
|
-
exit 1
|
|
111
|
-
fi
|
|
112
|
-
|
|
113
|
-
# Extract branch - strip any trailing annotations like "(pushed)"
|
|
114
|
-
BRANCH=$(grep -E '\*\*Branch:\*\*' "$SESSION_FILE" | sed 's/.*\*\*Branch:\*\* //' | sed 's/ *(.*//' | tr -d ' ' || echo "")
|
|
115
|
-
|
|
116
|
-
# Try to get PR number from session file first (format: **PR:** #422 - title)
|
|
117
|
-
PR_NUMBER=$(grep -E '\*\*PR:\*\*' "$SESSION_FILE" | sed 's/.*#\([0-9]*\).*/\1/' || echo "")
|
|
118
|
-
|
|
119
|
-
# Fallback: get PR number from GitHub if not in session file
|
|
120
|
-
if [[ -z "$PR_NUMBER" ]] && [[ -n "$BRANCH" ]]; then
|
|
121
|
-
PR_NUMBER=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null || echo "")
|
|
122
|
-
fi
|
|
123
|
-
|
|
124
|
-
TODAY=$(date +%Y-%m-%d)
|
|
125
|
-
|
|
126
|
-
echo "=== Finish Story: $STORY_ID ==="
|
|
127
|
-
echo "Jira Key: $JIRA_KEY"
|
|
128
|
-
echo "Branch: ${BRANCH:-none}"
|
|
129
|
-
echo "PR: ${PR_NUMBER:-none}"
|
|
130
|
-
echo ""
|
|
131
|
-
|
|
132
|
-
if $DRY_RUN; then
|
|
133
|
-
echo "[DRY RUN] Would perform:"
|
|
134
|
-
echo " 1. Archive session → $ARCHIVE_DIR/${JIRA_KEY}-session.md"
|
|
135
|
-
if [[ -n "$PR_NUMBER" ]]; then
|
|
136
|
-
echo " 2. Merge PR #$PR_NUMBER (squash, delete branch)"
|
|
137
|
-
else
|
|
138
|
-
echo " 2. No PR to merge"
|
|
139
|
-
fi
|
|
140
|
-
echo " 3. Transition $JIRA_KEY to Done"
|
|
141
|
-
echo " 4. Update sprint YAML (status: done, completed: $TODAY)"
|
|
142
|
-
echo " 5. Archive any completed epics"
|
|
143
|
-
echo " 6. Delete local branch: $BRANCH"
|
|
144
|
-
echo " 7. Remove session file"
|
|
145
|
-
exit 0
|
|
146
|
-
fi
|
|
147
|
-
|
|
148
|
-
# Step 1: Archive session file
|
|
149
|
-
echo "1. Archiving session file..."
|
|
150
|
-
cp "$SESSION_FILE" "$ARCHIVE_DIR/${JIRA_KEY}-session.md"
|
|
151
|
-
echo " → $ARCHIVE_DIR/${JIRA_KEY}-session.md"
|
|
152
|
-
|
|
153
|
-
# Step 2: Merge PR (if exists)
|
|
154
|
-
if [[ -n "$PR_NUMBER" ]]; then
|
|
155
|
-
echo "2. Merging PR #$PR_NUMBER..."
|
|
156
|
-
gh pr merge "$PR_NUMBER" --squash --delete-branch || {
|
|
157
|
-
echo " Warning: PR merge failed (may already be merged)"
|
|
158
|
-
}
|
|
159
|
-
else
|
|
160
|
-
echo "2. No PR found for branch $BRANCH (skipping merge)"
|
|
161
|
-
fi
|
|
162
|
-
|
|
163
|
-
# Step 3: Transition Jira to Done
|
|
164
|
-
echo "3. Transitioning Jira to Done..."
|
|
165
|
-
jira issue move "$JIRA_KEY" "Done" 2>/dev/null || {
|
|
166
|
-
echo " Warning: Jira transition failed (may already be Done)"
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
# Step 4: Update sprint YAML
|
|
170
|
-
echo "4. Updating sprint YAML..."
|
|
171
|
-
# Update status to done
|
|
172
|
-
yq eval -i "(.epics[].stories[] | select(.id == \"$STORY_ID\")).status = \"done\"" "$SPRINT_FILE"
|
|
173
|
-
# Add completed date
|
|
174
|
-
yq eval -i "(.epics[].stories[] | select(.id == \"$STORY_ID\")).completed = \"$TODAY\"" "$SPRINT_FILE"
|
|
175
|
-
# Remove assigned_to (no longer in progress)
|
|
176
|
-
yq eval -i "del((.epics[].stories[] | select(.id == \"$STORY_ID\")).assigned_to)" "$SPRINT_FILE"
|
|
177
|
-
echo " → status: done, completed: $TODAY"
|
|
178
|
-
|
|
179
|
-
# Step 5: Archive completed epics
|
|
180
|
-
echo "5. Archiving completed epics..."
|
|
181
|
-
pf sprint epic archive 2>/dev/null && echo " → Checked for completed epics" || echo " → No epics to archive"
|
|
182
|
-
|
|
183
|
-
# Step 6: Clean up git
|
|
184
|
-
echo "6. Cleaning up git..."
|
|
185
|
-
git checkout develop 2>/dev/null || git checkout main 2>/dev/null || true
|
|
186
|
-
git pull origin "$(git branch --show-current)" 2>/dev/null || true
|
|
187
|
-
|
|
188
|
-
if [[ -n "$BRANCH" ]]; then
|
|
189
|
-
git branch -d "$BRANCH" 2>/dev/null || echo " Local branch already deleted"
|
|
190
|
-
fi
|
|
191
|
-
|
|
192
|
-
# Step 7: Remove session file
|
|
193
|
-
echo "7. Removing session file..."
|
|
194
|
-
rm "$SESSION_FILE"
|
|
195
|
-
|
|
196
|
-
echo ""
|
|
197
|
-
echo "=== Story $STORY_ID Complete ==="
|
|
198
|
-
echo "Archived: sprint/archive/${JIRA_KEY}-session.md"
|
|
199
|
-
echo "Jira: https://1898andco.atlassian.net/browse/$JIRA_KEY"
|
|
20
|
+
exec pf sprint story finish "${ARGS[@]}"
|
|
@@ -98,6 +98,14 @@
|
|
|
98
98
|
"type": "array",
|
|
99
99
|
"items": { "type": "string" },
|
|
100
100
|
"description": "Tools this skill is allowed to use. If omitted, all tools are allowed. Use to restrict read-only skills from writing."
|
|
101
|
+
},
|
|
102
|
+
"deprecated": {
|
|
103
|
+
"type": "boolean",
|
|
104
|
+
"description": "Whether this skill is deprecated"
|
|
105
|
+
},
|
|
106
|
+
"redirect": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"description": "Skill name to redirect to when deprecated"
|
|
101
109
|
}
|
|
102
110
|
},
|
|
103
111
|
"required": ["name", "description", "category", "tags"],
|
|
@@ -386,7 +386,7 @@ skills:
|
|
|
386
386
|
anti_patterns:
|
|
387
387
|
- Don't switch workflows mid-story unless requirements fundamentally changed
|
|
388
388
|
related_skills: [sprint]
|
|
389
|
-
keywords: [tdd, trivial, agent-docs, bdd, architecture, bikelane, stepped, phased]
|
|
389
|
+
keywords: [tdd, tdd-tandem, trivial, agent-docs, bdd, bdd-tandem, architecture, bikelane, stepped, phased]
|
|
390
390
|
|
|
391
391
|
yq:
|
|
392
392
|
name: yq
|